1 1.1 christos /* 2 1.2 christos * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.2 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include <stdlib.h> 11 1.1 christos #include <string.h> 12 1.1 christos #include <openssl/conf.h> 13 1.1 christos #include <openssl/err.h> 14 1.1 christos #include "testutil.h" 15 1.1 christos 16 1.1 christos #ifdef _WIN32 17 1.1 christos # include <direct.h> 18 1.1 christos # define DIRSEP "/\\" 19 1.2 christos # ifndef __BORLANDC__ 20 1.2 christos # define chdir _chdir 21 1.2 christos # endif 22 1.1 christos # define DIRSEP_PRESERVE 0 23 1.1 christos #elif !defined(OPENSSL_NO_POSIX_IO) 24 1.1 christos # include <unistd.h> 25 1.1 christos # ifndef OPENSSL_SYS_VMS 26 1.1 christos # define DIRSEP "/" 27 1.1 christos # define DIRSEP_PRESERVE 0 28 1.1 christos # else 29 1.1 christos # define DIRSEP "/]:" 30 1.1 christos # define DIRSEP_PRESERVE 1 31 1.1 christos # endif 32 1.1 christos #else 33 1.1 christos /* the test does not work without chdir() */ 34 1.1 christos # define chdir(x) (-1); 35 1.1 christos # define DIRSEP "/" 36 1.1 christos # define DIRSEP_PRESERVE 0 37 1.1 christos #endif 38 1.1 christos 39 1.1 christos /* changes path to that of the filename */ 40 1.1 christos static int change_path(const char *file) 41 1.1 christos { 42 1.1 christos char *s = OPENSSL_strdup(file); 43 1.1 christos char *p = s; 44 1.1 christos char *last = NULL; 45 1.2 christos int ret = 0; 46 1.1 christos 47 1.1 christos if (s == NULL) 48 1.1 christos return -1; 49 1.1 christos 50 1.1 christos while ((p = strpbrk(p, DIRSEP)) != NULL) { 51 1.1 christos last = p++; 52 1.1 christos } 53 1.1 christos if (last == NULL) 54 1.2 christos goto err; 55 1.1 christos last[DIRSEP_PRESERVE] = 0; 56 1.1 christos 57 1.1 christos TEST_note("changing path to %s", s); 58 1.1 christos ret = chdir(s); 59 1.2 christos err: 60 1.1 christos OPENSSL_free(s); 61 1.1 christos return ret; 62 1.1 christos } 63 1.1 christos 64 1.1 christos /* 65 1.1 christos * This test program checks the operation of the .include directive. 66 1.1 christos */ 67 1.1 christos 68 1.1 christos static CONF *conf; 69 1.1 christos static BIO *in; 70 1.1 christos static int expect_failure = 0; 71 1.1 christos 72 1.1 christos static int test_load_config(void) 73 1.1 christos { 74 1.1 christos long errline; 75 1.1 christos long val; 76 1.1 christos char *str; 77 1.1 christos long err; 78 1.1 christos 79 1.1 christos if (!TEST_int_gt(NCONF_load_bio(conf, in, &errline), 0) 80 1.1 christos || !TEST_int_eq(err = ERR_peek_error(), 0)) { 81 1.1 christos if (expect_failure) 82 1.1 christos return 1; 83 1.1 christos TEST_note("Failure loading the configuration at line %ld", errline); 84 1.1 christos return 0; 85 1.1 christos } 86 1.1 christos if (expect_failure) { 87 1.1 christos TEST_note("Failure expected but did not happen"); 88 1.1 christos return 0; 89 1.1 christos } 90 1.1 christos 91 1.1 christos if (!TEST_int_gt(CONF_modules_load(conf, NULL, 0), 0)) { 92 1.1 christos TEST_note("Failed in CONF_modules_load"); 93 1.1 christos return 0; 94 1.1 christos } 95 1.1 christos 96 1.1 christos /* verify whether CA_default/default_days is set */ 97 1.1 christos val = 0; 98 1.1 christos if (!TEST_int_eq(NCONF_get_number(conf, "CA_default", "default_days", &val), 1) 99 1.1 christos || !TEST_int_eq(val, 365)) { 100 1.1 christos TEST_note("default_days incorrect"); 101 1.1 christos return 0; 102 1.1 christos } 103 1.1 christos 104 1.1 christos /* verify whether req/default_bits is set */ 105 1.1 christos val = 0; 106 1.1 christos if (!TEST_int_eq(NCONF_get_number(conf, "req", "default_bits", &val), 1) 107 1.1 christos || !TEST_int_eq(val, 2048)) { 108 1.1 christos TEST_note("default_bits incorrect"); 109 1.1 christos return 0; 110 1.1 christos } 111 1.1 christos 112 1.1 christos /* verify whether countryName_default is set correctly */ 113 1.1 christos str = NCONF_get_string(conf, "req_distinguished_name", "countryName_default"); 114 1.1 christos if (!TEST_ptr(str) || !TEST_str_eq(str, "AU")) { 115 1.1 christos TEST_note("countryName_default incorrect"); 116 1.1 christos return 0; 117 1.1 christos } 118 1.1 christos 119 1.1 christos return 1; 120 1.1 christos } 121 1.1 christos 122 1.1 christos static int test_check_null_numbers(void) 123 1.1 christos { 124 1.1 christos #if defined(_BSD_SOURCE) \ 125 1.1 christos || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) \ 126 1.1 christos || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) 127 1.1 christos long val = 0; 128 1.1 christos 129 1.1 christos /* Verify that a NULL config with a present environment variable returns 130 1.1 christos * success and the value. 131 1.1 christos */ 132 1.1 christos if (!TEST_int_eq(setenv("FNORD", "123", 1), 0) 133 1.1 christos || !TEST_true(NCONF_get_number(NULL, "missing", "FNORD", &val)) 134 1.1 christos || !TEST_long_eq(val, 123)) { 135 1.1 christos TEST_note("environment variable with NULL conf failed"); 136 1.1 christos return 0; 137 1.1 christos } 138 1.1 christos 139 1.1 christos /* 140 1.2 christos * Verify that a NULL config with a missing environment variable returns 141 1.1 christos * a failure code. 142 1.1 christos */ 143 1.1 christos if (!TEST_int_eq(unsetenv("FNORD"), 0) 144 1.1 christos || !TEST_false(NCONF_get_number(NULL, "missing", "FNORD", &val))) { 145 1.1 christos TEST_note("missing environment variable with NULL conf failed"); 146 1.1 christos return 0; 147 1.1 christos } 148 1.1 christos #endif 149 1.1 christos return 1; 150 1.1 christos } 151 1.1 christos 152 1.1 christos static int test_check_overflow(void) 153 1.1 christos { 154 1.1 christos #if defined(_BSD_SOURCE) \ 155 1.1 christos || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) \ 156 1.1 christos || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) 157 1.1 christos long val = 0; 158 1.1 christos char max[(sizeof(long) * 8) / 3 + 3]; 159 1.1 christos char *p; 160 1.1 christos 161 1.3 christos p = max + BIO_snprintf(max, sizeof(max), "0%ld", LONG_MAX) - 1; 162 1.1 christos setenv("FNORD", max, 1); 163 1.1 christos if (!TEST_true(NCONF_get_number(NULL, "missing", "FNORD", &val)) 164 1.1 christos || !TEST_long_eq(val, LONG_MAX)) 165 1.1 christos return 0; 166 1.1 christos 167 1.1 christos while (++*p > '9') 168 1.1 christos *p-- = '0'; 169 1.1 christos 170 1.1 christos setenv("FNORD", max, 1); 171 1.1 christos if (!TEST_false(NCONF_get_number(NULL, "missing", "FNORD", &val))) 172 1.1 christos return 0; 173 1.1 christos #endif 174 1.1 christos return 1; 175 1.1 christos } 176 1.1 christos 177 1.2 christos typedef enum OPTION_choice { 178 1.2 christos OPT_ERR = -1, 179 1.2 christos OPT_EOF = 0, 180 1.2 christos OPT_FAIL, 181 1.2 christos OPT_TEST_ENUM 182 1.2 christos } OPTION_CHOICE; 183 1.2 christos 184 1.2 christos const OPTIONS *test_get_options(void) 185 1.2 christos { 186 1.2 christos static const OPTIONS test_options[] = { 187 1.2 christos OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("conf_file\n"), 188 1.2 christos { "f", OPT_FAIL, '-', "A failure is expected" }, 189 1.2 christos { NULL } 190 1.2 christos }; 191 1.2 christos return test_options; 192 1.2 christos } 193 1.2 christos 194 1.1 christos int setup_tests(void) 195 1.1 christos { 196 1.1 christos const char *conf_file; 197 1.2 christos OPTION_CHOICE o; 198 1.1 christos 199 1.1 christos if (!TEST_ptr(conf = NCONF_new(NULL))) 200 1.1 christos return 0; 201 1.1 christos 202 1.2 christos while ((o = opt_next()) != OPT_EOF) { 203 1.2 christos switch (o) { 204 1.2 christos case OPT_FAIL: 205 1.2 christos expect_failure = 1; 206 1.2 christos break; 207 1.2 christos case OPT_TEST_CASES: 208 1.2 christos break; 209 1.2 christos default: 210 1.2 christos return 0; 211 1.2 christos } 212 1.2 christos } 213 1.2 christos 214 1.1 christos conf_file = test_get_argument(0); 215 1.1 christos if (!TEST_ptr(conf_file) 216 1.1 christos || !TEST_ptr(in = BIO_new_file(conf_file, "r"))) { 217 1.1 christos TEST_note("Unable to open the file argument"); 218 1.1 christos return 0; 219 1.1 christos } 220 1.1 christos 221 1.1 christos /* 222 1.1 christos * For this test we need to chdir as we use relative 223 1.1 christos * path names in the config files. 224 1.1 christos */ 225 1.1 christos change_path(conf_file); 226 1.1 christos 227 1.1 christos ADD_TEST(test_load_config); 228 1.1 christos ADD_TEST(test_check_null_numbers); 229 1.1 christos ADD_TEST(test_check_overflow); 230 1.1 christos return 1; 231 1.1 christos } 232 1.1 christos 233 1.1 christos void cleanup_tests(void) 234 1.1 christos { 235 1.1 christos BIO_vfree(in); 236 1.1 christos NCONF_free(conf); 237 1.1 christos CONF_modules_unload(1); 238 1.1 christos } 239