• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &section, 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