From b524b808a1d1ba204dbdcbb42de4e3bddb3472ac Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Tue, 27 Feb 2018 13:55:35 +0100 Subject: 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 Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/5351) --- apps/openssl-vms.cnf | 4 + apps/openssl.cnf | 4 + crypto/conf/conf_def.c | 202 +++++++++++++++++++-- crypto/conf/conf_err.c | 6 +- crypto/err/openssl.txt | 3 + doc/man5/config.pod | 18 ++ include/openssl/conferr.h | 3 + test/build.info | 5 + test/conf_include_test.c | 161 ++++++++++++++++ test/recipes/90-test_includes.t | 17 ++ .../conf-includes/includes1.cnf | 36 ++++ .../conf-includes/includes2.cnf | 53 ++++++ .../90-test_includes_data/includes-broken.cnf | 5 + .../90-test_includes_data/includes-file.cnf | 5 + test/recipes/90-test_includes_data/includes.cnf | 5 + 15 files changed, 512 insertions(+), 15 deletions(-) create mode 100644 test/conf_include_test.c create mode 100644 test/recipes/90-test_includes.t create mode 100644 test/recipes/90-test_includes_data/conf-includes/includes1.cnf create mode 100644 test/recipes/90-test_includes_data/conf-includes/includes2.cnf create mode 100644 test/recipes/90-test_includes_data/includes-broken.cnf create mode 100644 test/recipes/90-test_includes_data/includes-file.cnf create mode 100644 test/recipes/90-test_includes_data/includes.cnf diff --git a/apps/openssl-vms.cnf b/apps/openssl-vms.cnf index a3ca393018..f4a25112dc 100644 --- a/apps/openssl-vms.cnf +++ b/apps/openssl-vms.cnf @@ -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 = . diff --git a/apps/openssl.cnf b/apps/openssl.cnf index 32ee9e9fbb..7d1a8bb6e7 100644 --- a/apps/openssl.cnf +++ b/apps/openssl.cnf @@ -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 = . diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c index 82e191aef3..d689502e31 100644 --- a/crypto/conf/conf_def.c +++ b/crypto/conf/conf_def.c @@ -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 #include #include "internal/cryptlib.h" +#include "internal/o_dir.h" #include #include #include #include "conf_def.h" #include #include +#ifndef OPENSSL_NO_POSIX_IO +# include +# 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 (;;) { diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c index 8ba243ca69..dd20a1aafa 100644 --- a/crypto/conf/conf_err.c +++ b/crypto/conf/conf_err.c @@ -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), diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 318b400e31..9a41ea8e92 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -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 diff --git a/doc/man5/config.pod b/doc/man5/config.pod index a7cc16b2c0..485ec0870b 100644 --- a/doc/man5/config.pod +++ b/doc/man5/config.pod @@ -27,6 +27,21 @@ The environment is mapped onto a section called B. 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 @@ -52,6 +67,9 @@ 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. +All expansion and escape rules as described above that apply to B +also apply to the path of the B<.include> directive. + =head1 OPENSSL LIBRARY CONFIGURATION Applications can automatically configure certain diff --git a/include/openssl/conferr.h b/include/openssl/conferr.h index d623cea6d5..d2d0c7bace 100644 --- a/include/openssl/conferr.h +++ b/include/openssl/conferr.h @@ -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 diff --git a/test/build.info b/test/build.info index 38fcf842b8..30424dc4cf 100644 --- a/test/build.info +++ b/test/build.info @@ -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 diff --git a/test/conf_include_test.c b/test/conf_include_test.c new file mode 100644 index 0000000000..41e4da04eb --- /dev/null +++ b/test/conf_include_test.c @@ -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 +#include +#include +#include +#include "testutil.h" + +#ifdef _WIN32 +# include +# define DIRSEP "/\\" +# define chdir _chdir +# define DIRSEP_PRESERVE 0 +#elif !defined(OPENSSL_NO_POSIX_IO) +# include +# 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); +} diff --git a/test/recipes/90-test_includes.t b/test/recipes/90-test_includes.t new file mode 100644 index 0000000000..9cf75a1c43 --- /dev/null +++ b/test/recipes/90-test_includes.t @@ -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"); diff --git a/test/recipes/90-test_includes_data/conf-includes/includes1.cnf b/test/recipes/90-test_includes_data/conf-includes/includes1.cnf new file mode 100644 index 0000000000..66c89006d0 --- /dev/null +++ b/test/recipes/90-test_includes_data/conf-includes/includes1.cnf @@ -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 + diff --git a/test/recipes/90-test_includes_data/conf-includes/includes2.cnf b/test/recipes/90-test_includes_data/conf-includes/includes2.cnf new file mode 100644 index 0000000000..aa5e67c060 --- /dev/null +++ b/test/recipes/90-test_includes_data/conf-includes/includes2.cnf @@ -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 diff --git a/test/recipes/90-test_includes_data/includes-broken.cnf b/test/recipes/90-test_includes_data/includes-broken.cnf new file mode 100644 index 0000000000..d38e18c5e5 --- /dev/null +++ b/test/recipes/90-test_includes_data/includes-broken.cnf @@ -0,0 +1,5 @@ +# +# Example configuration file using includes. +# + +.include includes-broken3.cnf diff --git a/test/recipes/90-test_includes_data/includes-file.cnf b/test/recipes/90-test_includes_data/includes-file.cnf new file mode 100644 index 0000000000..1737b70d18 --- /dev/null +++ b/test/recipes/90-test_includes_data/includes-file.cnf @@ -0,0 +1,5 @@ +# +# Example configuration file using includes. +# + +.include includes.cnf diff --git a/test/recipes/90-test_includes_data/includes.cnf b/test/recipes/90-test_includes_data/includes.cnf new file mode 100644 index 0000000000..345eeb9884 --- /dev/null +++ b/test/recipes/90-test_includes_data/includes.cnf @@ -0,0 +1,5 @@ +# +# Example configuration file using includes. +# + +.include conf-includes -- cgit v1.2.3