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