/src/openssl30/crypto/conf/conf_mod.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 2002-2023 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 |  | /* We need to use some engine deprecated APIs */ | 
| 11 |  | #define OPENSSL_SUPPRESS_DEPRECATED | 
| 12 |  |  | 
| 13 |  | #include "internal/cryptlib.h" | 
| 14 |  | #include <stdio.h> | 
| 15 |  | #include <ctype.h> | 
| 16 |  | #include <openssl/crypto.h> | 
| 17 |  | #include "internal/conf.h" | 
| 18 |  | #include <openssl/conf_api.h> | 
| 19 |  | #include "internal/dso.h" | 
| 20 |  | #include "internal/thread_once.h" | 
| 21 |  | #include <openssl/x509.h> | 
| 22 |  | #include <openssl/trace.h> | 
| 23 |  | #include <openssl/engine.h> | 
| 24 |  | #include "conf_local.h" | 
| 25 |  |  | 
| 26 |  | DEFINE_STACK_OF(CONF_MODULE) | 
| 27 |  | DEFINE_STACK_OF(CONF_IMODULE) | 
| 28 |  |  | 
| 29 | 0 | #define DSO_mod_init_name "OPENSSL_init" | 
| 30 | 0 | #define DSO_mod_finish_name "OPENSSL_finish" | 
| 31 |  |  | 
| 32 |  | /* | 
| 33 |  |  * This structure contains a data about supported modules. entries in this | 
| 34 |  |  * table correspond to either dynamic or static modules. | 
| 35 |  |  */ | 
| 36 |  |  | 
| 37 |  | struct conf_module_st { | 
| 38 |  |     /* DSO of this module or NULL if static */ | 
| 39 |  |     DSO *dso; | 
| 40 |  |     /* Name of the module */ | 
| 41 |  |     char *name; | 
| 42 |  |     /* Init function */ | 
| 43 |  |     conf_init_func *init; | 
| 44 |  |     /* Finish function */ | 
| 45 |  |     conf_finish_func *finish; | 
| 46 |  |     /* Number of successfully initialized modules */ | 
| 47 |  |     int links; | 
| 48 |  |     void *usr_data; | 
| 49 |  | }; | 
| 50 |  |  | 
| 51 |  | /* | 
| 52 |  |  * This structure contains information about modules that have been | 
| 53 |  |  * successfully initialized. There may be more than one entry for a given | 
| 54 |  |  * module. | 
| 55 |  |  */ | 
| 56 |  |  | 
| 57 |  | struct conf_imodule_st { | 
| 58 |  |     CONF_MODULE *pmod; | 
| 59 |  |     char *name; | 
| 60 |  |     char *value; | 
| 61 |  |     unsigned long flags; | 
| 62 |  |     void *usr_data; | 
| 63 |  | }; | 
| 64 |  |  | 
| 65 |  | static CRYPTO_ONCE init_module_list_lock = CRYPTO_ONCE_STATIC_INIT; | 
| 66 |  | static CRYPTO_RWLOCK *module_list_lock = NULL; | 
| 67 |  | static STACK_OF(CONF_MODULE) *supported_modules = NULL; /* protected by lock */ | 
| 68 |  | static STACK_OF(CONF_IMODULE) *initialized_modules = NULL; /* protected by lock */ | 
| 69 |  |  | 
| 70 |  | static CRYPTO_ONCE load_builtin_modules = CRYPTO_ONCE_STATIC_INIT; | 
| 71 |  |  | 
| 72 |  | static void module_free(CONF_MODULE *md); | 
| 73 |  | static void module_finish(CONF_IMODULE *imod); | 
| 74 |  | static int module_run(const CONF *cnf, const char *name, const char *value, | 
| 75 |  |                       unsigned long flags); | 
| 76 |  | static CONF_MODULE *module_add(DSO *dso, const char *name, | 
| 77 |  |                                conf_init_func *ifunc, | 
| 78 |  |                                conf_finish_func *ffunc); | 
| 79 |  | static CONF_MODULE *module_find(const char *name); | 
| 80 |  | static int module_init(CONF_MODULE *pmod, const char *name, const char *value, | 
| 81 |  |                        const CONF *cnf); | 
| 82 |  | static CONF_MODULE *module_load_dso(const CONF *cnf, const char *name, | 
| 83 |  |                                     const char *value); | 
| 84 |  |  | 
| 85 |  | static int conf_modules_finish_int(void); | 
| 86 |  |  | 
| 87 |  | static void module_lists_free(void) | 
| 88 | 54 | { | 
| 89 | 54 |     CRYPTO_THREAD_lock_free(module_list_lock); | 
| 90 | 54 |     module_list_lock = NULL; | 
| 91 |  |  | 
| 92 | 54 |     sk_CONF_MODULE_free(supported_modules); | 
| 93 | 54 |     supported_modules = NULL; | 
| 94 |  |  | 
| 95 | 54 |     sk_CONF_IMODULE_free(initialized_modules); | 
| 96 | 54 |     initialized_modules = NULL; | 
| 97 | 54 | } | 
| 98 |  |  | 
| 99 |  | DEFINE_RUN_ONCE_STATIC(do_init_module_list_lock) | 
| 100 | 54 | { | 
| 101 | 54 |     module_list_lock = CRYPTO_THREAD_lock_new(); | 
| 102 | 54 |     if (module_list_lock == NULL) { | 
| 103 | 0 |         ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); | 
| 104 | 0 |         return 0; | 
| 105 | 0 |     } | 
| 106 |  |  | 
| 107 | 54 |     return 1; | 
| 108 | 54 | } | 
| 109 |  |  | 
| 110 |  | static int conf_diagnostics(const CONF *cnf) | 
| 111 | 0 | { | 
| 112 | 0 |     return _CONF_get_number(cnf, NULL, "config_diagnostics") != 0; | 
| 113 | 0 | } | 
| 114 |  |  | 
| 115 |  | /* Main function: load modules from a CONF structure */ | 
| 116 |  |  | 
| 117 |  | int CONF_modules_load(const CONF *cnf, const char *appname, | 
| 118 |  |                       unsigned long flags) | 
| 119 | 0 | { | 
| 120 | 0 |     STACK_OF(CONF_VALUE) *values; | 
| 121 | 0 |     CONF_VALUE *vl; | 
| 122 | 0 |     char *vsection = NULL; | 
| 123 | 0 |     int ret, i; | 
| 124 |  | 
 | 
| 125 | 0 |     if (!cnf) | 
| 126 | 0 |         return 1; | 
| 127 |  |  | 
| 128 | 0 |     if (conf_diagnostics(cnf)) | 
| 129 | 0 |         flags &= ~(CONF_MFLAGS_IGNORE_ERRORS | 
| 130 | 0 |                    | CONF_MFLAGS_IGNORE_RETURN_CODES | 
| 131 | 0 |                    | CONF_MFLAGS_SILENT | 
| 132 | 0 |                    | CONF_MFLAGS_IGNORE_MISSING_FILE); | 
| 133 |  | 
 | 
| 134 | 0 |     ERR_set_mark(); | 
| 135 | 0 |     if (appname) | 
| 136 | 0 |         vsection = NCONF_get_string(cnf, NULL, appname); | 
| 137 |  | 
 | 
| 138 | 0 |     if (!appname || (!vsection && (flags & CONF_MFLAGS_DEFAULT_SECTION))) | 
| 139 | 0 |         vsection = NCONF_get_string(cnf, NULL, "openssl_conf"); | 
| 140 |  | 
 | 
| 141 | 0 |     if (!vsection) { | 
| 142 | 0 |         ERR_pop_to_mark(); | 
| 143 | 0 |         return 1; | 
| 144 | 0 |     } | 
| 145 |  |  | 
| 146 | 0 |     OSSL_TRACE1(CONF, "Configuration in section %s\n", vsection); | 
| 147 | 0 |     values = NCONF_get_section(cnf, vsection); | 
| 148 |  | 
 | 
| 149 | 0 |     if (values == NULL) { | 
| 150 | 0 |         if (!(flags & CONF_MFLAGS_SILENT)) { | 
| 151 | 0 |             ERR_clear_last_mark(); | 
| 152 | 0 |             ERR_raise_data(ERR_LIB_CONF, | 
| 153 | 0 |                            CONF_R_OPENSSL_CONF_REFERENCES_MISSING_SECTION, | 
| 154 | 0 |                            "openssl_conf=%s", vsection); | 
| 155 | 0 |         } else { | 
| 156 | 0 |             ERR_pop_to_mark(); | 
| 157 | 0 |         } | 
| 158 | 0 |         return 0; | 
| 159 | 0 |     } | 
| 160 | 0 |     ERR_pop_to_mark(); | 
| 161 |  | 
 | 
| 162 | 0 |     for (i = 0; i < sk_CONF_VALUE_num(values); i++) { | 
| 163 | 0 |         vl = sk_CONF_VALUE_value(values, i); | 
| 164 | 0 |         ERR_set_mark(); | 
| 165 | 0 |         ret = module_run(cnf, vl->name, vl->value, flags); | 
| 166 | 0 |         OSSL_TRACE3(CONF, "Running module %s (%s) returned %d\n", | 
| 167 | 0 |                     vl->name, vl->value, ret); | 
| 168 | 0 |         if (ret <= 0) | 
| 169 | 0 |             if (!(flags & CONF_MFLAGS_IGNORE_ERRORS)) { | 
| 170 | 0 |                 ERR_clear_last_mark(); | 
| 171 | 0 |                 return ret; | 
| 172 | 0 |             } | 
| 173 | 0 |         ERR_pop_to_mark(); | 
| 174 | 0 |     } | 
| 175 |  |  | 
| 176 | 0 |     return 1; | 
| 177 |  | 
 | 
| 178 | 0 | } | 
| 179 |  |  | 
| 180 |  | int CONF_modules_load_file_ex(OSSL_LIB_CTX *libctx, const char *filename, | 
| 181 |  |                               const char *appname, unsigned long flags) | 
| 182 | 30 | { | 
| 183 | 30 |     char *file = NULL; | 
| 184 | 30 |     CONF *conf = NULL; | 
| 185 | 30 |     int ret = 0, diagnostics = 0; | 
| 186 |  |  | 
| 187 | 30 |     ERR_set_mark(); | 
| 188 |  |  | 
| 189 | 30 |     if (filename == NULL) { | 
| 190 | 30 |         file = CONF_get1_default_config_file(); | 
| 191 | 30 |         if (file == NULL) | 
| 192 | 0 |             goto err; | 
| 193 | 30 |         if (*file == '\0') { | 
| 194 |  |             /* Do not try to load an empty file name but do not error out */ | 
| 195 | 0 |             ret = 1; | 
| 196 | 0 |             goto err; | 
| 197 | 0 |         } | 
| 198 | 30 |     } else { | 
| 199 | 0 |         file = (char *)filename; | 
| 200 | 0 |     } | 
| 201 |  |  | 
| 202 | 30 |     conf = NCONF_new_ex(libctx, NULL); | 
| 203 | 30 |     if (conf == NULL) | 
| 204 | 0 |         goto err; | 
| 205 |  |  | 
| 206 | 30 |     if (NCONF_load(conf, file, NULL) <= 0) { | 
| 207 | 30 |         if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) && | 
| 208 | 30 |             (ERR_GET_REASON(ERR_peek_last_error()) == CONF_R_NO_SUCH_FILE)) { | 
| 209 | 30 |             ret = 1; | 
| 210 | 30 |         } | 
| 211 | 30 |         goto err; | 
| 212 | 30 |     } | 
| 213 |  |  | 
| 214 | 0 |     ret = CONF_modules_load(conf, appname, flags); | 
| 215 | 0 |     diagnostics = conf_diagnostics(conf); | 
| 216 |  | 
 | 
