--- xen-4.2.2.orig/tools/qemu-xen/ui/vnc-ws.c +++ xen-4.2.2/tools/qemu-xen/ui/vnc-ws.c @@ -20,7 +20,7 @@ #include "vnc.h" -void vncws_handshake_read(void *opaque) +static void vncws_handshake_read_impl(void *opaque) { VncState *vs = opaque; uint8_t *handshake_end; @@ -46,6 +46,78 @@ } } +#ifdef CONFIG_VNC_TLS +static void vncws_tls_handshake_io(void *opaque); + +int vncws_tls_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, vncws_tls_handshake_io, NULL, vs); + else + qemu_set_fd_handler(vs->csock, NULL, vncws_tls_handshake_io, vs); + return 0; + } + VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret)); + vnc_client_error(vs); + return -1; + } + + if (vs->vd->tls.x509verify) { + if (vnc_tls_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 and waiting for HTTPS upgrade\n"); + vs->tls.wiremode = VNC_WIREMODE_TLS; + qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read_impl, NULL, vs); + + return 0; +} + +static void vncws_tls_handshake_io(void *opaque) { + struct VncState *vs = (struct VncState *)opaque; + + VNC_DEBUG("Handshake IO continues\n"); + vncws_tls_handshake(vs); +} + +#define NEED_X509_AUTH(vs) \ + ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE || \ + (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC || \ + (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN || \ + (vs)->subauth == VNC_AUTH_VENCRYPT_X509SASL) +#endif + +void vncws_handshake_read(void *opaque) +{ + VncState *vs = opaque; + +#ifdef CONFIG_VNC_TLS + if (!vs->vd->want_tls) + return vncws_handshake_read_impl(vs); + + if (vnc_tls_client_setup(vs, NEED_X509_AUTH(vs)) < 0) { + VNC_DEBUG("Failed to setup TLS\n"); + return 0; + } + + if (vncws_tls_handshake(vs) < 0) { + VNC_DEBUG("Failed to start TLS handshake\n"); + return 0; + } +#else + vncws_handshake_read_impl(vs); +#endif +} long vnc_client_read_ws(VncState *vs) { --- xen-4.2.2.orig/tools/qemu-xen/ui/vnc.c +++ xen-4.2.2/tools/qemu-xen/ui/vnc.c @@ -2897,6 +2897,9 @@ } else if (strncmp(options, "x509", 4) == 0) { char *start, *end; x509 = 1; /* Require x509 certificates */ +#ifdef CONFIG_VNC_WS + vs->want_tls = true; +#endif if (strncmp(options, "x509verify", 10) == 0) vs->tls.x509verify = 1; /* ...and verify client certs */ --- xen-4.2.2.orig/tools/qemu-xen/ui/vnc.h +++ xen-4.2.2/tools/qemu-xen/ui/vnc.h @@ -157,6 +157,9 @@ bool lossy; bool non_adaptive; #ifdef CONFIG_VNC_TLS +#ifdef CONFIG_VNC_WS + bool want_tls; +#endif int subauth; /* Used by VeNCrypt */ VncDisplayTLS tls; #endif