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