Commit 8d5d2d4c478c6a853b7334f06253ab73410e9322

Authored by ths
1 parent 70848515

VeNCrypt basic TLS support, by Daniel P. Berrange.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3136 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
@@ -405,6 +405,11 @@ SOUND_HW += fmopl.o adlib.o @@ -405,6 +405,11 @@ SOUND_HW += fmopl.o adlib.o
405 endif 405 endif
406 AUDIODRV+= wavcapture.o 406 AUDIODRV+= wavcapture.o
407 407
  408 +ifdef CONFIG_VNC_TLS
  409 +CPPFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
  410 +LIBS += $(CONFIG_VNC_TLS_LIBS)
  411 +endif
  412 +
408 VL_OBJS += i2c.o smbus.o 413 VL_OBJS += i2c.o smbus.o
409 414
410 # SCSI layer 415 # SCSI layer
configure
@@ -89,6 +89,7 @@ alsa="no" @@ -89,6 +89,7 @@ alsa="no"
89 fmod="no" 89 fmod="no"
90 fmod_lib="" 90 fmod_lib=""
91 fmod_inc="" 91 fmod_inc=""
  92 +vnc_tls="yes"
92 bsd="no" 93 bsd="no"
93 linux="no" 94 linux="no"
94 kqemu="no" 95 kqemu="no"
@@ -252,6 +253,8 @@ for opt do @@ -252,6 +253,8 @@ for opt do
252 ;; 253 ;;
253 --fmod-inc=*) fmod_inc="$optarg" 254 --fmod-inc=*) fmod_inc="$optarg"
254 ;; 255 ;;
  256 + --disable-vnc-tls) vnc_tls="no"
  257 + ;;
255 --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; linux_user="no" 258 --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; linux_user="no"
256 ;; 259 ;;
257 --disable-slirp) slirp="no" 260 --disable-slirp) slirp="no"
@@ -362,6 +365,7 @@ echo " --enable-coreaudio enable Coreaudio audio driver" @@ -362,6 +365,7 @@ echo " --enable-coreaudio enable Coreaudio audio driver"
362 echo " --enable-alsa enable ALSA audio driver" 365 echo " --enable-alsa enable ALSA audio driver"
363 echo " --enable-fmod enable FMOD audio driver" 366 echo " --enable-fmod enable FMOD audio driver"
364 echo " --enable-dsound enable DirectSound audio driver" 367 echo " --enable-dsound enable DirectSound audio driver"
  368 +echo " --disable-vnc-tls disable TLS encryption for VNC server"
365 echo " --enable-system enable all system emulation targets" 369 echo " --enable-system enable all system emulation targets"
366 echo " --disable-system disable all system emulation targets" 370 echo " --disable-system disable all system emulation targets"
367 echo " --enable-linux-user enable all linux usermode emulation targets" 371 echo " --enable-linux-user enable all linux usermode emulation targets"
@@ -589,6 +593,16 @@ else @@ -589,6 +593,16 @@ else
589 fi # -z $sdl 593 fi # -z $sdl
590 594
591 ########################################## 595 ##########################################
  596 +# VNC TLS detection
  597 +if test "$vnc_tls" = "yes" ; then
  598 + `pkg-config gnutls` || vnc_tls="no"
  599 +fi
  600 +if test "$vnc_tls" = "yes" ; then
  601 + vnc_tls_cflags=`pkg-config --cflags gnutls`
  602 + vnc_tls_libs=`pkg-config --libs gnutls`
  603 +fi
  604 +
  605 +##########################################
592 # alsa sound support libraries 606 # alsa sound support libraries
593 607
594 if test "$alsa" = "yes" ; then 608 if test "$alsa" = "yes" ; then
@@ -675,6 +689,11 @@ else @@ -675,6 +689,11 @@ else
675 fi 689 fi
676 echo "FMOD support $fmod $fmod_support" 690 echo "FMOD support $fmod $fmod_support"
677 echo "OSS support $oss" 691 echo "OSS support $oss"
  692 +echo "VNC TLS support $vnc_tls"
  693 +if test "$vnc_tls" = "yes" ; then
  694 + echo " TLS CFLAGS $vnc_tls_cflags"
  695 + echo " TLS LIBS $vnc_tls_libs"
  696 +fi
