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