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; 93d454389cSBill Paul int _use_only_yp; 94958f4e36SBill Paul static int _netgr_yp_enabled; 951e890b05SBill Paul static int _yp_innetgr; 96958f4e36SBill Paul #endif 9758f0484fSRodney W. Grimes 981e890b05SBill Paul #ifndef _PATH_NETGROUP 9958f0484fSRodney W. Grimes #define _PATH_NETGROUP "/etc/netgroup" 1001e890b05SBill Paul #endif 10158f0484fSRodney W. Grimes 10258f0484fSRodney W. Grimes /* 10358f0484fSRodney W. Grimes * Static Variables and functions used by setnetgrent(), getnetgrent() and 10458f0484fSRodney W. Grimes * endnetgrent(). 10558f0484fSRodney W. Grimes * There are two linked lists: 10658f0484fSRodney W. Grimes * - linelist is just used by setnetgrent() to parse the net group file via. 10758f0484fSRodney W. Grimes * parse_netgrp() 10858f0484fSRodney W. Grimes * - netgrp is the list of entries for the current netgroup 10958f0484fSRodney W. Grimes */ 11058f0484fSRodney W. Grimes struct linelist { 11158f0484fSRodney W. Grimes struct linelist *l_next; /* Chain ptr. */ 11258f0484fSRodney W. Grimes int l_parsed; /* Flag for cycles */ 11358f0484fSRodney W. Grimes char *l_groupname; /* Name of netgroup */ 11458f0484fSRodney W. Grimes char *l_line; /* Netgroup entrie(s) to be parsed */ 11558f0484fSRodney W. Grimes }; 11658f0484fSRodney W. Grimes 11758f0484fSRodney W. Grimes struct netgrp { 11858f0484fSRodney W. Grimes struct netgrp *ng_next; /* Chain ptr */ 11958f0484fSRodney W. Grimes char *ng_str[3]; /* Field pointers, see below */ 12058f0484fSRodney W. Grimes }; 12158f0484fSRodney W. Grimes #define NG_HOST 0 /* Host name */ 12258f0484fSRodney W. Grimes #define NG_USER 1 /* User name */ 12358f0484fSRodney W. Grimes #define NG_DOM 2 /* and Domain name */ 12458f0484fSRodney W. Grimes 12558f0484fSRodney W. Grimes static struct linelist *linehead = (struct linelist *)0; 12658f0484fSRodney W. Grimes static struct netgrp *nextgrp = (struct netgrp *)0; 12758f0484fSRodney W. Grimes static struct { 12858f0484fSRodney W. Grimes struct netgrp *gr; 12958f0484fSRodney W. Grimes char *grname; 13058f0484fSRodney W. Grimes } grouphead = { 13158f0484fSRodney W. Grimes (struct netgrp *)0, 13258f0484fSRodney W. Grimes (char *)0, 13358f0484fSRodney W. Grimes }; 13458f0484fSRodney W. Grimes static FILE *netf = (FILE *)0; 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 166d454389cSBill Paul /* Presumed guilty until proven innocent. */ 167d454389cSBill Paul _use_only_yp = 0; 1681e890b05SBill Paul /* 1691e890b05SBill Paul * IF /etc/netgroup doesn't exist or is empty, 1701e890b05SBill Paul * use NIS exclusively. 1711e890b05SBill Paul */ 1721e890b05SBill Paul if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && 1731e890b05SBill Paul errno == ENOENT) || _yp_statp.st_size == 0) 1741e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1751e890b05SBill Paul if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){ 1761e890b05SBill Paul /* 1771e890b05SBill Paul * Icky: grab the first character of the netgroup file 1781e890b05SBill Paul * and turn on NIS if it's a '+'. rewind the stream 1791e890b05SBill Paul * afterwards so we don't goof up read_for_group() later. 1801e890b05SBill Paul */ 1811e890b05SBill Paul if (netf) { 1821e890b05SBill Paul fscanf(netf, "%c", &_yp_plus); 1831e890b05SBill Paul rewind(netf); 1841e890b05SBill Paul if (_yp_plus == '+') 1851e890b05SBill Paul _use_only_yp = _netgr_yp_enabled = 1; 1861e890b05SBill Paul } 1871e890b05SBill Paul /* 1881e890b05SBill Paul * If we were called specifically for an innetgr() 1891e890b05SBill Paul * lookup and we're in NIS-only mode, short-circuit 1901e890b05SBill Paul * parse_netgroup() and cut directly to the chase. 1911e890b05SBill Paul */ 192d454389cSBill Paul if (_use_only_yp && _yp_innetgr) { 193d454389cSBill Paul /* dohw! */ 194d454389cSBill Paul fclose(netf); 1951e890b05SBill Paul return; 196d454389cSBill Paul } 1971e890b05SBill Paul #else 19858f0484fSRodney W. Grimes if (netf = fopen(_PATH_NETGROUP, "r")) { 1991e890b05SBill Paul #endif 20058f0484fSRodney W. Grimes if (parse_netgrp(group)) 20158f0484fSRodney W. Grimes endnetgrent(); 20258f0484fSRodney W. Grimes else { 20358f0484fSRodney W. Grimes grouphead.grname = (char *) 20458f0484fSRodney W. Grimes malloc(strlen(group) + 1); 20558f0484fSRodney W. Grimes strcpy(grouphead.grname, group); 20658f0484fSRodney W. Grimes } 2071e890b05SBill Paul if (netf) 20858f0484fSRodney W. Grimes fclose(netf); 20958f0484fSRodney W. Grimes } 21058f0484fSRodney W. Grimes } 21158f0484fSRodney W. Grimes nextgrp = grouphead.gr; 21258f0484fSRodney W. Grimes } 21358f0484fSRodney W. Grimes 21458f0484fSRodney W. Grimes /* 21558f0484fSRodney W. Grimes * Get the next netgroup off the list. 21658f0484fSRodney W. Grimes */ 21758f0484fSRodney W. Grimes int 21858f0484fSRodney W. Grimes getnetgrent(hostp, userp, domp) 21958f0484fSRodney W. Grimes char **hostp, **userp, **domp; 22058f0484fSRodney W. Grimes { 2211e890b05SBill Paul #ifdef YP 2221e890b05SBill Paul _yp_innetgr = 0; 2231e890b05SBill Paul #endif 22458f0484fSRodney W. Grimes 22558f0484fSRodney W. Grimes if (nextgrp) { 22658f0484fSRodney W. Grimes *hostp = nextgrp->ng_str[NG_HOST]; 22758f0484fSRodney W. Grimes *userp = nextgrp->ng_str[NG_USER]; 22858f0484fSRodney W. Grimes *domp = nextgrp->ng_str[NG_DOM]; 22958f0484fSRodney W. Grimes nextgrp = nextgrp->ng_next; 23058f0484fSRodney W. Grimes return (1); 23158f0484fSRodney W. Grimes } 23258f0484fSRodney W. Grimes return (0); 23358f0484fSRodney W. Grimes } 23458f0484fSRodney W. Grimes 23558f0484fSRodney W. Grimes /* 23658f0484fSRodney W. Grimes * endnetgrent() - cleanup 23758f0484fSRodney W. Grimes */ 23858f0484fSRodney W. Grimes void 23958f0484fSRodney W. Grimes endnetgrent() 24058f0484fSRodney W. Grimes { 24158f0484fSRodney W. Grimes register struct linelist *lp, *olp; 24258f0484fSRodney W. Grimes register struct netgrp *gp, *ogp; 24358f0484fSRodney W. Grimes 24458f0484fSRodney W. Grimes lp = linehead; 24558f0484fSRodney W. Grimes while (lp) { 24658f0484fSRodney W. Grimes olp = lp; 24758f0484fSRodney W. Grimes lp = lp->l_next; 24858f0484fSRodney W. Grimes free(olp->l_groupname); 24958f0484fSRodney W. Grimes free(olp->l_line); 25058f0484fSRodney W. Grimes free((char *)olp); 25158f0484fSRodney W. Grimes } 25258f0484fSRodney W. Grimes linehead = (struct linelist *)0; 25358f0484fSRodney W. Grimes if (grouphead.grname) { 25458f0484fSRodney W. Grimes free(grouphead.grname); 25558f0484fSRodney W. Grimes grouphead.grname = (char *)0; 25658f0484fSRodney W. Grimes } 25758f0484fSRodney W. Grimes gp = grouphead.gr; 25858f0484fSRodney W. Grimes while (gp) { 25958f0484fSRodney W. Grimes ogp = gp; 26058f0484fSRodney W. Grimes gp = gp->ng_next; 26158f0484fSRodney W. Grimes if (ogp->ng_str[NG_HOST]) 26258f0484fSRodney W. Grimes free(ogp->ng_str[NG_HOST]); 26358f0484fSRodney W. Grimes if (ogp->ng_str[NG_USER]) 26458f0484fSRodney W. Grimes free(ogp->ng_str[NG_USER]); 26558f0484fSRodney W. Grimes if (ogp->ng_str[NG_DOM]) 26658f0484fSRodney W. Grimes free(ogp->ng_str[NG_DOM]); 26758f0484fSRodney W. Grimes free((char *)ogp); 26858f0484fSRodney W. Grimes } 26958f0484fSRodney W. Grimes grouphead.gr = (struct netgrp *)0; 270409495f6SBill Paul #ifdef YP 2718516cd0fSBill Paul _netgr_yp_enabled = 0; 272409495f6SBill Paul #endif 27358f0484fSRodney W. Grimes } 27458f0484fSRodney W. Grimes 2751e890b05SBill Paul #ifdef YP 27622397ec3SBill Paul static int _listmatch(list, group, len) 2771e890b05SBill Paul char *list, *group; 27822397ec3SBill Paul int len; 2791e890b05SBill Paul { 2801e890b05SBill Paul char *ptr = list; 2811e890b05SBill Paul 28222397ec3SBill Paul while (ptr != (char *)(list + len)) { 28322397ec3SBill Paul if (!strncmp(group, ptr, strlen(group))) 2841e890b05SBill Paul return(1); 2851e890b05SBill Paul ptr++; 2861e890b05SBill Paul } 2871e890b05SBill Paul return(0); 2881e890b05SBill Paul } 2891e890b05SBill Paul 2901e890b05SBill Paul static int _buildkey(key, str, dom, rotation) 2911e890b05SBill Paul char *key, *str, *dom; 2921e890b05SBill Paul int *rotation; 2931e890b05SBill Paul { 2941e890b05SBill Paul (*rotation)++; 2951e890b05SBill Paul if (*rotation > 4) 2961e890b05SBill Paul return(0); 2971e890b05SBill Paul switch(*rotation) { 2981e890b05SBill Paul case(1): sprintf((char *)key, "%s.%s", str, dom ? dom : "*"); 2991e890b05SBill Paul break; 3001e890b05SBill Paul case(2): sprintf((char *)key, "%s.*", str); 3011e890b05SBill Paul break; 3021e890b05SBill Paul case(3): sprintf((char *)key, "*.%s", dom ? dom : "*"); 3031e890b05SBill Paul break; 3041e890b05SBill Paul case(4): sprintf((char *)key, "*.*"); 3051e890b05SBill Paul break; 3061e890b05SBill Paul } 3071e890b05SBill Paul return(1); 3081e890b05SBill Paul } 3091e890b05SBill Paul #endif 3101e890b05SBill Paul 31158f0484fSRodney W. Grimes /* 31258f0484fSRodney W. Grimes * Search for a match in a netgroup. 31358f0484fSRodney W. Grimes */ 31458f0484fSRodney W. Grimes int 31558f0484fSRodney W. Grimes innetgr(group, host, user, dom) 31658f0484fSRodney W. Grimes char *group, *host, *user, *dom; 31758f0484fSRodney W. Grimes { 31858f0484fSRodney W. Grimes char *hst, *usr, *dm; 3191e890b05SBill Paul #ifdef YP 3201e890b05SBill Paul char *result; 3211e890b05SBill Paul int resultlen; 3221e890b05SBill Paul #endif 3230ffe27f5SBill Paul /* Sanity check */ 3240ffe27f5SBill Paul 3250ffe27f5SBill Paul if (group == NULL || !strlen(group)) 3260ffe27f5SBill Paul return (0); 3270ffe27f5SBill Paul 3281e890b05SBill Paul #ifdef YP 3291e890b05SBill Paul _yp_innetgr = 1; 3301e890b05SBill Paul #endif 33158f0484fSRodney W. Grimes setnetgrent(group); 3321e890b05SBill Paul #ifdef YP 3331e890b05SBill Paul /* 3341e890b05SBill Paul * If we're in NIS-only mode, do the search using 3351e890b05SBill Paul * NIS 'reverse netgroup' lookups. 3361e890b05SBill Paul */ 3371e890b05SBill Paul if (_use_only_yp) { 3381e890b05SBill Paul char _key[MAXHOSTNAMELEN]; 3391e890b05SBill Paul int rot = 0; 3401e890b05SBill Paul 3411e890b05SBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 3421e890b05SBill Paul return(0); 3431e890b05SBill Paul while(_buildkey(&_key, user ? user : host, dom, &rot)) { 3441e890b05SBill Paul if (yp_match(_netgr_yp_domain, user? "netgroup.byuser": 3451e890b05SBill Paul "netgroup.byhost", _key, strlen(_key), &result, 3461e890b05SBill Paul &resultlen)) 3471e890b05SBill Paul free(result); 3481e890b05SBill Paul else { 34922397ec3SBill Paul if (_listmatch(result, group, resultlen)) { 3501e890b05SBill Paul free(result); 3511e890b05SBill Paul return(1); 3521e890b05SBill Paul } 3531e890b05SBill Paul } 3541e890b05SBill Paul } 3551e890b05SBill Paul free(result); 3561e890b05SBill Paul #ifdef CHARITABLE 3571e890b05SBill Paul } 3581e890b05SBill Paul /* 3591e890b05SBill Paul * Couldn't match using NIS-exclusive mode -- try 3601e890b05SBill Paul * standard mode. 3611e890b05SBill Paul */ 3621e890b05SBill Paul _yp_innetgr = 0; 3631e890b05SBill Paul setnetgrent(group); 3641e890b05SBill Paul #else 3651e890b05SBill Paul return(0); 3661e890b05SBill Paul } 3671e890b05SBill Paul #endif /* CHARITABLE */ 3681e890b05SBill Paul #endif /* YP */ 36958f0484fSRodney W. Grimes while (getnetgrent(&hst, &usr, &dm)) 3701e890b05SBill Paul if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 3711e890b05SBill Paul (user == NULL || usr == NULL || !strcmp(user, usr)) && 3721e890b05SBill Paul ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 37358f0484fSRodney W. Grimes endnetgrent(); 37458f0484fSRodney W. Grimes return (1); 37558f0484fSRodney W. Grimes } 37658f0484fSRodney W. Grimes endnetgrent(); 37758f0484fSRodney W. Grimes return (0); 37858f0484fSRodney W. Grimes } 37958f0484fSRodney W. Grimes 38058f0484fSRodney W. Grimes /* 38158f0484fSRodney W. Grimes * Parse the netgroup file setting up the linked lists. 38258f0484fSRodney W. Grimes */ 38358f0484fSRodney W. Grimes static int 38458f0484fSRodney W. Grimes parse_netgrp(group) 38558f0484fSRodney W. Grimes char *group; 38658f0484fSRodney W. Grimes { 38758f0484fSRodney W. Grimes register char *spos, *epos; 38858f0484fSRodney W. Grimes register int len, strpos; 389dbf973c0SBill Paul #ifdef DEBUG 390dbf973c0SBill Paul register int fields; 391dbf973c0SBill Paul #endif 39258f0484fSRodney W. Grimes char *pos, *gpos; 39358f0484fSRodney W. Grimes struct netgrp *grp; 39458f0484fSRodney W. Grimes struct linelist *lp = linehead; 39558f0484fSRodney W. Grimes 39658f0484fSRodney W. Grimes /* 39758f0484fSRodney W. Grimes * First, see if the line has already been read in. 39858f0484fSRodney W. Grimes */ 39958f0484fSRodney W. Grimes while (lp) { 40058f0484fSRodney W. Grimes if (!strcmp(group, lp->l_groupname)) 40158f0484fSRodney W. Grimes break; 40258f0484fSRodney W. Grimes lp = lp->l_next; 40358f0484fSRodney W. Grimes } 40458f0484fSRodney W. Grimes if (lp == (struct linelist *)0 && 40558f0484fSRodney W. Grimes (lp = read_for_group(group)) == (struct linelist *)0) 40658f0484fSRodney W. Grimes return (1); 40758f0484fSRodney W. Grimes if (lp->l_parsed) { 408dbf973c0SBill Paul #ifdef DEBUG 409dbf973c0SBill Paul /* 410dbf973c0SBill Paul * This error message is largely superflous since the 411dbf973c0SBill Paul * code handles the error condition sucessfully, and 412dbf973c0SBill Paul * spewing it out from inside libc can actually hose 413dbf973c0SBill Paul * certain programs. 414dbf973c0SBill Paul */ 41558f0484fSRodney W. Grimes fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 416dbf973c0SBill Paul #endif 41758f0484fSRodney W. Grimes return (1); 41858f0484fSRodney W. Grimes } else 41958f0484fSRodney W. Grimes lp->l_parsed = 1; 42058f0484fSRodney W. Grimes pos = lp->l_line; 421409495f6SBill Paul /* Watch for null pointer dereferences, dammit! */ 422409495f6SBill Paul while (pos != NULL && *pos != '\0') { 42358f0484fSRodney W. Grimes if (*pos == '(') { 42458f0484fSRodney W. Grimes grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 42558f0484fSRodney W. Grimes bzero((char *)grp, sizeof (struct netgrp)); 42658f0484fSRodney W. Grimes grp->ng_next = grouphead.gr; 42758f0484fSRodney W. Grimes grouphead.gr = grp; 42858f0484fSRodney W. Grimes pos++; 42958f0484fSRodney W. Grimes gpos = strsep(&pos, ")"); 430dbf973c0SBill Paul #ifdef DEBUG 431dbf973c0SBill Paul fields = 0; 432dbf973c0SBill Paul #endif 43358f0484fSRodney W. Grimes for (strpos = 0; strpos < 3; strpos++) { 4341e890b05SBill Paul if ((spos = strsep(&gpos, ","))) { 435dbf973c0SBill Paul #ifdef DEBUG 436dbf973c0SBill Paul fields++; 437dbf973c0SBill Paul #endif 43858f0484fSRodney W. Grimes while (*spos == ' ' || *spos == '\t') 43958f0484fSRodney W. Grimes spos++; 4401e890b05SBill Paul if ((epos = strpbrk(spos, " \t"))) { 44158f0484fSRodney W. Grimes *epos = '\0'; 44258f0484fSRodney W. Grimes len = epos - spos; 44358f0484fSRodney W. Grimes } else 44458f0484fSRodney W. Grimes len = strlen(spos); 44558f0484fSRodney W. Grimes if (len > 0) { 44658f0484fSRodney W. Grimes grp->ng_str[strpos] = (char *) 44758f0484fSRodney W. Grimes malloc(len + 1); 44858f0484fSRodney W. Grimes bcopy(spos, grp->ng_str[strpos], 44958f0484fSRodney W. Grimes len + 1); 45058f0484fSRodney W. Grimes } 451dbf973c0SBill Paul } else { 452dbf973c0SBill Paul /* 453dbf973c0SBill Paul * All other systems I've tested 454dbf973c0SBill Paul * return NULL for empty netgroup 455dbf973c0SBill Paul * fields. It's up to user programs 456dbf973c0SBill Paul * to handle the NULLs appropriately. 457dbf973c0SBill Paul */ 458dbf973c0SBill Paul grp->ng_str[strpos] = NULL; 45958f0484fSRodney W. Grimes } 460dbf973c0SBill Paul } 461dbf973c0SBill Paul #ifdef DEBUG 462dbf973c0SBill Paul /* 463dbf973c0SBill Paul * Note: on other platforms, malformed netgroup 464dbf973c0SBill Paul * entries are not normally flagged. While we 465dbf973c0SBill Paul * can catch bad entries and report them, we should 466dbf973c0SBill Paul * stay silent by default for compatibility's sake. 467dbf973c0SBill Paul */ 468dbf973c0SBill Paul if (fields < 3) 469dbf973c0SBill Paul fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 470dbf973c0SBill Paul grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], 471dbf973c0SBill Paul grp->ng_str[NG_USER] == NULL ? "" : ",", 472dbf973c0SBill Paul grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], 473dbf973c0SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : ",", 474dbf973c0SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], 475dbf973c0SBill Paul lp->l_groupname); 476dbf973c0SBill Paul #endif 47758f0484fSRodney W. Grimes } else { 47858f0484fSRodney W. Grimes spos = strsep(&pos, ", \t"); 47958f0484fSRodney W. Grimes if (parse_netgrp(spos)) 480e8030794SBill Paul continue; 48158f0484fSRodney W. Grimes } 482409495f6SBill Paul /* Watch for null pointer dereferences, dammit! */ 483409495f6SBill Paul if (pos != NULL) 48458f0484fSRodney W. Grimes while (*pos == ' ' || *pos == ',' || *pos == '\t') 48558f0484fSRodney W. Grimes pos++; 48658f0484fSRodney W. Grimes } 48758f0484fSRodney W. Grimes return (0); 48858f0484fSRodney W. Grimes } 48958f0484fSRodney W. Grimes 49058f0484fSRodney W. Grimes /* 49158f0484fSRodney W. Grimes * Read the netgroup file and save lines until the line for the netgroup 49258f0484fSRodney W. Grimes * is found. Return 1 if eof is encountered. 49358f0484fSRodney W. Grimes */ 49458f0484fSRodney W. Grimes static struct linelist * 49558f0484fSRodney W. Grimes read_for_group(group) 49658f0484fSRodney W. Grimes char *group; 49758f0484fSRodney W. Grimes { 49858f0484fSRodney W. Grimes register char *pos, *spos, *linep, *olinep; 49958f0484fSRodney W. Grimes register int len, olen; 50058f0484fSRodney W. Grimes int cont; 50158f0484fSRodney W. Grimes struct linelist *lp; 50258f0484fSRodney W. Grimes char line[LINSIZ + 1]; 503409495f6SBill Paul #ifdef YP 504409495f6SBill Paul char *result; 505409495f6SBill Paul int resultlen; 50658f0484fSRodney W. Grimes 507409495f6SBill Paul while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 508409495f6SBill Paul if (_netgr_yp_enabled) { 509409495f6SBill Paul if(!_netgr_yp_domain) 5108516cd0fSBill Paul if(yp_get_default_domain(&_netgr_yp_domain)) 511409495f6SBill Paul continue; 5128516cd0fSBill Paul if (yp_match(_netgr_yp_domain, "netgroup", group, 5138516cd0fSBill Paul strlen(group), &result, &resultlen)) { 5148516cd0fSBill Paul free(result); 5151e890b05SBill Paul if (_use_only_yp) 5168516cd0fSBill Paul return ((struct linelist *)0); 5171e890b05SBill Paul else { 5181e890b05SBill Paul _netgr_yp_enabled = 0; 5191e890b05SBill Paul continue; 5201e890b05SBill Paul } 521409495f6SBill Paul } 5228516cd0fSBill Paul sprintf(line, "%s %s", group, result); 523409495f6SBill Paul free(result); 524409495f6SBill Paul } 525409495f6SBill Paul #else 52658f0484fSRodney W. Grimes while (fgets(line, LINSIZ, netf) != NULL) { 527409495f6SBill Paul #endif 528409495f6SBill Paul pos = (char *)&line; 529409495f6SBill Paul #ifdef YP 530409495f6SBill Paul if (*pos == '+') { 531409495f6SBill Paul _netgr_yp_enabled = 1; 532409495f6SBill Paul continue; 533409495f6SBill Paul } 534409495f6SBill Paul #endif 53558f0484fSRodney W. Grimes if (*pos == '#') 53658f0484fSRodney W. Grimes continue; 53758f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 53858f0484fSRodney W. Grimes pos++; 53958f0484fSRodney W. Grimes spos = pos; 54058f0484fSRodney W. Grimes while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 54158f0484fSRodney W. Grimes *pos != '\0') 54258f0484fSRodney W. Grimes pos++; 54358f0484fSRodney W. Grimes len = pos - spos; 54458f0484fSRodney W. Grimes while (*pos == ' ' || *pos == '\t') 54558f0484fSRodney W. Grimes pos++; 54658f0484fSRodney W. Grimes if (*pos != '\n' && *pos != '\0') { 54758f0484fSRodney W. Grimes lp = (struct linelist *)malloc(sizeof (*lp)); 54858f0484fSRodney W. Grimes lp->l_parsed = 0; 54958f0484fSRodney W. Grimes lp->l_groupname = (char *)malloc(len + 1); 55058f0484fSRodney W. Grimes bcopy(spos, lp->l_groupname, len); 55158f0484fSRodney W. Grimes *(lp->l_groupname + len) = '\0'; 55258f0484fSRodney W. Grimes len = strlen(pos); 55358f0484fSRodney W. Grimes olen = 0; 55458f0484fSRodney W. Grimes 55558f0484fSRodney W. Grimes /* 55658f0484fSRodney W. Grimes * Loop around handling line continuations. 55758f0484fSRodney W. Grimes */ 55858f0484fSRodney W. Grimes do { 55958f0484fSRodney W. Grimes if (*(pos + len - 1) == '\n') 56058f0484fSRodney W. Grimes len--; 56158f0484fSRodney W. Grimes if (*(pos + len - 1) == '\\') { 56258f0484fSRodney W. Grimes len--; 56358f0484fSRodney W. Grimes cont = 1; 56458f0484fSRodney W. Grimes } else 56558f0484fSRodney W. Grimes cont = 0; 56658f0484fSRodney W. Grimes if (len > 0) { 56758f0484fSRodney W. Grimes linep = (char *)malloc(olen + len + 1); 56858f0484fSRodney W. Grimes if (olen > 0) { 56958f0484fSRodney W. Grimes bcopy(olinep, linep, olen); 57058f0484fSRodney W. Grimes free(olinep); 57158f0484fSRodney W. Grimes } 57258f0484fSRodney W. Grimes bcopy(pos, linep + olen, len); 57358f0484fSRodney W. Grimes olen += len; 57458f0484fSRodney W. Grimes *(linep + olen) = '\0'; 57558f0484fSRodney W. Grimes olinep = linep; 57658f0484fSRodney W. Grimes } 57758f0484fSRodney W. Grimes if (cont) { 57858f0484fSRodney W. Grimes if (fgets(line, LINSIZ, netf)) { 57958f0484fSRodney W. Grimes pos = line; 58058f0484fSRodney W. Grimes len = strlen(pos); 58158f0484fSRodney W. Grimes } else 58258f0484fSRodney W. Grimes cont = 0; 58358f0484fSRodney W. Grimes } 58458f0484fSRodney W. Grimes } while (cont); 58558f0484fSRodney W. Grimes lp->l_line = linep; 58658f0484fSRodney W. Grimes lp->l_next = linehead; 58758f0484fSRodney W. Grimes linehead = lp; 58858f0484fSRodney W. Grimes 58958f0484fSRodney W. Grimes /* 59058f0484fSRodney W. Grimes * If this is the one we wanted, we are done. 59158f0484fSRodney W. Grimes */ 59258f0484fSRodney W. Grimes if (!strcmp(lp->l_groupname, group)) 59358f0484fSRodney W. Grimes return (lp); 59458f0484fSRodney W. Grimes } 59558f0484fSRodney W. Grimes } 5961e890b05SBill Paul #ifdef YP 5971e890b05SBill Paul /* 5981e890b05SBill Paul * Yucky. The recursive nature of this whole mess might require 5991e890b05SBill Paul * us to make more than one pass through the netgroup file. 6001e890b05SBill Paul * This might be best left outside the #ifdef YP, but YP is 6011e890b05SBill Paul * defined by default anyway, so I'll leave it like this 6021e890b05SBill Paul * until I know better. 6031e890b05SBill Paul */ 6041e890b05SBill Paul rewind(netf); 6051e890b05SBill Paul #endif 60658f0484fSRodney W. Grimes return ((struct linelist *)0); 60758f0484fSRodney W. Grimes } 608