aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2015-02-16 13:44:22 +0000
committerDr. Stephen Henson <steve@openssl.org>2015-03-25 14:19:04 +0000
commit2011b169fa90edd4d986e7dbbd3d64587d316a22 (patch)
tree829080631b83a40ab3843a533efb2677bd6c52b6
parent9837bfbfc7a53dd531081b4ba8fe369d9c99116e (diff)
downloadopenssl-2011b169fa90edd4d986e7dbbd3d64587d316a22.tar.gz
Support key loading from certificate file
Support loading of key and certificate from the same file if SSL_CONF_FLAG_REQUIRE_PRIVATE is set. This is done by remembering the filename used for each certificate type and attempting to load a private key from the file when SSL_CONF_CTX_finish is called. Update docs. Reviewed-by: Richard Levitte <levitte@openssl.org>
-rw-r--r--doc/ssl/SSL_CONF_CTX_set_flags.pod7
-rw-r--r--doc/ssl/SSL_CONF_cmd.pod6
-rw-r--r--ssl/ssl.h1
-rw-r--r--ssl/ssl_conf.c47
4 files changed, 56 insertions, 5 deletions
diff --git a/doc/ssl/SSL_CONF_CTX_set_flags.pod b/doc/ssl/SSL_CONF_CTX_set_flags.pod
index 4e34280469..fdff4706c7 100644
--- a/doc/ssl/SSL_CONF_CTX_set_flags.pod
+++ b/doc/ssl/SSL_CONF_CTX_set_flags.pod
@@ -40,6 +40,13 @@ both of these flags must be set.
recognise certificate and private key options.
+=item SSL_CONF_FLAG_REQUIRE_PRIVATE
+
+If this option is set then if a private key is not specified for a certificate
+it will attempt to load a private key from the certificate file when
+SSL_CONF_CTX_finish() is called. If a key cannot be loaded from the certificate
+file an error occurs.
+
=item SSL_CONF_FLAG_SHOW_ERRORS
indicate errors relating to unrecognised options or missing arguments in
diff --git a/doc/ssl/SSL_CONF_cmd.pod b/doc/ssl/SSL_CONF_cmd.pod
index 90a20d6c49..c4f1309c03 100644
--- a/doc/ssl/SSL_CONF_cmd.pod
+++ b/doc/ssl/SSL_CONF_cmd.pod
@@ -101,7 +101,7 @@ are permitted.
Attempts to use the file B<value> as the private key for the appropriate
context. This option is only supported if certificate operations
are permitted. Note: if no B<-key> option is set then a private key is
-not loaded: it does not currently use the B<-cert> file.
+not loaded unless the flag B<SSL_CONF_FLAG_REQUIRE_PRIVATE> is set.
=item B<-dhparam>
@@ -192,8 +192,8 @@ are permitted.
Attempts to use the file B<value> as the private key for the appropriate
context. This option is only supported if certificate operations
-are permitted. Note: if no B<-key> option is set then a private key is
-not loaded: it does not currently use the B<Certificate> file.
+are permitted. Note: if no B<PrivateKey> option is set then a private key is
+not loaded unless the B<SSL_CONF_FLAG_REQUIRE_PRIVATE> is set.
=item B<ServerInfoFile>
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 84de6a8653..c0a368b8f5 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -588,6 +588,7 @@ typedef int (*custom_ext_parse_cb) (SSL *s, unsigned int ext_type,
# define SSL_CONF_FLAG_SERVER 0x8
# define SSL_CONF_FLAG_SHOW_ERRORS 0x10
# define SSL_CONF_FLAG_CERTIFICATE 0x20
+# define SSL_CONF_FLAG_REQUIRE_PRIVATE 0x40
/* Configuration value types */
# define SSL_CONF_TYPE_UNKNOWN 0x0
# define SSL_CONF_TYPE_STRING 0x1
diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c
index 25af065233..0fd6c1f1be 100644
--- a/ssl/ssl_conf.c
+++ b/ssl/ssl_conf.c
@@ -119,6 +119,8 @@ struct ssl_conf_ctx_st {
SSL *ssl;
/* Pointer to SSL or SSL_CTX options field or NULL if none */
unsigned long *poptions;
+ /* Certificate filenames for each type */
+ char *cert_filename[SSL_PKEY_NUM];
/* Pointer to SSL or SSL_CTX cert_flags or NULL if none */
unsigned int *pcert_flags;
/* Current flag table being worked on */
@@ -364,12 +366,26 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
{
int rv = 1;
+ CERT *c = NULL;
if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE))
return -2;
- if (cctx->ctx)
+ if (cctx->ctx) {
rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value);
- if (cctx->ssl)
+ c = cctx->ctx->cert;
+ }
+ if (cctx->ssl) {
rv = SSL_use_certificate_file(cctx->ssl, value, SSL_FILETYPE_PEM);
+ c = cctx->ssl->cert;
+ }
+ if (rv > 0 && c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
+ char **pfilename = &cctx->cert_filename[c->key - c->pkeys];
+ if (*pfilename)
+ OPENSSL_free(*pfilename);
+ *pfilename = BUF_strdup(value);
+ if (!*pfilename)
+ rv = 0;
+ }
+
return rv > 0;
}
@@ -595,6 +611,7 @@ int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd)
SSL_CONF_CTX *SSL_CONF_CTX_new(void)
{
SSL_CONF_CTX *ret;
+ size_t i;
ret = OPENSSL_malloc(sizeof(SSL_CONF_CTX));
if (ret) {
ret->flags = 0;
@@ -606,18 +623,44 @@ SSL_CONF_CTX *SSL_CONF_CTX_new(void)
ret->pcert_flags = NULL;
ret->tbl = NULL;
ret->ntbl = 0;
+ for (i = 0; i < SSL_PKEY_NUM; i++)
+ ret->cert_filename[i] = NULL;
}
return ret;
}
int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
{
+ /* See if any certificates are missing private keys */
+ size_t i;
+ CERT *c = NULL;
+ if (cctx->ctx)
+ c = cctx->ctx->cert;
+ else if (cctx->ssl)
+ c = cctx->ssl->cert;
+ if (c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ const char *p = cctx->cert_filename[i];
+ /*
+ * If missing private key try to load one from certificate file
+ */
+ if (p && !c->pkeys[i].privatekey) {
+ if (!cmd_PrivateKey(cctx, p))
+ return 0;
+ }
+ }
+ }
return 1;
}
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
{
if (cctx) {
+ size_t i;
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ if (cctx->cert_filename[i])
+ OPENSSL_free(cctx->cert_filename[i]);
+ }
if (cctx->prefix)
OPENSSL_free(cctx->prefix);
OPENSSL_free(cctx);