1 /* $OpenBSD: conf.c,v 1.57 2003/07/25 08:31:16 markus 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 56 static char *conf_get_trans_str (int, char *, char *); 57 static void conf_load_defaults (int); 58 #if 0 59 static int conf_find_trans_xf (int, char *); 60 #endif 61 62 struct 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 73 TAILQ_HEAD (conf_trans_head, conf_trans) conf_trans_queue; 74 75 /* 76 * Radix-64 Encoding. 77 */ 78 const u_int8_t bin2asc[] 79 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 80 81 const 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 101 struct conf_binding { 102 LIST_ENTRY (conf_binding) link; 103 char *section; 104 char *tag; 105 char *value; 106 int is_default; 107 }; 108 109 char *conf_path = CONFIG_FILE; 110 LIST_HEAD (conf_bindings, conf_binding) conf_bindings[256]; 111 112 static char *conf_addr; 113 114 static __inline__ u_int8_t 115 conf_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 */ 130 static int 131 conf_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 154 static int 155 conf_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 */ 182 static int 183 conf_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 */ 219 static void 220 conf_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. */ 290 static void 291 conf_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, SHA2-{-256,384,512} 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. */ 340 static char * 341 conf_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. */ 360 static int 361 conf_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 383 static void 384 conf_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", 397 "HMAC_SHA2_256", "HMAC_SHA2_384", "HMAC_SHA2_512", 398 "NONE", 0 }; 399 400 /* Abbreviations to make section names a bit shorter. */ 401 char *mm_auth_p[] = { "", "-DSS", "-RSA_SIG", 0 }; 402 char *mm_enc_p[] = { "DES", "BLF", "3DES", "CAST", 0 }; 403 char *dh_group_p[]= { "-GRP1", "-GRP2", "-GRP5", "", 0 }; 404 char *qm_enc_p[] = { "-DES", "-3DES", "-CAST", "-BLF", "-AES", 0 }; 405 char *qm_hash_p[] = { "-MD5", "-SHA", "-RIPEMD", 406 "-SHA2-256", "-SHA2-384", "-SHA2-512", 407 "", 0 }; 408 409 /* Helper #defines, incl abbreviations. */ 410 #define PROTO(x) ((x) ? "AH" : "ESP") 411 #define PFS(x) ((x) ? "-PFS" : "") 412 #define MODE(x) ((x) ? "TRANSPORT" : "TUNNEL") 413 #define MODE_p(x) ((x) ? "-TRP" : "") 414 group_max = sizeof dh_group / sizeof *dh_group - 1; 415 416 /* General and X509 defaults */ 417 conf_set (tr, "General", "Retransmits", CONF_DFLT_RETRANSMITS, 0, 1); 418 conf_set (tr, "General", "Exchange-max-time", CONF_DFLT_EXCH_MAX_TIME, 0, 1); 419 conf_set (tr, "General", "Policy-file", CONF_DFLT_POLICY_FILE, 0, 1); 420 conf_set (tr, "General", "Pubkey-directory", CONF_DFLT_PUBKEY_DIR, 0, 1); 421 422 #ifdef USE_X509 423 conf_set (tr, "X509-certificates", "CA-directory", CONF_DFLT_X509_CA_DIR, 0, 424 1); 425 conf_set (tr, "X509-certificates", "Cert-directory", CONF_DFLT_X509_CERT_DIR, 426 0, 1); 427 conf_set (tr, "X509-certificates", "Private-key", CONF_DFLT_X509_PRIVATE_KEY, 428 0, 1); 429 conf_set (tr, "X509-certificates", "CRL-directory", CONF_DFLT_X509_CRL_DIR, 430 0, 1); 431 #endif 432 433 #ifdef USE_KEYNOTE 434 conf_set (tr, "KeyNote", "Credential-directory", CONF_DFLT_KEYNOTE_CRED_DIR, 435 0, 1); 436 #endif 437 438 /* Lifetimes. XXX p1/p2 vs main/quick mode may be unclear. */ 439 dflt = conf_get_trans_str (tr, "General", "Default-phase-1-lifetime"); 440 conf_set (tr, CONF_DFLT_TAG_LIFE_MAIN_MODE, "LIFE_TYPE", 441 CONF_DFLT_TYPE_LIFE_MAIN_MODE, 0, 1); 442 conf_set (tr, CONF_DFLT_TAG_LIFE_MAIN_MODE, "LIFE_DURATION", 443 (dflt ? dflt : CONF_DFLT_VAL_LIFE_MAIN_MODE), 0, 1); 444 445 dflt = conf_get_trans_str (tr, "General", "Default-phase-2-lifetime"); 446 conf_set (tr, CONF_DFLT_TAG_LIFE_QUICK_MODE, "LIFE_TYPE", 447 CONF_DFLT_TYPE_LIFE_QUICK_MODE, 0, 1); 448 conf_set (tr, CONF_DFLT_TAG_LIFE_QUICK_MODE, "LIFE_DURATION", 449 (dflt ? dflt : CONF_DFLT_VAL_LIFE_QUICK_MODE), 0, 1); 450 451 /* Default Phase-1 Configuration section */ 452 conf_set (tr, CONF_DFLT_TAG_PHASE1_CONFIG, "EXCHANGE_TYPE", 453 CONF_DFLT_PHASE1_EXCH_TYPE, 0, 1); 454 conf_set (tr, CONF_DFLT_TAG_PHASE1_CONFIG, "Transforms", 455 CONF_DFLT_PHASE1_TRANSFORMS, 0, 1); 456 457 /* Main modes */ 458 for (enc = 0; mm_enc[enc]; enc ++) 459 for (hash = 0; mm_hash[hash]; hash ++) 460 for (auth = 0; mm_auth[auth]; auth ++) 461 for (group = 0; dh_group_p[group]; group ++) /* special */ 462 { 463 snprintf (sect, sizeof sect, "%s-%s%s%s", mm_enc_p[enc], 464 mm_hash[hash], dh_group_p[group], mm_auth_p[auth]); 465 466 #if 0 467 if (!conf_find_trans_xf (1, sect)) 468 continue; 469 #endif 470 471 LOG_DBG ((LOG_MISC, 90, "conf_load_defaults : main mode %s", 472 sect)); 473 474 conf_set (tr, sect, "ENCRYPTION_ALGORITHM", mm_enc[enc], 0, 1); 475 if (strcmp (mm_enc[enc], "BLOWFISH_CBC") == 0) 476 conf_set (tr, sect, "KEY_LENGTH", CONF_DFLT_VAL_BLF_KEYLEN, 0, 477 1); 478 479 conf_set (tr, sect, "HASH_ALGORITHM", mm_hash[hash], 0, 1); 480 conf_set (tr, sect, "AUTHENTICATION_METHOD", mm_auth[auth], 0, 1); 481 482 /* XXX Always DH group 2 (MODP_1024) */ 483 conf_set (tr, sect, "GROUP_DESCRIPTION", 484 dh_group[group < group_max ? group : 1], 0, 1); 485 486 conf_set (tr, sect, "Life", CONF_DFLT_TAG_LIFE_MAIN_MODE, 0, 1); 487 } 488 489 /* Setup a default Phase 1 entry */ 490 conf_set (tr, "Phase 1", "Default", "Default-phase-1", 0, 1); 491 492 conf_set (tr, "Default-phase-1", "Phase", "1", 0, 1); 493 conf_set (tr, "Default-phase-1", "Configuration", 494 "Default-phase-1-configuration", 0, 1); 495 dflt = conf_get_trans_str (tr, "General", "Default-phase-1-ID"); 496 if (dflt) 497 conf_set (tr, "Default-phase-1", "ID", dflt, 0, 1); 498 499 /* Quick modes */ 500 for (enc = 0; qm_enc[enc]; enc ++) 501 for (proto = 0; proto < 2; proto ++) 502 for (mode = 0; mode < 2; mode ++) 503 for (pfs = 0; pfs < 2; pfs ++) 504 for (hash = 0; qm_hash[hash]; hash ++) 505 for (group = 0; dh_group_p[group]; group ++) 506 if ((proto == 1 && strcmp (qm_hash[hash], "NONE") == 0)) /* AH */ 507 continue; 508 else 509 { 510 char tmp[CONF_MAX]; 511 512 snprintf (tmp, sizeof tmp, "QM-%s%s%s%s%s%s", PROTO (proto), 513 MODE_p (mode), qm_enc_p[enc], qm_hash_p[hash], 514 PFS (pfs), dh_group_p[group]); 515 516 strlcpy (sect, tmp, CONF_MAX); 517 strlcat (sect, "-SUITE", CONF_MAX); 518 519 #if 0 520 if (!conf_find_trans_xf (2, sect)) 521 continue; 522 #endif 523 524 LOG_DBG ((LOG_MISC, 90, "conf_load_defaults : quick mode %s", 525 sect)); 526 527 conf_set (tr, sect, "Protocols", tmp, 0, 1); 528 529 snprintf (sect, sizeof sect, "IPSEC_%s", PROTO (proto)); 530 conf_set (tr, tmp, "PROTOCOL_ID", sect, 0, 1); 531 532 strlcpy (sect, tmp, CONF_MAX); 533 strlcat (sect, "-XF", CONF_MAX); 534 conf_set (tr, tmp, "Transforms", sect, 0, 1); 535 536 /* XXX For now, defaults contain one xf per protocol. */ 537 538 conf_set (tr, sect, "TRANSFORM_ID", qm_enc[enc], 0, 1); 539 540 if (strcmp (qm_enc[enc], "BLOWFISH") == 0) 541 conf_set (tr, sect, "KEY_LENGTH", CONF_DFLT_VAL_BLF_KEYLEN, 542 0, 1); 543 544 conf_set (tr, sect, "ENCAPSULATION_MODE", MODE (mode), 0, 1); 545 546 if (strcmp (qm_hash[hash], "NONE")) 547 { 548 conf_set (tr, sect, "AUTHENTICATION_ALGORITHM", 549 qm_hash[hash], 0, 1); 550 551 /* XXX Another shortcut -- to keep length down. */ 552 if (pfs) 553 conf_set (tr, sect, "GROUP_DESCRIPTION", 554 dh_group[group < group_max ? group : 1], 0, 555 1); 556 } 557 558 /* XXX Lifetimes depending on enc/auth strength? */ 559 conf_set (tr, sect, "Life", CONF_DFLT_TAG_LIFE_QUICK_MODE, 0, 560 1); 561 } 562 return; 563 } 564 565 void 566 conf_init (void) 567 { 568 unsigned int i; 569 570 for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) 571 LIST_INIT (&conf_bindings[i]); 572 TAILQ_INIT (&conf_trans_queue); 573 conf_reinit (); 574 } 575 576 /* Open the config file and map it into our address space, then parse it. */ 577 void 578 conf_reinit (void) 579 { 580 struct conf_binding *cb = 0; 581 int fd, trans; 582 unsigned int i; 583 size_t sz; 584 char *new_conf_addr = 0; 585 struct stat sb; 586 587 if ((stat (conf_path, &sb) == 0) || (errno != ENOENT)) 588 { 589 if (check_file_secrecy (conf_path, &sz)) 590 return; 591 592 fd = monitor_open (conf_path, O_RDONLY, 0); 593 if (fd == -1) 594 { 595 log_error ("conf_reinit: open (\"%s\", O_RDONLY) failed", conf_path); 596 return; 597 } 598 599 new_conf_addr = malloc (sz); 600 if (!new_conf_addr) 601 { 602 log_error ("conf_reinit: malloc (%lu) failed", (unsigned long)sz); 603 goto fail; 604 } 605 606 /* XXX I assume short reads won't happen here. */ 607 if (read (fd, new_conf_addr, sz) != (int)sz) 608 { 609 log_error ("conf_reinit: read (%d, %p, %lu) failed", 610 fd, new_conf_addr, (unsigned long)sz); 611 goto fail; 612 } 613 close (fd); 614 615 trans = conf_begin (); 616 617 /* XXX Should we not care about errors and rollback? */ 618 conf_parse (trans, new_conf_addr, sz); 619 } 620 else 621 trans = conf_begin (); 622 623 /* Load default configuration values. */ 624 conf_load_defaults (trans); 625 626 /* Free potential existing configuration. */ 627 if (conf_addr) 628 { 629 for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) 630 for (cb = LIST_FIRST (&conf_bindings[i]); cb; 631 cb = LIST_FIRST (&conf_bindings[i])) 632 conf_remove_now (cb->section, cb->tag); 633 free (conf_addr); 634 } 635 636 conf_end (trans, 1); 637 conf_addr = new_conf_addr; 638 return; 639 640 fail: 641 if (new_conf_addr) 642 free (new_conf_addr); 643 close (fd); 644 } 645 646 /* 647 * Return the numeric value denoted by TAG in section SECTION or DEF 648 * if that tag does not exist. 649 */ 650 int 651 conf_get_num (char *section, char *tag, int def) 652 { 653 char *value = conf_get_str (section, tag); 654 655 if (value) 656 return atoi (value); 657 return def; 658 } 659 660 /* 661 * Return the socket endpoint address denoted by TAG in SECTION as a 662 * struct sockaddr. It is the callers responsibility to deallocate 663 * this structure when it is finished with it. 664 */ 665 struct sockaddr * 666 conf_get_address (char *section, char *tag) 667 { 668 char *value = conf_get_str (section, tag); 669 struct sockaddr *sa; 670 671 if (!value) 672 return 0; 673 if (text2sockaddr (value, 0, &sa) == -1) 674 return 0; 675 return sa; 676 } 677 678 /* Validate X according to the range denoted by TAG in section SECTION. */ 679 int 680 conf_match_num (char *section, char *tag, int x) 681 { 682 char *value = conf_get_str (section, tag); 683 int val, min, max, n; 684 685 if (!value) 686 return 0; 687 n = sscanf (value, "%d,%d:%d", &val, &min, &max); 688 switch (n) 689 { 690 case 1: 691 LOG_DBG ((LOG_MISC, 90, "conf_match_num: %s:%s %d==%d?", section, tag, 692 val, x)); 693 return x == val; 694 case 3: 695 LOG_DBG ((LOG_MISC, 90, "conf_match_num: %s:%s %d<=%d<=%d?", section, 696 tag, min, x, max)); 697 return min <= x && max >= x; 698 default: 699 log_error ("conf_match_num: section %s tag %s: invalid number spec %s", 700 section, tag, value); 701 } 702 return 0; 703 } 704 705 /* Return the string value denoted by TAG in section SECTION. */ 706 char * 707 conf_get_str (char *section, char *tag) 708 { 709 struct conf_binding *cb; 710 711 for (cb = LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; 712 cb = LIST_NEXT (cb, link)) 713 if (strcasecmp (section, cb->section) == 0 714 && strcasecmp (tag, cb->tag) == 0) 715 { 716 LOG_DBG ((LOG_MISC, 95, "conf_get_str: [%s]:%s->%s", section, 717 tag, cb->value)); 718 return cb->value; 719 } 720 LOG_DBG ((LOG_MISC, 95, 721 "conf_get_str: configuration value not found [%s]:%s", section, 722 tag)); 723 return 0; 724 } 725 726 /* 727 * Build a list of string values out of the comma separated value denoted by 728 * TAG in SECTION. 729 */ 730 struct conf_list * 731 conf_get_list (char *section, char *tag) 732 { 733 char *liststr = 0, *p, *field, *t; 734 struct conf_list *list = 0; 735 struct conf_list_node *node; 736 737 list = malloc (sizeof *list); 738 if (!list) 739 goto cleanup; 740 TAILQ_INIT (&list->fields); 741 list->cnt = 0; 742 liststr = conf_get_str (section, tag); 743 if (!liststr) 744 goto cleanup; 745 liststr = strdup (liststr); 746 if (!liststr) 747 goto cleanup; 748 p = liststr; 749 while ((field = strsep (&p, ",")) != NULL) 750 { 751 /* Skip leading whitespace */ 752 while (isspace (*field)) 753 field++; 754 /* Skip trailing whitespace */ 755 if (p) 756 for (t = p - 1; t > field && isspace (*t); t--) 757 *t = '\0'; 758 if (*field == '\0') 759 { 760 log_print ("conf_get_list: empty field, ignoring..."); 761 continue; 762 } 763 list->cnt++; 764 node = calloc (1, sizeof *node); 765 if (!node) 766 goto cleanup; 767 node->field = strdup (field); 768 if (!node->field) 769 goto cleanup; 770 TAILQ_INSERT_TAIL (&list->fields, node, link); 771 } 772 free (liststr); 773 return list; 774 775 cleanup: 776 if (list) 777 conf_free_list (list); 778 if (liststr) 779 free (liststr); 780 return 0; 781 } 782 783 struct conf_list * 784 conf_get_tag_list (char *section) 785 { 786 struct conf_list *list = 0; 787 struct conf_list_node *node; 788 struct conf_binding *cb; 789 790 list = malloc (sizeof *list); 791 if (!list) 792 goto cleanup; 793 TAILQ_INIT (&list->fields); 794 list->cnt = 0; 795 for (cb = LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; 796 cb = LIST_NEXT (cb, link)) 797 if (strcasecmp (section, cb->section) == 0) 798 { 799 list->cnt++; 800 node = calloc (1, sizeof *node); 801 if (!node) 802 goto cleanup; 803 node->field = strdup (cb->tag); 804 if (!node->field) 805 goto cleanup; 806 TAILQ_INSERT_TAIL (&list->fields, node, link); 807 } 808 return list; 809 810 cleanup: 811 if (list) 812 conf_free_list (list); 813 return 0; 814 } 815 816 /* Decode a PEM encoded buffer. */ 817 int 818 conf_decode_base64 (u_int8_t *out, u_int32_t *len, u_char *buf) 819 { 820 u_int32_t c = 0; 821 u_int8_t c1, c2, c3, c4; 822 823 while (*buf) 824 { 825 if (*buf > 127 || (c1 = asc2bin[*buf]) == 255) 826 return 0; 827 buf++; 828 829 if (*buf > 127 || (c2 = asc2bin[*buf]) == 255) 830 return 0; 831 buf++; 832 833 if (*buf == '=') 834 { 835 c3 = c4 = 0; 836 c++; 837 838 /* Check last four bit */ 839 if (c2 & 0xF) 840 return 0; 841 842 if (strcmp ((char *)buf, "==") == 0) 843 buf++; 844 else 845 return 0; 846 } 847 else if (*buf > 127 || (c3 = asc2bin[*buf]) == 255) 848 return 0; 849 else 850 { 851 if (*++buf == '=') 852 { 853 c4 = 0; 854 c += 2; 855 856 /* Check last two bit */ 857 if (c3 & 3) 858 return 0; 859 860 if (strcmp ((char *)buf, "=")) 861 return 0; 862 863 } 864 else if (*buf > 127 || (c4 = asc2bin[*buf]) == 255) 865 return 0; 866 else 867 c += 3; 868 } 869 870 buf++; 871 *out++ = (c1 << 2) | (c2 >> 4); 872 *out++ = (c2 << 4) | (c3 >> 2); 873 *out++ = (c3 << 6) | c4; 874 } 875 876 *len = c; 877 return 1; 878 879 } 880 881 void 882 conf_free_list (struct conf_list *list) 883 { 884 struct conf_list_node *node = TAILQ_FIRST (&list->fields); 885 886 while (node) 887 { 888 TAILQ_REMOVE (&list->fields, node, link); 889 if (node->field) 890 free (node->field); 891 free (node); 892 node = TAILQ_FIRST (&list->fields); 893 } 894 free (list); 895 } 896 897 int 898 conf_begin (void) 899 { 900 static int seq = 0; 901 902 return ++seq; 903 } 904 905 static struct conf_trans * 906 conf_trans_node (int transaction, enum conf_op op) 907 { 908 struct conf_trans *node; 909 910 node = calloc (1, sizeof *node); 911 if (!node) 912 { 913 log_error ("conf_trans_node: calloc (1, %lu) failed", 914 (unsigned long)sizeof *node); 915 return 0; 916 } 917 node->trans = transaction; 918 node->op = op; 919 TAILQ_INSERT_TAIL (&conf_trans_queue, node, link); 920 return node; 921 } 922 923 /* Queue a set operation. */ 924 int 925 conf_set (int transaction, char *section, char *tag, char *value, int override, 926 int is_default) 927 { 928 struct conf_trans *node; 929 930 node = conf_trans_node (transaction, CONF_SET); 931 if (!node) 932 return 1; 933 node->section = strdup (section); 934 if (!node->section) 935 { 936 log_error ("conf_set: strdup (\"%s\") failed", section); 937 goto fail; 938 } 939 node->tag = strdup (tag); 940 if (!node->tag) 941 { 942 log_error ("conf_set: strdup (\"%s\") failed", tag); 943 goto fail; 944 } 945 node->value = strdup (value); 946 if (!node->value) 947 { 948 log_error ("conf_set: strdup (\"%s\") failed", value); 949 goto fail; 950 } 951 node->override = override; 952 node->is_default = is_default; 953 return 0; 954 955 fail: 956 if (node->tag) 957 free (node->tag); 958 if (node->section) 959 free (node->section); 960 if (node) 961 free (node); 962 return 1; 963 } 964 965 /* Queue a remove operation. */ 966 int 967 conf_remove (int transaction, char *section, char *tag) 968 { 969 struct conf_trans *node; 970 971 node = conf_trans_node (transaction, CONF_REMOVE); 972 if (!node) 973 goto fail; 974 node->section = strdup (section); 975 if (!node->section) 976 { 977 log_error ("conf_remove: strdup (\"%s\") failed", section); 978 goto fail; 979 } 980 node->tag = strdup (tag); 981 if (!node->tag) 982 { 983 log_error ("conf_remove: strdup (\"%s\") failed", tag); 984 goto fail; 985 } 986 return 0; 987 988 fail: 989 if (node->section) 990 free (node->section); 991 if (node) 992 free (node); 993 return 1; 994 } 995 996 /* Queue a remove section operation. */ 997 int 998 conf_remove_section (int transaction, char *section) 999 { 1000 struct conf_trans *node; 1001 1002 node = conf_trans_node (transaction, CONF_REMOVE_SECTION); 1003 if (!node) 1004 goto fail; 1005 node->section = strdup (section); 1006 if (!node->section) 1007 { 1008 log_error ("conf_remove_section: strdup (\"%s\") failed", section); 1009 goto fail; 1010 } 1011 return 0; 1012 1013 fail: 1014 if (node) 1015 free (node); 1016 return 1; 1017 } 1018 1019 /* Execute all queued operations for this transaction. Cleanup. */ 1020 int 1021 conf_end (int transaction, int commit) 1022 { 1023 struct conf_trans *node, *next; 1024 1025 for (node = TAILQ_FIRST (&conf_trans_queue); node; node = next) 1026 { 1027 next = TAILQ_NEXT (node, link); 1028 if (node->trans == transaction) 1029 { 1030 if (commit) 1031 switch (node->op) 1032 { 1033 case CONF_SET: 1034 conf_set_now (node->section, node->tag, node->value, 1035 node->override, node->is_default); 1036 break; 1037 case CONF_REMOVE: 1038 conf_remove_now (node->section, node->tag); 1039 break; 1040 case CONF_REMOVE_SECTION: 1041 conf_remove_section_now (node->section); 1042 break; 1043 default: 1044 log_print ("conf_end: unknown operation: %d", node->op); 1045 } 1046 TAILQ_REMOVE (&conf_trans_queue, node, link); 1047 if (node->section) 1048 free (node->section); 1049 if (node->tag) 1050 free (node->tag); 1051 if (node->value) 1052 free (node->value); 1053 free (node); 1054 } 1055 } 1056 return 0; 1057 } 1058 1059 /* 1060 * Dump running configuration upon SIGUSR1. 1061 * Configuration is "stored in reverse order", so reverse it again. 1062 */ 1063 struct dumper { 1064 char *s, *v; 1065 struct dumper *next; 1066 }; 1067 1068 static void 1069 conf_report_dump (struct dumper *node) 1070 { 1071 /* Recursive, cleanup when we're done. */ 1072 1073 if (node->next) 1074 conf_report_dump (node->next); 1075 1076 if (node->v) 1077 LOG_DBG ((LOG_REPORT, 0, "%s=\t%s", node->s, node->v)); 1078 else if (node->s) 1079 { 1080 LOG_DBG ((LOG_REPORT, 0, "%s", node->s)); 1081 if (strlen (node->s) > 0) 1082 free (node->s); 1083 } 1084 1085 free (node); 1086 } 1087 1088 void 1089 conf_report (void) 1090 { 1091 struct conf_binding *cb, *last = 0; 1092 unsigned int i, len; 1093 char *current_section = (char *)0; 1094 struct dumper *dumper, *dnode; 1095 1096 dumper = dnode = (struct dumper *)calloc (1, sizeof *dumper); 1097 if (!dumper) 1098 goto mem_fail; 1099 1100 LOG_DBG ((LOG_REPORT, 0, "conf_report: dumping running configuration")); 1101 1102 for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) 1103 for (cb = LIST_FIRST (&conf_bindings[i]); cb; 1104 cb = LIST_NEXT (cb, link)) 1105 { 1106 if (!cb->is_default) 1107 { 1108 /* Dump this entry. */ 1109 if (!current_section || strcmp (cb->section, current_section)) 1110 { 1111 if (current_section) 1112 { 1113 len = strlen (current_section) + 3; 1114 dnode->s = malloc (len); 1115 if (!dnode->s) 1116 goto mem_fail; 1117 1118 snprintf (dnode->s, len, "[%s]", current_section); 1119 dnode->next 1120 = (struct dumper *)calloc (1, sizeof (struct dumper)); 1121 dnode = dnode->next; 1122 if (!dnode) 1123 goto mem_fail; 1124 1125 dnode->s = ""; 1126 dnode->next 1127 = (struct dumper *)calloc (1, sizeof (struct dumper)); 1128 dnode = dnode->next; 1129 if (!dnode) 1130 goto mem_fail; 1131 } 1132 current_section = cb->section; 1133 } 1134 dnode->s = cb->tag; 1135 dnode->v = cb->value; 1136 dnode->next = (struct dumper *)calloc (1, sizeof (struct dumper)); 1137 dnode = dnode->next; 1138 if (!dnode) 1139 goto mem_fail; 1140 last = cb; 1141 } 1142 } 1143 1144 if (last) 1145 { 1146 len = strlen (last->section) + 3; 1147 dnode->s = malloc (len); 1148 if (!dnode->s) 1149 goto mem_fail; 1150 snprintf (dnode->s, len, "[%s]", last->section); 1151 } 1152 1153 conf_report_dump (dumper); 1154 1155 return; 1156 1157 mem_fail: 1158 log_error ("conf_report: malloc/calloc failed"); 1159 while ((dnode = dumper) != 0) 1160 { 1161 dumper = dumper->next; 1162 if (dnode->s) 1163 free (dnode->s); 1164 free (dnode); 1165 } 1166 return; 1167 } 1168