1 /* Copyright (C) 1995-1998 Eric Young ([email protected])
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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 <assert.h>
60 #include <string.h>
61 #include <ctype.h>
62
63 #include <openssl/bio.h>
64 #include <openssl/buf.h>
65 #include <openssl/err.h>
66 #include <openssl/lhash.h>
67 #include <openssl/mem.h>
68
69 #include "internal.h"
70 #include "../internal.h"
71
72
73 struct conf_section_st {
74 char *name;
75 // values contains non-owning pointers to the values in the section.
76 STACK_OF(CONF_VALUE) *values;
77 };
78
79 static const char kDefaultSectionName[] = "default";
80
conf_section_hash(const CONF_SECTION * s)81 static uint32_t conf_section_hash(const CONF_SECTION *s) {
82 return OPENSSL_strhash(s->name);
83 }
84
conf_section_cmp(const CONF_SECTION * a,const CONF_SECTION * b)85 static int conf_section_cmp(const CONF_SECTION *a, const CONF_SECTION *b) {
86 return strcmp(a->name, b->name);
87 }
88
conf_value_hash(const CONF_VALUE * v)89 static uint32_t conf_value_hash(const CONF_VALUE *v) {
90 const uint32_t section_hash = OPENSSL_strhash(v->section);
91 const uint32_t name_hash = OPENSSL_strhash(v->name);
92 return (section_hash << 2) ^ name_hash;
93 }
94
conf_value_cmp(const CONF_VALUE * a,const CONF_VALUE * b)95 static int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b) {
96 int cmp = strcmp(a->section, b->section);
97 if (cmp != 0) {
98 return cmp;
99 }
100
101 return strcmp(a->name, b->name);
102 }
103
NCONF_new(void * method)104 CONF *NCONF_new(void *method) {
105 if (method != NULL) {
106 return NULL;
107 }
108
109 CONF *conf = OPENSSL_malloc(sizeof(CONF));
110 if (conf == NULL) {
111 return NULL;
112 }
113
114 conf->sections = lh_CONF_SECTION_new(conf_section_hash, conf_section_cmp);
115 conf->values = lh_CONF_VALUE_new(conf_value_hash, conf_value_cmp);
116 if (conf->sections == NULL || conf->values == NULL) {
117 NCONF_free(conf);
118 return NULL;
119 }
120
121 return conf;
122 }
123
CONF_VALUE_new(void)124 CONF_VALUE *CONF_VALUE_new(void) { return OPENSSL_zalloc(sizeof(CONF_VALUE)); }
125
value_free(CONF_VALUE * value)126 static void value_free(CONF_VALUE *value) {
127 if (value == NULL) {
128 return;
129 }
130 OPENSSL_free(value->section);
131 OPENSSL_free(value->name);
132 OPENSSL_free(value->value);
133 OPENSSL_free(value);
134 }
135
section_free(CONF_SECTION * section)136 static void section_free(CONF_SECTION *section) {
137 if (section == NULL) {
138 return;
139 }
140 OPENSSL_free(section->name);
141 sk_CONF_VALUE_free(section->values);
142 OPENSSL_free(section);
143 }
144
value_free_arg(CONF_VALUE * value,void * arg)145 static void value_free_arg(CONF_VALUE *value, void *arg) { value_free(value); }
146
section_free_arg(CONF_SECTION * section,void * arg)147 static void section_free_arg(CONF_SECTION *section, void *arg) {
148 section_free(section);
149 }
150
NCONF_free(CONF * conf)151 void NCONF_free(CONF *conf) {
152 if (conf == NULL) {
153 return;
154 }
155
156 lh_CONF_SECTION_doall_arg(conf->sections, section_free_arg, NULL);
157 lh_CONF_SECTION_free(conf->sections);
158 lh_CONF_VALUE_doall_arg(conf->values, value_free_arg, NULL);
159 lh_CONF_VALUE_free(conf->values);
160 OPENSSL_free(conf);
161 }
162
NCONF_new_section(const CONF * conf,const char * section)163 static CONF_SECTION *NCONF_new_section(const CONF *conf, const char *section) {
164 CONF_SECTION *s = OPENSSL_malloc(sizeof(CONF_SECTION));
165 if (!s) {
166 return NULL;
167 }
168 s->name = OPENSSL_strdup(section);
169 s->values = sk_CONF_VALUE_new_null();
170 if (s->name == NULL || s->values == NULL) {
171 goto err;
172 }
173
174 CONF_SECTION *old_section;
175 if (!lh_CONF_SECTION_insert(conf->sections, &old_section, s)) {
176 goto err;
177 }
178 section_free(old_section);
179 return s;
180
181 err:
182 section_free(s);
183 return NULL;
184 }
185
is_comment(char c)186 static int is_comment(char c) { return c == '#'; }
187
is_quote(char c)188 static int is_quote(char c) { return c == '"' || c == '\'' || c == '`'; }
189
is_esc(char c)190 static int is_esc(char c) { return c == '\\'; }
191
is_conf_ws(char c)192 static int is_conf_ws(char c) {
193 // This differs from |OPENSSL_isspace| in that CONF does not accept '\v' and
194 // '\f' as whitespace.
195 return c == ' ' || c == '\t' || c == '\r' || c == '\n';
196 }
197
is_name_char(char c)198 static int is_name_char(char c) {
199 // Alphanumeric characters, and a handful of symbols, may appear in value and
200 // section names without escaping.
201 return OPENSSL_isalnum(c) || c == '_' || c == '!' || c == '.' || c == '%' ||
202 c == '&' || c == '*' || c == '+' || c == ',' || c == '/' || c == ';' ||
203 c == '?' || c == '@' || c == '^' || c == '~' || c == '|' || c == '-';
204 }
205
str_copy(CONF * conf,char * section,char ** pto,char * from)206 static int str_copy(CONF *conf, char *section, char **pto, char *from) {
207 int q, to = 0, len = 0;
208 char v;
209 BUF_MEM *buf;
210
211 buf = BUF_MEM_new();
212 if (buf == NULL) {
213 return 0;
214 }
215
216 len = strlen(from) + 1;
217 if (!BUF_MEM_grow(buf, len)) {
218 goto err;
219 }
220
221 for (;;) {
222 if (is_quote(*from)) {
223 q = *from;
224 from++;
225 while (*from != '\0' && *from != q) {
226 if (is_esc(*from)) {
227 from++;
228 if (*from == '\0') {
229 break;
230 }
231 }
232 buf->data[to++] = *(from++);
233 }
234 if (*from == q) {
235 from++;
236 }
237 } else if (is_esc(*from)) {
238 from++;
239 v = *(from++);
240 if (v == '\0') {
241 break;
242 } else if (v == 'r') {
243 v = '\r';
244 } else if (v == 'n') {
245 v = '\n';
246 } else if (v == 'b') {
247 v = '\b';
248 } else if (v == 't') {
249 v = '\t';
250 }
251 buf->data[to++] = v;
252 } else if (*from == '\0') {
253 break;
254 } else if (*from == '$') {
255 // Historically, $foo would expand to a previously-parsed value. This
256 // feature has been removed as it was unused and is a DoS vector. If
257 // trying to embed '$' in a line, either escape it or wrap the value in
258 // quotes.
259 OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_EXPANSION_NOT_SUPPORTED);
260 goto err;
261 } else {
262 buf->data[to++] = *(from++);
263 }
264 }
265
266 buf->data[to] = '\0';
267 OPENSSL_free(*pto);
268 *pto = buf->data;
269 OPENSSL_free(buf);
270 return 1;
271
272 err:
273 BUF_MEM_free(buf);
274 return 0;
275 }
276
get_section(const CONF * conf,const char * section)277 static CONF_SECTION *get_section(const CONF *conf, const char *section) {
278 CONF_SECTION template;
279 OPENSSL_memset(&template, 0, sizeof(template));
280 template.name = (char *) section;
281 return lh_CONF_SECTION_retrieve(conf->sections, &template);
282 }
283
STACK_OF(CONF_VALUE)284 const STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf,
285 const char *section) {
286 const CONF_SECTION *section_obj = get_section(conf, section);
287 if (section_obj == NULL) {
288 return NULL;
289 }
290 return section_obj->values;
291 }
292
NCONF_get_string(const CONF * conf,const char * section,const char * name)293 const char *NCONF_get_string(const CONF *conf, const char *section,
294 const char *name) {
295 CONF_VALUE template, *value;
296
297 if (section == NULL) {
298 section = kDefaultSectionName;
299 }
300
301 OPENSSL_memset(&template, 0, sizeof(template));
302 template.section = (char *)section;
303 template.name = (char *)name;
304 value = lh_CONF_VALUE_retrieve(conf->values, &template);
305 if (value == NULL) {
306 return NULL;
307 }
308 return value->value;
309 }
310
add_string(const CONF * conf,CONF_SECTION * section,CONF_VALUE * value)311 static int add_string(const CONF *conf, CONF_SECTION *section,
312 CONF_VALUE *value) {
313 value->section = OPENSSL_strdup(section->name);
314 if (value->section == NULL) {
315 return 0;
316 }
317
318 if (!sk_CONF_VALUE_push(section->values, value)) {
319 return 0;
320 }
321
322 CONF_VALUE *old_value;
323 if (!lh_CONF_VALUE_insert(conf->values, &old_value, value)) {
324 // Remove |value| from |section->values|, so we do not leave a dangling
325 // pointer.
326 sk_CONF_VALUE_pop(section->values);
327 return 0;
328 }
329 if (old_value != NULL) {
330 (void)sk_CONF_VALUE_delete_ptr(section->values, old_value);
331 value_free(old_value);
332 }
333
334 return 1;
335 }
336
eat_ws(char * p)337 static char *eat_ws(char *p) {
338 while (*p != '\0' && is_conf_ws(*p)) {
339 p++;
340 }
341 return p;
342 }
343
scan_esc(char * p)344 static char *scan_esc(char *p) {
345 assert(p[0] == '\\');
346 return p[1] == '\0' ? p + 1 : p + 2;
347 }
348
eat_name(char * p)349 static char *eat_name(char *p) {
350 for (;;) {
351 if (is_esc(*p)) {
352 p = scan_esc(p);
353 continue;
354 }
355 if (!is_name_char(*p)) {
356 return p;
357 }
358 p++;
359 }
360 }
361
scan_quote(char * p)362 static char *scan_quote(char *p) {
363 int q = *p;
364
365 p++;
366 while (*p != '\0' && *p != q) {
367 if (is_esc(*p)) {
368 p++;
369 if (*p == '\0') {
370 return p;
371 }
372 }
373 p++;
374 }
375 if (*p == q) {
376 p++;
377 }
378 return p;
379 }
380
clear_comments(char * p)381 static void clear_comments(char *p) {
382 for (;;) {
383 if (!is_conf_ws(*p)) {
384 break;
385 }
386 p++;
387 }
388
389 for (;;) {
390 if (is_comment(*p)) {
391 *p = '\0';
392 return;
393 }
394 if (is_quote(*p)) {
395 p = scan_quote(p);
396 continue;
397 }
398 if (is_esc(*p)) {
399 p = scan_esc(p);
400 continue;
401 }
402 if (*p == '\0') {
403 return;
404 } else {
405 p++;
406 }
407 }
408 }
409
NCONF_load_bio(CONF * conf,BIO * in,long * out_error_line)410 int NCONF_load_bio(CONF *conf, BIO *in, long *out_error_line) {
411 static const size_t CONFBUFSIZE = 512;
412 int bufnum = 0, i, ii;
413 BUF_MEM *buff = NULL;
414 char *s, *p, *end;
415 int again;
416 long eline = 0;
417 char btmp[DECIMAL_SIZE(eline) + 1];
418 CONF_VALUE *v = NULL;
419 CONF_SECTION *sv = NULL;
420 char *section = NULL, *buf;
421 char *start, *psection, *pname;
422
423 if ((buff = BUF_MEM_new()) == NULL) {
424 OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB);
425 goto err;
426 }
427
428 section = OPENSSL_strdup(kDefaultSectionName);
429 if (section == NULL) {
430 goto err;
431 }
432
433 sv = NCONF_new_section(conf, section);
434 if (sv == NULL) {
435 OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
436 goto err;
437 }
438
439 bufnum = 0;
440 again = 0;
441 for (;;) {
442 if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
443 OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB);
444 goto err;
445 }
446 p = &(buff->data[bufnum]);
447 *p = '\0';
448 BIO_gets(in, p, CONFBUFSIZE - 1);
449 p[CONFBUFSIZE - 1] = '\0';
450 ii = i = strlen(p);
451 if (i == 0 && !again) {
452 break;
453 }
454 again = 0;
455 while (i > 0) {
456 if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) {
457 break;
458 } else {
459 i--;
460 }
461 }
462 // we removed some trailing stuff so there is a new
463 // line on the end.
464 if (ii && i == ii) {
465 again = 1; // long line
466 } else {
467 p[i] = '\0';
468 eline++; // another input line
469 }
470
471 // we now have a line with trailing \r\n removed
472
473 // i is the number of bytes
474 bufnum += i;
475
476 v = NULL;
477 // check for line continuation
478 if (bufnum >= 1) {
479 // If we have bytes and the last char '\\' and
480 // second last char is not '\\'
481 p = &(buff->data[bufnum - 1]);
482 if (is_esc(p[0]) && ((bufnum <= 1) || !is_esc(p[-1]))) {
483 bufnum--;
484 again = 1;
485 }
486 }
487 if (again) {
488 continue;
489 }
490 bufnum = 0;
491 buf = buff->data;
492
493 clear_comments(buf);
494 s = eat_ws(buf);
495 if (*s == '\0') {
496 continue; // blank line
497 }
498 if (*s == '[') {
499 char *ss;
500
501 s++;
502 start = eat_ws(s);
503 ss = start;
504 again:
505 end = eat_name(ss);
506 p = eat_ws(end);
507 if (*p != ']') {
508 if (*p != '\0' && ss != p) {
509 ss = p;
510 goto again;
511 }
512 OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
513 goto err;
514 }
515 *end = '\0';
516 if (!str_copy(conf, NULL, §ion, start)) {
517 goto err;
518 }
519 if ((sv = get_section(conf, section)) == NULL) {
520 sv = NCONF_new_section(conf, section);
521 }
522 if (sv == NULL) {
523 OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
524 goto err;
525 }
526 continue;
527 } else {
528 pname = s;
529 psection = NULL;
530 end = eat_name(s);
531 if ((end[0] == ':') && (end[1] == ':')) {
532 *end = '\0';
533 end += 2;
534 psection = pname;
535 pname = end;
536 end = eat_name(end);
537 }
538 p = eat_ws(end);
539 if (*p != '=') {
540 OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_EQUAL_SIGN);
541 goto err;
542 }
543 *end = '\0';
544 p++;
545 start = eat_ws(p);
546 while (*p != '\0') {
547 p++;
548 }
549 p--;
550 while (p != start && is_conf_ws(*p)) {
551 p--;
552 }
553 p++;
554 *p = '\0';
555
556 if (!(v = CONF_VALUE_new())) {
557 goto err;
558 }
559 if (psection == NULL) {
560 psection = section;
561 }
562 v->name = OPENSSL_strdup(pname);
563 if (v->name == NULL) {
564 goto err;
565 }
566 if (!str_copy(conf, psection, &(v->value), start)) {
567 goto err;
568 }
569
570 CONF_SECTION *tv;
571 if (strcmp(psection, section) != 0) {
572 if ((tv = get_section(conf, psection)) == NULL) {
573 tv = NCONF_new_section(conf, psection);
574 }
575 if (tv == NULL) {
576 OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
577 goto err;
578 }
579 } else {
580 tv = sv;
581 }
582 if (add_string(conf, tv, v) == 0) {
583 goto err;
584 }
585 v = NULL;
586 }
587 }
588 BUF_MEM_free(buff);
589 OPENSSL_free(section);
590 return 1;
591
592 err:
593 BUF_MEM_free(buff);
594 OPENSSL_free(section);
595 if (out_error_line != NULL) {
596 *out_error_line = eline;
597 }
598 snprintf(btmp, sizeof btmp, "%ld", eline);
599 ERR_add_error_data(2, "line ", btmp);
600 value_free(v);
601 return 0;
602 }
603
NCONF_load(CONF * conf,const char * filename,long * out_error_line)604 int NCONF_load(CONF *conf, const char *filename, long *out_error_line) {
605 BIO *in = BIO_new_file(filename, "rb");
606 int ret;
607
608 if (in == NULL) {
609 OPENSSL_PUT_ERROR(CONF, ERR_R_SYS_LIB);
610 return 0;
611 }
612
613 ret = NCONF_load_bio(conf, in, out_error_line);
614 BIO_free(in);
615
616 return ret;
617 }
618
CONF_parse_list(const char * list,char sep,int remove_whitespace,int (* list_cb)(const char * elem,size_t len,void * usr),void * arg)619 int CONF_parse_list(const char *list, char sep, int remove_whitespace,
620 int (*list_cb)(const char *elem, size_t len, void *usr),
621 void *arg) {
622 int ret;
623 const char *lstart, *tmpend, *p;
624
625 if (list == NULL) {
626 OPENSSL_PUT_ERROR(CONF, CONF_R_LIST_CANNOT_BE_NULL);
627 return 0;
628 }
629
630 lstart = list;
631 for (;;) {
632 if (remove_whitespace) {
633 while (*lstart && OPENSSL_isspace((unsigned char)*lstart)) {
634 lstart++;
635 }
636 }
637 p = strchr(lstart, sep);
638 if (p == lstart || !*lstart) {
639 ret = list_cb(NULL, 0, arg);
640 } else {
641 if (p) {
642 tmpend = p - 1;
643 } else {
644 tmpend = lstart + strlen(lstart) - 1;
645 }
646 if (remove_whitespace) {
647 while (OPENSSL_isspace((unsigned char)*tmpend)) {
648 tmpend--;
649 }
650 }
651 ret = list_cb(lstart, tmpend - lstart + 1, arg);
652 }
653 if (ret <= 0) {
654 return ret;
655 }
656 if (p == NULL) {
657 return 1;
658 }
659 lstart = p + 1;
660 }
661 }
662
CONF_modules_load_file(const char * filename,const char * appname,unsigned long flags)663 int CONF_modules_load_file(const char *filename, const char *appname,
664 unsigned long flags) {
665 return 1;
666 }
667
CONF_modules_free(void)668 void CONF_modules_free(void) {}
669
OPENSSL_config(const char * config_name)670 void OPENSSL_config(const char *config_name) {}
671
OPENSSL_no_config(void)672 void OPENSSL_no_config(void) {}
673