diff options
author | Tim Hardeck <thardeck@suse.de> | 2013-04-23 16:33:01 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2013-05-03 12:04:57 -0500 |
commit | 0057a0d59006d00c294de0b012d9a290eb1a5c80 (patch) | |
tree | 5eb08a6086fe37394127fb6eb97b9141025061a6 /ui/vnc.c | |
parent | 8f3b664f6cc4153cc73941c941d54c4e499b7537 (diff) |
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.c')
-rw-r--r-- | ui/vnc.c | 86 |
1 files changed, 67 insertions, 19 deletions
@@ -1111,6 +1111,23 @@ void vnc_client_error(VncState *vs) vnc_disconnect_start(vs); } +#ifdef CONFIG_VNC_TLS +static long vnc_client_write_tls(gnutls_session_t *session, + const uint8_t *data, + size_t datalen) +{ + long ret = gnutls_write(*session, data, datalen); + if (ret < 0) { + if (ret == GNUTLS_E_AGAIN) { + errno = EAGAIN; + } else { + errno = EIO; + } + ret = -1; + } + return ret; +} +#endif /* CONFIG_VNC_TLS */ /* * Called to write a chunk of data to the client socket. The data may @@ -1132,17 +1149,20 @@ long vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen) long ret; #ifdef CONFIG_VNC_TLS if (vs->tls.session) { - ret = gnutls_write(vs->tls.session, data, datalen); - if (ret < 0) { - if (ret == GNUTLS_E_AGAIN) - errno = EAGAIN; - else - errno = EIO; - ret = -1; + ret = vnc_client_write_tls(&vs->tls.session, data, datalen); + } else { +#ifdef CONFIG_VNC_WS + if (vs->ws_tls.session) { + ret = vnc_client_write_tls(&vs->ws_tls.session, data, datalen); + } else +#endif /* CONFIG_VNC_WS */ +#endif /* CONFIG_VNC_TLS */ + { + ret = send(vs->csock, (const void *)data, datalen, 0); } - } else +#ifdef CONFIG_VNC_TLS + } #endif /* CONFIG_VNC_TLS */ - ret = send(vs->csock, (const void *)data, datalen, 0); VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret); return vnc_client_io_error(vs, ret, socket_error()); } @@ -1240,6 +1260,22 @@ void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting) vs->read_handler_expect = expecting; } +#ifdef CONFIG_VNC_TLS +static long vnc_client_read_tls(gnutls_session_t *session, uint8_t *data, + size_t datalen) +{ + long ret = gnutls_read(*session, data, datalen); + if (ret < 0) { + if (ret == GNUTLS_E_AGAIN) { + errno = EAGAIN; + } else { + errno = EIO; + } + ret = -1; + } + return ret; +} +#endif /* CONFIG_VNC_TLS */ /* * Called to read a chunk of data from the client socket. The data may @@ -1261,17 +1297,20 @@ long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen) long ret; #ifdef CONFIG_VNC_TLS if (vs->tls.session) { - ret = gnutls_read(vs->tls.session, data, datalen); - if (ret < 0) { - if (ret == GNUTLS_E_AGAIN) - errno = EAGAIN; - else - errno = EIO; - ret = -1; + ret = vnc_client_read_tls(&vs->tls.session, data, datalen); + } else { +#ifdef CONFIG_VNC_WS + if (vs->ws_tls.session) { + ret = vnc_client_read_tls(&vs->ws_tls.session, data, datalen); + } else +#endif /* CONFIG_VNC_WS */ +#endif /* CONFIG_VNC_TLS */ + { + ret = qemu_recv(vs->csock, data, datalen, 0); } - } else +#ifdef CONFIG_VNC_TLS + } #endif /* CONFIG_VNC_TLS */ - ret = qemu_recv(vs->csock, data, datalen, 0); VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret); return vnc_client_io_error(vs, ret, socket_error()); } @@ -2761,7 +2800,16 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket) #ifdef CONFIG_VNC_WS if (websocket) { vs->websocket = 1; - qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs); +#ifdef CONFIG_VNC_TLS + if (vd->tls.x509cert) { + qemu_set_fd_handler2(vs->csock, NULL, vncws_tls_handshake_peek, + NULL, vs); + } else +#endif /* CONFIG_VNC_TLS */ + { + qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, + NULL, vs); + } } else #endif /* CONFIG_VNC_WS */ { |