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