1*5bbd2a12Schristos /* $NetBSD: gen.c,v 1.1.1.2 2012/09/09 16:07:55 christos Exp $ */
2b5677b36Schristos
3b5677b36Schristos /*
4b5677b36Schristos * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5b5677b36Schristos * Copyright (c) 1996-1999 by Internet Software Consortium.
6b5677b36Schristos *
7b5677b36Schristos * Permission to use, copy, modify, and distribute this software for any
8b5677b36Schristos * purpose with or without fee is hereby granted, provided that the above
9b5677b36Schristos * copyright notice and this permission notice appear in all copies.
10b5677b36Schristos *
11b5677b36Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12b5677b36Schristos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13b5677b36Schristos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14b5677b36Schristos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15b5677b36Schristos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16b5677b36Schristos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17b5677b36Schristos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18b5677b36Schristos */
19b5677b36Schristos
20b5677b36Schristos #if !defined(LINT) && !defined(CODECENTER)
21b5677b36Schristos static const char rcsid[] = "Id: gen.c,v 1.7 2005/04/27 04:56:23 sra Exp ";
22b5677b36Schristos #endif
23b5677b36Schristos
24b5677b36Schristos /*! \file
25b5677b36Schristos * \brief
26b5677b36Schristos * this is the top level dispatcher
27b5677b36Schristos *
28b5677b36Schristos * The dispatcher is implemented as an accessor class; it is an
29b5677b36Schristos * accessor class that calls other accessor classes, as controlled by a
30b5677b36Schristos * configuration file.
31b5677b36Schristos *
32b5677b36Schristos * A big difference between this accessor class and others is that the
33b5677b36Schristos * map class initializers are NULL, and the map classes are already
34b5677b36Schristos * filled in with method functions that will do the right thing.
35b5677b36Schristos */
36b5677b36Schristos
37b5677b36Schristos /* Imports */
38b5677b36Schristos
39b5677b36Schristos #include "port_before.h"
40b5677b36Schristos
41b5677b36Schristos #include <isc/assertions.h>
42b5677b36Schristos #include <ctype.h>
43b5677b36Schristos #include <errno.h>
44b5677b36Schristos #include <stdio.h>
45b5677b36Schristos #include <stdlib.h>
46b5677b36Schristos #include <string.h>
47b5677b36Schristos
48b5677b36Schristos #include <sys/types.h>
49b5677b36Schristos #include <netinet/in.h>
50b5677b36Schristos #include <arpa/nameser.h>
51b5677b36Schristos #include <resolv.h>
52b5677b36Schristos
53b5677b36Schristos #include <isc/memcluster.h>
54b5677b36Schristos #include <irs.h>
55b5677b36Schristos
56b5677b36Schristos #include "port_after.h"
57b5677b36Schristos
58b5677b36Schristos #include "irs_p.h"
59b5677b36Schristos #include "gen_p.h"
60b5677b36Schristos
61b5677b36Schristos /* Definitions */
62b5677b36Schristos
63b5677b36Schristos struct nameval {
64b5677b36Schristos const char * name;
65b5677b36Schristos int val;
66b5677b36Schristos };
67b5677b36Schristos
68b5677b36Schristos static const struct nameval acc_names[irs_nacc+1] = {
69b5677b36Schristos { "local", irs_lcl },
70b5677b36Schristos { "dns", irs_dns },
71b5677b36Schristos { "nis", irs_nis },
72b5677b36Schristos { "irp", irs_irp },
73b5677b36Schristos { NULL, irs_nacc }
74b5677b36Schristos };
75b5677b36Schristos
76b5677b36Schristos typedef struct irs_acc *(*accinit) __P((const char *options));
77b5677b36Schristos
78b5677b36Schristos static const accinit accs[irs_nacc+1] = {
79b5677b36Schristos irs_lcl_acc,
80b5677b36Schristos irs_dns_acc,
81b5677b36Schristos #ifdef WANT_IRS_NIS
82b5677b36Schristos irs_nis_acc,
83b5677b36Schristos #else
84b5677b36Schristos NULL,
85b5677b36Schristos #endif
86b5677b36Schristos irs_irp_acc,
87b5677b36Schristos NULL
88b5677b36Schristos };
89b5677b36Schristos
90b5677b36Schristos static const struct nameval map_names[irs_nmap+1] = {
91b5677b36Schristos { "group", irs_gr },
92b5677b36Schristos { "passwd", irs_pw },
93b5677b36Schristos { "services", irs_sv },
94b5677b36Schristos { "protocols", irs_pr },
95b5677b36Schristos { "hosts", irs_ho },
96b5677b36Schristos { "networks", irs_nw },
97b5677b36Schristos { "netgroup", irs_ng },
98b5677b36Schristos { NULL, irs_nmap }
99b5677b36Schristos };
100b5677b36Schristos
101b5677b36Schristos static const struct nameval option_names[] = {
102b5677b36Schristos { "merge", IRS_MERGE },
103b5677b36Schristos { "continue", IRS_CONTINUE },
104b5677b36Schristos { NULL, 0 }
105b5677b36Schristos };
106b5677b36Schristos
107b5677b36Schristos /* Forward */
108b5677b36Schristos
109b5677b36Schristos static void gen_close(struct irs_acc *);
110b5677b36Schristos static struct __res_state * gen_res_get(struct irs_acc *);
111b5677b36Schristos static void gen_res_set(struct irs_acc *, struct __res_state *,
112b5677b36Schristos void (*)(void *));
113b5677b36Schristos static int find_name(const char *, const struct nameval nv[]);
114b5677b36Schristos static void init_map_rules(struct gen_p *, const char *conf_file);
115b5677b36Schristos static struct irs_rule *release_rule(struct irs_rule *);
116b5677b36Schristos static int add_rule(struct gen_p *,
117b5677b36Schristos enum irs_map_id, enum irs_acc_id,
118b5677b36Schristos const char *);
119b5677b36Schristos
120b5677b36Schristos /* Public */
121b5677b36Schristos
122b5677b36Schristos struct irs_acc *
irs_gen_acc(const char * options,const char * conf_file)123b5677b36Schristos irs_gen_acc(const char *options, const char *conf_file) {
124b5677b36Schristos struct irs_acc *acc;
125b5677b36Schristos struct gen_p *irs;
126b5677b36Schristos
127b5677b36Schristos if (!(acc = memget(sizeof *acc))) {
128b5677b36Schristos errno = ENOMEM;
129b5677b36Schristos return (NULL);
130b5677b36Schristos }
131b5677b36Schristos memset(acc, 0x5e, sizeof *acc);
132b5677b36Schristos if (!(irs = memget(sizeof *irs))) {
133b5677b36Schristos errno = ENOMEM;
134b5677b36Schristos memput(acc, sizeof *acc);
135b5677b36Schristos return (NULL);
136b5677b36Schristos }
137b5677b36Schristos memset(irs, 0x5e, sizeof *irs);
138b5677b36Schristos irs->options = strdup(options);
139b5677b36Schristos irs->res = NULL;
140b5677b36Schristos irs->free_res = NULL;
141b5677b36Schristos memset(irs->accessors, 0, sizeof irs->accessors);
142b5677b36Schristos memset(irs->map_rules, 0, sizeof irs->map_rules);
143b5677b36Schristos init_map_rules(irs, conf_file);
144b5677b36Schristos acc->private = irs;
145b5677b36Schristos #ifdef WANT_IRS_GR
146b5677b36Schristos acc->gr_map = irs_gen_gr;
147b5677b36Schristos #else
148b5677b36Schristos acc->gr_map = NULL;
149b5677b36Schristos #endif
150b5677b36Schristos #ifdef WANT_IRS_PW
151b5677b36Schristos acc->pw_map = irs_gen_pw;
152b5677b36Schristos #else
153b5677b36Schristos acc->pw_map = NULL;
154b5677b36Schristos #endif
155b5677b36Schristos acc->sv_map = irs_gen_sv;
156b5677b36Schristos acc->pr_map = irs_gen_pr;
157b5677b36Schristos acc->ho_map = irs_gen_ho;
158b5677b36Schristos acc->nw_map = irs_gen_nw;
159b5677b36Schristos acc->ng_map = irs_gen_ng;
160b5677b36Schristos acc->res_get = gen_res_get;
161b5677b36Schristos acc->res_set = gen_res_set;
162b5677b36Schristos acc->close = gen_close;
163b5677b36Schristos return (acc);
164b5677b36Schristos }
165b5677b36Schristos
166b5677b36Schristos /* Methods */
167b5677b36Schristos
168b5677b36Schristos static struct __res_state *
gen_res_get(struct irs_acc * this)169b5677b36Schristos gen_res_get(struct irs_acc *this) {
170b5677b36Schristos struct gen_p *irs = (struct gen_p *)this->private;
171b5677b36Schristos
172b5677b36Schristos if (irs->res == NULL) {
173b5677b36Schristos struct __res_state *res;
174b5677b36Schristos res = (struct __res_state *)malloc(sizeof *res);
175b5677b36Schristos if (res == NULL)
176b5677b36Schristos return (NULL);
177b5677b36Schristos memset(res, 0, sizeof *res);
178b5677b36Schristos gen_res_set(this, res, free);
179b5677b36Schristos }
180b5677b36Schristos
181b5677b36Schristos if (((irs->res->options & RES_INIT) == 0U) && res_ninit(irs->res) < 0)
182b5677b36Schristos return (NULL);
183b5677b36Schristos
184b5677b36Schristos return (irs->res);
185b5677b36Schristos }
186b5677b36Schristos
187b5677b36Schristos static void
gen_res_set(struct irs_acc * this,struct __res_state * res,void (* free_res)(void *))188b5677b36Schristos gen_res_set(struct irs_acc *this, struct __res_state *res,
189b5677b36Schristos void (*free_res)(void *)) {
190b5677b36Schristos struct gen_p *irs = (struct gen_p *)this->private;
191b5677b36Schristos #if 0
192b5677b36Schristos struct irs_rule *rule;
193b5677b36Schristos struct irs_ho *ho;
194b5677b36Schristos struct irs_nw *nw;
195b5677b36Schristos #endif
196b5677b36Schristos
197b5677b36Schristos if (irs->res && irs->free_res) {
198b5677b36Schristos res_nclose(irs->res);
199b5677b36Schristos (*irs->free_res)(irs->res);
200b5677b36Schristos }
201b5677b36Schristos
202b5677b36Schristos irs->res = res;
203b5677b36Schristos irs->free_res = free_res;
204b5677b36Schristos
205b5677b36Schristos #if 0
206b5677b36Schristos for (rule = irs->map_rules[irs_ho]; rule; rule = rule->next) {
207b5677b36Schristos ho = rule->inst->ho;
208b5677b36Schristos
209b5677b36Schristos (*ho->res_set)(ho, res, NULL);
210b5677b36Schristos }
211b5677b36Schristos for (rule = irs->map_rules[irs_nw]; rule; rule = rule->next) {
212b5677b36Schristos nw = rule->inst->nw;
213b5677b36Schristos
214b5677b36Schristos (*nw->res_set)(nw, res, NULL);
215b5677b36Schristos }
216b5677b36Schristos #endif
217b5677b36Schristos }
218b5677b36Schristos
219b5677b36Schristos static void
gen_close(struct irs_acc * this)220b5677b36Schristos gen_close(struct irs_acc *this) {
221b5677b36Schristos struct gen_p *irs = (struct gen_p *)this->private;
222b5677b36Schristos int n;
223b5677b36Schristos
224b5677b36Schristos /* Search rules. */
225b5677b36Schristos for (n = 0; n < irs_nmap; n++)
226b5677b36Schristos while (irs->map_rules[n] != NULL)
227b5677b36Schristos irs->map_rules[n] = release_rule(irs->map_rules[n]);
228b5677b36Schristos
229b5677b36Schristos /* Access methods. */
230b5677b36Schristos for (n = 0; n < irs_nacc; n++) {
231b5677b36Schristos /* Map objects. */
232b5677b36Schristos if (irs->accessors[n].gr != NULL)
233b5677b36Schristos (*irs->accessors[n].gr->close)(irs->accessors[n].gr);
234b5677b36Schristos if (irs->accessors[n].pw != NULL)
235b5677b36Schristos (*irs->accessors[n].pw->close)(irs->accessors[n].pw);
236b5677b36Schristos if (irs->accessors[n].sv != NULL)
237b5677b36Schristos (*irs->accessors[n].sv->close)(irs->accessors[n].sv);
238b5677b36Schristos if (irs->accessors[n].pr != NULL)
239b5677b36Schristos (*irs->accessors[n].pr->close)(irs->accessors[n].pr);
240b5677b36Schristos if (irs->accessors[n].ho != NULL)
241b5677b36Schristos (*irs->accessors[n].ho->close)(irs->accessors[n].ho);
242b5677b36Schristos if (irs->accessors[n].nw != NULL)
243b5677b36Schristos (*irs->accessors[n].nw->close)(irs->accessors[n].nw);
244b5677b36Schristos if (irs->accessors[n].ng != NULL)
245b5677b36Schristos (*irs->accessors[n].ng->close)(irs->accessors[n].ng);
246b5677b36Schristos /* Enclosing accessor. */
247b5677b36Schristos if (irs->accessors[n].acc != NULL)
248b5677b36Schristos (*irs->accessors[n].acc->close)(irs->accessors[n].acc);
249b5677b36Schristos }
250b5677b36Schristos
251b5677b36Schristos /* The options string was strdup'd. */
252b5677b36Schristos free((void*)irs->options);
253b5677b36Schristos
254b5677b36Schristos if (irs->res && irs->free_res)
255b5677b36Schristos (*irs->free_res)(irs->res);
256b5677b36Schristos
257b5677b36Schristos /* The private data container. */
258b5677b36Schristos memput(irs, sizeof *irs);
259b5677b36Schristos
260b5677b36Schristos /* The object. */
261b5677b36Schristos memput(this, sizeof *this);
262b5677b36Schristos }
263b5677b36Schristos
264b5677b36Schristos /* Private */
265b5677b36Schristos
266b5677b36Schristos static int
find_name(const char * name,const struct nameval names[])267b5677b36Schristos find_name(const char *name, const struct nameval names[]) {
268b5677b36Schristos int n;
269b5677b36Schristos
270b5677b36Schristos for (n = 0; names[n].name != NULL; n++)
271b5677b36Schristos if (strcmp(name, names[n].name) == 0)
272b5677b36Schristos return (names[n].val);
273b5677b36Schristos return (-1);
274b5677b36Schristos }
275b5677b36Schristos
276b5677b36Schristos static struct irs_rule *
release_rule(struct irs_rule * rule)277b5677b36Schristos release_rule(struct irs_rule *rule) {
278b5677b36Schristos struct irs_rule *next = rule->next;
279b5677b36Schristos
280b5677b36Schristos memput(rule, sizeof *rule);
281b5677b36Schristos return (next);
282b5677b36Schristos }
283b5677b36Schristos
284b5677b36Schristos static int
add_rule(struct gen_p * irs,enum irs_map_id map,enum irs_acc_id acc,const char * options)285b5677b36Schristos add_rule(struct gen_p *irs,
286b5677b36Schristos enum irs_map_id map, enum irs_acc_id acc,
287b5677b36Schristos const char *options)
288b5677b36Schristos {
289b5677b36Schristos struct irs_rule **rules, *last, *tmp, *new;
290b5677b36Schristos struct irs_inst *inst;
291b5677b36Schristos const char *cp;
292b5677b36Schristos int n;
293b5677b36Schristos
294b5677b36Schristos #ifndef WANT_IRS_GR
295b5677b36Schristos if (map == irs_gr)
296b5677b36Schristos return (-1);
297b5677b36Schristos #endif
298b5677b36Schristos #ifndef WANT_IRS_PW
299b5677b36Schristos if (map == irs_pw)
300b5677b36Schristos return (-1);
301b5677b36Schristos #endif
302b5677b36Schristos #ifndef WANT_IRS_NIS
303b5677b36Schristos if (acc == irs_nis)
304b5677b36Schristos return (-1);
305b5677b36Schristos #endif
306b5677b36Schristos new = memget(sizeof *new);
307b5677b36Schristos if (new == NULL)
308b5677b36Schristos return (-1);
309b5677b36Schristos memset(new, 0x5e, sizeof *new);
310b5677b36Schristos new->next = NULL;
311b5677b36Schristos
312b5677b36Schristos new->inst = &irs->accessors[acc];
313b5677b36Schristos
314b5677b36Schristos new->flags = 0;
315b5677b36Schristos cp = options;
316b5677b36Schristos while (cp && *cp) {
317b5677b36Schristos char option[50], *next;
318b5677b36Schristos
319b5677b36Schristos next = strchr(cp, ',');
320b5677b36Schristos if (next)
321b5677b36Schristos n = next++ - cp;
322b5677b36Schristos else
323b5677b36Schristos n = strlen(cp);
324b5677b36Schristos if ((size_t)n > sizeof option - 1)
325b5677b36Schristos n = sizeof option - 1;
326b5677b36Schristos strncpy(option, cp, n);
327b5677b36Schristos option[n] = '\0';
328b5677b36Schristos
329b5677b36Schristos n = find_name(option, option_names);
330b5677b36Schristos if (n >= 0)
331b5677b36Schristos new->flags |= n;
332b5677b36Schristos
333b5677b36Schristos cp = next;
334b5677b36Schristos }
335b5677b36Schristos
336b5677b36Schristos rules = &irs->map_rules[map];
337b5677b36Schristos for (last = NULL, tmp = *rules;
338b5677b36Schristos tmp != NULL;
339b5677b36Schristos last = tmp, tmp = tmp->next)
340b5677b36Schristos (void)NULL;
341b5677b36Schristos if (last == NULL)
342b5677b36Schristos *rules = new;
343b5677b36Schristos else
344b5677b36Schristos last->next = new;
345b5677b36Schristos
346b5677b36Schristos /* Try to instantiate map accessors for this if necessary & approp. */
347b5677b36Schristos inst = &irs->accessors[acc];
348b5677b36Schristos if (inst->acc == NULL && accs[acc] != NULL)
349b5677b36Schristos inst->acc = (*accs[acc])(irs->options);
350b5677b36Schristos if (inst->acc != NULL) {
351b5677b36Schristos if (inst->gr == NULL && inst->acc->gr_map != NULL)
352b5677b36Schristos inst->gr = (*inst->acc->gr_map)(inst->acc);
353b5677b36Schristos if (inst->pw == NULL && inst->acc->pw_map != NULL)
354b5677b36Schristos inst->pw = (*inst->acc->pw_map)(inst->acc);
355b5677b36Schristos if (inst->sv == NULL && inst->acc->sv_map != NULL)
356b5677b36Schristos inst->sv = (*inst->acc->sv_map)(inst->acc);
357b5677b36Schristos if (inst->pr == NULL && inst->acc->pr_map != NULL)
358b5677b36Schristos inst->pr = (*inst->acc->pr_map)(inst->acc);
359b5677b36Schristos if (inst->ho == NULL && inst->acc->ho_map != NULL)
360b5677b36Schristos inst->ho = (*inst->acc->ho_map)(inst->acc);
361b5677b36Schristos if (inst->nw == NULL && inst->acc->nw_map != NULL)
362b5677b36Schristos inst->nw = (*inst->acc->nw_map)(inst->acc);
363b5677b36Schristos if (inst->ng == NULL && inst->acc->ng_map != NULL)
364b5677b36Schristos inst->ng = (*inst->acc->ng_map)(inst->acc);
365b5677b36Schristos }
366b5677b36Schristos
367b5677b36Schristos return (0);
368b5677b36Schristos }
369b5677b36Schristos
370b5677b36Schristos static void
default_map_rules(struct gen_p * irs)371b5677b36Schristos default_map_rules(struct gen_p *irs) {
372b5677b36Schristos /* Install time honoured and proved BSD style rules as default. */
373b5677b36Schristos add_rule(irs, irs_gr, irs_lcl, "");
374b5677b36Schristos add_rule(irs, irs_pw, irs_lcl, "");
375b5677b36Schristos add_rule(irs, irs_sv, irs_lcl, "");
376b5677b36Schristos add_rule(irs, irs_pr, irs_lcl, "");
377b5677b36Schristos add_rule(irs, irs_ho, irs_dns, "continue");
378b5677b36Schristos add_rule(irs, irs_ho, irs_lcl, "");
379b5677b36Schristos add_rule(irs, irs_nw, irs_dns, "continue");
380b5677b36Schristos add_rule(irs, irs_nw, irs_lcl, "");
381b5677b36Schristos add_rule(irs, irs_ng, irs_lcl, "");
382b5677b36Schristos }
383b5677b36Schristos
384b5677b36Schristos static void
init_map_rules(struct gen_p * irs,const char * conf_file)385b5677b36Schristos init_map_rules(struct gen_p *irs, const char *conf_file) {
386b5677b36Schristos char line[1024], pattern[40], mapname[20], accname[20], options[100];
387b5677b36Schristos FILE *conf;
388b5677b36Schristos
389b5677b36Schristos if (conf_file == NULL)
390b5677b36Schristos conf_file = _PATH_IRS_CONF ;
391b5677b36Schristos
392b5677b36Schristos /* A conf file of "" means compiled in defaults. Irpd wants this */
393b5677b36Schristos if (conf_file[0] == '\0' || (conf = fopen(conf_file, "r")) == NULL) {
394b5677b36Schristos default_map_rules(irs);
395b5677b36Schristos return;
396b5677b36Schristos }
397b5677b36Schristos (void) sprintf(pattern, "%%%lus %%%lus %%%lus\n",
398b5677b36Schristos (unsigned long)sizeof mapname,
399b5677b36Schristos (unsigned long)sizeof accname,
400b5677b36Schristos (unsigned long)sizeof options);
401b5677b36Schristos while (fgets(line, sizeof line, conf)) {
402b5677b36Schristos enum irs_map_id map;
403b5677b36Schristos enum irs_acc_id acc;
404b5677b36Schristos char *tmp;
405b5677b36Schristos int n;
406b5677b36Schristos
407b5677b36Schristos for (tmp = line;
408b5677b36Schristos isascii((unsigned char)*tmp) &&
409b5677b36Schristos isspace((unsigned char)*tmp);
410b5677b36Schristos tmp++)
411b5677b36Schristos (void)NULL;
412b5677b36Schristos if (*tmp == '#' || *tmp == '\n' || *tmp == '\0')
413b5677b36Schristos continue;
414b5677b36Schristos n = sscanf(tmp, pattern, mapname, accname, options);
415b5677b36Schristos if (n < 2)
416b5677b36Schristos continue;
417b5677b36Schristos if (n < 3)
418b5677b36Schristos options[0] = '\0';
419b5677b36Schristos
420b5677b36Schristos n = find_name(mapname, map_names);
421b5677b36Schristos INSIST(n < irs_nmap);
422b5677b36Schristos if (n < 0)
423b5677b36Schristos continue;
424b5677b36Schristos map = (enum irs_map_id) n;
425b5677b36Schristos
426b5677b36Schristos n = find_name(accname, acc_names);
427b5677b36Schristos INSIST(n < irs_nacc);
428b5677b36Schristos if (n < 0)
429b5677b36Schristos continue;
430b5677b36Schristos acc = (enum irs_acc_id) n;
431b5677b36Schristos
432b5677b36Schristos add_rule(irs, map, acc, options);
433b5677b36Schristos }
434b5677b36Schristos fclose(conf);
435b5677b36Schristos }
436