diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2015-02-16 13:44:22 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2015-03-25 14:19:04 +0000 |
commit | 2011b169fa90edd4d986e7dbbd3d64587d316a22 (patch) | |
tree | 829080631b83a40ab3843a533efb2677bd6c52b6 | |
parent | 9837bfbfc7a53dd531081b4ba8fe369d9c99116e (diff) | |
download | openssl-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.pod | 7 | ||||
-rw-r--r-- | doc/ssl/SSL_CONF_cmd.pod | 6 | ||||
-rw-r--r-- | ssl/ssl.h | 1 | ||||
-rw-r--r-- | ssl/ssl_conf.c | 47 |
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> @@ -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); |