diff options
author | Richard Levitte <levitte@openssl.org> | 2017-02-20 02:39:52 +0100 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2018-02-23 07:40:42 +0100 |
commit | 93d2f9fa4a5d03ac227a54f5c0f2f9b23f1121b6 (patch) | |
tree | db8f0b360ad20ed6f2db59f3211eca78dd90c016 /crypto/store | |
parent | fac8673b8aed77231e23d51d78cd8eb995d21f5c (diff) |
STORE 'file' scheme loader: Add search capibility
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2688)
Diffstat (limited to 'crypto/store')
-rw-r--r-- | crypto/store/loader_file.c | 104 | ||||
-rw-r--r-- | crypto/store/store_err.c | 5 |
2 files changed, 108 insertions, 1 deletions
diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c index 1fa7fc4c2d..ea1b321672 100644 --- a/crypto/store/loader_file.c +++ b/crypto/store/loader_file.c @@ -10,6 +10,7 @@ #include "e_os.h" #include <string.h> #include <sys/stat.h> +#include <ctype.h> #include <assert.h> #include <openssl/bio.h> @@ -713,6 +714,13 @@ struct ossl_store_loader_ctx_st { char *uri; /* + * When a search expression is given, these are filled in. + * |search_name| contains the file basename to look for. + * The string is exactly 8 characters long. + */ + char search_name[9]; + + /* * The directory reading utility we have combines opening with * reading the first name. To make sure we can detect the end * at the right time, we read early and cache the name. @@ -917,6 +925,37 @@ static int file_expect(OSSL_STORE_LOADER_CTX *ctx, int expected) return 1; } +static int file_find(OSSL_STORE_LOADER_CTX *ctx, OSSL_STORE_SEARCH *search) +{ + /* + * If ctx == NULL, the library is looking to know if this loader supports + * the given search type. + */ + + if (OSSL_STORE_SEARCH_get_type(search) == OSSL_STORE_SEARCH_BY_NAME) { + unsigned long hash = 0; + + if (ctx == NULL) + return 1; + + if (ctx->type != is_dir) { + OSSL_STOREerr(OSSL_STORE_F_FILE_FIND, + OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES); + return 0; + } + + hash = X509_NAME_hash(OSSL_STORE_SEARCH_get0_name(search)); + BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name), + "%08lx", hash); + return 1; + } + + if (ctx != NULL) + OSSL_STOREerr(OSSL_STORE_F_FILE_FIND, + OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE); + return 0; +} + /* Internal function to decode an already opened PEM file */ OSSL_STORE_LOADER_CTX *ossl_store_file_attach_pem_bio_int(BIO *bp) { @@ -1137,6 +1176,68 @@ static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name, return 1; } +static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name) +{ + const char *p = NULL; + + /* If there are no search criteria, all names are accepted */ + if (ctx->_.dir.search_name[0] == '\0') + return 1; + + /* If the expected type isn't supported, no name is accepted */ + if (ctx->expected_type != 0 + && ctx->expected_type != OSSL_STORE_INFO_CERT + && ctx->expected_type != OSSL_STORE_INFO_CRL) + return 0; + + /* + * First, check the basename + */ + if (strncasecmp(name, ctx->_.dir.search_name, + sizeof(ctx->_.dir.search_name) - 1) != 0 + || name[sizeof(ctx->_.dir.search_name) - 1] != '.') + return 0; + p = &name[sizeof(ctx->_.dir.search_name)]; + + /* + * Then, if the expected type is a CRL, check that the extension starts + * with 'r' + */ + if (*p == 'r') { + p++; + if (ctx->expected_type != 0 + && ctx->expected_type != OSSL_STORE_INFO_CRL) + return 0; + } else if (ctx->expected_type == OSSL_STORE_INFO_CRL) { + return 0; + } + + /* + * Last, check that the rest of the extension is a decimal number, at + * least one digit long. + */ + if (!isdigit(*p)) + return 0; + while (isdigit(*p)) + p++; + +# ifdef __VMS + /* + * One extra step here, check for a possible generation number. + */ + if (*p == ';') + for (p++; *p != '\0'; p++) + if (!isdigit(*p)) + break; +# endif + + /* + * If we've reached the end of the string at this point, we've successfully + * found a fitting file name. + */ + return *p == '\0'; +} + static int file_eof(OSSL_STORE_LOADER_CTX *ctx); static int file_error(OSSL_STORE_LOADER_CTX *ctx); static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx, @@ -1165,6 +1266,7 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx, } if (ctx->_.dir.last_entry[0] != '.' + && file_name_check(ctx, ctx->_.dir.last_entry) && !file_name_to_uri(ctx, ctx->_.dir.last_entry, &newname)) return NULL; @@ -1313,7 +1415,7 @@ static OSSL_STORE_LOADER file_loader = file_open, file_ctrl, file_expect, - NULL, + file_find, file_load, file_eof, file_error, diff --git a/crypto/store/store_err.c b/crypto/store/store_err.c index e0280da809..5a8a8404dd 100644 --- a/crypto/store/store_err.c +++ b/crypto/store/store_err.c @@ -15,6 +15,7 @@ static const ERR_STRING_DATA OSSL_STORE_str_functs[] = { {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_CTRL, 0), "file_ctrl"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_FIND, 0), "file_find"}, {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_GET_PASS, 0), "file_get_pass"}, {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_FILE_LOAD, 0), "file_load"}, @@ -114,6 +115,8 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = { "passphrase callback error"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE), "path must be absolute"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES), + "search only supported for directories"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED), "ui process interrupted or cancelled"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNREGISTERED_SCHEME), @@ -122,6 +125,8 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = { "unsupported content type"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNSUPPORTED_OPERATION), "unsupported operation"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE), + "unsupported search type"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED), "uri authority unsupported"}, {0, NULL} |