|
|
1.1 ! root 1: /* ! 2: * QEMU VNC display driver: VeNCrypt authentication setup ! 3: * ! 4: * Copyright (C) 2006 Anthony Liguori <[email protected]> ! 5: * Copyright (C) 2006 Fabrice Bellard ! 6: * Copyright (C) 2009 Red Hat, Inc ! 7: * ! 8: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 9: * of this software and associated documentation files (the "Software"), to deal ! 10: * in the Software without restriction, including without limitation the rights ! 11: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 12: * copies of the Software, and to permit persons to whom the Software is ! 13: * furnished to do so, subject to the following conditions: ! 14: * ! 15: * The above copyright notice and this permission notice shall be included in ! 16: * all copies or substantial portions of the Software. ! 17: * ! 18: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 19: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 20: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! 21: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 22: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 23: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 24: * THE SOFTWARE. ! 25: */ ! 26: ! 27: #include "vnc.h" ! 28: ! 29: ! 30: static void start_auth_vencrypt_subauth(VncState *vs) ! 31: { ! 32: switch (vs->vd->subauth) { ! 33: case VNC_AUTH_VENCRYPT_TLSNONE: ! 34: case VNC_AUTH_VENCRYPT_X509NONE: ! 35: VNC_DEBUG("Accept TLS auth none\n"); ! 36: vnc_write_u32(vs, 0); /* Accept auth completion */ ! 37: start_client_init(vs); ! 38: break; ! 39: ! 40: case VNC_AUTH_VENCRYPT_TLSVNC: ! 41: case VNC_AUTH_VENCRYPT_X509VNC: ! 42: VNC_DEBUG("Start TLS auth VNC\n"); ! 43: start_auth_vnc(vs); ! 44: break; ! 45: ! 46: #ifdef CONFIG_VNC_SASL ! 47: case VNC_AUTH_VENCRYPT_TLSSASL: ! 48: case VNC_AUTH_VENCRYPT_X509SASL: ! 49: VNC_DEBUG("Start TLS auth SASL\n"); ! 50: return start_auth_sasl(vs); ! 51: #endif /* CONFIG_VNC_SASL */ ! 52: ! 53: default: /* Should not be possible, but just in case */ ! 54: VNC_DEBUG("Reject subauth %d server bug\n", vs->vd->auth); ! 55: vnc_write_u8(vs, 1); ! 56: if (vs->minor >= 8) { ! 57: static const char err[] = "Unsupported authentication type"; ! 58: vnc_write_u32(vs, sizeof(err)); ! 59: vnc_write(vs, err, sizeof(err)); ! 60: } ! 61: vnc_client_error(vs); ! 62: } ! 63: } ! 64: ! 65: static void vnc_tls_handshake_io(void *opaque); ! 66: ! 67: static int vnc_start_vencrypt_handshake(struct VncState *vs) { ! 68: int ret; ! 69: ! 70: if ((ret = gnutls_handshake(vs->tls.session)) < 0) { ! 71: if (!gnutls_error_is_fatal(ret)) { ! 72: VNC_DEBUG("Handshake interrupted (blocking)\n"); ! 73: if (!gnutls_record_get_direction(vs->tls.session)) ! 74: qemu_set_fd_handler(vs->csock, vnc_tls_handshake_io, NULL, vs); ! 75: else ! 76: qemu_set_fd_handler(vs->csock, NULL, vnc_tls_handshake_io, vs); ! 77: return 0; ! 78: } ! 79: VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret)); ! 80: vnc_client_error(vs); ! 81: return -1; ! 82: } ! 83: ! 84: if (vs->vd->tls.x509verify) { ! 85: if (vnc_tls_validate_certificate(vs) < 0) { ! 86: VNC_DEBUG("Client verification failed\n"); ! 87: vnc_client_error(vs); ! 88: return -1; ! 89: } else { ! 90: VNC_DEBUG("Client verification passed\n"); ! 91: } ! 92: } ! 93: ! 94: VNC_DEBUG("Handshake done, switching to TLS data mode\n"); ! 95: vs->tls.wiremode = VNC_WIREMODE_TLS; ! 96: qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs); ! 97: ! 98: start_auth_vencrypt_subauth(vs); ! 99: ! 100: return 0; ! 101: } ! 102: ! 103: static void vnc_tls_handshake_io(void *opaque) { ! 104: struct VncState *vs = (struct VncState *)opaque; ! 105: ! 106: VNC_DEBUG("Handshake IO continue\n"); ! 107: vnc_start_vencrypt_handshake(vs); ! 108: } ! 109: ! 110: ! 111: ! 112: #define NEED_X509_AUTH(vs) \ ! 113: ((vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509NONE || \ ! 114: (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509VNC || \ ! 115: (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509PLAIN || \ ! 116: (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL) ! 117: ! 118: ! 119: static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len) ! 120: { ! 121: int auth = read_u32(data, 0); ! 122: ! 123: if (auth != vs->vd->subauth) { ! 124: VNC_DEBUG("Rejecting auth %d\n", auth); ! 125: vnc_write_u8(vs, 0); /* Reject auth */ ! 126: vnc_flush(vs); ! 127: vnc_client_error(vs); ! 128: } else { ! 129: VNC_DEBUG("Accepting auth %d, setting up TLS for handshake\n", auth); ! 130: vnc_write_u8(vs, 1); /* Accept auth */ ! 131: vnc_flush(vs); ! 132: ! 133: if (vnc_tls_client_setup(vs, NEED_X509_AUTH(vs)) < 0) { ! 134: VNC_DEBUG("Failed to setup TLS\n"); ! 135: return 0; ! 136: } ! 137: ! 138: VNC_DEBUG("Start TLS VeNCrypt handshake process\n"); ! 139: if (vnc_start_vencrypt_handshake(vs) < 0) { ! 140: VNC_DEBUG("Failed to start TLS handshake\n"); ! 141: return 0; ! 142: } ! 143: } ! 144: return 0; ! 145: } ! 146: ! 147: static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len) ! 148: { ! 149: if (data[0] != 0 || ! 150: data[1] != 2) { ! 151: VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]); ! 152: vnc_write_u8(vs, 1); /* Reject version */ ! 153: vnc_flush(vs); ! 154: vnc_client_error(vs); ! 155: } else { ! 156: VNC_DEBUG("Sending allowed auth %d\n", vs->vd->subauth); ! 157: vnc_write_u8(vs, 0); /* Accept version */ ! 158: vnc_write_u8(vs, 1); /* Number of sub-auths */ ! 159: vnc_write_u32(vs, vs->vd->subauth); /* The supported auth */ ! 160: vnc_flush(vs); ! 161: vnc_read_when(vs, protocol_client_vencrypt_auth, 4); ! 162: } ! 163: return 0; ! 164: } ! 165: ! 166: ! 167: void start_auth_vencrypt(VncState *vs) ! 168: { ! 169: /* Send VeNCrypt version 0.2 */ ! 170: vnc_write_u8(vs, 0); ! 171: vnc_write_u8(vs, 2); ! 172: ! 173: vnc_read_when(vs, protocol_client_vencrypt_init, 2); ! 174: } ! 175:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.