Commit 5fb6c7a8b26eab1a22207d24b4784bd2b39ab54b

Authored by aliguori
1 parent 19a490bf

Move TLS auth into separate file ("Daniel P. Berrange")

This patch refactors the existing TLS code to make the main VNC code
more managable. The code moves to two new files

 - vnc-tls.c: generic helpers for TLS handshake & credential setup
 - vnc-auth-vencrypt.c: the actual VNC TLS authentication mechanism.

The reason for this split is that there are other TLS based auth
mechanisms which we may like to use in the future. These can all
share the same vnc-tls.c routines. In addition this will facilitate
anyone who may want to port the vnc-tls.c file to allow for choice
of GNUTLS & NSS for impl.

The TLS state is moved out of the VncState struct, and into a separate
VncStateTLS struct, defined in vnc-tls.h. This is then referenced from
the main VncState. End size of the struct is the same, but it keeps
things a little more managable.

The vnc.h file gains a bunch more function prototypes, for functions
in vnc.c that were previously static, but now need to be accessed
from the separate auth code files.

The only TLS related code still in the main vl.c is the command line
argument handling / setup, and the low level I/O routines calling
gnutls_send/recv.


 Makefile              |   11 
 b/vnc-auth-vencrypt.c |  167 ++++++++++++++
 b/vnc-auth-vencrypt.h |   33 ++
 b/vnc-tls.c           |  414 +++++++++++++++++++++++++++++++++++
 b/vnc-tls.h           |   70 ++++++
 vnc.c                 |  581 +++-----------------------------------------------
 vnc.h                 |   76 ++++--
 7 files changed, 780 insertions(+), 572 deletions(-)

   Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6723 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 3 changed files with 96 additions and 572 deletions
Makefile
... ... @@ -145,6 +145,9 @@ ifdef CONFIG_CURSES
145 145 OBJS+=curses.o
146 146 endif
147 147 OBJS+=vnc.o d3des.o
  148 +ifdef CONFIG_VNC_TLS
  149 +OBJS+=vnc-tls.o vnc-auth-vencrypt.o
  150 +endif
148 151  
149 152 ifdef CONFIG_COCOA
150 153 OBJS+=cocoa.o
... ... @@ -168,10 +171,16 @@ sdl.o: sdl.c keymaps.h sdl_keysym.h
168 171  
169 172 sdl.o audio/sdlaudio.o: CFLAGS += $(SDL_CFLAGS)
170 173  
171   -vnc.o: vnc.c keymaps.h sdl_keysym.h vnchextile.h d3des.c d3des.h
  174 +vnc.h: vnc-tls.h vnc-auth-vencrypt.h keymaps.h
  175 +
  176 +vnc.o: vnc.c vnc.h vnc_keysym.h vnchextile.h d3des.c d3des.h
172 177  
173 178 vnc.o: CFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
174 179  
  180 +vnc-tls.o: vnc-tls.c vnc.h
  181 +
  182 +vnc-auth-vencrypt.o: vnc-auth-vencrypt.c vnc.h
  183 +
175 184 curses.o: curses.c keymaps.h curses_keys.h
176 185  
177 186 bt-host.o: CFLAGS += $(CONFIG_BLUEZ_CFLAGS)
... ...
... ... @@ -34,21 +34,6 @@
34 34 #include "vnc_keysym.h"
35 35 #include "d3des.h"
36 36  
37   -// #define _VNC_DEBUG 1
38   -
39   -#ifdef _VNC_DEBUG
40   -#define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
41   -
42   -#if defined(CONFIG_VNC_TLS) && _VNC_DEBUG >= 2
43   -/* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
44   -static void vnc_debug_gnutls_log(int level, const char* str) {
45   - VNC_DEBUG("%d %s", level, str);
46   -}
47   -#endif /* CONFIG_VNC_TLS && _VNC_DEBUG */
48   -#else
49   -#define VNC_DEBUG(fmt, ...) do { } while (0)
50   -#endif
51   -
52 37 #define count_bits(c, v) { \
53 38 for (c = 0; v; v >>= 1) \
54 39 { \
... ... @@ -204,14 +189,7 @@ static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
204 189 3) resolutions > 1024
205 190 */
206 191  
207   -static void vnc_write(VncState *vs, const void *data, size_t len);
208   -static void vnc_write_u32(VncState *vs, uint32_t value);
209   -static void vnc_write_s32(VncState *vs, int32_t value);
210   -static void vnc_write_u16(VncState *vs, uint16_t value);
211   -static void vnc_write_u8(VncState *vs, uint8_t value);
212   -static void vnc_flush(VncState *vs);
213 192 static void vnc_update_client(void *opaque);
214   -static void vnc_client_read(void *opaque);
215 193  
216 194 static void vnc_colordepth(VncState *vs);
217 195  
... ... @@ -868,10 +846,7 @@ static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
868 846 if (vs->input.buffer) qemu_free(vs->input.buffer);
869 847 if (vs->output.buffer) qemu_free(vs->output.buffer);
870 848 #ifdef CONFIG_VNC_TLS
871   - if (vs->tls_session) {
872   - gnutls_deinit(vs->tls_session);
873   - vs->tls_session = NULL;
874   - }
  849 + vnc_tls_client_cleanup(vs);
