qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] PATCH 7/8: custom location for x509 cert paths


From: Daniel P. Berrange
Subject: Re: [Qemu-devel] PATCH 7/8: custom location for x509 cert paths
Date: Mon, 13 Aug 2007 20:50:11 +0100
User-agent: Mutt/1.4.1i

This final code patch extends the VNC server config syntax so that the x509
and x509verify flags both use a path following them. This path is then used
to determine the filenames for the CA certificate & revocation list, and the
server certificate & private key. If the path containing the certificates is
not provided, all client authentication attempts will be rejected.

Example usage on command line:

  qemu [...OPTIONS...] -vnc :1,tls,x509verify=/etc/pki/qemu


    Signed-off-by: Daniel P. Berrange <address@hidden>

diff -r 109ed8417169 vnc.c
--- a/vnc.c     Wed Aug 08 12:54:13 2007 -0400
+++ b/vnc.c     Wed Aug 08 12:54:18 2007 -0400
@@ -143,6 +143,11 @@ struct VncState
 #if CONFIG_VNC_TLS
     int subauth;
     int x509verify;
+
+    char *x509cacert;
+    char *x509cacrl;
+    char *x509cert;
+    char *x509key;
 #endif
     char challenge[VNC_AUTH_CHALLENGE_SIZE];
 
@@ -1386,37 +1391,49 @@ static gnutls_anon_server_credentials vn
 }
 
 
-static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(void)
+static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState 
*vs)
 {
     gnutls_certificate_credentials_t x509_cred;
     int ret;
-    struct stat st;
+
+    if (!vs->x509cacert) {
+       VNC_DEBUG("No CA x509 certificate specified\n");
+       return NULL;
+    }
+    if (!vs->x509cert) {
+       VNC_DEBUG("No server x509 certificate specified\n");
+       return NULL;
+    }
+    if (!vs->x509key) {
+       VNC_DEBUG("No server private key specified\n");
+       return NULL;
+    }
 
     if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
        VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
        return NULL;
     }
-    if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred, 
X509_CA_CERT_FILE, GNUTLS_X509_FMT_PEM)) < 0) {
+    if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
+                                                     vs->x509cacert,
+                                                     GNUTLS_X509_FMT_PEM)) < 
0) {
        VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
        gnutls_certificate_free_credentials(x509_cred);
        return NULL;
     }
 
-    if ((ret = gnutls_certificate_set_x509_key_file (x509_cred, 
X509_SERVER_CERT_FILE,
-                                                    X509_SERVER_KEY_FILE,
+    if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
+                                                    vs->x509cert,
+                                                    vs->x509key,
                                                     GNUTLS_X509_FMT_PEM)) < 0) 
{
        VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
        gnutls_certificate_free_credentials(x509_cred);
        return NULL;
     }
 
