CORE: query for operations only once per provider (unless no_store is true)
[openssl.git] / crypto / conf / conf_def.c
index a8581d7320ea72341f774545e8cc5d4b59445abc..1d34519d1aa5f29615cab735191551477a01093c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -27,6 +27,8 @@
 # endif
 #endif
 
+DEFINE_STACK_OF(BIO)
+
 #ifndef S_ISDIR
 # define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
 #endif
@@ -121,9 +123,9 @@ static int def_init_default(CONF *conf)
     if (conf == NULL)
         return 0;
 
+    memset(conf, 0, sizeof(*conf));
     conf->meth = &default_method;
     conf->meth_data = (void *)CONF_type_default;
-    conf->data = NULL;
 
     return 1;
 }
@@ -134,9 +136,9 @@ static int def_init_WIN32(CONF *conf)
     if (conf == NULL)
         return 0;
 
+    memset(conf, 0, sizeof(*conf));
     conf->meth = &WIN32_method;
     conf->meth_data = (void *)CONF_type_win32;
-    conf->data = NULL;
 
     return 1;
 }
@@ -354,7 +356,49 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
                 psection = section;
             }
             p = eat_ws(conf, end);
-            if (strncmp(pname, ".include", 8) == 0
+            if (strncmp(pname, ".pragma", 7) == 0
+                && (p != pname + 7 || *p == '=')) {
+                char *pval;
+
+                if (*p == '=') {
+                    p++;
+                    p = eat_ws(conf, p);
+                }
+                trim_ws(conf, p);
+
+                /* Pragma values take the form keyword:value */
+                pval = strchr(p, ':');
+                if (pval == NULL || pval == p || pval[1] == '\0') {
+                    CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_INVALID_PRAGMA);
+                    goto err;
+                }
+
+                *pval++ = '\0';
+                trim_ws(conf, p);
+                pval = eat_ws(conf, pval);
+
+                /*
+                 * Known pragmas:
+                 *
+                 * dollarid     takes "on", "true or "off", "false"
+                 */
+                if (strcmp(p, "dollarid") == 0) {
+                    if (strcmp(pval, "on") == 0
+                        || strcmp(pval, "true") == 0) {
+                        conf->flag_dollarid = 1;
+                    } else if (strcmp(pval, "off") == 0
+                               || strcmp(pval, "false") == 0) {
+                        conf->flag_dollarid = 0;
+                    } else {
+                        CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_INVALID_PRAGMA);
+                        goto err;
+                    }
+                }
+                /*
+                 * We *ignore* any unknown pragma.
+                 */
+                continue;
+            } else if (strncmp(pname, ".include", 8) == 0
                 && (p != pname + 8 || *p == '=')) {
                 char *include = NULL;
                 BIO *next;
@@ -376,6 +420,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
                     OPENSSL_strlcpy(include_path, include_dir, newlen);
                     OPENSSL_strlcat(include_path, "/", newlen);
                     OPENSSL_strlcat(include_path, include, newlen);
+                    OPENSSL_free(include);
                 } else {
                     include_path = include;
                 }
@@ -385,15 +430,11 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
                 next = process_include(include_path, &dirctx, &dirpath);
                 if (include_path != dirpath) {
                     /* dirpath will contain include in case of a directory */
-                    OPENSSL_free(include);
-                    if (include_path != include)
-                        OPENSSL_free(include_path);
+                    OPENSSL_free(include_path);
                 }
 #else
                 next = BIO_new_file(include_path, "r");
-                OPENSSL_free(include);
-                if (include_path != include)
-                    OPENSSL_free(include_path);
+                OPENSSL_free(include_path);
 #endif
 
                 if (next != NULL) {
@@ -414,6 +455,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
                 continue;
             } else if (*p != '=') {
                 CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN);
+                ERR_add_error_data(2, "HERE-->", p);
                 goto err;
             }
             *end = '\0';
@@ -590,7 +632,10 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
             buf->data[to++] = v;
         } else if (IS_EOF(conf, *from))
             break;
-        else if (*from == '$') {
+        else if (*from == '$'
+                 && (!conf->flag_dollarid
+                     || from[1] == '{'
+                     || from[1] == '(')) {
             size_t newsize;
 
             /* try to expand it */
@@ -607,7 +652,8 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
                 s++;
             cp = section;
             e = np = s;
-            while (IS_ALNUM(conf, *e))
+            while (IS_ALNUM(conf, *e)
+                   || (conf->flag_dollarid && IS_DOLLAR(conf, *e)))
                 e++;
             if ((e[0] == ':') && (e[1] == ':')) {
                 cp = np;
@@ -616,7 +662,8 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
                 *rrp = '\0';
                 e += 2;
                 np = e;
-                while (IS_ALNUM(conf, *e))
+                while (IS_ALNUM(conf, *e)
+                       || (conf->flag_dollarid && IS_DOLLAR(conf, *e)))
                     e++;
             }
             r = *e;
@@ -729,7 +776,9 @@ static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx,
 static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx)
 {
     const char *filename;
+    size_t pathlen;
 
+    pathlen = strlen(path);
     while ((filename = OPENSSL_DIR_read(dirctx, path)) != NULL) {
         size_t namelen;
 
@@ -742,7 +791,7 @@ static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx)
             char *newpath;
             BIO *bio;
 
-            newlen = strlen(path) + namelen + 2;
+            newlen = pathlen + namelen + 2;
             newpath = OPENSSL_zalloc(newlen);
             if (newpath == NULL) {
                 CONFerr(CONF_F_GET_NEXT_FILE, ERR_R_MALLOC_FAILURE);
@@ -753,14 +802,11 @@ static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx)
              * If the given path isn't clear VMS syntax,
              * we treat it as on Unix.
              */
-            {
-                size_t pathlen = strlen(path);
-
-                if (path[pathlen - 1] == ']' || path[pathlen - 1] == '>'
-                    || path[pathlen - 1] == ':') {
-                    /* Clear VMS directory syntax, just copy as is */
-                    OPENSSL_strlcpy(newpath, path, newlen);
-                }
+            if (path[pathlen - 1] == ']'
+                || path[pathlen - 1] == '>'
+                || path[pathlen - 1] == ':') {
+                /* Clear VMS directory syntax, just copy as is */
+                OPENSSL_strlcpy(newpath, path, newlen);
             }
 #endif
             if (newpath[0] == '\0') {
@@ -833,7 +879,8 @@ static char *eat_alpha_numeric(CONF *conf, char *p)
             p = scan_esc(conf, p);
             continue;
         }
-        if (!IS_ALNUM_PUNCT(conf, *p))
+        if (!(IS_ALNUM_PUNCT(conf, *p)
+              || (conf->flag_dollarid && IS_DOLLAR(conf, *p))))
             return p;
         p++;
     }