Add support for .include directive in config files
Either files or directories of *.cnf or *.conf files can be included. Recursive inclusion of directories is not supported. Reviewed-by: Andy Polyakov <appro@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5351)
This commit is contained in:
parent
aa2ed504ea
commit
b524b808a1
15 changed files with 512 additions and 15 deletions
|
@ -3,6 +3,10 @@
|
|||
# This is mostly being used for generation of certificate requests.
|
||||
#
|
||||
|
||||
# Note that you can include other files from the main configuration
|
||||
# file using the .include directive.
|
||||
#.include filename
|
||||
|
||||
# This definition stops the following lines choking if HOME isn't
|
||||
# defined.
|
||||
HOME = .
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
# This is mostly being used for generation of certificate requests.
|
||||
#
|
||||
|
||||
# Note that you can include other files from the main configuration
|
||||
# file using the .include directive.
|
||||
#.include filename
|
||||
|
||||
# This definition stops the following lines choking if HOME isn't
|
||||
# defined.
|
||||
HOME = .
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
|
@ -12,12 +12,20 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/o_dir.h"
|
||||
#include <openssl/lhash.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/conf_api.h>
|
||||
#include "conf_def.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/err.h>
|
||||
#ifndef OPENSSL_NO_POSIX_IO
|
||||
# include <sys/stat.h>
|
||||
# ifdef _WIN32
|
||||
# define stat _stat
|
||||
# define strcasecmp _stricmp
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The maximum length we can grow a value to after variable expansion. 64k
|
||||
|
@ -26,12 +34,18 @@
|
|||
#define MAX_CONF_VALUE_LENGTH 65536
|
||||
|
||||
static char *eat_ws(CONF *conf, char *p);
|
||||
static void trim_ws(CONF *conf, char *start);
|
||||
static char *eat_alpha_numeric(CONF *conf, char *p);
|
||||
static void clear_comments(CONF *conf, char *p);
|
||||
static int str_copy(CONF *conf, char *section, char **to, char *from);
|
||||
static char *scan_quote(CONF *conf, char *p);
|
||||
static char *scan_dquote(CONF *conf, char *p);
|
||||
#define scan_esc(conf,p) (((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2)))
|
||||
#ifndef OPENSSL_NO_POSIX_IO
|
||||
static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx,
|
||||
char **dirpath);
|
||||
static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx);
|
||||
#endif
|
||||
|
||||
static CONF *def_create(CONF_METHOD *meth);
|
||||
static int def_init_default(CONF *conf);
|
||||
|
@ -173,6 +187,11 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
|
|||
char *section = NULL, *buf;
|
||||
char *start, *psection, *pname;
|
||||
void *h = (void *)(conf->data);
|
||||
STACK_OF(BIO) *biosk = NULL;
|
||||
#ifndef OPENSSL_NO_POSIX_IO
|
||||
char *dirpath = NULL;
|
||||
OPENSSL_DIR_CTX *dirctx = NULL;
|
||||
#endif
|
||||
|
||||
if ((buff = BUF_MEM_new()) == NULL) {
|
||||
CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
|
||||
|
@ -205,11 +224,39 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
|
|||
}
|
||||
p = &(buff->data[bufnum]);
|
||||
*p = '\0';
|
||||
read_retry:
|
||||
BIO_gets(in, p, CONFBUFSIZE - 1);
|
||||
p[CONFBUFSIZE - 1] = '\0';
|
||||
ii = i = strlen(p);
|
||||
if (i == 0 && !again)
|
||||
break;
|
||||
if (i == 0 && !again) {
|
||||
/* the currently processed BIO is at EOF */
|
||||
BIO *parent;
|
||||
|
||||
#ifndef OPENSSL_NO_POSIX_IO
|
||||
/* continue processing with the next file from directory */
|
||||
if (dirctx != NULL) {
|
||||
BIO *next;
|
||||
|
||||
if ((next = get_next_file(dirpath, &dirctx)) != NULL) {
|
||||
BIO_vfree(in);
|
||||
in = next;
|
||||
goto read_retry;
|
||||
} else {
|
||||
OPENSSL_free(dirpath);
|
||||
dirpath = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* no more files in directory, continue with processing parent */
|
||||
if ((parent = sk_BIO_pop(biosk)) == NULL) {
|
||||
/* everything processed get out of the loop */
|
||||
break;
|
||||
} else {
|
||||
BIO_vfree(in);
|
||||
in = parent;
|
||||
goto read_retry;
|
||||
}
|
||||
}
|
||||
again = 0;
|
||||
while (i > 0) {
|
||||
if ((p[i - 1] != '\r') && (p[i - 1] != '\n'))
|
||||
|
@ -285,7 +332,6 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
|
|||
continue;
|
||||
} else {
|
||||
pname = s;
|
||||
psection = NULL;
|
||||
end = eat_alpha_numeric(conf, s);
|
||||
if ((end[0] == ':') && (end[1] == ':')) {
|
||||
*end = '\0';
|
||||
|
@ -293,29 +339,57 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
|
|||
psection = pname;
|
||||
pname = end;
|
||||
end = eat_alpha_numeric(conf, end);
|
||||
} else {
|
||||
psection = section;
|
||||
}
|
||||
p = eat_ws(conf, end);
|
||||
if (*p != '=') {
|
||||
if (strncmp(pname, ".include", 8) == 0 && p != pname + 8) {
|
||||
char *include = NULL;
|
||||
BIO *next;
|
||||
|
||||
trim_ws(conf, p);
|
||||
if (!str_copy(conf, psection, &include, p))
|
||||
goto err;
|
||||
/* get the BIO of the included file */
|
||||
#ifndef OPENSSL_NO_POSIX_IO
|
||||
next = process_include(include, &dirctx, &dirpath);
|
||||
if (include != dirpath) {
|
||||
/* dirpath will contain include in case of a directory */
|
||||
OPENSSL_free(include);
|
||||
}
|
||||
#else
|
||||
next = BIO_new_file(include, "r");
|
||||
OPENSSL_free(include);
|
||||
#endif
|
||||
if (next != NULL) {
|
||||
/* push the currently processing BIO onto stack */
|
||||
if (biosk == NULL) {
|
||||
if ((biosk = sk_BIO_new_null()) == NULL) {
|
||||
CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (!sk_BIO_push(biosk, in)) {
|
||||
CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
/* continue with reading from the included BIO */
|
||||
in = next;
|
||||
}
|
||||
continue;
|
||||
} else if (*p != '=') {
|
||||
CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN);
|
||||
goto err;
|
||||
}
|
||||
*end = '\0';
|
||||
p++;
|
||||
start = eat_ws(conf, p);
|
||||
while (!IS_EOF(conf, *p))
|
||||
p++;
|
||||
p--;
|
||||
while ((p != start) && (IS_WS(conf, *p)))
|
||||
p--;
|
||||
p++;
|
||||
*p = '\0';
|
||||
trim_ws(conf, start);
|
||||
|
||||
if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) {
|
||||
CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (psection == NULL)
|
||||
psection = section;
|
||||
v->name = OPENSSL_strdup(pname);
|
||||
v->value = NULL;
|
||||
if (v->name == NULL) {
|
||||
|
@ -345,10 +419,17 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
|
|||
}
|
||||
BUF_MEM_free(buff);
|
||||
OPENSSL_free(section);
|
||||
sk_BIO_pop_free(biosk, BIO_vfree);
|
||||
return 1;
|
||||
err:
|
||||
BUF_MEM_free(buff);
|
||||
OPENSSL_free(section);
|
||||
sk_BIO_pop_free(biosk, BIO_vfree);
|
||||
#ifndef OPENSSL_NO_POSIX_IO
|
||||
OPENSSL_free(dirpath);
|
||||
if (dirctx != NULL)
|
||||
OPENSSL_DIR_end(&dirctx);
|
||||
#endif
|
||||
if (line != NULL)
|
||||
*line = eline;
|
||||
BIO_snprintf(btmp, sizeof(btmp), "%ld", eline);
|
||||
|
@ -555,6 +636,86 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_POSIX_IO
|
||||
/*
|
||||
* Check whether included path is a directory.
|
||||
* Returns next BIO to process and in case of a directory
|
||||
* also an opened directory context and the include path.
|
||||
*/
|
||||
static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx,
|
||||
char **dirpath)
|
||||
{
|
||||
struct stat st = { 0 };
|
||||
BIO *next;
|
||||
|
||||
if (stat(include, &st) < 0) {
|
||||
SYSerr(SYS_F_STAT, errno);
|
||||
ERR_add_error_data(1, include);
|
||||
/* missing include file is not fatal error */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((st.st_mode & S_IFDIR) == S_IFDIR) {
|
||||
if (*dirctx != NULL) {
|
||||
CONFerr(CONF_F_PROCESS_INCLUDE,
|
||||
CONF_R_RECURSIVE_DIRECTORY_INCLUDE);
|
||||
ERR_add_error_data(1, include);
|
||||
return NULL;
|
||||
}
|
||||
/* a directory, load its contents */
|
||||
if ((next = get_next_file(include, dirctx)) != NULL)
|
||||
*dirpath = include;
|
||||
return next;
|
||||
}
|
||||
|
||||
next = BIO_new_file(include, "r");
|
||||
return next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get next file from the directory path.
|
||||
* Returns BIO of the next file to read and updates dirctx.
|
||||
*/
|
||||
static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx)
|
||||
{
|
||||
const char *filename;
|
||||
|
||||
while ((filename = OPENSSL_DIR_read(dirctx, path)) != NULL) {
|
||||
size_t namelen;
|
||||
|
||||
namelen = strlen(filename);
|
||||
|
||||
if ((namelen > 5 && strcasecmp(filename + namelen - 5, ".conf") == 0)
|
||||
|| (namelen > 4 && strcasecmp(filename + namelen - 4, ".cnf") == 0)) {
|
||||
size_t newlen;
|
||||
char *newpath;
|
||||
BIO *bio;
|
||||
|
||||
newlen = strlen(path) + namelen + 2;
|
||||
newpath = OPENSSL_zalloc(newlen);
|
||||
if (newpath == NULL) {
|
||||
CONFerr(CONF_F_GET_NEXT_FILE, ERR_R_MALLOC_FAILURE);
|
||||
break;
|
||||
}
|
||||
OPENSSL_strlcat(newpath, path, newlen);
|
||||
#ifndef OPENSSL_SYS_VMS
|
||||
OPENSSL_strlcat(newpath, "/", newlen);
|
||||
#endif
|
||||
OPENSSL_strlcat(newpath, filename, newlen);
|
||||
|
||||
bio = BIO_new_file(newpath, "r");
|
||||
OPENSSL_free(newpath);
|
||||
/* Errors when opening files are non-fatal. */
|
||||
if (bio != NULL)
|
||||
return bio;
|
||||
}
|
||||
}
|
||||
OPENSSL_DIR_end(dirctx);
|
||||
*dirctx = NULL;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *eat_ws(CONF *conf, char *p)
|
||||
{
|
||||
while (IS_WS(conf, *p) && (!IS_EOF(conf, *p)))
|
||||
|
@ -562,6 +723,19 @@ static char *eat_ws(CONF *conf, char *p)
|
|||
return p;
|
||||
}
|
||||
|
||||
static void trim_ws(CONF *conf, char *start)
|
||||
{
|
||||
char *p = start;
|
||||
|
||||
while (!IS_EOF(conf, *p))
|
||||
p++;
|
||||
p--;
|
||||
while ((p >= start) && IS_WS(conf, *p))
|
||||
p--;
|
||||
p++;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
static char *eat_alpha_numeric(CONF *conf, char *p)
|
||||
{
|
||||
for (;;) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
|
@ -20,6 +20,7 @@ static const ERR_STRING_DATA CONF_str_functs[] = {
|
|||
{ERR_PACK(ERR_LIB_CONF, CONF_F_CONF_PARSE_LIST, 0), "CONF_parse_list"},
|
||||
{ERR_PACK(ERR_LIB_CONF, CONF_F_DEF_LOAD, 0), "def_load"},
|
||||
{ERR_PACK(ERR_LIB_CONF, CONF_F_DEF_LOAD_BIO, 0), "def_load_bio"},
|
||||
{ERR_PACK(ERR_LIB_CONF, CONF_F_GET_NEXT_FILE, 0), "get_next_file"},
|
||||
{ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_INIT, 0), "module_init"},
|
||||
{ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_LOAD_DSO, 0), "module_load_dso"},
|
||||
{ERR_PACK(ERR_LIB_CONF, CONF_F_MODULE_RUN, 0), "module_run"},
|
||||
|
@ -33,6 +34,7 @@ static const ERR_STRING_DATA CONF_str_functs[] = {
|
|||
{ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_LOAD_BIO, 0), "NCONF_load_bio"},
|
||||
{ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_LOAD_FP, 0), "NCONF_load_fp"},
|
||||
{ERR_PACK(ERR_LIB_CONF, CONF_F_NCONF_NEW, 0), "NCONF_new"},
|
||||
{ERR_PACK(ERR_LIB_CONF, CONF_F_PROCESS_INCLUDE, 0), "process_include"},
|
||||
{ERR_PACK(ERR_LIB_CONF, CONF_F_STR_COPY, 0), "str_copy"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
@ -56,6 +58,8 @@ static const ERR_STRING_DATA CONF_str_reasons[] = {
|
|||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_SECTION), "no section"},
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_SUCH_FILE), "no such file"},
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_VALUE), "no value"},
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_RECURSIVE_DIRECTORY_INCLUDE),
|
||||
"recursive directory include"},
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_UNABLE_TO_CREATE_NEW_SECTION),
|
||||
"unable to create new section"},
|
||||
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_UNKNOWN_MODULE_NAME),
|
||||
|
|
|
@ -299,6 +299,7 @@ CONF_F_CONF_LOAD_FP:103:CONF_load_fp
|
|||
CONF_F_CONF_PARSE_LIST:119:CONF_parse_list
|
||||
CONF_F_DEF_LOAD:120:def_load
|
||||
CONF_F_DEF_LOAD_BIO:121:def_load_bio
|
||||
CONF_F_GET_NEXT_FILE:107:get_next_file
|
||||
CONF_F_MODULE_INIT:115:module_init
|
||||
CONF_F_MODULE_LOAD_DSO:117:module_load_dso
|
||||
CONF_F_MODULE_RUN:118:module_run
|
||||
|
@ -311,6 +312,7 @@ CONF_F_NCONF_LOAD:113:NCONF_load
|
|||
CONF_F_NCONF_LOAD_BIO:110:NCONF_load_bio
|
||||
CONF_F_NCONF_LOAD_FP:114:NCONF_load_fp
|
||||
CONF_F_NCONF_NEW:111:NCONF_new
|
||||
CONF_F_PROCESS_INCLUDE:116:process_include
|
||||
CONF_F_STR_COPY:101:str_copy
|
||||
CRYPTO_F_CRYPTO_DUP_EX_DATA:110:CRYPTO_dup_ex_data
|
||||
CRYPTO_F_CRYPTO_FREE_EX_DATA:111:CRYPTO_free_ex_data
|
||||
|
@ -1872,6 +1874,7 @@ CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE:106:no conf or environment variable
|
|||
CONF_R_NO_SECTION:107:no section
|
||||
CONF_R_NO_SUCH_FILE:114:no such file
|
||||
CONF_R_NO_VALUE:108:no value
|
||||
CONF_R_RECURSIVE_DIRECTORY_INCLUDE:111:recursive directory include
|
||||
CONF_R_UNABLE_TO_CREATE_NEW_SECTION:103:unable to create new section
|
||||
CONF_R_UNKNOWN_MODULE_NAME:113:unknown module name
|
||||
CONF_R_VARIABLE_EXPANSION_TOO_LONG:116:variable expansion too long
|
||||
|
|
|
@ -27,6 +27,21 @@ The environment is mapped onto a section called B<ENV>.
|
|||
|
||||
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.
|
||||
|
||||
Each section in a configuration file consists of a number of name and
|
||||
value pairs of the form B<name=value>
|
||||
|
||||
|
@ -52,6 +67,9 @@ or the B<\> character. By making the last character of a line a B<\>
|
|||
a B<value> string can be spread across multiple lines. In addition
|
||||
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<value>
|
||||
also apply to the path of the B<.include> directive.
|
||||
|
||||
=head1 OPENSSL LIBRARY CONFIGURATION
|
||||
|
||||
Applications can automatically configure certain
|
||||
|
|
|
@ -25,6 +25,7 @@ int ERR_load_CONF_strings(void);
|
|||
# define CONF_F_CONF_PARSE_LIST 119
|
||||
# define CONF_F_DEF_LOAD 120
|
||||
# define CONF_F_DEF_LOAD_BIO 121
|
||||
# define CONF_F_GET_NEXT_FILE 107
|
||||
# define CONF_F_MODULE_INIT 115
|
||||
# define CONF_F_MODULE_LOAD_DSO 117
|
||||
# define CONF_F_MODULE_RUN 118
|
||||
|
@ -37,6 +38,7 @@ int ERR_load_CONF_strings(void);
|
|||
# define CONF_F_NCONF_LOAD_BIO 110
|
||||
# define CONF_F_NCONF_LOAD_FP 114
|
||||
# define CONF_F_NCONF_NEW 111
|
||||
# define CONF_F_PROCESS_INCLUDE 116
|
||||
# define CONF_F_STR_COPY 101
|
||||
|
||||
/*
|
||||
|
@ -54,6 +56,7 @@ int ERR_load_CONF_strings(void);
|
|||
# define CONF_R_NO_SECTION 107
|
||||
# define CONF_R_NO_SUCH_FILE 114
|
||||
# define CONF_R_NO_VALUE 108
|
||||
# define CONF_R_RECURSIVE_DIRECTORY_INCLUDE 111
|
||||
# define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 103
|
||||
# define CONF_R_UNKNOWN_MODULE_NAME 113
|
||||
# define CONF_R_VARIABLE_EXPANSION_TOO_LONG 116
|
||||
|
|
|
@ -35,6 +35,7 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
|
|||
bftest ssltest_old dsatest exptest rsa_test \
|
||||
evp_test evp_extra_test igetest v3nametest v3ext \
|
||||
crltest danetest bad_dtls_test lhash_test \
|
||||
conf_include_test \
|
||||
constant_time_test verify_extra_test clienthellotest \
|
||||
packettest asynctest secmemtest srptest memleaktest stack_test \
|
||||
dtlsv1listentest ct_test threadstest afalgtest d2i_test \
|
||||
|
@ -390,6 +391,10 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
|
|||
INCLUDE[time_offset_test]=../include
|
||||
DEPEND[time_offset_test]=../libcrypto libtestutil.a
|
||||
|
||||
SOURCE[conf_include_test]=conf_include_test.c
|
||||
INCLUDE[conf_include_test]=../include
|
||||
DEPEND[conf_include_test]=../libcrypto libtestutil.a
|
||||
|
||||
# Internal test programs. These are essentially a collection of internal
|
||||
# test routines. Some of them need to reach internal symbols that aren't
|
||||
# available through the shared library (at least on Linux, Solaris, Windows
|
||||
|
|
161
test/conf_include_test.c
Normal file
161
test/conf_include_test.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/err.h>
|
||||
#include "testutil.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <direct.h>
|
||||
# define DIRSEP "/\\"
|
||||
# define chdir _chdir
|
||||
# define DIRSEP_PRESERVE 0
|
||||
#elif !defined(OPENSSL_NO_POSIX_IO)
|
||||
# include <unistd.h>
|
||||
# ifndef OPENSSL_SYS_VMS
|
||||
# define DIRSEP "/"
|
||||
# define DIRSEP_PRESERVE 0
|
||||
# else
|
||||
# define DIRSEP "/]:"
|
||||
# define DIRSEP_PRESERVE 1
|
||||
# endif
|
||||
#else
|
||||
/* the test does not work without chdir() */
|
||||
# define chdir(x) (-1);
|
||||
# define DIRSEP ""
|
||||
# define DIRSEP_PRESERVE 0
|
||||
#endif
|
||||
|
||||
/* changes path to that of the filename */
|
||||
static int change_path(const char *file)
|
||||
{
|
||||
char *s = OPENSSL_strdup(file);
|
||||
char *p = s;
|
||||
char *last = NULL;
|
||||
int ret;
|
||||
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
|
||||
while ((p = strpbrk(p, DIRSEP)) != NULL) {
|
||||
last = p++;
|
||||
}
|
||||
if (last == NULL)
|
||||
return 0;
|
||||
last[DIRSEP_PRESERVE] = 0;
|
||||
|
||||
TEST_note("changing path to %s", s);
|
||||
ret = chdir(s);
|
||||
OPENSSL_free(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This test program checks the operation of the .include directive.
|
||||
*/
|
||||
|
||||
static CONF *conf;
|
||||
static BIO *in;
|
||||
static int expect_failure = 0;
|
||||
|
||||
static int test_load_config(void)
|
||||
{
|
||||
long errline;
|
||||
long val;
|
||||
char *str;
|
||||
long err;
|
||||
|
||||
if (!TEST_int_gt(NCONF_load_bio(conf, in, &errline), 0)
|
||||
|| !TEST_int_eq(err = ERR_peek_error(), 0)) {
|
||||
if (expect_failure)
|
||||
return 1;
|
||||
TEST_note("Failure loading the configuration at line %ld", errline);
|
||||
return 0;
|
||||
}
|
||||
if (expect_failure) {
|
||||
TEST_note("Failure expected but did not happen");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!TEST_int_gt(CONF_modules_load(conf, NULL, 0), 0)) {
|
||||
TEST_note("Failed in CONF_modules_load");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* verify whether RANDFILE is set correctly */
|
||||
str = NCONF_get_string(conf, "", "RANDFILE");
|
||||
if (!TEST_ptr(str) || !TEST_str_eq(str, "./.rnd")) {
|
||||
TEST_note("RANDFILE incorrect");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* verify whether CA_default/default_days is set */
|
||||
val = 0;
|
||||
if (!TEST_int_eq(NCONF_get_number(conf, "CA_default", "default_days", &val), 1)
|
||||
|| !TEST_int_eq(val, 365)) {
|
||||
TEST_note("default_days incorrect");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* verify whether req/default_bits is set */
|
||||
val = 0;
|
||||
if (!TEST_int_eq(NCONF_get_number(conf, "req", "default_bits", &val), 1)
|
||||
|| !TEST_int_eq(val, 2048)) {
|
||||
TEST_note("default_bits incorrect");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* verify whether countryName_default is set correctly */
|
||||
str = NCONF_get_string(conf, "req_distinguished_name", "countryName_default");
|
||||
if (!TEST_ptr(str) || !TEST_str_eq(str, "AU")) {
|
||||
TEST_note("countryName_default incorrect");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
const char *conf_file;
|
||||
const char *arg2;
|
||||
|
||||
if (!TEST_ptr(conf = NCONF_new(NULL)))
|
||||
return 0;
|
||||
|
||||
conf_file = test_get_argument(0);
|
||||
|
||||
if (!TEST_ptr(conf_file)
|
||||
|| !TEST_ptr(in = BIO_new_file(conf_file, "r"))) {
|
||||
TEST_note("Unable to open the file argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((arg2 = test_get_argument(1)) != NULL && *arg2 == 'f') {
|
||||
expect_failure = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* For this test we need to chdir as we use relative
|
||||
* path names in the config files.
|
||||
*/
|
||||
change_path(conf_file);
|
||||
|
||||
ADD_TEST(test_load_config);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cleanup_tests(void)
|
||||
{
|
||||
BIO_vfree(in);
|
||||
NCONF_free(conf);
|
||||
CONF_modules_unload(1);
|
||||
}
|
17
test/recipes/90-test_includes.t
Normal file
17
test/recipes/90-test_includes.t
Normal file
|
@ -0,0 +1,17 @@
|
|||
#! /usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use OpenSSL::Test qw/:DEFAULT data_file/;
|
||||
use OpenSSL::Test::Utils;
|
||||
|
||||
setup("test_includes");
|
||||
|
||||
plan skip_all => "test_includes doesn't work without posix-io"
|
||||
if disabled("posix-io");
|
||||
|
||||
plan tests => 3; # The number of tests being performed
|
||||
|
||||
ok(run(test(["conf_include_test", data_file("includes.cnf")])), "test directory includes");
|
||||
ok(run(test(["conf_include_test", data_file("includes-file.cnf")])), "test file includes");
|
||||
ok(run(test(["conf_include_test", data_file("includes-broken.cnf"), "f"])), "test broken includes");
|
|
@ -0,0 +1,36 @@
|
|||
[ default ]
|
||||
#
|
||||
# SSLeay example configuration file.
|
||||
# This is mostly being used for generation of certificate requests.
|
||||
#
|
||||
|
||||
RANDFILE = ./.rnd
|
||||
|
||||
####################################################################
|
||||
[ ca ]
|
||||
default_ca = CA_default # The default ca section
|
||||
|
||||
####################################################################
|
||||
[ CA_default ]
|
||||
|
||||
dir = ./demoCA # Where everything is kept
|
||||
certs = $dir/certs # Where the issued certs are kept
|
||||
crl_dir = $dir/crl # Where the issued crl are kept
|
||||
database = $dir/index.txt # database index file.
|
||||
new_certs_dir = $dir/new_certs # default place for new certs.
|
||||
|
||||
certificate = $dir/CAcert.pem # The CA certificate
|
||||
serial = $dir/serial # The current serial number
|
||||
crl = $dir/crl.pem # The current CRL
|
||||
private_key = $dir/private/CAkey.pem# The private key
|
||||
RANDFILE = $dir/private/.rand # private random number file
|
||||
|
||||
default_days = 365 # how long to certify for
|
||||
default_crl_days= 30 # how long before next CRL
|
||||
default_md = md5 # which md to use.
|
||||
|
||||
# A few difference way of specifying how similar the request should look
|
||||
# For type CA, the listed attributes must be the same, and the optional
|
||||
# and supplied fields are just that :-)
|
||||
policy = policy_match
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
# For the CA policy
|
||||
[ policy_match ]
|
||||
countryName = match
|
||||
stateOrProvinceName = match
|
||||
organizationName = match
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
# For the 'anything' policy
|
||||
# At this point in time, you must list all acceptable 'object'
|
||||
# types.
|
||||
[ policy_anything ]
|
||||
countryName = optional
|
||||
stateOrProvinceName = optional
|
||||
localityName = optional
|
||||
organizationName = optional
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
####################################################################
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_keyfile = testkey.pem
|
||||
distinguished_name = req_distinguished_name
|
||||
encrypt_rsa_key = no
|
||||
|
||||
[ req_distinguished_name ]
|
||||
countryName = Country Name (2 letter code)
|
||||
countryName_default = AU
|
||||
countryName_value = AU
|
||||
|
||||
stateOrProvinceName = State or Province Name (full name)
|
||||
stateOrProvinceName_default = Queensland
|
||||
stateOrProvinceName_value =
|
||||
|
||||
localityName = Locality Name (eg, city)
|
||||
localityName_value = Brisbane
|
||||
|
||||
organizationName = Organization Name (eg, company)
|
||||
organizationName_default =
|
||||
organizationName_value = CryptSoft Pty Ltd
|
||||
|
||||
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||
organizationalUnitName_default =
|
||||
organizationalUnitName_value = .
|
||||
|
||||
commonName = Common Name (eg, YOUR name)
|
||||
commonName_value = Eric Young
|
||||
|
||||
emailAddress = Email Address
|
||||
emailAddress_value = eay@mincom.oz.au
|
5
test/recipes/90-test_includes_data/includes-broken.cnf
Normal file
5
test/recipes/90-test_includes_data/includes-broken.cnf
Normal file
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Example configuration file using includes.
|
||||
#
|
||||
|
||||
.include includes-broken3.cnf
|
5
test/recipes/90-test_includes_data/includes-file.cnf
Normal file
5
test/recipes/90-test_includes_data/includes-file.cnf
Normal file
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Example configuration file using includes.
|
||||
#
|
||||
|
||||
.include includes.cnf
|
5
test/recipes/90-test_includes_data/includes.cnf
Normal file
5
test/recipes/90-test_includes_data/includes.cnf
Normal file
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Example configuration file using includes.
|
||||
#
|
||||
|
||||
.include conf-includes
|
Loading…
Reference in a new issue