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