]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - crypto/store/store_lib.c
str[n]casecmp => OPENSSL_strncasecmp
[thirdparty/openssl.git] / crypto / store / store_lib.c
index 671852cea22c47cba1a85e808b17a2a4b353c99c..e748647a61216084984091014ef76486049b2ff6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -14,7 +14,7 @@
 /* We need to use some STORE deprecated APIs */
 #define OPENSSL_SUPPRESS_DEPRECATED
 
-#include "e_os.h"
+#include "internal/e_os.h"
 
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 #include "internal/thread_once.h"
 #include "internal/cryptlib.h"
 #include "internal/provider.h"
+#include "internal/bio.h"
 #include "crypto/store.h"
 #include "store_local.h"
 
 static int ossl_store_close_it(OSSL_STORE_CTX *ctx);
 
+static int loader_set_params(OSSL_STORE_LOADER *loader,
+                             OSSL_STORE_LOADER_CTX *loader_ctx,
+                             const OSSL_PARAM params[], const char *propq)
+{
+   if (params != NULL) {
+       if (!loader->p_set_ctx_params(loader_ctx, params))
+           return 0;
+   }
+
+   if (propq != NULL) {
+       OSSL_PARAM propp[2];
+
+       if (OSSL_PARAM_locate_const(params,
+                                   OSSL_STORE_PARAM_PROPERTIES) != NULL)
+           /* use the propq from params */
+           return 1;
+
+       propp[0] = OSSL_PARAM_construct_utf8_string(OSSL_STORE_PARAM_PROPERTIES,
+                                                   (char *)propq, 0);
+       propp[1] = OSSL_PARAM_construct_end();
+
+       if (!loader->p_set_ctx_params(loader_ctx, propp))
+           return 0;
+    }
+    return 1;
+}
+
 OSSL_STORE_CTX *
 OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
                    const UI_METHOD *ui_method, void *ui_data,
+                   const OSSL_PARAM params[],
                    OSSL_STORE_post_process_info_fn post_process,
                    void *post_process_data)
 {
@@ -42,7 +71,8 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
     OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
     OSSL_STORE_CTX *ctx = NULL;
     char *propq_copy = NULL;
-    char scheme_copy[256], *p, *schemes[2];
+    int no_loader_found = 1;
+    char scheme_copy[256], *p, *schemes[2], *scheme = NULL;
     size_t schemes_n = 0;
     size_t i;
 
@@ -63,8 +93,8 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
     OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy));
     if ((p = strchr(scheme_copy, ':')) != NULL) {
         *p++ = '\0';
-        if (strcasecmp(scheme_copy, "file") != 0) {
-            if (strncmp(p, "//", 2) == 0)
+        if (OPENSSL_strcasecmp(scheme_copy, "file") != 0) {
+            if (HAS_PREFIX(p, "//"))
                 schemes_n--;         /* Invalidate the file scheme */
             schemes[schemes_n++] = scheme_copy;
         }
@@ -81,49 +111,58 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
      * elsewhere.
      */
     for (i = 0; loader_ctx == NULL && i < schemes_n; i++) {
-        OSSL_TRACE1(STORE, "Looking up scheme %s\n", schemes[i]);
+        scheme = schemes[i];
+        OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
 #ifndef OPENSSL_NO_DEPRECATED_3_0
-        if ((loader = ossl_store_get0_loader_int(schemes[i])) != NULL) {
+        ERR_set_mark();
+        if ((loader = ossl_store_get0_loader_int(scheme)) != NULL) {
+            ERR_clear_last_mark();
+            no_loader_found = 0;
             if (loader->open_ex != NULL)
                 loader_ctx = loader->open_ex(loader, uri, libctx, propq,
                                              ui_method, ui_data);
             else
                 loader_ctx = loader->open(loader, uri, ui_method, ui_data);
+        } else {
+            ERR_pop_to_mark();
         }
 #endif
         if (loader == NULL
             && (fetched_loader =
-                OSSL_STORE_LOADER_fetch(schemes[i], libctx, propq)) != NULL) {
+                OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
             const OSSL_PROVIDER *provider =
-                OSSL_STORE_LOADER_provider(fetched_loader);
+                OSSL_STORE_LOADER_get0_provider(fetched_loader);
             void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
 
+            no_loader_found = 0;
             loader_ctx = fetched_loader->p_open(provctx, uri);
             if (loader_ctx == NULL) {
                 OSSL_STORE_LOADER_free(fetched_loader);
                 fetched_loader = NULL;
-            } else if (propq != NULL) {
-                OSSL_PARAM params[] = {
-                    OSSL_PARAM_utf8_string(OSSL_STORE_PARAM_PROPERTIES,
-                                           NULL, 0),
-                    OSSL_PARAM_END
-                };
-
-                params[0].data = (void *)propq;
-                if (!fetched_loader->p_set_ctx_params(loader_ctx, params)) {
-                    (void)fetched_loader->p_close(loader_ctx);
-                    OSSL_STORE_LOADER_free(fetched_loader);
-                    fetched_loader = NULL;
-                }
+            } else if (!loader_set_params(fetched_loader, loader_ctx,
+                                          params, propq)) {
+                (void)fetched_loader->p_close(loader_ctx);
+                OSSL_STORE_LOADER_free(fetched_loader);
+                fetched_loader = NULL;
             }
             loader = fetched_loader;
         }
     }
 
-    if (loader != NULL)
-        OSSL_TRACE1(STORE, "Found loader for scheme %s\n", schemes[i]);
+    if (no_loader_found)
+        /*
+         * It's assumed that ossl_store_get0_loader_int() and
+         * OSSL_STORE_LOADER_fetch() report their own errors
+         */
+        goto err;
+
+    OSSL_TRACE1(STORE, "Found loader for scheme %s\n", scheme);
 
     if (loader_ctx == NULL)
+        /*
+         * It's assumed that the loader's open() method reports its own
+         * errors
+         */
         goto err;
 
     OSSL_TRACE2(STORE, "Opened %s => %p\n", uri, (void *)loader_ctx);
@@ -135,7 +174,8 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
     }
 
     if (ui_method != NULL
-        && !ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data)) {
+        && (!ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data)
+            || !ossl_pw_enable_passphrase_caching(&ctx->pwdata))) {
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
         goto err;
     }
