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 2005 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 <errno.h> 35 #include <syslog.h> 36 37 #include "ldap_parse.h" 38 #include "nis_parse_ldap_conf.h" 39 #include "nis_parse_ldap_err.h" 40 #include "ldap_util.h" 41 42 extern __nis_mapping_rule_t **dup_mapping_rules( 43 __nis_mapping_rule_t **rules, int n_rules); 44 extern __nis_mapping_rule_t *dup_mapping_rule( 45 __nis_mapping_rule_t *in); 46 47 static int merge_table_mapping(__nis_table_mapping_t *in, 48 __nis_table_mapping_t *out); 49 __nis_table_mapping_t *new_merged_mapping(const char *, 50 __nis_table_mapping_t *intbl); 51 static int append_mapping_rule(__nis_mapping_rule_t *src_rule, 52 __nis_table_mapping_t *tbl, int flag); 53 54 55 static int copy_object_dn(__nis_object_dn_t *in, 56 __nis_object_dn_t *newdn); 57 58 /* 59 * FUNCTION: initialize_table_mapping 60 * 61 * Initialize the __nis_table_mapping_t structure. 62 * 63 * INPUT: __nis_table_mapping_t 64 * 65 */ 66 void 67 initialize_table_mapping( 68 __nis_table_mapping_t *mapping) 69 { 70 if (mapping != NULL) { 71 mapping->dbId = NULL; 72 73 mapping->index.numIndexes = 0; 74 mapping->index.name = NULL; 75 mapping->index.value = NULL; 76 77 mapping->numColumns = 0; 78 mapping->column = NULL; 79 80 mapping->initTtlLo = (time_t)NO_VALUE_SET; 81 mapping->initTtlHi = (time_t)NO_VALUE_SET; 82 mapping->ttl = (time_t)NO_VALUE_SET; 83 84 mapping->usedns_flag = 0; 85 mapping->securemap_flag = 0; 86 mapping->commentChar = DEFAULT_COMMENT_CHAR; 87 mapping->numSplits = 0; 88 89 mapping->objectDN = NULL; 90 91 mapping->separatorStr = DEFAULT_SEP_STRING; 92 93 mapping->numRulesFromLDAP = 0; 94 mapping->numRulesToLDAP = 0; 95 96 mapping->ruleFromLDAP = NULL; 97 mapping->ruleToLDAP = NULL; 98 99 mapping->e = NULL; 100 mapping->objName = NULL; 101 mapping->objPath = NULL; 102 mapping->obj = NULL; 103 mapping->isMaster = 0; 104 mapping->seq_num = NO_VALUE_SET; 105 } 106 } 107 108 /* 109 * FUNCTION: initialize_yp_parse_structs 110 * 111 * Initialize the __yp_domain_context_t structure. 112 * 113 * INPUT: __yp_domain_context_t 114 * 115 */ 116 void 117 initialize_yp_parse_structs( 118 __yp_domain_context_t *ypDomains) 119 { 120 ypDomains->numDomains = 0; 121 ypDomains->domainLabels = NULL; 122 ypDomains->domains = NULL; 123 ypDomains->numYppasswdd = 0; 124 ypDomains->yppasswddDomainLabels = NULL; 125 } 126 127 /* 128 * FUNCTION: merge_table_mapping 129 * 130 * Merges information from one table_mapping struct 131 * into another 132 * 133 * INPUT: Source and Destination table_mapping structs. 134 * RETURN: 0 on success and > 0 on error. 135 */ 136 137 static int 138 merge_table_mapping( 139 __nis_table_mapping_t *in, 140 __nis_table_mapping_t *out) 141 { 142 int i; 143 int len; 144 int orig_num_rules; 145 int append; 146 147 if (in == NULL) 148 return (1); 149 150 if (in->dbId == NULL) 151 return (1); 152 153 /* 154 * If 'in' is generic (non-expanded) and 'out' is domain-specific, 155 * then rules from 'in' should not be appended to those in 'out'. 156 */ 157 if (!strchr(in->dbId, COMMA_CHAR) && strchr(out->dbId, COMMA_CHAR)) 158 append = 0; 159 else 160 append = 1; 161 162 163 if (!out->index.numIndexes && in->index.numIndexes > 0) { 164 if (!dup_index(&in->index, &out->index)) 165 return (1); 166 } 167 168 /* add_column() increments numColumns, so we don't */ 169 if (!out->numColumns && in->numColumns > 0) { 170 for (i = 0; i < in->numColumns; i++) { 171 if (!add_column(out, in->column[i])) 172 return (1); 173 } 174 } 175 176 if (out->commentChar == DEFAULT_COMMENT_CHAR && 177 in->commentChar != DEFAULT_COMMENT_CHAR) 178 out->commentChar = in->commentChar; 179 180 if (out->usedns_flag == 0) 181 out->usedns_flag = in->usedns_flag; 182 183 if (out->securemap_flag == 0) 184 out->securemap_flag = in->securemap_flag; 185 186 if (out->separatorStr == DEFAULT_SEP_STRING && 187 in->separatorStr != DEFAULT_SEP_STRING) { 188 out->separatorStr = s_strdup(in->separatorStr); 189 if (!out->separatorStr) 190 return (2); 191 } 192 193 if (!out->numSplits && !out->e && in->e) { 194 out->numSplits = in->numSplits; 195 out->e = (__nis_mapping_element_t *) 196 s_calloc(1, (in->numSplits+1) * 197 sizeof (__nis_mapping_element_t)); 198 if (!out->e) 199 return (2); 200 for (i = 0; i <= in->numSplits; i++) { 201 if (!dup_mapping_element(&in->e[i], &out->e[i])) { 202 for (; i > 0; i--) { 203 free_mapping_element(&out->e[i - 1]); 204 } 205 out->e = NULL; 206 return (1); 207 } 208 } 209 } 210 211 if (out->initTtlLo == (time_t)NO_VALUE_SET && 212 in->initTtlLo != (time_t)NO_VALUE_SET) 213 out->initTtlLo = in->initTtlLo; 214 215 if (out->initTtlHi == (time_t)NO_VALUE_SET && 216 in->initTtlHi != (time_t)NO_VALUE_SET) 217 out->initTtlHi = in->initTtlHi; 218 219 if (out->ttl == (time_t)NO_VALUE_SET && 220 in->ttl != (time_t)NO_VALUE_SET) 221 out->ttl = in->ttl; 222 223 if (!out->numRulesFromLDAP && in->numRulesFromLDAP) { 224 out->ruleFromLDAP = dup_mapping_rules(in->ruleFromLDAP, 225 in->numRulesFromLDAP); 226 if (!out->ruleFromLDAP) 227 return (1); 228 out->numRulesFromLDAP = in->numRulesFromLDAP; 229 } else if (append && out->numRulesFromLDAP && in->numRulesFromLDAP) { 230 orig_num_rules = out->numRulesFromLDAP; 231 for (i = 0; i < in->numRulesFromLDAP; i++) { 232 if (append_mapping_rule(in->ruleFromLDAP[i], out, 0)) { 233 for (i = out->numRulesFromLDAP; 234 i > orig_num_rules; i--) { 235 free_mapping_rule(out->ruleFromLDAP[i]); 236 out->ruleFromLDAP[i] = NULL; 237 } 238 return (1); 239 240 } 241 } 242 } 243 244 if (!out->numRulesToLDAP && in->numRulesToLDAP) { 245 out->ruleToLDAP = dup_mapping_rules(in->ruleToLDAP, 246 in->numRulesToLDAP); 247 if (!out->ruleToLDAP) 248 return (1); 249 out->numRulesToLDAP = in->numRulesToLDAP; 250 } else if (append && out->numRulesToLDAP && in->numRulesToLDAP) { 251 orig_num_rules = out->numRulesToLDAP; 252 for (i = 0; i < in->numRulesToLDAP; i++) { 253 if (append_mapping_rule(in->ruleToLDAP[i], out, 1)) { 254 for (i = out->numRulesToLDAP; 255 i > orig_num_rules; i--) { 256 free_mapping_rule(out->ruleToLDAP[i]); 257 out->ruleToLDAP[i] = NULL; 258 } 259 return (1); 260 } 261 } 262 } 263 if (!out->objectDN && in->objectDN) { 264 out->objectDN = (__nis_object_dn_t *) 265 s_calloc(1, sizeof (__nis_object_dn_t)); 266 if (!out->objectDN) 267 return (2); 268 if (copy_object_dn(in->objectDN, out->objectDN)) { 269 free_object_dn(out->objectDN); 270 out->objectDN = NULL; 271 return (1); 272 } 273 } 274 275 if (!out->objName && in->objName) { 276 if (!strchr(in->objName, SPACE_CHAR)) { 277 /* objName has no space- a single map dbIdMapping */ 278 out->objName = s_strndup(in->objName, 279 strlen(in->objName)); 280 if (!out->objName) 281 return (2); 282 } 283 } 284 285 if (!out->objName && out->dbId) { 286 out->objName = s_strndup(out->dbId, strlen(out->dbId)); 287 if (!out->objName) 288 return (2); 289 } 290 291 if (out->seq_num == NO_VALUE_SET && in->seq_num >= 0) 292 out->seq_num = in->seq_num; 293 294 return (p_error == no_parse_error ? 0 : 1); 295 } 296 297 /* 298 * FUNCTION: copy_object_dn 299 * 300 * Copies a __nis_object_dn_t structure. 301 * 302 * RETURN: 0 on success, > 0 on failure. 303 * 304 * NOTE: The caller MUST free newdn using 305 * free_object_dn() if return value != 0 (error condition) 306 */ 307 308 static int 309 copy_object_dn( 310 __nis_object_dn_t *in, 311 __nis_object_dn_t *newdn) 312 { 313 if (in == NULL) { 314 p_error = parse_no_object_dn; 315 return (1); 316 } 317 while (in != NULL) { 318 if (in->read.base == NULL) { 319 newdn->read.base = NULL; 320 } else { 321 newdn->read.base = s_strndup( 322 in->read.base, 323 strlen(in->read.base)); 324 if (newdn->read.base == NULL) 325 return (2); 326 } 327 newdn->read.scope = in->read.scope; 328 if (in->read.attrs) { 329 newdn->read.attrs = s_strndup( 330 in->read.attrs, 331 strlen(in->read.attrs)); 332 if (newdn->read.attrs == NULL) { 333 return (2); 334 } 335 } else { 336 newdn->read.attrs = NULL; 337 } 338 newdn->read.element = in->read.element; 339 if (in->write.base != NULL) { 340 newdn->write.base = s_strndup( 341 in->write.base, 342 strlen(in->write.base)); 343 if (newdn->write.base == NULL) 344 return (2); 345 } else { 346 newdn->write.base = NULL; 347 } 348 newdn->write.scope = in->write.scope; 349 if (in->write.attrs != NULL) { 350 newdn->write.attrs = s_strndup( 351 in->write.attrs, 352 strlen(in->write.attrs)); 353 if (newdn->write.attrs == NULL) { 354 return (2); 355 } 356 } else { 357 newdn->write.attrs = NULL; 358 } 359 newdn->write.element = in->write.element; 360 if (in->dbIdName) { 361 newdn->dbIdName = s_strndup(in->dbIdName, 362 strlen(in->dbIdName)); 363 if (newdn->dbIdName == NULL) 364 return (2); 365 } 366 367 if (in->delDisp) 368 newdn->delDisp = in->delDisp; 369 370 if (in->dbId && in->numDbIds > 0) { 371 newdn->dbId = dup_mapping_rules(in->dbId, 372 in->numDbIds); 373 if (!newdn->dbId) 374 return (1); 375 newdn->numDbIds = in->numDbIds; 376 } 377 if (in->next != NULL) { 378 newdn->next = (__nis_object_dn_t *)s_calloc(1, 379 sizeof (__nis_object_dn_t)); 380 if (newdn->next == NULL) 381 return (1); 382 newdn = newdn->next; 383 in = in->next; 384 } else { 385 return (0); 386 } 387 } /* End of while on in */ 388 389 return (0); 390 } 391 392 /* 393 * FUNCTION: free_yp_domain_context 394 * 395 * Frees __yp_domain_context_t 396 * 397 * INPUT: __yp_domain_context_t 398 */ 399 void 400 free_yp_domain_context(__yp_domain_context_t *domains) 401 { 402 int i; 403 404 if (domains != NULL) { 405 for (i = 0; i < domains->numDomains; i++) { 406 if (domains->domains[i] != NULL) { 407 free(domains->domains[i]); 408 domains->domains[i] = NULL; 409 } 410 if (domains->domainLabels[i] != NULL) { 411 free(domains->domainLabels[i]); 412 domains->domainLabels[i] = NULL; 413 } 414 } 415 domains->domains = NULL; 416 domains->domainLabels = NULL; 417 for (i = 0; i < domains->numYppasswdd; i++) { 418 if (domains->yppasswddDomainLabels[i] != NULL) { 419 free(domains->yppasswddDomainLabels[i]); 420 domains->yppasswddDomainLabels[i] 421 = NULL; 422 } 423 } 424 domains->yppasswddDomainLabels = NULL; 425 domains->numDomains = 0; 426 domains = NULL; 427 } 428 } 429 430 /* 431 * FUNCTION: second_parser_pass 432 * 433 * Prepares the linked list of table_mappings for processing 434 * by finish_parse(), adding, merging and deleting structures 435 * as necessary. Also adds dummy objectDN info. for splitField's. 436 * 437 * RETURN VALUE: 0 on success, > 0 on failure. 438 */ 439 int 440 second_parser_pass( 441 __nis_table_mapping_t **table_mapping) 442 { 443 __nis_table_mapping_t *t, *t2; 444 __nis_table_mapping_t *t_new = NULL, *tg; 445 __nis_table_mapping_t *prev = NULL; 446 __nis_object_dn_t *objectDN; 447 char *objs, *dom; 448 char *objName = NULL; 449 char *lasts; 450 char *tobj, *alias, *dupalias, *tmp; 451 char *myself = "second_parser_pass"; 452 int i = 0, len; 453 int remove_t = 0; 454 int add_t = 0; 455 456 prev = NULL; 457 for (t = *table_mapping; t != NULL; ) { 458 /* 459 * Temporarily using this field to flag deletion. 460 * 0 : don't delete 461 * 1 : delete 462 * The mapping structure will be deleted in final_parser_pass 463 */ 464 t->isMaster = 0; 465 466 if (!t->dbId) { 467 p_error = parse_bad_map_error; 468 logmsg(MSG_NOTIMECHECK, LOG_ERR, 469 "%s: no dbId field", myself); 470 return (1); 471 } 472 tg = NULL; 473 dom = strchr(t->dbId, COMMA_CHAR); 474 if (t->objName != NULL) { 475 objName = strdup(t->objName); 476 if (objName == NULL) { 477 p_error = parse_no_mem_error; 478 logmsg(MSG_NOMEM, LOG_ERR, 479 "%s: Cannot allocate memory for objName", myself); 480 return (1); 481 } 482 objs = (char *)strtok_r(objName, " ", &lasts); 483 /* Get the generic mapping */ 484 if (dom != NULL) { 485 tg = find_table_mapping(t->dbId, dom - t->dbId, 486 *table_mapping); 487 } 488 } else { 489 objs = NULL; 490 if (dom == NULL) { 491 t->objName = s_strndup(t->dbId, 492 strlen(t->dbId)); 493 if (!t->objName) { 494 logmsg(MSG_NOMEM, LOG_ERR, 495 "%s: Cannot allocate memory for t->objName", 496 myself); 497 objs = NULL; 498 return (2); 499 } 500 } else { 501 /* Force relationship for domain specific */ 502 503 /* Get the generic mapping */ 504 tg = find_table_mapping(t->dbId, dom - t->dbId, 505 *table_mapping); 506 if (tg == NULL || tg->objName == NULL) { 507 /* If not found, use dbId for objName */ 508 t->objName = s_strndup(t->dbId, 509 strlen(t->dbId)); 510 if (t->objName == NULL) { 511 logmsg(MSG_NOMEM, LOG_ERR, 512 "%s: Cannot allocate memory for t->objName", 513 myself); 514 return (2); 515 } 516 } else { 517 dom++; 518 tobj = s_strndup(tg->objName, 519 strlen(tg->objName)); 520 if (tobj == NULL) { 521 logmsg(MSG_NOMEM, LOG_ERR, 522 "%s: Cannot allocate memory for t->objName", 523 myself); 524 return (2); 525 } 526 alias = (char *)strtok_r(tobj, " ", 527 &lasts); 528 529 /* Loop 'breaks' on errors */ 530 while (alias) { 531 tmp = NULL; 532 dupalias = s_strndup(alias, 533 strlen(alias)); 534 if (!dupalias) 535 break; 536 if (getfullmapname(&dupalias, 537 dom)) { 538 i = 1; 539 break; 540 } 541 if (t->objName == NULL) 542 t->objName = dupalias; 543 else { 544 len = strlen(t->objName) 545 + strlen(dupalias) + 2; 546 tmp = s_calloc(1, len); 547 if (tmp == NULL) 548 break; 549 snprintf(tmp, len, 550 "%s %s", 551 t->objName, 552 dupalias); 553 free(dupalias); 554 dupalias = NULL; 555 free(t->objName); 556 t->objName = tmp; 557 } 558 alias = (char *)strtok_r(NULL, 559 " ", &lasts); 560 } 561 562 if (tobj) 563 free(tobj); 564 565 if (alias || 566 (objName = s_strdup(t->objName)) 567 == NULL) { 568 if (i) 569 logmsg(MSG_NOTIMECHECK, 570 LOG_ERR, 571 "%s: getfullmapname failed for %s for domain \"%s\"", 572 myself, dupalias, dom); 573 else { 574 p_error = 575 parse_no_mem_error; 576 logmsg(MSG_NOMEM, 577 LOG_ERR, 578 "%s: Cannot allocate memory", 579 myself); 580 } 581 if (dupalias) 582 free(dupalias); 583 if (t->objName) 584 free(t->objName); 585 return (2); 586 587 } 588 objs = (char *)strtok_r(objName, " ", 589 &lasts); 590 } 591 } 592 } 593 594 if (tg != NULL) { 595 if (merge_table_mapping(tg, t)) { 596 logmsg(MSG_NOTIMECHECK, LOG_ERR, 597 "Error merging information from the %s to the %s mapping structure", 598 tg->dbId, t->dbId); 599 objs = NULL; 600 if (objName) 601 free(objName); 602 return (1); 603 } 604 } 605 606 /* 607 * If objName is "map1 map2" then do the second pass. 608 * If it is just "map1" however skip the expansion. 609 * Also skip it if t->objName is null. 610 */ 611 if (objs && strncasecmp(objs, t->objName, 612 strlen(t->objName))) { 613 t2 = find_table_mapping(objs, strlen(objs), 614 *table_mapping); 615 if (t2) { 616 if (merge_table_mapping(t, t2)) { 617 logmsg(MSG_NOTIMECHECK, LOG_ERR, 618 "Error merging information from the %s to the %s mapping structure", 619 t->dbId, t2->dbId); 620 objs = NULL; 621 if (objName) 622 free(objName); 623 return (1); 624 } 625 t->isMaster = 1; 626 } else { 627 t_new = new_merged_mapping(objs, t); 628 if (t_new) { 629 t->isMaster = 1; 630 if (prev != NULL) 631 prev->next = t_new; 632 else 633 *table_mapping = t_new; 634 prev = t_new; 635 prev->next = t; 636 } else { 637 logmsg(MSG_NOTIMECHECK, LOG_ERR, 638 "Error creating a new mapping structure %s", 639 objs); 640 objs = NULL; 641 if (objName) 642 free(objName); 643 return (1); 644 } 645 } 646 while ((objs = (char *)strtok_r(NULL, " ", &lasts)) 647 != NULL) { 648 t2 = find_table_mapping(objs, strlen(objs), 649 *table_mapping); 650 if (t2) { 651 if (merge_table_mapping(t, t2)) { 652 logmsg(MSG_NOTIMECHECK, LOG_ERR, 653 "Error merging information from the %s to the %s mapping structure", 654 t->dbId, t2->dbId); 655 objs = NULL; 656 if (objName) 657 free(objName); 658 return (1); 659 } 660 t->isMaster = 1; 661 } else { 662 /* 663 * create a new t_map with dbId = objs 664 * and copy t->* into new t_map 665 */ 666 t_new = new_merged_mapping(objs, t); 667 if (t_new) { 668 t->isMaster = 1; 669 if (prev != NULL) 670 prev->next = t_new; 671 else 672 *table_mapping = t_new; 673 prev = t_new; 674 prev->next = t; 675 } else { 676 logmsg(MSG_NOTIMECHECK, LOG_ERR, 677 "Error creating a new mapping structure %s", 678 objs); 679 objs = NULL; 680 if (objName) 681 free(objName); 682 return (1); 683 } 684 } 685 } 686 } /* if objs!= NULL */ 687 688 prev = t; 689 t = t->next; 690 691 if (objName) { 692 free(objName); 693 objName = NULL; 694 objs = NULL; 695 } 696 } /* for t = table_mapping loop */ 697 return (0); 698 } 699 700 __nis_table_mapping_t * 701 new_merged_mapping(const char *match, 702 __nis_table_mapping_t *intbl) 703 { 704 705 __nis_table_mapping_t *outtable = NULL; 706 707 outtable = (__nis_table_mapping_t *) 708 s_calloc(1, sizeof (__nis_table_mapping_t)); 709 if (outtable == NULL) 710 return (NULL); 711 initialize_table_mapping(outtable); 712 outtable->dbId = s_strndup(match, strlen(match)); 713 if (outtable->dbId == NULL) { 714 free_table_mapping(outtable); 715 outtable = NULL; 716 return (NULL); 717 } 718 if (merge_table_mapping(intbl, outtable)) { 719 free_table_mapping(outtable); 720 outtable = NULL; 721 } 722 return (outtable); 723 } 724 725 /* 726 * FUNCTION: final_parser_pass 727 * 728 * completes the final expansion of t_map structures linked list. 729 * all structures will have a non-null objPath as well as a objName 730 * in the form of "mapname . domainname ." or "splitfieldname . 731 * domainname .". 732 * 733 * RETURN VALUE: 0 on success, -1 on failure, -2 on fatal error. 734 */ 735 int 736 final_parser_pass( 737 __nis_table_mapping_t **table_mapping, 738 __yp_domain_context_t *ypDomains) 739 { 740 __nis_table_mapping_t *t; 741 __nis_table_mapping_t *t1, *returned_map; 742 __nis_table_mapping_t *prev = NULL; 743 int i; 744 char *myself = "final_parser_pass"; 745 int nm; 746 bool_t r; 747 int del_tbl_flag = 0; 748 749 if (ypDomains) { 750 if (!ypDomains->numDomains) { 751 p_error = parse_internal_error; 752 logmsg(MSG_NOTIMECHECK, LOG_ERR, 753 "%s:No domains specified.", myself); 754 return (-1); 755 } 756 } else { 757 p_error = parse_internal_error; 758 logmsg(MSG_NOTIMECHECK, LOG_ERR, 759 "%s:No domain structure supplied.", myself); 760 return (-1); 761 } 762 prev = NULL; 763 764 for (t = *table_mapping; t != NULL; ) { 765 766 /* Delete if marked for deletion by second_parser_pass */ 767 if (t->isMaster == 1) { 768 if (prev != NULL) 769 prev->next = t->next; 770 else 771 *table_mapping = t->next; 772 t1 = t; 773 t = t->next; 774 free_table_mapping(t1); 775 continue; 776 } 777 778 if (!t->objName && t->dbId) { 779 t->objName = s_strndup(t->dbId, strlen(t->dbId)); 780 if (!t->objName) { 781 logmsg(MSG_NOMEM, LOG_ERR, 782 "%s:Could not allocate.", myself); 783 return (-1); 784 } 785 } 786 i = ypDomains->numDomains; 787 while (i > 0) { 788 if (i == 1) { 789 /* modify existing table_mapping's */ 790 nm = checkfullmapname(t->dbId, 791 ypDomains->domainLabels[0], 792 table_mapping, &returned_map); 793 if (nm == 1) { 794 /* delete this mapping structure */ 795 logmsg(MSG_NOTIMECHECK, 796 LOG_WARNING, 797 "Mapping structure %s,%s " 798 "already exists.", 799 t->dbId, 800 ypDomains->domainLabels[0]); 801 if (merge_table_mapping(t, 802 returned_map)) { 803 logmsg(MSG_NOTIMECHECK, LOG_ERR, 804 "Error merging information " 805 "from the %s to the %s " 806 "mapping structure.", 807 t->dbId, returned_map->dbId); 808 return (-1); 809 } 810 if (del_tbl_flag == 0) 811 del_tbl_flag = 1; 812 } else if (nm == -1) { 813 logmsg(MSG_NOTIMECHECK, LOG_ERR, 814 "Error searching for %s,%s structure", 815 t->dbId, ypDomains->domainLabels[0]); 816 return (-1); 817 } else if (nm == 0 || nm == 2) { 818 if ((append_domainContext(&t, 819 ypDomains->domainLabels[0], 820 ypDomains->domains[0])) != 0) { 821 logmsg(MSG_NOTIMECHECK, LOG_ERR, 822 "Error appending domainContext %s", 823 ypDomains->domainLabels[0]); 824 return (-1); 825 } 826 del_tbl_flag = 0; 827 } 828 } else { /* if (i > 1) */ 829 /* need to create new table_mapping's */ 830 nm = checkfullmapname(t->dbId, 831 ypDomains->domainLabels[i - 1], 832 table_mapping, &returned_map); 833 if (nm == -1) { 834 logmsg(MSG_NOTIMECHECK, LOG_ERR, 835 "Error searching for %s,%s structure", 836 t->dbId, ypDomains->domainLabels[i - 1]); 837 return (-1); 838 } else if (nm == 0) { 839 t1 = new_merged_mapping(t->dbId, t); 840 /* we clone ourselves */ 841 if (t1) { 842 if ((append_domainContext(&t1, 843 ypDomains->domainLabels[i - 1], 844 ypDomains->domains[i - 1])) != 0) { 845 logmsg(MSG_NOTIMECHECK, LOG_ERR, 846 "Error appending domainContext %s", 847 ypDomains->domainLabels[i - 1]); 848 free(t1); 849 return (-1); 850 } 851 if (prev != NULL) { 852 t1->next = prev->next; 853 prev->next = t1; 854 prev = prev->next; 855 } else { 856 t1->next = 857 *table_mapping; 858 *table_mapping = t1; 859 prev = t1; 860 } 861 } else { /* if !t1 */ 862 p_error = parse_internal_error; 863 logmsg(MSG_NOTIMECHECK, LOG_ERR, 864 "%s:Could not create new table -" 865 " check all instances of %s for errors", 866 myself, t->dbId); 867 return (-1); 868 } 869 } else if (nm == 1) { 870 logmsg(MSG_NOTIMECHECK, LOG_WARNING, 871 "Mapping structure %s,%s already exists.", 872 t->dbId, 873 ypDomains->domainLabels[i - 1]); 874 /* 875 * We should be deleting this, but can't 876 * really do it here, because we need to 877 * match with the domainLabels[0] case 878 * too. So we will just flag it for now. 879 */ 880 if (merge_table_mapping(t, 881 returned_map)) { 882 logmsg(MSG_NOTIMECHECK, LOG_ERR, 883 "Error merging information from the %s to the %s mapping structure.", 884 t->dbId, 885 returned_map->dbId); 886 return (-1); 887 } 888 del_tbl_flag = 1; 889 } else if (nm == 2) { 890 if ((append_domainContext(&t, 891 ypDomains->domainLabels[i - 1], 892 ypDomains->domains[i - 1])) 893 != 0) { 894 logmsg(MSG_NOTIMECHECK, LOG_ERR, 895 "Error appending domainContext %s", 896 ypDomains->domainLabels[i - 1]); 897 return (-1); 898 } 899 } /* end of "if (nm == 0)" */ 900 } /* end of else if (i > 1) */ 901 902 903 /* 904 * 'merge_table_mapping' only copies unexpanded 905 * objectDN values into returned_map. Hence, 906 * read.base and write.base in returned_map 907 * needs to be expanded. 908 */ 909 if (nm == 1 && returned_map && returned_map->objectDN) { 910 r = make_fqdn( 911 returned_map->objectDN, 912 ypDomains->domains[i - 1]); 913 if (r == TRUE && 914 returned_map->objectDN->write.base) { 915 r = make_full_dn( 916 &returned_map->objectDN->write.base, 917 ypDomains->domains[i - 1]); 918 } 919 920 if (r == FALSE) { 921 logmsg(MSG_NOTIMECHECK, LOG_ERR, 922 "Error appending domainContext " 923 "%s to %s", 924 ypDomains->domainLabels[i - 1], 925 returned_map->dbId); 926 return (-2); 927 } 928 } 929 i--; 930 } /* end of while i > 0 loop */ 931 932 if (del_tbl_flag == 1) { 933 if (prev != NULL) { 934 prev->next = t->next; 935 free_table_mapping(t); 936 t = prev->next; 937 } else { 938 *table_mapping = t->next; 939 free_table_mapping(t); 940 t = *table_mapping; 941 } 942 del_tbl_flag = 0; 943 } else { 944 prev = t; 945 t = t->next; 946 } 947 } /* end of table mapping loop */ 948 949 for (t = *table_mapping; t != NULL; t = t->next) { 950 if (!t->dbId) { 951 logmsg(MSG_NOTIMECHECK, LOG_ERR, 952 "%s:Fatal error: structure with no dbId found.", 953 myself); 954 return (-2); 955 } 956 append_dot(&t->dbId); 957 if (!t->objectDN) { 958 p_error = parse_internal_error; 959 logmsg(MSG_NOTIMECHECK, LOG_ERR, 960 "%s:No objectDN for %s.", myself, t->dbId); 961 return (-1); 962 } 963 } 964 965 return (0); 966 } 967 968 /* 969 * FUNCTION: append_mapping_rule 970 * 971 * Appends mapping rules to a table_mapping structure 972 * with previously existing rules. flag controls whether 973 * the functions works on the rules From or To LDAP. 974 * 975 * RETURN VALUE: 0 on success, >= 1 on failure. 976 */ 977 978 static int 979 append_mapping_rule(__nis_mapping_rule_t *src_rule, 980 __nis_table_mapping_t *dst, int flag) 981 { 982 __nis_mapping_rule_t **rules = NULL; 983 984 if (flag == 0) { 985 if (dst->ruleFromLDAP == NULL) { 986 p_error = parse_internal_error; 987 return (1); 988 } 989 rules = (__nis_mapping_rule_t **) 990 s_realloc(dst->ruleFromLDAP, 991 (dst->numRulesFromLDAP + 1) * 992 sizeof (__nis_mapping_rule_t *)); 993 if (rules == NULL) 994 return (2); 995 dst->ruleFromLDAP = rules; 996 rules[dst->numRulesFromLDAP] = dup_mapping_rule(src_rule); 997 if (rules[dst->numRulesFromLDAP] == NULL) { 998 p_error = parse_no_mem_error; 999 return (2); 1000 } 1001 dst->numRulesFromLDAP++; 1002 } else if (flag == 1) { 1003 if (dst->ruleToLDAP == NULL) { 1004 p_error = parse_internal_error; 1005 return (1); 1006 } 1007 rules = (__nis_mapping_rule_t **) 1008 s_realloc(dst->ruleToLDAP, 1009 (dst->numRulesToLDAP + 1) * 1010 sizeof (__nis_mapping_rule_t *)); 1011 if (rules == NULL) 1012 return (2); 1013 dst->ruleToLDAP = rules; 1014 rules[dst->numRulesToLDAP] = dup_mapping_rule(src_rule); 1015 if (rules[dst->numRulesToLDAP] == NULL) { 1016 p_error = parse_no_mem_error; 1017 return (2); 1018 } 1019 dst->numRulesToLDAP++; 1020 } else 1021 return (1); 1022 1023 return (0); 1024 } 1025 1026 /* 1027 * FUNCTION: check_domain_specific_order 1028 * 1029 * Makes sure that an attribute with explicitly specified 1030 * nisLDAPdomainContext is found before its non-domain 1031 * specific counterpart. 1032 * 1033 * RETURN VALUE: 0 normal exit 1034 * 1 if domain specific attribute found 1035 * after non-domain specific one. 1036 * -1 some error condition 1037 */ 1038 1039 int 1040 check_domain_specific_order(const char *sd, 1041 config_key attrib_num, 1042 __nis_table_mapping_t *table_mapping, 1043 __yp_domain_context_t *ypDomains) 1044 { 1045 __nis_table_mapping_t *t; 1046 char *myself = "check_domain_specific_order"; 1047 char *type; 1048 char *dbId = 0; 1049 int i, len; 1050 int match = 0; 1051 1052 if (ypDomains) { 1053 if (!ypDomains->numDomains) { 1054 logmsg(MSG_NOTIMECHECK, LOG_ERR, 1055 "%s:No domains specified.", myself); 1056 return (-1); 1057 } 1058 } else { 1059 logmsg(MSG_NOTIMECHECK, LOG_ERR, 1060 "%s:No domain structure supplied.", myself); 1061 return (-1); 1062 } 1063 1064 for (i = 0; i < ypDomains->numDomains; i++) { 1065 for (t = table_mapping; t != NULL; t = t->next) { 1066 len = strlen(sd); 1067 if ((strcasecmp(t->dbId, sd) == 0) && (len == 1068 strlen(t->dbId))) 1069 /* prevent from matching against itself */ 1070 continue; 1071 dbId = s_strndup(t->dbId, strlen(t->dbId)); 1072 if (dbId == NULL) { 1073 logmsg(MSG_NOMEM, LOG_ERR, 1074 "%s:Memory allocation error.", myself); 1075 return (-1); 1076 } 1077 1078 if (getfullmapname(&dbId, 1079 ypDomains->domainLabels[i])) { 1080 logmsg(MSG_NOTIMECHECK, LOG_ERR, 1081 "Error getting fully qualified name for %s", 1082 dbId); 1083 free(dbId); 1084 return (-1); 1085 } 1086 if ((strcasecmp(dbId, sd) == 0) && (len == 1087 strlen(dbId))) { 1088 match = 0; 1089 switch (attrib_num) { 1090 case key_yp_map_flags: 1091 if (t->usedns_flag != 0 || 1092 t->securemap_flag != 0) 1093 match = 1; 1094 type = YP_MAP_FLAGS; 1095 break; 1096 case key_yp_comment_char: 1097 if (t->commentChar != 1098 DEFAULT_COMMENT_CHAR) 1099 match = 1; 1100 type = YP_COMMENT_CHAR; 1101 break; 1102 case key_yp_repeated_field_separators: 1103 if (t->separatorStr != 1104 DEFAULT_SEP_STRING) 1105 match = 1; 1106 type = 1107 YP_REPEATED_FIELD_SEPARATORS; 1108 break; 1109 case key_yp_name_fields: 1110 if (t->e && t->numColumns) 1111 match = 1; 1112 type = YP_NAME_FIELDS; 1113 case key_yp_split_field: 1114 if (t->e && t->numColumns) 1115 match = 1; 1116 type = YP_SPLIT_FIELD; 1117 break; 1118 case key_yp_db_id_map: 1119 if (t->objName) 1120 match = 1; 1121 type = YP_DB_ID_MAP; 1122 break; 1123 case key_yp_entry_ttl: 1124 if (t->initTtlLo != 1125 (time_t)NO_VALUE_SET) 1126 match = 1; 1127 type = YP_ENTRY_TTL; 1128 break; 1129 case key_yp_ldap_object_dn: 1130 if (t->objectDN) 1131 match = 1; 1132 type = YP_LDAP_OBJECT_DN; 1133 break; 1134 case key_nis_to_ldap_map: 1135 if (t->ruleToLDAP) 1136 match = 1; 1137 type = NIS_TO_LDAP_MAP; 1138 break; 1139 case key_ldap_to_nis_map: 1140 if (t->ruleFromLDAP) 1141 match = 1; 1142 type = LDAP_TO_NIS_MAP; 1143 break; 1144 default: 1145 type = "unknown"; 1146 match = 0; 1147 break; 1148 } /* end of switch */ 1149 if (match) { 1150 logmsg(MSG_NOTIMECHECK, LOG_ERR, 1151 "Relative attribute '%s' of type '%s' found before fully qualified one '%s'", 1152 t->dbId, type, sd); 1153 free(dbId); 1154 dbId = NULL; 1155 return (1); 1156 } 1157 } /* end of strncasecmp */ 1158 free(dbId); 1159 dbId = NULL; 1160 } /* end of t loop */ 1161 } /* end of i loop */ 1162 if (dbId) 1163 free(dbId); 1164 dbId = NULL; 1165 return (0); 1166 } 1167 1168 int 1169 getfullmapname(char **mapname, const char *domainname) 1170 { 1171 char *maps = *mapname; 1172 int maplen = strlen(maps); 1173 int domainlen = strlen(domainname); 1174 1175 if (!maplen || !domainlen || 1176 maps[maplen - 1] == PERIOD_CHAR) 1177 return (1); 1178 else if (strchr(maps, COMMA_CHAR)) { 1179 /* map already has a domain part, do nothing */ 1180 return (0); 1181 } else { 1182 append_comma(&maps); 1183 maplen = strlen(maps); 1184 maps = realloc(maps, (maplen + domainlen + 1)); 1185 if (maps != NULL) { 1186 if (strlcat(maps, domainname, (maplen + domainlen + 1)) 1187 >= (maplen + domainlen + 1)) 1188 return (1); 1189 *mapname = maps; 1190 return (0); 1191 } else 1192 return (1); 1193 } 1194 } 1195 1196 /* 1197 * FUNCTION: checkfullmapname 1198 * 1199 * Tries to find out if by appending the table mapping structures 1200 * with each of the provided nisLDAPdomainContexts, an already 1201 * existing fqdn table mapping structure results. That would be the 1202 * case when a full qualified domain specific attribute was present. 1203 * 1204 * Note that per NISLDAPmapping(4) such an attribute MUST be listed 1205 * in the mapping file BEFORE its non-fqdn counterpart. 1206 * 1207 * RETURNS: 0 normal exit, 1 if an existing structure found, -1 for all 1208 * errors, 2 if already fqdn. If returning 1 the existing structure is 1209 * in found_map. 1210 */ 1211 1212 int 1213 checkfullmapname(const char *mapname, const char *domainname, 1214 __nis_table_mapping_t **table_mapping, 1215 __nis_table_mapping_t **found_map) 1216 { 1217 char *map; 1218 1219 *found_map = NULL; 1220 1221 /* This function does not alter mapname */ 1222 1223 if (!mapname || !domainname || *table_mapping == NULL) 1224 return (-1); 1225 1226 if (strchr(mapname, COMMA_CHAR)) 1227 return (2); 1228 1229 if ((map = s_strndup(mapname, strlen(mapname))) == 0) 1230 return (-1); 1231 1232 if (getfullmapname(&map, domainname)) { 1233 free(map); 1234 return (-1); 1235 } 1236 1237 *found_map = find_table_mapping(map, strlen(map), *table_mapping); 1238 if (*found_map) { 1239 free(map); 1240 return (1); 1241 } 1242 1243 free(map); 1244 return (0); 1245 } 1246 1247 /* 1248 * FUNCTION: append_domainContext 1249 * 1250 * Higher level function to append the domains to the appropriate 1251 * fields in a table mapping structure. Calls either getfullmapname() 1252 * or make_full_dn() to do the actual append. 1253 * 1254 * RETURNS: 0 on success, -1 on any error. 1255 */ 1256 1257 int 1258 append_domainContext(__nis_table_mapping_t **table_map, 1259 char *DomainLabel, char *Domain) 1260 { 1261 __nis_table_mapping_t *tmp_map = *table_map; 1262 char *lasts; 1263 char *tmp_dbId = NULL; 1264 char *id = NULL; 1265 int domain_specific = 0; 1266 char *myself = "append_domainContext"; 1267 1268 if (!DomainLabel || !Domain || !tmp_map) 1269 return (-1); 1270 if (tmp_map->dbId == NULL || tmp_map->objName == NULL) { 1271 p_error = parse_bad_map_error; 1272 return (-1); 1273 } 1274 tmp_dbId = s_strndup(tmp_map->dbId, strlen(tmp_map->dbId)); 1275 if (!tmp_dbId) 1276 return (-1); 1277 if (strchr(tmp_map->dbId, COMMA_CHAR)) { 1278 domain_specific = 1; 1279 id = (char *)strtok_r(tmp_dbId, COMMA_STRING, &lasts); 1280 if (id) 1281 id = (char *)strtok_r(NULL, COMMA_STRING, &lasts); 1282 else { 1283 free(tmp_dbId); 1284 return (-1); 1285 } 1286 if (!id) { 1287 free(tmp_dbId); 1288 return (-1); 1289 } 1290 if (strcasecmp(id, DomainLabel)) { 1291 free(tmp_dbId); 1292 return (0); 1293 } 1294 } else { 1295 if (getfullmapname(&tmp_map->dbId, DomainLabel)) { 1296 free(tmp_dbId); 1297 return (-1); 1298 } 1299 append_dot(&tmp_map->dbId); 1300 } 1301 if (tmp_dbId) 1302 free(tmp_dbId); 1303 tmp_dbId = NULL; 1304 1305 if (getfullmapname(&tmp_map->objName, DomainLabel)) 1306 return (-1); 1307 append_dot(&tmp_map->objName); 1308 1309 /* 1310 * If domain specific mapping doesn't have objectDN, 1311 * then don't touch. Most probably, pass for the generic mapping 1312 * will handle this by coping over it's own objectDN 1313 */ 1314 if (domain_specific && tmp_map->objectDN == NULL) 1315 return (0); 1316 1317 if (tmp_map->objectDN == NULL) { 1318 /* Allocate memory to objectDN */ 1319 tmp_map->objectDN = (__nis_object_dn_t *) 1320 s_calloc(1, sizeof (__nis_object_dn_t)); 1321 if (tmp_map->objectDN == NULL) { 1322 logmsg(MSG_NOMEM, LOG_ERR, 1323 "%s: Cannot allocate memory for objectDN", 1324 myself); 1325 return (2); 1326 } 1327 tmp_map->objectDN->read.base = NULL; 1328 tmp_map->objectDN->write.base = NULL; 1329 tmp_map->objectDN->read.attrs = NULL; 1330 tmp_map->objectDN->write.attrs = NULL; 1331 tmp_map->objectDN->read.scope = LDAP_SCOPE_ONELEVEL; 1332 tmp_map->objectDN->write.scope = LDAP_SCOPE_UNKNOWN; 1333 } 1334 1335 if (!make_fqdn(tmp_map->objectDN, Domain)) 1336 return (-1); 1337 if (tmp_map->objectDN->write.base) { 1338 if (!make_full_dn(&tmp_map->objectDN->write.base, Domain)) 1339 return (-1); 1340 } 1341 1342 return (0); 1343 } 1344