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