158f0484fSRodney W. Grimes /* 258f0484fSRodney W. Grimes * Copyright (c) 1992, 1993 358f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 458f0484fSRodney W. Grimes * 558f0484fSRodney W. Grimes * This code is derived from software contributed to Berkeley by 658f0484fSRodney W. Grimes * Rick Macklem at The University of Guelph. 758f0484fSRodney W. Grimes * 858f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 958f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 1058f0484fSRodney W. Grimes * are met: 1158f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1258f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1358f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1458f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1558f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1658f0484fSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 1758f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 1858f0484fSRodney W. Grimes * without specific prior written permission. 1958f0484fSRodney W. Grimes * 2058f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2158f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2258f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2358f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2458f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2558f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2658f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2758f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2858f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2958f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3058f0484fSRodney W. Grimes * SUCH DAMAGE. 3158f0484fSRodney W. Grimes */ 3258f0484fSRodney W. Grimes 3358f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 34adf6ad9eSPeter Wemm static char sccsid[] = "@(#)getnetgrent.c 8.2 (Berkeley) 4/27/95"; 3558f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 3622626efaSDavid E. O'Brien #include <sys/cdefs.h> 3722626efaSDavid E. O'Brien __FBSDID("$FreeBSD$"); 3858f0484fSRodney W. Grimes 39185ec971STim J. Robbins #include <ctype.h> 4058f0484fSRodney W. Grimes #include <stdio.h> 41958f4e36SBill Paul #include <stdlib.h> 4273c9eb2fSDag-Erling Smørgrav #include <string.h> 43958f4e36SBill Paul #include <unistd.h> 44958f4e36SBill Paul 45958f4e36SBill Paul #ifdef YP 461e890b05SBill Paul /* 471e890b05SBill Paul * Notes: 481e890b05SBill Paul * We want to be able to use NIS netgroups properly while retaining 491e890b05SBill Paul * the ability to use a local /etc/netgroup file. Unfortunately, you 501e890b05SBill Paul * can't really do both at the same time - at least, not efficiently. 511e890b05SBill Paul * NetBSD deals with this problem by creating a netgroup database 521e890b05SBill Paul * using Berkeley DB (just like the password database) that allows 531e890b05SBill Paul * for lookups using netgroup, netgroup.byuser or netgroup.byhost 541e890b05SBill Paul * searches. This is a neat idea, but I don't have time to implement 551e890b05SBill Paul * something like that now. (I think ultimately it would be nice 561e890b05SBill Paul * if we DB-fied the group and netgroup stuff all in one shot, but 571e890b05SBill Paul * for now I'm satisfied just to have something that works well 581e890b05SBill Paul * without requiring massive code changes.) 591e890b05SBill Paul * 601e890b05SBill Paul * Therefore, to still permit the use of the local file and maintain 611e890b05SBill Paul * optimum NIS performance, we allow for the following conditions: 621e890b05SBill Paul * 631e890b05SBill Paul * - If /etc/netgroup does not exist and NIS is turned on, we use 641e890b05SBill Paul * NIS netgroups only. 651e890b05SBill Paul * 661e890b05SBill Paul * - If /etc/netgroup exists but is empty, we use NIS netgroups 671e890b05SBill Paul * only. 681e890b05SBill Paul * 691e890b05SBill Paul * - If /etc/netgroup exists and contains _only_ a '+', we use 701e890b05SBill Paul * NIS netgroups only. 711e890b05SBill Paul * 721e890b05SBill Paul * - If /etc/netgroup exists, contains locally defined netgroups 731e890b05SBill Paul * and a '+', we use a mixture of NIS and the local entries. 741e890b05SBill Paul * This method should return the same NIS data as just using 751e890b05SBill Paul * NIS alone, but it will be slower if the NIS netgroup database 761e890b05SBill Paul * is large (innetgr() in particular will suffer since extra 771e890b05SBill Paul * processing has to be done in order to determine memberships 781e890b05SBill Paul * using just the raw netgroup data). 791e890b05SBill Paul * 801e890b05SBill Paul * - If /etc/netgroup exists and contains only locally defined 811e890b05SBill Paul * netgroup entries, we use just those local entries and ignore 821e890b05SBill Paul * NIS (this is the original, pre-NIS behavior). 831e890b05SBill Paul */ 84c17942caSBill Paul 85958f4e36SBill Paul #include <rpc/rpc.h> 86958f4e36SBill Paul #include <rpcsvc/yp_prot.h> 87958f4e36SBill Paul #include <rpcsvc/ypclnt.h> 881e890b05SBill Paul #include <sys/types.h> 891e890b05SBill Paul #include <sys/stat.h> 901e890b05SBill Paul #include <sys/param.h> 911e890b05SBill Paul #include <sys/errno.h> 921e890b05SBill Paul static char *_netgr_yp_domain; 93d454389cSBill Paul int _use_only_yp; 94958f4e36SBill Paul static int _netgr_yp_enabled; 951e890b05SBill Paul static int _yp_innetgr; 96958f4e36SBill Paul #endif 9758f0484fSRodney W. Grimes 981e890b05SBill Paul #ifndef _PATH_NETGROUP 9958f0484fSRodney W. Grimes #define _PATH_NETGROUP "/etc/netgroup" 1001e890b05SBill Paul #endif 10158f0484fSRodney W. Grimes 10258f0484fSRodney W. Grimes /* 10358f0484fSRodney W. Grimes * Static Variables and functions used by setnetgrent(), getnetgrent() and 10458f0484fSRodney W. Grimes * endnetgrent(). 10558f0484fSRodney W. Grimes * There are two linked lists: 10658f0484fSRodney W. Grimes * - linelist is just used by setnetgrent() to parse the net group file via. 10758f0484fSRodney W. Grimes * parse_netgrp() 10858f0484fSRodney W. Grimes * - netgrp is the list of entries for the current netgroup 10958f0484fSRodney W. Grimes */ 11058f0484fSRodney W. Grimes struct linelist { 11158f0484fSRodney W. Grimes struct linelist *l_next; /* Chain ptr. */ 11258f0484fSRodney W. Grimes int l_parsed; /* Flag for cycles */ 11358f0484fSRodney W. Grimes char *l_groupname; /* Name of netgroup */ 11458f0484fSRodney W. Grimes char *l_line; /* Netgroup entrie(s) to be parsed */ 11558f0484fSRodney W. Grimes }; 11658f0484fSRodney W. Grimes 11758f0484fSRodney W. Grimes struct netgrp { 11858f0484fSRodney W. Grimes struct netgrp *ng_next; /* Chain ptr */ 11958f0484fSRodney W. Grimes char *ng_str[3]; /* Field pointers, see below */ 12058f0484fSRodney W. Grimes }; 12158f0484fSRodney W. Grimes #define NG_HOST 0 /* Host name */ 12258f0484fSRodney W. Grimes #define NG_USER 1 /* User name */ 12358f0484fSRodney W. Grimes #define NG_DOM 2 /* and Domain name */ 12458f0484fSRodney W. Grimes 12558f0484fSRodney W. Grimes static struct linelist *linehead = (struct linelist *)0; 12658f0484fSRodney W. Grimes static struct netgrp *nextgrp = (struct netgrp *)0; 12758f0484fSRodney W. Grimes static struct { 12858f0484fSRodney W. Grimes struct netgrp *gr; 12958f0484fSRodney W. Grimes char *grname; 13058f0484fSRodney W. Grimes } grouphead = { 13158f0484fSRodney W. Grimes (struct netgrp *)0, 13258f0484fSRodney W. Grimes (char *)0, 13358f0484fSRodney W. Grimes }; 13458f0484fSRodney W. Grimes static FILE *netf = (FILE *)0; 13576884596SDag-Erling Smørgrav 13676884596SDag-Erling Smørgrav static int parse_netgrp(const char *); 13776884596SDag-Erling Smørgrav static struct linelist *read_for_group(const char *); 13876884596SDag-Erling Smørgrav void setnetgrent(const char *); 13976884596SDag-Erling Smørgrav void endnetgrent(void); 14076884596SDag-Erling Smørgrav int getnetgrent(char **, char **, char **); 14176884596SDag-Erling Smørgrav int innetgr(const char *, const char *, const char *, const char *); 14258f0484fSRodney W. Grimes 14358f0484fSRodney W. Grimes #define LINSIZ 1024 /* Length of netgroup file line */ 14458f0484fSRodney W. Grimes 14558f0484fSRodney W. Grimes /* 14658f0484fSRodney W. Grimes * setnetgrent() 14758f0484fSRodney W. Grimes * Parse the netgroup file looking for the netgroup and build the list 14858f0484fSRodney W. Grimes * of netgrp structures. Let parse_netgrp() and read_for_group() do 14958f0484fSRodney W. Grimes * most of the work. 15058f0484fSRodney W. Grimes */ 15158f0484fSRodney W. Grimes void 15276884596SDag-Erling Smørgrav setnetgrent(const char *group) 15358f0484fSRodney W. Grimes { 1541e890b05SBill Paul #ifdef YP 1551e890b05SBill Paul struct stat _yp_statp; 1561e890b05SBill Paul char _yp_plus; 1571e890b05SBill Paul #endif 1581e890b05SBill Paul 1590ffe27f5SBill Paul /* Sanity check */ 16062a77170SBill Paul 1610ffe27f5SBill Paul if (group == NULL || !strlen(group)) 16262a77170SBill Paul return; 1630ffe27f5SBill Paul 16417ec7b7aSKonstantin Belousov if (grouphead.gr == NULL || strcmp(group, grouphead.grname)) { 16558f0484fSRodney W. Grimes endnetgrent(); 1661e890b05SBill Paul #ifdef YP 167d454389cSBill Paul /* Presumed guilty until proven innocent. */ 168d454389cSBill Paul _use_only_yp = 0; 1691e890b05SBill Paul /* 170cbe78b44SBill Paul * If /etc/netgroup doesn't exist or is empty, 1711e890b05SBill Paul * use NIS exclusively. 1721e890b05SBill Paul */ 1731e890b05SBill Paul if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && 1741e890b05SBill Paul errno == ENOENT) || _yp_statp.st_size == 0) 1751e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1761084b38bSJilles Tjoelker if ((netf = fopen(_PATH_NETGROUP,"re")) != NULL ||_use_only_yp){ 1771e890b05SBill Paul /* 1781e890b05SBill Paul * Icky: grab the first character of the netgroup file 1791e890b05SBill Paul * and turn on NIS if it's a '+'. rewind the stream 1801e890b05SBill Paul * afterwards so we don't goof up read_for_group() later. 1811e890b05SBill Paul */ 1821e890b05SBill Paul if (netf) { 1831e890b05SBill Paul fscanf(netf, "%c", &_yp_plus); 1841e890b05SBill Paul rewind(netf); 1851e890b05SBill Paul if (_yp_plus == '+') 1861e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1871e890b05SBill Paul } 1881e890b05SBill Paul /* 1891e890b05SBill Paul * If we were called specifically for an innetgr() 1901e890b05SBill Paul * lookup and we're in NIS-only mode, short-circuit 1911e890b05SBill Paul * parse_netgroup() and cut directly to the chase. 1921e890b05SBill Paul */ 193d454389cSBill Paul if (_use_only_yp && _yp_innetgr) { 194d454389cSBill Paul /* dohw! */ 195de32dbbdSBill Paul if (netf != NULL) 196d454389cSBill Paul fclose(netf); 1971e890b05SBill Paul return; 198d454389cSBill Paul } 1991e890b05SBill Paul #else 2001084b38bSJilles Tjoelker if ((netf = fopen(_PATH_NETGROUP, "re"))) { 2011e890b05SBill Paul #endif 20258f0484fSRodney W. Grimes if (parse_netgrp(group)) 20358f0484fSRodney W. Grimes endnetgrent(); 20458f0484fSRodney W. Grimes else { 205fed7420cSGuy Helmer grouphead.grname = strdup(group); 20658f0484fSRodney W. Grimes } 2071e890b05SBill Paul if (netf) 20858f0484fSRodney W. Grimes fclose(netf); 20958f0484fSRodney W. Grimes } 21058f0484fSRodney W. Grimes } 21158f0484fSRodney W. Grimes nextgrp = grouphead.gr; 21258f0484fSRodney W. Grimes } 21358f0484fSRodney W. Grimes 21458f0484fSRodney W. Grimes /* 21558f0484fSRodney W. Grimes * Get the next netgroup off the list. 21658f0484fSRodney W. Grimes */ 21758f0484fSRodney W. Grimes int 21876884596SDag-Erling Smørgrav getnetgrent(char **hostp, char **userp, char **domp) 21958f0484fSRodney W. Grimes { 2201e890b05SBill Paul #ifdef YP 2211e890b05SBill Paul _yp_innetgr = 0; 2221e890b05SBill Paul #endif 22358f0484fSRodney W. Grimes 22458f0484fSRodney W. Grimes if (nextgrp) { 22558f0484fSRodney W. Grimes *hostp = nextgrp->ng_str[NG_HOST]; 22658f0484fSRodney W. Grimes *userp = nextgrp->ng_str[NG_USER]; 22758f0484fSRodney W. Grimes *domp = nextgrp->ng_str[NG_DOM]; 22858f0484fSRodney W. Grimes nextgrp = nextgrp->ng_next; 22958f0484fSRodney W. Grimes return (1); 23058f0484fSRodney W. Grimes } 23158f0484fSRodney W. Grimes return (0); 23258f0484fSRodney W. Grimes } 23358f0484fSRodney W. Grimes 23458f0484fSRodney W. Grimes /* 23558f0484fSRodney W. Grimes * endnetgrent() - cleanup 23658f0484fSRodney W. Grimes */ 23758f0484fSRodney W. Grimes void 23876884596SDag-Erling Smørgrav endnetgrent(void) 23958f0484fSRodney W. Grimes { 24022626efaSDavid E. O'Brien struct linelist *lp, *olp; 24122626efaSDavid E. O'Brien struct netgrp *gp, *ogp; 24258f0484fSRodney W. Grimes 24358f0484fSRodney W. Grimes lp = linehead; 24458f0484fSRodney W. Grimes while (lp) { 24558f0484fSRodney W. Grimes olp = lp; 24658f0484fSRodney W. Grimes lp = lp->l_next; 24758f0484fSRodney W. Grimes free(olp->l_groupname); 24858f0484fSRodney W. Grimes free(olp->l_line); 24917ec7b7aSKonstantin Belousov free(olp); 25058f0484fSRodney W. Grimes } 25117ec7b7aSKonstantin Belousov linehead = NULL; 25258f0484fSRodney W. Grimes if (grouphead.grname) { 25358f0484fSRodney W. Grimes free(grouphead.grname); 25417ec7b7aSKonstantin Belousov grouphead.grname = NULL; 25558f0484fSRodney W. Grimes } 25658f0484fSRodney W. Grimes gp = grouphead.gr; 25758f0484fSRodney W. Grimes while (gp) { 25858f0484fSRodney W. Grimes ogp = gp; 25958f0484fSRodney W. Grimes gp = gp->ng_next; 26058f0484fSRodney W. Grimes free(ogp->ng_str[NG_HOST]); 26158f0484fSRodney W. Grimes free(ogp->ng_str[NG_USER]); 26258f0484fSRodney W. Grimes free(ogp->ng_str[NG_DOM]); 26317ec7b7aSKonstantin Belousov free(ogp); 26458f0484fSRodney W. Grimes } 26517ec7b7aSKonstantin Belousov grouphead.gr = NULL; 26617ec7b7aSKonstantin Belousov nextgrp = NULL; 267409495f6SBill Paul #ifdef YP 2688516cd0fSBill Paul _netgr_yp_enabled = 0; 269409495f6SBill Paul #endif 27058f0484fSRodney W. Grimes } 27158f0484fSRodney W. Grimes 2721e890b05SBill Paul #ifdef YP 27376884596SDag-Erling Smørgrav static int 27476884596SDag-Erling Smørgrav _listmatch(const char *list, const char *group, int len) 2751e890b05SBill Paul { 27676884596SDag-Erling Smørgrav const char *ptr = list; 27776884596SDag-Erling Smørgrav const char *cptr; 278d9cc92f5SBill Paul int glen = strlen(group); 2791e890b05SBill Paul 280d9cc92f5SBill Paul /* skip possible leading whitespace */ 28149435560SAndrey A. Chernov while (isspace((unsigned char)*ptr)) 282d9cc92f5SBill Paul ptr++; 283cbe78b44SBill Paul 284d9cc92f5SBill Paul while (ptr < list + len) { 285d9cc92f5SBill Paul cptr = ptr; 28649435560SAndrey A. Chernov while(*ptr != ',' && *ptr != '\0' && !isspace((unsigned char)*ptr)) 287d9cc92f5SBill Paul ptr++; 288f48bc662SSteve Price if (strncmp(cptr, group, glen) == 0 && glen == (ptr - cptr)) 2891e890b05SBill Paul return (1); 29049435560SAndrey A. Chernov while (*ptr == ',' || isspace((unsigned char)*ptr)) 291d9cc92f5SBill Paul ptr++; 292dfe8e51cSBill Paul } 293cbe78b44SBill Paul 2941e890b05SBill Paul return (0); 2951e890b05SBill Paul } 2961e890b05SBill Paul 29776884596SDag-Erling Smørgrav static int 298c5a096e0SJonathan Chen _revnetgr_lookup(char* lookupdom, char* map, const char* str, 299c5a096e0SJonathan Chen const char* dom, const char* group) 3001e890b05SBill Paul { 301c5a096e0SJonathan Chen int y, rv, rot; 302c5a096e0SJonathan Chen char key[MAXHOSTNAMELEN]; 303c5a096e0SJonathan Chen char *result; 304c5a096e0SJonathan Chen int resultlen; 305c5a096e0SJonathan Chen 306c5a096e0SJonathan Chen for (rot = 0; ; rot++) { 307c5a096e0SJonathan Chen switch (rot) { 3083d1d73c2SGuy Helmer case 0: 309299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "%s.%s", str, 310c5a096e0SJonathan Chen dom ? dom : lookupdom); 3111e890b05SBill Paul break; 3123d1d73c2SGuy Helmer case 1: 313299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "%s.*", str); 314299bafaeSGuy Helmer break; 3153d1d73c2SGuy Helmer case 2: 316299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "*.%s", 317299bafaeSGuy Helmer dom ? dom : lookupdom); 318299bafaeSGuy Helmer break; 3193d1d73c2SGuy Helmer case 3: 320299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "*.*"); 3211e890b05SBill Paul break; 3223d1d73c2SGuy Helmer default: 3233d1d73c2SGuy Helmer return (0); 3241e890b05SBill Paul } 325c5a096e0SJonathan Chen y = yp_match(lookupdom, map, key, strlen(key), &result, 326c5a096e0SJonathan Chen &resultlen); 327c5a096e0SJonathan Chen if (y == 0) { 328c5a096e0SJonathan Chen rv = _listmatch(result, group, resultlen); 329c5a096e0SJonathan Chen free(result); 3303d1d73c2SGuy Helmer if (rv) 3313d1d73c2SGuy Helmer return (1); 332c5a096e0SJonathan Chen } else if (y != YPERR_KEY) { 333c5a096e0SJonathan Chen /* 334c5a096e0SJonathan Chen * If we get an error other than 'no 335c5a096e0SJonathan Chen * such key in map' then something is 336c5a096e0SJonathan Chen * wrong and we should stop the search. 337c5a096e0SJonathan Chen */ 338c5a096e0SJonathan Chen return (-1); 339c5a096e0SJonathan Chen } 340c5a096e0SJonathan Chen } 3411e890b05SBill Paul } 3421e890b05SBill Paul #endif 3431e890b05SBill Paul 34458f0484fSRodney W. Grimes /* 34558f0484fSRodney W. Grimes * Search for a match in a netgroup. 34658f0484fSRodney W. Grimes */ 34758f0484fSRodney W. Grimes int 34876884596SDag-Erling Smørgrav innetgr(const char *group, const char *host, const char *user, const char *dom) 34958f0484fSRodney W. Grimes { 35058f0484fSRodney W. Grimes char *hst, *usr, *dm; 3510ffe27f5SBill Paul /* Sanity check */ 3520ffe27f5SBill Paul 3530ffe27f5SBill Paul if (group == NULL || !strlen(group)) 3540ffe27f5SBill Paul return (0); 3550ffe27f5SBill Paul 3561e890b05SBill Paul #ifdef YP 3571e890b05SBill Paul _yp_innetgr = 1; 3581e890b05SBill Paul #endif 35958f0484fSRodney W. Grimes setnetgrent(group); 3601e890b05SBill Paul #ifdef YP 361cbe78b44SBill Paul _yp_innetgr = 0; 3621e890b05SBill Paul /* 3631e890b05SBill Paul * If we're in NIS-only mode, do the search using 3641e890b05SBill Paul * NIS 'reverse netgroup' lookups. 365c5a096e0SJonathan Chen * 366c5a096e0SJonathan Chen * What happens with 'reverse netgroup' lookups: 367c5a096e0SJonathan Chen * 368c5a096e0SJonathan Chen * 1) try 'reverse netgroup' lookup 369c5a096e0SJonathan Chen * 1.a) if host is specified and user is null: 370c5a096e0SJonathan Chen * look in netgroup.byhost 371c5a096e0SJonathan Chen * (try host.domain, host.*, *.domain or *.*) 372c5a096e0SJonathan Chen * if found, return yes 373c5a096e0SJonathan Chen * 1.b) if user is specified and host is null: 374c5a096e0SJonathan Chen * look in netgroup.byuser 375c5a096e0SJonathan Chen * (try host.domain, host.*, *.domain or *.*) 376c5a096e0SJonathan Chen * if found, return yes 377c5a096e0SJonathan Chen * 1.c) if both host and user are specified, 378c5a096e0SJonathan Chen * don't do 'reverse netgroup' lookup. It won't work. 379c5a096e0SJonathan Chen * 1.d) if neither host ane user are specified (why?!?) 380c5a096e0SJonathan Chen * don't do 'reverse netgroup' lookup either. 381c5a096e0SJonathan Chen * 2) if domain is specified and 'reverse lookup' is done: 382c5a096e0SJonathan Chen * 'reverse lookup' was authoritative. bye bye. 383c5a096e0SJonathan Chen * 3) otherwise, too bad, try it the slow way. 3841e890b05SBill Paul */ 385c5a096e0SJonathan Chen if (_use_only_yp && (host == NULL) != (user == NULL)) { 386c5a096e0SJonathan Chen int ret; 3871e890b05SBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 3881e890b05SBill Paul return (0); 389c5a096e0SJonathan Chen ret = _revnetgr_lookup(_netgr_yp_domain, 390c5a096e0SJonathan Chen host?"netgroup.byhost":"netgroup.byuser", 391c5a096e0SJonathan Chen host?host:user, dom, group); 392c5a096e0SJonathan Chen if (ret == 1) 3931e890b05SBill Paul return (1); 394c5a096e0SJonathan Chen else if (ret == 0 && dom != NULL) 3951e890b05SBill Paul return (0); 3961e890b05SBill Paul } 397e882d43eSBill Paul 398e882d43eSBill Paul setnetgrent(group); 3991e890b05SBill Paul #endif /* YP */ 400e882d43eSBill Paul 40158f0484fSRodney W. Grimes while (getnetgrent(&hst, &usr, &dm)) 4021e890b05SBill Paul if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 4031e890b05SBill Paul (user == NULL || usr == NULL || !strcmp(user, usr)) && 4041e890b05SBill Paul ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 40558f0484fSRodney W. Grimes endnetgrent(); 40658f0484fSRodney W. Grimes return (1); 40758f0484fSRodney W. Grimes } 40858f0484fSRodney W. Grimes endnetgrent(); 40958f0484fSRodney W. Grimes return (0); 41058f0484fSRodney W. Grimes } 41158f0484fSRodney W. Grimes 41258f0484fSRodney W. Grimes /* 41358f0484fSRodney W. Grimes * Parse the netgroup file setting up the linked lists. 41458f0484fSRodney W. Grimes */ 41558f0484fSRodney W. Grimes static int 41676884596SDag-Erling Smørgrav parse_netgrp(const char *group) 41758f0484fSRodney W. Grimes { 4183d1d73c2SGuy Helmer struct netgrp *grp; 4193d1d73c2SGuy Helmer struct linelist *lp = linehead; 4203d1d73c2SGuy Helmer char **ng; 4213d1d73c2SGuy Helmer char *epos, *gpos, *pos, *spos; 4223d1d73c2SGuy Helmer int freepos, len, strpos; 423dbf973c0SBill Paul #ifdef DEBUG 42422626efaSDavid E. O'Brien int fields; 425dbf973c0SBill Paul #endif 42658f0484fSRodney W. Grimes 42758f0484fSRodney W. Grimes /* 42858f0484fSRodney W. Grimes * First, see if the line has already been read in. 42958f0484fSRodney W. Grimes */ 43058f0484fSRodney W. Grimes while (lp) { 43158f0484fSRodney W. Grimes if (!strcmp(group, lp->l_groupname)) 43258f0484fSRodney W. Grimes break; 43358f0484fSRodney W. Grimes lp = lp->l_next; 43458f0484fSRodney W. Grimes } 43517ec7b7aSKonstantin Belousov if (lp == NULL && (lp = read_for_group(group)) == NULL) 43658f0484fSRodney W. Grimes return (1); 43758f0484fSRodney W. Grimes if (lp->l_parsed) { 438dbf973c0SBill Paul #ifdef DEBUG 439dbf973c0SBill Paul /* 440dbf973c0SBill Paul * This error message is largely superflous since the 441dbf973c0SBill Paul * code handles the error condition sucessfully, and 442dbf973c0SBill Paul * spewing it out from inside libc can actually hose 443dbf973c0SBill Paul * certain programs. 444dbf973c0SBill Paul */ 44558f0484fSRodney W. Grimes fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 446dbf973c0SBill Paul #endif 44758f0484fSRodney W. Grimes return (1); 44858f0484fSRodney W. Grimes } else 44958f0484fSRodney W. Grimes lp->l_parsed = 1; 45058f0484fSRodney W. Grimes pos = lp->l_line; 451409495f6SBill Paul /* Watch for null pointer dereferences, dammit! */ 452409495f6SBill Paul while (pos != NULL && *pos != '\0') { 45358f0484fSRodney W. Grimes if (*pos == '(') { 4543d1d73c2SGuy Helmer grp = malloc(sizeof(*grp)); 455fed7420cSGuy Helmer if (grp == NULL) 456fed7420cSGuy Helmer return (1); 4573d1d73c2SGuy Helmer ng = grp->ng_str; 4583d1d73c2SGuy Helmer bzero(grp, sizeof(*grp)); 45958f0484fSRodney W. Grimes pos++; 46058f0484fSRodney W. Grimes gpos = strsep(&pos, ")"); 461dbf973c0SBill Paul #ifdef DEBUG 462dbf973c0SBill Paul fields = 0; 463dbf973c0SBill Paul #endif 46458f0484fSRodney W. Grimes for (strpos = 0; strpos < 3; strpos++) { 4653d1d73c2SGuy Helmer if ((spos = strsep(&gpos, ",")) == NULL) { 4663d1d73c2SGuy Helmer /* 4673d1d73c2SGuy Helmer * All other systems I've tested 4683d1d73c2SGuy Helmer * return NULL for empty netgroup 4693d1d73c2SGuy Helmer * fields. It's up to user programs 4703d1d73c2SGuy Helmer * to handle the NULLs appropriately. 4713d1d73c2SGuy Helmer */ 4723d1d73c2SGuy Helmer ng[strpos] = NULL; 4733d1d73c2SGuy Helmer continue; 4743d1d73c2SGuy Helmer } 475dbf973c0SBill Paul #ifdef DEBUG 476dbf973c0SBill Paul fields++; 477dbf973c0SBill Paul #endif 47858f0484fSRodney W. Grimes while (*spos == ' ' || *spos == '\t') 47958f0484fSRodney W. Grimes spos++; 4801e890b05SBill Paul if ((epos = strpbrk(spos, " \t"))) { 48158f0484fSRodney W. Grimes *epos = '\0'; 48258f0484fSRodney W. Grimes len = epos - spos; 48358f0484fSRodney W. Grimes } else 48458f0484fSRodney W. Grimes len = strlen(spos); 4853d1d73c2SGuy Helmer if (len <= 0) 4863d1d73c2SGuy Helmer continue; 4873d1d73c2SGuy Helmer ng[strpos] = malloc(len + 1); 4883d1d73c2SGuy Helmer if (ng[strpos] == NULL) { 4893d1d73c2SGuy Helmer for (freepos = 0; freepos < strpos; 4903d1d73c2SGuy Helmer freepos++) 4913d1d73c2SGuy Helmer free(ng[freepos]); 492fed7420cSGuy Helmer free(grp); 493fed7420cSGuy Helmer return (1); 494fed7420cSGuy Helmer } 4953d1d73c2SGuy Helmer bcopy(spos, ng[strpos], len + 1); 496dbf973c0SBill Paul } 497fed7420cSGuy Helmer grp->ng_next = grouphead.gr; 498fed7420cSGuy Helmer grouphead.gr = grp; 499dbf973c0SBill Paul #ifdef DEBUG 500dbf973c0SBill Paul /* 501dbf973c0SBill Paul * Note: on other platforms, malformed netgroup 502dbf973c0SBill Paul * entries are not normally flagged. While we 503dbf973c0SBill Paul * can catch bad entries and report them, we should 504dbf973c0SBill Paul * stay silent by default for compatibility's sake. 505dbf973c0SBill Paul */ 5063d1d73c2SGuy Helmer if (fields < 3) { 5073d1d73c2SGuy Helmer fprintf(stderr, 5083d1d73c2SGuy Helmer "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 5093d1d73c2SGuy Helmer ng[NG_HOST] == NULL ? "" : ng[NG_HOST], 5103d1d73c2SGuy Helmer ng[NG_USER] == NULL ? "" : ",", 5113d1d73c2SGuy Helmer ng[NG_USER] == NULL ? "" : ng[NG_USER], 5123d1d73c2SGuy Helmer ng[NG_DOM] == NULL ? "" : ",", 5133d1d73c2SGuy Helmer ng[NG_DOM] == NULL ? "" : ng[NG_DOM], 514dbf973c0SBill Paul lp->l_groupname); 515dbf973c0SBill Paul #endif 51658f0484fSRodney W. Grimes } else { 51758f0484fSRodney W. Grimes spos = strsep(&pos, ", \t"); 51858f0484fSRodney W. Grimes if (parse_netgrp(spos)) 519e8030794SBill Paul continue; 52058f0484fSRodney W. Grimes } 521adf6ad9eSPeter Wemm if (pos == NULL) 522adf6ad9eSPeter Wemm break; 52358f0484fSRodney W. Grimes while (*pos == ' ' || *pos == ',' || *pos == '\t') 52458f0484fSRodney W. Grimes pos++; 52558f0484fSRodney W. Grimes } 52658f0484fSRodney W. Grimes return (0); 52758f0484fSRodney W. Grimes } 52858f0484fSRodney W. Grimes 52958f0484fSRodney W. Grimes /* 53058f0484fSRodney W. Grimes * Read the netgroup file and save lines until the line for the netgroup 53158f0484fSRodney W. Grimes * is found. Return 1 if eof is encountered. 53258f0484fSRodney W. Grimes */ 53358f0484fSRodney W. Grimes static struct linelist * 53476884596SDag-Erling Smørgrav read_for_group(const char *group) 53558f0484fSRodney W. Grimes { 5363a3c9121SKonstantin Belousov char *linep, *olinep, *pos, *spos; 53722626efaSDavid E. O'Brien int len, olen; 53858f0484fSRodney W. Grimes int cont; 53958f0484fSRodney W. Grimes struct linelist *lp; 5401d2493ffSBill Paul char line[LINSIZ + 2]; 541409495f6SBill Paul #ifdef YP 542409495f6SBill Paul char *result; 543409495f6SBill Paul int resultlen; 544fed7420cSGuy Helmer linep = NULL; 54558f0484fSRodney W. Grimes 546409495f6SBill Paul while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 547409495f6SBill Paul if (_netgr_yp_enabled) { 548409495f6SBill Paul if(!_netgr_yp_domain) 5498516cd0fSBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 550409495f6SBill Paul continue; 5518516cd0fSBill Paul if (yp_match(_netgr_yp_domain, "netgroup", group, 5528516cd0fSBill Paul strlen(group), &result, &resultlen)) { 5538516cd0fSBill Paul free(result); 5541e890b05SBill Paul if (_use_only_yp) 5558516cd0fSBill Paul return ((struct linelist *)0); 5561e890b05SBill Paul else { 5571e890b05SBill Paul _netgr_yp_enabled = 0; 5581e890b05SBill Paul continue; 5591e890b05SBill Paul } 560409495f6SBill Paul } 5611d2493ffSBill Paul snprintf(line, LINSIZ, "%s %s", group, result); 562409495f6SBill Paul free(result); 563409495f6SBill Paul } 564409495f6SBill Paul #else 565fed7420cSGuy Helmer linep = NULL; 56658f0484fSRodney W. Grimes while (fgets(line, LINSIZ, netf) != NULL) { 567409495f6SBill Paul #endif 568409495f6SBill Paul pos = (char *)&line; 569409495f6SBill Paul #ifdef YP 570409495f6SBill Paul if (*pos == '+') { 571409495f6SBill Paul _netgr_yp_enabled = 1; 572409495f6SBill Paul continue; 573409495f6SBill Paul } 574409495f6SBill Paul #endif 57558f0484fSRodney W. Grimes if (*pos == '#') 57658f0484fSRodney W. Grimes continue; 57758f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 57858f0484fSRodney W. Grimes pos++; 57958f0484fSRodney W. Grimes spos = pos; 58058f0484fSRodney W. Grimes while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 58158f0484fSRodney W. Grimes *pos != '\0') 58258f0484fSRodney W. Grimes pos++; 58358f0484fSRodney W. Grimes len = pos - spos; 58458f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 58558f0484fSRodney W. Grimes pos++; 58658f0484fSRodney W. Grimes if (*pos != '\n' && *pos != '\0') { 58758f0484fSRodney W. Grimes lp = (struct linelist *)malloc(sizeof (*lp)); 588fed7420cSGuy Helmer if (lp == NULL) 589fed7420cSGuy Helmer return (NULL); 59058f0484fSRodney W. Grimes lp->l_parsed = 0; 59158f0484fSRodney W. Grimes lp->l_groupname = (char *)malloc(len + 1); 592fed7420cSGuy Helmer if (lp->l_groupname == NULL) { 593fed7420cSGuy Helmer free(lp); 594fed7420cSGuy Helmer return (NULL); 595fed7420cSGuy Helmer } 59658f0484fSRodney W. Grimes bcopy(spos, lp->l_groupname, len); 59758f0484fSRodney W. Grimes *(lp->l_groupname + len) = '\0'; 59858f0484fSRodney W. Grimes len = strlen(pos); 59958f0484fSRodney W. Grimes olen = 0; 60058f0484fSRodney W. Grimes 60158f0484fSRodney W. Grimes /* 60258f0484fSRodney W. Grimes * Loop around handling line continuations. 60358f0484fSRodney W. Grimes */ 60458f0484fSRodney W. Grimes do { 60558f0484fSRodney W. Grimes if (*(pos + len - 1) == '\n') 60658f0484fSRodney W. Grimes len--; 60758f0484fSRodney W. Grimes if (*(pos + len - 1) == '\\') { 60858f0484fSRodney W. Grimes len--; 60958f0484fSRodney W. Grimes cont = 1; 61058f0484fSRodney W. Grimes } else 61158f0484fSRodney W. Grimes cont = 0; 61258f0484fSRodney W. Grimes if (len > 0) { 6133a3c9121SKonstantin Belousov linep = malloc(olen + len + 1); 614fed7420cSGuy Helmer if (linep == NULL) { 615fed7420cSGuy Helmer free(lp->l_groupname); 616fed7420cSGuy Helmer free(lp); 617fed7420cSGuy Helmer return (NULL); 61858f0484fSRodney W. Grimes } 6193a3c9121SKonstantin Belousov if (olen > 0) { 6203a3c9121SKonstantin Belousov bcopy(olinep, linep, olen); 6213a3c9121SKonstantin Belousov free(olinep); 6223a3c9121SKonstantin Belousov } 62358f0484fSRodney W. Grimes bcopy(pos, linep + olen, len); 62458f0484fSRodney W. Grimes olen += len; 62558f0484fSRodney W. Grimes *(linep + olen) = '\0'; 6263a3c9121SKonstantin Belousov olinep = linep; 62758f0484fSRodney W. Grimes } 62858f0484fSRodney W. Grimes if (cont) { 62958f0484fSRodney W. Grimes if (fgets(line, LINSIZ, netf)) { 63058f0484fSRodney W. Grimes pos = line; 63158f0484fSRodney W. Grimes len = strlen(pos); 63258f0484fSRodney W. Grimes } else 63358f0484fSRodney W. Grimes cont = 0; 63458f0484fSRodney W. Grimes } 63558f0484fSRodney W. Grimes } while (cont); 63658f0484fSRodney W. Grimes lp->l_line = linep; 63758f0484fSRodney W. Grimes lp->l_next = linehead; 63858f0484fSRodney W. Grimes linehead = lp; 63958f0484fSRodney W. Grimes 64058f0484fSRodney W. Grimes /* 64158f0484fSRodney W. Grimes * If this is the one we wanted, we are done. 64258f0484fSRodney W. Grimes */ 64358f0484fSRodney W. Grimes if (!strcmp(lp->l_groupname, group)) 64458f0484fSRodney W. Grimes return (lp); 64558f0484fSRodney W. Grimes } 64658f0484fSRodney W. Grimes } 6471e890b05SBill Paul #ifdef YP 6481e890b05SBill Paul /* 6491e890b05SBill Paul * Yucky. The recursive nature of this whole mess might require 6501e890b05SBill Paul * us to make more than one pass through the netgroup file. 6511e890b05SBill Paul * This might be best left outside the #ifdef YP, but YP is 6521e890b05SBill Paul * defined by default anyway, so I'll leave it like this 6531e890b05SBill Paul * until I know better. 6541e890b05SBill Paul */ 6551e890b05SBill Paul rewind(netf); 6561e890b05SBill Paul #endif 657fed7420cSGuy Helmer return (NULL); 65858f0484fSRodney W. Grimes } 659