678 if test -n "$sparc_cpu"; then 697 if test -n "$sparc_cpu"; then
679 echo "Target Sparc Arch $sparc_cpu" 698 echo "Target Sparc Arch $sparc_cpu"
680 fi 699 fi
@@ -847,6 +866,12 @@ if test "$fmod" = "yes" ; then @@ -847,6 +866,12 @@ if test "$fmod" = "yes" ; then
847 echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak 866 echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak
848 echo "#define CONFIG_FMOD 1" >> $config_h 867 echo "#define CONFIG_FMOD 1" >> $config_h
849 fi 868 fi
  869 +if test "$vnc_tls" = "yes" ; then
  870 + echo "CONFIG_VNC_TLS=yes" >> $config_mak
  871 + echo "CONFIG_VNC_TLS_CFLAGS=$vnc_tls_cflags" >> $config_mak
  872 + echo "CONFIG_VNC_TLS_LIBS=$vnc_tls_libs" >> $config_mak
  873 + echo "#define CONFIG_VNC_TLS 1" >> $config_h
  874 +fi
850 qemu_version=`head $source_path/VERSION` 875 qemu_version=`head $source_path/VERSION`
851 echo "VERSION=$qemu_version" >>$config_mak 876 echo "VERSION=$qemu_version" >>$config_mak
852 echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h 877 echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h
@@ -32,14 +32,27 @@ @@ -32,14 +32,27 @@
32 #include "keymaps.c" 32 #include "keymaps.c"
33 #include "d3des.h" 33 #include "d3des.h"
34 34
35 -// #define _VNC_DEBUG 35 +#if CONFIG_VNC_TLS
  36 +#include <gnutls/gnutls.h>
  37 +#include <gnutls/x509.h>
  38 +#endif /* CONFIG_VNC_TLS */
36 39
37 -#ifdef _VNC_DEBUG 40 +// #define _VNC_DEBUG 1
  41 +
  42 +#if _VNC_DEBUG
38 #define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) 43 #define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
  44 +
  45 +#if CONFIG_VNC_TLS && _VNC_DEBUG >= 2
  46 +/* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
  47 +static void vnc_debug_gnutls_log(int level, const char* str) {
  48 + VNC_DEBUG("%d %s", level, str);
  49 +}
  50 +#endif /* CONFIG_VNC_TLS && _VNC_DEBUG */
39 #else 51 #else
40 #define VNC_DEBUG(fmt, ...) do { } while (0) 52 #define VNC_DEBUG(fmt, ...) do { } while (0)
41 #endif 53 #endif
42 54
  55 +
43 typedef struct Buffer 56 typedef struct Buffer
44 { 57 {
45 size_t capacity; 58 size_t capacity;
@@ -77,6 +90,23 @@ enum { @@ -77,6 +90,23 @@ enum {
77 VNC_AUTH_VENCRYPT = 19 90 VNC_AUTH_VENCRYPT = 19
78 }; 91 };
79 92
  93 +#if CONFIG_VNC_TLS
  94 +enum {
  95 + VNC_WIREMODE_CLEAR,
  96 + VNC_WIREMODE_TLS,
  97 +};
  98 +
  99 +enum {
  100 + VNC_AUTH_VENCRYPT_PLAIN = 256,
  101 + VNC_AUTH_VENCRYPT_TLSNONE = 257,
  102 + VNC_AUTH_VENCRYPT_TLSVNC = 258,
  103 + VNC_AUTH_VENCRYPT_TLSPLAIN = 259,
  104 + VNC_AUTH_VENCRYPT_X509NONE = 260,
  105 + VNC_AUTH_VENCRYPT_X509VNC = 261,
  106 + VNC_AUTH_VENCRYPT_X509PLAIN = 262,
  107 +};
  108 +#endif /* CONFIG_VNC_TLS */
  109 +
80 struct VncState 110 struct VncState
81 { 111 {
82 QEMUTimer *timer; 112 QEMUTimer *timer;
@@ -102,8 +132,16 @@ struct VncState @@ -102,8 +132,16 @@ struct VncState
102 char *display; 132 char *display;
103 char *password; 133 char *password;
104 int auth; 134 int auth;
  135 +#if CONFIG_VNC_TLS
  136 + int subauth;
  137 +#endif
105 char challenge[VNC_AUTH_CHALLENGE_SIZE]; 138 char challenge[VNC_AUTH_CHALLENGE_SIZE];
106 139
  140 +#if CONFIG_VNC_TLS
  141 + int wiremode;
  142 + gnutls_session_t tls_session;
  143 +#endif
  144 +
107 Buffer output; 145 Buffer output;
108 Buffer input; 146 Buffer input;
109 kbd_layout_t *kbd_layout; 147 kbd_layout_t *kbd_layout;
@@ -579,12 +617,20 @@ static int vnc_client_io_error(VncState *vs, int ret, int last_errno) @@ -579,12 +617,20 @@ static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
579 if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN)) 617 if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
580 return 0; 618 return 0;
581 619
  620 + VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0);
582 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); 621 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
583 closesocket(vs->csock); 622 closesocket(vs->csock);
584 vs->csock = -1; 623 vs->csock = -1;
585 buffer_reset(&vs->input); 624 buffer_reset(&vs->input);
586 buffer_reset(&vs->output); 625 buffer_reset(&vs->output);
587 vs->need_update = 0; 626 vs->need_update = 0;
  627 +#if CONFIG_VNC_TLS
  628 + if (vs->tls_session) {
  629 + gnutls_deinit(vs->tls_session);
  630 + vs->tls_session = NULL;
  631 + }
  632 + vs->wiremode = VNC_WIREMODE_CLEAR;
  633 +#endif /* CONFIG_VNC_TLS */
