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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <syslog.h> 29 #include "ldap_common.h" 30 31 /* netgroup attributes filters */ 32 #define _N_TRIPLE "nisnetgrouptriple" 33 #define _N_MEMBER "membernisnetgroup" 34 35 #define PRINT_VAL(a) (((a).argc == 0) || ((a).argv == NULL) || \ 36 ((a).argv[0] == NULL)) ? "*" : (a).argv[0] 37 #define ISNULL(a) (a == NULL ? "<NULL>" : a) 38 #define MAX_DOMAIN_LEN 1024 39 #define MAX_TRIPLE_LEN (MAXHOSTNAMELEN + LOGNAME_MAX + \ 40 MAX_DOMAIN_LEN + 5) 41 42 #define _F_SETMEMBER "(&(objectClass=nisNetGroup)(cn=%s))" 43 #define _F_SETMEMBER_SSD "(&(%%s)(cn=%s))" 44 45 #define N_HASH 257 46 #define COMMA ',' 47 48 static const char *netgrent_attrs[] = { 49 _N_TRIPLE, 50 _N_MEMBER, 51 (char *)NULL 52 }; 53 54 typedef struct netgroup_name { 55 char *name; 56 struct netgroup_name *next; 57 struct netgroup_name *next_hash; 58 } netgroup_name_t; 59 60 typedef struct { 61 netgroup_name_t *hash_list[N_HASH]; 62 netgroup_name_t *to_do; 63 netgroup_name_t *done; 64 } netgroup_table_t; 65 66 typedef struct { 67 ns_ldap_result_t *results; 68 ns_ldap_entry_t *entry; 69 char **attrs; 70 void *cookie; 71 char *netgroup; 72 netgroup_table_t tab; 73 } getnetgrent_cookie_t; 74 75 typedef struct { 76 struct nss_innetgr_args *ia; 77 const char *ssd_filter; 78 const char *netgrname; 79 const char *membername; 80 netgroup_table_t tab; 81 } innetgr_cookie_t; 82 83 typedef unsigned int hash_t; 84 85 static hash_t 86 get_hash(const char *s) 87 { 88 unsigned int sum = 0; 89 unsigned int i; 90 91 for (i = 0; s[i] != '\0'; i++) 92 sum += ((unsigned char *)s)[i]; 93 94 return ((sum + i) % N_HASH); 95 } 96 97 /* 98 * Adds a name to the netgroup table 99 * 100 * Returns 101 * 0 if successfully added or already present 102 * -1 if memory allocation error 103 */ 104 105 static int 106 add_netgroup_name(const char *name, netgroup_table_t *tab) 107 { 108 hash_t h; 109 netgroup_name_t *ng; 110 netgroup_name_t *ng_new; 111 112 if (tab == NULL || name == NULL || *name == '\0') 113 return (NULL); 114 115 h = get_hash(name); 116 ng = tab->hash_list[h]; 117 118 while (ng != NULL) { 119 if (strcmp(name, ng->name) == 0) 120 break; 121 ng = ng->next_hash; 122 } 123 124 if (ng == NULL) { 125 ng_new = (netgroup_name_t *) 126 calloc(1, sizeof (netgroup_name_t)); 127 if (ng_new == NULL) 128 return (-1); 129 ng_new->name = strdup(name); 130 if (ng_new->name == NULL) { 131 free(ng_new); 132 return (-1); 133 } 134 ng_new->next_hash = tab->hash_list[h]; 135 tab->hash_list[h] = ng_new; 136 ng_new->next = tab->to_do; 137 tab->to_do = ng_new; 138 } 139 return (0); 140 } 141 142 static netgroup_name_t * 143 get_next_netgroup(netgroup_table_t *tab) 144 { 145 netgroup_name_t *ng; 146 147 if (tab == NULL) 148 return (NULL); 149 150 ng = tab->to_do; 151 if (ng != NULL) { 152 tab->to_do = ng->next; 153 ng->next = tab->done; 154 tab->done = ng; 155 } 156 return (ng); 157 } 158 159 static void 160 free_netgroup_table(netgroup_table_t *tab) 161 { 162 netgroup_name_t *ng, *next; 163 164 if (tab == NULL) 165 return; 166 167 for (ng = tab->to_do; ng != NULL; ng = next) { 168 if (ng->name != NULL) 169 free(ng->name); 170 next = ng->next; 171 free(ng); 172 } 173 174 for (ng = tab->done; ng != NULL; ng = next) { 175 if (ng->name != NULL) 176 free(ng->name); 177 next = ng->next; 178 free(ng); 179 } 180 (void) memset(tab, 0, sizeof (*tab)); 181 } 182 183 /* 184 * domain comparing routine 185 * n1: See if n1 is n2 or an ancestor of it 186 * n2: (in string terms, n1 is a suffix of n2) 187 * Returns ZERO for success, -1 for failure. 188 */ 189 static int 190 domcmp(const char *n1, const char *n2) 191 { 192 #define PASS 0 193 #define FAIL -1 194 195 size_t l1, l2; 196 197 if ((n1 == NULL) || (n2 == NULL)) 198 return (FAIL); 199 200 l1 = strlen(n1); 201 l2 = strlen(n2); 202 203 /* Turn a blind eye to the presence or absence of trailing periods */ 204 if (l1 != 0 && n1[l1 - 1] == '.') { 205 --l1; 206 } 207 if (l2 != 0 && n2[l2 - 1] == '.') { 208 --l2; 209 } 210 if (l1 > l2) { /* Can't be a suffix */ 211 return (FAIL); 212 } else if (l1 == 0) { /* Trivially a suffix; */ 213 /* (do we want this case?) */ 214 return (PASS); 215 } 216 /* So 0 < l1 <= l2 */ 217 if (l1 < l2 && n2[l2 - l1 - 1] != '.') { 218 return (FAIL); 219 } 220 if (strncasecmp(n1, &n2[l2 - l1], l1) == 0) { 221 return (PASS); 222 } else { 223 return (FAIL); 224 } 225 } 226 227 static int 228 split_triple(char *triple, char **hostname, char **username, char **domain) 229 { 230 int i, syntax_err; 231 char *splittriple[3]; 232 char *p = triple; 233 234 #ifdef DEBUG 235 (void) fprintf(stdout, "\n[getnetgrent.c: split_triple]\n"); 236 #endif /* DEBUG */ 237 238 if (triple == NULL) 239 return (-1); 240 241 p++; 242 syntax_err = 0; 243 for (i = 0; i < 3; i++) { 244 char *start; 245 char *limit; 246 const char *terminators = ",) \t"; 247 248 if (i == 2) { 249 /* Don't allow comma */ 250 terminators++; 251 } 252 while (isspace(*p)) { 253 p++; 254 } 255 start = p; 256 limit = strpbrk(start, terminators); 257 if (limit == 0) { 258 syntax_err++; 259 break; 260 } 261 p = limit; 262 while (isspace(*p)) { 263 p++; 264 } 265 if (*p == terminators[0]) { 266 /* 267 * Successfully parsed this name and 268 * the separator after it (comma or 269 * right paren); leave p ready for 270 * next parse. 271 */ 272 p++; 273 if (start == limit) { 274 /* Wildcard */ 275 splittriple[i] = NULL; 276 } else { 277 *limit = '\0'; 278 splittriple[i] = start; 279 } 280 } else { 281 syntax_err++; 282 break; 283 } 284 } 285 286 if (syntax_err != 0) 287 return (-1); 288 289 *hostname = splittriple[0]; 290 *username = splittriple[1]; 291 *domain = splittriple[2]; 292 293 return (0); 294 } 295 296 /* 297 * Test membership in triple 298 * return 0 = no match 299 * return 1 = match 300 */ 301 302 static int 303 match_triple_entry(struct nss_innetgr_args *ia, const ns_ldap_entry_t *entry) 304 { 305 int ndomains; 306 char **pdomains; 307 int nhost; 308 char **phost; 309 int nusers; 310 char **pusers; 311 char **attr; 312 char triple[MAX_TRIPLE_LEN]; 313 char *tuser, *thost, *tdomain; 314 int i; 315 char *current, *limit; 316 int pulen, phlen; 317 char *pusers0, *phost0; 318 319 nhost = ia->arg[NSS_NETGR_MACHINE].argc; 320 phost = (char **)ia->arg[NSS_NETGR_MACHINE].argv; 321 if (phost == NULL || *phost == NULL) { 322 nhost = 0; 323 } else { 324 phost0 = phost[0]; 325 phlen = strlen(phost0); 326 } 327 nusers = ia->arg[NSS_NETGR_USER].argc; 328 pusers = (char **)ia->arg[NSS_NETGR_USER].argv; 329 if (pusers == NULL || *pusers == NULL) { 330 nusers = 0; 331 } else { 332 pusers0 = pusers[0]; 333 pulen = strlen(pusers0); 334 } 335 ndomains = ia->arg[NSS_NETGR_DOMAIN].argc; 336 pdomains = (char **)ia->arg[NSS_NETGR_DOMAIN].argv; 337 if (pdomains == NULL || *pdomains == NULL) 338 ndomains = 0; 339 340 attr = __ns_ldap_getAttr(entry, _N_TRIPLE); 341 if (attr == NULL || *attr == NULL) 342 return (0); 343 344 /* Special cases for speedup */ 345 if (nusers == 1 && nhost == 0 && ndomains == 0) { 346 /* Special case for finding a single user in a netgroup */ 347 for (; *attr; attr++) { 348 /* jump to first comma and check next character */ 349 current = *attr; 350 if ((current = strchr(current, COMMA)) == NULL) 351 continue; 352 current++; 353 354 /* skip whitespaces */ 355 while (isspace(*current)) 356 current++; 357 358 /* if user part is null, then treat as wildcard */ 359 if (*current == COMMA) 360 return (1); 361 362 /* compare first character */ 363 if (*pusers0 != *current) 364 continue; 365 366 /* limit username to COMMA */ 367 if ((limit = strchr(current, COMMA)) == NULL) 368 continue; 369 *limit = '\0'; 370 371 /* remove blanks before COMMA */ 372 if ((limit = strpbrk(current, " \t")) != NULL) 373 *limit = '\0'; 374 375 /* compare size of username */ 376 if (pulen != strlen(current)) { 377 continue; 378 } 379 380 /* do actual compare */ 381 if (strncmp(pusers0, current, pulen) == 0) { 382 return (1); 383 } else { 384 continue; 385 } 386 } 387 } else if (nusers == 0 && nhost == 1 && ndomains == 0) { 388 /* Special case for finding a single host in a netgroup */ 389 for (; *attr; attr++) { 390 391 /* jump to first character and check */ 392 current = *attr; 393 current++; 394 395 /* skip whitespaces */ 396 while (isspace(*current)) 397 current++; 398 399 /* if host part is null, then treat as wildcard */ 400 if (*current == COMMA) 401 return (1); 402 403 /* limit hostname to COMMA */ 404 if ((limit = strchr(current, COMMA)) == NULL) 405 continue; 406 *limit = '\0'; 407 408 /* remove blanks before COMMA */ 409 if ((limit = strpbrk(current, " \t")) != NULL) 410 *limit = '\0'; 411 412 /* compare size of hostname */ 413 if (phlen != strlen(current)) { 414 continue; 415 } 416 417 /* do actual compare */ 418 if (strncasecmp(phost0, current, phlen) == 0) { 419 return (1); 420 } else { 421 continue; 422 } 423 } 424 } else { 425 for (; *attr; attr++) { 426 if (strlcpy(triple, *attr, 427 sizeof (triple)) >= sizeof (triple)) 428 continue; 429 if (split_triple(triple, &thost, &tuser, &tdomain) != 0) 430 continue; 431 if (thost != NULL && *thost != '\0' && nhost != 0) { 432 for (i = 0; i < nhost; i++) 433 if (strcasecmp(thost, phost[i]) == 0) 434 break; 435 if (i == nhost) 436 continue; 437 } 438 if (tuser != NULL && *tuser != '\0' && nusers != 0) { 439 for (i = 0; i < nusers; i++) 440 if (strcmp(tuser, pusers[i]) == 0) 441 break; 442 if (i == nusers) 443 continue; 444 } 445 if (tdomain != NULL && *tdomain != '\0' && 446 ndomains != 0) { 447 for (i = 0; i < ndomains; i++) 448 if (domcmp(tdomain, pdomains[i]) == 0) 449 break; 450 if (i == ndomains) 451 continue; 452 } 453 return (1); 454 } 455 } 456 457 return (0); 458 } 459 460 static int 461 match_triple(struct nss_innetgr_args *ia, ns_ldap_result_t *result) 462 { 463 ns_ldap_entry_t *entry; 464 465 for (entry = result->entry; entry != NULL; entry = entry->next) 466 if (match_triple_entry(ia, entry) == 1) 467 return (1); 468 469 return (0); 470 } 471 472 static int 473 add_netgroup_member_entry(ns_ldap_entry_t *entry, netgroup_table_t *tab) 474 { 475 char **attrs; 476 char **a; 477 478 attrs = __ns_ldap_getAttr(entry, _N_MEMBER); 479 if (attrs == NULL || *attrs == NULL) 480 return (0); 481 482 for (a = attrs; *a != NULL; a++) {} 483 484 do { 485 a--; 486 if (add_netgroup_name(*a, tab) != 0) 487 return (-1); 488 } while (a > attrs); 489 return (0); 490 } 491 492 static int 493 add_netgroup_member(ns_ldap_result_t *result, netgroup_table_t *tab) 494 { 495 ns_ldap_entry_t *entry; 496 int ret = 0; 497 498 for (entry = result->entry; entry != NULL; entry = entry->next) { 499 ret = add_netgroup_member_entry(entry, tab); 500 if (ret != 0) 501 break; 502 } 503 return (ret); 504 } 505 506 /* 507 * top_down_search checks only checks the netgroup specified in netgrname 508 */ 509 static nss_status_t 510 top_down_search(struct nss_innetgr_args *ia, char *netgrname) 511 { 512 char searchfilter[SEARCHFILTERLEN]; 513 char name[SEARCHFILTERLEN]; 514 char userdata[SEARCHFILTERLEN]; 515 ns_ldap_result_t *result = NULL; 516 ns_ldap_error_t *error = NULL; 517 int rc; 518 void *cookie = NULL; 519 nss_status_t status = NSS_NOTFOUND; 520 nss_status_t status1; 521 netgroup_table_t tab; 522 netgroup_name_t *ng; 523 int ret; 524 525 (void) memset(&tab, 0, sizeof (tab)); 526 527 if (add_netgroup_name(netgrname, &tab) != 0) 528 return ((nss_status_t)NSS_NOTFOUND); 529 530 while ((ng = get_next_netgroup(&tab)) != NULL) { 531 if (_ldap_filter_name(name, ng->name, sizeof (name)) != 0) 532 break; 533 ret = snprintf(searchfilter, sizeof (searchfilter), 534 _F_SETMEMBER, name); 535 if (ret >= sizeof (searchfilter) || ret < 0) 536 break; 537 538 ret = snprintf(userdata, sizeof (userdata), _F_SETMEMBER_SSD, 539 name); 540 if (ret >= sizeof (userdata) || ret < 0) 541 break; 542 543 rc = __ns_ldap_firstEntry(_NETGROUP, searchfilter, 544 _merge_SSD_filter, netgrent_attrs, NULL, 0, &cookie, 545 &result, &error, userdata); 546 547 if (error != NULL) { 548 status1 = switch_err(rc, error); 549 if (status1 == NSS_TRYAGAIN) { 550 (void) __ns_ldap_freeError(&error); 551 free_netgroup_table(&tab); 552 return (status1); 553 } 554 } 555 556 (void) __ns_ldap_freeError(&error); 557 while (rc == NS_LDAP_SUCCESS && result != NULL) { 558 if (match_triple(ia, result) == 1) { 559 /* We found a match */ 560 ia->status = NSS_NETGR_FOUND; 561 status = NSS_SUCCESS; 562 break; 563 } 564 565 rc = add_netgroup_member(result, &tab); 566 (void) __ns_ldap_freeResult(&result); 567 568 if (rc != NS_LDAP_SUCCESS) 569 break; 570 rc = __ns_ldap_nextEntry(cookie, &result, &error); 571 if (error != NULL) { 572 status1 = switch_err(rc, error); 573 if (status1 == NSS_TRYAGAIN) { 574 free_netgroup_table(&tab); 575 (void) __ns_ldap_freeError(&error); 576 (void) __ns_ldap_endEntry(&cookie, 577 &error); 578 (void) __ns_ldap_freeError(&error); 579 return (status1); 580 } 581 } 582 (void) __ns_ldap_freeError(&error); 583 } 584 (void) __ns_ldap_freeResult(&result); 585 (void) __ns_ldap_endEntry(&cookie, &error); 586 (void) __ns_ldap_freeError(&error); 587 588 if (status == NSS_SUCCESS || 589 (rc != NS_LDAP_SUCCESS && rc != NS_LDAP_NOTFOUND)) 590 break; 591 } 592 593 (void) __ns_ldap_freeResult(&result); 594 (void) __ns_ldap_endEntry(&cookie, &error); 595 (void) __ns_ldap_freeError(&error); 596 free_netgroup_table(&tab); 597 return (status); 598 } 599 600 /* 601 * __netgr_in checks only checks the netgroup specified in ngroup 602 */ 603 static nss_status_t 604 __netgr_in(void *a, char *netgrname) 605 { 606 struct nss_innetgr_args *ia = (struct nss_innetgr_args *)a; 607 nss_status_t status = NSS_NOTFOUND; 608 609 #ifdef DEBUG 610 (void) fprintf(stdout, "\n[getnetgrent.c: netgr_in]\n"); 611 (void) fprintf(stdout, "\tmachine: argc[%d]='%s' user: " 612 "argc[%d]='%s',\n\tdomain:argc[%d]='%s' " 613 "netgroup: argc[%d]='%s'\n", 614 NSS_NETGR_MACHINE, 615 PRINT_VAL(ia->arg[NSS_NETGR_MACHINE]), 616 NSS_NETGR_USER, 617 PRINT_VAL(ia->arg[NSS_NETGR_USER]), 618 NSS_NETGR_DOMAIN, 619 PRINT_VAL(ia->arg[NSS_NETGR_DOMAIN]), 620 NSS_NETGR_N, 621 PRINT_VAL(ia->arg[NSS_NETGR_N])); 622 (void) fprintf(stdout, "\tgroups='%s'\n", netgrname); 623 #endif /* DEBUG */ 624 625 ia->status = NSS_NETGR_NO; 626 627 if (netgrname == NULL) 628 return (status); 629 630 return (top_down_search(ia, netgrname)); 631 } 632 633 /*ARGSUSED0*/ 634 static nss_status_t 635 netgr_in(ldap_backend_ptr be, void *a) 636 { 637 struct nss_innetgr_args *ia = (struct nss_innetgr_args *)a; 638 int i; 639 nss_status_t rc = (nss_status_t)NSS_NOTFOUND; 640 641 ia->status = NSS_NETGR_NO; 642 for (i = 0; i < ia->groups.argc; i++) { 643 rc = __netgr_in(a, ia->groups.argv[i]); 644 if (ia->status == NSS_NETGR_FOUND) 645 return (NSS_SUCCESS); 646 } 647 return (rc); 648 } 649 650 /* 651 * 652 */ 653 654 static nss_status_t 655 getnetgr_ldap_setent(ldap_backend_ptr be, void *a) 656 { 657 const char *netgroup = (const char *) a; 658 getnetgrent_cookie_t *cookie; 659 660 #ifdef DEBUG 661 (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_setent]\n"); 662 #endif /* DEBUG */ 663 664 cookie = (getnetgrent_cookie_t *)be->netgroup_cookie; 665 if (cookie != NULL && cookie->netgroup != NULL) { 666 /* is this another set on the same netgroup */ 667 if (strcmp(cookie->netgroup, netgroup) == 0) 668 return ((nss_status_t)NSS_SUCCESS); 669 } 670 671 return (NSS_NOTFOUND); 672 } 673 674 static void 675 free_getnetgrent_cookie(getnetgrent_cookie_t **cookie) 676 { 677 ns_ldap_error_t *error = NULL; 678 getnetgrent_cookie_t *p = *cookie; 679 680 #ifdef DEBUG 681 (void) fprintf(stdout, "\n[getnetgrent.c: free_getnetgrent_cookie]\n"); 682 #endif /* DEBUG */ 683 684 if (p == NULL) 685 return; 686 687 (void) __ns_ldap_freeResult(&p->results); 688 (void) __ns_ldap_endEntry(&p->cookie, &error); 689 (void) __ns_ldap_freeError(&error); 690 free_netgroup_table(&p->tab); 691 free(p->netgroup); 692 free(p); 693 *cookie = NULL; 694 } 695 696 /*ARGSUSED1*/ 697 static nss_status_t 698 getnetgr_ldap_endent(ldap_backend_ptr be, void *a) 699 { 700 701 #ifdef DEBUG 702 (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_endent]\n"); 703 #endif /* DEBUG */ 704 705 free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie); 706 707 return ((nss_status_t)NSS_NOTFOUND); 708 } 709 710 711 /*ARGSUSED1*/ 712 static nss_status_t 713 getnetgr_ldap_destr(ldap_backend_ptr be, void *a) 714 { 715 716 #ifdef DEBUG 717 (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_destr]\n"); 718 #endif /* DEBUG */ 719 720 free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie); 721 free(be); 722 723 return ((nss_status_t)NSS_NOTFOUND); 724 } 725 726 727 static nss_status_t 728 getnetgr_ldap_getent(ldap_backend_ptr be, void *a) 729 { 730 struct nss_getnetgrent_args *args; 731 getnetgrent_cookie_t *p; 732 char searchfilter[SEARCHFILTERLEN]; 733 char userdata[SEARCHFILTERLEN]; 734 char name[SEARCHFILTERLEN]; 735 int rc; 736 void *cookie = NULL; 737 ns_ldap_result_t *result = NULL; 738 ns_ldap_error_t *error = NULL; 739 char **attrs; 740 char *hostname, *username, *domain; 741 char *buffer; 742 nss_status_t status = NSS_SUCCESS; 743 netgroup_name_t *ng; 744 int ret; 745 746 #ifdef DEBUG 747 (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_getent]\n"); 748 #endif /* DEBUG */ 749 750 args = (struct nss_getnetgrent_args *)a; 751 752 args->status = NSS_NETGR_NO; 753 754 p = (getnetgrent_cookie_t *)be->netgroup_cookie; 755 if (p == NULL) 756 return ((nss_status_t)NSS_SUCCESS); 757 758 for (;;) { 759 while (p->cookie == NULL) { 760 ng = get_next_netgroup(&p->tab); 761 if (ng == NULL) /* no more */ 762 break; 763 764 if (_ldap_filter_name(name, ng->name, 765 sizeof (name)) != 0) 766 break; 767 768 ret = snprintf(searchfilter, 769 sizeof (searchfilter), 770 _F_SETMEMBER, name); 771 if (ret >= sizeof (searchfilter) || ret < 0) 772 break; 773 774 ret = snprintf(userdata, sizeof (userdata), 775 _F_SETMEMBER_SSD, name); 776 if (ret >= sizeof (userdata) || ret < 0) 777 break; 778 779 result = NULL; 780 rc = __ns_ldap_firstEntry(_NETGROUP, 781 searchfilter, 782 _merge_SSD_filter, netgrent_attrs, 783 NULL, 0, &cookie, 784 &result, &error, userdata); 785 (void) __ns_ldap_freeError(&error); 786 787 if (rc == NS_LDAP_SUCCESS && result != NULL) { 788 p->cookie = cookie; 789 p->results = result; 790 break; 791 } 792 (void) __ns_ldap_freeResult(&result); 793 (void) __ns_ldap_endEntry(&cookie, &error); 794 (void) __ns_ldap_freeError(&error); 795 } 796 if (p->cookie == NULL) 797 break; 798 if (p->results == NULL) { 799 result = NULL; 800 rc = __ns_ldap_nextEntry(p->cookie, &result, 801 &error); 802 (void) __ns_ldap_freeError(&error); 803 if (rc == NS_LDAP_SUCCESS && result != NULL) 804 p->results = result; 805 else { 806 (void) __ns_ldap_freeResult(&result); 807 (void) __ns_ldap_endEntry(&p->cookie, 808 &error); 809 (void) __ns_ldap_freeError(&error); 810 p->cookie = NULL; 811 } 812 } 813 if (p->results == NULL) 814 continue; 815 816 if (p->entry == NULL) 817 p->entry = p->results->entry; 818 819 if (p->entry == NULL) 820 continue; 821 822 if (p->attrs == NULL) { 823 attrs = __ns_ldap_getAttr(p->entry, _N_TRIPLE); 824 if (attrs != NULL && *attrs != NULL) 825 p->attrs = attrs; 826 } 827 828 if (p->attrs != NULL) { 829 attrs = p->attrs; 830 buffer = args->buffer; 831 832 if (strlcpy(buffer, *attrs, args->buflen) >= 833 args->buflen) { 834 status = NSS_STR_PARSE_ERANGE; 835 break; 836 } 837 838 rc = split_triple(buffer, &hostname, &username, 839 &domain); 840 attrs++; 841 if (attrs != NULL && *attrs != NULL) 842 p->attrs = attrs; 843 else 844 p->attrs = NULL; 845 if (rc == 0) { 846 args->retp[NSS_NETGR_MACHINE] = hostname; 847 args->retp[NSS_NETGR_USER] = username; 848 args->retp[NSS_NETGR_DOMAIN] = domain; 849 args->status = NSS_NETGR_FOUND; 850 if (p->attrs != NULL) 851 break; 852 } 853 } 854 855 if (p->attrs == NULL) { 856 rc = add_netgroup_member_entry(p->entry, &p->tab); 857 if (rc != 0) { 858 args->status = NSS_NETGR_NO; 859 break; 860 } 861 862 p->entry = p->entry->next; 863 if (p->entry == NULL) 864 (void) __ns_ldap_freeResult(&p->results); 865 if (args->status == NSS_NETGR_FOUND) 866 break; 867 } 868 } 869 870 return (status); 871 } 872 873 static ldap_backend_op_t getnetgroup_ops[] = { 874 getnetgr_ldap_destr, 875 getnetgr_ldap_endent, 876 getnetgr_ldap_setent, 877 getnetgr_ldap_getent, 878 }; 879 880 /* 881 * 882 */ 883 884 static nss_status_t 885 netgr_set(ldap_backend_ptr be, void *a) 886 { 887 struct nss_setnetgrent_args *args = 888 (struct nss_setnetgrent_args *)a; 889 ldap_backend_ptr get_be; 890 getnetgrent_cookie_t *p; 891 892 #ifdef DEBUG 893 (void) fprintf(stdout, "\n[getnetgrent.c: netgr_set]\n"); 894 (void) fprintf(stdout, 895 "\targs->netgroup: %s\n", ISNULL(args->netgroup)); 896 #endif /* DEBUG */ 897 898 if (args->netgroup == NULL) 899 return ((nss_status_t)NSS_NOTFOUND); 900 901 free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie); 902 p = (getnetgrent_cookie_t *)calloc(1, sizeof (getnetgrent_cookie_t)); 903 if (p == NULL) 904 return ((nss_status_t)NSS_NOTFOUND); 905 p->netgroup = strdup(args->netgroup); 906 if (p->netgroup == NULL) { 907 free(p); 908 return ((nss_status_t)NSS_NOTFOUND); 909 } 910 if (add_netgroup_name(args->netgroup, &p->tab) == -1) { 911 free_getnetgrent_cookie(&p); 912 return ((nss_status_t)NSS_NOTFOUND); 913 } 914 915 /* now allocate and return iteration backend structure */ 916 if ((get_be = (ldap_backend_ptr)malloc(sizeof (*get_be))) == NULL) 917 return (NSS_UNAVAIL); 918 get_be->ops = getnetgroup_ops; 919 get_be->nops = sizeof (getnetgroup_ops) / sizeof (getnetgroup_ops[0]); 920 get_be->tablename = NULL; 921 get_be->attrs = netgrent_attrs; 922 get_be->result = NULL; 923 get_be->ldapobj2str = NULL; 924 get_be->setcalled = 1; 925 get_be->filter = NULL; 926 get_be->toglue = NULL; 927 get_be->enumcookie = NULL; 928 get_be->netgroup_cookie = p; 929 args->iterator = (nss_backend_t *)get_be; 930 931 (void) __ns_ldap_freeResult(&be->result); 932 933 return (NSS_SUCCESS); 934 } 935 936 937 /*ARGSUSED1*/ 938 static nss_status_t 939 netgr_ldap_destr(ldap_backend_ptr be, void *a) 940 { 941 942 #ifdef DEBUG 943 (void) fprintf(stdout, "\n[getnetgrent.c: netgr_ldap_destr]\n"); 944 #endif /* DEBUG */ 945 946 (void) _clean_ldap_backend(be); 947 948 return ((nss_status_t)NSS_NOTFOUND); 949 } 950 951 952 953 954 static ldap_backend_op_t netgroup_ops[] = { 955 netgr_ldap_destr, 956 0, 957 0, 958 0, 959 netgr_in, /* innetgr() */ 960 netgr_set /* setnetgrent() */ 961 }; 962 963 964 /* 965 * _nss_ldap_netgroup_constr is where life begins. This function calls the 966 * generic ldap constructor function to define and build the abstract data 967 * types required to support ldap operations. 968 */ 969 970 /*ARGSUSED0*/ 971 nss_backend_t * 972 _nss_ldap_netgroup_constr(const char *dummy1, const char *dummy2, 973 const char *dummy3) 974 { 975 976 #ifdef DEBUG 977 (void) fprintf(stdout, 978 "\n[getnetgrent.c: _nss_ldap_netgroup_constr]\n"); 979 #endif /* DEBUG */ 980 981 return ((nss_backend_t *)_nss_ldap_constr(netgroup_ops, 982 sizeof (netgroup_ops)/sizeof (netgroup_ops[0]), _NETGROUP, 983 netgrent_attrs, NULL)); 984 } 985