1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
57 #include <openssl/conf.h>
58
59 #include <string.h>
60 #include <ctype.h>
61
62 #include <openssl/bio.h>
63 #include <openssl/buf.h>
64 #include <openssl/err.h>
65 #include <openssl/lhash.h>
66 #include <openssl/mem.h>
67
68 #include "conf_def.h"
69 #include "internal.h"
70 #include "../internal.h"
71 #include "../lhash/internal.h"
72
73
74 DEFINE_LHASH_OF(CONF_VALUE)
75
76 struct conf_st {
77 LHASH_OF(CONF_VALUE) *data;
78 };
79
80 static const char kDefaultSectionName[] = "default";
81
82 // The maximum length we can grow a value to after variable expansion. 64k
83 // should be more than enough for all reasonable uses.
84 #define MAX_CONF_VALUE_LENGTH 65536
85
conf_value_hash(const CONF_VALUE * v)86 static uint32_t conf_value_hash(const CONF_VALUE *v) {
87 const uint32_t section_hash = v->section ? OPENSSL_strhash(v->section) : 0;
88 const uint32_t name_hash = v->name ? OPENSSL_strhash(v->name) : 0;
89 return (section_hash << 2) ^ name_hash;
90 }
91
conf_value_cmp(const CONF_VALUE * a,const CONF_VALUE * b)92 static int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b) {
93 int i;
94
95 if (a->section != b->section) {
96 i = strcmp(a->section, b->section);
97 if (i) {
98 return i;
99 }
100 }
101
102 if (a->name != NULL && b->name != NULL) {
103 return strcmp(a->name, b->name);
104 } else if (a->name == b->name) {
105 return 0;
106 } else {
107 return (a->name == NULL) ? -1 : 1;
108 }
109 }
110
NCONF_new(void * method)111 CONF *NCONF_new(void *method) {
112 CONF *conf;
113
114 if (method != NULL) {
115 return NULL;
116 }
117
118 conf = OPENSSL_malloc(sizeof(CONF));
119 if (conf == NULL) {
120 return NULL;
121 }
122
123 conf->data = lh_CONF_VALUE_new(conf_value_hash, conf_value_cmp);
124 if (conf->data == NULL) {
125 OPENSSL_free(conf);
126 return NULL;
127 }
128
129 return conf;
130 }
131
CONF_VALUE_new(void)132 CONF_VALUE *CONF_VALUE_new(void) {
133 CONF_VALUE *v = OPENSSL_malloc(sizeof(CONF_VALUE));
134 if (!v) {
135 OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE);
136 return NULL;
137 }
138 OPENSSL_memset(v, 0, sizeof(CONF_VALUE));
139 return v;
140 }
141
value_free_contents(CONF_VALUE * value)142 static void value_free_contents(CONF_VALUE *value) {
143 if (value->section) {
144 OPENSSL_free(value->section);
145 }
146 if (value->name) {
147 OPENSSL_free(value->name);
148 if (value->value) {
149 OPENSSL_free(value->value);
150 }
151 } else {
152 if (value->value) {
153 sk_CONF_VALUE_free((STACK_OF(CONF_VALUE)*)value->value);
154 }
155 }
156 }
157
value_free(CONF_VALUE * value)158 static void value_free(CONF_VALUE *value) {
159 value_free_contents(value);
160 OPENSSL_free(value);
161 }
162
value_free_arg(CONF_VALUE * value,void * arg)163 static void value_free_arg(CONF_VALUE *value, void *arg) { value_free(value); }
164
NCONF_free(CONF * conf)165 void NCONF_free(CONF *conf) {
166 if (conf == NULL || conf->data == NULL) {
167 return;
168 }
169
170 lh_CONF_VALUE_doall_arg(conf->data, value_free_arg, NULL);
171 lh_CONF_VALUE_free(conf->data);
172 OPENSSL_free(conf);
173 }
174
NCONF_new_section(const CONF * conf,const char * section)175 static CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) {
176 STACK_OF(CONF_VALUE) *sk = NULL;
177 int ok = 0;
178 CONF_VALUE *v = NULL, *old_value;
179
180 sk = sk_CONF_VALUE_new_null();
181 v = CONF_VALUE_new();
182 if (sk == NULL || v == NULL) {
183 goto err;
184 }
185 v->section = OPENSSL_strdup(section);
186 if (v->section == NULL) {
187 goto err;
188 }
189
190 v->name = NULL;
191 v->value = (char *)sk;
192
193 if (!lh_CONF_VALUE_insert(conf->data, &old_value, v)) {
194 goto err;
195 }
196 if (old_value) {
197 value_free(old_value);
198 }
199 ok = 1;
200
201 err:
202 if (!ok) {
203 if (sk != NULL) {
204 sk_CONF_VALUE_free(sk);
205 }
206 if (v != NULL) {
207 OPENSSL_free(v);
208 }
209 v = NULL;
210 }
211 return v;
212 }
213
str_copy(CONF * conf,char * section,char ** pto,char * from)214 static int str_copy(CONF *conf, char *section, char **pto, char *from) {
215 int q, r, rr = 0, to = 0, len = 0;
216 char *s, *e, *rp, *rrp, *np, *cp, v;
217 const char *p;
218 BUF_MEM *buf;
219
220 buf = BUF_MEM_new();
221 if (buf == NULL) {
222 return 0;
223 }
224
225 len = strlen(from) + 1;
226 if (!BUF_MEM_grow(buf, len)) {
227 goto err;
228 }
229
230 for (;;) {
231 if (IS_QUOTE(conf, *from)) {
232 q = *from;
233 from++;
234 while (!IS_EOF(conf, *from) && (*from != q)) {
235 if (IS_ESC(conf, *from)) {
236 from++;
237 if (IS_EOF(conf, *from)) {
238 break;
239 }
240 }
241 buf->data[to++] = *(from++);
242 }
243 if (*from == q) {
244 from++;
245 }
246 } else if (IS_DQUOTE(conf, *from)) {
247 q = *from;
248 from++;
249 while (!IS_EOF(conf, *from)) {
250 if (*from == q) {
251 if (*(from + 1) == q) {
252 from++;
253 } else {
254 break;
255 }
256 }
257 buf->data[to++] = *(from++);
258 }
259 if (*from == q) {
260 from++;
261 }
262 } else if (IS_ESC(conf, *from)) {
263 from++;
264 v = *(from++);
265 if (IS_EOF(conf, v)) {
266 break;
267 } else if (v == 'r') {
268 v = '\r';
269 } else if (v == 'n') {
270 v = '\n';
271 } else if (v == 'b') {
272 v = '\b';
273 } else if (v == 't') {
274 v = '\t';
275 }
276 buf->data[to++] = v;
277 } else if (IS_EOF(conf, *from)) {
278 break;
279 } else if (*from == '$') {
280 // try to expand it
281 rrp = NULL;
282 s = &(from[1]);
283 if (*s == '{') {
284 q = '}';
285 } else if (*s == '(') {
286 q = ')';
287 } else {
288 q = 0;
289 }
290
291 if (q) {
292 s++;
293 }
294 cp = section;
295 e = np = s;
296 while (IS_ALPHA_NUMERIC(conf, *e)) {
297 e++;
298 }
299 if (e[0] == ':' && e[1] == ':') {
300 cp = np;
301 rrp = e;
302 rr = *e;
303 *rrp = '\0';
304 e += 2;
305 np = e;
306 while (IS_ALPHA_NUMERIC(conf, *e)) {
307 e++;
308 }
309 }
310 r = *e;
311 *e = '\0';
312 rp = e;
313 if (q) {
314 if (r != q) {
315 OPENSSL_PUT_ERROR(CONF, CONF_R_NO_CLOSE_BRACE);
316 goto err;
317 }
318 e++;
319 }
320 // So at this point we have
321 // np which is the start of the name string which is
322 // '\0' terminated.
323 // cp which is the start of the section string which is
324 // '\0' terminated.
325 // e is the 'next point after'.
326 // r and rr are the chars replaced by the '\0'
327 // rp and rrp is where 'r' and 'rr' came from.
328 p = NCONF_get_string(conf, cp, np);
329 if (rrp != NULL) {
330 *rrp = rr;
331 }
332 *rp = r;
333 if (p == NULL) {
334 OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_HAS_NO_VALUE);
335 goto err;
336 }
337 size_t newsize = strlen(p) + buf->length - (e - from);
338 if (newsize > MAX_CONF_VALUE_LENGTH) {
339 OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
340 goto err;
341 }
342 if (!BUF_MEM_grow_clean(buf, newsize)) {
343 OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE);
344 goto err;
345 }
346 while (*p) {
347 buf->data[to++] = *(p++);
348 }
349
350 /* Since we change the pointer 'from', we also have
351 to change the perceived length of the string it
352 points at. /RL */
353 len -= e - from;
354 from = e;
355
356 /* In case there were no braces or parenthesis around
357 the variable reference, we have to put back the
358 character that was replaced with a '\0'. /RL */
359 *rp = r;
360 } else {
361 buf->data[to++] = *(from++);
362 }
363 }
364
365 buf->data[to] = '\0';
366 if (*pto != NULL) {
367 OPENSSL_free(*pto);
368 }
369 *pto = buf->data;
370 OPENSSL_free(buf);
371 return 1;
372
373 err:
374 if (buf != NULL) {
375 BUF_MEM_free(buf);
376 }
377 return 0;
378 }
379
get_section(const CONF * conf,const char * section)380 static CONF_VALUE *get_section(const CONF *conf, const char *section) {
381 CONF_VALUE template;
382
383 OPENSSL_memset(&template, 0, sizeof(template));
384 template.section = (char *) section;
385 return lh_CONF_VALUE_retrieve(conf->data, &template);
386 }
387
STACK_OF(CONF_VALUE)388 STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section) {
389 CONF_VALUE *section_value = get_section(conf, section);
390 if (section_value == NULL) {
391 return NULL;
392 }
393 return (STACK_OF(CONF_VALUE)*) section_value->value;
394 }
395
NCONF_get_string(const CONF * conf,const char * section,const char * name)396 const char *NCONF_get_string(const CONF *conf, const char *section,
397 const char *name) {
398 CONF_VALUE template, *value;
399
400 if (section == NULL) {
401 section = kDefaultSectionName;
402 }
403
404 OPENSSL_memset(&template, 0, sizeof(template));
405 template.section = (char *) section;
406 template.name = (char *) name;
407 value = lh_CONF_VALUE_retrieve(conf->data, &template);
408 if (value == NULL) {
409 return NULL;
410 }
411 return value->value;
412 }
413
add_string(const CONF * conf,CONF_VALUE * section,CONF_VALUE * value)414 static int add_string(const CONF *conf, CONF_VALUE *section,
415 CONF_VALUE *value) {
416 STACK_OF(CONF_VALUE) *section_stack = (STACK_OF(CONF_VALUE)*) section->value;
417 CONF_VALUE *old_value;
418
419 value->section = OPENSSL_strdup(section->section);
420 if (!sk_CONF_VALUE_push(section_stack, value)) {
421 return 0;
422 }
423
424 if (!lh_CONF_VALUE_insert(conf->data, &old_value, value)) {
425 return 0;
426 }
427 if (old_value != NULL) {
428 (void)sk_CONF_VALUE_delete_ptr(section_stack, old_value);
429 value_free(old_value);
430 }
431
432 return 1;
433 }
434
eat_ws(CONF * conf,char * p)435 static char *eat_ws(CONF *conf, char *p) {
436 while (IS_WS(conf, *p) && !IS_EOF(conf, *p)) {
437 p++;
438 }
439 return p;
440 }
441
442 #define scan_esc(conf, p) (((IS_EOF((conf), (p)[1])) ? ((p) + 1) : ((p) + 2)))
443
eat_alpha_numeric(CONF * conf,char * p)444 static char *eat_alpha_numeric(CONF *conf, char *p) {
445 for (;;) {
446 if (IS_ESC(conf, *p)) {
447 p = scan_esc(conf, p);
448 continue;
449 }
450 if (!IS_ALPHA_NUMERIC_PUNCT(conf, *p)) {
451 return p;
452 }
453 p++;
454 }
455 }
456
scan_quote(CONF * conf,char * p)457 static char *scan_quote(CONF *conf, char *p) {
458 int q = *p;
459
460 p++;
461 while (!IS_EOF(conf, *p) && *p != q) {
462 if (IS_ESC(conf, *p)) {
463 p++;
464 if (IS_EOF(conf, *p)) {
465 return p;
466 }
467 }
468 p++;
469 }
470 if (*p == q) {
471 p++;
472 }
473 return p;
474 }
475
476
scan_dquote(CONF * conf,char * p)477 static char *scan_dquote(CONF *conf, char *p) {
478 int q = *p;
479
480 p++;
481 while (!(IS_EOF(conf, *p))) {
482 if (*p == q) {
483 if (*(p + 1) == q) {
484 p++;
485 } else {
486 break;
487 }
488 }
489 p++;
490 }
491 if (*p == q) {
492 p++;
493 }
494 return p;
495 }
496
clear_comments(CONF * conf,char * p)497 static void clear_comments(CONF *conf, char *p) {
498 for (;;) {
499 if (IS_FCOMMENT(conf, *p)) {
500 *p = '\0';
501 return;
502 }
503 if (!IS_WS(conf, *p)) {
504 break;
505 }
506 p++;
507 }
508
509 for (;;) {
510 if (IS_COMMENT(conf, *p)) {
511 *p = '\0';
512 return;
513 }
514 if (IS_DQUOTE(conf, *p)) {
515 p = scan_dquote(conf, p);
516 continue;
517 }
518 if (IS_QUOTE(conf, *p)) {
519 p = scan_quote(conf, p);
520 continue;
521 }
522 if (IS_ESC(conf, *p)) {
523 p = scan_esc(conf, p);
524 continue;
525 }
526 if (IS_EOF(conf, *p)) {
527 return;
528 } else {
529 p++;
530 }
531 }
532 }
533
def_load_bio(CONF * conf,BIO * in,long * out_error_line)534 static int def_load_bio(CONF *conf, BIO *in, long *out_error_line) {
535 static const size_t CONFBUFSIZE = 512;
536 int bufnum = 0, i, ii;
537 BUF_MEM *buff = NULL;
538 char *s, *p, *end;
539 int again;
540 long eline = 0;
541 char btmp[DECIMAL_SIZE(eline) + 1];
542 CONF_VALUE *v = NULL, *tv;
543 CONF_VALUE *sv = NULL;
544 char *section = NULL, *buf;
545 char *start, *psection, *pname;
546
547 if ((buff = BUF_MEM_new()) == NULL) {
548 OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB);
549 goto err;
550 }
551
552 section = OPENSSL_strdup(kDefaultSectionName);
553 if (section == NULL) {
554 OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE);
555 goto err;
556 }
557
558 sv = NCONF_new_section(conf, section);
559 if (sv == NULL) {
560 OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
561 goto err;
562 }
563
564 bufnum = 0;
565 again = 0;
566 for (;;) {
567 if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
568 OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB);
569 goto err;
570 }
571 p = &(buff->data[bufnum]);
572 *p = '\0';
573 BIO_gets(in, p, CONFBUFSIZE - 1);
574 p[CONFBUFSIZE - 1] = '\0';
575 ii = i = strlen(p);
576 if (i == 0 && !again) {
577 break;
578 }
579 again = 0;
580 while (i > 0) {
581 if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) {
582 break;
583 } else {
584 i--;
585 }
586 }
587 // we removed some trailing stuff so there is a new
588 // line on the end.
589 if (ii && i == ii) {
590 again = 1; // long line
591 } else {
592 p[i] = '\0';
593 eline++; // another input line
594 }
595
596 // we now have a line with trailing \r\n removed
597
598 // i is the number of bytes
599 bufnum += i;
600
601 v = NULL;
602 // check for line continuation
603 if (bufnum >= 1) {
604 // If we have bytes and the last char '\\' and
605 // second last char is not '\\'
606 p = &(buff->data[bufnum - 1]);
607 if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
608 bufnum--;
609 again = 1;
610 }
611 }
612 if (again) {
613 continue;
614 }
615 bufnum = 0;
616 buf = buff->data;
617
618 clear_comments(conf, buf);
619 s = eat_ws(conf, buf);
620 if (IS_EOF(conf, *s)) {
621 continue; // blank line
622 }
623 if (*s == '[') {
624 char *ss;
625
626 s++;
627 start = eat_ws(conf, s);
628 ss = start;
629 again:
630 end = eat_alpha_numeric(conf, ss);
631 p = eat_ws(conf, end);
632 if (*p != ']') {
633 if (*p != '\0' && ss != p) {
634 ss = p;
635 goto again;
636 }
637 OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
638 goto err;
639 }
640 *end = '\0';
641 if (!str_copy(conf, NULL, §ion, start)) {
642 goto err;
643 }
644 if ((sv = get_section(conf, section)) == NULL) {
645 sv = NCONF_new_section(conf, section);
646 }
647 if (sv == NULL) {
648 OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
649 goto err;
650 }
651 continue;
652 } else {
653 pname = s;
654 psection = NULL;
655 end = eat_alpha_numeric(conf, s);
656 if ((end[0] == ':') && (end[1] == ':')) {
657 *end = '\0';
658 end += 2;
659 psection = pname;
660 pname = end;
661 end = eat_alpha_numeric(conf, end);
662 }
663 p = eat_ws(conf, end);
664 if (*p != '=') {
665 OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_EQUAL_SIGN);
666 goto err;
667 }
668 *end = '\0';
669 p++;
670 start = eat_ws(conf, p);
671 while (!IS_EOF(conf, *p)) {
672 p++;
673 }
674 p--;
675 while ((p != start) && (IS_WS(conf, *p))) {
676 p--;
677 }
678 p++;
679 *p = '\0';
680
681 if (!(v = CONF_VALUE_new())) {
682 goto err;
683 }
684 if (psection == NULL) {
685 psection = section;
686 }
687 v->name = OPENSSL_strdup(pname);
688 if (v->name == NULL) {
689 OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE);
690 goto err;
691 }
692 if (!str_copy(conf, psection, &(v->value), start)) {
693 goto err;
694 }
695
696 if (strcmp(psection, section) != 0) {
697 if ((tv = get_section(conf, psection)) == NULL) {
698 tv = NCONF_new_section(conf, psection);
699 }
700 if (tv == NULL) {
701 OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
702 goto err;
703 }
704 } else {
705 tv = sv;
706 }
707 if (add_string(conf, tv, v) == 0) {
708 OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE);
709 goto err;
710 }
711 v = NULL;
712 }
713 }
714 if (buff != NULL) {
715 BUF_MEM_free(buff);
716 }
717 if (section != NULL) {
718 OPENSSL_free(section);
719 }
720 return 1;
721
722 err:
723 if (buff != NULL) {
724 BUF_MEM_free(buff);
725 }
726 if (section != NULL) {
727 OPENSSL_free(section);
728 }
729 if (out_error_line != NULL) {
730 *out_error_line = eline;
731 }
732 BIO_snprintf(btmp, sizeof btmp, "%ld", eline);
733 ERR_add_error_data(2, "line ", btmp);
734
735 if (v != NULL) {
736 if (v->name != NULL) {
737 OPENSSL_free(v->name);
738 }
739 if (v->value != NULL) {
740 OPENSSL_free(v->value);
741 }
742 if (v != NULL) {
743 OPENSSL_free(v);
744 }
745 }
746 return 0;
747 }
748
NCONF_load(CONF * conf,const char * filename,long * out_error_line)749 int NCONF_load(CONF *conf, const char *filename, long *out_error_line) {
750 BIO *in = BIO_new_file(filename, "rb");
751 int ret;
752
753 if (in == NULL) {
754 OPENSSL_PUT_ERROR(CONF, ERR_R_SYS_LIB);
755 return 0;
756 }
757
758 ret = def_load_bio(conf, in, out_error_line);
759 BIO_free(in);
760
761 return ret;
762 }
763
NCONF_load_bio(CONF * conf,BIO * bio,long * out_error_line)764 int NCONF_load_bio(CONF *conf, BIO *bio, long *out_error_line) {
765 return def_load_bio(conf, bio, out_error_line);
766 }
767
CONF_parse_list(const char * list,char sep,int remove_whitespace,int (* list_cb)(const char * elem,int len,void * usr),void * arg)768 int CONF_parse_list(const char *list, char sep, int remove_whitespace,
769 int (*list_cb)(const char *elem, int len, void *usr),
770 void *arg) {
771 int ret;
772 const char *lstart, *tmpend, *p;
773
774 if (list == NULL) {
775 OPENSSL_PUT_ERROR(CONF, CONF_R_LIST_CANNOT_BE_NULL);
776 return 0;
777 }
778
779 lstart = list;
780 for (;;) {
781 if (remove_whitespace) {
782 while (*lstart && isspace((unsigned char)*lstart)) {
783 lstart++;
784 }
785 }
786 p = strchr(lstart, sep);
787 if (p == lstart || !*lstart) {
788 ret = list_cb(NULL, 0, arg);
789 } else {
790 if (p) {
791 tmpend = p - 1;
792 } else {
793 tmpend = lstart + strlen(lstart) - 1;
794 }
795 if (remove_whitespace) {
796 while (isspace((unsigned char)*tmpend)) {
797 tmpend--;
798 }
799 }
800 ret = list_cb(lstart, tmpend - lstart + 1, arg);
801 }
802 if (ret <= 0) {
803 return ret;
804 }
805 if (p == NULL) {
806 return 1;
807 }
808 lstart = p + 1;
809 }
810 }
811
CONF_modules_load_file(const char * filename,const char * appname,unsigned long flags)812 int CONF_modules_load_file(const char *filename, const char *appname,
813 unsigned long flags) {
814 return 1;
815 }
816
CONF_modules_free(void)817 void CONF_modules_free(void) {}
818
OPENSSL_config(const char * config_name)819 void OPENSSL_config(const char *config_name) {}
820
OPENSSL_no_config(void)821 void OPENSSL_no_config(void) {}
822