588 return 0; 634 return 0;
589 } 635 }
590 return ret; 636 return ret;
@@ -600,7 +646,19 @@ static void vnc_client_write(void *opaque) @@ -600,7 +646,19 @@ static void vnc_client_write(void *opaque)
600 long ret; 646 long ret;
601 VncState *vs = opaque; 647 VncState *vs = opaque;
602 648
603 - ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0); 649 +#if CONFIG_VNC_TLS
  650 + if (vs->tls_session) {
  651 + ret = gnutls_write(vs->tls_session, vs->output.buffer, vs->output.offset);
  652 + if (ret < 0) {
  653 + if (ret == GNUTLS_E_AGAIN)
  654 + errno = EAGAIN;
  655 + else
  656 + errno = EIO;
  657 + ret = -1;
  658 + }
  659 + } else
  660 +#endif /* CONFIG_VNC_TLS */
  661 + ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
604 ret = vnc_client_io_error(vs, ret, socket_error()); 662 ret = vnc_client_io_error(vs, ret, socket_error());
605 if (!ret) 663 if (!ret)
606 return; 664 return;
@@ -626,7 +684,19 @@ static void vnc_client_read(void *opaque) @@ -626,7 +684,19 @@ static void vnc_client_read(void *opaque)
626 684
627 buffer_reserve(&vs->input, 4096); 685 buffer_reserve(&vs->input, 4096);
628 686
629 - ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0); 687 +#if CONFIG_VNC_TLS
  688 + if (vs->tls_session) {
  689 + ret = gnutls_read(vs->tls_session, buffer_end(&vs->input), 4096);
  690 + if (ret < 0) {
  691 + if (ret == GNUTLS_E_AGAIN)
  692 + errno = EAGAIN;
  693 + else
  694 + errno = EIO;
  695 + ret = -1;
  696 + }
  697 + } else
  698 +#endif /* CONFIG_VNC_TLS */
  699 + ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
630 ret = vnc_client_io_error(vs, ret, socket_error()); 700 ret = vnc_client_io_error(vs, ret, socket_error());
631 if (!ret) 701 if (!ret)
632 return; 702 return;
@@ -721,6 +791,41 @@ static uint32_t read_u32(uint8_t *data, size_t offset) @@ -721,6 +791,41 @@ static uint32_t read_u32(uint8_t *data, size_t offset)
721 (data[offset + 2] << 8) | data[offset + 3]); 791 (data[offset + 2] << 8) | data[offset + 3]);
722 } 792 }
723 793
  794 +#if CONFIG_VNC_TLS
  795 +ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
  796 + const void *data,
  797 + size_t len) {
  798 + struct VncState *vs = (struct VncState *)transport;
  799 + int ret;
  800 +
  801 + retry:
  802 + ret = send(vs->csock, data, len, 0);
  803 + if (ret < 0) {
  804 + if (errno == EINTR)
  805 + goto retry;
  806 + return -1;
  807 + }
  808 + return ret;
  809 +}
  810 +
  811 +
  812 +ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
  813 + void *data,
  814 + size_t len) {
  815 + struct VncState *vs = (struct VncState *)transport;
  816 + int ret;
  817 +
  818 + retry:
  819 + ret = recv(vs->csock, data, len, 0);
  820 + if (ret < 0) {
  821 + if (errno == EINTR)
  822 + goto retry;
  823 + return -1;
  824 + }
  825 + return ret;
  826 +}
  827 +#endif /* CONFIG_VNC_TLS */
  828 +
