1 /* $OpenBSD: parse.y,v 1.19 2016/07/13 16:35:47 jsing Exp $ */ 2 3 /* 4 * Copyright (c) 2009, 2010 Martin Hedenfalk <martinh@openbsd.org> 5 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> 6 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> 7 * Copyright (c) 2001 Markus Friedl. All rights reserved. 8 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 9 * Copyright (c) 2001 Theo de Raadt. All rights reserved. 10 * 11 * Permission to use, copy, modify, and distribute this software for any 12 * purpose with or without fee is hereby granted, provided that the above 13 * copyright notice and this permission notice appear in all copies. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24 %{ 25 #include <sys/types.h> 26 #include <sys/queue.h> 27 #include <sys/tree.h> 28 #include <sys/socket.h> 29 #include <sys/stat.h> 30 #include <sys/un.h> 31 #include <netinet/in.h> 32 #include <arpa/inet.h> 33 34 #include <ctype.h> 35 #include <err.h> 36 #include <errno.h> 37 #include <ifaddrs.h> 38 #include <limits.h> 39 #include <netdb.h> 40 #include <stdarg.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <syslog.h> 45 #include <unistd.h> 46 47 #include "ldapd.h" 48 49 TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 50 static struct file { 51 TAILQ_ENTRY(file) entry; 52 FILE *stream; 53 char *name; 54 int lineno; 55 int errors; 56 } *file, *topfile; 57 struct file *pushfile(const char *, int); 58 int popfile(void); 59 int check_file_secrecy(int, const char *); 60 int yyparse(void); 61 int yylex(void); 62 int yyerror(const char *, ...) 63 __attribute__((__format__ (printf, 1, 2))) 64 __attribute__((__nonnull__ (1))); 65 int kw_cmp(const void *, const void *); 66 int lookup(char *); 67 int lgetc(int); 68 int lungetc(int); 69 int findeol(void); 70 71 struct listener *host_unix(const char *path); 72 struct listener *host_v4(const char *, in_port_t); 73 struct listener *host_v6(const char *, in_port_t); 74 int host_dns(const char *, const char *, 75 struct listenerlist *, int, in_port_t, u_int8_t); 76 int host(const char *, const char *, 77 struct listenerlist *, int, in_port_t, u_int8_t); 78 int interface(const char *, const char *, 79 struct listenerlist *, int, in_port_t, u_int8_t); 80 int load_certfile(struct ldapd_config *, const char *, u_int8_t); 81 82 TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 83 struct sym { 84 TAILQ_ENTRY(sym) entry; 85 int used; 86 int persist; 87 char *nam; 88 char *val; 89 }; 90 int symset(const char *, const char *, int); 91 char *symget(const char *); 92 93 struct ldapd_config *conf; 94 95 SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp); 96 97 static struct aci *mk_aci(int type, int rights, enum scope scope, 98 char *target, char *subject); 99 100 typedef struct { 101 union { 102 int64_t number; 103 char *string; 104 struct aci *aci; 105 } v; 106 int lineno; 107 } YYSTYPE; 108 109 static struct namespace *current_ns = NULL; 110 111 %} 112 113 %token ERROR LISTEN ON TLS LDAPS PORT NAMESPACE ROOTDN ROOTPW INDEX 114 %token SECURE RELAX STRICT SCHEMA USE COMPRESSION LEVEL 115 %token INCLUDE CERTIFICATE FSYNC CACHE_SIZE INDEX_CACHE_SIZE 116 %token DENY ALLOW READ WRITE BIND ACCESS TO ROOT REFERRAL 117 %token ANY CHILDREN OF ATTRIBUTE IN SUBTREE BY SELF 118 %token <v.string> STRING 119 %token <v.number> NUMBER 120 %type <v.number> port ssl boolean comp_level 121 %type <v.number> aci_type aci_access aci_rights aci_right aci_scope 122 %type <v.string> aci_target aci_subject certname 123 %type <v.aci> aci 124 125 %% 126 127 grammar : /* empty */ 128 | grammar '\n' 129 | grammar include '\n' 130 | grammar varset '\n' 131 | grammar conf_main '\n' 132 | grammar error '\n' { file->errors++; } 133 | grammar namespace '\n' 134 | grammar aci '\n' { 135 SIMPLEQ_INSERT_TAIL(&conf->acl, $2, entry); 136 } 137 | grammar schema '\n' 138 ; 139 140 ssl : /* empty */ { $$ = 0; } 141 | TLS { $$ = F_STARTTLS; } 142 | LDAPS { $$ = F_LDAPS; } 143 | SECURE { $$ = F_SECURE; } 144 ; 145 146 certname : /* empty */ { $$ = NULL; } 147 | CERTIFICATE STRING { $$ = $2; } 148 ; 149 150 port : PORT STRING { 151 struct servent *servent; 152 153 servent = getservbyname($2, "tcp"); 154 if (servent == NULL) { 155 yyerror("port %s is invalid", $2); 156 free($2); 157 YYERROR; 158 } 159 $$ = servent->s_port; 160 free($2); 161 } 162 | PORT NUMBER { 163 if ($2 <= 0 || $2 >= (int)USHRT_MAX) { 164 yyerror("invalid port: %lld", $2); 165 YYERROR; 166 } 167 $$ = htons($2); 168 } 169 | /* empty */ { 170 $$ = 0; 171 } 172 ; 173 174 conf_main : LISTEN ON STRING port ssl certname { 175 char *cert; 176 177 if ($4 == 0) { 178 if ($5 == F_LDAPS) 179 $4 = htons(LDAPS_PORT); 180 else 181 $4 = htons(LDAP_PORT); 182 } 183 184 cert = ($6 != NULL) ? $6 : $3; 185 186 if (($5 == F_STARTTLS || $5 == F_LDAPS) && 187 load_certfile(conf, cert, F_SCERT) < 0) { 188 yyerror("cannot load certificate: %s", cert); 189 free($6); 190 free($3); 191 YYERROR; 192 } 193 194 if (! interface($3, cert, &conf->listeners, 195 MAX_LISTEN, $4, $5)) { 196 if (host($3, cert, &conf->listeners, 197 MAX_LISTEN, $4, $5) <= 0) { 198 yyerror("invalid virtual ip or interface: %s", $3); 199 free($6); 200 free($3); 201 YYERROR; 202 } 203 } 204 free($6); 205 free($3); 206 } 207 | REFERRAL STRING { 208 struct referral *ref; 209 if ((ref = calloc(1, sizeof(*ref))) == NULL) { 210 yyerror("calloc"); 211 free($2); 212 YYERROR; 213 } 214 ref->url = $2; 215 SLIST_INSERT_HEAD(&conf->referrals, ref, next); 216 } 217 | ROOTDN STRING { 218 conf->rootdn = $2; 219 normalize_dn(conf->rootdn); 220 } 221 | ROOTPW STRING { conf->rootpw = $2; } 222 ; 223 224 namespace : NAMESPACE STRING '{' '\n' { 225 log_debug("parsing namespace %s", $2); 226 current_ns = namespace_new($2); 227 free($2); 228 TAILQ_INSERT_TAIL(&conf->namespaces, current_ns, next); 229 } ns_opts '}' { current_ns = NULL; } 230 ; 231 232 boolean : STRING { 233 if (strcasecmp($1, "true") == 0 || 234 strcasecmp($1, "yes") == 0) 235 $$ = 1; 236 else if (strcasecmp($1, "false") == 0 || 237 strcasecmp($1, "off") == 0 || 238 strcasecmp($1, "no") == 0) 239 $$ = 0; 240 else { 241 yyerror("invalid boolean value '%s'", $1); 242 free($1); 243 YYERROR; 244 } 245 free($1); 246 } 247 | ON { $$ = 1; } 248 ; 249 250 ns_opts : /* empty */ 251 | ns_opts '\n' 252 | ns_opts ns_opt '\n' 253 ; 254 255 ns_opt : ROOTDN STRING { 256 current_ns->rootdn = $2; 257 normalize_dn(current_ns->rootdn); 258 } 259 | ROOTPW STRING { current_ns->rootpw = $2; } 260 | INDEX STRING { 261 struct attr_index *ai; 262 if ((ai = calloc(1, sizeof(*ai))) == NULL) { 263 yyerror("calloc"); 264 free($2); 265 YYERROR; 266 } 267 ai->attr = $2; 268 ai->type = INDEX_EQUAL; 269 TAILQ_INSERT_TAIL(¤t_ns->indices, ai, next); 270 } 271 | CACHE_SIZE NUMBER { current_ns->cache_size = $2; } 272 | INDEX_CACHE_SIZE NUMBER { current_ns->index_cache_size = $2; } 273 | FSYNC boolean { current_ns->sync = $2; } 274 | aci { 275 SIMPLEQ_INSERT_TAIL(¤t_ns->acl, $1, entry); 276 } 277 | RELAX SCHEMA { current_ns->relax = 1; } 278 | STRICT SCHEMA { current_ns->relax = 0; } 279 | USE COMPRESSION comp_level { current_ns->compression_level = $3; } 280 | REFERRAL STRING { 281 struct referral *ref; 282 if ((ref = calloc(1, sizeof(*ref))) == NULL) { 283 yyerror("calloc"); 284 free($2); 285 YYERROR; 286 } 287 ref->url = $2; 288 SLIST_INSERT_HEAD(¤t_ns->referrals, ref, next); 289 } 290 ; 291 292 comp_level : /* empty */ { $$ = 6; } 293 | LEVEL NUMBER { $$ = $2; } 294 ; 295 296 aci : aci_type aci_access TO aci_scope aci_target aci_subject { 297 if (($$ = mk_aci($1, $2, $4, $5, $6)) == NULL) { 298 free($5); 299 free($6); 300 YYERROR; 301 } 302 } 303 | aci_type aci_access { 304 if (($$ = mk_aci($1, $2, LDAP_SCOPE_SUBTREE, NULL, 305 NULL)) == NULL) { 306 YYERROR; 307 } 308 } 309 ; 310 311 aci_type : DENY { $$ = ACI_DENY; } 312 | ALLOW { $$ = ACI_ALLOW; } 313 ; 314 315 aci_access : /* empty */ { $$ = ACI_ALL; } 316 | ACCESS { $$ = ACI_ALL; } 317 | aci_rights ACCESS { $$ = $1; } 318 ; 319 320 aci_rights : aci_right { $$ = $1; } 321 | aci_rights ',' aci_right { $$ = $1 | $3; } 322 ; 323 324 aci_right : READ { $$ = ACI_READ; } 325 | WRITE { $$ = ACI_WRITE; } 326 | BIND { $$ = ACI_BIND; } 327 ; 328 329 330 aci_scope : /* empty */ { $$ = LDAP_SCOPE_BASE; } 331 | SUBTREE { $$ = LDAP_SCOPE_SUBTREE; } 332 | CHILDREN OF { $$ = LDAP_SCOPE_ONELEVEL; } 333 ; 334 335 aci_target : ANY { $$ = NULL; } 336 | ROOT { $$ = strdup(""); } 337 | STRING { $$ = $1; normalize_dn($$); } 338 ; 339 340 aci_subject : /* empty */ { $$ = NULL; } 341 | BY ANY { $$ = NULL; } 342 | BY STRING { $$ = $2; normalize_dn($$); } 343 | BY SELF { $$ = strdup("@"); } 344 ; 345 346 include : INCLUDE STRING { 347 struct file *nfile; 348 349 if ((nfile = pushfile($2, 1)) == NULL) { 350 yyerror("failed to include file %s", $2); 351 free($2); 352 YYERROR; 353 } 354 free($2); 355 356 file = nfile; 357 lungetc('\n'); 358 } 359 ; 360 361 varset : STRING '=' STRING { 362 char *s = $1; 363 while (*s++) { 364 if (isspace((unsigned char)*s)) { 365 yyerror("macro name cannot contain " 366 "whitespace"); 367 YYERROR; 368 } 369 } 370 if (symset($1, $3, 0) == -1) 371 fatal("cannot store variable"); 372 free($1); 373 free($3); 374 } 375 ; 376 377 schema : SCHEMA STRING { 378 int ret; 379 380 ret = schema_parse(conf->schema, $2); 381 free($2); 382 if (ret != 0) { 383 YYERROR; 384 } 385 } 386 ; 387 388 %% 389 390 struct keywords { 391 const char *k_name; 392 int k_val; 393 }; 394 395 int 396 yyerror(const char *fmt, ...) 397 { 398 va_list ap; 399 char *msg; 400 401 file->errors++; 402 va_start(ap, fmt); 403 if (vasprintf(&msg, fmt, ap) == -1) 404 fatalx("yyerror vasprintf"); 405 va_end(ap); 406 logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg); 407 free(msg); 408 return (0); 409 } 410 411 int 412 kw_cmp(const void *k, const void *e) 413 { 414 return (strcmp(k, ((const struct keywords *)e)->k_name)); 415 } 416 417 int 418 lookup(char *s) 419 { 420 /* this has to be sorted always */ 421 static const struct keywords keywords[] = { 422 { "access", ACCESS }, 423 { "allow", ALLOW }, 424 { "any", ANY }, 425 { "bind", BIND }, 426 { "by", BY }, 427 { "cache-size", CACHE_SIZE }, 428 { "certificate", CERTIFICATE }, 429 { "children", CHILDREN }, 430 { "compression", COMPRESSION }, 431 { "deny", DENY }, 432 { "fsync", FSYNC }, 433 { "in", IN }, 434 { "include", INCLUDE }, 435 { "index", INDEX }, 436 { "index-cache-size", INDEX_CACHE_SIZE }, 437 { "ldaps", LDAPS }, 438 { "level", LEVEL }, 439 { "listen", LISTEN }, 440 { "namespace", NAMESPACE }, 441 { "of", OF }, 442 { "on", ON }, 443 { "port", PORT }, 444 { "read", READ }, 445 { "referral", REFERRAL }, 446 { "relax", RELAX }, 447 { "root", ROOT }, 448 { "rootdn", ROOTDN }, 449 { "rootpw", ROOTPW }, 450 { "schema", SCHEMA }, 451 { "secure", SECURE }, 452 { "self", SELF }, 453 { "strict", STRICT }, 454 { "subtree", SUBTREE }, 455 { "tls", TLS }, 456 { "to", TO }, 457 { "use", USE }, 458 { "write", WRITE }, 459 460 }; 461 const struct keywords *p; 462 463 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 464 sizeof(keywords[0]), kw_cmp); 465 466 if (p) 467 return (p->k_val); 468 else 469 return (STRING); 470 } 471 472 #define MAXPUSHBACK 128 473 474 u_char *parsebuf; 475 int parseindex; 476 u_char pushback_buffer[MAXPUSHBACK]; 477 int pushback_index = 0; 478 479 int 480 lgetc(int quotec) 481 { 482 int c, next; 483 484 if (parsebuf) { 485 /* Read character from the parsebuffer instead of input. */ 486 if (parseindex >= 0) { 487 c = parsebuf[parseindex++]; 488 if (c != '\0') 489 return (c); 490 parsebuf = NULL; 491 } else 492 parseindex++; 493 } 494 495 if (pushback_index) 496 return (pushback_buffer[--pushback_index]); 497 498 if (quotec) { 499 if ((c = getc(file->stream)) == EOF) { 500 yyerror("reached end of file while parsing " 501 "quoted string"); 502 if (file == topfile || popfile() == EOF) 503 return (EOF); 504 return (quotec); 505 } 506 return (c); 507 } 508 509 while ((c = getc(file->stream)) == '\\') { 510 next = getc(file->stream); 511 if (next != '\n') { 512 c = next; 513 break; 514 } 515 yylval.lineno = file->lineno; 516 file->lineno++; 517 } 518 519 while (c == EOF) { 520 if (file == topfile || popfile() == EOF) 521 return (EOF); 522 c = getc(file->stream); 523 } 524 return (c); 525 } 526 527 int 528 lungetc(int c) 529 { 530 if (c == EOF) 531 return (EOF); 532 if (parsebuf) { 533 parseindex--; 534 if (parseindex >= 0) 535 return (c); 536 } 537 if (pushback_index < MAXPUSHBACK-1) 538 return (pushback_buffer[pushback_index++] = c); 539 else 540 return (EOF); 541 } 542 543 int 544 findeol(void) 545 { 546 int c; 547 548 parsebuf = NULL; 549 550 /* skip to either EOF or the first real EOL */ 551 while (1) { 552 if (pushback_index) 553 c = pushback_buffer[--pushback_index]; 554 else 555 c = lgetc(0); 556 if (c == '\n') { 557 file->lineno++; 558 break; 559 } 560 if (c == EOF) 561 break; 562 } 563 return (ERROR); 564 } 565 566 int 567 yylex(void) 568 { 569 u_char buf[4096]; 570 u_char *p, *val; 571 int quotec, next, c; 572 int token; 573 574 top: 575 p = buf; 576 while ((c = lgetc(0)) == ' ' || c == '\t') 577 ; /* nothing */ 578 579 yylval.lineno = file->lineno; 580 if (c == '#') 581 while ((c = lgetc(0)) != '\n' && c != EOF) 582 ; /* nothing */ 583 if (c == '$' && parsebuf == NULL) { 584 while (1) { 585 if ((c = lgetc(0)) == EOF) 586 return (0); 587 588 if (p + 1 >= buf + sizeof(buf) - 1) { 589 yyerror("string too long"); 590 return (findeol()); 591 } 592 if (isalnum(c) || c == '_') { 593 *p++ = c; 594 continue; 595 } 596 *p = '\0'; 597 lungetc(c); 598 break; 599 } 600 val = symget(buf); 601 if (val == NULL) { 602 yyerror("macro '%s' not defined", buf); 603 return (findeol()); 604 } 605 parsebuf = val; 606 parseindex = 0; 607 goto top; 608 } 609 610 switch (c) { 611 case '\'': 612 case '"': 613 quotec = c; 614 while (1) { 615 if ((c = lgetc(quotec)) == EOF) 616 return (0); 617 if (c == '\n') { 618 file->lineno++; 619 continue; 620 } else if (c == '\\') { 621 if ((next = lgetc(quotec)) == EOF) 622 return (0); 623 if (next == quotec || c == ' ' || c == '\t') 624 c = next; 625 else if (next == '\n') { 626 file->lineno++; 627 continue; 628 } else 629 lungetc(next); 630 } else if (c == quotec) { 631 *p = '\0'; 632 break; 633 } else if (c == '\0') { 634 yyerror("syntax error"); 635 return (findeol()); 636 } 637 if (p + 1 >= buf + sizeof(buf) - 1) { 638 log_warnx("string too long"); 639 return (findeol()); 640 } 641 *p++ = c; 642 } 643 yylval.v.string = strdup(buf); 644 if (yylval.v.string == NULL) 645 fatal("yylex: strdup"); 646 return (STRING); 647 } 648 649 #define allowed_to_end_number(x) \ 650 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 651 652 if (c == '-' || isdigit(c)) { 653 do { 654 *p++ = c; 655 if ((unsigned)(p-buf) >= sizeof(buf)) { 656 yyerror("string too long"); 657 return (findeol()); 658 } 659 } while ((c = lgetc(0)) != EOF && isdigit(c)); 660 lungetc(c); 661 if (p == buf + 1 && buf[0] == '-') 662 goto nodigits; 663 if (c == EOF || allowed_to_end_number(c)) { 664 const char *errstr = NULL; 665 666 *p = '\0'; 667 yylval.v.number = strtonum(buf, LLONG_MIN, 668 LLONG_MAX, &errstr); 669 if (errstr) { 670 yyerror("\"%s\" invalid number: %s", 671 buf, errstr); 672 return (findeol()); 673 } 674 return (NUMBER); 675 } else { 676 nodigits: 677 while (p > buf + 1) 678 lungetc(*--p); 679 c = *--p; 680 if (c == '-') 681 return (c); 682 } 683 } 684 685 #define allowed_in_string(x) \ 686 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 687 x != '{' && x != '}' && x != '<' && x != '>' && \ 688 x != '!' && x != '=' && x != '/' && x != '#' && \ 689 x != ',')) 690 691 if (isalnum(c) || c == ':' || c == '_' || c == '*') { 692 do { 693 *p++ = c; 694 if ((unsigned)(p-buf) >= sizeof(buf)) { 695 yyerror("string too long"); 696 return (findeol()); 697 } 698 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 699 lungetc(c); 700 *p = '\0'; 701 if ((token = lookup(buf)) == STRING) 702 if ((yylval.v.string = strdup(buf)) == NULL) 703 fatal("yylex: strdup"); 704 return (token); 705 } 706 if (c == '\n') { 707 yylval.lineno = file->lineno; 708 file->lineno++; 709 } 710 if (c == EOF) 711 return (0); 712 return (c); 713 } 714 715 int 716 check_file_secrecy(int fd, const char *fname) 717 { 718 struct stat st; 719 720 if (fstat(fd, &st)) { 721 log_warn("cannot stat %s", fname); 722 return (-1); 723 } 724 if (st.st_uid != 0 && st.st_uid != getuid()) { 725 log_warnx("%s: owner not root or current user", fname); 726 return (-1); 727 } 728 if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { 729 log_warnx("%s: group writable or world read/writable", fname); 730 return (-1); 731 } 732 return (0); 733 } 734 735 struct file * 736 pushfile(const char *name, int secret) 737 { 738 struct file *nfile; 739 740 log_debug("parsing config %s", name); 741 742 if ((nfile = calloc(1, sizeof(struct file))) == NULL) { 743 log_warn("malloc"); 744 return (NULL); 745 } 746 if ((nfile->name = strdup(name)) == NULL) { 747 log_warn("malloc"); 748 free(nfile); 749 return (NULL); 750 } 751 if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 752 log_warn("%s", nfile->name); 753 free(nfile->name); 754 free(nfile); 755 return (NULL); 756 } 757 if (secret && 758 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 759 fclose(nfile->stream); 760 free(nfile->name); 761 free(nfile); 762 return (NULL); 763 } 764 nfile->lineno = 1; 765 TAILQ_INSERT_TAIL(&files, nfile, entry); 766 return (nfile); 767 } 768 769 int 770 popfile(void) 771 { 772 struct file *prev; 773 774 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) 775 prev->errors += file->errors; 776 777 TAILQ_REMOVE(&files, file, entry); 778 fclose(file->stream); 779 free(file->name); 780 free(file); 781 file = prev; 782 return (file ? 0 : EOF); 783 } 784 785 int 786 parse_config(char *filename) 787 { 788 struct sym *sym, *next; 789 int errors = 0; 790 791 if ((conf = calloc(1, sizeof(struct ldapd_config))) == NULL) 792 fatal(NULL); 793 794 conf->schema = schema_new(); 795 if (conf->schema == NULL) 796 fatal("schema_new"); 797 798 TAILQ_INIT(&conf->namespaces); 799 TAILQ_INIT(&conf->listeners); 800 if ((conf->sc_ssl = calloc(1, sizeof(*conf->sc_ssl))) == NULL) 801 fatal(NULL); 802 SPLAY_INIT(conf->sc_ssl); 803 SIMPLEQ_INIT(&conf->acl); 804 SLIST_INIT(&conf->referrals); 805 806 if ((file = pushfile(filename, 1)) == NULL) { 807 free(conf); 808 return (-1); 809 } 810 topfile = file; 811 812 yyparse(); 813 errors = file->errors; 814 popfile(); 815 816 /* Free macros and check which have not been used. */ 817 for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { 818 next = TAILQ_NEXT(sym, entry); 819 log_debug("warning: macro \"%s\" not used", sym->nam); 820 if (!sym->persist) { 821 free(sym->nam); 822 free(sym->val); 823 TAILQ_REMOVE(&symhead, sym, entry); 824 free(sym); 825 } 826 } 827 828 return (errors ? -1 : 0); 829 } 830 831 int 832 symset(const char *nam, const char *val, int persist) 833 { 834 struct sym *sym; 835 836 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 837 sym = TAILQ_NEXT(sym, entry)) 838 ; /* nothing */ 839 840 if (sym != NULL) { 841 if (sym->persist == 1) 842 return (0); 843 else { 844 free(sym->nam); 845 free(sym->val); 846 TAILQ_REMOVE(&symhead, sym, entry); 847 free(sym); 848 } 849 } 850 if ((sym = calloc(1, sizeof(*sym))) == NULL) 851 return (-1); 852 853 sym->nam = strdup(nam); 854 if (sym->nam == NULL) { 855 free(sym); 856 return (-1); 857 } 858 sym->val = strdup(val); 859 if (sym->val == NULL) { 860 free(sym->nam); 861 free(sym); 862 return (-1); 863 } 864 sym->used = 0; 865 sym->persist = persist; 866 TAILQ_INSERT_TAIL(&symhead, sym, entry); 867 return (0); 868 } 869 870 int 871 cmdline_symset(char *s) 872 { 873 char *sym, *val; 874 int ret; 875 size_t len; 876 877 if ((val = strrchr(s, '=')) == NULL) 878 return (-1); 879 880 len = strlen(s) - strlen(val) + 1; 881 if ((sym = malloc(len)) == NULL) 882 fatal("cmdline_symset: malloc"); 883 884 strlcpy(sym, s, len); 885 886 ret = symset(sym, val + 1, 1); 887 free(sym); 888 889 return (ret); 890 } 891 892 char * 893 symget(const char *nam) 894 { 895 struct sym *sym; 896 897 TAILQ_FOREACH(sym, &symhead, entry) 898 if (strcmp(nam, sym->nam) == 0) { 899 sym->used = 1; 900 return (sym->val); 901 } 902 return (NULL); 903 } 904 905 struct listener * 906 host_unix(const char *path) 907 { 908 struct sockaddr_un *saun; 909 struct listener *h; 910 911 if (*path != '/') 912 return (NULL); 913 914 if ((h = calloc(1, sizeof(*h))) == NULL) 915 fatal(NULL); 916 saun = (struct sockaddr_un *)&h->ss; 917 saun->sun_len = sizeof(struct sockaddr_un); 918 saun->sun_family = AF_UNIX; 919 if (strlcpy(saun->sun_path, path, sizeof(saun->sun_path)) >= 920 sizeof(saun->sun_path)) 921 fatal("socket path too long"); 922 h->flags = F_SECURE; 923 924 return (h); 925 } 926 927 struct listener * 928 host_v4(const char *s, in_port_t port) 929 { 930 struct in_addr ina; 931 struct sockaddr_in *sain; 932 struct listener *h; 933 934 bzero(&ina, sizeof(ina)); 935 if (inet_pton(AF_INET, s, &ina) != 1) 936 return (NULL); 937 938 if ((h = calloc(1, sizeof(*h))) == NULL) 939 fatal(NULL); 940 sain = (struct sockaddr_in *)&h->ss; 941 sain->sin_len = sizeof(struct sockaddr_in); 942 sain->sin_family = AF_INET; 943 sain->sin_addr.s_addr = ina.s_addr; 944 sain->sin_port = port; 945 946 return (h); 947 } 948 949 struct listener * 950 host_v6(const char *s, in_port_t port) 951 { 952 struct in6_addr ina6; 953 struct sockaddr_in6 *sin6; 954 struct listener *h; 955 956 bzero(&ina6, sizeof(ina6)); 957 if (inet_pton(AF_INET6, s, &ina6) != 1) 958 return (NULL); 959 960 if ((h = calloc(1, sizeof(*h))) == NULL) 961 fatal(NULL); 962 sin6 = (struct sockaddr_in6 *)&h->ss; 963 sin6->sin6_len = sizeof(struct sockaddr_in6); 964 sin6->sin6_family = AF_INET6; 965 sin6->sin6_port = port; 966 memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6)); 967 968 return (h); 969 } 970 971 int 972 host_dns(const char *s, const char *cert, 973 struct listenerlist *al, int max, in_port_t port, u_int8_t flags) 974 { 975 struct addrinfo hints, *res0, *res; 976 int error, cnt = 0; 977 struct sockaddr_in *sain; 978 struct sockaddr_in6 *sin6; 979 struct listener *h; 980 981 bzero(&hints, sizeof(hints)); 982 hints.ai_family = PF_UNSPEC; 983 hints.ai_socktype = SOCK_DGRAM; /* DUMMY */ 984 error = getaddrinfo(s, NULL, &hints, &res0); 985 if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME) 986 return (0); 987 if (error) { 988 log_warnx("host_dns: could not parse \"%s\": %s", s, 989 gai_strerror(error)); 990 return (-1); 991 } 992 993 for (res = res0; res && cnt < max; res = res->ai_next) { 994 if (res->ai_family != AF_INET && 995 res->ai_family != AF_INET6) 996 continue; 997 if ((h = calloc(1, sizeof(*h))) == NULL) 998 fatal(NULL); 999 1000 h->port = port; 1001 h->flags = flags; 1002 h->ss.ss_family = res->ai_family; 1003 h->ssl = NULL; 1004 h->ssl_cert_name[0] = '\0'; 1005 if (cert != NULL) 1006 (void)strlcpy(h->ssl_cert_name, cert, sizeof(h->ssl_cert_name)); 1007 1008 if (res->ai_family == AF_INET) { 1009 sain = (struct sockaddr_in *)&h->ss; 1010 sain->sin_len = sizeof(struct sockaddr_in); 1011 sain->sin_addr.s_addr = ((struct sockaddr_in *) 1012 res->ai_addr)->sin_addr.s_addr; 1013 sain->sin_port = port; 1014 } else { 1015 sin6 = (struct sockaddr_in6 *)&h->ss; 1016 sin6->sin6_len = sizeof(struct sockaddr_in6); 1017 memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *) 1018 res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 1019 sin6->sin6_port = port; 1020 } 1021 1022 TAILQ_INSERT_HEAD(al, h, entry); 1023 cnt++; 1024 } 1025 if (cnt == max && res) { 1026 log_warnx("host_dns: %s resolves to more than %d hosts", 1027 s, max); 1028 } 1029 freeaddrinfo(res0); 1030 return (cnt); 1031 } 1032 1033 int 1034 host(const char *s, const char *cert, struct listenerlist *al, 1035 int max, in_port_t port, u_int8_t flags) 1036 { 1037 struct listener *h; 1038 1039 /* Unix socket path? */ 1040 h = host_unix(s); 1041 1042 /* IPv4 address? */ 1043 if (h == NULL) 1044 h = host_v4(s, port); 1045 1046 /* IPv6 address? */ 1047 if (h == NULL) 1048 h = host_v6(s, port); 1049 1050 if (h != NULL) { 1051 h->port = port; 1052 h->flags |= flags; 1053 h->ssl = NULL; 1054 h->ssl_cert_name[0] = '\0'; 1055 if (cert != NULL) 1056 strlcpy(h->ssl_cert_name, cert, sizeof(h->ssl_cert_name)); 1057 1058 TAILQ_INSERT_HEAD(al, h, entry); 1059 return (1); 1060 } 1061 1062 return (host_dns(s, cert, al, max, port, flags)); 1063 } 1064 1065 int 1066 interface(const char *s, const char *cert, 1067 struct listenerlist *al, int max, in_port_t port, u_int8_t flags) 1068 { 1069 int ret = 0; 1070 struct ifaddrs *ifap, *p; 1071 struct sockaddr_in *sain; 1072 struct sockaddr_in6 *sin6; 1073 struct listener *h; 1074 1075 if (getifaddrs(&ifap) == -1) 1076 fatal("getifaddrs"); 1077 1078 for (p = ifap; p != NULL; p = p->ifa_next) { 1079 if (strcmp(s, p->ifa_name) != 0) 1080 continue; 1081 1082 switch (p->ifa_addr->sa_family) { 1083 case AF_INET: 1084 if ((h = calloc(1, sizeof(*h))) == NULL) 1085 fatal(NULL); 1086 sain = (struct sockaddr_in *)&h->ss; 1087 *sain = *(struct sockaddr_in *)p->ifa_addr; 1088 sain->sin_len = sizeof(struct sockaddr_in); 1089 sain->sin_port = port; 1090 1091 h->fd = -1; 1092 h->port = port; 1093 h->flags = flags; 1094 h->ssl = NULL; 1095 h->ssl_cert_name[0] = '\0'; 1096 if (cert != NULL) 1097 (void)strlcpy(h->ssl_cert_name, cert, sizeof(h->ssl_cert_name)); 1098 1099 ret = 1; 1100 TAILQ_INSERT_HEAD(al, h, entry); 1101 1102 break; 1103 1104 case AF_INET6: 1105 if ((h = calloc(1, sizeof(*h))) == NULL) 1106 fatal(NULL); 1107 sin6 = (struct sockaddr_in6 *)&h->ss; 1108 *sin6 = *(struct sockaddr_in6 *)p->ifa_addr; 1109 sin6->sin6_len = sizeof(struct sockaddr_in6); 1110 sin6->sin6_port = port; 1111 1112 h->fd = -1; 1113 h->port = port; 1114 h->flags = flags; 1115 h->ssl = NULL; 1116 h->ssl_cert_name[0] = '\0'; 1117 if (cert != NULL) 1118 (void)strlcpy(h->ssl_cert_name, cert, sizeof(h->ssl_cert_name)); 1119 1120 ret = 1; 1121 TAILQ_INSERT_HEAD(al, h, entry); 1122 1123 break; 1124 } 1125 } 1126 1127 freeifaddrs(ifap); 1128 1129 return ret; 1130 } 1131 1132 static struct aci * 1133 mk_aci(int type, int rights, enum scope scope, char *target, char *subject) 1134 { 1135 struct aci *aci; 1136 1137 if ((aci = calloc(1, sizeof(*aci))) == NULL) { 1138 yyerror("calloc"); 1139 return NULL; 1140 } 1141 aci->type = type; 1142 aci->rights = rights; 1143 aci->scope = scope; 1144 aci->target = target; 1145 aci->subject = subject; 1146 1147 log_debug("%s %02X access to %s scope %d by %s", 1148 aci->type == ACI_DENY ? "deny" : "allow", 1149 aci->rights, 1150 aci->target ? aci->target : "any", 1151 aci->scope, 1152 aci->subject ? aci->subject : "any"); 1153 1154 return aci; 1155 } 1156 1157 struct namespace * 1158 namespace_new(const char *suffix) 1159 { 1160 struct namespace *ns; 1161 1162 if ((ns = calloc(1, sizeof(*ns))) == NULL) 1163 return NULL; 1164 ns->suffix = strdup(suffix); 1165 ns->sync = 1; 1166 ns->cache_size = 1024; 1167 ns->index_cache_size = 512; 1168 if (ns->suffix == NULL) { 1169 free(ns->suffix); 1170 free(ns); 1171 return NULL; 1172 } 1173 TAILQ_INIT(&ns->indices); 1174 TAILQ_INIT(&ns->request_queue); 1175 SIMPLEQ_INIT(&ns->acl); 1176 SLIST_INIT(&ns->referrals); 1177 1178 return ns; 1179 } 1180 1181 int 1182 ssl_cmp(struct ssl *s1, struct ssl *s2) 1183 { 1184 return (strcmp(s1->ssl_name, s2->ssl_name)); 1185 } 1186 1187 int 1188 load_certfile(struct ldapd_config *env, const char *name, u_int8_t flags) 1189 { 1190 struct ssl *s; 1191 struct ssl key; 1192 char certfile[PATH_MAX]; 1193 1194 if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name)) 1195 >= sizeof(key.ssl_name)) { 1196 log_warn("load_certfile: certificate name truncated"); 1197 return -1; 1198 } 1199 1200 s = SPLAY_FIND(ssltree, env->sc_ssl, &key); 1201 if (s != NULL) { 1202 s->flags |= flags; 1203 return 0; 1204 } 1205 1206 if ((s = calloc(1, sizeof(*s))) == NULL) 1207 fatal(NULL); 1208 1209 s->flags = flags; 1210 (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name)); 1211 1212 s->config = tls_config_new(); 1213 if (s->config == NULL) 1214 goto err; 1215 1216 tls_config_set_protocols(s->config, TLS_PROTOCOLS_ALL); 1217 if (tls_config_set_ciphers(s->config, "all")) { 1218 log_warn("load_certfile: failed to set tls ciphers: %s", 1219 tls_config_error(s->config)); 1220 goto err; 1221 } 1222 1223 if ((name[0] == '/' && 1224 !bsnprintf(certfile, sizeof(certfile), "%s.crt", name)) || 1225 !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.crt", 1226 name)) { 1227 log_warn("load_certfile: path truncated"); 1228 goto err; 1229 } 1230 1231 log_debug("loading certificate file %s", certfile); 1232 s->ssl_cert = tls_load_file(certfile, &s->ssl_cert_len, NULL); 1233 if (s->ssl_cert == NULL) 1234 goto err; 1235 1236 if (tls_config_set_cert_mem(s->config, s->ssl_cert, s->ssl_cert_len)) { 1237 log_warn("load_certfile: failed to set tls certificate: %s", 1238 tls_config_error(s->config)); 1239 goto err; 1240 } 1241 1242 if ((name[0] == '/' && 1243 !bsnprintf(certfile, sizeof(certfile), "%s.key", name)) || 1244 !bsnprintf(certfile, sizeof(certfile), "/etc/ldap/certs/%s.key", 1245 name)) { 1246 log_warn("load_certfile: path truncated"); 1247 goto err; 1248 } 1249 1250 log_debug("loading key file %s", certfile); 1251 s->ssl_key = tls_load_file(certfile, &s->ssl_key_len, NULL); 1252 if (s->ssl_key == NULL) 1253 goto err; 1254 1255 if (tls_config_set_key_mem(s->config, s->ssl_key, s->ssl_key_len)) { 1256 log_warn("load_certfile: failed to set tls key: %s", 1257 tls_config_error(s->config)); 1258 goto err; 1259 } 1260 1261 SPLAY_INSERT(ssltree, env->sc_ssl, s); 1262 1263 return (0); 1264 err: 1265 free(s->ssl_cert); 1266 free(s->ssl_key); 1267 tls_config_free(s->config); 1268 free(s); 1269 return (-1); 1270 } 1271