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