1 | /* |
2 | * Copyright 2000-2018 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 | #include "e_os.h" |
11 | #include <stdio.h> |
12 | #include <string.h> |
13 | #include "internal/conf.h" |
14 | #include "crypto/ctype.h" |
15 | #include <openssl/crypto.h> |
16 | #include <openssl/err.h> |
17 | #include <openssl/conf.h> |
18 | #include <openssl/conf_api.h> |
19 | #include <openssl/lhash.h> |
20 | |
21 | static CONF_METHOD *default_CONF_method = NULL; |
22 | |
23 | /* Init a 'CONF' structure from an old LHASH */ |
24 | |
25 | void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash) |
26 | { |
27 | if (default_CONF_method == NULL) |
28 | default_CONF_method = NCONF_default(); |
29 | |
30 | default_CONF_method->init(conf); |
31 | conf->data = hash; |
32 | } |
33 | |
34 | /* |
35 | * The following section contains the "CONF classic" functions, rewritten in |
36 | * terms of the new CONF interface. |
37 | */ |
38 | |
39 | int CONF_set_default_method(CONF_METHOD *meth) |
40 | { |
41 | default_CONF_method = meth; |
42 | return 1; |
43 | } |
44 | |
45 | LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file, |
46 | long *eline) |
47 | { |
48 | LHASH_OF(CONF_VALUE) *ltmp; |
49 | BIO *in = NULL; |
50 | |
51 | #ifdef OPENSSL_SYS_VMS |
52 | in = BIO_new_file(file, "r" ); |
53 | #else |
54 | in = BIO_new_file(file, "rb" ); |
55 | #endif |
56 | if (in == NULL) { |
57 | CONFerr(CONF_F_CONF_LOAD, ERR_R_SYS_LIB); |
58 | return NULL; |
59 | } |
60 | |
61 | ltmp = CONF_load_bio(conf, in, eline); |
62 | BIO_free(in); |
63 | |
64 | return ltmp; |
65 | } |
66 | |
67 | #ifndef OPENSSL_NO_STDIO |
68 | LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp, |
69 | long *eline) |
70 | { |
71 | BIO *btmp; |
72 | LHASH_OF(CONF_VALUE) *ltmp; |
73 | if ((btmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { |
74 | CONFerr(CONF_F_CONF_LOAD_FP, ERR_R_BUF_LIB); |
75 | return NULL; |
76 | } |
77 | ltmp = CONF_load_bio(conf, btmp, eline); |
78 | BIO_free(btmp); |
79 | return ltmp; |
80 | } |
81 | #endif |
82 | |
83 | LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp, |
84 | long *eline) |
85 | { |
86 | CONF ctmp; |
87 | int ret; |
88 | |
89 | CONF_set_nconf(&ctmp, conf); |
90 | |
91 | ret = NCONF_load_bio(&ctmp, bp, eline); |
92 | if (ret) |
93 | return ctmp.data; |
94 | return NULL; |
95 | } |
96 | |
97 | STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf, |
98 | const char *section) |
99 | { |
100 | if (conf == NULL) { |
101 | return NULL; |
102 | } else { |
103 | CONF ctmp; |
104 | CONF_set_nconf(&ctmp, conf); |
105 | return NCONF_get_section(&ctmp, section); |
106 | } |
107 | } |
108 | |
109 | char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group, |
110 | const char *name) |
111 | { |
112 | if (conf == NULL) { |
113 | return NCONF_get_string(NULL, group, name); |
114 | } else { |
115 | CONF ctmp; |
116 | CONF_set_nconf(&ctmp, conf); |
117 | return NCONF_get_string(&ctmp, group, name); |
118 | } |
119 | } |
120 | |
121 | long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group, |
122 | const char *name) |
123 | { |
124 | int status; |
125 | long result = 0; |
126 | |
127 | ERR_set_mark(); |
128 | if (conf == NULL) { |
129 | status = NCONF_get_number_e(NULL, group, name, &result); |
130 | } else { |
131 | CONF ctmp; |
132 | CONF_set_nconf(&ctmp, conf); |
133 | status = NCONF_get_number_e(&ctmp, group, name, &result); |
134 | } |
135 | ERR_pop_to_mark(); |
136 | return status == 0 ? 0L : result; |
137 | } |
138 | |
139 | void CONF_free(LHASH_OF(CONF_VALUE) *conf) |
140 | { |
141 | CONF ctmp; |
142 | CONF_set_nconf(&ctmp, conf); |
143 | NCONF_free_data(&ctmp); |
144 | } |
145 | |
146 | #ifndef OPENSSL_NO_STDIO |
147 | int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out) |
148 | { |
149 | BIO *btmp; |
150 | int ret; |
151 | |
152 | if ((btmp = BIO_new_fp(out, BIO_NOCLOSE)) == NULL) { |
153 | CONFerr(CONF_F_CONF_DUMP_FP, ERR_R_BUF_LIB); |
154 | return 0; |
155 | } |
156 | ret = CONF_dump_bio(conf, btmp); |
157 | BIO_free(btmp); |
158 | return ret; |
159 | } |
160 | #endif |
161 | |
162 | int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out) |
163 | { |
164 | CONF ctmp; |
165 | CONF_set_nconf(&ctmp, conf); |
166 | return NCONF_dump_bio(&ctmp, out); |
167 | } |
168 | |
169 | /* |
170 | * The following section contains the "New CONF" functions. They are |
171 | * completely centralised around a new CONF structure that may contain |
172 | * basically anything, but at least a method pointer and a table of data. |
173 | * These functions are also written in terms of the bridge functions used by |
174 | * the "CONF classic" functions, for consistency. |
175 | */ |
176 | |
177 | CONF *NCONF_new(CONF_METHOD *meth) |
178 | { |
179 | CONF *ret; |
180 | |
181 | if (meth == NULL) |
182 | meth = NCONF_default(); |
183 | |
184 | ret = meth->create(meth); |
185 | if (ret == NULL) { |
186 | CONFerr(CONF_F_NCONF_NEW, ERR_R_MALLOC_FAILURE); |
187 | return NULL; |
188 | } |
189 | |
190 | return ret; |
191 | } |
192 | |
193 | void NCONF_free(CONF *conf) |
194 | { |
195 | if (conf == NULL) |
196 | return; |
197 | conf->meth->destroy(conf); |
198 | } |
199 | |
200 | void NCONF_free_data(CONF *conf) |
201 | { |
202 | if (conf == NULL) |
203 | return; |
204 | conf->meth->destroy_data(conf); |
205 | } |
206 | |
207 | int NCONF_load(CONF *conf, const char *file, long *eline) |
208 | { |
209 | if (conf == NULL) { |
210 | CONFerr(CONF_F_NCONF_LOAD, CONF_R_NO_CONF); |
211 | return 0; |
212 | } |
213 | |
214 | return conf->meth->load(conf, file, eline); |
215 | } |
216 | |
217 | #ifndef OPENSSL_NO_STDIO |
218 | int NCONF_load_fp(CONF *conf, FILE *fp, long *eline) |
219 | { |
220 | BIO *btmp; |
221 | int ret; |
222 | if ((btmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { |
223 | CONFerr(CONF_F_NCONF_LOAD_FP, ERR_R_BUF_LIB); |
224 | return 0; |
225 | } |
226 | ret = NCONF_load_bio(conf, btmp, eline); |
227 | BIO_free(btmp); |
228 | return ret; |
229 | } |
230 | #endif |
231 | |
232 | int NCONF_load_bio(CONF *conf, BIO *bp, long *eline) |
233 | { |
234 | if (conf == NULL) { |
235 | CONFerr(CONF_F_NCONF_LOAD_BIO, CONF_R_NO_CONF); |
236 | return 0; |
237 | } |
238 | |
239 | return conf->meth->load_bio(conf, bp, eline); |
240 | } |
241 | |
242 | STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section) |
243 | { |
244 | if (conf == NULL) { |
245 | CONFerr(CONF_F_NCONF_GET_SECTION, CONF_R_NO_CONF); |
246 | return NULL; |
247 | } |
248 | |
249 | if (section == NULL) { |
250 | CONFerr(CONF_F_NCONF_GET_SECTION, CONF_R_NO_SECTION); |
251 | return NULL; |
252 | } |
253 | |
254 | return _CONF_get_section_values(conf, section); |
255 | } |
256 | |
257 | char *NCONF_get_string(const CONF *conf, const char *group, const char *name) |
258 | { |
259 | char *s = _CONF_get_string(conf, group, name); |
260 | |
261 | /* |
262 | * Since we may get a value from an environment variable even if conf is |
263 | * NULL, let's check the value first |
264 | */ |
265 | if (s) |
266 | return s; |
267 | |
268 | if (conf == NULL) { |
269 | CONFerr(CONF_F_NCONF_GET_STRING, |
270 | CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE); |
271 | return NULL; |
272 | } |
273 | CONFerr(CONF_F_NCONF_GET_STRING, CONF_R_NO_VALUE); |
274 | ERR_add_error_data(4, "group=" , group, " name=" , name); |
275 | return NULL; |
276 | } |
277 | |
278 | static int default_is_number(const CONF *conf, char c) |
279 | { |
280 | return ossl_isdigit(c); |
281 | } |
282 | |
283 | static int default_to_int(const CONF *conf, char c) |
284 | { |
285 | return (int)(c - '0'); |
286 | } |
287 | |
288 | int NCONF_get_number_e(const CONF *conf, const char *group, const char *name, |
289 | long *result) |
290 | { |
291 | char *str; |
292 | long res; |
293 | int (*is_number)(const CONF *, char) = &default_is_number; |
294 | int (*to_int)(const CONF *, char) = &default_to_int; |
295 | |
296 | if (result == NULL) { |
297 | CONFerr(CONF_F_NCONF_GET_NUMBER_E, ERR_R_PASSED_NULL_PARAMETER); |
298 | return 0; |
299 | } |
300 | |
301 | str = NCONF_get_string(conf, group, name); |
302 | |
303 | if (str == NULL) |
304 | return 0; |
305 | |
306 | if (conf != NULL) { |
307 | if (conf->meth->is_number != NULL) |
308 | is_number = conf->meth->is_number; |
309 | if (conf->meth->to_int != NULL) |
310 | to_int = conf->meth->to_int; |
311 | } |
312 | for (res = 0; is_number(conf, *str); str++) { |
313 | const int d = to_int(conf, *str); |
314 | |
315 | if (res > (LONG_MAX - d) / 10L) { |
316 | CONFerr(CONF_F_NCONF_GET_NUMBER_E, CONF_R_NUMBER_TOO_LARGE); |
317 | return 0; |
318 | } |
319 | res = res * 10 + d; |
320 | } |
321 | |
322 | *result = res; |
323 | return 1; |
324 | } |
325 | |
326 | #ifndef OPENSSL_NO_STDIO |
327 | int NCONF_dump_fp(const CONF *conf, FILE *out) |
328 | { |
329 | BIO *btmp; |
330 | int ret; |
331 | if ((btmp = BIO_new_fp(out, BIO_NOCLOSE)) == NULL) { |
332 | CONFerr(CONF_F_NCONF_DUMP_FP, ERR_R_BUF_LIB); |
333 | return 0; |
334 | } |
335 | ret = NCONF_dump_bio(conf, btmp); |
336 | BIO_free(btmp); |
337 | return ret; |
338 | } |
339 | #endif |
340 | |
341 | int NCONF_dump_bio(const CONF *conf, BIO *out) |
342 | { |
343 | if (conf == NULL) { |
344 | CONFerr(CONF_F_NCONF_DUMP_BIO, CONF_R_NO_CONF); |
345 | return 0; |
346 | } |
347 | |
348 | return conf->meth->dump(conf, out); |
349 | } |
350 | |
351 | /* |
352 | * These routines call the C malloc/free, to avoid intermixing with |
353 | * OpenSSL function pointers before the library is initialized. |
354 | */ |
355 | OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void) |
356 | { |
357 | OPENSSL_INIT_SETTINGS *ret = malloc(sizeof(*ret)); |
358 | |
359 | if (ret == NULL) |
360 | return NULL; |
361 | |
362 | memset(ret, 0, sizeof(*ret)); |
363 | ret->flags = DEFAULT_CONF_MFLAGS; |
364 | |
365 | return ret; |
366 | } |
367 | |
368 | |
369 | #ifndef OPENSSL_NO_STDIO |
370 | int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings, |
371 | const char *filename) |
372 | { |
373 | char *newfilename = NULL; |
374 | |
375 | if (filename != NULL) { |
376 | newfilename = strdup(filename); |
377 | if (newfilename == NULL) |
378 | return 0; |
379 | } |
380 | |
381 | free(settings->filename); |
382 | settings->filename = newfilename; |
383 | |
384 | return 1; |
385 | } |
386 | |
387 | void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings, |
388 | unsigned long flags) |
389 | { |
390 | settings->flags = flags; |
391 | } |
392 | |
393 | int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings, |
394 | const char *appname) |
395 | { |
396 | char *newappname = NULL; |
397 | |
398 | if (appname != NULL) { |
399 | newappname = strdup(appname); |
400 | if (newappname == NULL) |
401 | return 0; |
402 | } |
403 | |
404 | free(settings->appname); |
405 | settings->appname = newappname; |
406 | |
407 | return 1; |
408 | } |
409 | #endif |
410 | |
411 | void OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS *settings) |
412 | { |
413 | free(settings->filename); |
414 | free(settings->appname); |
415 | free(settings); |
416 | } |
417 | |