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