All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] PATCH 7/8: custom location for x509 cert paths
Date: Mon, 13 Aug 2007 20:50:11 +0100	[thread overview]
Message-ID: <20070813195011.GI30789@redhat.com> (raw)
In-Reply-To: <20070813192517.GB30789@redhat.com>

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 <berrange@redhat.com>

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  -=| 

  parent reply	other threads:[~2007-08-13 19:50 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-08-13 19:25 [Qemu-devel] PATCH 0/8: Authentication support for the VNC server Daniel P. Berrange
2007-08-13 19:41 ` [Qemu-devel] PATCH 1/8: Refactor VNC server setup API Daniel P. Berrange
2007-08-13 19:42 ` [Qemu-devel] PATCH 2/8: Extend monitor 'change' command for VNC Daniel P. Berrange
2007-08-13 19:44 ` [Qemu-devel] PATCH 3/8: VNC password authentication Daniel P. Berrange
2007-08-13 19:46 ` [Qemu-devel] PATCH 4/8: VeNCrypt basic TLS support Daniel P. Berrange
2007-08-13 19:47 ` [Qemu-devel] PATCH 5/8: x509 certificate for server Daniel P. Berrange
2007-08-13 19:48 ` [Qemu-devel] PATCH 6/8: x509 client certificate verification Daniel P. Berrange
2007-08-13 19:50 ` Daniel P. Berrange [this message]
2007-08-13 19:51 ` [Qemu-devel] PATCH 8/8: document all VNC authentication options Daniel P. Berrange
2007-08-15  4:32 ` [Qemu-devel] PATCH 0/8: Authentication support for the VNC server Anthony Liguori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070813195011.GI30789@redhat.com \
    --to=berrange@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.