11573Srgrimes/* 21573Srgrimes * Copyright (c) 1992, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * This code is derived from software contributed to Berkeley by 61573Srgrimes * Rick Macklem at The University of Guelph. 71573Srgrimes * 81573Srgrimes * Redistribution and use in source and binary forms, with or without 91573Srgrimes * modification, are permitted provided that the following conditions 101573Srgrimes * are met: 111573Srgrimes * 1. Redistributions of source code must retain the above copyright 121573Srgrimes * notice, this list of conditions and the following disclaimer. 131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141573Srgrimes * notice, this list of conditions and the following disclaimer in the 151573Srgrimes * documentation and/or other materials provided with the distribution. 161573Srgrimes * 4. Neither the name of the University nor the names of its contributors 171573Srgrimes * may be used to endorse or promote products derived from this software 181573Srgrimes * without specific prior written permission. 191573Srgrimes * 201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301573Srgrimes * SUCH DAMAGE. 311573Srgrimes */ 321573Srgrimes 331573Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 3423668Speterstatic char sccsid[] = "@(#)getnetgrent.c 8.2 (Berkeley) 4/27/95"; 351573Srgrimes#endif /* LIBC_SCCS and not lint */ 3690041Sobrien#include <sys/cdefs.h> 3790041Sobrien__FBSDID("$FreeBSD$"); 381573Srgrimes 39108626Stjr#include <ctype.h> 401573Srgrimes#include <stdio.h> 417615Swpaul#include <stdlib.h> 4295459Sdes#include <string.h> 437615Swpaul#include <unistd.h> 441573Srgrimes 457615Swpaul#ifdef YP 469978Swpaul/* 479978Swpaul * Notes: 489978Swpaul * We want to be able to use NIS netgroups properly while retaining 499978Swpaul * the ability to use a local /etc/netgroup file. Unfortunately, you 509978Swpaul * can't really do both at the same time - at least, not efficiently. 519978Swpaul * NetBSD deals with this problem by creating a netgroup database 529978Swpaul * using Berkeley DB (just like the password database) that allows 539978Swpaul * for lookups using netgroup, netgroup.byuser or netgroup.byhost 549978Swpaul * searches. This is a neat idea, but I don't have time to implement 559978Swpaul * something like that now. (I think ultimately it would be nice 569978Swpaul * if we DB-fied the group and netgroup stuff all in one shot, but 579978Swpaul * for now I'm satisfied just to have something that works well 589978Swpaul * without requiring massive code changes.) 599978Swpaul * 609978Swpaul * Therefore, to still permit the use of the local file and maintain 619978Swpaul * optimum NIS performance, we allow for the following conditions: 629978Swpaul * 639978Swpaul * - If /etc/netgroup does not exist and NIS is turned on, we use 649978Swpaul * NIS netgroups only. 659978Swpaul * 669978Swpaul * - If /etc/netgroup exists but is empty, we use NIS netgroups 679978Swpaul * only. 689978Swpaul * 699978Swpaul * - If /etc/netgroup exists and contains _only_ a '+', we use 709978Swpaul * NIS netgroups only. 719978Swpaul * 729978Swpaul * - If /etc/netgroup exists, contains locally defined netgroups 739978Swpaul * and a '+', we use a mixture of NIS and the local entries. 749978Swpaul * This method should return the same NIS data as just using 759978Swpaul * NIS alone, but it will be slower if the NIS netgroup database 769978Swpaul * is large (innetgr() in particular will suffer since extra 779978Swpaul * processing has to be done in order to determine memberships 789978Swpaul * using just the raw netgroup data). 799978Swpaul * 809978Swpaul * - If /etc/netgroup exists and contains only locally defined 819978Swpaul * netgroup entries, we use just those local entries and ignore 829978Swpaul * NIS (this is the original, pre-NIS behavior). 839978Swpaul */ 8430288Swpaul 857615Swpaul#include <rpc/rpc.h> 867615Swpaul#include <rpcsvc/yp_prot.h> 877615Swpaul#include <rpcsvc/ypclnt.h> 889978Swpaul#include <sys/types.h> 899978Swpaul#include <sys/stat.h> 909978Swpaul#include <sys/param.h> 919978Swpaul#include <sys/errno.h> 929978Swpaulstatic char *_netgr_yp_domain; 9310521Swpaulint _use_only_yp; 947615Swpaulstatic int _netgr_yp_enabled; 959978Swpaulstatic int _yp_innetgr; 967615Swpaul#endif 977615Swpaul 989978Swpaul#ifndef _PATH_NETGROUP 991573Srgrimes#define _PATH_NETGROUP "/etc/netgroup" 1009978Swpaul#endif 1011573Srgrimes 1021573Srgrimes/* 1031573Srgrimes * Static Variables and functions used by setnetgrent(), getnetgrent() and 1041573Srgrimes * endnetgrent(). 1051573Srgrimes * There are two linked lists: 1061573Srgrimes * - linelist is just used by setnetgrent() to parse the net group file via. 1071573Srgrimes * parse_netgrp() 1081573Srgrimes * - netgrp is the list of entries for the current netgroup 1091573Srgrimes */ 1101573Srgrimesstruct linelist { 1111573Srgrimes struct linelist *l_next; /* Chain ptr. */ 1121573Srgrimes int l_parsed; /* Flag for cycles */ 1131573Srgrimes char *l_groupname; /* Name of netgroup */ 1141573Srgrimes char *l_line; /* Netgroup entrie(s) to be parsed */ 1151573Srgrimes}; 1161573Srgrimes 1171573Srgrimesstruct netgrp { 1181573Srgrimes struct netgrp *ng_next; /* Chain ptr */ 1191573Srgrimes char *ng_str[3]; /* Field pointers, see below */ 1201573Srgrimes}; 1211573Srgrimes#define NG_HOST 0 /* Host name */ 1221573Srgrimes#define NG_USER 1 /* User name */ 1231573Srgrimes#define NG_DOM 2 /* and Domain name */ 1241573Srgrimes 1251573Srgrimesstatic struct linelist *linehead = (struct linelist *)0; 1261573Srgrimesstatic struct netgrp *nextgrp = (struct netgrp *)0; 1271573Srgrimesstatic struct { 1281573Srgrimes struct netgrp *gr; 1291573Srgrimes char *grname; 1301573Srgrimes} grouphead = { 1311573Srgrimes (struct netgrp *)0, 1321573Srgrimes (char *)0, 1331573Srgrimes}; 1341573Srgrimesstatic FILE *netf = (FILE *)0; 1351573Srgrimes 136132793Sdesstatic int parse_netgrp(const char *); 137132793Sdesstatic struct linelist *read_for_group(const char *); 138132793Sdesvoid setnetgrent(const char *); 139132793Sdesvoid endnetgrent(void); 140132793Sdesint getnetgrent(char **, char **, char **); 141132793Sdesint innetgr(const char *, const char *, const char *, const char *); 142132793Sdes 1431573Srgrimes#define LINSIZ 1024 /* Length of netgroup file line */ 1441573Srgrimes 1451573Srgrimes/* 1461573Srgrimes * setnetgrent() 1471573Srgrimes * Parse the netgroup file looking for the netgroup and build the list 1481573Srgrimes * of netgrp structures. Let parse_netgrp() and read_for_group() do 1491573Srgrimes * most of the work. 1501573Srgrimes */ 1511573Srgrimesvoid 152132793Sdessetnetgrent(const char *group) 1531573Srgrimes{ 1549978Swpaul#ifdef YP 1559978Swpaul struct stat _yp_statp; 1569978Swpaul char _yp_plus; 1579978Swpaul#endif 1589978Swpaul 1597336Swpaul /* Sanity check */ 1607289Swpaul 1617336Swpaul if (group == NULL || !strlen(group)) 1627289Swpaul return; 1637336Swpaul 164237160Skib if (grouphead.gr == NULL || strcmp(group, grouphead.grname)) { 1651573Srgrimes endnetgrent(); 1669978Swpaul#ifdef YP 16710521Swpaul /* Presumed guilty until proven innocent. */ 16810521Swpaul _use_only_yp = 0; 1699978Swpaul /* 17015264Swpaul * If /etc/netgroup doesn't exist or is empty, 1719978Swpaul * use NIS exclusively. 1729978Swpaul */ 1739978Swpaul if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && 174237160Skib errno == ENOENT) || _yp_statp.st_size == 0) 1759978Swpaul _use_only_yp = _netgr_yp_enabled = 1; 176244092Sjilles if ((netf = fopen(_PATH_NETGROUP,"re")) != NULL ||_use_only_yp){ 1779978Swpaul /* 1789978Swpaul * Icky: grab the first character of the netgroup file 1799978Swpaul * and turn on NIS if it's a '+'. rewind the stream 1809978Swpaul * afterwards so we don't goof up read_for_group() later. 1819978Swpaul */ 1829978Swpaul if (netf) { 1839978Swpaul fscanf(netf, "%c", &_yp_plus); 1849978Swpaul rewind(netf); 1859978Swpaul if (_yp_plus == '+') 1869978Swpaul _use_only_yp = _netgr_yp_enabled = 1; 1879978Swpaul } 1889978Swpaul /* 1899978Swpaul * If we were called specifically for an innetgr() 1909978Swpaul * lookup and we're in NIS-only mode, short-circuit 1919978Swpaul * parse_netgroup() and cut directly to the chase. 1929978Swpaul */ 19310521Swpaul if (_use_only_yp && _yp_innetgr) { 19410521Swpaul /* dohw! */ 19512585Swpaul if (netf != NULL) 19612585Swpaul fclose(netf); 1979978Swpaul return; 19810521Swpaul } 1999978Swpaul#else 200244092Sjilles if ((netf = fopen(_PATH_NETGROUP, "re"))) { 2019978Swpaul#endif 2021573Srgrimes if (parse_netgrp(group)) 2031573Srgrimes endnetgrent(); 2041573Srgrimes else { 205235740Sghelmer grouphead.grname = strdup(group); 2061573Srgrimes } 2079978Swpaul if (netf) 2089978Swpaul fclose(netf); 2091573Srgrimes } 2101573Srgrimes } 2111573Srgrimes nextgrp = grouphead.gr; 2121573Srgrimes} 2131573Srgrimes 2141573Srgrimes/* 2151573Srgrimes * Get the next netgroup off the list. 2161573Srgrimes */ 2171573Srgrimesint 218132793Sdesgetnetgrent(char **hostp, char **userp, char **domp) 2191573Srgrimes{ 2209978Swpaul#ifdef YP 2219978Swpaul _yp_innetgr = 0; 2229978Swpaul#endif 2231573Srgrimes 2241573Srgrimes if (nextgrp) { 2251573Srgrimes *hostp = nextgrp->ng_str[NG_HOST]; 2261573Srgrimes *userp = nextgrp->ng_str[NG_USER]; 2271573Srgrimes *domp = nextgrp->ng_str[NG_DOM]; 2281573Srgrimes nextgrp = nextgrp->ng_next; 2291573Srgrimes return (1); 2301573Srgrimes } 2311573Srgrimes return (0); 2321573Srgrimes} 2331573Srgrimes 2341573Srgrimes/* 2351573Srgrimes * endnetgrent() - cleanup 2361573Srgrimes */ 2371573Srgrimesvoid 238132793Sdesendnetgrent(void) 2391573Srgrimes{ 24090041Sobrien struct linelist *lp, *olp; 24190041Sobrien struct netgrp *gp, *ogp; 2421573Srgrimes 2431573Srgrimes lp = linehead; 2441573Srgrimes while (lp) { 2451573Srgrimes olp = lp; 2461573Srgrimes lp = lp->l_next; 2471573Srgrimes free(olp->l_groupname); 2481573Srgrimes free(olp->l_line); 249237160Skib free(olp); 2501573Srgrimes } 251237160Skib linehead = NULL; 2521573Srgrimes if (grouphead.grname) { 2531573Srgrimes free(grouphead.grname); 254237160Skib grouphead.grname = NULL; 2551573Srgrimes } 2561573Srgrimes gp = grouphead.gr; 2571573Srgrimes while (gp) { 2581573Srgrimes ogp = gp; 2591573Srgrimes gp = gp->ng_next; 260237160Skib free(ogp->ng_str[NG_HOST]); 261237160Skib free(ogp->ng_str[NG_USER]); 262237160Skib free(ogp->ng_str[NG_DOM]); 263237160Skib free(ogp); 2641573Srgrimes } 265237160Skib grouphead.gr = NULL; 266237160Skib nextgrp = NULL; 2677149Swpaul#ifdef YP 2687223Swpaul _netgr_yp_enabled = 0; 2697149Swpaul#endif 2701573Srgrimes} 2711573Srgrimes 2729978Swpaul#ifdef YP 273132793Sdesstatic int 274132793Sdes_listmatch(const char *list, const char *group, int len) 2759978Swpaul{ 276132793Sdes const char *ptr = list; 277132793Sdes const char *cptr; 27831180Swpaul int glen = strlen(group); 2799978Swpaul 28031180Swpaul /* skip possible leading whitespace */ 281237160Skib while (isspace((unsigned char)*ptr)) 28231180Swpaul ptr++; 28315264Swpaul 28433950Ssteve while (ptr < list + len) { 28533950Ssteve cptr = ptr; 28652856Sache while(*ptr != ',' && *ptr != '\0' && !isspace((unsigned char)*ptr)) 28733950Ssteve ptr++; 28833950Ssteve if (strncmp(cptr, group, glen) == 0 && glen == (ptr - cptr)) 289235739Sghelmer return (1); 290237160Skib while (*ptr == ',' || isspace((unsigned char)*ptr)) 29133950Ssteve ptr++; 29215839Swpaul } 29315839Swpaul 294235739Sghelmer return (0); 2959978Swpaul} 2969978Swpaul 297132793Sdesstatic int 298148317Sjon_revnetgr_lookup(char* lookupdom, char* map, const char* str, 299148317Sjon const char* dom, const char* group) 3009978Swpaul{ 301148317Sjon int y, rv, rot; 302148317Sjon char key[MAXHOSTNAMELEN]; 303148317Sjon char *result; 304148317Sjon int resultlen; 305148317Sjon 306148317Sjon for (rot = 0; ; rot++) { 307148317Sjon switch (rot) { 308236402Sghelmer case 0: 309235739Sghelmer snprintf(key, MAXHOSTNAMELEN, "%s.%s", str, 310235739Sghelmer dom ? dom : lookupdom); 311235739Sghelmer break; 312236402Sghelmer case 1: 313235739Sghelmer snprintf(key, MAXHOSTNAMELEN, "%s.*", str); 314235739Sghelmer break; 315236402Sghelmer case 2: 316235739Sghelmer snprintf(key, MAXHOSTNAMELEN, "*.%s", 317235739Sghelmer dom ? dom : lookupdom); 318235739Sghelmer break; 319236402Sghelmer case 3: 320235739Sghelmer snprintf(key, MAXHOSTNAMELEN, "*.*"); 321235739Sghelmer break; 322236402Sghelmer default: 323236402Sghelmer return (0); 324148317Sjon } 325148317Sjon y = yp_match(lookupdom, map, key, strlen(key), &result, 326236402Sghelmer &resultlen); 327148317Sjon if (y == 0) { 328148317Sjon rv = _listmatch(result, group, resultlen); 329148317Sjon free(result); 330236402Sghelmer if (rv) 331236402Sghelmer return (1); 332148317Sjon } else if (y != YPERR_KEY) { 333148317Sjon /* 334148317Sjon * If we get an error other than 'no 335148317Sjon * such key in map' then something is 336148317Sjon * wrong and we should stop the search. 337148317Sjon */ 338235739Sghelmer return (-1); 339148317Sjon } 3409978Swpaul } 3419978Swpaul} 3429978Swpaul#endif 3439978Swpaul 3441573Srgrimes/* 3451573Srgrimes * Search for a match in a netgroup. 3461573Srgrimes */ 3471573Srgrimesint 348132793Sdesinnetgr(const char *group, const char *host, const char *user, const char *dom) 3491573Srgrimes{ 3501573Srgrimes char *hst, *usr, *dm; 3517336Swpaul /* Sanity check */ 3529287Swpaul 3537336Swpaul if (group == NULL || !strlen(group)) 3547336Swpaul return (0); 3557336Swpaul 3569978Swpaul#ifdef YP 3579978Swpaul _yp_innetgr = 1; 3589978Swpaul#endif 3591573Srgrimes setnetgrent(group); 3609978Swpaul#ifdef YP 36115264Swpaul _yp_innetgr = 0; 3629978Swpaul /* 3639978Swpaul * If we're in NIS-only mode, do the search using 3649978Swpaul * NIS 'reverse netgroup' lookups. 365148317Sjon * 366148317Sjon * What happens with 'reverse netgroup' lookups: 367148317Sjon * 368148317Sjon * 1) try 'reverse netgroup' lookup 369148317Sjon * 1.a) if host is specified and user is null: 370148317Sjon * look in netgroup.byhost 371148317Sjon * (try host.domain, host.*, *.domain or *.*) 372148317Sjon * if found, return yes 373148317Sjon * 1.b) if user is specified and host is null: 374148317Sjon * look in netgroup.byuser 375148317Sjon * (try host.domain, host.*, *.domain or *.*) 376148317Sjon * if found, return yes 377148317Sjon * 1.c) if both host and user are specified, 378148317Sjon * don't do 'reverse netgroup' lookup. It won't work. 379148317Sjon * 1.d) if neither host ane user are specified (why?!?) 380148317Sjon * don't do 'reverse netgroup' lookup either. 381148317Sjon * 2) if domain is specified and 'reverse lookup' is done: 382148317Sjon * 'reverse lookup' was authoritative. bye bye. 383148317Sjon * 3) otherwise, too bad, try it the slow way. 3849978Swpaul */ 385148317Sjon if (_use_only_yp && (host == NULL) != (user == NULL)) { 386148317Sjon int ret; 3879978Swpaul if(yp_get_default_domain(&_netgr_yp_domain)) 388235739Sghelmer return (0); 389148317Sjon ret = _revnetgr_lookup(_netgr_yp_domain, 390148317Sjon host?"netgroup.byhost":"netgroup.byuser", 391148317Sjon host?host:user, dom, group); 392148317Sjon if (ret == 1) 393235739Sghelmer return (1); 394148317Sjon else if (ret == 0 && dom != NULL) 395235739Sghelmer return (0); 3969978Swpaul } 39730390Swpaul 3989978Swpaul setnetgrent(group); 3999978Swpaul#endif /* YP */ 40030390Swpaul 4011573Srgrimes while (getnetgrent(&hst, &usr, &dm)) 4029978Swpaul if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 4039978Swpaul (user == NULL || usr == NULL || !strcmp(user, usr)) && 4049978Swpaul ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 4051573Srgrimes endnetgrent(); 4061573Srgrimes return (1); 4071573Srgrimes } 4081573Srgrimes endnetgrent(); 4091573Srgrimes return (0); 4101573Srgrimes} 4111573Srgrimes 4121573Srgrimes/* 4131573Srgrimes * Parse the netgroup file setting up the linked lists. 4141573Srgrimes */ 4151573Srgrimesstatic int 416132793Sdesparse_netgrp(const char *group) 4171573Srgrimes{ 418236402Sghelmer struct netgrp *grp; 419236402Sghelmer struct linelist *lp = linehead; 420236402Sghelmer char **ng; 421236402Sghelmer char *epos, *gpos, *pos, *spos; 422236402Sghelmer int freepos, len, strpos; 4239287Swpaul#ifdef DEBUG 42490041Sobrien int fields; 4259287Swpaul#endif 4261573Srgrimes 4271573Srgrimes /* 4281573Srgrimes * First, see if the line has already been read in. 4291573Srgrimes */ 4301573Srgrimes while (lp) { 4311573Srgrimes if (!strcmp(group, lp->l_groupname)) 4321573Srgrimes break; 4331573Srgrimes lp = lp->l_next; 4341573Srgrimes } 435237160Skib if (lp == NULL && (lp = read_for_group(group)) == NULL) 4361573Srgrimes return (1); 4371573Srgrimes if (lp->l_parsed) { 4389287Swpaul#ifdef DEBUG 4399287Swpaul /* 4409287Swpaul * This error message is largely superflous since the 4419287Swpaul * code handles the error condition sucessfully, and 4429287Swpaul * spewing it out from inside libc can actually hose 4439287Swpaul * certain programs. 4449287Swpaul */ 4451573Srgrimes fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 4469287Swpaul#endif 4471573Srgrimes return (1); 4481573Srgrimes } else 4491573Srgrimes lp->l_parsed = 1; 4501573Srgrimes pos = lp->l_line; 4517149Swpaul /* Watch for null pointer dereferences, dammit! */ 4527149Swpaul while (pos != NULL && *pos != '\0') { 4531573Srgrimes if (*pos == '(') { 454236402Sghelmer grp = malloc(sizeof(*grp)); 455235740Sghelmer if (grp == NULL) 456235740Sghelmer return (1); 457236402Sghelmer ng = grp->ng_str; 458236402Sghelmer bzero(grp, sizeof(*grp)); 4591573Srgrimes pos++; 4601573Srgrimes gpos = strsep(&pos, ")"); 4619287Swpaul#ifdef DEBUG 4629287Swpaul fields = 0; 4639287Swpaul#endif 4641573Srgrimes for (strpos = 0; strpos < 3; strpos++) { 465236402Sghelmer if ((spos = strsep(&gpos, ",")) == NULL) { 4669287Swpaul /* 4679287Swpaul * All other systems I've tested 4689287Swpaul * return NULL for empty netgroup 4699287Swpaul * fields. It's up to user programs 4709287Swpaul * to handle the NULLs appropriately. 4719287Swpaul */ 472236402Sghelmer ng[strpos] = NULL; 473236402Sghelmer continue; 4749287Swpaul } 475236402Sghelmer#ifdef DEBUG 476236402Sghelmer fields++; 477236402Sghelmer#endif 478236402Sghelmer while (*spos == ' ' || *spos == '\t') 479236402Sghelmer spos++; 480236402Sghelmer if ((epos = strpbrk(spos, " \t"))) { 481236402Sghelmer *epos = '\0'; 482236402Sghelmer len = epos - spos; 483236402Sghelmer } else 484236402Sghelmer len = strlen(spos); 485236402Sghelmer if (len <= 0) 486236402Sghelmer continue; 487236402Sghelmer ng[strpos] = malloc(len + 1); 488236402Sghelmer if (ng[strpos] == NULL) { 489236402Sghelmer for (freepos = 0; freepos < strpos; 490236402Sghelmer freepos++) 491236402Sghelmer free(ng[freepos]); 492236402Sghelmer free(grp); 493236402Sghelmer return (1); 494236402Sghelmer } 495236402Sghelmer bcopy(spos, ng[strpos], len + 1); 4961573Srgrimes } 497235740Sghelmer grp->ng_next = grouphead.gr; 498235740Sghelmer grouphead.gr = grp; 4999287Swpaul#ifdef DEBUG 5009287Swpaul /* 5019287Swpaul * Note: on other platforms, malformed netgroup 5029287Swpaul * entries are not normally flagged. While we 5039287Swpaul * can catch bad entries and report them, we should 5049287Swpaul * stay silent by default for compatibility's sake. 5059287Swpaul */ 506236402Sghelmer if (fields < 3) { 507236402Sghelmer fprintf(stderr, 508236402Sghelmer "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 509236402Sghelmer ng[NG_HOST] == NULL ? "" : ng[NG_HOST], 510236402Sghelmer ng[NG_USER] == NULL ? "" : ",", 511236402Sghelmer ng[NG_USER] == NULL ? "" : ng[NG_USER], 512236402Sghelmer ng[NG_DOM] == NULL ? "" : ",", 513236402Sghelmer ng[NG_DOM] == NULL ? "" : ng[NG_DOM], 514236402Sghelmer lp->l_groupname); 5159287Swpaul#endif 5161573Srgrimes } else { 5171573Srgrimes spos = strsep(&pos, ", \t"); 5181573Srgrimes if (parse_netgrp(spos)) 5197175Swpaul continue; 5201573Srgrimes } 52123668Speter if (pos == NULL) 52223668Speter break; 52323668Speter while (*pos == ' ' || *pos == ',' || *pos == '\t') 52423668Speter pos++; 5251573Srgrimes } 5261573Srgrimes return (0); 5271573Srgrimes} 5281573Srgrimes 5291573Srgrimes/* 5301573Srgrimes * Read the netgroup file and save lines until the line for the netgroup 5311573Srgrimes * is found. Return 1 if eof is encountered. 5321573Srgrimes */ 5331573Srgrimesstatic struct linelist * 534132793Sdesread_for_group(const char *group) 5351573Srgrimes{ 536237159Skib char *linep, *olinep, *pos, *spos; 53790041Sobrien int len, olen; 5381573Srgrimes int cont; 5391573Srgrimes struct linelist *lp; 54020957Swpaul char line[LINSIZ + 2]; 5417149Swpaul#ifdef YP 5427149Swpaul char *result; 5437149Swpaul int resultlen; 544235740Sghelmer linep = NULL; 5451573Srgrimes 5467149Swpaul while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 5477149Swpaul if (_netgr_yp_enabled) { 5487149Swpaul if(!_netgr_yp_domain) 5497223Swpaul if(yp_get_default_domain(&_netgr_yp_domain)) 5507149Swpaul continue; 5517223Swpaul if (yp_match(_netgr_yp_domain, "netgroup", group, 552236402Sghelmer strlen(group), &result, &resultlen)) { 5537223Swpaul free(result); 5549978Swpaul if (_use_only_yp) 5559978Swpaul return ((struct linelist *)0); 5569978Swpaul else { 5579978Swpaul _netgr_yp_enabled = 0; 5589978Swpaul continue; 5599978Swpaul } 5607149Swpaul } 56120957Swpaul snprintf(line, LINSIZ, "%s %s", group, result); 5627149Swpaul free(result); 5637149Swpaul } 5647149Swpaul#else 565235740Sghelmer linep = NULL; 5661573Srgrimes while (fgets(line, LINSIZ, netf) != NULL) { 5677149Swpaul#endif 5687149Swpaul pos = (char *)&line; 5697149Swpaul#ifdef YP 5707149Swpaul if (*pos == '+') { 5717149Swpaul _netgr_yp_enabled = 1; 5727149Swpaul continue; 5737149Swpaul } 5747149Swpaul#endif 5751573Srgrimes if (*pos == '#') 5761573Srgrimes continue; 5771573Srgrimes while (*pos == ' ' || *pos == '\t') 5781573Srgrimes pos++; 5791573Srgrimes spos = pos; 5801573Srgrimes while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 5811573Srgrimes *pos != '\0') 5821573Srgrimes pos++; 5831573Srgrimes len = pos - spos; 5841573Srgrimes while (*pos == ' ' || *pos == '\t') 5851573Srgrimes pos++; 5861573Srgrimes if (*pos != '\n' && *pos != '\0') { 5871573Srgrimes lp = (struct linelist *)malloc(sizeof (*lp)); 588235740Sghelmer if (lp == NULL) 589235740Sghelmer return (NULL); 5901573Srgrimes lp->l_parsed = 0; 5911573Srgrimes lp->l_groupname = (char *)malloc(len + 1); 592235740Sghelmer if (lp->l_groupname == NULL) { 593235740Sghelmer free(lp); 594235740Sghelmer return (NULL); 595235740Sghelmer } 5961573Srgrimes bcopy(spos, lp->l_groupname, len); 5971573Srgrimes *(lp->l_groupname + len) = '\0'; 5981573Srgrimes len = strlen(pos); 5991573Srgrimes olen = 0; 6001573Srgrimes 6011573Srgrimes /* 6021573Srgrimes * Loop around handling line continuations. 6031573Srgrimes */ 6041573Srgrimes do { 6051573Srgrimes if (*(pos + len - 1) == '\n') 6061573Srgrimes len--; 6071573Srgrimes if (*(pos + len - 1) == '\\') { 6081573Srgrimes len--; 6091573Srgrimes cont = 1; 6101573Srgrimes } else 6111573Srgrimes cont = 0; 6121573Srgrimes if (len > 0) { 613237159Skib linep = malloc(olen + len + 1); 614235740Sghelmer if (linep == NULL) { 615235740Sghelmer free(lp->l_groupname); 616235740Sghelmer free(lp); 617235740Sghelmer return (NULL); 6181573Srgrimes } 619237159Skib if (olen > 0) { 620237159Skib bcopy(olinep, linep, olen); 621237159Skib free(olinep); 622237159Skib } 6231573Srgrimes bcopy(pos, linep + olen, len); 6241573Srgrimes olen += len; 6251573Srgrimes *(linep + olen) = '\0'; 626237159Skib olinep = linep; 6271573Srgrimes } 6281573Srgrimes if (cont) { 6291573Srgrimes if (fgets(line, LINSIZ, netf)) { 6301573Srgrimes pos = line; 6311573Srgrimes len = strlen(pos); 6321573Srgrimes } else 6331573Srgrimes cont = 0; 6341573Srgrimes } 6351573Srgrimes } while (cont); 6361573Srgrimes lp->l_line = linep; 6371573Srgrimes lp->l_next = linehead; 6381573Srgrimes linehead = lp; 6391573Srgrimes 6401573Srgrimes /* 6411573Srgrimes * If this is the one we wanted, we are done. 6421573Srgrimes */ 6431573Srgrimes if (!strcmp(lp->l_groupname, group)) 6441573Srgrimes return (lp); 6451573Srgrimes } 6461573Srgrimes } 6479978Swpaul#ifdef YP 6489978Swpaul /* 6499978Swpaul * Yucky. The recursive nature of this whole mess might require 6509978Swpaul * us to make more than one pass through the netgroup file. 6519978Swpaul * This might be best left outside the #ifdef YP, but YP is 6529978Swpaul * defined by default anyway, so I'll leave it like this 6539978Swpaul * until I know better. 6549978Swpaul */ 6559978Swpaul rewind(netf); 6569978Swpaul#endif 657235740Sghelmer return (NULL); 6581573Srgrimes} 659