]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Fix configuring provider certificate algs via config file
authorMatt Caswell <matt@openssl.org>
Fri, 7 Feb 2025 12:11:41 +0000 (12:11 +0000)
committerMatt Caswell <matt@openssl.org>
Tue, 11 Feb 2025 17:36:21 +0000 (17:36 +0000)
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 <viktor@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26663)

ssl/ssl_conf.c

index e22511b634bd4d8edee1981a76417bffd4d733a5..730a796a78fc34e9009a7f0475afad83347eecf0 100644 (file)
@@ -88,7 +88,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 */
@@ -453,12 +455,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;
@@ -1051,12 +1059,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;
             }
@@ -1074,12 +1083,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);
@@ -1119,6 +1137,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);
 
@@ -1129,6 +1148,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;
@@ -1142,12 +1165,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;