From 23977b53592f985bf58431f045144fd3fea90eec Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Thu, 7 Mar 2013 09:51:20 +0100 Subject: [PATCH] Added ability to specify multiple certificate and key pairs. --- NEWS | 5 ++++ src/config.c | 16 ++++++++--- src/ocserv-args.c | 2 +- src/ocserv-args.def | 3 ++ src/ocserv-args.h | 2 +- src/tlslib.c | 69 ++++++++++++++++++++++++++------------------- src/vpn.h | 6 ++-- 7 files changed, 66 insertions(+), 37 deletions(-) diff --git a/NEWS b/NEWS index a2ca44bc..93612dfe 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +* Version 0.0.3 (unreleased) + +- Corrected issue with ocsp-response configuration field. +- Added ability to specify multiple certificate and key pairs. + * Version 0.0.2 (released 2013-03-05) - Updated HTTP protocol handling (fixes issue with openconnect < 4). diff --git a/src/config.c b/src/config.c index c4399037..17b72842 100644 --- a/src/config.c +++ b/src/config.c @@ -148,9 +148,9 @@ unsigned j; READ_NUMERIC("dpd", config->dpd, 0); READ_NUMERIC("rate-limit-ms", config->rate_limit_ms, 0); - READ_STRING("ocsp-response", config->cert, 0); - READ_STRING("server-cert", config->cert, 1); - READ_STRING("server-key", config->key, 1); + READ_STRING("ocsp-response", config->ocsp_response, 0); + READ_MULTI_LINE("server-cert", config->cert, config->cert_size, 1); + READ_MULTI_LINE("server-key", config->key, config->key_size, 1); READ_STRING("dh-params", config->dh_params_file, 0); READ_STRING("pin-file", config->pin_file, 0); READ_STRING("srk-pin-file", config->srk_pin_file, 0); @@ -245,7 +245,11 @@ static void check_cfg( struct cfg_st *config) exit(1); } - + if (config->cert_size != config->key_size) { + fprintf(stderr, "The specified number of keys doesn't match the certificates\n"); + exit(1); + } + if (config->auth_types & AUTH_TYPE_CERTIFICATE) { if (config->force_cert_auth) config->cert_req = GNUTLS_CERT_REQUIRE; @@ -359,6 +363,10 @@ unsigned i; DEL(config->network.ipv6_dns); for (i=0;inetwork.routes_size;i++) DEL(config->network.routes[i]); + for (i=0;ikey_size;i++) + DEL(config->key[i]); + for (i=0;icert_size;i++) + DEL(config->cert[i]); DEL(config->network.routes); memset(config, 0, sizeof(*config)); diff --git a/src/ocserv-args.c b/src/ocserv-args.c index 78c98dd5..2fbd710d 100644 --- a/src/ocserv-args.c +++ b/src/ocserv-args.c @@ -2,7 +2,7 @@ * * DO NOT EDIT THIS FILE (ocserv-args.c) * - * It has been AutoGen-ed March 7, 2013 at 09:19:14 AM by AutoGen 5.16 + * It has been AutoGen-ed March 7, 2013 at 09:51:47 AM by AutoGen 5.16 * From the definitions ocserv-args.def * and the template file options * diff --git a/src/ocserv-args.def b/src/ocserv-args.def index 8ea2efd8..0e4e0932 100644 --- a/src/ocserv-args.def +++ b/src/ocserv-args.def @@ -115,6 +115,9 @@ try-mtu-discovery = false # The key may be a file, or any URL supported by GnuTLS (e.g., # tpmkey:uuid=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx;storage=user # or pkcs11:object=my-vpn-key;object-type=private) +# +# There may be multiple certificate and key pairs and each key +# should correspond to the preceding certificate. server-cert = /path/to/cert.pem server-key = /path/to/key.pem diff --git a/src/ocserv-args.h b/src/ocserv-args.h index 0a684991..a81c2d41 100644 --- a/src/ocserv-args.h +++ b/src/ocserv-args.h @@ -2,7 +2,7 @@ * * DO NOT EDIT THIS FILE (ocserv-args.h) * - * It has been AutoGen-ed March 7, 2013 at 09:19:14 AM by AutoGen 5.16 + * It has been AutoGen-ed March 7, 2013 at 09:51:47 AM by AutoGen 5.16 * From the definitions ocserv-args.def * and the template file options * diff --git a/src/tlslib.c b/src/tlslib.c index 48f52606..4378f42b 100644 --- a/src/tlslib.c +++ b/src/tlslib.c @@ -350,6 +350,8 @@ int ret; return; } +/* Checks, if there is a single certificate specified, whether it + * is compatible with all ciphersuites */ static void certificate_check(main_server_st *s) { gnutls_datum_t data; @@ -357,11 +359,14 @@ gnutls_x509_crt_t crt; int ret; unsigned usage; + if (s->config->cert_size > 1) + return; + #if GNUTLS_VERSION_NUMBER > 0x030100 - if (gnutls_url_is_supported(s->config->cert) == 0) { + if (gnutls_url_is_supported(s->config->cert[0]) == 0) { #endif /* no URL */ - ret = gnutls_load_file(s->config->cert, &data); + ret = gnutls_load_file(s->config->cert[0], &data); if (ret < 0) return; @@ -418,6 +423,7 @@ int ret; void tls_global_init_certs(main_server_st* s) { int ret; +unsigned i; const char* perr; if (s->config->tls_debug) { @@ -440,27 +446,29 @@ const char* perr; gnutls_certificate_set_pin_function (s->creds.xcred, pin_callback, &s->creds); - if (s->config->key == NULL || s->config->cert == NULL) { + if (s->config->key_size == 0 || s->config->cert_size == 0) { mslog(s, NULL, LOG_ERR, "no certificate or key files were specified.\n"); exit(1); } certificate_check(s); - if (strncmp(s->config->key, "pkcs11:", 7) != 0) { - ret = - gnutls_certificate_set_x509_key_file(s->creds.xcred, s->config->cert, - s->config->key, GNUTLS_X509_FMT_PEM); - if (ret < 0) { - mslog(s, NULL, LOG_ERR, "error setting the certificate (%s) or key (%s) files: %s\n", - s->config->cert, s->config->key, gnutls_strerror(ret)); - exit(1); - } - } else { + for (i=0;iconfig->key_size;i++) { + if (strncmp(s->config->key[i], "pkcs11:", 7) != 0) { + ret = + gnutls_certificate_set_x509_key_file(s->creds.xcred, s->config->cert[i], + s->config->key[i], GNUTLS_X509_FMT_PEM); + if (ret < 0) { + mslog(s, NULL, LOG_ERR, "error setting the certificate (%s) or key (%s) files: %s\n", + s->config->cert[i], s->config->key[i], gnutls_strerror(ret)); + exit(1); + } + } else { #ifndef HAVE_PKCS11 - mslog(s, NULL, LOG_ERR, "cannot load key, GnuTLS is compiled without pkcs11 support\n"); - exit(1); + mslog(s, NULL, LOG_ERR, "cannot load key, GnuTLS is compiled without pkcs11 support\n"); + exit(1); #endif + } } if (s->config->cert_req != GNUTLS_CERT_IGNORE) { @@ -512,26 +520,29 @@ int tls_global_init_client(worker_st* ws) { #ifdef HAVE_PKCS11 int ret; +unsigned i; /* when we have PKCS #11 keys we cannot open them and then fork(), we need * to open them at the process they are going to be used. */ - if (strncmp(ws->config->key, "pkcs11:", 7) == 0) { - ret = gnutls_pkcs11_reinit(); - if (ret < 0) { - oclog(ws, LOG_ERR, "could not reinitialize PKCS #11 subsystem: %s\n", - gnutls_strerror(ret)); - return -1; + for (i=0;iconfig->key_size;i++) { + if (strncmp(ws->config->key[i], "pkcs11:", 7) == 0) { + ret = gnutls_pkcs11_reinit(); + if (ret < 0) { + oclog(ws, LOG_ERR, "could not reinitialize PKCS #11 subsystem: %s\n", + gnutls_strerror(ret)); + return -1; - } + } - ret = - gnutls_certificate_set_x509_key_file(ws->creds->xcred, ws->config->cert, - ws->config->key, + ret = + gnutls_certificate_set_x509_key_file(ws->creds->xcred, ws->config->cert[i], + ws->config->key[i], GNUTLS_X509_FMT_PEM); - if (ret < 0) { - oclog(ws, LOG_ERR, "error setting the certificate (%s) or key (%s) files: %s\n", - ws->config->cert, ws->config->key, gnutls_strerror(ret)); - return -1; + if (ret < 0) { + oclog(ws, LOG_ERR, "error setting the certificate (%s) or key (%s) files: %s\n", + ws->config->cert[i], ws->config->key[i], gnutls_strerror(ret)); + return -1; + } } } #endif diff --git a/src/vpn.h b/src/vpn.h index 8f213b15..79a1f95f 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -59,9 +59,11 @@ struct cfg_st { unsigned int udp_port; char *pin_file; char *srk_pin_file; - char *cert; + char **cert; + unsigned cert_size; + char **key; + unsigned key_size; - char *key; char *ca; char *crl; char *dh_params_file;