diff options
-rw-r--r-- | crypto/store/loader_file.c | 61 | ||||
-rw-r--r-- | crypto/store/store_lib.c | 43 |
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; |