GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ypserv/revnetgroup/parse_netgroup.c Lines: 0 107 0.0 %
Date: 2017-11-13 Branches: 0 84 0.0 %

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