Commit 3a702699b26ba5116c153457d552c577383a9fa1

Authored by ths
1 parent 8d5d2d4c

x509 certificate for server, by Daniel P. Berrange.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3137 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 107 additions and 20 deletions
@@ -105,6 +105,14 @@ enum { @@ -105,6 +105,14 @@ enum {
105 VNC_AUTH_VENCRYPT_X509VNC = 261, 105 VNC_AUTH_VENCRYPT_X509VNC = 261,
106 VNC_AUTH_VENCRYPT_X509PLAIN = 262, 106 VNC_AUTH_VENCRYPT_X509PLAIN = 262,
107 }; 107 };
  108 +
  109 +#if CONFIG_VNC_TLS
  110 +#define X509_CA_CERT_FILE "ca-cert.pem"
  111 +#define X509_CA_CRL_FILE "ca-crl.pem"
  112 +#define X509_SERVER_KEY_FILE "server-key.pem"
  113 +#define X509_SERVER_CERT_FILE "server-cert.pem"
  114 +#endif
  115 +
108 #endif /* CONFIG_VNC_TLS */ 116 #endif /* CONFIG_VNC_TLS */
109 117
110 struct VncState 118 struct VncState
@@ -1377,16 +1385,60 @@ static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void) @@ -1377,16 +1385,60 @@ static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
1377 } 1385 }
1378 1386
1379 1387
  1388 +static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(void)
  1389 +{
  1390 + gnutls_certificate_credentials_t x509_cred;
  1391 + int ret;
  1392 + struct stat st;
  1393 +
  1394 + if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
  1395 + VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
  1396 + return NULL;
  1397 + }
  1398 + if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred, X509_CA_CERT_FILE, GNUTLS_X509_FMT_PEM)) < 0) {
  1399 + VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
  1400 + gnutls_certificate_free_credentials(x509_cred);
  1401 + return NULL;
  1402 + }
  1403 +
  1404 + if ((ret = gnutls_certificate_set_x509_key_file (x509_cred, X509_SERVER_CERT_FILE,
  1405 + X509_SERVER_KEY_FILE,
  1406 + GNUTLS_X509_FMT_PEM)) < 0) {
  1407 + VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
  1408 + gnutls_certificate_free_credentials(x509_cred);
  1409 + return NULL;
  1410 + }
  1411 +
  1412 + if (stat(X509_CA_CRL_FILE, &st) < 0) {
  1413 + if (errno != ENOENT) {
  1414 + gnutls_certificate_free_credentials(x509_cred);
  1415 + return NULL;
  1416 + }
  1417 + } else {
  1418 + if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred, X509_CA_CRL_FILE, GNUTLS_X509_FMT_PEM)) < 0) {
  1419 + VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
  1420 + gnutls_certificate_free_credentials(x509_cred);
  1421 + return NULL;
  1422 + }
  1423 + }
  1424 +
  1425 + gnutls_certificate_set_dh_params (x509_cred, dh_params);
  1426 +
  1427 + return x509_cred;
  1428 +}
  1429 +
