168651Skris/* conf_api.c */ 268651Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 368651Skris * All rights reserved. 468651Skris * 568651Skris * This package is an SSL implementation written 668651Skris * by Eric Young (eay@cryptsoft.com). 768651Skris * The implementation was written so as to conform with Netscapes SSL. 8296341Sdelphij * 968651Skris * This library is free for commercial and non-commercial use as long as 1068651Skris * the following conditions are aheared to. The following conditions 1168651Skris * apply to all code found in this distribution, be it the RC4, RSA, 1268651Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1368651Skris * included with this distribution is covered by the same copyright terms 1468651Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15296341Sdelphij * 1668651Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1768651Skris * the code are not to be removed. 1868651Skris * If this package is used in a product, Eric Young should be given attribution 1968651Skris * as the author of the parts of the library used. 2068651Skris * This can be in the form of a textual message at program startup or 2168651Skris * in documentation (online or textual) provided with the package. 22296341Sdelphij * 2368651Skris * Redistribution and use in source and binary forms, with or without 2468651Skris * modification, are permitted provided that the following conditions 2568651Skris * are met: 2668651Skris * 1. Redistributions of source code must retain the copyright 2768651Skris * notice, this list of conditions and the following disclaimer. 2868651Skris * 2. Redistributions in binary form must reproduce the above copyright 2968651Skris * notice, this list of conditions and the following disclaimer in the 3068651Skris * documentation and/or other materials provided with the distribution. 3168651Skris * 3. All advertising materials mentioning features or use of this software 3268651Skris * must display the following acknowledgement: 3368651Skris * "This product includes cryptographic software written by 3468651Skris * Eric Young (eay@cryptsoft.com)" 3568651Skris * The word 'cryptographic' can be left out if the rouines from the library 3668651Skris * being used are not cryptographic related :-). 37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 3868651Skris * the apps directory (application code) you must include an acknowledgement: 3968651Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40296341Sdelphij * 4168651Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4268651Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4368651Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4468651Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4568651Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4668651Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4768651Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4868651Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4968651Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5068651Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5168651Skris * SUCH DAMAGE. 52296341Sdelphij * 5368651Skris * The licence and distribution terms for any publically available version or 5468651Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5568651Skris * copied and put under another distribution licence 5668651Skris * [including the GNU Public Licence.] 5768651Skris */ 5868651Skris 5968651Skris/* Part of the code in here was originally in conf.c, which is now removed */ 6068651Skris 6168651Skris#ifndef CONF_DEBUG 62296341Sdelphij# undef NDEBUG /* avoid conflicting definitions */ 6368651Skris# define NDEBUG 6468651Skris#endif 6568651Skris 6668651Skris#include <assert.h> 67237657Sjkim#include <stdlib.h> 6868651Skris#include <string.h> 6968651Skris#include <openssl/conf.h> 7068651Skris#include <openssl/conf_api.h> 71109998Smarkm#include "e_os.h" 7268651Skris 73238405Sjkimstatic void value_free_hash_doall_arg(CONF_VALUE *a, 74296341Sdelphij LHASH_OF(CONF_VALUE) *conf); 75238405Sjkimstatic void value_free_stack_doall(CONF_VALUE *a); 76238405Sjkimstatic IMPLEMENT_LHASH_DOALL_ARG_FN(value_free_hash, CONF_VALUE, 77296341Sdelphij LHASH_OF(CONF_VALUE)) 78238405Sjkimstatic IMPLEMENT_LHASH_DOALL_FN(value_free_stack, CONF_VALUE) 7968651Skris 8068651Skris/* Up until OpenSSL 0.9.5a, this was get_section */ 81109998SmarkmCONF_VALUE *_CONF_get_section(const CONF *conf, const char *section) 82296341Sdelphij{ 83296341Sdelphij CONF_VALUE *v, vv; 8468651Skris 85296341Sdelphij if ((conf == NULL) || (section == NULL)) 86296341Sdelphij return (NULL); 87296341Sdelphij vv.name = NULL; 88296341Sdelphij vv.section = (char *)section; 89296341Sdelphij v = lh_CONF_VALUE_retrieve(conf->data, &vv); 90296341Sdelphij return (v); 91296341Sdelphij} 9268651Skris 9368651Skris/* Up until OpenSSL 0.9.5a, this was CONF_get_section */ 94109998SmarkmSTACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf, 95296341Sdelphij const char *section) 96296341Sdelphij{ 97296341Sdelphij CONF_VALUE *v; 9868651Skris 99296341Sdelphij v = _CONF_get_section(conf, section); 100296341Sdelphij if (v != NULL) 101296341Sdelphij return ((STACK_OF(CONF_VALUE) *)v->value); 102296341Sdelphij else 103296341Sdelphij return (NULL); 104296341Sdelphij} 10568651Skris 10668651Skrisint _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value) 107296341Sdelphij{ 108296341Sdelphij CONF_VALUE *v = NULL; 109296341Sdelphij STACK_OF(CONF_VALUE) *ts; 11068651Skris 111296341Sdelphij ts = (STACK_OF(CONF_VALUE) *)section->value; 11268651Skris 113296341Sdelphij value->section = section->section; 114296341Sdelphij if (!sk_CONF_VALUE_push(ts, value)) { 115296341Sdelphij return 0; 116296341Sdelphij } 11768651Skris 118296341Sdelphij v = lh_CONF_VALUE_insert(conf->data, value); 119296341Sdelphij if (v != NULL) { 120296341Sdelphij (void)sk_CONF_VALUE_delete_ptr(ts, v); 121296341Sdelphij OPENSSL_free(v->name); 122296341Sdelphij OPENSSL_free(v->value); 123296341Sdelphij OPENSSL_free(v); 124296341Sdelphij } 125296341Sdelphij return 1; 126296341Sdelphij} 12768651Skris 128296341Sdelphijchar *_CONF_get_string(const CONF *conf, const char *section, 129296341Sdelphij const char *name) 130296341Sdelphij{ 131296341Sdelphij CONF_VALUE *v, vv; 132296341Sdelphij char *p; 13368651Skris 134296341Sdelphij if (name == NULL) 135296341Sdelphij return (NULL); 136296341Sdelphij if (conf != NULL) { 137296341Sdelphij if (section != NULL) { 138296341Sdelphij vv.name = (char *)name; 139296341Sdelphij vv.section = (char *)section; 140296341Sdelphij v = lh_CONF_VALUE_retrieve(conf->data, &vv); 141296341Sdelphij if (v != NULL) 142296341Sdelphij return (v->value); 143296341Sdelphij if (strcmp(section, "ENV") == 0) { 144296341Sdelphij p = getenv(name); 145296341Sdelphij if (p != NULL) 146296341Sdelphij return (p); 147296341Sdelphij } 148296341Sdelphij } 149296341Sdelphij vv.section = "default"; 150296341Sdelphij vv.name = (char *)name; 151296341Sdelphij v = lh_CONF_VALUE_retrieve(conf->data, &vv); 152296341Sdelphij if (v != NULL) 153296341Sdelphij return (v->value); 154296341Sdelphij else 155296341Sdelphij return (NULL); 156296341Sdelphij } else 157296341Sdelphij return (getenv(name)); 158296341Sdelphij} 15968651Skris 160296341Sdelphij#if 0 /* There's no way to provide error checking 161296341Sdelphij * with this function, so force implementors 162296341Sdelphij * of the higher levels to get a string and 163296341Sdelphij * read the number themselves. */ 16468651Skrislong _CONF_get_number(CONF *conf, char *section, char *name) 165296341Sdelphij{ 166296341Sdelphij char *str; 167296341Sdelphij long ret = 0; 16868651Skris 169296341Sdelphij str = _CONF_get_string(conf, section, name); 170296341Sdelphij if (str == NULL) 171296341Sdelphij return (0); 172296341Sdelphij for (;;) { 173296341Sdelphij if (conf->meth->is_number(conf, *str)) 174296341Sdelphij ret = ret * 10 + conf->meth->to_int(conf, *str); 175296341Sdelphij else 176296341Sdelphij return (ret); 177296341Sdelphij str++; 178296341Sdelphij } 179296341Sdelphij} 180109998Smarkm#endif 18168651Skris 182238405Sjkimstatic unsigned long conf_value_hash(const CONF_VALUE *v) 183296341Sdelphij{ 184296341Sdelphij return (lh_strhash(v->section) << 2) ^ lh_strhash(v->name); 185296341Sdelphij} 186296341Sdelphij 187238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(conf_value, CONF_VALUE) 188238405Sjkim 189238405Sjkimstatic int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b) 190296341Sdelphij{ 191296341Sdelphij int i; 192238405Sjkim 193296341Sdelphij if (a->section != b->section) { 194296341Sdelphij i = strcmp(a->section, b->section); 195296341Sdelphij if (i) 196296341Sdelphij return (i); 197296341Sdelphij } 198238405Sjkim 199296341Sdelphij if ((a->name != NULL) && (b->name != NULL)) { 200296341Sdelphij i = strcmp(a->name, b->name); 201296341Sdelphij return (i); 202296341Sdelphij } else if (a->name == b->name) 203296341Sdelphij return (0); 204296341Sdelphij else 205296341Sdelphij return ((a->name == NULL) ? -1 : 1); 206296341Sdelphij} 207296341Sdelphij 208238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(conf_value, CONF_VALUE) 209238405Sjkim 21068651Skrisint _CONF_new_data(CONF *conf) 211296341Sdelphij{ 212296341Sdelphij if (conf == NULL) { 213296341Sdelphij return 0; 214296341Sdelphij } 215296341Sdelphij if (conf->data == NULL) 216296341Sdelphij if ((conf->data = lh_CONF_VALUE_new()) == NULL) { 217296341Sdelphij return 0; 218296341Sdelphij } 219296341Sdelphij return 1; 220296341Sdelphij} 22168651Skris 22268651Skrisvoid _CONF_free_data(CONF *conf) 223296341Sdelphij{ 224296341Sdelphij if (conf == NULL || conf->data == NULL) 225296341Sdelphij return; 22668651Skris 227296341Sdelphij lh_CONF_VALUE_down_load(conf->data) = 0; /* evil thing to make * sure the 228296341Sdelphij * 'OPENSSL_free()' works as * 229296341Sdelphij * expected */ 230296341Sdelphij lh_CONF_VALUE_doall_arg(conf->data, 231296341Sdelphij LHASH_DOALL_ARG_FN(value_free_hash), 232296341Sdelphij LHASH_OF(CONF_VALUE), conf->data); 23368651Skris 234296341Sdelphij /* 235296341Sdelphij * We now have only 'section' entries in the hash table. Due to problems 236296341Sdelphij * with 237296341Sdelphij */ 23868651Skris 239296341Sdelphij lh_CONF_VALUE_doall(conf->data, LHASH_DOALL_FN(value_free_stack)); 240296341Sdelphij lh_CONF_VALUE_free(conf->data); 241296341Sdelphij} 24268651Skris 243296341Sdelphijstatic void value_free_hash_doall_arg(CONF_VALUE *a, 244296341Sdelphij LHASH_OF(CONF_VALUE) *conf) 245296341Sdelphij{ 246296341Sdelphij if (a->name != NULL) 247296341Sdelphij (void)lh_CONF_VALUE_delete(conf, a); 248296341Sdelphij} 24968651Skris 250238405Sjkimstatic void value_free_stack_doall(CONF_VALUE *a) 251296341Sdelphij{ 252296341Sdelphij CONF_VALUE *vv; 253296341Sdelphij STACK_OF(CONF_VALUE) *sk; 254296341Sdelphij int i; 25568651Skris 256296341Sdelphij if (a->name != NULL) 257296341Sdelphij return; 25868651Skris 259296341Sdelphij sk = (STACK_OF(CONF_VALUE) *)a->value; 260296341Sdelphij for (i = sk_CONF_VALUE_num(sk) - 1; i >= 0; i--) { 261296341Sdelphij vv = sk_CONF_VALUE_value(sk, i); 262296341Sdelphij OPENSSL_free(vv->value); 263296341Sdelphij OPENSSL_free(vv->name); 264296341Sdelphij OPENSSL_free(vv); 265296341Sdelphij } 266296341Sdelphij if (sk != NULL) 267296341Sdelphij sk_CONF_VALUE_free(sk); 268296341Sdelphij OPENSSL_free(a->section); 269296341Sdelphij OPENSSL_free(a); 270296341Sdelphij} 27168651Skris 27268651Skris/* Up until OpenSSL 0.9.5a, this was new_section */ 273109998SmarkmCONF_VALUE *_CONF_new_section(CONF *conf, const char *section) 274296341Sdelphij{ 275296341Sdelphij STACK_OF(CONF_VALUE) *sk = NULL; 276296341Sdelphij int ok = 0, i; 277296341Sdelphij CONF_VALUE *v = NULL, *vv; 27868651Skris 279296341Sdelphij if ((sk = sk_CONF_VALUE_new_null()) == NULL) 280296341Sdelphij goto err; 281296341Sdelphij if ((v = OPENSSL_malloc(sizeof(CONF_VALUE))) == NULL) 282296341Sdelphij goto err; 283296341Sdelphij i = strlen(section) + 1; 284296341Sdelphij if ((v->section = OPENSSL_malloc(i)) == NULL) 285296341Sdelphij goto err; 28668651Skris 287296341Sdelphij memcpy(v->section, section, i); 288296341Sdelphij v->name = NULL; 289296341Sdelphij v->value = (char *)sk; 29068651Skris 291296341Sdelphij vv = lh_CONF_VALUE_insert(conf->data, v); 292296341Sdelphij OPENSSL_assert(vv == NULL); 293296341Sdelphij ok = 1; 294296341Sdelphij err: 295296341Sdelphij if (!ok) { 296296341Sdelphij if (sk != NULL) 297296341Sdelphij sk_CONF_VALUE_free(sk); 298296341Sdelphij if (v != NULL) 299296341Sdelphij OPENSSL_free(v); 300296341Sdelphij v = NULL; 301296341Sdelphij } 302296341Sdelphij return (v); 303296341Sdelphij} 304296341Sdelphij 30568651SkrisIMPLEMENT_STACK_OF(CONF_VALUE) 306