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