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