qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [6723] Move TLS auth into separate file ("Daniel P.


From: Anthony Liguori
Subject: [Qemu-devel] [6723] Move TLS auth into separate file ("Daniel P.
Date: Fri, 06 Mar 2009 20:27:23 +0000

Revision: 6723
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6723
Author:   aliguori
Date:     2009-03-06 20:27:23 +0000 (Fri, 06 Mar 2009)
Log Message:
-----------
Move TLS auth into separate file ("Daniel P. Berrange")

This patch refactors the existing TLS code to make the main VNC code
more managable. The code moves to two new files

 - vnc-tls.c: generic helpers for TLS handshake & credential setup
 - vnc-auth-vencrypt.c: the actual VNC TLS authentication mechanism.

The reason for this split is that there are other TLS based auth
mechanisms which we may like to use in the future. These can all
share the same vnc-tls.c routines. In addition this will facilitate
anyone who may want to port the vnc-tls.c file to allow for choice
of GNUTLS & NSS for impl.

The TLS state is moved out of the VncState struct, and into a separate
VncStateTLS struct, defined in vnc-tls.h. This is then referenced from
the main VncState. End size of the struct is the same, but it keeps
things a little more managable.

The vnc.h file gains a bunch more function prototypes, for functions
in vnc.c that were previously static, but now need to be accessed
from the separate auth code files.

The only TLS related code still in the main vl.c is the command line
argument handling / setup, and the low level I/O routines calling
gnutls_send/recv.


 Makefile              |   11 
 b/vnc-auth-vencrypt.c |  167 ++++++++++++++
 b/vnc-auth-vencrypt.h |   33 ++
 b/vnc-tls.c           |  414 +++++++++++++++++++++++++++++++++++
 b/vnc-tls.h           |   70 ++++++
 vnc.c                 |  581 +++-----------------------------------------------
 vnc.h                 |   76 ++++--
 7 files changed, 780 insertions(+), 572 deletions(-)

   Signed-off-by: Daniel P. Berrange <address@hidden>
Signed-off-by: Anthony Liguori <address@hidden>

Modified Paths:
--------------
    trunk/Makefile
    trunk/vnc.c
    trunk/vnc.h

Modified: trunk/Makefile
===================================================================
--- trunk/Makefile      2009-03-06 20:27:13 UTC (rev 6722)
+++ trunk/Makefile      2009-03-06 20:27:23 UTC (rev 6723)
@@ -145,6 +145,9 @@
 OBJS+=curses.o
 endif
 OBJS+=vnc.o d3des.o
+ifdef CONFIG_VNC_TLS
+OBJS+=vnc-tls.o vnc-auth-vencrypt.o
+endif
 
 ifdef CONFIG_COCOA
 OBJS+=cocoa.o
@@ -168,10 +171,16 @@
 
 sdl.o audio/sdlaudio.o: CFLAGS += $(SDL_CFLAGS)
 
-vnc.o: vnc.c keymaps.h sdl_keysym.h vnchextile.h d3des.c d3des.h
+vnc.h: vnc-tls.h vnc-auth-vencrypt.h keymaps.h
 
+vnc.o: vnc.c vnc.h vnc_keysym.h vnchextile.h d3des.c d3des.h
+
 vnc.o: CFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
 
+vnc-tls.o: vnc-tls.c vnc.h
+
+vnc-auth-vencrypt.o: vnc-auth-vencrypt.c vnc.h
+
 curses.o: curses.c keymaps.h curses_keys.h
 
 bt-host.o: CFLAGS += $(CONFIG_BLUEZ_CFLAGS)

Modified: trunk/vnc.c
===================================================================
--- trunk/vnc.c 2009-03-06 20:27:13 UTC (rev 6722)
+++ trunk/vnc.c 2009-03-06 20:27:23 UTC (rev 6723)
@@ -34,21 +34,6 @@
 #include "vnc_keysym.h"
 #include "d3des.h"
 
-// #define _VNC_DEBUG 1
-
-#ifdef _VNC_DEBUG
-#define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while 
(0)
-
-#if defined(CONFIG_VNC_TLS) && _VNC_DEBUG >= 2
-/* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
-static void vnc_debug_gnutls_log(int level, const char* str) {
-    VNC_DEBUG("%d %s", level, str);
-}
-#endif /* CONFIG_VNC_TLS && _VNC_DEBUG */
-#else
-#define VNC_DEBUG(fmt, ...) do { } while (0)
-#endif
-
 #define count_bits(c, v) { \
     for (c = 0; v; v >>= 1) \
     { \
@@ -204,14 +189,7 @@
    3) resolutions > 1024
 */
 
-static void vnc_write(VncState *vs, const void *data, size_t len);
-static void vnc_write_u32(VncState *vs, uint32_t value);
-static void vnc_write_s32(VncState *vs, int32_t value);
-static void vnc_write_u16(VncState *vs, uint16_t value);
-static void vnc_write_u8(VncState *vs, uint8_t value);
-static void vnc_flush(VncState *vs);
 static void vnc_update_client(void *opaque);
-static void vnc_client_read(void *opaque);
 
 static void vnc_colordepth(VncState *vs);
 
@@ -868,10 +846,7 @@
         if (vs->input.buffer) qemu_free(vs->input.buffer);
         if (vs->output.buffer) qemu_free(vs->output.buffer);
 #ifdef CONFIG_VNC_TLS
-       if (vs->tls_session) {
-           gnutls_deinit(vs->tls_session);
-           vs->tls_session = NULL;
-       }
+       vnc_tls_client_cleanup(vs);
 #endif /* CONFIG_VNC_TLS */
         audio_del(vs);
 
@@ -897,19 +872,20 @@
     return ret;
 }
 
-static void vnc_client_error(VncState *vs)
+
+void vnc_client_error(VncState *vs)
 {
     vnc_client_io_error(vs, -1, EINVAL);
 }
 
-static void vnc_client_write(void *opaque)
+void vnc_client_write(void *opaque)
 {
     long ret;
     VncState *vs = opaque;
 
 #ifdef CONFIG_VNC_TLS
-    if (vs->tls_session) {
-       ret = gnutls_write(vs->tls_session, vs->output.buffer, 
vs->output.offset);
+    if (vs->tls.session) {
+       ret = gnutls_write(vs->tls.session, vs->output.buffer, 
vs->output.offset);
        if (ret < 0) {
            if (ret == GNUTLS_E_AGAIN)
                errno = EAGAIN;
@@ -932,13 +908,13 @@
     }
 }
 
-static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
+void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
 {
     vs->read_handler = func;
     vs->read_handler_expect = expecting;
 }
 
-static void vnc_client_read(void *opaque)
+void vnc_client_read(void *opaque)
 {
     VncState *vs = opaque;
     long ret;
@@ -946,8 +922,8 @@
     buffer_reserve(&vs->input, 4096);
 
 #ifdef CONFIG_VNC_TLS
-    if (vs->tls_session) {
-       ret = gnutls_read(vs->tls_session, buffer_end(&vs->input), 4096);
+    if (vs->tls.session) {
+       ret = gnutls_read(vs->tls.session, buffer_end(&vs->input), 4096);
        if (ret < 0) {
            if (ret == GNUTLS_E_AGAIN)
                errno = EAGAIN;
@@ -981,7 +957,7 @@
     }
 }
 
-static void vnc_write(VncState *vs, const void *data, size_t len)
+void vnc_write(VncState *vs, const void *data, size_t len)
 {
     buffer_reserve(&vs->output, len);
 
@@ -992,12 +968,12 @@
     buffer_append(&vs->output, data, len);
 }
 
-static void vnc_write_s32(VncState *vs, int32_t value)
+void vnc_write_s32(VncState *vs, int32_t value)
 {
     vnc_write_u32(vs, *(uint32_t *)&value);
 }
 
-static void vnc_write_u32(VncState *vs, uint32_t value)
+void vnc_write_u32(VncState *vs, uint32_t value)
 {
     uint8_t buf[4];
 
@@ -1009,7 +985,7 @@
     vnc_write(vs, buf, 4);
 }
 
-static void vnc_write_u16(VncState *vs, uint16_t value)
+void vnc_write_u16(VncState *vs, uint16_t value)
 {
     uint8_t buf[2];
 
@@ -1019,74 +995,39 @@
     vnc_write(vs, buf, 2);
 }
 
-static void vnc_write_u8(VncState *vs, uint8_t value)
+void vnc_write_u8(VncState *vs, uint8_t value)
 {
     vnc_write(vs, (char *)&value, 1);
 }
 
-static void vnc_flush(VncState *vs)
+void vnc_flush(VncState *vs)
 {
     if (vs->output.offset)
        vnc_client_write(vs);
 }
 
-static uint8_t read_u8(uint8_t *data, size_t offset)
+uint8_t read_u8(uint8_t *data, size_t offset)
 {
     return data[offset];
 }
 
-static uint16_t read_u16(uint8_t *data, size_t offset)
+uint16_t read_u16(uint8_t *data, size_t offset)
 {
     return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
 }
 
-static int32_t read_s32(uint8_t *data, size_t offset)
+int32_t read_s32(uint8_t *data, size_t offset)
 {
     return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
                     (data[offset + 2] << 8) | data[offset + 3]);
 }
 
-static uint32_t read_u32(uint8_t *data, size_t offset)
+uint32_t read_u32(uint8_t *data, size_t offset)
 {
     return ((data[offset] << 24) | (data[offset + 1] << 16) |
            (data[offset + 2] << 8) | data[offset + 3]);
 }
 
-#ifdef CONFIG_VNC_TLS
-static ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
-                            const void *data,
-                            size_t len) {
-    struct VncState *vs = (struct VncState *)transport;
-    int ret;
-
- retry:
-    ret = send(vs->csock, data, len, 0);
-    if (ret < 0) {
-       if (errno == EINTR)
-           goto retry;
-       return -1;
-    }
-    return ret;
-}
-
-
-static ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
-                            void *data,
-                            size_t len) {
-    struct VncState *vs = (struct VncState *)transport;
-    int ret;
-
- retry:
-    ret = recv(vs->csock, data, len, 0);
-    if (ret < 0) {
-       if (errno == EINTR)
-           goto retry;
-       return -1;
-    }
-    return ret;
-}
-#endif /* CONFIG_VNC_TLS */
-
 static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
 {
 }
@@ -1669,6 +1610,11 @@
     return 0;
 }
 
+void start_client_init(VncState *vs)
+{
+    vnc_read_when(vs, protocol_client_init, 1);
+}
+
 static void make_challenge(VncState *vs)
 {
     int i;
@@ -1724,12 +1670,12 @@
        vnc_write_u32(vs, 0); /* Accept auth */
        vnc_flush(vs);
 
-       vnc_read_when(vs, protocol_client_init, 1);
+        start_client_init(vs);
     }
     return 0;
 }
 
