[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 08/10] ui: convert VNC websockets to use crypto
From: |
Gonglei |
Subject: |
Re: [Qemu-devel] [PATCH 08/10] ui: convert VNC websockets to use crypto APIs |
Date: |
Fri, 29 May 2015 14:55:45 +0800 |
User-agent: |
Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 |
On 2015/5/21 18:56, Daniel P. Berrange wrote:
> 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 <address@hidden>
> ---
> configure | 19 +--------------
> ui/Makefile.objs | 2 +-
> ui/vnc-ws.c | 22 ++++++++----------
> ui/vnc-ws.h | 2 --
> ui/vnc.c | 70
> ++++++++++++--------------------------------------------
> ui/vnc.h | 8 -------
> 6 files changed, 26 insertions(+), 97 deletions(-)
>
> diff --git a/configure b/configure
> index cc60f0b..661e7be 100755
> --- a/configure
> +++ b/configure
> @@ -245,7 +245,6 @@ vnc_tls=""
> vnc_sasl=""
> vnc_jpeg=""
> vnc_png=""
> -vnc_ws=""
> xen=""
> xen_ctrl_version=""
> xen_pci_passthrough=""
> @@ -887,10 +886,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"
> @@ -2378,7 +2373,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; }
> @@ -2389,20 +2384,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
>
> @@ -4465,7 +4453,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"
> @@ -4671,10 +4658,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 d9796b1..7e70d55 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 38a1b8b..215b9d6 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 14d4230..9494225 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
>
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 2b80160..73a6d5f 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -38,6 +38,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
> @@ -353,9 +354,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) {
> @@ -580,12 +579,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;
> @@ -1229,10 +1226,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);
>
> @@ -1411,12 +1406,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);
> }
> }
> @@ -1427,11 +1419,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_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
> @@ -1537,7 +1525,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) {
> @@ -1547,10 +1534,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)
> @@ -1622,11 +1607,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);
> @@ -3017,7 +2999,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
> @@ -3030,9 +3011,7 @@ static void vnc_connect(VncDisplay *vd, int csock,
> qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read,
> NULL, vs);
> }
> - } else
> -#endif /* CONFIG_VNC_WS */
> - {
> + } else {
> qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
> }
>
> @@ -3040,10 +3019,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 +3075,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 +3092,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 +3121,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 +3155,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_handler2(vs->lwebsock, NULL, 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 +3546,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 +3634,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 +3657,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,17 +3667,14 @@ void vnc_display_open(const char *id, Error **errp)
> goto fail;
> }
> }
> -#endif /* CONFIG_VNC_WS */
> }
> vs->enabled = true;
> qemu_set_fd_handler2(vs->lsock, NULL,
> vnc_listen_regular_read, NULL, vs);
> -#ifdef CONFIG_VNC_WS
> if (vs->ws_enabled) {
> qemu_set_fd_handler2(vs->lwebsock, NULL,
> vnc_listen_websocket_read, NULL, vs);
> }
> -#endif /* CONFIG_VNC_WS */
> }
> qemu_opts_del(sopts);
> qemu_opts_del(wsopts);
> @@ -3724,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)
> diff --git a/ui/vnc.h b/ui/vnc.h
> index 3f7c6a9..814d720 100644
> --- a/ui/vnc.h
> +++ b/ui/vnc.h
> @@ -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;
>
It's more clear now :)
Regards,
-Gonglei
- [Qemu-devel] [PATCH 03/10] crypto: move built-in D3DES implementation into crypto/, (continued)
- [Qemu-devel] [PATCH 07/10] block: convert quorum blockdrv to use crypto APIs, Daniel P. Berrange, 2015/05/21
- [Qemu-devel] [PATCH 05/10] crypto: add a gcrypt cipher implementation, Daniel P. Berrange, 2015/05/21
- [Qemu-devel] [PATCH 08/10] ui: convert VNC websockets to use crypto APIs, Daniel P. Berrange, 2015/05/21
- Re: [Qemu-devel] [PATCH 08/10] ui: convert VNC websockets to use crypto APIs,
Gonglei <=
- [Qemu-devel] [PATCH 06/10] crypto: add a nettle cipher implementation, Daniel P. Berrange, 2015/05/21
- [Qemu-devel] [PATCH 09/10] block: convert qcow/qcow2 to use generic cipher API, Daniel P. Berrange, 2015/05/21
- [Qemu-devel] [PATCH 10/10] ui: convert VNC to use generic cipher API, Daniel P. Berrange, 2015/05/21
- Re: [Qemu-devel] [PATCH 00/10] Consolidate crypto APIs & implementations, Gonglei, 2015/05/22