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