875 850 #endif /* CONFIG_VNC_TLS */
876 851 audio_del(vs);
877 852  
... ... @@ -897,19 +872,20 @@ static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
897 872 return ret;
898 873 }
899 874  
900   -static void vnc_client_error(VncState *vs)
  875 +
  876 +void vnc_client_error(VncState *vs)
901 877 {
902 878 vnc_client_io_error(vs, -1, EINVAL);
903 879 }
904 880  
905   -static void vnc_client_write(void *opaque)
  881 +void vnc_client_write(void *opaque)
906 882 {
907 883 long ret;
908 884 VncState *vs = opaque;
909 885  
910 886 #ifdef CONFIG_VNC_TLS
911   - if (vs->tls_session) {
912   - ret = gnutls_write(vs->tls_session, vs->output.buffer, vs->output.offset);
  887 + if (vs->tls.session) {
  888 + ret = gnutls_write(vs->tls.session, vs->output.buffer, vs->output.offset);
913 889 if (ret < 0) {
914 890 if (ret == GNUTLS_E_AGAIN)
915 891 errno = EAGAIN;
... ... @@ -932,13 +908,13 @@ static void vnc_client_write(void *opaque)
932 908 }
933 909 }
934 910  
935   -static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
  911 +void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
936 912 {
937 913 vs->read_handler = func;
938 914 vs->read_handler_expect = expecting;
939 915 }
940 916  
941   -static void vnc_client_read(void *opaque)
  917 +void vnc_client_read(void *opaque)
942 918 {
943 919 VncState *vs = opaque;
944 920 long ret;
... ... @@ -946,8 +922,8 @@ static void vnc_client_read(void *opaque)
946 922 buffer_reserve(&vs->input, 4096);
947 923  
948 924 #ifdef CONFIG_VNC_TLS
949   - if (vs->tls_session) {
950   - ret = gnutls_read(vs->tls_session, buffer_end(&vs->input), 4096);
  925 + if (vs->tls.session) {
  926 + ret = gnutls_read(vs->tls.session, buffer_end(&vs->input), 4096);
951 927 if (ret < 0) {
952 928 if (ret == GNUTLS_E_AGAIN)
953 929 errno = EAGAIN;
... ... @@ -981,7 +957,7 @@ static void vnc_client_read(void *opaque)
981 957 }
982 958 }
983 959  
984   -static void vnc_write(VncState *vs, const void *data, size_t len)
  960 +void vnc_write(VncState *vs, const void *data, size_t len)
985 961 {
986 962 buffer_reserve(&vs->output, len);
987 963  
... ... @@ -992,12 +968,12 @@ static void vnc_write(VncState *vs, const void *data, size_t len)
992 968 buffer_append(&vs->output, data, len);
993 969 }
994 970  
995   -static void vnc_write_s32(VncState *vs, int32_t value)
  971 +void vnc_write_s32(VncState *vs, int32_t value)
996 972 {
997 973 vnc_write_u32(vs, *(uint32_t *)&value);
998 974 }
999 975  
1000   -static void vnc_write_u32(VncState *vs, uint32_t value)
  976 +void vnc_write_u32(VncState *vs, uint32_t value)
1001 977 {
1002 978 uint8_t buf[4];
1003 979  
... ... @@ -1009,7 +985,7 @@ static void vnc_write_u32(VncState *vs, uint32_t value)
1009 985 vnc_write(vs, buf, 4);
1010 986 }
1011 987  
1012   -static void vnc_write_u16(VncState *vs, uint16_t value)
  988 +void vnc_write_u16(VncState *vs, uint16_t value)
1013 989 {
1014 990 uint8_t buf[2];
1015 991  
... ... @@ -1019,74 +995,39 @@ static void vnc_write_u16(VncState *vs, uint16_t value)
1019 995 vnc_write(vs, buf, 2);
1020 996 }
1021 997  
1022   -static void vnc_write_u8(VncState *vs, uint8_t value)
  998 +void vnc_write_u8(VncState *vs, uint8_t value)
1023 999 {
1024 1000 vnc_write(vs, (char *)&value, 1);
1025 1001 }
1026 1002  
1027   -static void vnc_flush(VncState *vs)
  1003 +void vnc_flush(VncState *vs)
1028 1004 {
1029 1005 if (vs->output.offset)
1030 1006 vnc_client_write(vs);
1031 1007 }
1032 1008  
1033   -static uint8_t read_u8(uint8_t *data, size_t offset)
  1009 +uint8_t read_u8(uint8_t *data, size_t offset)
1034 1010 {
1035 1011 return data[offset];
1036 1012 }
1037 1013  
1038   -static uint16_t read_u16(uint8_t *data, size_t offset)
  1014 +uint16_t read_u16(uint8_t *data, size_t offset)
1039 1015 {
1040 1016 return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
1041 1017 }
1042 1018  
1043   -static int32_t read_s32(uint8_t *data, size_t offset)
  1019 +int32_t read_s32(uint8_t *data, size_t offset)
1044 1020 {
1045 1021 return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
1046 1022 (data[offset + 2] << 8) | data[offset + 3]);
1047 1023 }
1048 1024  
1049   -static uint32_t read_u32(uint8_t *data, size_t offset)
  1025 +uint32_t read_u32(uint8_t *data, size_t offset)
1050 1026 {
1051 1027 return ((data[offset] << 24) | (data[offset + 1] << 16) |
1052 1028 (data[offset + 2] << 8) | data[offset + 3]);
1053 1029 }
1054 1030  
1055   -#ifdef CONFIG_VNC_TLS
1056   -static ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
1057   - const void *data,
1058   - size_t len) {
1059   - struct VncState *vs = (struct VncState *)transport;
1060   - int ret;
1061   -
1062   - retry:
1063   - ret = send(vs->csock, data, len, 0);
1064   - if (ret < 0) {
1065   - if (errno == EINTR)
1066   - goto retry;
1067   - return -1;
1068   - }
1069   - return ret;
1070   -}
1071   -
1072   -
1073   -static ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
1074   - void *data,
1075   - size_t len) {
1076   - struct VncState *vs = (struct VncState *)transport;
1077   - int ret;
1078   -
1079   - retry:
1080   - ret = recv(vs->csock, data, len, 0);
1081   - if (ret < 0) {
1082   - if (errno == EINTR)
1083   - goto retry;
1084   - return -1;
1085   - }
1086   - return ret;
1087   -}
1088   -#endif /* CONFIG_VNC_TLS */
1089   -
1090 1031 static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
1091 1032 {
1092 1033 }
... ... @@ -1669,6 +1610,11 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1669 1610 return 0;
1670 1611 }
1671 1612  
  1613 +void start_client_init(VncState *vs)
  1614 +{
  1615 + vnc_read_when(vs, protocol_client_init, 1);
  1616 +}
  1617 +
