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 143 #if CONFIG_VNC_TLS
144 144 int subauth;
145 145 int x509verify;
  146 +
  147 + char *x509cacert;
  148 + char *x509cacrl;
  149 + char *x509cert;
  150 + char *x509key;
146 151 #endif
147 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 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 1396 gnutls_certificate_credentials_t x509_cred;
1392 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 1412 if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
1396 1413 VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1397 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 1419 VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
1401 1420 gnutls_certificate_free_credentials(x509_cred);
1402 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 1427 GNUTLS_X509_FMT_PEM)) < 0) {
1408 1428 VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
1409 1429 gnutls_certificate_free_credentials(x509_cred);
1410 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 1437 VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
1421 1438 gnutls_certificate_free_credentials(x509_cred);
1422 1439 return NULL;
... ... @@ -1632,7 +1649,7 @@ static int vnc_start_tls(struct VncState *vs) {
1632 1649 }
1633 1650  
1634 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 1653 if (!x509_cred) {
1637 1654 gnutls_deinit(vs->tls_session);
1638 1655 vs->tls_session = NULL;
... ... @@ -1903,6 +1920,63 @@ void vnc_display_init(DisplayState *ds)
1903 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 1980 void vnc_display_close(DisplayState *ds)
1907 1981 {
1908 1982 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
... ... @@ -1986,11 +2060,36 @@ int vnc_display_open(DisplayState *ds, const char *display)
1986 2060 #if CONFIG_VNC_TLS
1987 2061 } else if (strncmp(options, "tls", 3) == 0) {
1988 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 2063 } else if (strncmp(options, "x509", 4) == 0) {
  2064 + char *start, *end;
1993 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 2093 #endif
1995 2094 }
1996 2095 }
... ...