From f7050588bc76901e0a147c158e64ac3140dc8bfd Mon Sep 17 00:00:00 2001 From: Rich Salz Date: Fri, 30 Apr 2021 12:18:00 -0400 Subject: Add .includedir pragma Also add a negative test, and fix typo's. Reviewed-by: Dmitry Belyavskiy Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/15090) --- CHANGES.md | 4 ++-- crypto/conf/conf_api.c | 1 + crypto/conf/conf_def.c | 31 +++++++++++++++++++-------- doc/man5/config.pod | 11 ++++++++-- include/openssl/conf.h.in | 4 +++- test/recipes/90-test_includes.t | 3 ++- test/recipes/90-test_includes_data/incdir.cnf | 6 ++++++ 7 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 test/recipes/90-test_includes_data/incdir.cnf diff --git a/CHANGES.md b/CHANGES.md index 1d2bfd5d63..7b6c7c5ffb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,8 +23,8 @@ OpenSSL 3.0 ### Changes between 1.1.1 and 3.0 [xx XXX xxxx] - * Add ".pragma abspath:true" to prevent relative file inclusion in - config files. + * Add "abspath" and "includedir" pragma's to config files, to prevent, + or modify relative pathname inclusion. * Rich Salz * diff --git a/crypto/conf/conf_api.c b/crypto/conf/conf_api.c index c2c461d832..41a09c42bc 100644 --- a/crypto/conf/conf_api.c +++ b/crypto/conf/conf_api.c @@ -146,6 +146,7 @@ void _CONF_free_data(CONF *conf) * with */ + OPENSSL_free(conf->includedir); lh_CONF_VALUE_doall(conf->data, value_free_stack_doall); lh_CONF_VALUE_free(conf->data); } diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c index 9561e2338a..ea6b5bf244 100644 --- a/crypto/conf/conf_def.c +++ b/crypto/conf/conf_def.c @@ -192,11 +192,11 @@ static int def_load(CONF *conf, const char *name, long *line) /* Parse a boolean value and fill in *flag. Return 0 on error. */ static int parsebool(const char *pval, int *flag) { - if (strcmp(pval, "on") == 0 - || strcmp(pval, "true") == 0) { + if (strcasecmp(pval, "on") == 0 + || strcasecmp(pval, "true") == 0) { *flag = 1; - } else if (strcmp(pval, "off") == 0 - || strcmp(pval, "false") == 0) { + } else if (strcasecmp(pval, "off") == 0 + || strcasecmp(pval, "false") == 0) { *flag = 0; } else { ERR_raise(ERR_LIB_CONF, CONF_R_INVALID_PRAGMA); @@ -414,6 +414,8 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) * Known pragmas: * * dollarid takes "on", "true or "off", "false" + * abspath takes "on", "true or "off", "false" + * includedir directory prefix */ if (strcmp(p, "dollarid") == 0) { if (!parsebool(pval, &conf->flag_dollarid)) @@ -421,7 +423,13 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) } else if (strcmp(p, "abspath") == 0) { if (!parsebool(pval, &conf->flag_abspath)) goto err; + } else if (strcmp(p, "includedir") == 0) { + if ((conf->includedir = OPENSSL_strdup(pval)) == NULL) { + ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + goto err; + } } + /* * We *ignore* any unknown pragma. */ @@ -433,6 +441,9 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) const char *include_dir = ossl_safe_getenv("OPENSSL_CONF_INCLUDE"); char *include_path = NULL; + if (include_dir == NULL) + include_dir = conf->includedir; + if (*p == '=') { p++; p = eat_ws(conf, p); @@ -441,11 +452,6 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) if (!str_copy(conf, psection, &include, p)) goto err; - if (conf->flag_abspath && !ossl_is_absolute_path(include)) { - ERR_raise(ERR_LIB_CONF, CONF_R_RELATIVE_PATH); - goto err; - } - if (include_dir != NULL && !ossl_is_absolute_path(include)) { size_t newlen = strlen(include_dir) + strlen(include) + 2; @@ -465,6 +471,12 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) include_path = include; } + if (conf->flag_abspath + && !ossl_is_absolute_path(include_path)) { + ERR_raise(ERR_LIB_CONF, CONF_R_RELATIVE_PATH); + goto err; + } + /* get the BIO of the included file */ #ifndef OPENSSL_NO_POSIX_IO next = process_include(include_path, &dirctx, &dirpath); @@ -544,6 +556,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) */ sk_BIO_free(biosk); return 1; + err: BUF_MEM_free(buff); OPENSSL_free(section); diff --git a/doc/man5/config.pod b/doc/man5/config.pod index 6b800b96e1..ad7d7e1e01 100644 --- a/doc/man5/config.pod +++ b/doc/man5/config.pod @@ -48,7 +48,7 @@ while scanning a directory, and that file has an B<.include> directive that specifies a directory, that is also ignored. As a general rule, the B should be an absolute path; this can -be enforced with the B pragma, described below. +be enforced with the B and B pragmas, described below. The environment variable B, if it exists, is prepended to all relative pathnames. If the pathname is still relative, it is interpreted based on the @@ -57,7 +57,7 @@ current working directory. To require all file inclusions to name absolute paths, use the following directive: - .progma [=] abspath:value + .pragma [=] abspath:value The default behavior, where the B is B or B, is to allow relative paths. To require all B<.include> pathnames to be absolute paths, @@ -76,6 +76,13 @@ C followed by the expansion of the variable C. If B is B or B, then C is a single seven-character name nad variable expansions must be specified using braces or parentheses. + .pragma [=] includedir:value + +If a relative pathname is specified in the B<.include> directive, and +the B environment variable doesn't exist, then +the value of the B pragma, if it exists, is prepended to the +pathname. + =head2 Settings A configuration file is divided into a number of I. A section diff --git a/include/openssl/conf.h.in b/include/openssl/conf.h.in index b82a915626..ee7cbb00e4 100644 --- a/include/openssl/conf.h.in +++ b/include/openssl/conf.h.in @@ -119,7 +119,9 @@ struct conf_st { CONF_METHOD *meth; void *meth_data; LHASH_OF(CONF_VALUE) *data; - unsigned int flag_dollarid:1; + int flag_dollarid; + int flag_abspath; + char *includedir; OSSL_LIB_CTX *libctx; }; diff --git a/test/recipes/90-test_includes.t b/test/recipes/90-test_includes.t index add3813a64..13c5c84202 100644 --- a/test/recipes/90-test_includes.t +++ b/test/recipes/90-test_includes.t @@ -13,7 +13,7 @@ plan skip_all => "test_includes doesn't work without posix-io" delete $ENV{OPENSSL_CONF_INCLUDE}; plan tests => # The number of tests being performed - 5 + 6 + ($^O eq "VMS" ? 2 : 0); ok(run(test(["conf_include_test", data_file("includes.cnf")])), "test directory includes"); @@ -27,3 +27,4 @@ if ($^O eq "VMS") { "test file includes, VMS syntax"); } ok(run(test(["conf_include_test", "-f", data_file("includes-broken.cnf")])), "test broken includes"); +ok(run(test(["conf_include_test", "-f", data_file("incdir.cnf")])), "test includedir"); diff --git a/test/recipes/90-test_includes_data/incdir.cnf b/test/recipes/90-test_includes_data/incdir.cnf new file mode 100644 index 0000000000..0d882eddcf --- /dev/null +++ b/test/recipes/90-test_includes_data/incdir.cnf @@ -0,0 +1,6 @@ +# +# Set includedir and expect to fail +# +.pragma includedir:/ + +.include includes.cnf -- cgit v1.2.3