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. 8296465Sdelphij * 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). 15296465Sdelphij * 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. 22296465Sdelphij * 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 :-). 37296465Sdelphij * 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)" 40296465Sdelphij * 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. 52296465Sdelphij * 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 62296465Sdelphij# undef NDEBUG /* avoid conflicting definitions */ 6368651Skris# define NDEBUG 6468651Skris#endif 6568651Skris 6668651Skris#include <assert.h> 67237998Sjkim#include <stdlib.h> 6868651Skris#include <string.h> 6968651Skris#include <openssl/conf.h> 7068651Skris#include <openssl/conf_api.h> 71109998Smarkm#include "e_os.h" 7268651Skris 7368651Skrisstatic void value_free_hash(CONF_VALUE *a, LHASH *conf); 74296465Sdelphijstatic void value_free_stack(CONF_VALUE *a, LHASH *conf); 75109998Smarkmstatic IMPLEMENT_LHASH_DOALL_ARG_FN(value_free_hash, CONF_VALUE *, LHASH *) 76109998Smarkmstatic IMPLEMENT_LHASH_DOALL_ARG_FN(value_free_stack, CONF_VALUE *, LHASH *) 77296465Sdelphij/* 78296465Sdelphij * We don't use function pointer casting or wrapper functions - but cast each 79296465Sdelphij * callback parameter inside the callback functions. 80296465Sdelphij */ 81109998Smarkm/* static unsigned long hash(CONF_VALUE *v); */ 82109998Smarkmstatic unsigned long hash(const void *v_void); 83109998Smarkm/* static int cmp_conf(CONF_VALUE *a,CONF_VALUE *b); */ 84296465Sdelphijstatic int cmp_conf(const void *a_void, const void *b_void); 8568651Skris 8668651Skris/* Up until OpenSSL 0.9.5a, this was get_section */ 87109998SmarkmCONF_VALUE *_CONF_get_section(const CONF *conf, const char *section) 88296465Sdelphij{ 89296465Sdelphij CONF_VALUE *v, vv; 9068651Skris 91296465Sdelphij if ((conf == NULL) || (section == NULL)) 92296465Sdelphij return (NULL); 93296465Sdelphij vv.name = NULL; 94296465Sdelphij vv.section = (char *)section; 95296465Sdelphij v = (CONF_VALUE *)lh_retrieve(conf->data, &vv); 96296465Sdelphij return (v); 97296465Sdelphij} 9868651Skris 9968651Skris/* Up until OpenSSL 0.9.5a, this was CONF_get_section */ 100109998SmarkmSTACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf, 101296465Sdelphij const char *section) 102296465Sdelphij{ 103296465Sdelphij CONF_VALUE *v; 10468651Skris 105296465Sdelphij v = _CONF_get_section(conf, section); 106296465Sdelphij if (v != NULL) 107296465Sdelphij return ((STACK_OF(CONF_VALUE) *)v->value); 108296465Sdelphij else 109296465Sdelphij return (NULL); 110296465Sdelphij} 11168651Skris 11268651Skrisint _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value) 113296465Sdelphij{ 114296465Sdelphij CONF_VALUE *v = NULL; 115296465Sdelphij STACK_OF(CONF_VALUE) *ts; 11668651Skris 117296465Sdelphij ts = (STACK_OF(CONF_VALUE) *)section->value; 11868651Skris 119296465Sdelphij value->section = section->section; 120296465Sdelphij if (!sk_CONF_VALUE_push(ts, value)) { 121296465Sdelphij return 0; 122296465Sdelphij } 12368651Skris 124296465Sdelphij v = (CONF_VALUE *)lh_insert(conf->data, value); 125296465Sdelphij if (v != NULL) { 126296465Sdelphij (void)sk_CONF_VALUE_delete_ptr(ts, v); 127296465Sdelphij OPENSSL_free(v->name); 128296465Sdelphij OPENSSL_free(v->value); 129296465Sdelphij OPENSSL_free(v); 130296465Sdelphij } 131296465Sdelphij return 1; 132296465Sdelphij} 13368651Skris 134296465Sdelphijchar *_CONF_get_string(const CONF *conf, const char *section, 135296465Sdelphij const char *name) 136296465Sdelphij{ 137296465Sdelphij CONF_VALUE *v, vv; 138296465Sdelphij char *p; 13968651Skris 140296465Sdelphij if (name == NULL) 141296465Sdelphij return (NULL); 142296465Sdelphij if (conf != NULL) { 143296465Sdelphij if (section != NULL) { 144296465Sdelphij vv.name = (char *)name; 145296465Sdelphij vv.section = (char *)section; 146296465Sdelphij v = (CONF_VALUE *)lh_retrieve(conf->data, &vv); 147296465Sdelphij if (v != NULL) 148296465Sdelphij return (v->value); 149296465Sdelphij if (strcmp(section, "ENV") == 0) { 150296465Sdelphij p = Getenv(name); 151296465Sdelphij if (p != NULL) 152296465Sdelphij return (p); 153296465Sdelphij } 154296465Sdelphij } 155296465Sdelphij vv.section = "default"; 156296465Sdelphij vv.name = (char *)name; 157296465Sdelphij v = (CONF_VALUE *)lh_retrieve(conf->data, &vv); 158296465Sdelphij if (v != NULL) 159296465Sdelphij return (v->value); 160296465Sdelphij else 161296465Sdelphij return (NULL); 162296465Sdelphij } else 163296465Sdelphij return (Getenv(name)); 164296465Sdelphij} 16568651Skris 166296465Sdelphij#if 0 /* There's no way to provide error checking 167296465Sdelphij * with this function, so force implementors 168296465Sdelphij * of the higher levels to get a string and 169296465Sdelphij * read the number themselves. */ 17068651Skrislong _CONF_get_number(CONF *conf, char *section, char *name) 171296465Sdelphij{ 172296465Sdelphij char *str; 173296465Sdelphij long ret = 0; 17468651Skris 175296465Sdelphij str = _CONF_get_string(conf, section, name); 176296465Sdelphij if (str == NULL) 177296465Sdelphij return (0); 178296465Sdelphij for (;;) { 179296465Sdelphij if (conf->meth->is_number(conf, *str)) 180296465Sdelphij ret = ret * 10 + conf->meth->to_int(conf, *str); 181296465Sdelphij else 182296465Sdelphij return (ret); 183296465Sdelphij str++; 184296465Sdelphij } 185296465Sdelphij} 186109998Smarkm#endif 18768651Skris 18868651Skrisint _CONF_new_data(CONF *conf) 189296465Sdelphij{ 190296465Sdelphij if (conf == NULL) { 191296465Sdelphij return 0; 192296465Sdelphij } 193296465Sdelphij if (conf->data == NULL) 194296465Sdelphij if ((conf->data = lh_new(hash, cmp_conf)) == NULL) { 195296465Sdelphij return 0; 196296465Sdelphij } 197296465Sdelphij return 1; 198296465Sdelphij} 19968651Skris 20068651Skrisvoid _CONF_free_data(CONF *conf) 201296465Sdelphij{ 202296465Sdelphij if (conf == NULL || conf->data == NULL) 203296465Sdelphij return; 20468651Skris 205296465Sdelphij conf->data->down_load = 0; /* evil thing to make sure the 206296465Sdelphij * 'OPENSSL_free()' works as expected */ 207296465Sdelphij lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(value_free_hash), conf->data); 20868651Skris 209296465Sdelphij /* 210296465Sdelphij * We now have only 'section' entries in the hash table. Due to problems 211296465Sdelphij * with 212296465Sdelphij */ 21368651Skris 214296465Sdelphij lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(value_free_stack), 215296465Sdelphij conf->data); 216296465Sdelphij lh_free(conf->data); 217296465Sdelphij} 21868651Skris 21968651Skrisstatic void value_free_hash(CONF_VALUE *a, LHASH *conf) 220296465Sdelphij{ 221296465Sdelphij if (a->name != NULL) { 222296465Sdelphij a = (CONF_VALUE *)lh_delete(conf, a); 223296465Sdelphij } 224296465Sdelphij} 22568651Skris 22668651Skrisstatic void value_free_stack(CONF_VALUE *a, LHASH *conf) 227296465Sdelphij{ 228296465Sdelphij CONF_VALUE *vv; 229296465Sdelphij STACK *sk; 230296465Sdelphij int i; 23168651Skris 232296465Sdelphij if (a->name != NULL) 233296465Sdelphij return; 23468651Skris 235296465Sdelphij sk = (STACK *) a->value; 236296465Sdelphij for (i = sk_num(sk) - 1; i >= 0; i--) { 237296465Sdelphij vv = (CONF_VALUE *)sk_value(sk, i); 238296465Sdelphij OPENSSL_free(vv->value); 239296465Sdelphij OPENSSL_free(vv->name); 240296465Sdelphij OPENSSL_free(vv); 241296465Sdelphij } 242296465Sdelphij if (sk != NULL) 243296465Sdelphij sk_free(sk); 244296465Sdelphij OPENSSL_free(a->section); 245296465Sdelphij OPENSSL_free(a); 246296465Sdelphij} 24768651Skris 248109998Smarkm/* static unsigned long hash(CONF_VALUE *v) */ 249109998Smarkmstatic unsigned long hash(const void *v_void) 250296465Sdelphij{ 251296465Sdelphij CONF_VALUE *v = (CONF_VALUE *)v_void; 252296465Sdelphij return ((lh_strhash(v->section) << 2) ^ lh_strhash(v->name)); 253296465Sdelphij} 25468651Skris 255109998Smarkm/* static int cmp_conf(CONF_VALUE *a, CONF_VALUE *b) */ 256296465Sdelphijstatic int cmp_conf(const void *a_void, const void *b_void) 257296465Sdelphij{ 258296465Sdelphij int i; 259296465Sdelphij CONF_VALUE *a = (CONF_VALUE *)a_void; 260296465Sdelphij CONF_VALUE *b = (CONF_VALUE *)b_void; 26168651Skris 262296465Sdelphij if (a->section != b->section) { 263296465Sdelphij i = strcmp(a->section, b->section); 264296465Sdelphij if (i) 265296465Sdelphij return (i); 266296465Sdelphij } 26768651Skris 268296465Sdelphij if ((a->name != NULL) && (b->name != NULL)) { 269296465Sdelphij i = strcmp(a->name, b->name); 270296465Sdelphij return (i); 271296465Sdelphij } else if (a->name == b->name) 272296465Sdelphij return (0); 273296465Sdelphij else 274296465Sdelphij return ((a->name == NULL) ? -1 : 1); 275296465Sdelphij} 27668651Skris 27768651Skris/* Up until OpenSSL 0.9.5a, this was new_section */ 278109998SmarkmCONF_VALUE *_CONF_new_section(CONF *conf, const char *section) 279296465Sdelphij{ 280296465Sdelphij STACK *sk = NULL; 281296465Sdelphij int ok = 0, i; 282296465Sdelphij CONF_VALUE *v = NULL, *vv; 28368651Skris 284296465Sdelphij if ((sk = sk_new_null()) == NULL) 285296465Sdelphij goto err; 286296465Sdelphij if ((v = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE))) == NULL) 287296465Sdelphij goto err; 288296465Sdelphij i = strlen(section) + 1; 289296465Sdelphij if ((v->section = (char *)OPENSSL_malloc(i)) == NULL) 290296465Sdelphij goto err; 29168651Skris 292296465Sdelphij memcpy(v->section, section, i); 293296465Sdelphij v->name = NULL; 294296465Sdelphij v->value = (char *)sk; 29568651Skris 296296465Sdelphij vv = (CONF_VALUE *)lh_insert(conf->data, v); 297296465Sdelphij OPENSSL_assert(vv == NULL); 298296465Sdelphij ok = 1; 299296465Sdelphij err: 300296465Sdelphij if (!ok) { 301296465Sdelphij if (sk != NULL) 302296465Sdelphij sk_free(sk); 303296465Sdelphij if (v != NULL) 304296465Sdelphij OPENSSL_free(v); 305296465Sdelphij v = NULL; 306296465Sdelphij } 307296465Sdelphij return (v); 308296465Sdelphij} 309296465Sdelphij 31068651SkrisIMPLEMENT_STACK_OF(CONF_VALUE) 311