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