From: Matt Caswell Date: Fri, 7 Feb 2025 12:11:41 +0000 (+0000) Subject: Fix configuring provider certificate algs via config file X-Git-Tag: openssl-3.4.2~193 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bc0d4577d6ef611bbb5c748e738dad20084994f9;p=thirdparty%2Fopenssl.git Fix configuring provider certificate algs via config file A crash could occur when attempting to configure a certificate via a config file, where the algorithm for the certificate key was added dynamically via a provider. Reviewed-by: Viktor Dukhovni Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/26663) (cherry picked from commit 9cbaa8763c096bc91e09fc121583f90d93ecfc82) --- diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index e5465dbc511..0497c26db26 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -86,7 +86,9 @@ struct ssl_conf_ctx_st { /* Pointer to SSL or SSL_CTX options field or NULL if none */ uint64_t *poptions; /* Certificate filenames for each type */ - char *cert_filename[SSL_PKEY_NUM]; + char **cert_filename; + /* Number of elements in the cert_filename array */ + size_t num_cert_filename; /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */ uint32_t *pcert_flags; /* Pointer to SSL or SSL_CTX verify_mode or NULL if none */ @@ -451,12 +453,18 @@ static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value) } } if (rv > 0 && c != NULL && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) { - char **pfilename = &cctx->cert_filename[c->key - c->pkeys]; + size_t fileidx = c->key - c->pkeys; - OPENSSL_free(*pfilename); - *pfilename = OPENSSL_strdup(value); - if (*pfilename == NULL) + if (fileidx >= cctx->num_cert_filename) { rv = 0; + } else { + char **pfilename = &cctx->cert_filename[c->key - c->pkeys]; + + OPENSSL_free(*pfilename); + *pfilename = OPENSSL_strdup(value); + if (*pfilename == NULL) + rv = 0; + } } return rv > 0; @@ -1049,12 +1057,13 @@ int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) c = sc->cert; } if (c != NULL && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) { - for (i = 0; i < SSL_PKEY_NUM; i++) { + for (i = 0; i < cctx->num_cert_filename; 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 (p != NULL && c->pkeys[i].privatekey == NULL) { if (!cmd_PrivateKey(cctx, p)) return 0; } @@ -1072,12 +1081,21 @@ int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) return 1; } +static void free_cert_filename(SSL_CONF_CTX *cctx) +{ + size_t i; + + for (i = 0; i < cctx->num_cert_filename; i++) + OPENSSL_free(cctx->cert_filename[i]); + OPENSSL_free(cctx->cert_filename); + cctx->cert_filename = NULL; + cctx->num_cert_filename = 0; +} + void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) { if (cctx) { - size_t i; - for (i = 0; i < SSL_PKEY_NUM; i++) - OPENSSL_free(cctx->cert_filename[i]); + free_cert_filename(cctx); OPENSSL_free(cctx->prefix); sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free); OPENSSL_free(cctx); @@ -1117,6 +1135,7 @@ void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl) { cctx->ssl = ssl; cctx->ctx = NULL; + free_cert_filename(cctx); if (ssl != NULL) { SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl); @@ -1127,6 +1146,10 @@ void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl) cctx->max_version = &sc->max_proto_version; cctx->pcert_flags = &sc->cert->cert_flags; cctx->pvfy_flags = &sc->verify_mode; + cctx->cert_filename = OPENSSL_zalloc(sc->ssl_pkey_num + * sizeof(*cctx->cert_filename)); + if (cctx->cert_filename != NULL) + cctx->num_cert_filename = sc->ssl_pkey_num; } else { cctx->poptions = NULL; cctx->min_version = NULL; @@ -1140,12 +1163,17 @@ void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) { cctx->ctx = ctx; cctx->ssl = NULL; + free_cert_filename(cctx); if (ctx) { cctx->poptions = &ctx->options; cctx->min_version = &ctx->min_proto_version; cctx->max_version = &ctx->max_proto_version; cctx->pcert_flags = &ctx->cert->cert_flags; cctx->pvfy_flags = &ctx->verify_mode; + cctx->cert_filename = OPENSSL_zalloc((SSL_PKEY_NUM + ctx->sigalg_list_len) + * sizeof(*cctx->cert_filename)); + if (cctx->cert_filename != NULL) + cctx->num_cert_filename = SSL_PKEY_NUM + ctx->sigalg_list_len; } else { cctx->poptions = NULL; cctx->min_version = NULL;