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