724 static void client_cut_text(VncState *vs, size_t len, char *text) 829 static void client_cut_text(VncState *vs, size_t len, char *text)
725 { 830 {
726 } 831 }
@@ -1225,6 +1330,243 @@ static int start_auth_vnc(VncState *vs) @@ -1225,6 +1330,243 @@ static int start_auth_vnc(VncState *vs)
1225 return 0; 1330 return 0;
1226 } 1331 }
1227 1332
  1333 +
  1334 +#if CONFIG_VNC_TLS
  1335 +#define DH_BITS 1024
  1336 +static gnutls_dh_params_t dh_params;
  1337 +
  1338 +static int vnc_tls_initialize(void)
  1339 +{
  1340 + static int tlsinitialized = 0;
  1341 +
  1342 + if (tlsinitialized)
  1343 + return 1;
  1344 +
  1345 + if (gnutls_global_init () < 0)
  1346 + return 0;
  1347 +
  1348 + /* XXX ought to re-generate diffie-hellmen params periodically */
  1349 + if (gnutls_dh_params_init (&dh_params) < 0)
  1350 + return 0;
  1351 + if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
  1352 + return 0;
  1353 +
  1354 +#if _VNC_DEBUG == 2
  1355 + gnutls_global_set_log_level(10);
  1356 + gnutls_global_set_log_function(vnc_debug_gnutls_log);
  1357 +#endif
  1358 +
  1359 + tlsinitialized = 1;
  1360 +
  1361 + return 1;
  1362 +}
  1363 +
  1364 +static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
  1365 +{
  1366 + gnutls_anon_server_credentials anon_cred;
  1367 + int ret;
  1368 +
  1369 + if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
  1370 + VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
  1371 + return NULL;
  1372 + }
  1373 +
  1374 + gnutls_anon_set_server_dh_params(anon_cred, dh_params);
  1375 +
  1376 + return anon_cred;
  1377 +}
  1378 +
  1379 +
  1380 +static int start_auth_vencrypt_subauth(VncState *vs)
  1381 +{
  1382 + switch (vs->subauth) {
  1383 + case VNC_AUTH_VENCRYPT_TLSNONE:
  1384 + VNC_DEBUG("Accept TLS auth none\n");
  1385 + vnc_write_u32(vs, 0); /* Accept auth completion */
  1386 + vnc_read_when(vs, protocol_client_init, 1);
  1387 + break;
  1388 +
  1389 + case VNC_AUTH_VENCRYPT_TLSVNC:
  1390 + VNC_DEBUG("Start TLS auth VNC\n");
  1391 + return start_auth_vnc(vs);
  1392 +
  1393 + default: /* Should not be possible, but just in case */
  1394 + VNC_DEBUG("Reject auth %d\n", vs->auth);
  1395 + vnc_write_u8(vs, 1);
  1396 + if (vs->minor >= 8) {
  1397 + static const char err[] = "Unsupported authentication type";
  1398 + vnc_write_u32(vs, sizeof(err));
  1399 + vnc_write(vs, err, sizeof(err));
  1400 + }
  1401 + vnc_client_error(vs);
  1402 + }
  1403 +
  1404 + return 0;
  1405 +}
  1406 +
  1407 +static void vnc_handshake_io(void *opaque);
  1408 +
  1409 +static int vnc_continue_handshake(struct VncState *vs) {
  1410 + int ret;
  1411 +
  1412 + if ((ret = gnutls_handshake(vs->tls_session)) < 0) {
  1413 + if (!gnutls_error_is_fatal(ret)) {
  1414 + VNC_DEBUG("Handshake interrupted (blocking)\n");
  1415 + if (!gnutls_record_get_direction(vs->tls_session))
  1416 + qemu_set_fd_handler(vs->csock, vnc_handshake_io, NULL, vs);
  1417 + else
  1418 + qemu_set_fd_handler(vs->csock, NULL, vnc_handshake_io, vs);
  1419 + return 0;
  1420 + }
  1421 + VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
  1422 + vnc_client_error(vs);
  1423 + return -1;
  1424 + }
  1425 +
  1426 + VNC_DEBUG("Handshake done, switching to TLS data mode\n");
  1427 + vs->wiremode = VNC_WIREMODE_TLS;
  1428 + qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
  1429 +
  1430 + return start_auth_vencrypt_subauth(vs);
  1431 +}
  1432 +
  1433 +static void vnc_handshake_io(void *opaque) {
  1434 + struct VncState *vs = (struct VncState *)opaque;
  1435 +
  1436 + VNC_DEBUG("Handshake IO continue\n");
  1437 + vnc_continue_handshake(vs);
  1438 +}
  1439 +
  1440 +static int vnc_start_tls(struct VncState *vs) {
  1441 + static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
  1442 + static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
  1443 + static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
  1444 + gnutls_anon_server_credentials anon_cred = NULL;
  1445 +
  1446 + VNC_DEBUG("Do TLS setup\n");
  1447 + if (vnc_tls_initialize() < 0) {
  1448 + VNC_DEBUG("Failed to init TLS\n");
  1449 + vnc_client_error(vs);
  1450 + return -1;
  1451 + }
  1452 + if (vs->tls_session == NULL) {
  1453 + if (gnutls_init(&vs->tls_session, GNUTLS_SERVER) < 0) {
  1454 + vnc_client_error(vs);
  1455 + return -1;
  1456 + }
  1457 +
  1458 + if (gnutls_set_default_priority(vs->tls_session) < 0) {
  1459 + gnutls_deinit(vs->tls_session);
  1460 + vs->tls_session = NULL;
  1461 + vnc_client_error(vs);
  1462 + return -1;
  1463 + }
  1464 +
  1465 + if (gnutls_kx_set_priority(vs->tls_session, kx_anon) < 0) {
  1466 + gnutls_deinit(vs->tls_session);
  1467 + vs->tls_session = NULL;
  1468 + vnc_client_error(vs);
  1469 + return -1;
  1470 + }
  1471 +
  1472 + if (gnutls_certificate_type_set_priority(vs->tls_session, cert_type_priority) < 0) {
  1473 + gnutls_deinit(vs->tls_session);
  1474 + vs->tls_session = NULL;
  1475 + vnc_client_error(vs);
  1476 + return -1;
  1477 + }
  1478 +
  1479 + if (gnutls_protocol_set_priority(vs->tls_session, protocol_priority) < 0) {
  1480 + gnutls_deinit(vs->tls_session);
  1481 + vs->tls_session = NULL;
  1482 + vnc_client_error(vs);
  1483 + return -1;
  1484 + }
  1485 +
  1486 + anon_cred = vnc_tls_initialize_anon_cred();
  1487 + if (!anon_cred) {
  1488 + gnutls_deinit(vs->tls_session);
  1489 + vs->tls_session = NULL;
  1490 + vnc_client_error(vs);
  1491 + return -1;
  1492 + }
  1493 + if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
  1494 + gnutls_deinit(vs->tls_session);
  1495 + vs->tls_session = NULL;
  1496 + gnutls_anon_free_server_credentials(anon_cred);
  1497 + vnc_client_error(vs);
  1498 + return -1;
  1499 + }
  1500 +
  1501 + gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
  1502 + gnutls_transport_set_push_function(vs->tls_session, vnc_tls_push);
  1503 + gnutls_transport_set_pull_function(vs->tls_session, vnc_tls_pull);
  1504 + }
  1505 +
  1506 + VNC_DEBUG("Start TLS handshake process\n");
  1507 + return vnc_continue_handshake(vs);
  1508 +}
  1509 +
  1510 +static int protocol_client_vencrypt_auth(VncState *vs, char *data, size_t len)
  1511 +{
  1512 + int auth = read_u32(data, 0);
  1513 +
  1514 + if (auth != vs->subauth) {
  1515 + VNC_DEBUG("Rejecting auth %d\n", auth);
  1516 + vnc_write_u8(vs, 0); /* Reject auth */
  1517 + vnc_flush(vs);
  1518 + vnc_client_error(vs);
  1519 + } else {
  1520 + VNC_DEBUG("Accepting auth %d, starting handshake\n", auth);
  1521 + vnc_write_u8(vs, 1); /* Accept auth */
  1522 + vnc_flush(vs);
  1523 +
  1524 + if (vnc_start_tls(vs) < 0) {
  1525 + VNC_DEBUG("Failed to complete TLS\n");
  1526 + return 0;
  1527 + }
  1528 +
  1529 + if (vs->wiremode == VNC_WIREMODE_TLS) {
  1530 + VNC_DEBUG("Starting VeNCrypt subauth\n");
  1531 + return start_auth_vencrypt_subauth(vs);
  1532 + } else {
  1533 + VNC_DEBUG("TLS handshake blocked\n");
  1534 + return 0;
  1535 + }
  1536 + }
  1537 + return 0;
  1538 +}
  1539 +
  1540 +static int protocol_client_vencrypt_init(VncState *vs, char *data, size_t len)
  1541 +{
  1542 + if (data[0] != 0 ||
  1543 + data[1] != 2) {
  1544 + VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]);
  1545 + vnc_write_u8(vs, 1); /* Reject version */
  1546 + vnc_flush(vs);
  1547 + vnc_client_error(vs);
  1548 + } else {
  1549 + VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
  1550 + vnc_write_u8(vs, 0); /* Accept version */
  1551 + vnc_write_u8(vs, 1); /* Number of sub-auths */
  1552 + vnc_write_u32(vs, vs->subauth); /* The supported auth */
  1553 + vnc_flush(vs);
  1554 + vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
  1555 + }
  1556 + return 0;
  1557 +}
  1558 +
  1559 +static int start_auth_vencrypt(VncState *vs)
  1560 +{
  1561 + /* Send VeNCrypt version 0.2 */
  1562 + vnc_write_u8(vs, 0);
  1563 + vnc_write_u8(vs, 2);
  1564 +
  1565 + vnc_read_when(vs, protocol_client_vencrypt_init, 2);
  1566 + return 0;
  1567 +}
  1568 +#endif /* CONFIG_VNC_TLS */
  1569 +
