aboutsummaryrefslogtreecommitdiff
path: root/ui/vnc-ws.c
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2015-08-06 14:39:32 +0100
committerDaniel P. Berrange <berrange@redhat.com>2015-09-15 15:20:55 +0100
commit3e305e4a4752f70c0b5c3cf5b43ec957881714f7 (patch)
treee3ba8537a1753b436804b676aaddbdcc9448bb15 /ui/vnc-ws.c
parentfdd1ab6ad5c27a1564a1c73045908736b228458b (diff)
ui: convert VNC server to use QCryptoTLSSession
Switch VNC server over to using the QCryptoTLSSession object for the TLS session. This removes the direct use of gnutls from the VNC server code. It also removes most knowledge about TLS certificate handling from the VNC server code. This has the nice effect that all the CONFIG_VNC_TLS conditionals go away and the user gets an actual error message when requesting TLS instead of it being silently ignored. With this change, the existing configuration options for enabling TLS with -vnc are deprecated. Old syntax for anon-DH credentials: -vnc hostname:0,tls New syntax: -object tls-creds-anon,id=tls0,endpoint=server \ -vnc hostname:0,tls-creds=tls0 Old syntax for x509 credentials, no client certs: -vnc hostname:0,tls,x509=/path/to/certs New syntax: -object tls-creds-x509,id=tls0,dir=/path/to/certs,endpoint=server,verify-peer=no \ -vnc hostname:0,tls-creds=tls0 Old syntax for x509 credentials, requiring client certs: -vnc hostname:0,tls,x509verify=/path/to/certs New syntax: -object tls-creds-x509,id=tls0,dir=/path/to/certs,endpoint=server,verify-peer=yes \ -vnc hostname:0,tls-creds=tls0 This aligns VNC with the way TLS credentials are to be configured in the future for chardev, nbd and migration backends. It also has the benefit that the same TLS credentials can be shared across multiple VNC server instances, if desired. If someone uses the deprecated syntax, it will internally result in the creation of a 'tls-creds' object with an ID based on the VNC server ID. This allows backwards compat with the CLI syntax, while still deleting all the original TLS code from the VNC server. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Diffstat (limited to 'ui/vnc-ws.c')
-rw-r--r--ui/vnc-ws.c84
1 files changed, 47 insertions, 37 deletions
diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
index b4cb6bde70..175ea50b4b 100644
--- a/ui/vnc-ws.c
+++ b/ui/vnc-ws.c
@@ -22,60 +22,70 @@
#include "qemu/main-loop.h"
#include "crypto/hash.h"
-#ifdef CONFIG_VNC_TLS
-#include "qemu/sockets.h"
-
static int vncws_start_tls_handshake(VncState *vs)
{
- int ret = gnutls_handshake(vs->tls.session);
-
- if (ret < 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;
+ Error *err = NULL;
+
+ if (qcrypto_tls_session_handshake(vs->tls, &err) < 0) {
+ goto error;
}
- 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");
+ switch (qcrypto_tls_session_get_handshake_status(vs->tls)) {
+ case QCRYPTO_TLS_HANDSHAKE_COMPLETE:
+ VNC_DEBUG("Handshake done, checking credentials\n");
+ if (qcrypto_tls_session_check_credentials(vs->tls, &err) < 0) {
+ goto error;
}
+ VNC_DEBUG("Client verification passed, starting TLS I/O\n");
+ qemu_set_fd_handler(vs->csock, vncws_handshake_read, NULL, vs);
+ break;
+
+ case QCRYPTO_TLS_HANDSHAKE_RECVING:
+ VNC_DEBUG("Handshake interrupted (blocking read)\n");
+ qemu_set_fd_handler(vs->csock, vncws_tls_handshake_io, NULL, vs);
+ break;
+
+ case QCRYPTO_TLS_HANDSHAKE_SENDING:
+ VNC_DEBUG("Handshake interrupted (blocking write)\n");
+ qemu_set_fd_handler(vs->csock, NULL, vncws_tls_handshake_io, vs);
+ break;
}
- VNC_DEBUG("Handshake done, switching to TLS data mode\n");
- qemu_set_fd_handler(vs->csock, vncws_handshake_read, NULL, vs);
-
return 0;
+
+ error:
+ VNC_DEBUG("Handshake failed %s\n", error_get_pretty(err));
+ error_free(err);
+ vnc_client_error(vs);
+ return -1;
}
void vncws_tls_handshake_io(void *opaque)
{
VncState *vs = (VncState *)opaque;
+ Error *err = NULL;
- if (!vs->tls.session) {
- VNC_DEBUG("TLS Websocket setup\n");
- if (vnc_tls_client_setup(vs, vs->vd->tls.x509cert != NULL) < 0) {
- return;
- }
+ vs->tls = qcrypto_tls_session_new(vs->vd->tlscreds,
+ NULL,
+ vs->vd->tlsaclname,
+ QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
+ &err);
+ if (!vs->tls) {
+ VNC_DEBUG("Failed to setup TLS %s\n",
+ error_get_pretty(err));
+ error_free(err);
+ vnc_client_error(vs);
+ return;
}
- VNC_DEBUG("Handshake IO continue\n");
+
+ qcrypto_tls_session_set_callbacks(vs->tls,
+ vnc_tls_push,
+ vnc_tls_pull,
+ vs);
+
+ VNC_DEBUG("Start TLS WS handshake process\n");
vncws_start_tls_handshake(vs);
}
-#endif /* CONFIG_VNC_TLS */
void vncws_handshake_read(void *opaque)
{