You need to sign in or sign up before continuing.
提交 ae9c39d8 编写于 作者: R Richard Levitte

OSSL_STORE: Treat URIs as files first (with exceptions), then as full URIs

To handle paths that contain devices (for example, C:/foo/bar.pem on
Windows), try to "open" the URI using the file scheme loader first,
and failing that, check if the device is really a scheme we know.

The "file" scheme does the same kind of thing to pick out the path
part of the URI.

An exception to this special treatment is if the URI has an authority
part (something that starts with "//" directly after what looks like a
scheme).  Such URIs will never be treated as plain file paths.
Reviewed-by: NAndy Polyakov <appro@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3907)
上级 ba476aa3
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册