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) 3858f0484fSRodney W. Grimes static char sccsid[] = "@(#)getnetgrent.c 8.1 (Berkeley) 6/4/93"; 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 */ 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; 931e890b05SBill Paul static 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; 13558f0484fSRodney W. Grimes static int parse_netgrp(); 13658f0484fSRodney W. Grimes static struct linelist *read_for_group(); 13758f0484fSRodney W. Grimes void setnetgrent(), endnetgrent(); 13858f0484fSRodney W. Grimes int getnetgrent(), innetgr(); 13958f0484fSRodney W. Grimes 14058f0484fSRodney W. Grimes #define LINSIZ 1024 /* Length of netgroup file line */ 14158f0484fSRodney W. Grimes 14258f0484fSRodney W. Grimes /* 14358f0484fSRodney W. Grimes * setnetgrent() 14458f0484fSRodney W. Grimes * Parse the netgroup file looking for the netgroup and build the list 14558f0484fSRodney W. Grimes * of netgrp structures. Let parse_netgrp() and read_for_group() do 14658f0484fSRodney W. Grimes * most of the work. 14758f0484fSRodney W. Grimes */ 14858f0484fSRodney W. Grimes void 14958f0484fSRodney W. Grimes setnetgrent(group) 15058f0484fSRodney W. Grimes char *group; 15158f0484fSRodney W. Grimes { 1521e890b05SBill Paul #ifdef YP 1531e890b05SBill Paul struct stat _yp_statp; 1541e890b05SBill Paul char _yp_plus; 1551e890b05SBill Paul #endif 1561e890b05SBill Paul 1570ffe27f5SBill Paul /* Sanity check */ 15862a77170SBill Paul 1590ffe27f5SBill Paul if (group == NULL || !strlen(group)) 16062a77170SBill Paul return; 1610ffe27f5SBill Paul 16258f0484fSRodney W. Grimes if (grouphead.gr == (struct netgrp *)0 || 16358f0484fSRodney W. Grimes strcmp(group, grouphead.grname)) { 16458f0484fSRodney W. Grimes endnetgrent(); 1651e890b05SBill Paul #ifdef YP 1661e890b05SBill Paul /* 1671e890b05SBill Paul * IF /etc/netgroup doesn't exist or is empty, 1681e890b05SBill Paul * use NIS exclusively. 1691e890b05SBill Paul */ 1701e890b05SBill Paul if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && 1711e890b05SBill Paul errno == ENOENT) || _yp_statp.st_size == 0) 1721e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1731e890b05SBill Paul if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){ 1741e890b05SBill Paul /* 1751e890b05SBill Paul * Icky: grab the first character of the netgroup file 1761e890b05SBill Paul * and turn on NIS if it's a '+'. rewind the stream 1771e890b05SBill Paul * afterwards so we don't goof up read_for_group() later. 1781e890b05SBill Paul */ 1791e890b05SBill Paul if (netf) { 1801e890b05SBill Paul fscanf(netf, "%c", &_yp_plus); 1811e890b05SBill Paul rewind(netf); 1821e890b05SBill Paul if (_yp_plus == '+') 1831e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1841e890b05SBill Paul } 1851e890b05SBill Paul /* 1861e890b05SBill Paul * If we were called specifically for an innetgr() 1871e890b05SBill Paul * lookup and we're in NIS-only mode, short-circuit 1881e890b05SBill Paul * parse_netgroup() and cut directly to the chase. 1891e890b05SBill Paul */ 1901e890b05SBill Paul if (_use_only_yp && _yp_innetgr) 1911e890b05SBill Paul return; 1921e890b05SBill Paul #else 19358f0484fSRodney W. Grimes if (netf = fopen(_PATH_NETGROUP, "r")) { 1941e890b05SBill Paul #endif 19558f0484fSRodney W. Grimes if (parse_netgrp(group)) 19658f0484fSRodney W. Grimes endnetgrent(); 19758f0484fSRodney W. Grimes else { 19858f0484fSRodney W. Grimes grouphead.grname = (char *) 19958f0484fSRodney W. Grimes malloc(strlen(group) + 1); 20058f0484fSRodney W. Grimes strcpy(grouphead.grname, group); 20158f0484fSRodney W. Grimes } 2021e890b05SBill Paul if (netf) 20358f0484fSRodney W. Grimes fclose(netf); 20458f0484fSRodney W. Grimes } 20558f0484fSRodney W. Grimes } 20658f0484fSRodney W. Grimes nextgrp = grouphead.gr; 20758f0484fSRodney W. Grimes } 20858f0484fSRodney W. Grimes 20958f0484fSRodney W. Grimes /* 21058f0484fSRodney W. Grimes * Get the next netgroup off the list. 21158f0484fSRodney W. Grimes */ 21258f0484fSRodney W. Grimes int 21358f0484fSRodney W. Grimes getnetgrent(hostp, userp, domp) 21458f0484fSRodney W. Grimes char **hostp, **userp, **domp; 21558f0484fSRodney W. Grimes { 2161e890b05SBill Paul #ifdef YP 2171e890b05SBill Paul _yp_innetgr = 0; 2181e890b05SBill Paul #endif 21958f0484fSRodney W. Grimes 22058f0484fSRodney W. Grimes if (nextgrp) { 22158f0484fSRodney W. Grimes *hostp = nextgrp->ng_str[NG_HOST]; 22258f0484fSRodney W. Grimes *userp = nextgrp->ng_str[NG_USER]; 22358f0484fSRodney W. Grimes *domp = nextgrp->ng_str[NG_DOM]; 22458f0484fSRodney W. Grimes nextgrp = nextgrp->ng_next; 22558f0484fSRodney W. Grimes return (1); 22658f0484fSRodney W. Grimes } 22758f0484fSRodney W. Grimes return (0); 22858f0484fSRodney W. Grimes } 22958f0484fSRodney W. Grimes 23058f0484fSRodney W. Grimes /* 23158f0484fSRodney W. Grimes * endnetgrent() - cleanup 23258f0484fSRodney W. Grimes */ 23358f0484fSRodney W. Grimes void 23458f0484fSRodney W. Grimes endnetgrent() 23558f0484fSRodney W. Grimes { 23658f0484fSRodney W. Grimes register struct linelist *lp, *olp; 23758f0484fSRodney W. Grimes register struct netgrp *gp, *ogp; 23858f0484fSRodney W. Grimes 23958f0484fSRodney W. Grimes lp = linehead; 24058f0484fSRodney W. Grimes while (lp) { 24158f0484fSRodney W. Grimes olp = lp; 24258f0484fSRodney W. Grimes lp = lp->l_next; 24358f0484fSRodney W. Grimes free(olp->l_groupname); 24458f0484fSRodney W. Grimes free(olp->l_line); 24558f0484fSRodney W. Grimes free((char *)olp); 24658f0484fSRodney W. Grimes } 24758f0484fSRodney W. Grimes linehead = (struct linelist *)0; 24858f0484fSRodney W. Grimes if (grouphead.grname) { 24958f0484fSRodney W. Grimes free(grouphead.grname); 25058f0484fSRodney W. Grimes grouphead.grname = (char *)0; 25158f0484fSRodney W. Grimes } 25258f0484fSRodney W. Grimes gp = grouphead.gr; 25358f0484fSRodney W. Grimes while (gp) { 25458f0484fSRodney W. Grimes ogp = gp; 25558f0484fSRodney W. Grimes gp = gp->ng_next; 25658f0484fSRodney W. Grimes if (ogp->ng_str[NG_HOST]) 25758f0484fSRodney W. Grimes free(ogp->ng_str[NG_HOST]); 25858f0484fSRodney W. Grimes if (ogp->ng_str[NG_USER]) 25958f0484fSRodney W. Grimes free(ogp->ng_str[NG_USER]); 26058f0484fSRodney W. Grimes if (ogp->ng_str[NG_DOM]) 26158f0484fSRodney W. Grimes free(ogp->ng_str[NG_DOM]); 26258f0484fSRodney W. Grimes free((char *)ogp); 26358f0484fSRodney W. Grimes } 26458f0484fSRodney W. Grimes grouphead.gr = (struct netgrp *)0; 265409495f6SBill Paul #ifdef YP 2668516cd0fSBill Paul _netgr_yp_enabled = 0; 267409495f6SBill Paul #endif 26858f0484fSRodney W. Grimes } 26958f0484fSRodney W. Grimes 2701e890b05SBill Paul #ifdef YP 2711e890b05SBill Paul static int _listmatch(list, group) 2721e890b05SBill Paul char *list, *group; 2731e890b05SBill Paul { 2741e890b05SBill Paul char *ptr = list; 2751e890b05SBill Paul 2761e890b05SBill Paul while (ptr != NULL) { 2771e890b05SBill Paul if (!strncmp(ptr, group, strlen(group)) && 2781e890b05SBill Paul (*(ptr+strlen(group)) == ',' || 2791e890b05SBill Paul *(ptr+strlen(group)) == '\n')) 2801e890b05SBill Paul return(1); 2811e890b05SBill Paul ptr++; 2821e890b05SBill Paul } 2831e890b05SBill Paul return(0); 2841e890b05SBill Paul } 2851e890b05SBill Paul 2861e890b05SBill Paul static int _buildkey(key, str, dom, rotation) 2871e890b05SBill Paul char *key, *str, *dom; 2881e890b05SBill Paul int *rotation; 2891e890b05SBill Paul { 2901e890b05SBill Paul (*rotation)++; 2911e890b05SBill Paul if (*rotation > 4) 2921e890b05SBill Paul return(0); 2931e890b05SBill Paul switch(*rotation) { 2941e890b05SBill Paul case(1): sprintf((char *)key, "%s.%s", str, dom ? dom : "*"); 2951e890b05SBill Paul break; 2961e890b05SBill Paul case(2): sprintf((char *)key, "%s.*", str); 2971e890b05SBill Paul break; 2981e890b05SBill Paul case(3): sprintf((char *)key, "*.%s", dom ? dom : "*"); 2991e890b05SBill Paul break; 3001e890b05SBill Paul case(4): sprintf((char *)key, "*.*"); 3011e890b05SBill Paul break; 3021e890b05SBill Paul } 3031e890b05SBill Paul return(1); 3041e890b05SBill Paul } 3051e890b05SBill Paul #endif 3061e890b05SBill Paul 30758f0484fSRodney W. Grimes /* 30858f0484fSRodney W. Grimes * Search for a match in a netgroup. 30958f0484fSRodney W. Grimes */ 31058f0484fSRodney W. Grimes int 31158f0484fSRodney W. Grimes innetgr(group, host, user, dom) 31258f0484fSRodney W. Grimes char *group, *host, *user, *dom; 31358f0484fSRodney W. Grimes { 31458f0484fSRodney W. Grimes char *hst, *usr, *dm; 3151e890b05SBill Paul #ifdef YP 3161e890b05SBill Paul char *result; 3171e890b05SBill Paul int resultlen; 3181e890b05SBill Paul #endif 3190ffe27f5SBill Paul /* Sanity check */ 3200ffe27f5SBill Paul 3210ffe27f5SBill Paul if (group == NULL || !strlen(group)) 3220ffe27f5SBill Paul return (0); 3230ffe27f5SBill Paul 3241e890b05SBill Paul #ifdef YP 3251e890b05SBill Paul _yp_innetgr = 1; 3261e890b05SBill Paul #endif 32758f0484fSRodney W. Grimes setnetgrent(group); 3281e890b05SBill Paul #ifdef YP 3291e890b05SBill Paul /* 3301e890b05SBill Paul * If we're in NIS-only mode, do the search using 3311e890b05SBill Paul * NIS 'reverse netgroup' lookups. 3321e890b05SBill Paul */ 3331e890b05SBill Paul if (_use_only_yp) { 3341e890b05SBill Paul char _key[MAXHOSTNAMELEN]; 3351e890b05SBill Paul int rot = 0; 3361e890b05SBill Paul 3371e890b05SBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 3381e890b05SBill Paul return(0); 3391e890b05SBill Paul while(_buildkey(&_key, user ? user : host, dom, &rot)) { 3401e890b05SBill Paul if (yp_match(_netgr_yp_domain, user? "netgroup.byuser": 3411e890b05SBill Paul "netgroup.byhost", _key, strlen(_key), &result, 3421e890b05SBill Paul &resultlen)) 3431e890b05SBill Paul free(result); 3441e890b05SBill Paul else { 3451e890b05SBill Paul if (_listmatch(result, group)) { 3461e890b05SBill Paul free(result); 3471e890b05SBill Paul return(1); 3481e890b05SBill Paul } 3491e890b05SBill Paul } 3501e890b05SBill Paul } 3511e890b05SBill Paul free(result); 3521e890b05SBill Paul #ifdef CHARITABLE 3531e890b05SBill Paul } 3541e890b05SBill Paul /* 3551e890b05SBill Paul * Couldn't match using NIS-exclusive mode -- try 3561e890b05SBill Paul * standard mode. 3571e890b05SBill Paul */ 3581e890b05SBill Paul _yp_innetgr = 0; 3591e890b05SBill Paul setnetgrent(group); 3601e890b05SBill Paul #else 3611e890b05SBill Paul return(0); 3621e890b05SBill Paul } 3631e890b05SBill Paul #endif /* CHARITABLE */ 3641e890b05SBill Paul #endif /* YP */ 36558f0484fSRodney W. Grimes while (getnetgrent(&hst, &usr, &dm)) 3661e890b05SBill Paul if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 3671e890b05SBill Paul (user == NULL || usr == NULL || !strcmp(user, usr)) && 3681e890b05SBill Paul ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 36958f0484fSRodney W. Grimes endnetgrent(); 37058f0484fSRodney W. Grimes return (1); 37158f0484fSRodney W. Grimes } 37258f0484fSRodney W. Grimes endnetgrent(); 37358f0484fSRodney W. Grimes return (0); 37458f0484fSRodney W. Grimes } 37558f0484fSRodney W. Grimes 37658f0484fSRodney W. Grimes /* 37758f0484fSRodney W. Grimes * Parse the netgroup file setting up the linked lists. 37858f0484fSRodney W. Grimes */ 37958f0484fSRodney W. Grimes static int 38058f0484fSRodney W. Grimes parse_netgrp(group) 38158f0484fSRodney W. Grimes char *group; 38258f0484fSRodney W. Grimes { 38358f0484fSRodney W. Grimes register char *spos, *epos; 38458f0484fSRodney W. Grimes register int len, strpos; 385dbf973c0SBill Paul #ifdef DEBUG 386dbf973c0SBill Paul register int fields; 387dbf973c0SBill Paul #endif 38858f0484fSRodney W. Grimes char *pos, *gpos; 38958f0484fSRodney W. Grimes struct netgrp *grp; 39058f0484fSRodney W. Grimes struct linelist *lp = linehead; 39158f0484fSRodney W. Grimes 39258f0484fSRodney W. Grimes /* 39358f0484fSRodney W. Grimes * First, see if the line has already been read in. 39458f0484fSRodney W. Grimes */ 39558f0484fSRodney W. Grimes while (lp) { 39658f0484fSRodney W. Grimes if (!strcmp(group, lp->l_groupname)) 39758f0484fSRodney W. Grimes break; 39858f0484fSRodney W. Grimes lp = lp->l_next; 39958f0484fSRodney W. Grimes } 40058f0484fSRodney W. Grimes if (lp == (struct linelist *)0 && 40158f0484fSRodney W. Grimes (lp = read_for_group(group)) == (struct linelist *)0) 40258f0484fSRodney W. Grimes return (1); 40358f0484fSRodney W. Grimes if (lp->l_parsed) { 404dbf973c0SBill Paul #ifdef DEBUG 405dbf973c0SBill Paul /* 406dbf973c0SBill Paul * This error message is largely superflous since the 407dbf973c0SBill Paul * code handles the error condition sucessfully, and 408dbf973c0SBill Paul * spewing it out from inside libc can actually hose 409dbf973c0SBill Paul * certain programs. 410dbf973c0SBill Paul */ 41158f0484fSRodney W. Grimes fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 412dbf973c0SBill Paul #endif 41358f0484fSRodney W. Grimes return (1); 41458f0484fSRodney W. Grimes } else 41558f0484fSRodney W. Grimes lp->l_parsed = 1; 41658f0484fSRodney W. Grimes pos = lp->l_line; 417409495f6SBill Paul /* Watch for null pointer dereferences, dammit! */ 418409495f6SBill Paul while (pos != NULL && *pos != '\0') { 41958f0484fSRodney W. Grimes if (*pos == '(') { 42058f0484fSRodney W. Grimes grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 42158f0484fSRodney W. Grimes bzero((char *)grp, sizeof (struct netgrp)); 42258f0484fSRodney W. Grimes grp->ng_next = grouphead.gr; 42358f0484fSRodney W. Grimes grouphead.gr = grp; 42458f0484fSRodney W. Grimes pos++; 42558f0484fSRodney W. Grimes gpos = strsep(&pos, ")"); 426dbf973c0SBill Paul #ifdef DEBUG 427dbf973c0SBill Paul fields = 0; 428dbf973c0SBill Paul #endif 42958f0484fSRodney W. Grimes for (strpos = 0; strpos < 3; strpos++) { 4301e890b05SBill Paul if ((spos = strsep(&gpos, ","))) { 431dbf973c0SBill Paul #ifdef DEBUG 432dbf973c0SBill Paul fields++; 433dbf973c0SBill Paul #endif 43458f0484fSRodney W. Grimes while (*spos == ' ' || *spos == '\t') 43558f0484fSRodney W. Grimes spos++; 4361e890b05SBill Paul if ((epos = strpbrk(spos, " \t"))) { 43758f0484fSRodney W. Grimes *epos = '\0'; 43858f0484fSRodney W. Grimes len = epos - spos; 43958f0484fSRodney W. Grimes } else 44058f0484fSRodney W. Grimes len = strlen(spos); 44158f0484fSRodney W. Grimes if (len > 0) { 44258f0484fSRodney W. Grimes grp->ng_str[strpos] = (char *) 44358f0484fSRodney W. Grimes malloc(len + 1); 44458f0484fSRodney W. Grimes bcopy(spos, grp->ng_str[strpos], 44558f0484fSRodney W. Grimes len + 1); 44658f0484fSRodney W. Grimes } 447dbf973c0SBill Paul } else { 448dbf973c0SBill Paul /* 449dbf973c0SBill Paul * All other systems I've tested 450dbf973c0SBill Paul * return NULL for empty netgroup 451dbf973c0SBill Paul * fields. It's up to user programs 452dbf973c0SBill Paul * to handle the NULLs appropriately. 453dbf973c0SBill Paul */ 454dbf973c0SBill Paul grp->ng_str[strpos] = NULL; 45558f0484fSRodney W. Grimes } 456dbf973c0SBill Paul } 457dbf973c0SBill Paul #ifdef DEBUG 458dbf973c0SBill Paul /* 459dbf973c0SBill Paul * Note: on other platforms, malformed netgroup 460dbf973c0SBill Paul * entries are not normally flagged. While we 461dbf973c0SBill Paul * can catch bad entries and report them, we should 462dbf973c0SBill Paul * stay silent by default for compatibility's sake. 463dbf973c0SBill Paul */ 464dbf973c0SBill Paul if (fields < 3) 465dbf973c0SBill Paul fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 466dbf973c0SBill Paul grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], 467dbf973c0SBill Paul grp->ng_str[NG_USER] == NULL ? "" : ",", 468dbf973c0SBill Paul grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], 469dbf973c0SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : ",", 470dbf973c0SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], 471dbf973c0SBill Paul lp->l_groupname); 472dbf973c0SBill Paul #endif 47358f0484fSRodney W. Grimes } else { 47458f0484fSRodney W. Grimes spos = strsep(&pos, ", \t"); 47558f0484fSRodney W. Grimes if (parse_netgrp(spos)) 476e8030794SBill Paul continue; 47758f0484fSRodney W. Grimes } 478409495f6SBill Paul /* Watch for null pointer dereferences, dammit! */ 479409495f6SBill Paul if (pos != NULL) 48058f0484fSRodney W. Grimes while (*pos == ' ' || *pos == ',' || *pos == '\t') 48158f0484fSRodney W. Grimes pos++; 48258f0484fSRodney W. Grimes } 48358f0484fSRodney W. Grimes return (0); 48458f0484fSRodney W. Grimes } 48558f0484fSRodney W. Grimes 48658f0484fSRodney W. Grimes /* 48758f0484fSRodney W. Grimes * Read the netgroup file and save lines until the line for the netgroup 48858f0484fSRodney W. Grimes * is found. Return 1 if eof is encountered. 48958f0484fSRodney W. Grimes */ 49058f0484fSRodney W. Grimes static struct linelist * 49158f0484fSRodney W. Grimes read_for_group(group) 49258f0484fSRodney W. Grimes char *group; 49358f0484fSRodney W. Grimes { 49458f0484fSRodney W. Grimes register char *pos, *spos, *linep, *olinep; 49558f0484fSRodney W. Grimes register int len, olen; 49658f0484fSRodney W. Grimes int cont; 49758f0484fSRodney W. Grimes struct linelist *lp; 49858f0484fSRodney W. Grimes char line[LINSIZ + 1]; 499409495f6SBill Paul #ifdef YP 500409495f6SBill Paul char *result; 501409495f6SBill Paul int resultlen; 50258f0484fSRodney W. Grimes 503409495f6SBill Paul while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 504409495f6SBill Paul if (_netgr_yp_enabled) { 505409495f6SBill Paul if(!_netgr_yp_domain) 5068516cd0fSBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 507409495f6SBill Paul continue; 5088516cd0fSBill Paul if (yp_match(_netgr_yp_domain, "netgroup", group, 5098516cd0fSBill Paul strlen(group), &result, &resultlen)) { 5108516cd0fSBill Paul free(result); 5111e890b05SBill Paul if (_use_only_yp) 5128516cd0fSBill Paul return ((struct linelist *)0); 5131e890b05SBill Paul else { 5141e890b05SBill Paul _netgr_yp_enabled = 0; 5151e890b05SBill Paul continue; 5161e890b05SBill Paul } 517409495f6SBill Paul } 5188516cd0fSBill Paul sprintf(line, "%s %s", group, result); 519409495f6SBill Paul free(result); 520409495f6SBill Paul } 521409495f6SBill Paul #else 52258f0484fSRodney W. Grimes while (fgets(line, LINSIZ, netf) != NULL) { 523409495f6SBill Paul #endif 524409495f6SBill Paul pos = (char *)&line; 525409495f6SBill Paul #ifdef YP 526409495f6SBill Paul if (*pos == '+') { 527409495f6SBill Paul _netgr_yp_enabled = 1; 528409495f6SBill Paul continue; 529409495f6SBill Paul } 530409495f6SBill Paul #endif 53158f0484fSRodney W. Grimes if (*pos == '#') 53258f0484fSRodney W. Grimes continue; 53358f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 53458f0484fSRodney W. Grimes pos++; 53558f0484fSRodney W. Grimes spos = pos; 53658f0484fSRodney W. Grimes while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 53758f0484fSRodney W. Grimes *pos != '\0') 53858f0484fSRodney W. Grimes pos++; 53958f0484fSRodney W. Grimes len = pos - spos; 54058f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 54158f0484fSRodney W. Grimes pos++; 54258f0484fSRodney W. Grimes if (*pos != '\n' && *pos != '\0') { 54358f0484fSRodney W. Grimes lp = (struct linelist *)malloc(sizeof (*lp)); 54458f0484fSRodney W. Grimes lp->l_parsed = 0; 54558f0484fSRodney W. Grimes lp->l_groupname = (char *)malloc(len + 1); 54658f0484fSRodney W. Grimes bcopy(spos, lp->l_groupname, len); 54758f0484fSRodney W. Grimes *(lp->l_groupname + len) = '\0'; 54858f0484fSRodney W. Grimes len = strlen(pos); 54958f0484fSRodney W. Grimes olen = 0; 55058f0484fSRodney W. Grimes 55158f0484fSRodney W. Grimes /* 55258f0484fSRodney W. Grimes * Loop around handling line continuations. 55358f0484fSRodney W. Grimes */ 55458f0484fSRodney W. Grimes do { 55558f0484fSRodney W. Grimes if (*(pos + len - 1) == '\n') 55658f0484fSRodney W. Grimes len--; 55758f0484fSRodney W. Grimes if (*(pos + len - 1) == '\\') { 55858f0484fSRodney W. Grimes len--; 55958f0484fSRodney W. Grimes cont = 1; 56058f0484fSRodney W. Grimes } else 56158f0484fSRodney W. Grimes cont = 0; 56258f0484fSRodney W. Grimes if (len > 0) { 56358f0484fSRodney W. Grimes linep = (char *)malloc(olen + len + 1); 56458f0484fSRodney W. Grimes if (olen > 0) { 56558f0484fSRodney W. Grimes bcopy(olinep, linep, olen); 56658f0484fSRodney W. Grimes free(olinep); 56758f0484fSRodney W. Grimes } 56858f0484fSRodney W. Grimes bcopy(pos, linep + olen, len); 56958f0484fSRodney W. Grimes olen += len; 57058f0484fSRodney W. Grimes *(linep + olen) = '\0'; 57158f0484fSRodney W. Grimes olinep = linep; 57258f0484fSRodney W. Grimes } 57358f0484fSRodney W. Grimes if (cont) { 57458f0484fSRodney W. Grimes if (fgets(line, LINSIZ, netf)) { 57558f0484fSRodney W. Grimes pos = line; 57658f0484fSRodney W. Grimes len = strlen(pos); 57758f0484fSRodney W. Grimes } else 57858f0484fSRodney W. Grimes cont = 0; 57958f0484fSRodney W. Grimes } 58058f0484fSRodney W. Grimes } while (cont); 58158f0484fSRodney W. Grimes lp->l_line = linep; 58258f0484fSRodney W. Grimes lp->l_next = linehead; 58358f0484fSRodney W. Grimes linehead = lp; 58458f0484fSRodney W. Grimes 58558f0484fSRodney W. Grimes /* 58658f0484fSRodney W. Grimes * If this is the one we wanted, we are done. 58758f0484fSRodney W. Grimes */ 58858f0484fSRodney W. Grimes if (!strcmp(lp->l_groupname, group)) 58958f0484fSRodney W. Grimes return (lp); 59058f0484fSRodney W. Grimes } 59158f0484fSRodney W. Grimes } 5921e890b05SBill Paul #ifdef YP 5931e890b05SBill Paul /* 5941e890b05SBill Paul * Yucky. The recursive nature of this whole mess might require 5951e890b05SBill Paul * us to make more than one pass through the netgroup file. 5961e890b05SBill Paul * This might be best left outside the #ifdef YP, but YP is 5971e890b05SBill Paul * defined by default anyway, so I'll leave it like this 5981e890b05SBill Paul * until I know better. 5991e890b05SBill Paul */ 6001e890b05SBill Paul rewind(netf); 6011e890b05SBill Paul #endif 60258f0484fSRodney W. Grimes return ((struct linelist *)0); 60358f0484fSRodney W. Grimes } 604