summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/store/loader_file.c61
-rw-r--r--crypto/store/store_lib.c43
2 files changed, 76 insertions, 28 deletions
diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c
index 85ab2b4206..0a9191d2d6 100644
--- a/crypto/store/loader_file.c
+++ b/crypto/store/loader_file.c
@@ -744,26 +744,41 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
{
OSSL_STORE_LOADER_CTX *ctx = NULL;
struct stat st;
- const char *path = NULL;
+ const char *paths[2], *path;
+ size_t paths_n = 0, i;
+ /*
+ * First step, just take the URI as is.
+ */
+ paths[paths_n++] = uri;
+
+ /*
+ * Second step, if the URI appears to start with the 'file' scheme,
+ * extract the path and make that the second path to check.
+ * There's a special case if the URI also contains an authority, then
+ * the full URI shouldn't be used as a path anywhere.
+ */
if (strncasecmp(uri, "file:", 5) == 0) {
- if (strncasecmp(&uri[5], "//localhost/", 12) == 0) {
- path = &uri[16];
- } else if (strncmp(&uri[5], "///", 3) == 0) {
- path = &uri[7];
- } else if (strncmp(&uri[5], "//", 2) != 0) {
- path = &uri[5];
- } else {
- OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN,
- OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED);
- return NULL;
+ const char *p = &uri[5];
+
+ if (strncmp(&uri[5], "//", 2) == 0) {
+ paths_n--; /* Invalidate using the full URI */
+ if (strncasecmp(&uri[7], "localhost/", 10) == 0) {
+ p = &uri[16];
+ } else if (uri[7] == '/') {
+ p = &uri[7];
+ } else {
+ OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN,
+ OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED);
+ return NULL;
+ }
}
/*
* If the scheme "file" was an explicit part of the URI, the path must
* be absolute. So says RFC 8089
*/
- if (path[0] != '/') {
+ if (p[0] != '/') {
OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN,
OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE);
return NULL;
@@ -771,20 +786,28 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
#ifdef _WIN32
/* Windows file: URIs with a drive letter start with a / */
- if (path[0] == '/' && path[2] == ':' && path[3] == '/')
- path++;
+ if (p[0] == '/' && p[2] == ':' && p[3] == '/')
+ p++;
#endif
- } else {
- path = uri;
+ paths[paths_n++] = p;
}
- if (stat(path, &st) < 0) {
- SYSerr(SYS_F_STAT, errno);
- ERR_add_error_data(1, path);
+ for (i = 0, path = NULL; path == NULL && i < paths_n; i++) {
+ if (stat(paths[i], &st) < 0) {
+ SYSerr(SYS_F_STAT, errno);
+ ERR_add_error_data(1, paths[i]);
+ } else {
+ path = paths[i];
+ }
+ }
+ if (path == NULL) {
return NULL;
}
+ /* Successfully found a working path, clear possible collected errors */
+ ERR_clear_error();
+
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx == NULL) {
OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_MALLOC_FAILURE);
diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c
index 91faae20c5..9dc3a70a41 100644
--- a/crypto/store/store_lib.c
+++ b/crypto/store/store_lib.c
@@ -10,6 +10,8 @@
#include <stdlib.h>
#include <string.h>
+#include "e_os.h"
+
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/store.h>
@@ -31,22 +33,45 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
OSSL_STORE_post_process_info_fn post_process,
void *post_process_data)
{
- const OSSL_STORE_LOADER *loader;
+ const OSSL_STORE_LOADER *loader = NULL;
OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
OSSL_STORE_CTX *ctx = NULL;
- char scheme_copy[256], *p;
-
+ char scheme_copy[256], *p, *schemes[2];
+ size_t schemes_n = 0;
+ size_t i;
+
+ /*
+ * Put the file scheme first. If the uri does represent an existing file,
+ * possible device name and all, then it should be loaded. Only a failed
+ * attempt at loading a local file should have us try something else.
+ */
+ schemes[schemes_n++] = "file";
+
+ /*
+ * Now, check if we have something that looks like a scheme, and add it
+ * as a second scheme. However, also check if there's an authority start
+ * (://), because that will invalidate the previous file scheme. Also,
+ * check that this isn't actually the file scheme, as there's no point
+ * going through that one twice!
+ */
OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy));
if ((p = strchr(scheme_copy, ':')) != NULL) {
- *p = '\0';
- p = scheme_copy;
- } else {
- p = "file";
+ *p++ = '\0';
+ if (strcasecmp(scheme_copy, "file") != 0) {
+ if (strncmp(p, "//", 2) == 0)
+ schemes_n--; /* Invalidate the file scheme */
+ schemes[schemes_n++] = scheme_copy;
+ }
}
- if ((loader = ossl_store_get0_loader_int(p)) == NULL
- || (loader_ctx = loader->open(loader, uri, ui_method, ui_data)) == NULL)
+ /* Try each scheme until we find one that could open the URI */
+ for (i = 0; loader_ctx == NULL && i < schemes_n; i++) {
+ if ((loader = ossl_store_get0_loader_int(schemes[i])) != NULL)
+ loader_ctx = loader->open(loader, uri, ui_method, ui_data);
+ }
+ if (loader_ctx == NULL)
goto done;
+
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_OPEN, ERR_R_MALLOC_FAILURE);
goto done;