STORE 'file' scheme loader: Add info type expectation
[openssl.git] / crypto / store / loader_file.c
index 99c9350cf80399b94058bc95c6855b39c364c79d..7232b9858a18318462740749ee643d2d53e88ad8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -7,6 +7,7 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include "e_os.h"
 #include <string.h>
 #include <sys/stat.h>
 #include <assert.h>
 #include <openssl/ui.h>
 #include <openssl/x509.h>        /* For the PKCS8 stuff o.O */
 #include "internal/asn1_int.h"
+#include "internal/ctype.h"
 #include "internal/o_dir.h"
 #include "internal/cryptlib.h"
 #include "internal/store_int.h"
 #include "store_locl.h"
 
-#include "e_os.h"
-
 #ifdef _WIN32
 # define stat    _stat
 #endif
@@ -721,6 +721,9 @@ struct ossl_store_loader_ctx_st {
             int last_errno;
         } dir;
     } _;
+
+    /* Expected object type.  May be unspecified */
+    int expected_type;
 };
 
 static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
@@ -783,7 +786,7 @@ 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 (p[0] == '/' && p[2] == ':' && p[3] == '/') {
-            char c = tolower(p[1]);
+            char c = ossl_tolower(p[1]);
 
             if (c >= 'a' && c <= 'z') {
                 p++;
@@ -855,7 +858,7 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
         }
     } else {
         BIO *buff = NULL;
-        char peekbuf[4096];
+        char peekbuf[4096] = { 0, };
 
         if ((buff = BIO_new(BIO_f_buffer())) == NULL
             || (ctx->_.file.file = BIO_new_file(path, "rb")) == NULL) {
@@ -908,6 +911,12 @@ static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args)
     return ret;
 }
 
+static int file_expect(OSSL_STORE_LOADER_CTX *ctx, int expected)
+{
+    ctx->expected_type = expected;
+    return 1;
+}
+
 /* Internal function to decode an already opened PEM file */
 OSSL_STORE_LOADER_CTX *ossl_store_file_attach_pem_bio_int(BIO *bp)
 {
@@ -962,8 +971,8 @@ static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx,
                                     ui_method, ui_data);
 
             if (try_matchcount > 0) {
-                if (matching_handlers)
-                    matching_handlers[*matchcount] = handler;
+
+                matching_handlers[*matchcount] = handler;
 
                 if (handler_ctx)
                     handler->destroy_ctx(&handler_ctx);
@@ -1181,6 +1190,7 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
     } else {
         int matchcount = -1;
 
+     again:
         result = file_load_try_repeat(ctx, ui_method, ui_data);
         if (result != NULL)
             return result;
@@ -1251,6 +1261,13 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
         /* We bail out on ambiguity */
         if (matchcount > 1)
             return NULL;
+
+        if (result != NULL
+            && ctx->expected_type != 0
+            && ctx->expected_type != OSSL_STORE_INFO_get_type(result)) {
+            OSSL_STORE_INFO_free(result);
+            goto again;
+        }
     }
 
     return result;
@@ -1295,6 +1312,7 @@ static OSSL_STORE_LOADER file_loader =
         NULL,
         file_open,
         file_ctrl,
+        file_expect,
         file_load,
         file_eof,
         file_error,