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