Home | History | Annotate | Line # | Download | only in irs
lcl_ng.c revision 1.1
      1  1.1  christos /*	$NetBSD: lcl_ng.c,v 1.1 2009/04/12 15:33:38 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  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