conf.c revision 1.56
1/* $OpenBSD: conf.c,v 1.56 2003/06/10 16:41:29 deraadt Exp $ */ 2/* $EOM: conf.c,v 1.48 2000/12/04 02:04:29 angelos Exp $ */ 3 4/* 5 * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. 6 * Copyright (c) 2000, 2001, 2002 H�kan Olsson. All rights reserved. 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 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * This code was written under funding by Ericsson Radio Systems. 31 */ 32 33#include <sys/param.h> 34#include <sys/mman.h> 35#include <sys/queue.h> 36#include <sys/socket.h> 37#include <sys/stat.h> 38#include <netinet/in.h> 39#include <arpa/inet.h> 40#include <ctype.h> 41#include <fcntl.h> 42#include <stdio.h> 43#include <stdlib.h> 44#include <string.h> 45#include <unistd.h> 46#include <errno.h> 47 48#include "sysdep.h" 49 50#include "app.h" 51#include "conf.h" 52#include "log.h" 53#include "monitor.h" 54#include "util.h" 55 56static char *conf_get_trans_str (int, char *, char *); 57static void conf_load_defaults (int); 58#if 0 59static int conf_find_trans_xf (int, char *); 60#endif 61 62struct conf_trans { 63 TAILQ_ENTRY (conf_trans) link; 64 int trans; 65 enum conf_op { CONF_SET, CONF_REMOVE, CONF_REMOVE_SECTION } op; 66 char *section; 67 char *tag; 68 char *value; 69 int override; 70 int is_default; 71}; 72 73TAILQ_HEAD (conf_trans_head, conf_trans) conf_trans_queue; 74 75/* 76 * Radix-64 Encoding. 77 */ 78const u_int8_t bin2asc[] 79 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 80 81const u_int8_t asc2bin[] = 82{ 83 255, 255, 255, 255, 255, 255, 255, 255, 84 255, 255, 255, 255, 255, 255, 255, 255, 85 255, 255, 255, 255, 255, 255, 255, 255, 86 255, 255, 255, 255, 255, 255, 255, 255, 87 255, 255, 255, 255, 255, 255, 255, 255, 88 255, 255, 255, 62, 255, 255, 255, 63, 89 52, 53, 54, 55, 56, 57, 58, 59, 90 60, 61, 255, 255, 255, 255, 255, 255, 91 255, 0, 1, 2, 3, 4, 5, 6, 92 7, 8, 9, 10, 11, 12, 13, 14, 93 15, 16, 17, 18, 19, 20, 21, 22, 94 23, 24, 25, 255, 255, 255, 255, 255, 95 255, 26, 27, 28, 29, 30, 31, 32, 96 33, 34, 35, 36, 37, 38, 39, 40, 97 41, 42, 43, 44, 45, 46, 47, 48, 98 49, 50, 51, 255, 255, 255, 255, 255 99}; 100 101struct conf_binding { 102 LIST_ENTRY (conf_binding) link; 103 char *section; 104 char *tag; 105 char *value; 106 int is_default; 107}; 108 109char *conf_path = CONFIG_FILE; 110LIST_HEAD (conf_bindings, conf_binding) conf_bindings[256]; 111 112static char *conf_addr; 113 114static __inline__ u_int8_t 115conf_hash (char *s) 116{ 117 u_int8_t hash = 0; 118 119 while (*s) 120 { 121 hash = ((hash << 1) | (hash >> 7)) ^ tolower (*s); 122 s++; 123 } 124 return hash; 125} 126 127/* 128 * Insert a tag-value combination from LINE (the equal sign is at POS) 129 */ 130static int 131conf_remove_now (char *section, char *tag) 132{ 133 struct conf_binding *cb, *next; 134 135 for (cb = LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; cb = next) 136 { 137 next = LIST_NEXT (cb, link); 138 if (strcasecmp (cb->section, section) == 0 139 && strcasecmp (cb->tag, tag) == 0) 140 { 141 LIST_REMOVE (cb, link); 142 LOG_DBG ((LOG_MISC, 95, "[%s]:%s->%s removed", section, tag, 143 cb->value)); 144 free (cb->section); 145 free (cb->tag); 146 free (cb->value); 147 free (cb); 148 return 0; 149 } 150 } 151 return 1; 152} 153 154static int 155conf_remove_section_now (char *section) 156{ 157 struct conf_binding *cb, *next; 158 int unseen = 1; 159 160 for (cb = LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; cb = next) 161 { 162 next = LIST_NEXT (cb, link); 163 if (strcasecmp (cb->section, section) == 0) 164 { 165 unseen = 0; 166 LIST_REMOVE (cb, link); 167 LOG_DBG ((LOG_MISC, 95, "[%s]:%s->%s removed", section, cb->tag, 168 cb->value)); 169 free (cb->section); 170 free (cb->tag); 171 free (cb->value); 172 free (cb); 173 } 174 } 175 return unseen; 176} 177 178/* 179 * Insert a tag-value combination from LINE (the equal sign is at POS) 180 * into SECTION of our configuration database. 181 */ 182static int 183conf_set_now (char *section, char *tag, char *value, int override, 184 int is_default) 185{ 186 struct conf_binding *node = 0; 187 188 if (override) 189 conf_remove_now (section, tag); 190 else if (conf_get_str (section, tag)) 191 { 192 if (!is_default) 193 log_print ("conf_set: duplicate tag [%s]:%s, ignoring...\n", section, 194 tag); 195 return 1; 196 } 197 198 node = calloc (1, sizeof *node); 199 if (!node) 200 { 201 log_error ("conf_set: calloc (1, %lu) failed", (unsigned long)sizeof *node); 202 return 1; 203 } 204 node->section = strdup (section); 205 node->tag = strdup (tag); 206 node->value = strdup (value); 207 node->is_default = is_default; 208 209 LIST_INSERT_HEAD (&conf_bindings[conf_hash (section)], node, link); 210 LOG_DBG ((LOG_MISC, 95, "conf_set: [%s]:%s->%s", node->section, node->tag, 211 node->value)); 212 return 0; 213} 214 215/* 216 * Parse the line LINE of SZ bytes. Skip Comments, recognize section 217 * headers and feed tag-value pairs into our configuration database. 218 */ 219static void 220conf_parse_line (int trans, char *line, size_t sz) 221{ 222 char *val; 223 size_t i; 224 int j; 225 static char *section = 0; 226 static int ln = 0; 227 228 ln++; 229 230 /* Lines starting with '#' or ';' are comments. */ 231 if (*line == '#' || *line == ';') 232 return; 233 234 /* '[section]' parsing... */ 235 if (*line == '[') 236 { 237 for (i = 1; i < sz; i++) 238 if (line[i] == ']') 239 break; 240 if (section) 241 free (section); 242 if (i == sz) 243 { 244 log_print ("conf_parse_line: %d:" 245 "non-matched ']', ignoring until next section", ln); 246 section = 0; 247 return; 248 } 249 section = malloc (i); 250 if (!section) 251 { 252 log_print ("conf_parse_line: %d: malloc (%lu) failed", ln, 253 (unsigned long)i); 254 return; 255 } 256 strlcpy (section, line + 1, i); 257 return; 258 } 259 260 /* Deal with assignments. */ 261 for (i = 0; i < sz; i++) 262 if (line[i] == '=') 263 { 264 /* If no section, we are ignoring the lines. */ 265 if (!section) 266 { 267 log_print ("conf_parse_line: %d: ignoring line due to no section", 268 ln); 269 return; 270 } 271 line[strcspn (line, " \t=")] = '\0'; 272 val = line + i + 1 + strspn (line + i + 1, " \t"); 273 /* Skip trailing whitespace, if any */ 274 for (j = sz - (val - line) - 1; j > 0 && isspace (val[j]); j--) 275 val[j] = '\0'; 276 /* XXX Perhaps should we not ignore errors? */ 277 conf_set (trans, section, line, val, 0, 0); 278 return; 279 } 280 281 /* Other non-empty lines are weird. */ 282 i = strspn (line, " \t"); 283 if (line[i]) 284 log_print ("conf_parse_line: %d: syntax error", ln); 285 286 return; 287} 288 289/* Parse the mapped configuration file. */ 290static void 291conf_parse (int trans, char *buf, size_t sz) 292{ 293 char *cp = buf; 294 char *bufend = buf + sz; 295 char *line; 296 297 line = cp; 298 while (cp < bufend) 299 { 300 if (*cp == '\n') 301 { 302 /* Check for escaped newlines. */ 303 if (cp > buf && *(cp - 1) == '\\') 304 *(cp - 1) = *cp = ' '; 305 else 306 { 307 *cp = '\0'; 308 conf_parse_line (trans, line, cp - line); 309 line = cp + 1; 310 } 311 } 312 cp++; 313 } 314 if (cp != line) 315 log_print ("conf_parse: last line non-terminated, ignored."); 316} 317 318/* 319 * Auto-generate default configuration values for the transforms and 320 * suites the user wants. 321 * 322 * Resulting section names can be: 323 * For main mode: 324 * {DES,BLF,3DES,CAST}-{MD5,SHA}[-GRP{1,2,5}][-{DSS,RSA_SIG}] 325 * For quick mode: 326 * QM-{proto}[-TRP]-{cipher}[-{hash}][-PFS[-{group}]]-SUITE 327 * where 328 * {proto} = ESP, AH 329 * {cipher} = DES, 3DES, CAST, BLF, AES 330 * {hash} = MD5, SHA, RIPEMD 331 * {group} = GRP1, GRP2, GRP5 332 * 333 * DH group defaults to MODP_1024. 334 * 335 * XXX We may want to support USE_BLOWFISH, USE_TRIPLEDES, etc... 336 * XXX No EC2N DH support here yet. 337 */ 338 339/* Find the value for a section+tag in the transaction list. */ 340static char * 341conf_get_trans_str (int trans, char *section, char *tag) 342{ 343 struct conf_trans *node, *nf = 0; 344 345 for (node = TAILQ_FIRST (&conf_trans_queue); node; 346 node = TAILQ_NEXT (node, link)) 347 if (node->trans == trans && strcasecmp (section, node->section) == 0 348 && strcasecmp (tag, node->tag) == 0) 349 { 350 if (!nf) 351 nf = node; 352 else if (node->override) 353 nf = node; 354 } 355 return nf ? nf->value : 0; 356} 357 358#if 0 359/* XXX Currently unused. */ 360static int 361conf_find_trans_xf (int phase, char *xf) 362{ 363 struct conf_trans *node; 364 char *p; 365 366 /* Find the relevant transforms and suites, if any. */ 367 for (node = TAILQ_FIRST (&conf_trans_queue); node; 368 node = TAILQ_NEXT (node, link)) 369 if ((phase == 1 && strcmp ("Transforms", node->tag) == 0) || 370 (phase == 2 && strcmp ("Suites", node->tag) == 0)) 371 { 372 p = node->value; 373 while ((p = strstr (p, xf)) != NULL) 374 if (*(p + strlen (p)) && *(p + strlen (p)) != ',') 375 p += strlen (p); 376 else 377 return 1; 378 } 379 return 0; 380} 381#endif 382 383static void 384conf_load_defaults (int tr) 385{ 386#define CONF_MAX 256 387 int enc, auth, hash, group, group_max, proto, mode, pfs; 388 char sect[CONF_MAX], *dflt; 389 390 char *mm_auth[] = { "PRE_SHARED", "DSS", "RSA_SIG", 0 }; 391 char *mm_hash[] = { "MD5", "SHA", 0 }; 392 char *mm_enc[] = { "DES_CBC", "BLOWFISH_CBC", "3DES_CBC", 393 "CAST_CBC", 0 }; 394 char *dh_group[] = { "MODP_768", "MODP_1024", "MODP_1536", 0 }; 395 char *qm_enc[] = { "DES", "3DES", "CAST", "BLOWFISH", "AES", 0 }; 396 char *qm_hash[] = { "HMAC_MD5", "HMAC_SHA", "HMAC_RIPEMD", "NONE", 0 }; 397 398 /* Abbreviations to make section names a bit shorter. */ 399 char *mm_auth_p[] = { "", "-DSS", "-RSA_SIG", 0 }; 400 char *mm_enc_p[] = { "DES", "BLF", "3DES", "CAST", 0 }; 401 char *dh_group_p[]= { "-GRP1", "-GRP2", "-GRP5", "", 0 }; 402 char *qm_enc_p[] = { "-DES", "-3DES", "-CAST", "-BLF", "-AES", 0 }; 403 char *qm_hash_p[] = { "-MD5", "-SHA", "-RIPEMD", "", 0 }; 404 405 /* Helper #defines, incl abbreviations. */ 406#define PROTO(x) ((x) ? "AH" : "ESP") 407#define PFS(x) ((x) ? "-PFS" : "") 408#define MODE(x) ((x) ? "TRANSPORT" : "TUNNEL") 409#define MODE_p(x) ((x) ? "-TRP" : "") 410 group_max = sizeof dh_group / sizeof *dh_group - 1; 411 412 /* General and X509 defaults */ 413 conf_set (tr, "General", "Retransmits", CONF_DFLT_RETRANSMITS, 0, 1); 414 conf_set (tr, "General", "Exchange-max-time", CONF_DFLT_EXCH_MAX_TIME, 0, 1); 415 conf_set (tr, "General", "Policy-file", CONF_DFLT_POLICY_FILE, 0, 1); 416 conf_set (tr, "General", "Pubkey-directory", CONF_DFLT_PUBKEY_DIR, 0, 1); 417 418#ifdef USE_X509 419 conf_set (tr, "X509-certificates", "CA-directory", CONF_DFLT_X509_CA_DIR, 0, 420 1); 421 conf_set (tr, "X509-certificates", "Cert-directory", CONF_DFLT_X509_CERT_DIR, 422 0, 1); 423 conf_set (tr, "X509-certificates", "Private-key", CONF_DFLT_X509_PRIVATE_KEY, 424 0, 1); 425 conf_set (tr, "X509-certificates", "CRL-directory", CONF_DFLT_X509_CRL_DIR, 426 0, 1); 427#endif 428 429#ifdef USE_KEYNOTE 430 conf_set (tr, "KeyNote", "Credential-directory", CONF_DFLT_KEYNOTE_CRED_DIR, 431 0, 1); 432#endif 433 434 /* Lifetimes. XXX p1/p2 vs main/quick mode may be unclear. */ 435 dflt = conf_get_trans_str (tr, "General", "Default-phase-1-lifetime"); 436 conf_set (tr, CONF_DFLT_TAG_LIFE_MAIN_MODE, "LIFE_TYPE", 437 CONF_DFLT_TYPE_LIFE_MAIN_MODE, 0, 1); 438 conf_set (tr, CONF_DFLT_TAG_LIFE_MAIN_MODE, "LIFE_DURATION", 439 (dflt ? dflt : CONF_DFLT_VAL_LIFE_MAIN_MODE), 0, 1); 440 441 dflt = conf_get_trans_str (tr, "General", "Default-phase-2-lifetime"); 442 conf_set (tr, CONF_DFLT_TAG_LIFE_QUICK_MODE, "LIFE_TYPE", 443 CONF_DFLT_TYPE_LIFE_QUICK_MODE, 0, 1); 444 conf_set (tr, CONF_DFLT_TAG_LIFE_QUICK_MODE, "LIFE_DURATION", 445 (dflt ? dflt : CONF_DFLT_VAL_LIFE_QUICK_MODE), 0, 1); 446 447 /* Default Phase-1 Configuration section */ 448 conf_set (tr, CONF_DFLT_TAG_PHASE1_CONFIG, "EXCHANGE_TYPE", 449 CONF_DFLT_PHASE1_EXCH_TYPE, 0, 1); 450 conf_set (tr, CONF_DFLT_TAG_PHASE1_CONFIG, "Transforms", 451 CONF_DFLT_PHASE1_TRANSFORMS, 0, 1); 452 453 /* Main modes */ 454 for (enc = 0; mm_enc[enc]; enc ++) 455 for (hash = 0; mm_hash[hash]; hash ++) 456 for (auth = 0; mm_auth[auth]; auth ++) 457 for (group = 0; dh_group_p[group]; group ++) /* special */ 458 { 459 snprintf (sect, sizeof sect, "%s-%s%s%s", mm_enc_p[enc], 460 mm_hash[hash], dh_group_p[group], mm_auth_p[auth]); 461 462#if 0 463 if (!conf_find_trans_xf (1, sect)) 464 continue; 465#endif 466 467 LOG_DBG ((LOG_MISC, 90, "conf_load_defaults : main mode %s", 468 sect)); 469 470 conf_set (tr, sect, "ENCRYPTION_ALGORITHM", mm_enc[enc], 0, 1); 471 if (strcmp (mm_enc[enc], "BLOWFISH_CBC") == 0) 472 conf_set (tr, sect, "KEY_LENGTH", CONF_DFLT_VAL_BLF_KEYLEN, 0, 473 1); 474 475 conf_set (tr, sect, "HASH_ALGORITHM", mm_hash[hash], 0, 1); 476 conf_set (tr, sect, "AUTHENTICATION_METHOD", mm_auth[auth], 0, 1); 477 478 /* XXX Always DH group 2 (MODP_1024) */ 479 conf_set (tr, sect, "GROUP_DESCRIPTION", 480 dh_group[group < group_max ? group : 1], 0, 1); 481 482 conf_set (tr, sect, "Life", CONF_DFLT_TAG_LIFE_MAIN_MODE, 0, 1); 483 } 484 485 /* Setup a default Phase 1 entry */ 486 conf_set (tr, "Phase 1", "Default", "Default-phase-1", 0, 1); 487 488 conf_set (tr, "Default-phase-1", "Phase", "1", 0, 1); 489 conf_set (tr, "Default-phase-1", "Configuration", 490 "Default-phase-1-configuration", 0, 1); 491 dflt = conf_get_trans_str (tr, "General", "Default-phase-1-ID"); 492 if (dflt) 493 conf_set (tr, "Default-phase-1", "ID", dflt, 0, 1); 494 495 /* Quick modes */ 496 for (enc = 0; qm_enc[enc]; enc ++) 497 for (proto = 0; proto < 2; proto ++) 498 for (mode = 0; mode < 2; mode ++) 499 for (pfs = 0; pfs < 2; pfs ++) 500 for (hash = 0; qm_hash[hash]; hash ++) 501 for (group = 0; dh_group_p[group]; group ++) 502 if ((proto == 1 && strcmp (qm_hash[hash], "NONE") == 0)) /* AH */ 503 continue; 504 else 505 { 506 char tmp[CONF_MAX]; 507 508 snprintf (tmp, sizeof tmp, "QM-%s%s%s%s%s%s", PROTO (proto), 509 MODE_p (mode), qm_enc_p[enc], qm_hash_p[hash], 510 PFS (pfs), dh_group_p[group]); 511 512 strlcpy (sect, tmp, CONF_MAX); 513 strlcat (sect, "-SUITE", CONF_MAX); 514 515#if 0 516 if (!conf_find_trans_xf (2, sect)) 517 continue; 518#endif 519 520 LOG_DBG ((LOG_MISC, 90, "conf_load_defaults : quick mode %s", 521 sect)); 522 523 conf_set (tr, sect, "Protocols", tmp, 0, 1); 524 525 snprintf (sect, sizeof sect, "IPSEC_%s", PROTO (proto)); 526 conf_set (tr, tmp, "PROTOCOL_ID", sect, 0, 1); 527 528 strlcpy (sect, tmp, CONF_MAX); 529 strlcat (sect, "-XF", CONF_MAX); 530 conf_set (tr, tmp, "Transforms", sect, 0, 1); 531 532 /* XXX For now, defaults contain one xf per protocol. */ 533 534 conf_set (tr, sect, "TRANSFORM_ID", qm_enc[enc], 0, 1); 535 536 if (strcmp (qm_enc[enc], "BLOWFISH") == 0) 537 conf_set (tr, sect, "KEY_LENGTH", CONF_DFLT_VAL_BLF_KEYLEN, 538 0, 1); 539 540 conf_set (tr, sect, "ENCAPSULATION_MODE", MODE (mode), 0, 1); 541 542 if (strcmp (qm_hash[hash], "NONE")) 543 { 544 conf_set (tr, sect, "AUTHENTICATION_ALGORITHM", 545 qm_hash[hash], 0, 1); 546 547 /* XXX Another shortcut -- to keep length down. */ 548 if (pfs) 549 conf_set (tr, sect, "GROUP_DESCRIPTION", 550 dh_group[group < group_max ? group : 1], 0, 551 1); 552 } 553 554 /* XXX Lifetimes depending on enc/auth strength? */ 555 conf_set (tr, sect, "Life", CONF_DFLT_TAG_LIFE_QUICK_MODE, 0, 556 1); 557 } 558 return; 559} 560 561void 562conf_init (void) 563{ 564 unsigned int i; 565 566 for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) 567 LIST_INIT (&conf_bindings[i]); 568 TAILQ_INIT (&conf_trans_queue); 569 conf_reinit (); 570} 571 572/* Open the config file and map it into our address space, then parse it. */ 573void 574conf_reinit (void) 575{ 576 struct conf_binding *cb = 0; 577 int fd, trans; 578 unsigned int i; 579 size_t sz; 580 char *new_conf_addr = 0; 581 struct stat sb; 582 583 if ((stat (conf_path, &sb) == 0) || (errno != ENOENT)) 584 { 585 if (check_file_secrecy (conf_path, &sz)) 586 return; 587 588 fd = monitor_open (conf_path, O_RDONLY, 0); 589 if (fd == -1) 590 { 591 log_error ("conf_reinit: open (\"%s\", O_RDONLY) failed", conf_path); 592 return; 593 } 594 595 new_conf_addr = malloc (sz); 596 if (!new_conf_addr) 597 { 598 log_error ("conf_reinit: malloc (%lu) failed", (unsigned long)sz); 599 goto fail; 600 } 601 602 /* XXX I assume short reads won't happen here. */ 603 if (read (fd, new_conf_addr, sz) != (int)sz) 604 { 605 log_error ("conf_reinit: read (%d, %p, %lu) failed", 606 fd, new_conf_addr, (unsigned long)sz); 607 goto fail; 608 } 609 close (fd); 610 611 trans = conf_begin (); 612 613 /* XXX Should we not care about errors and rollback? */ 614 conf_parse (trans, new_conf_addr, sz); 615 } 616 else 617 trans = conf_begin (); 618 619 /* Load default configuration values. */ 620 conf_load_defaults (trans); 621 622 /* Free potential existing configuration. */ 623 if (conf_addr) 624 { 625 for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) 626 for (cb = LIST_FIRST (&conf_bindings[i]); cb; 627 cb = LIST_FIRST (&conf_bindings[i])) 628 conf_remove_now (cb->section, cb->tag); 629 free (conf_addr); 630 } 631 632 conf_end (trans, 1); 633 conf_addr = new_conf_addr; 634 return; 635 636 fail: 637 if (new_conf_addr) 638 free (new_conf_addr); 639 close (fd); 640} 641 642/* 643 * Return the numeric value denoted by TAG in section SECTION or DEF 644 * if that tag does not exist. 645 */ 646int 647conf_get_num (char *section, char *tag, int def) 648{ 649 char *value = conf_get_str (section, tag); 650 651 if (value) 652 return atoi (value); 653 return def; 654} 655 656/* 657 * Return the socket endpoint address denoted by TAG in SECTION as a 658 * struct sockaddr. It is the callers responsibility to deallocate 659 * this structure when it is finished with it. 660 */ 661struct sockaddr * 662conf_get_address (char *section, char *tag) 663{ 664 char *value = conf_get_str (section, tag); 665 struct sockaddr *sa; 666 667 if (!value) 668 return 0; 669 if (text2sockaddr (value, 0, &sa) == -1) 670 return 0; 671 return sa; 672} 673 674/* Validate X according to the range denoted by TAG in section SECTION. */ 675int 676conf_match_num (char *section, char *tag, int x) 677{ 678 char *value = conf_get_str (section, tag); 679 int val, min, max, n; 680 681 if (!value) 682 return 0; 683 n = sscanf (value, "%d,%d:%d", &val, &min, &max); 684 switch (n) 685 { 686 case 1: 687 LOG_DBG ((LOG_MISC, 90, "conf_match_num: %s:%s %d==%d?", section, tag, 688 val, x)); 689 return x == val; 690 case 3: 691 LOG_DBG ((LOG_MISC, 90, "conf_match_num: %s:%s %d<=%d<=%d?", section, 692 tag, min, x, max)); 693 return min <= x && max >= x; 694 default: 695 log_error ("conf_match_num: section %s tag %s: invalid number spec %s", 696 section, tag, value); 697 } 698 return 0; 699} 700 701/* Return the string value denoted by TAG in section SECTION. */ 702char * 703conf_get_str (char *section, char *tag) 704{ 705 struct conf_binding *cb; 706 707 for (cb = LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; 708 cb = LIST_NEXT (cb, link)) 709 if (strcasecmp (section, cb->section) == 0 710 && strcasecmp (tag, cb->tag) == 0) 711 { 712 LOG_DBG ((LOG_MISC, 95, "conf_get_str: [%s]:%s->%s", section, 713 tag, cb->value)); 714 return cb->value; 715 } 716 LOG_DBG ((LOG_MISC, 95, 717 "conf_get_str: configuration value not found [%s]:%s", section, 718 tag)); 719 return 0; 720} 721 722/* 723 * Build a list of string values out of the comma separated value denoted by 724 * TAG in SECTION. 725 */ 726struct conf_list * 727conf_get_list (char *section, char *tag) 728{ 729 char *liststr = 0, *p, *field, *t; 730 struct conf_list *list = 0; 731 struct conf_list_node *node; 732 733 list = malloc (sizeof *list); 734 if (!list) 735 goto cleanup; 736 TAILQ_INIT (&list->fields); 737 list->cnt = 0; 738 liststr = conf_get_str (section, tag); 739 if (!liststr) 740 goto cleanup; 741 liststr = strdup (liststr); 742 if (!liststr) 743 goto cleanup; 744 p = liststr; 745 while ((field = strsep (&p, ",")) != NULL) 746 { 747 /* Skip leading whitespace */ 748 while (isspace (*field)) 749 field++; 750 /* Skip trailing whitespace */ 751 if (p) 752 for (t = p - 1; t > field && isspace (*t); t--) 753 *t = '\0'; 754 if (*field == '\0') 755 { 756 log_print ("conf_get_list: empty field, ignoring..."); 757 continue; 758 } 759 list->cnt++; 760 node = calloc (1, sizeof *node); 761 if (!node) 762 goto cleanup; 763 node->field = strdup (field); 764 if (!node->field) 765 goto cleanup; 766 TAILQ_INSERT_TAIL (&list->fields, node, link); 767 } 768 free (liststr); 769 return list; 770 771 cleanup: 772 if (list) 773 conf_free_list (list); 774 if (liststr) 775 free (liststr); 776 return 0; 777} 778 779struct conf_list * 780conf_get_tag_list (char *section) 781{ 782 struct conf_list *list = 0; 783 struct conf_list_node *node; 784 struct conf_binding *cb; 785 786 list = malloc (sizeof *list); 787 if (!list) 788 goto cleanup; 789 TAILQ_INIT (&list->fields); 790 list->cnt = 0; 791 for (cb = LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; 792 cb = LIST_NEXT (cb, link)) 793 if (strcasecmp (section, cb->section) == 0) 794 { 795 list->cnt++; 796 node = calloc (1, sizeof *node); 797 if (!node) 798 goto cleanup; 799 node->field = strdup (cb->tag); 800 if (!node->field) 801 goto cleanup; 802 TAILQ_INSERT_TAIL (&list->fields, node, link); 803 } 804 return list; 805 806 cleanup: 807 if (list) 808 conf_free_list (list); 809 return 0; 810} 811 812/* Decode a PEM encoded buffer. */ 813int 814conf_decode_base64 (u_int8_t *out, u_int32_t *len, u_char *buf) 815{ 816 u_int32_t c = 0; 817 u_int8_t c1, c2, c3, c4; 818 819 while (*buf) 820 { 821 if (*buf > 127 || (c1 = asc2bin[*buf]) == 255) 822 return 0; 823 buf++; 824 825 if (*buf > 127 || (c2 = asc2bin[*buf]) == 255) 826 return 0; 827 buf++; 828 829 if (*buf == '=') 830 { 831 c3 = c4 = 0; 832 c++; 833 834 /* Check last four bit */ 835 if (c2 & 0xF) 836 return 0; 837 838 if (strcmp ((char *)buf, "==") == 0) 839 buf++; 840 else 841 return 0; 842 } 843 else if (*buf > 127 || (c3 = asc2bin[*buf]) == 255) 844 return 0; 845 else 846 { 847 if (*++buf == '=') 848 { 849 c4 = 0; 850 c += 2; 851 852 /* Check last two bit */ 853 if (c3 & 3) 854 return 0; 855 856 if (strcmp ((char *)buf, "=")) 857 return 0; 858 859 } 860 else if (*buf > 127 || (c4 = asc2bin[*buf]) == 255) 861 return 0; 862 else 863 c += 3; 864 } 865 866 buf++; 867 *out++ = (c1 << 2) | (c2 >> 4); 868 *out++ = (c2 << 4) | (c3 >> 2); 869 *out++ = (c3 << 6) | c4; 870 } 871 872 *len = c; 873 return 1; 874 875} 876 877void 878conf_free_list (struct conf_list *list) 879{ 880 struct conf_list_node *node = TAILQ_FIRST (&list->fields); 881 882 while (node) 883 { 884 TAILQ_REMOVE (&list->fields, node, link); 885 if (node->field) 886 free (node->field); 887 free (node); 888 node = TAILQ_FIRST (&list->fields); 889 } 890 free (list); 891} 892 893int 894conf_begin (void) 895{ 896 static int seq = 0; 897 898 return ++seq; 899} 900 901static struct conf_trans * 902conf_trans_node (int transaction, enum conf_op op) 903{ 904 struct conf_trans *node; 905 906 node = calloc (1, sizeof *node); 907 if (!node) 908 { 909 log_error ("conf_trans_node: calloc (1, %lu) failed", 910 (unsigned long)sizeof *node); 911 return 0; 912 } 913 node->trans = transaction; 914 node->op = op; 915 TAILQ_INSERT_TAIL (&conf_trans_queue, node, link); 916 return node; 917} 918 919/* Queue a set operation. */ 920int 921conf_set (int transaction, char *section, char *tag, char *value, int override, 922 int is_default) 923{ 924 struct conf_trans *node; 925 926 node = conf_trans_node (transaction, CONF_SET); 927 if (!node) 928 return 1; 929 node->section = strdup (section); 930 if (!node->section) 931 { 932 log_error ("conf_set: strdup (\"%s\") failed", section); 933 goto fail; 934 } 935 node->tag = strdup (tag); 936 if (!node->tag) 937 { 938 log_error ("conf_set: strdup (\"%s\") failed", tag); 939 goto fail; 940 } 941 node->value = strdup (value); 942 if (!node->value) 943 { 944 log_error ("conf_set: strdup (\"%s\") failed", value); 945 goto fail; 946 } 947 node->override = override; 948 node->is_default = is_default; 949 return 0; 950 951 fail: 952 if (node->tag) 953 free (node->tag); 954 if (node->section) 955 free (node->section); 956 if (node) 957 free (node); 958 return 1; 959} 960 961/* Queue a remove operation. */ 962int 963conf_remove (int transaction, char *section, char *tag) 964{ 965 struct conf_trans *node; 966 967 node = conf_trans_node (transaction, CONF_REMOVE); 968 if (!node) 969 goto fail; 970 node->section = strdup (section); 971 if (!node->section) 972 { 973 log_error ("conf_remove: strdup (\"%s\") failed", section); 974 goto fail; 975 } 976 node->tag = strdup (tag); 977 if (!node->tag) 978 { 979 log_error ("conf_remove: strdup (\"%s\") failed", tag); 980 goto fail; 981 } 982 return 0; 983 984 fail: 985 if (node->section) 986 free (node->section); 987 if (node) 988 free (node); 989 return 1; 990} 991 992/* Queue a remove section operation. */ 993int 994conf_remove_section (int transaction, char *section) 995{ 996 struct conf_trans *node; 997 998 node = conf_trans_node (transaction, CONF_REMOVE_SECTION); 999 if (!node) 1000 goto fail; 1001 node->section = strdup (section); 1002 if (!node->section) 1003 { 1004 log_error ("conf_remove_section: strdup (\"%s\") failed", section); 1005 goto fail; 1006 } 1007 return 0; 1008 1009 fail: 1010 if (node) 1011 free (node); 1012 return 1; 1013} 1014 1015/* Execute all queued operations for this transaction. Cleanup. */ 1016int 1017conf_end (int transaction, int commit) 1018{ 1019 struct conf_trans *node, *next; 1020 1021 for (node = TAILQ_FIRST (&conf_trans_queue); node; node = next) 1022 { 1023 next = TAILQ_NEXT (node, link); 1024 if (node->trans == transaction) 1025 { 1026 if (commit) 1027 switch (node->op) 1028 { 1029 case CONF_SET: 1030 conf_set_now (node->section, node->tag, node->value, 1031 node->override, node->is_default); 1032 break; 1033 case CONF_REMOVE: 1034 conf_remove_now (node->section, node->tag); 1035 break; 1036 case CONF_REMOVE_SECTION: 1037 conf_remove_section_now (node->section); 1038 break; 1039 default: 1040 log_print ("conf_end: unknown operation: %d", node->op); 1041 } 1042 TAILQ_REMOVE (&conf_trans_queue, node, link); 1043 if (node->section) 1044 free (node->section); 1045 if (node->tag) 1046 free (node->tag); 1047 if (node->value) 1048 free (node->value); 1049 free (node); 1050 } 1051 } 1052 return 0; 1053} 1054 1055/* 1056 * Dump running configuration upon SIGUSR1. 1057 * Configuration is "stored in reverse order", so reverse it again. 1058 */ 1059struct dumper { 1060 char *s, *v; 1061 struct dumper *next; 1062}; 1063 1064static void 1065conf_report_dump (struct dumper *node) 1066{ 1067 /* Recursive, cleanup when we're done. */ 1068 1069 if (node->next) 1070 conf_report_dump (node->next); 1071 1072 if (node->v) 1073 LOG_DBG ((LOG_REPORT, 0, "%s=\t%s", node->s, node->v)); 1074 else if (node->s) 1075 { 1076 LOG_DBG ((LOG_REPORT, 0, "%s", node->s)); 1077 if (strlen (node->s) > 0) 1078 free (node->s); 1079 } 1080 1081 free (node); 1082} 1083 1084void 1085conf_report (void) 1086{ 1087 struct conf_binding *cb, *last = 0; 1088 unsigned int i, len; 1089 char *current_section = (char *)0; 1090 struct dumper *dumper, *dnode; 1091 1092 dumper = dnode = (struct dumper *)calloc (1, sizeof *dumper); 1093 if (!dumper) 1094 goto mem_fail; 1095 1096 LOG_DBG ((LOG_REPORT, 0, "conf_report: dumping running configuration")); 1097 1098 for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) 1099 for (cb = LIST_FIRST (&conf_bindings[i]); cb; 1100 cb = LIST_NEXT (cb, link)) 1101 { 1102 if (!cb->is_default) 1103 { 1104 /* Dump this entry. */ 1105 if (!current_section || strcmp (cb->section, current_section)) 1106 { 1107 if (current_section) 1108 { 1109 len = strlen (current_section) + 3; 1110 dnode->s = malloc (len); 1111 if (!dnode->s) 1112 goto mem_fail; 1113 1114 snprintf (dnode->s, len, "[%s]", current_section); 1115 dnode->next 1116 = (struct dumper *)calloc (1, sizeof (struct dumper)); 1117 dnode = dnode->next; 1118 if (!dnode) 1119 goto mem_fail; 1120 1121 dnode->s = ""; 1122 dnode->next 1123 = (struct dumper *)calloc (1, sizeof (struct dumper)); 1124 dnode = dnode->next; 1125 if (!dnode) 1126 goto mem_fail; 1127 } 1128 current_section = cb->section; 1129 } 1130 dnode->s = cb->tag; 1131 dnode->v = cb->value; 1132 dnode->next = (struct dumper *)calloc (1, sizeof (struct dumper)); 1133 dnode = dnode->next; 1134 if (!dnode) 1135 goto mem_fail; 1136 last = cb; 1137 } 1138 } 1139 1140 if (last) 1141 { 1142 len = strlen (last->section) + 3; 1143 dnode->s = malloc (len); 1144 if (!dnode->s) 1145 goto mem_fail; 1146 snprintf (dnode->s, len, "[%s]", last->section); 1147 } 1148 1149 conf_report_dump (dumper); 1150 1151 return; 1152 1153 mem_fail: 1154 log_error ("conf_report: malloc/calloc failed"); 1155 while ((dnode = dumper) != 0) 1156 { 1157 dumper = dumper->next; 1158 if (dnode->s) 1159 free (dnode->s); 1160 free (dnode); 1161 } 1162 return; 1163} 1164