1*8a16b7a1SPedro F. Giffuni /*-
2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
3*8a16b7a1SPedro F. Giffuni *
4a44e4d14SBill Paul * Copyright (c) 1992, 1993
5a44e4d14SBill Paul * The Regents of the University of California. All rights reserved.
6a44e4d14SBill Paul *
7a44e4d14SBill Paul * This code is derived from software contributed to Berkeley by
8a44e4d14SBill Paul * Rick Macklem at The University of Guelph.
9a44e4d14SBill Paul *
10a44e4d14SBill Paul * Redistribution and use in source and binary forms, with or without
11a44e4d14SBill Paul * modification, are permitted provided that the following conditions
12a44e4d14SBill Paul * are met:
13a44e4d14SBill Paul * 1. Redistributions of source code must retain the above copyright
14a44e4d14SBill Paul * notice, this list of conditions and the following disclaimer.
15a44e4d14SBill Paul * 2. Redistributions in binary form must reproduce the above copyright
16a44e4d14SBill Paul * notice, this list of conditions and the following disclaimer in the
17a44e4d14SBill Paul * documentation and/or other materials provided with the distribution.
185efaea4cSChristian Brueffer * 3. Neither the name of the University nor the names of its contributors
19a44e4d14SBill Paul * may be used to endorse or promote products derived from this software
20a44e4d14SBill Paul * without specific prior written permission.
21a44e4d14SBill Paul *
22a44e4d14SBill Paul * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23a44e4d14SBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24a44e4d14SBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25a44e4d14SBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26a44e4d14SBill Paul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27a44e4d14SBill Paul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28a44e4d14SBill Paul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29a44e4d14SBill Paul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30a44e4d14SBill Paul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31a44e4d14SBill Paul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32a44e4d14SBill Paul * SUCH DAMAGE.
33a44e4d14SBill Paul */
34a44e4d14SBill Paul
35a44e4d14SBill Paul /*
36a44e4d14SBill Paul * This is a specially hacked-up version of getnetgrent.c used to parse
37a44e4d14SBill Paul * data from the stored hash table of netgroup info rather than from a
38a44e4d14SBill Paul * file. It's used mainly for the parse_netgroup() function. All the YP
39a44e4d14SBill Paul * stuff and file support has been stripped out since it isn't needed.
40a44e4d14SBill Paul */
41a44e4d14SBill Paul
42a44e4d14SBill Paul #include <stdio.h>
43467a0b06SMike Barcroft #include <string.h>
44a44e4d14SBill Paul #include <strings.h>
45a44e4d14SBill Paul #include <stdlib.h>
46a44e4d14SBill Paul #include <unistd.h>
47a44e4d14SBill Paul #include "hash.h"
48a44e4d14SBill Paul
49a44e4d14SBill Paul /*
50a44e4d14SBill Paul * Static Variables and functions used by setnetgrent(), getnetgrent() and
51a44e4d14SBill Paul * __endnetgrent().
52a44e4d14SBill Paul * There are two linked lists:
53a44e4d14SBill Paul * - linelist is just used by setnetgrent() to parse the net group file via.
54a44e4d14SBill Paul * parse_netgrp()
55a44e4d14SBill Paul * - netgrp is the list of entries for the current netgroup
56a44e4d14SBill Paul */
57a44e4d14SBill Paul struct linelist {
58a44e4d14SBill Paul struct linelist *l_next; /* Chain ptr. */
59a44e4d14SBill Paul int l_parsed; /* Flag for cycles */
60a44e4d14SBill Paul char *l_groupname; /* Name of netgroup */
61a44e4d14SBill Paul char *l_line; /* Netgroup entrie(s) to be parsed */
62a44e4d14SBill Paul };
63a44e4d14SBill Paul
64a44e4d14SBill Paul struct netgrp {
65a44e4d14SBill Paul struct netgrp *ng_next; /* Chain ptr */
66a44e4d14SBill Paul char *ng_str[3]; /* Field pointers, see below */
67a44e4d14SBill Paul };
68a44e4d14SBill Paul #define NG_HOST 0 /* Host name */
69a44e4d14SBill Paul #define NG_USER 1 /* User name */
70a44e4d14SBill Paul #define NG_DOM 2 /* and Domain name */
71a44e4d14SBill Paul
72a44e4d14SBill Paul static struct linelist *linehead = (struct linelist *)0;
73a44e4d14SBill Paul static struct netgrp *nextgrp = (struct netgrp *)0;
74a44e4d14SBill Paul static struct {
75a44e4d14SBill Paul struct netgrp *gr;
76a44e4d14SBill Paul char *grname;
77a44e4d14SBill Paul } grouphead = {
78a44e4d14SBill Paul (struct netgrp *)0,
79a44e4d14SBill Paul (char *)0,
80a44e4d14SBill Paul };
81266ebcd3SWarner Losh static int parse_netgrp(char *group);
82266ebcd3SWarner Losh static struct linelist *read_for_group(char *group);
83a44e4d14SBill Paul extern struct group_entry *gtable[];
84a44e4d14SBill Paul
85a44e4d14SBill Paul /*
86a44e4d14SBill Paul * setnetgrent()
87a44e4d14SBill Paul * Parse the netgroup file looking for the netgroup and build the list
88a44e4d14SBill Paul * of netgrp structures. Let parse_netgrp() and read_for_group() do
89a44e4d14SBill Paul * most of the work.
90a44e4d14SBill Paul */
91a44e4d14SBill Paul void
__setnetgrent(char * group)92266ebcd3SWarner Losh __setnetgrent(char *group)
93a44e4d14SBill Paul {
94a44e4d14SBill Paul /* Sanity check */
95a44e4d14SBill Paul
96a44e4d14SBill Paul if (group == NULL || !strlen(group))
97a44e4d14SBill Paul return;
98a44e4d14SBill Paul
99a44e4d14SBill Paul if (grouphead.gr == (struct netgrp *)0 ||
100a44e4d14SBill Paul strcmp(group, grouphead.grname)) {
101a44e4d14SBill Paul __endnetgrent();
102a44e4d14SBill Paul if (parse_netgrp(group))
103a44e4d14SBill Paul __endnetgrent();
104a44e4d14SBill Paul else {
105a44e4d14SBill Paul grouphead.grname = (char *)
106a44e4d14SBill Paul malloc(strlen(group) + 1);
107a44e4d14SBill Paul strcpy(grouphead.grname, group);
108a44e4d14SBill Paul }
109a44e4d14SBill Paul }
110a44e4d14SBill Paul nextgrp = grouphead.gr;
111a44e4d14SBill Paul }
112a44e4d14SBill Paul
113a44e4d14SBill Paul /*
114a44e4d14SBill Paul * Get the next netgroup off the list.
115a44e4d14SBill Paul */
116a44e4d14SBill Paul int
__getnetgrent(char ** hostp,char ** userp,char ** domp)117266ebcd3SWarner Losh __getnetgrent(char **hostp, char **userp, char **domp)
118a44e4d14SBill Paul {
119a44e4d14SBill Paul if (nextgrp) {
120a44e4d14SBill Paul *hostp = nextgrp->ng_str[NG_HOST];
121a44e4d14SBill Paul *userp = nextgrp->ng_str[NG_USER];
122a44e4d14SBill Paul *domp = nextgrp->ng_str[NG_DOM];
123a44e4d14SBill Paul nextgrp = nextgrp->ng_next;
124a44e4d14SBill Paul return (1);
125a44e4d14SBill Paul }
126a44e4d14SBill Paul return (0);
127a44e4d14SBill Paul }
128a44e4d14SBill Paul
129a44e4d14SBill Paul /*
130a44e4d14SBill Paul * __endnetgrent() - cleanup
131a44e4d14SBill Paul */
132a44e4d14SBill Paul void
__endnetgrent(void)133266ebcd3SWarner Losh __endnetgrent(void)
134a44e4d14SBill Paul {
135266ebcd3SWarner Losh struct linelist *lp, *olp;
136266ebcd3SWarner Losh struct netgrp *gp, *ogp;
137a44e4d14SBill Paul
138a44e4d14SBill Paul lp = linehead;
139a44e4d14SBill Paul while (lp) {
140a44e4d14SBill Paul olp = lp;
141a44e4d14SBill Paul lp = lp->l_next;
142a44e4d14SBill Paul free(olp->l_groupname);
143a44e4d14SBill Paul free(olp->l_line);
144a44e4d14SBill Paul free((char *)olp);
145a44e4d14SBill Paul }
146a44e4d14SBill Paul linehead = (struct linelist *)0;
147a44e4d14SBill Paul if (grouphead.grname) {
148a44e4d14SBill Paul free(grouphead.grname);
149a44e4d14SBill Paul grouphead.grname = (char *)0;
150a44e4d14SBill Paul }
151a44e4d14SBill Paul gp = grouphead.gr;
152a44e4d14SBill Paul while (gp) {
153a44e4d14SBill Paul ogp = gp;
154a44e4d14SBill Paul gp = gp->ng_next;
155a44e4d14SBill Paul if (ogp->ng_str[NG_HOST])
156a44e4d14SBill Paul free(ogp->ng_str[NG_HOST]);
157a44e4d14SBill Paul if (ogp->ng_str[NG_USER])
158a44e4d14SBill Paul free(ogp->ng_str[NG_USER]);
159a44e4d14SBill Paul if (ogp->ng_str[NG_DOM])
160a44e4d14SBill Paul free(ogp->ng_str[NG_DOM]);
161a44e4d14SBill Paul free((char *)ogp);
162a44e4d14SBill Paul }
163a44e4d14SBill Paul grouphead.gr = (struct netgrp *)0;
164a44e4d14SBill Paul }
165a44e4d14SBill Paul
166a44e4d14SBill Paul /*
167a44e4d14SBill Paul * Parse the netgroup file setting up the linked lists.
168a44e4d14SBill Paul */
169a44e4d14SBill Paul static int
parse_netgrp(char * group)170266ebcd3SWarner Losh parse_netgrp(char *group)
171a44e4d14SBill Paul {
172266ebcd3SWarner Losh char *spos, *epos;
173266ebcd3SWarner Losh int len, strpos;
174a44e4d14SBill Paul #ifdef DEBUG
175266ebcd3SWarner Losh int fields;
176a44e4d14SBill Paul #endif
177a44e4d14SBill Paul char *pos, *gpos;
178a44e4d14SBill Paul struct netgrp *grp;
179a44e4d14SBill Paul struct linelist *lp = linehead;
180a44e4d14SBill Paul
181a44e4d14SBill Paul /*
182a44e4d14SBill Paul * First, see if the line has already been read in.
183a44e4d14SBill Paul */
184a44e4d14SBill Paul while (lp) {
185a44e4d14SBill Paul if (!strcmp(group, lp->l_groupname))
186a44e4d14SBill Paul break;
187a44e4d14SBill Paul lp = lp->l_next;
188a44e4d14SBill Paul }
189a44e4d14SBill Paul if (lp == (struct linelist *)0 &&
190a44e4d14SBill Paul (lp = read_for_group(group)) == (struct linelist *)0)
191a44e4d14SBill Paul return (1);
192a44e4d14SBill Paul if (lp->l_parsed) {
193a44e4d14SBill Paul #ifdef DEBUG
194a44e4d14SBill Paul /*
1951acf0dbaSUlrich Spörlein * This error message is largely superfluous since the
1961acf0dbaSUlrich Spörlein * code handles the error condition successfully, and
197a44e4d14SBill Paul * spewing it out from inside libc can actually hose
198a44e4d14SBill Paul * certain programs.
199a44e4d14SBill Paul */
2003029b69fSPhilippe Charnier warnx("cycle in netgroup %s", lp->l_groupname);
201a44e4d14SBill Paul #endif
202a44e4d14SBill Paul return (1);
203a44e4d14SBill Paul } else
204a44e4d14SBill Paul lp->l_parsed = 1;
205a44e4d14SBill Paul pos = lp->l_line;
206a44e4d14SBill Paul /* Watch for null pointer dereferences, dammit! */
207a44e4d14SBill Paul while (pos != NULL && *pos != '\0') {
208a44e4d14SBill Paul if (*pos == '(') {
209a44e4d14SBill Paul grp = (struct netgrp *)malloc(sizeof (struct netgrp));
210a44e4d14SBill Paul bzero((char *)grp, sizeof (struct netgrp));
211a44e4d14SBill Paul grp->ng_next = grouphead.gr;
212a44e4d14SBill Paul grouphead.gr = grp;
213a44e4d14SBill Paul pos++;
214a44e4d14SBill Paul gpos = strsep(&pos, ")");
215a44e4d14SBill Paul #ifdef DEBUG
216a44e4d14SBill Paul fields = 0;
217a44e4d14SBill Paul #endif
218a44e4d14SBill Paul for (strpos = 0; strpos < 3; strpos++) {
219a44e4d14SBill Paul if ((spos = strsep(&gpos, ","))) {
220a44e4d14SBill Paul #ifdef DEBUG
221a44e4d14SBill Paul fields++;
222a44e4d14SBill Paul #endif
223a44e4d14SBill Paul while (*spos == ' ' || *spos == '\t')
224a44e4d14SBill Paul spos++;
225a44e4d14SBill Paul if ((epos = strpbrk(spos, " \t"))) {
226a44e4d14SBill Paul *epos = '\0';
227a44e4d14SBill Paul len = epos - spos;
228a44e4d14SBill Paul } else
229a44e4d14SBill Paul len = strlen(spos);
230a44e4d14SBill Paul if (len > 0) {
231a44e4d14SBill Paul grp->ng_str[strpos] = (char *)
232a44e4d14SBill Paul malloc(len + 1);
233a44e4d14SBill Paul bcopy(spos, grp->ng_str[strpos],
234a44e4d14SBill Paul len + 1);
235a44e4d14SBill Paul }
236a44e4d14SBill Paul } else {
237a44e4d14SBill Paul /*
238a44e4d14SBill Paul * All other systems I've tested
239a44e4d14SBill Paul * return NULL for empty netgroup
240a44e4d14SBill Paul * fields. It's up to user programs
241a44e4d14SBill Paul * to handle the NULLs appropriately.
242a44e4d14SBill Paul */
243a44e4d14SBill Paul grp->ng_str[strpos] = NULL;
244a44e4d14SBill Paul }
245a44e4d14SBill Paul }
246a44e4d14SBill Paul #ifdef DEBUG
247a44e4d14SBill Paul /*
248a44e4d14SBill Paul * Note: on other platforms, malformed netgroup
249a44e4d14SBill Paul * entries are not normally flagged. While we
250a44e4d14SBill Paul * can catch bad entries and report them, we should
251a44e4d14SBill Paul * stay silent by default for compatibility's sake.
252a44e4d14SBill Paul */
253a44e4d14SBill Paul if (fields < 3)
2543029b69fSPhilippe Charnier warnx("bad entry (%s%s%s%s%s) in netgroup \"%s\"",
255a44e4d14SBill Paul grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST],
256a44e4d14SBill Paul grp->ng_str[NG_USER] == NULL ? "" : ",",
257a44e4d14SBill Paul grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER],
258a44e4d14SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : ",",
259a44e4d14SBill Paul grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM],
260a44e4d14SBill Paul lp->l_groupname);
261a44e4d14SBill Paul #endif
262a44e4d14SBill Paul } else {
263a44e4d14SBill Paul spos = strsep(&pos, ", \t");
264a44e4d14SBill Paul if (parse_netgrp(spos))
265a44e4d14SBill Paul continue;
266a44e4d14SBill Paul }
267a44e4d14SBill Paul /* Watch for null pointer dereferences, dammit! */
268a44e4d14SBill Paul if (pos != NULL)
269a44e4d14SBill Paul while (*pos == ' ' || *pos == ',' || *pos == '\t')
270a44e4d14SBill Paul pos++;
271a44e4d14SBill Paul }
272a44e4d14SBill Paul return (0);
273a44e4d14SBill Paul }
274a44e4d14SBill Paul
275a44e4d14SBill Paul /*
276a44e4d14SBill Paul * Read the netgroup file and save lines until the line for the netgroup
277a44e4d14SBill Paul * is found. Return 1 if eof is encountered.
278a44e4d14SBill Paul */
279a44e4d14SBill Paul static struct linelist *
read_for_group(char * group)280266ebcd3SWarner Losh read_for_group(char *group)
281a44e4d14SBill Paul {
282266ebcd3SWarner Losh char *pos, *spos, *linep = NULL, *olinep = NULL;
283266ebcd3SWarner Losh int len, olen;
284a44e4d14SBill Paul int cont;
285a44e4d14SBill Paul struct linelist *lp;
286a44e4d14SBill Paul char line[LINSIZ + 1];
28779cc85d3SBill Paul char *data = NULL;
288a44e4d14SBill Paul
289a44e4d14SBill Paul data = lookup (gtable, group);
290a44e4d14SBill Paul sprintf(line, "%s %s", group, data);
291a44e4d14SBill Paul pos = (char *)&line;
292a44e4d14SBill Paul #ifdef CANT_HAPPEN
293a44e4d14SBill Paul if (*pos == '#')
294a44e4d14SBill Paul continue;
295a44e4d14SBill Paul #endif
296a44e4d14SBill Paul while (*pos == ' ' || *pos == '\t')
297a44e4d14SBill Paul pos++;
298a44e4d14SBill Paul spos = pos;
299a44e4d14SBill Paul while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
300a44e4d14SBill Paul *pos != '\0')
301a44e4d14SBill Paul pos++;
302a44e4d14SBill Paul len = pos - spos;
303a44e4d14SBill Paul while (*pos == ' ' || *pos == '\t')
304a44e4d14SBill Paul pos++;
305a44e4d14SBill Paul if (*pos != '\n' && *pos != '\0') {
306a44e4d14SBill Paul lp = (struct linelist *)malloc(sizeof (*lp));
307a44e4d14SBill Paul lp->l_parsed = 0;
308a44e4d14SBill Paul lp->l_groupname = (char *)malloc(len + 1);
309a44e4d14SBill Paul bcopy(spos, lp->l_groupname, len);
310a44e4d14SBill Paul *(lp->l_groupname + len) = '\0';
311a44e4d14SBill Paul len = strlen(pos);
312a44e4d14SBill Paul olen = 0;
313a44e4d14SBill Paul /*
314a44e4d14SBill Paul * Loop around handling line continuations.
315a44e4d14SBill Paul */
316a44e4d14SBill Paul do {
317a44e4d14SBill Paul if (*(pos + len - 1) == '\n')
318a44e4d14SBill Paul len--;
319a44e4d14SBill Paul if (*(pos + len - 1) == '\\') {
320a44e4d14SBill Paul len--;
321a44e4d14SBill Paul cont = 1;
322a44e4d14SBill Paul } else
323a44e4d14SBill Paul cont = 0;
324a44e4d14SBill Paul if (len > 0) {
325a44e4d14SBill Paul linep = (char *)malloc(olen + len + 1);
326a44e4d14SBill Paul if (olen > 0) {
327a44e4d14SBill Paul bcopy(olinep, linep, olen);
328a44e4d14SBill Paul free(olinep);
329a44e4d14SBill Paul }
330a44e4d14SBill Paul bcopy(pos, linep + olen, len);
331a44e4d14SBill Paul olen += len;
332a44e4d14SBill Paul *(linep + olen) = '\0';
333a44e4d14SBill Paul olinep = linep;
334a44e4d14SBill Paul }
335a44e4d14SBill Paul #ifdef CANT_HAPPEN
336a44e4d14SBill Paul if (cont) {
337a44e4d14SBill Paul if (fgets(line, LINSIZ, netf)) {
338a44e4d14SBill Paul pos = line;
339a44e4d14SBill Paul len = strlen(pos);
340a44e4d14SBill Paul } else
341a44e4d14SBill Paul cont = 0;
342a44e4d14SBill Paul }
343a44e4d14SBill Paul #endif
344a44e4d14SBill Paul } while (cont);
345a44e4d14SBill Paul lp->l_line = linep;
346a44e4d14SBill Paul lp->l_next = linehead;
347a44e4d14SBill Paul linehead = lp;
348a44e4d14SBill Paul #ifdef CANT_HAPPEN
349a44e4d14SBill Paul /*
350a44e4d14SBill Paul * If this is the one we wanted, we are done.
351a44e4d14SBill Paul */
352a44e4d14SBill Paul if (!strcmp(lp->l_groupname, group))
353a44e4d14SBill Paul #endif
354a44e4d14SBill Paul return (lp);
355a44e4d14SBill Paul }
356a44e4d14SBill Paul return ((struct linelist *)0);
357a44e4d14SBill Paul }
358