xref: /openbsd/sbin/isakmpd/conf.c (revision db3296cf)
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