From: Richard Levitte Date: Mon, 6 May 2019 08:50:35 +0000 (+0200) Subject: Add a .pragma directive for configuration files X-Git-Tag: openssl-3.0.0-alpha1~974 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=0255c1742a5a8186802fdef19b4f1c8c701a27bc;p=oweals%2Fopenssl.git Add a .pragma directive for configuration files Currently added pragma: .pragma dollarid:on This allows dollar signs to be a keyword character unless it's followed by a opening brace or parenthesis. Fixes #8207 Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/8882) --- diff --git a/CHANGES b/CHANGES index f500f2f4cf..fd11739193 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,18 @@ Changes between 1.1.1 and 3.0.0 [xx XXX xxxx] + *) Added a .pragma directive to the syntax of configuration files, to + allow varying behavior in a supported and predictable manner. + Currently added pragma: + + .pragma dollarid:on + + This allows dollar signs to be a keyword character unless it's + followed by a opening brace or parenthesis. This is useful for + platforms where dollar signs are commonly used in names, such as + volume names and system directory names on VMS. + [Richard Levitte] + *) Added functionality to create an EVP_PKEY from user data. This is effectively the same as creating a RSA, DH or DSA object and then assigning them to an EVP_PKEY, but directly using algorithm diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c index 91ae658f65..811f8809d3 100644 --- a/crypto/conf/conf_def.c +++ b/crypto/conf/conf_def.c @@ -354,7 +354,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; @@ -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; @@ -832,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++; } diff --git a/crypto/conf/conf_def.h b/crypto/conf/conf_def.h index 160611788f..1a3557d954 100644 --- a/crypto/conf/conf_def.h +++ b/crypto/conf/conf_def.h @@ -20,6 +20,7 @@ #define CONF_DQUOTE 1024 #define CONF_COMMENT 128 #define CONF_FCOMMENT 2048 +#define CONF_DOLLAR 4096 #define CONF_EOF 8 #define CONF_ALPHA (CONF_UPPER|CONF_LOWER) #define CONF_ALNUM (CONF_ALPHA|CONF_NUMBER|CONF_UNDER) @@ -36,13 +37,14 @@ #define IS_ALNUM_PUNCT(conf,c) is_keytype(conf, c, CONF_ALNUM_PUNCT) #define IS_QUOTE(conf,c) is_keytype(conf, c, CONF_QUOTE) #define IS_DQUOTE(conf,c) is_keytype(conf, c, CONF_DQUOTE) +#define IS_DOLLAR(conf,c) is_keytype(conf, c, CONF_DOLLAR) static const unsigned short CONF_type_default[128] = { 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0010, 0x0010, 0x0000, 0x0000, 0x0010, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0010, 0x0200, 0x0040, 0x0080, 0x0000, 0x0200, 0x0200, 0x0040, + 0x0010, 0x0200, 0x0040, 0x0080, 0x1000, 0x0200, 0x0200, 0x0040, 0x0000, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0200, 0x0000, 0x0000, 0x0000, 0x0200, @@ -62,7 +64,7 @@ static const unsigned short CONF_type_win32[128] = { 0x0000, 0x0010, 0x0010, 0x0000, 0x0000, 0x0010, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0010, 0x0200, 0x0400, 0x0000, 0x0000, 0x0200, 0x0200, 0x0000, + 0x0010, 0x0200, 0x0400, 0x0000, 0x1000, 0x0200, 0x0200, 0x0000, 0x0000, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0A00, 0x0000, 0x0000, 0x0000, 0x0200, diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c index 96d2cd99f5..daf2320a19 100644 --- a/crypto/conf/conf_err.c +++ b/crypto/conf/conf_err.c @@ -15,8 +15,11 @@ static const ERR_STRING_DATA CONF_str_reasons[] = { {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_ERROR_LOADING_DSO), "error loading dso"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_INVALID_PRAGMA), "invalid pragma"}, {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_LIST_CANNOT_BE_NULL), "list cannot be null"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MANDATORY_BRACES_IN_VARIABLE_EXPANSION), + "mandatory braces in variable expansion"}, {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_CLOSE_SQUARE_BRACKET), "missing close square bracket"}, {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_MISSING_EQUAL_SIGN), diff --git a/crypto/conf/keysets.pl b/crypto/conf/keysets.pl index 3c6eecd9ca..b0e2249364 100644 --- a/crypto/conf/keysets.pl +++ b/crypto/conf/keysets.pl @@ -20,6 +20,7 @@ my $QUOTE = 0x0040; my $DQUOTE = 0x0400; my $COMMENT = 0x0080; my $FCOMMENT = 0x0800; +my $DOLLAR = 0x1000; my $EOF = 0x0008; my @V_def; my @V_w32; @@ -38,6 +39,7 @@ foreach (0 .. 127) { $v |= $ESC if $c =~ /\\/; $v |= $QUOTE if $c =~ /['`"]/; # for emacs: "`' $v |= $COMMENT if $c =~ /\#/; + $v |= $DOLLAR if $c eq '$'; $v |= $EOF if $c =~ /\0/; push(@V_def, $v); @@ -50,6 +52,7 @@ foreach (0 .. 127) { $v |= $WS if $c =~ /[ \t\r\n]/; $v |= $DQUOTE if $c =~ /["]/; # for emacs: " $v |= $FCOMMENT if $c =~ /;/; + $v |= $DOLLAR if $c eq '$'; $v |= $EOF if $c =~ /\0/; push(@V_w32, $v); } @@ -80,6 +83,7 @@ print <<"EOF"; #define CONF_DQUOTE $DQUOTE #define CONF_COMMENT $COMMENT #define CONF_FCOMMENT $FCOMMENT +#define CONF_DOLLAR $DOLLAR #define CONF_EOF $EOF #define CONF_ALPHA (CONF_UPPER|CONF_LOWER) #define CONF_ALNUM (CONF_ALPHA|CONF_NUMBER|CONF_UNDER) @@ -96,6 +100,7 @@ print <<"EOF"; #define IS_ALNUM_PUNCT(conf,c) is_keytype(conf, c, CONF_ALNUM_PUNCT) #define IS_QUOTE(conf,c) is_keytype(conf, c, CONF_QUOTE) #define IS_DQUOTE(conf,c) is_keytype(conf, c, CONF_DQUOTE) +#define IS_DOLLAR(conf,c) is_keytype(conf, c, CONF_DOLLAR) EOF diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index abbf232133..f3fb8a55d9 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2163,7 +2163,10 @@ COMP_R_ZLIB_DEFLATE_ERROR:99:zlib deflate error COMP_R_ZLIB_INFLATE_ERROR:100:zlib inflate error COMP_R_ZLIB_NOT_SUPPORTED:101:zlib not supported CONF_R_ERROR_LOADING_DSO:110:error loading dso +CONF_R_INVALID_PRAGMA:122:invalid pragma CONF_R_LIST_CANNOT_BE_NULL:115:list cannot be null +CONF_R_MANDATORY_BRACES_IN_VARIABLE_EXPANSION:123:\ + mandatory braces in variable expansion CONF_R_MISSING_CLOSE_SQUARE_BRACKET:100:missing close square bracket CONF_R_MISSING_EQUAL_SIGN:101:missing equal sign CONF_R_MISSING_INIT_FUNCTION:112:missing init function diff --git a/doc/man5/config.pod b/doc/man5/config.pod index e727a2e22d..4b8465594a 100644 --- a/doc/man5/config.pod +++ b/doc/man5/config.pod @@ -50,6 +50,9 @@ not support the B<.include> syntax. They would bail out with error if the B<=> character is not present but with it they just ignore the include. +Pragmas can be specified with the B<.pragma> directive. +See L for mor information. + Each section in a configuration file consists of a number of name and value pairs of the form B @@ -78,6 +81,40 @@ the sequences B<\n>, B<\r>, B<\b> and B<\t> are recognized. All expansion and escape rules as described above that apply to B also apply to the path of the B<.include> directive. +=head1 PRAGMAS + +Pragmas can be used to change the behavior of the configuration file +parser, among others. Currently supported pragmas are: + +=over 4 + +=item B<.pragma> B:I + +I can be one of: + +=over 4 + +=item B<"on"> or B<"true"> + +this signifies that dollar signs are considered an identity character +from this point on and that variable expansion requires the use of +braces or parentheses. In other words, C will be considered +a name instead of C followed by the expansion of the variable +C. +This is suitable for platforms where the dollar sign is commonly used +as part of names. + +=item B<"off"> or B<"false"> + +Turns this pragma off, i.e. C will be interpreted as C +followed by the expansion of the variable C. + +=back + +By default, this pragma is turned off. + +=back + =head1 OPENSSL LIBRARY CONFIGURATION Applications can automatically configure certain diff --git a/include/openssl/conf.h b/include/openssl/conf.h index 39bfe570c8..438361e7a9 100644 --- a/include/openssl/conf.h +++ b/include/openssl/conf.h @@ -110,6 +110,7 @@ struct conf_st { CONF_METHOD *meth; void *meth_data; LHASH_OF(CONF_VALUE) *data; + unsigned int flag_dollarid:1; }; CONF *NCONF_new(CONF_METHOD *meth); diff --git a/include/openssl/conferr.h b/include/openssl/conferr.h index eb41737fd7..b3d2596f68 100644 --- a/include/openssl/conferr.h +++ b/include/openssl/conferr.h @@ -59,7 +59,9 @@ int ERR_load_CONF_strings(void); * CONF reason codes. */ # define CONF_R_ERROR_LOADING_DSO 110 +# define CONF_R_INVALID_PRAGMA 122 # define CONF_R_LIST_CANNOT_BE_NULL 115 +# define CONF_R_MANDATORY_BRACES_IN_VARIABLE_EXPANSION 123 # define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 100 # define CONF_R_MISSING_EQUAL_SIGN 101 # define CONF_R_MISSING_INIT_FUNCTION 112