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 */ 4058f0484fSRodney W. Grimes 4158f0484fSRodney W. Grimes #include <stdio.h> 4258f0484fSRodney W. Grimes #include <strings.h> 43958f4e36SBill Paul #include <stdlib.h> 44958f4e36SBill Paul #include <unistd.h> 45958f4e36SBill Paul 46958f4e36SBill Paul #ifdef YP 471e890b05SBill Paul /* 481e890b05SBill Paul * Notes: 491e890b05SBill Paul * We want to be able to use NIS netgroups properly while retaining 501e890b05SBill Paul * the ability to use a local /etc/netgroup file. Unfortunately, you 511e890b05SBill Paul * can't really do both at the same time - at least, not efficiently. 521e890b05SBill Paul * NetBSD deals with this problem by creating a netgroup database 531e890b05SBill Paul * using Berkeley DB (just like the password database) that allows 541e890b05SBill Paul * for lookups using netgroup, netgroup.byuser or netgroup.byhost 551e890b05SBill Paul * searches. This is a neat idea, but I don't have time to implement 561e890b05SBill Paul * something like that now. (I think ultimately it would be nice 571e890b05SBill Paul * if we DB-fied the group and netgroup stuff all in one shot, but 581e890b05SBill Paul * for now I'm satisfied just to have something that works well 591e890b05SBill Paul * without requiring massive code changes.) 601e890b05SBill Paul * 611e890b05SBill Paul * Therefore, to still permit the use of the local file and maintain 621e890b05SBill Paul * optimum NIS performance, we allow for the following conditions: 631e890b05SBill Paul * 641e890b05SBill Paul * - If /etc/netgroup does not exist and NIS is turned on, we use 651e890b05SBill Paul * NIS netgroups only. 661e890b05SBill Paul * 671e890b05SBill Paul * - If /etc/netgroup exists but is empty, we use NIS netgroups 681e890b05SBill Paul * only. 691e890b05SBill Paul * 701e890b05SBill Paul * - If /etc/netgroup exists and contains _only_ a '+', we use 711e890b05SBill Paul * NIS netgroups only. 721e890b05SBill Paul * 731e890b05SBill Paul * - If /etc/netgroup exists, contains locally defined netgroups 741e890b05SBill Paul * and a '+', we use a mixture of NIS and the local entries. 751e890b05SBill Paul * This method should return the same NIS data as just using 761e890b05SBill Paul * NIS alone, but it will be slower if the NIS netgroup database 771e890b05SBill Paul * is large (innetgr() in particular will suffer since extra 781e890b05SBill Paul * processing has to be done in order to determine memberships 791e890b05SBill Paul * using just the raw netgroup data). 801e890b05SBill Paul * 811e890b05SBill Paul * - If /etc/netgroup exists and contains only locally defined 821e890b05SBill Paul * netgroup entries, we use just those local entries and ignore 831e890b05SBill Paul * NIS (this is the original, pre-NIS behavior). 841e890b05SBill Paul */ 85c17942caSBill Paul 86958f4e36SBill Paul #include <rpc/rpc.h> 87958f4e36SBill Paul #include <rpcsvc/yp_prot.h> 88958f4e36SBill Paul #include <rpcsvc/ypclnt.h> 891e890b05SBill Paul #include <sys/types.h> 901e890b05SBill Paul #include <sys/stat.h> 911e890b05SBill Paul #include <sys/param.h> 921e890b05SBill Paul #include <sys/errno.h> 931e890b05SBill Paul static char *_netgr_yp_domain; 94d454389cSBill Paul int _use_only_yp; 95958f4e36SBill Paul static int _netgr_yp_enabled; 961e890b05SBill Paul static int _yp_innetgr; 97958f4e36SBill Paul #endif 9858f0484fSRodney W. Grimes 991e890b05SBill Paul #ifndef _PATH_NETGROUP 10058f0484fSRodney W. Grimes #define _PATH_NETGROUP "/etc/netgroup" 1011e890b05SBill Paul #endif 10258f0484fSRodney W. Grimes 10358f0484fSRodney W. Grimes /* 10458f0484fSRodney W. Grimes * Static Variables and functions used by setnetgrent(), getnetgrent() and 10558f0484fSRodney W. Grimes * endnetgrent(). 10658f0484fSRodney W. Grimes * There are two linked lists: 10758f0484fSRodney W. Grimes * - linelist is just used by setnetgrent() to parse the net group file via. 10858f0484fSRodney W. Grimes * parse_netgrp() 10958f0484fSRodney W. Grimes * - netgrp is the list of entries for the current netgroup 11058f0484fSRodney W. Grimes */ 11158f0484fSRodney W. Grimes struct linelist { 11258f0484fSRodney W. Grimes struct linelist *l_next; /* Chain ptr. */ 11358f0484fSRodney W. Grimes int l_parsed; /* Flag for cycles */ 11458f0484fSRodney W. Grimes char *l_groupname; /* Name of netgroup */ 11558f0484fSRodney W. Grimes char *l_line; /* Netgroup entrie(s) to be parsed */ 11658f0484fSRodney W. Grimes }; 11758f0484fSRodney W. Grimes 11858f0484fSRodney W. Grimes struct netgrp { 11958f0484fSRodney W. Grimes struct netgrp *ng_next; /* Chain ptr */ 12058f0484fSRodney W. Grimes char *ng_str[3]; /* Field pointers, see below */ 12158f0484fSRodney W. Grimes }; 12258f0484fSRodney W. Grimes #define NG_HOST 0 /* Host name */ 12358f0484fSRodney W. Grimes #define NG_USER 1 /* User name */ 12458f0484fSRodney W. Grimes #define NG_DOM 2 /* and Domain name */ 12558f0484fSRodney W. Grimes 12658f0484fSRodney W. Grimes static struct linelist *linehead = (struct linelist *)0; 12758f0484fSRodney W. Grimes static struct netgrp *nextgrp = (struct netgrp *)0; 12858f0484fSRodney W. Grimes static struct { 12958f0484fSRodney W. Grimes struct netgrp *gr; 13058f0484fSRodney W. Grimes char *grname; 13158f0484fSRodney W. Grimes } grouphead = { 13258f0484fSRodney W. Grimes (struct netgrp *)0, 13358f0484fSRodney W. Grimes (char *)0, 13458f0484fSRodney W. Grimes }; 13558f0484fSRodney W. Grimes static FILE *netf = (FILE *)0; 13658f0484fSRodney W. Grimes static int parse_netgrp(); 13758f0484fSRodney W. Grimes static struct linelist *read_for_group(); 13858f0484fSRodney W. Grimes void setnetgrent(), endnetgrent(); 13958f0484fSRodney W. Grimes int getnetgrent(), innetgr(); 14058f0484fSRodney W. Grimes 14158f0484fSRodney W. Grimes #define LINSIZ 1024 /* Length of netgroup file line */ 14258f0484fSRodney W. Grimes 14358f0484fSRodney W. Grimes /* 14458f0484fSRodney W. Grimes * setnetgrent() 14558f0484fSRodney W. Grimes * Parse the netgroup file looking for the netgroup and build the list 14658f0484fSRodney W. Grimes * of netgrp structures. Let parse_netgrp() and read_for_group() do 14758f0484fSRodney W. Grimes * most of the work. 14858f0484fSRodney W. Grimes */ 14958f0484fSRodney W. Grimes void 15058f0484fSRodney W. Grimes setnetgrent(group) 15158f0484fSRodney W. Grimes char *group; 15258f0484fSRodney W. Grimes { 1531e890b05SBill Paul #ifdef YP 1541e890b05SBill Paul struct stat _yp_statp; 1551e890b05SBill Paul char _yp_plus; 1561e890b05SBill Paul #endif 1571e890b05SBill Paul 1580ffe27f5SBill Paul /* Sanity check */ 15962a77170SBill Paul 1600ffe27f5SBill Paul if (group == NULL || !strlen(group)) 16162a77170SBill Paul return; 1620ffe27f5SBill Paul 16358f0484fSRodney W. Grimes if (grouphead.gr == (struct netgrp *)0 || 16458f0484fSRodney W. Grimes strcmp(group, grouphead.grname)) { 16558f0484fSRodney W. Grimes endnetgrent(); 1661e890b05SBill Paul #ifdef YP 167d454389cSBill Paul /* Presumed guilty until proven innocent. */ 168d454389cSBill Paul _use_only_yp = 0; 1691e890b05SBill Paul /* 170cbe78b44SBill Paul * If /etc/netgroup doesn't exist or is empty, 1711e890b05SBill Paul * use NIS exclusively. 1721e890b05SBill Paul */ 1731e890b05SBill Paul if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && 1741e890b05SBill Paul errno == ENOENT) || _yp_statp.st_size == 0) 1751e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1761e890b05SBill Paul if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){ 1771e890b05SBill Paul /* 1781e890b05SBill Paul * Icky: grab the first character of the netgroup file 1791e890b05SBill Paul * and turn on NIS if it's a '+'. rewind the stream 1801e890b05SBill Paul * afterwards so we don't goof up read_for_group() later. 1811e890b05SBill Paul */ 1821e890b05SBill Paul if (netf) { 1831e890b05SBill Paul fscanf(netf, "%c", &_yp_plus); 1841e890b05SBill Paul rewind(netf); 1851e890b05SBill Paul if (_yp_plus == '+') 1861e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1871e890b05SBill Paul } 1881e890b05SBill Paul /* 1891e890b05SBill Paul * If we were called specifically for an innetgr() 1901e890b05SBill Paul * lookup and we're in NIS-only mode, short-circuit 1911e890b05SBill Paul * parse_netgroup() and cut directly to the chase. 1921e890b05SBill Paul */ 193d454389cSBill Paul if (_use_only_yp && _yp_innetgr) { 194d454389cSBill Paul /* dohw! */ 195de32dbbdSBill Paul if (netf != NULL) 196d454389cSBill Paul fclose(netf); 1971e890b05SBill Paul return; 198d454389cSBill Paul } 1991e890b05SBill Paul #else 20058f0484fSRodney W. Grimes if (netf = fopen(_PATH_NETGROUP, "r")) { 2011e890b05SBill Paul #endif 20258f0484fSRodney W. Grimes if (parse_netgrp(group)) 20358f0484fSRodney W. Grimes endnetgrent(); 20458f0484fSRodney W. Grimes else { 20558f0484fSRodney W. Grimes grouphead.grname = (char *) 20658f0484fSRodney W. Grimes malloc(strlen(group) + 1); 20758f0484fSRodney W. Grimes strcpy(grouphead.grname, group); 20858f0484fSRodney W. Grimes } 2091e890b05SBill Paul if (netf) 21058f0484fSRodney W. Grimes fclose(netf); 21158f0484fSRodney W. Grimes } 21258f0484fSRodney W. Grimes } 21358f0484fSRodney W. Grimes nextgrp = grouphead.gr; 21458f0484fSRodney W. Grimes } 21558f0484fSRodney W. Grimes 21658f0484fSRodney W. Grimes /* 21758f0484fSRodney W. Grimes * Get the next netgroup off the list. 21858f0484fSRodney W. Grimes */ 21958f0484fSRodney W. Grimes int 22058f0484fSRodney W. Grimes getnetgrent(hostp, userp, domp) 22158f0484fSRodney W. Grimes char **hostp, **userp, **domp; 22258f0484fSRodney W. Grimes { 2231e890b05SBill Paul #ifdef YP 2241e890b05SBill Paul _yp_innetgr = 0; 2251e890b05SBill Paul #endif 22658f0484fSRodney W. Grimes 22758f0484fSRodney W. Grimes if (nextgrp) { 22858f0484fSRodney W. Grimes *hostp = nextgrp->ng_str[NG_HOST]; 22958f0484fSRodney W. Grimes *userp = nextgrp->ng_str[NG_USER]; 23058f0484fSRodney W. Grimes *domp = nextgrp->ng_str[NG_DOM]; 23158f0484fSRodney W. Grimes nextgrp = nextgrp->ng_next; 23258f0484fSRodney W. Grimes return (1); 23358f0484fSRodney W. Grimes } 23458f0484fSRodney W. Grimes return (0); 23558f0484fSRodney W. Grimes } 23658f0484fSRodney W. Grimes 23758f0484fSRodney W. Grimes /* 23858f0484fSRodney W. Grimes * endnetgrent() - cleanup 23958f0484fSRodney W. Grimes */ 24058f0484fSRodney W. Grimes void 24158f0484fSRodney W. Grimes endnetgrent() 24258f0484fSRodney W. Grimes { 24358f0484fSRodney W. Grimes register struct linelist *lp, *olp; 24458f0484fSRodney W. Grimes register struct netgrp *gp, *ogp; 24558f0484fSRodney W. Grimes 24658f0484fSRodney W. Grimes lp = linehead; 24758f0484fSRodney W. Grimes while (lp) { 24858f0484fSRodney W. Grimes olp = lp; 24958f0484fSRodney W. Grimes lp = lp->l_next; 25058f0484fSRodney W. Grimes free(olp->l_groupname); 25158f0484fSRodney W. Grimes free(olp->l_line); 25258f0484fSRodney W. Grimes free((char *)olp); 25358f0484fSRodney W. Grimes } 25458f0484fSRodney W. Grimes linehead = (struct linelist *)0; 25558f0484fSRodney W. Grimes if (grouphead.grname) { 25658f0484fSRodney W. Grimes free(grouphead.grname); 25758f0484fSRodney W. Grimes grouphead.grname = (char *)0; 25858f0484fSRodney W. Grimes } 25958f0484fSRodney W. Grimes gp = grouphead.gr; 26058f0484fSRodney W. Grimes while (gp) { 26158f0484fSRodney W. Grimes ogp = gp; 26258f0484fSRodney W. Grimes gp = gp->ng_next; 26358f0484fSRodney W. Grimes if (ogp->ng_str[NG_HOST]) 26458f0484fSRodney W. Grimes free(ogp->ng_str[NG_HOST]); 26558f0484fSRodney W. Grimes if (ogp->ng_str[NG_USER]) 26658f0484fSRodney W. Grimes free(ogp->ng_str[NG_USER]); 26758f0484fSRodney W. Grimes if (ogp->ng_str[NG_DOM]) 26858f0484fSRodney W. Grimes free(ogp->ng_str[NG_DOM]); 26958f0484fSRodney W. Grimes free((char *)ogp); 27058f0484fSRodney W. Grimes } 27158f0484fSRodney W. Grimes grouphead.gr = (struct netgrp *)0; 272409495f6SBill Paul #ifdef YP 2738516cd0fSBill Paul _netgr_yp_enabled = 0; 274409495f6SBill Paul #endif 27558f0484fSRodney W. Grimes } 27658f0484fSRodney W. Grimes 2771e890b05SBill Paul #ifdef YP 27822397ec3SBill Paul static int _listmatch(list, group, len) 2791e890b05SBill Paul char *list, *group; 28022397ec3SBill Paul int len; 2811e890b05SBill Paul { 282d9cc92f5SBill Paul char *ptr = list, *cptr; 283d9cc92f5SBill Paul int glen = strlen(group); 2841e890b05SBill Paul 285d9cc92f5SBill Paul /* skip possible leading whitespace */ 286d9cc92f5SBill Paul while(isspace(*ptr)) 287d9cc92f5SBill Paul ptr++; 288cbe78b44SBill Paul 289d9cc92f5SBill Paul while (ptr < list + len) { 290d9cc92f5SBill Paul cptr = ptr; 291f48bc662SSteve Price while(*ptr != ',' && *ptr != '\0' && !isspace(*ptr)) 292d9cc92f5SBill Paul ptr++; 293f48bc662SSteve Price if (strncmp(cptr, group, glen) == 0 && glen == (ptr - cptr)) 2941e890b05SBill Paul return(1); 295d9cc92f5SBill Paul while(*ptr == ',' || isspace(*ptr)) 296d9cc92f5SBill Paul ptr++; 297dfe8e51cSBill Paul } 298cbe78b44SBill Paul 2991e890b05SBill Paul return(0); 3001e890b05SBill Paul } 3011e890b05SBill Paul 3021e890b05SBill Paul static int _buildkey(key, str, dom, rotation) 3031e890b05SBill Paul char *key, *str, *dom; 3041e890b05SBill Paul int *rotation; 3051e890b05SBill Paul { 3061e890b05SBill Paul (*rotation)++; 3071e890b05SBill Paul if (*rotation > 4) 3081e890b05SBill Paul return(0); 3091e890b05SBill Paul switch(*rotation) { 3101e890b05SBill Paul case(1): sprintf((char *)key, "%s.%s", str, dom ? dom : "*"); 3111e890b05SBill Paul break; 3121e890b05SBill Paul case(2): sprintf((char *)key, "%s.*", str); 3131e890b05SBill Paul break; 3141e890b05SBill Paul case(3): sprintf((char *)key, "*.%s", dom ? dom : "*"); 3151e890b05SBill Paul break; 3161e890b05SBill Paul case(4): sprintf((char *)key, "*.*"); 3171e890b05SBill Paul break; 3181e890b05SBill Paul } 3191e890b05SBill Paul return(1); 3201e890b05SBill Paul } 3211e890b05SBill Paul #endif 3221e890b05SBill Paul 32358f0484fSRodney W. Grimes /* 32458f0484fSRodney W. Grimes * Search for a match in a netgroup. 32558f0484fSRodney W. Grimes */ 32658f0484fSRodney W. Grimes int 32758f0484fSRodney W. Grimes innetgr(group, host, user, dom) 32851295a4dSJordan K. Hubbard const char *group, *host, *user, *dom; 32958f0484fSRodney W. Grimes { 33058f0484fSRodney W. Grimes char *hst, *usr, *dm; 3311e890b05SBill Paul #ifdef YP 3321e890b05SBill Paul char *result; 3331e890b05SBill Paul int resultlen; 334cbe78b44SBill Paul int rv; 3351e890b05SBill Paul #endif 3360ffe27f5SBill Paul /* Sanity check */ 3370ffe27f5SBill Paul 3380ffe27f5SBill Paul if (group == NULL || !strlen(group)) 3390ffe27f5SBill Paul return (0); 3400ffe27f5SBill Paul 3411e890b05SBill Paul #ifdef YP 3421e890b05SBill Paul _yp_innetgr = 1; 3431e890b05SBill Paul #endif 34458f0484fSRodney W. Grimes setnetgrent(group); 3451e890b05SBill Paul #ifdef YP 346cbe78b44SBill Paul _yp_innetgr = 0; 3471e890b05SBill Paul /* 3481e890b05SBill Paul * If we're in NIS-only mode, do the search using 3491e890b05SBill Paul * NIS 'reverse netgroup' lookups. 3501e890b05SBill Paul */ 3511e890b05SBill Paul if (_use_only_yp) { 3521e890b05SBill Paul char _key[MAXHOSTNAMELEN]; 353e882d43eSBill Paul int rot = 0, y = 0; 3541e890b05SBill Paul 3551e890b05SBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 3561e890b05SBill Paul return(0); 35741864740SJordan K. Hubbard while(_buildkey(_key, user ? user : host, dom, &rot)) { 358e882d43eSBill Paul y = yp_match(_netgr_yp_domain, user? "netgroup.byuser": 3591e890b05SBill Paul "netgroup.byhost", _key, strlen(_key), &result, 360e882d43eSBill Paul &resultlen); 361e882d43eSBill Paul if (y) { 362e882d43eSBill Paul /* 363e882d43eSBill Paul * If we get an error other than 'no 364e882d43eSBill Paul * such key in map' then something is 365e882d43eSBill Paul * wrong and we should stop the search. 366e882d43eSBill Paul */ 367e882d43eSBill Paul if (y != YPERR_KEY) 368e882d43eSBill Paul break; 369e882d43eSBill Paul } else { 370cbe78b44SBill Paul rv = _listmatch(result, group, resultlen); 3711e890b05SBill Paul free(result); 372cbe78b44SBill Paul if (rv) 3731e890b05SBill Paul return(1); 374cbe78b44SBill Paul else 375cbe78b44SBill Paul return(0); 3761e890b05SBill Paul } 3771e890b05SBill Paul } 3781e890b05SBill Paul /* 379e882d43eSBill Paul * Couldn't match using NIS-exclusive mode. If the error 380e882d43eSBill Paul * was YPERR_MAP, then the failure happened because there 381e882d43eSBill Paul * was no netgroup.byhost or netgroup.byuser map. The odds 382e882d43eSBill Paul * are we are talking to an Sun NIS+ server in YP emulation 383e882d43eSBill Paul * mode; if this is the case, then we have to do the check 384e882d43eSBill Paul * the 'old-fashioned' way by grovelling through the netgroup 385e882d43eSBill Paul * map and resolving memberships on the fly. 3861e890b05SBill Paul */ 387e882d43eSBill Paul if (y != YPERR_MAP) 3881e890b05SBill Paul return(0); 3891e890b05SBill Paul } 390e882d43eSBill Paul 391e882d43eSBill Paul setnetgrent(group); 3921e890b05SBill Paul #endif /* YP */ 393e882d43eSBill Paul 39458f0484fSRodney W. Grimes while (getnetgrent(&hst, &usr, &dm)) 3951e890b05SBill Paul if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 3961e890b05SBill Paul (user == NULL || usr == NULL || !strcmp(user, usr)) && 3971e890b05SBill Paul ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 39858f0484fSRodney W. Grimes endnetgrent(); 39958f0484fSRodney W. Grimes return (1); 40058f0484fSRodney W. Grimes } 40158f0484fSRodney W. Grimes endnetgrent(); 40258f0484fSRodney W. Grimes return (0); 40358f0484fSRodney W. Grimes } 40458f0484fSRodney W. Grimes 40558f0484fSRodney W. Grimes /* 40658f0484fSRodney W. Grimes * Parse the netgroup file setting up the linked lists. 40758f0484fSRodney W. Grimes */ 40858f0484fSRodney W. Grimes static int 40958f0484fSRodney W. Grimes parse_netgrp(group) 41058f0484fSRodney W. Grimes char *group; 41158f0484fSRodney W. Grimes { 41258f0484fSRodney W. Grimes register char *spos, *epos; 41358f0484fSRodney W. Grimes register int len, strpos; 414dbf973c0SBill Paul #ifdef DEBUG 415dbf973c0SBill Paul register int fields; 416dbf973c0SBill Paul #endif 41758f0484fSRodney W. Grimes char *pos, *gpos; 41858f0484fSRodney W. Grimes struct netgrp *grp; 41958f0484fSRodney W. Grimes struct linelist *lp = linehead; 42058f0484fSRodney W. Grimes 42158f0484fSRodney W. Grimes /* 42258f0484fSRodney W. Grimes * First, see if the line has already been read in. 42358f0484fSRodney W. Grimes */ 42458f0484fSRodney W. Grimes while (lp) { 42558f0484fSRodney W. Grimes if (!strcmp(group, lp->l_groupname)) 42658f0484fSRodney W. Grimes break; 42758f0484fSRodney W. Grimes lp = lp->l_next; 42858f0484fSRodney W. Grimes } 42958f0484fSRodney W. Grimes if (lp == (struct linelist *)0 && 43058f0484fSRodney W. Grimes (lp = read_for_group(group)) == (struct linelist *)0) 43158f0484fSRodney W. Grimes return (1); 43258f0484fSRodney W. Grimes if (lp->l_parsed) { 433dbf973c0SBill Paul #ifdef DEBUG 434dbf973c0SBill Paul /* 435dbf973c0SBill Paul * This error message is largely superflous since the 436dbf973c0SBill Paul * code handles the error condition sucessfully, and 437dbf973c0SBill Paul * spewing it out from inside libc can actually hose 438dbf973c0SBill Paul * certain programs. 439dbf973c0SBill Paul */ 44058f0484fSRodney W. Grimes fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 441dbf973c0SBill Paul #endif 44258f0484fSRodney W. Grimes return (1); 44358f0484fSRodney W. Grimes } else 44458f0484fSRodney W. Grimes lp->l_parsed = 1; 44558f0484fSRodney W. Grimes pos = lp->l_line; 446409495f6SBill Paul /* Watch for null pointer dereferences, dammit! */ 447409495f6SBill Paul while (pos != NULL && *pos != '\0') { 44858f0484fSRodney W. Grimes if (*pos == '(') { 44958f0484fSRodney W. Grimes grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 45058f0484fSRodney W. Grimes bzero((char *)grp, sizeof (struct netgrp)); 45158f0484fSRodney W. Grimes grp->ng_next = grouphead.gr; 45258f0484fSRodney W. Grimes grouphead.gr = grp; 45358f0484fSRodney W. Grimes pos++; 45458f0484fSRodney W. Grimes gpos = strsep(&pos, ")"); 455dbf973c0SBill Paul #ifdef DEBUG 456dbf973c0SBill Paul fields = 0; 457dbf973c0SBill Paul #endif 45858f0484fSRodney W. Grimes for (strpos = 0; strpos < 3; strpos++) { 4591e890b05SBill Paul if ((spos = strsep(&gpos, ","))) { 460dbf973c0SBill Paul #ifdef DEBUG 461dbf973c0SBill Paul fields++; 462dbf973c0SBill Paul #endif 46358f0484fSRodney W. Grimes while (*spos == ' ' || *spos == '\t') 46458f0484fSRodney W. Grimes spos++; 4651e890b05SBill Paul if ((epos = strpbrk(spos, " \t"))) { 46658f0484fSRodney W. Grimes *epos = '\0'; 46758f0484fSRodney W. Grimes len = epos - spos; 46858f0484fSRodney W. Grimes } else 46958f0484fSRodney W. Grimes len = strlen(spos); 47058f0484fSRodney W. Grimes if (len > 0) { 47158f0484fSRodney W. Grimes grp->ng_str[strpos] = (char *) 47258f0484fSRodney W. Grimes malloc(len + 1); 47358f0484fSRodney W. Grimes bcopy(spos, grp->ng_str[strpos], 47458f0484fSRodney W. Grimes len + 1); 47558f0484fSRodney W. Grimes } 476dbf973c0SBill Paul } else { 477dbf973c0SBill Paul /* 478dbf973c0SBill Paul * All other systems I've tested 479dbf973c0SBill Paul * return NULL for empty netgroup 480dbf973c0SBill Paul * fields. It's up to user programs 481dbf973c0SBill Paul * to handle the NULLs appropriately. 482dbf973c0SBill Paul */ 483dbf973c0SBill Paul grp->ng_str[strpos] = NULL; 48458f0484fSRodney W. Grimes } 485dbf973c0SBill Paul } 486dbf973c0SBill Paul #ifdef DEBUG 487dbf973c0SBill Paul /* 488dbf973c0SBill Paul * Note: on other platforms, malformed netgroup 489dbf973c0SBill Paul * entries are not normally flagged. While we 490dbf973c0SBill Paul * can catch bad entries and report them, we should 491dbf973c0SBill Paul * stay silent by default for compatibility's sake. 492dbf973c0SBill Paul */ 493dbf973c0SBill Paul if (fields < 3) 494dbf973c0SBill Paul fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 495dbf973c0SBill Paul grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], 496dbf973c0SBill Paul grp->ng_str[NG_USER] == NULL ? "" : ",", 497dbf973c0SBill Paul grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], 498dbf973c0SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : ",", 499dbf973c0SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], 500dbf973c0SBill Paul lp->l_groupname); 501dbf973c0SBill Paul #endif 50258f0484fSRodney W. Grimes } else { 50358f0484fSRodney W. Grimes spos = strsep(&pos, ", \t"); 50458f0484fSRodney W. Grimes if (parse_netgrp(spos)) 505e8030794SBill Paul continue; 50658f0484fSRodney W. Grimes } 507adf6ad9eSPeter Wemm if (pos == NULL) 508adf6ad9eSPeter Wemm break; 50958f0484fSRodney W. Grimes while (*pos == ' ' || *pos == ',' || *pos == '\t') 51058f0484fSRodney W. Grimes pos++; 51158f0484fSRodney W. Grimes } 51258f0484fSRodney W. Grimes return (0); 51358f0484fSRodney W. Grimes } 51458f0484fSRodney W. Grimes 51558f0484fSRodney W. Grimes /* 51658f0484fSRodney W. Grimes * Read the netgroup file and save lines until the line for the netgroup 51758f0484fSRodney W. Grimes * is found. Return 1 if eof is encountered. 51858f0484fSRodney W. Grimes */ 51958f0484fSRodney W. Grimes static struct linelist * 52058f0484fSRodney W. Grimes read_for_group(group) 52158f0484fSRodney W. Grimes char *group; 52258f0484fSRodney W. Grimes { 52358f0484fSRodney W. Grimes register char *pos, *spos, *linep, *olinep; 52458f0484fSRodney W. Grimes register int len, olen; 52558f0484fSRodney W. Grimes int cont; 52658f0484fSRodney W. Grimes struct linelist *lp; 5271d2493ffSBill Paul char line[LINSIZ + 2]; 528409495f6SBill Paul #ifdef YP 529409495f6SBill Paul char *result; 530409495f6SBill Paul int resultlen; 53158f0484fSRodney W. Grimes 532409495f6SBill Paul while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 533409495f6SBill Paul if (_netgr_yp_enabled) { 534409495f6SBill Paul if(!_netgr_yp_domain) 5358516cd0fSBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 536409495f6SBill Paul continue; 5378516cd0fSBill Paul if (yp_match(_netgr_yp_domain, "netgroup", group, 5388516cd0fSBill Paul strlen(group), &result, &resultlen)) { 5398516cd0fSBill Paul free(result); 5401e890b05SBill Paul if (_use_only_yp) 5418516cd0fSBill Paul return ((struct linelist *)0); 5421e890b05SBill Paul else { 5431e890b05SBill Paul _netgr_yp_enabled = 0; 5441e890b05SBill Paul continue; 5451e890b05SBill Paul } 546409495f6SBill Paul } 5471d2493ffSBill Paul snprintf(line, LINSIZ, "%s %s", group, result); 548409495f6SBill Paul free(result); 549409495f6SBill Paul } 550409495f6SBill Paul #else 55158f0484fSRodney W. Grimes while (fgets(line, LINSIZ, netf) != NULL) { 552409495f6SBill Paul #endif 553409495f6SBill Paul pos = (char *)&line; 554409495f6SBill Paul #ifdef YP 555409495f6SBill Paul if (*pos == '+') { 556409495f6SBill Paul _netgr_yp_enabled = 1; 557409495f6SBill Paul continue; 558409495f6SBill Paul } 559409495f6SBill Paul #endif 56058f0484fSRodney W. Grimes if (*pos == '#') 56158f0484fSRodney W. Grimes continue; 56258f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 56358f0484fSRodney W. Grimes pos++; 56458f0484fSRodney W. Grimes spos = pos; 56558f0484fSRodney W. Grimes while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 56658f0484fSRodney W. Grimes *pos != '\0') 56758f0484fSRodney W. Grimes pos++; 56858f0484fSRodney W. Grimes len = pos - spos; 56958f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 57058f0484fSRodney W. Grimes pos++; 57158f0484fSRodney W. Grimes if (*pos != '\n' && *pos != '\0') { 57258f0484fSRodney W. Grimes lp = (struct linelist *)malloc(sizeof (*lp)); 57358f0484fSRodney W. Grimes lp->l_parsed = 0; 57458f0484fSRodney W. Grimes lp->l_groupname = (char *)malloc(len + 1); 57558f0484fSRodney W. Grimes bcopy(spos, lp->l_groupname, len); 57658f0484fSRodney W. Grimes *(lp->l_groupname + len) = '\0'; 57758f0484fSRodney W. Grimes len = strlen(pos); 57858f0484fSRodney W. Grimes olen = 0; 57958f0484fSRodney W. Grimes 58058f0484fSRodney W. Grimes /* 58158f0484fSRodney W. Grimes * Loop around handling line continuations. 58258f0484fSRodney W. Grimes */ 58358f0484fSRodney W. Grimes do { 58458f0484fSRodney W. Grimes if (*(pos + len - 1) == '\n') 58558f0484fSRodney W. Grimes len--; 58658f0484fSRodney W. Grimes if (*(pos + len - 1) == '\\') { 58758f0484fSRodney W. Grimes len--; 58858f0484fSRodney W. Grimes cont = 1; 58958f0484fSRodney W. Grimes } else 59058f0484fSRodney W. Grimes cont = 0; 59158f0484fSRodney W. Grimes if (len > 0) { 59258f0484fSRodney W. Grimes linep = (char *)malloc(olen + len + 1); 59358f0484fSRodney W. Grimes if (olen > 0) { 59458f0484fSRodney W. Grimes bcopy(olinep, linep, olen); 59558f0484fSRodney W. Grimes free(olinep); 59658f0484fSRodney W. Grimes } 59758f0484fSRodney W. Grimes bcopy(pos, linep + olen, len); 59858f0484fSRodney W. Grimes olen += len; 59958f0484fSRodney W. Grimes *(linep + olen) = '\0'; 60058f0484fSRodney W. Grimes olinep = linep; 60158f0484fSRodney W. Grimes } 60258f0484fSRodney W. Grimes if (cont) { 60358f0484fSRodney W. Grimes if (fgets(line, LINSIZ, netf)) { 60458f0484fSRodney W. Grimes pos = line; 60558f0484fSRodney W. Grimes len = strlen(pos); 60658f0484fSRodney W. Grimes } else 60758f0484fSRodney W. Grimes cont = 0; 60858f0484fSRodney W. Grimes } 60958f0484fSRodney W. Grimes } while (cont); 61058f0484fSRodney W. Grimes lp->l_line = linep; 61158f0484fSRodney W. Grimes lp->l_next = linehead; 61258f0484fSRodney W. Grimes linehead = lp; 61358f0484fSRodney W. Grimes 61458f0484fSRodney W. Grimes /* 61558f0484fSRodney W. Grimes * If this is the one we wanted, we are done. 61658f0484fSRodney W. Grimes */ 61758f0484fSRodney W. Grimes if (!strcmp(lp->l_groupname, group)) 61858f0484fSRodney W. Grimes return (lp); 61958f0484fSRodney W. Grimes } 62058f0484fSRodney W. Grimes } 6211e890b05SBill Paul #ifdef YP 6221e890b05SBill Paul /* 6231e890b05SBill Paul * Yucky. The recursive nature of this whole mess might require 6241e890b05SBill Paul * us to make more than one pass through the netgroup file. 6251e890b05SBill Paul * This might be best left outside the #ifdef YP, but YP is 6261e890b05SBill Paul * defined by default anyway, so I'll leave it like this 6271e890b05SBill Paul * until I know better. 6281e890b05SBill Paul */ 6291e890b05SBill Paul rewind(netf); 6301e890b05SBill Paul #endif 63158f0484fSRodney W. Grimes return ((struct linelist *)0); 63258f0484fSRodney W. Grimes } 633