1 /* $NetBSD: getnetgrent.c,v 1.40 2008/04/05 08:01:54 rtr 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.40 2008/04/05 08:01:54 rtr 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
*
150 _DIAGASSERT(pp
!= NULL
);
151 _DIAGASSERT(*pp
!= NULL
);
153 ng
= malloc(sizeof(struct netgroup
));
157 (*pp
)++; /* skip '(' */
158 if (!getstring(pp
, ',', &ng
->ng_host
))
161 if (!getstring(pp
, ',', &ng
->ng_user
))
164 if (!getstring(pp
, ')', &ng
->ng_domain
))
170 (void) fprintf(stderr
, "netgroup %s\n",
171 _ng_print(buf
, sizeof(buf
), ng
));
188 _ng_cycle(const char *grp
, const StringList
*sl
)
191 warnx("netgroup: Cycle in group `%s'", grp
);
192 (void)fprintf(stderr
, "groups: ");
193 for (i
= 0; i
< sl
->sl_cur
; i
++)
194 (void)fprintf(stderr
, "%s ", sl
->sl_str
[i
]);
195 (void)fprintf(stderr
, "\n");
198 static int _local_lookup(void *, void *, va_list);
202 _local_lookup(void *rv
, void *cb_data
, va_list ap
)
204 char *name
= va_arg(ap
, char *);
205 char **line
= va_arg(ap
, char **);
206 int bywhat
= va_arg(ap
, int);
216 len
= strlen(name
) + 2;
222 (void)memcpy(&ks
[1], name
, len
- 1);
224 key
.data
= (u_char
*)ks
;
227 r
= (*_ng_db
->get
)(_ng_db
, &key
, &data
, 0);
235 /* XXX: call endnetgrent() here ? */
239 *line
= strdup(data
.data
);
246 static int _nis_lookup(void *, void *, va_list);
250 _nis_lookup(void *rv
, void *cb_data
, va_list ap
)
252 char *name
= va_arg(ap
, char *);
253 char **line
= va_arg(ap
, char **);
254 int bywhat
= va_arg(ap
, int);
256 static char *__ypdomain
;
258 const char *map
= NULL
;
260 if(__ypdomain
== NULL
) {
261 switch (yp_get_default_domain(&__ypdomain
)) {
277 map
= "netgroup.byuser";
281 map
= "netgroup.byhost";
289 switch (yp_match(__ypdomain
, map
, name
, (int)strlen(name
), line
, &i
)) {
307 * lookup(): Find the given key in the database or yp, and return its value
308 * in *line; returns 1 if key was found, 0 otherwise
311 lookup(char *name
, char **line
, int bywhat
)
314 static const ns_dtab dtab
[] = {
315 NS_FILES_CB(_local_lookup
, NULL
)
316 NS_NIS_CB(_nis_lookup
, NULL
)
320 _DIAGASSERT(name
!= NULL
);
321 _DIAGASSERT(line
!= NULL
);
323 r
= nsdispatch(NULL
, dtab
, NSDB_NETGROUP
, "lookup", default_files_nis
,
325 return (r
== NS_SUCCESS
) ? 1 : 0;
329 _local_lookupv(int *rv
, void *cbdata
, ...)
333 va_start(ap
, cbdata
);
334 e
= _local_lookup(rv
, cbdata
, ap
);
340 lookup(name
, line
, bywhat
)
345 return _local_lookupv(NULL
, NULL
, name
, line
, bywhat
) == NS_SUCCESS
;
350 * _ng_parse(): Parse a line and return: _NG_ERROR: Syntax Error _NG_NONE:
351 * line was empty or a comment _NG_GROUP: line had a netgroup definition,
352 * returned in ng _NG_NAME: line had a netgroup name, returned in name
354 * Public since used by netgroup_mkdb
357 _ng_parse(char **p
, char **name
, struct netgroup
**ng
)
360 _DIAGASSERT(p
!= NULL
);
361 _DIAGASSERT(*p
!= NULL
);
362 _DIAGASSERT(name
!= NULL
);
363 _DIAGASSERT(ng
!= NULL
);
370 while (**p
&& _NG_ISSPACE(**p
))
375 if ((*ng
= getnetgroup(p
)) == NULL
)
382 for (np
= *p
; **p
&& !_NG_ISSPACE(**p
); (*p
)++)
389 (void)memcpy(*name
, np
, i
);
390 (*name
)[i
- 1] = '\0';
400 * addgroup(): Recursively add all the members of the netgroup to this group.
401 * returns 0 upon failure, nonzero upon success.
402 * grp is not a valid pointer after return (either free(3)ed or allocated
403 * to a stringlist). in either case, it shouldn't be used again.
406 addgroup(StringList
*sl
, char *grp
)
412 _DIAGASSERT(sl
!= NULL
);
413 _DIAGASSERT(grp
!= NULL
);
416 (void)fprintf(stderr
, "addgroup(%s)\n", grp
);
418 /* check for cycles */
419 if (sl_find(sl
, grp
) != NULL
) {
424 if (sl_add(sl
, grp
) == -1) {
429 /* Lookup this netgroup */
431 if (!lookup(grp
, &line
, _NG_KEYBYNAME
)) {
440 switch (_ng_parse(&p
, &name
, &ng
)) {
442 /* Done with the line */
448 /* add to the list */
449 ng
->ng_next
= _nglist
;
455 if (!addgroup(sl
, name
))
470 * in_check(): Compare the spec with the netgroup
473 in_check(const char *host
, const char *user
, const char *domain
,
477 /* host may be NULL */
478 /* user may be NULL */
479 /* domain may be NULL */
480 _DIAGASSERT(ng
!= NULL
);
482 if ((host
!= NULL
) && (ng
->ng_host
!= NULL
)
483 && strcmp(ng
->ng_host
, host
) != 0)
486 if ((user
!= NULL
) && (ng
->ng_user
!= NULL
)
487 && strcmp(ng
->ng_user
, user
) != 0)
490 if ((domain
!= NULL
) && (ng
->ng_domain
!= NULL
)
491 && strcmp(ng
->ng_domain
, domain
) != 0)
499 * in_find(): Find a match for the host, user, domain spec.
500 * grp is not a valid pointer after return (either free(3)ed or allocated
501 * to a stringlist). in either case, it shouldn't be used again.
504 in_find(StringList
*sl
, char *grp
, const char *host
, const char *user
,
512 _DIAGASSERT(sl
!= NULL
);
513 _DIAGASSERT(grp
!= NULL
);
514 /* host may be NULL */
515 /* user may be NULL */
516 /* domain may be NULL */
519 (void)fprintf(stderr
, "in_find(%s)\n", grp
);
521 /* check for cycles */
522 if (sl_find(sl
, grp
) != NULL
) {
527 if (sl_add(sl
, grp
) == -1) {
532 /* Lookup this netgroup */
534 if (!lookup(grp
, &line
, _NG_KEYBYNAME
)) {
543 switch (_ng_parse(&p
, &name
, &ng
)) {
545 /* Done with the line */
551 i
= in_check(host
, user
, domain
, ng
);
552 if (ng
->ng_host
!= NULL
)
554 if (ng
->ng_user
!= NULL
)
556 if (ng
->ng_domain
!= NULL
)
567 if (in_find(sl
, name
, host
, user
, domain
)) {
584 * _ng_makekey(): Make a key from the two names given. The key is of the form
585 * <name1>.<name2> Names strings are replaced with * if they are empty;
586 * Returns NULL if there's a problem.
589 _ng_makekey(const char *s1
, const char *s2
, size_t len
)
598 (void)snprintf(buf
, len
, "%s.%s", _NG_STAR(s1
), _NG_STAR(s2
));
603 _ng_print(char *buf
, size_t len
, const struct netgroup
*ng
)
605 _DIAGASSERT(buf
!= NULL
);
606 _DIAGASSERT(ng
!= NULL
);
608 (void)snprintf(buf
, len
, "(%s,%s,%s)", _NG_EMPTY(ng
->ng_host
),
609 _NG_EMPTY(ng
->ng_user
), _NG_EMPTY(ng
->ng_domain
));
614 * in_lookup1(): Fast lookup for a key in the appropriate map
617 in_lookup1(const char *key
, const char *domain
, int map
)
624 /* key may be NULL */
625 /* domain may be NULL */
627 len
= (key
? strlen(key
) : 1) + (domain
? strlen(domain
) : 1) + 2;
628 ptr
= _ng_makekey(key
, domain
, len
);
631 res
= lookup(ptr
, &line
, map
);
633 return res
? line
: NULL
;
638 * in_lookup(): Fast lookup for a key in the appropriate map
641 in_lookup(const char *group
, const char *key
, const char *domain
, int map
)
646 _DIAGASSERT(group
!= NULL
);
647 /* key may be NULL */
648 /* domain may be NULL */
650 if (domain
!= NULL
) {
651 /* Domain specified; look in "group.domain" and "*.domain" */
652 if ((line
= in_lookup1(key
, domain
, map
)) == NULL
)
653 line
= in_lookup1(NULL
, domain
, map
);
659 * domain not specified or domain lookup failed; look in
660 * "group.*" and "*.*"
662 if (((line
= in_lookup1(key
, NULL
, map
)) == NULL
) &&
663 ((line
= in_lookup1(NULL
, NULL
, map
)) == NULL
))
669 for (ptr
= line
; (ptr
= strstr(ptr
, group
)) != NULL
;)
670 /* Make sure we did not find a substring */
671 if ((ptr
!= line
&& ptr
[-1] != ',') ||
672 (ptr
[len
] != '\0' && strchr("\n\t ,", ptr
[len
]) == NULL
))
685 _local_endnetgrent(void *rv
, void *cb_data
, va_list ap
)
687 for (_nglist
= _nghead
; _nglist
!= NULL
; _nglist
= _nghead
) {
688 _nghead
= _nglist
->ng_next
;
689 if (_nglist
->ng_host
!= NULL
)
690 free(_nglist
->ng_host
);
691 if (_nglist
->ng_user
!= NULL
)
692 free(_nglist
->ng_user
);
693 if (_nglist
->ng_domain
!= NULL
)
694 free(_nglist
->ng_domain
);
699 (void)(*_ng_db
->close
)(_ng_db
);
708 _local_setnetgrent(void *rv
, void *cb_data
, va_list ap
)
710 const char *ng
= va_arg(ap
, const char *);
714 _DIAGASSERT(ng
!= NULL
);
720 /* Cleanup any previous storage */
725 _ng_db
= dbopen(_PATH_NETGROUP_DB
, O_RDONLY
, 0, DB_HASH
, NULL
);
727 ng_copy
= strdup(ng
);
729 addgroup(sl
, ng_copy
);
738 _local_getnetgrent(void *rv
, void *cb_data
, va_list ap
)
740 int *retval
= va_arg(ap
, int *);
741 const char **host
= va_arg(ap
, const char **);
742 const char **user
= va_arg(ap
, const char **);
743 const char **domain
= va_arg(ap
, const char **);
745 _DIAGASSERT(host
!= NULL
);
746 _DIAGASSERT(user
!= NULL
);
747 _DIAGASSERT(domain
!= NULL
);
754 *host
= _nglist
->ng_host
;
755 *user
= _nglist
->ng_user
;
756 *domain
= _nglist
->ng_domain
;
758 _nglist
= _nglist
->ng_next
;
767 _local_innetgr(void *rv
, void *cb_data
, va_list ap
)
769 int *retval
= va_arg(ap
, int *);
770 const char *grp
= va_arg(ap
, const char *);
771 const char *host
= va_arg(ap
, const char *);
772 const char *user
= va_arg(ap
, const char *);
773 const char *domain
= va_arg(ap
, const char *);
779 _DIAGASSERT(grp
!= NULL
);
780 /* host may be NULL */
781 /* user may be NULL */
782 /* domain may be NULL */
785 _ng_db
= dbopen(_PATH_NETGROUP_DB
, O_RDONLY
, 0, DB_HASH
, NULL
);
787 /* Try the fast lookup first */
788 if (host
!= NULL
&& user
== NULL
) {
789 if (in_lookup(grp
, host
, domain
, _NG_KEYBYHOST
)) {
793 } else if (host
== NULL
&& user
!= NULL
) {
794 if (in_lookup(grp
, user
, domain
, _NG_KEYBYUSER
)) {
799 /* If a domainname is given, we would have found a match */
800 if (domain
!= NULL
) {
805 /* Too bad need the slow recursive way */
811 if ((grcpy
= strdup(grp
)) == NULL
) {
816 found
= in_find(sl
, grcpy
, host
, user
, domain
);
827 _nis_endnetgrent(void *rv
, void *cb_data
, va_list ap
)
829 return _local_endnetgrent(rv
, cb_data
, ap
);
834 _nis_setnetgrent(void *rv
, void *cb_data
, va_list ap
)
836 return _local_setnetgrent(rv
, cb_data
, ap
);
841 _nis_getnetgrent(void *rv
, void *cb_data
, va_list ap
)
843 return _local_getnetgrent(rv
, cb_data
, ap
);
848 _nis_innetgr(void *rv
, void *cb_data
, va_list ap
)
850 return _local_innetgr(rv
, cb_data
, ap
);
860 static const ns_dtab dtab
[] = {
861 NS_FILES_CB(_local_endnetgrent
, NULL
)
862 NS_NIS_CB(_nis_endnetgrent
, NULL
)
866 (void) nsdispatch(NULL
, dtab
, NSDB_NETGROUP
, "endnetgrent",
871 _local_endnetgrentv(int *rv
, void *cbdata
, ...)
875 va_start(ap
, cbdata
);
876 e
= _local_endnetgrent(rv
, cbdata
, ap
);
884 (void)_local_endnetgrentv(NULL
, NULL
, NULL
);
890 setnetgrent(const char *ng
)
892 static const ns_dtab dtab
[] = {
893 NS_FILES_CB(_local_setnetgrent
, NULL
)
894 NS_NIS_CB(_nis_setnetgrent
, NULL
)
898 (void) nsdispatch(NULL
, dtab
, NSDB_NETGROUP
, "setnetgrent",
903 _local_setnetgrentv(int *rv
, void *cbdata
, ...)
907 va_start(ap
, cbdata
);
908 e
= _local_setnetgrent(rv
, cbdata
, ap
);
914 setnetgrent(const char *ng
)
916 (void) _local_setnetgrentv(NULL
, NULL
,ng
);
923 getnetgrent(const char **host
, const char **user
, const char **domain
)
926 static const ns_dtab dtab
[] = {
927 NS_FILES_CB(_local_getnetgrent
, NULL
)
928 NS_NIS_CB(_nis_getnetgrent
, NULL
)
932 r
= nsdispatch(NULL
, dtab
, NSDB_NETGROUP
, "getnetgrent",
933 __nsdefaultnis
, &retval
, host
, user
, domain
);
935 return (r
== NS_SUCCESS
) ? retval
: 0;
939 _local_getnetgrentv(int *rv
, void *cbdata
, ...)
943 va_start(ap
, cbdata
);
944 e
= _local_getnetgrent(rv
, cbdata
, ap
);
950 getnetgrent(const char **host
, const char **user
, const char **domain
)
952 return _local_getnetgrentv(NULL
, NULL
, host
, user
, domain
) == NS_SUCCESS
;
958 innetgr(const char *grp
, const char *host
, const char *user
,
962 static const ns_dtab dtab
[] = {
963 NS_FILES_CB(_local_innetgr
, NULL
)
964 NS_NIS_CB(_nis_innetgr
, NULL
)
968 r
= nsdispatch(NULL
, dtab
, NSDB_NETGROUP
, "innetgr",
969 __nsdefaultnis
, &retval
, grp
, host
, user
, domain
);
971 return (r
== NS_SUCCESS
) ? retval
: 0;
975 _local_innetgrv(int *rv
, void *cbdata
, ...)
979 va_start(ap
, cbdata
);
980 e
= _local_innetgr(rv
, cbdata
, ap
);
986 innetgr(const char *grp
, const char *host
, const char *user
,
989 return _local_innetgrv(NULL
, NULL
, grp
, host
, user
, domain
) == NS_SUCCESS
;