1228 static int protocol_client_auth(VncState *vs, char *data, size_t len) 1570 static int protocol_client_auth(VncState *vs, char *data, size_t len)
1229 { 1571 {
1230 /* We only advertise 1 auth scheme at a time, so client 1572 /* We only advertise 1 auth scheme at a time, so client
@@ -1251,6 +1593,12 @@ static int protocol_client_auth(VncState *vs, char *data, size_t len) @@ -1251,6 +1593,12 @@ static int protocol_client_auth(VncState *vs, char *data, size_t len)
1251 VNC_DEBUG("Start VNC auth\n"); 1593 VNC_DEBUG("Start VNC auth\n");
1252 return start_auth_vnc(vs); 1594 return start_auth_vnc(vs);
1253 1595
  1596 +#if CONFIG_VNC_TLS
  1597 + case VNC_AUTH_VENCRYPT:
  1598 + VNC_DEBUG("Accept VeNCrypt auth\n");;
  1599 + return start_auth_vencrypt(vs);
  1600 +#endif /* CONFIG_VNC_TLS */
  1601 +
1254 default: /* Should not be possible, but just in case */ 1602 default: /* Should not be possible, but just in case */
1255 VNC_DEBUG("Reject auth %d\n", vs->auth); 1603 VNC_DEBUG("Reject auth %d\n", vs->auth);
1256 vnc_write_u8(vs, 1); 1604 vnc_write_u8(vs, 1);
@@ -1331,6 +1679,7 @@ static void vnc_listen_read(void *opaque) @@ -1331,6 +1679,7 @@ static void vnc_listen_read(void *opaque)
1331 1679
1332 vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); 1680 vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
1333 if (vs->csock != -1) { 1681 if (vs->csock != -1) {
  1682 + VNC_DEBUG("New client on socket %d\n", vs->csock);
1334 socket_set_nonblock(vs->csock); 1683 socket_set_nonblock(vs->csock);
1335 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque); 1684 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
1336 vnc_write(vs, "RFB 003.008\n", 12); 1685 vnc_write(vs, "RFB 003.008\n", 12);
@@ -1404,8 +1753,18 @@ void vnc_display_close(DisplayState *ds) @@ -1404,8 +1753,18 @@ void vnc_display_close(DisplayState *ds)
1404 buffer_reset(&vs->input); 1753 buffer_reset(&vs->input);
1405 buffer_reset(&vs->output); 1754 buffer_reset(&vs->output);
1406 vs->need_update = 0; 1755 vs->need_update = 0;
  1756 +#if CONFIG_VNC_TLS
  1757 + if (vs->tls_session) {
  1758 + gnutls_deinit(vs->tls_session);
  1759 + vs->tls_session = NULL;
  1760 + }
  1761 + vs->wiremode = VNC_WIREMODE_CLEAR;
  1762 +#endif /* CONFIG_VNC_TLS */
1407 } 1763 }
1408 vs->auth = VNC_AUTH_INVALID; 1764 vs->auth = VNC_AUTH_INVALID;
  1765 +#if CONFIG_VNC_TLS
  1766 + vs->subauth = VNC_AUTH_INVALID;
  1767 +#endif
