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 * 3. All advertising materials mentioning features or use of this software 1758f0484fSRodney W. Grimes * must display the following acknowledgement: 1858f0484fSRodney W. Grimes * This product includes software developed by the University of 1958f0484fSRodney W. Grimes * California, Berkeley and its contributors. 2058f0484fSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 2158f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 2258f0484fSRodney W. Grimes * without specific prior written permission. 2358f0484fSRodney W. Grimes * 2458f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2558f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2658f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2758f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2858f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2958f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3058f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3158f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3258f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3358f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3458f0484fSRodney W. Grimes * SUCH DAMAGE. 3558f0484fSRodney W. Grimes */ 3658f0484fSRodney W. Grimes 3758f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 38adf6ad9eSPeter Wemm static char sccsid[] = "@(#)getnetgrent.c 8.2 (Berkeley) 4/27/95"; 3958f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 4022626efaSDavid E. O'Brien #include <sys/cdefs.h> 4122626efaSDavid E. O'Brien __FBSDID("$FreeBSD$"); 4258f0484fSRodney W. Grimes 43185ec971STim J. Robbins #include <ctype.h> 4458f0484fSRodney W. Grimes #include <stdio.h> 45958f4e36SBill Paul #include <stdlib.h> 4673c9eb2fSDag-Erling Smørgrav #include <string.h> 47958f4e36SBill Paul #include <unistd.h> 48958f4e36SBill Paul 49958f4e36SBill Paul #ifdef YP 501e890b05SBill Paul /* 511e890b05SBill Paul * Notes: 521e890b05SBill Paul * We want to be able to use NIS netgroups properly while retaining 531e890b05SBill Paul * the ability to use a local /etc/netgroup file. Unfortunately, you 541e890b05SBill Paul * can't really do both at the same time - at least, not efficiently. 551e890b05SBill Paul * NetBSD deals with this problem by creating a netgroup database 561e890b05SBill Paul * using Berkeley DB (just like the password database) that allows 571e890b05SBill Paul * for lookups using netgroup, netgroup.byuser or netgroup.byhost 581e890b05SBill Paul * searches. This is a neat idea, but I don't have time to implement 591e890b05SBill Paul * something like that now. (I think ultimately it would be nice 601e890b05SBill Paul * if we DB-fied the group and netgroup stuff all in one shot, but 611e890b05SBill Paul * for now I'm satisfied just to have something that works well 621e890b05SBill Paul * without requiring massive code changes.) 631e890b05SBill Paul * 641e890b05SBill Paul * Therefore, to still permit the use of the local file and maintain 651e890b05SBill Paul * optimum NIS performance, we allow for the following conditions: 661e890b05SBill Paul * 671e890b05SBill Paul * - If /etc/netgroup does not exist and NIS is turned on, we use 681e890b05SBill Paul * NIS netgroups only. 691e890b05SBill Paul * 701e890b05SBill Paul * - If /etc/netgroup exists but is empty, we use NIS netgroups 711e890b05SBill Paul * only. 721e890b05SBill Paul * 731e890b05SBill Paul * - If /etc/netgroup exists and contains _only_ a '+', we use 741e890b05SBill Paul * NIS netgroups only. 751e890b05SBill Paul * 761e890b05SBill Paul * - If /etc/netgroup exists, contains locally defined netgroups 771e890b05SBill Paul * and a '+', we use a mixture of NIS and the local entries. 781e890b05SBill Paul * This method should return the same NIS data as just using 791e890b05SBill Paul * NIS alone, but it will be slower if the NIS netgroup database 801e890b05SBill Paul * is large (innetgr() in particular will suffer since extra 811e890b05SBill Paul * processing has to be done in order to determine memberships 821e890b05SBill Paul * using just the raw netgroup data). 831e890b05SBill Paul * 841e890b05SBill Paul * - If /etc/netgroup exists and contains only locally defined 851e890b05SBill Paul * netgroup entries, we use just those local entries and ignore 861e890b05SBill Paul * NIS (this is the original, pre-NIS behavior). 871e890b05SBill Paul */ 88c17942caSBill Paul 89958f4e36SBill Paul #include <rpc/rpc.h> 90958f4e36SBill Paul #include <rpcsvc/yp_prot.h> 91958f4e36SBill Paul #include <rpcsvc/ypclnt.h> 921e890b05SBill Paul #include <sys/types.h> 931e890b05SBill Paul #include <sys/stat.h> 941e890b05SBill Paul #include <sys/param.h> 951e890b05SBill Paul #include <sys/errno.h> 961e890b05SBill Paul static char *_netgr_yp_domain; 97d454389cSBill Paul int _use_only_yp; 98958f4e36SBill Paul static int _netgr_yp_enabled; 991e890b05SBill Paul static int _yp_innetgr; 100958f4e36SBill Paul #endif 10158f0484fSRodney W. Grimes 1021e890b05SBill Paul #ifndef _PATH_NETGROUP 10358f0484fSRodney W. Grimes #define _PATH_NETGROUP "/etc/netgroup" 1041e890b05SBill Paul #endif 10558f0484fSRodney W. Grimes 10658f0484fSRodney W. Grimes /* 10758f0484fSRodney W. Grimes * Static Variables and functions used by setnetgrent(), getnetgrent() and 10858f0484fSRodney W. Grimes * endnetgrent(). 10958f0484fSRodney W. Grimes * There are two linked lists: 11058f0484fSRodney W. Grimes * - linelist is just used by setnetgrent() to parse the net group file via. 11158f0484fSRodney W. Grimes * parse_netgrp() 11258f0484fSRodney W. Grimes * - netgrp is the list of entries for the current netgroup 11358f0484fSRodney W. Grimes */ 11458f0484fSRodney W. Grimes struct linelist { 11558f0484fSRodney W. Grimes struct linelist *l_next; /* Chain ptr. */ 11658f0484fSRodney W. Grimes int l_parsed; /* Flag for cycles */ 11758f0484fSRodney W. Grimes char *l_groupname; /* Name of netgroup */ 11858f0484fSRodney W. Grimes char *l_line; /* Netgroup entrie(s) to be parsed */ 11958f0484fSRodney W. Grimes }; 12058f0484fSRodney W. Grimes 12158f0484fSRodney W. Grimes struct netgrp { 12258f0484fSRodney W. Grimes struct netgrp *ng_next; /* Chain ptr */ 12358f0484fSRodney W. Grimes char *ng_str[3]; /* Field pointers, see below */ 12458f0484fSRodney W. Grimes }; 12558f0484fSRodney W. Grimes #define NG_HOST 0 /* Host name */ 12658f0484fSRodney W. Grimes #define NG_USER 1 /* User name */ 12758f0484fSRodney W. Grimes #define NG_DOM 2 /* and Domain name */ 12858f0484fSRodney W. Grimes 12958f0484fSRodney W. Grimes static struct linelist *linehead = (struct linelist *)0; 13058f0484fSRodney W. Grimes static struct netgrp *nextgrp = (struct netgrp *)0; 13158f0484fSRodney W. Grimes static struct { 13258f0484fSRodney W. Grimes struct netgrp *gr; 13358f0484fSRodney W. Grimes char *grname; 13458f0484fSRodney W. Grimes } grouphead = { 13558f0484fSRodney W. Grimes (struct netgrp *)0, 13658f0484fSRodney W. Grimes (char *)0, 13758f0484fSRodney W. Grimes }; 13858f0484fSRodney W. Grimes static FILE *netf = (FILE *)0; 13958f0484fSRodney W. Grimes static int parse_netgrp(); 14058f0484fSRodney W. Grimes static struct linelist *read_for_group(); 14158f0484fSRodney W. Grimes void setnetgrent(), endnetgrent(); 14258f0484fSRodney W. Grimes int getnetgrent(), innetgr(); 14358f0484fSRodney W. Grimes 14458f0484fSRodney W. Grimes #define LINSIZ 1024 /* Length of netgroup file line */ 14558f0484fSRodney W. Grimes 14658f0484fSRodney W. Grimes /* 14758f0484fSRodney W. Grimes * setnetgrent() 14858f0484fSRodney W. Grimes * Parse the netgroup file looking for the netgroup and build the list 14958f0484fSRodney W. Grimes * of netgrp structures. Let parse_netgrp() and read_for_group() do 15058f0484fSRodney W. Grimes * most of the work. 15158f0484fSRodney W. Grimes */ 15258f0484fSRodney W. Grimes void 15358f0484fSRodney W. Grimes setnetgrent(group) 15458f0484fSRodney W. Grimes char *group; 15558f0484fSRodney W. Grimes { 1561e890b05SBill Paul #ifdef YP 1571e890b05SBill Paul struct stat _yp_statp; 1581e890b05SBill Paul char _yp_plus; 1591e890b05SBill Paul #endif 1601e890b05SBill Paul 1610ffe27f5SBill Paul /* Sanity check */ 16262a77170SBill Paul 1630ffe27f5SBill Paul if (group == NULL || !strlen(group)) 16462a77170SBill Paul return; 1650ffe27f5SBill Paul 16658f0484fSRodney W. Grimes if (grouphead.gr == (struct netgrp *)0 || 16758f0484fSRodney W. Grimes strcmp(group, grouphead.grname)) { 16858f0484fSRodney W. Grimes endnetgrent(); 1691e890b05SBill Paul #ifdef YP 170d454389cSBill Paul /* Presumed guilty until proven innocent. */ 171d454389cSBill Paul _use_only_yp = 0; 1721e890b05SBill Paul /* 173cbe78b44SBill Paul * If /etc/netgroup doesn't exist or is empty, 1741e890b05SBill Paul * use NIS exclusively. 1751e890b05SBill Paul */ 1761e890b05SBill Paul if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && 1771e890b05SBill Paul errno == ENOENT) || _yp_statp.st_size == 0) 1781e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1791e890b05SBill Paul if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){ 1801e890b05SBill Paul /* 1811e890b05SBill Paul * Icky: grab the first character of the netgroup file 1821e890b05SBill Paul * and turn on NIS if it's a '+'. rewind the stream 1831e890b05SBill Paul * afterwards so we don't goof up read_for_group() later. 1841e890b05SBill Paul */ 1851e890b05SBill Paul if (netf) { 1861e890b05SBill Paul fscanf(netf, "%c", &_yp_plus); 1871e890b05SBill Paul rewind(netf); 1881e890b05SBill Paul if (_yp_plus == '+') 1891e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1901e890b05SBill Paul } 1911e890b05SBill Paul /* 1921e890b05SBill Paul * If we were called specifically for an innetgr() 1931e890b05SBill Paul * lookup and we're in NIS-only mode, short-circuit 1941e890b05SBill Paul * parse_netgroup() and cut directly to the chase. 1951e890b05SBill Paul */ 196d454389cSBill Paul if (_use_only_yp && _yp_innetgr) { 197d454389cSBill Paul /* dohw! */ 198de32dbbdSBill Paul if (netf != NULL) 199d454389cSBill Paul fclose(netf); 2001e890b05SBill Paul return; 201d454389cSBill Paul } 2021e890b05SBill Paul #else 20358f0484fSRodney W. Grimes if (netf = fopen(_PATH_NETGROUP, "r")) { 2041e890b05SBill Paul #endif 20558f0484fSRodney W. Grimes if (parse_netgrp(group)) 20658f0484fSRodney W. Grimes endnetgrent(); 20758f0484fSRodney W. Grimes else { 20858f0484fSRodney W. Grimes grouphead.grname = (char *) 20958f0484fSRodney W. Grimes malloc(strlen(group) + 1); 21058f0484fSRodney W. Grimes strcpy(grouphead.grname, group); 21158f0484fSRodney W. Grimes } 2121e890b05SBill Paul if (netf) 21358f0484fSRodney W. Grimes fclose(netf); 21458f0484fSRodney W. Grimes } 21558f0484fSRodney W. Grimes } 21658f0484fSRodney W. Grimes nextgrp = grouphead.gr; 21758f0484fSRodney W. Grimes } 21858f0484fSRodney W. Grimes 21958f0484fSRodney W. Grimes /* 22058f0484fSRodney W. Grimes * Get the next netgroup off the list. 22158f0484fSRodney W. Grimes */ 22258f0484fSRodney W. Grimes int 22358f0484fSRodney W. Grimes getnetgrent(hostp, userp, domp) 22458f0484fSRodney W. Grimes char **hostp, **userp, **domp; 22558f0484fSRodney W. Grimes { 2261e890b05SBill Paul #ifdef YP 2271e890b05SBill Paul _yp_innetgr = 0; 2281e890b05SBill Paul #endif 22958f0484fSRodney W. Grimes 23058f0484fSRodney W. Grimes if (nextgrp) { 23158f0484fSRodney W. Grimes *hostp = nextgrp->ng_str[NG_HOST]; 23258f0484fSRodney W. Grimes *userp = nextgrp->ng_str[NG_USER]; 23358f0484fSRodney W. Grimes *domp = nextgrp->ng_str[NG_DOM]; 23458f0484fSRodney W. Grimes nextgrp = nextgrp->ng_next; 23558f0484fSRodney W. Grimes return (1); 23658f0484fSRodney W. Grimes } 23758f0484fSRodney W. Grimes return (0); 23858f0484fSRodney W. Grimes } 23958f0484fSRodney W. Grimes 24058f0484fSRodney W. Grimes /* 24158f0484fSRodney W. Grimes * endnetgrent() - cleanup 24258f0484fSRodney W. Grimes */ 24358f0484fSRodney W. Grimes void 24458f0484fSRodney W. Grimes endnetgrent() 24558f0484fSRodney W. Grimes { 24622626efaSDavid E. O'Brien struct linelist *lp, *olp; 24722626efaSDavid E. O'Brien struct netgrp *gp, *ogp; 24858f0484fSRodney W. Grimes 24958f0484fSRodney W. Grimes lp = linehead; 25058f0484fSRodney W. Grimes while (lp) { 25158f0484fSRodney W. Grimes olp = lp; 25258f0484fSRodney W. Grimes lp = lp->l_next; 25358f0484fSRodney W. Grimes free(olp->l_groupname); 25458f0484fSRodney W. Grimes free(olp->l_line); 25558f0484fSRodney W. Grimes free((char *)olp); 25658f0484fSRodney W. Grimes } 25758f0484fSRodney W. Grimes linehead = (struct linelist *)0; 25858f0484fSRodney W. Grimes if (grouphead.grname) { 25958f0484fSRodney W. Grimes free(grouphead.grname); 26058f0484fSRodney W. Grimes grouphead.grname = (char *)0; 26158f0484fSRodney W. Grimes } 26258f0484fSRodney W. Grimes gp = grouphead.gr; 26358f0484fSRodney W. Grimes while (gp) { 26458f0484fSRodney W. Grimes ogp = gp; 26558f0484fSRodney W. Grimes gp = gp->ng_next; 26658f0484fSRodney W. Grimes if (ogp->ng_str[NG_HOST]) 26758f0484fSRodney W. Grimes free(ogp->ng_str[NG_HOST]); 26858f0484fSRodney W. Grimes if (ogp->ng_str[NG_USER]) 26958f0484fSRodney W. Grimes free(ogp->ng_str[NG_USER]); 27058f0484fSRodney W. Grimes if (ogp->ng_str[NG_DOM]) 27158f0484fSRodney W. Grimes free(ogp->ng_str[NG_DOM]); 27258f0484fSRodney W. Grimes free((char *)ogp); 27358f0484fSRodney W. Grimes } 27458f0484fSRodney W. Grimes grouphead.gr = (struct netgrp *)0; 275409495f6SBill Paul #ifdef YP 2768516cd0fSBill Paul _netgr_yp_enabled = 0; 277409495f6SBill Paul #endif 27858f0484fSRodney W. Grimes } 27958f0484fSRodney W. Grimes 2801e890b05SBill Paul #ifdef YP 28122397ec3SBill Paul static int _listmatch(list, group, len) 2821e890b05SBill Paul char *list, *group; 28322397ec3SBill Paul int len; 2841e890b05SBill Paul { 285d9cc92f5SBill Paul char *ptr = list, *cptr; 286d9cc92f5SBill Paul int glen = strlen(group); 2871e890b05SBill Paul 288d9cc92f5SBill Paul /* skip possible leading whitespace */ 28949435560SAndrey A. Chernov while(isspace((unsigned char)*ptr)) 290d9cc92f5SBill Paul ptr++; 291cbe78b44SBill Paul 292d9cc92f5SBill Paul while (ptr < list + len) { 293d9cc92f5SBill Paul cptr = ptr; 29449435560SAndrey A. Chernov while(*ptr != ',' && *ptr != '\0' && !isspace((unsigned char)*ptr)) 295d9cc92f5SBill Paul ptr++; 296f48bc662SSteve Price if (strncmp(cptr, group, glen) == 0 && glen == (ptr - cptr)) 2971e890b05SBill Paul return(1); 29849435560SAndrey A. Chernov while(*ptr == ',' || isspace((unsigned char)*ptr)) 299d9cc92f5SBill Paul ptr++; 300dfe8e51cSBill Paul } 301cbe78b44SBill Paul 3021e890b05SBill Paul return(0); 3031e890b05SBill Paul } 3041e890b05SBill Paul 3051e890b05SBill Paul static int _buildkey(key, str, dom, rotation) 3061e890b05SBill Paul char *key, *str, *dom; 3071e890b05SBill Paul int *rotation; 3081e890b05SBill Paul { 3091e890b05SBill Paul (*rotation)++; 3101e890b05SBill Paul if (*rotation > 4) 3111e890b05SBill Paul return(0); 3121e890b05SBill Paul switch(*rotation) { 3131e890b05SBill Paul case(1): sprintf((char *)key, "%s.%s", str, dom ? dom : "*"); 3141e890b05SBill Paul break; 3151e890b05SBill Paul case(2): sprintf((char *)key, "%s.*", str); 3161e890b05SBill Paul break; 3171e890b05SBill Paul case(3): sprintf((char *)key, "*.%s", dom ? dom : "*"); 3181e890b05SBill Paul break; 3191e890b05SBill Paul case(4): sprintf((char *)key, "*.*"); 3201e890b05SBill Paul break; 3211e890b05SBill Paul } 3221e890b05SBill Paul return(1); 3231e890b05SBill Paul } 3241e890b05SBill Paul #endif 3251e890b05SBill Paul 32658f0484fSRodney W. Grimes /* 32758f0484fSRodney W. Grimes * Search for a match in a netgroup. 32858f0484fSRodney W. Grimes */ 32958f0484fSRodney W. Grimes int 33058f0484fSRodney W. Grimes innetgr(group, host, user, dom) 33151295a4dSJordan K. Hubbard const char *group, *host, *user, *dom; 33258f0484fSRodney W. Grimes { 33358f0484fSRodney W. Grimes char *hst, *usr, *dm; 3341e890b05SBill Paul #ifdef YP 3351e890b05SBill Paul char *result; 3361e890b05SBill Paul int resultlen; 337cbe78b44SBill Paul int rv; 3381e890b05SBill Paul #endif 3390ffe27f5SBill Paul /* Sanity check */ 3400ffe27f5SBill Paul 3410ffe27f5SBill Paul if (group == NULL || !strlen(group)) 3420ffe27f5SBill Paul return (0); 3430ffe27f5SBill Paul 3441e890b05SBill Paul #ifdef YP 3451e890b05SBill Paul _yp_innetgr = 1; 3461e890b05SBill Paul #endif 34758f0484fSRodney W. Grimes setnetgrent(group); 3481e890b05SBill Paul #ifdef YP 349cbe78b44SBill Paul _yp_innetgr = 0; 3501e890b05SBill Paul /* 3511e890b05SBill Paul * If we're in NIS-only mode, do the search using 3521e890b05SBill Paul * NIS 'reverse netgroup' lookups. 3531e890b05SBill Paul */ 3541e890b05SBill Paul if (_use_only_yp) { 3551e890b05SBill Paul char _key[MAXHOSTNAMELEN]; 356e882d43eSBill Paul int rot = 0, y = 0; 3571e890b05SBill Paul 3581e890b05SBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 3591e890b05SBill Paul return(0); 36041864740SJordan K. Hubbard while(_buildkey(_key, user ? user : host, dom, &rot)) { 361e882d43eSBill Paul y = yp_match(_netgr_yp_domain, user? "netgroup.byuser": 3621e890b05SBill Paul "netgroup.byhost", _key, strlen(_key), &result, 363e882d43eSBill Paul &resultlen); 364e882d43eSBill Paul if (y) { 365e882d43eSBill Paul /* 366e882d43eSBill Paul * If we get an error other than 'no 367e882d43eSBill Paul * such key in map' then something is 368e882d43eSBill Paul * wrong and we should stop the search. 369e882d43eSBill Paul */ 370e882d43eSBill Paul if (y != YPERR_KEY) 371e882d43eSBill Paul break; 372e882d43eSBill Paul } else { 373cbe78b44SBill Paul rv = _listmatch(result, group, resultlen); 3741e890b05SBill Paul free(result); 375cbe78b44SBill Paul if (rv) 3761e890b05SBill Paul return(1); 377cbe78b44SBill Paul else 378cbe78b44SBill Paul return(0); 3791e890b05SBill Paul } 3801e890b05SBill Paul } 3811e890b05SBill Paul /* 382e882d43eSBill Paul * Couldn't match using NIS-exclusive mode. If the error 383e882d43eSBill Paul * was YPERR_MAP, then the failure happened because there 384e882d43eSBill Paul * was no netgroup.byhost or netgroup.byuser map. The odds 385d64ada50SJens Schweikhardt * are we are talking to a Sun NIS+ server in YP emulation 386e882d43eSBill Paul * mode; if this is the case, then we have to do the check 387e882d43eSBill Paul * the 'old-fashioned' way by grovelling through the netgroup 388e882d43eSBill Paul * map and resolving memberships on the fly. 3891e890b05SBill Paul */ 390e882d43eSBill Paul if (y != YPERR_MAP) 3911e890b05SBill Paul return(0); 3921e890b05SBill Paul } 393e882d43eSBill Paul 394e882d43eSBill Paul setnetgrent(group); 3951e890b05SBill Paul #endif /* YP */ 396e882d43eSBill Paul 39758f0484fSRodney W. Grimes while (getnetgrent(&hst, &usr, &dm)) 3981e890b05SBill Paul if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 3991e890b05SBill Paul (user == NULL || usr == NULL || !strcmp(user, usr)) && 4001e890b05SBill Paul ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 40158f0484fSRodney W. Grimes endnetgrent(); 40258f0484fSRodney W. Grimes return (1); 40358f0484fSRodney W. Grimes } 40458f0484fSRodney W. Grimes endnetgrent(); 40558f0484fSRodney W. Grimes return (0); 40658f0484fSRodney W. Grimes } 40758f0484fSRodney W. Grimes 40858f0484fSRodney W. Grimes /* 40958f0484fSRodney W. Grimes * Parse the netgroup file setting up the linked lists. 41058f0484fSRodney W. Grimes */ 41158f0484fSRodney W. Grimes static int 41258f0484fSRodney W. Grimes parse_netgrp(group) 41358f0484fSRodney W. Grimes char *group; 41458f0484fSRodney W. Grimes { 41522626efaSDavid E. O'Brien char *spos, *epos; 41622626efaSDavid E. O'Brien int len, strpos; 417dbf973c0SBill Paul #ifdef DEBUG 41822626efaSDavid E. O'Brien int fields; 419dbf973c0SBill Paul #endif 42058f0484fSRodney W. Grimes char *pos, *gpos; 42158f0484fSRodney W. Grimes struct netgrp *grp; 42258f0484fSRodney W. Grimes struct linelist *lp = linehead; 42358f0484fSRodney W. Grimes 42458f0484fSRodney W. Grimes /* 42558f0484fSRodney W. Grimes * First, see if the line has already been read in. 42658f0484fSRodney W. Grimes */ 42758f0484fSRodney W. Grimes while (lp) { 42858f0484fSRodney W. Grimes if (!strcmp(group, lp->l_groupname)) 42958f0484fSRodney W. Grimes break; 43058f0484fSRodney W. Grimes lp = lp->l_next; 43158f0484fSRodney W. Grimes } 43258f0484fSRodney W. Grimes if (lp == (struct linelist *)0 && 43358f0484fSRodney W. Grimes (lp = read_for_group(group)) == (struct linelist *)0) 43458f0484fSRodney W. Grimes return (1); 43558f0484fSRodney W. Grimes if (lp->l_parsed) { 436dbf973c0SBill Paul #ifdef DEBUG 437dbf973c0SBill Paul /* 438dbf973c0SBill Paul * This error message is largely superflous since the 439dbf973c0SBill Paul * code handles the error condition sucessfully, and 440dbf973c0SBill Paul * spewing it out from inside libc can actually hose 441dbf973c0SBill Paul * certain programs. 442dbf973c0SBill Paul */ 44358f0484fSRodney W. Grimes fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 444dbf973c0SBill Paul #endif 44558f0484fSRodney W. Grimes return (1); 44658f0484fSRodney W. Grimes } else 44758f0484fSRodney W. Grimes lp->l_parsed = 1; 44858f0484fSRodney W. Grimes pos = lp->l_line; 449409495f6SBill Paul /* Watch for null pointer dereferences, dammit! */ 450409495f6SBill Paul while (pos != NULL && *pos != '\0') { 45158f0484fSRodney W. Grimes if (*pos == '(') { 45258f0484fSRodney W. Grimes grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 45358f0484fSRodney W. Grimes bzero((char *)grp, sizeof (struct netgrp)); 45458f0484fSRodney W. Grimes grp->ng_next = grouphead.gr; 45558f0484fSRodney W. Grimes grouphead.gr = grp; 45658f0484fSRodney W. Grimes pos++; 45758f0484fSRodney W. Grimes gpos = strsep(&pos, ")"); 458dbf973c0SBill Paul #ifdef DEBUG 459dbf973c0SBill Paul fields = 0; 460dbf973c0SBill Paul #endif 46158f0484fSRodney W. Grimes for (strpos = 0; strpos < 3; strpos++) { 4621e890b05SBill Paul if ((spos = strsep(&gpos, ","))) { 463dbf973c0SBill Paul #ifdef DEBUG 464dbf973c0SBill Paul fields++; 465dbf973c0SBill Paul #endif 46658f0484fSRodney W. Grimes while (*spos == ' ' || *spos == '\t') 46758f0484fSRodney W. Grimes spos++; 4681e890b05SBill Paul if ((epos = strpbrk(spos, " \t"))) { 46958f0484fSRodney W. Grimes *epos = '\0'; 47058f0484fSRodney W. Grimes len = epos - spos; 47158f0484fSRodney W. Grimes } else 47258f0484fSRodney W. Grimes len = strlen(spos); 47358f0484fSRodney W. Grimes if (len > 0) { 47458f0484fSRodney W. Grimes grp->ng_str[strpos] = (char *) 47558f0484fSRodney W. Grimes malloc(len + 1); 47658f0484fSRodney W. Grimes bcopy(spos, grp->ng_str[strpos], 47758f0484fSRodney W. Grimes len + 1); 47858f0484fSRodney W. Grimes } 479dbf973c0SBill Paul } else { 480dbf973c0SBill Paul /* 481dbf973c0SBill Paul * All other systems I've tested 482dbf973c0SBill Paul * return NULL for empty netgroup 483dbf973c0SBill Paul * fields. It's up to user programs 484dbf973c0SBill Paul * to handle the NULLs appropriately. 485dbf973c0SBill Paul */ 486dbf973c0SBill Paul grp->ng_str[strpos] = NULL; 48758f0484fSRodney W. Grimes } 488dbf973c0SBill Paul } 489dbf973c0SBill Paul #ifdef DEBUG 490dbf973c0SBill Paul /* 491dbf973c0SBill Paul * Note: on other platforms, malformed netgroup 492dbf973c0SBill Paul * entries are not normally flagged. While we 493dbf973c0SBill Paul * can catch bad entries and report them, we should 494dbf973c0SBill Paul * stay silent by default for compatibility's sake. 495dbf973c0SBill Paul */ 496dbf973c0SBill Paul if (fields < 3) 497dbf973c0SBill Paul fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 498dbf973c0SBill Paul grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], 499dbf973c0SBill Paul grp->ng_str[NG_USER] == NULL ? "" : ",", 500dbf973c0SBill Paul grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], 501dbf973c0SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : ",", 502dbf973c0SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], 503dbf973c0SBill Paul lp->l_groupname); 504dbf973c0SBill Paul #endif 50558f0484fSRodney W. Grimes } else { 50658f0484fSRodney W. Grimes spos = strsep(&pos, ", \t"); 50758f0484fSRodney W. Grimes if (parse_netgrp(spos)) 508e8030794SBill Paul continue; 50958f0484fSRodney W. Grimes } 510adf6ad9eSPeter Wemm if (pos == NULL) 511adf6ad9eSPeter Wemm break; 51258f0484fSRodney W. Grimes while (*pos == ' ' || *pos == ',' || *pos == '\t') 51358f0484fSRodney W. Grimes pos++; 51458f0484fSRodney W. Grimes } 51558f0484fSRodney W. Grimes return (0); 51658f0484fSRodney W. Grimes } 51758f0484fSRodney W. Grimes 51858f0484fSRodney W. Grimes /* 51958f0484fSRodney W. Grimes * Read the netgroup file and save lines until the line for the netgroup 52058f0484fSRodney W. Grimes * is found. Return 1 if eof is encountered. 52158f0484fSRodney W. Grimes */ 52258f0484fSRodney W. Grimes static struct linelist * 52358f0484fSRodney W. Grimes read_for_group(group) 52458f0484fSRodney W. Grimes char *group; 52558f0484fSRodney W. Grimes { 52622626efaSDavid E. O'Brien char *pos, *spos, *linep, *olinep; 52722626efaSDavid E. O'Brien int len, olen; 52858f0484fSRodney W. Grimes int cont; 52958f0484fSRodney W. Grimes struct linelist *lp; 5301d2493ffSBill Paul char line[LINSIZ + 2]; 531409495f6SBill Paul #ifdef YP 532409495f6SBill Paul char *result; 533409495f6SBill Paul int resultlen; 53458f0484fSRodney W. Grimes 535409495f6SBill Paul while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 536409495f6SBill Paul if (_netgr_yp_enabled) { 537409495f6SBill Paul if(!_netgr_yp_domain) 5388516cd0fSBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 539409495f6SBill Paul continue; 5408516cd0fSBill Paul if (yp_match(_netgr_yp_domain, "netgroup", group, 5418516cd0fSBill Paul strlen(group), &result, &resultlen)) { 5428516cd0fSBill Paul free(result); 5431e890b05SBill Paul if (_use_only_yp) 5448516cd0fSBill Paul return ((struct linelist *)0); 5451e890b05SBill Paul else { 5461e890b05SBill Paul _netgr_yp_enabled = 0; 5471e890b05SBill Paul continue; 5481e890b05SBill Paul } 549409495f6SBill Paul } 5501d2493ffSBill Paul snprintf(line, LINSIZ, "%s %s", group, result); 551409495f6SBill Paul free(result); 552409495f6SBill Paul } 553409495f6SBill Paul #else 55458f0484fSRodney W. Grimes while (fgets(line, LINSIZ, netf) != NULL) { 555409495f6SBill Paul #endif 556409495f6SBill Paul pos = (char *)&line; 557409495f6SBill Paul #ifdef YP 558409495f6SBill Paul if (*pos == '+') { 559409495f6SBill Paul _netgr_yp_enabled = 1; 560409495f6SBill Paul continue; 561409495f6SBill Paul } 562409495f6SBill Paul #endif 56358f0484fSRodney W. Grimes if (*pos == '#') 56458f0484fSRodney W. Grimes continue; 56558f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 56658f0484fSRodney W. Grimes pos++; 56758f0484fSRodney W. Grimes spos = pos; 56858f0484fSRodney W. Grimes while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 56958f0484fSRodney W. Grimes *pos != '\0') 57058f0484fSRodney W. Grimes pos++; 57158f0484fSRodney W. Grimes len = pos - spos; 57258f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 57358f0484fSRodney W. Grimes pos++; 57458f0484fSRodney W. Grimes if (*pos != '\n' && *pos != '\0') { 57558f0484fSRodney W. Grimes lp = (struct linelist *)malloc(sizeof (*lp)); 57658f0484fSRodney W. Grimes lp->l_parsed = 0; 57758f0484fSRodney W. Grimes lp->l_groupname = (char *)malloc(len + 1); 57858f0484fSRodney W. Grimes bcopy(spos, lp->l_groupname, len); 57958f0484fSRodney W. Grimes *(lp->l_groupname + len) = '\0'; 58058f0484fSRodney W. Grimes len = strlen(pos); 58158f0484fSRodney W. Grimes olen = 0; 58258f0484fSRodney W. Grimes 58358f0484fSRodney W. Grimes /* 58458f0484fSRodney W. Grimes * Loop around handling line continuations. 58558f0484fSRodney W. Grimes */ 58658f0484fSRodney W. Grimes do { 58758f0484fSRodney W. Grimes if (*(pos + len - 1) == '\n') 58858f0484fSRodney W. Grimes len--; 58958f0484fSRodney W. Grimes if (*(pos + len - 1) == '\\') { 59058f0484fSRodney W. Grimes len--; 59158f0484fSRodney W. Grimes cont = 1; 59258f0484fSRodney W. Grimes } else 59358f0484fSRodney W. Grimes cont = 0; 59458f0484fSRodney W. Grimes if (len > 0) { 59558f0484fSRodney W. Grimes linep = (char *)malloc(olen + len + 1); 59658f0484fSRodney W. Grimes if (olen > 0) { 59758f0484fSRodney W. Grimes bcopy(olinep, linep, olen); 59858f0484fSRodney W. Grimes free(olinep); 59958f0484fSRodney W. Grimes } 60058f0484fSRodney W. Grimes bcopy(pos, linep + olen, len); 60158f0484fSRodney W. Grimes olen += len; 60258f0484fSRodney W. Grimes *(linep + olen) = '\0'; 60358f0484fSRodney W. Grimes olinep = linep; 60458f0484fSRodney W. Grimes } 60558f0484fSRodney W. Grimes if (cont) { 60658f0484fSRodney W. Grimes if (fgets(line, LINSIZ, netf)) { 60758f0484fSRodney W. Grimes pos = line; 60858f0484fSRodney W. Grimes len = strlen(pos); 60958f0484fSRodney W. Grimes } else 61058f0484fSRodney W. Grimes cont = 0; 61158f0484fSRodney W. Grimes } 61258f0484fSRodney W. Grimes } while (cont); 61358f0484fSRodney W. Grimes lp->l_line = linep; 61458f0484fSRodney W. Grimes lp->l_next = linehead; 61558f0484fSRodney W. Grimes linehead = lp; 61658f0484fSRodney W. Grimes 61758f0484fSRodney W. Grimes /* 61858f0484fSRodney W. Grimes * If this is the one we wanted, we are done. 61958f0484fSRodney W. Grimes */ 62058f0484fSRodney W. Grimes if (!strcmp(lp->l_groupname, group)) 62158f0484fSRodney W. Grimes return (lp); 62258f0484fSRodney W. Grimes } 62358f0484fSRodney W. Grimes } 6241e890b05SBill Paul #ifdef YP 6251e890b05SBill Paul /* 6261e890b05SBill Paul * Yucky. The recursive nature of this whole mess might require 6271e890b05SBill Paul * us to make more than one pass through the netgroup file. 6281e890b05SBill Paul * This might be best left outside the #ifdef YP, but YP is 6291e890b05SBill Paul * defined by default anyway, so I'll leave it like this 6301e890b05SBill Paul * until I know better. 6311e890b05SBill Paul */ 6321e890b05SBill Paul rewind(netf); 6331e890b05SBill Paul #endif 63458f0484fSRodney W. Grimes return ((struct linelist *)0); 63558f0484fSRodney W. Grimes } 636