-static int start_auth_vnc(VncState *vs)
+void start_auth_vnc(VncState *vs)
 {
     make_challenge(vs);
     /* Send client a 'random' challenge */
@@ -1737,411 +1683,9 @@
     vnc_flush(vs);
 
     vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
-    return 0;
 }
 
 
-#ifdef CONFIG_VNC_TLS
-#define DH_BITS 1024
-static gnutls_dh_params_t dh_params;
-
-static int vnc_tls_initialize(void)
-{
-    static int tlsinitialized = 0;
-
-    if (tlsinitialized)
-       return 1;
-
-    if (gnutls_global_init () < 0)
-       return 0;
-
-    /* XXX ought to re-generate diffie-hellmen params periodically */
-    if (gnutls_dh_params_init (&dh_params) < 0)
-       return 0;
-    if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
-       return 0;
-
-#if defined(_VNC_DEBUG) && _VNC_DEBUG >= 2
-    gnutls_global_set_log_level(10);
-    gnutls_global_set_log_function(vnc_debug_gnutls_log);
-#endif
-
-    tlsinitialized = 1;
-
-    return 1;
-}
-
-static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
-{
-    gnutls_anon_server_credentials anon_cred;
-    int ret;
-
-    if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
-       VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
-       return NULL;
-    }
-
-    gnutls_anon_set_server_dh_params(anon_cred, dh_params);
-
-    return anon_cred;
-}
-
-
-static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState 
*vs)
-{
-    gnutls_certificate_credentials_t x509_cred;
-    int ret;
-
-    if (!vs->vd->x509cacert) {
-       VNC_DEBUG("No CA x509 certificate specified\n");
-       return NULL;
-    }
-    if (!vs->vd->x509cert) {
-       VNC_DEBUG("No server x509 certificate specified\n");
-       return NULL;
-    }
-    if (!vs->vd->x509key) {
-       VNC_DEBUG("No server private key specified\n");
-       return NULL;
-    }
-
-    if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
-       VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
-       return NULL;
-    }
-    if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
-                                                     vs->vd->x509cacert,
-                                                     GNUTLS_X509_FMT_PEM)) < 
0) {
-       VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
-       gnutls_certificate_free_credentials(x509_cred);
-       return NULL;
-    }
-
-    if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
-                                                    vs->vd->x509cert,
-                                                    vs->vd->x509key,
-                                                    GNUTLS_X509_FMT_PEM)) < 0) 
{
-       VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
-       gnutls_certificate_free_credentials(x509_cred);
-       return NULL;
-    }
-
-    if (vs->vd->x509cacrl) {
-       if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
-                                                       vs->vd->x509cacrl,
-                                                       GNUTLS_X509_FMT_PEM)) < 
0) {
-           VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
-           gnutls_certificate_free_credentials(x509_cred);
-           return NULL;
-       }
-    }
-
-    gnutls_certificate_set_dh_params (x509_cred, dh_params);
-
-    return x509_cred;
-}
-
-static int vnc_validate_certificate(struct VncState *vs)
-{
-    int ret;
-    unsigned int status;
-    const gnutls_datum_t *certs;
-    unsigned int nCerts, i;
-    time_t now;
-
-    VNC_DEBUG("Validating client certificate\n");
-    if ((ret = gnutls_certificate_verify_peers2 (vs->tls_session, &status)) < 
0) {
-       VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret));
-       return -1;
-    }
-
-    if ((now = time(NULL)) == ((time_t)-1)) {
-       return -1;
-    }
-
-    if (status != 0) {
-       if (status & GNUTLS_CERT_INVALID)
-           VNC_DEBUG("The certificate is not trusted.\n");
-
-       if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
-           VNC_DEBUG("The certificate hasn't got a known issuer.\n");
-
-       if (status & GNUTLS_CERT_REVOKED)
-           VNC_DEBUG("The certificate has been revoked.\n");
-
-       if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
-           VNC_DEBUG("The certificate uses an insecure algorithm\n");
-
-       return -1;
-    } else {
-       VNC_DEBUG("Certificate is valid!\n");
-    }
-
-    /* Only support x509 for now */
-    if (gnutls_certificate_type_get(vs->tls_session) != GNUTLS_CRT_X509)
-       return -1;
-
-    if (!(certs = gnutls_certificate_get_peers(vs->tls_session, &nCerts)))
-       return -1;
-
-    for (i = 0 ; i < nCerts ; i++) {
-       gnutls_x509_crt_t cert;
-       VNC_DEBUG ("Checking certificate chain %d\n", i);
-       if (gnutls_x509_crt_init (&cert) < 0)
-           return -1;
-
-       if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
-           gnutls_x509_crt_deinit (cert);
-           return -1;
-       }
-
-       if (gnutls_x509_crt_get_expiration_time (cert) < now) {
-           VNC_DEBUG("The certificate has expired\n");
-           gnutls_x509_crt_deinit (cert);
-           return -1;
-       }
-
-       if (gnutls_x509_crt_get_activation_time (cert) > now) {
-           VNC_DEBUG("The certificate is not yet activated\n");
-           gnutls_x509_crt_deinit (cert);
-           return -1;
-       }
-
-       if (gnutls_x509_crt_get_activation_time (cert) > now) {
-           VNC_DEBUG("The certificate is not yet activated\n");
-           gnutls_x509_crt_deinit (cert);
-           return -1;
-       }
-
-       gnutls_x509_crt_deinit (cert);
-    }
-
-    return 0;
-}
-
-
-static int start_auth_vencrypt_subauth(VncState *vs)
-{
-    switch (vs->vd->subauth) {
-    case VNC_AUTH_VENCRYPT_TLSNONE:
-    case VNC_AUTH_VENCRYPT_X509NONE:
-       VNC_DEBUG("Accept TLS auth none\n");
-       vnc_write_u32(vs, 0); /* Accept auth completion */
-       vnc_read_when(vs, protocol_client_init, 1);
-       break;
-
-    case VNC_AUTH_VENCRYPT_TLSVNC:
-    case VNC_AUTH_VENCRYPT_X509VNC:
-       VNC_DEBUG("Start TLS auth VNC\n");
-       return start_auth_vnc(vs);
-
-    default: /* Should not be possible, but just in case */
-       VNC_DEBUG("Reject auth %d\n", vs->vd->auth);
-       vnc_write_u8(vs, 1);
-       if (vs->minor >= 8) {
-           static const char err[] = "Unsupported authentication type";
-           vnc_write_u32(vs, sizeof(err));
-           vnc_write(vs, err, sizeof(err));
-       }
-       vnc_client_error(vs);
-    }
-
-    return 0;
-}
-
-static void vnc_handshake_io(void *opaque);
-
-static int vnc_continue_handshake(struct VncState *vs) {
-    int ret;
-
-    if ((ret = gnutls_handshake(vs->tls_session)) < 0) {
-       if (!gnutls_error_is_fatal(ret)) {
-           VNC_DEBUG("Handshake interrupted (blocking)\n");
-           if (!gnutls_record_get_direction(vs->tls_session))
-               qemu_set_fd_handler(vs->csock, vnc_handshake_io, NULL, vs);
-           else
-               qemu_set_fd_handler(vs->csock, NULL, vnc_handshake_io, vs);
-           return 0;
-       }
-       VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
-       vnc_client_error(vs);
-       return -1;
-    }
-
-    if (vs->vd->x509verify) {
-       if (vnc_validate_certificate(vs) < 0) {
-           VNC_DEBUG("Client verification failed\n");
-           vnc_client_error(vs);
-           return -1;
-       } else {
-           VNC_DEBUG("Client verification passed\n");
-       }
-    }
-
-    VNC_DEBUG("Handshake done, switching to TLS data mode\n");
-    vs->wiremode = VNC_WIREMODE_TLS;
-    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, 
vs);
-
-    return start_auth_vencrypt_subauth(vs);
-}
-
-static void vnc_handshake_io(void *opaque) {
-    struct VncState *vs = (struct VncState *)opaque;
-
-    VNC_DEBUG("Handshake IO continue\n");
-    vnc_continue_handshake(vs);
-}
-
-#define NEED_X509_AUTH(vs)                           \
-    ((vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
-     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
-     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509PLAIN)
-
-
-static int vnc_start_tls(struct VncState *vs) {
-    static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
-    static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, 
GNUTLS_SSL3, 0 };
-    static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
-    static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, 
GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
-
-    VNC_DEBUG("Do TLS setup\n");
-    if (vnc_tls_initialize() < 0) {
-       VNC_DEBUG("Failed to init TLS\n");
-       vnc_client_error(vs);
-       return -1;
-    }
-    if (vs->tls_session == NULL) {
-       if (gnutls_init(&vs->tls_session, GNUTLS_SERVER) < 0) {
-           vnc_client_error(vs);
-           return -1;
-       }
-
-       if (gnutls_set_default_priority(vs->tls_session) < 0) {
-           gnutls_deinit(vs->tls_session);
-           vs->tls_session = NULL;
-           vnc_client_error(vs);
-           return -1;
-       }
-
-       if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ? 
kx_x509 : kx_anon) < 0) {
-           gnutls_deinit(vs->tls_session);
-           vs->tls_session = NULL;
-           vnc_client_error(vs);
-           return -1;
-       }
-
-       if (gnutls_certificate_type_set_priority(vs->tls_session, 
cert_type_priority) < 0) {
-           gnutls_deinit(vs->tls_session);
-           vs->tls_session = NULL;
-           vnc_client_error(vs);
-           return -1;
-       }
-
-       if (gnutls_protocol_set_priority(vs->tls_session, protocol_priority) < 
0) {
-           gnutls_deinit(vs->tls_session);
-           vs->tls_session = NULL;
-           vnc_client_error(vs);
-           return -1;
-       }
-
-       if (NEED_X509_AUTH(vs)) {
-           gnutls_certificate_server_credentials x509_cred = 
vnc_tls_initialize_x509_cred(vs);
-           if (!x509_cred) {
-               gnutls_deinit(vs->tls_session);
-               vs->tls_session = NULL;
-               vnc_client_error(vs);
-               return -1;
-           }
-           if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE, 
x509_cred) < 0) {
-               gnutls_deinit(vs->tls_session);
-               vs->tls_session = NULL;
-               gnutls_certificate_free_credentials(x509_cred);
-               vnc_client_error(vs);
-               return -1;
-           }
-           if (vs->vd->x509verify) {
-               VNC_DEBUG("Requesting a client certificate\n");
-               gnutls_certificate_server_set_request (vs->tls_session, 
GNUTLS_CERT_REQUEST);
-           }
-
-       } else {
-           gnutls_anon_server_credentials anon_cred = 
vnc_tls_initialize_anon_cred();
-           if (!anon_cred) {
-               gnutls_deinit(vs->tls_session);
-               vs->tls_session = NULL;
-               vnc_client_error(vs);
-               return -1;
-           }
-           if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, 
anon_cred) < 0) {
-               gnutls_deinit(vs->tls_session);
-               vs->tls_session = NULL;
-               gnutls_anon_free_server_credentials(anon_cred);
-               vnc_client_error(vs);
-               return -1;
-           }
-       }
-
-       gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
-       gnutls_transport_set_push_function(vs->tls_session, vnc_tls_push);
-       gnutls_transport_set_pull_function(vs->tls_session, vnc_tls_pull);
-    }
-
-    VNC_DEBUG("Start TLS handshake process\n");
-    return vnc_continue_handshake(vs);
-}
-
-static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t 
len)
-{
-    int auth = read_u32(data, 0);
-
-    if (auth != vs->vd->subauth) {
-       VNC_DEBUG("Rejecting auth %d\n", auth);
-       vnc_write_u8(vs, 0); /* Reject auth */
-       vnc_flush(vs);
-       vnc_client_error(vs);
-    } else {
-       VNC_DEBUG("Accepting auth %d, starting handshake\n", auth);
-       vnc_write_u8(vs, 1); /* Accept auth */
-       vnc_flush(vs);
-
-       if (vnc_start_tls(vs) < 0) {
-           VNC_DEBUG("Failed to complete TLS\n");
-           return 0;
-       }
-    }
-    return 0;
-}
-
-static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t 
len)
-{
-    if (data[0] != 0 ||
-       data[1] != 2) {
-       VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], 
(int)data[1]);
-       vnc_write_u8(vs, 1); /* Reject version */
-       vnc_flush(vs);
-       vnc_client_error(vs);
-    } else {
-       VNC_DEBUG("Sending allowed auth %d\n", vs->vd->subauth);
-       vnc_write_u8(vs, 0); /* Accept version */
-       vnc_write_u8(vs, 1); /* Number of sub-auths */
-       vnc_write_u32(vs, vs->vd->subauth); /* The supported auth */
-       vnc_flush(vs);
-       vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
-    }
-    return 0;
-}
-
-static int start_auth_vencrypt(VncState *vs)
-{
-    /* Send VeNCrypt version 0.2 */
-    vnc_write_u8(vs, 0);
-    vnc_write_u8(vs, 2);
-
-    vnc_read_when(vs, protocol_client_vencrypt_init, 2);
-    return 0;
-}
-#endif /* CONFIG_VNC_TLS */
-
 static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
 {
     /* We only advertise 1 auth scheme at a time, so client
@@ -2164,17 +1708,19 @@
                vnc_write_u32(vs, 0); /* Accept auth completion */
                vnc_flush(vs);
            }
