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