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