-    if (stat(X509_CA_CRL_FILE, &st) < 0) {
-       if (errno != ENOENT) {
-           gnutls_certificate_free_credentials(x509_cred);
-           return NULL;
-       }
-    } else {
-       if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred, 
X509_CA_CRL_FILE, GNUTLS_X509_FMT_PEM)) < 0) {
+    if (vs->x509cacrl) {
+       if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
+                                                       vs->x509cacrl,
+                                                       GNUTLS_X509_FMT_PEM)) < 
0) {
            VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
            gnutls_certificate_free_credentials(x509_cred);
            return NULL;
@@ -1632,7 +1649,7 @@ static int vnc_start_tls(struct VncState
        }
 
        if (NEED_X509_AUTH(vs)) {
-           gnutls_certificate_server_credentials x509_cred = 
vnc_tls_initialize_x509_cred();
+           gnutls_certificate_server_credentials x509_cred = 
vnc_tls_initialize_x509_cred(vs);
            if (!x509_cred) {
                gnutls_deinit(vs->tls_session);
                vs->tls_session = NULL;
@@ -1903,6 +1920,63 @@ void vnc_display_init(DisplayState *ds)
     vnc_dpy_resize(vs->ds, 640, 400);
 }
 
+#if CONFIG_VNC_TLS
+static int vnc_set_x509_credential(VncState *vs,
+                                  const char *certdir,
+                                  const char *filename,
+                                  char **cred,
+                                  int ignoreMissing)
+{
+    struct stat sb;
+
+    if (*cred) {
+       qemu_free(*cred);
+       *cred = NULL;
+    }
+
+    if (!(*cred = qemu_malloc(strlen(certdir) + strlen(filename) + 2)))
+       return -1;
+
+    strcpy(*cred, certdir);
+    strcat(*cred, "/");
+    strcat(*cred, filename);
+
+    VNC_DEBUG("Check %s\n", *cred);
+    if (stat(*cred, &sb) < 0) {
+       qemu_free(*cred);
+       *cred = NULL;
+       if (ignoreMissing && errno == ENOENT)
+           return 0;
+       return -1;
+    }
+
+    return 0;
+}
+
+static int vnc_set_x509_credential_dir(VncState *vs,
+                                      const char *certdir)
+{
+    if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, 
&vs->x509cacert, 0) < 0)
+       goto cleanup;
+    if (vnc_set_x509_credential(vs, certdir, X509_CA_CRL_FILE, &vs->x509cacrl, 
1) < 0)
+       goto cleanup;
+    if (vnc_set_x509_credential(vs, certdir, X509_SERVER_CERT_FILE, 
&vs->x509cert, 0) < 0)
+       goto cleanup;
+    if (vnc_set_x509_credential(vs, certdir, X509_SERVER_KEY_FILE, 
&vs->x509key, 0) < 0)
+       goto cleanup;
+
+    return 0;
+
+ cleanup:
+    qemu_free(vs->x509cacert);
+    qemu_free(vs->x509cacrl);
+    qemu_free(vs->x509cert);
+    qemu_free(vs->x509key);
+    vs->x509cacert = vs->x509cacrl = vs->x509cert = vs->x509key = NULL;
+    return -1;
+}
+#endif /* CONFIG_VNC_TLS */
+
 void vnc_display_close(DisplayState *ds)
 {
     VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
@@ -1985,11 +2059,36 @@ int vnc_display_open(DisplayState *ds, c
 #if CONFIG_VNC_TLS
        } else if (strncmp(options, "tls", 3) == 0) {
            tls = 1; /* Require TLS */
-       } else if (strncmp(options, "x509verify", 10) == 0) {
-           x509 = 1; /* Require x509 certificates... */
-           vs->x509verify = 1;/* ...and verify client certs */
        } else if (strncmp(options, "x509", 4) == 0) {
+           char *start, *end;
            x509 = 1; /* Require x509 certificates */
+           if (strncmp(options, "x509verify", 10) == 0)
+               vs->x509verify = 1; /* ...and verify client certs */
+
+           /* Now check for 'x509=/some/path' postfix
+            * and use that to setup x509 certificate/key paths */
+           start = strchr(options, '=');
+           end = strchr(options, ',');
+           if (start && (!end || (start < end))) {
+               int len = end ? end-(start+1) : strlen(start+1);
+               char *path = qemu_malloc(len+1);
+               strncpy(path, start+1, len);
+               path[len] = '\0';
+               VNC_DEBUG("Trying certificate path '%s'\n", path);
+               if (vnc_set_x509_credential_dir(vs, path) < 0) {
+                   fprintf(stderr, "Failed to find x509 certificates/keys in 
%s\n", path);
+                   qemu_free(path);
+                   qemu_free(vs->display);
+                   vs->display = NULL;
+                   return -1;
+               }
+               qemu_free(path);
+           } else {
+               fprintf(stderr, "No certificate path provided\n");
+               qemu_free(vs->display);
+               vs->display = NULL;
+               return -1;
+           }
 #endif
        }
     }

-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]