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