1/* $OpenBSD: conf_lib.c,v 1.17 2024/04/09 13:56:30 beck Exp $ */ 2/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL 3 * project 2000. 4 */ 5/* ==================================================================== 6 * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59#include <stdio.h> 60#include <openssl/crypto.h> 61#include <openssl/err.h> 62#include <openssl/conf.h> 63#include <openssl/conf_api.h> 64#include <openssl/lhash.h> 65 66static CONF_METHOD *default_CONF_method = NULL; 67 68/* Init a 'CONF' structure from an old LHASH */ 69 70void 71CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash) 72{ 73 if (default_CONF_method == NULL) 74 default_CONF_method = NCONF_default(); 75 default_CONF_method->init(conf); 76 conf->data = hash; 77} 78LCRYPTO_ALIAS(CONF_set_nconf); 79 80/* The following section contains the "CONF classic" functions, 81 rewritten in terms of the new CONF interface. */ 82 83int 84CONF_set_default_method(CONF_METHOD *meth) 85{ 86 default_CONF_method = meth; 87 return 1; 88} 89LCRYPTO_ALIAS(CONF_set_default_method); 90 91LHASH_OF(CONF_VALUE) * 92CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file, long *eline) 93{ 94 LHASH_OF(CONF_VALUE) *ltmp; 95 BIO *in = NULL; 96 97 in = BIO_new_file(file, "rb"); 98 if (in == NULL) { 99 CONFerror(ERR_R_SYS_LIB); 100 return NULL; 101 } 102 103 ltmp = CONF_load_bio(conf, in, eline); 104 BIO_free(in); 105 106 return ltmp; 107} 108LCRYPTO_ALIAS(CONF_load); 109 110LHASH_OF(CONF_VALUE) * 111CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp, long *eline) 112{ 113 BIO *btmp; 114 LHASH_OF(CONF_VALUE) *ltmp; 115 116 if (!(btmp = BIO_new_fp(fp, BIO_NOCLOSE))) { 117 CONFerror(ERR_R_BUF_LIB); 118 return NULL; 119 } 120 ltmp = CONF_load_bio(conf, btmp, eline); 121 BIO_free(btmp); 122 return ltmp; 123} 124LCRYPTO_ALIAS(CONF_load_fp); 125 126LHASH_OF(CONF_VALUE) * 127CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp, long *eline) 128{ 129 CONF ctmp; 130 int ret; 131 132 CONF_set_nconf(&ctmp, conf); 133 134 ret = NCONF_load_bio(&ctmp, bp, eline); 135 if (ret) 136 return ctmp.data; 137 return NULL; 138} 139LCRYPTO_ALIAS(CONF_load_bio); 140 141STACK_OF(CONF_VALUE) * 142CONF_get_section(LHASH_OF(CONF_VALUE) *conf, const char *section) 143{ 144 if (conf == NULL) { 145 return NULL; 146 } else { 147 CONF ctmp; 148 CONF_set_nconf(&ctmp, conf); 149 return NCONF_get_section(&ctmp, section); 150 } 151} 152LCRYPTO_ALIAS(CONF_get_section); 153 154char * 155CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group, 156 const char *name) 157{ 158 if (conf == NULL) { 159 return NCONF_get_string(NULL, group, name); 160 } else { 161 CONF ctmp; 162 CONF_set_nconf(&ctmp, conf); 163 return NCONF_get_string(&ctmp, group, name); 164 } 165} 166LCRYPTO_ALIAS(CONF_get_string); 167 168long 169CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group, 170 const char *name) 171{ 172 int status; 173 long result = 0; 174 175 if (conf == NULL) { 176 status = NCONF_get_number_e(NULL, group, name, &result); 177 } else { 178 CONF ctmp; 179 CONF_set_nconf(&ctmp, conf); 180 status = NCONF_get_number_e(&ctmp, group, name, &result); 181 } 182 183 if (status == 0) { 184 /* This function does not believe in errors... */ 185 ERR_clear_error(); 186 } 187 return result; 188} 189LCRYPTO_ALIAS(CONF_get_number); 190 191void 192CONF_free(LHASH_OF(CONF_VALUE) *conf) 193{ 194 CONF ctmp; 195 196 CONF_set_nconf(&ctmp, conf); 197 NCONF_free_data(&ctmp); 198} 199LCRYPTO_ALIAS(CONF_free); 200 201int 202CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out) 203{ 204 BIO *btmp; 205 int ret; 206 207 if (!(btmp = BIO_new_fp(out, BIO_NOCLOSE))) { 208 CONFerror(ERR_R_BUF_LIB); 209 return 0; 210 } 211 ret = CONF_dump_bio(conf, btmp); 212 BIO_free(btmp); 213 return ret; 214} 215LCRYPTO_ALIAS(CONF_dump_fp); 216 217int 218CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out) 219{ 220 CONF ctmp; 221 222 CONF_set_nconf(&ctmp, conf); 223 return NCONF_dump_bio(&ctmp, out); 224} 225LCRYPTO_ALIAS(CONF_dump_bio); 226 227/* The following section contains the "New CONF" functions. They are 228 completely centralised around a new CONF structure that may contain 229 basically anything, but at least a method pointer and a table of data. 230 These functions are also written in terms of the bridge functions used 231 by the "CONF classic" functions, for consistency. */ 232 233CONF * 234NCONF_new(CONF_METHOD *meth) 235{ 236 CONF *ret; 237 238 if (meth == NULL) 239 meth = NCONF_default(); 240 241 ret = meth->create(meth); 242 if (ret == NULL) { 243 CONFerror(ERR_R_MALLOC_FAILURE); 244 return (NULL); 245 } 246 247 return ret; 248} 249LCRYPTO_ALIAS(NCONF_new); 250 251void 252NCONF_free(CONF *conf) 253{ 254 if (conf == NULL) 255 return; 256 conf->meth->destroy(conf); 257} 258LCRYPTO_ALIAS(NCONF_free); 259 260void 261NCONF_free_data(CONF *conf) 262{ 263 if (conf == NULL) 264 return; 265 conf->meth->destroy_data(conf); 266} 267LCRYPTO_ALIAS(NCONF_free_data); 268 269int 270NCONF_load(CONF *conf, const char *file, long *eline) 271{ 272 if (conf == NULL) { 273 CONFerror(CONF_R_NO_CONF); 274 return 0; 275 } 276 277 return conf->meth->load(conf, file, eline); 278} 279LCRYPTO_ALIAS(NCONF_load); 280 281int 282NCONF_load_fp(CONF *conf, FILE *fp, long *eline) 283{ 284 BIO *btmp; 285 int ret; 286 287 if (!(btmp = BIO_new_fp(fp, BIO_NOCLOSE))) { 288 CONFerror(ERR_R_BUF_LIB); 289 return 0; 290 } 291 ret = NCONF_load_bio(conf, btmp, eline); 292 BIO_free(btmp); 293 return ret; 294} 295LCRYPTO_ALIAS(NCONF_load_fp); 296 297int 298NCONF_load_bio(CONF *conf, BIO *bp, long *eline) 299{ 300 if (conf == NULL) { 301 CONFerror(CONF_R_NO_CONF); 302 return 0; 303 } 304 305 return conf->meth->load_bio(conf, bp, eline); 306} 307LCRYPTO_ALIAS(NCONF_load_bio); 308 309STACK_OF(CONF_VALUE) * 310NCONF_get_section(const CONF *conf, const char *section) 311{ 312 if (conf == NULL) { 313 CONFerror(CONF_R_NO_CONF); 314 return NULL; 315 } 316 317 if (section == NULL) { 318 CONFerror(CONF_R_NO_SECTION); 319 return NULL; 320 } 321 322 return _CONF_get_section_values(conf, section); 323} 324LCRYPTO_ALIAS(NCONF_get_section); 325 326char * 327NCONF_get_string(const CONF *conf, const char *group, const char *name) 328{ 329 char *s = _CONF_get_string(conf, group, name); 330 331 /* Since we may get a value from an environment variable even 332 if conf is NULL, let's check the value first */ 333 if (s) 334 return s; 335 336 if (conf == NULL) { 337 CONFerror(CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE); 338 return NULL; 339 } 340 CONFerror(CONF_R_NO_VALUE); 341 ERR_asprintf_error_data("group=%s name=%s", 342 group ? group : "", name); 343 return NULL; 344} 345LCRYPTO_ALIAS(NCONF_get_string); 346 347int 348NCONF_get_number_e(const CONF *conf, const char *group, const char *name, 349 long *result) 350{ 351 char *str; 352 353 if (result == NULL) { 354 CONFerror(ERR_R_PASSED_NULL_PARAMETER); 355 return 0; 356 } 357 358 str = NCONF_get_string(conf, group, name); 359 360 if (str == NULL) 361 return 0; 362 363 for (*result = 0; conf->meth->is_number(conf, *str); ) { 364 *result = (*result) * 10 + conf->meth->to_int(conf, *str); 365 str++; 366 } 367 368 return 1; 369} 370LCRYPTO_ALIAS(NCONF_get_number_e); 371 372int 373NCONF_dump_fp(const CONF *conf, FILE *out) 374{ 375 BIO *btmp; 376 int ret; 377 if (!(btmp = BIO_new_fp(out, BIO_NOCLOSE))) { 378 CONFerror(ERR_R_BUF_LIB); 379 return 0; 380 } 381 ret = NCONF_dump_bio(conf, btmp); 382 BIO_free(btmp); 383 return ret; 384} 385LCRYPTO_ALIAS(NCONF_dump_fp); 386 387int 388NCONF_dump_bio(const CONF *conf, BIO *out) 389{ 390 if (conf == NULL) { 391 CONFerror(CONF_R_NO_CONF); 392 return 0; 393 } 394 395 return conf->meth->dump(conf, out); 396} 397LCRYPTO_ALIAS(NCONF_dump_bio); 398