| 217 | 30 |  err: | 
| 218 | 30 |     if (filename == NULL) | 
| 219 | 30 |         OPENSSL_free(file); | 
| 220 | 30 |     NCONF_free(conf); | 
| 221 |  |  | 
| 222 | 30 |     if ((flags & CONF_MFLAGS_IGNORE_RETURN_CODES) != 0 && !diagnostics) | 
| 223 | 30 |         ret = 1; | 
| 224 |  |  | 
| 225 | 30 |     if (ret > 0) | 
| 226 | 30 |         ERR_pop_to_mark(); | 
| 227 | 0 |     else | 
| 228 | 0 |         ERR_clear_last_mark(); | 
| 229 |  |  | 
| 230 | 30 |     return ret; | 
| 231 | 0 | } | 
| 232 |  |  | 
| 233 |  | int CONF_modules_load_file(const char *filename, | 
| 234 |  |                            const char *appname, unsigned long flags) | 
| 235 |  | { | 
| 236 |  |     return CONF_modules_load_file_ex(NULL, filename, appname, flags); | 
| 237 |  | } | 
| 238 |  |  | 
| 239 |  | DEFINE_RUN_ONCE_STATIC(do_load_builtin_modules) | 
| 240 | 0 | { | 
| 241 | 0 |     OPENSSL_load_builtin_modules(); | 
| 242 | 0 | #ifndef OPENSSL_NO_ENGINE | 
| 243 |  |     /* Need to load ENGINEs */ | 
| 244 | 0 |     ENGINE_load_builtin_engines(); | 
| 245 | 0 | #endif | 
| 246 | 0 |     return 1; | 
| 247 | 0 | } | 
| 248 |  |  | 
| 249 |  | static int module_run(const CONF *cnf, const char *name, const char *value, | 
| 250 |  |                       unsigned long flags) | 
| 251 | 0 | { | 
| 252 | 0 |     CONF_MODULE *md; | 
| 253 | 0 |     int ret; | 
| 254 |  | 
 | 
| 255 | 0 |     if (!RUN_ONCE(&load_builtin_modules, do_load_builtin_modules)) | 
| 256 | 0 |         return -1; | 
| 257 |  |  | 
| 258 | 0 |     md = module_find(name); | 
| 259 |  |  | 
| 260 |  |     /* Module not found: try to load DSO */ | 
| 261 | 0 |     if (!md && !(flags & CONF_MFLAGS_NO_DSO)) | 
| 262 | 0 |         md = module_load_dso(cnf, name, value); | 
| 263 |  | 
 | 
| 264 | 0 |     if (!md) { | 
| 265 | 0 |         if (!(flags & CONF_MFLAGS_SILENT)) { | 
| 266 | 0 |             ERR_raise_data(ERR_LIB_CONF, CONF_R_UNKNOWN_MODULE_NAME, | 
| 267 | 0 |                            "module=%s", name); | 
| 268 | 0 |         } | 
| 269 | 0 |         return -1; | 
| 270 | 0 |     } | 
| 271 |  |  | 
| 272 | 0 |     ret = module_init(md, name, value, cnf); | 
| 273 |  | 
 | 
| 274 | 0 |     if (ret <= 0) { | 
| 275 | 0 |         if (!(flags & CONF_MFLAGS_SILENT)) | 
| 276 | 0 |             ERR_raise_data(ERR_LIB_CONF, CONF_R_MODULE_INITIALIZATION_ERROR, | 
| 277 | 0 |                            "module=%s, value=%s retcode=%-8d", | 
| 278 | 0 |                            name, value, ret); | 
| 279 | 0 |     } | 
| 280 |  | 
 | 
| 281 | 0 |     return ret; | 
| 282 | 0 | } | 
| 283 |  |  | 
| 284 |  | /* Load a module from a DSO */ | 
| 285 |  | static CONF_MODULE *module_load_dso(const CONF *cnf, | 
| 286 |  |                                     const char *name, const char *value) | 
| 287 | 0 | { | 
| 288 | 0 |     DSO *dso = NULL; | 
| 289 | 0 |     conf_init_func *ifunc; | 
| 290 | 0 |     conf_finish_func *ffunc; | 
| 291 | 0 |     const char *path = NULL; | 
| 292 | 0 |     int errcode = 0; | 
| 293 | 0 |     CONF_MODULE *md; | 
| 294 |  |  | 
| 295 |  |     /* Look for alternative path in module section */ | 
| 296 | 0 |     path = _CONF_get_string(cnf, value, "path"); | 
| 297 | 0 |     if (path == NULL) { | 
| 298 | 0 |         path = name; | 
| 299 | 0 |     } | 
| 300 | 0 |     dso = DSO_load(NULL, path, NULL, 0); | 
| 301 | 0 |     if (dso == NULL) { | 
| 302 | 0 |         errcode = CONF_R_ERROR_LOADING_DSO; | 
| 303 | 0 |         goto err; | 
| 304 | 0 |     } | 
| 305 | 0 |     ifunc = (conf_init_func *)DSO_bind_func(dso, DSO_mod_init_name); | 
| 306 | 0 |     if (ifunc == NULL) { | 
| 307 | 0 |         errcode = CONF_R_MISSING_INIT_FUNCTION; | 
| 308 | 0 |         goto err; | 
| 309 | 0 |     } | 
| 310 | 0 |     ffunc = (conf_finish_func *)DSO_bind_func(dso, DSO_mod_finish_name); | 
| 311 |  |     /* All OK, add module */ | 
| 312 | 0 |     md = module_add(dso, name, ifunc, ffunc); | 
| 313 |  | 
 | 
| 314 | 0 |     if (md == NULL) | 
| 315 | 0 |         goto err; | 
| 316 |  |  | 
| 317 | 0 |     return md; | 
| 318 |  |  | 
| 319 | 0 |  err: | 
| 320 | 0 |     DSO_free(dso); | 
| 321 | 0 |     ERR_raise_data(ERR_LIB_CONF, errcode, "module=%s, path=%s", name, path); | 
| 322 | 0 |     return NULL; | 
| 323 | 0 | } | 
| 324 |  |  | 
| 325 |  | /* add module to list */ | 
| 326 |  | static CONF_MODULE *module_add(DSO *dso, const char *name, | 
| 327 |  |                                conf_init_func *ifunc, conf_finish_func *ffunc) | 
| 328 |  | { | 
| 329 |  |     CONF_MODULE *tmod = NULL; | 
| 330 |  |  | 
| 331 |  |     if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock)) | 
| 332 |  |         return NULL; | 
| 333 |  |  | 
| 334 |  |     if (!CRYPTO_THREAD_write_lock(module_list_lock)) | 
| 335 |  |         return NULL; | 
| 336 |  |  | 
| 337 |  |     if (supported_modules == NULL) | 
| 338 |  |         supported_modules = sk_CONF_MODULE_new_null(); | 
| 339 |  |     if (supported_modules == NULL) | 
| 340 |  |         goto err; | 
| 341 |  |     if ((tmod = OPENSSL_zalloc(sizeof(*tmod))) == NULL) { | 
| 342 |  |         ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); | 
| 343 |  |         goto err; | 
| 344 |  |     } | 
| 345 |  |  | 
| 346 |  |     tmod->dso = dso; | 
| 347 |  |     tmod->name = OPENSSL_strdup(name); | 
| 348 |  |     tmod->init = ifunc; | 
| 349 |  |     tmod->finish = ffunc; | 
| 350 |  |     if (tmod->name == NULL) | 
| 351 |  |         goto err; | 
| 352 |  |  | 
| 353 |  |     if (!sk_CONF_MODULE_push(supported_modules, tmod)) | 
| 354 |  |         goto err; | 
| 355 |  |  | 
| 356 |  |     CRYPTO_THREAD_unlock(module_list_lock); | 
| 357 |  |     return tmod; | 
| 358 |  |  | 
| 359 |  |  err: | 
| 360 |  |     CRYPTO_THREAD_unlock(module_list_lock); | 
| 361 |  |     if (tmod != NULL) { | 
| 362 |  |         OPENSSL_free(tmod->name); | 
| 363 |  |         OPENSSL_free(tmod); | 
| 364 |  |     } | 
| 365 |  |     return NULL; | 
| 366 |  | } | 
| 367 |  |  | 
| 368 |  | /* | 
| 369 |  |  * Find a module from the list. We allow module names of the form | 
| 370 |  |  * modname.XXXX to just search for modname to allow the same module to be | 
| 371 |  |  * initialized more than once. | 
| 372 |  |  */ | 
| 373 |  |  | 
| 374 |  | static CONF_MODULE *module_find(const char *name) | 
| 375 | 0 | { | 
| 376 | 0 |     CONF_MODULE *tmod; | 
| 377 | 0 |     int i, nchar; | 
| 378 | 0 |     char *p; | 
| 379 | 0 |     p = strrchr(name, '.'); | 
| 380 |  | 
 | 
| 381 | 0 |     if (p) | 
| 382 | 0 |         nchar = p - name; | 
| 383 | 0 |     else | 
| 384 | 0 |         nchar = strlen(name); | 
| 385 |  | 
 | 
| 386 | 0 |     if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock)) | 
| 387 | 0 |         return NULL; | 
| 388 |  |  | 
| 389 | 0 |     if (!CRYPTO_THREAD_read_lock(module_list_lock)) | 
| 390 | 0 |         return NULL; | 
| 391 |  |  | 
| 392 | 0 |     for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++) { | 
| 393 | 0 |         tmod = sk_CONF_MODULE_value(supported_modules, i); | 
| 394 | 0 |         if (strncmp(tmod->name, name, nchar) == 0) { | 
| 395 | 0 |             CRYPTO_THREAD_unlock(module_list_lock); | 
| 396 | 0 |             return tmod; | 
| 397 | 0 |         } | 
| 398 | 0 |     } | 
| 399 |  |  | 
| 400 | 0 |     CRYPTO_THREAD_unlock(module_list_lock); | 
| 401 | 0 |     return NULL; | 
| 402 | 0 | } | 
| 403 |  |  | 
| 404 |  | /* initialize a module */ | 
| 405 |  | static int module_init(CONF_MODULE *pmod, const char *name, const char *value, | 
| 406 |  |                        const CONF *cnf) | 
| 407 | 0 | { | 
| 408 | 0 |     int ret = 1; | 
| 409 | 0 |     int init_called = 0; | 
| 410 | 0 |     CONF_IMODULE *imod = NULL; | 
| 411 |  |  | 
| 412 |  |     /* Otherwise add initialized module to list */ | 
| 413 | 0 |     imod = OPENSSL_malloc(sizeof(*imod)); | 
| 414 | 0 |     if (imod == NULL) | 
| 415 | 0 |         goto err; | 
| 416 |  |  | 
| 417 | 0 |     imod->pmod = pmod; | 
| 418 | 0 |     imod->name = OPENSSL_strdup(name); | 
| 419 | 0 |     imod->value = OPENSSL_strdup(value); | 
| 420 | 0 |     imod->usr_data = NULL; | 
| 421 |  | 
 | 
| 422 | 0 |     if (!imod->name || !imod->value) | 
| 423 | 0 |         goto memerr; | 
| 424 |  |  | 
| 425 |  |     /* Try to initialize module */ | 
| 426 | 0 |     if (pmod->init) { | 
| 427 | 0 |         ret = pmod->init(imod, cnf); | 
| 428 | 0 |         init_called = 1; | 
| 429 |  |         /* Error occurred, exit */ | 
| 430 | 0 |         if (ret <= 0) | 
| 431 | 0 |             goto err; | 
| 432 | 0 |     } | 
| 433 |  |  | 
| 434 | 0 |     if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock)) | 
| 435 | 0 |         goto err; | 
| 436 |  |  | 
| 437 | 0 |     if (!CRYPTO_THREAD_write_lock(module_list_lock)) | 
| 438 | 0 |         goto err; | 
| 439 |  |  | 
| 440 | 0 |     if (initialized_modules == NULL) { | 
| 441 | 0 |         initialized_modules = sk_CONF_IMODULE_new_null(); | 
| 442 | 0 |         if (initialized_modules == NULL) { | 
| 443 | 0 |             CRYPTO_THREAD_unlock(module_list_lock); | 
| 444 | 0 |             ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); | 
| 445 | 0 |             goto err; | 
| 446 | 0 |         } | 
| 447 | 0 |     } | 
| 448 |  |  | 
| 449 | 0 |     if (!sk_CONF_IMODULE_push(initialized_modules, imod)) { | 
| 450 | 0 |         CRYPTO_THREAD_unlock(module_list_lock); | 
| 451 | 0 |         ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); | 
| 452 | 0 |         goto err; | 
| 453 | 0 |     } | 
| 454 |  |  | 
| 455 | 0 |     pmod->links++; | 
| 456 |  | 
 | 
