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 405 endif
406 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 413 VL_OBJS += i2c.o smbus.o
409 414  
410 415 # SCSI layer
... ...
configure
... ... @@ -89,6 +89,7 @@ alsa="no"
89 89 fmod="no"
90 90 fmod_lib=""
91 91 fmod_inc=""
  92 +vnc_tls="yes"
92 93 bsd="no"
93 94 linux="no"
94 95 kqemu="no"
... ... @@ -252,6 +253,8 @@ for opt do
252 253 ;;
253 254 --fmod-inc=*) fmod_inc="$optarg"
254 255 ;;
  256 + --disable-vnc-tls) vnc_tls="no"
  257 + ;;
255 258 --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; linux_user="no"
256 259 ;;
257 260 --disable-slirp) slirp="no"
... ... @@ -362,6 +365,7 @@ echo " --enable-coreaudio enable Coreaudio audio driver"
362 365 echo " --enable-alsa enable ALSA audio driver"
363 366 echo " --enable-fmod enable FMOD audio driver"
364 367 echo " --enable-dsound enable DirectSound audio driver"
  368 +echo " --disable-vnc-tls disable TLS encryption for VNC server"
365 369 echo " --enable-system enable all system emulation targets"
366 370 echo " --disable-system disable all system emulation targets"
367 371 echo " --enable-linux-user enable all linux usermode emulation targets"
... ... @@ -589,6 +593,16 @@ else
589 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 606 # alsa sound support libraries
593 607  
594 608 if test "$alsa" = "yes" ; then
... ... @@ -675,6 +689,11 @@ else
675 689 fi
676 690 echo "FMOD support $fmod $fmod_support"
677 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 697 if test -n "$sparc_cpu"; then
679 698 echo "Target Sparc Arch $sparc_cpu"
680 699 fi
... ... @@ -847,6 +866,12 @@ if test "$fmod" = "yes" ; then
847 866 echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak
848 867 echo "#define CONFIG_FMOD 1" >> $config_h
849 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 875 qemu_version=`head $source_path/VERSION`
851 876 echo "VERSION=$qemu_version" >>$config_mak
852 877 echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h
... ...
... ... @@ -32,14 +32,27 @@
32 32 #include "keymaps.c"
33 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 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 51 #else
40 52 #define VNC_DEBUG(fmt, ...) do { } while (0)
41 53 #endif
42 54  
  55 +
43 56 typedef struct Buffer
44 57 {
45 58 size_t capacity;
... ... @@ -77,6 +90,23 @@ enum {
77 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 110 struct VncState
81 111 {
82 112 QEMUTimer *timer;
... ... @@ -102,8 +132,16 @@ struct VncState
102 132 char *display;
103 133 char *password;
104 134 int auth;
  135 +#if CONFIG_VNC_TLS
  136 + int subauth;
  137 +#endif
105 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 145 Buffer output;
108 146 Buffer input;
109 147 kbd_layout_t *kbd_layout;
... ... @@ -579,12 +617,20 @@ static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
579 617 if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
580 618 return 0;
581 619  
  620 + VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0);
582 621 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
583 622 closesocket(vs->csock);
584 623 vs->csock = -1;
585 624 buffer_reset(&vs->input);
586 625 buffer_reset(&vs->output);
587 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 634 return 0;
589 635 }
590 636 return ret;
... ... @@ -600,7 +646,19 @@ static void vnc_client_write(void *opaque)
600 646 long ret;
601 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 662 ret = vnc_client_io_error(vs, ret, socket_error());
605 663 if (!ret)
606 664 return;
... ... @@ -626,7 +684,19 @@ static void vnc_client_read(void *opaque)
626 684  
627 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 700 ret = vnc_client_io_error(vs, ret, socket_error());
631 701 if (!ret)
632 702 return;
... ... @@ -721,6 +791,41 @@ static uint32_t read_u32(uint8_t *data, size_t offset)
721 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 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 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 1570 static int protocol_client_auth(VncState *vs, char *data, size_t len)
1229 1571 {
1230 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 1593 VNC_DEBUG("Start VNC auth\n");
1252 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 1602 default: /* Should not be possible, but just in case */
1255 1603 VNC_DEBUG("Reject auth %d\n", vs->auth);
1256 1604 vnc_write_u8(vs, 1);
... ... @@ -1331,6 +1679,7 @@ static void vnc_listen_read(void *opaque)
1331 1679  
1332 1680 vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
1333 1681 if (vs->csock != -1) {
  1682 + VNC_DEBUG("New client on socket %d\n", vs->csock);
1334 1683 socket_set_nonblock(vs->csock);
1335 1684 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
1336 1685 vnc_write(vs, "RFB 003.008\n", 12);
... ... @@ -1404,8 +1753,18 @@ void vnc_display_close(DisplayState *ds)
1404 1753 buffer_reset(&vs->input);
1405 1754 buffer_reset(&vs->output);
1406 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 1764 vs->auth = VNC_AUTH_INVALID;
  1765 +#if CONFIG_VNC_TLS
  1766 + vs->subauth = VNC_AUTH_INVALID;
  1767 +#endif
1409 1768 }
1410 1769  
1411 1770 int vnc_display_password(DisplayState *ds, const char *password)
... ... @@ -1437,6 +1796,9 @@ int vnc_display_open(DisplayState *ds, const char *display)
1437 1796 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
1438 1797 const char *options;
1439 1798 int password = 0;
  1799 +#if CONFIG_VNC_TLS
  1800 + int tls = 0;
  1801 +#endif
1440 1802  
1441 1803 vnc_display_close(ds);
1442 1804 if (strcmp(display, "none") == 0)
... ... @@ -1450,14 +1812,40 @@ int vnc_display_open(DisplayState *ds, const char *display)
1450 1812 options++;
1451 1813 if (strncmp(options, "password", 8) == 0)
1452 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 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 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 1850 #ifndef _WIN32
1463 1851 if (strstart(display, "unix:", &p)) {
... ...