1 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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/mem.h> 66 67 #include "conf_def.h" 68 69 70 static uint32_t conf_value_hash(const CONF_VALUE *v) { 71 return (lh_strhash(v->section) << 2) ^ lh_strhash(v->name); 72 } 73 74 static int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b) { 75 int i; 76 77 if (a->section != b->section) { 78 i = strcmp(a->section, b->section); 79 if (i) { 80 return i; 81 } 82 } 83 84 if (a->name != NULL && b->name != NULL) { 85 return strcmp(a->name, b->name); 86 } else if (a->name == b->name) { 87 return 0; 88 } else { 89 return (a->name == NULL) ? -1 : 1; 90 } 91 } 92 93 CONF *NCONF_new(void *method) { 94 CONF *conf; 95 96 if (method != NULL) { 97 return NULL; 98 } 99 100 conf = OPENSSL_malloc(sizeof(CONF)); 101 if (conf == NULL) { 102 return NULL; 103 } 104 105 conf->data = lh_CONF_VALUE_new(conf_value_hash, conf_value_cmp); 106 if (conf->data == NULL) { 107 OPENSSL_free(conf); 108 return NULL; 109 } 110 111 return conf; 112 } 113 114 CONF_VALUE *CONF_VALUE_new(void) { 115 CONF_VALUE *v = OPENSSL_malloc(sizeof(CONF_VALUE)); 116 if (!v) { 117 OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); 118 return NULL; 119 } 120 memset(v, 0, sizeof(CONF_VALUE)); 121 return v; 122 } 123 124 static void value_free_contents(CONF_VALUE *value) { 125 if (value->section) { 126 OPENSSL_free(value->section); 127 } 128 if (value->name) { 129 OPENSSL_free(value->name); 130 if (value->value) { 131 OPENSSL_free(value->value); 132 } 133 } else { 134 if (value->value) { 135 sk_CONF_VALUE_free((STACK_OF(CONF_VALUE)*)value->value); 136 } 137 } 138 } 139 140 static void value_free(CONF_VALUE *value) { 141 value_free_contents(value); 142 OPENSSL_free(value); 143 } 144 145 void NCONF_free(CONF *conf) { 146 if (conf == NULL || conf->data == NULL) { 147 return; 148 } 149 150 lh_CONF_VALUE_doall(conf->data, value_free); 151 lh_CONF_VALUE_free(conf->data); 152 OPENSSL_free(conf); 153 } 154 155 CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) { 156 STACK_OF(CONF_VALUE) *sk = NULL; 157 int ok = 0; 158 CONF_VALUE *v = NULL, *old_value; 159 160 sk = sk_CONF_VALUE_new_null(); 161 v = CONF_VALUE_new(); 162 if (sk == NULL || v == NULL) { 163 goto err; 164 } 165 v->section = OPENSSL_strdup(section); 166 if (v->section == NULL) { 167 goto err; 168 } 169 170 v->name = NULL; 171 v->value = (char *)sk; 172 173 if (!lh_CONF_VALUE_insert(conf->data, &old_value, v)) { 174 goto err; 175 } 176 if (old_value) { 177 value_free(old_value); 178 } 179 ok = 1; 180 181 err: 182 if (!ok) { 183 if (sk != NULL) { 184 sk_CONF_VALUE_free(sk); 185 } 186 if (v != NULL) { 187 OPENSSL_free(v); 188 } 189 v = NULL; 190 } 191 return v; 192 } 193 194 static int str_copy(CONF *conf, char *section, char **pto, char *from) { 195 int q, r, rr = 0, to = 0, len = 0; 196 char *s, *e, *rp, *rrp, *np, *cp, v; 197 const char *p; 198 BUF_MEM *buf; 199 200 buf = BUF_MEM_new(); 201 if (buf == NULL) { 202 return 0; 203 } 204 205 len = strlen(from) + 1; 206 if (!BUF_MEM_grow(buf, len)) { 207 goto err; 208 } 209 210 for (;;) { 211 if (IS_QUOTE(conf, *from)) { 212 q = *from; 213 from++; 214 while (!IS_EOF(conf, *from) && (*from != q)) { 215 if (IS_ESC(conf, *from)) { 216 from++; 217 if (IS_EOF(conf, *from)) { 218 break; 219 } 220 } 221 buf->data[to++] = *(from++); 222 } 223 if (*from == q) { 224 from++; 225 } 226 } else if (IS_DQUOTE(conf, *from)) { 227 q = *from; 228 from++; 229 while (!IS_EOF(conf, *from)) { 230 if (*from == q) { 231 if (*(from + 1) == q) { 232 from++; 233 } else { 234 break; 235 } 236 } 237 buf->data[to++] = *(from++); 238 } 239 if (*from == q) { 240 from++; 241 } 242 } else if (IS_ESC(conf, *from)) { 243 from++; 244 v = *(from++); 245 if (IS_EOF(conf, v)) { 246 break; 247 } else if (v == 'r') { 248 v = '\r'; 249 } else if (v == 'n') { 250 v = '\n'; 251 } else if (v == 'b') { 252 v = '\b'; 253 } else if (v == 't') { 254 v = '\t'; 255 } 256 buf->data[to++] = v; 257 } else if (IS_EOF(conf, *from)) { 258 break; 259 } else if (*from == '$') { 260 /* try to expand it */ 261 rrp = NULL; 262 s = &(from[1]); 263 if (*s == '{') { 264 q = '}'; 265 } else if (*s == '(') { 266 q = ')'; 267 } else { 268 q = 0; 269 } 270 271 if (q) { 272 s++; 273 } 274 cp = section; 275 e = np = s; 276 while (IS_ALPHA_NUMERIC(conf, *e)) { 277 e++; 278 } 279 if (e[0] == ':' && e[1] == ':') { 280 cp = np; 281 rrp = e; 282 rr = *e; 283 *rrp = '\0'; 284 e += 2; 285 np = e; 286 while (IS_ALPHA_NUMERIC(conf, *e)) { 287 e++; 288 } 289 } 290 r = *e; 291 *e = '\0'; 292 rp = e; 293 if (q) { 294 if (r != q) { 295 OPENSSL_PUT_ERROR(CONF, CONF_R_NO_CLOSE_BRACE); 296 goto err; 297 } 298 e++; 299 } 300 /* So at this point we have 301 * np which is the start of the name string which is 302 * '\0' terminated. 303 * cp which is the start of the section string which is 304 * '\0' terminated. 305 * e is the 'next point after'. 306 * r and rr are the chars replaced by the '\0' 307 * rp and rrp is where 'r' and 'rr' came from. */ 308 p = NCONF_get_string(conf, cp, np); 309 if (rrp != NULL) { 310 *rrp = rr; 311 } 312 *rp = r; 313 if (p == NULL) { 314 OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_HAS_NO_VALUE); 315 goto err; 316 } 317 BUF_MEM_grow_clean(buf, (strlen(p) + buf->length - (e - from))); 318 while (*p) { 319 buf->data[to++] = *(p++); 320 } 321 322 /* Since we change the pointer 'from', we also have 323 to change the perceived length of the string it 324 points at. /RL */ 325 len -= e - from; 326 from = e; 327 328 /* In case there were no braces or parenthesis around 329 the variable reference, we have to put back the 330 character that was replaced with a '\0'. /RL */ 331 *rp = r; 332 } else { 333 buf->data[to++] = *(from++); 334 } 335 } 336 337 buf->data[to] = '\0'; 338 if (*pto != NULL) { 339 OPENSSL_free(*pto); 340 } 341 *pto = buf->data; 342 OPENSSL_free(buf); 343 return 1; 344 345 err: 346 if (buf != NULL) { 347 BUF_MEM_free(buf); 348 } 349 return 0; 350 } 351 352 static CONF_VALUE *get_section(const CONF *conf, const char *section) { 353 CONF_VALUE template; 354 355 memset(&template, 0, sizeof(template)); 356 template.section = (char *) section; 357 return lh_CONF_VALUE_retrieve(conf->data, &template); 358 } 359 360 STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section) { 361 CONF_VALUE *section_value = get_section(conf, section); 362 if (section_value == NULL) { 363 return NULL; 364 } 365 return (STACK_OF(CONF_VALUE)*) section_value->value; 366 } 367 368 const char *NCONF_get_string(const CONF *conf, const char *section, 369 const char *name) { 370 CONF_VALUE template, *value; 371 372 memset(&template, 0, sizeof(template)); 373 template.section = (char *) section; 374 template.name = (char *) name; 375 value = lh_CONF_VALUE_retrieve(conf->data, &template); 376 if (value == NULL) { 377 return NULL; 378 } 379 return value->value; 380 } 381 382 static int add_string(const CONF *conf, CONF_VALUE *section, 383 CONF_VALUE *value) { 384 STACK_OF(CONF_VALUE) *section_stack = (STACK_OF(CONF_VALUE)*) section->value; 385 CONF_VALUE *old_value; 386 387 value->section = OPENSSL_strdup(section->section); 388 if (!sk_CONF_VALUE_push(section_stack, value)) { 389 return 0; 390 } 391 392 if (!lh_CONF_VALUE_insert(conf->data, &old_value, value)) { 393 return 0; 394 } 395 if (old_value != NULL) { 396 (void)sk_CONF_VALUE_delete_ptr(section_stack, old_value); 397 value_free(old_value); 398 } 399 400 return 1; 401 } 402 403 static char *eat_ws(CONF *conf, char *p) { 404 while (IS_WS(conf, *p) && !IS_EOF(conf, *p)) { 405 p++; 406 } 407 return p; 408 } 409 410 #define scan_esc(conf, p) (((IS_EOF((conf), (p)[1])) ? ((p) + 1) : ((p) + 2))) 411 412 static char *eat_alpha_numeric(CONF *conf, char *p) { 413 for (;;) { 414 if (IS_ESC(conf, *p)) { 415 p = scan_esc(conf, p); 416 continue; 417 } 418 if (!IS_ALPHA_NUMERIC_PUNCT(conf, *p)) { 419 return p; 420 } 421 p++; 422 } 423 } 424 425 static char *scan_quote(CONF *conf, char *p) { 426 int q = *p; 427 428 p++; 429 while (!IS_EOF(conf, *p) && *p != q) { 430 if (IS_ESC(conf, *p)) { 431 p++; 432 if (IS_EOF(conf, *p)) { 433 return p; 434 } 435 } 436 p++; 437 } 438 if (*p == q) { 439 p++; 440 } 441 return p; 442 } 443 444 445 static char *scan_dquote(CONF *conf, char *p) { 446 int q = *p; 447 448 p++; 449 while (!(IS_EOF(conf, *p))) { 450 if (*p == q) { 451 if (*(p + 1) == q) { 452 p++; 453 } else { 454 break; 455 } 456 } 457 p++; 458 } 459 if (*p == q) { 460 p++; 461 } 462 return p; 463 } 464 465 static void clear_comments(CONF *conf, char *p) { 466 for (;;) { 467 if (IS_FCOMMENT(conf, *p)) { 468 *p = '\0'; 469 return; 470 } 471 if (!IS_WS(conf, *p)) { 472 break; 473 } 474 p++; 475 } 476 477 for (;;) { 478 if (IS_COMMENT(conf, *p)) { 479 *p = '\0'; 480 return; 481 } 482 if (IS_DQUOTE(conf, *p)) { 483 p = scan_dquote(conf, p); 484 continue; 485 } 486 if (IS_QUOTE(conf, *p)) { 487 p = scan_quote(conf, p); 488 continue; 489 } 490 if (IS_ESC(conf, *p)) { 491 p = scan_esc(conf, p); 492 continue; 493 } 494 if (IS_EOF(conf, *p)) { 495 return; 496 } else { 497 p++; 498 } 499 } 500 } 501 502 static int def_load_bio(CONF *conf, BIO *in, long *out_error_line) { 503 static const size_t CONFBUFSIZE = 512; 504 int bufnum = 0, i, ii; 505 BUF_MEM *buff = NULL; 506 char *s, *p, *end; 507 int again; 508 long eline = 0; 509 char btmp[DECIMAL_SIZE(eline) + 1]; 510 CONF_VALUE *v = NULL, *tv; 511 CONF_VALUE *sv = NULL; 512 char *section = NULL, *buf; 513 char *start, *psection, *pname; 514 515 if ((buff = BUF_MEM_new()) == NULL) { 516 OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB); 517 goto err; 518 } 519 520 section = OPENSSL_strdup("default"); 521 if (section == NULL) { 522 OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); 523 goto err; 524 } 525 526 sv = NCONF_new_section(conf, section); 527 if (sv == NULL) { 528 OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); 529 goto err; 530 } 531 532 bufnum = 0; 533 again = 0; 534 for (;;) { 535 if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) { 536 OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB); 537 goto err; 538 } 539 p = &(buff->data[bufnum]); 540 *p = '\0'; 541 BIO_gets(in, p, CONFBUFSIZE - 1); 542 p[CONFBUFSIZE - 1] = '\0'; 543 ii = i = strlen(p); 544 if (i == 0 && !again) { 545 break; 546 } 547 again = 0; 548 while (i > 0) { 549 if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) { 550 break; 551 } else { 552 i--; 553 } 554 } 555 /* we removed some trailing stuff so there is a new 556 * line on the end. */ 557 if (ii && i == ii) { 558 again = 1; /* long line */ 559 } else { 560 p[i] = '\0'; 561 eline++; /* another input line */ 562 } 563 564 /* we now have a line with trailing \r\n removed */ 565 566 /* i is the number of bytes */ 567 bufnum += i; 568 569 v = NULL; 570 /* check for line continuation */ 571 if (bufnum >= 1) { 572 /* If we have bytes and the last char '\\' and 573 * second last char is not '\\' */ 574 p = &(buff->data[bufnum - 1]); 575 if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) { 576 bufnum--; 577 again = 1; 578 } 579 } 580 if (again) { 581 continue; 582 } 583 bufnum = 0; 584 buf = buff->data; 585 586 clear_comments(conf, buf); 587 s = eat_ws(conf, buf); 588 if (IS_EOF(conf, *s)) { 589 continue; /* blank line */ 590 } 591 if (*s == '[') { 592 char *ss; 593 594 s++; 595 start = eat_ws(conf, s); 596 ss = start; 597 again: 598 end = eat_alpha_numeric(conf, ss); 599 p = eat_ws(conf, end); 600 if (*p != ']') { 601 if (*p != '\0' && ss != p) { 602 ss = p; 603 goto again; 604 } 605 OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET); 606 goto err; 607 } 608 *end = '\0'; 609 if (!str_copy(conf, NULL, §ion, start)) { 610 goto err; 611 } 612 if ((sv = get_section(conf, section)) == NULL) { 613 sv = NCONF_new_section(conf, section); 614 } 615 if (sv == NULL) { 616 OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); 617 goto err; 618 } 619 continue; 620 } else { 621 pname = s; 622 psection = NULL; 623 end = eat_alpha_numeric(conf, s); 624 if ((end[0] == ':') && (end[1] == ':')) { 625 *end = '\0'; 626 end += 2; 627 psection = pname; 628 pname = end; 629 end = eat_alpha_numeric(conf, end); 630 } 631 p = eat_ws(conf, end); 632 if (*p != '=') { 633 OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_EQUAL_SIGN); 634 goto err; 635 } 636 *end = '\0'; 637 p++; 638 start = eat_ws(conf, p); 639 while (!IS_EOF(conf, *p)) { 640 p++; 641 } 642 p--; 643 while ((p != start) && (IS_WS(conf, *p))) { 644 p--; 645 } 646 p++; 647 *p = '\0'; 648 649 if (!(v = CONF_VALUE_new())) { 650 goto err; 651 } 652 if (psection == NULL) { 653 psection = section; 654 } 655 v->name = OPENSSL_strdup(pname); 656 if (v->name == NULL) { 657 OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); 658 goto err; 659 } 660 if (!str_copy(conf, psection, &(v->value), start)) { 661 goto err; 662 } 663 664 if (strcmp(psection, section) != 0) { 665 if ((tv = get_section(conf, psection)) == NULL) { 666 tv = NCONF_new_section(conf, psection); 667 } 668 if (tv == NULL) { 669 OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); 670 goto err; 671 } 672 } else { 673 tv = sv; 674 } 675 if (add_string(conf, tv, v) == 0) { 676 OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE); 677 goto err; 678 } 679 v = NULL; 680 } 681 } 682 if (buff != NULL) { 683 BUF_MEM_free(buff); 684 } 685 if (section != NULL) { 686 OPENSSL_free(section); 687 } 688 return 1; 689 690 err: 691 if (buff != NULL) { 692 BUF_MEM_free(buff); 693 } 694 if (section != NULL) { 695 OPENSSL_free(section); 696 } 697 if (out_error_line != NULL) { 698 *out_error_line = eline; 699 } 700 BIO_snprintf(btmp, sizeof btmp, "%ld", eline); 701 ERR_add_error_data(2, "line ", btmp); 702 703 if (v != NULL) { 704 if (v->name != NULL) { 705 OPENSSL_free(v->name); 706 } 707 if (v->value != NULL) { 708 OPENSSL_free(v->value); 709 } 710 if (v != NULL) { 711 OPENSSL_free(v); 712 } 713 } 714 return 0; 715 } 716 717 int NCONF_load(CONF *conf, const char *filename, long *out_error_line) { 718 BIO *in = BIO_new_file(filename, "rb"); 719 int ret; 720 721 if (in == NULL) { 722 OPENSSL_PUT_ERROR(CONF, ERR_R_SYS_LIB); 723 return 0; 724 } 725 726 ret = def_load_bio(conf, in, out_error_line); 727 BIO_free(in); 728 729 return ret; 730 } 731 732 int NCONF_load_bio(CONF *conf, BIO *bio, long *out_error_line) { 733 return def_load_bio(conf, bio, out_error_line); 734 } 735 736 int CONF_parse_list(const char *list, char sep, int remove_whitespace, 737 int (*list_cb)(const char *elem, int len, void *usr), 738 void *arg) { 739 int ret; 740 const char *lstart, *tmpend, *p; 741 742 if (list == NULL) { 743 OPENSSL_PUT_ERROR(CONF, CONF_R_LIST_CANNOT_BE_NULL); 744 return 0; 745 } 746 747 lstart = list; 748 for (;;) { 749 if (remove_whitespace) { 750 while (*lstart && isspace((unsigned char)*lstart)) { 751 lstart++; 752 } 753 } 754 p = strchr(lstart, sep); 755 if (p == lstart || !*lstart) { 756 ret = list_cb(NULL, 0, arg); 757 } else { 758 if (p) { 759 tmpend = p - 1; 760 } else { 761 tmpend = lstart + strlen(lstart) - 1; 762 } 763 if (remove_whitespace) { 764 while (isspace((unsigned char)*tmpend)) { 765 tmpend--; 766 } 767 } 768 ret = list_cb(lstart, tmpend - lstart + 1, arg); 769 } 770 if (ret <= 0) { 771 return ret; 772 } 773 if (p == NULL) { 774 return 1; 775 } 776 lstart = p + 1; 777 } 778 } 779 780 int CONF_modules_load_file(CONF_MUST_BE_NULL *filename, const char *appname, 781 unsigned long flags) { 782 return 1; 783 } 784 785 void CONF_modules_free(void) {} 786