From: Richard Levitte Date: Mon, 20 Feb 2017 01:39:52 +0000 (+0100) Subject: STORE 'file' scheme loader: Add search capibility X-Git-Tag: OpenSSL_1_1_1-pre2~19 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=93d2f9fa4a5d03ac227a54f5c0f2f9b23f1121b6 STORE 'file' scheme loader: Add search capibility Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/2688) --- diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 756d1fc2b0..e406becddb 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -751,6 +751,7 @@ OCSP_F_OCSP_REQUEST_VERIFY:116:OCSP_request_verify OCSP_F_OCSP_RESPONSE_GET1_BASIC:111:OCSP_response_get1_basic OCSP_F_PARSE_HTTP_LINE1:118:parse_http_line1 OSSL_STORE_F_FILE_CTRL:129:file_ctrl +OSSL_STORE_F_FILE_FIND:138:file_find OSSL_STORE_F_FILE_GET_PASS:118:file_get_pass OSSL_STORE_F_FILE_LOAD:119:file_load OSSL_STORE_F_FILE_LOAD_TRY_DECODE:124:file_load_try_decode @@ -2167,11 +2168,14 @@ OSSL_STORE_R_NOT_A_NAME:103:not a name OSSL_STORE_R_NOT_PARAMETERS:104:not parameters OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR:114:passphrase callback error OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE:108:path must be absolute +OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:119:\ + search only supported for directories OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED:109:\ ui process interrupted or cancelled OSSL_STORE_R_UNREGISTERED_SCHEME:105:unregistered scheme OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE:110:unsupported content type OSSL_STORE_R_UNSUPPORTED_OPERATION:118:unsupported operation +OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE:120:unsupported search type OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED:111:uri authority unsupported PEM_R_BAD_BASE64_DECODE:100:bad base64 decode PEM_R_BAD_DECRYPT:101:bad decrypt 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 #include +#include #include #include @@ -712,6 +713,13 @@ struct ossl_store_loader_ctx_st { int end_reached; 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 @@ -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} diff --git a/include/openssl/storeerr.h b/include/openssl/storeerr.h index 0eb8e88a48..33d0ab7903 100644 --- a/include/openssl/storeerr.h +++ b/include/openssl/storeerr.h @@ -20,6 +20,7 @@ int ERR_load_OSSL_STORE_strings(void); * OSSL_STORE function codes. */ # define OSSL_STORE_F_FILE_CTRL 129 +# define OSSL_STORE_F_FILE_FIND 138 # define OSSL_STORE_F_FILE_GET_PASS 118 # define OSSL_STORE_F_FILE_LOAD 119 # define OSSL_STORE_F_FILE_LOAD_TRY_DECODE 124 @@ -75,10 +76,12 @@ int ERR_load_OSSL_STORE_strings(void); # define OSSL_STORE_R_NOT_PARAMETERS 104 # define OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR 114 # define OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE 108 +# define OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES 119 # define OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED 109 # define OSSL_STORE_R_UNREGISTERED_SCHEME 105 # define OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE 110 # define OSSL_STORE_R_UNSUPPORTED_OPERATION 118 +# define OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE 120 # define OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED 111 #endif