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