qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] PATCH 5/8: x509 certificate for server
Date: Tue, 31 Jul 2007 20:28:14 +0100	[thread overview]
Message-ID: <20070731192814.GN18730@redhat.com> (raw)
In-Reply-To: <20070731192316.GI18730@redhat.com>

This patch adds support for using x509 certificates on the server
end. The server needs a CA certificate, and its own certificate and
private key. A CA revocation list is optional. This this patch the
file names are hardcoded. The next-but-one patch will make them
configurable.

The use of x509 certificates is controlled by the 'x509' flag to
the VNC arg, eg '-vnc :1,tls,x509'. This only provides encryption
of the session, no authentication.

diff -r b5430bd9f883 vnc.c
--- a/vnc.c	Tue Jul 31 11:32:19 2007 -0400
+++ b/vnc.c	Tue Jul 31 11:43:59 2007 -0400
@@ -104,6 +104,14 @@ enum {
     VNC_AUTH_VENCRYPT_X509VNC = 261,
     VNC_AUTH_VENCRYPT_X509PLAIN = 262,
 };
+
+#if CONFIG_VNC_TLS
+#define CA_FILE "ca-cert.pem"
+#define CRL_FILE "ca-crl.pem"
+#define KEY_FILE "key.pem"
+#define CERT_FILE "cert.pem"
+#endif
+
 #endif /* CONFIG_VNC_TLS */
 
 struct VncState
@@ -1369,16 +1377,59 @@ static gnutls_anon_server_credentials vn
 }
 
 
