Store the list of activated providers in the libctx
authorMatt Caswell <matt@openssl.org>
Mon, 26 Apr 2021 13:58:40 +0000 (14:58 +0100)
committerMatt Caswell <matt@openssl.org>
Wed, 28 Apr 2021 15:04:25 +0000 (16:04 +0100)
The provider config module was storing the list of activated providers
in a global variable. However, because different libctxs can each load
providers via config files we need to keep the list of activated providers
separate and in the libctx.

Partially fixes #15030

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15033)

crypto/provider_conf.c
include/internal/cryptlib.h

index fb83977e6d4e722bb48baf1b8b752898cd6604ab..a04a7aa5535e86c9b724bd82800b875ea8871730 100644 (file)
 #include <openssl/conf.h>
 #include <openssl/safestack.h>
 #include "internal/provider.h"
+#include "internal/cryptlib.h"
 
 DEFINE_STACK_OF(OSSL_PROVIDER)
 
 /* PROVIDER config module */
 
-static STACK_OF(OSSL_PROVIDER) *activated_providers = NULL;
+typedef struct {
+    STACK_OF(OSSL_PROVIDER) *activated_providers;
+} PROVIDER_CONF_GLOBAL;
+
+static void *prov_conf_ossl_ctx_new(OSSL_LIB_CTX *libctx)
+{
+    PROVIDER_CONF_GLOBAL *pcgbl = OPENSSL_zalloc(sizeof(*pcgbl));
+
+    if (pcgbl == NULL)
+        return NULL;
+
+    return pcgbl;
+}
+
+static void prov_conf_ossl_ctx_free(void *vpcgbl)
+{
+    PROVIDER_CONF_GLOBAL *pcgbl = vpcgbl;
+
+    sk_OSSL_PROVIDER_pop_free(pcgbl->activated_providers,
+                              ossl_provider_free);
+
+    OSSL_TRACE(CONF, "Cleaned up providers\n");
+    OPENSSL_free(pcgbl);
+}
+
+static const OSSL_LIB_CTX_METHOD provider_conf_ossl_ctx_method = {
+    prov_conf_ossl_ctx_new,
+    prov_conf_ossl_ctx_free,
+};
 
 static const char *skip_dot(const char *name)
 {
@@ -80,6 +109,9 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name,
     const char *path = NULL;
     long activate = 0;
     int ok = 0;
+    PROVIDER_CONF_GLOBAL *pcgbl
+        = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_CONF_INDEX,
+                                &provider_conf_ossl_ctx_method);
 
     name = skip_dot(name);
     OSSL_TRACE1(CONF, "Configuring provider %s\n", name);
@@ -133,9 +165,9 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name,
         if (!ossl_provider_activate(prov, 0)) {
             ok = 0;
         } else {
-            if (activated_providers == NULL)
-                activated_providers = sk_OSSL_PROVIDER_new_null();
-            sk_OSSL_PROVIDER_push(activated_providers, prov);
+            if (pcgbl->activated_providers == NULL)
+                pcgbl->activated_providers = sk_OSSL_PROVIDER_new_null();
+            sk_OSSL_PROVIDER_push(pcgbl->activated_providers, prov);
             ok = 1;
         }
     }
@@ -172,16 +204,8 @@ static int provider_conf_init(CONF_IMODULE *md, const CONF *cnf)
     return 1;
 }
 
-
-static void provider_conf_deinit(CONF_IMODULE *md)
-{
-    sk_OSSL_PROVIDER_pop_free(activated_providers, ossl_provider_free);
-    activated_providers = NULL;
-    OSSL_TRACE(CONF, "Cleaned up providers\n");
-}
-
 void ossl_provider_add_conf_module(void)
 {
     OSSL_TRACE(CONF, "Adding config module 'providers'\n");
-    CONF_module_add("providers", provider_conf_init, provider_conf_deinit);
+    CONF_module_add("providers", provider_conf_init, NULL);
 }
index ea42447e7884d7c3fd93f0ae867857df4b482ef1..e7dd1f65b4e2ca60bd9dc6568e5825810a0122d4 100644 (file)
@@ -162,7 +162,8 @@ typedef struct ossl_ex_data_global_st {
 # define OSSL_LIB_CTX_BIO_PROV_INDEX                13
 # define OSSL_LIB_CTX_GLOBAL_PROPERTIES             14
 # define OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX      15
-# define OSSL_LIB_CTX_MAX_INDEXES                   16
+# define OSSL_LIB_CTX_PROVIDER_CONF_INDEX           16
+# define OSSL_LIB_CTX_MAX_INDEXES                   17
 
 typedef struct ossl_lib_ctx_method {
     void *(*new_func)(OSSL_LIB_CTX *ctx);