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 16458f0484fSRodney W. Grimes if (grouphead.gr == (struct netgrp *)0 || 16558f0484fSRodney W. Grimes strcmp(group, grouphead.grname)) { 16658f0484fSRodney W. Grimes endnetgrent(); 1671e890b05SBill Paul #ifdef YP 168d454389cSBill Paul /* Presumed guilty until proven innocent. */ 169d454389cSBill Paul _use_only_yp = 0; 1701e890b05SBill Paul /* 171cbe78b44SBill Paul * If /etc/netgroup doesn't exist or is empty, 1721e890b05SBill Paul * use NIS exclusively. 1731e890b05SBill Paul */ 1741e890b05SBill Paul if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && 1751e890b05SBill Paul errno == ENOENT) || _yp_statp.st_size == 0) 1761e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1771e890b05SBill Paul if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){ 1781e890b05SBill Paul /* 1791e890b05SBill Paul * Icky: grab the first character of the netgroup file 1801e890b05SBill Paul * and turn on NIS if it's a '+'. rewind the stream 1811e890b05SBill Paul * afterwards so we don't goof up read_for_group() later. 1821e890b05SBill Paul */ 1831e890b05SBill Paul if (netf) { 1841e890b05SBill Paul fscanf(netf, "%c", &_yp_plus); 1851e890b05SBill Paul rewind(netf); 1861e890b05SBill Paul if (_yp_plus == '+') 1871e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1881e890b05SBill Paul } 1891e890b05SBill Paul /* 1901e890b05SBill Paul * If we were called specifically for an innetgr() 1911e890b05SBill Paul * lookup and we're in NIS-only mode, short-circuit 1921e890b05SBill Paul * parse_netgroup() and cut directly to the chase. 1931e890b05SBill Paul */ 194d454389cSBill Paul if (_use_only_yp && _yp_innetgr) { 195d454389cSBill Paul /* dohw! */ 196de32dbbdSBill Paul if (netf != NULL) 197d454389cSBill Paul fclose(netf); 1981e890b05SBill Paul return; 199d454389cSBill Paul } 2001e890b05SBill Paul #else 2016c58990dSBjoern A. Zeeb if ((netf = fopen(_PATH_NETGROUP, "r"))) { 2021e890b05SBill Paul #endif 20358f0484fSRodney W. Grimes if (parse_netgrp(group)) 20458f0484fSRodney W. Grimes endnetgrent(); 20558f0484fSRodney W. Grimes else { 206fed7420cSGuy Helmer grouphead.grname = strdup(group); 20758f0484fSRodney W. Grimes } 2081e890b05SBill Paul if (netf) 20958f0484fSRodney W. Grimes fclose(netf); 21058f0484fSRodney W. Grimes } 21158f0484fSRodney W. Grimes } 21258f0484fSRodney W. Grimes nextgrp = grouphead.gr; 21358f0484fSRodney W. Grimes } 21458f0484fSRodney W. Grimes 21558f0484fSRodney W. Grimes /* 21658f0484fSRodney W. Grimes * Get the next netgroup off the list. 21758f0484fSRodney W. Grimes */ 21858f0484fSRodney W. Grimes int 21976884596SDag-Erling Smørgrav getnetgrent(char **hostp, char **userp, char **domp) 22058f0484fSRodney W. Grimes { 2211e890b05SBill Paul #ifdef YP 2221e890b05SBill Paul _yp_innetgr = 0; 2231e890b05SBill Paul #endif 22458f0484fSRodney W. Grimes 22558f0484fSRodney W. Grimes if (nextgrp) { 22658f0484fSRodney W. Grimes *hostp = nextgrp->ng_str[NG_HOST]; 22758f0484fSRodney W. Grimes *userp = nextgrp->ng_str[NG_USER]; 22858f0484fSRodney W. Grimes *domp = nextgrp->ng_str[NG_DOM]; 22958f0484fSRodney W. Grimes nextgrp = nextgrp->ng_next; 23058f0484fSRodney W. Grimes return (1); 23158f0484fSRodney W. Grimes } 23258f0484fSRodney W. Grimes return (0); 23358f0484fSRodney W. Grimes } 23458f0484fSRodney W. Grimes 23558f0484fSRodney W. Grimes /* 23658f0484fSRodney W. Grimes * endnetgrent() - cleanup 23758f0484fSRodney W. Grimes */ 23858f0484fSRodney W. Grimes void 23976884596SDag-Erling Smørgrav endnetgrent(void) 24058f0484fSRodney W. Grimes { 24122626efaSDavid E. O'Brien struct linelist *lp, *olp; 24222626efaSDavid E. O'Brien struct netgrp *gp, *ogp; 24358f0484fSRodney W. Grimes 24458f0484fSRodney W. Grimes lp = linehead; 24558f0484fSRodney W. Grimes while (lp) { 24658f0484fSRodney W. Grimes olp = lp; 24758f0484fSRodney W. Grimes lp = lp->l_next; 24858f0484fSRodney W. Grimes free(olp->l_groupname); 24958f0484fSRodney W. Grimes free(olp->l_line); 25058f0484fSRodney W. Grimes free((char *)olp); 25158f0484fSRodney W. Grimes } 25258f0484fSRodney W. Grimes linehead = (struct linelist *)0; 25358f0484fSRodney W. Grimes if (grouphead.grname) { 25458f0484fSRodney W. Grimes free(grouphead.grname); 25558f0484fSRodney W. Grimes grouphead.grname = (char *)0; 25658f0484fSRodney W. Grimes } 25758f0484fSRodney W. Grimes gp = grouphead.gr; 25858f0484fSRodney W. Grimes while (gp) { 25958f0484fSRodney W. Grimes ogp = gp; 26058f0484fSRodney W. Grimes gp = gp->ng_next; 26158f0484fSRodney W. Grimes if (ogp->ng_str[NG_HOST]) 26258f0484fSRodney W. Grimes free(ogp->ng_str[NG_HOST]); 26358f0484fSRodney W. Grimes if (ogp->ng_str[NG_USER]) 26458f0484fSRodney W. Grimes free(ogp->ng_str[NG_USER]); 26558f0484fSRodney W. Grimes if (ogp->ng_str[NG_DOM]) 26658f0484fSRodney W. Grimes free(ogp->ng_str[NG_DOM]); 26758f0484fSRodney W. Grimes free((char *)ogp); 26858f0484fSRodney W. Grimes } 26958f0484fSRodney W. Grimes grouphead.gr = (struct netgrp *)0; 2706920b9ccSJonathan Chen nextgrp = (struct netgrp *)0; 271409495f6SBill Paul #ifdef YP 2728516cd0fSBill Paul _netgr_yp_enabled = 0; 273409495f6SBill Paul #endif 27458f0484fSRodney W. Grimes } 27558f0484fSRodney W. Grimes 2761e890b05SBill Paul #ifdef YP 27776884596SDag-Erling Smørgrav static int 27876884596SDag-Erling Smørgrav _listmatch(const char *list, const char *group, int len) 2791e890b05SBill Paul { 28076884596SDag-Erling Smørgrav const char *ptr = list; 28176884596SDag-Erling Smørgrav const char *cptr; 282d9cc92f5SBill Paul int glen = strlen(group); 2831e890b05SBill Paul 284d9cc92f5SBill Paul /* skip possible leading whitespace */ 28549435560SAndrey A. Chernov while(isspace((unsigned char)*ptr)) 286d9cc92f5SBill Paul ptr++; 287cbe78b44SBill Paul 288d9cc92f5SBill Paul while (ptr < list + len) { 289d9cc92f5SBill Paul cptr = ptr; 29049435560SAndrey A. Chernov while(*ptr != ',' && *ptr != '\0' && !isspace((unsigned char)*ptr)) 291d9cc92f5SBill Paul ptr++; 292f48bc662SSteve Price if (strncmp(cptr, group, glen) == 0 && glen == (ptr - cptr)) 2931e890b05SBill Paul return (1); 29449435560SAndrey A. Chernov while(*ptr == ',' || isspace((unsigned char)*ptr)) 295d9cc92f5SBill Paul ptr++; 296dfe8e51cSBill Paul } 297cbe78b44SBill Paul 2981e890b05SBill Paul return (0); 2991e890b05SBill Paul } 3001e890b05SBill Paul 30176884596SDag-Erling Smørgrav static int 302c5a096e0SJonathan Chen _revnetgr_lookup(char* lookupdom, char* map, const char* str, 303c5a096e0SJonathan Chen const char* dom, const char* group) 3041e890b05SBill Paul { 305c5a096e0SJonathan Chen int y, rv, rot; 306c5a096e0SJonathan Chen char key[MAXHOSTNAMELEN]; 307c5a096e0SJonathan Chen char *result; 308c5a096e0SJonathan Chen int resultlen; 309c5a096e0SJonathan Chen 310c5a096e0SJonathan Chen for (rot = 0; ; rot++) { 311c5a096e0SJonathan Chen switch (rot) { 312299bafaeSGuy Helmer case(0): 313299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "%s.%s", str, 314c5a096e0SJonathan Chen dom ? dom : lookupdom); 3151e890b05SBill Paul break; 316299bafaeSGuy Helmer case(1): 317299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "%s.*", str); 318299bafaeSGuy Helmer break; 319299bafaeSGuy Helmer case(2): 320299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "*.%s", 321299bafaeSGuy Helmer dom ? dom : lookupdom); 322299bafaeSGuy Helmer break; 323299bafaeSGuy Helmer case(3): 324299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "*.*"); 3251e890b05SBill Paul break; 326c5a096e0SJonathan Chen default: return (0); 3271e890b05SBill Paul } 328c5a096e0SJonathan Chen y = yp_match(lookupdom, map, key, strlen(key), &result, 329c5a096e0SJonathan Chen &resultlen); 330c5a096e0SJonathan Chen if (y == 0) { 331c5a096e0SJonathan Chen rv = _listmatch(result, group, resultlen); 332c5a096e0SJonathan Chen free(result); 333c5a096e0SJonathan Chen if (rv) return (1); 334c5a096e0SJonathan Chen } else if (y != YPERR_KEY) { 335c5a096e0SJonathan Chen /* 336c5a096e0SJonathan Chen * If we get an error other than 'no 337c5a096e0SJonathan Chen * such key in map' then something is 338c5a096e0SJonathan Chen * wrong and we should stop the search. 339c5a096e0SJonathan Chen */ 340c5a096e0SJonathan Chen return (-1); 341c5a096e0SJonathan Chen } 342c5a096e0SJonathan Chen } 3431e890b05SBill Paul } 3441e890b05SBill Paul #endif 3451e890b05SBill Paul 34658f0484fSRodney W. Grimes /* 34758f0484fSRodney W. Grimes * Search for a match in a netgroup. 34858f0484fSRodney W. Grimes */ 34958f0484fSRodney W. Grimes int 35076884596SDag-Erling Smørgrav innetgr(const char *group, const char *host, const char *user, const char *dom) 35158f0484fSRodney W. Grimes { 35258f0484fSRodney W. Grimes char *hst, *usr, *dm; 3530ffe27f5SBill Paul /* Sanity check */ 3540ffe27f5SBill Paul 3550ffe27f5SBill Paul if (group == NULL || !strlen(group)) 3560ffe27f5SBill Paul return (0); 3570ffe27f5SBill Paul 3581e890b05SBill Paul #ifdef YP 3591e890b05SBill Paul _yp_innetgr = 1; 3601e890b05SBill Paul #endif 36158f0484fSRodney W. Grimes setnetgrent(group); 3621e890b05SBill Paul #ifdef YP 363cbe78b44SBill Paul _yp_innetgr = 0; 3641e890b05SBill Paul /* 3651e890b05SBill Paul * If we're in NIS-only mode, do the search using 3661e890b05SBill Paul * NIS 'reverse netgroup' lookups. 367c5a096e0SJonathan Chen * 368c5a096e0SJonathan Chen * What happens with 'reverse netgroup' lookups: 369c5a096e0SJonathan Chen * 370c5a096e0SJonathan Chen * 1) try 'reverse netgroup' lookup 371c5a096e0SJonathan Chen * 1.a) if host is specified and user is null: 372c5a096e0SJonathan Chen * look in netgroup.byhost 373c5a096e0SJonathan Chen * (try host.domain, host.*, *.domain or *.*) 374c5a096e0SJonathan Chen * if found, return yes 375c5a096e0SJonathan Chen * 1.b) if user is specified and host is null: 376c5a096e0SJonathan Chen * look in netgroup.byuser 377c5a096e0SJonathan Chen * (try host.domain, host.*, *.domain or *.*) 378c5a096e0SJonathan Chen * if found, return yes 379c5a096e0SJonathan Chen * 1.c) if both host and user are specified, 380c5a096e0SJonathan Chen * don't do 'reverse netgroup' lookup. It won't work. 381c5a096e0SJonathan Chen * 1.d) if neither host ane user are specified (why?!?) 382c5a096e0SJonathan Chen * don't do 'reverse netgroup' lookup either. 383c5a096e0SJonathan Chen * 2) if domain is specified and 'reverse lookup' is done: 384c5a096e0SJonathan Chen * 'reverse lookup' was authoritative. bye bye. 385c5a096e0SJonathan Chen * 3) otherwise, too bad, try it the slow way. 3861e890b05SBill Paul */ 387c5a096e0SJonathan Chen if (_use_only_yp && (host == NULL) != (user == NULL)) { 388c5a096e0SJonathan Chen int ret; 3891e890b05SBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 3901e890b05SBill Paul return (0); 391c5a096e0SJonathan Chen ret = _revnetgr_lookup(_netgr_yp_domain, 392c5a096e0SJonathan Chen host?"netgroup.byhost":"netgroup.byuser", 393c5a096e0SJonathan Chen host?host:user, dom, group); 394c5a096e0SJonathan Chen if (ret == 1) 3951e890b05SBill Paul return (1); 396c5a096e0SJonathan Chen else if (ret == 0 && dom != NULL) 3971e890b05SBill Paul return (0); 3981e890b05SBill Paul } 399e882d43eSBill Paul 400e882d43eSBill Paul setnetgrent(group); 4011e890b05SBill Paul #endif /* YP */ 402e882d43eSBill Paul 40358f0484fSRodney W. Grimes while (getnetgrent(&hst, &usr, &dm)) 4041e890b05SBill Paul if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 4051e890b05SBill Paul (user == NULL || usr == NULL || !strcmp(user, usr)) && 4061e890b05SBill Paul ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 40758f0484fSRodney W. Grimes endnetgrent(); 40858f0484fSRodney W. Grimes return (1); 40958f0484fSRodney W. Grimes } 41058f0484fSRodney W. Grimes endnetgrent(); 41158f0484fSRodney W. Grimes return (0); 41258f0484fSRodney W. Grimes } 41358f0484fSRodney W. Grimes 41458f0484fSRodney W. Grimes /* 41558f0484fSRodney W. Grimes * Parse the netgroup file setting up the linked lists. 41658f0484fSRodney W. Grimes */ 41758f0484fSRodney W. Grimes static int 41876884596SDag-Erling Smørgrav parse_netgrp(const char *group) 41958f0484fSRodney W. Grimes { 42022626efaSDavid E. O'Brien char *spos, *epos; 4219a261158SGuy Helmer int len, strpos; 422dbf973c0SBill Paul #ifdef DEBUG 42322626efaSDavid E. O'Brien int fields; 424dbf973c0SBill Paul #endif 42558f0484fSRodney W. Grimes char *pos, *gpos; 42658f0484fSRodney W. Grimes struct netgrp *grp; 42758f0484fSRodney W. Grimes struct linelist *lp = linehead; 42858f0484fSRodney W. Grimes 42958f0484fSRodney W. Grimes /* 43058f0484fSRodney W. Grimes * First, see if the line has already been read in. 43158f0484fSRodney W. Grimes */ 43258f0484fSRodney W. Grimes while (lp) { 43358f0484fSRodney W. Grimes if (!strcmp(group, lp->l_groupname)) 43458f0484fSRodney W. Grimes break; 43558f0484fSRodney W. Grimes lp = lp->l_next; 43658f0484fSRodney W. Grimes } 43758f0484fSRodney W. Grimes if (lp == (struct linelist *)0 && 43858f0484fSRodney W. Grimes (lp = read_for_group(group)) == (struct linelist *)0) 43958f0484fSRodney W. Grimes return (1); 44058f0484fSRodney W. Grimes if (lp->l_parsed) { 441dbf973c0SBill Paul #ifdef DEBUG 442dbf973c0SBill Paul /* 443dbf973c0SBill Paul * This error message is largely superflous since the 444dbf973c0SBill Paul * code handles the error condition sucessfully, and 445dbf973c0SBill Paul * spewing it out from inside libc can actually hose 446dbf973c0SBill Paul * certain programs. 447dbf973c0SBill Paul */ 44858f0484fSRodney W. Grimes fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 449dbf973c0SBill Paul #endif 45058f0484fSRodney W. Grimes return (1); 45158f0484fSRodney W. Grimes } else 45258f0484fSRodney W. Grimes lp->l_parsed = 1; 45358f0484fSRodney W. Grimes pos = lp->l_line; 454409495f6SBill Paul /* Watch for null pointer dereferences, dammit! */ 455409495f6SBill Paul while (pos != NULL && *pos != '\0') { 45658f0484fSRodney W. Grimes if (*pos == '(') { 45758f0484fSRodney W. Grimes grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 458fed7420cSGuy Helmer if (grp == NULL) 459fed7420cSGuy Helmer return (1); 46058f0484fSRodney W. Grimes bzero((char *)grp, sizeof (struct netgrp)); 46158f0484fSRodney W. Grimes pos++; 46258f0484fSRodney W. Grimes gpos = strsep(&pos, ")"); 463dbf973c0SBill Paul #ifdef DEBUG 464dbf973c0SBill Paul fields = 0; 465dbf973c0SBill Paul #endif 46658f0484fSRodney W. Grimes for (strpos = 0; strpos < 3; strpos++) { 4671e890b05SBill Paul if ((spos = strsep(&gpos, ","))) { 468dbf973c0SBill Paul #ifdef DEBUG 469dbf973c0SBill Paul fields++; 470dbf973c0SBill Paul #endif 47158f0484fSRodney W. Grimes while (*spos == ' ' || *spos == '\t') 47258f0484fSRodney W. Grimes spos++; 4731e890b05SBill Paul if ((epos = strpbrk(spos, " \t"))) { 47458f0484fSRodney W. Grimes *epos = '\0'; 47558f0484fSRodney W. Grimes len = epos - spos; 47658f0484fSRodney W. Grimes } else 47758f0484fSRodney W. Grimes len = strlen(spos); 47858f0484fSRodney W. Grimes if (len > 0) { 47958f0484fSRodney W. Grimes grp->ng_str[strpos] = (char *) 48058f0484fSRodney W. Grimes malloc(len + 1); 481fed7420cSGuy Helmer if (grp->ng_str[strpos] == NULL) { 482fed7420cSGuy Helmer int freepos; 483fed7420cSGuy Helmer for (freepos = 0; freepos < strpos; freepos++) 484fed7420cSGuy Helmer free(grp->ng_str[freepos]); 485fed7420cSGuy Helmer free(grp); 486fed7420cSGuy Helmer return (1); 487fed7420cSGuy Helmer } 48858f0484fSRodney W. Grimes bcopy(spos, grp->ng_str[strpos], 48958f0484fSRodney W. Grimes len + 1); 49058f0484fSRodney W. Grimes } 491dbf973c0SBill Paul } else { 492dbf973c0SBill Paul /* 493dbf973c0SBill Paul * All other systems I've tested 494dbf973c0SBill Paul * return NULL for empty netgroup 495dbf973c0SBill Paul * fields. It's up to user programs 496dbf973c0SBill Paul * to handle the NULLs appropriately. 497dbf973c0SBill Paul */ 498dbf973c0SBill Paul grp->ng_str[strpos] = NULL; 49958f0484fSRodney W. Grimes } 500dbf973c0SBill Paul } 501fed7420cSGuy Helmer grp->ng_next = grouphead.gr; 502fed7420cSGuy Helmer grouphead.gr = grp; 503dbf973c0SBill Paul #ifdef DEBUG 504dbf973c0SBill Paul /* 505dbf973c0SBill Paul * Note: on other platforms, malformed netgroup 506dbf973c0SBill Paul * entries are not normally flagged. While we 507dbf973c0SBill Paul * can catch bad entries and report them, we should 508dbf973c0SBill Paul * stay silent by default for compatibility's sake. 509dbf973c0SBill Paul */ 510dbf973c0SBill Paul if (fields < 3) 511dbf973c0SBill Paul fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 512dbf973c0SBill Paul grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], 513dbf973c0SBill Paul grp->ng_str[NG_USER] == NULL ? "" : ",", 514dbf973c0SBill Paul grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], 515dbf973c0SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : ",", 516dbf973c0SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], 517dbf973c0SBill Paul lp->l_groupname); 518dbf973c0SBill Paul #endif 51958f0484fSRodney W. Grimes } else { 52058f0484fSRodney W. Grimes spos = strsep(&pos, ", \t"); 52158f0484fSRodney W. Grimes if (parse_netgrp(spos)) 522e8030794SBill Paul continue; 52358f0484fSRodney W. Grimes } 524adf6ad9eSPeter Wemm if (pos == NULL) 525adf6ad9eSPeter Wemm break; 52658f0484fSRodney W. Grimes while (*pos == ' ' || *pos == ',' || *pos == '\t') 52758f0484fSRodney W. Grimes pos++; 52858f0484fSRodney W. Grimes } 52958f0484fSRodney W. Grimes return (0); 53058f0484fSRodney W. Grimes } 53158f0484fSRodney W. Grimes 53258f0484fSRodney W. Grimes /* 53358f0484fSRodney W. Grimes * Read the netgroup file and save lines until the line for the netgroup 53458f0484fSRodney W. Grimes * is found. Return 1 if eof is encountered. 53558f0484fSRodney W. Grimes */ 53658f0484fSRodney W. Grimes static struct linelist * 53776884596SDag-Erling Smørgrav read_for_group(const char *group) 53858f0484fSRodney W. Grimes { 539fed7420cSGuy Helmer char *pos, *spos, *linep; 54022626efaSDavid E. O'Brien int len, olen; 54158f0484fSRodney W. Grimes int cont; 54258f0484fSRodney W. Grimes struct linelist *lp; 5431d2493ffSBill Paul char line[LINSIZ + 2]; 544409495f6SBill Paul #ifdef YP 545409495f6SBill Paul char *result; 546409495f6SBill Paul int resultlen; 547fed7420cSGuy Helmer linep = NULL; 54858f0484fSRodney W. Grimes 549409495f6SBill Paul while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 550409495f6SBill Paul if (_netgr_yp_enabled) { 551409495f6SBill Paul if(!_netgr_yp_domain) 5528516cd0fSBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 553409495f6SBill Paul continue; 5548516cd0fSBill Paul if (yp_match(_netgr_yp_domain, "netgroup", group, 5558516cd0fSBill Paul strlen(group), &result, &resultlen)) { 5568516cd0fSBill Paul free(result); 5571e890b05SBill Paul if (_use_only_yp) 5588516cd0fSBill Paul return ((struct linelist *)0); 5591e890b05SBill Paul else { 5601e890b05SBill Paul _netgr_yp_enabled = 0; 5611e890b05SBill Paul continue; 5621e890b05SBill Paul } 563409495f6SBill Paul } 5641d2493ffSBill Paul snprintf(line, LINSIZ, "%s %s", group, result); 565409495f6SBill Paul free(result); 566409495f6SBill Paul } 567409495f6SBill Paul #else 568fed7420cSGuy Helmer linep = NULL; 56958f0484fSRodney W. Grimes while (fgets(line, LINSIZ, netf) != NULL) { 570409495f6SBill Paul #endif 571409495f6SBill Paul pos = (char *)&line; 572409495f6SBill Paul #ifdef YP 573409495f6SBill Paul if (*pos == '+') { 574409495f6SBill Paul _netgr_yp_enabled = 1; 575409495f6SBill Paul continue; 576409495f6SBill Paul } 577409495f6SBill Paul #endif 57858f0484fSRodney W. Grimes if (*pos == '#') 57958f0484fSRodney W. Grimes continue; 58058f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 58158f0484fSRodney W. Grimes pos++; 58258f0484fSRodney W. Grimes spos = pos; 58358f0484fSRodney W. Grimes while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 58458f0484fSRodney W. Grimes *pos != '\0') 58558f0484fSRodney W. Grimes pos++; 58658f0484fSRodney W. Grimes len = pos - spos; 58758f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 58858f0484fSRodney W. Grimes pos++; 58958f0484fSRodney W. Grimes if (*pos != '\n' && *pos != '\0') { 59058f0484fSRodney W. Grimes lp = (struct linelist *)malloc(sizeof (*lp)); 591fed7420cSGuy Helmer if (lp == NULL) 592fed7420cSGuy Helmer return (NULL); 59358f0484fSRodney W. Grimes lp->l_parsed = 0; 59458f0484fSRodney W. Grimes lp->l_groupname = (char *)malloc(len + 1); 595fed7420cSGuy Helmer if (lp->l_groupname == NULL) { 596fed7420cSGuy Helmer free(lp); 597fed7420cSGuy Helmer return (NULL); 598fed7420cSGuy Helmer } 59958f0484fSRodney W. Grimes bcopy(spos, lp->l_groupname, len); 60058f0484fSRodney W. Grimes *(lp->l_groupname + len) = '\0'; 60158f0484fSRodney W. Grimes len = strlen(pos); 60258f0484fSRodney W. Grimes olen = 0; 60358f0484fSRodney W. Grimes 60458f0484fSRodney W. Grimes /* 60558f0484fSRodney W. Grimes * Loop around handling line continuations. 60658f0484fSRodney W. Grimes */ 60758f0484fSRodney W. Grimes do { 60858f0484fSRodney W. Grimes if (*(pos + len - 1) == '\n') 60958f0484fSRodney W. Grimes len--; 61058f0484fSRodney W. Grimes if (*(pos + len - 1) == '\\') { 61158f0484fSRodney W. Grimes len--; 61258f0484fSRodney W. Grimes cont = 1; 61358f0484fSRodney W. Grimes } else 61458f0484fSRodney W. Grimes cont = 0; 61558f0484fSRodney W. Grimes if (len > 0) { 616fed7420cSGuy Helmer linep = (char *)reallocf(linep, olen + len + 1); 617fed7420cSGuy Helmer if (linep == NULL) { 618fed7420cSGuy Helmer free(lp->l_groupname); 619fed7420cSGuy Helmer free(lp); 620fed7420cSGuy Helmer return (NULL); 62158f0484fSRodney W. Grimes } 62258f0484fSRodney W. Grimes bcopy(pos, linep + olen, len); 62358f0484fSRodney W. Grimes olen += len; 62458f0484fSRodney W. Grimes *(linep + olen) = '\0'; 62558f0484fSRodney W. Grimes } 62658f0484fSRodney W. Grimes if (cont) { 62758f0484fSRodney W. Grimes if (fgets(line, LINSIZ, netf)) { 62858f0484fSRodney W. Grimes pos = line; 62958f0484fSRodney W. Grimes len = strlen(pos); 63058f0484fSRodney W. Grimes } else 63158f0484fSRodney W. Grimes cont = 0; 63258f0484fSRodney W. Grimes } 63358f0484fSRodney W. Grimes } while (cont); 63458f0484fSRodney W. Grimes lp->l_line = linep; 63558f0484fSRodney W. Grimes lp->l_next = linehead; 63658f0484fSRodney W. Grimes linehead = lp; 63758f0484fSRodney W. Grimes 63858f0484fSRodney W. Grimes /* 63958f0484fSRodney W. Grimes * If this is the one we wanted, we are done. 64058f0484fSRodney W. Grimes */ 64158f0484fSRodney W. Grimes if (!strcmp(lp->l_groupname, group)) 64258f0484fSRodney W. Grimes return (lp); 64358f0484fSRodney W. Grimes } 64458f0484fSRodney W. Grimes } 6451e890b05SBill Paul #ifdef YP 6461e890b05SBill Paul /* 6471e890b05SBill Paul * Yucky. The recursive nature of this whole mess might require 6481e890b05SBill Paul * us to make more than one pass through the netgroup file. 6491e890b05SBill Paul * This might be best left outside the #ifdef YP, but YP is 6501e890b05SBill Paul * defined by default anyway, so I'll leave it like this 6511e890b05SBill Paul * until I know better. 6521e890b05SBill Paul */ 6531e890b05SBill Paul rewind(netf); 6541e890b05SBill Paul #endif 655fed7420cSGuy Helmer return (NULL); 65658f0484fSRodney W. Grimes } 657