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) { 3123d1d73c2SGuy Helmer case 0: 313299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "%s.%s", str, 314c5a096e0SJonathan Chen dom ? dom : lookupdom); 3151e890b05SBill Paul break; 3163d1d73c2SGuy Helmer case 1: 317299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "%s.*", str); 318299bafaeSGuy Helmer break; 3193d1d73c2SGuy Helmer case 2: 320299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "*.%s", 321299bafaeSGuy Helmer dom ? dom : lookupdom); 322299bafaeSGuy Helmer break; 3233d1d73c2SGuy Helmer case 3: 324299bafaeSGuy Helmer snprintf(key, MAXHOSTNAMELEN, "*.*"); 3251e890b05SBill Paul break; 3263d1d73c2SGuy Helmer default: 3273d1d73c2SGuy Helmer return (0); 3281e890b05SBill Paul } 329c5a096e0SJonathan Chen y = yp_match(lookupdom, map, key, strlen(key), &result, 330c5a096e0SJonathan Chen &resultlen); 331c5a096e0SJonathan Chen if (y == 0) { 332c5a096e0SJonathan Chen rv = _listmatch(result, group, resultlen); 333c5a096e0SJonathan Chen free(result); 3343d1d73c2SGuy Helmer if (rv) 3353d1d73c2SGuy Helmer return (1); 336c5a096e0SJonathan Chen } else if (y != YPERR_KEY) { 337c5a096e0SJonathan Chen /* 338c5a096e0SJonathan Chen * If we get an error other than 'no 339c5a096e0SJonathan Chen * such key in map' then something is 340c5a096e0SJonathan Chen * wrong and we should stop the search. 341c5a096e0SJonathan Chen */ 342c5a096e0SJonathan Chen return (-1); 343c5a096e0SJonathan Chen } 344c5a096e0SJonathan Chen } 3451e890b05SBill Paul } 3461e890b05SBill Paul #endif 3471e890b05SBill Paul 34858f0484fSRodney W. Grimes /* 34958f0484fSRodney W. Grimes * Search for a match in a netgroup. 35058f0484fSRodney W. Grimes */ 35158f0484fSRodney W. Grimes int 35276884596SDag-Erling Smørgrav innetgr(const char *group, const char *host, const char *user, const char *dom) 35358f0484fSRodney W. Grimes { 35458f0484fSRodney W. Grimes char *hst, *usr, *dm; 3550ffe27f5SBill Paul /* Sanity check */ 3560ffe27f5SBill Paul 3570ffe27f5SBill Paul if (group == NULL || !strlen(group)) 3580ffe27f5SBill Paul return (0); 3590ffe27f5SBill Paul 3601e890b05SBill Paul #ifdef YP 3611e890b05SBill Paul _yp_innetgr = 1; 3621e890b05SBill Paul #endif 36358f0484fSRodney W. Grimes setnetgrent(group); 3641e890b05SBill Paul #ifdef YP 365cbe78b44SBill Paul _yp_innetgr = 0; 3661e890b05SBill Paul /* 3671e890b05SBill Paul * If we're in NIS-only mode, do the search using 3681e890b05SBill Paul * NIS 'reverse netgroup' lookups. 369c5a096e0SJonathan Chen * 370c5a096e0SJonathan Chen * What happens with 'reverse netgroup' lookups: 371c5a096e0SJonathan Chen * 372c5a096e0SJonathan Chen * 1) try 'reverse netgroup' lookup 373c5a096e0SJonathan Chen * 1.a) if host is specified and user is null: 374c5a096e0SJonathan Chen * look in netgroup.byhost 375c5a096e0SJonathan Chen * (try host.domain, host.*, *.domain or *.*) 376c5a096e0SJonathan Chen * if found, return yes 377c5a096e0SJonathan Chen * 1.b) if user is specified and host is null: 378c5a096e0SJonathan Chen * look in netgroup.byuser 379c5a096e0SJonathan Chen * (try host.domain, host.*, *.domain or *.*) 380c5a096e0SJonathan Chen * if found, return yes 381c5a096e0SJonathan Chen * 1.c) if both host and user are specified, 382c5a096e0SJonathan Chen * don't do 'reverse netgroup' lookup. It won't work. 383c5a096e0SJonathan Chen * 1.d) if neither host ane user are specified (why?!?) 384c5a096e0SJonathan Chen * don't do 'reverse netgroup' lookup either. 385c5a096e0SJonathan Chen * 2) if domain is specified and 'reverse lookup' is done: 386c5a096e0SJonathan Chen * 'reverse lookup' was authoritative. bye bye. 387c5a096e0SJonathan Chen * 3) otherwise, too bad, try it the slow way. 3881e890b05SBill Paul */ 389c5a096e0SJonathan Chen if (_use_only_yp && (host == NULL) != (user == NULL)) { 390c5a096e0SJonathan Chen int ret; 3911e890b05SBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 3921e890b05SBill Paul return (0); 393c5a096e0SJonathan Chen ret = _revnetgr_lookup(_netgr_yp_domain, 394c5a096e0SJonathan Chen host?"netgroup.byhost":"netgroup.byuser", 395c5a096e0SJonathan Chen host?host:user, dom, group); 396c5a096e0SJonathan Chen if (ret == 1) 3971e890b05SBill Paul return (1); 398c5a096e0SJonathan Chen else if (ret == 0 && dom != NULL) 3991e890b05SBill Paul return (0); 4001e890b05SBill Paul } 401e882d43eSBill Paul 402e882d43eSBill Paul setnetgrent(group); 4031e890b05SBill Paul #endif /* YP */ 404e882d43eSBill Paul 40558f0484fSRodney W. Grimes while (getnetgrent(&hst, &usr, &dm)) 4061e890b05SBill Paul if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 4071e890b05SBill Paul (user == NULL || usr == NULL || !strcmp(user, usr)) && 4081e890b05SBill Paul ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 40958f0484fSRodney W. Grimes endnetgrent(); 41058f0484fSRodney W. Grimes return (1); 41158f0484fSRodney W. Grimes } 41258f0484fSRodney W. Grimes endnetgrent(); 41358f0484fSRodney W. Grimes return (0); 41458f0484fSRodney W. Grimes } 41558f0484fSRodney W. Grimes 41658f0484fSRodney W. Grimes /* 41758f0484fSRodney W. Grimes * Parse the netgroup file setting up the linked lists. 41858f0484fSRodney W. Grimes */ 41958f0484fSRodney W. Grimes static int 42076884596SDag-Erling Smørgrav parse_netgrp(const char *group) 42158f0484fSRodney W. Grimes { 4223d1d73c2SGuy Helmer struct netgrp *grp; 4233d1d73c2SGuy Helmer struct linelist *lp = linehead; 4243d1d73c2SGuy Helmer char **ng; 4253d1d73c2SGuy Helmer char *epos, *gpos, *pos, *spos; 4263d1d73c2SGuy Helmer int freepos, len, strpos; 427dbf973c0SBill Paul #ifdef DEBUG 42822626efaSDavid E. O'Brien int fields; 429dbf973c0SBill Paul #endif 43058f0484fSRodney W. Grimes 43158f0484fSRodney W. Grimes /* 43258f0484fSRodney W. Grimes * First, see if the line has already been read in. 43358f0484fSRodney W. Grimes */ 43458f0484fSRodney W. Grimes while (lp) { 43558f0484fSRodney W. Grimes if (!strcmp(group, lp->l_groupname)) 43658f0484fSRodney W. Grimes break; 43758f0484fSRodney W. Grimes lp = lp->l_next; 43858f0484fSRodney W. Grimes } 43958f0484fSRodney W. Grimes if (lp == (struct linelist *)0 && 44058f0484fSRodney W. Grimes (lp = read_for_group(group)) == (struct linelist *)0) 44158f0484fSRodney W. Grimes return (1); 44258f0484fSRodney W. Grimes if (lp->l_parsed) { 443dbf973c0SBill Paul #ifdef DEBUG 444dbf973c0SBill Paul /* 445dbf973c0SBill Paul * This error message is largely superflous since the 446dbf973c0SBill Paul * code handles the error condition sucessfully, and 447dbf973c0SBill Paul * spewing it out from inside libc can actually hose 448dbf973c0SBill Paul * certain programs. 449dbf973c0SBill Paul */ 45058f0484fSRodney W. Grimes fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 451dbf973c0SBill Paul #endif 45258f0484fSRodney W. Grimes return (1); 45358f0484fSRodney W. Grimes } else 45458f0484fSRodney W. Grimes lp->l_parsed = 1; 45558f0484fSRodney W. Grimes pos = lp->l_line; 456409495f6SBill Paul /* Watch for null pointer dereferences, dammit! */ 457409495f6SBill Paul while (pos != NULL && *pos != '\0') { 45858f0484fSRodney W. Grimes if (*pos == '(') { 4593d1d73c2SGuy Helmer grp = malloc(sizeof(*grp)); 460fed7420cSGuy Helmer if (grp == NULL) 461fed7420cSGuy Helmer return (1); 4623d1d73c2SGuy Helmer ng = grp->ng_str; 4633d1d73c2SGuy Helmer bzero(grp, sizeof(*grp)); 46458f0484fSRodney W. Grimes pos++; 46558f0484fSRodney W. Grimes gpos = strsep(&pos, ")"); 466dbf973c0SBill Paul #ifdef DEBUG 467dbf973c0SBill Paul fields = 0; 468dbf973c0SBill Paul #endif 46958f0484fSRodney W. Grimes for (strpos = 0; strpos < 3; strpos++) { 4703d1d73c2SGuy Helmer if ((spos = strsep(&gpos, ",")) == NULL) { 4713d1d73c2SGuy Helmer /* 4723d1d73c2SGuy Helmer * All other systems I've tested 4733d1d73c2SGuy Helmer * return NULL for empty netgroup 4743d1d73c2SGuy Helmer * fields. It's up to user programs 4753d1d73c2SGuy Helmer * to handle the NULLs appropriately. 4763d1d73c2SGuy Helmer */ 4773d1d73c2SGuy Helmer ng[strpos] = NULL; 4783d1d73c2SGuy Helmer continue; 4793d1d73c2SGuy Helmer } 480dbf973c0SBill Paul #ifdef DEBUG 481dbf973c0SBill Paul fields++; 482dbf973c0SBill Paul #endif 48358f0484fSRodney W. Grimes while (*spos == ' ' || *spos == '\t') 48458f0484fSRodney W. Grimes spos++; 4851e890b05SBill Paul if ((epos = strpbrk(spos, " \t"))) { 48658f0484fSRodney W. Grimes *epos = '\0'; 48758f0484fSRodney W. Grimes len = epos - spos; 48858f0484fSRodney W. Grimes } else 48958f0484fSRodney W. Grimes len = strlen(spos); 4903d1d73c2SGuy Helmer if (len <= 0) 4913d1d73c2SGuy Helmer continue; 4923d1d73c2SGuy Helmer ng[strpos] = malloc(len + 1); 4933d1d73c2SGuy Helmer if (ng[strpos] == NULL) { 4943d1d73c2SGuy Helmer for (freepos = 0; freepos < strpos; 4953d1d73c2SGuy Helmer freepos++) 4963d1d73c2SGuy Helmer free(ng[freepos]); 497fed7420cSGuy Helmer free(grp); 498fed7420cSGuy Helmer return (1); 499fed7420cSGuy Helmer } 5003d1d73c2SGuy Helmer bcopy(spos, ng[strpos], len + 1); 501dbf973c0SBill Paul } 502fed7420cSGuy Helmer grp->ng_next = grouphead.gr; 503fed7420cSGuy Helmer grouphead.gr = grp; 504dbf973c0SBill Paul #ifdef DEBUG 505dbf973c0SBill Paul /* 506dbf973c0SBill Paul * Note: on other platforms, malformed netgroup 507dbf973c0SBill Paul * entries are not normally flagged. While we 508dbf973c0SBill Paul * can catch bad entries and report them, we should 509dbf973c0SBill Paul * stay silent by default for compatibility's sake. 510dbf973c0SBill Paul */ 5113d1d73c2SGuy Helmer if (fields < 3) { 5123d1d73c2SGuy Helmer fprintf(stderr, 5133d1d73c2SGuy Helmer "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 5143d1d73c2SGuy Helmer ng[NG_HOST] == NULL ? "" : ng[NG_HOST], 5153d1d73c2SGuy Helmer ng[NG_USER] == NULL ? "" : ",", 5163d1d73c2SGuy Helmer ng[NG_USER] == NULL ? "" : ng[NG_USER], 5173d1d73c2SGuy Helmer ng[NG_DOM] == NULL ? "" : ",", 5183d1d73c2SGuy Helmer ng[NG_DOM] == NULL ? "" : ng[NG_DOM], 519dbf973c0SBill Paul lp->l_groupname); 520dbf973c0SBill Paul #endif 52158f0484fSRodney W. Grimes } else { 52258f0484fSRodney W. Grimes spos = strsep(&pos, ", \t"); 52358f0484fSRodney W. Grimes if (parse_netgrp(spos)) 524e8030794SBill Paul continue; 52558f0484fSRodney W. Grimes } 526adf6ad9eSPeter Wemm if (pos == NULL) 527adf6ad9eSPeter Wemm break; 52858f0484fSRodney W. Grimes while (*pos == ' ' || *pos == ',' || *pos == '\t') 52958f0484fSRodney W. Grimes pos++; 53058f0484fSRodney W. Grimes } 53158f0484fSRodney W. Grimes return (0); 53258f0484fSRodney W. Grimes } 53358f0484fSRodney W. Grimes 53458f0484fSRodney W. Grimes /* 53558f0484fSRodney W. Grimes * Read the netgroup file and save lines until the line for the netgroup 53658f0484fSRodney W. Grimes * is found. Return 1 if eof is encountered. 53758f0484fSRodney W. Grimes */ 53858f0484fSRodney W. Grimes static struct linelist * 53976884596SDag-Erling Smørgrav read_for_group(const char *group) 54058f0484fSRodney W. Grimes { 541fed7420cSGuy Helmer char *pos, *spos, *linep; 54222626efaSDavid E. O'Brien int len, olen; 54358f0484fSRodney W. Grimes int cont; 54458f0484fSRodney W. Grimes struct linelist *lp; 5451d2493ffSBill Paul char line[LINSIZ + 2]; 546409495f6SBill Paul #ifdef YP 547409495f6SBill Paul char *result; 548409495f6SBill Paul int resultlen; 549fed7420cSGuy Helmer linep = NULL; 55058f0484fSRodney W. Grimes 551409495f6SBill Paul while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 552409495f6SBill Paul if (_netgr_yp_enabled) { 553409495f6SBill Paul if(!_netgr_yp_domain) 5548516cd0fSBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 555409495f6SBill Paul continue; 5568516cd0fSBill Paul if (yp_match(_netgr_yp_domain, "netgroup", group, 5578516cd0fSBill Paul strlen(group), &result, &resultlen)) { 5588516cd0fSBill Paul free(result); 5591e890b05SBill Paul if (_use_only_yp) 5608516cd0fSBill Paul return ((struct linelist *)0); 5611e890b05SBill Paul else { 5621e890b05SBill Paul _netgr_yp_enabled = 0; 5631e890b05SBill Paul continue; 5641e890b05SBill Paul } 565409495f6SBill Paul } 5661d2493ffSBill Paul snprintf(line, LINSIZ, "%s %s", group, result); 567409495f6SBill Paul free(result); 568409495f6SBill Paul } 569409495f6SBill Paul #else 570fed7420cSGuy Helmer linep = NULL; 57158f0484fSRodney W. Grimes while (fgets(line, LINSIZ, netf) != NULL) { 572409495f6SBill Paul #endif 573409495f6SBill Paul pos = (char *)&line; 574409495f6SBill Paul #ifdef YP 575409495f6SBill Paul if (*pos == '+') { 576409495f6SBill Paul _netgr_yp_enabled = 1; 577409495f6SBill Paul continue; 578409495f6SBill Paul } 579409495f6SBill Paul #endif 58058f0484fSRodney W. Grimes if (*pos == '#') 58158f0484fSRodney W. Grimes continue; 58258f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 58358f0484fSRodney W. Grimes pos++; 58458f0484fSRodney W. Grimes spos = pos; 58558f0484fSRodney W. Grimes while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 58658f0484fSRodney W. Grimes *pos != '\0') 58758f0484fSRodney W. Grimes pos++; 58858f0484fSRodney W. Grimes len = pos - spos; 58958f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 59058f0484fSRodney W. Grimes pos++; 59158f0484fSRodney W. Grimes if (*pos != '\n' && *pos != '\0') { 59258f0484fSRodney W. Grimes lp = (struct linelist *)malloc(sizeof (*lp)); 593fed7420cSGuy Helmer if (lp == NULL) 594fed7420cSGuy Helmer return (NULL); 59558f0484fSRodney W. Grimes lp->l_parsed = 0; 59658f0484fSRodney W. Grimes lp->l_groupname = (char *)malloc(len + 1); 597fed7420cSGuy Helmer if (lp->l_groupname == NULL) { 598fed7420cSGuy Helmer free(lp); 599fed7420cSGuy Helmer return (NULL); 600fed7420cSGuy Helmer } 60158f0484fSRodney W. Grimes bcopy(spos, lp->l_groupname, len); 60258f0484fSRodney W. Grimes *(lp->l_groupname + len) = '\0'; 60358f0484fSRodney W. Grimes len = strlen(pos); 60458f0484fSRodney W. Grimes olen = 0; 60558f0484fSRodney W. Grimes 60658f0484fSRodney W. Grimes /* 60758f0484fSRodney W. Grimes * Loop around handling line continuations. 60858f0484fSRodney W. Grimes */ 60958f0484fSRodney W. Grimes do { 61058f0484fSRodney W. Grimes if (*(pos + len - 1) == '\n') 61158f0484fSRodney W. Grimes len--; 61258f0484fSRodney W. Grimes if (*(pos + len - 1) == '\\') { 61358f0484fSRodney W. Grimes len--; 61458f0484fSRodney W. Grimes cont = 1; 61558f0484fSRodney W. Grimes } else 61658f0484fSRodney W. Grimes cont = 0; 61758f0484fSRodney W. Grimes if (len > 0) { 6183d1d73c2SGuy Helmer linep = reallocf(linep, olen + len + 1); 619fed7420cSGuy Helmer if (linep == NULL) { 620fed7420cSGuy Helmer free(lp->l_groupname); 621fed7420cSGuy Helmer free(lp); 622fed7420cSGuy Helmer return (NULL); 62358f0484fSRodney W. Grimes } 62458f0484fSRodney W. Grimes bcopy(pos, linep + olen, len); 62558f0484fSRodney W. Grimes olen += len; 62658f0484fSRodney W. Grimes *(linep + olen) = '\0'; 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