Commit 6f43024c90ec6de51e31193ebf6e6ea3b776652a

Authored by ths
1 parent 469b15c6

Custom location for x509 cert paths, by Daniel P. Berrange.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3139 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 115 additions and 16 deletions
@@ -143,6 +143,11 @@ struct VncState @@ -143,6 +143,11 @@ struct VncState
143 #if CONFIG_VNC_TLS 143 #if CONFIG_VNC_TLS
144 int subauth; 144 int subauth;
145 int x509verify; 145 int x509verify;
  146 +
  147 + char *x509cacert;
  148 + char *x509cacrl;
  149 + char *x509cert;
  150 + char *x509key;
146 #endif 151 #endif
147 char challenge[VNC_AUTH_CHALLENGE_SIZE]; 152 char challenge[VNC_AUTH_CHALLENGE_SIZE];
148 153
@@ -1386,37 +1391,49 @@ static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void) @@ -1386,37 +1391,49 @@ static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
1386 } 1391 }
1387 1392
1388 1393
1389 -static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(void) 1394 +static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *vs)
1390 { 1395 {
1391 gnutls_certificate_credentials_t x509_cred; 1396 gnutls_certificate_credentials_t x509_cred;
1392 int ret; 1397 int ret;
1393 - struct stat st; 1398 +
  1399 + if (!vs->x509cacert) {
  1400 + VNC_DEBUG("No CA x509 certificate specified\n");
  1401 + return NULL;
  1402 + }
  1403 + if (!vs->x509cert) {
  1404 + VNC_DEBUG("No server x509 certificate specified\n");
  1405 + return NULL;
  1406 + }
  1407 + if (!vs->x509key) {
  1408 + VNC_DEBUG("No server private key specified\n");
  1409 + return NULL;
  1410 + }
1394 1411
1395 if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) { 1412 if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
1396 VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret)); 1413 VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1397 return NULL; 1414 return NULL;
1398 } 1415 }
1399 - if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred, X509_CA_CERT_FILE, GNUTLS_X509_FMT_PEM)) < 0) { 1416 + if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
  1417 + vs->x509cacert,
  1418 + GNUTLS_X509_FMT_PEM)) < 0) {
1400 VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret)); 1419 VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
1401 gnutls_certificate_free_credentials(x509_cred); 1420 gnutls_certificate_free_credentials(x509_cred);
1402 return NULL; 1421 return NULL;
1403 } 1422 }
1404 1423
1405 - if ((ret = gnutls_certificate_set_x509_key_file (x509_cred, X509_SERVER_CERT_FILE,  
1406 - X509_SERVER_KEY_FILE, 1424 + if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
  1425 + vs->x509cert,
  1426 + vs->x509key,
1407 GNUTLS_X509_FMT_PEM)) < 0) { 1427 GNUTLS_X509_FMT_PEM)) < 0) {
1408 VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret)); 1428 VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
1409 gnutls_certificate_free_credentials(x509_cred); 1429 gnutls_certificate_free_credentials(x509_cred);
1410 return NULL; 1430 return NULL;
1411 } 1431 }
1412 1432
1413 - if (stat(X509_CA_CRL_FILE, &st) < 0) {  
1414 - if (errno != ENOENT) {  
1415 - gnutls_certificate_free_credentials(x509_cred);  
1416 - return NULL;  
1417 - }  
1418 - } else {  
1419 - if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred, X509_CA_CRL_FILE, GNUTLS_X509_FMT_PEM)) < 0) { 1433 + if (vs->x509cacrl) {
  1434 + if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
  1435 + vs->x509cacrl,
  1436 + GNUTLS_X509_FMT_PEM)) < 0) {
1420 VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret)); 1437 VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
1421 gnutls_certificate_free_credentials(x509_cred); 1438 gnutls_certificate_free_credentials(x509_cred);
1422 return NULL; 1439 return NULL;
@@ -1632,7 +1649,7 @@ static int vnc_start_tls(struct VncState *vs) { @@ -1632,7 +1649,7 @@ static int vnc_start_tls(struct VncState *vs) {
1632 } 1649 }
1633 1650
1634 if (NEED_X509_AUTH(vs)) { 1651 if (NEED_X509_AUTH(vs)) {
1635 - gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(); 1652 + gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs);
1636 if (!x509_cred) { 1653 if (!x509_cred) {
1637 gnutls_deinit(vs->tls_session); 1654 gnutls_deinit(vs->tls_session);
1638 vs->tls_session = NULL; 1655 vs->tls_session = NULL;
@@ -1903,6 +1920,63 @@ void vnc_display_init(DisplayState *ds) @@ -1903,6 +1920,63 @@ void vnc_display_init(DisplayState *ds)
1903 vnc_dpy_resize(vs->ds, 640, 400); 1920 vnc_dpy_resize(vs->ds, 640, 400);
1904 } 1921 }
1905 1922
  1923 +#if CONFIG_VNC_TLS
  1924 +static int vnc_set_x509_credential(VncState *vs,
  1925 + const char *certdir,
  1926 + const char *filename,
  1927 + char **cred,
  1928 + int ignoreMissing)
  1929 +{
  1930 + struct stat sb;
  1931 +
  1932 + if (*cred) {
  1933 + qemu_free(*cred);
  1934 + *cred = NULL;
  1935 + }
  1936 +
  1937 + if (!(*cred = qemu_malloc(strlen(certdir) + strlen(filename) + 2)))
  1938 + return -1;
  1939 +
  1940 + strcpy(*cred, certdir);
  1941 + strcat(*cred, "/");
  1942 + strcat(*cred, filename);
  1943 +
  1944 + VNC_DEBUG("Check %s\n", *cred);
  1945 + if (stat(*cred, &sb) < 0) {
  1946 + qemu_free(*cred);
  1947 + *cred = NULL;
  1948 + if (ignoreMissing && errno == ENOENT)
  1949 + return 0;
  1950 + return -1;
  1951 + }
  1952 +
  1953 + return 0;
  1954 +}
  1955 +
  1956 +static int vnc_set_x509_credential_dir(VncState *vs,
  1957 + const char *certdir)
  1958 +{
  1959 + if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, &vs->x509cacert, 0) < 0)
  1960 + goto cleanup;
  1961 + if (vnc_set_x509_credential(vs, certdir, X509_CA_CRL_FILE, &vs->x509cacrl, 1) < 0)
  1962 + goto cleanup;
  1963 + if (vnc_set_x509_credential(vs, certdir, X509_SERVER_CERT_FILE, &vs->x509cert, 0) < 0)
  1964 + goto cleanup;
  1965 + if (vnc_set_x509_credential(vs, certdir, X509_SERVER_KEY_FILE, &vs->x509key, 0) < 0)
  1966 + goto cleanup;
  1967 +
  1968 + return 0;
  1969 +
  1970 + cleanup:
  1971 + qemu_free(vs->x509cacert);
  1972 + qemu_free(vs->x509cacrl);
  1973 + qemu_free(vs->x509cert);
  1974 + qemu_free(vs->x509key);
  1975 + vs->x509cacert = vs->x509cacrl = vs->x509cert = vs->x509key = NULL;
  1976 + return -1;
  1977 +}
  1978 +#endif /* CONFIG_VNC_TLS */
  1979 +
