Home | History | Annotate | Line # | Download | only in irs
lcl_ng.c revision 1.1.1.1.6.2
      1 /*	$NetBSD: lcl_ng.c,v 1.1.1.1.6.2 2011/01/09 20:42:55 riz Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
      5  * Copyright (c) 1996-1999 by Internet Software Consortium.
      6  *
      7  * Permission to use, copy, modify, and distribute this software for any
      8  * purpose with or without fee is hereby granted, provided that the above
      9  * copyright notice and this permission notice appear in all copies.
     10  *
     11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  */
     19 
     20 #if !defined(LINT) && !defined(CODECENTER)
     21 static const char rcsid[] = "Id: lcl_ng.c,v 1.3 2005/04/27 04:56:31 sra Exp";
     22 #endif
     23 
     24 /* Imports */
     25 
     26 #include "port_before.h"
     27 
     28 #include <sys/types.h>
     29 #include <netinet/in.h>
     30 #include <arpa/nameser.h>
     31 #include <resolv.h>
     32 #include <errno.h>
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <string.h>
     36 #include <unistd.h>
     37 
     38 #include <irs.h>
     39 #include <isc/memcluster.h>
     40 
     41 #include "port_after.h"
     42 
     43 #include "irs_p.h"
     44 #include "lcl_p.h"
     45 
     46 /* Definitions */
     47 
     48 #define NG_HOST         0       /*%< Host name */
     49 #define NG_USER         1       /*%< User name */
     50 #define NG_DOM          2       /*%< and Domain name */
     51 #define LINSIZ		1024    /*%< Length of netgroup file line */
     52 /*
     53  * XXX Warning XXX
     54  * This code is a hack-and-slash special.  It realy needs to be
     55  * rewritten with things like strdup, and realloc in mind.
     56  * More reasonable data structures would not be a bad thing.
     57  */
     58 
     59 /*%
     60  * Static Variables and functions used by setnetgrent(), getnetgrent() and
     61  * endnetgrent().
     62  *
     63  * There are two linked lists:
     64  * \li linelist is just used by setnetgrent() to parse the net group file via.
     65  *   parse_netgrp()
     66  * \li 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 ng_old_struct {
     76 	struct ng_old_struct *ng_next;	/*%< Chain ptr */
     77 	char *		ng_str[3];	/*%< Field pointers, see below */
     78 };
     79 
     80 struct pvt {
     81 	FILE			*fp;
     82 	struct linelist		*linehead;
     83 	struct ng_old_struct    *nextgrp;
     84 	struct {
     85 		struct ng_old_struct	*gr;
     86 		char			*grname;
     87 	} grouphead;
     88 };
     89 
     90 /* Forward */
     91 
     92 static void 		ng_rewind(struct irs_ng *, const char*);
     93 static void 		ng_close(struct irs_ng *);
     94 static int		ng_next(struct irs_ng *, const char **,
     95 				const char **, const char **);
     96 static int 		ng_test(struct irs_ng *, const char *,
     97 				const char *, const char *,
     98 				const char *);
     99 static void		ng_minimize(struct irs_ng *);
    100 
    101 static int 		parse_netgrp(struct irs_ng *, const char*);
    102 static struct linelist *read_for_group(struct irs_ng *, const char *);
    103 static void		freelists(struct irs_ng *);
    104 
    105 /* Public */
    106 
    107 struct irs_ng *
    108 irs_lcl_ng(struct irs_acc *this) {
    109 	struct irs_ng *ng;
    110 	struct pvt *pvt;
    111 
    112 	UNUSED(this);
    113 
    114 	if (!(ng = memget(sizeof *ng))) {
    115 		errno = ENOMEM;
    116 		return (NULL);
    117 	}
    118 	memset(ng, 0x5e, sizeof *ng);
    119 	if (!(pvt = memget(sizeof *pvt))) {
    120 		memput(ng, sizeof *ng);
    121 		errno = ENOMEM;
    122 		return (NULL);
    123 	}
    124 	memset(pvt, 0, sizeof *pvt);
    125 	ng->private = pvt;
    126 	ng->close = ng_close;
    127 	ng->next = ng_next;
    128 	ng->test = ng_test;
    129 	ng->rewind = ng_rewind;
    130 	ng->minimize = ng_minimize;
    131 	return (ng);
    132 }
    133 
    134 /* Methods */
    135 
    136 static void
    137 ng_close(struct irs_ng *this) {
    138 	struct pvt *pvt = (struct pvt *)this->private;
    139 
    140 	if (pvt->fp != NULL)
    141 		fclose(pvt->fp);
    142 	freelists(this);
    143 	memput(pvt, sizeof *pvt);
    144 	memput(this, sizeof *this);
    145 }
    146 
    147 /*%
    148  * Parse the netgroup file looking for the netgroup and build the list
    149  * of netgrp structures. Let parse_netgrp() and read_for_group() do
    150  * most of the work.
    151  */
    152 static void
    153 ng_rewind(struct irs_ng *this, const char *group) {
    154 	struct pvt *pvt = (struct pvt *)this->private;
    155 
    156 	if (pvt->fp != NULL && fseek(pvt->fp, SEEK_CUR, 0L) == -1) {
    157 		fclose(pvt->fp);
    158 		pvt->fp = NULL;
    159 	}
    160 
    161 	if (pvt->fp == NULL || pvt->grouphead.gr == NULL ||
    162 	    strcmp(group, pvt->grouphead.grname)) {
    163 		freelists(this);
    164 		if (pvt->fp != NULL)
    165 			fclose(pvt->fp);
    166 		pvt->fp = fopen(_PATH_NETGROUP, "r");
    167 		if (pvt->fp != NULL) {
    168 			if (parse_netgrp(this, group))
    169 				freelists(this);
    170 			if (!(pvt->grouphead.grname = strdup(group)))
    171 				freelists(this);
    172 			fclose(pvt->fp);
    173 			pvt->fp = NULL;
    174 		}
    175 	}
    176 	pvt->nextgrp = pvt->grouphead.gr;
    177 }
    178 
    179 /*%
    180  * Get the next netgroup off the list.
    181  */
    182 static int
    183 ng_next(struct irs_ng *this, const char **host, const char **user,
    184 	const char **domain)
    185 {
    186 	struct pvt *pvt = (struct pvt *)this->private;
    187 
    188 	if (pvt->nextgrp) {
    189 		*host = pvt->nextgrp->ng_str[NG_HOST];
    190 		*user = pvt->nextgrp->ng_str[NG_USER];
    191 		*domain = pvt->nextgrp->ng_str[NG_DOM];
    192 		pvt->nextgrp = pvt->nextgrp->ng_next;
    193 		return (1);
    194 	}
    195 	return (0);
    196 }
    197 
    198 /*%
    199  * Search for a match in a netgroup.
    200  */
    201 static int
    202 ng_test(struct irs_ng *this, const char *name,
    203 	const char *host, const char *user, const char *domain)
    204 {
    205 	const char *ng_host, *ng_user, *ng_domain;
    206 
    207 	ng_rewind(this, name);
    208 	while (ng_next(this, &ng_host, &ng_user, &ng_domain))
    209 		if ((host == NULL || ng_host == NULL ||
    210 		     !strcmp(host, ng_host)) &&
    211 		    (user ==  NULL || ng_user == NULL ||
    212 		     !strcmp(user, ng_user)) &&
    213 		    (domain == NULL || ng_domain == NULL ||
    214 		     !strcmp(domain, ng_domain))) {
    215 			freelists(this);
    216 			return (1);
    217 		}
    218 	freelists(this);
    219 	return (0);
    220 }
    221 
    222 static void
    223 ng_minimize(struct irs_ng *this) {
    224 	struct pvt *pvt = (struct pvt *)this->private;
    225 
    226 	if (pvt->fp != NULL) {
    227 		(void)fclose(pvt->fp);
    228 		pvt->fp = NULL;
    229 	}
    230 }
    231 
    232 /* Private */
    233 
    234 /*%
    235  * endnetgrent() - cleanup
    236  */
    237 static void
    238 freelists(struct irs_ng *this) {
    239 	struct pvt *pvt = (struct pvt *)this->private;
    240 	struct linelist *lp, *olp;
    241 	struct ng_old_struct *gp, *ogp;
    242 
    243 	lp = pvt->linehead;
    244 	while (lp) {
    245 		olp = lp;
    246 		lp = lp->l_next;
    247 		free(olp->l_groupname);
    248 		free(olp->l_line);
    249 		free((char *)olp);
    250 	}
    251 	pvt->linehead = NULL;
    252 	if (pvt->grouphead.grname) {
    253 		free(pvt->grouphead.grname);
    254 		pvt->grouphead.grname = NULL;
    255 	}
    256 	gp = pvt->grouphead.gr;
    257 	while (gp) {
    258 		ogp = gp;
    259 		gp = gp->ng_next;
    260 		if (ogp->ng_str[NG_HOST])
    261 			free(ogp->ng_str[NG_HOST]);
    262 		if (ogp->ng_str[NG_USER])
    263 			free(ogp->ng_str[NG_USER]);
    264 		if (ogp->ng_str[NG_DOM])
    265 			free(ogp->ng_str[NG_DOM]);
    266 		free((char *)ogp);
    267 	}
    268 	pvt->grouphead.gr = NULL;
    269 }
    270 
    271 /*%
    272  * Parse the netgroup file setting up the linked lists.
    273  */
    274 static int
    275 parse_netgrp(struct irs_ng *this, const char *group) {
    276 	struct pvt *pvt = (struct pvt *)this->private;
    277 	char *spos, *epos;
    278 	int len, strpos;
    279 	char *pos, *gpos;
    280 	struct ng_old_struct *grp;
    281 	struct linelist *lp = pvt->linehead;
    282 
    283         /*
    284          * First, see if the line has already been read in.
    285          */
    286 	while (lp) {
    287 		if (!strcmp(group, lp->l_groupname))
    288 			break;
    289 		lp = lp->l_next;
    290 	}
    291 	if (lp == NULL &&
    292 	    (lp = read_for_group(this, group)) == NULL)
    293 		return (1);
    294 	if (lp->l_parsed) {
    295 		/*fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);*/
    296 		return (1);
    297 	} else
    298 		lp->l_parsed = 1;
    299 	pos = lp->l_line;
    300 	while (*pos != '\0') {
    301 		if (*pos == '(') {
    302 			if (!(grp = malloc(sizeof (struct ng_old_struct)))) {
    303 				freelists(this);
    304 				errno = ENOMEM;
    305 				return (1);
    306 			}
    307 			memset(grp, 0, sizeof (struct ng_old_struct));
    308 			grp->ng_next = pvt->grouphead.gr;
    309 			pvt->grouphead.gr = grp;
    310 			pos++;
    311 			gpos = strsep(&pos, ")");
    312 			for (strpos = 0; strpos < 3; strpos++) {
    313 				if ((spos = strsep(&gpos, ","))) {
    314 					while (*spos == ' ' || *spos == '\t')
    315 						spos++;
    316 					if ((epos = strpbrk(spos, " \t"))) {
    317 						*epos = '\0';
    318 						len = epos - spos;
    319 					} else
    320 						len = strlen(spos);
    321 					if (len > 0) {
    322 						if(!(grp->ng_str[strpos]
    323 						   =  (char *)
    324 						   malloc(len + 1))) {
    325 							freelists(this);
    326 							return (1);
    327 						}
    328 						memcpy(grp->ng_str[strpos],
    329 						       spos,
    330 						       len + 1);
    331 					}
    332 				} else
    333 					goto errout;
    334 			}
    335 		} else {
    336 			spos = strsep(&pos, ", \t");
    337 			if (spos != NULL && parse_netgrp(this, spos)) {
    338 				freelists(this);
    339 				return (1);
    340 			}
    341 		}
    342 		if (pos == NULL)
    343 			break;
    344 		while (*pos == ' ' || *pos == ',' || *pos == '\t')
    345 			pos++;
    346 	}
    347 	return (0);
    348  errout:
    349 	/*fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname,
    350 		  spos);*/
    351 	return (1);
    352 }
    353 
    354 /*%
    355  * Read the netgroup file and save lines until the line for the netgroup
    356  * is found. Return 1 if eof is encountered.
    357  */
    358 static struct linelist *
    359 read_for_group(struct irs_ng *this, const char *group) {
    360 	struct pvt *pvt = (struct pvt *)this->private;
    361 	char *pos, *spos, *linep = NULL, *olinep;
    362 	int len, olen, cont;
    363 	struct linelist *lp;
    364 	char line[LINSIZ + 1];
    365 
    366 	while (fgets(line, LINSIZ, pvt->fp) != NULL) {
    367 		pos = line;
    368 		if (*pos == '#')
    369 			continue;
    370 		while (*pos == ' ' || *pos == '\t')
    371 			pos++;
    372 		spos = pos;
    373 		while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
    374 			*pos != '\0')
    375 			pos++;
    376 		len = pos - spos;
    377 		while (*pos == ' ' || *pos == '\t')
    378 			pos++;
    379 		if (*pos != '\n' && *pos != '\0') {
    380 			if (!(lp = malloc(sizeof (*lp)))) {
    381 				freelists(this);
    382 				return (NULL);
    383 			}
    384 			lp->l_parsed = 0;
    385 			if (!(lp->l_groupname = malloc(len + 1))) {
    386 				free(lp);
    387 				freelists(this);
    388 				return (NULL);
    389 			}
    390 			memcpy(lp->l_groupname, spos,  len);
    391 			*(lp->l_groupname + len) = '\0';
    392 			len = strlen(pos);
    393 			olen = 0;
    394 			olinep = NULL;
    395 
    396 			/*
    397 			 * Loop around handling line continuations.
    398 			 */
    399 			do {
    400 				if (*(pos + len - 1) == '\n')
    401 					len--;
    402 				if (*(pos + len - 1) == '\\') {
    403 					len--;
    404 					cont = 1;
    405 				} else
    406 					cont = 0;
    407 				if (len > 0) {
    408 					if (!(linep = malloc(olen + len + 1))){
    409 						if (olen > 0)
    410 							free(olinep);
    411 						free(lp->l_groupname);
    412 						free(lp);
    413 						freelists(this);
    414 						errno = ENOMEM;
    415 						return (NULL);
    416 					}
    417 					if (olen > 0) {
    418 						memcpy(linep, olinep, olen);
    419 						free(olinep);
    420 					}
    421 					memcpy(linep + olen, pos, len);
    422 					olen += len;
    423 					*(linep + olen) = '\0';
    424 					olinep = linep;
    425 				}
    426 				if (cont) {
    427 					if (fgets(line, LINSIZ, pvt->fp)) {
    428 						pos = line;
    429 						len = strlen(pos);
    430 					} else
    431 						cont = 0;
    432 				}
    433 			} while (cont);
    434 			lp->l_line = linep;
    435 			lp->l_next = pvt->linehead;
    436 			pvt->linehead = lp;
    437 
    438 			/*
    439 			 * If this is the one we wanted, we are done.
    440 			 */
    441 			if (!strcmp(lp->l_groupname, group))
    442 				return (lp);
    443 		}
    444 	}
    445 	return (NULL);
    446 }
    447 
    448 /*! \file */
    449