-           vnc_read_when(vs, protocol_client_init, 1);
+           start_client_init(vs);
            break;
 
        case VNC_AUTH_VNC:
            VNC_DEBUG("Start VNC auth\n");
-           return start_auth_vnc(vs);
+           start_auth_vnc(vs);
+           break;
 
 #ifdef CONFIG_VNC_TLS
        case VNC_AUTH_VENCRYPT:
            VNC_DEBUG("Accept VeNCrypt auth\n");;
-           return start_auth_vencrypt(vs);
+           start_auth_vencrypt(vs);
+           break;
 #endif /* CONFIG_VNC_TLS */
 
        default: /* Should not be possible, but just in case */
@@ -2227,7 +1773,7 @@
             VNC_DEBUG("Tell client auth none\n");
             vnc_write_u32(vs, vs->vd->auth);
             vnc_flush(vs);
-            vnc_read_when(vs, protocol_client_init, 1);
+           start_client_init(vs);
        } else if (vs->vd->auth == VNC_AUTH_VNC) {
             VNC_DEBUG("Tell client VNC auth\n");
             vnc_write_u32(vs, vs->vd->auth);
@@ -2329,62 +1875,7 @@
     register_displaychangelistener(ds, dcl);
 }
 
-#ifdef CONFIG_VNC_TLS
-static int vnc_set_x509_credential(VncDisplay *vs,
-                                  const char *certdir,
-                                  const char *filename,
-                                  char **cred,
-                                  int ignoreMissing)
-{
-    struct stat sb;
 
-    if (*cred) {
-       qemu_free(*cred);
-       *cred = NULL;
-    }
-
-    *cred = qemu_malloc(strlen(certdir) + strlen(filename) + 2);
-
-    strcpy(*cred, certdir);
-    strcat(*cred, "/");
-    strcat(*cred, filename);
-
-    VNC_DEBUG("Check %s\n", *cred);
-    if (stat(*cred, &sb) < 0) {
-       qemu_free(*cred);
-       *cred = NULL;
-       if (ignoreMissing && errno == ENOENT)
-           return 0;
-       return -1;
-    }
-
-    return 0;
-}
-
-static int vnc_set_x509_credential_dir(VncDisplay *vs,
-                                      const char *certdir)
-{
-    if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, 
&vs->x509cacert, 0) < 0)
-       goto cleanup;
-    if (vnc_set_x509_credential(vs, certdir, X509_CA_CRL_FILE, &vs->x509cacrl, 
1) < 0)
-       goto cleanup;
-    if (vnc_set_x509_credential(vs, certdir, X509_SERVER_CERT_FILE, 
&vs->x509cert, 0) < 0)
-       goto cleanup;
-    if (vnc_set_x509_credential(vs, certdir, X509_SERVER_KEY_FILE, 
&vs->x509key, 0) < 0)
-       goto cleanup;
-
-    return 0;
-
- cleanup:
-    qemu_free(vs->x509cacert);
-    qemu_free(vs->x509cacrl);
-    qemu_free(vs->x509cert);
-    qemu_free(vs->x509key);
-    vs->x509cacert = vs->x509cacrl = vs->x509cert = vs->x509key = NULL;
-    return -1;
-}
-#endif /* CONFIG_VNC_TLS */
-
 void vnc_display_close(DisplayState *ds)
 {
     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
@@ -2403,7 +1894,7 @@
     vs->auth = VNC_AUTH_INVALID;
 #ifdef CONFIG_VNC_TLS
     vs->subauth = VNC_AUTH_INVALID;
-    vs->x509verify = 0;
+    vs->tls.x509verify = 0;
 #endif
 }
 
