1 /* $NetBSD: getnetgrent.c,v 1.42 2012/03/20 16:36:05 matt Exp $ */
4 * Copyright (c) 1994 Christos Zoulas
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 #if defined(LIBC_SCCS) && !defined(lint)
31 __RCSID("$NetBSD: getnetgrent.c,v 1.42 2012/03/20 16:36:05 matt Exp $");
32 #endif /* LIBC_SCCS and not lint */
34 #include "namespace.h"
35 #include <sys/types.h>
42 #define _NETGROUP_PRIVATE
43 #include <stringlist.h>
53 #include <rpcsvc/ypclnt.h>
54 #include <rpcsvc/yp_prot.h>
58 __weak_alias(endnetgrent
,_endnetgrent
)
59 __weak_alias(getnetgrent
,_getnetgrent
)
60 __weak_alias(innetgr
,_innetgr
)
61 __weak_alias(setnetgrent
,_setnetgrent
)
64 #define _NG_STAR(s) (((s) == NULL || *(s) == '\0') ? _ngstar : s)
65 #define _NG_EMPTY(s) ((s) == NULL ? "" : s)
66 #define _NG_ISSPACE(p) (isspace((unsigned char) (p)) || (p) == '\n')
68 static const char _ngstar
[] = "*";
69 static struct netgroup
*_nghead
= NULL
;
70 static struct netgroup
*_nglist
= NULL
;
73 static int getstring(char **, int, __aconst
char **);
74 static struct netgroup
*getnetgroup(char **);
75 static int lookup(char *, char **, int);
76 static int addgroup(StringList
*, char *);
77 static int in_check(const char *, const char *, const char *,
79 static int in_find(StringList
*, char *, const char *, const char *,
81 static char *in_lookup1(const char *, const char *, int);
82 static int in_lookup(const char *, const char *, const char *, int);
85 static const ns_src default_files_nis
[] = {
86 { NSSRC_FILES
, NS_SUCCESS
| NS_NOTFOUND
},
88 { NSSRC_NIS
, NS_SUCCESS
},
95 * getstring(): Get a string delimited by the character, skipping leading and
96 * trailing blanks and advancing the pointer
99 getstring(char **pp
, int del
, char __aconst
**str
)
104 _DIAGASSERT(pp
!= NULL
);
105 _DIAGASSERT(str
!= NULL
);
107 /* skip leading blanks */
108 for (sp
= *pp
; *sp
&& _NG_ISSPACE(*sp
); sp
++)
111 /* accumulate till delimiter or space */
112 for (ep
= sp
; *ep
&& *ep
!= del
&& !_NG_ISSPACE(*ep
); ep
++)
115 /* hunt for the delimiter */
116 for (dp
= ep
; *dp
&& *dp
!= del
&& _NG_ISSPACE(*dp
); dp
++)
131 (void)memcpy(dp
, sp
, len
);
142 * getnetgroup(): Parse a netgroup, and advance the pointer
144 static struct netgroup
*
145 getnetgroup(char **pp
)
149 _DIAGASSERT(pp
!= NULL
);
150 _DIAGASSERT(*pp
!= NULL
);
152 ng
= malloc(sizeof(struct netgroup
));
156 (*pp
)++; /* skip '(' */
157 if (!getstring(pp
, ',', &ng
->ng_host
))
160 if (!getstring(pp
, ',', &ng
->ng_user
))
163 if (!getstring(pp
, ')', &ng
->ng_domain
))
169 (void) fprintf(stderr
, "netgroup %s\n",
170 _ng_print(buf
, sizeof(buf
), ng
));
187 _ng_cycle(const char *grp
, const StringList
*sl
)
190 warnx("netgroup: Cycle in group `%s'", grp
);
191 (void)fprintf(stderr
, "groups: ");
192 for (i
= 0; i
< sl
->sl_cur
; i
++)
193 (void)fprintf(stderr
, "%s ", sl
->sl_str
[i
]);
194 (void)fprintf(stderr
, "\n");
197 static int _local_lookup(void *, void *, va_list);
201 _local_lookup(void *rv
, void *cb_data
, va_list ap
)
203 char *name
= va_arg(ap
, char *);
204 char **line
= va_arg(ap
, char **);
205 int bywhat
= va_arg(ap
, int);
215 len
= strlen(name
) + 2;
221 (void)memcpy(&ks
[1], name
, len
- 1);
223 key
.data
= (u_char
*)ks
;
226 r
= (*_ng_db
->get
)(_ng_db
, &key
, &data
, 0);
234 /* XXX: call endnetgrent() here ? */
238 *line
= strdup(data
.data
);
245 static int _nis_lookup(void *, void *, va_list);
249 _nis_lookup(void *rv
, void *cb_data
, va_list ap
)
251 char *name
= va_arg(ap
, char *);
252 char **line
= va_arg(ap
, char **);
253 int bywhat
= va_arg(ap
, int);
255 static char *__ypdomain
;
257 const char *map
= NULL
;
259 if(__ypdomain
== NULL
) {
260 switch (yp_get_default_domain(&__ypdomain
)) {
276 map
= "netgroup.byuser";
280 map
= "netgroup.byhost";
288 switch (yp_match(__ypdomain
, map
, name
, (int)strlen(name
), line
, &i
)) {
306 * lookup(): Find the given key in the database or yp, and return its value
307 * in *line; returns 1 if key was found, 0 otherwise
310 lookup(char *name
, char **line
, int bywhat
)
313 static const ns_dtab dtab
[] = {
314 NS_FILES_CB(_local_lookup
, NULL
)
315 NS_NIS_CB(_nis_lookup
, NULL
)
319 _DIAGASSERT(name
!= NULL
);
320 _DIAGASSERT(line
!= NULL
);
322 r
= nsdispatch(NULL
, dtab
, NSDB_NETGROUP
, "lookup", default_files_nis
,
324 return (r
== NS_SUCCESS
) ? 1 : 0;
328 _local_lookupv(int *rv
, void *cbdata
, ...)
332 va_start(ap
, cbdata
);
333 e
= _local_lookup(rv
, cbdata
, ap
);
339 lookup(name
, line
, bywhat
)
344 return _local_lookupv(NULL
, NULL
, name
, line
, bywhat
) == NS_SUCCESS
;
349 * _ng_parse(): Parse a line and return: _NG_ERROR: Syntax Error _NG_NONE:
350 * line was empty or a comment _NG_GROUP: line had a netgroup definition,
351 * returned in ng _NG_NAME: line had a netgroup name, returned in name
353 * Public since used by netgroup_mkdb
356 _ng_parse(char **p
, char **name
, struct netgroup
**ng
)
359 _DIAGASSERT(p
!= NULL
);
360 _DIAGASSERT(*p
!= NULL
);
361 _DIAGASSERT(name
!= NULL
);
362 _DIAGASSERT(ng
!= NULL
);
369 while (**p
&& _NG_ISSPACE(**p
))
374 if ((*ng
= getnetgroup(p
)) == NULL
)
381 for (np
= *p
; **p
&& !_NG_ISSPACE(**p
); (*p
)++)
388 (void)memcpy(*name
, np
, i
);
389 (*name
)[i
- 1] = '\0';
399 * addgroup(): Recursively add all the members of the netgroup to this group.
400 * returns 0 upon failure, nonzero upon success.
401 * grp is not a valid pointer after return (either free(3)ed or allocated
402 * to a stringlist). in either case, it shouldn't be used again.
405 addgroup(StringList
*sl
, char *grp
)
411 _DIAGASSERT(sl
!= NULL
);
412 _DIAGASSERT(grp
!= NULL
);
415 (void)fprintf(stderr
, "addgroup(%s)\n", grp
);
417 /* check for cycles */
418 if (sl_find(sl
, grp
) != NULL
) {
423 if (sl_add(sl
, grp
) == -1) {
428 /* Lookup this netgroup */
430 if (!lookup(grp
, &line
, _NG_KEYBYNAME
)) {
439 switch (_ng_parse(&p
, &name
, &ng
)) {
441 /* Done with the line */
447 /* add to the list */
448 ng
->ng_next
= _nglist
;
454 if (!addgroup(sl
, name
))
469 * in_check(): Compare the spec with the netgroup
472 in_check(const char *host
, const char *user
, const char *domain
,
476 /* host may be NULL */
477 /* user may be NULL */
478 /* domain may be NULL */
479 _DIAGASSERT(ng
!= NULL
);
481 if ((host
!= NULL
) && (ng
->ng_host
!= NULL
)
482 && strcmp(ng
->ng_host
, host
) != 0)
485 if ((user
!= NULL
) && (ng
->ng_user
!= NULL
)
486 && strcmp(ng
->ng_user
, user
) != 0)
489 if ((domain
!= NULL
) && (ng
->ng_domain
!= NULL
)
490 && strcmp(ng
->ng_domain
, domain
) != 0)
498 * in_find(): Find a match for the host, user, domain spec.
499 * grp is not a valid pointer after return (either free(3)ed or allocated
500 * to a stringlist). in either case, it shouldn't be used again.
503 in_find(StringList
*sl
, char *grp
, const char *host
, const char *user
,
511 _DIAGASSERT(sl
!= NULL
);
512 _DIAGASSERT(grp
!= NULL
);
513 /* host may be NULL */
514 /* user may be NULL */
515 /* domain may be NULL */
518 (void)fprintf(stderr
, "in_find(%s)\n", grp
);
520 /* check for cycles */
521 if (sl_find(sl
, grp
) != NULL
) {
526 if (sl_add(sl
, grp
) == -1) {
531 /* Lookup this netgroup */
533 if (!lookup(grp
, &line
, _NG_KEYBYNAME
)) {
542 switch (_ng_parse(&p
, &name
, &ng
)) {
544 /* Done with the line */
550 i
= in_check(host
, user
, domain
, ng
);
551 if (ng
->ng_host
!= NULL
)
553 if (ng
->ng_user
!= NULL
)
555 if (ng
->ng_domain
!= NULL
)
566 if (in_find(sl
, name
, host
, user
, domain
)) {
583 * _ng_makekey(): Make a key from the two names given. The key is of the form
584 * <name1>.<name2> Names strings are replaced with * if they are empty;
585 * Returns NULL if there's a problem.
588 _ng_makekey(const char *s1
, const char *s2
, size_t len
)
597 (void)snprintf(buf
, len
, "%s.%s", _NG_STAR(s1
), _NG_STAR(s2
));
602 _ng_print(char *buf
, size_t len
, const struct netgroup
*ng
)
604 _DIAGASSERT(buf
!= NULL
);
605 _DIAGASSERT(ng
!= NULL
);
607 (void)snprintf(buf
, len
, "(%s,%s,%s)", _NG_EMPTY(ng
->ng_host
),
608 _NG_EMPTY(ng
->ng_user
), _NG_EMPTY(ng
->ng_domain
));
613 * in_lookup1(): Fast lookup for a key in the appropriate map
616 in_lookup1(const char *key
, const char *domain
, int map
)
623 /* key may be NULL */
624 /* domain may be NULL */
626 len
= (key
? strlen(key
) : 1) + (domain
? strlen(domain
) : 1) + 2;
627 ptr
= _ng_makekey(key
, domain
, len
);
630 res
= lookup(ptr
, &line
, map
);
632 return res
? line
: NULL
;
637 * in_lookup(): Fast lookup for a key in the appropriate map
640 in_lookup(const char *group
, const char *key
, const char *domain
, int map
)
645 _DIAGASSERT(group
!= NULL
);
646 /* key may be NULL */
647 /* domain may be NULL */
649 if (domain
!= NULL
) {
650 /* Domain specified; look in "group.domain" and "*.domain" */
651 if ((line
= in_lookup1(key
, domain
, map
)) == NULL
)
652 line
= in_lookup1(NULL
, domain
, map
);
658 * domain not specified or domain lookup failed; look in
659 * "group.*" and "*.*"
661 if (((line
= in_lookup1(key
, NULL
, map
)) == NULL
) &&
662 ((line
= in_lookup1(NULL
, NULL
, map
)) == NULL
))
668 for (ptr
= line
; (ptr
= strstr(ptr
, group
)) != NULL
;)
669 /* Make sure we did not find a substring */
670 if ((ptr
!= line
&& ptr
[-1] != ',') ||
671 (ptr
[len
] != '\0' && strchr("\n\t ,", ptr
[len
]) == NULL
))
684 _local_endnetgrent(void *rv
, void *cb_data
, va_list ap
)
686 for (_nglist
= _nghead
; _nglist
!= NULL
; _nglist
= _nghead
) {
687 _nghead
= _nglist
->ng_next
;
688 if (_nglist
->ng_host
!= NULL
)
689 free(_nglist
->ng_host
);
690 if (_nglist
->ng_user
!= NULL
)
691 free(_nglist
->ng_user
);
692 if (_nglist
->ng_domain
!= NULL
)
693 free(_nglist
->ng_domain
);
698 (void)(*_ng_db
->close
)(_ng_db
);
707 _local_setnetgrent(void *rv
, void *cb_data
, va_list ap
)
709 const char *ng
= va_arg(ap
, const char *);
713 _DIAGASSERT(ng
!= NULL
);
719 /* Cleanup any previous storage */
724 _ng_db
= dbopen(_PATH_NETGROUP_DB
, O_RDONLY
, 0, DB_HASH
, NULL
);
726 ng_copy
= strdup(ng
);
728 addgroup(sl
, ng_copy
);
737 _local_getnetgrent(void *rv
, void *cb_data
, va_list ap
)
739 int *retval
= va_arg(ap
, int *);
740 const char **host
= va_arg(ap
, const char **);
741 const char **user
= va_arg(ap
, const char **);
742 const char **domain
= va_arg(ap
, const char **);
744 _DIAGASSERT(host
!= NULL
);
745 _DIAGASSERT(user
!= NULL
);
746 _DIAGASSERT(domain
!= NULL
);
753 *host
= _nglist
->ng_host
;
754 *user
= _nglist
->ng_user
;
755 *domain
= _nglist
->ng_domain
;
757 _nglist
= _nglist
->ng_next
;
766 _local_innetgr(void *rv
, void *cb_data
, va_list ap
)
768 int *retval
= va_arg(ap
, int *);
769 const char *grp
= va_arg(ap
, const char *);
770 const char *host
= va_arg(ap
, const char *);
771 const char *user
= va_arg(ap
, const char *);
772 const char *domain
= va_arg(ap
, const char *);
778 _DIAGASSERT(grp
!= NULL
);
779 /* host may be NULL */
780 /* user may be NULL */
781 /* domain may be NULL */
784 _ng_db
= dbopen(_PATH_NETGROUP_DB
, O_RDONLY
, 0, DB_HASH
, NULL
);
786 /* Try the fast lookup first */
787 if (host
!= NULL
&& user
== NULL
) {
788 if (in_lookup(grp
, host
, domain
, _NG_KEYBYHOST
)) {
792 } else if (host
== NULL
&& user
!= NULL
) {
793 if (in_lookup(grp
, user
, domain
, _NG_KEYBYUSER
)) {
798 /* If a domainname is given, we would have found a match */
799 if (domain
!= NULL
) {
804 /* Too bad need the slow recursive way */
810 if ((grcpy
= strdup(grp
)) == NULL
) {
815 found
= in_find(sl
, grcpy
, host
, user
, domain
);
826 _nis_endnetgrent(void *rv
, void *cb_data
, va_list ap
)
828 return _local_endnetgrent(rv
, cb_data
, ap
);
833 _nis_setnetgrent(void *rv
, void *cb_data
, va_list ap
)
835 return _local_setnetgrent(rv
, cb_data
, ap
);
840 _nis_getnetgrent(void *rv
, void *cb_data
, va_list ap
)
842 return _local_getnetgrent(rv
, cb_data
, ap
);
847 _nis_innetgr(void *rv
, void *cb_data
, va_list ap
)
849 return _local_innetgr(rv
, cb_data
, ap
);
859 static const ns_dtab dtab
[] = {
860 NS_FILES_CB(_local_endnetgrent
, NULL
)
861 NS_NIS_CB(_nis_endnetgrent
, NULL
)
865 (void) nsdispatch(NULL
, dtab
, NSDB_NETGROUP
, "endnetgrent",
870 _local_endnetgrentv(int *rv
, void *cbdata
, ...)
874 va_start(ap
, cbdata
);
875 e
= _local_endnetgrent(rv
, cbdata
, ap
);
883 (void)_local_endnetgrentv(NULL
, NULL
, NULL
);
889 setnetgrent(const char *ng
)
891 static const ns_dtab dtab
[] = {
892 NS_FILES_CB(_local_setnetgrent
, NULL
)
893 NS_NIS_CB(_nis_setnetgrent
, NULL
)
897 (void) nsdispatch(NULL
, dtab
, NSDB_NETGROUP
, "setnetgrent",
902 _local_setnetgrentv(int *rv
, void *cbdata
, ...)
906 va_start(ap
, cbdata
);
907 e
= _local_setnetgrent(rv
, cbdata
, ap
);
913 setnetgrent(const char *ng
)
915 (void) _local_setnetgrentv(NULL
, NULL
,ng
);
922 getnetgrent(const char **host
, const char **user
, const char **domain
)
925 static const ns_dtab dtab
[] = {
926 NS_FILES_CB(_local_getnetgrent
, NULL
)
927 NS_NIS_CB(_nis_getnetgrent
, NULL
)
931 r
= nsdispatch(NULL
, dtab
, NSDB_NETGROUP
, "getnetgrent",
932 __nsdefaultnis
, &retval
, host
, user
, domain
);
934 return (r
== NS_SUCCESS
) ? retval
: 0;
938 _local_getnetgrentv(int *rv
, void *cbdata
, ...)
942 va_start(ap
, cbdata
);
943 e
= _local_getnetgrent(rv
, cbdata
, ap
);
949 getnetgrent(const char **host
, const char **user
, const char **domain
)
951 return _local_getnetgrentv(NULL
, NULL
, host
, user
, domain
) == NS_SUCCESS
;
957 innetgr(const char *grp
, const char *host
, const char *user
,
961 static const ns_dtab dtab
[] = {
962 NS_FILES_CB(_local_innetgr
, NULL
)
963 NS_NIS_CB(_nis_innetgr
, NULL
)
967 r
= nsdispatch(NULL
, dtab
, NSDB_NETGROUP
, "innetgr",
968 __nsdefaultnis
, &retval
, grp
, host
, user
, domain
);
970 return (r
== NS_SUCCESS
) ? retval
: 0;
974 _local_innetgrv(int *rv
, void *cbdata
, ...)
978 va_start(ap
, cbdata
);
979 e
= _local_innetgr(rv
, cbdata
, ap
);
985 innetgr(const char *grp
, const char *host
, const char *user
,
988 return _local_innetgrv(NULL
, NULL
, grp
, host
, user
, domain
) == NS_SUCCESS
;