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
get_hash(const char * s)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
add_netgroup_name(const char * name,netgroup_table_t * tab)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 *
get_next_netgroup(netgroup_table_t * tab)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
free_netgroup_table(netgroup_table_t * tab)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
domcmp(const char * n1,const char * n2)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
split_triple(char * triple,char ** hostname,char ** username,char ** domain)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
match_triple_entry(struct nss_innetgr_args * ia,const ns_ldap_entry_t * entry)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
match_triple(struct nss_innetgr_args * ia,ns_ldap_result_t * result)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
add_netgroup_member_entry(ns_ldap_entry_t * entry,netgroup_table_t * tab)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
add_netgroup_member(ns_ldap_result_t * result,netgroup_table_t * tab)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
top_down_search(struct nss_innetgr_args * ia,char * netgrname)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
__netgr_in(void * a,char * netgrname)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
netgr_in(ldap_backend_ptr be,void * a)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
getnetgr_ldap_setent(ldap_backend_ptr be,void * a)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
free_getnetgrent_cookie(getnetgrent_cookie_t ** cookie)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
getnetgr_ldap_endent(ldap_backend_ptr be,void * a)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
getnetgr_ldap_destr(ldap_backend_ptr be,void * a)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
getnetgr_ldap_getent(ldap_backend_ptr be,void * a)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
netgr_set(ldap_backend_ptr be,void * a)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
netgr_ldap_destr(ldap_backend_ptr be,void * a)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 *
_nss_ldap_netgroup_constr(const char * dummy1,const char * dummy2,const char * dummy3)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