1409 } 1768 }
1410 1769
1411 int vnc_display_password(DisplayState *ds, const char *password) 1770 int vnc_display_password(DisplayState *ds, const char *password)
@@ -1437,6 +1796,9 @@ int vnc_display_open(DisplayState *ds, const char *display) @@ -1437,6 +1796,9 @@ int vnc_display_open(DisplayState *ds, const char *display)
1437 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; 1796 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
1438 const char *options; 1797 const char *options;
1439 int password = 0; 1798 int password = 0;
  1799 +#if CONFIG_VNC_TLS
  1800 + int tls = 0;
  1801 +#endif
1440 1802
1441 vnc_display_close(ds); 1803 vnc_display_close(ds);
1442 if (strcmp(display, "none") == 0) 1804 if (strcmp(display, "none") == 0)
@@ -1450,14 +1812,40 @@ int vnc_display_open(DisplayState *ds, const char *display) @@ -1450,14 +1812,40 @@ int vnc_display_open(DisplayState *ds, const char *display)
1450 options++; 1812 options++;
1451 if (strncmp(options, "password", 8) == 0) 1813 if (strncmp(options, "password", 8) == 0)
1452 password = 1; /* Require password auth */ 1814 password = 1; /* Require password auth */
  1815 +#if CONFIG_VNC_TLS
  1816 + else if (strncmp(options, "tls", 3) == 0)
  1817 + tls = 1; /* Require TLS */
  1818 +#endif
