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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <syslog.h> 30 #include "ldap_common.h" 31 32 /* netgroup attributes filters */ 33 #define _N_NAME "cn" 34 #define _N_TRIPLE "nisnetgrouptriple" 35 #define _N_MEMBER "membernisnetgroup" 36 37 #define PRINT_VAL(a) (((a).argc == 0) || ((a).argv == NULL) || \ 38 ((a).argv[0] == NULL)) ? "*" : (a).argv[0] 39 #define ISWILD(a) ((a) == NULL) 40 #define GET_ARGV(a) (((a).argc == 0) || ((a).argv == NULL) || \ 41 ((a).argv[0] == NULL)) ? NULL : (a).argv[0] 42 #define ISNULL(a) (a == NULL ? "<NULL>" : a) 43 #define MAX_NETGR_NAME_LEN 256 44 #define MAX_DOMAIN_LEN 1024 45 #define MAX_TRIPLE_LEN (MAXHOSTNAMELEN + LOGNAME_MAX + \ 46 MAX_DOMAIN_LEN + 5) 47 48 #define _F_GETNETGR_TRIPLE \ 49 "(&(objectClass=nisNetGroup)" \ 50 "(|(nisnetgrouptriple=(%s,%s,*))(nisnetgrouptriple=(%s,,*))" \ 51 "(nisnetgrouptriple=(,%s,*))(nisnetgrouptriple=(,,*))))" 52 #define _F_GETNETGR_TRIPLE_SSD \ 53 "(&(%%s)(|(nisnetgrouptriple=(%s,%s,*))(nisnetgrouptriple=(%s,,*))" \ 54 "(nisnetgrouptriple=(,%s,*))(nisnetgrouptriple=(,,*))))" 55 #define _F_GETNETGR_TRIPLE_MACHINE \ 56 "(&(objectClass=nisNetGroup)" \ 57 "(|(nisnetgrouptriple=(%s,*,*))(nisnetgrouptriple=(,*,*))))" 58 #define _F_GETNETGR_TRIPLE_MACHINE_SSD \ 59 "(&(%%s)(|(nisnetgrouptriple=(%s,*,*))(nisnetgrouptriple=(,*,*))))" 60 #define _F_GETNETGRENT \ 61 "(&(objectClass=nisNetGroup)(nisnetgrouptriple=(%s,%s,%s)))" 62 #define _F_GETNETGRENT_SSD \ 63 "(&(%%s)(nisnetgrouptriple=(%s,%s,%s)))" 64 65 /* 66 * Although the filter should include the test for (*,,*), this leads to 67 * an unindexed search. To support this, a plugin should be the directory 68 * server. 69 */ 70 #define _F_GETNETGR_TRIPLE_USER \ 71 "(&(objectClass=nisNetGroup)(nisnetgrouptriple=(*,%s,*)))" 72 #define _F_GETNETGR_TRIPLE_USER_SSD \ 73 "(&(%%s)(nisnetgrouptriple=(*,%s,*)))" 74 75 #define _F_GETMEMBERGRENT \ 76 "(&(objectClass=nisNetGroup)(membernisnetgroup=%s))" 77 #define _F_GETMEMBERGRENT_SSD \ 78 "(&(%%s)(membernisnetgroup=%s))" 79 80 #define _F_ISMEMBERGRENT \ 81 "(&(objectClass=nisNetGroup)(cn=%s)(membernisnetgroup=%s))" 82 #define _F_ISMEMBERGRENT_SSD \ 83 "(&(%%s)(cn=%s)(membernisnetgroup=%s))" 84 85 #define MAX_INNETGR_FILTER_LEN (2 * MAXHOSTNAMELEN + 2 * LOGNAME_MAX + 140) 86 #define MAX_GETMEM_FILTER_LEN (MAX_NETGR_NAME_LEN + 50) 87 #define MAX_ISMEM_FILTER_LEN (2 * MAX_NETGR_NAME_LEN + 56) 88 89 #define _F_GETMEMBER \ 90 "(&(objectClass=nisNetGroup)(membernisnetgroup=%s))" 91 #define _F_GETMEMBER_SSD "(&(%%s)(membernisnetgroup=%s))" 92 #define _F_SETMEMBER "(&(objectClass=nisNetGroup)(cn=%s))" 93 #define _F_SETMEMBER_SSD "(&(%%s)(cn=%s))" 94 95 #define N_HASH 257 96 97 static const char *netgrent_attrs[] = { 98 _N_TRIPLE, 99 _N_MEMBER, 100 (char *)NULL 101 }; 102 103 static const char *netgr_name_attrs[] = { 104 _N_NAME, 105 (char *)NULL 106 }; 107 108 static const char *netgr_leaf_attrs[] = { 109 _N_NAME, 110 _N_TRIPLE, 111 (char *)NULL 112 }; 113 114 static const char *netgr_node_attrs[] = { 115 _N_NAME, 116 _N_MEMBER, 117 (char *)NULL 118 }; 119 120 typedef struct netgroup_name { 121 char *name; 122 struct netgroup_name *next; 123 struct netgroup_name *next_hash; 124 } netgroup_name_t; 125 126 typedef struct { 127 netgroup_name_t *hash_list[N_HASH]; 128 netgroup_name_t *to_do; 129 netgroup_name_t *done; 130 } netgroup_table_t; 131 132 typedef struct { 133 ns_ldap_result_t *results; 134 ns_ldap_entry_t *entry; 135 char **attrs; 136 void *cookie; 137 char *netgroup; 138 netgroup_table_t tab; 139 } getnetgrent_cookie_t; 140 141 typedef struct { 142 struct nss_innetgr_args *ia; 143 const char *ssd_filter; 144 const char *netgrname; 145 const char *membername; 146 netgroup_table_t tab; 147 } innetgr_cookie_t; 148 149 typedef unsigned int hash_t; 150 151 static hash_t 152 get_hash(const char *s) 153 { 154 unsigned int sum = 0; 155 unsigned int i; 156 157 for (i = 0; s[i] != '\0'; i++) 158 sum += ((unsigned char *)s)[i]; 159 160 return ((sum + i) % N_HASH); 161 } 162 163 static netgroup_name_t * 164 in_netgroup_table(const char *name, netgroup_table_t *tab) 165 { 166 hash_t h; 167 netgroup_name_t *ret; 168 169 if (tab == NULL || name == NULL || *name == '\0') 170 return (NULL); 171 172 h = get_hash(name); 173 ret = tab->hash_list[h]; 174 175 while (ret != NULL) { 176 if (strcmp(name, ret->name) == 0) 177 break; 178 ret = ret->next_hash; 179 } 180 181 return (ret); 182 } 183 184 /* 185 * Adds a name to the netgroup table 186 * 187 * Returns 188 * 0 if successfully added or already present 189 * -1 if memory allocation error 190 */ 191 192 static int 193 add_netgroup_name(const char *name, netgroup_table_t *tab) 194 { 195 hash_t h; 196 netgroup_name_t *ng; 197 netgroup_name_t *ng_new; 198 199 if (tab == NULL || name == NULL || *name == '\0') 200 return (NULL); 201 202 h = get_hash(name); 203 ng = tab->hash_list[h]; 204 205 while (ng != NULL) { 206 if (strcmp(name, ng->name) == 0) 207 break; 208 ng = ng->next_hash; 209 } 210 211 if (ng == NULL) { 212 ng_new = (netgroup_name_t *) 213 calloc(1, sizeof (netgroup_name_t)); 214 if (ng_new == NULL) 215 return (-1); 216 ng_new->name = strdup(name); 217 if (ng_new->name == NULL) { 218 free(ng_new); 219 return (-1); 220 } 221 ng_new->next_hash = tab->hash_list[h]; 222 tab->hash_list[h] = ng_new; 223 ng_new->next = tab->to_do; 224 tab->to_do = ng_new; 225 } 226 return (0); 227 } 228 229 static netgroup_name_t * 230 get_next_netgroup(netgroup_table_t *tab) 231 { 232 netgroup_name_t *ng; 233 234 if (tab == NULL) 235 return (NULL); 236 237 ng = tab->to_do; 238 if (ng != NULL) { 239 tab->to_do = ng->next; 240 ng->next = tab->done; 241 tab->done = ng; 242 } 243 return (ng); 244 } 245 246 static void 247 free_netgroup_table(netgroup_table_t *tab) 248 { 249 netgroup_name_t *ng, *next; 250 251 if (tab == NULL) 252 return; 253 254 for (ng = tab->to_do; ng != NULL; ng = next) { 255 if (ng->name != NULL) 256 free(ng->name); 257 next = ng->next; 258 free(ng); 259 } 260 261 for (ng = tab->done; ng != NULL; ng = next) { 262 if (ng->name != NULL) 263 free(ng->name); 264 next = ng->next; 265 free(ng); 266 } 267 (void) memset(tab, 0, sizeof (*tab)); 268 } 269 270 /* 271 * domain comparing routine 272 * n1: See if n1 is n2 or an ancestor of it 273 * n2: (in string terms, n1 is a suffix of n2) 274 * Returns ZERO for success, -1 for failure. 275 */ 276 static int 277 domcmp(const char *n1, const char *n2) 278 { 279 #define PASS 0 280 #define FAIL -1 281 282 size_t l1, l2; 283 284 if ((n1 == NULL) || (n2 == NULL)) 285 return (FAIL); 286 287 l1 = strlen(n1); 288 l2 = strlen(n2); 289 290 /* Turn a blind eye to the presence or absence of trailing periods */ 291 if (l1 != 0 && n1[l1 - 1] == '.') { 292 --l1; 293 } 294 if (l2 != 0 && n2[l2 - 1] == '.') { 295 --l2; 296 } 297 if (l1 > l2) { /* Can't be a suffix */ 298 return (FAIL); 299 } else if (l1 == 0) { /* Trivially a suffix; */ 300 /* (do we want this case?) */ 301 return (PASS); 302 } 303 /* So 0 < l1 <= l2 */ 304 if (l1 < l2 && n2[l2 - l1 - 1] != '.') { 305 return (FAIL); 306 } 307 if (strncasecmp(n1, &n2[l2 - l1], l1) == 0) { 308 return (PASS); 309 } else { 310 return (FAIL); 311 } 312 } 313 314 static int 315 split_triple(char *triple, char **hostname, char **username, char **domain) 316 { 317 int i, syntax_err; 318 char *splittriple[3]; 319 char *p = triple; 320 321 #ifdef DEBUG 322 (void) fprintf(stdout, "\n[getnetgrent.c: split_triple]\n"); 323 #endif /* DEBUG */ 324 325 if (triple == NULL) 326 return (-1); 327 328 p++; 329 syntax_err = 0; 330 for (i = 0; i < 3; i++) { 331 char *start; 332 char *limit; 333 const char *terminators = ",) \t"; 334 335 if (i == 2) { 336 /* Don't allow comma */ 337 terminators++; 338 } 339 while (isspace(*p)) { 340 p++; 341 } 342 start = p; 343 limit = strpbrk(start, terminators); 344 if (limit == 0) { 345 syntax_err++; 346 break; 347 } 348 p = limit; 349 while (isspace(*p)) { 350 p++; 351 } 352 if (*p == terminators[0]) { 353 /* 354 * Successfully parsed this name and 355 * the separator after it (comma or 356 * right paren); leave p ready for 357 * next parse. 358 */ 359 p++; 360 if (start == limit) { 361 /* Wildcard */ 362 splittriple[i] = NULL; 363 } else { 364 *limit = '\0'; 365 splittriple[i] = start; 366 } 367 } else { 368 syntax_err++; 369 break; 370 } 371 } 372 373 if (syntax_err != 0) 374 return (-1); 375 376 *hostname = splittriple[0]; 377 *username = splittriple[1]; 378 *domain = splittriple[2]; 379 380 return (0); 381 } 382 383 /* 384 * check the domain part of the triples. 385 * -1 = fails to match, 0 = match 386 */ 387 388 static int 389 match_triple_entry(struct nss_innetgr_args *ia, const ns_ldap_entry_t *entry) 390 { 391 int ndomains; 392 char **pdomains; 393 int nhost; 394 char **phost; 395 int nusers; 396 char **pusers; 397 char **attr; 398 char triple[MAX_TRIPLE_LEN]; 399 char *tuser, *thost, *tdomain; 400 int i; 401 402 nhost = ia->arg[NSS_NETGR_MACHINE].argc; 403 phost = (char **)ia->arg[NSS_NETGR_MACHINE].argv; 404 if (phost == NULL || *phost == NULL) 405 nhost = 0; 406 nusers = ia->arg[NSS_NETGR_USER].argc; 407 pusers = (char **)ia->arg[NSS_NETGR_USER].argv; 408 if (pusers == NULL || *pusers == NULL) 409 nusers = 0; 410 ndomains = ia->arg[NSS_NETGR_DOMAIN].argc; 411 pdomains = (char **)ia->arg[NSS_NETGR_DOMAIN].argv; 412 if (pdomains == NULL || *pdomains == NULL) 413 ndomains = 0; 414 415 attr = __ns_ldap_getAttr(entry, _N_TRIPLE); 416 if (attr == NULL || *attr == NULL) 417 return (0); 418 419 for (; *attr; attr++) { 420 if (strlcpy(triple, *attr, sizeof (triple)) >= sizeof (triple)) 421 continue; 422 if (split_triple(triple, &thost, &tuser, &tdomain) != 0) 423 continue; 424 if (thost != NULL && *thost != '\0' && nhost != 0) { 425 for (i = 0; i < nhost; i++) 426 if (strcasecmp(thost, phost[i]) == 0) 427 break; 428 if (i == nhost) 429 continue; 430 } 431 if (tuser != NULL && *tuser != '\0' && nusers != 0) { 432 for (i = 0; i < nusers; i++) 433 if (strcmp(tuser, pusers[i]) == 0) 434 break; 435 if (i == nusers) 436 continue; 437 } 438 if (tdomain != NULL && *tdomain != '\0' && ndomains != 0) { 439 for (i = 0; i < ndomains; i++) 440 if (domcmp(tdomain, pdomains[i]) == 0) 441 break; 442 if (i == ndomains) 443 continue; 444 } 445 return (1); 446 } 447 448 return (0); 449 } 450 451 static int 452 match_triple(struct nss_innetgr_args *ia, ns_ldap_result_t *result) 453 { 454 ns_ldap_entry_t *entry; 455 456 for (entry = result->entry; entry != NULL; entry = entry->next) 457 if (match_triple_entry(ia, entry) == 1) 458 return (1); 459 460 return (0); 461 } 462 463 static int 464 add_netgroup_member_entry(ns_ldap_entry_t *entry, netgroup_table_t *tab) 465 { 466 char **attrs; 467 char **a; 468 469 attrs = __ns_ldap_getAttr(entry, _N_MEMBER); 470 if (attrs == NULL || *attrs == NULL) 471 return (0); 472 473 for (a = attrs; *a != NULL; a++) {} 474 475 do { 476 a--; 477 if (add_netgroup_name(*a, tab) != 0) 478 return (-1); 479 } while (a > attrs); 480 return (0); 481 } 482 483 static int 484 add_netgroup_member(ns_ldap_result_t *result, netgroup_table_t *tab) 485 { 486 ns_ldap_entry_t *entry; 487 int ret = 0; 488 489 for (entry = result->entry; entry != NULL; entry = entry->next) { 490 ret = add_netgroup_member_entry(entry, tab); 491 if (ret != 0) 492 break; 493 } 494 return (ret); 495 } 496 497 /* 498 * top_down_search checks only checks the netgroup specified in netgrname 499 */ 500 static nss_status_t 501 top_down_search(struct nss_innetgr_args *ia, char *netgrname) 502 { 503 char searchfilter[SEARCHFILTERLEN]; 504 char name[SEARCHFILTERLEN]; 505 char userdata[SEARCHFILTERLEN]; 506 ns_ldap_result_t *result = NULL; 507 ns_ldap_error_t *error = NULL; 508 int rc; 509 void *cookie = NULL; 510 nss_status_t status = NSS_NOTFOUND; 511 netgroup_table_t tab; 512 netgroup_name_t *ng; 513 int ret; 514 515 (void) memset(&tab, 0, sizeof (tab)); 516 517 if (add_netgroup_name(netgrname, &tab) != 0) 518 return ((nss_status_t)NSS_NOTFOUND); 519 520 while ((ng = get_next_netgroup(&tab)) != NULL) { 521 if (_ldap_filter_name(name, ng->name, sizeof (name)) != 0) 522 break; 523 ret = snprintf(searchfilter, sizeof (searchfilter), _F_SETMEMBER, 524 name); 525 if (ret >= sizeof (searchfilter) || ret < 0) 526 break; 527 528 ret = snprintf(userdata, sizeof (userdata), _F_SETMEMBER_SSD, name); 529 if (ret >= sizeof (userdata) || ret < 0) 530 break; 531 532 rc = __ns_ldap_firstEntry(_NETGROUP, searchfilter, 533 _merge_SSD_filter, netgrent_attrs, NULL, 0, &cookie, &result, 534 &error, userdata); 535 536 (void) __ns_ldap_freeError(&error); 537 while (rc == NS_LDAP_SUCCESS && result != NULL) { 538 if (match_triple(ia, result) == 1) { 539 /* We found a match */ 540 ia->status = NSS_NETGR_FOUND; 541 status = NSS_SUCCESS; 542 break; 543 } 544 545 rc = add_netgroup_member(result, &tab); 546 (void) __ns_ldap_freeResult(&result); 547 548 if (rc != NS_LDAP_SUCCESS) 549 break; 550 rc = __ns_ldap_nextEntry(cookie, &result, &error); 551 (void) __ns_ldap_freeError(&error); 552 } 553 (void) __ns_ldap_freeResult(&result); 554 (void) __ns_ldap_endEntry(&cookie, &error); 555 (void) __ns_ldap_freeError(&error); 556 557 if (status == NSS_SUCCESS || 558 (rc != NS_LDAP_SUCCESS && rc != NS_LDAP_NOTFOUND)) 559 break; 560 } 561 562 (void) __ns_ldap_freeResult(&result); 563 (void) __ns_ldap_endEntry(&cookie, &error); 564 (void) __ns_ldap_freeError(&error); 565 free_netgroup_table(&tab); 566 return (status); 567 } 568 569 static int 570 innetgr_SSD_filter(const ns_ldap_search_desc_t *desc, char **realfilter, 571 const void *userdata) 572 { 573 const innetgr_cookie_t *cookie = (innetgr_cookie_t *)userdata; 574 575 return (_merge_SSD_filter(desc, realfilter, cookie->ssd_filter)); 576 } 577 578 static int process_innetgr_node(const ns_ldap_entry_t *entry, 579 const void *userdata); 580 581 /* return 1 when done, 0 otherwise */ 582 static int 583 check_parent(const char *gr_name, innetgr_cookie_t *cookie) 584 { 585 ns_ldap_result_t *result = NULL; 586 ns_ldap_error_t *error = NULL; 587 char searchfilter[MAX_GETMEM_FILTER_LEN]; 588 char name[MAX_GETMEM_FILTER_LEN]; 589 char ssd_filter[MAX_GETMEM_FILTER_LEN]; 590 const char *ssd_filter_sav = cookie->ssd_filter; 591 int ret; 592 593 #ifdef DEBUG 594 (void) fprintf(stdout, "\n[getnetgrent.c: check_parent:%s]\n", gr_name); 595 #endif /* DEBUG */ 596 597 if (_ldap_filter_name(name, gr_name, sizeof (name)) != 0) 598 return (0); 599 ret = snprintf(searchfilter, sizeof (searchfilter), 600 _F_GETMEMBERGRENT, name); 601 if (ret >= sizeof (searchfilter) || ret < 0) 602 return (0); 603 604 ret = snprintf(ssd_filter, sizeof (ssd_filter), 605 _F_GETMEMBERGRENT_SSD, name); 606 if (ret >= sizeof (ssd_filter) || ret < 0) 607 return (0); 608 609 cookie->ssd_filter = ssd_filter; 610 cookie->membername = gr_name; 611 612 (void) __ns_ldap_list(_NETGROUP, searchfilter, innetgr_SSD_filter, 613 netgr_node_attrs, NULL, 0, &result, &error, 614 process_innetgr_node, cookie); 615 616 cookie->ssd_filter = ssd_filter_sav; 617 618 (void) __ns_ldap_freeResult(&result); 619 (void) __ns_ldap_freeError(&error); 620 621 return (cookie->ia->status == NSS_NETGR_NO ? 0 : 1); 622 } 623 624 /* Use the server's matching rule if not a case exact match */ 625 626 static int 627 server_match(innetgr_cookie_t *cookie) 628 { 629 ns_ldap_result_t *result = NULL; 630 ns_ldap_error_t *error = NULL; 631 char searchfilter[MAX_ISMEM_FILTER_LEN]; 632 char netgrname[MAX_ISMEM_FILTER_LEN]; 633 char membername[MAX_ISMEM_FILTER_LEN]; 634 char ssd_filter[MAX_ISMEM_FILTER_LEN]; 635 const char *ssd_filter_sav = cookie->ssd_filter; 636 int rc; 637 int ret; 638 639 if (_ldap_filter_name(netgrname, cookie->netgrname, 640 sizeof (netgrname)) != 0) 641 return (0); 642 if (_ldap_filter_name(membername, cookie->membername, 643 sizeof (membername)) != 0) 644 return (0); 645 ret = snprintf(searchfilter, sizeof (searchfilter), _F_ISMEMBERGRENT, 646 netgrname, membername); 647 if (ret >= sizeof (searchfilter) || ret < 0) 648 return (0); 649 650 ret = snprintf(ssd_filter, sizeof (ssd_filter), _F_ISMEMBERGRENT_SSD, 651 netgrname, membername); 652 if (ret >= sizeof (ssd_filter) || ret < 0) 653 return (0); 654 655 cookie->ssd_filter = ssd_filter; 656 657 rc = __ns_ldap_list(_NETGROUP, searchfilter, innetgr_SSD_filter, 658 netgr_name_attrs, NULL, 0, &result, &error, 659 NULL, &cookie); 660 661 (void) __ns_ldap_freeResult(&result); 662 (void) __ns_ldap_freeError(&error); 663 664 cookie->ssd_filter = ssd_filter_sav; 665 return (rc == NS_LDAP_SUCCESS); 666 } 667 668 static int 669 process_innetgr_node(const ns_ldap_entry_t *entry, const void *userdata) 670 { 671 innetgr_cookie_t *cookie = (innetgr_cookie_t *)userdata; 672 char **a, **attr; 673 674 attr = __ns_ldap_getAttr(entry, _N_NAME); 675 if (attr == NULL) 676 return (NS_LDAP_CB_NEXT); 677 678 for (a = attr; *a; a++) { 679 #ifdef DEBUG 680 (void) fprintf(stdout, "\n[getnetgrent.c: process_innetgr_node:%s]\n", 681 *a); 682 #endif /* DEBUG */ 683 684 if (strcasecmp(*a, cookie->netgrname) == 0) { 685 if (strcmp(*a, cookie->netgrname) == 0 || 686 server_match(cookie)) { 687 cookie->ia->status = NSS_NETGR_FOUND; 688 return (NS_LDAP_CB_DONE); 689 } 690 } 691 } 692 for (a = attr; *a; a++) { 693 /* check if we have already visited this node */ 694 if (in_netgroup_table(*a, &cookie->tab) != NULL) 695 continue; 696 if (add_netgroup_name(*a, &cookie->tab) != 0) { 697 cookie->ia->status = NSS_NETGR_NOMEM; 698 return (NS_LDAP_CB_DONE); 699 } 700 if (check_parent(*a, cookie) == 1) 701 return (NS_LDAP_CB_DONE); 702 } 703 return (NS_LDAP_CB_NEXT); 704 } 705 706 static int 707 process_innetgr_leaf(const ns_ldap_entry_t *entry, const void *userdata) 708 { 709 innetgr_cookie_t *cookie = (innetgr_cookie_t *)userdata; 710 711 /* Check to see if this entry matches the triple */ 712 if (match_triple_entry(cookie->ia, entry) != 1) 713 return (NS_LDAP_CB_NEXT); 714 715 return (process_innetgr_node(entry, userdata)); 716 } 717 718 /* 719 * __netgr_in checks only checks the netgroup specified in ngroup 720 */ 721 static nss_status_t 722 __netgr_in(void *a, char *netgrname) 723 { 724 struct nss_innetgr_args *ia = (struct nss_innetgr_args *)a; 725 char searchfilter[MAX_INNETGR_FILTER_LEN]; 726 char ssd_filter[MAX_INNETGR_FILTER_LEN]; 727 char mach[MAX_INNETGR_FILTER_LEN]; 728 char user[MAX_INNETGR_FILTER_LEN]; 729 ns_ldap_result_t *result = NULL; 730 ns_ldap_error_t *error = NULL; 731 int rc; 732 nss_status_t status = NSS_NOTFOUND; 733 innetgr_cookie_t cookie = {NULL, NULL, NULL}; 734 int user_wild, mach_wild; 735 int ret; 736 737 #ifdef DEBUG 738 (void) fprintf(stdout, "\n[getnetgrent.c: netgr_in]\n"); 739 (void) fprintf(stdout, "\tmachine: argc[%d]='%s' user: " 740 "argc[%d]='%s',\n\tdomain:argc[%d]='%s' " 741 "netgroup: argc[%d]='%s'\n", 742 NSS_NETGR_MACHINE, 743 PRINT_VAL(ia->arg[NSS_NETGR_MACHINE]), 744 NSS_NETGR_USER, 745 PRINT_VAL(ia->arg[NSS_NETGR_USER]), 746 NSS_NETGR_DOMAIN, 747 PRINT_VAL(ia->arg[NSS_NETGR_DOMAIN]), 748 NSS_NETGR_N, 749 PRINT_VAL(ia->arg[NSS_NETGR_N])); 750 (void) fprintf(stdout, "\tgroups='%s'\n", netgrname); 751 #endif /* DEBUG */ 752 753 ia->status = NSS_NETGR_NO; 754 755 if (netgrname == NULL) 756 return (status); 757 758 mach_wild = (ia->arg[NSS_NETGR_MACHINE].argc == 0) || 759 (ia->arg[NSS_NETGR_MACHINE].argv == NULL) || 760 (ia->arg[NSS_NETGR_MACHINE].argv[0] == NULL); 761 762 user_wild = (ia->arg[NSS_NETGR_USER].argc == 0) || 763 (ia->arg[NSS_NETGR_USER].argv == NULL) || 764 (ia->arg[NSS_NETGR_USER].argv[0] == NULL); 765 766 if (!mach_wild && _ldap_filter_name(mach, 767 ia->arg[NSS_NETGR_MACHINE].argv[0], sizeof (mach)) != 0) 768 return ((nss_status_t)NSS_NOTFOUND); 769 770 if (!user_wild && _ldap_filter_name(user, 771 ia->arg[NSS_NETGR_USER].argv[0], sizeof (user)) != 0) 772 return ((nss_status_t)NSS_NOTFOUND); 773 774 if (!mach_wild && !user_wild) { 775 ret = snprintf(searchfilter, sizeof (searchfilter), 776 _F_GETNETGR_TRIPLE, mach, user, mach, user); 777 if (ret >= sizeof (searchfilter) || ret < 0) 778 return ((nss_status_t)NSS_NOTFOUND); 779 780 ret = snprintf(ssd_filter, sizeof (ssd_filter), 781 _F_GETNETGR_TRIPLE_SSD, mach, user, mach, user); 782 if (ret >= sizeof (ssd_filter) || ret < 0) 783 return ((nss_status_t)NSS_NOTFOUND); 784 } else if (!mach_wild && user_wild) { 785 ret = snprintf(searchfilter, sizeof (searchfilter), 786 _F_GETNETGR_TRIPLE_MACHINE, mach); 787 if (ret >= sizeof (searchfilter) || ret < 0) 788 return ((nss_status_t)NSS_NOTFOUND); 789 790 ret = snprintf(ssd_filter, sizeof (ssd_filter), 791 _F_GETNETGR_TRIPLE_MACHINE_SSD, mach); 792 if (ret >= sizeof (ssd_filter) || ret < 0) 793 return ((nss_status_t)NSS_NOTFOUND); 794 } else if (mach_wild && !user_wild) { 795 ret = snprintf(searchfilter, sizeof (searchfilter), 796 _F_GETNETGR_TRIPLE_USER, user); 797 if (ret >= sizeof (searchfilter) || ret < 0) 798 return ((nss_status_t)NSS_NOTFOUND); 799 800 ret = snprintf(ssd_filter, sizeof (ssd_filter), 801 _F_GETNETGR_TRIPLE_USER_SSD, user); 802 if (ret >= sizeof (ssd_filter) || ret < 0) 803 return ((nss_status_t)NSS_NOTFOUND); 804 } else { 805 return (top_down_search(ia, netgrname)); 806 } 807 808 cookie.ia = ia; 809 cookie.ssd_filter = ssd_filter; 810 cookie.netgrname = netgrname; 811 (void) memset(&cookie.tab, 0, sizeof (cookie.tab)); 812 813 rc = __ns_ldap_list(_NETGROUP, searchfilter, innetgr_SSD_filter, 814 netgr_leaf_attrs, NULL, 0, &result, &error, 815 process_innetgr_leaf, &cookie); 816 status = switch_err(rc, error); 817 818 (void) __ns_ldap_freeResult(&result); 819 (void) __ns_ldap_freeError(&error); 820 free_netgroup_table(&cookie.tab); 821 822 return (status); 823 } 824 825 /*ARGSUSED0*/ 826 static nss_status_t 827 netgr_in(ldap_backend_ptr be, void *a) 828 { 829 struct nss_innetgr_args *ia = (struct nss_innetgr_args *)a; 830 int i; 831 nss_status_t rc = (nss_status_t)NSS_NOTFOUND; 832 833 ia->status = NSS_NETGR_NO; 834 for (i = 0; i < ia->groups.argc; i++) { 835 rc = __netgr_in(a, ia->groups.argv[i]); 836 if (ia->status == NSS_NETGR_FOUND) 837 return (NSS_SUCCESS); 838 } 839 return (rc); 840 } 841 842 /* 843 * 844 */ 845 846 static nss_status_t 847 getnetgr_ldap_setent(ldap_backend_ptr be, void *a) 848 { 849 const char *netgroup = (const char *) a; 850 getnetgrent_cookie_t *cookie; 851 852 #ifdef DEBUG 853 (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_setent]\n"); 854 #endif /* DEBUG */ 855 856 cookie = (getnetgrent_cookie_t *)be->netgroup_cookie; 857 if (cookie != NULL && cookie->netgroup != NULL) { 858 /* is this another set on the same netgroup */ 859 if (strcmp(cookie->netgroup, netgroup) == 0) 860 return ((nss_status_t)NSS_SUCCESS); 861 } 862 863 return (NSS_NOTFOUND); 864 } 865 866 static void 867 free_getnetgrent_cookie(getnetgrent_cookie_t **cookie) 868 { 869 ns_ldap_error_t *error = NULL; 870 getnetgrent_cookie_t *p = *cookie; 871 872 #ifdef DEBUG 873 (void) fprintf(stdout, "\n[getnetgrent.c: free_getnetgrent_cookie]\n"); 874 #endif /* DEBUG */ 875 876 if (p == NULL) 877 return; 878 879 (void) __ns_ldap_freeResult(&p->results); 880 (void) __ns_ldap_endEntry(&p->cookie, &error); 881 (void) __ns_ldap_freeError(&error); 882 free_netgroup_table(&p->tab); 883 free(p->netgroup); 884 free(p); 885 *cookie = NULL; 886 } 887 888 /*ARGSUSED1*/ 889 static nss_status_t 890 getnetgr_ldap_endent(ldap_backend_ptr be, void *a) 891 { 892 893 #ifdef DEBUG 894 (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_endent]\n"); 895 #endif /* DEBUG */ 896 897 free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie); 898 899 return ((nss_status_t)NSS_NOTFOUND); 900 } 901 902 903 /*ARGSUSED1*/ 904 static nss_status_t 905 getnetgr_ldap_destr(ldap_backend_ptr be, void *a) 906 { 907 908 #ifdef DEBUG 909 (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_destr]\n"); 910 #endif /* DEBUG */ 911 912 free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie); 913 free(be); 914 915 return ((nss_status_t)NSS_NOTFOUND); 916 } 917 918 919 static nss_status_t 920 getnetgr_ldap_getent(ldap_backend_ptr be, void *a) 921 { 922 struct nss_getnetgrent_args *args; 923 getnetgrent_cookie_t *p; 924 char searchfilter[SEARCHFILTERLEN]; 925 char userdata[SEARCHFILTERLEN]; 926 char name[SEARCHFILTERLEN]; 927 int rc; 928 void *cookie = NULL; 929 ns_ldap_result_t *result = NULL; 930 ns_ldap_error_t *error = NULL; 931 char **attrs; 932 char *hostname, *username, *domain; 933 char *buffer; 934 nss_status_t status = NSS_SUCCESS; 935 netgroup_name_t *ng; 936 int ret; 937 938 #ifdef DEBUG 939 (void) fprintf(stdout, "\n[getnetgrent.c: getnetgr_ldap_getent]\n"); 940 #endif /* DEBUG */ 941 942 args = (struct nss_getnetgrent_args *)a; 943 944 args->status = NSS_NETGR_NO; 945 946 p = (getnetgrent_cookie_t *)be->netgroup_cookie; 947 if (p == NULL) 948 return ((nss_status_t)NSS_SUCCESS); 949 950 for (;;) { 951 while (p->cookie == NULL) { 952 ng = get_next_netgroup(&p->tab); 953 if (ng == NULL) /* no more */ 954 break; 955 956 if (_ldap_filter_name(name, ng->name, sizeof (name)) != 0) 957 break; 958 959 ret = snprintf(searchfilter, sizeof (searchfilter), 960 _F_SETMEMBER, name); 961 if (ret >= sizeof (searchfilter) || ret < 0) 962 break; 963 964 ret = snprintf(userdata, sizeof (userdata), _F_SETMEMBER_SSD, 965 name); 966 if (ret >= sizeof (userdata) || ret < 0) 967 break; 968 969 result = NULL; 970 rc = __ns_ldap_firstEntry(_NETGROUP, searchfilter, 971 _merge_SSD_filter, netgrent_attrs, NULL, 0, &cookie, 972 &result, &error, userdata); 973 (void) __ns_ldap_freeError(&error); 974 975 if (rc == NS_LDAP_SUCCESS && result != NULL) { 976 p->cookie = cookie; 977 p->results = result; 978 break; 979 } 980 (void) __ns_ldap_freeResult(&result); 981 (void) __ns_ldap_endEntry(&cookie, &error); 982 (void) __ns_ldap_freeError(&error); 983 } 984 if (p->cookie == NULL) 985 break; 986 if (p->results == NULL) { 987 result = NULL; 988 rc = __ns_ldap_nextEntry(p->cookie, &result, &error); 989 (void) __ns_ldap_freeError(&error); 990 if (rc == NS_LDAP_SUCCESS && result != NULL) 991 p->results = result; 992 else { 993 (void) __ns_ldap_freeResult(&result); 994 (void) __ns_ldap_endEntry(&p->cookie, &error); 995 (void) __ns_ldap_freeError(&error); 996 p->cookie = NULL; 997 } 998 } 999 if (p->results == NULL) 1000 continue; 1001 1002 if (p->entry == NULL) 1003 p->entry = p->results->entry; 1004 1005 if (p->entry == NULL) 1006 continue; 1007 1008 if (p->attrs == NULL) { 1009 attrs = __ns_ldap_getAttr(p->entry, _N_TRIPLE); 1010 if (attrs != NULL && *attrs != NULL) 1011 p->attrs = attrs; 1012 } 1013 1014 if (p->attrs != NULL) { 1015 attrs = p->attrs; 1016 buffer = args->buffer; 1017 1018 if (strlcpy(buffer, *attrs, args->buflen) >= args->buflen) { 1019 status = NSS_STR_PARSE_ERANGE; 1020 break; 1021 } 1022 1023 rc = split_triple(buffer, &hostname, &username, &domain); 1024 attrs++; 1025 if (attrs != NULL && *attrs != NULL) 1026 p->attrs = attrs; 1027 else 1028 p->attrs = NULL; 1029 if (rc == 0) { 1030 args->retp[NSS_NETGR_MACHINE] = hostname; 1031 args->retp[NSS_NETGR_USER] = username; 1032 args->retp[NSS_NETGR_DOMAIN] = domain; 1033 args->status = NSS_NETGR_FOUND; 1034 if (p->attrs != NULL) 1035 break; 1036 } 1037 } 1038 1039 if (p->attrs == NULL) { 1040 rc = add_netgroup_member_entry(p->entry, &p->tab); 1041 if (rc != 0) { 1042 args->status = NSS_NETGR_NO; 1043 break; 1044 } 1045 1046 p->entry = p->entry->next; 1047 if (p->entry == NULL) 1048 (void) __ns_ldap_freeResult(&p->results); 1049 if (args->status == NSS_NETGR_FOUND) 1050 break; 1051 } 1052 } 1053 1054 return (status); 1055 } 1056 1057 static ldap_backend_op_t getnetgroup_ops[] = { 1058 getnetgr_ldap_destr, 1059 getnetgr_ldap_endent, 1060 getnetgr_ldap_setent, 1061 getnetgr_ldap_getent, 1062 }; 1063 1064 /* 1065 * 1066 */ 1067 1068 static nss_status_t 1069 netgr_set(ldap_backend_ptr be, void *a) 1070 { 1071 struct nss_setnetgrent_args *args = 1072 (struct nss_setnetgrent_args *)a; 1073 ldap_backend_ptr get_be; 1074 getnetgrent_cookie_t *p; 1075 1076 #ifdef DEBUG 1077 (void) fprintf(stdout, "\n[getnetgrent.c: netgr_set]\n"); 1078 (void) fprintf(stdout, 1079 "\targs->netgroup: %s\n", ISNULL(args->netgroup)); 1080 #endif /* DEBUG */ 1081 1082 if (args->netgroup == NULL) 1083 return ((nss_status_t)NSS_NOTFOUND); 1084 1085 free_getnetgrent_cookie((getnetgrent_cookie_t **)&be->netgroup_cookie); 1086 p = (getnetgrent_cookie_t *)calloc(1, sizeof (getnetgrent_cookie_t)); 1087 if (p == NULL) 1088 return ((nss_status_t)NSS_NOTFOUND); 1089 p->netgroup = strdup(args->netgroup); 1090 if (p->netgroup == NULL) { 1091 free(p); 1092 return ((nss_status_t)NSS_NOTFOUND); 1093 } 1094 if (add_netgroup_name(args->netgroup, &p->tab) == -1) { 1095 free_getnetgrent_cookie(&p); 1096 return ((nss_status_t)NSS_NOTFOUND); 1097 } 1098 1099 /* now allocate and return iteration backend structure */ 1100 if ((get_be = (ldap_backend_ptr)malloc(sizeof (*get_be))) == NULL) 1101 return (NSS_UNAVAIL); 1102 get_be->ops = getnetgroup_ops; 1103 get_be->nops = sizeof (getnetgroup_ops) / sizeof (getnetgroup_ops[0]); 1104 get_be->tablename = NULL; 1105 get_be->attrs = netgrent_attrs; 1106 get_be->result = NULL; 1107 get_be->ldapobj2ent = NULL; 1108 get_be->setcalled = 1; 1109 get_be->filter = NULL; 1110 get_be->toglue = NULL; 1111 get_be->enumcookie = NULL; 1112 get_be->netgroup_cookie = p; 1113 args->iterator = (nss_backend_t *)get_be; 1114 1115 (void) __ns_ldap_freeResult(&be->result); 1116 1117 return (NSS_SUCCESS); 1118 } 1119 1120 1121 /*ARGSUSED1*/ 1122 static nss_status_t 1123 netgr_ldap_destr(ldap_backend_ptr be, void *a) 1124 { 1125 1126 #ifdef DEBUG 1127 (void) fprintf(stdout, "\n[getnetgrent.c: netgr_ldap_destr]\n"); 1128 #endif /* DEBUG */ 1129 1130 (void) _clean_ldap_backend(be); 1131 1132 return ((nss_status_t)NSS_NOTFOUND); 1133 } 1134 1135 1136 1137 1138 static ldap_backend_op_t netgroup_ops[] = { 1139 netgr_ldap_destr, 1140 0, 1141 0, 1142 0, 1143 netgr_in, /* innetgr() */ 1144 netgr_set /* setnetgrent() */ 1145 }; 1146 1147 1148 /* 1149 * _nss_ldap_netgroup_constr is where life begins. This function calls the 1150 * generic ldap constructor function to define and build the abstract data 1151 * types required to support ldap operations. 1152 */ 1153 1154 /*ARGSUSED0*/ 1155 nss_backend_t * 1156 _nss_ldap_netgroup_constr(const char *dummy1, const char *dummy2, 1157 const char *dummy3) 1158 { 1159 1160 #ifdef DEBUG 1161 (void) fprintf(stdout, 1162 "\n[getnetgrent.c: _nss_ldap_netgroup_constr]\n"); 1163 #endif /* DEBUG */ 1164 1165 return ((nss_backend_t *)_nss_ldap_constr(netgroup_ops, 1166 sizeof (netgroup_ops)/sizeof (netgroup_ops[0]), _NETGROUP, 1167 netgrent_attrs, NULL)); 1168 } 1169