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