/*
* Copyright (c) 1994 Christos Zoulas
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* getstring(): Get a string delimited by the character, skipping leading and
* trailing blanks and advancing the pointer
*/
static int
getstring(char **pp, int del, char __aconst **str)
{
size_t len;
char *sp, *ep, *dp;
static char *__ypdomain;
int i;
const char *map = NULL;
if(__ypdomain == NULL) {
switch (yp_get_default_domain(&__ypdomain)) {
case 0:
break;
case YPERR_RESRC:
return NS_TRYAGAIN;
default:
return NS_UNAVAIL;
}
}
switch (bywhat) {
case _NG_KEYBYNAME:
map = "netgroup";
break;
case _NG_KEYBYUSER:
map = "netgroup.byuser";
break;
case _NG_KEYBYHOST:
map = "netgroup.byhost";
break;
default:
abort();
}
*line = NULL;
switch (yp_match(__ypdomain, map, name, (int)strlen(name), line, &i)) {
case 0:
return NS_SUCCESS;
case YPERR_KEY:
if (*line)
free(*line);
return NS_NOTFOUND;
default:
if (*line)
free(*line);
return NS_UNAVAIL;
}
/* NOTREACHED */
}
#endif
#ifdef NSSRC_FILES
/*
* lookup(): Find the given key in the database or yp, and return its value
* in *line; returns 1 if key was found, 0 otherwise
*/
static int
lookup(char *name, char **line, int bywhat)
{
int r;
static const ns_dtab dtab[] = {
NS_FILES_CB(_local_lookup, NULL)
NS_NIS_CB(_nis_lookup, NULL)
NS_NULL_CB
};
/*
* _ng_parse(): Parse a line and return: _NG_ERROR: Syntax Error _NG_NONE:
* line was empty or a comment _NG_GROUP: line had a netgroup definition,
* returned in ng _NG_NAME: line had a netgroup name, returned in name
*
* Public since used by netgroup_mkdb
*/
int
_ng_parse(char **p, char **name, struct netgroup **ng)
{
/*
* addgroup(): Recursively add all the members of the netgroup to this group.
* returns 0 upon failure, nonzero upon success.
* grp is not a valid pointer after return (either free(3)ed or allocated
* to a stringlist). in either case, it shouldn't be used again.
*/
static int
addgroup(StringList *sl, char *grp)
{
char *line, *p;
struct netgroup *ng;
char *name;
/*
* in_find(): Find a match for the host, user, domain spec.
* grp is not a valid pointer after return (either free(3)ed or allocated
* to a stringlist). in either case, it shouldn't be used again.
*/
static int
in_find(StringList *sl, char *grp, const char *host, const char *user,
const char *domain)
{
char *line, *p;
int i;
struct netgroup *ng;
char *name;
_DIAGASSERT(sl != NULL);
_DIAGASSERT(grp != NULL);
/* host may be NULL */
/* user may be NULL */
/* domain may be NULL */
/* Lookup this netgroup */
line = NULL;
if (!lookup(grp, &line, _NG_KEYBYNAME)) {
if (line)
free(line);
return 0;
}
p = line;
for (;;) {
switch (_ng_parse(&p, &name, &ng)) {
case _NG_NONE:
/* Done with the line */
free(line);
return 0;
case _NG_GROUP:
/* new netgroup */
i = in_check(host, user, domain, ng);
if (ng->ng_host != NULL)
free(ng->ng_host);
if (ng->ng_user != NULL)
free(ng->ng_user);
if (ng->ng_domain != NULL)
free(ng->ng_domain);
free(ng);
if (i) {
free(line);
return 1;
}
break;
case _NG_NAME:
/* netgroup name */
if (in_find(sl, name, host, user, domain)) {
free(line);
return 1;
}
break;
case _NG_ERROR:
free(line);
return 0;
default:
abort();
}
}
}
/*
* _ng_makekey(): Make a key from the two names given. The key is of the form
* <name1>.<name2> Names strings are replaced with * if they are empty;
* Returns NULL if there's a problem.
*/
char *
_ng_makekey(const char *s1, const char *s2, size_t len)
{
char *buf;
/*
* in_lookup1(): Fast lookup for a key in the appropriate map
*/
static char *
in_lookup1(const char *key, const char *domain, int map)
{
char *line;
size_t len;
char *ptr;
int res;
/* key may be NULL */
/* domain may be NULL */
len = (key ? strlen(key) : 1) + (domain ? strlen(domain) : 1) + 2;
ptr = _ng_makekey(key, domain, len);
if (ptr == NULL)
return NULL;
res = lookup(ptr, &line, map);
free(ptr);
return res ? line : NULL;
}
/*
* in_lookup(): Fast lookup for a key in the appropriate map
*/
static int
in_lookup(const char *group, const char *key, const char *domain, int map)
{
size_t len;
char *ptr, *line;
_DIAGASSERT(group != NULL);
/* key may be NULL */
/* domain may be NULL */
if (domain != NULL) {
/* Domain specified; look in "group.domain" and "*.domain" */
if ((line = in_lookup1(key, domain, map)) == NULL)
line = in_lookup1(NULL, domain, map);
} else
line = NULL;
if (line == NULL) {
/*
* domain not specified or domain lookup failed; look in
* "group.*" and "*.*"
*/
if (((line = in_lookup1(key, NULL, map)) == NULL) &&
((line = in_lookup1(NULL, NULL, map)) == NULL))
return 0;
}
len = strlen(group);
for (ptr = line; (ptr = strstr(ptr, group)) != NULL;)
/* Make sure we did not find a substring */
if ((ptr != line && ptr[-1] != ',') ||
(ptr[len] != '\0' && strchr("\n\t ,", ptr[len]) == NULL))
ptr++;
else {
free(line);
return 1;
}
free(line);
return 0;
}
/*ARGSUSED*/
static int
_local_endnetgrent(void *rv, void *cb_data, va_list ap)
{
for (_nglist = _nghead; _nglist != NULL; _nglist = _nghead) {
_nghead = _nglist->ng_next;
if (_nglist->ng_host != NULL)
free(_nglist->ng_host);
if (_nglist->ng_user != NULL)
free(_nglist->ng_user);
if (_nglist->ng_domain != NULL)
free(_nglist->ng_domain);
free(_nglist);
}
if (_ng_db) {
(void)(*_ng_db->close)(_ng_db);
_ng_db = NULL;
}
/* Try the fast lookup first */
if (host != NULL && user == NULL) {
if (in_lookup(grp, host, domain, _NG_KEYBYHOST)) {
*retval = 1;
return NS_SUCCESS;
}
} else if (host == NULL && user != NULL) {
if (in_lookup(grp, user, domain, _NG_KEYBYUSER)) {
*retval = 1;
return NS_SUCCESS;
}
}
/* If a domainname is given, we would have found a match */
if (domain != NULL) {
*retval = 0;
return NS_SUCCESS;
}
/* Too bad need the slow recursive way */
sl = sl_init();
if (sl == NULL) {
*retval = 0;
return NS_SUCCESS;
}
if ((grcpy = strdup(grp)) == NULL) {
sl_free(sl, 1);
*retval = 0;
return NS_SUCCESS;
}
found = in_find(sl, grcpy, host, user, domain);
sl_free(sl, 1);