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: Mon, 13 Aug 2007 20:47:50 +0100 [thread overview]
Message-ID: <20070813194750.GG30789@redhat.com> (raw)
In-Reply-To: <20070813192517.GB30789@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. The subsequent patch will allow
certificates to be used for authentication too.
Example using TLS, x509 server certificates and password auth
qemu [...OPTIONS...] -vnc :1,password,tls,x509 -monitor stdio
(qemu) change vnc password
Password: ********
(qemu)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
diff -r 4199204d1b36 vnc.c
--- a/vnc.c Wed Aug 08 12:53:40 2007 -0400
+++ b/vnc.c Wed Aug 08 12:53:43 2007 -0400
@@ -105,6 +105,14 @@ enum {
VNC_AUTH_VENCRYPT_X509VNC = 261,
VNC_AUTH_VENCRYPT_X509PLAIN = 262,
};
+
+#if CONFIG_VNC_TLS
+#define X509_CA_CERT_FILE "ca-cert.pem"
+#define X509_CA_CRL_FILE "ca-crl.pem"
+#define X509_SERVER_KEY_FILE "server-key.pem"
+#define X509_SERVER_CERT_FILE "server-cert.pem"
+#endif
+
#endif /* CONFIG_VNC_TLS */
struct VncState
@@ -1377,16 +1385,60 @@ 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, X509_CA_CERT_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, X509_SERVER_CERT_FILE,
+ X509_SERVER_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(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) {
+ 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);
@@ -1437,11 +1489,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) {
@@ -1462,7 +1520,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);
@@ -1483,19 +1541,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);
@@ -1796,7 +1871,7 @@ int vnc_display_open(DisplayState *ds, c
const char *options;
int password = 0;
#if CONFIG_VNC_TLS
- int tls = 0;
+ int tls = 0, x509 = 0;
#endif
vnc_display_close(ds);
@@ -1814,15 +1889,22 @@ 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, "x509", 4) == 0)
+ x509 = 1; /* Require x509 certificates */
#endif
}
if (password) {
#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");
@@ -1834,9 +1916,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 -=|
next prev parent reply other threads:[~2007-08-13 19:48 UTC|newest]
Thread overview: 11+ 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 ` Daniel P. Berrange [this message]
2007-08-13 19:48 ` [Qemu-devel] PATCH 6/8: x509 client certificate verification Daniel P. Berrange
2007-08-13 19:50 ` [Qemu-devel] PATCH 7/8: custom location for x509 cert paths Daniel P. Berrange
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
-- strict thread matches above, loose matches on Subject: below --
2007-07-31 19:23 Daniel P. Berrange
2007-07-31 19:28 ` [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=20070813194750.GG30789@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).