+static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(void)
+{
+    gnutls_certificate_credentials_t x509_cred;
+    int ret;
+    struct stat st;
+
+    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, CA_FILE, 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, CERT_FILE, KEY_FILE,
+						     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(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, CRL_FILE, GNUTLS_X509_FMT_PEM)) < 0) {
+	    VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
+	    gnutls_certificate_free_credentials(x509_cred);
+	    return NULL;
+	}
+    }
+
+    gnutls_certificate_set_dh_params (x509_cred, dh_params);
+
+    return x509_cred;
+}
+
 static int start_auth_vencrypt_subauth(VncState *vs)
 {
     switch (vs->subauth) {
     case VNC_AUTH_VENCRYPT_TLSNONE:
+    case VNC_AUTH_VENCRYPT_X509NONE:
        VNC_DEBUG("Accept TLS auth none\n");
        vnc_write_u32(vs, 0); /* Accept auth completion */
        vnc_read_when(vs, protocol_client_init, 1);
        break;
 
     case VNC_AUTH_VENCRYPT_TLSVNC:
+    case VNC_AUTH_VENCRYPT_X509VNC:
        VNC_DEBUG("Start TLS auth VNC\n");
        return start_auth_vnc(vs);
 
@@ -1429,11 +1480,17 @@ static void vnc_handshake_io(void *opaqu
     vnc_continue_handshake(vs);
 }
 
+#define NEED_X509_AUTH(vs)			      \
+    ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
+     (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
+     (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN)
+
+
 static int vnc_start_tls(struct VncState *vs) {
     static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
     static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
     static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
-    gnutls_anon_server_credentials anon_cred = NULL;
+    static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
 
     VNC_DEBUG("Do TLS setup\n");
     if (vnc_tls_initialize() < 0) {
@@ -1454,7 +1511,7 @@ static int vnc_start_tls(struct VncState
 	    return -1;
 	}
 
-	if (gnutls_kx_set_priority(vs->tls_session, kx_anon) < 0) {
+	if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ? kx_x509 : kx_anon) < 0) {
 	    gnutls_deinit(vs->tls_session);
 	    vs->tls_session = NULL;
 	    vnc_client_error(vs);
@@ -1475,19 +1532,36 @@ static int vnc_start_tls(struct VncState
 	    return -1;
 	}
 
-	anon_cred = vnc_tls_initialize_anon_cred();
-	if (!anon_cred) {
-	    gnutls_deinit(vs->tls_session);
-	    vs->tls_session = NULL;
-	    vnc_client_error(vs);
-	    return -1;
-	}
-	if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
-	    gnutls_deinit(vs->tls_session);
-	    vs->tls_session = NULL;
-	    gnutls_anon_free_server_credentials(anon_cred);
-	    vnc_client_error(vs);
-	    return -1;
+	if (NEED_X509_AUTH(vs)) {
+	    gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred();
+	    if (!x509_cred) {
+		gnutls_deinit(vs->tls_session);
+		vs->tls_session = NULL;
+		vnc_client_error(vs);
+		return -1;
+	    }
+	    if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
+		gnutls_deinit(vs->tls_session);
+		vs->tls_session = NULL;
+		gnutls_certificate_free_credentials(x509_cred);
+		vnc_client_error(vs);
+		return -1;
+	    }
+	} else {
+	    gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
+	    if (!anon_cred) {
+		gnutls_deinit(vs->tls_session);
+		vs->tls_session = NULL;
+		vnc_client_error(vs);
+		return -1;
+	    }
+	    if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
+		gnutls_deinit(vs->tls_session);
+		vs->tls_session = NULL;
+		gnutls_anon_free_server_credentials(anon_cred);
+		vnc_client_error(vs);
+		return -1;
+	    }
 	}
 
 	gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
@@ -1754,7 +1828,7 @@ int vnc_display_open(DisplayState *ds, c
     VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
 #if CONFIG_VNC_TLS
     const char *options;
-    int tls = 0;
+    int tls = 0, x509 = 0;
 #endif
 
     vnc_display_close(ds);
@@ -1770,6 +1844,8 @@ int vnc_display_open(DisplayState *ds, c
 	options++;
 	if (strncmp(options, "tls", 3) == 0)
 	    tls = 1; /* Require TLS */
+	else if (strncmp(options, "x509", 4) == 0)
+	    x509 = 1; /* Require x509 certificates */
     }
 #endif
 
@@ -1781,9 +1857,14 @@ int vnc_display_open(DisplayState *ds, c
 	}
 #if CONFIG_VNC_TLS
 	if (tls) {
-	    VNC_DEBUG("Initializing VNC server with TLS password auth\n");
 	    vs->auth = VNC_AUTH_VENCRYPT;
-	    vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
+	    if (x509) {
+		VNC_DEBUG("Initializing VNC server with x509 password auth\n");
+		vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
+	    } else {
+		VNC_DEBUG("Initializing VNC server with TLS password auth\n");
+		vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
+	    }
 	} else {
 #endif
 	    VNC_DEBUG("Initializing VNC server with password auth\n");
@@ -1795,9 +1876,14 @@ int vnc_display_open(DisplayState *ds, c
     } else {
 #if CONFIG_VNC_TLS
 	if (tls) {
-	    VNC_DEBUG("Initializing VNC server with TLS no auth\n");
 	    vs->auth = VNC_AUTH_VENCRYPT;
-	    vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
+	    if (x509) {
+		VNC_DEBUG("Initializing VNC server with x509 no auth\n");
+		vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
+	    } else {
+		VNC_DEBUG("Initializing VNC server with TLS no auth\n");
+		vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
+	    }
 	} else {
 #endif
 	    VNC_DEBUG("Initializing VNC server with no auth\n");

-- 
|=- 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-07-31 19:28 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-31 19:23 [Qemu-devel] PATCH 0/8: Authentication support for the VNC server Daniel P. Berrange
2007-07-31 19:25 ` [Qemu-devel] PATCH 1/8: Refactor VNC server setup API Daniel P. Berrange
2007-07-31 19:25 ` [Qemu-devel] PATCH 2/8: Extend monitor 'change' command for VNC Daniel P. Berrange
2007-08-01  1:43   ` Anthony Liguori
2007-07-31 19:26 ` [Qemu-devel] PATCH 3/8: VNC password authentication Daniel P. Berrange
2007-08-01  1:46   ` Anthony Liguori
2007-08-01 16:26     ` Daniel P. Berrange
2007-08-02 14:35       ` Anthony Liguori
2007-07-31 19:27 ` [Qemu-devel] PATCH 4/8: VeNCrypt basic TLS support Daniel P. Berrange
2007-08-01  1:50   ` Anthony Liguori
2007-08-01 16:28     ` Daniel P. Berrange
2007-07-31 19:28 ` Daniel P. Berrange [this message]
2007-07-31 19:28 ` [Qemu-devel] PATCH 6/8: x509 client certificate verification Daniel P. Berrange
2007-07-31 19:29 ` [Qemu-devel] PATCH 7/8: command line args for x509 cert paths Daniel P. Berrange
2007-08-01  1:54   ` Anthony Liguori
2007-08-01 16:31     ` Daniel P. Berrange
2007-07-31 19:30 ` [Qemu-devel] PATCH 8/8: document all VNC authentication options Daniel P. Berrange
2007-08-01  1:55 ` [Qemu-devel] PATCH 0/8: Authentication support for the VNC server Anthony Liguori
  -- strict thread matches above, loose matches on Subject: below --
2007-08-13 19:25 Daniel P. Berrange
2007-08-13 19:47 ` [Qemu-devel] PATCH 5/8: x509 certificate for server Daniel P. Berrange

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=20070731192814.GN18730@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).