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