1672 1618 static void make_challenge(VncState *vs)
1673 1619 {
1674 1620 int i;
... ... @@ -1724,12 +1670,12 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
1724 1670 vnc_write_u32(vs, 0); /* Accept auth */
1725 1671 vnc_flush(vs);
1726 1672  
1727   - vnc_read_when(vs, protocol_client_init, 1);
  1673 + start_client_init(vs);
1728 1674 }
1729 1675 return 0;
1730 1676 }
1731 1677  
1732   -static int start_auth_vnc(VncState *vs)
  1678 +void start_auth_vnc(VncState *vs)
1733 1679 {
1734 1680 make_challenge(vs);
1735 1681 /* Send client a 'random' challenge */
... ... @@ -1737,411 +1683,9 @@ static int start_auth_vnc(VncState *vs)
1737 1683 vnc_flush(vs);
1738 1684  
1739 1685 vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
1740   - return 0;
1741   -}
1742   -
1743   -
1744   -#ifdef CONFIG_VNC_TLS
1745   -#define DH_BITS 1024
1746   -static gnutls_dh_params_t dh_params;
1747   -
1748   -static int vnc_tls_initialize(void)
1749   -{
1750   - static int tlsinitialized = 0;
1751   -
1752   - if (tlsinitialized)
1753   - return 1;
1754   -
1755   - if (gnutls_global_init () < 0)
1756   - return 0;
1757   -
1758   - /* XXX ought to re-generate diffie-hellmen params periodically */
1759   - if (gnutls_dh_params_init (&dh_params) < 0)
1760   - return 0;
1761   - if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
1762   - return 0;
1763   -
1764   -#if defined(_VNC_DEBUG) && _VNC_DEBUG >= 2
1765   - gnutls_global_set_log_level(10);
1766   - gnutls_global_set_log_function(vnc_debug_gnutls_log);
1767   -#endif
1768   -
1769   - tlsinitialized = 1;
1770   -
1771   - return 1;
1772   -}
1773   -
1774   -static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
1775   -{
1776   - gnutls_anon_server_credentials anon_cred;
1777   - int ret;
1778   -
1779   - if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
1780   - VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1781   - return NULL;
1782   - }
1783   -
1784   - gnutls_anon_set_server_dh_params(anon_cred, dh_params);
1785   -
1786   - return anon_cred;
1787   -}
1788   -
1789   -
1790   -static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *vs)
1791   -{
1792   - gnutls_certificate_credentials_t x509_cred;
1793   - int ret;
1794   -
1795   - if (!vs->vd->x509cacert) {
1796   - VNC_DEBUG("No CA x509 certificate specified\n");
1797   - return NULL;
1798   - }
1799   - if (!vs->vd->x509cert) {
1800   - VNC_DEBUG("No server x509 certificate specified\n");
1801   - return NULL;
1802   - }
1803   - if (!vs->vd->x509key) {
1804   - VNC_DEBUG("No server private key specified\n");
1805   - return NULL;
1806   - }
1807   -
1808   - if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
1809   - VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1810   - return NULL;
1811   - }
1812   - if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
1813   - vs->vd->x509cacert,
1814   - GNUTLS_X509_FMT_PEM)) < 0) {
1815   - VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
1816   - gnutls_certificate_free_credentials(x509_cred);
1817   - return NULL;
1818   - }
1819   -
1820   - if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
1821   - vs->vd->x509cert,
1822   - vs->vd->x509key,
1823   - GNUTLS_X509_FMT_PEM)) < 0) {
1824   - VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
1825   - gnutls_certificate_free_credentials(x509_cred);
1826   - return NULL;
1827   - }
1828   -
1829   - if (vs->vd->x509cacrl) {
1830   - if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
1831   - vs->vd->x509cacrl,
1832   - GNUTLS_X509_FMT_PEM)) < 0) {
1833   - VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
1834   - gnutls_certificate_free_credentials(x509_cred);
1835   - return NULL;
1836   - }
1837   - }
1838   -
1839   - gnutls_certificate_set_dh_params (x509_cred, dh_params);
1840   -
1841   - return x509_cred;
1842   -}
1843   -
1844   -static int vnc_validate_certificate(struct VncState *vs)
1845   -{
1846   - int ret;
1847   - unsigned int status;
1848   - const gnutls_datum_t *certs;
1849   - unsigned int nCerts, i;
1850   - time_t now;
1851   -
1852   - VNC_DEBUG("Validating client certificate\n");
1853   - if ((ret = gnutls_certificate_verify_peers2 (vs->tls_session, &status)) < 0) {
1854   - VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret));
1855   - return -1;
1856   - }
1857   -
1858   - if ((now = time(NULL)) == ((time_t)-1)) {
1859   - return -1;
1860   - }
1861   -
1862   - if (status != 0) {
1863   - if (status & GNUTLS_CERT_INVALID)
1864   - VNC_DEBUG("The certificate is not trusted.\n");
1865   -
1866   - if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1867   - VNC_DEBUG("The certificate hasn't got a known issuer.\n");
1868   -
1869   - if (status & GNUTLS_CERT_REVOKED)
1870   - VNC_DEBUG("The certificate has been revoked.\n");
1871   -
1872   - if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1873   - VNC_DEBUG("The certificate uses an insecure algorithm\n");
1874   -
1875   - return -1;
1876   - } else {
1877   - VNC_DEBUG("Certificate is valid!\n");
1878   - }
1879   -
1880   - /* Only support x509 for now */
1881   - if (gnutls_certificate_type_get(vs->tls_session) != GNUTLS_CRT_X509)
1882   - return -1;
1883   -
1884   - if (!(certs = gnutls_certificate_get_peers(vs->tls_session, &nCerts)))
1885   - return -1;
1886   -
1887   - for (i = 0 ; i < nCerts ; i++) {
1888   - gnutls_x509_crt_t cert;
1889   - VNC_DEBUG ("Checking certificate chain %d\n", i);
1890   - if (gnutls_x509_crt_init (&cert) < 0)
1891   - return -1;
1892   -
1893   - if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
1894   - gnutls_x509_crt_deinit (cert);
1895   - return -1;
1896   - }
1897   -
1898   - if (gnutls_x509_crt_get_expiration_time (cert) < now) {
1899   - VNC_DEBUG("The certificate has expired\n");
1900   - gnutls_x509_crt_deinit (cert);
1901   - return -1;
1902   - }
1903   -
1904   - if (gnutls_x509_crt_get_activation_time (cert) > now) {
1905   - VNC_DEBUG("The certificate is not yet activated\n");
1906   - gnutls_x509_crt_deinit (cert);
1907   - return -1;
1908   - }
1909   -
1910   - if (gnutls_x509_crt_get_activation_time (cert) > now) {
1911   - VNC_DEBUG("The certificate is not yet activated\n");
1912   - gnutls_x509_crt_deinit (cert);
1913   - return -1;
1914   - }
1915   -
1916   - gnutls_x509_crt_deinit (cert);
1917   - }
1918   -
1919   - return 0;
1920 1686 }
1921 1687  
1922 1688  
1923   -static int start_auth_vencrypt_subauth(VncState *vs)
1924   -{
1925   - switch (vs->vd->subauth) {
1926   - case VNC_AUTH_VENCRYPT_TLSNONE:
1927   - case VNC_AUTH_VENCRYPT_X509NONE:
1928   - VNC_DEBUG("Accept TLS auth none\n");
1929   - vnc_write_u32(vs, 0); /* Accept auth completion */
1930   - vnc_read_when(vs, protocol_client_init, 1);
1931   - break;
1932   -
1933   - case VNC_AUTH_VENCRYPT_TLSVNC:
1934   - case VNC_AUTH_VENCRYPT_X509VNC:
1935   - VNC_DEBUG("Start TLS auth VNC\n");
1936   - return start_auth_vnc(vs);
1937   -
1938   - default: /* Should not be possible, but just in case */
1939   - VNC_DEBUG("Reject auth %d\n", vs->vd->auth);
1940   - vnc_write_u8(vs, 1);
1941   - if (vs->minor >= 8) {
1942   - static const char err[] = "Unsupported authentication type";
1943   - vnc_write_u32(vs, sizeof(err));
1944   - vnc_write(vs, err, sizeof(err));
1945   - }
1946   - vnc_client_error(vs);
1947   - }
1948   -
1949   - return 0;
1950   -}
1951   -
1952   -static void vnc_handshake_io(void *opaque);
1953   -
1954   -static int vnc_continue_handshake(struct VncState *vs) {
1955   - int ret;
1956   -
1957   - if ((ret = gnutls_handshake(vs->tls_session)) < 0) {
1958   - if (!gnutls_error_is_fatal(ret)) {
1959   - VNC_DEBUG("Handshake interrupted (blocking)\n");
1960   - if (!gnutls_record_get_direction(vs->tls_session))
1961   - qemu_set_fd_handler(vs->csock, vnc_handshake_io, NULL, vs);
1962   - else
1963   - qemu_set_fd_handler(vs->csock, NULL, vnc_handshake_io, vs);
1964   - return 0;
1965   - }
1966   - VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
1967   - vnc_client_error(vs);
1968   - return -1;
1969   - }
1970   -
1971   - if (vs->vd->x509verify) {
1972   - if (vnc_validate_certificate(vs) < 0) {
1973   - VNC_DEBUG("Client verification failed\n");
1974   - vnc_client_error(vs);
1975   - return -1;
1976   - } else {
1977   - VNC_DEBUG("Client verification passed\n");
1978   - }
1979   - }
1980   -
1981   - VNC_DEBUG("Handshake done, switching to TLS data mode\n");
1982   - vs->wiremode = VNC_WIREMODE_TLS;
1983   - qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
1984   -
1985   - return start_auth_vencrypt_subauth(vs);
1986   -}
1987   -
1988   -static void vnc_handshake_io(void *opaque) {
1989   - struct VncState *vs = (struct VncState *)opaque;
1990   -
1991   - VNC_DEBUG("Handshake IO continue\n");
1992   - vnc_continue_handshake(vs);
1993   -}
1994   -
1995   -#define NEED_X509_AUTH(vs) \
1996   - ((vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509NONE || \
1997   - (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509VNC || \
1998   - (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509PLAIN)
1999   -
2000   -
2001   -static int vnc_start_tls(struct VncState *vs) {
2002   - static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
2003   - static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
2004   - static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
2005   - static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
2006   -
2007   - VNC_DEBUG("Do TLS setup\n");
2008   - if (vnc_tls_initialize() < 0) {
2009   - VNC_DEBUG("Failed to init TLS\n");
2010   - vnc_client_error(vs);
2011   - return -1;
2012   - }
2013   - if (vs->tls_session == NULL) {
2014   - if (gnutls_init(&vs->tls_session, GNUTLS_SERVER) < 0) {
2015   - vnc_client_error(vs);
2016   - return -1;
2017   - }
2018   -
2019   - if (gnutls_set_default_priority(vs->tls_session) < 0) {
2020   - gnutls_deinit(vs->tls_session);
2021   - vs->tls_session = NULL;
2022   - vnc_client_error(vs);
2023   - return -1;
2024   - }
2025   -
2026   - if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ? kx_x509 : kx_anon) < 0) {
2027   - gnutls_deinit(vs->tls_session);
2028   - vs->tls_session = NULL;
2029   - vnc_client_error(vs);
2030   - return -1;
2031   - }
2032   -
2033   - if (gnutls_certificate_type_set_priority(vs->tls_session, cert_type_priority) < 0) {
2034   - gnutls_deinit(vs->tls_session);
2035   - vs->tls_session = NULL;
2036   - vnc_client_error(vs);
2037   - return -1;
2038   - }
2039   -
2040   - if (gnutls_protocol_set_priority(vs->tls_session, protocol_priority) < 0) {
2041   - gnutls_deinit(vs->tls_session);
2042   - vs->tls_session = NULL;
2043   - vnc_client_error(vs);
2044   - return -1;
2045   - }
2046   -
2047   - if (NEED_X509_AUTH(vs)) {
2048   - gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs);
2049   - if (!x509_cred) {
2050   - gnutls_deinit(vs->tls_session);
2051   - vs->tls_session = NULL;
2052   - vnc_client_error(vs);
2053   - return -1;
2054   - }
2055   - if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
2056   - gnutls_deinit(vs->tls_session);
2057   - vs->tls_session = NULL;
2058   - gnutls_certificate_free_credentials(x509_cred);
2059   - vnc_client_error(vs);
2060   - return -1;
2061   - }
2062   - if (vs->vd->x509verify) {
2063   - VNC_DEBUG("Requesting a client certificate\n");
2064   - gnutls_certificate_server_set_request (vs->tls_session, GNUTLS_CERT_REQUEST);
2065   - }
2066   -
2067   - } else {
2068   - gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
2069   - if (!anon_cred) {
2070   - gnutls_deinit(vs->tls_session);
2071   - vs->tls_session = NULL;
2072   - vnc_client_error(vs);
2073   - return -1;
2074   - }
2075   - if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
2076   - gnutls_deinit(vs->tls_session);
2077   - vs->tls_session = NULL;
2078   - gnutls_anon_free_server_credentials(anon_cred);
2079   - vnc_client_error(vs);
2080   - return -1;
2081   - }
2082   - }
2083   -
2084   - gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
2085   - gnutls_transport_set_push_function(vs->tls_session, vnc_tls_push);
2086   - gnutls_transport_set_pull_function(vs->tls_session, vnc_tls_pull);
2087   - }
2088   -
2089   - VNC_DEBUG("Start TLS handshake process\n");
2090   - return vnc_continue_handshake(vs);
2091   -}
2092   -
2093   -static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
2094   -{
2095   - int auth = read_u32(data, 0);
2096   -
2097   - if (auth != vs->vd->subauth) {
2098   - VNC_DEBUG("Rejecting auth %d\n", auth);
2099   - vnc_write_u8(vs, 0); /* Reject auth */
2100   - vnc_flush(vs);
2101   - vnc_client_error(vs);
2102   - } else {
2103   - VNC_DEBUG("Accepting auth %d, starting handshake\n", auth);
2104   - vnc_write_u8(vs, 1); /* Accept auth */
2105   - vnc_flush(vs);
2106   -
2107   - if (vnc_start_tls(vs) < 0) {
2108   - VNC_DEBUG("Failed to complete TLS\n");
2109   - return 0;
2110   - }
2111   - }
2112   - return 0;
2113   -}
2114   -
2115   -static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len)
2116   -{
2117   - if (data[0] != 0 ||
2118   - data[1] != 2) {
2119   - VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]);
2120   - vnc_write_u8(vs, 1); /* Reject version */
2121   - vnc_flush(vs);
2122   - vnc_client_error(vs);
2123   - } else {
2124   - VNC_DEBUG("Sending allowed auth %d\n", vs->vd->subauth);
2125   - vnc_write_u8(vs, 0); /* Accept version */
2126   - vnc_write_u8(vs, 1); /* Number of sub-auths */
2127   - vnc_write_u32(vs, vs->vd->subauth); /* The supported auth */
2128   - vnc_flush(vs);
2129   - vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
2130   - }
2131   - return 0;
2132   -}
2133   -
2134   -static int start_auth_vencrypt(VncState *vs)
2135   -{
2136   - /* Send VeNCrypt version 0.2 */
2137   - vnc_write_u8(vs, 0);
2138   - vnc_write_u8(vs, 2);
2139   -
2140   - vnc_read_when(vs, protocol_client_vencrypt_init, 2);
2141   - return 0;
2142   -}
2143   -#endif /* CONFIG_VNC_TLS */
2144   -
2145 1689 static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
2146 1690 {
2147 1691 /* We only advertise 1 auth scheme at a time, so client
... ... @@ -2164,17 +1708,19 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
2164 1708 vnc_write_u32(vs, 0); /* Accept auth completion */
2165 1709 vnc_flush(vs);
2166 1710 }
2167   - vnc_read_when(vs, protocol_client_init, 1);
  1711 + start_client_init(vs);
