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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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);
|