1906 void vnc_display_close(DisplayState *ds) 1980 void vnc_display_close(DisplayState *ds)
1907 { 1981 {
1908 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; 1982 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
@@ -1986,11 +2060,36 @@ int vnc_display_open(DisplayState *ds, const char *display) @@ -1986,11 +2060,36 @@ int vnc_display_open(DisplayState *ds, const char *display)
1986 #if CONFIG_VNC_TLS 2060 #if CONFIG_VNC_TLS
1987 } else if (strncmp(options, "tls", 3) == 0) { 2061 } else if (strncmp(options, "tls", 3) == 0) {
1988 tls = 1; /* Require TLS */ 2062 tls = 1; /* Require TLS */
1989 - } else if (strncmp(options, "x509verify", 10) == 0) {  
1990 - x509 = 1; /* Require x509 certificates... */  
1991 - vs->x509verify = 1;/* ...and verify client certs */  
1992 } else if (strncmp(options, "x509", 4) == 0) { 2063 } else if (strncmp(options, "x509", 4) == 0) {
  2064 + char *start, *end;
1993 x509 = 1; /* Require x509 certificates */ 2065 x509 = 1; /* Require x509 certificates */
  2066 + if (strncmp(options, "x509verify", 10) == 0)
  2067 + vs->x509verify = 1; /* ...and verify client certs */
  2068 +
  2069 + /* Now check for 'x509=/some/path' postfix
  2070 + * and use that to setup x509 certificate/key paths */
  2071 + start = strchr(options, '=');
  2072 + end = strchr(options, ',');
  2073 + if (start && (!end || (start < end))) {
  2074 + int len = end ? end-(start+1) : strlen(start+1);
  2075 + char *path = qemu_malloc(len+1);
  2076 + strncpy(path, start+1, len);
  2077 + path[len] = '\0';
  2078 + VNC_DEBUG("Trying certificate path '%s'\n", path);
  2079 + if (vnc_set_x509_credential_dir(vs, path) < 0) {
  2080 + fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
  2081 + qemu_free(path);
  2082 + qemu_free(vs->display);
  2083 + vs->display = NULL;
  2084 + return -1;
  2085 + }
  2086 + qemu_free(path);
  2087 + } else {
  2088 + fprintf(stderr, "No certificate path provided\n");
  2089 + qemu_free(vs->display);
  2090 + vs->display = NULL;
  2091 + return -1;
  2092 + }
1994 #endif 2093 #endif
1995 } 2094 }
1996 } 2095 }