| 457 | 0 |     CRYPTO_THREAD_unlock(module_list_lock); | 
| 458 | 0 |     return ret; | 
| 459 |  |  | 
| 460 | 0 |  err: | 
| 461 |  |  | 
| 462 |  |     /* We've started the module so we'd better finish it */ | 
| 463 | 0 |     if (pmod->finish && init_called) | 
| 464 | 0 |         pmod->finish(imod); | 
| 465 |  | 
 | 
| 466 | 0 |  memerr: | 
| 467 | 0 |     if (imod) { | 
| 468 | 0 |         OPENSSL_free(imod->name); | 
| 469 | 0 |         OPENSSL_free(imod->value); | 
| 470 | 0 |         OPENSSL_free(imod); | 
| 471 | 0 |     } | 
| 472 |  | 
 | 
| 473 | 0 |     return -1; | 
| 474 |  | 
 | 
| 475 | 0 | } | 
| 476 |  |  | 
| 477 |  | /* | 
| 478 |  |  * Unload any dynamic modules that have a link count of zero: i.e. have no | 
| 479 |  |  * active initialized modules. If 'all' is set then all modules are unloaded | 
| 480 |  |  * including static ones. | 
| 481 |  |  */ | 
| 482 |  |  | 
| 483 |  | void CONF_modules_unload(int all) | 
| 484 | 54 | { | 
| 485 | 54 |     int i; | 
| 486 | 54 |     CONF_MODULE *md; | 
| 487 |  |  | 
| 488 | 54 |     if (!conf_modules_finish_int()) /* also inits module list lock */ | 
| 489 | 0 |         return; | 
| 490 |  |  | 
| 491 | 54 |     if (!CRYPTO_THREAD_write_lock(module_list_lock)) | 
| 492 | 0 |         return; | 
| 493 |  |  | 
| 494 |  |     /* unload modules in reverse order */ | 
| 495 | 54 |     for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--) { | 
| 496 | 0 |         md = sk_CONF_MODULE_value(supported_modules, i); | 
| 497 |  |         /* If static or in use and 'all' not set ignore it */ | 
| 498 | 0 |         if (((md->links > 0) || !md->dso) && !all) | 
| 499 | 0 |             continue; | 
| 500 |  |         /* Since we're working in reverse this is OK */ | 
| 501 | 0 |         (void)sk_CONF_MODULE_delete(supported_modules, i); | 
| 502 | 0 |         module_free(md); | 
| 503 | 0 |     } | 
| 504 |  |  | 
| 505 | 54 |     if (sk_CONF_MODULE_num(supported_modules) == 0) { | 
| 506 | 0 |         sk_CONF_MODULE_free(supported_modules); | 
| 507 | 0 |         supported_modules = NULL; | 
| 508 | 0 |     } | 
| 509 |  |  | 
| 510 | 54 |     CRYPTO_THREAD_unlock(module_list_lock); | 
| 511 | 54 | } | 
| 512 |  |  | 
| 513 |  | /* unload a single module */ | 
| 514 |  | static void module_free(CONF_MODULE *md) | 
| 515 | 30 | { | 
| 516 | 30 |     DSO_free(md->dso); | 
| 517 | 30 |     OPENSSL_free(md->name); | 
| 518 | 30 |     OPENSSL_free(md); | 
| 519 | 30 | } | 
| 520 |  |  | 
| 521 |  | /* finish and free up all modules instances */ | 
| 522 |  |  | 
| 523 |  | static int conf_modules_finish_int(void) | 
| 524 | 54 | { | 
| 525 | 54 |     CONF_IMODULE *imod; | 
| 526 |  |  | 
| 527 | 54 |     if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock)) | 
| 528 | 0 |         return 0; | 
| 529 |  |  | 
| 530 |  |     /* If module_list_lock is NULL here it means we were already unloaded */ | 
| 531 | 54 |     if (module_list_lock == NULL | 
| 532 | 54 |         || !CRYPTO_THREAD_write_lock(module_list_lock)) | 
| 533 | 0 |         return 0; | 
| 534 |  |  | 
| 535 | 54 |     while (sk_CONF_IMODULE_num(initialized_modules) > 0) { | 
| 536 | 0 |         imod = sk_CONF_IMODULE_pop(initialized_modules); | 
| 537 | 0 |         module_finish(imod); | 
| 538 | 0 |     } | 
| 539 | 54 |     sk_CONF_IMODULE_free(initialized_modules); | 
| 540 | 54 |     initialized_modules = NULL; | 
| 541 |  |  | 
| 542 | 54 |     CRYPTO_THREAD_unlock(module_list_lock); | 
| 543 |  |  | 
| 544 | 54 |     return 1; | 
| 545 | 54 | } | 
| 546 |  |  | 
| 547 |  | void CONF_modules_finish(void) | 
| 548 |  | { | 
| 549 |  |     conf_modules_finish_int(); | 
| 550 |  | } | 
| 551 |  |  | 
| 552 |  | /* finish a module instance */ | 
| 553 |  |  | 
| 554 |  | static void module_finish(CONF_IMODULE *imod) | 
| 555 | 0 | { | 
| 556 | 0 |     if (!imod) | 
| 557 | 0 |         return; | 
| 558 | 0 |     if (imod->pmod->finish) | 
| 559 | 0 |         imod->pmod->finish(imod); | 
| 560 | 0 |     imod->pmod->links--; | 
| 561 | 0 |     OPENSSL_free(imod->name); | 
| 562 | 0 |     OPENSSL_free(imod->value); | 
| 563 | 0 |     OPENSSL_free(imod); | 
| 564 | 0 | } | 
| 565 |  |  | 
| 566 |  | /* Add a static module to OpenSSL */ | 
| 567 |  |  | 
| 568 |  | int CONF_module_add(const char *name, conf_init_func *ifunc, | 
| 569 |  |                     conf_finish_func *ffunc) | 
| 570 | 30 | { | 
| 571 | 30 |     if (module_add(NULL, name, ifunc, ffunc)) | 
| 572 | 30 |         return 1; | 
| 573 | 0 |     else | 
| 574 | 0 |         return 0; | 
| 575 | 30 | } | 
| 576 |  |  | 
| 577 |  | void ossl_config_modules_free(void) | 
| 578 | 54 | { | 
| 579 | 54 |     CONF_modules_unload(1); /* calls CONF_modules_finish */ | 
| 580 | 54 |     module_lists_free(); | 
| 581 | 54 | } | 
| 582 |  |  | 
| 583 |  | /* Utility functions */ | 
| 584 |  |  | 
| 585 |  | const char *CONF_imodule_get_name(const CONF_IMODULE *md) | 
| 586 | 0 | { | 
| 587 | 0 |     return md->name; | 
| 588 | 0 | } | 
| 589 |  |  | 
| 590 |  | const char *CONF_imodule_get_value(const CONF_IMODULE *md) | 
| 591 | 0 | { | 
| 592 | 0 |     return md->value; | 
| 593 | 0 | } | 
| 594 |  |  | 
| 595 |  | void *CONF_imodule_get_usr_data(const CONF_IMODULE *md) | 
| 596 | 0 | { | 
| 597 | 0 |     return md->usr_data; | 
| 598 | 0 | } | 
| 599 |  |  | 
| 600 |  | void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data) | 
| 601 | 0 | { | 
| 602 | 0 |     md->usr_data = usr_data; | 
| 603 | 0 | } | 
| 604 |  |  | 
| 605 |  | CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md) | 
| 606 | 0 | { | 
| 607 | 0 |     return md->pmod; | 
| 608 | 0 | } | 
| 609 |  |  | 
| 610 |  | unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md) | 
| 611 | 0 | { | 
| 612 | 0 |     return md->flags; | 
| 613 | 0 | } | 
| 614 |  |  | 
| 615 |  | void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags) | 
| 616 | 0 | { | 
| 617 | 0 |     md->flags = flags; | 
| 618 | 0 | } | 
| 619 |  |  | 
| 620 |  | void *CONF_module_get_usr_data(CONF_MODULE *pmod) | 
| 621 | 0 | { | 
| 622 | 0 |     return pmod->usr_data; | 
| 623 | 0 | } | 
| 624 |  |  | 
| 625 |  | void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data) | 
| 626 | 0 | { | 
| 627 | 0 |     pmod->usr_data = usr_data; | 
| 628 | 0 | } | 
| 629 |  |  | 
| 630 |  | /* Return default config file name */ | 
| 631 |  | char *CONF_get1_default_config_file(void) | 
| 632 | 36 | { | 
| 633 | 36 |     const char *t; | 
| 634 | 36 |     char *file, *sep = ""; | 
| 635 | 36 |     size_t size; | 
| 636 |  |  | 
| 637 | 36 |     if ((file = ossl_safe_getenv("OPENSSL_CONF")) != NULL) | 
| 638 | 0 |         return OPENSSL_strdup(file); | 
| 639 |  |  | 
| 640 | 36 |     t = X509_get_default_cert_area(); | 
| 641 | 36 | #ifndef OPENSSL_SYS_VMS | 
| 642 | 36 |     sep = "/"; | 
| 643 | 36 | #endif | 
| 644 | 36 |     size = strlen(t) + strlen(sep) + strlen(OPENSSL_CONF) + 1; | 
| 645 | 36 |     file = OPENSSL_malloc(size); | 
| 646 |  |  | 
| 647 | 36 |     if (file == NULL) | 
| 648 | 0 |         return NULL; | 
| 649 | 36 |     BIO_snprintf(file, size, "%s%s%s", t, sep, OPENSSL_CONF); | 
| 650 |  |  | 
| 651 | 36 |     return file; | 
| 652 | 36 | } | 
| 653 |  |  | 
| 654 |  | /* | 
| 655 |  |  * This function takes a list separated by 'sep' and calls the callback | 
| 656 |  |  * function giving the start and length of each member optionally stripping | 
| 657 |  |  * leading and trailing whitespace. This can be used to parse comma separated | 
| 658 |  |  * lists for example. | 
| 659 |  |  */ | 
| 660 |  |  | 
| 661 |  | int CONF_parse_list(const char *list_, int sep, int nospc, | 
| 662 |  |                     int (*list_cb) (const char *elem, int len, void *usr), | 
| 663 |  |                     void *arg) | 
| 664 | 24.3k | { | 
| 665 | 24.3k |     int ret; | 
| 666 | 24.3k |     const char *lstart, *tmpend, *p; | 
| 667 |  |  | 
| 668 | 24.3k |     if (list_ == NULL) { | 
| 669 | 0 |         ERR_raise(ERR_LIB_CONF, CONF_R_LIST_CANNOT_BE_NULL); | 
| 670 | 0 |         return 0; | 
| 671 | 0 |     } | 
| 672 |  |  | 
| 673 | 24.3k |     lstart = list_; | 
| 674 | 73.0k |     for (;;) { | 
| 675 | 73.0k |         if (nospc) { | 
| 676 | 73.0k |             while (*lstart && isspace((unsigned char)*lstart)) | 
| 677 | 0 |                 lstart++; | 
| 678 | 73.0k |         } | 
| 679 | 73.0k |         p = strchr(lstart, sep); | 
| 680 | 73.0k |         if (p == lstart || *lstart == '\0') | 
| 681 | 0 |             ret = list_cb(NULL, 0, arg); | 
| 682 | 73.0k |         else { | 
| 683 | 73.0k |             if (p) | 
| 684 | 48.6k |                 tmpend = p - 1; | 
| 685 | 24.3k |             else | 
| 686 | 24.3k |                 tmpend = lstart + strlen(lstart) - 1; | 
| 687 | 73.0k |             if (nospc) { | 
| 688 | 73.0k |                 while (isspace((unsigned char)*tmpend)) | 
| 689 | 0 |                     tmpend--; | 
| 690 | 73.0k |             } | 
| 691 | 73.0k |             ret = list_cb(lstart, tmpend - lstart + 1, arg); | 
| 692 | 73.0k |         } | 
| 693 | 73.0k |         if (ret <= 0) | 
| 694 | 0 |             return ret; | 
| 695 | 73.0k |         if (p == NULL) | 
| 696 | 24.3k |             return 1; | 
| 697 | 48.6k |         lstart = p + 1; | 
| 698 | 48.6k |     } | 
| 699 | 24.3k | } |