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 }