1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/* Part of the code in here was originally in conf.c, which is now removed */
11e1051a39Sopenharmony_ci
12e1051a39Sopenharmony_ci#include "e_os.h"
13e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
14e1051a39Sopenharmony_ci#include <stdlib.h>
15e1051a39Sopenharmony_ci#include <string.h>
16e1051a39Sopenharmony_ci#include <openssl/conf.h>
17e1051a39Sopenharmony_ci#include <openssl/conf_api.h>
18e1051a39Sopenharmony_ci#include "conf_local.h"
19e1051a39Sopenharmony_ci
20e1051a39Sopenharmony_cistatic void value_free_hash(const CONF_VALUE *a, LHASH_OF(CONF_VALUE) *conf);
21e1051a39Sopenharmony_cistatic void value_free_stack_doall(CONF_VALUE *a);
22e1051a39Sopenharmony_ci
23e1051a39Sopenharmony_ciCONF_VALUE *_CONF_get_section(const CONF *conf, const char *section)
24e1051a39Sopenharmony_ci{
25e1051a39Sopenharmony_ci    CONF_VALUE vv;
26e1051a39Sopenharmony_ci
27e1051a39Sopenharmony_ci    if (conf == NULL || section == NULL)
28e1051a39Sopenharmony_ci        return NULL;
29e1051a39Sopenharmony_ci    vv.name = NULL;
30e1051a39Sopenharmony_ci    vv.section = (char *)section;
31e1051a39Sopenharmony_ci    return conf->data != NULL ? lh_CONF_VALUE_retrieve(conf->data, &vv) : NULL;
32e1051a39Sopenharmony_ci}
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_ciSTACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf,
35e1051a39Sopenharmony_ci                                               const char *section)
36e1051a39Sopenharmony_ci{
37e1051a39Sopenharmony_ci    CONF_VALUE *v;
38e1051a39Sopenharmony_ci
39e1051a39Sopenharmony_ci    v = _CONF_get_section(conf, section);
40e1051a39Sopenharmony_ci    if (v == NULL)
41e1051a39Sopenharmony_ci        return NULL;
42e1051a39Sopenharmony_ci    return ((STACK_OF(CONF_VALUE) *)v->value);
43e1051a39Sopenharmony_ci}
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_ciint _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value)
46e1051a39Sopenharmony_ci{
47e1051a39Sopenharmony_ci    CONF_VALUE *v = NULL;
48e1051a39Sopenharmony_ci    STACK_OF(CONF_VALUE) *ts;
49e1051a39Sopenharmony_ci
50e1051a39Sopenharmony_ci    ts = (STACK_OF(CONF_VALUE) *)section->value;
51e1051a39Sopenharmony_ci
52e1051a39Sopenharmony_ci    value->section = section->section;
53e1051a39Sopenharmony_ci    if (!sk_CONF_VALUE_push(ts, value))
54e1051a39Sopenharmony_ci        return 0;
55e1051a39Sopenharmony_ci
56e1051a39Sopenharmony_ci    v = lh_CONF_VALUE_insert(conf->data, value);
57e1051a39Sopenharmony_ci    if (v != NULL) {
58e1051a39Sopenharmony_ci        (void)sk_CONF_VALUE_delete_ptr(ts, v);
59e1051a39Sopenharmony_ci        OPENSSL_free(v->name);
60e1051a39Sopenharmony_ci        OPENSSL_free(v->value);
61e1051a39Sopenharmony_ci        OPENSSL_free(v);
62e1051a39Sopenharmony_ci    }
63e1051a39Sopenharmony_ci    return 1;
64e1051a39Sopenharmony_ci}
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_cichar *_CONF_get_string(const CONF *conf, const char *section,
67e1051a39Sopenharmony_ci                       const char *name)
68e1051a39Sopenharmony_ci{
69e1051a39Sopenharmony_ci    CONF_VALUE *v, vv;
70e1051a39Sopenharmony_ci    char *p;
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_ci    if (name == NULL)
73e1051a39Sopenharmony_ci        return NULL;
74e1051a39Sopenharmony_ci    if (conf == NULL)
75e1051a39Sopenharmony_ci        return ossl_safe_getenv(name);
76e1051a39Sopenharmony_ci    if (conf->data == NULL)
77e1051a39Sopenharmony_ci        return NULL;
78e1051a39Sopenharmony_ci    if (section != NULL) {
79e1051a39Sopenharmony_ci        vv.name = (char *)name;
80e1051a39Sopenharmony_ci        vv.section = (char *)section;
81e1051a39Sopenharmony_ci        v = lh_CONF_VALUE_retrieve(conf->data, &vv);
82e1051a39Sopenharmony_ci        if (v != NULL)
83e1051a39Sopenharmony_ci            return v->value;
84e1051a39Sopenharmony_ci        if (strcmp(section, "ENV") == 0) {
85e1051a39Sopenharmony_ci            p = ossl_safe_getenv(name);
86e1051a39Sopenharmony_ci            if (p != NULL)
87e1051a39Sopenharmony_ci                return p;
88e1051a39Sopenharmony_ci        }
89e1051a39Sopenharmony_ci    }
90e1051a39Sopenharmony_ci    vv.section = "default";
91e1051a39Sopenharmony_ci    vv.name = (char *)name;
92e1051a39Sopenharmony_ci    v = lh_CONF_VALUE_retrieve(conf->data, &vv);
93e1051a39Sopenharmony_ci    if (v == NULL)
94e1051a39Sopenharmony_ci        return NULL;
95e1051a39Sopenharmony_ci    return v->value;
96e1051a39Sopenharmony_ci}
97e1051a39Sopenharmony_ci
98e1051a39Sopenharmony_cistatic unsigned long conf_value_hash(const CONF_VALUE *v)
99e1051a39Sopenharmony_ci{
100e1051a39Sopenharmony_ci    return (OPENSSL_LH_strhash(v->section) << 2) ^ OPENSSL_LH_strhash(v->name);
101e1051a39Sopenharmony_ci}
102e1051a39Sopenharmony_ci
103e1051a39Sopenharmony_cistatic int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b)
104e1051a39Sopenharmony_ci{
105e1051a39Sopenharmony_ci    int i;
106e1051a39Sopenharmony_ci
107e1051a39Sopenharmony_ci    if (a->section != b->section) {
108e1051a39Sopenharmony_ci        i = strcmp(a->section, b->section);
109e1051a39Sopenharmony_ci        if (i != 0)
110e1051a39Sopenharmony_ci            return i;
111e1051a39Sopenharmony_ci    }
112e1051a39Sopenharmony_ci
113e1051a39Sopenharmony_ci    if (a->name != NULL && b->name != NULL)
114e1051a39Sopenharmony_ci        return strcmp(a->name, b->name);
115e1051a39Sopenharmony_ci    if (a->name == b->name)
116e1051a39Sopenharmony_ci        return 0;
117e1051a39Sopenharmony_ci    return (a->name == NULL) ? -1 : 1;
118e1051a39Sopenharmony_ci}
119e1051a39Sopenharmony_ci
120e1051a39Sopenharmony_ciint _CONF_new_data(CONF *conf)
121e1051a39Sopenharmony_ci{
122e1051a39Sopenharmony_ci    if (conf == NULL)
123e1051a39Sopenharmony_ci        return 0;
124e1051a39Sopenharmony_ci    if (conf->data == NULL) {
125e1051a39Sopenharmony_ci        conf->data = lh_CONF_VALUE_new(conf_value_hash, conf_value_cmp);
126e1051a39Sopenharmony_ci        if (conf->data == NULL)
127e1051a39Sopenharmony_ci            return 0;
128e1051a39Sopenharmony_ci    }
129e1051a39Sopenharmony_ci    return 1;
130e1051a39Sopenharmony_ci}
131e1051a39Sopenharmony_ci
132e1051a39Sopenharmony_citypedef LHASH_OF(CONF_VALUE) LH_CONF_VALUE;
133e1051a39Sopenharmony_ci
134e1051a39Sopenharmony_ciIMPLEMENT_LHASH_DOALL_ARG_CONST(CONF_VALUE, LH_CONF_VALUE);
135e1051a39Sopenharmony_ci
136e1051a39Sopenharmony_civoid _CONF_free_data(CONF *conf)
137e1051a39Sopenharmony_ci{
138e1051a39Sopenharmony_ci    if (conf == NULL)
139e1051a39Sopenharmony_ci        return;
140e1051a39Sopenharmony_ci
141e1051a39Sopenharmony_ci    OPENSSL_free(conf->includedir);
142e1051a39Sopenharmony_ci    if (conf->data == NULL)
143e1051a39Sopenharmony_ci        return;
144e1051a39Sopenharmony_ci
145e1051a39Sopenharmony_ci    /* evil thing to make sure the 'OPENSSL_free()' works as expected */
146e1051a39Sopenharmony_ci    lh_CONF_VALUE_set_down_load(conf->data, 0);
147e1051a39Sopenharmony_ci    lh_CONF_VALUE_doall_LH_CONF_VALUE(conf->data, value_free_hash, conf->data);
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci    /*
150e1051a39Sopenharmony_ci     * We now have only 'section' entries in the hash table. Due to problems
151e1051a39Sopenharmony_ci     * with
152e1051a39Sopenharmony_ci     */
153e1051a39Sopenharmony_ci
154e1051a39Sopenharmony_ci    lh_CONF_VALUE_doall(conf->data, value_free_stack_doall);
155e1051a39Sopenharmony_ci    lh_CONF_VALUE_free(conf->data);
156e1051a39Sopenharmony_ci}
157e1051a39Sopenharmony_ci
158e1051a39Sopenharmony_cistatic void value_free_hash(const CONF_VALUE *a, LHASH_OF(CONF_VALUE) *conf)
159e1051a39Sopenharmony_ci{
160e1051a39Sopenharmony_ci    if (a->name != NULL)
161e1051a39Sopenharmony_ci        (void)lh_CONF_VALUE_delete(conf, a);
162e1051a39Sopenharmony_ci}
163e1051a39Sopenharmony_ci
164e1051a39Sopenharmony_cistatic void value_free_stack_doall(CONF_VALUE *a)
165e1051a39Sopenharmony_ci{
166e1051a39Sopenharmony_ci    CONF_VALUE *vv;
167e1051a39Sopenharmony_ci    STACK_OF(CONF_VALUE) *sk;
168e1051a39Sopenharmony_ci    int i;
169e1051a39Sopenharmony_ci
170e1051a39Sopenharmony_ci    if (a->name != NULL)
171e1051a39Sopenharmony_ci        return;
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ci    sk = (STACK_OF(CONF_VALUE) *)a->value;
174e1051a39Sopenharmony_ci    for (i = sk_CONF_VALUE_num(sk) - 1; i >= 0; i--) {
175e1051a39Sopenharmony_ci        vv = sk_CONF_VALUE_value(sk, i);
176e1051a39Sopenharmony_ci        OPENSSL_free(vv->value);
177e1051a39Sopenharmony_ci        OPENSSL_free(vv->name);
178e1051a39Sopenharmony_ci        OPENSSL_free(vv);
179e1051a39Sopenharmony_ci    }
180e1051a39Sopenharmony_ci    sk_CONF_VALUE_free(sk);
181e1051a39Sopenharmony_ci    OPENSSL_free(a->section);
182e1051a39Sopenharmony_ci    OPENSSL_free(a);
183e1051a39Sopenharmony_ci}
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ciCONF_VALUE *_CONF_new_section(CONF *conf, const char *section)
186e1051a39Sopenharmony_ci{
187e1051a39Sopenharmony_ci    STACK_OF(CONF_VALUE) *sk = NULL;
188e1051a39Sopenharmony_ci    int i;
189e1051a39Sopenharmony_ci    CONF_VALUE *v = NULL, *vv;
190e1051a39Sopenharmony_ci
191e1051a39Sopenharmony_ci    if ((sk = sk_CONF_VALUE_new_null()) == NULL)
192e1051a39Sopenharmony_ci        goto err;
193e1051a39Sopenharmony_ci    if ((v = OPENSSL_malloc(sizeof(*v))) == NULL)
194e1051a39Sopenharmony_ci        goto err;
195e1051a39Sopenharmony_ci    i = strlen(section) + 1;
196e1051a39Sopenharmony_ci    if ((v->section = OPENSSL_malloc(i)) == NULL)
197e1051a39Sopenharmony_ci        goto err;
198e1051a39Sopenharmony_ci
199e1051a39Sopenharmony_ci    memcpy(v->section, section, i);
200e1051a39Sopenharmony_ci    v->name = NULL;
201e1051a39Sopenharmony_ci    v->value = (char *)sk;
202e1051a39Sopenharmony_ci
203e1051a39Sopenharmony_ci    vv = lh_CONF_VALUE_insert(conf->data, v);
204e1051a39Sopenharmony_ci    if (vv != NULL || lh_CONF_VALUE_error(conf->data) > 0)
205e1051a39Sopenharmony_ci        goto err;
206e1051a39Sopenharmony_ci    return v;
207e1051a39Sopenharmony_ci
208e1051a39Sopenharmony_ci err:
209e1051a39Sopenharmony_ci    sk_CONF_VALUE_free(sk);
210e1051a39Sopenharmony_ci    if (v != NULL)
211e1051a39Sopenharmony_ci        OPENSSL_free(v->section);
212e1051a39Sopenharmony_ci    OPENSSL_free(v);
213e1051a39Sopenharmony_ci    return NULL;
214e1051a39Sopenharmony_ci}
215