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 <openssl/stack.h> 64 #include <openssl/lhash.h> 65 #include <openssl/conf.h> 66 #include <openssl/conf_api.h> 67 #include "conf_def.h" 68 #include <openssl/buffer.h> 69 #include <openssl/err.h> 70 71 static char *eat_ws(CONF *conf, char *p); 72 static char *eat_alpha_numeric(CONF *conf, char *p); 73 static void clear_comments(CONF *conf, char *p); 74 static int str_copy(CONF *conf,char *section,char **to, char *from); 75 static char *scan_quote(CONF *conf, char *p); 76 static char *scan_dquote(CONF *conf, char *p); 77 #define scan_esc(conf,p) (((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2))) 78 79 static CONF *def_create(CONF_METHOD *meth); 80 static int def_init_default(CONF *conf); 81 static int def_init_WIN32(CONF *conf); 82 static int def_destroy(CONF *conf); 83 static int def_destroy_data(CONF *conf); 84 static int def_load(CONF *conf, BIO *bp, long *eline); 85 static int def_dump(CONF *conf, BIO *bp); 86 static int def_is_number(CONF *conf, char c); 87 static int def_to_int(CONF *conf, char c); 88 89 const char *CONF_def_version="CONF_def" OPENSSL_VERSION_PTEXT; 90 91 static CONF_METHOD default_method = { 92 "OpenSSL default", 93 def_create, 94 def_init_default, 95 def_destroy, 96 def_destroy_data, 97 def_load, 98 def_dump, 99 def_is_number, 100 def_to_int 101 }; 102 103 static CONF_METHOD WIN32_method = { 104 "WIN32", 105 def_create, 106 def_init_WIN32, 107 def_destroy, 108 def_destroy_data, 109 def_load, 110 def_dump, 111 def_is_number, 112 def_to_int 113 }; 114 115 CONF_METHOD *NCONF_default() 116 { 117 return &default_method; 118 } 119 CONF_METHOD *NCONF_WIN32() 120 { 121 return &WIN32_method; 122 } 123 124 static CONF *def_create(CONF_METHOD *meth) 125 { 126 CONF *ret; 127 128 ret = (CONF *)OPENSSL_malloc(sizeof(CONF) + sizeof(unsigned short *)); 129 if (ret) 130 if (meth->init(ret) == 0) 131 { 132 OPENSSL_free(ret); 133 ret = NULL; 134 } 135 return ret; 136 } 137 138 static int def_init_default(CONF *conf) 139 { 140 if (conf == NULL) 141 return 0; 142 143 conf->meth = &default_method; 144 conf->meth_data = (void *)CONF_type_default; 145 conf->data = NULL; 146 147 return 1; 148 } 149 150 static int def_init_WIN32(CONF *conf) 151 { 152 if (conf == NULL) 153 return 0; 154 155 conf->meth = &WIN32_method; 156 conf->meth_data = (void *)CONF_type_win32; 157 conf->data = NULL; 158 159 return 1; 160 } 161 162 static int def_destroy(CONF *conf) 163 { 164 if (def_destroy_data(conf)) 165 { 166 OPENSSL_free(conf); 167 return 1; 168 } 169 return 0; 170 } 171 172 static int def_destroy_data(CONF *conf) 173 { 174 if (conf == NULL) 175 return 0; 176 _CONF_free_data(conf); 177 return 1; 178 } 179 180 static int def_load(CONF *conf, BIO *in, long *line) 181 { 182 #define BUFSIZE 512 183 char btmp[16]; 184 int bufnum=0,i,ii; 185 BUF_MEM *buff=NULL; 186 char *s,*p,*end; 187 int again,n; 188 long eline=0; 189 CONF_VALUE *v=NULL,*tv; 190 CONF_VALUE *sv=NULL; 191 char *section=NULL,*buf; 192 STACK_OF(CONF_VALUE) *section_sk=NULL,*ts; 193 char *start,*psection,*pname; 194 void *h = (void *)(conf->data); 195 196 if ((buff=BUF_MEM_new()) == NULL) 197 { 198 CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_BUF_LIB); 199 goto err; 200 } 201 202 section=(char *)OPENSSL_malloc(10); 203 if (section == NULL) 204 { 205 CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_MALLOC_FAILURE); 206 goto err; 207 } 208 strcpy(section,"default"); 209 210 if (_CONF_new_data(conf) == 0) 211 { 212 CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_MALLOC_FAILURE); 213 goto err; 214 } 215 216 sv=_CONF_new_section(conf,section); 217 if (sv == NULL) 218 { 219 CONFerr(CONF_F_CONF_LOAD_BIO, 220 CONF_R_UNABLE_TO_CREATE_NEW_SECTION); 221 goto err; 222 } 223 section_sk=(STACK_OF(CONF_VALUE) *)sv->value; 224 225 bufnum=0; 226 for (;;) 227 { 228 again=0; 229 if (!BUF_MEM_grow(buff,bufnum+BUFSIZE)) 230 { 231 CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_BUF_LIB); 232 goto err; 233 } 234 p= &(buff->data[bufnum]); 235 *p='\0'; 236 BIO_gets(in, p, BUFSIZE-1); 237 p[BUFSIZE-1]='\0'; 238 ii=i=strlen(p); 239 if (i == 0) break; 240 while (i > 0) 241 { 242 if ((p[i-1] != '\r') && (p[i-1] != '\n')) 243 break; 244 else 245 i--; 246 } 247 /* we removed some trailing stuff so there is a new 248 * line on the end. */ 249 if (i == ii) 250 again=1; /* long line */ 251 else 252 { 253 p[i]='\0'; 254 eline++; /* another input line */ 255 } 256 257 /* we now have a line with trailing \r\n removed */ 258 259 /* i is the number of bytes */ 260 bufnum+=i; 261 262 v=NULL; 263 /* check for line continuation */ 264 if (bufnum >= 1) 265 { 266 /* If we have bytes and the last char '\\' and 267 * second last char is not '\\' */ 268 p= &(buff->data[bufnum-1]); 269 if (IS_ESC(conf,p[0]) && 270 ((bufnum <= 1) || !IS_ESC(conf,p[-1]))) 271 { 272 bufnum--; 273 again=1; 274 } 275 } 276 if (again) continue; 277 bufnum=0; 278 buf=buff->data; 279 280 clear_comments(conf, buf); 281 n=strlen(buf); 282 s=eat_ws(conf, buf); 283 if (IS_EOF(conf,*s)) continue; /* blank line */ 284 if (*s == '[') 285 { 286 char *ss; 287 288 s++; 289 start=eat_ws(conf, s); 290 ss=start; 291 again: 292 end=eat_alpha_numeric(conf, ss); 293 p=eat_ws(conf, end); 294 if (*p != ']') 295 { 296 if (*p != '\0') 297 { 298 ss=p; 299 goto again; 300 } 301 CONFerr(CONF_F_CONF_LOAD_BIO, 302 CONF_R_MISSING_CLOSE_SQUARE_BRACKET); 303 goto err; 304 } 305 *end='\0'; 306 if (!str_copy(conf,NULL,§ion,start)) goto err; 307 if ((sv=_CONF_get_section(conf,section)) == NULL) 308 sv=_CONF_new_section(conf,section); 309 if (sv == NULL) 310 { 311 CONFerr(CONF_F_CONF_LOAD_BIO, 312 CONF_R_UNABLE_TO_CREATE_NEW_SECTION); 313 goto err; 314 } 315 section_sk=(STACK_OF(CONF_VALUE) *)sv->value; 316 continue; 317 } 318 else 319 { 320 pname=s; 321 psection=NULL; 322 end=eat_alpha_numeric(conf, s); 323 if ((end[0] == ':') && (end[1] == ':')) 324 { 325 *end='\0'; 326 end+=2; 327 psection=pname; 328 pname=end; 329 end=eat_alpha_numeric(conf, end); 330 } 331 p=eat_ws(conf, end); 332 if (*p != '=') 333 { 334 CONFerr(CONF_F_CONF_LOAD_BIO, 335 CONF_R_MISSING_EQUAL_SIGN); 336 goto err; 337 } 338 *end='\0'; 339 p++; 340 start=eat_ws(conf, p); 341 while (!IS_EOF(conf,*p)) 342 p++; 343 p--; 344 while ((p != start) && (IS_WS(conf,*p))) 345 p--; 346 p++; 347 *p='\0'; 348 349 if (!(v=(CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) 350 { 351 CONFerr(CONF_F_CONF_LOAD_BIO, 352 ERR_R_MALLOC_FAILURE); 353 goto err; 354 } 355 if (psection == NULL) psection=section; 356 v->name=(char *)OPENSSL_malloc(strlen(pname)+1); 357 v->value=NULL; 358 if (v->name == NULL) 359 { 360 CONFerr(CONF_F_CONF_LOAD_BIO, 361 ERR_R_MALLOC_FAILURE); 362 goto err; 363 } 364 strcpy(v->name,pname); 365 if (!str_copy(conf,psection,&(v->value),start)) goto err; 366 367 if (strcmp(psection,section) != 0) 368 { 369 if ((tv=_CONF_get_section(conf,psection)) 370 == NULL) 371 tv=_CONF_new_section(conf,psection); 372 if (tv == NULL) 373 { 374 CONFerr(CONF_F_CONF_LOAD_BIO, 375 CONF_R_UNABLE_TO_CREATE_NEW_SECTION); 376 goto err; 377 } 378 ts=(STACK_OF(CONF_VALUE) *)tv->value; 379 } 380 else 381 { 382 tv=sv; 383 ts=section_sk; 384 } 385 #if 1 386 if (_CONF_add_string(conf, tv, v) == 0) 387 { 388 CONFerr(CONF_F_CONF_LOAD_BIO, 389 ERR_R_MALLOC_FAILURE); 390 goto err; 391 } 392 #else 393 v->section=tv->section; 394 if (!sk_CONF_VALUE_push(ts,v)) 395 { 396 CONFerr(CONF_F_CONF_LOAD_BIO, 397 ERR_R_MALLOC_FAILURE); 398 goto err; 399 } 400 vv=(CONF_VALUE *)lh_insert(conf->data,v); 401 if (vv != NULL) 402 { 403 sk_CONF_VALUE_delete_ptr(ts,vv); 404 OPENSSL_free(vv->name); 405 OPENSSL_free(vv->value); 406 OPENSSL_free(vv); 407 } 408 #endif 409 v=NULL; 410 } 411 } 412 if (buff != NULL) BUF_MEM_free(buff); 413 if (section != NULL) OPENSSL_free(section); 414 return(1); 415 err: 416 if (buff != NULL) BUF_MEM_free(buff); 417 if (section != NULL) OPENSSL_free(section); 418 if (line != NULL) *line=eline; 419 sprintf(btmp,"%ld",eline); 420 ERR_add_error_data(2,"line ",btmp); 421 if ((h != conf->data) && (conf->data != NULL)) CONF_free(conf->data); 422 if (v != NULL) 423 { 424 if (v->name != NULL) OPENSSL_free(v->name); 425 if (v->value != NULL) OPENSSL_free(v->value); 426 if (v != NULL) OPENSSL_free(v); 427 } 428 return(0); 429 } 430 431 static void clear_comments(CONF *conf, char *p) 432 { 433 char *to; 434 435 to=p; 436 for (;;) 437 { 438 if (IS_FCOMMENT(conf,*p)) 439 { 440 *p='\0'; 441 return; 442 } 443 if (!IS_WS(conf,*p)) 444 { 445 break; 446 } 447 p++; 448 } 449 450 for (;;) 451 { 452 if (IS_COMMENT(conf,*p)) 453 { 454 *p='\0'; 455 return; 456 } 457 if (IS_DQUOTE(conf,*p)) 458 { 459 p=scan_dquote(conf, p); 460 continue; 461 } 462 if (IS_QUOTE(conf,*p)) 463 { 464 p=scan_quote(conf, p); 465 continue; 466 } 467 if (IS_ESC(conf,*p)) 468 { 469 p=scan_esc(conf,p); 470 continue; 471 } 472 if (IS_EOF(conf,*p)) 473 return; 474 else 475 p++; 476 } 477 } 478 479 static int str_copy(CONF *conf, char *section, char **pto, char *from) 480 { 481 int q,r,rr=0,to=0,len=0; 482 char *s,*e,*rp,*p,*rrp,*np,*cp,v; 483 BUF_MEM *buf; 484 485 if ((buf=BUF_MEM_new()) == NULL) return(0); 486 487 len=strlen(from)+1; 488 if (!BUF_MEM_grow(buf,len)) goto err; 489 490 for (;;) 491 { 492 if (IS_QUOTE(conf,*from)) 493 { 494 q= *from; 495 from++; 496 while (!IS_EOF(conf,*from) && (*from != q)) 497 { 498 if (IS_ESC(conf,*from)) 499 { 500 from++; 501 if (IS_EOF(conf,*from)) break; 502 } 503 buf->data[to++]= *(from++); 504 } 505 if (*from == q) from++; 506 } 507 else if (IS_DQUOTE(conf,*from)) 508 { 509 q= *from; 510 from++; 511 while (!IS_EOF(conf,*from)) 512 { 513 if (*from == q) 514 { 515 if (*(from+1) == q) 516 { 517 from++; 518 } 519 else 520 { 521 break; 522 } 523 } 524 buf->data[to++]= *(from++); 525 } 526 if (*from == q) from++; 527 } 528 else if (IS_ESC(conf,*from)) 529 { 530 from++; 531 v= *(from++); 532 if (IS_EOF(conf,v)) break; 533 else if (v == 'r') v='\r'; 534 else if (v == 'n') v='\n'; 535 else if (v == 'b') v='\b'; 536 else if (v == 't') v='\t'; 537 buf->data[to++]= v; 538 } 539 else if (IS_EOF(conf,*from)) 540 break; 541 else if (*from == '$') 542 { 543 /* try to expand it */ 544 rrp=NULL; 545 s= &(from[1]); 546 if (*s == '{') 547 q='}'; 548 else if (*s == '(') 549 q=')'; 550 else q=0; 551 552 if (q) s++; 553 cp=section; 554 e=np=s; 555 while (IS_ALPHA_NUMERIC(conf,*e)) 556 e++; 557 if ((e[0] == ':') && (e[1] == ':')) 558 { 559 cp=np; 560 rrp=e; 561 rr= *e; 562 *rrp='\0'; 563 e+=2; 564 np=e; 565 while (IS_ALPHA_NUMERIC(conf,*e)) 566 e++; 567 } 568 r= *e; 569 *e='\0'; 570 rp=e; 571 if (q) 572 { 573 if (r != q) 574 { 575 CONFerr(CONF_F_STR_COPY,CONF_R_NO_CLOSE_BRACE); 576 goto err; 577 } 578 e++; 579 } 580 /* So at this point we have 581 * ns which is the start of the name string which is 582 * '\0' terminated. 583 * cs which is the start of the section string which is 584 * '\0' terminated. 585 * e is the 'next point after'. 586 * r and s are the chars replaced by the '\0' 587 * rp and sp is where 'r' and 's' came from. 588 */ 589 p=_CONF_get_string(conf,cp,np); 590 if (rrp != NULL) *rrp=rr; 591 *rp=r; 592 if (p == NULL) 593 { 594 CONFerr(CONF_F_STR_COPY,CONF_R_VARIABLE_HAS_NO_VALUE); 595 goto err; 596 } 597 BUF_MEM_grow(buf,(strlen(p)+len-(e-from))); 598 while (*p) 599 buf->data[to++]= *(p++); 600 from=e; 601 } 602 else 603 buf->data[to++]= *(from++); 604 } 605 buf->data[to]='\0'; 606 if (*pto != NULL) OPENSSL_free(*pto); 607 *pto=buf->data; 608 OPENSSL_free(buf); 609 return(1); 610 err: 611 if (buf != NULL) BUF_MEM_free(buf); 612 return(0); 613 } 614 615 static char *eat_ws(CONF *conf, char *p) 616 { 617 while (IS_WS(conf,*p) && (!IS_EOF(conf,*p))) 618 p++; 619 return(p); 620 } 621 622 static char *eat_alpha_numeric(CONF *conf, char *p) 623 { 624 for (;;) 625 { 626 if (IS_ESC(conf,*p)) 627 { 628 p=scan_esc(conf,p); 629 continue; 630 } 631 if (!IS_ALPHA_NUMERIC_PUNCT(conf,*p)) 632 return(p); 633 p++; 634 } 635 } 636 637 static char *scan_quote(CONF *conf, char *p) 638 { 639 int q= *p; 640 641 p++; 642 while (!(IS_EOF(conf,*p)) && (*p != q)) 643 { 644 if (IS_ESC(conf,*p)) 645 { 646 p++; 647 if (IS_EOF(conf,*p)) return(p); 648 } 649 p++; 650 } 651 if (*p == q) p++; 652 return(p); 653 } 654 655 656 static char *scan_dquote(CONF *conf, char *p) 657 { 658 int q= *p; 659 660 p++; 661 while (!(IS_EOF(conf,*p))) 662 { 663 if (*p == q) 664 { 665 if (*(p+1) == q) 666 { 667 p++; 668 } 669 else 670 { 671 break; 672 } 673 } 674 p++; 675 } 676 if (*p == q) p++; 677 return(p); 678 } 679 680 static void dump_value(CONF_VALUE *a, BIO *out) 681 { 682 if (a->name) 683 BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value); 684 else 685 BIO_printf(out, "[[%s]]\n", a->section); 686 } 687 688 static int def_dump(CONF *conf, BIO *out) 689 { 690 lh_doall_arg(conf->data, (void (*)())dump_value, out); 691 return 1; 692 } 693 694 static int def_is_number(CONF *conf, char c) 695 { 696 return IS_NUMBER(conf,c); 697 } 698 699 static int def_to_int(CONF *conf, char c) 700 { 701 return c - '0'; 702 } 703 704