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 2001-2003 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 <lber.h> 30 #include <ldap.h> 31 #include <strings.h> 32 #include <errno.h> 33 34 #include "nisdb_mt.h" 35 36 #include "ldap_util.h" 37 #include "ldap_op.h" 38 #include "ldap_ruleval.h" 39 #include "ldap_attr.h" 40 #include "ldap_val.h" 41 #include "ldap_nisplus.h" 42 #include "ldap_ldap.h" 43 44 extern int yp2ldap; 45 46 47 __nis_mapping_format_t * 48 cloneMappingFormat(__nis_mapping_format_t *m) { 49 __nis_mapping_format_t *new; 50 int i, nf, err; 51 char *myself = "cloneMappingFormat"; 52 53 if (m == 0) 54 return (0); 55 56 for (nf = 0; m[nf].type != mmt_end; nf++); 57 nf++; 58 59 new = am(myself, nf * sizeof (new[0])); 60 if (new == 0) 61 return (0); 62 63 /* Copy the whole array */ 64 memcpy(new, m, nf * sizeof (new[0])); 65 66 /* Make copies of allocated stuff */ 67 for (i = 0, err = 0; i < nf; i++) { 68 switch (m[i].type) { 69 case mmt_string: 70 new[i].match.string = sdup(myself, T, 71 m[i].match.string); 72 if (new[i].match.string == 0 && m[i].match.string != 0) 73 err++; 74 break; 75 case mmt_single: 76 new[i].match.single.lo = 77 am(myself, m[i].match.single.numRange * 78 sizeof (new[i].match.single.lo[0])); 79 new[i].match.single.hi = 80 am(myself, m[i].match.single.numRange * 81 sizeof (new[i].match.single.hi[0])); 82 if (new[i].match.single.lo != 0) 83 memcpy(new[i].match.single.lo, 84 m[i].match.single.lo, 85 m[i].match.single.numRange); 86 else if (m[i].match.single.lo != 0) 87 err++; 88 if (new[i].match.single.hi != 0) 89 memcpy(new[i].match.single.hi, 90 m[i].match.single.hi, 91 m[i].match.single.numRange); 92 else if (m[i].match.single.hi != 0) 93 err++; 94 break; 95 case mmt_berstring: 96 new[i].match.berString = sdup(myself, T, 97 m[i].match.berString); 98 if (new[i].match.berString == 0 && 99 m[i].match.berString != 0) 100 err++; 101 break; 102 case mmt_item: 103 case mmt_limit: 104 case mmt_any: 105 case mmt_begin: 106 case mmt_end: 107 default: 108 break; 109 } 110 } 111 112 /* If there were memory allocation errors, free the copy */ 113 if (err > 0) { 114 freeMappingFormat(new); 115 new = 0; 116 } 117 118 return (new); 119 } 120 121 void 122 freeMappingFormat(__nis_mapping_format_t *m) { 123 int i; 124 125 if (m == 0) 126 return; 127 128 for (i = 0; m[i].type != mmt_end; i++) { 129 switch (m[i].type) { 130 case mmt_string: 131 sfree(m[i].match.string); 132 break; 133 case mmt_single: 134 sfree(m[i].match.single.lo); 135 sfree(m[i].match.single.hi); 136 break; 137 case mmt_berstring: 138 sfree(m[i].match.berString); 139 break; 140 case mmt_item: 141 case mmt_limit: 142 case mmt_any: 143 case mmt_begin: 144 case mmt_end: 145 default: 146 break; 147 } 148 } 149 150 free(m); 151 } 152 153 154 void 155 copyIndex(__nis_index_t *old, __nis_index_t *new, int *err) { 156 int i; 157 char *myself = "copyIndex"; 158 159 if (old == 0 || new == 0) { 160 *err = EINVAL; 161 return; 162 } 163 164 for (i = 0; i < old->numIndexes; i++) { 165 new->name[i] = sdup(myself, T, old->name[i]); 166 if (new->name[i] == 0 && old->name[i] != 0) { 167 *err = ENOMEM; 168 return; 169 } 170 new->value[i] = cloneMappingFormat(old->value[i]); 171 if (new->value[i] == 0 && old->value[i] != 0) { 172 *err = ENOMEM; 173 return; 174 } 175 } 176 177 new->numIndexes = old->numIndexes; 178 } 179 180 __nis_index_t * 181 cloneIndex(__nis_index_t *old) { 182 char *myself = "cloneIndex"; 183 int err = 0; 184 __nis_index_t *new = am(myself, sizeof (*new)); 185 186 if (old == 0) 187 return (0); 188 189 if (new != 0) { 190 copyIndex(old, new, &err); 191 if (err != 0) { 192 freeIndex(new, 1); 193 new = 0; 194 } 195 } 196 197 return (new); 198 } 199 200 void 201 freeIndex(__nis_index_t *old, bool_t doFree) { 202 int i; 203 204 if (old == 0) 205 return; 206 207 for (i = 0; i < old->numIndexes; i++) { 208 sfree(old->name[i]); 209 freeMappingFormat(old->value[i]); 210 } 211 212 if (doFree) 213 free(old); 214 } 215 216 char ** 217 cloneName(char **name, int numNames) { 218 char **new; 219 int i; 220 char *myself = "cloneName"; 221 222 if (name == 0 || numNames <= 0) 223 return (0); 224 225 new = am(myself, numNames * sizeof (new[0])); 226 if (new == 0) 227 return (0); 228 229 for (i = 0; i < numNames; i++) { 230 if (name[i] != 0) { 231 new[i] = sdup(myself, T, name[i]); 232 if (new[i] == 0) { 233 for (i--; i >= 0; i--) { 234 sfree(new[i]); 235 } 236 sfree(new); 237 return (0); 238 } 239 } else { 240 new[i] = 0; 241 } 242 } 243 244 return (new); 245 } 246 247 void 248 freeValue(__nis_value_t *val, int count) { 249 int c, i; 250 251 if (val == 0) 252 return; 253 254 for (c = 0; c < count; c++) { 255 if (val[c].val != 0) { 256 for (i = 0; i < val[c].numVals; i++) { 257 sfree(val[c].val[i].value); 258 } 259 free(val[c].val); 260 } 261 } 262 263 free(val); 264 } 265 266 __nis_value_t * 267 cloneValue(__nis_value_t *val, int count) { 268 __nis_value_t *n; 269 int c, i; 270 char *myself = "cloneValue"; 271 272 if (count <= 0 || val == 0) 273 return (0); 274 275 n = am(myself, count * sizeof (*n)); 276 if (n == 0) 277 return (0); 278 279 for (c = 0; c < count; c++) { 280 n[c].type = val[c].type; 281 n[c].repeat = val[c].repeat; 282 n[c].numVals = val[c].numVals; 283 if (n[c].numVals > 0) { 284 n[c].val = am(myself, n[c].numVals * 285 sizeof (n[c].val[0])); 286 if (n[c].val == 0) { 287 freeValue(n, c); 288 return (0); 289 } 290 } else { 291 n[c].val = 0; 292 } 293 for (i = 0; i < n[c].numVals; i++) { 294 int amlen = val[c].val[i].length; 295 296 /* 297 * The functions that create string values try to 298 * make sure that there's a NUL at the end. However, 299 * both NIS+ and LDAP have a tendency to store strings 300 * without a NUL, so the value length may not include 301 * the NUL (even though it's there). In order to 302 * preserve that NUL, we add a byte to the length if 303 * the type is vt_string, and there isn't already a 304 * NUL at the end. The memory allocation function 305 * (am()) will take care of actually putting the NUL 306 * in place, since it allocates zero-initialized 307 * memory. 308 */ 309 n[c].val[i].length = val[c].val[i].length; 310 if (n[c].type == vt_string && amlen > 0 && 311 ((char *)val[c].val[i].value)[amlen-1] != 312 '\0') { 313 amlen++; 314 } 315 n[c].val[i].value = am(myself, amlen); 316 if (amlen > 0 && n[c].val[i].value == 0) { 317 freeValue(n, c); 318 return (0); 319 } 320 memcpy(n[c].val[i].value, val[c].val[i].value, 321 n[c].val[i].length); 322 } 323 } 324 325 return (n); 326 } 327 328 /* Define LBER_USE_DER per ber_decode(3LDAP) */ 329 #ifndef LBER_USE_DER 330 #define LBER_USE_DER 0x01 331 #endif /* LBER_USE_DER */ 332 333 /* 334 * Return a copy of 'valIn' where each value has been replaced by the 335 * BER encoded equivalent specified by 'berstring'. 'valIn' is unchanged. 336 */ 337 __nis_value_t * 338 berEncode(__nis_value_t *valIn, char *berstring) { 339 char *myself = "berEncode"; 340 __nis_value_t *val; 341 int i; 342 343 if (valIn == 0 || berstring == 0) 344 return (0); 345 346 val = cloneValue(valIn, 1); 347 if (val == 0) 348 return (0); 349 350 for (i = 0; i < val->numVals; i++) { 351 BerElement *ber = ber_alloc(); 352 struct berval *bv = 0; 353 int ret; 354 355 if (ber == 0) { 356 logmsg(MSG_NOMEM, LOG_ERR, "%s: ber_alloc() => NULL", 357 myself); 358 freeValue(val, 1); 359 return (0); 360 } 361 362 if ((strcmp("b", berstring) == 0 || 363 strcmp("i", berstring) == 0)) { 364 if (val->val[i].length >= sizeof (int)) { 365 ret = ber_printf(ber, berstring, 366 *((int *)(val->val[i].value))); 367 } else { 368 ret = -1; 369 } 370 } else if (strcmp("B", berstring) == 0) { 371 ret = ber_printf(ber, berstring, 372 val->val[i].value, 373 val->val[i].length * 8); 374 } else if (strcmp("n", berstring) == 0) { 375 ret = ber_printf(ber, berstring); 376 } else if (strcmp("o", berstring) == 0) { 377 ret = ber_printf(ber, berstring, 378 val->val[i].value, val->val[i].length); 379 } else if (strcmp("s", berstring) == 0) { 380 char *str = am(myself, val->val[i].length + 1); 381 382 if (str != 0) { 383 ret = ber_printf(ber, berstring, str); 384 free(str); 385 } else { 386 ret = -1; 387 } 388 } else { 389 ret = -1; 390 } 391 392 if (ret == -1) { 393 reportError(NPL_BERENCODE, "%s: BER encoding error", 394 myself); 395 ber_free(ber, 1); 396 freeValue(val, 1); 397 return (0); 398 } 399 400 if (ber_flatten(ber, &bv) != 0 || bv == 0) { 401 reportError(NPL_BERENCODE, "%s: ber_flatten() error", 402 myself); 403 ber_free(ber, 1); 404 freeValue(val, 1); 405 return (0); 406 } 407 408 sfree(val->val[i].value); 409 val->val[i].length = bv->bv_len; 410 val->val[i].value = bv->bv_val; 411 412 ber_free(ber, 1); 413 } 414 415 val->type = vt_ber; 416 417 return (val); 418 } 419 420 __nis_value_t * 421 berDecode(__nis_value_t *valIn, char *berstring) { 422 __nis_value_t *val; 423 int i; 424 char *myself = "berDecode"; 425 426 if (valIn == 0 || berstring == 0) 427 return (0); 428 429 val = cloneValue(valIn, 1); 430 if (val == 0) 431 return (0); 432 433 for (i = 0; i < val->numVals; i++) { 434 void *v = 0; 435 int ret, len = 0; 436 struct berval bv; 437 BerElement *ber; 438 439 if (val->val[i].value == 0 || val->val[i].length <= 0) 440 continue; 441 442 bv.bv_val = val->val[i].value; 443 bv.bv_len = val->val[i].length; 444 ber = ber_init(&bv); 445 if (ber == 0) { 446 reportError(NPL_BERDECODE, "%s: ber_init() error", 447 myself); 448 freeValue(val, 1); 449 return (0); 450 } 451 452 if ((strcmp("b", berstring) == 0 || 453 strcmp("i", berstring) == 0)) { 454 len = sizeof (int); 455 v = am(myself, len); 456 if (v != 0) { 457 ret = ber_scanf(ber, berstring, v); 458 } else { 459 ret = -1; 460 } 461 } else if (strcmp("B", berstring) == 0) { 462 long llen; 463 464 ret = ber_scanf(ber, berstring, &v, &llen); 465 if (ret != -1) { 466 len = llen/8; 467 } 468 } else if (strcmp("n", berstring) == 0) { 469 ret = 0; 470 } else if (strcmp("o", berstring) == 0) { 471 struct berval *bv = am(myself, sizeof (*bv)); 472 473 if (bv != 0) { 474 ret = ber_scanf(ber, "O", &bv); 475 if (ret != -1 && bv != 0) { 476 v = bv->bv_val; 477 len = bv->bv_len; 478 } else { 479 ret = -1; 480 } 481 /* Only free 'bv' itself */ 482 free(bv); 483 } else { 484 ret = -1; 485 } 486 } else if (strcmp("s", berstring) == 0) { 487 ret = ber_scanf(ber, "a", &v); 488 if (ret != -1) { 489 len = slen(v); 490 } 491 } else { 492 ret = -1; 493 } 494 495 if (ret == -1) { 496 reportError(NPL_BERDECODE, "%s: BER decoding error", 497 myself); 498 freeValue(val, 1); 499 return (0); 500 } 501 502 /* Free the old value, and replace it with the decoded one */ 503 sfree(val->val[i].value); 504 val->val[i].value = v; 505 val->val[i].length = len; 506 } 507 508 return (val); 509 } 510 511 /* 512 * Return the value of the specified item. 513 */ 514 __nis_value_t * 515 getMappingItemVal(__nis_mapping_item_t *item, __nis_mapping_item_type_t native, 516 __nis_rule_value_t *rv, char *berstring, int *np_ldap_stat) { 517 __nis_value_t *val = 0, *nameVal, *exVal = 0; 518 int numName, caseInsens, cmp; 519 int i, j, k; 520 char **name; 521 enum {rvOnly, rvThenLookup, lookupOnly} check; 522 unsigned char fromldap = '\0'; 523 524 if (item == 0) 525 return (0); 526 527 /* 528 * First, we decide if we should look for the value in 'rv', 529 * directly from NIS+/LDAP, or both. 530 */ 531 switch (item->type) { 532 case mit_nisplus: 533 /* Do we have a valid index/object spec ? */ 534 if (item->searchSpec.obj.index.numIndexes <= 0 && 535 item->searchSpec.obj.name == 0) { 536 /* 537 * No valid index/object. If we have a rule-value, 538 * use it. Otherwise, return error. 539 */ 540 if (rv != 0) { 541 name = rv->colName; 542 nameVal = rv->colVal; 543 numName = rv->numColumns; 544 caseInsens = 0; 545 check = rvOnly; 546 } else { 547 return (0); 548 } 549 } else { 550 /* 551 * Valid index, so skip the rule-value and do 552 * a direct NIS+ lookup. 553 */ 554 check = lookupOnly; 555 } 556 break; 557 case mit_ldap: 558 if (rv != 0) { 559 name = rv->attrName; 560 nameVal = rv->attrVal; 561 numName = rv->numAttrs; 562 caseInsens = 1; 563 fromldap = '1'; 564 } 565 /* Do we have a valid triple ? */ 566 if (item->searchSpec.triple.scope == LDAP_SCOPE_UNKNOWN) { 567 /* 568 * No valid triple. If we have a rule-value, use it. 569 * Otherwise, return error. 570 */ 571 if (rv != 0) { 572 check = rvOnly; 573 } else { 574 return (0); 575 } 576 } else if (item->searchSpec.triple.base == 0 && 577 item->searchSpec.triple.scope == 578 LDAP_SCOPE_ONELEVEL && 579 item->searchSpec.triple.attrs == 0 && 580 item->searchSpec.triple.element == 0) { 581 /* 582 * We have a valid triple, but it points to the 583 * current LDAP container. Thus, first look in 584 * the rule-value; if that fails, perform a direct 585 * LDAP lookup. 586 */ 587 if (rv != 0) { 588 check = rvThenLookup; 589 } else { 590 check = lookupOnly; 591 } 592 } else { 593 /* 594 * Valid triple, and it's not the current container 595 * (at least not in the trivial sense). Hence, do 596 * a direct LDAP lookup. 597 */ 598 check = lookupOnly; 599 } 600 break; 601 default: 602 return (0); 603 } 604 605 /* Check the rule-value */ 606 if (check == rvOnly || check == rvThenLookup) { 607 for (i = 0; i < numName; i++) { 608 if (caseInsens) 609 cmp = strcasecmp(item->name, name[i]); 610 else 611 cmp = strcmp(item->name, name[i]); 612 if (cmp == 0) { 613 if (nameVal[i].numVals <= 0) 614 break; 615 if (berstring == 0) { 616 val = cloneValue(&nameVal[i], 1); 617 } else if (yp2ldap && berstring[0] == 'a') { 618 val = cloneValue(&nameVal[i], 1); 619 } else { 620 val = berDecode(&nameVal[i], 621 berstring); 622 } 623 if (val != 0) { 624 val->repeat = item->repeat; 625 /* 626 * If value for nis+ column is 627 * passed with value, val is 628 * manipulated in cloneValue(). 629 * To decide whether there are 630 * enough nis+ column values 631 * for rule to produce a value, 632 * we need nis+ column values 633 * as well as nis_mapping_element 634 * from the rule. If we are here, 635 * it indicates that the 'val has 636 * an valid value for the column 637 * item-> name. So set 638 * NP_LDAP_MAP_SUCCESS 639 * to np_ldap-stat. 640 */ 641 642 if (np_ldap_stat != NULL) 643 *np_ldap_stat = 644 NP_LDAP_MAP_SUCCESS; 645 } 646 break; 647 } 648 } 649 } 650 651 /* Do a direct lookup ? */ 652 if (val == 0 && (check == rvThenLookup || check == lookupOnly)) { 653 if (item->type == mit_nisplus) { 654 val = lookupNisPlus(&item->searchSpec.obj, item->name, 655 rv); 656 } else if (item->type == mit_ldap) { 657 int err = 0; 658 __nis_search_triple_t triple; 659 char *baseDN; 660 661 /* 662 * If item->searchSpec.triple.base is NULL, or ends 663 * in a comma, append the current search base from 664 * the TSD (put there by an upper layer). 665 * 666 * Special case for N2L mode: 667 * if item->searchSpec.triple.base ends in a comma, 668 * the current domain Context is used. 669 */ 670 if (yp2ldap && item->searchSpec.triple.base && 671 strlen(item->searchSpec.triple.base) > 0) { 672 baseDN = __nisdb_get_tsd()->domainContext; 673 } else { 674 baseDN = __nisdb_get_tsd()->searchBase; 675 } 676 triple.base = appendBase(item->searchSpec.triple.base, 677 baseDN, &err, 0); 678 if (err == 0) { 679 triple.scope = item->searchSpec.triple.scope; 680 triple.attrs = item->searchSpec.triple.attrs; 681 triple.element = 682 item->searchSpec.triple.element; 683 val = lookupLDAP(&triple, item->name, rv, 0, 684 np_ldap_stat); 685 fromldap = '1'; 686 } else { 687 val = 0; 688 } 689 sfree(triple.base); 690 } 691 } 692 693 694 /* Special processing for NIS to LDAP mode */ 695 if (yp2ldap && val != 0) { 696 697 /* 698 * Escape special chars from dn before sending to DIT, 699 * provided val is not ldap-based 700 */ 701 if (fromldap == '\0' && __nisdb_get_tsd()->escapeFlag == '1') { 702 if (escapeSpecialChars(val) < 0) { 703 freeValue(val, 1); 704 return (0); 705 } 706 } else if (__nisdb_get_tsd()->escapeFlag == '2') { 707 /* Remove escape chars from data received from DIT */ 708 (void) removeEscapeChars(val); 709 } 710 711 /* 712 * Remove from 'val', any values obtained using 713 * the 'removespec' syntax 714 */ 715 716 /* Obtain exVal */ 717 if (item->exItem) 718 exVal = getMappingItemVal(item->exItem, native, rv, 719 berstring, NULL); 720 721 /* delete */ 722 if (exVal != 0) { 723 for (i = 0; i < val->numVals; ) { 724 for (j = 0; j < exVal->numVals; j++) { 725 if (sstrncmp(val->val[i].value, 726 exVal->val[j].value, 727 MAX(val->val[i].length, 728 exVal->val[j].length)) 729 == 0) 730 break; 731 } 732 if (j < exVal->numVals) { 733 sfree(val->val[i].value); 734 val->val[i].value = 0; 735 val->val[i].length = 0; 736 for (k = i; k < val->numVals - 1; k++) { 737 val->val[k] = val->val[k + 1]; 738 val->val[k + 1].value = 0; 739 val->val[k + 1].length = 0; 740 } 741 val->numVals--; 742 } else 743 i++; 744 } 745 746 freeValue(exVal, 1); 747 748 /* 749 * If val->numVals <= 0, then we have no val to 750 * return. So free up stuff. 751 */ 752 if (val->numVals <= 0) { 753 free(val->val); 754 val->val = 0; 755 free(val); 756 return (0); 757 } 758 } 759 } 760 761 return (val); 762 } 763 764 __nis_value_t * 765 getMappingFormat(__nis_mapping_format_t *f, __nis_rule_value_t *rv, 766 __nis_format_arg_t at, void *a, int *numArg) { 767 char *myself = "getMappingFormat"; 768 __nis_value_t *val = 0; 769 __nis_buffer_t b = {0, 0}; 770 int i; 771 772 if (f == 0) 773 return (0); 774 775 if (rv == 0) { 776 val = am(myself, sizeof (*val)); 777 if (val == 0) 778 return (0); 779 780 switch (f->type) { 781 case mmt_item: 782 bp2buf(myself, &b, "%%s"); 783 break; 784 case mmt_string: 785 bp2buf(myself, &b, "%s", NIL(f->match.string)); 786 break; 787 case mmt_single: 788 bp2buf(myself, &b, "["); 789 for (i = 0; i < f->match.single.numRange; i++) { 790 if (f->match.single.lo[i] == 791 f->match.single.hi[i]) 792 bp2buf(myself, &b, "%c", 793 f->match.single.lo[i]); 794 else 795 bp2buf(myself, &b, "%c-%c", 796 f->match.single.lo[i], 797 f->match.single.hi[i]); 798 } 799 bp2buf(myself, &b, "]"); 800 break; 801 case mmt_limit: 802 break; 803 case mmt_any: 804 bp2buf(myself, &b, "*"); 805 break; 806 case mmt_berstring: 807 bp2buf(myself, &b, "%s", NIL(f->match.berString)); 808 break; 809 case mmt_begin: 810 case mmt_end: 811 bp2buf(myself, &b, "\""); 812 break; 813 default: 814 bp2buf(myself, &b, "<unknown>"); 815 } 816 val->type = vt_string; 817 val->numVals = 1; 818 val->val = am(myself, sizeof (val->val[0])); 819 if (val->val == 0) { 820 sfree(val); 821 return (0); 822 } 823 val->val[0].value = b.buf; 824 val->val[0].length = b.len; 825 } else { 826 switch (f->type) { 827 case mmt_item: 828 case mmt_berstring: 829 if (a != 0) { 830 if (at == fa_item) { 831 val = getMappingItemVal( 832 (__nis_mapping_item_t *)a, 833 mit_any, rv, 834 (f->type == mmt_berstring) ? f->match.berString : 0, NULL); 835 if (numArg != 0) 836 (*numArg)++; 837 } else { 838 val = cloneValue( 839 (__nis_value_t *)a, 1); 840 if (numArg != 0) 841 (*numArg)++; 842 } 843 } 844 break; 845 case mmt_string: 846 val = am(myself, sizeof (*val)); 847 if (val == 0) 848 return (0); 849 val->type = vt_string; 850 val->numVals = 1; 851 val->val = am(myself, sizeof (val->val[0])); 852 if (val->val == 0) { 853 sfree(val); 854 return (0); 855 } 856 val->val[0].value = sdup(myself, T, f->match.string); 857 val->val[0].length = strlen(val->val[0].value); 858 break; 859 case mmt_single: 860 case mmt_limit: 861 case mmt_any: 862 case mmt_begin: 863 case mmt_end: 864 /* Not an error, so return an empty value */ 865 val = am(myself, sizeof (*val)); 866 if (val == 0) 867 return (0); 868 val->type = vt_string; 869 val->numVals = 0; 870 val->val = 0; 871 break; 872 default: 873 /* Do nothing */ 874 val = 0; 875 break; 876 } 877 } 878 return (val); 879 } 880 881 /* 882 * Used when evaluating an expression. Typically, the value of the 883 * expression so far will be kept in 'v1', and 'v2' is the value 884 * of the current component of the expression. In the general case, 885 * both will be multi-valued, and the result is an "explosion" 886 * resulting in N*M new values (if 'v1' had N values, and 'v2' 887 * M ditto). 888 * 889 * For example, if v1 = {"ab", "cd", "ef"}, and v2 = {"gh", "ij", "kl"}, 890 * the result will be {"abgh", "abij", "abkl", "cdgh", "cdij", "cdkl", 891 * "efgh", "efij", "efkl"}. 892 * 893 * There are special cases when v1->repeat and/or v2->repeat are set. 894 * Repeat mostly makes sense with single values; for example, if 895 * v1 = {"x="} with repeat on, and v2 = {"1", "2", "3"}, the result 896 * is {"x=1", "x=2", "x=3"}. 897 * 898 * The result if v2 also had repeat on would be {"x=1x=2x=3"}. It's 899 * not clear if there's a useful application for this, but the code's 900 * there for the sake of orthogonality. 901 */ 902 __nis_value_t * 903 explodeValues(__nis_value_t *v1, __nis_value_t *v2) { 904 int i1, i2, n, nv; 905 __nis_value_t *v; 906 __nis_buffer_t b = {0, 0}; 907 char *myself = "explodeValues"; 908 909 if (v1 == 0 || v1->numVals <= 0) 910 return (cloneValue(v2, 1)); 911 if (v2 == 0 || v2->numVals <= 0) 912 return (cloneValue(v1, 1)); 913 914 /* 915 * XXX What should we do if (v1->type != v2->type) ? 916 * Policy: Just explode anyway, even though the result is 917 * unlikely to be very useful. 918 */ 919 920 v = am(myself, sizeof (*v)); 921 if (v == 0) 922 return (0); 923 924 if (!v1->repeat && !v2->repeat) 925 nv = v1->numVals * v2->numVals; 926 else if (v1->repeat && !v2->repeat) 927 nv = v2->numVals; 928 else if (!v1->repeat && v2->repeat) 929 nv = v1->numVals; 930 else /* v1->repeat && v2->repeat */ 931 nv = 1; 932 933 v->val = am(myself, nv * sizeof (v->val[0])); 934 if (v->val == 0) { 935 free(v); 936 return (0); 937 } 938 939 /* 940 * Four different cases, depending on the 'repeat' flags. 941 */ 942 if (!v1->repeat && !v2->repeat) { 943 for (i1 = 0, n = 0; i1 < v1->numVals; i1++) { 944 for (i2 = 0; i2 < v2->numVals; i2++) { 945 if (v1->type == vt_string) 946 sbc2buf(myself, v1->val[i1].value, 947 v1->val[i1].length, 948 &b); 949 else 950 bc2buf(myself, v1->val[i1].value, 951 v1->val[i1].length, 952 &b); 953 if (v2->type == vt_string) 954 sbc2buf(myself, v2->val[i2].value, 955 v2->val[i2].length, 956 &b); 957 else 958 bc2buf(myself, v2->val[i2].value, 959 v2->val[i2].length, 960 &b); 961 v->val[n].value = b.buf; 962 v->val[n].length = b.len; 963 n++; 964 b.buf = 0; 965 b.len = 0; 966 } 967 } 968 } else if (v1->repeat && !v2->repeat) { 969 for (i2 = 0; i2 < v2->numVals; i2++) { 970 for (i1 = 0, n = 0; i1 < v1->numVals; i1++) { 971 if (v1->type == vt_string) 972 sbc2buf(myself, v1->val[i1].value, 973 v1->val[i1].length, 974 &b); 975 else 976 bc2buf(myself, v1->val[i1].value, 977 v1->val[i1].length, 978 &b); 979 if (v2->type == vt_string) 980 sbc2buf(myself, v2->val[i2].value, 981 v2->val[i2].length, 982 &b); 983 else 984 bc2buf(myself, v2->val[i2].value, 985 v2->val[i2].length, 986 &b); 987 } 988 v->val[n].value = b.buf; 989 v->val[n].length = b.len; 990 n++; 991 b.buf = 0; 992 b.len = 0; 993 } 994 } else if (!v1->repeat && v2->repeat) { 995 for (i1 = 0, n = 0; i1 < v1->numVals; i1++) { 996 for (i2 = 0; i2 < v2->numVals; i2++) { 997 if (v1->type == vt_string) 998 sbc2buf(myself, v1->val[i1].value, 999 v1->val[i1].length, 1000 &b); 1001 else 1002 bc2buf(myself, v1->val[i1].value, 1003 v1->val[i1].length, 1004 &b); 1005 if (v2->type == vt_string) 1006 sbc2buf(myself, v2->val[i2].value, 1007 v2->val[i2].length, 1008 &b); 1009 else 1010 bc2buf(myself, v2->val[i2].value, 1011 v2->val[i2].length, 1012 &b); 1013 } 1014 v->val[n].value = b.buf; 1015 v->val[n].length = b.len; 1016 n++; 1017 b.buf = 0; 1018 b.len = 0; 1019 } 1020 } else { /* v1->repeat && v2->repeat */ 1021 for (i1 = 0, n = 0; i1 < v1->numVals; i1++) { 1022 for (i2 = 0; i2 < v2->numVals; i2++) { 1023 if (v1->type == vt_string) 1024 sbc2buf(myself, v1->val[i1].value, 1025 v1->val[i1].length, 1026 &b); 1027 else 1028 bc2buf(myself, v1->val[i1].value, 1029 v1->val[i1].length, 1030 &b); 1031 if (v2->type == vt_string) 1032 sbc2buf(myself, v2->val[i2].value, 1033 v2->val[i2].length, 1034 &b); 1035 else 1036 bc2buf(myself, v2->val[i2].value, 1037 v2->val[i2].length, 1038 &b); 1039 } 1040 } 1041 v->val[n].value = b.buf; 1042 v->val[n].length = b.len; 1043 n++; 1044 b.buf = 0; 1045 b.len = 0; 1046 } 1047 1048 #ifdef NISDB_LDAP_DEBUG 1049 /* Sanity check */ 1050 if (n != nv) 1051 abort(); 1052 #endif /* NISD__LDAP_DEBUG */ 1053 1054 v->type = (v1->type == vt_string) ? 1055 ((v2->type == vt_string) ? 1056 vt_string : vt_ber) : vt_ber; 1057 v->repeat = 0; 1058 v->numVals = n; 1059 1060 return (v); 1061 } 1062 1063 __nis_value_t * 1064 getMappingFormatArray(__nis_mapping_format_t *a, __nis_rule_value_t *rv, 1065 __nis_format_arg_t at, int numArgs, void *arg) { 1066 int i, ia = 0; 1067 __nis_value_t *val, *v = 0; 1068 bool_t moreFormat = (a != 0); 1069 bool_t moreArgs = (numArgs > 0); 1070 1071 while (moreFormat && (arg == 0 || ia < numArgs)) { 1072 for (i = 0; moreFormat; i++) { 1073 moreFormat = (a[i].type != mmt_end); 1074 if (at == fa_item) { 1075 __nis_mapping_item_t *item = arg; 1076 val = getMappingFormat(&a[i], rv, at, 1077 ((item != 0) ? &item[ia] : 0), &ia); 1078 } else { 1079 __nis_value_t **ival = arg; 1080 val = getMappingFormat(&a[i], rv, at, 1081 ((ival != 0) ? ival[ia] : 0), &ia); 1082 } 1083 if (val != 0) { 1084 __nis_value_t *new = explodeValues(v, val); 1085 1086 freeValue(v, 1); 1087 freeValue(val, 1); 1088 if (new == 0) 1089 return (0); 1090 1091 v = new; 1092 } else { 1093 freeValue(v, 1); 1094 return (0); 1095 } 1096 /* 1097 * If we run out of arguments, but still have format 1098 * remaining, repeat the last argument. Keep track of 1099 * the fact that we've really consumed all arguments. 1100 */ 1101 if (moreFormat && ia >= numArgs) { 1102 ia = (numArgs > 0) ? numArgs - 1 : 0; 1103 moreArgs = FALSE; 1104 } 1105 } 1106 /* 1107 * We've run out of format, so if we still have arguments 1108 * left, start over on the format. 1109 */ 1110 if (ia < numArgs && moreArgs) { 1111 /* 1112 * However, if we didn't consume any arguments going 1113 * through the format once, abort to avoid an infinite 1114 * loop. 1115 */ 1116 if (numArgs > 0 && ia <= 0) { 1117 freeValue(v, 1); 1118 return (0); 1119 } 1120 moreFormat = 1; 1121 } 1122 } 1123 1124 return (v); 1125 } 1126 1127 /* 1128 * Returns a string representation (such as "[name=foo, value=bar]") 1129 * of a nis_index_t. 1130 */ 1131 char * 1132 getIndex(__nis_index_t *i, int *len) { 1133 int n; 1134 __nis_buffer_t b = {0, 0}; 1135 char *myself = "getIndex"; 1136 1137 if (i == 0) 1138 return (0); 1139 1140 if (i->numIndexes > 0) { 1141 bp2buf(myself, &b, "["); 1142 for (n = 0; n < i->numIndexes; n++) { 1143 __nis_value_t *val; 1144 int j; 1145 1146 val = getMappingFormatArray(i->value[n], 1147 0, fa_any, 0, 0); 1148 if (n > 0) 1149 bp2buf(myself, &b, ", "); 1150 bp2buf(myself, &b, "%s=", i->name[n]); 1151 if (val != 0) { 1152 for (j = 0; j < val->numVals; j++) { 1153 bc2buf(myself, val->val[j].value, 1154 val->val[j].length, &b); 1155 } 1156 } else { 1157 bp2buf(myself, &b, "<no-vals>"); 1158 } 1159 freeValue(val, 1); 1160 } 1161 bp2buf(myself, &b, "]"); 1162 } 1163 if (len != 0) 1164 *len = b.len; 1165 return (b.buf); 1166 } 1167 1168 char * 1169 getObjSpec(__nis_obj_spec_t *o, int *len) { 1170 __nis_buffer_t b = {0, 0}; 1171 char *myself = "getObjSpec"; 1172 1173 if (o == 0) 1174 return (0); 1175 1176 b.buf = getIndex(&o->index, &b.len); 1177 sbc2buf(myself, o->name, slen(o->name), &b); 1178 if (len != 0) 1179 *len = b.len; 1180 return (b.buf); 1181 } 1182 1183 /* 1184 * Returns a string representation of the LDAP scope. Note that the 1185 * returned value is a static entity, and must be copied by the 1186 * caller (but, obviously, must not be freed). 1187 */ 1188 char * 1189 getScope(int scope) { 1190 switch (scope) { 1191 case LDAP_SCOPE_BASE: 1192 return ("base"); 1193 case LDAP_SCOPE_ONELEVEL: 1194 return ("one"); 1195 case LDAP_SCOPE_SUBTREE: 1196 return ("sub"); 1197 default: 1198 return ("one"); 1199 } 1200 } 1201 1202 /* 1203 * Return a string representation of an LDAP search triple (such as 1204 * "ou=Hosts,dc=eng,dc=sun,dc=com?one?cn=xyzzy"). 1205 */ 1206 char * 1207 getSearchTriple(__nis_search_triple_t *s, int *len) { 1208 __nis_buffer_t b = {0, 0}; 1209 char *a; 1210 int l; 1211 char *myself = "getSearchTriple"; 1212 1213 /* If the scope is LDAP_SCOPE_UNKNOWN, the search triple is unused */ 1214 if (s == 0 || s->scope == LDAP_SCOPE_UNKNOWN) { 1215 if (len != 0) 1216 *len = 0; 1217 return (0); 1218 } 1219 1220 if (s->base != 0) 1221 sbc2buf(myself, s->base, slen(s->base), &b); 1222 if (!(s->scope == LDAP_SCOPE_ONELEVEL && 1223 (s->base == 0 || s->base[0] == '\0'))) { 1224 bp2buf(myself, &b, "?%s?", getScope(s->scope)); 1225 } 1226 if ((l = slen(s->attrs)) > 0) { 1227 /* 1228 * Remove white space from the filter/attribute list. 1229 * The parser usually keeps any white space from the 1230 * config file (or LDAP/command line), but we don't 1231 * want it. 1232 */ 1233 a = am(myself, l+1); 1234 if (a != 0) { 1235 int i, la; 1236 1237 for (i = 0, la = 0; i < l; i++) { 1238 if (s->attrs[i] != ' ' && 1239 s->attrs[i] != '\t') 1240 a[la++] = s->attrs[i]; 1241 } 1242 sbc2buf(myself, a, la, &b); 1243 sfree(a); 1244 } else { 1245 sbc2buf(myself, s->attrs, slen(s->attrs), &b); 1246 } 1247 } 1248 1249 if (len != 0) 1250 *len = b.len; 1251 return (b.buf); 1252 } 1253 1254 __nis_value_t * 1255 getMappingItem(__nis_mapping_item_t *i, __nis_mapping_item_type_t native, 1256 __nis_rule_value_t *rv, char *berstring, int *np_ldap_stat) { 1257 char *myself = "getMappingItem"; 1258 __nis_value_t *val = 0; 1259 __nis_buffer_t b = {0, 0}; 1260 int len = 0; 1261 char *buf; 1262 1263 if (i == 0) 1264 return (0); 1265 1266 if (rv != 0) 1267 return (getMappingItemVal(i, native, rv, berstring, 1268 np_ldap_stat)); 1269 1270 val = am(myself, sizeof (*val)); 1271 if (val == 0) 1272 return (0); 1273 1274 switch (i->type) { 1275 case mit_nisplus: 1276 if (native != mit_nisplus) 1277 bp2buf(myself, &b, "nis+:"); 1278 bp2buf(myself, &b, "%s", NIL(i->name)); 1279 buf = getObjSpec(&i->searchSpec.obj, &len); 1280 if (buf != 0 && len > 0) { 1281 bc2buf(myself, ":", 1, &b); 1282 sbc2buf(myself, buf, len, &b); 1283 } 1284 sfree(buf); 1285 val->type = vt_string; 1286 val->repeat = i->repeat; 1287 val->numVals = 1; 1288 val->val = am(myself, sizeof (val->val[0])); 1289 if (val->val == 0) { 1290 sfree(b.buf); 1291 free(val); 1292 return (0); 1293 } 1294 val->val[0].value = b.buf; 1295 val->val[0].length = b.len; 1296 break; 1297 case mit_ldap: 1298 if (native != mit_ldap) 1299 bp2buf(myself, &b, "ldap:"); 1300 bp2buf(myself, &b, "%s", NIL(i->name)); 1301 buf = getSearchTriple(&i->searchSpec.triple, &len); 1302 if (buf != 0 && len > 0) { 1303 bc2buf(myself, ":", 1, &b); 1304 sbc2buf(myself, buf, len, &b); 1305 } 1306 sfree(buf); 1307 val->type = vt_string; 1308 val->repeat = i->repeat; 1309 val->numVals = 1; 1310 val->val = am(myself, sizeof (val->val[0])); 1311 if (val->val == 0) { 1312 sfree(b.buf); 1313 free(val); 1314 return (0); 1315 } 1316 val->val[0].value = b.buf; 1317 val->val[0].length = b.len; 1318 break; 1319 default: 1320 p2buf(myself, "<unknown>:"); 1321 p2buf(myself, "%s", NIL(i->name)); 1322 break; 1323 } 1324 1325 return (val); 1326 } 1327 1328 void 1329 copyObjSpec(__nis_obj_spec_t *old, __nis_obj_spec_t *new, int *err) { 1330 char *myself = "copyObjSpec"; 1331 1332 if (old == 0 || new == 0) { 1333 *err = EINVAL; 1334 return; 1335 } 1336 1337 if (new->index.name == 0) { 1338 new->index.name = am(myself, old->index.numIndexes * 1339 sizeof (new->index.name[0])); 1340 if (old->index.numIndexes > 0 && new->index.name == 0) { 1341 *err = ENOMEM; 1342 return; 1343 } 1344 new->index.value = am(myself, old->index.numIndexes * 1345 sizeof (new->index.value[0])); 1346 if (old->index.numIndexes > 0 && new->index.value == 0) { 1347 *err = ENOMEM; 1348 return; 1349 } 1350 } 1351 new->name = sdup(myself, T, old->name); 1352 if (new->name == 0 && old->name != 0) { 1353 *err = ENOMEM; 1354 return; 1355 } 1356 copyIndex(&old->index, &new->index, err); 1357 } 1358 1359 __nis_obj_spec_t * 1360 cloneObjSpec(__nis_obj_spec_t *old) { 1361 char *myself = "cloneObjSpec"; 1362 int err = 0; 1363 __nis_obj_spec_t *new = am(myself, sizeof (*new)); 1364 1365 if (new != 0) { 1366 copyObjSpec(old, new, &err); 1367 if (err != 0) { 1368 freeObjSpec(new, 1); 1369 new = 0; 1370 } 1371 } 1372 1373 return (new); 1374 } 1375 1376 void 1377 freeObjSpec(__nis_obj_spec_t *old, bool_t doFree) { 1378 1379 if (old == 0) 1380 return; 1381 1382 sfree(old->name); 1383 freeIndex(&old->index, FALSE); 1384 if (doFree) 1385 free(old); 1386 } 1387 1388 void 1389 copySearchTriple(__nis_search_triple_t *old, __nis_search_triple_t *new, 1390 int *err) { 1391 char *myself = "copySearchTriple"; 1392 1393 *err = 0; 1394 1395 if (old == 0 || new == 0) { 1396 *err = EINVAL; 1397 return; 1398 } 1399 1400 if (old->base != NULL) 1401 new->base = sdup(myself, T, old->base); 1402 else 1403 new->base = NULL; 1404 if (old->attrs != NULL) 1405 new->attrs = sdup(myself, T, old->attrs); 1406 else 1407 new->attrs = NULL; 1408 if ((new->base == 0 && old->base != 0) || 1409 (new->attrs == 0 && old->attrs != 0)) { 1410 sfree(new->base); 1411 new->base = 0; 1412 sfree(new->attrs); 1413 new->attrs = 0; 1414 *err = ENOMEM; 1415 return; 1416 } 1417 new->scope = old->scope; 1418 /* 1419 * XXX Really should have a cloneMappingElement() function. 1420 * However, since whatever the 'element' field points to 1421 * is allocated at parse time, and never is freed or modified, 1422 * it's sufficient to copy the pointer value. 1423 */ 1424 new->element = old->element; 1425 } 1426 1427 __nis_search_triple_t * 1428 cloneSearchTriple(__nis_search_triple_t *old) { 1429 char *myself = "cloneSearchTriple"; 1430 int err = 0; 1431 __nis_search_triple_t *new = am(myself, sizeof (*new)); 1432 1433 if (new != 0) { 1434 copySearchTriple(old, new, &err); 1435 if (err != 0) { 1436 freeSearchTriple(new, 1); 1437 new = 0; 1438 } 1439 } 1440 1441 return (new); 1442 } 1443 1444 void 1445 freeSearchTriple(__nis_search_triple_t *old, bool_t doFree) { 1446 1447 if (old == 0) 1448 return; 1449 1450 sfree(old->base); 1451 sfree(old->attrs); 1452 /* 1453 * Since we only copied the element pointer when this structure 1454 * was created, we don't free old->element. 1455 */ 1456 if (doFree) 1457 free(old); 1458 } 1459 1460 void 1461 copyTripleOrObj(__nis_mapping_item_type_t type, 1462 __nis_triple_or_obj_t *old, __nis_triple_or_obj_t *new, 1463 int *err) { 1464 1465 *err = 0; 1466 1467 if (old == 0 || new == 0) { 1468 *err = EINVAL; 1469 return; 1470 } 1471 1472 if (type == mit_nisplus) { 1473 copyObjSpec(&old->obj, &new->obj, err); 1474 } else if (type == mit_ldap) { 1475 copySearchTriple(&old->triple, &new->triple, err); 1476 } 1477 } 1478 1479 __nis_triple_or_obj_t * 1480 cloneTripleOrObj(__nis_mapping_item_type_t type, __nis_triple_or_obj_t *old) { 1481 char *myself = "cloneTripleOrObj"; 1482 int err = 0; 1483 __nis_triple_or_obj_t *new = am(myself, sizeof (*new)); 1484 1485 if (new != 0) { 1486 copyTripleOrObj(type, old, new, &err); 1487 if (err != 0) { 1488 freeTripleOrObj(type, new, 1); 1489 new = 0; 1490 } 1491 } 1492 1493 return (new); 1494 } 1495 1496 void 1497 freeTripleOrObj(__nis_mapping_item_type_t type, __nis_triple_or_obj_t *old, 1498 bool_t doFree) { 1499 1500 if (old == 0) 1501 return; 1502 1503 if (type == mit_nisplus) 1504 freeObjSpec(&old->obj, doFree); 1505 else if (type == mit_ldap) 1506 freeSearchTriple(&old->triple, doFree); 1507 1508 if (doFree) 1509 free(old); 1510 } 1511 1512 void 1513 copyItem(__nis_mapping_item_t *old, __nis_mapping_item_t *new, int *err) { 1514 1515 *err = 0; 1516 1517 if (old == 0 || new == 0) { 1518 *err = EINVAL; 1519 return; 1520 } 1521 1522 new->type = old->type; 1523 new->repeat = old->repeat; 1524 if (old->name != 0) { 1525 new->name = strdup(old->name); 1526 if (new->name == 0) { 1527 *err = ENOMEM; 1528 return; 1529 } 1530 } else { 1531 new->name = 0; 1532 } 1533 if (old->type == mit_nisplus || old->type == mit_ldap) 1534 copyTripleOrObj(old->type, &old->searchSpec, &new->searchSpec, 1535 err); 1536 else 1537 memset(&new->searchSpec, 0, sizeof (new->searchSpec)); 1538 } 1539 1540 __nis_mapping_item_t * 1541 cloneItem(__nis_mapping_item_t *old) { 1542 __nis_mapping_item_t *new; 1543 int err = 0; 1544 char *myself = "cloneItem"; 1545 1546 if (old == 0) 1547 return (0); 1548 1549 new = am(myself, sizeof (*new)); 1550 if (new == 0) 1551 return (0); 1552 1553 copyItem(old, new, &err); 1554 if (err != 0) { 1555 freeMappingItem(new, 1); 1556 return (0); 1557 } 1558 1559 return (new); 1560 } 1561 1562 void 1563 freeMappingItem(__nis_mapping_item_t *item, int numItems) { 1564 int i; 1565 1566 if (item == 0) 1567 return; 1568 1569 for (i = 0; i < numItems; i++) { 1570 sfree(item[i].name); 1571 freeTripleOrObj(item[i].type, &item[i].searchSpec, FALSE); 1572 } 1573 sfree(item); 1574 } 1575 1576 __nis_mapping_item_t * 1577 concatenateMappingItem(__nis_mapping_item_t *old, int numItems, 1578 __nis_mapping_item_t *cat) { 1579 __nis_mapping_item_t *new; 1580 int i, err = 0; 1581 char *myself = "concatenateMappingItem"; 1582 1583 if (old == 0 || numItems < 1) 1584 return (cloneItem(cat)); 1585 1586 new = am(myself, (numItems + 1) * sizeof (*new)); 1587 if (new == 0) 1588 return (0); 1589 1590 for (i = 0; i < numItems; i++) { 1591 copyItem(&old[i], &new[i], &err); 1592 if (err != 0) { 1593 freeMappingItem(new, i); 1594 return (0); 1595 } 1596 } 1597 copyItem(cat, &new[numItems], &err); 1598 if (err != 0) { 1599 freeMappingItem(new, numItems); 1600 new = 0; 1601 } 1602 1603 return (new); 1604 } 1605 1606 __nis_value_t * 1607 concatenateValues(__nis_value_t *v1, __nis_value_t *v2) { 1608 int i, n, a; 1609 __nis_value_t *v; 1610 char *myself = "concatenateValues"; 1611 1612 if (v1 == 0 || v1->numVals <= 0) 1613 return (cloneValue(v2, 1)); 1614 if (v2 == 0 || v2->numVals <= 0) 1615 return (cloneValue(v1, 1)); 1616 1617 if (v1->type != v2->type) 1618 return (0); 1619 1620 n = v1->numVals + v2->numVals; 1621 v = am(myself, sizeof (*v)); 1622 if (v == 0) 1623 return (0); 1624 v->val = am(myself, n * sizeof (v->val[0])); 1625 if (v->val == 0) { 1626 free(v); 1627 return (0); 1628 } 1629 v->type = v1->type; 1630 v->numVals = 0; 1631 1632 for (a = 0; a < 2; a++) { 1633 __nis_single_value_t *val = (a == 0) ? v1->val : v2->val; 1634 int numv = (a == 0) ? v1->numVals : 1635 v2->numVals; 1636 for (i = 0; i < numv; i++) { 1637 int clen, alen = val[i].length; 1638 1639 clen = alen; 1640 1641 /* 1642 * Make sure there's a NUL at the end of a string, 1643 * but avoid adding to the allocated length if there's 1644 * already a NUL at the end. 1645 */ 1646 if (alen > 0 && v->type == vt_string && 1647 ((char *)val[i].value)[alen-1] != '\0') 1648 alen += 1; 1649 v->val[v->numVals].value = am(myself, alen); 1650 if (v->val[v->numVals].value == 0) { 1651 freeValue(v, 1); 1652 return (0); 1653 } 1654 memcpy(v->val[v->numVals].value, val[i].value, clen); 1655 v->val[v->numVals].length = val[i].length; 1656 v->numVals++; 1657 } 1658 } 1659 1660 return (v); 1661 } 1662 1663 __nis_value_t * 1664 splitMappingItem(__nis_mapping_item_t *item, char delim, 1665 __nis_rule_value_t *rv) { 1666 __nis_value_t *val = getMappingItem(item, mit_any, 1667 rv, 0, NULL); 1668 __nis_single_value_t *nval; 1669 int i, n, nv; 1670 1671 if (val == 0) 1672 return (0); 1673 else if (delim == 0 || val->val == 0 || val->numVals <= 0 || 1674 val->type != vt_string) { 1675 freeValue(val, 1); 1676 return (0); 1677 } 1678 1679 nval = val->val; 1680 nv = val->numVals; 1681 val->repeat = FALSE; 1682 val->val = 0; 1683 val->numVals = 0; 1684 1685 /* In N2L, space and tab delimiters are treated the same */ 1686 if (yp2ldap && delim == '\t') 1687 delim = ' '; 1688 1689 /* If the item has multiple values, we split each one independently */ 1690 for (i = 0; i < nv; i++) { 1691 char *str; 1692 int s, e; 1693 char *newstr; 1694 __nis_single_value_t *newval; 1695 1696 if (yp2ldap && delim == ' ') 1697 nval[i].value = trimWhiteSpaces(nval[i].value, 1698 &nval[i].length, 1); 1699 1700 str = nval[i].value; 1701 1702 if (nval[i].value == 0) 1703 continue; 1704 1705 for (s = 0; s < nval[i].length; s = e+1) { 1706 /* Find the next delimiter, or end-of-string */ 1707 for (e = s; str[e] != '\0' && str[e] != delim; e++); 1708 /* 1709 * 'str[e]' is either a delimiter, or the concluding 1710 * NUL. Make sure it's NUL. 1711 */ 1712 str[e] = '\0'; 1713 /* Add to val->val */ 1714 newstr = strdup(&str[s]); 1715 newval = realloc(val->val, 1716 (val->numVals+1) * 1717 sizeof (val->val[0])); 1718 if (newval != 0) 1719 val->val = newval; 1720 if (newstr == 0 || newval == 0) { 1721 freeValue(val, 1); 1722 for (n = i; n < nv; n++) { 1723 sfree(nval[n].value); 1724 } 1725 free(nval); 1726 sfree(newstr); 1727 return (0); 1728 } 1729 val->val[val->numVals].value = newstr; 1730 val->val[val->numVals].length = strlen(newstr) + 1; 1731 val->numVals++; 1732 } 1733 free(nval[i].value); 1734 nval[i].value = 0; 1735 } 1736 /* Already freed the nval[i].value's as we traversed nval */ 1737 free(nval); 1738 1739 return (val); 1740 } 1741 1742 /* 1743 * Match the format spec 'f[curf]' to the input value string 'str'. 1744 * 1745 * If successful, returns the updated position in the value string 'str'. 1746 * Otherwise, NULL is returned. 1747 * 1748 * curf Current index (i.e., the one we should look at) in 'f' 1749 * nf Number of elements in 'f', including 'mmt_end' 1750 * str The value string we're scanning 1751 * val Pointer to where an item value (if any) should be returned 1752 * Set to NULL if not an 'mmt_item'. 1753 * fmtstart If non-zero on entry, skip characters in 'str' until we find 1754 * the f[curf].type data, if doing so makes any sense. On exit, 1755 * set to the start of the fmt element data (which will be 'str', 1756 * unless we did skip characters) 1757 * sepset List of separators 1758 */ 1759 char * 1760 scanMappingFormat(__nis_mapping_format_t *f, int curf, int nf, char *str, 1761 char **val, char **fmtstart, char *sepset) { 1762 char *mstr, *next, *start = 0, *tmpstr; 1763 int i, len; 1764 bool_t match; 1765 char *myself = "scanMappingFormat"; 1766 /* N2L variables */ 1767 int af, skipspaces = 0; 1768 bool_t ipaddr = FALSE; 1769 char *spacestr = " ", *emptystr = ""; 1770 1771 1772 if (f == 0 || curf < 0 || nf <= 0 || str == 0) 1773 return (0); 1774 1775 /* 1776 * If separator list is NULL (which will be the case for 1777 * nis+2ldap), then simply use empty string 1778 */ 1779 if (sepset == 0) 1780 sepset = emptystr; 1781 1782 if (curf >= nf) { 1783 /* OK if the string also is exhausted */ 1784 if (strchr(sepset, *str) != 0) 1785 return (str); 1786 else 1787 return (0); 1788 } 1789 1790 switch (f[curf].type) { 1791 case mmt_berstring: 1792 if (f[curf].match.berString[0] != 'a') { 1793 /* Not a matchable element */ 1794 return (0); 1795 } 1796 1797 /* 1798 * If here, it means it's an IP address (N2L case) 1799 * So continue processing as if it was mmt_item 1800 */ 1801 ipaddr = TRUE; 1802 1803 case mmt_item: 1804 /* 1805 * In order to find the end of the item value, we must look 1806 * ahead and determine the start of the next formatting element. 1807 * If successful, 'next' will be the start of the fmt element 1808 * after the next one; we don't care about that, other than to 1809 * check for error. 1810 * 1811 * Since an item match is somewhat like an any match, in that 1812 * we don't know a priori if the first occurence of the next 1813 * element really is the one we want, we have to scan ahead 1814 * until we've reached the end. 1815 */ 1816 tmpstr = str; 1817 while ((next = scanMappingFormat(f, curf+1, nf, tmpstr, 0, 1818 &start, sepset)) != 0) { 1819 char *tmp = next; 1820 int cf; 1821 1822 for (cf = curf+2; cf < nf; cf++) { 1823 tmp = scanMappingFormat(f, cf, nf, tmp, 0, 1824 0, sepset); 1825 if (tmp == 0) 1826 break; 1827 } 1828 if (tmp == 0) { 1829 tmpstr = next; 1830 } else if (strchr(sepset, *tmp) != 0) { 1831 break; 1832 } else { 1833 return (0); 1834 } 1835 1836 } 1837 if (next == 0 || start == 0) 1838 return (0); 1839 1840 if (val != 0) { 1841 len = (int)((long)start - (long)str); 1842 *val = am(myself, len + 1); 1843 if (*val == 0) 1844 return (0); 1845 memcpy(*val, str, len); 1846 (*val)[len] = '\0'; 1847 1848 if (ipaddr == TRUE) { 1849 /* 1850 * In N2L, we need to check if *val is truly an 1851 * IP address 1852 */ 1853 af = checkIPaddress(*val, len, &tmpstr); 1854 1855 if (af == -2) { 1856 logmsg(MSG_NOTIMECHECK, LOG_WARNING, 1857 "%s:Internal error while " 1858 "processing IPaddress %s", 1859 myself, *val); 1860 sfree(*val); 1861 return (0); 1862 } else if (af == -1) { 1863 logmsg(MSG_NOTIMECHECK, LOG_WARNING, 1864 "%s:%s is not an IP address", 1865 myself, *val); 1866 sfree(*val); 1867 return (0); 1868 } else if (af == 0) { 1869 logmsg(MSG_NOTIMECHECK, LOG_WARNING, 1870 "%s:IP address %s is not " 1871 "supported by rfc2307bis", 1872 myself, *val); 1873 sfree(*val); 1874 return (0); 1875 } else if (sstrncmp(*val, tmpstr, len) != 0) { 1876 logmsg(MSG_NOTIMECHECK, LOG_WARNING, 1877 "%s:IPaddress %s converted " 1878 "to %s", myself, *val, tmpstr); 1879 } 1880 1881 sfree(*val); 1882 *val = tmpstr; 1883 } 1884 } 1885 1886 if (fmtstart != 0) 1887 *fmtstart = str; 1888 1889 return (start); 1890 1891 case mmt_string: 1892 if ((mstr = f[curf].match.string) == 0 || *mstr == '\0') { 1893 /* 1894 * Count this as a successful match of an empty 1895 * string. 1896 */ 1897 if (fmtstart != 0) 1898 *fmtstart = str; 1899 return (str); 1900 } 1901 1902 /* 1903 * In N2L, if the format string 'mstr' contains only 1904 * whitespaces (spaces and tabs), then it should 1905 * match one or more whitespaces from the input 1906 * string 'str'. 1907 */ 1908 if (yp2ldap && strspn(mstr, " \t") == strlen(mstr)) { 1909 mstr = spacestr; 1910 skipspaces = 1; 1911 next = str + strcspn(str, " \t"); 1912 /* 1913 * Even if there is no whitespace in 'str', 1914 * it's OK. This is to allow formats like 1915 * "%s %s %s" to match inputs like "foo bar". 1916 */ 1917 if (*next == '\0') 1918 mstr = emptystr; 1919 } else { 1920 /* No match string in 'str' => failure */ 1921 if ((next = strstr(str, mstr)) == 0) 1922 return (0); 1923 } 1924 1925 /* If 'fmtstart' == 0, we require 'next' == 'str' */ 1926 if (fmtstart == 0 && next != str) 1927 return (0); 1928 /* Success; save start of match string if requested */ 1929 if (fmtstart != 0) 1930 *fmtstart = next; 1931 /* Update position in the value string */ 1932 str = (char *)((long)next + (long)strlen(mstr)); 1933 1934 /* Skip whitespaces for N2L */ 1935 if (skipspaces == 1) 1936 for (; *str == ' ' || *str == '\t'; str++); 1937 1938 return (str); 1939 1940 case mmt_single: 1941 if (fmtstart != 0) { 1942 match = FALSE; 1943 /* Skip ahead until we match */ 1944 for (next = str; *next != '\0'; next++) { 1945 unsigned char *lo = f[curf].match.single.lo; 1946 unsigned char *hi = f[curf].match.single.hi; 1947 1948 for (i = 0; i < f[curf].match.single.numRange; 1949 i++) { 1950 if (*next >= lo[i] && *next <= hi[i]) { 1951 match = TRUE; 1952 break; 1953 } 1954 } 1955 if (match) 1956 break; 1957 } 1958 if (!match) 1959 return (0); 1960 *fmtstart = next; 1961 str = next; 1962 } else { 1963 match = FALSE; 1964 for (i = 0; i < f[curf].match.single.numRange; i++) { 1965 if (*str >= f[curf].match.single.lo[i] && 1966 *str <= f[curf].match.single.hi[i]) { 1967 match = TRUE; 1968 break; 1969 } 1970 } 1971 if (!match) 1972 return (0); 1973 } 1974 /* Step over the matched character */ 1975 str++; 1976 return (str); 1977 1978 case mmt_any: 1979 /* 1980 * Look ahead to find the beginning of the next element. 1981 * Because a wildcard-match isn't necessarily uniquely 1982 * determined until we've reached the end, we then continue 1983 * to scan ahead. 1984 */ 1985 while ((next = scanMappingFormat(f, curf+1, nf, str, 0, 1986 &start, sepset)) != 0) { 1987 char *tmp = next; 1988 int cf; 1989 1990 for (cf = curf+2; cf < nf; cf++) { 1991 tmp = scanMappingFormat(f, cf, nf, tmp, 0, 1992 0, sepset); 1993 if (tmp == 0) 1994 break; 1995 } 1996 if (tmp == 0) { 1997 str = next; 1998 } else if (*tmp == '\0') { 1999 break; 2000 } else { 2001 return (0); 2002 } 2003 } 2004 if (next == 0 || start == 0) 2005 return (0); 2006 2007 if (fmtstart != 0) 2008 *fmtstart = str; 2009 2010 return (start); 2011 2012 case mmt_limit: 2013 if (f[curf].match.limit == eos) { 2014 if (fmtstart != 0) { 2015 /* Skip to the end */ 2016 str = str + strcspn(str, sepset); 2017 *fmtstart = str; 2018 } else if (strchr(sepset, *str) == 0) { 2019 return (0); 2020 } 2021 } 2022 return (str); 2023 2024 case mmt_begin: 2025 if (fmtstart != 0) 2026 *fmtstart = str; 2027 return (str); 2028 2029 case mmt_end: 2030 if (fmtstart != 0) { 2031 /* Skip to the end */ 2032 str = str + strcspn(str, sepset); 2033 *fmtstart = str; 2034 return (str); 2035 } 2036 /* No skipping, so we must be at the end of the value */ 2037 if (strchr(sepset, *str) == 0) 2038 return (0); 2039 return (str); 2040 2041 default: 2042 break; 2043 } 2044 2045 return (0); 2046 } 2047 2048 /* 2049 * Verify that the string 'str' matches the mapping format array 'f'. 2050 * Returns 1 in case of a match, 0 otherwise. 2051 */ 2052 int 2053 verifyMappingMatch(__nis_mapping_format_t *f, char *str) { 2054 int n, nf; 2055 __nis_mapping_format_t *ftmp; 2056 2057 /* Count the number of format elements in the format */ 2058 for (nf = 0, ftmp = f; ftmp->type != mmt_end; ftmp++) { 2059 nf++; 2060 } 2061 /* Count the mmt_end as well */ 2062 nf++; 2063 2064 for (n = 0; n < nf; n++) { 2065 str = scanMappingFormat(f, n, nf, str, 0, 0, 0); 2066 if (str == 0) 2067 break; 2068 } 2069 2070 return ((str != 0) ? 1 : 0); 2071 } 2072 2073 /* 2074 * Perform a match operation. For example, given the rule 2075 * ("{%s}%s", auth_name, public_data)=nisPublicKey 2076 * and assuming that 'nisPublicKey' has the value "{dh640-0}abcdef12345", 2077 * assign "dh640-0" to 'auth_name' and "abcdef12345" to 'public_data'. 2078 * 2079 * Note that this function doesn't perform the actual assignment. Rather, 2080 * it returns an array of __nis_value_t's, with element zero of the value 2081 * array being the new value of the first matched item, element one the 2082 * value of the second matched item, etc. In the example above, we'd 2083 * return a value array with two elements. 2084 * 2085 * If there is more than one input value (inVal->numVals > 1), the 2086 * output array elements will also be multi-valued. 2087 * 2088 * f The match format 2089 * inVal Input value(s) 2090 * numVal Number of elements in the output value array 2091 * sepset List of separators 2092 * outstr Points to the updated position upto which the 2093 * input string has been matched 2094 */ 2095 __nis_value_t ** 2096 matchMappingItem(__nis_mapping_format_t *f, __nis_value_t *inVal, 2097 int *numVals, char *sepset, char **outstr) { 2098 __nis_value_t **v = 0; 2099 int i, n, ni, numItems, nf, nv = 0; 2100 char *str, *valstr; 2101 __nis_mapping_format_t *ftmp; 2102 char *myself = "matchMappingItem"; 2103 2104 if (f == 0 || 2105 inVal == 0 || inVal->numVals < 1 || inVal->type != vt_string) 2106 return (0); 2107 2108 /* Count the number of format elements and items in the format */ 2109 for (nf = numItems = 0, ftmp = f; ftmp->type != mmt_end; ftmp++) { 2110 nf++; 2111 2112 /* 2113 * Count mmt_item and mmt_berstring (used by N2L to 2114 * represent address %a) 2115 */ 2116 if (ftmp->type == mmt_item) 2117 numItems++; 2118 else if (ftmp->type == mmt_berstring && ftmp->match.berString && 2119 ftmp->match.berString[0] == 'a') 2120 numItems++; 2121 } 2122 /* Count the mmt_end as well */ 2123 nf++; 2124 2125 /* 2126 * If no items, there will be no values. This isn't exactly an error 2127 * from the limited point of view of this function, so we return a 2128 * __nis_value_t with zero values. 2129 */ 2130 if (numItems <= 0) { 2131 v = am(myself, sizeof (v[0])); 2132 if (v == 0) 2133 return (0); 2134 v[0] = am(myself, sizeof (*v[0])); 2135 if (v[0] == 0) { 2136 sfree(v); 2137 return (0); 2138 } 2139 v[0]->type = vt_string; 2140 v[0]->numVals = 0; 2141 v[0]->val = 0; 2142 if (numVals != 0) 2143 *numVals = 1; 2144 return (v); 2145 } 2146 2147 /* Allocate and initialize the return array */ 2148 v = am(myself, numItems * sizeof (v[0])); 2149 if (v == 0) 2150 return (0); 2151 for (n = 0; n < numItems; n++) { 2152 v[n] = am(myself, sizeof (*v[n])); 2153 if (v[n] == 0) { 2154 int j; 2155 2156 for (j = 0; j < n; j++) 2157 freeValue(v[j], 1); 2158 sfree(v); 2159 return (0); 2160 } 2161 v[n]->type = vt_string; 2162 v[n]->numVals = 0; 2163 v[n]->val = am(myself, inVal->numVals * sizeof (v[n]->val[0])); 2164 if (v[n]->val == 0) { 2165 int j; 2166 2167 for (j = 0; j < n; j++) 2168 freeValue(v[j], 1); 2169 sfree(v); 2170 return (0); 2171 } 2172 for (i = 0; i < inVal->numVals; i++) { 2173 v[n]->val[i].length = 0; 2174 v[n]->val[i].value = 0; 2175 } 2176 } 2177 2178 /* For each input value, perform the match operation */ 2179 for (i = 0; i < inVal->numVals; i++) { 2180 str = inVal->val[i].value; 2181 if (str == 0) 2182 continue; 2183 for (n = 0, ni = 0; n < nf; n++) { 2184 valstr = 0; 2185 str = scanMappingFormat(f, n, nf, str, &valstr, 2186 0, sepset); 2187 if (str == 0) 2188 break; 2189 if (valstr != 0 && ni < numItems && 2190 v[ni]->numVals < inVal->numVals) { 2191 v[ni]->val[v[ni]->numVals].value = valstr; 2192 v[ni]->val[v[ni]->numVals].length = 2193 strlen(valstr) + 1; 2194 v[ni]->numVals++; 2195 ni++; 2196 } else if (valstr != 0) { 2197 sfree(valstr); 2198 } 2199 } 2200 if (str == 0) { 2201 for (n = 0; n < numItems; n++) 2202 freeValue(v[n], 1); 2203 sfree(v); 2204 return (0); 2205 } 2206 } 2207 2208 if (numVals != 0) 2209 *numVals = numItems; 2210 2211 /* 2212 * Update the return string upto the point it has been matched 2213 * This string will be used by the N2L code in its next call 2214 * to this function 2215 */ 2216 if (outstr != 0) 2217 *outstr = str; 2218 2219 return (v); 2220 } 2221 2222 /* 2223 * Perform an extract operation. For example, given the expression 2224 * (name, "%s.*") 2225 * and assuming 'name' is an item with the value "some.thing", the 2226 * value returned by the extract is "some". 2227 */ 2228 __nis_value_t * 2229 extractMappingItem(__nis_mapping_item_t *item, __nis_mapping_format_t *f, 2230 __nis_rule_value_t *rv, int *stat) { 2231 __nis_value_t *val = getMappingItem(item, mit_any, 2232 rv, 0, stat); 2233 __nis_single_value_t *nval; 2234 int i, n, nv, nf; 2235 __nis_mapping_format_t *ftmp; 2236 2237 if (val == 0) 2238 return (0); 2239 else if (f == 0 || rv == 0 || val->val == 0 || 2240 val->numVals <= 0 || val->type != vt_string) { 2241 freeValue(val, 1); 2242 return (0); 2243 } 2244 2245 /* Sanity check the format; it must have one and only one mmt_item */ 2246 { 2247 int numitem; 2248 2249 for (nf = numitem = 0, ftmp = f; ftmp->type != mmt_end; 2250 ftmp++) { 2251 nf++; 2252 if (ftmp->type == mmt_item) 2253 numitem++; 2254 } 2255 /* Count the mmt_end as well */ 2256 nf++; 2257 if (numitem != 1) { 2258 freeValue(val, 1); 2259 return (0); 2260 } 2261 } 2262 2263 nval = val->val; 2264 nv = val->numVals; 2265 val->repeat = FALSE; 2266 val->val = 0; 2267 val->numVals = 0; 2268 2269 /* If the item has multiple values, we extract each one independently */ 2270 for (i = 0; i < nv; i++) { 2271 char *str = nval[i].value; 2272 char *newstr = 0; 2273 __nis_single_value_t *newval; 2274 2275 if (nval[i].value == 0) 2276 continue; 2277 2278 /* 2279 * We match the whole string, even if we find a value for 2280 * the item before exhausting all format elements. By doing 2281 * this, we ensure that the string really matches the complete 2282 * format specification. 2283 */ 2284 for (n = 0; n < nf; n++) { 2285 str = scanMappingFormat(f, n, nf, str, &newstr, 0, 0); 2286 if (str == 0) 2287 break; 2288 } 2289 2290 /* 2291 * *str should now be NUL, meaning we've reached the end of 2292 * the string (value), and it completely matched the format. 2293 * If 'str' is NULL, there was an error, and if 'newstr' is 2294 * 0, we somehow failed to obtain a value. 2295 */ 2296 if (str == 0 || *str != '\0' || newstr == 0 || 2297 (newval = realloc(val->val, 2298 (val->numVals+1) * 2299 sizeof (val->val[0]))) == 0) { 2300 freeValue(val, 1); 2301 for (n = 0; n < nv; n++) { 2302 sfree(nval[n].value); 2303 } 2304 free(nval); 2305 sfree(newstr); 2306 return (0); 2307 } 2308 2309 val->val = newval; 2310 val->val[val->numVals].value = newstr; 2311 val->val[val->numVals].length = strlen(newstr) + 1; 2312 val->numVals++; 2313 2314 free(nval[i].value); 2315 nval[i].value = 0; 2316 } 2317 free(nval); 2318 2319 return (val); 2320 } 2321 2322 /* 2323 * For each value in 'val', remove the last character, provided that 2324 * it matches 'elide'. 2325 */ 2326 void 2327 stringElide(__nis_value_t *val, char elide) { 2328 2329 if (val != 0 && val->type == vt_string) { 2330 int i; 2331 2332 for (i = 0; i < val->numVals; i++) { 2333 int end = val->val[i].length; 2334 char *str = val->val[i].value; 2335 2336 if (str == 0 || end <= 0) 2337 continue; 2338 2339 /* 2340 * If the NUL was counted in the length, step back 2341 * over it. 2342 */ 2343 if (str[end-1] == '\0') 2344 end--; 2345 if (end > 0 && str[end-1] == elide) { 2346 str[end-1] = '\0'; 2347 val->val[i].length--; 2348 } 2349 } 2350 } 2351 } 2352 2353 /* 2354 * Obtain the value for the mapping sub-element 'e', given the input 2355 * rule-value 'rv'. 2356 */ 2357 __nis_value_t * 2358 getMappingSubElement(__nis_mapping_sub_element_t *e, 2359 __nis_rule_value_t *rv, int *np_ldap_stat) { 2360 __nis_value_t *val; 2361 2362 if (e == 0) 2363 return (0); 2364 2365 switch (e->type) { 2366 case me_item: 2367 val = getMappingItem(&e->element.item, mit_any, rv, 0, 2368 np_ldap_stat); 2369 break; 2370 case me_print: 2371 val = getMappingFormatArray(e->element.print.fmt, rv, 2372 fa_item, 2373 e->element.print.numItems, 2374 e->element.print.item); 2375 if (e->element.print.doElide) 2376 stringElide(val, e->element.print.elide); 2377 break; 2378 case me_split: 2379 val = splitMappingItem(&e->element.split.item, 2380 e->element.split.delim, 2381 rv); 2382 break; 2383 case me_extract: 2384 val = extractMappingItem(&e->element.extract.item, 2385 e->element.extract.fmt, 2386 rv, np_ldap_stat); 2387 break; 2388 case me_match: 2389 default: 2390 val = 0; 2391 break; 2392 } 2393 2394 return (val); 2395 } 2396 2397 /* 2398 * Obtain the value of the mapping element 'e', given the input rule- 2399 * value 'rv'. The 'native' mapping type is used when 'rv' is NULL, 2400 * and the result is a string representation of the mapping element; 2401 * in that case, items of the 'native' type are printed without their 2402 * type designation ("nis+" or "ldap"). 2403 */ 2404 __nis_value_t * 2405 getMappingElement(__nis_mapping_element_t *e, __nis_mapping_item_type_t native, 2406 __nis_rule_value_t *rv, int *stat) { 2407 __nis_value_t *val, **tv; 2408 int i, success = 0, novalue = 0; 2409 int *np_ldap_stat; 2410 char *myself = "getMappingElement"; 2411 2412 switch (e->type) { 2413 case me_item: 2414 val = getMappingItem(&e->element.item, native, rv, 0, NULL); 2415 break; 2416 case me_print: 2417 tv = am(myself, e->element.print.numSubElements * 2418 sizeof (tv[0])); 2419 np_ldap_stat = am(myself, 2420 e->element.print.numSubElements * sizeof (int)); 2421 if ((e->element.print.numSubElements > 0) && 2422 (tv == 0 || np_ldap_stat == 0)) { 2423 val = 0; 2424 sfree(tv); 2425 sfree(np_ldap_stat); 2426 break; 2427 } 2428 for (i = 0; i < e->element.print.numSubElements; i++) { 2429 np_ldap_stat[i] = 0; 2430 tv[i] = getMappingSubElement( 2431 &e->element.print.subElement[i], 2432 rv, &np_ldap_stat[i]); 2433 } 2434 /* 2435 * if we get NP_LDAP_NO_VALUE to any of the subelement 2436 * and we get NP_LDAP_MAP_SUCCESS to all other subelement 2437 * then we had enough nis+ column values which can 2438 * produce value for this rule, but didn't. So return 2439 * NP_LDAP_RULES_NO_VALUE to indicate to proceed to 2440 * next database id. 2441 */ 2442 for (i = 0; i < e->element.print.numSubElements; i++) { 2443 if (np_ldap_stat[i] == NP_LDAP_MAP_SUCCESS) 2444 success++; 2445 if (np_ldap_stat[i] == NP_LDAP_NO_VALUE) 2446 novalue++; 2447 } 2448 if (stat != NULL && novalue > 0 && 2449 ((novalue+success) == 2450 e->element.print.numSubElements)) 2451 *stat = NP_LDAP_RULES_NO_VALUE; 2452 val = getMappingFormatArray(e->element.print.fmt, rv, 2453 fa_value, 2454 e->element.print.numSubElements, 2455 tv); 2456 for (i = 0; i < e->element.print.numSubElements; i++) { 2457 freeValue(tv[i], 1); 2458 } 2459 sfree(tv); 2460 sfree(np_ldap_stat); 2461 if (e->element.print.doElide) 2462 stringElide(val, e->element.print.elide); 2463 break; 2464 case me_split: 2465 val = splitMappingItem(&e->element.split.item, 2466 e->element.split.delim, 2467 rv); 2468 break; 2469 case me_match: 2470 /* 2471 * A match doesn't produce an assignable value per se, 2472 * so we shouldn't get one here. 2473 */ 2474 val = 0; 2475 break; 2476 case me_extract: 2477 val = extractMappingItem(&e->element.extract.item, 2478 e->element.extract.fmt, 2479 rv, NULL); 2480 break; 2481 default: 2482 val = 0; 2483 break; 2484 } 2485 2486 return (val); 2487 } 2488