From 2b9bafe607421e394265dcbaad6234b4efee19e8 Mon Sep 17 00:00:00 2001 From: Rich Salz Date: Sat, 28 Mar 2020 12:51:05 -0400 Subject: Rewrite man5/config.pod and related conf code cleanup The manpage is basically rewritten. Use consistent name/value terminology. Use consistent phraseology to refer to section pointers and lists of section pointers. Add more cross-references. Also found a bunch of trivial style things in conf_api.c while investigating how config works. Reviewed-by: Nicola Tuveri Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/11431) --- doc/man5/config.pod | 696 +++++++++++++++++++++++----------------------------- 1 file changed, 301 insertions(+), 395 deletions(-) (limited to 'doc/man5') diff --git a/doc/man5/config.pod b/doc/man5/config.pod index 98b8cd3317..14b80e0b31 100644 --- a/doc/man5/config.pod +++ b/doc/man5/config.pod @@ -6,316 +6,259 @@ config - OpenSSL CONF library configuration files =head1 DESCRIPTION -The OpenSSL CONF library can be used to read configuration files. -It is used for the OpenSSL master configuration file B -and in a few other places like B files and certificate extension -files for the B utility. OpenSSL applications can also use the -CONF library for their own purposes. - -A configuration file is divided into a number of sections. Each section -starts with a line C<[section_name]> and ends when a new section is -started or end of file is reached. A section name can consist of -alphanumeric characters and underscores. The brackets are required. - -The first section of a configuration file is special and is referred -to as the B section. This section is usually unnamed and spans from the -start of file until the first named section. When a name is being looked up -it is first looked up in a named section (if any) and then the -default section. +This page documents the syntax of OpenSSL configuration files, +as parsed by L and related functions. +This format is used by many of the OpenSSL commands, and to +initialize the libraries when used by any application. -The environment is mapped onto a section called B. +The first part describes the general syntax of the configuration +files, and subsequent sections describe the semantics of individual +modules. Other modules are described in L and +L. +The syntax for defining ASN.1 values is described in +L. -Comments can be included by preceding them with the B<#> character - -Other files can be included using the B<.include> directive followed -by a path. If the path points to a directory all files with -names ending with B<.cnf> or B<.conf> are included from the directory. -Recursive inclusion of directories from files in such directory is not -supported. That means the files in the included directory can also contain -B<.include> directives but only inclusion of regular files is supported -there. The inclusion of directories is not supported on systems without -POSIX IO support. - -It is strongly recommended to use absolute paths with the B<.include> -directive. Relative paths are evaluated based on the application current -working directory so unless the configuration file containing the -B<.include> directive is application specific the inclusion will not -work as expected. The environment variable B can also be -used to specify the path to prepend to all .include paths. - -There can be optional B<=> character and whitespace characters between -B<.include> directive and the path which can be useful in cases the -configuration file needs to be loaded by old OpenSSL versions which do -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 more information. - -Each section in a configuration file consists of a number of name and -value pairs of the form B - -The B string can contain any alphanumeric characters as well as -a few punctuation symbols such as B<.> B<,> B<;> and B<_>. - -The B string consists of the string following the B<=> character -until end of line with any leading and trailing white space removed. - -The value string undergoes variable expansion. This can be done by -including the form B<$var> or B<${var}>: this will substitute the value -of the named variable in the current section. It is also possible to -substitute a value from another section using the syntax B<$section::name> -or B<${section::name}>. By using the form B<$ENV::name> environment -variables can be substituted. It is also possible to assign values to -environment variables by using the name B, this will work -if the program looks up environment variables using the B library -instead of calling getenv() directly. The value string must not exceed 64k in -length after variable expansion. Otherwise an error will occur. - -It is possible to escape certain characters by using any kind of quote -or the B<\> character. By making the last character of a line a B<\> -a B string can be spread across multiple lines. In addition -the sequences B<\n>, B<\r>, B<\b> and B<\t> are recognized. +=head1 SYNTAX -All expansion and escape rules as described above that apply to B -also apply to the path of the B<.include> directive. +A configuration file is a series of lines. Blank lines, and whitespace +between the elements of a line, have no significance. A comment starts +with a B<#> character; the rest of the line is ignored. If the B<#> +is the first non-space character in a line, the entire line is ignored. -=head1 PRAGMAS +=head2 Directives -Pragmas can be used to change the behavior of the configuration file -parser, among others. Currently supported pragmas are: +Two directives can be used to control the parsing of configuration files: +B<.include> and B<.pragma>. -=over 4 +For compatibility with older versions of OpenSSL, an equal sign after the +directive will be ignored. Older versions will treat it as an assignment, +so care should be taken if the difference in semantics is important. -=item B<.pragma> B:I - -I can be one of: - -=over 4 +A file can include other files using the include syntax: -=item B<"on"> or B<"true"> + .include [=] pathname -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. +If B is a simple filename, that file is included directly at +that point. Included files can have B<.include> statements that specify +other files. If B is a directory, all files within that directory +that have a C<.cnf> or C<.conf> extension will be included. (This is only +available on systems with POSIX IO support.) Any sub-directories found +inside the B are B. Similarly, if a file is opened +while scanning a directory, and that file has an B<.include> directive +that specifies a directory, that is also ignored. -=item B<"off"> or B<"false"> +As a general rule, the B should be an absolute path. Relative +paths are evaluated based on the current working directory, so unless the +file with the B<.include> directive is application-specific, the inclusion +will not work as expected. The environment variable B, +if it exists, will be prepended to all B<.include> B's. -Turns this pragma off, i.e. C will be interpreted as C -followed by the expansion of the variable C. +In these files, the dollar sign, B<$>, is used to reference a variable, as +described below. On some platforms, however, it is common to treat B<$> +as a regular character in symbol names. Supporting this behavior can be +done with the following directive: -=back - -By default, this pragma is turned off. - -=back - -=head1 OPENSSL LIBRARY CONFIGURATION + .pragma [=] dollarid:value -Applications can automatically configure certain -aspects of OpenSSL using the master OpenSSL configuration file, or optionally -an alternative configuration file. The B utility includes this -functionality: any sub command uses the master OpenSSL configuration file -unless an option is used in the sub command to use an alternative configuration -file. - -To enable library configuration the default section needs to contain an -appropriate line which points to the main configuration section. The default -name is B which is used by the B utility. Other -applications may use an alternative name such as B. -All library configuration lines appear in the default section at the start -of the configuration file. - -The configuration section should consist of a set of name value pairs which -contain specific module configuration information. The B represents -the name of the I. The meaning of the B is -module specific: it may, for example, represent a further configuration -section containing configuration module specific information. E.g.: +Where B is one of the following: - # This must be in the default section - openssl_conf = openssl_init - - [openssl_init] - - oid_section = new_oids - engines = engine_section - providers = provider_section - - [new_oids] - - ... new oids here ... - - [engine_section] - - ... engine stuff here ... +=over 4 - [provider_section] +=item B or B - ... provider stuff here ... +This is the default behavior. For example, C is interpreted as +C followed by the expansion of the variable C. -The features of each configuration module are described below. +=item B or B -=head2 ASN1 Object Configuration Module +This specifies that dollar signs are part of the symbol name and +variable expansions must be specified using braces or parentheses. +For example, C is treated as a single seven-character name. -This module has the name B. The value of this variable points -to a section containing name value pairs of OIDs: the name is the OID short -and long name, the value is the numerical form of the OID. Although some of -the B utility sub commands already have their own ASN1 OBJECT section -functionality not all do. By using the ASN1 OBJECT configuration module -B the B utility sub commands can see the new objects as well -as any compliant applications. For example: - - [new_oids] +=back - some_new_oid = 1.2.3.4 - some_other_oid = 1.2.3.5 +=head2 Settings -It is also possible to set the value to the long name followed -by a comma and the numerical OID form. For example: +A configuration file is divided into a number of I. A section +begins with the section name in square brackets, and ends when a new +section starts, or at the end of the file. The section name can consist +of alphanumeric characters and underscores. +Whitespace between the name and the brackets is removed. - shortName = some object long name, 1.2.3.4 +The first section of a configuration file is special and is referred to +as the B section. This section is usually unnamed and spans from +the start of file until the first named section. When a name is being +looked up, it is first looked up in the current or named section, +and then the default section if necessary. -=head2 Engine Configuration Module +The environment is mapped onto a section called B. -This ENGINE configuration module has the name B. The value of this -variable points to a section containing further ENGINE configuration -information. +Within a section are a series of name/value assignments, described in more +detail below. As a reminder, the square brackets shown in this example +are required, not optional: + + [ section ] + name1 = This is value1 + name2 = Another value + ... + [ newsection ] + name1 = New value1 + name3 = Value 3 + +The B can contain any alphanumeric characters as well as a few +punctuation symbols such as B<.> B<,> B<;> and B<_>. +Whitespace after the name and before the equal sign is ignored. + +If a name is repeated in the same section, then all but the last +value are ignored. In certain circumstances, such as with +Certificate DNs, the same field may occur multiple times. +In order to support this, commands like L ignore any +leading text that is preceeded with a period. For example: + + 1.OU = First OU + 2.OU = Second OU + +The B consists of the string following the B<=> character until end +of line with any leading and trailing white space removed. + +The value string undergoes variable expansion. The text C<$var> or C<${var}> +inserts the value of the named variable from the current section. +To use a value from another section use C<$section::name> +or C<${section::name}>. +By using C<$ENV::name>, the value of the specified environment +variable will be substituted. + +Variables must be defined before their value is referenced, otherwise +an error is flagged and the file will not load. +This can be worked around by specifying a default value in the B +section before the variable is used. + +Any name/value settings in an B section are available +to the configuration file, but are not propagated to the environment. + +It is an error if the value ends up longer than 64k. + +It is possible to escape certain characters by using a single B<'> or +double B<"> quote around the value, or using a backslash B<\> before the +character, +By making the last character of a line a B<\> +a B string can be spread across multiple lines. In addition +the sequences B<\n>, B<\r>, B<\b> and B<\t> are recognized. -The section pointed to by B is a table of engine names (though see -B below) and further sections containing configuration information -specific to each ENGINE. +The expansion and escape rules as described above that apply to B +also apply to the pathname of the B<.include> directive. -Each ENGINE specific section is used to set default algorithms, load -dynamic, perform initialization and send ctrls. The actual operation performed -depends on the I name which is the name of the name value pair. The -currently supported commands are listed below. +=head1 OPENSSL LIBRARY CONFIGURATION -For example: +The sections below use the informal term I to refer to a part +of the OpenSSL functionality. This is not the same as the formal term +I, for example. - [engine_section] +The OpenSSL configuration looks up the value of B +in the default section and takes that as the name of a section that specifies +how to configure any modules in the library. It is not an error to leave +any module in its default configuration. An application can specify a +different name by calling CONF_modules_load_file(), for example, directly. - # Configure ENGINE named "foo" - foo = foo_section - # Configure ENGINE named "bar" - bar = bar_section + # This must be in the default section + openssl_conf = openssl_init - [foo_section] - ... foo ENGINE specific commands ... + [openssl_init] + oid_section = oids + providers = providers + alg_section = evp_properties + ssl_conf = ssl_configuration + engines = engines - [bar_section] - ... "bar" ENGINE specific commands ... + [oids] + ... new oids here ... -The command B is used to give the ENGINE name. If used this -command must be first. For example: + [providers] + ... provider stuff here ... - [engine_section] - # This would normally handle an ENGINE named "foo" - foo = foo_section + [evp_properties] + ... EVP properties here ... - [foo_section] - # Override default name and use "myfoo" instead. - engine_id = myfoo + [ssl_configuration] + ... SSL/TLS configuration properties here ... -The command B loads and adds an ENGINE from the given path. It -is equivalent to sending the ctrls B with the path argument followed -by B with value 2 and B to the dynamic ENGINE. If this is -not the required behaviour then alternative ctrls can be sent directly -to the dynamic ENGINE using ctrl commands. + [engines] + ... engine properties here ... -The command B determines whether to initialize the ENGINE. If the value -is B<0> the ENGINE will not be initialized, if B<1> and attempt it made to -initialized the ENGINE immediately. If the B command is not present -then an attempt will be made to initialize the ENGINE after all commands in -its section have been processed. +The semantics of each module are described below. The phrase "in the +initialization section" refers to the section identified by the +B or other name (given as B in the +example above). The examples below assume the configuration above +is used to specify the individual sections. -The command B sets the default algorithms an ENGINE will -supply using the functions ENGINE_set_default_string(). +=head2 ASN.1 Object Identifier Configuration -If the name matches none of the above command names it is assumed to be a -ctrl command which is sent to the ENGINE. The value of the command is the -argument to the ctrl command. If the value is the string B then no -value is sent to the command. +The name B in the initialization section names the section +containing name/value pairs of OID's. +The name is the short name; the value is an optional long name followed +by a comma, and the numeric value. +While some OpenSSL commands have their own section for specifying OID's, +this section makes them avilable to all commands and applications. -For example: + [oids] + shortName = a very long OID name, 1.2.3.4 + newoid1 = 1.2.3.4.1 + some_other_oid = 1.2.3.5 +If a full configuration with the above fragment is in the file +F, then the following command line: - [engine_section] + OPENSSL_CONF=example.cnf openssl asn1parse -genstr OID:1.2.3.4.1 - # Configure ENGINE named "foo" - foo = foo_section +will output: - [foo_section] - # Load engine from DSO - dynamic_path = /some/path/fooengine.so - # A foo specific ctrl. - some_ctrl = some_value - # Another ctrl that doesn't take a value. - other_ctrl = EMPTY - # Supply all default algorithms - default_algorithms = ALL + 0:d=0 hl=2 l= 4 prim: OBJECT :newoid1 -=head2 Provider Configuration Module +showing that the OID "newoid1" has been added as "1.2.3.4.1". -This provider configuration module has the name B. The -value of this variable points to a section containing further provider -configuration information. +=head2 Provider Configuration -The section pointed to by B is a table of provider names -(though see B below) and further sections containing -configuration information specific to each provider module. +The name B in the initialization section names the section +containing cryptographic provider configuration. The name/value assignments +in this section each name a provider, and point to the configuration section +for that provider. The provider-specific section is used to specify how +to load the module, activate it, and set other parameters. -Each provider specific section is used to load its module, perform -activation and set parameters to pass to the provider on demand. The -actual operation performed depends on the name of the name value pair. -The currently supported commands are listed below. +Within a provider section, the following names have meaning: -For example: +=over 4 - [provider_section] +=item B - # Configure provider named "foo" - foo = foo_section - # Configure provider named "bar" - bar = bar_section +This is used to specify an alternate name, overriding the default name +specified in the list of providers. For example: - [foo_section] - ... "foo" provider specific parameters ... + [providers] + foo = foo_provider - [bar_section] - ... "bar" provider specific parameters ... + [foo_provider] + identity = my_fips_module -The command B is used to give the provider name. For example: +=item B - [provider_section] - # This would normally handle a provider named "foo" - foo = foo_section +Specifies the pathname of the module (typically a shared library) to load. - [foo_section] - # Override default name and use "myfoo" instead. - identity = myfoo +=item B -The parameter B loads and adds a provider module from the -given module path. That path may be a simple filename, a relative -path or an absolute path. +If present, the module is activated. The value assigned to this name is not +significant. -The parameter B determines whether to activate the -provider. The value has no importance, the presence of the parameter -is enough for activation to take place. +=back All parameters in the section as well as sub-sections are made available to the provider. -=head2 EVP Configuration Module +=head2 EVP Configuration -This module has the name B which points to a section containing -algorithm commands. +The name B in the initialization section names the section +containing algorithmic properties when using the B API. -The supported algorithm commands are: +Within the algorithm properties section, the following names have meaning: =over 4 @@ -329,197 +272,157 @@ string for EVP_set_default_properties(). The value is a boolean that can be B or B. If the value is B, this is exactly equivalent to: - default_properties = fips=yes + default_properties = fips=yes -If the value is B, nothing happens. +If the value is B, nothing happens. Using this name is deprecated, and +if used, it must be the only name in the section. =back -These two commands should not be used together, as there is no control -over how they affect each other. -The use of B is strongly discouraged and is only present -for backward compatibility with earlier OpenSSL FIPS modules. +=head2 SSL Configuration -=head2 SSL Configuration Module +The name B in the initialization section names the section +containing the list of SSL/TLS configurations. +As with the providers, each name in this section identifies a +section with the configuration for that name. For example: -This module has the name B which points to a section containing -SSL configurations. + [ssl_configuration] + server = server_tls_config + client = client_tls_config + system_default = tls_system_default -Each line in the SSL configuration section contains the name of the -configuration and the section containing it. + [server_tls_config] + ... configuration for SSL/TLS servers ... -Each configuration section consists of command value pairs for B. -Each pair will be passed to a B or B structure if it calls -SSL_CTX_config() or SSL_config() with the appropriate configuration name. + [client_tls_config] + ... configuration for SSL/TLS clients ... -Note: any characters before an initial dot in the configuration section are -ignored so the same command can be used multiple times. +The configuration name B has a special meaning. If it +exists, it is applied whenever an B object is created. For example, +to impose a system-wide minimum on protocol version: -For example: + [tls_system_default] + MinProtocol = TLSv1.2 + +Each configuration section consists of name/value pairs that are parsed +by B, which will be called by SSL_CTX_config() or +SSL_config(), appropriately. Note that any characters before an initial +dot in the configuration section are ignored, so that the same command can +be used multiple times. This probably is most useful for loading different +key types, as shown here: - ssl_conf = ssl_sect + [server_tls_config] + RSA.Certificate = server-rsa.pem + ECDSA.Certificate = server-ecdsa.pem - [ssl_sect] +=head2 Engine Configuration - server = server_section +The name B in the initialization section names the section +containing the list of ENGINE configurations. +As with the providers, each name in this section identifies an engine +with the configuration for that engine. +The engine-specific section is used to specify how to load the engine, +activate it, and set other parameters. - [server_section] +Within an engine section, the following names have meaning: - RSA.Certificate = server-rsa.pem - ECDSA.Certificate = server-ecdsa.pem - Ciphers = ALL:!RC4 +=over 4 + +=item B -The system default configuration with name B if present will -be applied during any creation of the B structure. +This is used to specify an alternate name, overriding the default name +specified in the list of engines. If present, it must be first. +For example: -Example of a configuration with the system default: + [engines] + foo = foo_engine - ssl_conf = ssl_sect + [foo_engine] + engine_id = myfoo - [ssl_sect] +=item B - system_default = system_default_sect +This loads and adds an ENGINE from the given path. It is equivalent to +sending the ctrls B with the path argument followed by B +with value B<2> and B to the dynamic ENGINE. If this is not the +required behaviour then alternative ctrls can be sent directly to the +dynamic ENGINE using ctrl commands. - [system_default_sect] +=item B - MinProtocol = TLSv1.2 +This specifies whether to initialize the ENGINE. If the value is B<0> the +ENGINE will not be initialized, if the value is B<1> an attempt is made +to initialize +the ENGINE immediately. If the B command is not present then an +attempt will be made to initialize the ENGINE after all commands in its +section have been processed. +=item B -=head1 NOTES +This sets the default algorithms an ENGINE will supply using the function +ENGINE_set_default_string(). -If a configuration file attempts to expand a variable that doesn't exist -then an error is flagged and the file will not load. This can happen -if an attempt is made to expand an environment variable that doesn't -exist. For example in a previous version of OpenSSL the default OpenSSL -master configuration file used the value of B which may not be -defined on non Unix systems and would cause an error. +=back -This can be worked around by including a B section to provide -a default value: then if the environment lookup fails the default value -will be used instead. For this to work properly the default value must -be defined earlier in the configuration file than the expansion. See -the B section for an example of how to do this. +All other names are taken to be the name of a ctrl command that is +sent to the ENGINE, and the value is the argument passed with the command. +The special value B means no value is sent with the command. +For example: -If the same variable exists in the same section then all but the last -value will be silently ignored. In certain circumstances such as with -DNs the same field may occur multiple times. This is usually worked -around by ignoring any characters before an initial B<.> e.g. + [engines] + foo = foo_engine - 1.OU="My first OU" - 2.OU="My Second OU" + [foo_engine] + dynamic_path = /some/path/fooengine.so + some_ctrl = some_value + default_algorithms = ALL + other_ctrl = EMPTY =head1 EXAMPLES -Here is a sample configuration file using some of the features -mentioned above. +This example shows how to use quoting and escaping. # This is the default section. - - HOME=/temp - configdir=$ENV::HOME/config + HOME = /temp + configdir = $ENV::HOME/config [ section_one ] - - # We are now in section one. - # Quotes permit leading and trailing whitespace any = " any variable name " - other = A string that can \ cover several lines \ by including \\ characters - message = Hello World\n [ section_two ] - greeting = $section_one::message -This next example shows how to expand environment variables safely. - -Suppose you want a variable called B to refer to a -temporary filename. The directory it is placed in can determined by -the B or B environment variables but they may not be -set to any value at all. If you just include the environment variable -names and the variable doesn't exist then this will cause an error when -an attempt is made to load the configuration file. By making use of the -default section both values can be looked up with B taking -priority and B used if neither is defined: - - TMP=/tmp - # The above value is used if TMP isn't in the environment - TEMP=$ENV::TMP - # The above value is used if TEMP isn't in the environment - tmpfile=${ENV::TEMP}/tmp.filename - -Simple OpenSSL library configuration example to enter FIPS mode: - - # Default appname: should match "appname" parameter (if any) - # supplied to CONF_modules_load_file_with_libctx et al. - openssl_conf = openssl_conf_section - - [openssl_conf_section] - # Configuration module list - alg_section = evp_sect - - [evp_sect] - # Set to "yes" to enter FIPS mode if supported - fips_mode = yes - -Note: in the above example you will get an error in non FIPS capable versions -of OpenSSL. - -Simple OpenSSL library configuration to make TLS 1.3 the system-default -minimum TLS version: - - # Toplevel section for openssl (including libssl) - openssl_conf = default_conf_section +This example shows how to expand environment variables safely. +In this example, the variable B is intended to refer +to a temporary file, and the environment variable B or +B, if present, specify the directory where the file +should be put. +Since the default section is checked if a variable does not +exist, it is possible to set B to default to F, and +B to default to B. - [default_conf_section] - # We only specify configuration for the "ssl module" - ssl_conf = ssl_section + # These two lines must be in the default section. + TMP = /tmp + TEMP = $ENV::TMP - [ssl_section] - system_default = system_default_section + # This can be used anywhere + tmpfile = ${ENV::TEMP}/tmp.filename - [system_default_section] - MinProtocol = TLSv1.3 +This example shows how to enforce FIPS mode for the application +F. -More complex OpenSSL library configuration. Add OID and don't enter FIPS mode: + sample = fips_config - # Default appname: should match "appname" parameter (if any) - # supplied to CONF_modules_load_file_with_libctx et al. - openssl_conf = openssl_conf_section + [fips_config] + alg_section = evp_properties - [openssl_conf_section] - # Configuration module list - alg_section = evp_sect - oid_section = new_oids - - [evp_sect] - # This will have no effect as FIPS mode is off by default. - # Set to "yes" to enter FIPS mode, if supported - fips_mode = no - - [new_oids] - # New OID, just short name - newoid1 = 1.2.3.4.1 - # New OID shortname and long name - newoid2 = New OID 2 long name, 1.2.3.4.2 - -The above examples can be used with any application supporting library -configuration if "openssl_conf" is modified to match the appropriate "appname". - -For example if the second sample file above is saved to "example.cnf" then -the command line: - - OPENSSL_CONF=example.cnf openssl asn1parse -genstr OID:1.2.3.4.1 - -will output: - - 0:d=0 hl=2 l= 4 prim: OBJECT :newoid1 - -showing that the OID "newoid1" has been added as "1.2.3.4.1". + [evp_properties] + default_properties = "fips=yes" =head1 ENVIRONMENT @@ -542,22 +445,20 @@ Ignored in set-user-ID and set-group-ID programs. =item B -The optional path to prepend to all .include paths. +The optional path to prepend to all B<.include> paths. =back =head1 BUGS -Currently there is no way to include characters using the octal B<\nnn> -form. Strings are all null terminated so nulls cannot form part of -the value. +There is no way to include characters using the octal B<\nnn> form. Strings +are all null terminated so nulls cannot form part of the value. The escaping isn't quite right: if you want to use sequences like B<\n> you can't use any quote escaping on the same line. -Files are loaded in a single pass. This means that an variable expansion -will only work if the variables referenced are defined earlier in the -file. +The limit that only one directory can be opened and read at a time +can be considered a bug and should be fixed. =head1 HISTORY @@ -572,7 +473,12 @@ configuration files using that syntax will have to be modified. =head1 SEE ALSO -L, L, L, L +L, L, L, +L, +L, +L, +L, and +L. =head1 COPYRIGHT -- cgit v1.2.3