1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <string.h> 31 #include <stdlib.h> 32 #include <ctype.h> 33 #include <fcntl.h> 34 #include <unistd.h> 35 #include <errno.h> 36 #include <locale.h> 37 #include <lber.h> 38 #include <ldap.h> 39 #include <syslog.h> 40 #include <dlfcn.h> /* for dynamic loading only */ 41 42 #include "ldap_parse.h" 43 #include "nis_parse_ldap_conf.h" 44 #include "nis_parse_ldap_err.h" 45 #include "ldap_util.h" 46 #include "ldap_util.h" 47 48 void append_dot(char **str); 49 void append_comma(char **str); 50 bool_t make_full_dn(char **dn, const char *base); 51 bool_t make_fqdn(__nis_object_dn_t *dn, const char *base); 52 char *get_default_ldap_base(const char *domain); 53 bool_t add_domain(char **objName, const char *domain); 54 bool_t add_column(__nis_table_mapping_t *t, const char *col_name); 55 __nis_mapping_rule_t **dup_mapping_rules( 56 __nis_mapping_rule_t **rules, int n_rules); 57 __nis_mapping_rule_t *dup_mapping_rule( 58 __nis_mapping_rule_t *in); 59 void *s_malloc(size_t size); 60 __nis_mapping_format_t *dup_format_mapping( 61 __nis_mapping_format_t *in); 62 bool_t dup_mapping_element(__nis_mapping_element_t *in, 63 __nis_mapping_element_t *out); 64 65 extern FILE *cons; 66 67 /* 68 * FUNCTION: free_parse_structs 69 * 70 * Release the resources in parse results 71 * 72 */ 73 74 void 75 free_parse_structs() 76 { 77 __nis_table_mapping_t *t; 78 __nis_table_mapping_t *t1; 79 80 free_proxy_info(&proxyInfo); 81 for (t = ldapTableMapping; t != NULL; t = t1) { 82 t1 = t->next; 83 free_table_mapping(t); 84 } 85 ldapTableMapping = NULL; 86 } 87 88 /* 89 * FUNCTION: initialize_parse_structs 90 * 91 * Initialize fields to unset values 92 * 93 * INPUT: __nis_ldap_proxy_info, __nis_config_t 94 * and __nisdb_table_mapping_t structures 95 */ 96 97 void 98 initialize_parse_structs( 99 __nis_ldap_proxy_info *proxy_info, 100 __nis_config_t *config_info, 101 __nisdb_table_mapping_t *table_info) 102 { 103 proxy_info->default_servers = NULL; 104 proxy_info->auth_method = (auth_method_t)NO_VALUE_SET; 105 proxy_info->tls_method = (tls_method_t)NO_VALUE_SET; 106 proxy_info->tls_cert_db = NULL; 107 proxy_info->default_search_base = NULL; 108 proxy_info->proxy_dn = NULL; 109 proxy_info->proxy_passwd = NULL; 110 proxy_info->default_nis_domain = NULL; 111 proxy_info->bind_timeout.tv_sec = (time_t)NO_VALUE_SET; 112 proxy_info->bind_timeout.tv_usec = 0; 113 proxy_info->search_timeout.tv_sec = (time_t)NO_VALUE_SET; 114 proxy_info->search_timeout.tv_usec = 0; 115 proxy_info->modify_timeout.tv_sec = (time_t)NO_VALUE_SET; 116 proxy_info->modify_timeout.tv_usec = 0; 117 proxy_info->add_timeout.tv_sec = (time_t)NO_VALUE_SET; 118 proxy_info->add_timeout.tv_usec = 0; 119 proxy_info->delete_timeout.tv_sec = (time_t)NO_VALUE_SET; 120 proxy_info->delete_timeout.tv_usec = 0; 121 proxy_info->search_time_limit = (int)NO_VALUE_SET; 122 proxy_info->search_size_limit = (int)NO_VALUE_SET; 123 proxy_info->follow_referral = (follow_referral_t)NO_VALUE_SET; 124 125 126 config_info->initialUpdate = (__nis_initial_update_t)NO_VALUE_SET; 127 config_info->threadCreationError = 128 (__nis_thread_creation_error_t)NO_VALUE_SET; 129 config_info->threadCreationErrorTimeout.attempts = NO_VALUE_SET; 130 config_info->threadCreationErrorTimeout.timeout = (time_t)NO_VALUE_SET; 131 config_info->dumpError = (__nis_dump_error_t)NO_VALUE_SET; 132 config_info->dumpErrorTimeout.attempts = NO_VALUE_SET; 133 config_info->dumpErrorTimeout.timeout = (time_t)NO_VALUE_SET; 134 config_info->resyncService = (__nis_resync_service_t)NO_VALUE_SET; 135 config_info->updateBatching = (__nis_update_batching_t)NO_VALUE_SET; 136 config_info->updateBatchingTimeout.timeout = (time_t)NO_VALUE_SET; 137 config_info->numberOfServiceThreads = (int)NO_VALUE_SET; 138 config_info->emulate_yp = (int)NO_VALUE_SET; 139 config_info->maxRPCRecordSize = (int)NO_VALUE_SET; 140 141 table_info->retrieveError = (__nis_retrieve_error_t)NO_VALUE_SET; 142 table_info->retrieveErrorRetry.attempts = NO_VALUE_SET; 143 table_info->retrieveErrorRetry.timeout = (time_t)NO_VALUE_SET; 144 table_info->storeError = (__nis_store_error_t)NO_VALUE_SET; 145 table_info->storeErrorRetry.attempts = NO_VALUE_SET; 146 table_info->storeErrorRetry.timeout = (time_t)NO_VALUE_SET; 147 table_info->refreshError = (__nis_refresh_error_t)NO_VALUE_SET; 148 table_info->refreshErrorRetry.attempts = NO_VALUE_SET; 149 table_info->refreshErrorRetry.timeout = (time_t)NO_VALUE_SET; 150 table_info->matchFetch = (__nis_match_fetch_t)NO_VALUE_SET; 151 } 152 153 /* 154 * FUNCTION: free_mapping_rule 155 * 156 * Frees __nis_mapping_rule_t 157 * 158 * INPUT: __nis_mapping_rule_t 159 */ 160 161 void 162 free_mapping_rule(__nis_mapping_rule_t *rule) 163 { 164 int i; 165 __nis_mapping_rlhs_t *r; 166 167 if (rule != NULL) { 168 r = &rule->lhs; 169 for (i = 0; i < r->numElements; i++) 170 free_mapping_element(&r->element[i]); 171 if (r->element != NULL) 172 free(r->element); 173 174 r = &rule->rhs; 175 for (i = 0; i < r->numElements; i++) 176 free_mapping_element(&r->element[i]); 177 if (r->element != NULL) 178 free(r->element); 179 180 free(rule); 181 } 182 } 183 184 /* 185 * FUNCTION: free_mapping_element 186 * 187 * Frees __nis_mapping_element_t 188 * 189 * INPUT: __nis_mapping_element_t 190 */ 191 192 void 193 free_mapping_element(__nis_mapping_element_t *e) 194 { 195 int i; 196 197 if (e == NULL) 198 return; 199 200 switch (e->type) { 201 case me_item: 202 free_mapping_item(&e->element.item); 203 break; 204 case me_print: 205 if (e->element.print.fmt != NULL) 206 free_mapping_format(e->element.print.fmt); 207 e->element.print.fmt = NULL; 208 for (i = 0; i < e->element.print.numSubElements; i++) 209 free_mapping_sub_element( 210 &e->element.print.subElement[i]); 211 e->element.print.numSubElements = 0; 212 if (e->element.print.subElement != NULL) 213 free(e->element.print.subElement); 214 e->element.print.subElement = NULL; 215 break; 216 case me_split: 217 free_mapping_item(&e->element.split.item); 218 break; 219 case me_match: 220 if (e->element.match.fmt != NULL) 221 free_mapping_format(e->element.match.fmt); 222 e->element.match.fmt = NULL; 223 for (i = 0; i < e->element.match.numItems; i++) 224 free_mapping_item(&e->element.match.item[i]); 225 e->element.match.numItems = 0; 226 if (e->element.match.item != NULL) 227 free(e->element.match.item); 228 e->element.match.item = NULL; 229 break; 230 case me_extract: 231 if (e->element.extract.fmt != NULL) 232 free_mapping_format(e->element.extract.fmt); 233 e->element.extract.fmt = NULL; 234 free_mapping_item(&e->element.extract.item); 235 break; 236 } 237 e = NULL; 238 } 239 240 /* 241 * FUNCTION: free_table_mapping 242 * 243 * Frees __nis_table_mapping_t 244 * 245 * INPUT: __nis_table_mapping_t 246 */ 247 248 /* 249 * free_table_mapping does not remove the table mapping from 250 * its hashed list 251 */ 252 253 void 254 free_table_mapping(__nis_table_mapping_t *mapping) 255 { 256 int i; 257 258 if (mapping == NULL) 259 return; 260 261 if (mapping->dbId != NULL) 262 free(mapping->dbId); 263 mapping->dbId = NULL; 264 265 if (mapping->objName != NULL) 266 free(mapping->objName); 267 mapping->objName = NULL; 268 269 for (i = 0; i < mapping->index.numIndexes; i++) { 270 free(mapping->index.name[i]); 271 free_mapping_format(mapping->index.value[i]); 272 } 273 274 if (mapping->index.name != NULL) 275 free(mapping->index.name); 276 mapping->index.name = NULL; 277 278 if (mapping->index.value != NULL) 279 free(mapping->index.value); 280 mapping->index.value = NULL; 281 282 mapping->index.numIndexes = 0; 283 284 if (mapping->column != NULL) { 285 for (i = 0; i < mapping->numColumns; i++) { 286 free(mapping->column[i]); 287 } 288 mapping->numColumns = 0; 289 free(mapping->column); 290 mapping->column = NULL; 291 } 292 293 if (mapping->commentChar != NULL) 294 mapping->commentChar = NULL; 295 296 if (mapping->objectDN != NULL) 297 free_object_dn(mapping->objectDN); 298 mapping->objectDN = NULL; 299 300 if (mapping->separatorStr != NULL) 301 mapping->separatorStr = NULL; 302 303 for (i = 0; i < mapping->numRulesFromLDAP; i++) { 304 if (mapping->ruleFromLDAP[i]) /* See Comment below */ 305 free_mapping_rule(mapping->ruleFromLDAP[i]); 306 } 307 mapping->numRulesFromLDAP = 0; 308 309 if (mapping->ruleFromLDAP != NULL) 310 free(mapping->ruleFromLDAP); 311 mapping->ruleFromLDAP = NULL; 312 313 for (i = 0; i < mapping->numRulesToLDAP; i++) { 314 if (mapping->ruleToLDAP[i]) 315 /* 316 * Normally mapping->ruleToLDAP[i] should 317 * always be non-null if 318 * mapping->numRulesToLDAP is > 0. 319 * However it is possible to have data 320 * corruption where numRulesToLDAP gets 321 * some integer value even though no real 322 * data is present in mapping->ruleToLDAP. 323 */ 324 free_mapping_rule(mapping->ruleToLDAP[i]); 325 } 326 mapping->numRulesToLDAP = 0; 327 328 if (mapping->ruleToLDAP != NULL) 329 free(mapping->ruleToLDAP); 330 mapping->ruleToLDAP = NULL; 331 332 if (mapping->e != NULL) { 333 /* Similar logic as in above comment applies. */ 334 for (i = 0; i <= mapping->numSplits; i++) { 335 free_mapping_element(&mapping->e[i]); 336 } 337 free(mapping->e); 338 } 339 mapping->e = NULL; 340 341 mapping->numSplits = 0; 342 343 free(mapping); 344 } 345 346 /* 347 * FUNCTION: free_config_info 348 * 349 * Frees __nis_config_info_t 350 * 351 * INPUT: __nis_config_info_t 352 */ 353 354 void 355 free_config_info(__nis_config_info_t *config_info) 356 { 357 if (config_info->config_dn != NULL) 358 free(config_info->config_dn); 359 config_info->config_dn = NULL; 360 361 if (config_info->default_servers != NULL) 362 free(config_info->default_servers); 363 config_info->default_servers = NULL; 364 365 if (config_info->proxy_dn != NULL) 366 free(config_info->proxy_dn); 367 config_info->proxy_dn = NULL; 368 369 if (config_info->proxy_passwd != NULL) 370 free(config_info->proxy_passwd); 371 config_info->proxy_passwd = NULL; 372 373 if (config_info->tls_cert_db != NULL) 374 free(config_info->tls_cert_db); 375 config_info->tls_cert_db = NULL; 376 } 377 378 /* 379 * FUNCTION: free_proxy_info 380 * 381 * Frees __nis_ldap_proxy_info 382 * 383 * INPUT: __nis_ldap_proxy_info 384 */ 385 386 void 387 free_proxy_info(__nis_ldap_proxy_info *proxy_info) 388 { 389 if (proxy_info->tls_cert_db != NULL) 390 free(proxy_info->tls_cert_db); 391 proxy_info->tls_cert_db = NULL; 392 393 if (proxy_info->default_servers != NULL) 394 free(proxy_info->default_servers); 395 proxy_info->default_servers = NULL; 396 397 if (proxy_info->default_search_base != NULL) 398 free(proxy_info->default_search_base); 399 proxy_info->default_search_base = NULL; 400 401 if (proxy_info->proxy_dn != NULL) 402 free(proxy_info->proxy_dn); 403 proxy_info->proxy_dn = NULL; 404 405 if (proxy_info->proxy_passwd != NULL) 406 free(proxy_info->proxy_passwd); 407 proxy_info->proxy_passwd = NULL; 408 409 if (proxy_info->default_nis_domain != NULL) 410 free(proxy_info->default_nis_domain); 411 proxy_info->default_nis_domain = NULL; 412 } 413 414 /* 415 * FUNCTION: free_object_dn 416 * 417 * Frees __nis_object_dn_t 418 * 419 * INPUT: __nis_object_dn_t 420 */ 421 422 void 423 free_object_dn(__nis_object_dn_t *obj_dn) 424 { 425 __nis_object_dn_t *t; 426 int i; 427 428 while (obj_dn != NULL) { 429 if (obj_dn->read.base != NULL) 430 free(obj_dn->read.base); 431 obj_dn->read.base = NULL; 432 if (obj_dn->read.attrs != NULL) 433 free(obj_dn->read.attrs); 434 obj_dn->read.attrs = NULL; 435 if (obj_dn->write.base != NULL) 436 free(obj_dn->write.base); 437 obj_dn->write.base = NULL; 438 if (obj_dn->write.attrs != NULL) 439 free(obj_dn->write.attrs); 440 obj_dn->write.attrs = NULL; 441 if (obj_dn->dbIdName != NULL) 442 free(obj_dn->dbIdName); 443 obj_dn->dbIdName = NULL; 444 for (i = 0; i < obj_dn->numDbIds; i++) 445 free_mapping_rule(obj_dn->dbId[i]); 446 obj_dn->numDbIds = 0; 447 448 if (obj_dn->dbId != NULL) 449 free(obj_dn->dbId); 450 obj_dn->dbId = NULL; 451 452 t = obj_dn; 453 obj_dn = obj_dn->next; 454 free(t); 455 } 456 } 457 458 /* 459 * FUNCTION: free_index 460 * 461 * Frees __nis_index_t 462 * 463 * INPUT: __nis_index_t 464 */ 465 466 void 467 free_index(__nis_index_t *index) 468 { 469 int i; 470 for (i = 0; i < index->numIndexes; i++) { 471 free(index->name[i]); 472 free_mapping_format(index->value[i]); 473 } 474 index->numIndexes = 0; 475 if (index->name != NULL) 476 free(index->name); 477 index->name = NULL; 478 if (index->value != NULL) 479 free(index->value); 480 index->value = NULL; 481 } 482 483 /* 484 * FUNCTION: free_mapping_item 485 * 486 * Frees __nis_mapping_item_t 487 * 488 * INPUT: __nis_mapping_item_t 489 */ 490 491 void 492 free_mapping_item(__nis_mapping_item_t *item) 493 { 494 if (item == NULL) 495 return; 496 497 if (item->name != NULL) 498 free(item->name); 499 item->name = NULL; 500 if (item->type == mit_nisplus) { 501 free_index(&item->searchSpec.obj.index); 502 if (item->searchSpec.obj.name != NULL) 503 free(item->searchSpec.obj.name); 504 item->searchSpec.obj.name = NULL; 505 } else if (item->type == mit_ldap) { 506 if (item->searchSpec.triple.base != NULL) 507 free(item->searchSpec.triple.base); 508 item->searchSpec.triple.base = NULL; 509 if (item->searchSpec.triple.attrs != NULL) 510 free(item->searchSpec.triple.attrs); 511 item->searchSpec.triple.attrs = NULL; 512 if (item->searchSpec.triple.element != NULL) { 513 free_mapping_element( 514 item->searchSpec.triple.element); 515 free(item->searchSpec.triple.element); 516 } 517 item->searchSpec.triple.element = NULL; 518 } 519 if (item->exItem != NULL) { 520 free_mapping_item(item->exItem); 521 free(item->exItem); 522 item->exItem = 0; 523 } 524 } 525 526 /* 527 * FUNCTION: free_mapping_format 528 * 529 * Frees __nis_mapping_format_t 530 * 531 * INPUT: __nis_mapping_format_t 532 */ 533 534 void 535 free_mapping_format(__nis_mapping_format_t *fmt) 536 { 537 __nis_mapping_format_t *f = fmt; 538 539 while (fmt->type != mmt_end) { 540 switch (fmt->type) { 541 case mmt_item: 542 break; 543 case mmt_string: 544 if (fmt->match.string != NULL) 545 free(fmt->match.string); 546 fmt->match.string = NULL; 547 break; 548 case mmt_single: 549 if (fmt->match.single.lo != NULL) 550 free(fmt->match.single.lo); 551 fmt->match.single.lo = NULL; 552 if (fmt->match.single.hi != NULL) 553 free(fmt->match.single.hi); 554 fmt->match.single.hi = NULL; 555 break; 556 case mmt_limit: 557 break; 558 case mmt_any: 559 break; 560 case mmt_berstring: 561 case mmt_berstring_null: 562 if (fmt->match.berString != NULL) 563 free(fmt->match.berString); 564 fmt->match.berString = NULL; 565 break; 566 case mmt_begin: 567 break; 568 case mmt_end: 569 break; 570 } 571 fmt++; 572 } 573 free(f); 574 } 575 576 /* 577 * FUNCTION: free_mapping_sub_element 578 * 579 * Frees __nis_mapping_sub_element_t 580 * 581 * INPUT: __nis_mapping_sub_element_t 582 */ 583 584 void 585 free_mapping_sub_element(__nis_mapping_sub_element_t *sub) 586 { 587 int i; 588 589 switch (sub->type) { 590 case me_item: 591 free_mapping_item(&sub->element.item); 592 break; 593 case me_print: 594 if (sub->element.print.fmt != NULL) 595 free_mapping_format(sub->element.print.fmt); 596 sub->element.print.fmt = NULL; 597 for (i = 0; i < sub->element.print.numItems; i++) 598 free_mapping_item(&sub->element.print.item[i]); 599 sub->element.print.numItems = 0; 600 if (sub->element.print.item != NULL) 601 free(sub->element.print.item); 602 sub->element.print.item = NULL; 603 break; 604 case me_split: 605 free_mapping_item(&sub->element.split.item); 606 break; 607 case me_extract: 608 if (sub->element.extract.fmt != NULL) 609 free_mapping_format(sub->element.extract.fmt); 610 sub->element.extract.fmt = NULL; 611 free_mapping_item(&sub->element.extract.item); 612 break; 613 } 614 } 615 616 /* 617 * FUNCTION: read_line 618 * 619 * Gets next line in buffer - using '\' at end of line 620 * to indicate continuation. Lines beginning with # are 621 * ignored. start_line_num and start_line_num are 622 * maintained to track the line number currently being 623 * parsed. 624 * 625 * RETURN VALUE: The number of characters read. 0 for 626 * eof, -1 for error 627 * 628 * INPUT: file descriptor, buffer, and buffer size 629 */ 630 631 int 632 read_line(int fd, char *buffer, int buflen) 633 { 634 int linelen; 635 int rc; 636 char c; 637 bool_t skip_line = FALSE; 638 bool_t begin_line = TRUE; 639 static bool_t prev_cr = FALSE; 640 641 start_line_num = cur_line_num; 642 (void) memset(buffer, 0, buflen); 643 for (; p_error == no_parse_error; ) { 644 linelen = 0; 645 while (linelen < buflen) { 646 rc = read(fd, &c, 1); 647 if (1 == rc) { 648 if (c == '\n' || c == '\r') { 649 if (c == '\n') { 650 if (prev_cr) { 651 prev_cr = FALSE; 652 continue; 653 } else { 654 if (linelen == 0) 655 start_line_num = 656 cur_line_num; 657 else { 658 if ( 659 is_string_ok( 660 buffer, 661 linelen)) { 662 (void) memset( 663 buffer, 0, 664 linelen); 665 linelen = 0; 666 cur_line_num++; 667 begin_line = 668 TRUE; 669 continue; 670 } 671 } 672 cur_line_num++; 673 } 674 prev_cr = FALSE; 675 } else { 676 prev_cr = TRUE; 677 if (linelen == 0) 678 start_line_num = 679 cur_line_num; 680 cur_line_num++; 681 } 682 if (skip_line) { 683 skip_line = FALSE; 684 if (linelen == 0) 685 start_line_num = 686 cur_line_num; 687 } else if (linelen > 0 && 688 buffer[linelen - 1] 689 == ESCAPE_CHAR) { 690 --linelen; 691 } else if (linelen > 0) { 692 buffer[linelen] = '\0'; 693 return (linelen); 694 } 695 begin_line = TRUE; 696 } else { 697 if (begin_line) 698 skip_line = c == POUND_SIGN; 699 begin_line = FALSE; 700 if (!skip_line) 701 buffer[linelen++] = c; 702 } 703 } else { 704 if (linelen > 0 && 705 buffer[linelen - 1] == ESCAPE_CHAR) { 706 /* continuation on last line */ 707 p_error = parse_bad_continuation_error; 708 return (-1); 709 } else { 710 buffer[linelen] = '\0'; 711 return (linelen); 712 } 713 } 714 } 715 p_error = parse_line_too_long; 716 } 717 return (-1); 718 } 719 720 /* 721 * FUNCTION: finish_parse 722 * 723 * Adds any elements not configured, fully qualifies 724 * names 725 * 726 * RETURN VALUE: 0 on success, -1 on failure 727 */ 728 729 int 730 finish_parse( 731 __nis_ldap_proxy_info *proxy_info, 732 __nis_table_mapping_t **table_mapping) 733 { 734 __nis_table_mapping_t *t; 735 __nis_table_mapping_t *t1; 736 __nis_table_mapping_t *t2; 737 __nis_table_mapping_t *t_del = NULL; 738 int i; 739 int j; 740 int k; 741 __nis_object_dn_t *objectDN; 742 __nis_mapping_rlhs_t *lhs; 743 __nis_mapping_element_t *e; 744 char *s; 745 int errnum; 746 747 /* set to default those values yet set */ 748 if (proxy_info->auth_method == 749 (auth_method_t)NO_VALUE_SET) { 750 p_error = parse_no_proxy_auth_error; 751 report_error(NULL, NULL); 752 return (-1); 753 } 754 755 if (proxy_info->default_servers == NULL) { 756 p_error = parse_no_ldap_server_error; 757 report_error(NULL, NULL); 758 return (-1); 759 } 760 761 if (proxy_info->tls_method == (tls_method_t)NO_VALUE_SET) 762 proxy_info->tls_method = no_tls; 763 else if (proxy_info->tls_method == ssl_tls && 764 (proxy_info->tls_cert_db == NULL || 765 *proxy_info->tls_cert_db == '\0')) { 766 p_error = parse_no_cert_db; 767 report_error(NULL, NULL); 768 return (-1); 769 } 770 771 if (proxy_info->default_nis_domain == NULL) 772 proxy_info->default_nis_domain = 773 s_strdup(__nis_rpc_domain()); 774 else if (*proxy_info->default_nis_domain == '\0') { 775 free(proxy_info->default_nis_domain); 776 proxy_info->default_nis_domain = 777 s_strdup(__nis_rpc_domain()); 778 } 779 if (proxy_info->default_nis_domain != NULL) 780 append_dot(&proxy_info->default_nis_domain); 781 782 if (proxy_info->tls_method == ssl_tls) { 783 if ((errnum = ldapssl_client_init( 784 proxy_info->tls_cert_db, NULL)) < 0) { 785 p_error = parse_ldapssl_client_init_error; 786 report_error(ldapssl_err2string(errnum), NULL); 787 return (-1); 788 } 789 } 790 791 if (proxy_info->default_search_base == NULL) 792 proxy_info->default_search_base = 793 get_default_ldap_base(proxy_info->default_nis_domain); 794 795 /* convert a relative dn to a fullly qualified dn */ 796 (void) make_full_dn(&proxy_info->proxy_dn, 797 proxy_info->default_search_base); 798 799 if (p_error != no_parse_error) { 800 report_error(NULL, NULL); 801 return (-1); 802 } 803 804 /* 805 * Create a list of potential delete mappings 806 * those have NULL objectDNs, but badly also rules 807 * that are missing object dn's will be included. 808 * We will use the ttl field to determine if the 809 * delete rule is actually used 810 */ 811 t2 = NULL; 812 for (t = *table_mapping; t != NULL; t = t1) { 813 t1 = t->next; 814 if (t->objectDN == NULL) { 815 if (t2 == NULL) 816 *table_mapping = t1; 817 else 818 t2->next = t1; 819 t->next = t_del; 820 t_del = t; 821 t->ttl = 0; 822 } else 823 t2 = t; 824 } 825 826 for (t = *table_mapping; t != NULL; t = t->next) { 827 objectDN = t->objectDN; 828 while (objectDN != NULL) { 829 if (objectDN->dbIdName != NULL) { 830 s = objectDN->dbIdName; 831 t1 = find_table_mapping(s, strlen(s), t_del); 832 if (t1 == NULL) { 833 p_error = parse_no_db_del_mapping_rule; 834 report_error2(objectDN->dbIdName, t->dbId); 835 return (-1); 836 } else if (t1->objName != NULL || 837 t1->numRulesToLDAP == 0 || 838 t1->numRulesFromLDAP != 0) { 839 p_error = parse_invalid_db_del_mapping_rule; 840 report_error(t1->dbId, NULL); 841 return (-1); 842 } 843 objectDN->dbId = 844 dup_mapping_rules(t1->ruleToLDAP, 845 t1->numRulesToLDAP); 846 if (objectDN->dbId == NULL) { 847 break; 848 } 849 objectDN->numDbIds = t1->numRulesToLDAP; 850 t1->ttl++; 851 } 852 objectDN = objectDN->next; 853 } 854 } 855 856 for (t = t_del; t != NULL; t = t1) { 857 t1 = t->next; 858 if (t->ttl == 0) { 859 p_error = parse_no_object_dn; 860 report_error(t->dbId, NULL); 861 } 862 free_table_mapping(t); 863 } 864 865 if (p_error != no_parse_error) 866 return (-1); 867 868 /* set to default those table mapping values yet set */ 869 for (t = *table_mapping; t != NULL; t = t->next) { 870 if (t->objName == 0) { 871 p_error = parse_no_object_dn; 872 report_error(t->dbId, NULL); 873 return (-1); 874 } 875 if (!yp2ldap) { 876 if (!add_domain(&t->objName, 877 proxy_info->default_nis_domain)) { 878 report_error(NULL, NULL); 879 return (-1); 880 } 881 } 882 if (t->initTtlHi == (time_t)NO_VALUE_SET) 883 t->initTtlHi = DEFAULT_TTL_HIGH; 884 if (t->initTtlLo == (time_t)NO_VALUE_SET) 885 t->initTtlLo = DEFAULT_TTL_LOW; 886 if (t->ttl == (time_t)NO_VALUE_SET) 887 t->ttl = DEFAULT_TTL; 888 objectDN = t->objectDN; 889 890 /* fixup relative dn's */ 891 while (objectDN != NULL) { 892 if (!yp2ldap) { 893 if (!make_full_dn(&objectDN->read.base, 894 proxy_info->default_search_base)) 895 break; 896 } 897 if (objectDN->write.scope != LDAP_SCOPE_UNKNOWN) { 898 if (objectDN->write.base != NULL && 899 !make_full_dn(&objectDN->write.base, 900 proxy_info->default_search_base)) 901 break; 902 if (objectDN->write.base == NULL) { 903 objectDN->write.base = 904 s_strdup(objectDN->read.base); 905 if (objectDN->write.base == NULL) 906 break; 907 } 908 } 909 objectDN = objectDN->next; 910 } 911 912 if (p_error != no_parse_error) { 913 report_error(NULL, NULL); 914 return (-1); 915 } 916 917 /* Check for ruleToLDAP with no rhs */ 918 for (i = 0; i < t->numRulesToLDAP; i++) { 919 if (t->ruleToLDAP[i]->rhs.numElements == 0) { 920 p_error = parse_unexpected_data_end_rule; 921 report_error(t->dbId, NULL); 922 return (-1); 923 } 924 } 925 926 /* populate cols field */ 927 if (!yp2ldap) { 928 for (i = 0; i < t->numRulesFromLDAP; i++) { 929 lhs = &t->ruleFromLDAP[i]->lhs; 930 for (j = 0; j < lhs->numElements; j++) { 931 e = &lhs->element[j]; 932 switch (e->type) { 933 case me_item: 934 if (!add_column(t, 935 e->element.item.name)) { 936 report_error( 937 NULL, NULL); 938 return (-1); 939 } 940 break; 941 case me_match: 942 for (k = 0; 943 k < e->element.match.numItems; 944 k++) 945 if (!add_column(t, 946 e->element.match.item[k].name)) { 947 report_error( 948 NULL, NULL); 949 return (-1); 950 } 951 break; 952 } 953 } 954 } 955 } 956 } 957 return (0); 958 } 959 960 /* 961 * FUNCTION: set_default_values 962 * 963 * Sets unconfigured values to their default value 964 */ 965 966 void 967 set_default_values(__nis_ldap_proxy_info *proxy_info, 968 __nis_config_t *config_info, __nisdb_table_mapping_t *table_info) 969 { 970 if (proxy_info->bind_timeout.tv_sec == (time_t)NO_VALUE_SET) 971 proxy_info->bind_timeout.tv_sec = DEFAULT_BIND_TIMEOUT; 972 if (proxy_info->search_timeout.tv_sec == (time_t)NO_VALUE_SET) 973 proxy_info->search_timeout.tv_sec = 974 (yp2ldap)?DEFAULT_YP_SEARCH_TIMEOUT: 975 DEFAULT_SEARCH_TIMEOUT; 976 if (proxy_info->modify_timeout.tv_sec == (time_t)NO_VALUE_SET) 977 proxy_info->modify_timeout.tv_sec = DEFAULT_MODIFY_TIMEOUT; 978 if (proxy_info->add_timeout.tv_sec == (time_t)NO_VALUE_SET) 979 proxy_info->add_timeout.tv_sec = DEFAULT_ADD_TIMEOUT; 980 if (proxy_info->delete_timeout.tv_sec == (time_t)NO_VALUE_SET) 981 proxy_info->delete_timeout.tv_sec = DEFAULT_DELETE_TIMEOUT; 982 983 if (proxy_info->search_time_limit == (int)NO_VALUE_SET) 984 proxy_info->search_time_limit = DEFAULT_SEARCH_TIME_LIMIT; 985 if (proxy_info->search_size_limit == (int)NO_VALUE_SET) 986 proxy_info->search_size_limit = DEFAULT_SEARCH_SIZE_LIMIT; 987 988 if (proxy_info->follow_referral == (follow_referral_t)NO_VALUE_SET) 989 proxy_info->follow_referral = no_follow; 990 991 switch (config_info->initialUpdate) { 992 case (__nis_initial_update_t)NO_VALUE_SET: 993 case (__nis_initial_update_t)INITIAL_UPDATE_NO_ACTION: 994 case (__nis_initial_update_t)NO_INITIAL_UPDATE_NO_ACTION: 995 config_info->initialUpdate = ini_none; 996 break; 997 case (__nis_initial_update_t)FROM_NO_INITIAL_UPDATE: 998 config_info->initialUpdate = from_ldap; 999 break; 1000 case (__nis_initial_update_t)TO_NO_INITIAL_UPDATE: 1001 config_info->initialUpdate = to_ldap; 1002 break; 1003 } 1004 if (config_info->threadCreationError == 1005 (__nis_thread_creation_error_t)NO_VALUE_SET) 1006 config_info->threadCreationError = pass_error; 1007 if (config_info->threadCreationErrorTimeout.attempts == NO_VALUE_SET) 1008 config_info->threadCreationErrorTimeout.attempts = 1009 DEFAULT_THREAD_ERROR_ATTEMPTS; 1010 if (config_info->threadCreationErrorTimeout.timeout == 1011 (time_t)NO_VALUE_SET) 1012 config_info->threadCreationErrorTimeout.timeout = 1013 DEFAULT_THREAD_ERROR_TIME_OUT; 1014 if (config_info->dumpError == 1015 (__nis_dump_error_t)NO_VALUE_SET) 1016 config_info->dumpError = de_retry; 1017 if (config_info->dumpErrorTimeout.attempts == NO_VALUE_SET) 1018 config_info->dumpErrorTimeout.attempts = 1019 DEFAULT_DUMP_ERROR_ATTEMPTS; 1020 if (config_info->dumpErrorTimeout.timeout == (time_t)NO_VALUE_SET) 1021 config_info->dumpErrorTimeout.timeout = 1022 DEFAULT_DUMP_ERROR_TIME_OUT; 1023 if (config_info->resyncService == 1024 (__nis_resync_service_t)NO_VALUE_SET) 1025 config_info->resyncService = from_copy; 1026 if (config_info->updateBatching == 1027 (__nis_update_batching_t)NO_VALUE_SET) 1028 config_info->updateBatching = accumulate; 1029 if (config_info->updateBatchingTimeout.timeout == (time_t)NO_VALUE_SET) 1030 config_info->updateBatchingTimeout.timeout = 1031 DEFAULT_BATCHING_TIME_OUT; 1032 if (config_info->numberOfServiceThreads == (int)NO_VALUE_SET) 1033 config_info->numberOfServiceThreads = 1034 DEFAULT_NUMBER_OF_THREADS; 1035 if (config_info->emulate_yp == (int)NO_VALUE_SET) 1036 config_info->emulate_yp = 1037 DEFAULT_YP_EMULATION; 1038 if (config_info->maxRPCRecordSize == (int)NO_VALUE_SET) 1039 config_info->maxRPCRecordSize = RPC_MAXDATASIZE; 1040 1041 if (table_info->retrieveError == 1042 (__nis_retrieve_error_t)NO_VALUE_SET) 1043 table_info->retrieveError = use_cached; 1044 if (table_info->retrieveErrorRetry.attempts == NO_VALUE_SET) 1045 table_info->retrieveErrorRetry.attempts = 1046 DEFAULT_RETRIEVE_ERROR_ATTEMPTS; 1047 if (table_info->retrieveErrorRetry.timeout == (time_t)NO_VALUE_SET) 1048 table_info->retrieveErrorRetry.timeout = 1049 DEFAULT_RETRIEVE_ERROR_TIME_OUT; 1050 if (table_info->storeError == 1051 (__nis_store_error_t)NO_VALUE_SET) 1052 table_info->storeError = sto_retry; 1053 if (table_info->storeErrorRetry.attempts == NO_VALUE_SET) 1054 table_info->storeErrorRetry.attempts = 1055 DEFAULT_STORE_ERROR_ATTEMPTS; 1056 if (table_info->storeErrorRetry.timeout == (time_t)NO_VALUE_SET) 1057 table_info->storeErrorRetry.timeout = 1058 DEFAULT_STORE_ERROR_TIME_OUT; 1059 if (table_info->refreshError == 1060 (__nis_refresh_error_t)NO_VALUE_SET) 1061 table_info->refreshError = continue_using; 1062 if (table_info->refreshErrorRetry.attempts == NO_VALUE_SET) 1063 table_info->refreshErrorRetry.attempts = 1064 DEFAULT_REFRESH_ERROR_ATTEMPTS; 1065 if (table_info->refreshErrorRetry.timeout == (time_t)NO_VALUE_SET) 1066 table_info->refreshErrorRetry.timeout = 1067 DEFAULT_REFRESH_ERROR_TIME_OUT; 1068 if (table_info->matchFetch == 1069 (__nis_match_fetch_t)NO_VALUE_SET) 1070 table_info->matchFetch = no_match_only; 1071 } 1072 1073 __nis_table_mapping_t * 1074 find_table_mapping(const char *s, int len, __nis_table_mapping_t *table_mapping) 1075 { 1076 __nis_table_mapping_t *t; 1077 1078 for (t = table_mapping; t != NULL; t = t->next) 1079 if (strlen(t->dbId) == len && 1080 strncasecmp(t->dbId, s, len) == 0) 1081 break; 1082 return (t); 1083 } 1084 1085 void 1086 append_dot(char **str) 1087 { 1088 char *s = *str; 1089 int len = strlen(s); 1090 1091 if (len == 0 || s[len - 1] != PERIOD_CHAR) { 1092 s = s_realloc(s, len + 2); 1093 if (s != NULL) { 1094 s[len] = PERIOD_CHAR; 1095 s[len+1] = '\0'; 1096 *str = s; 1097 } 1098 } 1099 } 1100 1101 void 1102 append_comma(char **str) 1103 { 1104 1105 char *s = *str; 1106 int len = strlen(s); 1107 1108 if (len == 0 || s[len - 1] != COMMA_CHAR) { 1109 s = s_realloc(s, len + 2); 1110 if (s != NULL) { 1111 s[len] = COMMA_CHAR; 1112 s[len+1] = '\0'; 1113 *str = s; 1114 } 1115 } 1116 } 1117 1118 /* 1119 * FUNCTION: make_full_dn 1120 * 1121 * Appends the base dn if a relative ldap dn 1122 * (invoked only for LDAP write cycle) 1123 * 1124 * RETURN VALUE: FALSE if error 1125 * TRUE if __nis_index_t returned 1126 * 1127 * INPUT: the relative dn and ldap base 1128 */ 1129 1130 bool_t 1131 make_full_dn(char **dn, const char *base) 1132 { 1133 int len; 1134 int len1; 1135 1136 if (*dn == NULL) { 1137 *dn = s_strdup(base); 1138 } else { 1139 len = strlen(*dn); 1140 if (len > 0 && (*dn)[len-1] == COMMA_CHAR) { 1141 len1 = strlen(base) + 1; 1142 *dn = s_realloc(*dn, len + len1); 1143 if (*dn != NULL) 1144 (void) strcpy(*dn + len, base); 1145 } 1146 } 1147 return (*dn != NULL); 1148 } 1149 1150 /* 1151 * FUNCTION: make_fqdn 1152 * 1153 * Appends the base dn if a relative ldap dn 1154 * (invoked only for LDAP read cycle) 1155 * 1156 * RETURN VALUE: FALSE if error 1157 * TRUE if success 1158 * 1159 * INPUT: the relative dn and ldap base 1160 */ 1161 bool_t 1162 make_fqdn(__nis_object_dn_t *dn, const char *base) 1163 { 1164 int len; 1165 int len1; 1166 1167 if (dn == NULL) { 1168 return (FALSE); 1169 } else { 1170 while (dn != NULL && dn->read.base != NULL) { 1171 len = strlen(dn->read.base); 1172 if (len > 0 && (dn->read.base)[len-1] == COMMA_CHAR) { 1173 len1 = strlen(base) + 1; 1174 dn->read.base = 1175 s_realloc(dn->read.base, len + len1); 1176 if (dn->read.base != NULL) 1177 (void) strlcpy(dn->read.base + len, 1178 base, len1); 1179 else 1180 return (FALSE); 1181 } 1182 dn = dn->next; 1183 } 1184 } 1185 return (TRUE); 1186 } 1187 1188 /* 1189 * FUNCTION: get_default_ldap_base 1190 * 1191 * Gets the default LDAP search base from the 1192 * nis+ default domain 1193 * 1194 * RETURN VALUE: NULL if error 1195 * the default base 1196 * 1197 * INPUT: the nis domain 1198 */ 1199 1200 char * 1201 get_default_ldap_base(const char *domain) 1202 { 1203 1204 int len = strlen(domain); 1205 int i; 1206 int count = len + 4; 1207 char *base; 1208 1209 for (i = 0; i < len - 1; i++) 1210 if (domain[i] == PERIOD_CHAR) 1211 count += 4; 1212 if ((base = malloc(count)) == NULL) { 1213 p_error = parse_no_mem_error; 1214 } else { 1215 (void) strcpy(base, "dc="); 1216 count = 3; 1217 for (i = 0; i < len - 1; i++) { 1218 if (domain[i] == PERIOD_CHAR) { 1219 (void) strcpy(base + count, ",dc="); 1220 count += 4; 1221 } else { 1222 base[count++] = domain[i]; 1223 } 1224 } 1225 base[count] = '\0'; 1226 } 1227 return (base); 1228 } 1229 1230 /* 1231 * FUNCTION: add_domain 1232 * 1233 * Appends the base domain if a relative object name 1234 * 1235 * RETURN VALUE: FALSE if error 1236 * TRUE if OK 1237 * 1238 * INPUT: the relative object name and base domain 1239 * name 1240 */ 1241 1242 bool_t 1243 add_domain(char **objName, const char *domain) 1244 { 1245 int len; 1246 int len1; 1247 bool_t trailing_dot; 1248 char *obj_name; 1249 1250 if (domain == NULL || *objName == NULL) { 1251 p_error = parse_internal_error; 1252 return (FALSE); 1253 } 1254 len1 = strlen(domain); 1255 trailing_dot = (len1 > 0 && domain[len1 - 1] == PERIOD_CHAR) ? 1256 0 : 1; 1257 len = strlen(*objName); 1258 if (len == 0 || (*objName)[len - 1] != PERIOD_CHAR) { 1259 obj_name = s_realloc(*objName, 1260 len + len1 + 2 + trailing_dot); 1261 if (obj_name != NULL) { 1262 obj_name[len++] = PERIOD_CHAR; 1263 (void) strcpy(obj_name + len, domain); 1264 if (trailing_dot != 0) { 1265 obj_name[len + len1] = PERIOD_CHAR; 1266 obj_name[len + len1 + 1] = '\0'; 1267 } 1268 *objName = obj_name; 1269 } 1270 } 1271 1272 return (*objName != NULL); 1273 } 1274 1275 bool_t 1276 dup_index(__nis_index_t *in, __nis_index_t *out) 1277 { 1278 int i; 1279 int j; 1280 1281 out->name = (char **)s_calloc(in->numIndexes, sizeof (char *)); 1282 if (out->name == NULL) 1283 return (FALSE); 1284 out->value = (__nis_mapping_format_t **) 1285 s_calloc(in->numIndexes, sizeof (__nis_mapping_format_t *)); 1286 if (out->value == NULL) { 1287 free(out->name); 1288 out->name = NULL; 1289 return (FALSE); 1290 } 1291 1292 for (i = 0; i < in->numIndexes; i++) { 1293 out->name[i] = s_strdup(in->name[i]); 1294 if (out->name[i] == NULL) 1295 break; 1296 out->value[i] = dup_format_mapping(in->value[i]); 1297 if (out->value[i] == NULL) 1298 break; 1299 } 1300 if (i < in->numIndexes) { 1301 for (j = 0; j <= i; j++) { 1302 if (out->name[j] != NULL) 1303 free(out->name[j]); 1304 if (out->value[j] != NULL) 1305 free_mapping_format(out->value[j]); 1306 } 1307 free(out->name); 1308 out->name = NULL; 1309 free(out->value); 1310 out->value = NULL; 1311 } else { 1312 out->numIndexes = in->numIndexes; 1313 } 1314 return (i == in->numIndexes); 1315 } 1316 1317 bool_t 1318 dup_mapping_item(__nis_mapping_item_t *in, __nis_mapping_item_t *out) 1319 { 1320 bool_t ret; 1321 1322 if (in->type == mit_nisplus) { 1323 ret = dup_index(&in->searchSpec.obj.index, 1324 &out->searchSpec.obj.index); 1325 if (!ret) 1326 return (ret); 1327 if (in->searchSpec.obj.name != NULL) { 1328 out->searchSpec.obj.name = 1329 s_strdup(in->searchSpec.obj.name); 1330 if (out->searchSpec.obj.name == NULL) 1331 return (FALSE); 1332 } else 1333 out->searchSpec.obj.name = NULL; 1334 } else if (in->type == mit_ldap) { 1335 if (in->searchSpec.triple.base != NULL) { 1336 out->searchSpec.triple.base = 1337 s_strdup(in->searchSpec.triple.base); 1338 if (out->searchSpec.triple.base == NULL) 1339 return (FALSE); 1340 } else 1341 out->searchSpec.triple.base = NULL; 1342 out->searchSpec.triple.scope = 1343 in->searchSpec.triple.scope; 1344 if (in->searchSpec.triple.attrs != NULL) { 1345 out->searchSpec.triple.attrs = 1346 s_strdup(in->searchSpec.triple.attrs); 1347 if (out->searchSpec.triple.attrs == NULL) 1348 return (FALSE); 1349 } else 1350 out->searchSpec.triple.attrs = NULL; 1351 if (in->searchSpec.triple.element != NULL) { 1352 out->searchSpec.triple.element = 1353 (__nis_mapping_element_t *) 1354 s_calloc(1, sizeof (__nis_mapping_element_t)); 1355 if (out->searchSpec.triple.element != NULL) 1356 dup_mapping_element( 1357 in->searchSpec.triple.element, 1358 out->searchSpec.triple.element); 1359 if (out->searchSpec.triple.element == NULL) 1360 return (FALSE); 1361 } else 1362 out->searchSpec.triple.element = NULL; 1363 } 1364 1365 if (in->name != NULL) { 1366 out->name = s_strdup(in->name); 1367 if (out->name == NULL) 1368 return (FALSE); 1369 } else 1370 out->name = NULL; 1371 out->type = in->type; 1372 out->repeat = in->repeat; 1373 if (in->exItem) { 1374 out->exItem = (__nis_mapping_item_t *)s_malloc 1375 (sizeof (__nis_mapping_item_t)); 1376 if (out->exItem == NULL) 1377 return (FALSE); 1378 else { 1379 (void) memset 1380 (out->exItem, 0, sizeof (out->exItem[0])); 1381 if (!dup_mapping_item 1382 (in->exItem, out->exItem)) 1383 p_error = parse_internal_error; 1384 } 1385 } else 1386 out->exItem = NULL; 1387 1388 return (p_error == no_parse_error); 1389 } 1390 1391 __nis_mapping_format_t * 1392 dup_format_mapping(__nis_mapping_format_t *in) 1393 { 1394 int i; 1395 __nis_mapping_format_t *out; 1396 bool_t got_end; 1397 1398 i = 0; 1399 while (in[i].type != mmt_end) 1400 i++; 1401 out = (__nis_mapping_format_t *)s_calloc( 1402 i + 1, sizeof (__nis_mapping_format_t)); 1403 if (out != NULL) { 1404 got_end = FALSE; 1405 for (i = 0; !got_end; i++) { 1406 switch (in[i].type) { 1407 case mmt_item: 1408 break; 1409 case mmt_string: 1410 out[i].match.string = 1411 s_strdup(in[i].match.string); 1412 break; 1413 case mmt_single: 1414 out[i].match.single.numRange = 1415 in[i].match.single.numRange; 1416 out[i].match.single.lo = 1417 s_malloc(in[i].match.single.numRange); 1418 if (out[i].match.single.lo == NULL) 1419 break; 1420 out[i].match.single.hi = 1421 s_malloc(in[i].match.single.numRange); 1422 if (out[i].match.single.hi == NULL) 1423 break; 1424 memcpy(out[i].match.single.lo, 1425 in[i].match.single.lo, 1426 in[i].match.single.numRange); 1427 memcpy(out[i].match.single.hi, 1428 in[i].match.single.hi, 1429 in[i].match.single.numRange); 1430 break; 1431 case mmt_limit: 1432 out[i].match.limit = in[i].match.limit; 1433 break; 1434 case mmt_any: 1435 break; 1436 case mmt_berstring: 1437 out[i].match.berString = 1438 s_strdup(in[i].match.berString); 1439 break; 1440 case mmt_begin: 1441 break; 1442 case mmt_end: 1443 got_end = TRUE; 1444 break; 1445 default: 1446 p_error = parse_internal_error; 1447 } 1448 if (p_error != no_parse_error) 1449 break; 1450 out[i].type = in[i].type; 1451 } 1452 if (p_error != no_parse_error) { 1453 free_mapping_format(out); 1454 out = NULL; 1455 } 1456 } 1457 1458 return (out); 1459 } 1460 1461 bool_t 1462 dup_mapping_sub_element( 1463 __nis_mapping_sub_element_t *in, 1464 __nis_mapping_sub_element_t *out) 1465 { 1466 bool_t ret = FALSE; 1467 int i; 1468 1469 switch (in->type) { 1470 case me_item: 1471 ret = dup_mapping_item(&in->element.item, 1472 &out->element.item); 1473 break; 1474 case me_print: 1475 out->element.print.fmt = 1476 dup_format_mapping(in->element.print.fmt); 1477 if (out->element.print.fmt == NULL) 1478 break; 1479 out->element.print.numItems = 1480 in->element.print.numItems; 1481 out->element.print.item = (__nis_mapping_item_t *) 1482 s_calloc(in->element.print.numItems, 1483 sizeof (__nis_mapping_item_t)); 1484 if (out->element.print.item == NULL) 1485 break; 1486 for (i = 0; i < in->element.print.numItems; i++) 1487 if (!dup_mapping_item( 1488 &in->element.print.item[i], 1489 &out->element.print.item[i])) 1490 break; 1491 if (i < in->element.print.numItems) 1492 break; 1493 ret = TRUE; 1494 out->element.print.doElide = in->element.print.doElide; 1495 out->element.print.elide = in->element.print.elide; 1496 break; 1497 case me_split: 1498 ret = dup_mapping_item(&in->element.split.item, 1499 &out->element.split.item); 1500 out->element.split.delim = in->element.split.delim; 1501 break; 1502 case me_extract: 1503 out->element.extract.fmt = 1504 dup_format_mapping(in->element.extract.fmt); 1505 if (out->element.extract.fmt == NULL) 1506 break; 1507 ret = dup_mapping_item(&in->element.extract.item, 1508 &out->element.extract.item); 1509 break; 1510 default: 1511 p_error = parse_internal_error; 1512 } 1513 out->type = in->type; 1514 1515 return (ret); 1516 } 1517 1518 bool_t 1519 dup_mapping_element( 1520 __nis_mapping_element_t *in, 1521 __nis_mapping_element_t *out) 1522 { 1523 bool_t ret = FALSE; 1524 int i; 1525 1526 if (in == NULL) 1527 return (ret); 1528 1529 switch (in->type) { 1530 case me_item: 1531 ret = dup_mapping_item(&in->element.item, 1532 &out->element.item); 1533 break; 1534 case me_print: 1535 out->element.print.fmt = 1536 dup_format_mapping(in->element.print.fmt); 1537 if (out->element.print.fmt == NULL) 1538 break; 1539 out->element.print.numSubElements = 1540 in->element.print.numSubElements; 1541 out->element.print.subElement = 1542 (__nis_mapping_sub_element_t *) 1543 s_calloc(in->element.print.numSubElements, 1544 sizeof (__nis_mapping_sub_element_t)); 1545 if (out->element.print.subElement == NULL) 1546 break; 1547 for (i = 0; i < in->element.print.numSubElements; i++) 1548 if (!dup_mapping_sub_element( 1549 &in->element.print.subElement[i], 1550 &out->element.print.subElement[i])) 1551 break; 1552 if (i < in->element.print.numSubElements) 1553 break; 1554 ret = TRUE; 1555 out->element.print.doElide = in->element.print.doElide; 1556 out->element.print.elide = in->element.print.elide; 1557 break; 1558 case me_split: 1559 ret = dup_mapping_item(&in->element.split.item, 1560 &out->element.split.item); 1561 out->element.split.delim = in->element.split.delim; 1562 break; 1563 case me_match: 1564 out->element.match.fmt = 1565 dup_format_mapping(in->element.match.fmt); 1566 if (out->element.match.fmt == NULL) 1567 break; 1568 out->element.match.numItems = 1569 in->element.match.numItems; 1570 out->element.match.item = (__nis_mapping_item_t *) 1571 s_calloc(in->element.match.numItems, 1572 sizeof (__nis_mapping_item_t)); 1573 if (out->element.match.item == NULL) 1574 break; 1575 for (i = 0; i < in->element.match.numItems; i++) 1576 if (!dup_mapping_item( 1577 &in->element.match.item[i], 1578 &out->element.match.item[i])) 1579 break; 1580 if (i < in->element.match.numItems) 1581 break; 1582 ret = TRUE; 1583 break; 1584 case me_extract: 1585 out->element.extract.fmt = 1586 dup_format_mapping(in->element.extract.fmt); 1587 if (out->element.extract.fmt == NULL) 1588 break; 1589 ret = dup_mapping_item(&in->element.extract.item, 1590 &out->element.extract.item); 1591 break; 1592 default: 1593 p_error = parse_internal_error; 1594 } 1595 out->type = in->type; 1596 1597 return (ret); 1598 } 1599 1600 __nis_mapping_rule_t * 1601 dup_mapping_rule(__nis_mapping_rule_t *in) 1602 { 1603 int i; 1604 __nis_mapping_rlhs_t *r_in; 1605 __nis_mapping_rlhs_t *r_out; 1606 __nis_mapping_rule_t *out; 1607 1608 out = (__nis_mapping_rule_t *) 1609 s_calloc(1, sizeof (__nis_mapping_rule_t)); 1610 if (out != NULL) { 1611 r_in = &in->lhs; 1612 r_out = &out->lhs; 1613 r_out->numElements = r_in->numElements; 1614 r_out->element = (__nis_mapping_element_t *)s_calloc 1615 (r_in->numElements, sizeof (__nis_mapping_element_t)); 1616 if (r_out->element == NULL) { 1617 free_mapping_rule(out); 1618 return (NULL); 1619 } 1620 for (i = 0; i < r_in->numElements; i++) { 1621 if (!dup_mapping_element(&r_in->element[i], 1622 &r_out->element[i])) 1623 break; 1624 } 1625 if (i < r_in->numElements) { 1626 free_mapping_rule(out); 1627 return (NULL); 1628 } 1629 1630 r_in = &in->rhs; 1631 r_out = &out->rhs; 1632 r_out->numElements = r_in->numElements; 1633 r_out->element = (__nis_mapping_element_t *)s_calloc 1634 (r_in->numElements, sizeof (__nis_mapping_element_t)); 1635 if (r_out->element == NULL) { 1636 free_mapping_rule(out); 1637 return (NULL); 1638 } 1639 for (i = 0; i < r_in->numElements; i++) { 1640 if (!dup_mapping_element(&r_in->element[i], 1641 &r_out->element[i])) 1642 break; 1643 } 1644 if (i < r_in->numElements) { 1645 free_mapping_rule(out); 1646 return (NULL); 1647 } 1648 } 1649 return (out); 1650 } 1651 1652 __nis_mapping_rule_t ** 1653 dup_mapping_rules(__nis_mapping_rule_t **rules, int n_rules) 1654 { 1655 int i, j; 1656 __nis_mapping_rule_t **r; 1657 1658 r = (__nis_mapping_rule_t **)s_calloc(n_rules, 1659 sizeof (__nis_mapping_rule_t *)); 1660 if (r != NULL) { 1661 for (i = 0; i < n_rules; i++) { 1662 r[i] = dup_mapping_rule(rules[i]); 1663 if (r[i] == NULL) { 1664 for (j = 0; j < i; j++) 1665 free_mapping_rule(r[j]); 1666 free(r); 1667 r = NULL; 1668 break; 1669 } 1670 } 1671 } 1672 return (r); 1673 } 1674 1675 /* 1676 * FUNCTION: add_column 1677 * 1678 * Adds a column name to the column list in __nis_table_mapping_t 1679 * 1680 * RETURN VALUE: FALSE if error 1681 * TRUE if __nis_index_t returned 1682 * 1683 * INPUT: the __nis_table_mapping_t and column name 1684 */ 1685 1686 bool_t 1687 add_column(__nis_table_mapping_t *t, const char *col_name) 1688 { 1689 int i; 1690 char **cols = NULL; 1691 1692 if (!yp2ldap) { 1693 for (i = 0; i < t->numColumns; i++) { 1694 if (strcasecmp(col_name, t->column[i]) == 0) 1695 return (TRUE); 1696 } 1697 } 1698 cols = (char **)s_realloc(t->column, (t->numColumns + 1) * 1699 sizeof (char *)); 1700 if (cols == NULL) 1701 return (FALSE); 1702 t->column = cols; 1703 cols[t->numColumns] = s_strdup(col_name); 1704 if (cols[t->numColumns] == NULL) 1705 return (FALSE); 1706 t->numColumns++; 1707 return (TRUE); 1708 } 1709 1710 /* 1711 * FUNCTION: add_element 1712 * 1713 * Adds a __nis_mapping_element_t to __nis_mapping_rlhs_t 1714 * 1715 * RETURN VALUE: FALSE if error 1716 * TRUE if __nis_index_t returned 1717 * 1718 * INPUT: the __nis_mapping_element_t and 1719 * __nis_mapping_rlhs_t 1720 */ 1721 1722 bool_t 1723 add_element( 1724 __nis_mapping_element_t *e, 1725 __nis_mapping_rlhs_t *m) 1726 { 1727 __nis_mapping_element_t *e1; 1728 int i; 1729 int n = m->numElements; 1730 1731 e1 = (__nis_mapping_element_t *)s_realloc(m->element, 1732 (n + 1) * sizeof (__nis_mapping_element_t)); 1733 if (e1 == NULL) { 1734 e1 = m->element; 1735 for (i = 0; i < n; i++) 1736 free_mapping_element(e1++); 1737 if (m->element != NULL) 1738 free(m->element); 1739 m->element = NULL; 1740 m->numElements = 0; 1741 } else { 1742 e1[m->numElements++] = *e; 1743 free(e); 1744 m->element = (__nis_mapping_element_t *)e1; 1745 } 1746 return (e1 != NULL); 1747 } 1748 1749 /* 1750 * FUNCTION: get_next_object_dn_token 1751 * 1752 * Get the next token in parsing object_dn 1753 * 1754 * RETURN VALUE: NULL if error 1755 * position of beginning next token after 1756 * token 1757 * 1758 * INPUT: the attribute value 1759 */ 1760 1761 const char * 1762 get_next_object_dn_token( 1763 const char **begin_ret, 1764 const char **end_ret, 1765 object_dn_token *token) 1766 { 1767 object_dn_token t = dn_no_token; 1768 const char *s = *begin_ret; 1769 const char *begin; 1770 const char *end = *end_ret; 1771 const char *s1; 1772 bool_t in_quotes; 1773 1774 while (s < end && is_whitespace(*s)) 1775 s++; 1776 if (s >= end) { 1777 /* EMPTY */ 1778 } else if (*s == SEMI_COLON_CHAR) { 1779 t = dn_semi_token; 1780 s++; 1781 } else if (*s == QUESTION_MARK) { 1782 t = dn_ques_token; 1783 s++; 1784 } else if (*s == COLON_CHAR) { 1785 t = dn_colon_token; 1786 s++; 1787 } else if (*s == OPEN_PAREN_CHAR) { 1788 begin = s; 1789 s = get_ldap_filter(&begin, &end); 1790 if (s != NULL) { 1791 t = dn_text_token; 1792 *begin_ret = begin; 1793 *end_ret = end; 1794 } 1795 } else { 1796 begin = s; 1797 in_quotes = FALSE; 1798 while (s < end) { 1799 if (*s == ESCAPE_CHAR) { 1800 if (s + 2 > end) { 1801 p_error = parse_unmatched_escape; 1802 s = NULL; 1803 break; 1804 } 1805 s++; 1806 } else if (*s == DOUBLE_QUOTE_CHAR) { 1807 in_quotes = ! in_quotes; 1808 } else if (in_quotes) 1809 ; 1810 else if (*s == SEMI_COLON_CHAR || 1811 *s == QUESTION_MARK || 1812 *s == COLON_CHAR) 1813 break; 1814 s++; 1815 } 1816 if (s != NULL) { 1817 s1 = s - 1; 1818 while (is_whitespace(*s1)) 1819 s1--; 1820 s1++; 1821 if (same_string("base", begin, s1 - begin)) 1822 t = dn_base_token; 1823 else if (same_string("one", begin, s1 - begin)) 1824 t = dn_one_token; 1825 else if (same_string("sub", begin, s1 - begin)) 1826 t = dn_sub_token; 1827 else 1828 t = dn_text_token; 1829 *begin_ret = begin; 1830 *end_ret = s1; 1831 } 1832 } 1833 *token = t; 1834 return (s); 1835 } 1836 1837 /* 1838 * FUNCTION: get_next_token 1839 * 1840 * Get the next token in parsing mapping attribute 1841 * 1842 * RETURN VALUE: NULL if error 1843 * position of beginning next token after 1844 * token 1845 * 1846 * INPUT: the attribute value 1847 */ 1848 1849 const char * 1850 get_next_token(const char **begin_token, const char **end_token, token_type *t) 1851 { 1852 const char *s = *begin_token; 1853 const char *end_s = *end_token; 1854 const char *s_begin; 1855 1856 while (s < end_s && is_whitespace(*s)) 1857 s++; 1858 if (s == end_s) { 1859 *t = no_token; 1860 return (s); 1861 } 1862 1863 s_begin = s; 1864 1865 if (*s == OPEN_PAREN_CHAR) { 1866 *begin_token = s; 1867 s++; 1868 *end_token = s; 1869 while (s < end_s && is_whitespace(*s)) 1870 s++; 1871 *t = open_paren_token; 1872 } else if (*s == DOUBLE_QUOTE_CHAR) { 1873 s++; 1874 while (s < end_s) { 1875 if (*s == ESCAPE_CHAR) 1876 s += 2; 1877 else if (*s == DOUBLE_QUOTE_CHAR) 1878 break; 1879 else 1880 s++; 1881 } 1882 if (s >= end_s) { 1883 p_error = parse_unmatched_escape; 1884 return (NULL); 1885 } 1886 1887 *t = quoted_string_token; 1888 *begin_token = s_begin + 1; 1889 *end_token = s++; 1890 } else if (*s == EQUAL_CHAR || *s == COMMA_CHAR || 1891 *s == CLOSE_PAREN_CHAR || *s == COLON_CHAR) { 1892 if (*s == EQUAL_CHAR) 1893 *t = equal_token; 1894 else if (*s == COMMA_CHAR) 1895 *t = comma_token; 1896 else if (*s == CLOSE_PAREN_CHAR) 1897 *t = close_paren_token; 1898 else 1899 *t = colon_token; 1900 *begin_token = s; 1901 *end_token = ++s; 1902 } else { 1903 s_begin = s; 1904 while (s < end_s && !is_whitespace(*s)) { 1905 if (*s == ESCAPE_CHAR) 1906 s += 2; 1907 else if (*s == EQUAL_CHAR || *s == CLOSE_PAREN_CHAR || 1908 *s == OPEN_PAREN_CHAR || *s == COMMA_CHAR || 1909 *s == COLON_CHAR || *s == OPEN_BRACKET || 1910 *s == CLOSE_BRACKET) 1911 break; 1912 else 1913 s++; 1914 } 1915 if (s > end_s) { 1916 p_error = parse_unmatched_escape; 1917 return (NULL); 1918 } 1919 *t = string_token; 1920 *end_token = s; 1921 *begin_token = s_begin; 1922 } 1923 if (s) { 1924 while (s < end_s && is_whitespace(*s)) 1925 s++; 1926 } 1927 return (s); 1928 } 1929 1930 /* 1931 * FUNCTION: skip_token 1932 * 1933 * Skip over the specified token - An error is set if 1934 * next token does not match expected token 1935 * 1936 * RETURN VALUE: NULL if error 1937 * position of beginning next token after 1938 * token 1939 * 1940 * INPUT: the attribute value 1941 */ 1942 1943 const char * 1944 skip_token(const char *s, const char *end_s, token_type t) 1945 { 1946 bool_t match; 1947 char c = 0; 1948 1949 if (s == NULL) 1950 return (s); 1951 while (s < end_s && is_whitespace(*s)) 1952 s++; 1953 c = (s == end_s) ? 0 : *s; 1954 switch (t) { 1955 case equal_token: 1956 match = c == EQUAL_CHAR; 1957 if (!match) 1958 p_error = parse_equal_expected_error; 1959 break; 1960 case comma_token: 1961 match = c == COMMA_CHAR; 1962 if (!match) 1963 p_error = parse_comma_expected_error; 1964 break; 1965 case close_paren_token: 1966 match = c == CLOSE_PAREN_CHAR; 1967 if (!match) 1968 p_error = parse_close_paren_expected_error; 1969 break; 1970 default: 1971 match = FALSE; 1972 break; 1973 } 1974 if (match) { 1975 s++; 1976 while (s < end_s && is_whitespace(*s)) 1977 s++; 1978 } else { 1979 s = NULL; 1980 } 1981 return (s); 1982 } 1983 1984 /* 1985 * FUNCTION: get_next_extract_format_item 1986 * 1987 * Get the next format token from the string. Note that 1988 * get_next_extract_format_item may change the input string. 1989 * 1990 * RETURN VALUE: NULL if error 1991 * position of beginning next token after 1992 * token 1993 * 1994 * INPUT: the format string 1995 */ 1996 1997 const char * 1998 get_next_extract_format_item( 1999 const char *begin_fmt, 2000 const char *end_fmt, 2001 __nis_mapping_format_t *fmt) 2002 { 2003 const char *s = begin_fmt; 2004 const char *s_end = end_fmt; 2005 bool_t escape; 2006 bool_t in_range; 2007 bool_t got_char; 2008 bool_t done; 2009 int numRange; 2010 char *lo = NULL; 2011 char *hi = NULL; 2012 bool_t skip_ber; 2013 2014 for (; p_error == no_parse_error; ) { 2015 if (s >= s_end) 2016 break; 2017 2018 if (*s == PERCENT_SIGN) { 2019 s++; 2020 /* 2021 * If the format is %s, it is interpreted 2022 * as a string. 2023 */ 2024 if (s >= s_end) { 2025 p_error = parse_unsupported_format; 2026 break; 2027 } 2028 skip_ber = FALSE; 2029 switch (*s) { 2030 case 's': 2031 fmt->type = mmt_item; 2032 break; 2033 case 'n': /* null */ 2034 case 'x': /* skip the next element */ 2035 skip_ber = TRUE; 2036 /* FALLTHRU */ 2037 case 'b': /* boolean */ 2038 case 'e': /* enumerated */ 2039 case 'i': /* int */ 2040 case 'o': /* octet string */ 2041 case 'B': /* bit string */ 2042 fmt->match.berString = s_strndup(s, 1); 2043 fmt->type = skip_ber ? 2044 mmt_berstring_null : 2045 mmt_berstring; 2046 break; 2047 case 'a': /* octet string */ 2048 if (yp2ldap) { 2049 fmt->match.berString = 2050 s_strndup(s, 1); 2051 fmt->type = skip_ber ? 2052 mmt_berstring_null : 2053 mmt_berstring; 2054 break; 2055 } /* else FALLTHRU */ 2056 case '{': /* begin sequence */ 2057 case '[': /* begin set */ 2058 case '}': /* end sequence */ 2059 case ']': /* end set */ 2060 case 'l': /* length of next item */ 2061 case 'O': /* octet string */ 2062 case 't': /* tag of next item */ 2063 case 'T': /* skip tag of next item */ 2064 case 'v': /* seq of strings */ 2065 case 'V': /* seq of strings + lengths */ 2066 default: 2067 p_error = parse_bad_ber_format; 2068 break; 2069 } 2070 s++; 2071 } else if (*s == ASTERIX_CHAR) { 2072 fmt->type = mmt_any; 2073 s++; 2074 while (s < s_end && *s == ASTERIX_CHAR) 2075 s++; 2076 2077 } else if (*s == OPEN_BRACKET) { 2078 escape = FALSE; 2079 in_range = FALSE; 2080 got_char = FALSE; 2081 numRange = 0; 2082 done = FALSE; 2083 s++; 2084 for (; s < s_end; s++) { 2085 if (escape) { 2086 escape = FALSE; 2087 } else if (*s == DASH_CHAR) { 2088 if (in_range || !got_char) { 2089 p_error = parse_unexpected_dash; 2090 break; 2091 } 2092 in_range = TRUE; 2093 got_char = FALSE; 2094 continue; 2095 } else if (*s == CLOSE_BRACKET) { 2096 if (in_range) { 2097 p_error = parse_unexpected_dash; 2098 } 2099 done = TRUE; 2100 break; 2101 } else if (*s == ESCAPE_CHAR) { 2102 escape = TRUE; 2103 continue; 2104 } 2105 if (in_range) { 2106 hi[numRange - 1] = *s; 2107 in_range = FALSE; 2108 } else { 2109 lo = s_realloc(lo, numRange + 1); 2110 hi = s_realloc(hi, numRange + 1); 2111 if (lo == NULL || hi == NULL) 2112 break; 2113 lo[numRange] = *s; 2114 hi[numRange] = *s; 2115 numRange++; 2116 got_char = TRUE; 2117 } 2118 } 2119 if (p_error != no_parse_error) { 2120 break; 2121 } else if (!done) { 2122 p_error = parse_mismatched_brackets; 2123 break; 2124 } 2125 s++; 2126 fmt->type = mmt_single; 2127 fmt->match.single.numRange = numRange; 2128 fmt->match.single.lo = (unsigned char *)lo; 2129 fmt->match.single.hi = (unsigned char *)hi; 2130 } else { 2131 /* go to next key symbol - copy escaped key symbols */ 2132 escape = FALSE; 2133 done = FALSE; 2134 while (s < s_end) { 2135 if (escape) 2136 escape = FALSE; 2137 else { 2138 switch (*s) { 2139 case OPEN_BRACKET: 2140 case ASTERIX_CHAR: 2141 case PERCENT_SIGN: 2142 done = TRUE; 2143 break; 2144 case ESCAPE_CHAR: 2145 escape = !escape; 2146 break; 2147 default: 2148 break; 2149 } 2150 } 2151 if (done) 2152 break; 2153 s++; 2154 } 2155 if (escape) { 2156 p_error = parse_unmatched_escape; 2157 break; 2158 } 2159 fmt->type = mmt_string; 2160 fmt->match.string = 2161 s_strndup_esc(begin_fmt, s - begin_fmt); 2162 if (fmt->match.string == NULL) 2163 break; 2164 } 2165 2166 if (p_error == no_parse_error) 2167 return (s); 2168 } 2169 if (lo != NULL) 2170 free(lo); 2171 if (hi != NULL) 2172 free(hi); 2173 return (NULL); 2174 } 2175 2176 /* 2177 * FUNCTION: get_next_print_format_item 2178 * 2179 * Get the next format token from the string 2180 * 2181 * RETURN VALUE: NULL if error 2182 * position of beginning next token after 2183 * token 2184 * 2185 * INPUT: the format string 2186 */ 2187 2188 const char * 2189 get_next_print_format_item( 2190 const char *begin_fmt, 2191 const char *end_fmt, 2192 __nis_mapping_format_t *fmt) 2193 { 2194 const char *s = begin_fmt; 2195 const char *s_end = end_fmt; 2196 bool_t skip_ber; 2197 2198 for (; p_error == no_parse_error; ) { 2199 if (s >= s_end) { 2200 p_error = parse_internal_error; 2201 break; 2202 } 2203 2204 if (*s == PERCENT_SIGN) { 2205 s++; 2206 if (s >= s_end) { 2207 p_error = parse_unsupported_format; 2208 break; 2209 } 2210 skip_ber = FALSE; 2211 /* 2212 * If the format is %s, it is interpretted 2213 * as a string. 2214 */ 2215 switch (*s) { 2216 case 's': 2217 fmt->type = mmt_item; 2218 break; 2219 case 'n': /* null */ 2220 case 'x': /* skip the next element */ 2221 skip_ber = TRUE; 2222 /* FALLTHRU */ 2223 case 'b': /* boolean */ 2224 case 'e': /* enumerated */ 2225 case 'i': /* int */ 2226 case 'o': /* octet string */ 2227 case 'B': /* bit string */ 2228 fmt->match.berString = s_strndup(s, 1); 2229 fmt->type = skip_ber ? 2230 mmt_berstring_null : 2231 mmt_berstring; 2232 break; 2233 case '{': /* begin sequence */ 2234 case '[': /* begin set */ 2235 case '}': /* end sequence */ 2236 case ']': /* end set */ 2237 case 'a': /* octet string */ 2238 case 'l': /* length of next item */ 2239 case 'O': /* octet string */ 2240 case 't': /* tag of next item */ 2241 case 'T': /* skip tag of next item */ 2242 case 'v': /* seq of strings */ 2243 case 'V': /* seq of strings + lengths */ 2244 default: 2245 p_error = parse_bad_ber_format; 2246 break; 2247 } 2248 s++; 2249 } else { 2250 while (s < s_end) { 2251 if (*s == PERCENT_SIGN) 2252 break; 2253 else if (*s == ESCAPE_CHAR) 2254 s++; 2255 s++; 2256 } 2257 if (s > s_end) { 2258 p_error = parse_unmatched_escape; 2259 break; 2260 } 2261 fmt->match.string = 2262 s_strndup_esc(begin_fmt, s - begin_fmt); 2263 if (fmt->match.string == NULL) 2264 break; 2265 fmt->type = mmt_string; 2266 } 2267 if (p_error == no_parse_error) 2268 return (s); 2269 } 2270 return (NULL); 2271 } 2272 2273 /* 2274 * FUNCTION: get_ldap_filter 2275 * 2276 * Gets an LDAP filter - see RFC 2254. Note that this does not 2277 * determine if the ldap filter is valid. This only determines 2278 * that the parentheses are balanced. 2279 * 2280 * RETURN VALUE: NULL if error 2281 * position of beginning next token after 2282 * filter 2283 * 2284 * INPUT: the begin and end of string 2285 * 2286 * OUTPUT: the begin and end of LDAP filter 2287 * 2288 */ 2289 2290 const char * 2291 get_ldap_filter(const char **begin, const char **end) 2292 { 2293 const char *s = *begin; 2294 const char *s_begin; 2295 const char *s_end = *end; 2296 int nParen; 2297 2298 for (; p_error == no_parse_error; ) { 2299 while (s < s_end && is_whitespace(*s)) 2300 s++; 2301 if (s == s_end) { 2302 s = NULL; 2303 break; 2304 } 2305 2306 s_begin = s; 2307 if (*s == OPEN_PAREN_CHAR) { 2308 nParen = 1; 2309 s++; 2310 while (s < s_end && nParen > 0) { 2311 if (*s == ESCAPE_CHAR) 2312 s++; 2313 else if (*s == OPEN_PAREN_CHAR) 2314 nParen++; 2315 else if (*s == CLOSE_PAREN_CHAR) 2316 nParen--; 2317 s++; 2318 } 2319 if (nParen == 0) { 2320 *begin = s_begin; 2321 *end = s; 2322 while (s < s_end && is_whitespace(*s)) 2323 s++; 2324 } else 2325 s = NULL; 2326 } else 2327 s = NULL; 2328 if (p_error == no_parse_error) 2329 break; 2330 } 2331 if (s == NULL) 2332 p_error = parse_invalid_ldap_search_filter; 2333 2334 return (s); 2335 } 2336 2337 /* 2338 * FUNCTION: get_ava_list 2339 * 2340 * Gets an attribute value assertion list 2341 * 2342 * RETURN VALUE: NULL if error 2343 * position of beginning next token after 2344 * after attribute assertion 2345 * 2346 * INPUT: the begin and end of string 2347 * Indicator if ava list is part of a nisplus 2348 * item 2349 * 2350 * OUTPUT: the begin and end of LDAP filter 2351 * 2352 */ 2353 2354 const char * 2355 get_ava_list(const char **begin, const char **end, bool_t end_nisplus) 2356 { 2357 const char *s = *begin; 2358 const char *s_begin; 2359 const char *s_end = *end; 2360 bool_t in_quote; 2361 bool_t got_equal; 2362 bool_t got_data; 2363 2364 for (; p_error == no_parse_error; ) { 2365 while (s < s_end && is_whitespace(*s)) 2366 s++; 2367 if (s == s_end) { 2368 s = NULL; 2369 break; 2370 } 2371 2372 in_quote = FALSE; 2373 got_equal = FALSE; 2374 got_data = FALSE; 2375 s_begin = s; 2376 while (s < s_end) { 2377 if (*s == ESCAPE_CHAR) { 2378 s++; 2379 got_data = TRUE; 2380 } else if (*s == DOUBLE_QUOTE_CHAR) { 2381 in_quote = !in_quote; 2382 got_data = TRUE; 2383 } else if (in_quote) 2384 ; 2385 else if (*s == EQUAL_CHAR) { 2386 if (end_nisplus && got_data && got_equal) 2387 break; 2388 if (!got_data || got_equal) { 2389 got_equal = FALSE; 2390 break; 2391 } 2392 got_equal = TRUE; 2393 got_data = FALSE; 2394 } else if (*s == COMMA_CHAR) { 2395 if (!got_data || !got_equal) 2396 break; 2397 got_data = FALSE; 2398 got_equal = FALSE; 2399 } else if (is_whitespace(*s)) 2400 ; 2401 else 2402 got_data = TRUE; 2403 s++; 2404 } 2405 if (!got_data || !got_equal || in_quote) 2406 s = NULL; 2407 else { 2408 *begin = s_begin; 2409 *end = s; 2410 while (s < s_end && is_whitespace(*s)) 2411 s++; 2412 } 2413 if (p_error == no_parse_error) 2414 break; 2415 } 2416 if (s == NULL) 2417 p_error = parse_invalid_ldap_search_filter; 2418 2419 return (s); 2420 } 2421 2422 /* Utility functions */ 2423 bool_t 2424 validate_dn(const char *s, int len) 2425 { 2426 const char *end = s + len; 2427 bool_t valid; 2428 2429 valid = skip_get_dn(s, end) == end; 2430 2431 if (!valid) 2432 p_error = parse_bad_dn; 2433 return (valid); 2434 } 2435 2436 bool_t 2437 validate_ldap_filter(const char *s, const char *end) 2438 { 2439 const char *s_begin; 2440 const char *s_end; 2441 2442 s_begin = s; 2443 s_end = end; 2444 2445 if (*s == OPEN_PAREN_CHAR) { 2446 s = get_ldap_filter(&s_begin, &s_end); 2447 } else { 2448 /* Assume an attribute value list */ 2449 s = get_ava_list(&s_begin, &s_end, FALSE); 2450 } 2451 if (s == NULL || s_end != end) 2452 p_error = parse_invalid_ldap_search_filter; 2453 2454 return (p_error == no_parse_error); 2455 } 2456 2457 char * 2458 s_strndup(const char *s, int n) 2459 { 2460 char *d = (char *)malloc(n + 1); 2461 2462 if (d != NULL) { 2463 (void) memcpy(d, s, n); 2464 d[n] = '\0'; 2465 } else { 2466 p_error = parse_no_mem_error; 2467 } 2468 2469 return (d); 2470 } 2471 2472 char * 2473 s_strndup_esc(const char *s, int n) 2474 { 2475 char *d = (char *)malloc(n + 1); 2476 int i; 2477 int j; 2478 2479 if (d != NULL) { 2480 for (i = 0, j = 0; i < n; i++) { 2481 if (s[i] == ESCAPE_CHAR) 2482 i++; 2483 d[j++] = s[i]; 2484 } 2485 d[j] = '\0'; 2486 } else { 2487 p_error = parse_no_mem_error; 2488 } 2489 2490 return (d); 2491 } 2492 2493 void * 2494 s_calloc(size_t n, size_t size) 2495 { 2496 void *d = (char *)calloc(n, size); 2497 2498 if (d == NULL) { 2499 p_error = parse_no_mem_error; 2500 } 2501 2502 return (d); 2503 } 2504 2505 void * 2506 s_malloc(size_t size) 2507 { 2508 void *d = malloc(size); 2509 if (d == NULL) 2510 p_error = parse_no_mem_error; 2511 return (d); 2512 } 2513 2514 void * 2515 s_realloc(void *s, size_t size) 2516 { 2517 s = realloc(s, size); 2518 if (s == NULL) 2519 p_error = parse_no_mem_error; 2520 return (s); 2521 } 2522 2523 char * 2524 s_strdup(const char *s) 2525 { 2526 return (s != NULL ? s_strndup(s, strlen(s)) : NULL); 2527 } 2528 2529 bool_t 2530 is_whitespace(int c) 2531 { 2532 return (c == ' ' || c == '\t'); 2533 } 2534 2535 bool_t 2536 is_string_ok(char *buffer, int buflen) 2537 { 2538 int i; 2539 2540 if (buffer == NULL) 2541 return (FALSE); 2542 2543 for (i = 0; i < buflen; i++) { 2544 if (!is_whitespace(buffer[i])) { 2545 if (buffer[i] == POUND_SIGN) 2546 return (TRUE); 2547 else 2548 return (FALSE); 2549 } 2550 } 2551 return (TRUE); 2552 } 2553 2554 /* 2555 * Returns true if the first string is contained at the beginning of the 2556 * second string. Otherwise returns false. 2557 */ 2558 2559 bool_t 2560 contains_string(const char *s1, const char *s2) 2561 { 2562 return (strncasecmp(s1, s2, strlen(s1)) == 0); 2563 } 2564 2565 /* 2566 * Returns the next character position in the second string, if the first 2567 * string is contained at the beginning of the second string. Otherwise 2568 * returns NULL. 2569 */ 2570 2571 const char * 2572 skip_string(const char *s1, const char *s2, int len) 2573 { 2574 int len1 = strlen(s1); 2575 2576 if (len >= len1 && strncasecmp(s1, s2, strlen(s1)) == 0) 2577 return (s2 + len1); 2578 else 2579 return (NULL); 2580 } 2581 2582 /* 2583 * The second string is not necessarily null terminated. 2584 * same_string returns true if the second string matches the first. 2585 * Otherwise returns false. 2586 */ 2587 2588 bool_t 2589 same_string(const char *s1, const char *s2, int len) 2590 { 2591 int len1 = strlen(s1); 2592 2593 return (len1 == len && strncasecmp(s1, s2, len1) == 0); 2594 } 2595 2596 void 2597 report_error(const char *str, const char *attr) 2598 { 2599 char fmt_buf[1024]; 2600 int pos = 0; 2601 2602 if (command_line_source != NULL) { 2603 snprintf(fmt_buf, sizeof (fmt_buf), "Error parsing %s: ", 2604 command_line_source); 2605 pos = strlen(fmt_buf); 2606 } else if (file_source != NULL) { 2607 snprintf(fmt_buf, sizeof (fmt_buf), "Error parsing file '%s': ", 2608 file_source); 2609 pos = strlen(fmt_buf); 2610 } else if (ldap_source != NULL) { 2611 snprintf(fmt_buf, sizeof (fmt_buf), "Error for LDAP dn '%s': ", 2612 ldap_source); 2613 pos = strlen(fmt_buf); 2614 } 2615 2616 if (start_line_num != 0) { 2617 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos, "at line %d: ", 2618 start_line_num); 2619 pos += strlen(fmt_buf + pos); 2620 } 2621 2622 if (attr != NULL) { 2623 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos, 2624 "for attribute %s: ", attr); 2625 pos += strlen(fmt_buf + pos); 2626 } 2627 2628 if (cons != NULL) { 2629 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos, "%s\n", 2630 parse_error_msg[p_error]); 2631 fprintf(cons, fmt_buf, str == NULL ? "" : str); 2632 } else { 2633 snprintf(fmt_buf + pos, sizeof (fmt_buf) - pos, "%s", 2634 parse_error_msg[p_error]); 2635 syslog(LOG_ERR, fmt_buf, str == NULL ? "" : str); 2636 } 2637 } 2638 2639 void 2640 report_error2( 2641 const char *str1, 2642 const char *str2) 2643 { 2644 char fmt_buf[1024]; 2645 2646 if (cons != NULL) { 2647 snprintf(fmt_buf, sizeof (fmt_buf), 2648 "%s\n", parse_error_msg[p_error]); 2649 fprintf(cons, fmt_buf, str1, str2); 2650 } else { 2651 syslog(LOG_ERR, parse_error_msg[p_error], str1, str2); 2652 } 2653 } 2654 2655 void 2656 report_conn_error( 2657 conn_error e, 2658 const char *str1, 2659 const char *str2) 2660 { 2661 char fmt_buf[1024]; 2662 2663 if (cons != NULL) { 2664 snprintf(fmt_buf, sizeof (fmt_buf), 2665 "%s\n", conn_error_msg[e]); 2666 fprintf(cons, fmt_buf, 2667 str1 == NULL ? "" : str1, 2668 str2 == NULL ? "" : str2); 2669 } else { 2670 syslog(LOG_ERR, 2671 conn_error_msg[e], 2672 str1 == NULL ? "" : str1, 2673 str2 == NULL ? "" : str2); 2674 } 2675 } 2676 2677 void 2678 report_info( 2679 const char *str, 2680 const char *arg) 2681 { 2682 if (cons != NULL) { 2683 fputs(str, cons); 2684 if (arg != NULL) 2685 fputs(arg, cons); 2686 fputs("\n", cons); 2687 } else 2688 syslog(LOG_INFO, str, arg); 2689 }