OSSL_STORE "file" scheme loader: check for absolute path in URI later
authorRichard Levitte <levitte@openssl.org>
Wed, 12 Jul 2017 10:44:24 +0000 (12:44 +0200)
committerRichard Levitte <levitte@openssl.org>
Sat, 15 Jul 2017 16:53:07 +0000 (18:53 +0200)
If we have a local file with a name starting with 'file:', we don't
want to check if the part after 'file:' is absolute.  Instead, mark
each possibility for absolute check if needed, and perform the
absolute check later on, when checking each actual path.

Reviewed-by: Andy Polyakov <appro@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3907)

crypto/store/loader_file.c

index 0a9191d..31ca2c6 100644 (file)
@@ -744,13 +744,18 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
 {
     OSSL_STORE_LOADER_CTX *ctx = NULL;
     struct stat st;
-    const char *paths[2], *path;
-    size_t paths_n = 0, i;
+    struct {
+        const char *path;
+        unsigned int check_absolute:1;
+    } path_data[2];
+    size_t path_data_n = 0, i;
+    const char *path;
 
     /*
      * First step, just take the URI as is.
      */
-    paths[paths_n++] = uri;
+    path_data[path_data_n].check_absolute = 0;
+    path_data[path_data_n++].path = uri;
 
     /*
      * Second step, if the URI appears to start with the 'file' scheme,
@@ -762,7 +767,7 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
         const char *p = &uri[5];
 
         if (strncmp(&uri[5], "//", 2) == 0) {
-            paths_n--;           /* Invalidate using the full URI */
+            path_data_n--;           /* Invalidate using the full URI */
             if (strncasecmp(&uri[7], "localhost/", 10) == 0) {
                 p = &uri[16];
             } else if (uri[7] == '/') {
@@ -774,31 +779,36 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
             }
         }
 
+        path_data[path_data_n].check_absolute = 1;
+#ifdef _WIN32
+        /* Windows file: URIs with a drive letter start with a / */
+        if (p[0] == '/' && p[2] == ':' && p[3] == '/') {
+            p++;
+            /* We know it's absolute, so no need to check */
+            path_data[path_data_n].check_absolute = 0;
+        }
+#endif
+        path_data[path_data_n++].path = p;
+    }
+
+
+    for (i = 0, path = NULL; path == NULL && i < path_data_n; i++) {
         /*
          * If the scheme "file" was an explicit part of the URI, the path must
          * be absolute.  So says RFC 8089
          */
-        if (p[0] != '/') {
+        if (path_data[i].check_absolute && path_data[i].path[0] != '/') {
             OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN,
                           OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE);
+            ERR_add_error_data(1, path_data[i].path);
             return NULL;
         }
 
-#ifdef _WIN32
-        /* Windows file: URIs with a drive letter start with a / */
-        if (p[0] == '/' && p[2] == ':' && p[3] == '/')
-            p++;
-#endif
-        paths[paths_n++] = p;
-    }
-
-
-    for (i = 0, path = NULL; path == NULL && i < paths_n; i++) {
-        if (stat(paths[i], &st) < 0) {
+        if (stat(path_data[i].path, &st) < 0) {
             SYSerr(SYS_F_STAT, errno);
-            ERR_add_error_data(1, paths[i]);
+            ERR_add_error_data(1, path_data[i].path);
         } else {
-            path = paths[i];
+            path = path_data[i].path;
         }
     }
     if (path == NULL) {