@@ -186,8 +226,8 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri,
                                 OSSL_STORE_post_process_info_fn post_process,
                                 void *post_process_data)
 {
-    return OSSL_STORE_open_ex(uri, NULL, NULL, ui_method, ui_data, post_process,
-                              post_process_data);
+    return OSSL_STORE_open_ex(uri, NULL, NULL, ui_method, ui_data, NULL,
+                              post_process, post_process_data);
 }
 
 #ifndef OPENSSL_NO_DEPRECATED_3_0
@@ -240,6 +280,11 @@ int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type)
 {
     int ret = 1;
 
+    if (ctx == NULL
+            || expected_type < 0 || expected_type > OSSL_STORE_INFO_CRL) {
+        ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
     if (ctx->loading) {
         ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADING_STARTED);
         return 0;
@@ -319,7 +364,8 @@ int OSSL_STORE_find(OSSL_STORE_CTX *ctx, const OSSL_STORE_SEARCH *search)
             break;
         case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
             if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_STORE_PARAM_DIGEST,
-                                                EVP_MD_name(search->digest), 0)
+                                                EVP_MD_get0_name(search->digest),
+                                                0)
                 && OSSL_PARAM_BLD_push_octet_string(bld,
                                                     OSSL_STORE_PARAM_FINGERPRINT,
                                                     search->string,
@@ -337,7 +383,7 @@ int OSSL_STORE_find(OSSL_STORE_CTX *ctx, const OSSL_STORE_SEARCH *search)
             params = OSSL_PARAM_BLD_to_param(bld);
             ret = ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx,
                                                         params);
-            OSSL_PARAM_BLD_free_params(params);
+            OSSL_PARAM_free(params);
         }
         OSSL_PARAM_BLD_free(bld);
         OPENSSL_free(name_der);
@@ -413,6 +459,9 @@ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
             goto again;
     }
 
