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