File:  [Qemu by Fabrice Bellard] / qemu / vnc-auth-vencrypt.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:20:20 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0125, qemu0124, qemu0123, qemu0122, qemu0121, qemu0120, qemu0111, qemu0110, HEAD
qemu 0.11.0

    1: /*
    2:  * QEMU VNC display driver: VeNCrypt authentication setup
    3:  *
    4:  * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
    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: 

unix.superglobalmegacorp.com