summaryrefslogtreecommitdiffstats
path: root/crypto/store
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2017-02-20 02:39:52 +0100
committerRichard Levitte <levitte@openssl.org>2018-02-23 07:40:42 +0100
commit93d2f9fa4a5d03ac227a54f5c0f2f9b23f1121b6 (patch)
treedb8f0b360ad20ed6f2db59f3211eca78dd90c016 /crypto/store
parentfac8673b8aed77231e23d51d78cd8eb995d21f5c (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.c104
-rw-r--r--crypto/store/store_err.c5
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}