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