+    /* Clear any internally cached passphrase */
+    (void)ossl_pw_clear_passphrase_cache(&ctx->pwdata);
+
     if (v != NULL && ctx->expected_type != 0) {
         int returned_type = OSSL_STORE_INFO_get_type(v);
 
@@ -454,7 +503,7 @@ int OSSL_STORE_eof(OSSL_STORE_CTX *ctx)
     if (ctx->fetched_loader == NULL)
         ret = ctx->loader->eof(ctx->loader_ctx);
 #endif
-    return ret;
+    return ret != 0;
 }
 
 static int ossl_store_close_it(OSSL_STORE_CTX *ctx)
@@ -469,7 +518,7 @@ static int ossl_store_close_it(OSSL_STORE_CTX *ctx)
         ret = ctx->loader->p_close(ctx->loader_ctx);
 #ifndef OPENSSL_NO_DEPRECATED_3_0
     if (ctx->fetched_loader == NULL)
-        ret = ctx->loader->close(ctx->loader_ctx);
+        ret = ctx->loader->closefn(ctx->loader_ctx);
 #endif
 
     sk_OSSL_STORE_INFO_pop_free(ctx->cached_info, OSSL_STORE_INFO_free);
@@ -755,7 +804,7 @@ int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type)
 
     if (ctx->fetched_loader != NULL) {
         void *provctx =
-            ossl_provider_ctx(OSSL_STORE_LOADER_provider(ctx->fetched_loader));
+            ossl_provider_ctx(OSSL_STORE_LOADER_get0_provider(ctx->fetched_loader));
         const OSSL_PARAM *params;
         const OSSL_PARAM *p_subject = NULL;
         const OSSL_PARAM *p_issuer = NULL;
@@ -844,11 +893,11 @@ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest,
         return NULL;
     }
 
-    if (digest != NULL && len != (size_t)EVP_MD_size(digest)) {
+    if (digest != NULL && len != (size_t)EVP_MD_get_size(digest)) {
         ERR_raise_data(ERR_LIB_OSSL_STORE,
                        OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST,
                        "%s size is %d, fingerprint size is %zu",
-                       EVP_MD_name(digest), EVP_MD_size(digest), len);
+                       EVP_MD_get0_name(digest), EVP_MD_get_size(digest), len);
         OPENSSL_free(search);
         return NULL;
     }
@@ -918,6 +967,7 @@ const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion)
 OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme,
                                   OSSL_LIB_CTX *libctx, const char *propq,
                                   const UI_METHOD *ui_method, void *ui_data,
+                                  const OSSL_PARAM params[],
                                   OSSL_STORE_post_process_info_fn post_process,
                                   void *post_process_data)
 {
@@ -930,6 +980,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,
@@ -937,50 +988,56 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme,
 #endif
     if (loader == NULL
         && (fetched_loader =
-            OSSL_STORE_LOADER_fetch(scheme, libctx, propq)) != NULL) {
+            OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
         const OSSL_PROVIDER *provider =
-            OSSL_STORE_LOADER_provider(fetched_loader);
+            OSSL_STORE_LOADER_get0_provider(fetched_loader);
         void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
+        OSSL_CORE_BIO *cbio = ossl_core_bio_new_from_bio(bp);
 
-        if ((loader_ctx =
-             fetched_loader->p_attach(provctx, (OSSL_CORE_BIO *)bp)) == NULL) {
+        if (cbio == NULL
+            || (loader_ctx = fetched_loader->p_attach(provctx, cbio)) == NULL) {
+            OSSL_STORE_LOADER_free(fetched_loader);
+            fetched_loader = NULL;
+        } else if (!loader_set_params(fetched_loader, loader_ctx,
+                                      params, propq)) {
+            (void)fetched_loader->p_close(loader_ctx);
             OSSL_STORE_LOADER_free(fetched_loader);
             fetched_loader = NULL;
-        } else if (propq != NULL) {
-            OSSL_PARAM params[] = {
-                OSSL_PARAM_utf8_string(OSSL_STORE_PARAM_PROPERTIES,
-                                       NULL, 0),
-                OSSL_PARAM_END
-            };
-
-            params[0].data = (void *)propq;
-            if (!fetched_loader->p_set_ctx_params(loader_ctx, params)) {
-                (void)fetched_loader->p_close(loader_ctx);
-                OSSL_STORE_LOADER_free(fetched_loader);
-                fetched_loader = NULL;
-            }
         }
         loader = fetched_loader;
+        ossl_core_bio_free(cbio);
     }
 
-    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;
 }