qemu/ui/vnc-auth-vencrypt.c
<<
>>
Prefs
   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#include "qemu/main-loop.h"
  29
  30static void start_auth_vencrypt_subauth(VncState *vs)
  31{
  32    switch (vs->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      start_auth_sasl(vs);
  51      break;
  52#endif /* CONFIG_VNC_SASL */
  53
  54    default: /* Should not be possible, but just in case */
  55       VNC_DEBUG("Reject subauth %d server bug\n", vs->auth);
  56       vnc_write_u8(vs, 1);
  57       if (vs->minor >= 8) {
  58           static const char err[] = "Unsupported authentication type";
  59           vnc_write_u32(vs, sizeof(err));
  60           vnc_write(vs, err, sizeof(err));
  61       }
  62       vnc_client_error(vs);
  63    }
  64}
  65
  66static void vnc_tls_handshake_io(void *opaque);
  67
  68static int vnc_start_vencrypt_handshake(struct VncState *vs) {
  69    int ret;
  70
  71    if ((ret = gnutls_handshake(vs->tls.session)) < 0) {
  72       if (!gnutls_error_is_fatal(ret)) {
  73           VNC_DEBUG("Handshake interrupted (blocking)\n");
  74           if (!gnutls_record_get_direction(vs->tls.session))
  75               qemu_set_fd_handler(vs->csock, vnc_tls_handshake_io, NULL, vs);
  76           else
  77               qemu_set_fd_handler(vs->csock, NULL, vnc_tls_handshake_io, vs);
  78           return 0;
  79       }
  80       VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
  81       vnc_client_error(vs);
  82       return -1;
  83    }
  84
  85    if (vs->vd->tls.x509verify) {
  86        if (vnc_tls_validate_certificate(vs) < 0) {
  87            VNC_DEBUG("Client verification failed\n");
  88            vnc_client_error(vs);
  89            return -1;
  90        } else {
  91            VNC_DEBUG("Client verification passed\n");
  92        }
  93    }
  94
  95    VNC_DEBUG("Handshake done, switching to TLS data mode\n");
  96    vs->tls.wiremode = VNC_WIREMODE_TLS;
  97    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
  98
  99    start_auth_vencrypt_subauth(vs);
 100
 101    return 0;
 102}
 103
 104static void vnc_tls_handshake_io(void *opaque) {
 105    struct VncState *vs = (struct VncState *)opaque;
 106
 107    VNC_DEBUG("Handshake IO continue\n");
 108    vnc_start_vencrypt_handshake(vs);
 109}
 110
 111
 112
 113#define NEED_X509_AUTH(vs)                              \
 114    ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
 115     (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
 116     (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN ||  \
 117     (vs)->subauth == VNC_AUTH_VENCRYPT_X509SASL)
 118
 119
 120static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
 121{
 122    int auth = read_u32(data, 0);
 123
 124    if (auth != vs->subauth) {
 125        VNC_DEBUG("Rejecting auth %d\n", auth);
 126        vnc_write_u8(vs, 0); /* Reject auth */
 127        vnc_flush(vs);
 128        vnc_client_error(vs);
 129    } else {
 130        VNC_DEBUG("Accepting auth %d, setting up TLS for handshake\n", auth);
 131        vnc_write_u8(vs, 1); /* Accept auth */
 132        vnc_flush(vs);
 133
 134        if (vnc_tls_client_setup(vs, NEED_X509_AUTH(vs)) < 0) {
 135            VNC_DEBUG("Failed to setup TLS\n");
 136            return 0;
 137        }
 138
 139        VNC_DEBUG("Start TLS VeNCrypt handshake process\n");
 140        if (vnc_start_vencrypt_handshake(vs) < 0) {
 141            VNC_DEBUG("Failed to start TLS handshake\n");
 142            return 0;
 143        }
 144    }
 145    return 0;
 146}
 147
 148static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len)
 149{
 150    if (data[0] != 0 ||
 151        data[1] != 2) {
 152        VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]);
 153        vnc_write_u8(vs, 1); /* Reject version */
 154        vnc_flush(vs);
 155        vnc_client_error(vs);
 156    } else {
 157        VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
 158        vnc_write_u8(vs, 0); /* Accept version */
 159        vnc_write_u8(vs, 1); /* Number of sub-auths */
 160        vnc_write_u32(vs, vs->subauth); /* The supported auth */
 161        vnc_flush(vs);
 162        vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
 163    }
 164    return 0;
 165}
 166
 167
 168void start_auth_vencrypt(VncState *vs)
 169{
 170    /* Send VeNCrypt version 0.2 */
 171    vnc_write_u8(vs, 0);
 172    vnc_write_u8(vs, 2);
 173
 174    vnc_read_when(vs, protocol_client_vencrypt_init, 2);
 175}
 176
 177