1 | /* |
2 | * Copyright 1995-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 | /* Part of the code in here was originally in conf.c, which is now removed */ |
11 | |
12 | #include <stdio.h> |
13 | #include <string.h> |
14 | #include "internal/cryptlib.h" |
15 | #include "internal/o_dir.h" |
16 | #include <openssl/lhash.h> |
17 | #include <openssl/conf.h> |
18 | #include <openssl/conf_api.h> |
19 | #include "conf_def.h" |
20 | #include <openssl/buffer.h> |
21 | #include <openssl/err.h> |
22 | #ifndef OPENSSL_NO_POSIX_IO |
23 | # include <sys/stat.h> |
24 | # ifdef _WIN32 |
25 | # define stat _stat |
26 | # define strcasecmp _stricmp |
27 | # endif |
28 | #endif |
29 | |
30 | #ifndef S_ISDIR |
31 | # define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) |
32 | #endif |
33 | |
34 | /* |
35 | * The maximum length we can grow a value to after variable expansion. 64k |
36 | * should be more than enough for all reasonable uses. |
37 | */ |
38 | #define MAX_CONF_VALUE_LENGTH 65536 |
39 | |
40 | static int is_keytype(const CONF *conf, char c, unsigned short type); |
41 | static char *eat_ws(CONF *conf, char *p); |
42 | static void trim_ws(CONF *conf, char *start); |
43 | static char *eat_alpha_numeric(CONF *conf, char *p); |
44 | static void clear_comments(CONF *conf, char *p); |
45 | static int str_copy(CONF *conf, char *section, char **to, char *from); |
46 | static char *scan_quote(CONF *conf, char *p); |
47 | static char *scan_dquote(CONF *conf, char *p); |
48 | #define scan_esc(conf,p) (((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2))) |
49 | #ifndef OPENSSL_NO_POSIX_IO |
50 | static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx, |
51 | char **dirpath); |
52 | static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx); |
53 | #endif |
54 | |
55 | static CONF *def_create(CONF_METHOD *meth); |
56 | static int def_init_default(CONF *conf); |
57 | #ifndef OPENSSL_NO_DEPRECATED_3_0 |
58 | static int def_init_WIN32(CONF *conf); |
59 | #endif |
60 | static int def_destroy(CONF *conf); |
61 | static int def_destroy_data(CONF *conf); |
62 | static int def_load(CONF *conf, const char *name, long *eline); |
63 | static int def_load_bio(CONF *conf, BIO *bp, long *eline); |
64 | static int def_dump(const CONF *conf, BIO *bp); |
65 | static int def_is_number(const CONF *conf, char c); |
66 | static int def_to_int(const CONF *conf, char c); |
67 | |
68 | static CONF_METHOD default_method = { |
69 | "OpenSSL default" , |
70 | def_create, |
71 | def_init_default, |
72 | def_destroy, |
73 | def_destroy_data, |
74 | def_load_bio, |
75 | def_dump, |
76 | def_is_number, |
77 | def_to_int, |
78 | def_load |
79 | }; |
80 | |
81 | CONF_METHOD *NCONF_default(void) |
82 | { |
83 | return &default_method; |
84 | } |
85 | |
86 | #ifndef OPENSSL_NO_DEPRECATED_3_0 |
87 | static CONF_METHOD WIN32_method = { |
88 | "WIN32" , |
89 | def_create, |
90 | def_init_WIN32, |
91 | def_destroy, |
92 | def_destroy_data, |
93 | def_load_bio, |
94 | def_dump, |
95 | def_is_number, |
96 | def_to_int, |
97 | def_load |
98 | }; |
99 | |
100 | CONF_METHOD *NCONF_WIN32(void) |
101 | { |
102 | return &WIN32_method; |
103 | } |
104 | #endif |
105 | |
106 | static CONF *def_create(CONF_METHOD *meth) |
107 | { |
108 | CONF *ret; |
109 | |
110 | ret = OPENSSL_malloc(sizeof(*ret)); |
111 | if (ret != NULL) |
112 | if (meth->init(ret) == 0) { |
113 | OPENSSL_free(ret); |
114 | ret = NULL; |
115 | } |
116 | return ret; |
117 | } |
118 | |
119 | static int def_init_default(CONF *conf) |
120 | { |
121 | if (conf == NULL) |
122 | return 0; |
123 | |
124 | memset(conf, 0, sizeof(*conf)); |
125 | conf->meth = &default_method; |
126 | conf->meth_data = (void *)CONF_type_default; |
127 | |
128 | return 1; |
129 | } |
130 | |
131 | #ifndef OPENSSL_NO_DEPRECATED_3_0 |
132 | static int def_init_WIN32(CONF *conf) |
133 | { |
134 | if (conf == NULL) |
135 | return 0; |
136 | |
137 | memset(conf, 0, sizeof(*conf)); |
138 | conf->meth = &WIN32_method; |
139 | conf->meth_data = (void *)CONF_type_win32; |
140 | |
141 | return 1; |
142 | } |
143 | #endif |
144 | |
145 | static int def_destroy(CONF *conf) |
146 | { |
147 | if (def_destroy_data(conf)) { |
148 | OPENSSL_free(conf); |
149 | return 1; |
150 | } |
151 | return 0; |
152 | } |
153 | |
154 | static int def_destroy_data(CONF *conf) |
155 | { |
156 | if (conf == NULL) |
157 | return 0; |
158 | _CONF_free_data(conf); |
159 | return 1; |
160 | } |
161 | |
162 | static int def_load(CONF *conf, const char *name, long *line) |
163 | { |
164 | int ret; |
165 | BIO *in = NULL; |
166 | |
167 | #ifdef OPENSSL_SYS_VMS |
168 | in = BIO_new_file(name, "r" ); |
169 | #else |
170 | in = BIO_new_file(name, "rb" ); |
171 | #endif |
172 | if (in == NULL) { |
173 | if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE) |
174 | CONFerr(CONF_F_DEF_LOAD, CONF_R_NO_SUCH_FILE); |
175 | else |
176 | CONFerr(CONF_F_DEF_LOAD, ERR_R_SYS_LIB); |
177 | return 0; |
178 | } |
179 | |
180 | ret = def_load_bio(conf, in, line); |
181 | BIO_free(in); |
182 | |
183 | return ret; |
184 | } |
185 | |
186 | static int def_load_bio(CONF *conf, BIO *in, long *line) |
187 | { |
188 | /* The macro BUFSIZE conflicts with a system macro in VxWorks */ |
189 | #define CONFBUFSIZE 512 |
190 | int bufnum = 0, i, ii; |
191 | BUF_MEM *buff = NULL; |
192 | char *s, *p, *end; |
193 | int again; |
194 | long eline = 0; |
195 | char btmp[DECIMAL_SIZE(eline) + 1]; |
196 | CONF_VALUE *v = NULL, *tv; |
197 | CONF_VALUE *sv = NULL; |
198 | char *section = NULL, *buf; |
199 | char *start, *psection, *pname; |
200 | void *h = (void *)(conf->data); |
201 | STACK_OF(BIO) *biosk = NULL; |
202 | #ifndef OPENSSL_NO_POSIX_IO |
203 | char *dirpath = NULL; |
204 | OPENSSL_DIR_CTX *dirctx = NULL; |
205 | #endif |
206 | |
207 | if ((buff = BUF_MEM_new()) == NULL) { |
208 | CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB); |
209 | goto err; |
210 | } |
211 | |
212 | section = OPENSSL_strdup("default" ); |
213 | if (section == NULL) { |
214 | CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); |
215 | goto err; |
216 | } |
217 | |
218 | if (_CONF_new_data(conf) == 0) { |
219 | CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); |
220 | goto err; |
221 | } |
222 | |
223 | sv = _CONF_new_section(conf, section); |
224 | if (sv == NULL) { |
225 | CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); |
226 | goto err; |
227 | } |
228 | |
229 | bufnum = 0; |
230 | again = 0; |
231 | for (;;) { |
232 | if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) { |
233 | CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB); |
234 | goto err; |
235 | } |
236 | p = &(buff->data[bufnum]); |
237 | *p = '\0'; |
238 | read_retry: |
239 | BIO_gets(in, p, CONFBUFSIZE - 1); |
240 | p[CONFBUFSIZE - 1] = '\0'; |
241 | ii = i = strlen(p); |
242 | if (i == 0 && !again) { |
243 | /* the currently processed BIO is at EOF */ |
244 | BIO *parent; |
245 | |
246 | #ifndef OPENSSL_NO_POSIX_IO |
247 | /* continue processing with the next file from directory */ |
248 | if (dirctx != NULL) { |
249 | BIO *next; |
250 | |
251 | if ((next = get_next_file(dirpath, &dirctx)) != NULL) { |
252 | BIO_vfree(in); |
253 | in = next; |
254 | goto read_retry; |
255 | } else { |
256 | OPENSSL_free(dirpath); |
257 | dirpath = NULL; |
258 | } |
259 | } |
260 | #endif |
261 | /* no more files in directory, continue with processing parent */ |
262 | if ((parent = sk_BIO_pop(biosk)) == NULL) { |
263 | /* everything processed get out of the loop */ |
264 | break; |
265 | } else { |
266 | BIO_vfree(in); |
267 | in = parent; |
268 | goto read_retry; |
269 | } |
270 | } |
271 | again = 0; |
272 | while (i > 0) { |
273 | if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) |
274 | break; |
275 | else |
276 | i--; |
277 | } |
278 | /* |
279 | * we removed some trailing stuff so there is a new line on the end. |
280 | */ |
281 | if (ii && i == ii) |
282 | again = 1; /* long line */ |
283 | else { |
284 | p[i] = '\0'; |
285 | eline++; /* another input line */ |
286 | } |
287 | |
288 | /* we now have a line with trailing \r\n removed */ |
289 | |
290 | /* i is the number of bytes */ |
291 | bufnum += i; |
292 | |
293 | v = NULL; |
294 | /* check for line continuation */ |
295 | if (bufnum >= 1) { |
296 | /* |
297 | * If we have bytes and the last char '\\' and second last char |
298 | * is not '\\' |
299 | */ |
300 | p = &(buff->data[bufnum - 1]); |
301 | if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) { |
302 | bufnum--; |
303 | again = 1; |
304 | } |
305 | } |
306 | if (again) |
307 | continue; |
308 | bufnum = 0; |
309 | buf = buff->data; |
310 | |
311 | clear_comments(conf, buf); |
312 | s = eat_ws(conf, buf); |
313 | if (IS_EOF(conf, *s)) |
314 | continue; /* blank line */ |
315 | if (*s == '[') { |
316 | char *ss; |
317 | |
318 | s++; |
319 | start = eat_ws(conf, s); |
320 | ss = start; |
321 | again: |
322 | end = eat_alpha_numeric(conf, ss); |
323 | p = eat_ws(conf, end); |
324 | if (*p != ']') { |
325 | if (*p != '\0' && ss != p) { |
326 | ss = p; |
327 | goto again; |
328 | } |
329 | CONFerr(CONF_F_DEF_LOAD_BIO, |
330 | CONF_R_MISSING_CLOSE_SQUARE_BRACKET); |
331 | goto err; |
332 | } |
333 | *end = '\0'; |
334 | if (!str_copy(conf, NULL, §ion, start)) |
335 | goto err; |
336 | if ((sv = _CONF_get_section(conf, section)) == NULL) |
337 | sv = _CONF_new_section(conf, section); |
338 | if (sv == NULL) { |
339 | CONFerr(CONF_F_DEF_LOAD_BIO, |
340 | CONF_R_UNABLE_TO_CREATE_NEW_SECTION); |
341 | goto err; |
342 | } |
343 | continue; |
344 | } else { |
345 | pname = s; |
346 | end = eat_alpha_numeric(conf, s); |
347 | if ((end[0] == ':') && (end[1] == ':')) { |
348 | *end = '\0'; |
349 | end += 2; |
350 | psection = pname; |
351 | pname = end; |
352 | end = eat_alpha_numeric(conf, end); |
353 | } else { |
354 | psection = section; |
355 | } |
356 | p = eat_ws(conf, end); |
357 | if (strncmp(pname, ".pragma" , 7) == 0 |
358 | && (p != pname + 7 || *p == '=')) { |
359 | char *pval; |
360 | |
361 | if (*p == '=') { |
362 | p++; |
363 | p = eat_ws(conf, p); |
364 | } |
365 | trim_ws(conf, p); |
366 | |
367 | /* Pragma values take the form keyword:value */ |
368 | pval = strchr(p, ':'); |
369 | if (pval == NULL || pval == p || pval[1] == '\0') { |
370 | CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_INVALID_PRAGMA); |
371 | goto err; |
372 | } |
373 | |
374 | *pval++ = '\0'; |
375 | trim_ws(conf, p); |
376 | pval = eat_ws(conf, pval); |
377 | |
378 | /* |
379 | * Known pragmas: |
380 | * |
381 | * dollarid takes "on", "true or "off", "false" |
382 | */ |
383 | if (strcmp(p, "dollarid" ) == 0) { |
384 | if (strcmp(pval, "on" ) == 0 |
385 | || strcmp(pval, "true" ) == 0) { |
386 | conf->flag_dollarid = 1; |
387 | } else if (strcmp(pval, "off" ) == 0 |
388 | || strcmp(pval, "false" ) == 0) { |
389 | conf->flag_dollarid = 0; |
390 | } else { |
391 | CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_INVALID_PRAGMA); |
392 | goto err; |
393 | } |
394 | } |
395 | /* |
396 | * We *ignore* any unknown pragma. |
397 | */ |
398 | continue; |
399 | } else if (strncmp(pname, ".include" , 8) == 0 |
400 | && (p != pname + 8 || *p == '=')) { |
401 | char *include = NULL; |
402 | BIO *next; |
403 | const char *include_dir = ossl_safe_getenv("OPENSSL_CONF_INCLUDE" ); |
404 | char *include_path = NULL; |
405 | |
406 | if (*p == '=') { |
407 | p++; |
408 | p = eat_ws(conf, p); |
409 | } |
410 | trim_ws(conf, p); |
411 | if (!str_copy(conf, psection, &include, p)) |
412 | goto err; |
413 | |
414 | if (include_dir != NULL) { |
415 | size_t newlen = strlen(include_dir) + strlen(include) + 2; |
416 | |
417 | include_path = OPENSSL_malloc(newlen); |
418 | OPENSSL_strlcpy(include_path, include_dir, newlen); |
419 | OPENSSL_strlcat(include_path, "/" , newlen); |
420 | OPENSSL_strlcat(include_path, include, newlen); |
421 | } else { |
422 | include_path = include; |
423 | } |
424 | |
425 | /* get the BIO of the included file */ |
426 | #ifndef OPENSSL_NO_POSIX_IO |
427 | next = process_include(include_path, &dirctx, &dirpath); |
428 | if (include_path != dirpath) { |
429 | /* dirpath will contain include in case of a directory */ |
430 | OPENSSL_free(include); |
431 | if (include_path != include) |
432 | OPENSSL_free(include_path); |
433 | } |
434 | #else |
435 | next = BIO_new_file(include_path, "r" ); |
436 | OPENSSL_free(include); |
437 | if (include_path != include) |
438 | OPENSSL_free(include_path); |
439 | #endif |
440 | |
441 | if (next != NULL) { |
442 | /* push the currently processing BIO onto stack */ |
443 | if (biosk == NULL) { |
444 | if ((biosk = sk_BIO_new_null()) == NULL) { |
445 | CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); |
446 | goto err; |
447 | } |
448 | } |
449 | if (!sk_BIO_push(biosk, in)) { |
450 | CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); |
451 | goto err; |
452 | } |
453 | /* continue with reading from the included BIO */ |
454 | in = next; |
455 | } |
456 | continue; |
457 | } else if (*p != '=') { |
458 | CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN); |
459 | ERR_add_error_data(2, "HERE-->" , p); |
460 | goto err; |
461 | } |
462 | *end = '\0'; |
463 | p++; |
464 | start = eat_ws(conf, p); |
465 | trim_ws(conf, start); |
466 | |
467 | if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) { |
468 | CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); |
469 | goto err; |
470 | } |
471 | v->name = OPENSSL_strdup(pname); |
472 | v->value = NULL; |
473 | if (v->name == NULL) { |
474 | CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); |
475 | goto err; |
476 | } |
477 | if (!str_copy(conf, psection, &(v->value), start)) |
478 | goto err; |
479 | |
480 | if (strcmp(psection, section) != 0) { |
481 | if ((tv = _CONF_get_section(conf, psection)) |
482 | == NULL) |
483 | tv = _CONF_new_section(conf, psection); |
484 | if (tv == NULL) { |
485 | CONFerr(CONF_F_DEF_LOAD_BIO, |
486 | CONF_R_UNABLE_TO_CREATE_NEW_SECTION); |
487 | goto err; |
488 | } |
489 | } else |
490 | tv = sv; |
491 | if (_CONF_add_string(conf, tv, v) == 0) { |
492 | CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); |
493 | goto err; |
494 | } |
495 | v = NULL; |
496 | } |
497 | } |
498 | BUF_MEM_free(buff); |
499 | OPENSSL_free(section); |
500 | /* |
501 | * No need to pop, since we only get here if the stack is empty. |
502 | * If this causes a BIO leak, THE ISSUE IS SOMEWHERE ELSE! |
503 | */ |
504 | sk_BIO_free(biosk); |
505 | return 1; |
506 | err: |
507 | BUF_MEM_free(buff); |
508 | OPENSSL_free(section); |
509 | /* |
510 | * Since |in| is the first element of the stack and should NOT be freed |
511 | * here, we cannot use sk_BIO_pop_free(). Instead, we pop and free one |
512 | * BIO at a time, making sure that the last one popped isn't. |
513 | */ |
514 | while (sk_BIO_num(biosk) > 0) { |
515 | BIO *popped = sk_BIO_pop(biosk); |
516 | BIO_vfree(in); |
517 | in = popped; |
518 | } |
519 | sk_BIO_free(biosk); |
520 | #ifndef OPENSSL_NO_POSIX_IO |
521 | OPENSSL_free(dirpath); |
522 | if (dirctx != NULL) |
523 | OPENSSL_DIR_end(&dirctx); |
524 | #endif |
525 | if (line != NULL) |
526 | *line = eline; |
527 | BIO_snprintf(btmp, sizeof(btmp), "%ld" , eline); |
528 | ERR_add_error_data(2, "line " , btmp); |
529 | if (h != conf->data) { |
530 | CONF_free(conf->data); |
531 | conf->data = NULL; |
532 | } |
533 | if (v != NULL) { |
534 | OPENSSL_free(v->name); |
535 | OPENSSL_free(v->value); |
536 | OPENSSL_free(v); |
537 | } |
538 | return 0; |
539 | } |
540 | |
541 | static void (CONF *conf, char *p) |
542 | { |
543 | for (;;) { |
544 | if (IS_FCOMMENT(conf, *p)) { |
545 | *p = '\0'; |
546 | return; |
547 | } |
548 | if (!IS_WS(conf, *p)) { |
549 | break; |
550 | } |
551 | p++; |
552 | } |
553 | |
554 | for (;;) { |
555 | if (IS_COMMENT(conf, *p)) { |
556 | *p = '\0'; |
557 | return; |
558 | } |
559 | if (IS_DQUOTE(conf, *p)) { |
560 | p = scan_dquote(conf, p); |
561 | continue; |
562 | } |
563 | if (IS_QUOTE(conf, *p)) { |
564 | p = scan_quote(conf, p); |
565 | continue; |
566 | } |
567 | if (IS_ESC(conf, *p)) { |
568 | p = scan_esc(conf, p); |
569 | continue; |
570 | } |
571 | if (IS_EOF(conf, *p)) |
572 | return; |
573 | else |
574 | p++; |
575 | } |
576 | } |
577 | |
578 | static int str_copy(CONF *conf, char *section, char **pto, char *from) |
579 | { |
580 | int q, r, rr = 0, to = 0, len = 0; |
581 | char *s, *e, *rp, *p, *rrp, *np, *cp, v; |
582 | BUF_MEM *buf; |
583 | |
584 | if ((buf = BUF_MEM_new()) == NULL) |
585 | return 0; |
586 | |
587 | len = strlen(from) + 1; |
588 | if (!BUF_MEM_grow(buf, len)) |
589 | goto err; |
590 | |
591 | for (;;) { |
592 | if (IS_QUOTE(conf, *from)) { |
593 | q = *from; |
594 | from++; |
595 | while (!IS_EOF(conf, *from) && (*from != q)) { |
596 | if (IS_ESC(conf, *from)) { |
597 | from++; |
598 | if (IS_EOF(conf, *from)) |
599 | break; |
600 | } |
601 | buf->data[to++] = *(from++); |
602 | } |
603 | if (*from == q) |
604 | from++; |
605 | } else if (IS_DQUOTE(conf, *from)) { |
606 | q = *from; |
607 | from++; |
608 | while (!IS_EOF(conf, *from)) { |
609 | if (*from == q) { |
610 | if (*(from + 1) == q) { |
611 | from++; |
612 | } else { |
613 | break; |
614 | } |
615 | } |
616 | buf->data[to++] = *(from++); |
617 | } |
618 | if (*from == q) |
619 | from++; |
620 | } else if (IS_ESC(conf, *from)) { |
621 | from++; |
622 | v = *(from++); |
623 | if (IS_EOF(conf, v)) |
624 | break; |
625 | else if (v == 'r') |
626 | v = '\r'; |
627 | else if (v == 'n') |
628 | v = '\n'; |
629 | else if (v == 'b') |
630 | v = '\b'; |
631 | else if (v == 't') |
632 | v = '\t'; |
633 | buf->data[to++] = v; |
634 | } else if (IS_EOF(conf, *from)) |
635 | break; |
636 | else if (*from == '$' |
637 | && (!conf->flag_dollarid |
638 | || from[1] == '{' |
639 | || from[1] == '(')) { |
640 | size_t newsize; |
641 | |
642 | /* try to expand it */ |
643 | rrp = NULL; |
644 | s = &(from[1]); |
645 | if (*s == '{') |
646 | q = '}'; |
647 | else if (*s == '(') |
648 | q = ')'; |
649 | else |
650 | q = 0; |
651 | |
652 | if (q) |
653 | s++; |
654 | cp = section; |
655 | e = np = s; |
656 | while (IS_ALNUM(conf, *e) |
657 | || (conf->flag_dollarid && IS_DOLLAR(conf, *e))) |
658 | e++; |
659 | if ((e[0] == ':') && (e[1] == ':')) { |
660 | cp = np; |
661 | rrp = e; |
662 | rr = *e; |
663 | *rrp = '\0'; |
664 | e += 2; |
665 | np = e; |
666 | while (IS_ALNUM(conf, *e) |
667 | || (conf->flag_dollarid && IS_DOLLAR(conf, *e))) |
668 | e++; |
669 | } |
670 | r = *e; |
671 | *e = '\0'; |
672 | rp = e; |
673 | if (q) { |
674 | if (r != q) { |
675 | CONFerr(CONF_F_STR_COPY, CONF_R_NO_CLOSE_BRACE); |
676 | goto err; |
677 | } |
678 | e++; |
679 | } |
680 | /*- |
681 | * So at this point we have |
682 | * np which is the start of the name string which is |
683 | * '\0' terminated. |
684 | * cp which is the start of the section string which is |
685 | * '\0' terminated. |
686 | * e is the 'next point after'. |
687 | * r and rr are the chars replaced by the '\0' |
688 | * rp and rrp is where 'r' and 'rr' came from. |
689 | */ |
690 | p = _CONF_get_string(conf, cp, np); |
691 | if (rrp != NULL) |
692 | *rrp = rr; |
693 | *rp = r; |
694 | if (p == NULL) { |
695 | CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_HAS_NO_VALUE); |
696 | goto err; |
697 | } |
698 | newsize = strlen(p) + buf->length - (e - from); |
699 | if (newsize > MAX_CONF_VALUE_LENGTH) { |
700 | CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_EXPANSION_TOO_LONG); |
701 | goto err; |
702 | } |
703 | if (!BUF_MEM_grow_clean(buf, newsize)) { |
704 | CONFerr(CONF_F_STR_COPY, ERR_R_MALLOC_FAILURE); |
705 | goto err; |
706 | } |
707 | while (*p) |
708 | buf->data[to++] = *(p++); |
709 | |
710 | /* |
711 | * Since we change the pointer 'from', we also have to change the |
712 | * perceived length of the string it points at. /RL |
713 | */ |
714 | len -= e - from; |
715 | from = e; |
716 | |
717 | /* |
718 | * In case there were no braces or parenthesis around the |
719 | * variable reference, we have to put back the character that was |
720 | * replaced with a '\0'. /RL |
721 | */ |
722 | *rp = r; |
723 | } else |
724 | buf->data[to++] = *(from++); |
725 | } |
726 | buf->data[to] = '\0'; |
727 | OPENSSL_free(*pto); |
728 | *pto = buf->data; |
729 | OPENSSL_free(buf); |
730 | return 1; |
731 | err: |
732 | BUF_MEM_free(buf); |
733 | return 0; |
734 | } |
735 | |
736 | #ifndef OPENSSL_NO_POSIX_IO |
737 | /* |
738 | * Check whether included path is a directory. |
739 | * Returns next BIO to process and in case of a directory |
740 | * also an opened directory context and the include path. |
741 | */ |
742 | static BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx, |
743 | char **dirpath) |
744 | { |
745 | struct stat st; |
746 | BIO *next; |
747 | |
748 | if (stat(include, &st) < 0) { |
749 | ERR_raise_data(ERR_LIB_SYS, errno, |
750 | "calling stat(%s)" , |
751 | include); |
752 | /* missing include file is not fatal error */ |
753 | return NULL; |
754 | } |
755 | |
756 | if (S_ISDIR(st.st_mode)) { |
757 | if (*dirctx != NULL) { |
758 | CONFerr(CONF_F_PROCESS_INCLUDE, |
759 | CONF_R_RECURSIVE_DIRECTORY_INCLUDE); |
760 | ERR_add_error_data(1, include); |
761 | return NULL; |
762 | } |
763 | /* a directory, load its contents */ |
764 | if ((next = get_next_file(include, dirctx)) != NULL) |
765 | *dirpath = include; |
766 | return next; |
767 | } |
768 | |
769 | next = BIO_new_file(include, "r" ); |
770 | return next; |
771 | } |
772 | |
773 | /* |
774 | * Get next file from the directory path. |
775 | * Returns BIO of the next file to read and updates dirctx. |
776 | */ |
777 | static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx) |
778 | { |
779 | const char *filename; |
780 | size_t pathlen; |
781 | |
782 | pathlen = strlen(path); |
783 | while ((filename = OPENSSL_DIR_read(dirctx, path)) != NULL) { |
784 | size_t namelen; |
785 | |
786 | namelen = strlen(filename); |
787 | |
788 | |
789 | if ((namelen > 5 && strcasecmp(filename + namelen - 5, ".conf" ) == 0) |
790 | || (namelen > 4 && strcasecmp(filename + namelen - 4, ".cnf" ) == 0)) { |
791 | size_t newlen; |
792 | char *newpath; |
793 | BIO *bio; |
794 | |
795 | newlen = pathlen + namelen + 2; |
796 | newpath = OPENSSL_zalloc(newlen); |
797 | if (newpath == NULL) { |
798 | CONFerr(CONF_F_GET_NEXT_FILE, ERR_R_MALLOC_FAILURE); |
799 | break; |
800 | } |
801 | #ifdef OPENSSL_SYS_VMS |
802 | /* |
803 | * If the given path isn't clear VMS syntax, |
804 | * we treat it as on Unix. |
805 | */ |
806 | if (path[pathlen - 1] == ']' |
807 | || path[pathlen - 1] == '>' |
808 | || path[pathlen - 1] == ':') { |
809 | /* Clear VMS directory syntax, just copy as is */ |
810 | OPENSSL_strlcpy(newpath, path, newlen); |
811 | } |
812 | #endif |
813 | if (newpath[0] == '\0') { |
814 | OPENSSL_strlcpy(newpath, path, newlen); |
815 | OPENSSL_strlcat(newpath, "/" , newlen); |
816 | } |
817 | OPENSSL_strlcat(newpath, filename, newlen); |
818 | |
819 | bio = BIO_new_file(newpath, "r" ); |
820 | OPENSSL_free(newpath); |
821 | /* Errors when opening files are non-fatal. */ |
822 | if (bio != NULL) |
823 | return bio; |
824 | } |
825 | } |
826 | OPENSSL_DIR_end(dirctx); |
827 | *dirctx = NULL; |
828 | return NULL; |
829 | } |
830 | #endif |
831 | |
832 | static int is_keytype(const CONF *conf, char c, unsigned short type) |
833 | { |
834 | const unsigned short * keytypes = (const unsigned short *) conf->meth_data; |
835 | unsigned char key = (unsigned char)c; |
836 | |
837 | #ifdef CHARSET_EBCDIC |
838 | # if CHAR_BIT > 8 |
839 | if (key > 255) { |
840 | /* key is out of range for os_toascii table */ |
841 | return 0; |
842 | } |
843 | # endif |
844 | /* convert key from ebcdic to ascii */ |
845 | key = os_toascii[key]; |
846 | #endif |
847 | |
848 | if (key > 127) { |
849 | /* key is not a seven bit ascii character */ |
850 | return 0; |
851 | } |
852 | |
853 | return (keytypes[key] & type) ? 1 : 0; |
854 | } |
855 | |
856 | static char *eat_ws(CONF *conf, char *p) |
857 | { |
858 | while (IS_WS(conf, *p) && (!IS_EOF(conf, *p))) |
859 | p++; |
860 | return p; |
861 | } |
862 | |
863 | static void trim_ws(CONF *conf, char *start) |
864 | { |
865 | char *p = start; |
866 | |
867 | while (!IS_EOF(conf, *p)) |
868 | p++; |
869 | p--; |
870 | while ((p >= start) && IS_WS(conf, *p)) |
871 | p--; |
872 | p++; |
873 | *p = '\0'; |
874 | } |
875 | |
876 | static char *eat_alpha_numeric(CONF *conf, char *p) |
877 | { |
878 | for (;;) { |
879 | if (IS_ESC(conf, *p)) { |
880 | p = scan_esc(conf, p); |
881 | continue; |
882 | } |
883 | if (!(IS_ALNUM_PUNCT(conf, *p) |
884 | || (conf->flag_dollarid && IS_DOLLAR(conf, *p)))) |
885 | return p; |
886 | p++; |
887 | } |
888 | } |
889 | |
890 | static char *scan_quote(CONF *conf, char *p) |
891 | { |
892 | int q = *p; |
893 | |
894 | p++; |
895 | while (!(IS_EOF(conf, *p)) && (*p != q)) { |
896 | if (IS_ESC(conf, *p)) { |
897 | p++; |
898 | if (IS_EOF(conf, *p)) |
899 | return p; |
900 | } |
901 | p++; |
902 | } |
903 | if (*p == q) |
904 | p++; |
905 | return p; |
906 | } |
907 | |
908 | static char *scan_dquote(CONF *conf, char *p) |
909 | { |
910 | int q = *p; |
911 | |
912 | p++; |
913 | while (!(IS_EOF(conf, *p))) { |
914 | if (*p == q) { |
915 | if (*(p + 1) == q) { |
916 | p++; |
917 | } else { |
918 | break; |
919 | } |
920 | } |
921 | p++; |
922 | } |
923 | if (*p == q) |
924 | p++; |
925 | return p; |
926 | } |
927 | |
928 | static void dump_value_doall_arg(const CONF_VALUE *a, BIO *out) |
929 | { |
930 | if (a->name) |
931 | BIO_printf(out, "[%s] %s=%s\n" , a->section, a->name, a->value); |
932 | else |
933 | BIO_printf(out, "[[%s]]\n" , a->section); |
934 | } |
935 | |
936 | IMPLEMENT_LHASH_DOALL_ARG_CONST(CONF_VALUE, BIO); |
937 | |
938 | static int def_dump(const CONF *conf, BIO *out) |
939 | { |
940 | lh_CONF_VALUE_doall_BIO(conf->data, dump_value_doall_arg, out); |
941 | return 1; |
942 | } |
943 | |
944 | static int def_is_number(const CONF *conf, char c) |
945 | { |
946 | return IS_NUMBER(conf, c); |
947 | } |
948 | |
949 | static int def_to_int(const CONF *conf, char c) |
950 | { |
951 | return c - '0'; |
952 | } |
953 | |