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