2168 1712 break;
2169 1713  
2170 1714 case VNC_AUTH_VNC:
2171 1715 VNC_DEBUG("Start VNC auth\n");
2172   - return start_auth_vnc(vs);
  1716 + start_auth_vnc(vs);
  1717 + break;
2173 1718  
2174 1719 #ifdef CONFIG_VNC_TLS
2175 1720 case VNC_AUTH_VENCRYPT:
2176 1721 VNC_DEBUG("Accept VeNCrypt auth\n");;
2177   - return start_auth_vencrypt(vs);
  1722 + start_auth_vencrypt(vs);
  1723 + break;
2178 1724 #endif /* CONFIG_VNC_TLS */
2179 1725  
2180 1726 default: /* Should not be possible, but just in case */
... ... @@ -2227,7 +1773,7 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len)
2227 1773 VNC_DEBUG("Tell client auth none\n");
2228 1774 vnc_write_u32(vs, vs->vd->auth);
2229 1775 vnc_flush(vs);
2230   - vnc_read_when(vs, protocol_client_init, 1);
  1776 + start_client_init(vs);
2231 1777 } else if (vs->vd->auth == VNC_AUTH_VNC) {
2232 1778 VNC_DEBUG("Tell client VNC auth\n");
2233 1779 vnc_write_u32(vs, vs->vd->auth);
... ... @@ -2329,61 +1875,6 @@ void vnc_display_init(DisplayState *ds)
2329 1875 register_displaychangelistener(ds, dcl);
2330 1876 }
2331 1877  
2332   -#ifdef CONFIG_VNC_TLS
2333   -static int vnc_set_x509_credential(VncDisplay *vs,
2334   - const char *certdir,
2335   - const char *filename,
2336   - char **cred,
2337   - int ignoreMissing)
2338   -{
2339   - struct stat sb;
2340   -
2341   - if (*cred) {
2342   - qemu_free(*cred);
2343   - *cred = NULL;
2344   - }
2345   -
2346   - *cred = qemu_malloc(strlen(certdir) + strlen(filename) + 2);
2347   -
2348   - strcpy(*cred, certdir);
2349   - strcat(*cred, "/");
2350   - strcat(*cred, filename);
2351   -
2352   - VNC_DEBUG("Check %s\n", *cred);
2353   - if (stat(*cred, &sb) < 0) {
2354   - qemu_free(*cred);
2355   - *cred = NULL;
2356   - if (ignoreMissing && errno == ENOENT)
2357   - return 0;
2358   - return -1;
2359   - }
2360   -
2361   - return 0;
2362   -}
2363   -
2364   -static int vnc_set_x509_credential_dir(VncDisplay *vs,
2365   - const char *certdir)
2366   -{
2367   - if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, &vs->x509cacert, 0) < 0)
2368   - goto cleanup;
2369   - if (vnc_set_x509_credential(vs, certdir, X509_CA_CRL_FILE, &vs->x509cacrl, 1) < 0)
2370   - goto cleanup;
2371   - if (vnc_set_x509_credential(vs, certdir, X509_SERVER_CERT_FILE, &vs->x509cert, 0) < 0)
2372   - goto cleanup;
2373   - if (vnc_set_x509_credential(vs, certdir, X509_SERVER_KEY_FILE, &vs->x509key, 0) < 0)
2374   - goto cleanup;
2375   -
2376   - return 0;
2377   -
2378   - cleanup:
2379   - qemu_free(vs->x509cacert);
2380   - qemu_free(vs->x509cacrl);
2381   - qemu_free(vs->x509cert);
2382   - qemu_free(vs->x509key);
2383   - vs->x509cacert = vs->x509cacrl = vs->x509cert = vs->x509key = NULL;
2384   - return -1;
2385   -}
2386   -#endif /* CONFIG_VNC_TLS */
2387 1878  
2388 1879 void vnc_display_close(DisplayState *ds)
2389 1880 {
... ... @@ -2403,7 +1894,7 @@ void vnc_display_close(DisplayState *ds)
2403 1894 vs->auth = VNC_AUTH_INVALID;
2404 1895 #ifdef CONFIG_VNC_TLS
2405 1896 vs->subauth = VNC_AUTH_INVALID;
2406   - vs->x509verify = 0;
  1897 + vs->tls.x509verify = 0;
2407 1898 #endif
2408 1899 }
2409 1900  
... ... @@ -2459,7 +1950,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
2459 1950 char *start, *end;
2460 1951 x509 = 1; /* Require x509 certificates */
2461 1952 if (strncmp(options, "x509verify", 10) == 0)
2462   - vs->x509verify = 1; /* ...and verify client certs */
  1953 + vs->tls.x509verify = 1; /* ...and verify client certs */
