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