diff options
author | Daniel P. Berrange <berrange@redhat.com> | 2015-07-01 18:10:36 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-07-08 13:11:01 +0200 |
commit | 8e9b0d24fb986d4241ae3b77752eca5dab4cb486 (patch) | |
tree | ce366ef15d1da340c5219bfd7814fa0b4a102d87 | |
parent | 488981a4af396551a3178d032cc2b41d9553ada2 (diff) |
ui: convert VNC websockets to use crypto APIs
Remove the direct use of gnutls for hash processing in the
websockets code, in favour of using the crypto APIs. This
allows the websockets code to be built unconditionally
removing countless conditional checks from the VNC code.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <1435770638-25715-9-git-send-email-berrange@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rwxr-xr-x | configure | 19 | ||||
-rw-r--r-- | ui/Makefile.objs | 2 | ||||
-rw-r--r-- | ui/vnc-ws.c | 22 | ||||
-rw-r--r-- | ui/vnc-ws.h | 2 | ||||
-rw-r--r-- | ui/vnc.c | 67 | ||||
-rw-r--r-- | ui/vnc.h | 8 |
6 files changed, 25 insertions, 95 deletions
@@ -246,7 +246,6 @@ vnc_tls="" vnc_sasl="" vnc_jpeg="" vnc_png="" -vnc_ws="" xen="" xen_ctrl_version="" xen_pci_passthrough="" @@ -896,10 +895,6 @@ for opt do ;; --enable-vnc-png) vnc_png="yes" ;; - --disable-vnc-ws) vnc_ws="no" - ;; - --enable-vnc-ws) vnc_ws="yes" - ;; --disable-slirp) slirp="no" ;; --disable-uuid) uuid="no" @@ -2343,7 +2338,7 @@ fi ########################################## # VNC TLS/WS detection -if test "$vnc" = "yes" -a \( "$vnc_tls" != "no" -o "$vnc_ws" != "no" \) ; then +if test "$vnc" = "yes" -a "$vnc_tls" != "no" ; then cat > $TMPC <<EOF #include <gnutls/gnutls.h> int main(void) { gnutls_session_t s; gnutls_init(&s, GNUTLS_SERVER); return 0; } @@ -2354,20 +2349,13 @@ EOF if test "$vnc_tls" != "no" ; then vnc_tls=yes fi - if test "$vnc_ws" != "no" ; then - vnc_ws=yes - fi libs_softmmu="$vnc_tls_libs $libs_softmmu" QEMU_CFLAGS="$QEMU_CFLAGS $vnc_tls_cflags" else if test "$vnc_tls" = "yes" ; then feature_not_found "vnc-tls" "Install gnutls devel" fi - if test "$vnc_ws" = "yes" ; then - feature_not_found "vnc-ws" "Install gnutls devel" - fi vnc_tls=no - vnc_ws=no fi fi @@ -4496,7 +4484,6 @@ if test "$vnc" = "yes" ; then echo "VNC SASL support $vnc_sasl" echo "VNC JPEG support $vnc_jpeg" echo "VNC PNG support $vnc_png" - echo "VNC WS support $vnc_ws" fi if test -n "$sparc_cpu"; then echo "Target Sparc Arch $sparc_cpu" @@ -4708,10 +4695,6 @@ fi if test "$vnc_png" = "yes" ; then echo "CONFIG_VNC_PNG=y" >> $config_host_mak fi -if test "$vnc_ws" = "yes" ; then - echo "CONFIG_VNC_WS=y" >> $config_host_mak - echo "VNC_WS_CFLAGS=$vnc_ws_cflags" >> $config_host_mak -fi if test "$fnmatch" = "yes" ; then echo "CONFIG_FNMATCH=y" >> $config_host_mak fi diff --git a/ui/Makefile.objs b/ui/Makefile.objs index dd1f8e42ca..c62d4d9722 100644 --- a/ui/Makefile.objs +++ b/ui/Makefile.objs @@ -4,7 +4,7 @@ vnc-obj-y += vnc-enc-tight.o vnc-palette.o vnc-obj-y += vnc-enc-zrle.o vnc-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o -vnc-obj-$(CONFIG_VNC_WS) += vnc-ws.o +vnc-obj-y += vnc-ws.o vnc-obj-y += vnc-jobs.o common-obj-y += keymaps.o console.o cursor.o qemu-pixman.o diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c index 8c18268054..b4cb6bde70 100644 --- a/ui/vnc-ws.c +++ b/ui/vnc-ws.c @@ -20,6 +20,7 @@ #include "vnc.h" #include "qemu/main-loop.h" +#include "crypto/hash.h" #ifdef CONFIG_VNC_TLS #include "qemu/sockets.h" @@ -203,24 +204,21 @@ static char *vncws_extract_handshake_entry(const char *handshake, static void vncws_send_handshake_response(VncState *vs, const char* key) { char combined_key[WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1]; - unsigned char hash[SHA1_DIGEST_LEN]; - size_t hash_size = sizeof(hash); char *accept = NULL, *response = NULL; - gnutls_datum_t in; - int ret; + Error *err = NULL; g_strlcpy(combined_key, key, WS_CLIENT_KEY_LEN + 1); g_strlcat(combined_key, WS_GUID, WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1); /* hash and encode it */ - in.data = (void *)combined_key; - in.size = WS_CLIENT_KEY_LEN + WS_GUID_LEN; - ret = gnutls_fingerprint(GNUTLS_DIG_SHA1, &in, hash, &hash_size); - if (ret == GNUTLS_E_SUCCESS && hash_size <= SHA1_DIGEST_LEN) { - accept = g_base64_encode(hash, hash_size); - } - if (accept == NULL) { - VNC_DEBUG("Hashing Websocket combined key failed\n"); + if (qcrypto_hash_base64(QCRYPTO_HASH_ALG_SHA1, + combined_key, + WS_CLIENT_KEY_LEN + WS_GUID_LEN, + &accept, + &err) < 0) { + VNC_DEBUG("Hashing Websocket combined key failed %s\n", + error_get_pretty(err)); + error_free(err); vnc_client_error(vs); return; } diff --git a/ui/vnc-ws.h b/ui/vnc-ws.h index 14d4230eff..94942258ec 100644 --- a/ui/vnc-ws.h +++ b/ui/vnc-ws.h @@ -21,8 +21,6 @@ #ifndef __QEMU_UI_VNC_WS_H #define __QEMU_UI_VNC_WS_H -#include <gnutls/gnutls.h> - #define B64LEN(__x) (((__x + 2) / 3) * 12 / 3) #define SHA1_DIGEST_LEN 20 @@ -40,6 +40,7 @@ #include "qemu/osdep.h" #include "ui/input.h" #include "qapi-event.h" +#include "crypto/hash.h" #define VNC_REFRESH_INTERVAL_BASE GUI_REFRESH_INTERVAL_DEFAULT #define VNC_REFRESH_INTERVAL_INC 50 @@ -355,9 +356,7 @@ static VncClientInfo *qmp_query_vnc_client(const VncState *client) info->base->host = g_strdup(host); info->base->service = g_strdup(serv); info->base->family = inet_netfamily(sa.ss_family); -#ifdef CONFIG_VNC_WS info->base->websocket = client->websocket; -#endif #ifdef CONFIG_VNC_TLS if (client->tls.session && client->tls.dname) { @@ -582,12 +581,10 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp) info->server = qmp_query_server_entry(vd->lsock, false, info->server); } -#ifdef CONFIG_VNC_WS if (vd->lwebsock != -1) { info->server = qmp_query_server_entry(vd->lwebsock, true, info->server); } -#endif item = g_new0(VncInfo2List, 1); item->value = info; @@ -1231,10 +1228,8 @@ void vnc_disconnect_finish(VncState *vs) buffer_free(&vs->input); buffer_free(&vs->output); -#ifdef CONFIG_VNC_WS buffer_free(&vs->ws_input); buffer_free(&vs->ws_output); -#endif /* CONFIG_VNC_WS */ qapi_free_VncClientInfo(vs->info); @@ -1413,12 +1408,9 @@ static void vnc_client_write_locked(void *opaque) } else #endif /* CONFIG_VNC_SASL */ { -#ifdef CONFIG_VNC_WS if (vs->encode_ws) { vnc_client_write_ws(vs); - } else -#endif /* CONFIG_VNC_WS */ - { + } else { vnc_client_write_plain(vs); } } @@ -1429,11 +1421,7 @@ void vnc_client_write(void *opaque) VncState *vs = opaque; vnc_lock_output(vs); - if (vs->output.offset -#ifdef CONFIG_VNC_WS - || vs->ws_output.offset -#endif - ) { + if (vs->output.offset || vs->ws_output.offset) { vnc_client_write_locked(opaque); } else if (vs->csock != -1) { qemu_set_fd_handler(vs->csock, vnc_client_read, NULL, vs); @@ -1539,7 +1527,6 @@ void vnc_client_read(void *opaque) ret = vnc_client_read_sasl(vs); else #endif /* CONFIG_VNC_SASL */ -#ifdef CONFIG_VNC_WS if (vs->encode_ws) { ret = vnc_client_read_ws(vs); if (ret == -1) { @@ -1549,10 +1536,8 @@ void vnc_client_read(void *opaque) vnc_client_error(vs); return; } - } else -#endif /* CONFIG_VNC_WS */ - { - ret = vnc_client_read_plain(vs); + } else { + ret = vnc_client_read_plain(vs); } if (!ret) { if (vs->csock == -1) @@ -1624,11 +1609,8 @@ void vnc_write_u8(VncState *vs, uint8_t value) void vnc_flush(VncState *vs) { vnc_lock_output(vs); - if (vs->csock != -1 && (vs->output.offset -#ifdef CONFIG_VNC_WS - || vs->ws_output.offset -#endif - )) { + if (vs->csock != -1 && (vs->output.offset || + vs->ws_output.offset)) { vnc_client_write_locked(vs); } vnc_unlock_output(vs); @@ -3019,7 +3001,6 @@ static void vnc_connect(VncDisplay *vd, int csock, VNC_DEBUG("New client on socket %d\n", csock); update_displaychangelistener(&vd->dcl, VNC_REFRESH_INTERVAL_BASE); qemu_set_nonblock(vs->csock); -#ifdef CONFIG_VNC_WS if (websocket) { vs->websocket = 1; #ifdef CONFIG_VNC_TLS @@ -3031,7 +3012,6 @@ static void vnc_connect(VncDisplay *vd, int csock, qemu_set_fd_handler(vs->csock, vncws_handshake_read, NULL, vs); } } else -#endif /* CONFIG_VNC_WS */ { qemu_set_fd_handler(vs->csock, vnc_client_read, NULL, vs); } @@ -3040,10 +3020,7 @@ static void vnc_connect(VncDisplay *vd, int csock, vnc_qmp_event(vs, QAPI_EVENT_VNC_CONNECTED); vnc_set_share_mode(vs, VNC_SHARE_MODE_CONNECTING); -#ifdef CONFIG_VNC_WS - if (!vs->websocket) -#endif - { + if (!vs->websocket) { vnc_init_state(vs); } @@ -3099,12 +3076,9 @@ static void vnc_listen_read(void *opaque, bool websocket) /* Catch-up */ graphic_hw_update(vs->dcl.con); -#ifdef CONFIG_VNC_WS if (websocket) { csock = qemu_accept(vs->lwebsock, (struct sockaddr *)&addr, &addrlen); - } else -#endif /* CONFIG_VNC_WS */ - { + } else { csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); } @@ -3119,12 +3093,10 @@ static void vnc_listen_regular_read(void *opaque) vnc_listen_read(opaque, false); } -#ifdef CONFIG_VNC_WS static void vnc_listen_websocket_read(void *opaque) { vnc_listen_read(opaque, true); } -#endif /* CONFIG_VNC_WS */ static const DisplayChangeListenerOps dcl_ops = { .dpy_name = "vnc", @@ -3150,9 +3122,7 @@ void vnc_display_init(const char *id) QTAILQ_INSERT_TAIL(&vnc_displays, vs, next); vs->lsock = -1; -#ifdef CONFIG_VNC_WS vs->lwebsock = -1; -#endif QTAILQ_INIT(&vs->clients); vs->expires = TIME_MAX; @@ -3186,14 +3156,12 @@ static void vnc_display_close(VncDisplay *vs) close(vs->lsock); vs->lsock = -1; } -#ifdef CONFIG_VNC_WS vs->ws_enabled = false; if (vs->lwebsock != -1) { qemu_set_fd_handler(vs->lwebsock, NULL, NULL, NULL); close(vs->lwebsock); vs->lwebsock = -1; } -#endif /* CONFIG_VNC_WS */ vs->auth = VNC_AUTH_INVALID; vs->subauth = VNC_AUTH_INVALID; #ifdef CONFIG_VNC_TLS @@ -3579,13 +3547,12 @@ void vnc_display_open(const char *id, Error **errp) websocket = qemu_opt_get(opts, "websocket"); if (websocket) { -#ifdef CONFIG_VNC_WS vs->ws_enabled = true; qemu_opt_set(wsopts, "port", websocket, &error_abort); -#else /* ! CONFIG_VNC_WS */ - error_setg(errp, "Websockets protocol requires gnutls support"); - goto fail; -#endif /* ! CONFIG_VNC_WS */ + if (!qcrypto_hash_supports(QCRYPTO_HASH_ALG_SHA1)) { + error_setg(errp, "SHA1 hash support is required for websockets"); + goto fail; + } } #ifdef CONFIG_VNC_JPEG @@ -3668,9 +3635,7 @@ void vnc_display_open(const char *id, Error **errp) /* connect to viewer */ int csock; vs->lsock = -1; -#ifdef CONFIG_VNC_WS vs->lwebsock = -1; -#endif if (strncmp(vnc, "unix:", 5) == 0) { csock = unix_connect(vnc+5, errp); } else { @@ -3693,7 +3658,6 @@ void vnc_display_open(const char *id, Error **errp) if (vs->lsock < 0) { goto fail; } -#ifdef CONFIG_VNC_WS if (vs->ws_enabled) { vs->lwebsock = inet_listen_opts(wsopts, 0, errp); if (vs->lwebsock < 0) { @@ -3704,16 +3668,13 @@ void vnc_display_open(const char *id, Error **errp) goto fail; } } -#endif /* CONFIG_VNC_WS */ } vs->enabled = true; qemu_set_fd_handler(vs->lsock, vnc_listen_regular_read, NULL, vs); -#ifdef CONFIG_VNC_WS if (vs->ws_enabled) { qemu_set_fd_handler(vs->lwebsock, vnc_listen_websocket_read, NULL, vs); } -#endif /* CONFIG_VNC_WS */ } qemu_opts_del(sopts); qemu_opts_del(wsopts); @@ -3723,9 +3684,7 @@ fail: qemu_opts_del(sopts); qemu_opts_del(wsopts); vs->enabled = false; -#ifdef CONFIG_VNC_WS vs->ws_enabled = false; -#endif /* CONFIG_VNC_WS */ } void vnc_display_add_client(const char *id, int csock, bool skipauth) @@ -108,9 +108,7 @@ typedef struct VncDisplay VncDisplay; #ifdef CONFIG_VNC_SASL #include "vnc-auth-sasl.h" #endif -#ifdef CONFIG_VNC_WS #include "vnc-ws.h" -#endif struct VncRectStat { @@ -156,10 +154,8 @@ struct VncDisplay int connections_limit; VncSharePolicy share_policy; int lsock; -#ifdef CONFIG_VNC_WS int lwebsock; bool ws_enabled; -#endif DisplaySurface *ds; DisplayChangeListener dcl; kbd_layout_t *kbd_layout; @@ -294,21 +290,17 @@ struct VncState #ifdef CONFIG_VNC_SASL VncStateSASL sasl; #endif -#ifdef CONFIG_VNC_WS bool encode_ws; bool websocket; -#endif /* CONFIG_VNC_WS */ VncClientInfo *info; Buffer output; Buffer input; -#ifdef CONFIG_VNC_WS Buffer ws_input; Buffer ws_output; size_t ws_payload_remain; WsMask ws_payload_mask; -#endif /* current output mode information */ VncWritePixels *write_pixels; PixelFormat client_pf; |