2463 1954  
2464 1955 /* Now check for 'x509=/some/path' postfix
2465 1956 * and use that to setup x509 certificate/key paths */
... ... @@ -2470,7 +1961,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
2470 1961 char *path = qemu_strndup(start + 1, len);
2471 1962  
2472 1963 VNC_DEBUG("Trying certificate path '%s'\n", path);
2473   - if (vnc_set_x509_credential_dir(vs, path) < 0) {
  1964 + if (vnc_tls_set_x509_creds_dir(vs, path) < 0) {
2474 1965 fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
2475 1966 qemu_free(path);
2476 1967 qemu_free(vs->display);
... ...
... ... @@ -33,13 +33,16 @@
33 33 #include "audio/audio.h"
34 34 #include <zlib.h>
35 35  
36   -#ifdef CONFIG_VNC_TLS
37   -#include <gnutls/gnutls.h>
38   -#include <gnutls/x509.h>
39   -#endif /* CONFIG_VNC_TLS */
40   -
41 36 #include "keymaps.h"
42 37  
  38 +// #define _VNC_DEBUG 1
  39 +
  40 +#ifdef _VNC_DEBUG
  41 +#define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
  42 +#else
  43 +#define VNC_DEBUG(fmt, ...) do { } while (0)
  44 +#endif
  45 +
43 46 /*****************************************************************************
44 47 *
45 48 * Core data structures
... ... @@ -73,6 +76,11 @@ typedef void VncSendHextileTile(VncState *vs,
73 76  
74 77 typedef struct VncDisplay VncDisplay;
75 78  
  79 +#ifdef CONFIG_VNC_TLS
  80 +#include "vnc-tls.h"
  81 +#include "vnc-auth-vencrypt.h"
  82 +#endif
  83 +
76 84 struct VncDisplay
77 85 {
78 86 int lsock;
... ... @@ -84,13 +92,8 @@ struct VncDisplay
84 92 char *password;
85 93 int auth;
86 94 #ifdef CONFIG_VNC_TLS
87   - int subauth;
88   - int x509verify;
89   -
90   - char *x509cacert;
91   - char *x509cacrl;
92   - char *x509cert;
93   - char *x509key;
  95 + int subauth; /* Used by VeNCrypt */
  96 + VncDisplayTLS tls;
94 97 #endif
95 98 };
96 99  
... ... @@ -118,8 +121,7 @@ struct VncState
118 121 char challenge[VNC_AUTH_CHALLENGE_SIZE];
119 122  
120 123 #ifdef CONFIG_VNC_TLS
121   - int wiremode;
122   - gnutls_session_t tls_session;
  124 + VncStateTLS tls;
123 125 #endif
124 126  
125 127 Buffer output;
... ... @@ -163,12 +165,6 @@ enum {
163 165 VNC_AUTH_VENCRYPT = 19
164 166 };
165 167  
166   -#ifdef CONFIG_VNC_TLS
167   -enum {
168   - VNC_WIREMODE_CLEAR,
169   - VNC_WIREMODE_TLS,
170   -};
171   -
172 168 enum {
173 169 VNC_AUTH_VENCRYPT_PLAIN = 256,
174 170 VNC_AUTH_VENCRYPT_TLSNONE = 257,
... ... @@ -179,12 +175,6 @@ enum {
179 175 VNC_AUTH_VENCRYPT_X509PLAIN = 262,
180 176 };
181 177  
182   -#define X509_CA_CERT_FILE "ca-cert.pem"
183   -#define X509_CA_CRL_FILE "ca-crl.pem"
184   -#define X509_SERVER_KEY_FILE "server-key.pem"
185   -#define X509_SERVER_CERT_FILE "server-cert.pem"
186   -
187   -#endif /* CONFIG_VNC_TLS */
188 178  
189 179 /*****************************************************************************
190 180 *
... ... @@ -255,4 +245,38 @@ enum {
255 245 #define VNC_FEATURE_ZLIB_MASK (1 << VNC_FEATURE_ZLIB)
256 246 #define VNC_FEATURE_COPYRECT_MASK (1 << VNC_FEATURE_COPYRECT)
257 247  
  248 +
  249 +/*****************************************************************************
  250 + *
  251 + * Internal APIs
  252 + *
  253 + *****************************************************************************/
  254 +
  255 +/* Event loop functions */
  256 +void vnc_client_read(void *opaque);
  257 +void vnc_client_write(void *opaque);
  258 +
  259 +
  260 +/* Protocol I/O functions */
  261 +void vnc_write(VncState *vs, const void *data, size_t len);
  262 +void vnc_write_u32(VncState *vs, uint32_t value);
  263 +void vnc_write_s32(VncState *vs, int32_t value);
  264 +void vnc_write_u16(VncState *vs, uint16_t value);
  265 +void vnc_write_u8(VncState *vs, uint8_t value);
  266 +void vnc_flush(VncState *vs);
  267 +void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting);
  268 +
  269 +
  270 +/* Buffer I/O functions */
  271 +uint8_t read_u8(uint8_t *data, size_t offset);
  272 +uint16_t read_u16(uint8_t *data, size_t offset);
  273 +int32_t read_s32(uint8_t *data, size_t offset);
  274 +uint32_t read_u32(uint8_t *data, size_t offset);
  275 +
  276 +/* Protocol stage functions */
  277 +void vnc_client_error(VncState *vs);
  278 +
  279 +void start_client_init(VncState *vs);
  280 +void start_auth_vnc(VncState *vs);
  281 +
258 282 #endif /* __QEMU_VNC_H */
... ...