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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <sys/types.h> 30 #include <stdlib.h> 31 #include <libintl.h> 32 #include <ctype.h> 33 #include <syslog.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 #include <unistd.h> 37 #include <string.h> 38 #include <strings.h> 39 40 #include "ns_sldap.h" 41 #include "ns_internal.h" 42 #include "ns_cache_door.h" 43 44 #define _NIS_FILTER "nisdomain=*" 45 #define _NIS_DOMAIN "nisdomain" 46 static const char *nis_domain_attrs[] = { 47 _NIS_DOMAIN, 48 (char *)NULL 49 }; 50 51 static int validate_filter(ns_ldap_cookie_t *cookie); 52 53 void 54 __ns_ldap_freeEntry(ns_ldap_entry_t *ep) 55 { 56 int j, k = 0; 57 58 if (ep == NULL) 59 return; 60 61 if (ep->attr_pair == NULL) { 62 free(ep); 63 return; 64 } 65 for (j = 0; j < ep->attr_count; j++) { 66 if (ep->attr_pair[j] == NULL) 67 continue; 68 if (ep->attr_pair[j]->attrname) 69 free(ep->attr_pair[j]->attrname); 70 if (ep->attr_pair[j]->attrvalue) { 71 for (k = 0; (k < ep->attr_pair[j]->value_count) && 72 (ep->attr_pair[j]->attrvalue[k]); k++) { 73 free(ep->attr_pair[j]->attrvalue[k]); 74 } 75 free(ep->attr_pair[j]->attrvalue); 76 } 77 free(ep->attr_pair[j]); 78 } 79 free(ep->attr_pair); 80 free(ep); 81 } 82 83 static void 84 _freeControlList(LDAPControl ***ctrls) 85 { 86 LDAPControl **ctrl; 87 88 if (ctrls == NULL || *ctrls == NULL) 89 return; 90 91 for (ctrl = *ctrls; *ctrl != NULL; ctrl++) 92 ldap_control_free(*ctrl); 93 free(*ctrls); 94 *ctrls = NULL; 95 } 96 /* 97 * Convert attribute type in a RDN that has an attribute mapping to the 98 * original mappped type. 99 * e.g. 100 * cn<->cn-st and iphostnumber<->iphostnumber-st 101 * cn-st=aaa+iphostnumber-st=10.10.01.01 102 * is mapped to 103 * cn=aaa+iphostnumber=10.10.01.01 104 * 105 * Input - service: e.g. hosts, passwd etc. 106 * rdn: RDN 107 * Return: NULL - No attribute mapping in the RDN 108 * Non-NULL - The attribute type(s) in the RDN are mapped and 109 * the memory is allocated for the new rdn. 110 * 111 */ 112 static char * 113 _cvtRDN(const char *service, const char *rdn) { 114 char **attrs, **mapped_attrs, **mapp, *type, *value, *attr; 115 char *new_rdn = NULL; 116 int nAttr = 0, i, attr_mapped, len = 0; 117 118 /* Break down "type=value\0" pairs. Assume RDN is normalized */ 119 if ((attrs = ldap_explode_rdn(rdn, 0)) == NULL) 120 return (NULL); 121 122 for (nAttr = 0; attrs[nAttr] != NULL; nAttr++); 123 124 if ((mapped_attrs = (char **)calloc(nAttr, sizeof (char *))) == NULL) { 125 ldap_value_free(attrs); 126 return (NULL); 127 } 128 129 attr_mapped = 0; 130 for (i = 0; i < nAttr; i++) { 131 /* Parse type=value pair */ 132 if ((type = strtok_r(attrs[i], "=", &value)) == NULL || 133 value == NULL) 134 goto cleanup; 135 /* Reverse map: e.g. cn-sm -> cn */ 136 mapp = __ns_ldap_getOrigAttribute(service, type); 137 if (mapp != NULL && mapp[0] != NULL) { 138 /* The attribute mapping is found */ 139 type = mapp[0]; 140 attr_mapped = 1; 141 142 /* "type=value\0" */ 143 len = strlen(type) + strlen(value) + 2; 144 145 /* Reconstruct type=value pair. A string is allocated */ 146 if ((attr = (char *)calloc(1, len)) == NULL) { 147 __s_api_free2dArray(mapp); 148 goto cleanup; 149 } 150 (void) snprintf(attr, len, "%s=%s", 151 type, value); 152 mapped_attrs[i] = attr; 153 } else { 154 /* 155 * No attribute mapping. attrs[i] is going to be copied 156 * later. Restore "type\0value\0" back to 157 * "type=value\0". 158 */ 159 type[strlen(type)] = '='; 160 } 161 __s_api_free2dArray(mapp); 162 } 163 if (attr_mapped == 0) 164 /* No attribute mapping. Don't bother to reconstruct RDN */ 165 goto cleanup; 166 167 len = 0; 168 /* Reconstruct RDN from type=value pairs */ 169 for (i = 0; i < nAttr; i++) { 170 if (mapped_attrs[i]) 171 len += strlen(mapped_attrs[i]); 172 else 173 len += strlen(attrs[i]); 174 /* Add 1 for "+" */ 175 len++; 176 } 177 if ((new_rdn = (char *)calloc(1, ++len)) == NULL) 178 goto cleanup; 179 for (i = 0; i < nAttr; i++) { 180 if (i > 0) 181 /* Add seperator */ 182 (void) strlcat(new_rdn, "+", len); 183 184 if (mapped_attrs[i]) 185 (void) strlcat(new_rdn, mapped_attrs[i], len); 186 else 187 (void) strlcat(new_rdn, attrs[i], len); 188 189 } 190 cleanup: 191 ldap_value_free(attrs); 192 if (mapped_attrs) { 193 if (attr_mapped) { 194 for (i = 0; i < nAttr; i++) { 195 if (mapped_attrs[i]) 196 free(mapped_attrs[i]); 197 } 198 } 199 free(mapped_attrs); 200 } 201 202 return (new_rdn); 203 } 204 /* 205 * Convert attribute type in a DN that has an attribute mapping to the 206 * original mappped type. 207 * e.g 208 * The mappings are cn<->cn-sm, iphostnumber<->iphostnumber-sm 209 * 210 * dn: cn-sm=aaa+iphostnumber-sm=9.9.9.9,dc=central,dc=sun,dc=com 211 * is converted to 212 * dn: cn=aaa+iphostnumber=9.9.9.9,dc=central,dc=sun,dc=com 213 * 214 * Input - service: e.g. hosts, passwd etc. 215 * dn: the value of a distinguished name 216 * Return - NULL: error 217 * non-NULL: A converted DN and the memory is allocated 218 */ 219 static char * 220 _cvtDN(const char *service, const char *dn) { 221 char **mapped_rdns; 222 char **rdns, *new_rdn, *new_dn = NULL; 223 int nRdn = 0, i, len = 0, rdn_mapped; 224 225 if (service == NULL || dn == NULL) 226 return (NULL); 227 228 if ((rdns = ldap_explode_dn(dn, 0)) == NULL) 229 return (NULL); 230 231 for (nRdn = 0; rdns[nRdn] != NULL; nRdn++); 232 233 if ((mapped_rdns = (char **)calloc(nRdn, sizeof (char *))) == NULL) { 234 ldap_value_free(rdns); 235 return (NULL); 236 } 237 238 rdn_mapped = 0; 239 /* Break down RDNs in a DN */ 240 for (i = 0; i < nRdn; i++) { 241 if ((new_rdn = _cvtRDN(service, rdns[i])) != NULL) { 242 mapped_rdns[i] = new_rdn; 243 rdn_mapped = 1; 244 } 245 } 246 if (rdn_mapped == 0) { 247 /* 248 * No RDN contains any attribute mapping. 249 * Don't bother to reconstruct DN from RDN. Copy DN directly. 250 */ 251 new_dn = strdup(dn); 252 goto cleanup; 253 } 254 /* 255 * Reconstruct dn from RDNs. 256 * Calculate the length first. 257 */ 258 for (i = 0; i < nRdn; i++) { 259 if (mapped_rdns[i]) 260 len += strlen(mapped_rdns[i]); 261 else 262 len += strlen(rdns[i]); 263 264 /* add 1 for ',' */ 265 len ++; 266 } 267 if ((new_dn = (char *)calloc(1, ++len)) == NULL) 268 goto cleanup; 269 for (i = 0; i < nRdn; i++) { 270 if (i > 0) 271 /* Add seperator */ 272 (void) strlcat(new_dn, ",", len); 273 274 if (mapped_rdns[i]) 275 (void) strlcat(new_dn, mapped_rdns[i], len); 276 else 277 (void) strlcat(new_dn, rdns[i], len); 278 279 } 280 281 cleanup: 282 ldap_value_free(rdns); 283 if (mapped_rdns) { 284 if (rdn_mapped) { 285 for (i = 0; i < nRdn; i++) { 286 if (mapped_rdns[i]) 287 free(mapped_rdns[i]); 288 } 289 } 290 free(mapped_rdns); 291 } 292 293 return (new_dn); 294 } 295 /* 296 * Convert a single ldap entry from a LDAPMessage 297 * into an ns_ldap_entry structure. 298 * Schema map the entry if specified in flags 299 */ 300 301 static int 302 __s_api_cvtEntry(LDAP *ld, 303 const char *service, 304 LDAPMessage *e, 305 int flags, 306 ns_ldap_entry_t **ret, 307 ns_ldap_error_t **error) 308 { 309 310 ns_ldap_entry_t *ep = NULL; 311 ns_ldap_attr_t **ap = NULL; 312 BerElement *ber; 313 char *attr = NULL; 314 char **vals = NULL; 315 char **mapping; 316 char *dn; 317 int nAttrs = 0; 318 int i, j, k = 0; 319 char **gecos_mapping = NULL; 320 int gecos_val_index[3] = { -1, -1, -1}; 321 char errstr[MAXERROR]; 322 int schema_mapping_existed = FALSE; 323 int gecos_mapping_existed = FALSE; 324 int gecos_attr_matched; 325 int auto_service = FALSE; 326 int rc = NS_LDAP_SUCCESS; 327 328 if (e == NULL || ret == NULL || error == NULL) 329 return (NS_LDAP_INVALID_PARAM); 330 331 *error = NULL; 332 333 ep = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t)); 334 if (ep == NULL) 335 return (NS_LDAP_MEMORY); 336 337 if (service != NULL && 338 (strncasecmp(service, "auto_", 5) == 0 || 339 strcasecmp(service, "automount") == 0)) 340 auto_service = TRUE; 341 /* 342 * see if schema mapping existed for the given service 343 */ 344 mapping = __ns_ldap_getOrigAttribute(service, 345 NS_HASH_SCHEMA_MAPPING_EXISTED); 346 if (mapping) { 347 schema_mapping_existed = TRUE; 348 __s_api_free2dArray(mapping); 349 mapping = NULL; 350 } else if (auto_service) { 351 /* 352 * If service == auto_* and no 353 * schema mapping found 354 * then try automount 355 * There is certain case that schema mapping exist 356 * but __ns_ldap_getOrigAttribute(service, 357 * NS_HASH_SCHEMA_MAPPING_EXISTED); 358 * returns NULL. 359 * e.g. 360 * NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA 361 * NS_LDAP_OBJECTCLASSMAP = automount:automountMap=MynisMap 362 * NS_LDAP_OBJECTCLASSMAP = automount:automount=MynisObject 363 * 364 * Make a check for schema_mapping_existed here 365 * so later on __s_api_convert_automountmapname won't be called 366 * unnecessarily. It is also used for attribute mapping 367 * and objectclass mapping. 368 */ 369 mapping = __ns_ldap_getOrigAttribute("automount", 370 NS_HASH_SCHEMA_MAPPING_EXISTED); 371 if (mapping) { 372 schema_mapping_existed = TRUE; 373 __s_api_free2dArray(mapping); 374 mapping = NULL; 375 } 376 } 377 378 nAttrs = 1; /* start with 1 for the DN attr */ 379 for (attr = ldap_first_attribute(ld, e, &ber); attr != NULL; 380 attr = ldap_next_attribute(ld, e, ber)) { 381 nAttrs++; 382 ldap_memfree(attr); 383 attr = NULL; 384 } 385 ber_free(ber, 0); 386 ber = NULL; 387 388 ep->attr_count = nAttrs; 389 390 /* 391 * add 1 for "gecos" 1 to N attribute mapping, 392 * just in case it is needed. 393 * ep->attr_count will be updated later if that is true. 394 */ 395 ap = (ns_ldap_attr_t **)calloc(ep->attr_count + 1, 396 sizeof (ns_ldap_attr_t *)); 397 if (ap == NULL) { 398 __ns_ldap_freeEntry(ep); 399 ep = NULL; 400 return (NS_LDAP_MEMORY); 401 } 402 ep->attr_pair = ap; 403 404 /* DN attribute */ 405 dn = ldap_get_dn(ld, e); 406 ap[0] = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); 407 if (ap[0] == NULL) { 408 ldap_memfree(dn); 409 dn = NULL; 410 __ns_ldap_freeEntry(ep); 411 ep = NULL; 412 return (NS_LDAP_MEMORY); 413 } 414 415 if ((ap[0]->attrname = strdup("dn")) == NULL) { 416 ldap_memfree(dn); 417 dn = NULL; 418 __ns_ldap_freeEntry(ep); 419 ep = NULL; 420 return (NS_LDAP_INVALID_PARAM); 421 } 422 ap[0]->value_count = 1; 423 if ((ap[0]->attrvalue = (char **) 424 calloc(2, sizeof (char *))) == NULL) { 425 ldap_memfree(dn); 426 dn = NULL; 427 __ns_ldap_freeEntry(ep); 428 ep = NULL; 429 return (NS_LDAP_MEMORY); 430 } 431 432 if (schema_mapping_existed && ((flags & NS_LDAP_NOT_CVT_DN) == 0)) 433 ap[0]->attrvalue[0] = _cvtDN(service, dn); 434 else 435 ap[0]->attrvalue[0] = strdup(dn); 436 437 if (ap[0]->attrvalue[0] == NULL) { 438 ldap_memfree(dn); 439 dn = NULL; 440 __ns_ldap_freeEntry(ep); 441 ep = NULL; 442 return (NS_LDAP_MEMORY); 443 } 444 ldap_memfree(dn); 445 dn = NULL; 446 447 if ((flags & NS_LDAP_NOMAP) == 0 && auto_service && 448 schema_mapping_existed) { 449 rc = __s_api_convert_automountmapname(service, 450 &ap[0]->attrvalue[0], 451 error); 452 if (rc != NS_LDAP_SUCCESS) { 453 __ns_ldap_freeEntry(ep); 454 ep = NULL; 455 return (rc); 456 } 457 } 458 459 /* other attributes */ 460 for (attr = ldap_first_attribute(ld, e, &ber), j = 1; 461 attr != NULL && j != nAttrs; 462 attr = ldap_next_attribute(ld, e, ber), j++) { 463 /* allocate new attr name */ 464 465 if ((ap[j] = (ns_ldap_attr_t *) 466 calloc(1, sizeof (ns_ldap_attr_t))) == NULL) { 467 ber_free(ber, 0); 468 ber = NULL; 469 __ns_ldap_freeEntry(ep); 470 ep = NULL; 471 if (gecos_mapping) 472 __s_api_free2dArray(gecos_mapping); 473 gecos_mapping = NULL; 474 return (NS_LDAP_MEMORY); 475 } 476 477 if ((flags & NS_LDAP_NOMAP) || schema_mapping_existed == FALSE) 478 mapping = NULL; 479 else 480 mapping = __ns_ldap_getOrigAttribute(service, attr); 481 482 if (mapping == NULL && auto_service && 483 schema_mapping_existed && 484 (flags & NS_LDAP_NOMAP) == 0) 485 /* 486 * if service == auto_* and no 487 * schema mapping found 488 * and schema_mapping_existed is TRUE 489 * and NS_LDAP_NOMAP is not set 490 * then try automount 491 * e.g. 492 * NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA 493 */ 494 mapping = __ns_ldap_getOrigAttribute("automount", attr); 495 496 if (mapping == NULL) { 497 if ((ap[j]->attrname = strdup(attr)) == NULL) { 498 ber_free(ber, 0); 499 ber = NULL; 500 __ns_ldap_freeEntry(ep); 501 ep = NULL; 502 if (gecos_mapping) 503 __s_api_free2dArray(gecos_mapping); 504 gecos_mapping = NULL; 505 return (NS_LDAP_MEMORY); 506 } 507 } else { 508 /* 509 * for "gecos" 1 to N mapping, 510 * do not remove the mapped attribute, 511 * just create a new gecos attribute 512 * and append it to the end of the attribute list 513 */ 514 if (strcasecmp(mapping[0], "gecos") == 0) { 515 ap[j]->attrname = strdup(attr); 516 gecos_mapping_existed = TRUE; 517 } else 518 ap[j]->attrname = strdup(mapping[0]); 519 520 if (ap[j]->attrname == NULL) { 521 ber_free(ber, 0); 522 ber = NULL; 523 __ns_ldap_freeEntry(ep); 524 ep = NULL; 525 if (gecos_mapping) 526 __s_api_free2dArray(gecos_mapping); 527 gecos_mapping = NULL; 528 return (NS_LDAP_MEMORY); 529 } 530 /* 531 * 1 to N attribute mapping processing 532 * is only done for "gecos" 533 */ 534 535 if (strcasecmp(mapping[0], "gecos") == 0) { 536 /* 537 * get attribute mapping for "gecos", 538 * need to know the number and order of the 539 * mapped attributes 540 */ 541 if (gecos_mapping == NULL) { 542 gecos_mapping = 543 __ns_ldap_getMappedAttributes(service, 544 mapping[0]); 545 if (gecos_mapping == NULL || 546 gecos_mapping[0] == NULL) { 547 /* 548 * this should never happens, 549 * syslog the error 550 */ 551 (void) sprintf(errstr, 552 gettext( 553 "Attribute mapping " 554 "inconsistency " 555 "found for attributes " 556 "'%s' and '%s'."), 557 mapping[0], attr); 558 syslog(LOG_ERR, "libsldap: %s", errstr); 559 560 ber_free(ber, 0); 561 ber = NULL; 562 __ns_ldap_freeEntry(ep); 563 ep = NULL; 564 __s_api_free2dArray(mapping); 565 mapping = NULL; 566 if (gecos_mapping) 567 __s_api_free2dArray( 568 gecos_mapping); 569 gecos_mapping = NULL; 570 return (NS_LDAP_INTERNAL); 571 } 572 } 573 574 /* 575 * is this attribute the 1st, 2nd, or 576 * 3rd attr in the mapping list? 577 */ 578 gecos_attr_matched = FALSE; 579 for (i = 0; i < 3 && gecos_mapping[i]; i++) { 580 if (gecos_mapping[i] && 581 strcasecmp(gecos_mapping[i], 582 attr) == 0) { 583 gecos_val_index[i] = j; 584 gecos_attr_matched = TRUE; 585 break; 586 } 587 } 588 if (gecos_attr_matched == FALSE) { 589 /* 590 * Not match found. 591 * This should never happens, 592 * syslog the error 593 */ 594 (void) sprintf(errstr, 595 gettext( 596 "Attribute mapping " 597 "inconsistency " 598 "found for attributes " 599 "'%s' and '%s'."), 600 mapping[0], attr); 601 syslog(LOG_ERR, "libsldap: %s", errstr); 602 603 ber_free(ber, 0); 604 ber = NULL; 605 __ns_ldap_freeEntry(ep); 606 ep = NULL; 607 __s_api_free2dArray(mapping); 608 mapping = NULL; 609 __s_api_free2dArray(gecos_mapping); 610 gecos_mapping = NULL; 611 return (NS_LDAP_INTERNAL); 612 } 613 } 614 __s_api_free2dArray(mapping); 615 mapping = NULL; 616 } 617 618 if ((vals = ldap_get_values(ld, e, attr)) != NULL) { 619 620 if ((ap[j]->value_count = ldap_count_values(vals)) == 0) { 621 ldap_value_free(vals); 622 vals = NULL; 623 continue; 624 } else { 625 ap[j]->attrvalue = (char **) 626 calloc(ap[j]->value_count+1, sizeof (char *)); 627 if (ap[j]->attrvalue == NULL) { 628 ber_free(ber, 0); 629 ber = NULL; 630 __ns_ldap_freeEntry(ep); 631 ep = NULL; 632 if (gecos_mapping) 633 __s_api_free2dArray(gecos_mapping); 634 gecos_mapping = NULL; 635 return (NS_LDAP_MEMORY); 636 } 637 } 638 639 /* map object classes if necessary */ 640 if ((flags & NS_LDAP_NOMAP) == 0 && 641 schema_mapping_existed && ap[j]->attrname && 642 strcasecmp(ap[j]->attrname, "objectclass") == 0) { 643 for (k = 0; k < ap[j]->value_count; k++) { 644 mapping = 645 __ns_ldap_getOrigObjectClass(service, vals[k]); 646 647 if (mapping == NULL && auto_service) 648 /* 649 * if service == auto_* and no 650 * schema mapping found 651 * then try automount 652 */ 653 mapping = 654 __ns_ldap_getOrigObjectClass( 655 "automount", vals[k]); 656 657 if (mapping == NULL) { 658 ap[j]->attrvalue[k] = strdup(vals[k]); 659 } else { 660 ap[j]->attrvalue[k] = strdup(mapping[0]); 661 __s_api_free2dArray(mapping); 662 mapping = NULL; 663 } 664 if (ap[j]->attrvalue[k] == NULL) { 665 ber_free(ber, 0); 666 ber = NULL; 667 __ns_ldap_freeEntry(ep); 668 ep = NULL; 669 if (gecos_mapping) 670 __s_api_free2dArray(gecos_mapping); 671 gecos_mapping = NULL; 672 return (NS_LDAP_MEMORY); 673 } 674 } 675 } else { 676 for (k = 0; k < ap[j]->value_count; k++) { 677 if ((ap[j]->attrvalue[k] = strdup(vals[k])) == NULL) { 678 ber_free(ber, 0); 679 ber = NULL; 680 __ns_ldap_freeEntry(ep); 681 ep = NULL; 682 if (gecos_mapping) 683 __s_api_free2dArray(gecos_mapping); 684 gecos_mapping = NULL; 685 return (NS_LDAP_MEMORY); 686 } 687 } 688 } 689 690 ap[j]->attrvalue[k] = NULL; 691 ldap_value_free(vals); 692 vals = NULL; 693 } 694 695 ldap_memfree(attr); 696 attr = NULL; 697 } 698 699 ber_free(ber, 0); 700 ber = NULL; 701 702 if (gecos_mapping) { 703 __s_api_free2dArray(gecos_mapping); 704 gecos_mapping = NULL; 705 } 706 707 /* special processing for gecos 1 to up to 3 attribute mapping */ 708 if (schema_mapping_existed && gecos_mapping_existed) { 709 710 int f = -1; 711 712 for (i = 0; i < 3; i++) { 713 k = gecos_val_index[i]; 714 715 /* 716 * f is the index of the first returned 717 * attribute which "gecos" attribute mapped to 718 */ 719 if (k != -1 && f == -1) 720 f = k; 721 722 if (k != -1 && ap[k]->value_count > 0 && 723 ap[k]->attrvalue[0] && 724 strlen(ap[k]->attrvalue[0]) > 0) { 725 726 if (k == f) { 727 /* 728 * Create and fill in the last reserved 729 * ap with the data from the "gecos" 730 * mapping attributes 731 */ 732 ap[nAttrs] = (ns_ldap_attr_t *) 733 calloc(1, 734 sizeof (ns_ldap_attr_t)); 735 if (ap[nAttrs] == NULL) { 736 __ns_ldap_freeEntry(ep); 737 ep = NULL; 738 return (NS_LDAP_MEMORY); 739 } 740 ap[nAttrs]->attrvalue = (char **)calloc( 741 2, sizeof (char *)); 742 if (ap[nAttrs]->attrvalue == NULL) { 743 __ns_ldap_freeEntry(ep); 744 ep = NULL; 745 return (NS_LDAP_MEMORY); 746 } 747 /* add 1 more for a possible "," */ 748 ap[nAttrs]->attrvalue[0] = 749 (char *)calloc( 750 strlen(ap[f]->attrvalue[0]) + 751 2, 1); 752 if (ap[nAttrs]->attrvalue[0] == NULL) { 753 __ns_ldap_freeEntry(ep); 754 ep = NULL; 755 return (NS_LDAP_MEMORY); 756 } 757 (void) strcpy(ap[nAttrs]->attrvalue[0], 758 ap[f]->attrvalue[0]); 759 760 ap[nAttrs]->attrname = strdup("gecos"); 761 if (ap[nAttrs]->attrname == NULL) { 762 __ns_ldap_freeEntry(ep); 763 ep = NULL; 764 return (NS_LDAP_MEMORY); 765 } 766 767 ap[nAttrs]->value_count = 1; 768 ep->attr_count = nAttrs + 1; 769 770 } else { 771 char *tmp = NULL; 772 773 /* 774 * realloc to add "," and 775 * ap[k]->attrvalue[0] 776 */ 777 tmp = (char *)realloc( 778 ap[nAttrs]->attrvalue[0], 779 strlen(ap[nAttrs]-> 780 attrvalue[0]) + 781 strlen(ap[k]-> 782 attrvalue[0]) + 2); 783 if (tmp == NULL) { 784 __ns_ldap_freeEntry(ep); 785 ep = NULL; 786 return (NS_LDAP_MEMORY); 787 } 788 ap[nAttrs]->attrvalue[0] = tmp; 789 (void) strcat(ap[nAttrs]->attrvalue[0], 790 ","); 791 (void) strcat(ap[nAttrs]->attrvalue[0], 792 ap[k]->attrvalue[0]); 793 } 794 } 795 } 796 } 797 798 *ret = ep; 799 return (NS_LDAP_SUCCESS); 800 } 801 802 static int 803 __s_api_getEntry(ns_ldap_cookie_t *cookie) 804 { 805 ns_ldap_entry_t *curEntry = NULL; 806 int ret; 807 808 #ifdef DEBUG 809 (void) fprintf(stderr, "__s_api_getEntry START\n"); 810 #endif 811 812 if (cookie->resultMsg == NULL) { 813 return (NS_LDAP_INVALID_PARAM); 814 } 815 ret = __s_api_cvtEntry(cookie->conn->ld, cookie->service, 816 cookie->resultMsg, cookie->i_flags, 817 &curEntry, &cookie->errorp); 818 if (ret != NS_LDAP_SUCCESS) { 819 return (ret); 820 } 821 822 if (cookie->result == NULL) { 823 cookie->result = (ns_ldap_result_t *) 824 calloc(1, sizeof (ns_ldap_result_t)); 825 if (cookie->result == NULL) { 826 __ns_ldap_freeEntry(curEntry); 827 curEntry = NULL; 828 return (NS_LDAP_MEMORY); 829 } 830 cookie->result->entry = curEntry; 831 cookie->nextEntry = curEntry; 832 } else { 833 cookie->nextEntry->next = curEntry; 834 cookie->nextEntry = curEntry; 835 } 836 cookie->result->entries_count++; 837 838 return (NS_LDAP_SUCCESS); 839 } 840 841 static int 842 __s_api_get_cachemgr_data(const char *type, 843 const char *from, char **to) 844 { 845 union { 846 ldap_data_t s_d; 847 char s_b[DOORBUFFERSIZE]; 848 } space; 849 ldap_data_t *sptr; 850 int ndata; 851 int adata; 852 int rc; 853 854 #ifdef DEBUG 855 (void) fprintf(stderr, "__s_api_get_cachemgr_data START\n"); 856 #endif 857 858 if (from == NULL || from[0] == '\0' || to == NULL) 859 return (-1); 860 861 *to = NULL; 862 (void) memset(space.s_b, 0, DOORBUFFERSIZE); 863 864 space.s_d.ldap_call.ldap_callnumber = GETCACHE; 865 (void) snprintf(space.s_d.ldap_call.ldap_u.domainname, 866 DOORBUFFERSIZE - sizeof (space.s_d.ldap_call.ldap_callnumber), 867 "%s%s%s", 868 type, 869 DOORLINESEP, 870 from); 871 ndata = sizeof (space); 872 adata = sizeof (ldap_call_t) + 873 strlen(space.s_d.ldap_call.ldap_u.domainname) + 1; 874 sptr = &space.s_d; 875 876 rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata); 877 if (rc != SUCCESS) 878 return (-1); 879 else 880 *to = strdup(sptr->ldap_ret.ldap_u.buff); 881 return (NS_LDAP_SUCCESS); 882 } 883 884 static int 885 __s_api_set_cachemgr_data(const char *type, 886 const char *from, const char *to) 887 { 888 union { 889 ldap_data_t s_d; 890 char s_b[DOORBUFFERSIZE]; 891 } space; 892 ldap_data_t *sptr; 893 int ndata; 894 int adata; 895 int rc; 896 897 #ifdef DEBUG 898 (void) fprintf(stderr, "__s_api_set_cachemgr_data START\n"); 899 #endif 900 901 if ((from == NULL) || (from[0] == '\0') || 902 (to == NULL) || (to[0] == '\0')) 903 return (-1); 904 905 (void) memset(space.s_b, 0, DOORBUFFERSIZE); 906 907 space.s_d.ldap_call.ldap_callnumber = SETCACHE; 908 (void) snprintf(space.s_d.ldap_call.ldap_u.domainname, 909 DOORBUFFERSIZE - sizeof (space.s_d.ldap_call.ldap_callnumber), 910 "%s%s%s%s%s", 911 type, 912 DOORLINESEP, 913 from, 914 DOORLINESEP, 915 to); 916 917 ndata = sizeof (space); 918 adata = sizeof (ldap_call_t) + 919 strlen(space.s_d.ldap_call.ldap_u.domainname) + 1; 920 sptr = &space.s_d; 921 922 rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata); 923 if (rc != SUCCESS) 924 return (-1); 925 926 return (NS_LDAP_SUCCESS); 927 } 928 929 930 static char * 931 __s_api_remove_rdn_space(char *rdn) 932 { 933 char *tf, *tl, *vf, *vl, *eqsign; 934 935 /* if no space(s) to remove, return */ 936 if (strchr(rdn, SPACETOK) == NULL) 937 return (rdn); 938 939 /* if no '=' separator, return */ 940 eqsign = strchr(rdn, '='); 941 if (eqsign == NULL) 942 return (rdn); 943 944 tf = rdn; 945 tl = eqsign - 1; 946 vf = eqsign + 1; 947 vl = rdn + strlen(rdn) - 1; 948 949 /* now two strings, type and value */ 950 *eqsign = '\0'; 951 952 /* remove type's leading spaces */ 953 while (tf < tl && *tf == SPACETOK) 954 tf++; 955 /* remove type's trailing spaces */ 956 while (tf < tl && *tl == SPACETOK) 957 tl--; 958 /* add '=' separator back */ 959 *(++tl) = '='; 960 /* remove value's leading spaces */ 961 while (vf < vl && *vf == SPACETOK) 962 vf++; 963 /* remove value's trailing spaces */ 964 while (vf < vl && *vl == SPACETOK) 965 *vl-- = '\0'; 966 967 /* move value up if necessary */ 968 if (vf != tl + 1) 969 (void) strcpy(tl + 1, vf); 970 971 return (tf); 972 } 973 974 static 975 ns_ldap_cookie_t * 976 init_search_state_machine() 977 { 978 ns_ldap_cookie_t *cookie; 979 ns_config_t *cfg; 980 981 cookie = (ns_ldap_cookie_t *)calloc(1, sizeof (ns_ldap_cookie_t)); 982 if (cookie == NULL) 983 return (NULL); 984 cookie->state = INIT; 985 /* assign other state variables */ 986 cfg = __s_api_loadrefresh_config(); 987 cookie->connectionId = -1; 988 if (cfg == NULL || 989 cfg->paramList[NS_LDAP_SEARCH_TIME_P].ns_ptype == NS_UNKNOWN) { 990 cookie->search_timeout.tv_sec = NS_DEFAULT_SEARCH_TIMEOUT; 991 } else { 992 cookie->search_timeout.tv_sec = 993 cfg->paramList[NS_LDAP_SEARCH_TIME_P].ns_i; 994 } 995 if (cfg != NULL) 996 __s_api_release_config(cfg); 997 cookie->search_timeout.tv_usec = 0; 998 999 return (cookie); 1000 } 1001 1002 static void 1003 delete_search_cookie(ns_ldap_cookie_t *cookie) 1004 { 1005 if (cookie == NULL) 1006 return; 1007 if (cookie->connectionId > -1) 1008 DropConnection(cookie->connectionId, cookie->i_flags); 1009 if (cookie->filter) 1010 free(cookie->filter); 1011 if (cookie->i_filter) 1012 free(cookie->i_filter); 1013 if (cookie->service) 1014 free(cookie->service); 1015 if (cookie->sdlist) 1016 (void) __ns_ldap_freeSearchDescriptors(&(cookie->sdlist)); 1017 if (cookie->result) 1018 (void) __ns_ldap_freeResult(&cookie->result); 1019 if (cookie->attribute) 1020 __s_api_free2dArray(cookie->attribute); 1021 if (cookie->errorp) 1022 (void) __ns_ldap_freeError(&cookie->errorp); 1023 if (cookie->reflist) 1024 __s_api_deleteRefInfo(cookie->reflist); 1025 if (cookie->basedn) 1026 free(cookie->basedn); 1027 if (cookie->ctrlCookie) 1028 ber_bvfree(cookie->ctrlCookie); 1029 _freeControlList(&cookie->p_serverctrls); 1030 if (cookie->resultctrl) 1031 ldap_controls_free(cookie->resultctrl); 1032 free(cookie); 1033 } 1034 1035 static int 1036 get_mapped_filter(ns_ldap_cookie_t *cookie, char **new_filter) 1037 { 1038 1039 typedef struct filter_mapping_info { 1040 char oc_or_attr; 1041 char *name_start; 1042 char *name_end; 1043 char *veq_pos; 1044 char *from_name; 1045 char *to_name; 1046 char **mapping; 1047 } filter_mapping_info_t; 1048 1049 char *c, *last_copied; 1050 char *filter_c, *filter_c_next; 1051 char *key, *tail, *head; 1052 char errstr[MAXERROR]; 1053 int num_eq = 0, num_veq = 0; 1054 int in_quote = FALSE; 1055 int is_value = FALSE; 1056 int i, j, oc_len, len; 1057 int at_least_one = FALSE; 1058 filter_mapping_info_t **info, *info1; 1059 char **mapping; 1060 char *service, *filter, *err; 1061 int auto_service = FALSE; 1062 1063 if (cookie == NULL || new_filter == NULL) 1064 return (NS_LDAP_INVALID_PARAM); 1065 1066 *new_filter = NULL; 1067 service = cookie->service; 1068 filter = cookie->filter; 1069 1070 /* 1071 * count the number of '=' char 1072 */ 1073 for (c = filter; *c; c++) { 1074 if (*c == TOKENSEPARATOR) 1075 num_eq++; 1076 } 1077 1078 if (service != NULL && strncasecmp(service, "auto_", 5) == 0) 1079 auto_service = TRUE; 1080 1081 /* 1082 * See if schema mapping existed for the given service. 1083 * If not, just return success. 1084 */ 1085 mapping = __ns_ldap_getOrigAttribute(service, 1086 NS_HASH_SCHEMA_MAPPING_EXISTED); 1087 1088 if (mapping == NULL && auto_service) 1089 /* 1090 * if service == auto_* and no 1091 * schema mapping found 1092 * then try automount 1093 */ 1094 mapping = __ns_ldap_getOrigAttribute( 1095 "automount", NS_HASH_SCHEMA_MAPPING_EXISTED); 1096 1097 if (mapping) 1098 __s_api_free2dArray(mapping); 1099 else 1100 return (NS_LDAP_SUCCESS); 1101 1102 /* 1103 * no '=' sign, just say OK and return nothing 1104 */ 1105 if (num_eq == 0) 1106 return (NS_LDAP_SUCCESS); 1107 1108 /* 1109 * Make a copy of the filter string 1110 * for saving the name of the objectclasses or 1111 * attributes that need to be passed to the 1112 * objectclass or attribute mapping functions. 1113 * pointer "info->from_name" points to the locations 1114 * within this string. 1115 * 1116 * The input filter string, filter, will be used 1117 * to indicate where these names start and end. 1118 * pointers "info->name_start" and "info->name_end" 1119 * point to locations within the input filter string, 1120 * and are used at the end of this function to 1121 * merge the original filter data with the 1122 * mapped objectclass or attribute names. 1123 */ 1124 filter_c = strdup(filter); 1125 if (filter_c == NULL) 1126 return (NS_LDAP_MEMORY); 1127 filter_c_next = filter_c; 1128 1129 /* 1130 * get memory for info arrays 1131 */ 1132 info = (filter_mapping_info_t **)calloc(num_eq + 1, 1133 sizeof (filter_mapping_info_t *)); 1134 1135 if (info == NULL) { 1136 free(filter_c); 1137 return (NS_LDAP_MEMORY); 1138 } 1139 1140 /* 1141 * find valid '=' for further processing, 1142 * ignore the "escaped =" (.i.e. "\="), or 1143 * "=" in quoted string 1144 */ 1145 for (c = filter_c; *c; c++) { 1146 1147 switch (*c) { 1148 case TOKENSEPARATOR: 1149 if (!in_quote && !is_value) { 1150 info1 = (filter_mapping_info_t *)calloc(1, 1151 sizeof (filter_mapping_info_t)); 1152 if (!info1) { 1153 free(filter_c); 1154 for (i = 0; i < num_veq; i++) 1155 free(info[i]); 1156 free(info); 1157 return (NS_LDAP_MEMORY); 1158 } 1159 info[num_veq] = info1; 1160 1161 /* 1162 * remember the location of this "=" 1163 */ 1164 info[num_veq++]->veq_pos = c; 1165 1166 /* 1167 * skip until the end of the attribute value 1168 */ 1169 is_value = TRUE; 1170 } 1171 break; 1172 case CPARATOK: 1173 /* 1174 * mark the end of the attribute value 1175 */ 1176 if (!in_quote) 1177 is_value = FALSE; 1178 break; 1179 case QUOTETOK: 1180 /* 1181 * switch on/off the in_quote mode 1182 */ 1183 in_quote = (in_quote == FALSE); 1184 break; 1185 case '\\': 1186 /* 1187 * ignore escape characters 1188 * don't skip if next char is '\0' 1189 */ 1190 if (!in_quote) 1191 if (*(++c) == '\0') 1192 c--; 1193 break; 1194 } 1195 1196 } 1197 1198 /* 1199 * for each valid "=" found, get the name to 1200 * be mapped 1201 */ 1202 oc_len = strlen("objectclass"); 1203 for (i = 0; i < num_veq; i++) { 1204 1205 /* 1206 * look at the left side of "=" to see 1207 * if assertion is "objectclass=<ocname>" 1208 * or "<attribute name>=<attribute value>" 1209 * 1210 * first skip spaces before "=". 1211 * Note that filter_c_next may not point to the 1212 * start of the filter string. For i > 0, 1213 * it points to the end of the last name processed + 2 1214 */ 1215 for (tail = info[i]->veq_pos; (tail > filter_c_next) && 1216 (*(tail - 1) == SPACETOK); tail--); 1217 1218 /* 1219 * mark the end of the left side string (the key) 1220 */ 1221 *tail = '\0'; 1222 info[i]->name_end = tail - filter_c - 1 + filter; 1223 1224 /* 1225 * find the start of the key 1226 */ 1227 key = filter_c_next; 1228 for (c = tail; filter_c_next <= c; c--) { 1229 /* OPARATOK is '(' */ 1230 if (*c == OPARATOK || 1231 *c == SPACETOK) { 1232 key = c + 1; 1233 break; 1234 } 1235 } 1236 info[i]->name_start = key - filter_c + filter; 1237 1238 if ((key + oc_len) <= tail) { 1239 if (strncasecmp(key, "objectclass", 1240 oc_len) == 0) { 1241 /* 1242 * assertion is "objectclass=ocname", 1243 * ocname is the one needs to be mapped 1244 * 1245 * skip spaces after "=" to find start 1246 * of the ocname 1247 */ 1248 head = info[i]->veq_pos; 1249 for (head = info[i]->veq_pos + 1; 1250 *head && *head == SPACETOK; head++); 1251 1252 /* ignore empty ocname */ 1253 if (!(*head)) 1254 continue; 1255 1256 info[i]->name_start = head - filter_c + 1257 filter; 1258 1259 /* 1260 * now find the end of the ocname 1261 */ 1262 for (c = head; ; c++) { 1263 /* CPARATOK is ')' */ 1264 if (*c == CPARATOK || 1265 *c == '\0' || 1266 *c == SPACETOK) { 1267 *c = '\0'; 1268 info[i]->name_end = 1269 c - filter_c - 1 + 1270 filter; 1271 filter_c_next = c + 1; 1272 info[i]->oc_or_attr = 'o'; 1273 info[i]->from_name = head; 1274 break; 1275 } 1276 } 1277 } 1278 } 1279 1280 /* 1281 * assertion is not "objectclass=ocname", 1282 * assume assertion is "<key> = <value>", 1283 * <key> is the one needs to be mapped 1284 */ 1285 if (info[i]->from_name == NULL && strlen(key) > 0) { 1286 info[i]->oc_or_attr = 'a'; 1287 info[i]->from_name = key; 1288 } 1289 } 1290 1291 /* perform schema mapping */ 1292 for (i = 0; i < num_veq; i++) { 1293 if (info[i]->from_name == NULL) 1294 continue; 1295 1296 if (info[i]->oc_or_attr == 'a') 1297 info[i]->mapping = 1298 __ns_ldap_getMappedAttributes(service, 1299 info[i]->from_name); 1300 else 1301 info[i]->mapping = 1302 __ns_ldap_getMappedObjectClass(service, 1303 info[i]->from_name); 1304 1305 if (info[i]->mapping == NULL && auto_service) { 1306 /* 1307 * If no mapped attribute/objectclass is found 1308 * and service == auto* 1309 * try to find automount's 1310 * mapped attribute/objectclass 1311 */ 1312 if (info[i]->oc_or_attr == 'a') 1313 info[i]->mapping = 1314 __ns_ldap_getMappedAttributes("automount", 1315 info[i]->from_name); 1316 else 1317 info[i]->mapping = 1318 __ns_ldap_getMappedObjectClass("automount", 1319 info[i]->from_name); 1320 } 1321 1322 if (info[i]->mapping == NULL || 1323 info[i]->mapping[0] == NULL) { 1324 info[i]->to_name = NULL; 1325 } else if (info[i]->mapping[1] == NULL) { 1326 info[i]->to_name = info[i]->mapping[0]; 1327 at_least_one = TRUE; 1328 } else { 1329 __s_api_free2dArray(info[i]->mapping); 1330 /* 1331 * multiple mapping 1332 * not allowed 1333 */ 1334 (void) sprintf(errstr, 1335 gettext( 1336 "Multiple attribute or objectclass " 1337 "mapping for '%s' in filter " 1338 "'%s' not allowed."), 1339 info[i]->from_name, filter); 1340 err = strdup(errstr); 1341 if (err) 1342 MKERROR(LOG_WARNING, cookie->errorp, 1343 NS_CONFIG_SYNTAX, 1344 err, NULL); 1345 1346 free(filter_c); 1347 for (j = 0; j < num_veq; j++) { 1348 if (info[j]->mapping) 1349 __s_api_free2dArray( 1350 info[j]->mapping); 1351 free(info[j]); 1352 } 1353 free(info); 1354 return (NS_LDAP_CONFIG); 1355 } 1356 } 1357 1358 1359 if (at_least_one) { 1360 1361 len = strlen(filter); 1362 last_copied = filter - 1; 1363 1364 for (i = 0; i < num_veq; i++) { 1365 if (info[i]->to_name) 1366 len += strlen(info[i]->to_name); 1367 } 1368 1369 *new_filter = (char *)calloc(1, len); 1370 if (*new_filter == NULL) { 1371 free(filter_c); 1372 for (j = 0; j < num_veq; j++) { 1373 if (info[j]->mapping) 1374 __s_api_free2dArray( 1375 info[j]->mapping); 1376 free(info[j]); 1377 } 1378 free(info); 1379 return (NS_LDAP_MEMORY); 1380 } 1381 1382 for (i = 0; i < num_veq; i++) { 1383 if (info[i]->to_name != NULL && 1384 info[i]->to_name != NULL) { 1385 1386 /* 1387 * copy the original filter data 1388 * between the last name and current 1389 * name 1390 */ 1391 if ((last_copied + 1) != info[i]->name_start) 1392 (void) strncat(*new_filter, last_copied + 1, 1393 info[i]->name_start - 1394 last_copied - 1); 1395 1396 /* the data is copied */ 1397 last_copied = info[i]->name_end; 1398 1399 /* 1400 * replace the name with 1401 * the mapped name 1402 */ 1403 (void) strcat(*new_filter, info[i]->to_name); 1404 } 1405 1406 /* copy the filter data after the last name */ 1407 if (i == (num_veq -1) && 1408 info[i]->name_end < 1409 (filter + strlen(filter))) 1410 (void) strncat(*new_filter, last_copied + 1, 1411 filter + strlen(filter) - 1412 last_copied - 1); 1413 } 1414 1415 } 1416 1417 /* free memory */ 1418 free(filter_c); 1419 for (j = 0; j < num_veq; j++) { 1420 if (info[j]->mapping) 1421 __s_api_free2dArray(info[j]->mapping); 1422 free(info[j]); 1423 } 1424 free(info); 1425 1426 return (NS_LDAP_SUCCESS); 1427 } 1428 1429 static int 1430 setup_next_search(ns_ldap_cookie_t *cookie) 1431 { 1432 ns_ldap_search_desc_t *dptr; 1433 int scope; 1434 char *filter, *str; 1435 int baselen; 1436 int rc; 1437 void **param; 1438 1439 dptr = *cookie->sdpos; 1440 scope = cookie->i_flags & (NS_LDAP_SCOPE_BASE | 1441 NS_LDAP_SCOPE_ONELEVEL | 1442 NS_LDAP_SCOPE_SUBTREE); 1443 if (scope) 1444 cookie->scope = scope; 1445 else 1446 cookie->scope = dptr->scope; 1447 switch (cookie->scope) { 1448 case NS_LDAP_SCOPE_BASE: 1449 cookie->scope = LDAP_SCOPE_BASE; 1450 break; 1451 case NS_LDAP_SCOPE_ONELEVEL: 1452 cookie->scope = LDAP_SCOPE_ONELEVEL; 1453 break; 1454 case NS_LDAP_SCOPE_SUBTREE: 1455 cookie->scope = LDAP_SCOPE_SUBTREE; 1456 break; 1457 } 1458 1459 filter = NULL; 1460 if (cookie->use_filtercb && cookie->init_filter_cb && 1461 dptr->filter && strlen(dptr->filter) > 0) { 1462 (*cookie->init_filter_cb)(dptr, &filter, 1463 cookie->userdata); 1464 } 1465 if (filter == NULL) { 1466 if (cookie->i_filter == NULL) { 1467 cookie->err_rc = NS_LDAP_INVALID_PARAM; 1468 return (-1); 1469 } else { 1470 if (cookie->filter) 1471 free(cookie->filter); 1472 cookie->filter = strdup(cookie->i_filter); 1473 if (cookie->filter == NULL) { 1474 cookie->err_rc = NS_LDAP_MEMORY; 1475 return (-1); 1476 } 1477 } 1478 } else { 1479 if (cookie->filter) 1480 free(cookie->filter); 1481 cookie->filter = strdup(filter); 1482 free(filter); 1483 if (cookie->filter == NULL) { 1484 cookie->err_rc = NS_LDAP_MEMORY; 1485 return (-1); 1486 } 1487 } 1488 1489 /* 1490 * perform attribute/objectclass mapping on filter 1491 */ 1492 filter = NULL; 1493 1494 if (cookie->service) { 1495 rc = get_mapped_filter(cookie, &filter); 1496 if (rc != NS_LDAP_SUCCESS) { 1497 cookie->err_rc = rc; 1498 return (-1); 1499 } else { 1500 /* 1501 * get_mapped_filter returns 1502 * NULL filter pointer, if 1503 * no mapping was done 1504 */ 1505 if (filter) { 1506 free(cookie->filter); 1507 cookie->filter = filter; 1508 } 1509 } 1510 } 1511 1512 /* 1513 * validate filter to make sure it's legal 1514 * [remove redundant ()'s] 1515 */ 1516 rc = validate_filter(cookie); 1517 if (rc != NS_LDAP_SUCCESS) { 1518 cookie->err_rc = rc; 1519 return (-1); 1520 } 1521 1522 baselen = strlen(dptr->basedn); 1523 if (baselen > 0 && dptr->basedn[baselen-1] == COMMATOK) { 1524 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 1525 (void ***)¶m, &cookie->errorp); 1526 if (rc != NS_LDAP_SUCCESS) { 1527 cookie->err_rc = rc; 1528 return (-1); 1529 } 1530 str = ((char **)param)[0]; 1531 baselen += strlen(str)+1; 1532 if (cookie->basedn) 1533 free(cookie->basedn); 1534 cookie->basedn = (char *)malloc(baselen); 1535 if (cookie->basedn == NULL) { 1536 cookie->err_rc = NS_LDAP_MEMORY; 1537 return (-1); 1538 } 1539 (void) strcpy(cookie->basedn, dptr->basedn); 1540 (void) strcat(cookie->basedn, str); 1541 (void) __ns_ldap_freeParam(¶m); 1542 } else { 1543 if (cookie->basedn) 1544 free(cookie->basedn); 1545 cookie->basedn = strdup(dptr->basedn); 1546 } 1547 return (0); 1548 } 1549 1550 static int 1551 setup_referral_search(ns_ldap_cookie_t *cookie) 1552 { 1553 ns_referral_info_t *ref; 1554 1555 ref = cookie->refpos; 1556 cookie->scope = ref->refScope; 1557 if (cookie->filter) { 1558 free(cookie->filter); 1559 } 1560 cookie->filter = strdup(ref->refFilter); 1561 if (cookie->basedn) { 1562 free(cookie->basedn); 1563 } 1564 cookie->basedn = strdup(ref->refDN); 1565 if (cookie->filter == NULL || cookie->basedn == NULL) { 1566 cookie->err_rc = NS_LDAP_MEMORY; 1567 return (-1); 1568 } 1569 return (0); 1570 } 1571 1572 static int 1573 get_current_session(ns_ldap_cookie_t *cookie) 1574 { 1575 ConnectionID connectionId = -1; 1576 Connection *conp = NULL; 1577 int rc; 1578 int fail_if_new_pwd_reqd = 1; 1579 1580 rc = __s_api_getConnection(NULL, cookie->i_flags, 1581 cookie->i_auth, &connectionId, &conp, 1582 &cookie->errorp, fail_if_new_pwd_reqd, 1583 cookie->nopasswd_acct_mgmt); 1584 1585 /* 1586 * If password control attached in *cookie->errorp, 1587 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 1588 * free the error structure (we do not need 1589 * the sec_to_expired info). 1590 * Reset rc to NS_LDAP_SUCCESS. 1591 */ 1592 if (rc == NS_LDAP_SUCCESS_WITH_INFO) { 1593 (void) __ns_ldap_freeError( 1594 &cookie->errorp); 1595 cookie->errorp = NULL; 1596 rc = NS_LDAP_SUCCESS; 1597 } 1598 1599 if (rc != NS_LDAP_SUCCESS) { 1600 cookie->err_rc = rc; 1601 return (-1); 1602 } 1603 cookie->conn = conp; 1604 cookie->connectionId = connectionId; 1605 1606 return (0); 1607 } 1608 1609 static int 1610 get_next_session(ns_ldap_cookie_t *cookie) 1611 { 1612 ConnectionID connectionId = -1; 1613 Connection *conp = NULL; 1614 int rc; 1615 int fail_if_new_pwd_reqd = 1; 1616 1617 if (cookie->connectionId > -1) 1618 DropConnection(cookie->connectionId, cookie->i_flags); 1619 1620 rc = __s_api_getConnection(NULL, cookie->i_flags, 1621 cookie->i_auth, &connectionId, &conp, 1622 &cookie->errorp, fail_if_new_pwd_reqd, 1623 cookie->nopasswd_acct_mgmt); 1624 1625 /* 1626 * If password control attached in *cookie->errorp, 1627 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 1628 * free the error structure (we do not need 1629 * the sec_to_expired info). 1630 * Reset rc to NS_LDAP_SUCCESS. 1631 */ 1632 if (rc == NS_LDAP_SUCCESS_WITH_INFO) { 1633 (void) __ns_ldap_freeError( 1634 &cookie->errorp); 1635 cookie->errorp = NULL; 1636 rc = NS_LDAP_SUCCESS; 1637 } 1638 1639 if (rc != NS_LDAP_SUCCESS) { 1640 cookie->err_rc = rc; 1641 return (-1); 1642 } 1643 cookie->conn = conp; 1644 cookie->connectionId = connectionId; 1645 return (0); 1646 } 1647 1648 static int 1649 get_referral_session(ns_ldap_cookie_t *cookie) 1650 { 1651 ConnectionID connectionId = -1; 1652 Connection *conp = NULL; 1653 int rc; 1654 int fail_if_new_pwd_reqd = 1; 1655 1656 if (cookie->connectionId > -1) 1657 DropConnection(cookie->connectionId, cookie->i_flags); 1658 1659 rc = __s_api_getConnection(cookie->refpos->refHost, 0, 1660 cookie->i_auth, &connectionId, &conp, 1661 &cookie->errorp, fail_if_new_pwd_reqd, 1662 cookie->nopasswd_acct_mgmt); 1663 1664 /* 1665 * If password control attached in *cookie->errorp, 1666 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 1667 * free the error structure (we do not need 1668 * the sec_to_expired info). 1669 * Reset rc to NS_LDAP_SUCCESS. 1670 */ 1671 if (rc == NS_LDAP_SUCCESS_WITH_INFO) { 1672 (void) __ns_ldap_freeError( 1673 &cookie->errorp); 1674 cookie->errorp = NULL; 1675 rc = NS_LDAP_SUCCESS; 1676 } 1677 1678 if (rc != NS_LDAP_SUCCESS) { 1679 cookie->err_rc = rc; 1680 return (-1); 1681 } 1682 cookie->conn = conp; 1683 cookie->connectionId = connectionId; 1684 return (0); 1685 } 1686 1687 static int 1688 paging_supported(ns_ldap_cookie_t *cookie) 1689 { 1690 int rc; 1691 1692 cookie->listType = 0; 1693 rc = __s_api_isCtrlSupported(cookie->conn, 1694 LDAP_CONTROL_VLVREQUEST); 1695 if (rc == NS_LDAP_SUCCESS) { 1696 cookie->listType = VLVCTRLFLAG; 1697 return (1); 1698 } 1699 rc = __s_api_isCtrlSupported(cookie->conn, 1700 LDAP_CONTROL_SIMPLE_PAGE); 1701 if (rc == NS_LDAP_SUCCESS) { 1702 cookie->listType = SIMPLEPAGECTRLFLAG; 1703 return (1); 1704 } 1705 return (0); 1706 } 1707 1708 static int 1709 setup_vlv_params(ns_ldap_cookie_t *cookie) 1710 { 1711 LDAPControl **ctrls; 1712 LDAPsortkey **sortkeylist; 1713 LDAPControl *sortctrl = NULL; 1714 LDAPControl *vlvctrl = NULL; 1715 LDAPVirtualList vlist; 1716 int rc; 1717 1718 _freeControlList(&cookie->p_serverctrls); 1719 1720 rc = ldap_create_sort_keylist(&sortkeylist, SORTKEYLIST); 1721 if (rc != LDAP_SUCCESS) { 1722 (void) ldap_get_option(cookie->conn->ld, 1723 LDAP_OPT_ERROR_NUMBER, &rc); 1724 return (rc); 1725 } 1726 rc = ldap_create_sort_control(cookie->conn->ld, 1727 sortkeylist, 1, &sortctrl); 1728 ldap_free_sort_keylist(sortkeylist); 1729 if (rc != LDAP_SUCCESS) { 1730 (void) ldap_get_option(cookie->conn->ld, 1731 LDAP_OPT_ERROR_NUMBER, &rc); 1732 return (rc); 1733 } 1734 1735 vlist.ldvlist_index = cookie->index; 1736 vlist.ldvlist_size = 0; 1737 1738 vlist.ldvlist_before_count = 0; 1739 vlist.ldvlist_after_count = LISTPAGESIZE-1; 1740 vlist.ldvlist_attrvalue = NULL; 1741 vlist.ldvlist_extradata = NULL; 1742 1743 rc = ldap_create_virtuallist_control(cookie->conn->ld, 1744 &vlist, &vlvctrl); 1745 if (rc != LDAP_SUCCESS) { 1746 ldap_control_free(sortctrl); 1747 (void) ldap_get_option(cookie->conn->ld, LDAP_OPT_ERROR_NUMBER, 1748 &rc); 1749 return (rc); 1750 } 1751 1752 ctrls = (LDAPControl **)calloc(3, sizeof (LDAPControl *)); 1753 if (ctrls == NULL) { 1754 ldap_control_free(sortctrl); 1755 ldap_control_free(vlvctrl); 1756 return (LDAP_NO_MEMORY); 1757 } 1758 1759 ctrls[0] = sortctrl; 1760 ctrls[1] = vlvctrl; 1761 1762 cookie->p_serverctrls = ctrls; 1763 return (LDAP_SUCCESS); 1764 } 1765 1766 static int 1767 setup_simplepg_params(ns_ldap_cookie_t *cookie) 1768 { 1769 LDAPControl **ctrls; 1770 LDAPControl *pgctrl = NULL; 1771 int rc; 1772 1773 _freeControlList(&cookie->p_serverctrls); 1774 1775 rc = ldap_create_page_control(cookie->conn->ld, LISTPAGESIZE, 1776 cookie->ctrlCookie, (char)0, &pgctrl); 1777 if (rc != LDAP_SUCCESS) { 1778 (void) ldap_get_option(cookie->conn->ld, LDAP_OPT_ERROR_NUMBER, 1779 &rc); 1780 return (rc); 1781 } 1782 1783 ctrls = (LDAPControl **)calloc(2, sizeof (LDAPControl *)); 1784 if (ctrls == NULL) { 1785 ldap_control_free(pgctrl); 1786 return (LDAP_NO_MEMORY); 1787 } 1788 ctrls[0] = pgctrl; 1789 cookie->p_serverctrls = ctrls; 1790 return (LDAP_SUCCESS); 1791 } 1792 1793 static void 1794 proc_result_referrals(ns_ldap_cookie_t *cookie) 1795 { 1796 int errCode, i, rc; 1797 char **referrals = NULL; 1798 1799 /* 1800 * Only follow one level of referrals, i.e. 1801 * if already in referral mode, do nothing 1802 */ 1803 if (cookie->refpos == NULL) { 1804 cookie->new_state = END_RESULT; 1805 rc = ldap_parse_result(cookie->conn->ld, 1806 cookie->resultMsg, 1807 &errCode, NULL, 1808 NULL, &referrals, 1809 NULL, 0); 1810 if (rc != NS_LDAP_SUCCESS) { 1811 (void) ldap_get_option(cookie->conn->ld, 1812 LDAP_OPT_ERROR_NUMBER, 1813 &cookie->err_rc); 1814 cookie->new_state = LDAP_ERROR; 1815 return; 1816 } 1817 if (errCode == LDAP_REFERRAL) { 1818 for (i = 0; referrals[i] != NULL; 1819 i++) { 1820 /* add to referral list */ 1821 rc = __s_api_addRefInfo( 1822 &cookie->reflist, 1823 referrals[i], 1824 cookie->basedn, 1825 &cookie->scope, 1826 cookie->filter, 1827 cookie->conn->ld); 1828 if (rc != NS_LDAP_SUCCESS) { 1829 cookie->new_state = 1830 ERROR; 1831 break; 1832 } 1833 } 1834 ldap_value_free(referrals); 1835 } 1836 } 1837 } 1838 1839 static void 1840 proc_search_references(ns_ldap_cookie_t *cookie) 1841 { 1842 char **refurls = NULL; 1843 int i, rc; 1844 1845 /* 1846 * Only follow one level of referrals, i.e. 1847 * if already in referral mode, do nothing 1848 */ 1849 if (cookie->refpos == NULL) { 1850 refurls = ldap_get_reference_urls( 1851 cookie->conn->ld, 1852 cookie->resultMsg); 1853 if (refurls == NULL) { 1854 (void) ldap_get_option(cookie->conn->ld, 1855 LDAP_OPT_ERROR_NUMBER, 1856 &cookie->err_rc); 1857 cookie->new_state = LDAP_ERROR; 1858 return; 1859 } 1860 for (i = 0; refurls[i] != NULL; i++) { 1861 /* add to referral list */ 1862 rc = __s_api_addRefInfo( 1863 &cookie->reflist, 1864 refurls[i], 1865 cookie->basedn, 1866 &cookie->scope, 1867 cookie->filter, 1868 cookie->conn->ld); 1869 if (rc != NS_LDAP_SUCCESS) { 1870 cookie->new_state = 1871 ERROR; 1872 break; 1873 } 1874 } 1875 /* free allocated storage */ 1876 for (i = 0; refurls[i] != NULL; i++) 1877 free(refurls[i]); 1878 } 1879 } 1880 1881 static ns_state_t 1882 multi_result(ns_ldap_cookie_t *cookie) 1883 { 1884 char errstr[MAXERROR]; 1885 char *err; 1886 ns_ldap_error_t **errorp = NULL; 1887 LDAPControl **retCtrls = NULL; 1888 int i, rc; 1889 int errCode; 1890 int finished = 0; 1891 unsigned long target_posp = 0; 1892 unsigned long list_size = 0; 1893 unsigned int count = 0; 1894 char **referrals = NULL; 1895 1896 if (cookie->listType == VLVCTRLFLAG) { 1897 rc = ldap_parse_result(cookie->conn->ld, cookie->resultMsg, 1898 &errCode, NULL, NULL, &referrals, &retCtrls, 0); 1899 if (rc != LDAP_SUCCESS) { 1900 (void) ldap_get_option(cookie->conn->ld, 1901 LDAP_OPT_ERROR_NUMBER, 1902 &cookie->err_rc); 1903 (void) sprintf(errstr, 1904 gettext("LDAP ERROR (%d): %s.\n"), 1905 cookie->err_rc, 1906 gettext(ldap_err2string(cookie->err_rc))); 1907 err = strdup(errstr); 1908 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err, 1909 NULL); 1910 cookie->err_rc = NS_LDAP_INTERNAL; 1911 cookie->errorp = *errorp; 1912 return (LDAP_ERROR); 1913 } 1914 if (errCode == LDAP_REFERRAL) { 1915 for (i = 0; referrals[i] != NULL; 1916 i++) { 1917 /* add to referral list */ 1918 rc = __s_api_addRefInfo( 1919 &cookie->reflist, 1920 referrals[i], 1921 cookie->basedn, 1922 &cookie->scope, 1923 cookie->filter, 1924 cookie->conn->ld); 1925 if (rc != NS_LDAP_SUCCESS) { 1926 ldap_value_free( 1927 referrals); 1928 if (retCtrls) 1929 ldap_controls_free( 1930 retCtrls); 1931 return (ERROR); 1932 } 1933 } 1934 ldap_value_free(referrals); 1935 if (retCtrls) 1936 ldap_controls_free(retCtrls); 1937 return (END_RESULT); 1938 } 1939 if (retCtrls) { 1940 rc = ldap_parse_virtuallist_control( 1941 cookie->conn->ld, retCtrls, 1942 &target_posp, &list_size, &errCode); 1943 if (rc == LDAP_SUCCESS) { 1944 cookie->index = target_posp + LISTPAGESIZE; 1945 if (cookie->index > list_size) { 1946 finished = 1; 1947 } 1948 } 1949 ldap_controls_free(retCtrls); 1950 retCtrls = NULL; 1951 } 1952 else 1953 finished = 1; 1954 } else if (cookie->listType == SIMPLEPAGECTRLFLAG) { 1955 rc = ldap_parse_result(cookie->conn->ld, cookie->resultMsg, 1956 &errCode, NULL, NULL, &referrals, &retCtrls, 0); 1957 if (rc != LDAP_SUCCESS) { 1958 (void) ldap_get_option(cookie->conn->ld, 1959 LDAP_OPT_ERROR_NUMBER, 1960 &cookie->err_rc); 1961 (void) sprintf(errstr, 1962 gettext("LDAP ERROR (%d): %s.\n"), 1963 cookie->err_rc, 1964 gettext(ldap_err2string(cookie->err_rc))); 1965 err = strdup(errstr); 1966 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err, 1967 NULL); 1968 cookie->err_rc = NS_LDAP_INTERNAL; 1969 cookie->errorp = *errorp; 1970 return (LDAP_ERROR); 1971 } 1972 if (errCode == LDAP_REFERRAL) { 1973 for (i = 0; referrals[i] != NULL; 1974 i++) { 1975 /* add to referral list */ 1976 rc = __s_api_addRefInfo( 1977 &cookie->reflist, 1978 referrals[i], 1979 cookie->basedn, 1980 &cookie->scope, 1981 cookie->filter, 1982 cookie->conn->ld); 1983 if (rc != NS_LDAP_SUCCESS) { 1984 ldap_value_free( 1985 referrals); 1986 if (retCtrls) 1987 ldap_controls_free( 1988 retCtrls); 1989 return (ERROR); 1990 } 1991 } 1992 ldap_value_free(referrals); 1993 if (retCtrls) 1994 ldap_controls_free(retCtrls); 1995 return (END_RESULT); 1996 } 1997 if (retCtrls) { 1998 if (cookie->ctrlCookie) 1999 ber_bvfree(cookie->ctrlCookie); 2000 cookie->ctrlCookie = NULL; 2001 rc = ldap_parse_page_control( 2002 cookie->conn->ld, retCtrls, 2003 &count, &cookie->ctrlCookie); 2004 if (rc == LDAP_SUCCESS) { 2005 if ((cookie->ctrlCookie == NULL) || 2006 (cookie->ctrlCookie->bv_val == NULL) || 2007 (cookie->ctrlCookie->bv_len == 0)) 2008 finished = 1; 2009 } 2010 ldap_controls_free(retCtrls); 2011 retCtrls = NULL; 2012 } 2013 else 2014 finished = 1; 2015 } 2016 if (!finished && cookie->listType == VLVCTRLFLAG) 2017 return (NEXT_VLV); 2018 if (!finished && cookie->listType == SIMPLEPAGECTRLFLAG) 2019 return (NEXT_PAGE); 2020 if (finished) 2021 return (END_RESULT); 2022 return (ERROR); 2023 } 2024 2025 /* 2026 * This state machine performs one or more LDAP searches to a given 2027 * directory server using service search descriptors and schema 2028 * mapping as appropriate. The approximate pseudocode for 2029 * this routine is the following: 2030 * Given the current configuration [set/reset connection etc.] 2031 * and the current service search descriptor list 2032 * or default search filter parameters 2033 * foreach (service search filter) { 2034 * initialize the filter [via filter_init if appropriate] 2035 * get a valid session/connection (preferably the current one) 2036 * Recover if the connection is lost 2037 * perform the search 2038 * foreach (result entry) { 2039 * process result [via callback if appropriate] 2040 * save result for caller if accepted. 2041 * exit and return all collected if allResults found; 2042 * } 2043 * } 2044 * return collected results and exit 2045 */ 2046 2047 static 2048 ns_state_t 2049 search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle) 2050 { 2051 char errstr[MAXERROR]; 2052 char *err; 2053 int rc, ret; 2054 ns_ldap_entry_t *nextEntry; 2055 ns_ldap_error_t *error = NULL; 2056 ns_ldap_error_t **errorp; 2057 2058 errorp = &error; 2059 cookie->err_rc = 0; 2060 cookie->state = state; 2061 errstr[0] = '\0'; 2062 2063 for (;;) { 2064 switch (cookie->state) { 2065 case GET_ACCT_MGMT_INFO: 2066 /* 2067 * Set the flag to get ldap account management controls. 2068 */ 2069 cookie->nopasswd_acct_mgmt = 1; 2070 cookie->new_state = INIT; 2071 break; 2072 case EXIT: 2073 /* state engine/connection cleaned up in delete */ 2074 if (cookie->attribute) { 2075 __s_api_free2dArray(cookie->attribute); 2076 cookie->attribute = NULL; 2077 } 2078 if (cookie->reflist) { 2079 __s_api_deleteRefInfo(cookie->reflist); 2080 cookie->reflist = NULL; 2081 } 2082 return (EXIT); 2083 case INIT: 2084 cookie->sdpos = NULL; 2085 cookie->new_state = NEXT_SEARCH_DESCRIPTOR; 2086 if (cookie->attribute) { 2087 __s_api_free2dArray(cookie->attribute); 2088 cookie->attribute = NULL; 2089 } 2090 if ((cookie->i_flags & NS_LDAP_NOMAP) == 0 && 2091 cookie->i_attr) { 2092 cookie->attribute = 2093 __ns_ldap_mapAttributeList( 2094 cookie->service, 2095 cookie->i_attr); 2096 } 2097 break; 2098 case NEXT_SEARCH_DESCRIPTOR: 2099 /* get next search descriptor */ 2100 if (cookie->sdpos == NULL) { 2101 cookie->sdpos = cookie->sdlist; 2102 cookie->new_state = GET_SESSION; 2103 } else { 2104 cookie->sdpos++; 2105 cookie->new_state = NEXT_SEARCH; 2106 } 2107 if (*cookie->sdpos == NULL) 2108 cookie->new_state = EXIT; 2109 break; 2110 case GET_SESSION: 2111 if (get_current_session(cookie) < 0) 2112 cookie->new_state = NEXT_SESSION; 2113 else 2114 cookie->new_state = NEXT_SEARCH; 2115 break; 2116 case NEXT_SESSION: 2117 if (get_next_session(cookie) < 0) 2118 cookie->new_state = RESTART_SESSION; 2119 else 2120 cookie->new_state = NEXT_SEARCH; 2121 break; 2122 case RESTART_SESSION: 2123 if (cookie->i_flags & NS_LDAP_HARD) { 2124 cookie->new_state = NEXT_SESSION; 2125 break; 2126 } 2127 (void) sprintf(errstr, 2128 gettext("Session error no available conn.\n"), 2129 state); 2130 err = strdup(errstr); 2131 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err, 2132 NULL); 2133 cookie->err_rc = NS_LDAP_INTERNAL; 2134 cookie->errorp = *errorp; 2135 cookie->new_state = EXIT; 2136 break; 2137 case NEXT_SEARCH: 2138 /* setup referrals search if necessary */ 2139 if (cookie->refpos) { 2140 if (setup_referral_search(cookie) < 0) { 2141 cookie->new_state = EXIT; 2142 break; 2143 } 2144 } else if (setup_next_search(cookie) < 0) { 2145 cookie->new_state = EXIT; 2146 break; 2147 } 2148 /* only do VLV/PAGE on scopes onelevel/subtree */ 2149 if (paging_supported(cookie)) { 2150 if (cookie->use_paging && 2151 (cookie->scope != LDAP_SCOPE_BASE)) { 2152 cookie->index = 1; 2153 if (cookie->listType == VLVCTRLFLAG) 2154 cookie->new_state = NEXT_VLV; 2155 else 2156 cookie->new_state = NEXT_PAGE; 2157 break; 2158 } 2159 } 2160 cookie->new_state = ONE_SEARCH; 2161 break; 2162 case NEXT_VLV: 2163 rc = setup_vlv_params(cookie); 2164 if (rc != LDAP_SUCCESS) { 2165 cookie->err_rc = rc; 2166 cookie->new_state = LDAP_ERROR; 2167 break; 2168 } 2169 cookie->next_state = MULTI_RESULT; 2170 cookie->new_state = DO_SEARCH; 2171 break; 2172 case NEXT_PAGE: 2173 rc = setup_simplepg_params(cookie); 2174 if (rc != LDAP_SUCCESS) { 2175 cookie->err_rc = rc; 2176 cookie->new_state = LDAP_ERROR; 2177 break; 2178 } 2179 cookie->next_state = MULTI_RESULT; 2180 cookie->new_state = DO_SEARCH; 2181 break; 2182 case ONE_SEARCH: 2183 cookie->next_state = NEXT_RESULT; 2184 cookie->new_state = DO_SEARCH; 2185 break; 2186 case DO_SEARCH: 2187 rc = ldap_search_ext(cookie->conn->ld, 2188 cookie->basedn, 2189 cookie->scope, 2190 cookie->filter, 2191 cookie->attribute, 2192 0, 2193 cookie->p_serverctrls, 2194 NULL, 2195 &cookie->search_timeout, 0, 2196 &cookie->msgId); 2197 if (rc != LDAP_SUCCESS) { 2198 if (rc == LDAP_BUSY || 2199 rc == LDAP_UNAVAILABLE || 2200 rc == LDAP_UNWILLING_TO_PERFORM || 2201 rc == LDAP_CONNECT_ERROR || 2202 rc == LDAP_SERVER_DOWN) { 2203 2204 cookie->new_state = NEXT_SESSION; 2205 2206 /* 2207 * If not able to reach the 2208 * server, inform the ldap 2209 * cache manager that the 2210 * server should be removed 2211 * from it's server list. 2212 * Thus, the manager will not 2213 * return this server on the next 2214 * get-server request and will 2215 * also reduce the server list 2216 * refresh TTL, so that it will 2217 * find out sooner when the server 2218 * is up again. 2219 */ 2220 if (rc == LDAP_CONNECT_ERROR || 2221 rc == LDAP_SERVER_DOWN) { 2222 ret = __s_api_removeServer( 2223 cookie->conn->serverAddr); 2224 if (ret == NOSERVER && 2225 cookie->conn_auth_type 2226 == NS_LDAP_AUTH_NONE) { 2227 /* 2228 * Couldn't remove 2229 * server from server 2230 * list. 2231 * Exit to avoid 2232 * potential infinite 2233 * loop. 2234 */ 2235 cookie->err_rc = rc; 2236 cookie->new_state = 2237 LDAP_ERROR; 2238 } 2239 if (cookie->connectionId > -1) { 2240 /* 2241 * NS_LDAP_NEW_CONN 2242 * indicates that the 2243 * connection should 2244 * be deleted, not 2245 * kept alive 2246 */ 2247 DropConnection( 2248 cookie->connectionId, 2249 NS_LDAP_NEW_CONN); 2250 cookie->connectionId = 2251 -1; 2252 } 2253 } 2254 break; 2255 } 2256 cookie->err_rc = rc; 2257 cookie->new_state = LDAP_ERROR; 2258 break; 2259 } 2260 cookie->new_state = cookie->next_state; 2261 break; 2262 case NEXT_RESULT: 2263 rc = ldap_result(cookie->conn->ld, cookie->msgId, 2264 LDAP_MSG_ONE, 2265 (struct timeval *)&cookie->search_timeout, 2266 &cookie->resultMsg); 2267 if (rc == LDAP_RES_SEARCH_RESULT) { 2268 cookie->new_state = END_RESULT; 2269 /* check and process referrals info */ 2270 if (cookie->followRef) 2271 proc_result_referrals( 2272 cookie); 2273 (void) ldap_msgfree(cookie->resultMsg); 2274 cookie->resultMsg = NULL; 2275 break; 2276 } 2277 /* handle referrals if necessary */ 2278 if (rc == LDAP_RES_SEARCH_REFERENCE) { 2279 if (cookie->followRef) 2280 proc_search_references(cookie); 2281 (void) ldap_msgfree(cookie->resultMsg); 2282 cookie->resultMsg = NULL; 2283 break; 2284 } 2285 if (rc != LDAP_RES_SEARCH_ENTRY) { 2286 switch (rc) { 2287 case 0: 2288 rc = LDAP_TIMEOUT; 2289 break; 2290 case -1: 2291 rc = ldap_get_lderrno(cookie->conn->ld, 2292 NULL, NULL); 2293 break; 2294 default: 2295 rc = ldap_result2error(cookie->conn->ld, 2296 cookie->resultMsg, 1); 2297 break; 2298 } 2299 if (rc == LDAP_TIMEOUT || 2300 rc == LDAP_SERVER_DOWN) { 2301 if (rc == LDAP_TIMEOUT) 2302 (void) __s_api_removeServer( 2303 cookie->conn->serverAddr); 2304 if (cookie->connectionId > -1) { 2305 DropConnection( 2306 cookie->connectionId, 2307 NS_LDAP_NEW_CONN); 2308 cookie->connectionId = -1; 2309 } 2310 cookie->err_from_result = 1; 2311 } 2312 (void) ldap_msgfree(cookie->resultMsg); 2313 cookie->resultMsg = NULL; 2314 if (rc == LDAP_BUSY || 2315 rc == LDAP_UNAVAILABLE || 2316 rc == LDAP_UNWILLING_TO_PERFORM) { 2317 cookie->new_state = NEXT_SESSION; 2318 break; 2319 } 2320 cookie->err_rc = rc; 2321 cookie->new_state = LDAP_ERROR; 2322 break; 2323 } 2324 /* else LDAP_RES_SEARCH_ENTRY */ 2325 /* get account management response control */ 2326 if (cookie->nopasswd_acct_mgmt == 1) { 2327 rc = ldap_get_entry_controls(cookie->conn->ld, 2328 cookie->resultMsg, 2329 &(cookie->resultctrl)); 2330 if (rc != LDAP_SUCCESS) { 2331 cookie->new_state = LDAP_ERROR; 2332 cookie->err_rc = rc; 2333 break; 2334 } 2335 } 2336 rc = __s_api_getEntry(cookie); 2337 (void) ldap_msgfree(cookie->resultMsg); 2338 cookie->resultMsg = NULL; 2339 if (rc != NS_LDAP_SUCCESS) { 2340 cookie->new_state = LDAP_ERROR; 2341 break; 2342 } 2343 cookie->new_state = PROCESS_RESULT; 2344 cookie->next_state = NEXT_RESULT; 2345 break; 2346 case MULTI_RESULT: 2347 rc = ldap_result(cookie->conn->ld, cookie->msgId, 2348 LDAP_MSG_ONE, 2349 (struct timeval *)&cookie->search_timeout, 2350 &cookie->resultMsg); 2351 if (rc == LDAP_RES_SEARCH_RESULT) { 2352 rc = ldap_result2error(cookie->conn->ld, 2353 cookie->resultMsg, 0); 2354 if (rc != LDAP_SUCCESS) { 2355 cookie->err_rc = rc; 2356 cookie->new_state = LDAP_ERROR; 2357 (void) ldap_msgfree(cookie->resultMsg); 2358 break; 2359 } 2360 cookie->new_state = multi_result(cookie); 2361 (void) ldap_msgfree(cookie->resultMsg); 2362 cookie->resultMsg = NULL; 2363 break; 2364 } 2365 /* handle referrals if necessary */ 2366 if (rc == LDAP_RES_SEARCH_REFERENCE && 2367 cookie->followRef) { 2368 proc_search_references(cookie); 2369 (void) ldap_msgfree(cookie->resultMsg); 2370 cookie->resultMsg = NULL; 2371 break; 2372 } 2373 if (rc != LDAP_RES_SEARCH_ENTRY) { 2374 switch (rc) { 2375 case 0: 2376 rc = LDAP_TIMEOUT; 2377 break; 2378 case -1: 2379 rc = ldap_get_lderrno(cookie->conn->ld, 2380 NULL, NULL); 2381 break; 2382 default: 2383 rc = ldap_result2error(cookie->conn->ld, 2384 cookie->resultMsg, 1); 2385 break; 2386 } 2387 if (rc == LDAP_TIMEOUT || 2388 rc == LDAP_SERVER_DOWN) { 2389 if (rc == LDAP_TIMEOUT) 2390 (void) __s_api_removeServer( 2391 cookie->conn->serverAddr); 2392 if (cookie->connectionId > -1) { 2393 DropConnection( 2394 cookie->connectionId, 2395 NS_LDAP_NEW_CONN); 2396 cookie->connectionId = -1; 2397 } 2398 cookie->err_from_result = 1; 2399 } 2400 (void) ldap_msgfree(cookie->resultMsg); 2401 cookie->resultMsg = NULL; 2402 if (rc == LDAP_BUSY || 2403 rc == LDAP_UNAVAILABLE || 2404 rc == LDAP_UNWILLING_TO_PERFORM) { 2405 cookie->new_state = NEXT_SESSION; 2406 break; 2407 } 2408 cookie->err_rc = rc; 2409 cookie->new_state = LDAP_ERROR; 2410 break; 2411 } 2412 /* else LDAP_RES_SEARCH_ENTRY */ 2413 rc = __s_api_getEntry(cookie); 2414 (void) ldap_msgfree(cookie->resultMsg); 2415 cookie->resultMsg = NULL; 2416 if (rc != NS_LDAP_SUCCESS) { 2417 cookie->new_state = LDAP_ERROR; 2418 break; 2419 } 2420 cookie->new_state = PROCESS_RESULT; 2421 cookie->next_state = MULTI_RESULT; 2422 break; 2423 case PROCESS_RESULT: 2424 /* NOTE THIS STATE MAY BE PROCESSED BY CALLER */ 2425 if (cookie->use_usercb && cookie->callback) { 2426 rc = 0; 2427 for (nextEntry = cookie->result->entry; 2428 nextEntry != NULL; 2429 nextEntry = nextEntry->next) { 2430 rc = (*cookie->callback)(nextEntry, 2431 cookie->userdata); 2432 2433 if (rc == NS_LDAP_CB_DONE) { 2434 /* cb doesn't want any more data */ 2435 rc = NS_LDAP_PARTIAL; 2436 cookie->err_rc = rc; 2437 break; 2438 } else if (rc != NS_LDAP_CB_NEXT) { 2439 /* invalid return code */ 2440 rc = NS_LDAP_OP_FAILED; 2441 cookie->err_rc = rc; 2442 break; 2443 } 2444 } 2445 (void) __ns_ldap_freeResult(&cookie->result); 2446 cookie->result = NULL; 2447 } 2448 if (rc != 0) { 2449 cookie->new_state = EXIT; 2450 break; 2451 } 2452 /* NOTE PREVIOUS STATE SPECIFIES NEXT STATE */ 2453 cookie->new_state = cookie->next_state; 2454 break; 2455 case END_PROCESS_RESULT: 2456 cookie->new_state = cookie->next_state; 2457 break; 2458 case END_RESULT: 2459 /* 2460 * XXX DO WE NEED THIS CASE? 2461 * if (search is complete) { 2462 * cookie->new_state = EXIT; 2463 * } else 2464 */ 2465 /* 2466 * entering referral mode if necessary 2467 */ 2468 if (cookie->followRef && cookie->reflist) 2469 cookie->new_state = 2470 NEXT_REFERRAL; 2471 else 2472 cookie->new_state = 2473 NEXT_SEARCH_DESCRIPTOR; 2474 break; 2475 case NEXT_REFERRAL: 2476 /* get next referral info */ 2477 if (cookie->refpos == NULL) 2478 cookie->refpos = 2479 cookie->reflist; 2480 else 2481 cookie->refpos = 2482 cookie->refpos->next; 2483 /* check see if done with all referrals */ 2484 if (cookie->refpos != NULL) 2485 cookie->new_state = 2486 GET_REFERRAL_SESSION; 2487 else { 2488 __s_api_deleteRefInfo(cookie->reflist); 2489 cookie->reflist = NULL; 2490 cookie->new_state = 2491 NEXT_SEARCH_DESCRIPTOR; 2492 } 2493 break; 2494 case GET_REFERRAL_SESSION: 2495 if (get_referral_session(cookie) < 0) 2496 cookie->new_state = EXIT; 2497 else { 2498 cookie->new_state = NEXT_SEARCH; 2499 } 2500 break; 2501 case LDAP_ERROR: 2502 if (cookie->err_from_result) { 2503 if (cookie->err_rc == LDAP_SERVER_DOWN) { 2504 (void) sprintf(errstr, 2505 gettext("LDAP ERROR (%d): " 2506 "Error occurred during" 2507 " receiving results. " 2508 "This may be due to a " 2509 "stalled connection."), 2510 cookie->err_rc); 2511 } else if (cookie->err_rc == LDAP_TIMEOUT) { 2512 (void) sprintf(errstr, 2513 gettext("LDAP ERROR (%d): " 2514 "Error occurred during" 2515 " receiving results. %s" 2516 "."), cookie->err_rc, 2517 ldap_err2string( 2518 cookie->err_rc)); 2519 } 2520 } else 2521 (void) sprintf(errstr, 2522 gettext("LDAP ERROR (%d): %s."), 2523 cookie->err_rc, 2524 ldap_err2string(cookie->err_rc)); 2525 err = strdup(errstr); 2526 if (cookie->err_from_result) { 2527 MKERROR(LOG_WARNING, *errorp, cookie->err_rc, 2528 err, NULL); 2529 } else { 2530 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, 2531 err, NULL); 2532 } 2533 cookie->err_rc = NS_LDAP_INTERNAL; 2534 cookie->errorp = *errorp; 2535 return (ERROR); 2536 default: 2537 case ERROR: 2538 (void) sprintf(errstr, 2539 gettext("Internal State machine exit (%d).\n"), 2540 cookie->state); 2541 err = strdup(errstr); 2542 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err, 2543 NULL); 2544 cookie->err_rc = NS_LDAP_INTERNAL; 2545 cookie->errorp = *errorp; 2546 return (ERROR); 2547 } 2548 2549 if (cycle == ONE_STEP) { 2550 return (cookie->new_state); 2551 } 2552 cookie->state = cookie->new_state; 2553 } 2554 /*NOTREACHED*/ 2555 #if 0 2556 (void) sprintf(errstr, 2557 gettext("Unexpected State machine error.\n")); 2558 err = strdup(errstr); 2559 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err, NULL); 2560 cookie->err_rc = NS_LDAP_INTERNAL; 2561 cookie->errorp = *errorp; 2562 return (ERROR); 2563 #endif 2564 } 2565 2566 2567 2568 /* 2569 * __ns_ldap_list performs one or more LDAP searches to a given 2570 * directory server using service search descriptors and schema 2571 * mapping as appropriate. 2572 */ 2573 2574 int 2575 __ns_ldap_list( 2576 const char *service, 2577 const char *filter, 2578 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc, 2579 char **realfilter, const void *userdata), 2580 const char * const *attribute, 2581 const ns_cred_t *auth, 2582 const int flags, 2583 ns_ldap_result_t **rResult, /* return result entries */ 2584 ns_ldap_error_t **errorp, 2585 int (*callback)(const ns_ldap_entry_t *entry, const void *userdata), 2586 const void *userdata) 2587 { 2588 ns_ldap_cookie_t *cookie; 2589 ns_ldap_search_desc_t **sdlist = NULL; 2590 ns_ldap_search_desc_t *dptr; 2591 ns_ldap_error_t *error = NULL; 2592 char **dns = NULL; 2593 int scope; 2594 int rc; 2595 int from_result; 2596 2597 *errorp = NULL; 2598 2599 /* Initialize State machine cookie */ 2600 cookie = init_search_state_machine(); 2601 if (cookie == NULL) { 2602 return (NS_LDAP_MEMORY); 2603 } 2604 2605 /* see if need to follow referrals */ 2606 rc = __s_api_toFollowReferrals(flags, 2607 &cookie->followRef, errorp); 2608 if (rc != NS_LDAP_SUCCESS) { 2609 delete_search_cookie(cookie); 2610 return (rc); 2611 } 2612 2613 /* get the service descriptor - or create a default one */ 2614 rc = __s_api_get_SSD_from_SSDtoUse_service(service, 2615 &sdlist, errorp); 2616 if (rc != NS_LDAP_SUCCESS) { 2617 delete_search_cookie(cookie); 2618 *errorp = error; 2619 return (rc); 2620 } 2621 2622 if (sdlist == NULL) { 2623 /* Create default service Desc */ 2624 sdlist = (ns_ldap_search_desc_t **)calloc(2, 2625 sizeof (ns_ldap_search_desc_t *)); 2626 if (sdlist == NULL) { 2627 delete_search_cookie(cookie); 2628 cookie = NULL; 2629 return (NS_LDAP_MEMORY); 2630 } 2631 dptr = (ns_ldap_search_desc_t *) 2632 calloc(1, sizeof (ns_ldap_search_desc_t)); 2633 if (dptr == NULL) { 2634 free(sdlist); 2635 delete_search_cookie(cookie); 2636 cookie = NULL; 2637 return (NS_LDAP_MEMORY); 2638 } 2639 sdlist[0] = dptr; 2640 2641 /* default base */ 2642 rc = __s_api_getDNs(&dns, service, &cookie->errorp); 2643 if (rc != NS_LDAP_SUCCESS) { 2644 if (dns) { 2645 __s_api_free2dArray(dns); 2646 dns = NULL; 2647 } 2648 *errorp = cookie->errorp; 2649 cookie->errorp = NULL; 2650 delete_search_cookie(cookie); 2651 cookie = NULL; 2652 return (rc); 2653 } 2654 dptr->basedn = strdup(dns[0]); 2655 __s_api_free2dArray(dns); 2656 dns = NULL; 2657 2658 /* default scope */ 2659 scope = 0; 2660 rc = __s_api_getSearchScope(&scope, &cookie->errorp); 2661 dptr->scope = scope; 2662 } 2663 2664 cookie->sdlist = sdlist; 2665 2666 /* 2667 * use VLV/PAGE control only if NS_LDAP_PAGE_CTRL is set 2668 */ 2669 if (flags & NS_LDAP_PAGE_CTRL) 2670 cookie->use_paging = TRUE; 2671 else 2672 cookie->use_paging = FALSE; 2673 2674 /* Set up other arguments */ 2675 cookie->userdata = userdata; 2676 if (init_filter_cb != NULL) { 2677 cookie->init_filter_cb = init_filter_cb; 2678 cookie->use_filtercb = 1; 2679 } 2680 if (callback != NULL) { 2681 cookie->callback = callback; 2682 cookie->use_usercb = 1; 2683 } 2684 if (service) { 2685 cookie->service = strdup(service); 2686 if (cookie->service == NULL) { 2687 delete_search_cookie(cookie); 2688 cookie = NULL; 2689 return (NS_LDAP_MEMORY); 2690 } 2691 } 2692 2693 cookie->i_filter = strdup(filter); 2694 cookie->i_attr = attribute; 2695 cookie->i_auth = auth; 2696 cookie->i_flags = flags; 2697 2698 /* Process search */ 2699 rc = search_state_machine(cookie, INIT, 0); 2700 2701 /* Copy results back to user */ 2702 rc = cookie->err_rc; 2703 if (rc != NS_LDAP_SUCCESS) 2704 *errorp = cookie->errorp; 2705 *rResult = cookie->result; 2706 from_result = cookie->err_from_result; 2707 2708 cookie->errorp = NULL; 2709 cookie->result = NULL; 2710 delete_search_cookie(cookie); 2711 cookie = NULL; 2712 2713 if (from_result == 0 && *rResult == NULL) 2714 rc = NS_LDAP_NOTFOUND; 2715 return (rc); 2716 } 2717 2718 /* 2719 * __s_api_find_domainname performs one or more LDAP searches to 2720 * find the value of the nisdomain attribute associated with 2721 * the input DN 2722 */ 2723 2724 static int 2725 __s_api_find_domainname( 2726 const char *dn, 2727 char **domainname, 2728 const ns_cred_t *cred, 2729 ns_ldap_error_t **errorp) 2730 { 2731 2732 ns_ldap_cookie_t *cookie; 2733 ns_ldap_search_desc_t **sdlist; 2734 ns_ldap_search_desc_t *dptr; 2735 int rc; 2736 char **value; 2737 int flags = 0; 2738 2739 *domainname = NULL; 2740 *errorp = NULL; 2741 2742 /* Initialize State machine cookie */ 2743 cookie = init_search_state_machine(); 2744 if (cookie == NULL) { 2745 return (NS_LDAP_MEMORY); 2746 } 2747 2748 /* see if need to follow referrals */ 2749 rc = __s_api_toFollowReferrals(flags, 2750 &cookie->followRef, errorp); 2751 if (rc != NS_LDAP_SUCCESS) { 2752 delete_search_cookie(cookie); 2753 return (rc); 2754 } 2755 2756 /* Create default service Desc */ 2757 sdlist = (ns_ldap_search_desc_t **)calloc(2, 2758 sizeof (ns_ldap_search_desc_t *)); 2759 if (sdlist == NULL) { 2760 delete_search_cookie(cookie); 2761 cookie = NULL; 2762 return (NS_LDAP_MEMORY); 2763 } 2764 dptr = (ns_ldap_search_desc_t *) 2765 calloc(1, sizeof (ns_ldap_search_desc_t)); 2766 if (dptr == NULL) { 2767 free(sdlist); 2768 delete_search_cookie(cookie); 2769 cookie = NULL; 2770 return (NS_LDAP_MEMORY); 2771 } 2772 sdlist[0] = dptr; 2773 2774 /* search base is dn */ 2775 dptr->basedn = strdup(dn); 2776 2777 /* search scope is base */ 2778 dptr->scope = NS_LDAP_SCOPE_BASE; 2779 2780 /* search filter is "nisdomain=*" */ 2781 dptr->filter = strdup(_NIS_FILTER); 2782 2783 cookie->sdlist = sdlist; 2784 cookie->i_filter = strdup(dptr->filter); 2785 cookie->i_attr = nis_domain_attrs; 2786 cookie->i_auth = cred; 2787 cookie->i_flags = 0; 2788 2789 /* Process search */ 2790 rc = search_state_machine(cookie, INIT, 0); 2791 2792 /* Copy domain name if found */ 2793 rc = cookie->err_rc; 2794 if (rc != NS_LDAP_SUCCESS) 2795 *errorp = cookie->errorp; 2796 if (cookie->result == NULL) 2797 rc = NS_LDAP_NOTFOUND; 2798 if (rc == NS_LDAP_SUCCESS) { 2799 value = __ns_ldap_getAttr(cookie->result->entry, 2800 _NIS_DOMAIN); 2801 if (value[0]) 2802 *domainname = strdup(value[0]); 2803 else 2804 rc = NS_LDAP_NOTFOUND; 2805 } 2806 if (cookie->result != NULL) 2807 (void) __ns_ldap_freeResult(&cookie->result); 2808 cookie->errorp = NULL; 2809 delete_search_cookie(cookie); 2810 cookie = NULL; 2811 return (rc); 2812 } 2813 2814 int 2815 __ns_ldap_firstEntry( 2816 const char *service, 2817 const char *filter, 2818 int (*init_filter_cb)(const ns_ldap_search_desc_t *desc, 2819 char **realfilter, const void *userdata), 2820 const char * const *attribute, 2821 const ns_cred_t *auth, 2822 const int flags, 2823 void **vcookie, 2824 ns_ldap_result_t **result, 2825 ns_ldap_error_t ** errorp, 2826 const void *userdata) 2827 { 2828 ns_ldap_cookie_t *cookie = NULL; 2829 ns_ldap_error_t *error = NULL; 2830 ns_state_t state; 2831 ns_ldap_search_desc_t **sdlist; 2832 ns_ldap_search_desc_t *dptr; 2833 char **dns = NULL; 2834 int scope; 2835 int rc; 2836 2837 *errorp = NULL; 2838 *result = NULL; 2839 2840 /* get the service descriptor - or create a default one */ 2841 rc = __s_api_get_SSD_from_SSDtoUse_service(service, 2842 &sdlist, errorp); 2843 if (rc != NS_LDAP_SUCCESS) { 2844 *errorp = error; 2845 return (rc); 2846 } 2847 if (sdlist == NULL) { 2848 /* Create default service Desc */ 2849 sdlist = (ns_ldap_search_desc_t **)calloc(2, 2850 sizeof (ns_ldap_search_desc_t *)); 2851 if (sdlist == NULL) { 2852 return (NS_LDAP_MEMORY); 2853 } 2854 dptr = (ns_ldap_search_desc_t *) 2855 calloc(1, sizeof (ns_ldap_search_desc_t)); 2856 if (dptr == NULL) { 2857 free(sdlist); 2858 return (NS_LDAP_MEMORY); 2859 } 2860 sdlist[0] = dptr; 2861 2862 /* default base */ 2863 rc = __s_api_getDNs(&dns, service, &error); 2864 if (rc != NS_LDAP_SUCCESS) { 2865 if (dns) { 2866 __s_api_free2dArray(dns); 2867 dns = NULL; 2868 } 2869 if (sdlist) { 2870 (void) __ns_ldap_freeSearchDescriptors( 2871 &sdlist); 2872 2873 sdlist = NULL; 2874 } 2875 *errorp = error; 2876 return (rc); 2877 } 2878 dptr->basedn = strdup(dns[0]); 2879 __s_api_free2dArray(dns); 2880 dns = NULL; 2881 2882 /* default scope */ 2883 scope = 0; 2884 cookie = init_search_state_machine(); 2885 if (cookie == NULL) { 2886 if (sdlist) { 2887 (void) __ns_ldap_freeSearchDescriptors(&sdlist); 2888 sdlist = NULL; 2889 } 2890 return (NS_LDAP_MEMORY); 2891 } 2892 rc = __s_api_getSearchScope(&scope, &cookie->errorp); 2893 dptr->scope = scope; 2894 } 2895 2896 /* Initialize State machine cookie */ 2897 if (cookie == NULL) 2898 cookie = init_search_state_machine(); 2899 if (cookie == NULL) { 2900 if (sdlist) { 2901 (void) __ns_ldap_freeSearchDescriptors(&sdlist); 2902 sdlist = NULL; 2903 } 2904 return (NS_LDAP_MEMORY); 2905 } 2906 2907 cookie->sdlist = sdlist; 2908 2909 /* see if need to follow referrals */ 2910 rc = __s_api_toFollowReferrals(flags, 2911 &cookie->followRef, errorp); 2912 if (rc != NS_LDAP_SUCCESS) { 2913 delete_search_cookie(cookie); 2914 return (rc); 2915 } 2916 2917 /* 2918 * use VLV/PAGE control only if NS_LDAP_NO_PAGE_CTRL is not set 2919 */ 2920 if (flags & NS_LDAP_NO_PAGE_CTRL) 2921 cookie->use_paging = FALSE; 2922 else 2923 cookie->use_paging = TRUE; 2924 2925 /* Set up other arguments */ 2926 cookie->userdata = userdata; 2927 if (init_filter_cb != NULL) { 2928 cookie->init_filter_cb = init_filter_cb; 2929 cookie->use_filtercb = 1; 2930 } 2931 cookie->use_usercb = 0; 2932 if (service) { 2933 cookie->service = strdup(service); 2934 if (cookie->service == NULL) { 2935 delete_search_cookie(cookie); 2936 return (NS_LDAP_MEMORY); 2937 } 2938 } 2939 2940 cookie->i_filter = strdup(filter); 2941 cookie->i_attr = attribute; 2942 cookie->i_auth = auth; 2943 cookie->i_flags = flags; 2944 2945 state = INIT; 2946 for (;;) { 2947 state = search_state_machine(cookie, state, ONE_STEP); 2948 switch (state) { 2949 case PROCESS_RESULT: 2950 *result = cookie->result; 2951 cookie->result = NULL; 2952 *vcookie = (void *)cookie; 2953 return (NS_LDAP_SUCCESS); 2954 case ERROR: 2955 case LDAP_ERROR: 2956 rc = cookie->err_rc; 2957 *errorp = cookie->errorp; 2958 cookie->errorp = NULL; 2959 delete_search_cookie(cookie); 2960 return (rc); 2961 case EXIT: 2962 rc = cookie->err_rc; 2963 if (rc != NS_LDAP_SUCCESS) { 2964 *errorp = cookie->errorp; 2965 cookie->errorp = NULL; 2966 } else { 2967 rc = NS_LDAP_NOTFOUND; 2968 } 2969 2970 delete_search_cookie(cookie); 2971 return (rc); 2972 2973 default: 2974 break; 2975 } 2976 } 2977 } 2978 2979 /*ARGSUSED2*/ 2980 int 2981 __ns_ldap_nextEntry( 2982 void *vcookie, 2983 ns_ldap_result_t **result, 2984 ns_ldap_error_t ** errorp) 2985 { 2986 ns_ldap_cookie_t *cookie; 2987 ns_state_t state; 2988 int rc; 2989 2990 cookie = (ns_ldap_cookie_t *)vcookie; 2991 cookie->result = NULL; 2992 *result = NULL; 2993 2994 state = END_PROCESS_RESULT; 2995 for (;;) { 2996 /* 2997 * if the ldap connection being used is shared, 2998 * ensure the thread-specific data area for setting 2999 * status is allocated 3000 */ 3001 if (cookie->conn->shared > 0) { 3002 rc = __s_api_check_MTC_tsd(); 3003 if (rc != NS_LDAP_SUCCESS) 3004 return (rc); 3005 } 3006 3007 state = search_state_machine(cookie, state, ONE_STEP); 3008 switch (state) { 3009 case PROCESS_RESULT: 3010 *result = cookie->result; 3011 cookie->result = NULL; 3012 return (NS_LDAP_SUCCESS); 3013 case ERROR: 3014 case LDAP_ERROR: 3015 rc = cookie->err_rc; 3016 *errorp = cookie->errorp; 3017 cookie->errorp = NULL; 3018 return (rc); 3019 case EXIT: 3020 return (NS_LDAP_SUCCESS); 3021 } 3022 } 3023 } 3024 3025 int 3026 __ns_ldap_endEntry( 3027 void **vcookie, 3028 ns_ldap_error_t ** errorp) 3029 { 3030 ns_ldap_cookie_t *cookie; 3031 int rc; 3032 3033 if (*vcookie == NULL) 3034 return (NS_LDAP_INVALID_PARAM); 3035 3036 cookie = (ns_ldap_cookie_t *)(*vcookie); 3037 cookie->result = NULL; 3038 3039 /* Complete search */ 3040 rc = search_state_machine(cookie, EXIT, 0); 3041 3042 /* Copy results back to user */ 3043 rc = cookie->err_rc; 3044 if (rc != NS_LDAP_SUCCESS) 3045 *errorp = cookie->errorp; 3046 3047 cookie->errorp = NULL; 3048 delete_search_cookie(cookie); 3049 cookie = NULL; 3050 *vcookie = NULL; 3051 3052 return (rc); 3053 } 3054 3055 3056 int 3057 __ns_ldap_freeResult(ns_ldap_result_t **result) 3058 { 3059 3060 ns_ldap_entry_t *curEntry = NULL; 3061 ns_ldap_entry_t *delEntry = NULL; 3062 int i; 3063 ns_ldap_result_t *res = *result; 3064 3065 #ifdef DEBUG 3066 (void) fprintf(stderr, "__ns_ldap_freeResult START\n"); 3067 #endif 3068 if (res == NULL) 3069 return (NS_LDAP_INVALID_PARAM); 3070 3071 if (res->entry != NULL) 3072 curEntry = res->entry; 3073 3074 for (i = 0; i < res->entries_count; i++) { 3075 if (curEntry != NULL) { 3076 delEntry = curEntry; 3077 curEntry = curEntry->next; 3078 __ns_ldap_freeEntry(delEntry); 3079 } 3080 } 3081 3082 free(res); 3083 *result = NULL; 3084 return (NS_LDAP_SUCCESS); 3085 } 3086 3087 /*ARGSUSED*/ 3088 int 3089 __ns_ldap_auth(const ns_cred_t *auth, 3090 const int flags, 3091 ns_ldap_error_t **errorp, 3092 LDAPControl **serverctrls, 3093 LDAPControl **clientctrls) 3094 { 3095 3096 ConnectionID connectionId = -1; 3097 Connection *conp; 3098 int rc = 0; 3099 int do_not_fail_if_new_pwd_reqd = 0; 3100 int nopasswd_acct_mgmt = 0; 3101 3102 3103 #ifdef DEBUG 3104 (void) fprintf(stderr, "__ns_ldap_auth START\n"); 3105 #endif 3106 3107 *errorp = NULL; 3108 if (!auth) 3109 return (NS_LDAP_INVALID_PARAM); 3110 3111 rc = __s_api_getConnection(NULL, flags | NS_LDAP_NEW_CONN, 3112 auth, &connectionId, &conp, errorp, 3113 do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt); 3114 if (rc == NS_LDAP_OP_FAILED && *errorp) 3115 (void) __ns_ldap_freeError(errorp); 3116 3117 if (connectionId > -1) 3118 DropConnection(connectionId, flags); 3119 return (rc); 3120 } 3121 3122 char ** 3123 __ns_ldap_getAttr(const ns_ldap_entry_t *entry, const char *attrname) 3124 { 3125 int i; 3126 3127 if (entry == NULL) 3128 return (NULL); 3129 for (i = 0; i < entry->attr_count; i++) { 3130 if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == NULL) 3131 return (entry->attr_pair[i]->attrvalue); 3132 } 3133 return (NULL); 3134 } 3135 3136 ns_ldap_attr_t * 3137 __ns_ldap_getAttrStruct(const ns_ldap_entry_t *entry, const char *attrname) 3138 { 3139 int i; 3140 3141 if (entry == NULL) 3142 return (NULL); 3143 for (i = 0; i < entry->attr_count; i++) { 3144 if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == NULL) 3145 return (entry->attr_pair[i]); 3146 } 3147 return (NULL); 3148 } 3149 3150 3151 /*ARGSUSED*/ 3152 int 3153 __ns_ldap_uid2dn(const char *uid, 3154 char **userDN, 3155 const ns_cred_t *cred, /* cred is ignored */ 3156 ns_ldap_error_t **errorp) 3157 { 3158 ns_ldap_result_t *result = NULL; 3159 char *filter, *userdata; 3160 char errstr[MAXERROR]; 3161 char **value; 3162 int rc = 0; 3163 int i = 0; 3164 size_t len; 3165 3166 *errorp = NULL; 3167 *userDN = NULL; 3168 if ((uid == NULL) || (uid[0] == '\0')) 3169 return (NS_LDAP_INVALID_PARAM); 3170 3171 while (uid[i] != '\0') { 3172 if (uid[i] == '=') { 3173 *userDN = strdup(uid); 3174 return (NS_LDAP_SUCCESS); 3175 } 3176 i++; 3177 } 3178 i = 0; 3179 while ((uid[i] != '\0') && (isdigit(uid[i]))) 3180 i++; 3181 if (uid[i] == '\0') { 3182 len = strlen(UIDNUMFILTER) + strlen(uid) + 1; 3183 filter = (char *)malloc(len); 3184 if (filter == NULL) { 3185 *userDN = NULL; 3186 return (NS_LDAP_MEMORY); 3187 } 3188 (void) snprintf(filter, len, UIDNUMFILTER, uid); 3189 3190 len = strlen(UIDNUMFILTER_SSD) + strlen(uid) + 1; 3191 userdata = (char *)malloc(len); 3192 if (userdata == NULL) { 3193 *userDN = NULL; 3194 return (NS_LDAP_MEMORY); 3195 } 3196 (void) snprintf(userdata, len, UIDNUMFILTER_SSD, uid); 3197 } else { 3198 len = strlen(UIDFILTER) + strlen(uid) + 1; 3199 filter = (char *)malloc(len); 3200 if (filter == NULL) { 3201 *userDN = NULL; 3202 return (NS_LDAP_MEMORY); 3203 } 3204 (void) snprintf(filter, len, UIDFILTER, uid); 3205 3206 len = strlen(UIDFILTER_SSD) + strlen(uid) + 1; 3207 userdata = (char *)malloc(len); 3208 if (userdata == NULL) { 3209 *userDN = NULL; 3210 return (NS_LDAP_MEMORY); 3211 } 3212 (void) snprintf(userdata, len, UIDFILTER_SSD, uid); 3213 } 3214 3215 /* 3216 * we want to retrieve the DN as it appears in LDAP 3217 * hence the use of NS_LDAP_NOT_CVT_DN in flags 3218 */ 3219 rc = __ns_ldap_list("passwd", filter, 3220 __s_api_merge_SSD_filter, 3221 NULL, cred, NS_LDAP_NOT_CVT_DN, 3222 &result, errorp, NULL, 3223 userdata); 3224 free(filter); 3225 filter = NULL; 3226 free(userdata); 3227 userdata = NULL; 3228 if (rc != NS_LDAP_SUCCESS) { 3229 if (result) { 3230 (void) __ns_ldap_freeResult(&result); 3231 result = NULL; 3232 } 3233 return (rc); 3234 } 3235 if (result->entries_count > 1) { 3236 (void) __ns_ldap_freeResult(&result); 3237 result = NULL; 3238 *userDN = NULL; 3239 (void) sprintf(errstr, 3240 gettext("Too many entries are returned for %s"), uid); 3241 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr), 3242 NULL); 3243 return (NS_LDAP_INTERNAL); 3244 } 3245 3246 value = __ns_ldap_getAttr(result->entry, "dn"); 3247 *userDN = strdup(value[0]); 3248 (void) __ns_ldap_freeResult(&result); 3249 result = NULL; 3250 return (NS_LDAP_SUCCESS); 3251 } 3252 3253 3254 /*ARGSUSED*/ 3255 int 3256 __ns_ldap_host2dn(const char *host, 3257 const char *domain, 3258 char **hostDN, 3259 const ns_cred_t *cred, /* cred is ignored */ 3260 ns_ldap_error_t **errorp) 3261 { 3262 ns_ldap_result_t *result = NULL; 3263 char *filter, *userdata; 3264 char errstr[MAXERROR]; 3265 char **value; 3266 int rc; 3267 size_t len; 3268 3269 /* 3270 * XXX 3271 * the domain parameter needs to be used in case domain is not local, if 3272 * this routine is to support multi domain setups, it needs lots of work... 3273 */ 3274 *errorp = NULL; 3275 *hostDN = NULL; 3276 if ((host == NULL) || (host[0] == '\0')) 3277 return (NS_LDAP_INVALID_PARAM); 3278 3279 len = strlen(HOSTFILTER) + strlen(host) + 1; 3280 filter = (char *)malloc(len); 3281 if (filter == NULL) { 3282 return (NS_LDAP_MEMORY); 3283 } 3284 (void) snprintf(filter, len, HOSTFILTER, host); 3285 3286 len = strlen(HOSTFILTER_SSD) + strlen(host) + 1; 3287 userdata = (char *)malloc(len); 3288 if (userdata == NULL) { 3289 return (NS_LDAP_MEMORY); 3290 } 3291 (void) snprintf(userdata, len, HOSTFILTER_SSD, host); 3292 3293 /* 3294 * we want to retrieve the DN as it appears in LDAP 3295 * hence the use of NS_LDAP_NOT_CVT_DN in flags 3296 */ 3297 rc = __ns_ldap_list("hosts", filter, 3298 __s_api_merge_SSD_filter, 3299 NULL, cred, NS_LDAP_NOT_CVT_DN, &result, 3300 errorp, NULL, 3301 userdata); 3302 free(filter); 3303 filter = NULL; 3304 free(userdata); 3305 userdata = NULL; 3306 if (rc != NS_LDAP_SUCCESS) { 3307 if (result) { 3308 (void) __ns_ldap_freeResult(&result); 3309 result = NULL; 3310 } 3311 return (rc); 3312 } 3313 3314 if (result->entries_count > 1) { 3315 (void) __ns_ldap_freeResult(&result); 3316 result = NULL; 3317 *hostDN = NULL; 3318 (void) sprintf(errstr, 3319 gettext("Too many entries are returned for %s"), host); 3320 MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr), 3321 NULL); 3322 return (NS_LDAP_INTERNAL); 3323 } 3324 3325 value = __ns_ldap_getAttr(result->entry, "dn"); 3326 *hostDN = strdup(value[0]); 3327 (void) __ns_ldap_freeResult(&result); 3328 result = NULL; 3329 return (NS_LDAP_SUCCESS); 3330 } 3331 3332 /*ARGSUSED*/ 3333 int 3334 __ns_ldap_dn2domain(const char *dn, 3335 char **domain, 3336 const ns_cred_t *cred, 3337 ns_ldap_error_t **errorp) 3338 { 3339 int rc, pnum, i, j, len = 0; 3340 char *newdn, **rdns = NULL; 3341 char **dns, *dn1; 3342 3343 *errorp = NULL; 3344 3345 if (domain == NULL) 3346 return (NS_LDAP_INVALID_PARAM); 3347 else 3348 *domain = NULL; 3349 3350 if ((dn == NULL) || (dn[0] == '\0')) 3351 return (NS_LDAP_INVALID_PARAM); 3352 3353 /* 3354 * break dn into rdns 3355 */ 3356 dn1 = strdup(dn); 3357 if (dn1 == NULL) 3358 return (NS_LDAP_MEMORY); 3359 rdns = ldap_explode_dn(dn1, 0); 3360 free(dn1); 3361 if (rdns == NULL || *rdns == NULL) 3362 return (NS_LDAP_INVALID_PARAM); 3363 3364 for (i = 0; rdns[i]; i++) 3365 len += strlen(rdns[i]) + 1; 3366 pnum = i; 3367 3368 newdn = (char *)malloc(len + 1); 3369 dns = (char **)calloc(pnum, sizeof (char *)); 3370 if (newdn == NULL || dns == NULL) { 3371 if (newdn) 3372 free(newdn); 3373 ldap_value_free(rdns); 3374 return (NS_LDAP_MEMORY); 3375 } 3376 3377 /* construct a semi-normalized dn, newdn */ 3378 *newdn = '\0'; 3379 for (i = 0; rdns[i]; i++) { 3380 dns[i] = newdn + strlen(newdn); 3381 (void) strcat(newdn, 3382 __s_api_remove_rdn_space(rdns[i])); 3383 (void) strcat(newdn, ","); 3384 } 3385 /* remove the last ',' */ 3386 newdn[strlen(newdn) - 1] = '\0'; 3387 ldap_value_free(rdns); 3388 3389 /* 3390 * loop and find the domain name associated with newdn, 3391 * removing rdn one by one from left to right 3392 */ 3393 for (i = 0; i < pnum; i++) { 3394 3395 if (*errorp) 3396 (void) __ns_ldap_freeError(errorp); 3397 3398 /* 3399 * try cache manager first 3400 */ 3401 rc = __s_api_get_cachemgr_data(NS_CACHE_DN2DOMAIN, 3402 dns[i], domain); 3403 if (rc != NS_LDAP_SUCCESS) { 3404 /* 3405 * try ldap server second 3406 */ 3407 rc = __s_api_find_domainname(dns[i], domain, 3408 cred, errorp); 3409 } else { 3410 /* 3411 * skip the last one, 3412 * since it is already cached by ldap_cachemgr 3413 */ 3414 i--; 3415 } 3416 if (rc == NS_LDAP_SUCCESS) { 3417 /* 3418 * ask cache manager to save the 3419 * dn to domain mapping(s) 3420 */ 3421 for (j = 0; j <= i; j++) { 3422 (void) __s_api_set_cachemgr_data( 3423 NS_CACHE_DN2DOMAIN, 3424 dns[j], 3425 *domain); 3426 } 3427 break; 3428 } 3429 } 3430 3431 free(dns); 3432 free(newdn); 3433 if (rc != NS_LDAP_SUCCESS) 3434 rc = NS_LDAP_NOTFOUND; 3435 return (rc); 3436 } 3437 3438 /*ARGSUSED*/ 3439 int 3440 __ns_ldap_getServiceAuthMethods(const char *service, 3441 ns_auth_t ***auth, 3442 ns_ldap_error_t **errorp) 3443 { 3444 char errstr[MAXERROR]; 3445 int rc, i, done = 0; 3446 int slen; 3447 void **param; 3448 char **sam, *srv, *send; 3449 ns_auth_t **authpp = NULL, *ap; 3450 int cnt, max; 3451 ns_config_t *cfg; 3452 ns_ldap_error_t *error = NULL; 3453 3454 if (errorp == NULL) 3455 return (NS_LDAP_INVALID_PARAM); 3456 *errorp = NULL; 3457 3458 if ((service == NULL) || (service[0] == '\0') || 3459 (auth == NULL)) 3460 return (NS_LDAP_INVALID_PARAM); 3461 3462 *auth = NULL; 3463 rc = __ns_ldap_getParam(NS_LDAP_SERVICE_AUTH_METHOD_P, ¶m, &error); 3464 if (rc != NS_LDAP_SUCCESS || param == NULL) { 3465 *errorp = error; 3466 return (rc); 3467 } 3468 sam = (char **)param; 3469 3470 cfg = __s_api_get_default_config(); 3471 cnt = 0; 3472 3473 slen = strlen(service); 3474 3475 for (; *sam; sam++) { 3476 srv = *sam; 3477 if (strncasecmp(service, srv, slen) != 0) 3478 continue; 3479 srv += slen; 3480 if (*srv != COLONTOK) 3481 continue; 3482 send = srv; 3483 srv++; 3484 for (max = 1; (send = strchr(++send, SEMITOK)) != NULL; 3485 max++) {} 3486 authpp = (ns_auth_t **)calloc(++max, sizeof (ns_auth_t *)); 3487 if (authpp == NULL) { 3488 (void) __ns_ldap_freeParam(¶m); 3489 __s_api_release_config(cfg); 3490 return (NS_LDAP_MEMORY); 3491 } 3492 while (!done) { 3493 send = strchr(srv, SEMITOK); 3494 if (send != NULL) { 3495 *send = '\0'; 3496 send++; 3497 } 3498 i = __s_get_enum_value(cfg, srv, NS_LDAP_AUTH_P); 3499 if (i == -1) { 3500 (void) __ns_ldap_freeParam(¶m); 3501 (void) sprintf(errstr, 3502 gettext("Unsupported serviceAuthenticationMethod: %s.\n"), srv); 3503 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX, 3504 strdup(errstr), NULL); 3505 __s_api_release_config(cfg); 3506 return (NS_LDAP_CONFIG); 3507 } 3508 ap = __s_api_AuthEnumtoStruct((EnumAuthType_t)i); 3509 if (ap == NULL) { 3510 (void) __ns_ldap_freeParam(¶m); 3511 __s_api_release_config(cfg); 3512 return (NS_LDAP_MEMORY); 3513 } 3514 authpp[cnt++] = ap; 3515 if (send == NULL) 3516 done = TRUE; 3517 else 3518 srv = send; 3519 } 3520 } 3521 3522 *auth = authpp; 3523 (void) __ns_ldap_freeParam(¶m); 3524 __s_api_release_config(cfg); 3525 return (NS_LDAP_SUCCESS); 3526 } 3527 3528 /* 3529 * This routine is called when certain scenario occurs 3530 * e.g. 3531 * service == auto_home 3532 * SSD = automount: ou = mytest, 3533 * NS_LDAP_MAPATTRIBUTE= auto_home: automountMapName=AAA 3534 * NS_LDAP_OBJECTCLASSMAP= auto_home:automountMap=MynisMap 3535 * NS_LDAP_OBJECTCLASSMAP= auto_home:automount=MynisObject 3536 * 3537 * The automountMapName is prepended implicitely but is mapped 3538 * to AAA. So dn could appers as 3539 * dn: AAA=auto_home,ou=bar,dc=foo,dc=com 3540 * dn: automountKey=user_01,AAA=auto_home,ou=bar,dc=foo,dc=com 3541 * dn: automountKey=user_02,AAA=auto_home,ou=bar,dc=foo,dc=com 3542 * in the directory. 3543 * This function is called to covert the mapped attr back to 3544 * orig attr when the entries are searched and returned 3545 */ 3546 3547 int 3548 __s_api_convert_automountmapname(const char *service, char **dn, 3549 ns_ldap_error_t **errp) { 3550 3551 char **mapping = NULL; 3552 char *mapped_attr = NULL; 3553 char *automountmapname = "automountMapName"; 3554 char *buffer = NULL; 3555 int rc = NS_LDAP_SUCCESS; 3556 char errstr[MAXERROR]; 3557 3558 /* 3559 * dn is an input/out parameter, check it first 3560 */ 3561 3562 if (service == NULL || dn == NULL || *dn == NULL) 3563 return (NS_LDAP_INVALID_PARAM); 3564 3565 /* 3566 * Check to see if there is a mapped attribute for auto_xxx 3567 */ 3568 3569 mapping = __ns_ldap_getMappedAttributes(service, automountmapname); 3570 3571 /* 3572 * if no mapped attribute for auto_xxx, try automount 3573 */ 3574 3575 if (mapping == NULL) 3576 mapping = __ns_ldap_getMappedAttributes( 3577 "automount", automountmapname); 3578 3579 /* 3580 * if no mapped attribute is found, return SUCCESS (no op) 3581 */ 3582 3583 if (mapping == NULL) 3584 return (NS_LDAP_SUCCESS); 3585 3586 /* 3587 * if the mapped attribute is found and attr is not empty, 3588 * copy it 3589 */ 3590 3591 if (mapping[0] != NULL) { 3592 mapped_attr = strdup(mapping[0]); 3593 __s_api_free2dArray(mapping); 3594 if (mapped_attr == NULL) { 3595 return (NS_LDAP_MEMORY); 3596 } 3597 } else { 3598 __s_api_free2dArray(mapping); 3599 3600 (void) snprintf(errstr, (2 * MAXERROR), 3601 gettext( 3602 "Attribute nisMapName is mapped to an " 3603 "empty string.\n")); 3604 3605 MKERROR(LOG_ERR, *errp, NS_CONFIG_SYNTAX, 3606 strdup(errstr), NULL); 3607 3608 return (NS_LDAP_CONFIG); 3609 } 3610 3611 /* 3612 * Locate the mapped attribute in the dn 3613 * and replace it if it exists 3614 */ 3615 3616 rc = __s_api_replace_mapped_attr_in_dn( 3617 (const char *) automountmapname, (const char *) mapped_attr, 3618 (const char *) *dn, &buffer); 3619 3620 /* clean up */ 3621 3622 free(mapped_attr); 3623 3624 /* 3625 * If mapped attr is found(buffer != NULL) 3626 * a new dn is returned 3627 * If no mapped attribute is in dn, 3628 * return NS_LDAP_SUCCESS (no op) 3629 * If no memory, 3630 * return NS_LDAP_MEMORY (no op) 3631 */ 3632 3633 if (buffer != NULL) { 3634 free(*dn); 3635 *dn = buffer; 3636 } 3637 3638 return (rc); 3639 } 3640 3641 /* 3642 * If the mapped attr is found in the dn, 3643 * return NS_LDAP_SUCCESS and a new_dn. 3644 * If no mapped attr is found, 3645 * return NS_LDAP_SUCCESS and *new_dn == NULL 3646 * If there is not enough memory, 3647 * return NS_LDAP_MEMORY and *new_dn == NULL 3648 */ 3649 3650 int 3651 __s_api_replace_mapped_attr_in_dn( 3652 const char *orig_attr, const char *mapped_attr, 3653 const char *dn, char **new_dn) { 3654 3655 char **dnArray = NULL; 3656 char *cur = NULL, *start = NULL; 3657 int i = 0, found = 0; 3658 int len = 0, orig_len = 0, mapped_len = 0; 3659 int dn_len = 0, tmp_len = 0; 3660 3661 *new_dn = NULL; 3662 3663 /* 3664 * seperate dn into individual componets 3665 * e.g. 3666 * "automountKey=user_01" , "automountMapName_test=auto_home", ... 3667 */ 3668 dnArray = ldap_explode_dn(dn, 0); 3669 3670 /* 3671 * This will find "mapped attr=value" in dn. 3672 * It won't find match if mapped attr appears 3673 * in the value. 3674 */ 3675 for (i = 0; dnArray[i] != NULL; i++) { 3676 /* 3677 * This function is called when reading from 3678 * the directory so assume each component has "=". 3679 * Any ill formatted dn should be rejected 3680 * before adding to the directory 3681 */ 3682 cur = strchr(dnArray[i], '='); 3683 *cur = '\0'; 3684 if (strcasecmp(mapped_attr, dnArray[i]) == 0) 3685 found = 1; 3686 *cur = '='; 3687 if (found) break; 3688 } 3689 3690 if (!found) { 3691 __s_api_free2dArray(dnArray); 3692 *new_dn = NULL; 3693 return (NS_LDAP_SUCCESS); 3694 } 3695 /* 3696 * The new length is *dn length + (difference between 3697 * orig attr and mapped attr) + 1 ; 3698 * e.g. 3699 * automountKey=aa,automountMapName_test=auto_home,dc=foo,dc=com 3700 * ==> 3701 * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com 3702 */ 3703 mapped_len = strlen(mapped_attr); 3704 orig_len = strlen(orig_attr); 3705 dn_len = strlen(dn); 3706 len = dn_len + orig_len - mapped_len + 1; 3707 *new_dn = (char *)calloc(1, len); 3708 if (*new_dn == NULL) { 3709 __s_api_free2dArray(dnArray); 3710 return (NS_LDAP_MEMORY); 3711 } 3712 3713 /* 3714 * Locate the mapped attr in the dn. 3715 * Use dnArray[i] instead of mapped_attr 3716 * because mapped_attr could appear in 3717 * the value 3718 */ 3719 3720 cur = strstr(dn, dnArray[i]); 3721 __s_api_free2dArray(dnArray); 3722 /* copy the portion before mapped attr in dn */ 3723 start = *new_dn; 3724 tmp_len = cur - dn; 3725 (void) memcpy((void *) start, (const void*) dn, tmp_len); 3726 3727 /* 3728 * Copy the orig_attr. e.g. automountMapName 3729 * This replaces mapped attr with orig attr 3730 */ 3731 start = start + (cur - dn); /* move cursor in buffer */ 3732 (void) memcpy((void *) start, (const void*) orig_attr, orig_len); 3733 3734 /* 3735 * Copy the portion after mapped attr in dn 3736 */ 3737 cur = cur + mapped_len; /* move cursor in dn */ 3738 start = start + orig_len; /* move cursor in buffer */ 3739 (void) strcpy(start, cur); 3740 3741 return (NS_LDAP_SUCCESS); 3742 } 3743 3744 /* 3745 * Validate Filter functions 3746 */ 3747 3748 /* ***** Start of modified libldap.so.5 filter parser ***** */ 3749 3750 /* filter parsing routine forward references */ 3751 static int adj_filter_list(char *str); 3752 static int adj_simple_filter(char *str); 3753 static int unescape_filterval(char *val); 3754 static int hexchar2int(char c); 3755 static int adj_substring_filter(char *val); 3756 3757 3758 /* 3759 * assumes string manipulation is in-line 3760 * and all strings are sufficient in size 3761 * return value is the position after 'c' 3762 */ 3763 3764 static char * 3765 resync_str(char *str, char *next, char c) 3766 { 3767 char *ret; 3768 3769 ret = str + strlen(str); 3770 *next = c; 3771 if (ret == next) 3772 return (ret); 3773 (void) strcat(str, next); 3774 return (ret); 3775 } 3776 3777 static char * 3778 find_right_paren(char *s) 3779 { 3780 int balance, escape; 3781 3782 balance = 1; 3783 escape = 0; 3784 while (*s && balance) { 3785 if (escape == 0) { 3786 if (*s == '(') 3787 balance++; 3788 else if (*s == ')') 3789 balance--; 3790 } 3791 if (*s == '\\' && ! escape) 3792 escape = 1; 3793 else 3794 escape = 0; 3795 if (balance) 3796 s++; 3797 } 3798 3799 return (*s ? s : NULL); 3800 } 3801 3802 static char * 3803 adj_complex_filter(char *str) 3804 { 3805 char *next; 3806 3807 /* 3808 * We have (x(filter)...) with str sitting on 3809 * the x. We have to find the paren matching 3810 * the one before the x and put the intervening 3811 * filters by calling adj_filter_list(). 3812 */ 3813 3814 str++; 3815 if ((next = find_right_paren(str)) == NULL) 3816 return (NULL); 3817 3818 *next = '\0'; 3819 if (adj_filter_list(str) == -1) 3820 return (NULL); 3821 next = resync_str(str, next, ')'); 3822 next++; 3823 3824 return (next); 3825 } 3826 3827 static int 3828 adj_filter(char *str) 3829 { 3830 char *next; 3831 int parens, balance, escape; 3832 char *np, *cp, *dp; 3833 3834 parens = 0; 3835 while (*str) { 3836 switch (*str) { 3837 case '(': 3838 str++; 3839 parens++; 3840 switch (*str) { 3841 case '&': 3842 if ((str = adj_complex_filter(str)) == NULL) 3843 return (-1); 3844 3845 parens--; 3846 break; 3847 3848 case '|': 3849 if ((str = adj_complex_filter(str)) == NULL) 3850 return (-1); 3851 3852 parens--; 3853 break; 3854 3855 case '!': 3856 if ((str = adj_complex_filter(str)) == NULL) 3857 return (-1); 3858 3859 parens--; 3860 break; 3861 3862 case '(': 3863 /* illegal ((case - generated by conversion */ 3864 3865 /* find missing close) */ 3866 np = find_right_paren(str+1); 3867 3868 /* error if not found */ 3869 if (np == NULL) 3870 return (-1); 3871 3872 /* remove redundant (and) */ 3873 for (dp = str, cp = str+1; cp < np; ) { 3874 *dp++ = *cp++; 3875 } 3876 cp++; 3877 while (*cp) 3878 *dp++ = *cp++; 3879 *dp = '\0'; 3880 3881 /* re-start test at original ( */ 3882 parens--; 3883 str--; 3884 break; 3885 3886 default: 3887 balance = 1; 3888 escape = 0; 3889 next = str; 3890 while (*next && balance) { 3891 if (escape == 0) { 3892 if (*next == '(') 3893 balance++; 3894 else if (*next == ')') 3895 balance--; 3896 } 3897 if (*next == '\\' && ! escape) 3898 escape = 1; 3899 else 3900 escape = 0; 3901 if (balance) 3902 next++; 3903 } 3904 if (balance != 0) 3905 return (-1); 3906 3907 *next = '\0'; 3908 if (adj_simple_filter(str) == -1) { 3909 return (-1); 3910 } 3911 next = resync_str(str, next, ')'); 3912 next++; 3913 str = next; 3914 parens--; 3915 break; 3916 } 3917 break; 3918 3919 case ')': 3920 str++; 3921 parens--; 3922 break; 3923 3924 case ' ': 3925 str++; 3926 break; 3927 3928 default: /* assume it's a simple type=value filter */ 3929 next = strchr(str, '\0'); 3930 if (adj_simple_filter(str) == -1) { 3931 return (-1); 3932 } 3933 str = next; 3934 break; 3935 } 3936 } 3937 3938 return (parens ? -1 : 0); 3939 } 3940 3941 3942 /* 3943 * Put a list of filters like this "(filter1)(filter2)..." 3944 */ 3945 3946 static int 3947 adj_filter_list(char *str) 3948 { 3949 char *next; 3950 char save; 3951 3952 while (*str) { 3953 while (*str && isspace(*str)) 3954 str++; 3955 if (*str == '\0') 3956 break; 3957 3958 if ((next = find_right_paren(str + 1)) == NULL) 3959 return (-1); 3960 save = *++next; 3961 3962 /* now we have "(filter)" with str pointing to it */ 3963 *next = '\0'; 3964 if (adj_filter(str) == -1) 3965 return (-1); 3966 next = resync_str(str, next, save); 3967 3968 str = next; 3969 } 3970 3971 return (0); 3972 } 3973 3974 3975 /* 3976 * is_valid_attr - returns 1 if a is a syntactically valid left-hand side 3977 * of a filter expression, 0 otherwise. A valid string may contain only 3978 * letters, numbers, hyphens, semi-colons, colons and periods. examples: 3979 * cn 3980 * cn;lang-fr 3981 * 1.2.3.4;binary;dynamic 3982 * mail;dynamic 3983 * cn:dn:1.2.3.4 3984 * 3985 * For compatibility with older servers, we also allow underscores in 3986 * attribute types, even through they are not allowed by the LDAPv3 RFCs. 3987 */ 3988 static int 3989 is_valid_attr(char *a) 3990 { 3991 for (; *a; a++) { 3992 if (!isascii(*a)) { 3993 return (0); 3994 } else if (!isalnum(*a)) { 3995 switch (*a) { 3996 case '-': 3997 case '.': 3998 case ';': 3999 case ':': 4000 case '_': 4001 break; /* valid */ 4002 default: 4003 return (0); 4004 } 4005 } 4006 } 4007 return (1); 4008 } 4009 4010 static char * 4011 find_star(char *s) 4012 { 4013 for (; *s; ++s) { 4014 switch (*s) { 4015 case '*': 4016 return (s); 4017 case '\\': 4018 ++s; 4019 if (hexchar2int(s[0]) >= 0 && hexchar2int(s[1]) >= 0) 4020 ++s; 4021 default: 4022 break; 4023 } 4024 } 4025 return (NULL); 4026 } 4027 4028 static int 4029 adj_simple_filter(char *str) 4030 { 4031 char *s, *s2, *s3, filterop; 4032 char *value; 4033 int ftype = 0; 4034 int rc; 4035 4036 rc = -1; /* pessimistic */ 4037 4038 if ((str = strdup(str)) == NULL) { 4039 return (rc); 4040 } 4041 4042 if ((s = strchr(str, '=')) == NULL) { 4043 goto free_and_return; 4044 } 4045 value = s + 1; 4046 *s-- = '\0'; 4047 filterop = *s; 4048 if (filterop == '<' || filterop == '>' || filterop == '~' || 4049 filterop == ':') { 4050 *s = '\0'; 4051 } 4052 4053 if (! is_valid_attr(str)) { 4054 goto free_and_return; 4055 } 4056 4057 switch (filterop) { 4058 case '<': /* LDAP_FILTER_LE */ 4059 case '>': /* LDAP_FILTER_GE */ 4060 case '~': /* LDAP_FILTER_APPROX */ 4061 break; 4062 case ':': /* extended filter - v3 only */ 4063 /* 4064 * extended filter looks like this: 4065 * 4066 * [type][':dn'][':'oid]':='value 4067 * 4068 * where one of type or :oid is required. 4069 * 4070 */ 4071 s2 = s3 = NULL; 4072 if ((s2 = strrchr(str, ':')) == NULL) { 4073 goto free_and_return; 4074 } 4075 if (strcasecmp(s2, ":dn") == 0) { 4076 *s2 = '\0'; 4077 } else { 4078 *s2 = '\0'; 4079 if ((s3 = strrchr(str, ':')) != NULL) { 4080 if (strcasecmp(s3, ":dn") != 0) { 4081 goto free_and_return; 4082 } 4083 *s3 = '\0'; 4084 } 4085 } 4086 if (unescape_filterval(value) < 0) { 4087 goto free_and_return; 4088 } 4089 rc = 0; 4090 goto free_and_return; 4091 /* break; */ 4092 default: 4093 if (find_star(value) == NULL) { 4094 ftype = 0; /* LDAP_FILTER_EQUALITY */ 4095 } else if (strcmp(value, "*") == 0) { 4096 ftype = 1; /* LDAP_FILTER_PRESENT */ 4097 } else { 4098 rc = adj_substring_filter(value); 4099 goto free_and_return; 4100 } 4101 break; 4102 } 4103 4104 if (ftype != 0) { /* == LDAP_FILTER_PRESENT */ 4105 rc = 0; 4106 } else if (unescape_filterval(value) >= 0) { 4107 rc = 0; 4108 } 4109 if (rc != -1) { 4110 rc = 0; 4111 } 4112 4113 free_and_return: 4114 free(str); 4115 return (rc); 4116 } 4117 4118 4119 /* 4120 * Check in place both LDAPv2 (RFC-1960) and LDAPv3 (hexadecimal) escape 4121 * sequences within the null-terminated string 'val'. 4122 * 4123 * If 'val' contains invalid escape sequences we return -1. 4124 * Otherwise return 1 4125 */ 4126 static int 4127 unescape_filterval(char *val) 4128 { 4129 int escape, firstdigit; 4130 char *s; 4131 4132 firstdigit = 0; 4133 escape = 0; 4134 for (s = val; *s; s++) { 4135 if (escape) { 4136 /* 4137 * first try LDAPv3 escape (hexadecimal) sequence 4138 */ 4139 if (hexchar2int(*s) < 0) { 4140 if (firstdigit) { 4141 /* 4142 * LDAPv2 (RFC1960) escape sequence 4143 */ 4144 escape = 0; 4145 } else { 4146 return (-1); 4147 } 4148 } 4149 if (firstdigit) { 4150 firstdigit = 0; 4151 } else { 4152 escape = 0; 4153 } 4154 4155 } else if (*s != '\\') { 4156 escape = 0; 4157 4158 } else { 4159 escape = 1; 4160 firstdigit = 1; 4161 } 4162 } 4163 4164 return (1); 4165 } 4166 4167 4168 /* 4169 * convert character 'c' that represents a hexadecimal digit to an integer. 4170 * if 'c' is not a hexidecimal digit [0-9A-Fa-f], -1 is returned. 4171 * otherwise the converted value is returned. 4172 */ 4173 static int 4174 hexchar2int(char c) 4175 { 4176 if (c >= '0' && c <= '9') { 4177 return (c - '0'); 4178 } 4179 if (c >= 'A' && c <= 'F') { 4180 return (c - 'A' + 10); 4181 } 4182 if (c >= 'a' && c <= 'f') { 4183 return (c - 'a' + 10); 4184 } 4185 return (-1); 4186 } 4187 4188 static int 4189 adj_substring_filter(char *val) 4190 { 4191 char *nextstar; 4192 4193 for (; val != NULL; val = nextstar) { 4194 if ((nextstar = find_star(val)) != NULL) { 4195 *nextstar++ = '\0'; 4196 } 4197 4198 if (*val != '\0') { 4199 if (unescape_filterval(val) < 0) { 4200 return (-1); 4201 } 4202 } 4203 } 4204 4205 return (0); 4206 } 4207 4208 /* ***** End of modified libldap.so.5 filter parser ***** */ 4209 4210 4211 /* 4212 * Walk filter, remove redundant parentheses in-line 4213 * verify that the filter is reasonable 4214 */ 4215 static int 4216 validate_filter(ns_ldap_cookie_t *cookie) 4217 { 4218 char *filter = cookie->filter; 4219 int rc; 4220 4221 /* Parse filter looking for illegal values */ 4222 4223 rc = adj_filter(filter); 4224 if (rc != 0) { 4225 return (NS_LDAP_OP_FAILED); 4226 } 4227 4228 /* end of filter checking */ 4229 4230 return (NS_LDAP_SUCCESS); 4231 } 4232 4233 /* 4234 * Set the account management request control that needs to be sent to server. 4235 * This control is required to get the account management information of 4236 * a user to do local account checking. 4237 */ 4238 static int 4239 setup_acctmgmt_params(ns_ldap_cookie_t *cookie) 4240 { 4241 LDAPControl *req = NULL, **requestctrls; 4242 4243 req = (LDAPControl *)malloc(sizeof (LDAPControl)); 4244 4245 if (req == NULL) 4246 return (NS_LDAP_MEMORY); 4247 4248 /* fill in the fields of this new control */ 4249 req->ldctl_iscritical = 1; 4250 req->ldctl_oid = strdup(NS_LDAP_ACCOUNT_USABLE_CONTROL); 4251 if (req->ldctl_oid == NULL) { 4252 free(req); 4253 return (NS_LDAP_MEMORY); 4254 } 4255 req->ldctl_value.bv_len = 0; 4256 req->ldctl_value.bv_val = NULL; 4257 4258 requestctrls = (LDAPControl **)calloc(2, sizeof (LDAPControl *)); 4259 if (requestctrls == NULL) { 4260 ldap_control_free(req); 4261 return (NS_LDAP_MEMORY); 4262 } 4263 4264 requestctrls[0] = req; 4265 4266 cookie->p_serverctrls = requestctrls; 4267 4268 return (NS_LDAP_SUCCESS); 4269 } 4270 4271 /* 4272 * **** This function needs to be moved to libldap library **** 4273 * parse_acct_cont_resp_msg() parses the message received by server according to 4274 * following format: 4275 * BER encoding: 4276 * * account is usable *ti* 4277 * +t: tag is 0 4278 * +i: contains the num of seconds before expiration. -1 means no expiry. 4279 * * account is not usable *t{bbbtiti}* 4280 * +t: tag is 1 4281 * +b: TRUE if inactive due to account inactivation 4282 * +b: TRUE if password has been reset 4283 * +b: TRUE if password is expired 4284 * +t: tag is 2 4285 * +i: contains num of remaining grace, 0 means no grace 4286 * +t: tag is 3 4287 * +i: contains num of seconds before auto-unlock. -1 means acct is locked 4288 * forever (i.e. until reset) 4289 */ 4290 static int 4291 parse_acct_cont_resp_msg(LDAPControl **ectrls, AcctUsableResponse_t *acctResp) 4292 { 4293 BerElement *ber; 4294 int tag; 4295 ber_len_t len; 4296 int seconds_before_expiry, i; 4297 int inactive, reset, expired, rem_grace, sec_b4_unlock; 4298 4299 if (ectrls == NULL) 4300 return (NS_LDAP_INVALID_PARAM); 4301 4302 for (i = 0; ectrls[i] != NULL; i++) { 4303 if (strcmp(ectrls[i]->ldctl_oid, NS_LDAP_ACCOUNT_USABLE_CONTROL) 4304 == 0) 4305 goto found; 4306 /* We have found some other control, ignore & continue */ 4307 } 4308 /* Ldap control is not found */ 4309 return (NS_LDAP_NOTFOUND); 4310 4311 found: 4312 if ((ber = ber_init(&ectrls[i]->ldctl_value)) == NULL) 4313 return (NS_LDAP_MEMORY); 4314 4315 if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) { 4316 /* Ldap decoding error */ 4317 ber_free(ber, 1); 4318 return (NS_LDAP_INTERNAL); 4319 } 4320 4321 switch (tag) { 4322 case 0: acctResp->choice = 0; 4323 if (ber_scanf(ber, "i", &seconds_before_expiry) 4324 == LBER_ERROR) { 4325 /* Ldap decoding error */ 4326 ber_free(ber, 1); 4327 return (NS_LDAP_INTERNAL); 4328 } 4329 (acctResp->AcctUsableResp).seconds_before_expiry = 4330 seconds_before_expiry; 4331 ber_free(ber, 1); 4332 return (NS_LDAP_SUCCESS); 4333 case 1: acctResp->choice = 1; 4334 if (ber_scanf(ber, "{bbb", &inactive, &reset, &expired) 4335 == LBER_ERROR) { 4336 /* Ldap decoding error */ 4337 ber_free(ber, 1); 4338 return (NS_LDAP_INTERNAL); 4339 } 4340 (acctResp->AcctUsableResp).more_info.inactive = 4341 inactive; 4342 (acctResp->AcctUsableResp).more_info.reset = 4343 reset; 4344 (acctResp->AcctUsableResp).more_info.expired = 4345 expired; 4346 break; 4347 default: /* Ldap decoding error */ 4348 ber_free(ber, 1); 4349 return (NS_LDAP_INTERNAL); 4350 } 4351 4352 if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) { 4353 ber_free(ber, 1); 4354 return (NS_LDAP_SUCCESS); 4355 } 4356 4357 switch (tag) { 4358 case 2: if (ber_scanf(ber, "i", &rem_grace) == LBER_ERROR) { 4359 ber_free(ber, 1); 4360 return (NS_LDAP_INTERNAL); 4361 } 4362 (acctResp->AcctUsableResp).more_info.rem_grace = 4363 rem_grace; 4364 if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) { 4365 ber_free(ber, 1); 4366 return (NS_LDAP_SUCCESS); 4367 } 4368 if (tag == 3) 4369 goto timeb4unlock; 4370 goto unknowntag; 4371 case 3: 4372 timeb4unlock: 4373 if (ber_scanf(ber, "i", &sec_b4_unlock) == LBER_ERROR) { 4374 ber_free(ber, 1); 4375 return (NS_LDAP_INTERNAL); 4376 } 4377 (acctResp->AcctUsableResp).more_info.sec_b4_unlock = 4378 sec_b4_unlock; 4379 break; 4380 default: 4381 unknowntag: 4382 ber_free(ber, 1); 4383 return (NS_LDAP_INTERNAL); 4384 } 4385 4386 ber_free(ber, 1); 4387 return (NS_LDAP_SUCCESS); 4388 } 4389 4390 /* 4391 * __ns_ldap_getAcctMgmt() is called from pam account management stack 4392 * for retrieving accounting information of users with no user password - 4393 * eg. rlogin, rsh, etc. This function uses the account management control 4394 * request to do a search on the server for the user in question. The 4395 * response control returned from the server is got from the cookie. 4396 * Input params: username of whose account mgmt information is to be got 4397 * pointer to hold the parsed account management information 4398 * Return values: NS_LDAP_SUCCESS on success or appropriate error 4399 * code on failure 4400 */ 4401 int 4402 __ns_ldap_getAcctMgmt(const char *user, AcctUsableResponse_t *acctResp) 4403 { 4404 int scope, rc; 4405 char ldapfilter[1024]; 4406 ns_ldap_cookie_t *cookie; 4407 ns_ldap_search_desc_t **sdlist = NULL; 4408 ns_ldap_search_desc_t *dptr; 4409 ns_ldap_error_t *error = NULL; 4410 char **dns = NULL; 4411 char service[] = "shadow"; 4412 4413 if (user == NULL || acctResp == NULL) 4414 return (NS_LDAP_INVALID_PARAM); 4415 4416 /* Initialize State machine cookie */ 4417 cookie = init_search_state_machine(); 4418 if (cookie == NULL) 4419 return (NS_LDAP_MEMORY); 4420 4421 /* see if need to follow referrals */ 4422 rc = __s_api_toFollowReferrals(0, 4423 &cookie->followRef, &error); 4424 if (rc != NS_LDAP_SUCCESS) { 4425 (void) __ns_ldap_freeError(&error); 4426 goto out; 4427 } 4428 4429 /* get the service descriptor - or create a default one */ 4430 rc = __s_api_get_SSD_from_SSDtoUse_service(service, 4431 &sdlist, &error); 4432 if (rc != NS_LDAP_SUCCESS) { 4433 (void) __ns_ldap_freeError(&error); 4434 goto out; 4435 } 4436 4437 if (sdlist == NULL) { 4438 /* Create default service Desc */ 4439 sdlist = (ns_ldap_search_desc_t **)calloc(2, 4440 sizeof (ns_ldap_search_desc_t *)); 4441 if (sdlist == NULL) { 4442 rc = NS_LDAP_MEMORY; 4443 goto out; 4444 } 4445 dptr = (ns_ldap_search_desc_t *) 4446 calloc(1, sizeof (ns_ldap_search_desc_t)); 4447 if (dptr == NULL) { 4448 free(sdlist); 4449 rc = NS_LDAP_MEMORY; 4450 goto out; 4451 } 4452 sdlist[0] = dptr; 4453 4454 /* default base */ 4455 rc = __s_api_getDNs(&dns, service, &cookie->errorp); 4456 if (rc != NS_LDAP_SUCCESS) { 4457 if (dns) { 4458 __s_api_free2dArray(dns); 4459 dns = NULL; 4460 } 4461 (void) __ns_ldap_freeError(&(cookie->errorp)); 4462 cookie->errorp = NULL; 4463 goto out; 4464 } 4465 dptr->basedn = strdup(dns[0]); 4466 if (dptr->basedn == NULL) { 4467 free(sdlist); 4468 free(dptr); 4469 if (dns) { 4470 __s_api_free2dArray(dns); 4471 dns = NULL; 4472 } 4473 rc = NS_LDAP_MEMORY; 4474 goto out; 4475 } 4476 __s_api_free2dArray(dns); 4477 dns = NULL; 4478 4479 /* default scope */ 4480 scope = 0; 4481 rc = __s_api_getSearchScope(&scope, &cookie->errorp); 4482 dptr->scope = scope; 4483 } 4484 4485 cookie->sdlist = sdlist; 4486 4487 cookie->service = strdup(service); 4488 if (cookie->service == NULL) { 4489 rc = NS_LDAP_MEMORY; 4490 goto out; 4491 } 4492 4493 /* search for entries for this particular uid */ 4494 (void) snprintf(ldapfilter, sizeof (ldapfilter), "(uid=%s)", user); 4495 cookie->i_filter = strdup(ldapfilter); 4496 if (cookie->i_filter == NULL) { 4497 rc = NS_LDAP_MEMORY; 4498 goto out; 4499 } 4500 4501 /* create the control request */ 4502 if ((rc = setup_acctmgmt_params(cookie)) != NS_LDAP_SUCCESS) 4503 goto out; 4504 4505 /* Process search */ 4506 rc = search_state_machine(cookie, GET_ACCT_MGMT_INFO, 0); 4507 4508 /* Copy results back to user */ 4509 rc = cookie->err_rc; 4510 if (rc != NS_LDAP_SUCCESS) 4511 (void) __ns_ldap_freeError(&(cookie->errorp)); 4512 4513 if (cookie->result == NULL) 4514 goto out; 4515 4516 if ((rc = parse_acct_cont_resp_msg(cookie->resultctrl, acctResp)) 4517 != NS_LDAP_SUCCESS) 4518 goto out; 4519 4520 rc = NS_LDAP_SUCCESS; 4521 4522 out: 4523 delete_search_cookie(cookie); 4524 4525 return (rc); 4526 } 4527