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