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>
This commit is contained in:
parent
9837bfbfc7
commit
2011b169fa
4 changed files with 56 additions and 5 deletions
|
@ -40,6 +40,13 @@ both of these flags must be set.
|
||||||
|
|
||||||
recognise certificate and private key options.
|
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
|
=item SSL_CONF_FLAG_SHOW_ERRORS
|
||||||
|
|
||||||
indicate errors relating to unrecognised options or missing arguments in
|
indicate errors relating to unrecognised options or missing arguments in
|
||||||
|
|
|
@ -101,7 +101,7 @@ are permitted.
|
||||||
Attempts to use the file B<value> as the private key for the appropriate
|
Attempts to use the file B<value> as the private key for the appropriate
|
||||||
context. This option is only supported if certificate operations
|
context. This option is only supported if certificate operations
|
||||||
are permitted. Note: if no B<-key> option is set then a private key is
|
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>
|
=item B<-dhparam>
|
||||||
|
|
||||||
|
@ -192,8 +192,8 @@ are permitted.
|
||||||
|
|
||||||
Attempts to use the file B<value> as the private key for the appropriate
|
Attempts to use the file B<value> as the private key for the appropriate
|
||||||
context. This option is only supported if certificate operations
|
context. This option is only supported if certificate operations
|
||||||
are permitted. Note: if no B<-key> option is set then a private key is
|
are permitted. Note: if no B<PrivateKey> option is set then a private key is
|
||||||
not loaded: it does not currently use the B<Certificate> file.
|
not loaded unless the B<SSL_CONF_FLAG_REQUIRE_PRIVATE> is set.
|
||||||
|
|
||||||
=item B<ServerInfoFile>
|
=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_SERVER 0x8
|
||||||
# define SSL_CONF_FLAG_SHOW_ERRORS 0x10
|
# define SSL_CONF_FLAG_SHOW_ERRORS 0x10
|
||||||
# define SSL_CONF_FLAG_CERTIFICATE 0x20
|
# define SSL_CONF_FLAG_CERTIFICATE 0x20
|
||||||
|
# define SSL_CONF_FLAG_REQUIRE_PRIVATE 0x40
|
||||||
/* Configuration value types */
|
/* Configuration value types */
|
||||||
# define SSL_CONF_TYPE_UNKNOWN 0x0
|
# define SSL_CONF_TYPE_UNKNOWN 0x0
|
||||||
# define SSL_CONF_TYPE_STRING 0x1
|
# define SSL_CONF_TYPE_STRING 0x1
|
||||||
|
|
|
@ -119,6 +119,8 @@ struct ssl_conf_ctx_st {
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
/* Pointer to SSL or SSL_CTX options field or NULL if none */
|
/* Pointer to SSL or SSL_CTX options field or NULL if none */
|
||||||
unsigned long *poptions;
|
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 */
|
/* Pointer to SSL or SSL_CTX cert_flags or NULL if none */
|
||||||
unsigned int *pcert_flags;
|
unsigned int *pcert_flags;
|
||||||
/* Current flag table being worked on */
|
/* 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)
|
static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
|
||||||
{
|
{
|
||||||
int rv = 1;
|
int rv = 1;
|
||||||
|
CERT *c = NULL;
|
||||||
if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE))
|
if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE))
|
||||||
return -2;
|
return -2;
|
||||||
if (cctx->ctx)
|
if (cctx->ctx) {
|
||||||
rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value);
|
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);
|
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;
|
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 *SSL_CONF_CTX_new(void)
|
||||||
{
|
{
|
||||||
SSL_CONF_CTX *ret;
|
SSL_CONF_CTX *ret;
|
||||||
|
size_t i;
|
||||||
ret = OPENSSL_malloc(sizeof(SSL_CONF_CTX));
|
ret = OPENSSL_malloc(sizeof(SSL_CONF_CTX));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ret->flags = 0;
|
ret->flags = 0;
|
||||||
|
@ -606,18 +623,44 @@ SSL_CONF_CTX *SSL_CONF_CTX_new(void)
|
||||||
ret->pcert_flags = NULL;
|
ret->pcert_flags = NULL;
|
||||||
ret->tbl = NULL;
|
ret->tbl = NULL;
|
||||||
ret->ntbl = 0;
|
ret->ntbl = 0;
|
||||||
|
for (i = 0; i < SSL_PKEY_NUM; i++)
|
||||||
|
ret->cert_filename[i] = NULL;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
|
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
|
||||||
{
|
{
|
||||||
if (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)
|
if (cctx->prefix)
|
||||||
OPENSSL_free(cctx->prefix);
|
OPENSSL_free(cctx->prefix);
|
||||||
OPENSSL_free(cctx);
|
OPENSSL_free(cctx);
|
||||||
|
|
Loading…
Reference in a new issue