1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <sys/types.h> 30 #include <stdlib.h> 31 #include <libintl.h> 32 #include <ctype.h> 33 34 #include <sys/stat.h> 35 #include <sys/mman.h> 36 #include <fcntl.h> 37 #include <unistd.h> 38 #include <string.h> 39 #include <syslog.h> 40 #include <sys/socket.h> 41 #include <sys/sockio.h> 42 #include <netinet/in.h> 43 #include <arpa/inet.h> 44 #include <net/if.h> 45 #include <netdir.h> 46 #include <lber.h> 47 #include <ldap.h> 48 49 #include "ns_sldap.h" 50 #include "ns_internal.h" 51 #include "ns_cache_door.h" 52 53 #define UDP "/dev/udp" 54 #define MAXIFS 32 55 56 struct ifinfo { 57 struct in_addr addr, netmask; 58 }; 59 60 static ns_service_map ns_def_map[] = { 61 { "passwd", "ou=people,", NULL }, 62 { "shadow", "ou=people,", "passwd" }, 63 { "user_attr", "ou=people,", "passwd" }, 64 { "audit_user", "ou=people,", "passwd" }, 65 { "group", "ou=group,", NULL }, 66 { "rpc", "ou=rpc,", NULL }, 67 { "project", "ou=projects,", NULL }, 68 { "protocols", "ou=protocols,", NULL }, 69 { "networks", "ou=networks,", NULL }, 70 { "netmasks", "ou=networks,", "networks" }, 71 { "netgroup", "ou=netgroup,", NULL }, 72 { "aliases", "ou=aliases,", NULL }, 73 { "Hosts", "ou=Hosts,", NULL }, 74 { "ipnodes", "ou=Hosts,", "hosts" }, 75 { "Services", "ou=Services,", NULL }, 76 { "bootparams", "ou=ethers,", "ethers" }, 77 { "ethers", "ou=ethers,", NULL }, 78 { "auth_attr", "ou=SolarisAuthAttr,", NULL }, 79 { "prof_attr", "ou=SolarisProfAttr,", NULL }, 80 { "exec_attr", "ou=SolarisProfAttr,", "prof_attr" }, 81 { "profile", "ou=profile,", NULL }, 82 { "printers", "ou=printers,", NULL }, 83 { "automount", "", NULL }, 84 { "tnrhtp", "ou=ipTnet,", NULL }, 85 { "tnrhdb", "ou=ipTnet,", "tnrhtp" }, 86 { NULL, NULL, NULL } 87 }; 88 89 90 static char ** parseDN(const char *val, const char *service); 91 static char ** sortServerNet(char **srvlist); 92 static char ** sortServerPref(char **srvlist, char **preflist, 93 boolean_t flag, int version, int *error); 94 95 /* 96 * FUNCTION: s_api_printResult 97 * Given a ns_ldap_result structure print it. 98 */ 99 int 100 __s_api_printResult(ns_ldap_result_t *result) 101 { 102 103 ns_ldap_entry_t *curEntry; 104 int i, j, k = 0; 105 106 #ifdef DEBUG 107 (void) fprintf(stderr, "__s_api_printResult START\n"); 108 #endif 109 (void) printf("--------------------------------------\n"); 110 if (result == NULL) { 111 (void) printf("No result\n"); 112 return (0); 113 } 114 (void) printf("entries_count %d\n", result->entries_count); 115 curEntry = result->entry; 116 for (i = 0; i < result->entries_count; i++) { 117 118 (void) printf("entry %d has attr_count = %d \n", i, 119 curEntry->attr_count); 120 for (j = 0; j < curEntry->attr_count; j++) { 121 (void) printf("entry %d has attr_pair[%d] = %s \n", 122 i, j, curEntry->attr_pair[j]->attrname); 123 for (k = 0; k < 20 && 124 curEntry->attr_pair[j]->attrvalue[k]; k++) 125 (void) printf("entry %d has attr_pair[%d]->" 126 "attrvalue[%d] = %s \n", i, j, k, 127 curEntry->attr_pair[j]->attrvalue[k]); 128 } 129 (void) printf("\n--------------------------------------\n"); 130 curEntry = curEntry->next; 131 } 132 return (1); 133 } 134 135 /* 136 * FUNCTION: __s_api_getSearchScope 137 * 138 * Retrieve the search scope for ldap search from the config module. 139 * 140 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_CONFIG 141 * INPUT: NONE 142 * OUTPUT: searchScope, errorp 143 */ 144 int 145 __s_api_getSearchScope( 146 int *searchScope, 147 ns_ldap_error_t **errorp) 148 { 149 150 char errmsg[MAXERROR]; 151 void **paramVal = NULL; 152 int rc = 0; 153 int scope = 0; 154 155 #ifdef DEBUG 156 (void) fprintf(stderr, "__s_api_getSearchScope START\n"); 157 #endif 158 if (*searchScope == 0) { 159 if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_SCOPE_P, 160 ¶mVal, errorp)) != NS_LDAP_SUCCESS) { 161 return (rc); 162 } 163 if (paramVal && *paramVal) 164 scope = * (int *)(*paramVal); 165 else 166 scope = NS_LDAP_SCOPE_ONELEVEL; 167 (void) __ns_ldap_freeParam(¶mVal); 168 } else { 169 scope = *searchScope; 170 } 171 172 switch (scope) { 173 174 case NS_LDAP_SCOPE_ONELEVEL: 175 *searchScope = LDAP_SCOPE_ONELEVEL; 176 break; 177 case NS_LDAP_SCOPE_BASE: 178 *searchScope = LDAP_SCOPE_BASE; 179 break; 180 case NS_LDAP_SCOPE_SUBTREE: 181 *searchScope = LDAP_SCOPE_SUBTREE; 182 break; 183 default: 184 (void) snprintf(errmsg, sizeof (errmsg), 185 gettext("Invalid search scope!")); 186 MKERROR(LOG_ERR, *errorp, NS_CONFIG_FILE, 187 strdup(errmsg), NS_LDAP_CONFIG); 188 return (NS_LDAP_CONFIG); 189 } 190 191 return (NS_LDAP_SUCCESS); 192 } 193 194 /* 195 * FUNCTION: __ns_ldap_dupAuth 196 * 197 * Duplicates an authentication structure. 198 * 199 * RETURN VALUES: copy of authp or NULL on error 200 * INPUT: authp 201 */ 202 ns_cred_t * 203 __ns_ldap_dupAuth(const ns_cred_t *authp) 204 { 205 ns_cred_t *ap; 206 207 #ifdef DEBUG 208 (void) fprintf(stderr, "__ns_ldap_dupAuth START\n"); 209 #endif 210 if (authp == NULL) 211 return (NULL); 212 213 ap = (ns_cred_t *)calloc(1, sizeof (ns_cred_t)); 214 if (ap == NULL) 215 return (NULL); 216 217 if (authp->hostcertpath) { 218 ap->hostcertpath = strdup(authp->hostcertpath); 219 if (ap->hostcertpath == NULL) { 220 free(ap); 221 return (NULL); 222 } 223 } 224 if (authp->cred.unix_cred.userID) { 225 ap->cred.unix_cred.userID = 226 strdup(authp->cred.unix_cred.userID); 227 if (ap->cred.unix_cred.userID == NULL) { 228 (void) __ns_ldap_freeCred(&ap); 229 return (NULL); 230 } 231 } 232 if (authp->cred.unix_cred.passwd) { 233 ap->cred.unix_cred.passwd = 234 strdup(authp->cred.unix_cred.passwd); 235 if (ap->cred.unix_cred.passwd == NULL) { 236 (void) __ns_ldap_freeCred(&ap); 237 return (NULL); 238 } 239 } 240 if (authp->cred.cert_cred.nickname) { 241 ap->cred.cert_cred.nickname = 242 strdup(authp->cred.cert_cred.nickname); 243 if (ap->cred.cert_cred.nickname == NULL) { 244 (void) __ns_ldap_freeCred(&ap); 245 return (NULL); 246 } 247 } 248 ap->auth.type = authp->auth.type; 249 ap->auth.tlstype = authp->auth.tlstype; 250 ap->auth.saslmech = authp->auth.saslmech; 251 ap->auth.saslopt = authp->auth.saslopt; 252 return (ap); 253 } 254 255 /* 256 * FUNCTION: __ns_ldap_freeCred 257 * 258 * Frees all the memory associated with a ns_cred_t structure. 259 * 260 * RETURN VALUES: NS_LDAP_INVALID_PARAM, NS_LDAP_SUCCESS, NS_LDAP_CONFIG 261 * INPUT: ns_cred_t 262 */ 263 int 264 __ns_ldap_freeCred(ns_cred_t ** credp) 265 { 266 ns_cred_t *ap; 267 268 #ifdef DEBUG 269 (void) fprintf(stderr, "__ns_ldap_freeCred START\n"); 270 #endif 271 if (credp == NULL || *credp == NULL) 272 return (NS_LDAP_INVALID_PARAM); 273 274 ap = *credp; 275 if (ap->hostcertpath) { 276 (void) memset(ap->hostcertpath, 0, 277 strlen(ap->hostcertpath)); 278 free(ap->hostcertpath); 279 } 280 281 if (ap->cred.unix_cred.userID) { 282 (void) memset(ap->cred.unix_cred.userID, 0, 283 strlen(ap->cred.unix_cred.userID)); 284 free(ap->cred.unix_cred.userID); 285 } 286 287 if (ap->cred.unix_cred.passwd) { 288 (void) memset(ap->cred.unix_cred.passwd, 0, 289 strlen(ap->cred.unix_cred.passwd)); 290 free(ap->cred.unix_cred.passwd); 291 } 292 293 if (ap->cred.cert_cred.nickname) { 294 (void) memset(ap->cred.cert_cred.nickname, 0, 295 strlen(ap->cred.cert_cred.nickname)); 296 free(ap->cred.cert_cred.nickname); 297 } 298 299 free(ap); 300 *credp = NULL; 301 return (NS_LDAP_SUCCESS); 302 } 303 304 /* 305 * FUNCTION: __s_api_getDNs 306 * 307 * Retrieves the default base dn for the given 308 * service. 309 * 310 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_CONFIG 311 * INPUT: service 312 * OUTPUT: DN, error 313 */ 314 typedef int (*pf)(const char *, char **, ns_ldap_error_t **); 315 int 316 __s_api_getDNs( 317 char *** DN, 318 const char *service, 319 ns_ldap_error_t ** error) 320 { 321 322 void **paramVal = NULL; 323 char **dns = NULL; 324 int rc = 0; 325 int i, len; 326 pf prepend_auto2dn = __s_api_prepend_automountmapname_to_dn; 327 328 #ifdef DEBUG 329 (void) fprintf(stderr, "__s_api_getDNs START\n"); 330 #endif 331 if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P, 332 ¶mVal, error)) != NS_LDAP_SUCCESS) { 333 return (rc); 334 } 335 if (!paramVal) { 336 char errmsg[MAXERROR]; 337 338 (void) snprintf(errmsg, sizeof (errmsg), 339 gettext("BaseDN not defined")); 340 MKERROR(LOG_ERR, *error, NS_CONFIG_FILE, strdup(errmsg), 341 NS_LDAP_CONFIG); 342 return (NS_LDAP_CONFIG); 343 } 344 345 dns = (char **)calloc(2, sizeof (char *)); 346 if (dns == NULL) { 347 (void) __ns_ldap_freeParam(¶mVal); 348 return (NS_LDAP_MEMORY); 349 } 350 351 if (service == NULL) { 352 dns[0] = strdup((char *)*paramVal); 353 if (dns[0] == NULL) { 354 (void) __ns_ldap_freeParam(¶mVal); 355 free(dns); 356 return (NS_LDAP_MEMORY); 357 } 358 } else { 359 for (i = 0; ns_def_map[i].service != NULL; i++) { 360 if (strcasecmp(service, 361 ns_def_map[i].service) == 0) { 362 363 len = strlen((char *)*paramVal) + 364 strlen(ns_def_map[i].rdn) + 1; 365 dns[0] = (char *) 366 calloc(len, sizeof (char)); 367 if (dns[0] == NULL) { 368 (void) __ns_ldap_freeParam( 369 ¶mVal); 370 free(dns); 371 return (NS_LDAP_MEMORY); 372 } 373 (void) strcpy(dns[0], 374 ns_def_map[i].rdn); 375 (void) strcat(dns[0], 376 (char *)*paramVal); 377 break; 378 } 379 } 380 if (ns_def_map[i].service == NULL) { 381 char *p = (char *)*paramVal; 382 char *buffer = NULL; 383 int buflen = 0; 384 385 if (strchr(service, '=') == NULL) { 386 /* automount entries */ 387 if (strncasecmp(service, "auto_", 5) == 0) { 388 buffer = strdup(p); 389 if (!buffer) { 390 free(dns); 391 (void) __ns_ldap_freeParam( 392 ¶mVal); 393 return (NS_LDAP_MEMORY); 394 } 395 /* shorten name to avoid cstyle error */ 396 rc = prepend_auto2dn( 397 service, &buffer, error); 398 if (rc != NS_LDAP_SUCCESS) { 399 free(dns); 400 free(buffer); 401 (void) __ns_ldap_freeParam( 402 ¶mVal); 403 return (rc); 404 } 405 } else { 406 /* strlen("nisMapName")+"="+","+'\0' = 13 */ 407 buflen = strlen(service) + strlen(p) + 408 13; 409 buffer = (char *)malloc(buflen); 410 if (buffer == NULL) { 411 free(dns); 412 (void) __ns_ldap_freeParam( 413 ¶mVal); 414 return (NS_LDAP_MEMORY); 415 } 416 (void) snprintf(buffer, buflen, 417 "nisMapName=%s,%s", service, p); 418 } 419 } else { 420 buflen = strlen(service) + strlen(p) + 2; 421 buffer = (char *)malloc(buflen); 422 if (buffer == NULL) { 423 free(dns); 424 (void) __ns_ldap_freeParam(¶mVal); 425 return (NS_LDAP_MEMORY); 426 } 427 (void) snprintf(buffer, buflen, 428 "%s,%s", service, p); 429 } 430 dns[0] = buffer; 431 } 432 } 433 434 (void) __ns_ldap_freeParam(¶mVal); 435 *DN = dns; 436 return (NS_LDAP_SUCCESS); 437 } 438 /* 439 * FUNCTION: __s_api_get_search_DNs_v1 440 * 441 * Retrieves the list of search DNS from the V1 profile for the given 442 * service. 443 * 444 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_CONFIG 445 * INPUT: service 446 * OUTPUT: DN, error 447 */ 448 int 449 __s_api_get_search_DNs_v1( 450 char *** DN, 451 const char *service, 452 ns_ldap_error_t ** error) 453 { 454 455 void **paramVal = NULL; 456 void **temptr = NULL; 457 char **dns = NULL; 458 int rc = 0; 459 460 if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_DN_P, 461 ¶mVal, error)) != NS_LDAP_SUCCESS) { 462 return (rc); 463 } 464 465 if (service && paramVal) { 466 for (temptr = paramVal; *temptr != NULL; temptr++) { 467 dns = parseDN((const char *)(*temptr), 468 (const char *)service); 469 if (dns != NULL) 470 break; 471 } 472 } 473 474 (void) __ns_ldap_freeParam(¶mVal); 475 *DN = dns; 476 return (NS_LDAP_SUCCESS); 477 478 } 479 /* 480 * FUNCTION: parseDN 481 * 482 * Parse a special formated list(val) into an array of char *. 483 * 484 * RETURN VALUE: A char * pointer to the new list of dns. 485 * INPUT: val, service 486 */ 487 static char ** 488 parseDN( 489 const char *val, 490 const char *service) 491 { 492 493 size_t len = 0; 494 size_t slen = 0; 495 char **retVal = NULL; 496 const char *temptr; 497 char *temptr2; 498 const char *valend; 499 int valNo = 0; 500 int valSize = 0; 501 int i; 502 char *SSD_service = NULL; 503 504 #ifdef DEBUG 505 (void) fprintf(stderr, "parseDN START\n"); 506 #endif 507 if (val == NULL || *val == '\0') 508 return (NULL); 509 if (service == NULL || *service == '\0') 510 return (NULL); 511 512 len = strlen(val); 513 slen = strlen(service); 514 if (strncasecmp(val, service, slen) != 0) { 515 /* 516 * This routine is only called 517 * to process V1 profile and 518 * for V1 profile, map service 519 * to the corresponding SSD_service 520 * which is associated with a 521 * real container in the LDAP directory 522 * tree, e.g., map "shadow" to 523 * "password". See function 524 * __s_api_get_SSD_from_SSDtoUse_service 525 * for similar service to SSD_service 526 * mapping handling for V2 profile. 527 */ 528 for (i = 0; ns_def_map[i].service != NULL; i++) { 529 if (ns_def_map[i].SSDtoUse_service && 530 strcasecmp(service, 531 ns_def_map[i].service) == 0) { 532 SSD_service = 533 ns_def_map[i].SSDtoUse_service; 534 break; 535 } 536 } 537 538 if (SSD_service == NULL) 539 return (NULL); 540 541 slen = strlen(SSD_service); 542 if (strncasecmp(val, SSD_service, slen) != 0) 543 return (NULL); 544 } 545 546 temptr = val + slen; 547 while (*temptr == SPACETOK || *temptr == TABTOK) 548 temptr++; 549 if (*temptr != COLONTOK) 550 return (NULL); 551 552 while (*temptr) { 553 temptr2 = strchr(temptr, OPARATOK); 554 if (temptr2 == NULL) 555 break; 556 temptr2++; 557 temptr2 = strchr(temptr2, CPARATOK); 558 if (temptr2 == NULL) 559 break; 560 valNo++; 561 temptr = temptr2+1; 562 } 563 564 retVal = (char **)calloc(valNo +1, sizeof (char *)); 565 if (retVal == NULL) 566 return (NULL); 567 568 temptr = val; 569 valend = val+len; 570 571 for (i = 0; (i < valNo) && (temptr < valend); i++) { 572 temptr = strchr(temptr, OPARATOK); 573 if (temptr == NULL) { 574 __s_api_free2dArray(retVal); 575 return (NULL); 576 } 577 temptr++; 578 temptr2 = strchr(temptr, CPARATOK); 579 if (temptr2 == NULL) { 580 __s_api_free2dArray(retVal); 581 return (NULL); 582 } 583 valSize = temptr2 - temptr; 584 585 retVal[i] = (char *)calloc(valSize + 1, sizeof (char)); 586 if (retVal[i] == NULL) { 587 __s_api_free2dArray(retVal); 588 return (NULL); 589 } 590 (void) strncpy(retVal[i], temptr, valSize); 591 retVal[i][valSize] = '\0'; 592 temptr = temptr2 + 1; 593 } 594 595 return (retVal); 596 } 597 598 599 /* 600 * __s_api_get_local_interfaces 601 * 602 * Returns a pointer to an array of addresses and netmasks of all interfaces 603 * configured on the system. 604 * 605 * NOTE: This function is very IPv4 centric. 606 */ 607 static struct ifinfo * 608 __s_api_get_local_interfaces() 609 { 610 struct ifconf ifc; 611 struct ifreq ifreq, *ifr; 612 struct ifinfo *localinfo; 613 struct in_addr netmask; 614 struct sockaddr_in *sin; 615 void *buf = NULL; 616 int fd = 0; 617 int numifs = 0; 618 int i, n = 0; 619 620 if ((fd = open(UDP, O_RDONLY)) < 0) 621 return ((struct ifinfo *)NULL); 622 623 if (ioctl(fd, SIOCGIFNUM, (char *)&numifs) < 0) { 624 numifs = MAXIFS; 625 } 626 627 buf = malloc(numifs * sizeof (struct ifreq)); 628 if (buf == NULL) { 629 (void) close(fd); 630 return ((struct ifinfo *)NULL); 631 } 632 ifc.ifc_len = numifs * (int)sizeof (struct ifreq); 633 ifc.ifc_buf = buf; 634 if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) { 635 (void) close(fd); 636 free(buf); 637 buf = NULL; 638 return ((struct ifinfo *)NULL); 639 } 640 ifr = (struct ifreq *)buf; 641 numifs = ifc.ifc_len/(int)sizeof (struct ifreq); 642 localinfo = (struct ifinfo *)malloc((numifs + 1) * 643 sizeof (struct ifinfo)); 644 if (localinfo == NULL) { 645 (void) close(fd); 646 free(buf); 647 buf = NULL; 648 return ((struct ifinfo *)NULL); 649 } 650 651 for (i = 0, n = numifs; n > 0; n--, ifr++) { 652 uint_t ifrflags; 653 654 ifreq = *ifr; 655 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifreq) < 0) 656 continue; 657 658 ifrflags = ifreq.ifr_flags; 659 if (((ifrflags & IFF_UP) == 0) || 660 (ifr->ifr_addr.sa_family != AF_INET)) 661 continue; 662 663 if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifreq) < 0) 664 continue; 665 netmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr; 666 667 if (ioctl(fd, SIOCGIFADDR, (char *)&ifreq) < 0) 668 continue; 669 670 sin = (struct sockaddr_in *)&ifreq.ifr_addr; 671 672 localinfo[i].addr = sin->sin_addr; 673 localinfo[i].netmask = netmask; 674 i++; 675 } 676 localinfo[i].addr.s_addr = 0; 677 678 free(buf); 679 buf = NULL; 680 (void) close(fd); 681 return (localinfo); 682 } 683 684 685 /* 686 * __s_api_samenet(char *, struct ifinfo *) 687 * 688 * Returns 1 if address is on the same subnet of the array of addresses 689 * passed in. 690 * 691 * NOTE: This function is only valid for IPv4 addresses. 692 */ 693 static int 694 __s_api_IPv4sameNet(char *addr, struct ifinfo *ifs) 695 { 696 int answer = 0; 697 698 if (addr && ifs) { 699 char *addr_raw; 700 unsigned long iaddr; 701 int i; 702 703 if ((addr_raw = strdup(addr)) != NULL) { 704 char *s; 705 706 /* Remove port number. */ 707 if ((s = strchr(addr_raw, ':')) != NULL) 708 *s = '\0'; 709 710 iaddr = inet_addr(addr_raw); 711 712 /* Loop through interface list to find match. */ 713 for (i = 0; ifs[i].addr.s_addr != 0; i++) { 714 if ((iaddr & ifs[i].netmask.s_addr) == 715 (ifs[i].addr.s_addr & 716 ifs[i].netmask.s_addr)) 717 answer++; 718 } 719 free(addr_raw); 720 } 721 } 722 723 return (answer); 724 } 725 726 /* 727 * FUNCTION: __s_api_getServers 728 * 729 * Retrieve a list of ldap servers from the config module. 730 * 731 * RETURN VALUE: NS_LDAP_SUCCESS, NS_LDAP_CONFIG, NS_LDAP_MEMORY 732 * INPUT: NONE 733 * OUTPUT: servers, error 734 */ 735 int 736 __s_api_getServers( 737 char *** servers, 738 ns_ldap_error_t ** error) 739 { 740 void **paramVal = NULL; 741 char errmsg[MAXERROR]; 742 char **sortServers = NULL; 743 char **netservers = NULL; 744 int rc = 0, err = NS_LDAP_CONFIG, version = 1; 745 const char *str, *str1; 746 747 #ifdef DEBUG 748 (void) fprintf(stderr, "__s_api_getServers START\n"); 749 #endif 750 *servers = NULL; 751 /* get profile version number */ 752 if ((rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, 753 ¶mVal, error)) != NS_LDAP_SUCCESS) 754 return (rc); 755 756 if (paramVal == NULL || *paramVal == NULL) { 757 (void) snprintf(errmsg, sizeof (errmsg), 758 gettext("No file version")); 759 MKERROR(LOG_INFO, *error, NS_CONFIG_FILE, strdup(errmsg), 760 NS_LDAP_CONFIG); 761 return (NS_LDAP_CONFIG); 762 } 763 764 if (strcasecmp((char *)*paramVal, NS_LDAP_VERSION_1) == 0) 765 version = 1; 766 else if (strcasecmp((char *)*paramVal, NS_LDAP_VERSION_2) == 0) 767 version = 2; 768 769 (void) __ns_ldap_freeParam(¶mVal); 770 paramVal = NULL; 771 772 if ((rc = __ns_ldap_getParam(NS_LDAP_SERVERS_P, 773 ¶mVal, error)) != NS_LDAP_SUCCESS) 774 return (rc); 775 776 /* 777 * For version 2, default server list could be 778 * empty. 779 */ 780 if ((paramVal == NULL || (char *)*paramVal == NULL) && 781 version == 1) { 782 str = NULL_OR_STR(__s_api_get_configname(NS_LDAP_SERVERS_P)); 783 (void) snprintf(errmsg, sizeof (errmsg), 784 gettext("Unable to retrieve the '%s' list"), str); 785 MKERROR(LOG_WARNING, *error, NS_CONFIG_FILE, strdup(errmsg), 786 NS_LDAP_CONFIG); 787 return (NS_LDAP_CONFIG); 788 } 789 790 /* 791 * Get server address(es) and go through them. 792 */ 793 *servers = (char **)paramVal; 794 paramVal = NULL; 795 796 /* Sort servers based on network. */ 797 if (*servers) { 798 netservers = sortServerNet(*servers); 799 if (netservers) { 800 free(*servers); 801 *servers = netservers; 802 } else { 803 return (NS_LDAP_MEMORY); 804 } 805 } 806 807 /* Get preferred server list and sort servers based on that. */ 808 if ((rc = __ns_ldap_getParam(NS_LDAP_SERVER_PREF_P, 809 ¶mVal, error)) != NS_LDAP_SUCCESS) { 810 if (*servers) 811 __s_api_free2dArray(*servers); 812 *servers = NULL; 813 return (rc); 814 } 815 816 if (paramVal != NULL) { 817 char **prefServers; 818 void **val = NULL; 819 820 if ((rc = __ns_ldap_getParam(NS_LDAP_PREF_ONLY_P, 821 &val, error)) != NS_LDAP_SUCCESS) { 822 if (*servers) 823 __s_api_free2dArray(*servers); 824 *servers = NULL; 825 (void) __ns_ldap_freeParam(¶mVal); 826 return (rc); 827 } 828 829 prefServers = (char **)paramVal; 830 paramVal = NULL; 831 if (prefServers) { 832 if (val != NULL && (*val) != NULL && 833 *(int *)val[0] == 1) 834 sortServers = sortServerPref(*servers, 835 prefServers, B_FALSE, version, 836 &err); 837 else 838 sortServers = sortServerPref(*servers, 839 prefServers, B_TRUE, version, 840 &err); 841 if (sortServers) { 842 if (*servers) 843 free(*servers); 844 *servers = NULL; 845 free(prefServers); 846 prefServers = NULL; 847 *servers = sortServers; 848 } else { 849 if (*servers) 850 __s_api_free2dArray(*servers); 851 *servers = NULL; 852 __s_api_free2dArray(prefServers); 853 prefServers = NULL; 854 } 855 } 856 (void) __ns_ldap_freeParam(&val); 857 } 858 (void) __ns_ldap_freeParam(¶mVal); 859 860 if (*servers == NULL) { 861 if (err == NS_LDAP_CONFIG) { 862 str = NULL_OR_STR(__s_api_get_configname( 863 NS_LDAP_SERVERS_P)); 864 str1 = NULL_OR_STR(__s_api_get_configname( 865 NS_LDAP_SERVER_PREF_P)); 866 (void) snprintf(errmsg, sizeof (errmsg), 867 gettext("Unable to generate a new server list " 868 "based on '%s' and/or '%s'"), str, str1); 869 MKERROR(LOG_WARNING, *error, NS_CONFIG_FILE, 870 strdup(errmsg), err); 871 return (err); 872 } 873 return (NS_LDAP_MEMORY); 874 } 875 876 return (NS_LDAP_SUCCESS); 877 878 } 879 880 /* 881 * FUNCTION: sortServerNet 882 * Sort the serverlist based on the distance from client as long 883 * as the list only contains IPv4 addresses. Otherwise do nothing. 884 */ 885 static char ** 886 sortServerNet(char **srvlist) 887 { 888 int count = 0; 889 int all = 0; 890 int ipv4only = 1; 891 struct ifinfo *ifs = __s_api_get_local_interfaces(); 892 char **tsrvs; 893 char **psrvs, **retsrvs; 894 895 /* Sanity check. */ 896 if (srvlist == NULL || srvlist[0] == NULL) 897 return (NULL); 898 899 /* Count the number of servers to sort. */ 900 for (count = 0; srvlist[count] != NULL; count++) { 901 if (!__s_api_isipv4(srvlist[count])) 902 ipv4only = 0; 903 } 904 count++; 905 906 /* Make room for the returned list of servers. */ 907 retsrvs = (char **)calloc(count, sizeof (char *)); 908 if (retsrvs == NULL) { 909 free(ifs); 910 ifs = NULL; 911 return (NULL); 912 } 913 914 retsrvs[count - 1] = NULL; 915 916 /* Make a temporary list of servers. */ 917 psrvs = (char **)calloc(count, sizeof (char *)); 918 if (psrvs == NULL) { 919 free(ifs); 920 ifs = NULL; 921 free(retsrvs); 922 retsrvs = NULL; 923 return (NULL); 924 } 925 926 /* Filter servers on the same subnet */ 927 tsrvs = srvlist; 928 while (*tsrvs) { 929 if (ipv4only && __s_api_IPv4sameNet(*tsrvs, ifs)) { 930 psrvs[all] = *tsrvs; 931 retsrvs[all++] = *(tsrvs); 932 } 933 tsrvs++; 934 } 935 936 /* Filter remaining servers. */ 937 tsrvs = srvlist; 938 while (*tsrvs) { 939 char **ttsrvs = psrvs; 940 941 while (*ttsrvs) { 942 if (strcmp(*tsrvs, *ttsrvs) == 0) 943 break; 944 ttsrvs++; 945 } 946 947 if (*ttsrvs == NULL) 948 retsrvs[all++] = *(tsrvs); 949 tsrvs++; 950 } 951 952 free(ifs); 953 ifs = NULL; 954 free(psrvs); 955 psrvs = NULL; 956 957 return (retsrvs); 958 } 959 960 /* 961 * FUNCTION: sortServerPref 962 * Sort the serverlist based on the preferred server list. 963 * 964 * The sorting algorithm works as follows: 965 * 966 * If version 1, if flag is TRUE, find all the servers in both preflist 967 * and srvlist, then append other servers in srvlist to this list 968 * and return the list. 969 * If flag is FALSE, just return srvlist. 970 * srvlist can not be empty. 971 * 972 * If version 2, append all the servers in srvlist 973 * but not in preflist to preflist, and return the merged list. 974 * If srvlist is empty, just return preflist. 975 * If preflist is empty, just return srvlist. 976 */ 977 static char ** 978 sortServerPref(char **srvlist, char **preflist, 979 boolean_t flag, int version, int *error) 980 { 981 int i, scount = 0, pcount = 0; 982 int all = 0, dup = 0; 983 char **tsrvs; 984 char **retsrvs; 985 char **dupsrvs; 986 987 /* Count the number of servers to sort. */ 988 if (srvlist && srvlist[0]) 989 for (i = 0; srvlist[i] != NULL; i++) 990 scount++; 991 992 /* Sanity check. */ 993 if (scount == 0 && version == 1) { 994 *error = NS_LDAP_CONFIG; 995 return (NULL); 996 } 997 998 /* Count the number of preferred servers */ 999 if (preflist && preflist[0]) 1000 for (i = 0; preflist[i] != NULL; i++) 1001 pcount++; 1002 1003 /* Sanity check. */ 1004 if (scount == 0 && pcount == 0) { 1005 *error = NS_LDAP_CONFIG; 1006 return (NULL); 1007 } 1008 1009 /* Make room for the returned list of servers */ 1010 retsrvs = (char **)calloc(scount + pcount + 1, sizeof (char *)); 1011 if (retsrvs == NULL) { 1012 *error = NS_LDAP_MEMORY; 1013 return (NULL); 1014 } 1015 1016 /* 1017 * if the preferred server list is empty, 1018 * just return a copy of the server list 1019 */ 1020 if (pcount == 0) { 1021 tsrvs = srvlist; 1022 while (*tsrvs) 1023 retsrvs[all++] = *(tsrvs++); 1024 return (retsrvs); 1025 } 1026 all = 0; 1027 1028 /* 1029 * if the server list is empty, 1030 * just return a copy of the preferred server list 1031 */ 1032 if (scount == 0) { 1033 tsrvs = preflist; 1034 while (*tsrvs) 1035 retsrvs[all++] = *(tsrvs++); 1036 return (retsrvs); 1037 } 1038 all = 0; 1039 1040 /* Make room for the servers whose memory needs to be freed */ 1041 dupsrvs = (char **)calloc(scount + pcount + 1, sizeof (char *)); 1042 if (dupsrvs == NULL) { 1043 free(retsrvs); 1044 *error = NS_LDAP_MEMORY; 1045 return (NULL); 1046 } 1047 1048 /* 1049 * If version 1, 1050 * throw out preferred servers not on server list. 1051 * If version 2, make a copy of the preferred server list. 1052 */ 1053 if (version == 1) { 1054 tsrvs = preflist; 1055 while (*tsrvs) { 1056 char **ttsrvs = srvlist; 1057 1058 while (*ttsrvs) { 1059 if (strcmp(*tsrvs, *(ttsrvs)) == 0) 1060 break; 1061 ttsrvs++; 1062 } 1063 if (*ttsrvs != NULL) 1064 retsrvs[all++] = *tsrvs; 1065 else 1066 dupsrvs[dup++] = *tsrvs; 1067 tsrvs++; 1068 } 1069 } else { 1070 tsrvs = preflist; 1071 while (*tsrvs) 1072 retsrvs[all++] = *(tsrvs++); 1073 } 1074 /* 1075 * If version 1, 1076 * if PREF_ONLY is false, we append the non-preferred servers 1077 * to bottom of list. 1078 * For version 2, always append. 1079 */ 1080 if (flag == B_TRUE || version != 1) { 1081 1082 tsrvs = srvlist; 1083 while (*tsrvs) { 1084 char **ttsrvs = preflist; 1085 1086 while (*ttsrvs) { 1087 if (strcmp(*tsrvs, *ttsrvs) == 0) { 1088 break; 1089 } 1090 ttsrvs++; 1091 } 1092 if (*ttsrvs == NULL) 1093 retsrvs[all++] = *tsrvs; 1094 else 1095 dupsrvs[dup++] = *tsrvs; 1096 tsrvs++; 1097 } 1098 } 1099 1100 /* free memory for duplicate servers */ 1101 if (dup) { 1102 for (tsrvs = dupsrvs; *tsrvs; tsrvs++) 1103 free(*tsrvs); 1104 } 1105 free(dupsrvs); 1106 1107 return (retsrvs); 1108 } 1109 1110 /* 1111 * FUNCTION: __s_api_removeBadServers 1112 * Contacts the ldap cache manager for marking the 1113 * problem servers as down, so that the server is 1114 * not contacted until the TTL expires. 1115 */ 1116 void 1117 __s_api_removeBadServers(char ** Servers) 1118 { 1119 1120 char **host; 1121 1122 if (Servers == NULL) 1123 return; 1124 1125 for (host = Servers; *host != NULL; host++) { 1126 if (__s_api_removeServer(*host) < 0) { 1127 /* 1128 * Couldn't remove server from 1129 * server list. Log a warning. 1130 */ 1131 syslog(LOG_WARNING, "libsldap: could " 1132 "not remove %s from servers list", *host); 1133 } 1134 } 1135 } 1136 1137 /* 1138 * FUNCTION: __s_api_free2dArray 1139 */ 1140 void 1141 __s_api_free2dArray(char ** inarray) 1142 { 1143 1144 char **temptr; 1145 1146 if (inarray == NULL) 1147 return; 1148 1149 for (temptr = inarray; *temptr != NULL; temptr++) { 1150 free(*temptr); 1151 } 1152 free(inarray); 1153 } 1154 1155 /* 1156 * FUNCTION: __s_api_cp2dArray 1157 */ 1158 char ** 1159 __s_api_cp2dArray(char **inarray) 1160 { 1161 char **newarray; 1162 char **ttarray, *ret; 1163 int count; 1164 1165 if (inarray == NULL) 1166 return (NULL); 1167 1168 for (count = 0; inarray[count] != NULL; count++) 1169 ; 1170 1171 newarray = (char **)calloc(count + 1, sizeof (char *)); 1172 if (newarray == NULL) 1173 return (NULL); 1174 1175 ttarray = newarray; 1176 for (; *inarray; inarray++) { 1177 *(ttarray++) = ret = strdup(*inarray); 1178 if (ret == NULL) { 1179 __s_api_free2dArray(newarray); 1180 return (NULL); 1181 } 1182 } 1183 return (newarray); 1184 } 1185 1186 /* 1187 * FUNCTION: __s_api_isCtrlSupported 1188 * Determines if the passed control is supported by the LDAP sever. 1189 * RETURNS: NS_LDAP_SUCCESS if yes, NS_LDAP_OP_FAIL if not. 1190 */ 1191 int 1192 __s_api_isCtrlSupported(Connection *con, char *ctrlString) 1193 { 1194 char **ctrl; 1195 int len; 1196 1197 len = strlen(ctrlString); 1198 for (ctrl = con->controls; ctrl && *ctrl; ctrl++) { 1199 if (strncasecmp(*ctrl, ctrlString, len) == 0) 1200 return (NS_LDAP_SUCCESS); 1201 } 1202 return (NS_LDAP_OP_FAILED); 1203 } 1204 1205 /* 1206 * FUNCTION: __s_api_toFollowReferrals 1207 * Determines if need to follow referral for an SLDAP API. 1208 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_INVALID_PARAM, or 1209 * other rc from __ns_ldap_getParam() 1210 * INPUT: flags 1211 * OUTPUT: toFollow, errorp 1212 */ 1213 int 1214 __s_api_toFollowReferrals(const int flags, 1215 int *toFollow, 1216 ns_ldap_error_t **errorp) 1217 { 1218 void **paramVal = NULL; 1219 int rc = 0; 1220 int iflags = 0; 1221 1222 #ifdef DEBUG 1223 (void) fprintf(stderr, "__s_api_toFollowReferrals START\n"); 1224 #endif 1225 1226 /* Either NS_LDAP_NOREF or NS_LDAP_FOLLOWREF not both */ 1227 if ((flags & (NS_LDAP_NOREF | NS_LDAP_FOLLOWREF)) == 1228 (NS_LDAP_NOREF | NS_LDAP_FOLLOWREF)) { 1229 return (NS_LDAP_INVALID_PARAM); 1230 } 1231 1232 /* 1233 * if the NS_LDAP_NOREF or NS_LDAP_FOLLOWREF is set 1234 * this will take precendence over the values specified 1235 * in the configuration file 1236 */ 1237 if (flags & (NS_LDAP_NOREF | NS_LDAP_FOLLOWREF)) { 1238 iflags = flags; 1239 } else { 1240 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_REF_P, 1241 ¶mVal, errorp); 1242 if (rc != NS_LDAP_SUCCESS) 1243 return (rc); 1244 if (paramVal == NULL || *paramVal == NULL) { 1245 (void) __ns_ldap_freeParam(¶mVal); 1246 if (*errorp) 1247 (void) __ns_ldap_freeError(errorp); 1248 *toFollow = TRUE; 1249 return (NS_LDAP_SUCCESS); 1250 } 1251 iflags = (* (int *)(*paramVal)); 1252 (void) __ns_ldap_freeParam(¶mVal); 1253 } 1254 1255 if (iflags & NS_LDAP_NOREF) 1256 *toFollow = FALSE; 1257 else 1258 *toFollow = TRUE; 1259 1260 return (NS_LDAP_SUCCESS); 1261 } 1262 1263 /* 1264 * FUNCTION: __s_api_addRefInfo 1265 * Insert a referral info into a referral info list. 1266 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_OP_FAILED 1267 * INPUT: LDAP URL, pointer to the referral info list, 1268 * search baseDN, search scope, search filter, 1269 * previous connection 1270 */ 1271 int 1272 __s_api_addRefInfo(ns_referral_info_t **head, char *url, 1273 char *baseDN, int *scope, 1274 char *filter, LDAP *ld) 1275 { 1276 char errmsg[MAXERROR], *tmp; 1277 ns_referral_info_t *ref, *tmpref; 1278 LDAPURLDesc *ludp = NULL; 1279 int hostlen; 1280 char *ld_defhost = NULL; 1281 1282 #ifdef DEBUG 1283 (void) fprintf(stderr, "__s_api_addRefInfo START\n"); 1284 #endif 1285 1286 /* sanity check */ 1287 if (head == NULL) 1288 return (NS_LDAP_OP_FAILED); 1289 1290 /* 1291 * log error and return NS_LDAP_SUCCESS 1292 * if one of the following: 1293 * 1. non-LDAP URL 1294 * 2. LDAP URL which can not be parsed 1295 */ 1296 if (!ldap_is_ldap_url(url) || 1297 ldap_url_parse_nodn(url, &ludp) != 0) { 1298 (void) snprintf(errmsg, MAXERROR, "%s: %s", 1299 gettext("Invalid or non-LDAP URL when" 1300 " processing referrals URL"), 1301 url); 1302 syslog(LOG_ERR, "libsldap: %s", errmsg); 1303 if (ludp) 1304 ldap_free_urldesc(ludp); 1305 return (NS_LDAP_SUCCESS); 1306 } 1307 1308 ref = (ns_referral_info_t *)calloc(1, 1309 sizeof (ns_referral_info_t)); 1310 if (ref == NULL) { 1311 ldap_free_urldesc(ludp); 1312 return (NS_LDAP_MEMORY); 1313 } 1314 1315 /* 1316 * we do have a valid URL and we were able to parse it 1317 * however, we still need to find out what hostport to 1318 * use if none were provided in the LDAP URL 1319 * (e.g., ldap:///...) 1320 */ 1321 if ((ludp->lud_port == 0) && (ludp->lud_host == NULL)) { 1322 if (ld == NULL) { 1323 (void) snprintf(errmsg, MAXERROR, "%s: %s", 1324 gettext("no LDAP handle when" 1325 " processing referrals URL"), 1326 url); 1327 syslog(LOG_WARNING, "libsldap: %s", errmsg); 1328 ldap_free_urldesc(ludp); 1329 free(ref); 1330 return (NS_LDAP_SUCCESS); 1331 } else { 1332 (void) ldap_get_option(ld, LDAP_OPT_HOST_NAME, 1333 &ld_defhost); 1334 if (ld_defhost == NULL) { 1335 (void) snprintf(errmsg, MAXERROR, "%s: %s", 1336 gettext("not able to retrieve default " 1337 "host when processing " 1338 "referrals URL"), 1339 url); 1340 syslog(LOG_WARNING, "libsldap: %s", errmsg); 1341 ldap_free_urldesc(ludp); 1342 free(ref); 1343 return (NS_LDAP_SUCCESS); 1344 } else { 1345 ref->refHost = strdup(ld_defhost); 1346 if (ref->refHost == NULL) { 1347 ldap_free_urldesc(ludp); 1348 free(ref); 1349 return (NS_LDAP_MEMORY); 1350 } 1351 } 1352 } 1353 } else { 1354 /* 1355 * add 4 here: 1356 * 1 for the last '\0'. 1357 * 1 for host and prot separator ":" 1358 * and "[" & "]" for possible ipV6 addressing 1359 */ 1360 hostlen = strlen(ludp->lud_host) + 1361 sizeof (MAXPORTNUMBER_STR) + 4; 1362 ref->refHost = (char *)malloc(hostlen); 1363 if (ref->refHost == NULL) { 1364 ldap_free_urldesc(ludp); 1365 free(ref); 1366 return (NS_LDAP_MEMORY); 1367 } 1368 1369 if (ludp->lud_port != 0) { 1370 /* 1371 * serverAddr = host:port 1372 * or 1373 * if host is an IPV6 address 1374 * [host]:port 1375 */ 1376 tmp = strstr(url, ludp->lud_host); 1377 if (tmp && (tmp > url) && *(tmp - 1) == '[') { 1378 (void) snprintf(ref->refHost, hostlen, 1379 "[%s]:%d", 1380 ludp->lud_host, 1381 ludp->lud_port); 1382 } else { 1383 (void) snprintf(ref->refHost, hostlen, 1384 "%s:%d", 1385 ludp->lud_host, 1386 ludp->lud_port); 1387 } 1388 } else { 1389 /* serverAddr = host */ 1390 (void) snprintf(ref->refHost, hostlen, "%s", 1391 ludp->lud_host); 1392 } 1393 } 1394 1395 if (ludp->lud_dn) { 1396 ref->refDN = strdup(ludp->lud_dn); 1397 if (ref->refDN == NULL) { 1398 ldap_free_urldesc(ludp); 1399 free(ref->refHost); 1400 free(ref); 1401 return (NS_LDAP_MEMORY); 1402 } 1403 } else { 1404 if (baseDN) { 1405 ref->refDN = strdup(baseDN); 1406 if (ref->refDN == NULL) { 1407 ldap_free_urldesc(ludp); 1408 free(ref->refHost); 1409 free(ref); 1410 return (NS_LDAP_MEMORY); 1411 } 1412 } 1413 } 1414 1415 if (filter) 1416 ref->refFilter = strdup(filter); 1417 else if (ludp->lud_filter) 1418 ref->refFilter = strdup(ludp->lud_filter); 1419 else 1420 ref->refFilter = strdup(""); 1421 1422 if (ref->refFilter == NULL) { 1423 ldap_free_urldesc(ludp); 1424 free(ref->refHost); 1425 if (ref->refDN) 1426 free(ref->refDN); 1427 free(ref); 1428 return (NS_LDAP_MEMORY); 1429 } 1430 1431 if (scope) 1432 ref->refScope = *scope; 1433 1434 ref->next = NULL; 1435 1436 ldap_free_urldesc(ludp); 1437 1438 /* insert the referral info */ 1439 if (*head) { 1440 for (tmpref = *head; tmpref->next; tmpref = tmpref->next) 1441 ; 1442 tmpref->next = ref; 1443 } else 1444 *head = ref; 1445 1446 return (NS_LDAP_SUCCESS); 1447 } 1448 1449 /* 1450 * FUNCTION: __s_api_deleteRefInfo 1451 * Delete a referral info list. 1452 * INPUT: pointer to the referral info list 1453 */ 1454 void 1455 __s_api_deleteRefInfo(ns_referral_info_t *head) 1456 { 1457 ns_referral_info_t *ref, *tmp; 1458 1459 #ifdef DEBUG 1460 (void) fprintf(stderr, "__s_api_deleteRefInfo START\n"); 1461 #endif 1462 1463 for (ref = head; ref; ) { 1464 if (ref->refHost) 1465 free(ref->refHost); 1466 if (ref->refDN) 1467 free(ref->refDN); 1468 if (ref->refFilter) 1469 free(ref->refFilter); 1470 tmp = ref->next; 1471 free(ref); 1472 ref = tmp; 1473 } 1474 1475 } 1476 1477 /* 1478 * FUNCTION: __s_api_get_SSD_from_SSDtoUse_service 1479 * 1480 * Retrieves the Service Search Descriptors which should be used for 1481 * the given service. For example, return all the "passwd" SSDs for 1482 * service "shadow" if no SSD is defined for service "shadow" and 1483 * no filter component is defined in all the "passwd" SSDs. This idea 1484 * of sharing the SSDs defined for some other service is to reduce the 1485 * configuration complexity. For a service, which does not have its own 1486 * entries in the LDAP directory, SSD for it is useless, and should not 1487 * be set. But since this service must share the container with at least 1488 * one other service which does have it own entries, the SSD for 1489 * this other service will be shared by this service. 1490 * This other service is called the SSD-to-use service. 1491 * The static data structure, ns_def_map[], in this file 1492 * defines the SSD-to-use service for all the services supported. 1493 * 1494 * RETURN VALUES: NS_LDAP_SUCCESS, NS_LDAP_MEMORY, NS_LDAP_INVALID_PARAM 1495 * INPUT: service 1496 * OUTPUT: *SSDlist, *errorp if error 1497 */ 1498 int 1499 __s_api_get_SSD_from_SSDtoUse_service(const char *service, 1500 ns_ldap_search_desc_t ***SSDlist, 1501 ns_ldap_error_t **errorp) 1502 { 1503 int i, rc; 1504 int found = FALSE; 1505 int filter_found = FALSE; 1506 char *SSD_service = NULL; 1507 char errmsg[MAXERROR]; 1508 ns_ldap_search_desc_t **sdlist; 1509 int auto_service = FALSE; 1510 1511 #ifdef DEBUG 1512 (void) fprintf(stderr, 1513 "__s_api_get_SSD_from_SSDtoUse_service START\n"); 1514 #endif 1515 1516 if (SSDlist == NULL || errorp == NULL) 1517 return (NS_LDAP_INVALID_PARAM); 1518 1519 *SSDlist = NULL; 1520 *errorp = NULL; 1521 1522 if (service == NULL) 1523 return (NS_LDAP_SUCCESS); 1524 1525 if (strncasecmp(service, "auto_", 5) == 0) 1526 auto_service = TRUE; 1527 1528 /* 1529 * First try to return the configured SSDs for the input server 1530 */ 1531 rc = __ns_ldap_getSearchDescriptors(service, SSDlist, errorp); 1532 if (rc != NS_LDAP_SUCCESS) 1533 return (rc); 1534 else { 1535 if (*SSDlist != NULL) 1536 return (NS_LDAP_SUCCESS); 1537 } 1538 1539 /* 1540 * If service == auto_* and SSD is not found, 1541 * then try automount to see if there is an SSD 1542 * for automount. 1543 */ 1544 1545 if (auto_service) { 1546 rc = __ns_ldap_getSearchDescriptors( 1547 "automount", SSDlist, errorp); 1548 if (rc != NS_LDAP_SUCCESS) 1549 return (rc); 1550 else { 1551 if (*SSDlist != NULL) { 1552 /* 1553 * If SSDlist is found, 1554 * prepend automountMapName to the basedn 1555 * in the SSDlist 1556 * 1557 */ 1558 rc = __s_api_prepend_automountmapname( 1559 service, 1560 SSDlist, 1561 errorp); 1562 1563 if (rc != NS_LDAP_SUCCESS) { 1564 (void) __ns_ldap_freeSearchDescriptors( 1565 SSDlist); 1566 *SSDlist = NULL; 1567 } 1568 1569 return (rc); 1570 } 1571 } 1572 } 1573 1574 /* 1575 * Find the SSDtoUse service. 1576 * If none found, flag "found" remains FALSE. 1577 */ 1578 for (i = 0; ns_def_map[i].service != NULL; i++) { 1579 if (ns_def_map[i].SSDtoUse_service && 1580 strcasecmp(service, 1581 ns_def_map[i].service) == 0) { 1582 found = TRUE; 1583 SSD_service = ns_def_map[i].SSDtoUse_service; 1584 break; 1585 } 1586 } 1587 1588 if (!found) 1589 return (NS_LDAP_SUCCESS); 1590 1591 /* 1592 * return the SSDs for SSD_service only if no optional filter 1593 * component is defined in the SSDs 1594 */ 1595 rc = __ns_ldap_getSearchDescriptors(SSD_service, 1596 SSDlist, errorp); 1597 if (rc != NS_LDAP_SUCCESS) { 1598 return (rc); 1599 } else { 1600 if (*SSDlist == NULL) 1601 return (NS_LDAP_SUCCESS); 1602 1603 /* check to see if filter defined in SSD */ 1604 for (sdlist = *SSDlist; *sdlist; sdlist++) { 1605 if ((*sdlist)->filter && 1606 strlen((*sdlist)->filter) > 0) { 1607 filter_found = TRUE; 1608 break; 1609 } 1610 } 1611 if (filter_found) { 1612 (void) __ns_ldap_freeSearchDescriptors(SSDlist); 1613 *SSDlist = NULL; 1614 (void) snprintf(errmsg, sizeof (errmsg), 1615 gettext("Service search descriptor for " 1616 "service '%s' contains filter, " 1617 "which can not be used for " 1618 "service '%s'."), 1619 SSD_service, service); 1620 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_FILE, 1621 strdup(errmsg), NS_LDAP_CONFIG); 1622 return (NS_LDAP_CONFIG); 1623 } 1624 1625 } 1626 return (NS_LDAP_SUCCESS); 1627 } 1628 1629 1630 /* 1631 * verify addr is an IPv4 address with the optional [:portno] 1632 * RFC2373 & RFC2732 & RFC2396 1633 */ 1634 int 1635 __s_api_isipv4(char *addr) 1636 { 1637 int i, seg, digit, port; 1638 1639 if (!addr) 1640 return (0); 1641 1642 digit = seg = port = 0; 1643 1644 for (i = 0; i < strlen(addr); i++) { 1645 if (isdigit(addr[i])) { 1646 digit++; 1647 continue; 1648 } 1649 if (addr[i] == '.') { 1650 if (digit > 3 || digit == 0) 1651 return (0); 1652 digit = 0; 1653 seg++; 1654 continue; 1655 } 1656 if (addr[i] == ':') { 1657 if (digit > 3) 1658 return (0); 1659 port++; 1660 digit = 0; 1661 seg++; 1662 continue; 1663 } 1664 return (0); 1665 } 1666 1667 if ((seg == 3 && port == 0 && digit > 0 && digit < 4) || 1668 (seg == 4 && port == 1 && digit > 0)) 1669 return (1); 1670 1671 return (0); 1672 } 1673 1674 1675 /* 1676 * verify addr is an IPv6 address with the optional [IPv6]:portno 1677 * RFC2373 & RFC2732 & RFC2396 1678 */ 1679 int 1680 __s_api_isipv6(char *addr) 1681 { 1682 int i, col, digit, port, dc, tc; 1683 char *laddr, *c1, *s; 1684 1685 if (!addr) 1686 return (0); 1687 1688 s = addr; 1689 laddr = NULL; 1690 digit = col = port = 0; 1691 if (addr[0] == '[') { 1692 laddr = strdup(addr); 1693 if (!laddr) 1694 return (0); 1695 c1 = strchr(laddr, ']'); 1696 /* only 1 ']' should be in an addr */ 1697 if (!c1 || (strchr(c1+1, ']'))) 1698 goto bad; 1699 switch (c1[1]) { 1700 case ':': 1701 port++; 1702 for (i = 2; i < strlen(c1); i++) { 1703 if (!isdigit(c1[i])) 1704 goto bad; 1705 digit++; 1706 } 1707 if (!digit) 1708 goto bad; 1709 c1[0] = '\0'; 1710 break; 1711 case '\0': 1712 c1[0] = '\0'; 1713 break; 1714 default: 1715 goto bad; 1716 } 1717 s = &laddr[1]; 1718 } 1719 1720 digit = dc = tc = 0; 1721 for (i = 0; i < strlen(s); i++) { 1722 if (isxdigit(s[i])) { 1723 if (digit == 0) 1724 dc = i; 1725 digit++; 1726 col = 0; 1727 continue; 1728 } 1729 if (s[i] == ':') { 1730 tc++; 1731 if ((col > 1) || (i && !col && !digit)) 1732 goto bad; 1733 digit = 0; 1734 col++; 1735 continue; 1736 } 1737 if (s[i] == '.') { 1738 if (__s_api_isipv4(&s[dc]) && tc) 1739 goto good; 1740 else 1741 goto bad; 1742 } 1743 goto bad; 1744 } 1745 1746 good: 1747 free(laddr); 1748 return (1); 1749 bad: 1750 free(laddr); 1751 return (0); 1752 } 1753 1754 1755 /* 1756 * verify addr is a valid hostname with the optional [:portno] 1757 * RFC2373 & RFC2732 & RFC2396 1758 */ 1759 int 1760 __s_api_ishost(char *addr) 1761 { 1762 int i, seg, alpha, digit, port; 1763 1764 if (!addr) 1765 return (0); 1766 1767 alpha = digit = seg = port = 0; 1768 1769 /* must start with alpha character */ 1770 if (!isalpha(addr[0])) 1771 return (0); 1772 1773 for (i = 0; i < strlen(addr); i++) { 1774 if (isalpha(addr[i]) || (i && addr[i] == '-')) { 1775 alpha++; 1776 continue; 1777 } 1778 if (isdigit(addr[i])) { 1779 digit++; 1780 continue; 1781 } 1782 if (addr[i] == '.') { 1783 if (!alpha && !digit) 1784 return (0); 1785 alpha = digit = 0; 1786 seg++; 1787 continue; 1788 } 1789 if (addr[i] == ':') { 1790 if (!alpha && !digit) 1791 return (0); 1792 alpha = digit = 0; 1793 port++; 1794 seg++; 1795 continue; 1796 } 1797 return (0); 1798 } 1799 1800 if ((port == 0 && (seg || alpha || digit)) || 1801 (port == 1 && alpha == 0 && digit)) 1802 return (1); 1803 1804 return (0); 1805 } 1806 1807 1808 /* 1809 * Prepend automountMapName=auto_xxx to the basedn 1810 * in the SSDlist 1811 */ 1812 1813 int __s_api_prepend_automountmapname( 1814 const char *service, 1815 ns_ldap_search_desc_t ***SSDlist, 1816 ns_ldap_error_t **errorp) 1817 { 1818 int i, rc; 1819 ns_ldap_search_desc_t ** ssdlist = NULL; 1820 1821 if (service == NULL || SSDlist == NULL || *SSDlist == NULL) 1822 return (NS_LDAP_INVALID_PARAM); 1823 1824 ssdlist = *SSDlist; 1825 1826 for (i = 0; ssdlist[i] != NULL; i++) { 1827 rc = __s_api_prepend_automountmapname_to_dn( 1828 service, &ssdlist[i]->basedn, errorp); 1829 1830 if (rc != NS_LDAP_SUCCESS) 1831 return (rc); 1832 } 1833 1834 return (NS_LDAP_SUCCESS); 1835 } 1836 1837 1838 /* 1839 * Prepend automountMapName=auto_xxx to the DN 1840 * Construct a string of 1841 * "automountMapName=auto_xxx,dn" 1842 * 1843 * If automountMapName is mapped to some other attribute, 1844 * then use the mapping in the setup. 1845 * 1846 * If a version 1 profile is in use, use nisMapName for 1847 * backward compatibility (i.e. "nisMapName=auto_xxx,dn"). 1848 */ 1849 1850 int 1851 __s_api_prepend_automountmapname_to_dn( 1852 const char *service, 1853 char **dn, 1854 ns_ldap_error_t **errorp) 1855 { 1856 int rc, len_s = 0, len_d = 0, len = 0; 1857 char *buffer = NULL; 1858 char *default_automountmapname = "automountMapName"; 1859 char *automountmapname = NULL; 1860 char **mappedattrs = NULL; 1861 char errstr[MAXERROR]; 1862 void **paramVal = NULL; 1863 1864 if (service == NULL || dn == NULL || *dn == NULL) 1865 return (NS_LDAP_INVALID_PARAM); 1866 1867 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, errorp); 1868 if (rc != NS_LDAP_SUCCESS || !paramVal || !*paramVal) { 1869 if (paramVal) 1870 (void) __ns_ldap_freeParam(¶mVal); 1871 return (rc); 1872 } 1873 if (strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0) { 1874 automountmapname = strdup("nisMapName"); 1875 (void) __ns_ldap_freeParam(¶mVal); 1876 if (automountmapname == NULL) { 1877 return (NS_LDAP_MEMORY); 1878 } 1879 } else { 1880 (void) __ns_ldap_freeParam(¶mVal); 1881 1882 /* Find mapped attribute name of auto_xxx first */ 1883 mappedattrs = __ns_ldap_getMappedAttributes( 1884 service, default_automountmapname); 1885 /* 1886 * if mapped attribute name of auto_xxx is not found, 1887 * find the mapped attribute name of automount 1888 */ 1889 1890 if (mappedattrs == NULL) 1891 mappedattrs = __ns_ldap_getMappedAttributes( 1892 "automount", default_automountmapname); 1893 1894 /* 1895 * if mapped attr is not found, use the default automountmapname 1896 */ 1897 1898 if (mappedattrs == NULL) { 1899 automountmapname = strdup(default_automountmapname); 1900 if (automountmapname == NULL) 1901 return (NS_LDAP_MEMORY); 1902 } else { 1903 if (mappedattrs[0] != NULL) { 1904 /* 1905 * Copy it from the mapped attr list 1906 * Assume it's 1 to 1 mapping 1907 * 1 to n does not make sense 1908 */ 1909 automountmapname = strdup(mappedattrs[0]); 1910 __s_api_free2dArray(mappedattrs); 1911 if (automountmapname == NULL) { 1912 return (NS_LDAP_MEMORY); 1913 } 1914 } else { 1915 1916 /* 1917 * automountmapname is mapped to an empty string 1918 */ 1919 1920 __s_api_free2dArray(mappedattrs); 1921 1922 (void) sprintf(errstr, 1923 gettext( 1924 "Attribute automountMapName is " 1925 "mapped to an empty string.\n")); 1926 1927 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX, 1928 strdup(errstr), NULL); 1929 1930 return (NS_LDAP_CONFIG); 1931 } 1932 } 1933 } 1934 1935 len_s = strlen(service); 1936 len_d = strlen(*dn); 1937 /* automountMapName + "=" + service + "," + dn + '\0' */ 1938 len = strlen(automountmapname) + 1 + len_s + 1 + len_d + 1; 1939 buffer = (char *)malloc(len); 1940 if (buffer == NULL) { 1941 free(automountmapname); 1942 return (NS_LDAP_MEMORY); 1943 } 1944 1945 (void) snprintf(buffer, len, "%s=%s,%s", 1946 automountmapname, service, *dn); 1947 1948 buffer[len-1] = '\0'; 1949 1950 free(automountmapname); 1951 1952 /* free the original dn */ 1953 (void) free(*dn); 1954 1955 *dn = buffer; 1956 1957 return (NS_LDAP_SUCCESS); 1958 } 1959 1960 /* 1961 * Map the LDAP error code and error message from LDAP server 1962 * to a password status used for password aging/management. 1963 */ 1964 ns_ldap_passwd_status_t 1965 __s_api_set_passwd_status(int errnum, char *errmsg) 1966 { 1967 if (errmsg) { 1968 if (errnum == 1969 LDAP_INVALID_CREDENTIALS) { 1970 /* 1971 * case 1 (Bind): 1972 * password expired 1973 */ 1974 if (strstr(errmsg, 1975 NS_PWDERR_EXPIRED)) 1976 return (NS_PASSWD_EXPIRED); 1977 } 1978 1979 if (errnum == 1980 LDAP_UNWILLING_TO_PERFORM) { 1981 /* 1982 * case 1.1 (Bind): 1983 * password expired 1984 */ 1985 if (strstr(errmsg, 1986 NS_PWDERR_EXPIRED)) 1987 return (NS_PASSWD_EXPIRED); 1988 1989 /* 1990 * case 2 (Bind): 1991 * Account inactivated 1992 */ 1993 if (strstr(errmsg, 1994 NS_PWDERR_ACCT_INACTIVATED)) 1995 return (NS_PASSWD_EXPIRED); 1996 1997 1998 /* 1999 * case 3 (Modify passwd): 2000 * the user is not allow to change 2001 * password; only admin can change it 2002 */ 2003 if (strstr(errmsg, 2004 NS_PWDERR_CHANGE_NOT_ALLOW)) 2005 return (NS_PASSWD_CHANGE_NOT_ALLOWED); 2006 } 2007 2008 if (errnum == 2009 LDAP_CONSTRAINT_VIOLATION) { 2010 /* 2011 * case 4 (Bind): 2012 * the user account is locked due to 2013 * too many login failures. 2014 */ 2015 if (strstr(errmsg, 2016 NS_PWDERR_MAXTRIES)) 2017 return (NS_PASSWD_RETRY_EXCEEDED); 2018 /* 2019 * case 5 (Modify passwd): 2020 * syntax error: the new password 2021 * has length less than defined 2022 * minimum 2023 */ 2024 if (strstr(errmsg, 2025 NS_PWDERR_INVALID_SYNTAX)) 2026 return (NS_PASSWD_TOO_SHORT); 2027 /* 2028 * case 6 (Modify passwd): 2029 * trivial password: same valule as 2030 * that of attribute cn, sn, or uid ... 2031 */ 2032 if (strstr(errmsg, 2033 NS_PWDERR_TRIVIAL_PASSWD)) 2034 return (NS_PASSWD_INVALID_SYNTAX); 2035 /* 2036 * case 7 (Modify passwd): 2037 * re-use one of the old passwords 2038 * in history list 2039 */ 2040 if (strstr(errmsg, 2041 NS_PWDERR_IN_HISTORY)) 2042 return (NS_PASSWD_IN_HISTORY); 2043 /* 2044 * case 8 (Modify passwd): 2045 * password not allowed to be 2046 * changed yet; within minimum 2047 * age 2048 */ 2049 if (strstr(errmsg, 2050 NS_PWDERR_WITHIN_MIN_AGE)) 2051 return (NS_PASSWD_WITHIN_MIN_AGE); 2052 } 2053 2054 } 2055 2056 return (NS_PASSWD_GOOD); 2057 } 2058 2059 /* 2060 * Determine if the input OID list contains 2061 * one of the password control OIDs, which are: 2062 * LDAP_CONTROL_PWEXPIRED: 2.16.840.1.113730.3.4.4 2063 * LDAP_CONTROL_PWEXPIRING: 2.16.840.1.113730.3.4.5. 2064 * If yes, return 1, if no, 0. 2065 */ 2066 int 2067 __s_api_contain_passwd_control_oid(char **oids) 2068 { 2069 char **oid; 2070 2071 if (oids == NULL) 2072 return (0); 2073 2074 for (oid = oids; *oid; oid++) { 2075 if (strcmp(*oid, LDAP_CONTROL_PWEXPIRED) == 0 || 2076 strcmp(*oid, LDAP_CONTROL_PWEXPIRING) == 0) { 2077 return (1); 2078 } 2079 } 2080 2081 return (0); 2082 } 2083 2084 /* 2085 * Determine if the input OID list contains LDAP V3 password less 2086 * account management control OID, which is: 2087 * NS_LDAP_ACCOUNT_USABLE_CONTROL:1.3.6.1.4.1.42.2.27.9.5.8 2088 * If yes, return 1, if no, 0. 2089 */ 2090 int 2091 __s_api_contain_account_usable_control_oid(char **oids) 2092 { 2093 char **oid; 2094 2095 if (oids == NULL) 2096 return (0); 2097 2098 for (oid = oids; *oid; oid++) { 2099 if (strcmp(*oid, NS_LDAP_ACCOUNT_USABLE_CONTROL) == 0) { 2100 return (1); 2101 } 2102 } 2103 2104 return (0); 2105 } 2106 2107 /* 2108 * For some databases in name switch, the name and aliases are saved 2109 * as "cn". When the "cn" valuse are retrieved, there is no distinction 2110 * which is the name and which is(are) aliase(s). 2111 * This function is to parse RDN and find the value of the "cn" and 2112 * then find the matching value in "cn" attribute. 2113 * Also see RFC 2307 section 5.6. 2114 * 2115 * Input - 2116 * entry: An LDAP entry 2117 * attrptr: A attribute which value appears in RDN 2118 * This should be "cn" for the name switch for now. 2119 * case_ignore: 0 Case sensitive comparison on the attribute value 2120 * 1 Case insensitive comparison 2121 * 2122 * Return - 2123 * The value of an attrbute which is used as canonical name 2124 * This is read only and the caller should not try to free it. 2125 * If it's a NULL, it could be either an RDN parsing error 2126 * or RDN value does not match any existing "cn" values. 2127 * e.g. 2128 * dn: cn=xx+ipserviceprotocol=udp,...... 2129 * cn: aa 2130 * cn: bb 2131 * 2132 * Note: 2133 * Although the name switch/ldap's rdn is in "cn=xx" or "cn=xx+..." 2134 * format, this function makes no such assumption. If the DN 2135 * is saved as "dn: yy=...+sn=my_canocical_name, ..", then it can still work. 2136 * The comments use "cn" as an example only. 2137 * 2138 */ 2139 typedef int (*cmpfunc)(const char *, const char *); 2140 2141 char * 2142 __s_api_get_canonical_name(ns_ldap_entry_t *entry, ns_ldap_attr_t *attrptr, 2143 int case_ignore) { 2144 uint_t i; 2145 char *token, *lasts, *value = NULL; 2146 char **rdn = NULL, **attrs = NULL, **values = NULL; 2147 char *rdn_attr_value = NULL; 2148 cmpfunc cmp; 2149 2150 if (entry == NULL || attrptr == NULL) 2151 return (NULL); 2152 2153 /* "values" is read-only */ 2154 if ((values = __ns_ldap_getAttr(entry, "dn")) == NULL || 2155 values[0] == NULL) 2156 return (NULL); 2157 2158 if ((rdn = ldap_explode_dn(values[0], 0)) == NULL || 2159 rdn[0] == NULL) 2160 return (NULL); 2161 2162 if ((attrs = ldap_explode_rdn(rdn[0], 0)) == NULL) { 2163 ldap_value_free(rdn); 2164 return (NULL); 2165 } 2166 /* Assume the rdn is normalized */ 2167 for (i = 0; attrs[i] != NULL; i++) { 2168 /* parse attribute name and value, get attribute name first */ 2169 if ((token = strtok_r(attrs[i], "=", &lasts)) == NULL) { 2170 goto cleanup; 2171 } 2172 if (strcasecmp(token, attrptr->attrname) == 0) { 2173 /* get value */ 2174 rdn_attr_value = lasts; 2175 break; 2176 } 2177 } 2178 if (rdn_attr_value) { 2179 if (case_ignore) 2180 cmp = strcasecmp; 2181 else 2182 cmp = strcmp; 2183 /* 2184 * After parsing RDN and find the matching attribute in RDN, 2185 * match rdn value with values in "cn". 2186 */ 2187 for (i = 0; i < attrptr->value_count; i++) { 2188 if (attrptr->attrvalue[i] && 2189 (*cmp)(rdn_attr_value, 2190 attrptr->attrvalue[i]) == 0) { 2191 /* RDN "cn" value matches the "cn" value */ 2192 value = attrptr->attrvalue[i]; 2193 break; 2194 } 2195 } 2196 } 2197 cleanup: 2198 ldap_value_free(rdn); 2199 ldap_value_free(attrs); 2200 2201 return (value); 2202 } 2203 2204 /* 2205 * This function requests a server to be removed from 2206 * the cache manager maintained server list. This is 2207 * done via the door functionality. 2208 * Returns 0 if OK, else a negative value. 2209 */ 2210 2211 int 2212 __s_api_removeServer(const char *server) 2213 { 2214 union { 2215 ldap_data_t s_d; 2216 char s_b[DOORBUFFERSIZE]; 2217 } space; 2218 2219 ns_server_info_t r, *ret = &r; 2220 const char *ireq; 2221 ldap_data_t *sptr; 2222 int ndata; 2223 int adata; 2224 int len; 2225 int rc; 2226 2227 if (server == NULL) 2228 return (-1); 2229 2230 ireq = NS_CACHE_NORESP; 2231 2232 (void) memset(ret, 0, sizeof (ns_server_info_t)); 2233 (void) memset(space.s_b, 0, DOORBUFFERSIZE); 2234 2235 adata = (sizeof (ldap_call_t) + strlen(ireq) + 2236 strlen(NS_CACHE_ADDR_IP) + 1); 2237 adata += strlen(DOORLINESEP) + 1; 2238 adata += strlen(server) + 1; 2239 2240 ndata = sizeof (space); 2241 space.s_d.ldap_call.ldap_callnumber = GETLDAPSERVER; 2242 len = sizeof (space) - sizeof (space.s_d.ldap_call.ldap_callnumber); 2243 if (strlcpy(space.s_d.ldap_call.ldap_u.domainname, ireq, len) >= len) 2244 return (-1); 2245 if (strlcat(space.s_d.ldap_call.ldap_u.domainname, 2246 NS_CACHE_ADDR_IP, len) >= len) 2247 return (-1); 2248 if (strlcat(space.s_d.ldap_call.ldap_u.domainname, DOORLINESEP, len) >= 2249 len) 2250 return (-1); 2251 if (strlcat(space.s_d.ldap_call.ldap_u.domainname, server, len) >= len) 2252 return (-1); 2253 sptr = &space.s_d; 2254 2255 /* try to remove the server via the door interface */ 2256 rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata); 2257 2258 /* clean up the door call */ 2259 if (sptr != &space.s_d) { 2260 (void) munmap((char *)sptr, ndata); 2261 } 2262 2263 return (rc); 2264 } 2265 2266 void 2267 __s_api_free_server_info(ns_server_info_t *sinfo) { 2268 if (sinfo->server) { 2269 free(sinfo->server); 2270 sinfo->server = NULL; 2271 } 2272 if (sinfo->serverFQDN) { 2273 free(sinfo->serverFQDN); 2274 sinfo->serverFQDN = NULL; 2275 } 2276 __s_api_free2dArray(sinfo->saslMechanisms); 2277 sinfo->saslMechanisms = NULL; 2278 __s_api_free2dArray(sinfo->controls); 2279 sinfo->controls = NULL; 2280 } 2281