summaryrefslogtreecommitdiff
path: root/ui/vnc-ws.c
diff options
context:
space:
mode:
authorTim Hardeck <thardeck@suse.de>2013-04-23 16:33:01 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2013-05-03 12:04:57 -0500
commit0057a0d59006d00c294de0b012d9a290eb1a5c80 (patch)
tree5eb08a6086fe37394127fb6eb97b9141025061a6 /ui/vnc-ws.c
parent8f3b664f6cc4153cc73941c941d54c4e499b7537 (diff)
downloadqemu-0057a0d59006d00c294de0b012d9a290eb1a5c80.tar.gz
TLS support for VNC Websockets
Added TLS support to the VNC QEMU Websockets implementation. VNC-TLS needs to be enabled for this feature to be used. The required certificates are specified as in case of VNC-TLS with the VNC parameter "x509=<path>". If the server certificate isn't signed by a rooth authority it needs to be manually imported in the browser because at least in case of Firefox and Chrome there is no user dialog, the connection just gets canceled. As a side note VEncrypt over Websocket doesn't work atm because TLS can't be stacked in the current implementation. (It also didn't work before) Nevertheless to my knowledge there is no HTML 5 VNC client which supports it and the Websocket connection can be encrypted with regular TLS now so it should be fine for most use cases. Signed-off-by: Tim Hardeck <thardeck@suse.de> Reviewed-by: Anthony Liguori <aliguori@us.ibm.com> Message-id: 1366727581-5772-1-git-send-email-thardeck@suse.de Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'ui/vnc-ws.c')
-rw-r--r--ui/vnc-ws.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
index 3e3020916c..df89315733 100644
--- a/ui/vnc-ws.c
+++ b/ui/vnc-ws.c
@@ -20,6 +20,69 @@
#include "vnc.h"
+#ifdef CONFIG_VNC_TLS
+#include "qemu/sockets.h"
+
+static void vncws_tls_handshake_io(void *opaque);
+
+static int vncws_start_tls_handshake(struct VncState *vs)
+{
+ int ret = gnutls_handshake(vs->ws_tls.session);
+
+ if (ret < 0) {
+ if (!gnutls_error_is_fatal(ret)) {
+ VNC_DEBUG("Handshake interrupted (blocking)\n");
+ if (!gnutls_record_get_direction(vs->ws_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;
+ }
+
+ VNC_DEBUG("Handshake done, switching to TLS data mode\n");
+ vs->ws_tls.wiremode = VNC_WIREMODE_TLS;
+ qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs);
+
+ return 0;
+}
+
+static void vncws_tls_handshake_io(void *opaque)
+{
+ struct VncState *vs = (struct VncState *)opaque;
+
+ VNC_DEBUG("Handshake IO continue\n");
+ vncws_start_tls_handshake(vs);
+}
+
+void vncws_tls_handshake_peek(void *opaque)
+{
+ VncState *vs = opaque;
+ long ret;
+
+ if (!vs->ws_tls.session) {
+ char peek[4];
+ ret = qemu_recv(vs->csock, peek, sizeof(peek), MSG_PEEK);
+ if (ret && (strncmp(peek, "\x16", 1) == 0
+ || strncmp(peek, "\x80", 1) == 0)) {
+ VNC_DEBUG("TLS Websocket connection recognized");
+ vnc_tls_client_setup(vs, 1);
+ vncws_start_tls_handshake(vs);
+ } else {
+ vncws_handshake_read(vs);
+ }
+ } else {
+ qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs);
+ }
+}
+#endif /* CONFIG_VNC_TLS */
+
void vncws_handshake_read(void *opaque)
{
VncState *vs = opaque;