STORE 'file' scheme loader: Add search capibility
authorRichard Levitte <levitte@openssl.org>
Mon, 20 Feb 2017 01:39:52 +0000 (02:39 +0100)
committerRichard Levitte <levitte@openssl.org>
Fri, 23 Feb 2018 06:40:42 +0000 (07:40 +0100)
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2688)

crypto/err/openssl.txt
crypto/store/loader_file.c
crypto/store/store_err.c
include/openssl/storeerr.h

index 756d1fc..e406bec 100644 (file)
@@ -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
index 1fa7fc4..ea1b321 100644 (file)
@@ -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>
@@ -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,
index e0280da..5a8a840 100644 (file)
@@ -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}
index 0eb8e88..33d0ab7 100644 (file)
@@ -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