STORE: clear err after ossl_store_get0_loader_int
authorDaniel Bevenius <daniel.bevenius@gmail.com>
Thu, 17 Sep 2020 07:48:29 +0000 (09:48 +0200)
committerTomas Mraz <tmraz@fedoraproject.org>
Tue, 8 Dec 2020 17:23:29 +0000 (18:23 +0100)
This commit clears the error that might have been set when
ossl_store_get0_loader_int has been called as it will try to retrieve
a loader for the scheme on an empty store, which will cause the error
OSSL_STORE_R_UNREGISTERED_SCHEME to be set.

The motivation for this after returning from
ossl_store_get0_loader_int, OSSL_STORE_attach will continue and try to
fetch a OSSL_STORE_LOADER from the provider.

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/12901)

crypto/store/store_lib.c
test/ossl_store_test.c

index 671852cea22c47cba1a85e808b17a2a4b353c99c..c59c508be1e08ea859e03729422050fe4bc83346 100644 (file)
@@ -930,6 +930,7 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme,
         scheme = "file";
 
     OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
+    ERR_set_mark();
 #ifndef OPENSSL_NO_DEPRECATED_3_0
     if ((loader = ossl_store_get0_loader_int(scheme)) != NULL)
         loader_ctx = loader->attach(loader, bp, libctx, propq,
@@ -963,24 +964,36 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme,
         loader = fetched_loader;
     }
 
-    if (loader_ctx == NULL)
+    if (loader_ctx == NULL) {
+        ERR_clear_last_mark();
         return NULL;
+    }
 
     if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
+        ERR_clear_last_mark();
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
     if (ui_method != NULL
         && !ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data)) {
+        ERR_clear_last_mark();
         OPENSSL_free(ctx);
         return NULL;
     }
+
     ctx->fetched_loader = fetched_loader;
     ctx->loader = loader;
     ctx->loader_ctx = loader_ctx;
     ctx->post_process = post_process;
     ctx->post_process_data = post_process_data;
 
+    /*
+     * ossl_store_get0_loader_int will raise an error if the loader for the
+     * the scheme cannot be retrieved. But if a loader was successfully
+     * fetched then we remove this error from the error stack.
+     */
+    ERR_pop_to_mark();
+
     return ctx;
 }
index f48c282b2e938898697e56df9b8e357d98e82979..7424aed0dd573857cf52524200feb42d2b978c87 100644 (file)
@@ -132,6 +132,33 @@ static int test_store_get_params(int idx)
     return 1;
 }
 
+/*
+ * This test verifies that calling OSSL_STORE_ATTACH does not set an
+ * "unregistered scheme" error when called.
+ */
+static int test_store_attach_unregistered_scheme(void)
+{
+    int ret;
+    OSSL_STORE_CTX *store_ctx;
+    OSSL_PROVIDER *provider;
+    OSSL_LIB_CTX *libctx;
+    BIO *bio;
+    libctx = OSSL_LIB_CTX_new();
+    provider = OSSL_PROVIDER_load(libctx, "default");
+    bio = BIO_new_file("test/certs/sm2-root.crt", "r");
+
+    ret = TEST_ptr(store_ctx = OSSL_STORE_attach(bio, "file", libctx, NULL,
+                                                 NULL, NULL, NULL, NULL)) &&
+          TEST_int_ne(ERR_GET_LIB(ERR_peek_error()), ERR_LIB_OSSL_STORE) &&
+          TEST_int_ne(ERR_GET_REASON(ERR_peek_error()),
+                      OSSL_STORE_R_UNREGISTERED_SCHEME);
+
+    BIO_free(bio);
+    OSSL_STORE_close(store_ctx);
+    OSSL_PROVIDER_unload(provider);
+    OSSL_LIB_CTX_free(libctx);
+    return ret;
+}
 
 const OPTIONS *test_get_options(void)
 {
@@ -172,5 +199,6 @@ int setup_tests(void)
     ADD_TEST(test_store_open);
     ADD_TEST(test_store_search_by_key_fingerprint_fail);
     ADD_ALL_TESTS(test_store_get_params, 3);
+    ADD_TEST(test_store_attach_unregistered_scheme);
     return 1;
 }