@@ -2459,7 +1950,7 @@
            char *start, *end;
            x509 = 1; /* Require x509 certificates */
            if (strncmp(options, "x509verify", 10) == 0)
-               vs->x509verify = 1; /* ...and verify client certs */
+               vs->tls.x509verify = 1; /* ...and verify client certs */
 
            /* Now check for 'x509=/some/path' postfix
             * and use that to setup x509 certificate/key paths */
@@ -2470,7 +1961,7 @@
                char *path = qemu_strndup(start + 1, len);
 
                VNC_DEBUG("Trying certificate path '%s'\n", path);
-               if (vnc_set_x509_credential_dir(vs, path) < 0) {
+               if (vnc_tls_set_x509_creds_dir(vs, path) < 0) {
                    fprintf(stderr, "Failed to find x509 certificates/keys in 
%s\n", path);
                    qemu_free(path);
                    qemu_free(vs->display);

Modified: trunk/vnc.h
===================================================================
--- trunk/vnc.h 2009-03-06 20:27:13 UTC (rev 6722)
+++ trunk/vnc.h 2009-03-06 20:27:23 UTC (rev 6723)
@@ -33,13 +33,16 @@
 #include "audio/audio.h"
 #include <zlib.h>
 
-#ifdef CONFIG_VNC_TLS
-#include <gnutls/gnutls.h>
-#include <gnutls/x509.h>
-#endif /* CONFIG_VNC_TLS */
-
 #include "keymaps.h"
 
+// #define _VNC_DEBUG 1
+
+#ifdef _VNC_DEBUG
+#define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while 
(0)
+#else
+#define VNC_DEBUG(fmt, ...) do { } while (0)
+#endif
+
 /*****************************************************************************
  *
  * Core data structures
@@ -73,6 +76,11 @@
 
 typedef struct VncDisplay VncDisplay;
 
+#ifdef CONFIG_VNC_TLS
+#include "vnc-tls.h"
+#include "vnc-auth-vencrypt.h"
+#endif
+
 struct VncDisplay
 {
     int lsock;
@@ -84,13 +92,8 @@
     char *password;
     int auth;
 #ifdef CONFIG_VNC_TLS
-    int subauth;
-    int x509verify;
-
-    char *x509cacert;
-    char *x509cacrl;
-    char *x509cert;
-    char *x509key;
+    int subauth; /* Used by VeNCrypt */
+    VncDisplayTLS tls;
 #endif
 };
 
@@ -118,8 +121,7 @@
     char challenge[VNC_AUTH_CHALLENGE_SIZE];
 
 #ifdef CONFIG_VNC_TLS
-    int wiremode;
-    gnutls_session_t tls_session;
+    VncStateTLS tls;
 #endif
 
     Buffer output;
@@ -163,13 +165,7 @@
     VNC_AUTH_VENCRYPT = 19
 };
 
-#ifdef CONFIG_VNC_TLS
 enum {
-    VNC_WIREMODE_CLEAR,
-    VNC_WIREMODE_TLS,
-};
-
-enum {
     VNC_AUTH_VENCRYPT_PLAIN = 256,
     VNC_AUTH_VENCRYPT_TLSNONE = 257,
     VNC_AUTH_VENCRYPT_TLSVNC = 258,
@@ -179,13 +175,7 @@
     VNC_AUTH_VENCRYPT_X509PLAIN = 262,
 };
 
-#define X509_CA_CERT_FILE "ca-cert.pem"
-#define X509_CA_CRL_FILE "ca-crl.pem"
-#define X509_SERVER_KEY_FILE "server-key.pem"
-#define X509_SERVER_CERT_FILE "server-cert.pem"
 
-#endif /* CONFIG_VNC_TLS */
-
 /*****************************************************************************
  *
  * Encoding types
@@ -255,4 +245,38 @@
 #define VNC_FEATURE_ZLIB_MASK                (1 << VNC_FEATURE_ZLIB)
 #define VNC_FEATURE_COPYRECT_MASK            (1 << VNC_FEATURE_COPYRECT)
 
+
+/*****************************************************************************
+ *
+ * Internal APIs
+ *
+ *****************************************************************************/
+
+/* Event loop functions */
+void vnc_client_read(void *opaque);
+void vnc_client_write(void *opaque);
+
+
+/* Protocol I/O functions */
+void vnc_write(VncState *vs, const void *data, size_t len);
+void vnc_write_u32(VncState *vs, uint32_t value);
+void vnc_write_s32(VncState *vs, int32_t value);
+void vnc_write_u16(VncState *vs, uint16_t value);
+void vnc_write_u8(VncState *vs, uint8_t value);
+void vnc_flush(VncState *vs);
+void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting);
+
+
+/* Buffer I/O functions */
+uint8_t read_u8(uint8_t *data, size_t offset);
+uint16_t read_u16(uint8_t *data, size_t offset);
+int32_t read_s32(uint8_t *data, size_t offset);
+uint32_t read_u32(uint8_t *data, size_t offset);
+
+/* Protocol stage functions */
+void vnc_client_error(VncState *vs);
+
+void start_client_init(VncState *vs);
+void start_auth_vnc(VncState *vs);
+
 #endif /* __QEMU_VNC_H */





reply via email to

[Prev in Thread] Current Thread [Next in Thread]