1380 static int start_auth_vencrypt_subauth(VncState *vs) 1430 static int start_auth_vencrypt_subauth(VncState *vs)
1381 { 1431 {
1382 switch (vs->subauth) { 1432 switch (vs->subauth) {
1383 case VNC_AUTH_VENCRYPT_TLSNONE: 1433 case VNC_AUTH_VENCRYPT_TLSNONE:
  1434 + case VNC_AUTH_VENCRYPT_X509NONE:
1384 VNC_DEBUG("Accept TLS auth none\n"); 1435 VNC_DEBUG("Accept TLS auth none\n");
1385 vnc_write_u32(vs, 0); /* Accept auth completion */ 1436 vnc_write_u32(vs, 0); /* Accept auth completion */
1386 vnc_read_when(vs, protocol_client_init, 1); 1437 vnc_read_when(vs, protocol_client_init, 1);
1387 break; 1438 break;
1388 1439
1389 case VNC_AUTH_VENCRYPT_TLSVNC: 1440 case VNC_AUTH_VENCRYPT_TLSVNC:
  1441 + case VNC_AUTH_VENCRYPT_X509VNC:
1390 VNC_DEBUG("Start TLS auth VNC\n"); 1442 VNC_DEBUG("Start TLS auth VNC\n");
1391 return start_auth_vnc(vs); 1443 return start_auth_vnc(vs);
1392 1444
@@ -1437,11 +1489,17 @@ static void vnc_handshake_io(void *opaque) { @@ -1437,11 +1489,17 @@ static void vnc_handshake_io(void *opaque) {
1437 vnc_continue_handshake(vs); 1489 vnc_continue_handshake(vs);
1438 } 1490 }
1439 1491
  1492 +#define NEED_X509_AUTH(vs) \
  1493 + ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE || \
  1494 + (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC || \
  1495 + (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN)
  1496 +
  1497 +
1440 static int vnc_start_tls(struct VncState *vs) { 1498 static int vnc_start_tls(struct VncState *vs) {
1441 static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; 1499 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 }; 1500 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}; 1501 static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
1444 - gnutls_anon_server_credentials anon_cred = NULL; 1502 + static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
1445 1503
1446 VNC_DEBUG("Do TLS setup\n"); 1504 VNC_DEBUG("Do TLS setup\n");
1447 if (vnc_tls_initialize() < 0) { 1505 if (vnc_tls_initialize() < 0) {
@@ -1462,7 +1520,7 @@ static int vnc_start_tls(struct VncState *vs) { @@ -1462,7 +1520,7 @@ static int vnc_start_tls(struct VncState *vs) {
1462 return -1; 1520 return -1;
1463 } 1521 }
1464 1522
1465 - if (gnutls_kx_set_priority(vs->tls_session, kx_anon) < 0) { 1523 + if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ? kx_x509 : kx_anon) < 0) {
1466 gnutls_deinit(vs->tls_session); 1524 gnutls_deinit(vs->tls_session);
1467 vs->tls_session = NULL; 1525 vs->tls_session = NULL;
1468 vnc_client_error(vs); 1526 vnc_client_error(vs);
@@ -1483,19 +1541,36 @@ static int vnc_start_tls(struct VncState *vs) { @@ -1483,19 +1541,36 @@ static int vnc_start_tls(struct VncState *vs) {
1483 return -1; 1541 return -1;
1484 } 1542 }
1485 1543
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; 1544 + if (NEED_X509_AUTH(vs)) {
  1545 + gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred();
  1546 + if (!x509_cred) {
  1547 + gnutls_deinit(vs->tls_session);
  1548 + vs->tls_session = NULL;
  1549 + vnc_client_error(vs);
  1550 + return -1;
  1551 + }
  1552 + if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
  1553 + gnutls_deinit(vs->tls_session);
  1554 + vs->tls_session = NULL;
  1555 + gnutls_certificate_free_credentials(x509_cred);
  1556 + vnc_client_error(vs);
  1557 + return -1;
  1558 + }
  1559 + } else {
  1560 + gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
  1561 + if (!anon_cred) {
  1562 + gnutls_deinit(vs->tls_session);
  1563 + vs->tls_session = NULL;
  1564 + vnc_client_error(vs);
  1565 + return -1;
  1566 + }
  1567 + if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
  1568 + gnutls_deinit(vs->tls_session);
  1569 + vs->tls_session = NULL;
  1570 + gnutls_anon_free_server_credentials(anon_cred);
  1571 + vnc_client_error(vs);
  1572 + return -1;
  1573 + }
1499 } 1574 }
1500 1575
1501 gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs); 1576 gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
@@ -1797,7 +1872,7 @@ int vnc_display_open(DisplayState *ds, const char *display) @@ -1797,7 +1872,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
1797 const char *options; 1872 const char *options;
1798 int password = 0; 1873 int password = 0;
1799 #if CONFIG_VNC_TLS 1874 #if CONFIG_VNC_TLS
1800 - int tls = 0; 1875 + int tls = 0, x509 = 0;
1801 #endif 1876 #endif
1802 1877
1803 vnc_display_close(ds); 1878 vnc_display_close(ds);
@@ -1815,15 +1890,22 @@ int vnc_display_open(DisplayState *ds, const char *display) @@ -1815,15 +1890,22 @@ int vnc_display_open(DisplayState *ds, const char *display)
1815 #if CONFIG_VNC_TLS 1890 #if CONFIG_VNC_TLS
1816 else if (strncmp(options, "tls", 3) == 0) 1891 else if (strncmp(options, "tls", 3) == 0)
1817 tls = 1; /* Require TLS */ 1892 tls = 1; /* Require TLS */
  1893 + else if (strncmp(options, "x509", 4) == 0)
  1894 + x509 = 1; /* Require x509 certificates */
1818 #endif 1895 #endif
1819 } 1896 }
1820 1897
1821 if (password) { 1898 if (password) {
1822 #if CONFIG_VNC_TLS 1899 #if CONFIG_VNC_TLS
1823 if (tls) { 1900 if (tls) {
1824 - VNC_DEBUG("Initializing VNC server with TLS password auth\n");  
1825 vs->auth = VNC_AUTH_VENCRYPT; 1901 vs->auth = VNC_AUTH_VENCRYPT;
1826 - vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC; 1902 + if (x509) {
  1903 + VNC_DEBUG("Initializing VNC server with x509 password auth\n");
  1904 + vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
  1905 + } else {
  1906 + VNC_DEBUG("Initializing VNC server with TLS password auth\n");
  1907 + vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
  1908 + }
1827 } else { 1909 } else {
1828 #endif 1910 #endif
1829 VNC_DEBUG("Initializing VNC server with password auth\n"); 1911 VNC_DEBUG("Initializing VNC server with password auth\n");
@@ -1835,9 +1917,14 @@ int vnc_display_open(DisplayState *ds, const char *display) @@ -1835,9 +1917,14 @@ int vnc_display_open(DisplayState *ds, const char *display)
1835 } else { 1917 } else {
1836 #if CONFIG_VNC_TLS 1918 #if CONFIG_VNC_TLS
1837 if (tls) { 1919 if (tls) {
1838 - VNC_DEBUG("Initializing VNC server with TLS no auth\n");  
1839 vs->auth = VNC_AUTH_VENCRYPT; 1920 vs->auth = VNC_AUTH_VENCRYPT;
1840 - vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE; 1921 + if (x509) {
  1922 + VNC_DEBUG("Initializing VNC server with x509 no auth\n");
  1923 + vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
  1924 + } else {
  1925 + VNC_DEBUG("Initializing VNC server with TLS no auth\n");
  1926 + vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
  1927 + }
1841 } else { 1928 } else {
1842 #endif 1929 #endif
1843 VNC_DEBUG("Initializing VNC server with no auth\n"); 1930 VNC_DEBUG("Initializing VNC server with no auth\n");