1453 } 1819 }
1454 1820
1455 if (password) { 1821 if (password) {
1456 - VNC_DEBUG("Initializing VNC server with password auth\n");  
1457 - vs->auth = VNC_AUTH_VNC; 1822 +#if CONFIG_VNC_TLS
  1823 + if (tls) {
  1824 + VNC_DEBUG("Initializing VNC server with TLS password auth\n");
  1825 + vs->auth = VNC_AUTH_VENCRYPT;
  1826 + vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
  1827 + } else {
  1828 +#endif
  1829 + VNC_DEBUG("Initializing VNC server with password auth\n");
  1830 + vs->auth = VNC_AUTH_VNC;
  1831 +#if CONFIG_VNC_TLS
  1832 + vs->subauth = VNC_AUTH_INVALID;
  1833 + }
  1834 +#endif
1458 } else { 1835 } else {
1459 - VNC_DEBUG("Initializing VNC server with no auth\n");  
1460 - vs->auth = VNC_AUTH_NONE; 1836 +#if CONFIG_VNC_TLS
  1837 + if (tls) {
  1838 + VNC_DEBUG("Initializing VNC server with TLS no auth\n");
  1839 + vs->auth = VNC_AUTH_VENCRYPT;
  1840 + vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
  1841 + } else {
  1842 +#endif
  1843 + VNC_DEBUG("Initializing VNC server with no auth\n");
  1844 + vs->auth = VNC_AUTH_NONE;
  1845 +#if CONFIG_VNC_TLS
  1846 + vs->subauth = VNC_AUTH_INVALID;
  1847 + }
  1848 +#endif
1461 } 1849 }
1462 #ifndef _WIN32 1850 #ifndef _WIN32
1463 if (strstart(display, "unix:", &p)) { 1851 if (strstart(display, "unix:", &p)) {