Fix TLS in ACL's.
[pwmd.git] / src / rcfile.c
blob9a5fe8288b375a87cddf7b3a1c8c5d596fc0a81c
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <ctype.h>
31 #include <pwd.h>
33 #include "pwmd-error.h"
34 #include <gcrypt.h>
35 #include "mutex.h"
36 #include "rcfile.h"
37 #include "util-misc.h"
38 #include "common.h"
39 #include "util-slist.h"
40 #include "util-string.h"
41 #include "mem.h"
43 #define DEFAULT_PINENTRY_TIMEOUT "30"
44 #define DEFAULT_CACHE_TIMEOUT "600"
45 #define DEFAULT_KEEPALIVE_INTERVAL "60"
47 #define INVALID_VALUE(file, line) do { \
48 if (file) \
49 log_write(_("%s(%i): invalid value for parameter."), file, line); \
50 } while (0);
52 enum
54 PARAM_INT, PARAM_CHARP, PARAM_LONG, PARAM_LONGLONG, PARAM_CHARPP,
55 PARAM_BOOL, PARAM_ULONG, PARAM_ULONGLONG
58 static struct config_params_s
60 char *name;
61 int type;
62 char *value;
63 } config_params[] = {
64 { "backup", PARAM_BOOL, "true"},
65 { "socket_path", PARAM_CHARP, NULL},
66 { "socket_perms", PARAM_CHARP, NULL},
67 { "passphrase", PARAM_CHARP, NULL},
68 { "passphrase_file", PARAM_CHARP, NULL},
69 { "agent_env_file", PARAM_CHARP, NULL},
70 { "log_path", PARAM_CHARP, "~/.pwmd/log"},
71 { "enable_logging", PARAM_BOOL, "0"},
72 { "log_keepopen", PARAM_BOOL, "true"},
73 { "log_level", PARAM_INT, "0"},
74 { "disable_mlockall", PARAM_BOOL, "true"},
75 { "cache_timeout", PARAM_INT, DEFAULT_CACHE_TIMEOUT},
76 { "cache_push", PARAM_CHARPP, NULL},
77 { "disable_list_and_dump", PARAM_BOOL, "false"},
78 { "recursion_depth", PARAM_INT, "100"},
79 { "syslog", PARAM_BOOL, "false"},
80 { "xfer_progress", PARAM_INT, "8196"},
81 { "allowed", PARAM_CHARPP, NULL},
82 { "keyparam", PARAM_CHARP, "(genkey (rsa (nbits 4:2048)))"},
83 { "cipher", PARAM_CHARP, "aes256"},
84 { "kill_scd", PARAM_BOOL, "false"},
85 { "cipher_iterations", PARAM_ULONGLONG, "0"},
86 { "cipher_progress", PARAM_LONG, DEFAULT_ITERATION_PROGRESS},
87 { "priority", PARAM_INT, INVALID_PRIORITY},
88 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
89 { "tcp_port", PARAM_INT, "6466"},
90 { "enable_tcp", PARAM_BOOL, "false"},
91 { "tcp_require_key", PARAM_BOOL, "false"},
92 { "tcp_wait", PARAM_INT, "0"},
93 { "tcp_bind", PARAM_CHARP, "any"},
94 { "tcp_interface", PARAM_CHARP, NULL},
95 { "tls_timeout", PARAM_INT, "300"},
96 { "tls_cipher_suite", PARAM_CHARP, "SECURE256"},
97 { "tls_access", PARAM_CHARPP, NULL},
98 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
99 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
100 { "use_agent", PARAM_BOOL, "false"},
101 { "require_save_key", PARAM_BOOL, "true"},
102 { "invoking_user", PARAM_CHARP, NULL},
103 { "invoking_tls", PARAM_CHARP, NULL},
104 { NULL, 0, NULL},
107 struct config_param_s
109 char *name;
110 int type;
111 union
113 int itype;
114 char *cptype;
115 char **cpptype;
116 long ltype;
117 long long lltype;
118 unsigned long ultype;
119 unsigned long long ulltype;
120 } value;
123 static struct config_section_s *config_find_section (struct slist_s *config,
124 const char *name);
125 static int new_param (struct config_section_s *section, const char *filename,
126 int lineno, const char *name, const char *value,
127 int type);
128 static void free_section (struct config_section_s *s);
129 static int set_defaults (struct slist_s **config);
131 static void
132 section_remove_param (struct config_section_s *section, const char *name)
134 unsigned i, t = slist_length (section->params);
136 for (i = 0; i < t; i++)
138 struct config_param_s *p = slist_nth_data (section->params, i);
140 if (!p)
141 continue;
143 if (!strcmp (p->name, name))
145 switch (p->type)
147 case PARAM_CHARP:
148 xfree (p->value.cptype);
149 break;
150 case PARAM_CHARPP:
151 strv_free (p->value.cpptype);
152 break;
155 section->params = slist_remove (section->params, p);
156 xfree (p->name);
157 xfree (p);
158 break;
163 void
164 config_clear_keys ()
166 MUTEX_LOCK (&rcfile_mutex);
167 unsigned i, t = slist_length (global_config);
169 for (i = 0; i < t; i++)
171 struct config_section_s *s = slist_nth_data (global_config, i);
172 if (!s)
173 continue;
175 section_remove_param (s, "passphrase");
178 MUTEX_UNLOCK (&rcfile_mutex);
181 static struct config_param_s *
182 config_has_param (struct config_section_s *s, const char *what)
184 unsigned i, t = slist_length (s->params);
186 for (i = 0; i < t; i++)
188 struct config_param_s *p = slist_nth_data (s->params, i);
189 if (!p)
190 break;
192 if (!strcmp (p->name, what))
193 return p;
196 return NULL;
199 static struct config_param_s *
200 config_get_param (struct slist_s *config,
201 const char *section, const char *what, int *exists)
203 unsigned i, t = slist_length (config);
205 *exists = 0;
207 for (i = 0; i < t; i++)
209 struct config_param_s *p;
210 struct config_section_s *s = slist_nth_data (config, i);
212 if (!s)
213 break;
215 if (strcmp (s->name, section))
216 continue;
218 p = config_has_param (s, what);
219 if (!p)
220 return NULL;
222 *exists = 1;
223 return p;
226 return NULL;
229 static struct config_section_s *
230 new_section (struct slist_s **config, const char *name)
232 struct slist_s *tmp;
233 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
235 if (!s)
236 return NULL;
238 s->name = str_dup (name);
239 if (!s->name)
241 log_write ("%s", pwmd_strerror (ENOMEM));
242 xfree (s);
243 return NULL;
246 tmp = slist_append (*config, s);
247 if (!tmp)
249 log_write ("%s", pwmd_strerror (ENOMEM));
250 xfree (s->name);
251 xfree (s);
252 return NULL;
255 *config = tmp;
256 return s;
260 config_set_string_param (struct slist_s **config, const char *section,
261 const char *name, const char *value)
263 struct config_section_s *s = config_find_section (*config, section);
265 if (!s)
267 s = new_section (config, section);
268 if (!s)
269 return 1;
272 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
275 char *
276 config_get_string_param (struct slist_s *config, const char *section,
277 const char *what, int *exists)
279 struct config_param_s *p = config_get_param (config, section, what, exists);
280 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
284 config_set_int_param (struct slist_s **config, const char *section,
285 const char *name, const char *value)
287 struct config_section_s *s = config_find_section (*config, section);
289 if (!s)
291 s = new_section (config, section);
292 if (!s)
293 return 1;
296 return new_param (s, NULL, 0, name, value, PARAM_INT);
300 config_get_int_param (struct slist_s *config, const char *section,
301 const char *what, int *exists)
303 struct config_param_s *p = config_get_param (config, section, what, exists);
304 return *exists ? p->value.itype : -1;
308 config_set_bool_param (struct slist_s **config, const char *section,
309 const char *name, const char *value)
311 struct config_section_s *s = config_find_section (*config, section);
313 if (!s)
315 s = new_section (config, section);
316 if (!s)
317 return 1;
320 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
324 config_get_bool_param (struct slist_s *config, const char *section,
325 const char *what, int *exists)
327 return config_get_int_param (config, section, what, exists);
331 config_set_long_param (struct slist_s **config, const char *section,
332 const char *name, const char *value)
334 struct config_section_s *s = config_find_section (*config, section);
336 if (!s)
338 s = new_section (config, section);
339 if (!s)
340 return 1;
343 return new_param (s, NULL, 0, name, value, PARAM_LONG);
346 unsigned long
347 config_get_ulong_param (struct slist_s *config, const char *section,
348 const char *what, int *exists)
350 struct config_param_s *p = config_get_param (config, section, what, exists);
351 return *exists ? p->value.ultype : 0;
354 long
355 config_get_long_param (struct slist_s *config, const char *section,
356 const char *what, int *exists)
358 struct config_param_s *p = config_get_param (config, section, what, exists);
359 return *exists ? p->value.ltype : -1;
363 config_set_longlong_param (struct slist_s **config, const char *section,
364 const char *name, const char *value)
366 struct config_section_s *s = config_find_section (*config, section);
368 if (!s)
370 s = new_section (config, section);
371 if (!s)
372 return 1;
375 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
378 long long
379 config_get_longlong_param (struct slist_s *config,
380 const char *section, const char *what, int *exists)
382 struct config_param_s *p = config_get_param (config, section, what, exists);
383 return *exists ? p->value.lltype : -1;
386 unsigned long long
387 config_get_ulonglong_param (struct slist_s *config,
388 const char *section,
389 const char *what, int *exists)
391 struct config_param_s *p = config_get_param (config, section, what, exists);
392 return *exists ? p->value.ulltype : 0;
396 config_set_list_param (struct slist_s **config, const char *section,
397 const char *name, const char *value)
399 struct config_section_s *s = config_find_section (*config, section);
401 if (!s)
403 s = new_section (config, section);
404 if (!s)
405 return 1;
408 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
411 char **
412 config_get_list_param (struct slist_s *config, const char *section,
413 const char *what, int *exists)
415 struct config_param_s *p = config_get_param (config, section, what, exists);
416 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
419 char *
420 config_get_string (const char *section, const char *what)
422 char *val = NULL;
423 const char *where = section ? section : "global";
424 int exists = 0;
426 MUTEX_LOCK (&rcfile_mutex);
427 val = config_get_string_param (global_config, where, what, &exists);
428 if (!exists && strcmp (section ? section : "", "global"))
429 val = config_get_string_param (global_config, "global", what, &exists);
431 MUTEX_UNLOCK (&rcfile_mutex);
432 return val;
435 char **
436 config_get_list (const char *section, const char *what)
438 char **val = NULL;
439 const char *where = section ? section : "global";
440 int exists = 0;
442 MUTEX_LOCK (&rcfile_mutex);
443 val = config_get_list_param (global_config, where, what, &exists);
444 if (!exists && strcmp (section ? section : "", "global"))
445 val = config_get_list_param (global_config, "global", what, &exists);
447 MUTEX_UNLOCK (&rcfile_mutex);
448 return val;
452 config_get_integer (const char *section, const char *what)
454 int val = 0;
455 const char *where = section ? section : "global";
456 int exists = 0;
458 MUTEX_LOCK (&rcfile_mutex);
459 val = config_get_int_param (global_config, where, what, &exists);
460 if (!exists && strcmp (section ? section : "", "global"))
461 val = config_get_int_param (global_config, "global", what, &exists);
463 MUTEX_UNLOCK (&rcfile_mutex);
464 return val;
467 long long
468 config_get_longlong (const char *section, const char *what)
470 long long val = 0;
471 const char *where = section ? section : "global";
472 int exists = 0;
474 MUTEX_LOCK (&rcfile_mutex);
475 val = config_get_longlong_param (global_config, where, what, &exists);
476 if (!exists && strcmp (section ? section : "", "global"))
477 val = config_get_longlong_param (global_config, "global", what, &exists);
479 MUTEX_UNLOCK (&rcfile_mutex);
480 return val;
483 unsigned long long
484 config_get_ulonglong (const char *section, const char *what)
486 unsigned long long val = 0;
487 const char *where = section ? section : "global";
488 int exists = 0;
490 MUTEX_LOCK (&rcfile_mutex);
491 val = config_get_ulonglong_param (global_config, where, what, &exists);
492 if (!exists && strcmp (section ? section : "", "global"))
493 val = config_get_ulonglong_param (global_config, "global", what, &exists);
495 MUTEX_UNLOCK (&rcfile_mutex);
496 return val;
499 long
500 config_get_long (const char *section, const char *what)
502 long val = 0;
503 const char *where = section ? section : "global";
504 int exists = 0;
506 MUTEX_LOCK (&rcfile_mutex);
507 val = config_get_long_param (global_config, where, what, &exists);
508 if (!exists && strcmp (section ? section : "", "global"))
509 val = config_get_long_param (global_config, "global", what, &exists);
511 MUTEX_UNLOCK (&rcfile_mutex);
512 return val;
515 unsigned long
516 config_get_ulong (const char *section, const char *what)
518 unsigned long val = 0;
519 const char *where = section ? section : "global";
520 int exists = 0;
522 MUTEX_LOCK (&rcfile_mutex);
523 val = config_get_ulong_param (global_config, where, what, &exists);
524 if (!exists && strcmp (section ? section : "", "global"))
525 val = config_get_ulong_param (global_config, "global", what, &exists);
527 MUTEX_UNLOCK (&rcfile_mutex);
528 return val;
532 config_get_boolean (const char *section, const char *what)
534 return config_get_integer (section, what);
537 char *
538 config_get_value (const char *section, const char *what)
540 const char *where = section ? section : "global";
541 int exists = 0;
542 int i;
543 int ival;
544 long lval;
545 long long llval;
546 unsigned long ulval;
547 unsigned long long ullval;
548 char *cpval;
549 char **cppval;
550 char *result = NULL;
552 MUTEX_LOCK (&rcfile_mutex);
554 for (i = 0; config_params[i].name; i++)
556 if (!strcmp (config_params[i].name, what))
558 switch (config_params[i].type)
560 case PARAM_BOOL:
561 case PARAM_INT:
562 ival = config_get_int_param (global_config, where, what,
563 &exists);
564 if (!exists && strcmp (section ? section : "", "global"))
565 ival = config_get_int_param (global_config, "global", what,
566 &exists);
567 result = str_asprintf ("%i", ival);
568 break;
569 case PARAM_CHARP:
570 cpval = config_get_string_param (global_config, where, what,
571 &exists);
572 if (!exists && strcmp (section ? section : "", "global"))
573 cpval =
574 config_get_string_param (global_config, "global", what,
575 &exists);
576 result = cpval;
577 break;
578 case PARAM_LONG:
579 lval = config_get_long_param (global_config, where, what,
580 &exists);
581 if (!exists && strcmp (section ? section : "", "global"))
582 lval = config_get_long_param (global_config, "global", what,
583 &exists);
584 result = str_asprintf ("%li", lval);
585 break;
586 case PARAM_ULONG:
587 ulval = config_get_ulong_param (global_config, where, what,
588 &exists);
589 if (!exists && strcmp (section ? section : "", "global"))
590 ulval = config_get_ulong_param (global_config, "global", what,
591 &exists);
592 result = str_asprintf ("%lu", ulval);
593 break;
594 case PARAM_LONGLONG:
595 llval = config_get_longlong_param (global_config, where, what,
596 &exists);
597 if (!exists && strcmp (section ? section : "", "global"))
598 llval = config_get_longlong_param (global_config, "global",
599 what, &exists);
600 result = str_asprintf ("%lli", llval);
601 break;
602 case PARAM_ULONGLONG:
603 ullval = config_get_ulonglong_param (global_config, where, what,
604 &exists);
605 if (!exists && strcmp (section ? section : "", "global"))
606 ullval = config_get_ulonglong_param (global_config, "global",
607 what, &exists);
608 result = str_asprintf ("%llu", ullval);
609 break;
610 case PARAM_CHARPP:
611 cppval = config_get_list_param (global_config, where, what,
612 &exists);
613 if (!exists && strcmp (section ? section : "", "global"))
614 cppval = config_get_list_param (global_config, "global", what,
615 &exists);
617 if (cppval)
618 result = strv_join (",", cppval);
620 strv_free (cppval);
621 break;
626 MUTEX_UNLOCK (&rcfile_mutex);
627 return result;
630 static int
631 set_defaults (struct slist_s **config)
633 char *s = NULL;
634 char **list;
635 int exists;
636 int i;
637 struct passwd *pwd;
639 for (i = 0; config_params[i].name; i++)
641 switch (config_params[i].type)
643 case PARAM_BOOL:
644 config_get_bool_param (*config, "global", config_params[i].name,
645 &exists);
646 if (!exists)
648 if (config_set_bool_param
649 (config, "global", config_params[i].name,
650 config_params[i].value))
651 goto fail;
653 break;
654 case PARAM_INT:
655 config_get_int_param (*config, "global", config_params[i].name,
656 &exists);
657 if (!exists)
659 if (config_set_int_param
660 (config, "global", config_params[i].name,
661 config_params[i].value))
662 goto fail;
664 break;
665 case PARAM_CHARP:
666 s = config_get_string_param (*config, "global",
667 config_params[i].name, &exists);
668 xfree (s);
669 if (!exists && config_params[i].value)
671 if (config_set_string_param (config, "global",
672 config_params[i].name,
673 config_params[i].value))
674 goto fail;
676 break;
677 case PARAM_CHARPP:
678 list = config_get_list_param (*config, "global",
679 config_params[i].name, &exists);
680 strv_free (list);
681 if (!exists && config_params[i].value)
683 if (config_set_list_param (config, "global",
684 config_params[i].name,
685 config_params[i].value))
686 goto fail;
688 break;
689 case PARAM_LONG:
690 config_get_long_param (*config, "global", config_params[i].name,
691 &exists);
692 if (!exists)
694 if (config_set_long_param
695 (config, "global", config_params[i].name,
696 config_params[i].value))
697 goto fail;
699 break;
700 case PARAM_LONGLONG:
701 config_get_longlong_param (*config, "global", config_params[i].name,
702 &exists);
703 if (!exists)
705 if (config_set_longlong_param (config, "global",
706 config_params[i].name,
707 config_params[i].value))
708 goto fail;
710 break;
714 list = config_get_list_param (*config, "global", "allowed", &exists);
715 strv_free (list);
716 if (!exists)
718 if (config_set_list_param
719 (config, "global", "allowed", get_username ()))
720 goto fail;
723 max_recursion_depth = config_get_int_param (*config, "global",
724 "recursion_depth", &exists);
725 disable_list_and_dump = config_get_bool_param (*config, "global",
726 "disable_list_and_dump",
727 &exists);
728 #ifdef HAVE_MLOCKALL
729 disable_mlock =
730 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
731 #endif
733 s = config_get_string_param(*config, "global", "invoking_user", &exists);
734 errno = 0;
735 if (!s || !*s)
736 pwd = getpwuid(getuid());
737 else
738 pwd = getpwnam(s);
740 if (!pwd)
742 log_write (_("could not set invoking user: user '%s' is invalid"), s);
743 goto fail;
746 xfree (s);
747 #ifdef WITH_GNUTLS
748 invoking_tls = config_get_string_param(*config, "global", "invoking_tls",
749 &exists);
750 #endif
751 invoking_uid = pwd->pw_uid;
752 invoking_gid = pwd->pw_gid;
753 return 0;
755 fail:
756 xfree (s);
757 return 1;
760 static struct config_section_s *
761 config_find_section (struct slist_s *config, const char *name)
763 unsigned i, t = slist_length (config);
765 for (i = 0; i < t; i++)
767 struct config_section_s *s = slist_nth_data (config, i);
769 if (!strcmp (s->name, name))
770 return s;
773 return NULL;
776 /* Append a new parameter to the list of parameters for a file
777 * section. When an existing parameter of the same name exists, its
778 * value is updated.
780 static int
781 new_param (struct config_section_s *section, const char *filename, int lineno,
782 const char *name, const char *value, int type)
784 struct config_param_s *param = NULL;
785 struct slist_s *tmp;
786 char *e;
787 unsigned i, t = slist_length (section->params);
788 int dup = 0;
790 for (i = 0; i < t; i++)
792 struct config_param_s *p = slist_nth_data (section->params, i);
793 if (!p)
794 break;
796 if (!strcmp (name, p->name))
798 param = p;
799 dup = 1;
800 break;
804 if (!param)
806 param = xcalloc (1, sizeof (struct config_param_s));
807 if (!param)
809 log_write ("%s", pwmd_strerror (ENOMEM));
810 return 1;
813 param->name = str_dup (name);
814 if (!param->name)
816 xfree (param);
817 log_write ("%s", pwmd_strerror (ENOMEM));
818 return 1;
822 param->type = type;
824 switch (type)
826 case PARAM_BOOL:
827 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
828 || !strcasecmp (value, "false"))
829 param->value.itype = 0;
830 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
831 || !strcasecmp (value, "true"))
832 param->value.itype = 1;
833 else
835 INVALID_VALUE (filename, lineno);
836 goto fail;
838 param->type = PARAM_INT;
839 break;
840 case PARAM_CHARP:
841 xfree (param->value.cptype);
842 param->value.cptype = value ? str_dup (value) : NULL;
843 if (value && !param->value.cptype)
845 log_write ("%s", pwmd_strerror (ENOMEM));
846 goto fail;
848 break;
849 case PARAM_CHARPP:
850 strv_free (param->value.cpptype);
851 param->value.cpptype = value ? str_split (value, ",", 0) : NULL;
852 if (value && !param->value.cpptype)
854 log_write ("%s", pwmd_strerror (ENOMEM));
855 goto fail;
857 break;
858 case PARAM_INT:
859 param->value.itype = strtol (value, &e, 10);
860 if (e && *e)
862 INVALID_VALUE (filename, lineno);
863 goto fail;
865 break;
866 case PARAM_LONG:
867 param->value.ltype = strtol (value, &e, 10);
868 if (e && *e)
870 INVALID_VALUE (filename, lineno);
871 goto fail;
873 break;
874 case PARAM_LONGLONG:
875 param->value.lltype = strtoll (value, &e, 10);
876 if (e && *e)
878 INVALID_VALUE (filename, lineno);
879 goto fail;
881 break;
882 case PARAM_ULONGLONG:
883 param->value.ulltype = strtoull (value, &e, 10);
884 if (e && *e)
886 INVALID_VALUE (filename, lineno);
887 goto fail;
889 break;
890 case PARAM_ULONG:
891 param->value.ultype = strtoul (value, &e, 10);
892 if (e && *e)
894 INVALID_VALUE (filename, lineno);
895 goto fail;
897 break;
900 if (dup)
901 return 0;
903 tmp = slist_append (section->params, param);
904 if (!tmp)
906 log_write ("%s", pwmd_strerror (ENOMEM));
907 goto fail;
910 section->params = tmp;
911 return 0;
913 fail:
914 xfree (param->name);
915 xfree (param);
916 return 1;
919 struct slist_s *
920 config_parse (const char *filename)
922 struct slist_s *tmpconfig = NULL, *tmp;
923 struct config_section_s *cur_section = NULL;
924 char buf[LINE_MAX];
925 char *s;
926 int lineno = 1;
927 int have_global = 0;
928 FILE *fp = fopen (filename, "r");
930 if (!fp)
932 log_write ("%s: %s", filename,
933 pwmd_strerror (gpg_error_from_errno (errno)));
935 if (errno != ENOENT)
936 return NULL;
938 log_write (_("Using defaults!"));
939 goto defaults;
942 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
944 char line[LINE_MAX] = { 0 };
945 size_t len = 0;
947 if (*s == '#')
948 continue;
950 s = str_chomp (s);
951 for (; s && *s; s++)
953 int match = 0;
955 /* New file section. */
956 if (*s == '[')
958 struct config_section_s *section;
959 char *p = strchr (++s, ']');
961 if (!p)
963 log_write (_("%s(%i): unbalanced braces"), filename,
964 lineno);
965 goto fail;
968 len = strlen (s) - strlen (p);
969 memcpy (line, s, len);
970 line[len] = 0;
972 section = config_find_section (tmpconfig, line);
973 if (section)
975 log_write (_("%s(%i): section '%s' already exists!"),
976 filename, lineno, line);
977 goto fail;
980 if (!strcmp (line, "global"))
981 have_global = 1;
983 section = xcalloc (1, sizeof (struct config_section_s));
984 section->name = str_dup (line);
986 if (cur_section)
988 tmp = slist_append (tmpconfig, cur_section);
989 if (!tmp)
991 log_write ("%s", pwmd_strerror (ENOMEM));
992 goto fail;
995 tmpconfig = tmp;
998 cur_section = section;
999 break;
1002 if (!cur_section)
1004 log_write (_("%s(%i): parameter outside of section!"), filename,
1005 lineno);
1006 goto fail;
1009 /* Parameters for each section. */
1010 for (int m = 0; config_params[m].name; m++)
1012 size_t len = strlen (config_params[m].name);
1014 if (!strncmp (s, config_params[m].name, len))
1016 char *p = s + len;
1018 while (*p && *p == ' ')
1019 p++;
1021 if (!*p || *p != '=')
1022 continue;
1024 p++;
1025 while (*p && isspace (*p))
1026 p++;
1028 s[len] = 0;
1029 if (new_param (cur_section, filename, lineno, s, p,
1030 config_params[m].type))
1031 goto fail;
1033 match = 1;
1034 break;
1038 if (!match)
1040 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1041 goto fail;
1044 break;
1048 if (cur_section)
1050 tmp = slist_append (tmpconfig, cur_section);
1051 if (!tmp)
1053 log_write ("%s", pwmd_strerror (ENOMEM));
1054 goto fail;
1057 cur_section = NULL;
1058 tmpconfig = tmp;
1061 if (!have_global)
1062 log_write (_
1063 ("WARNING: %s: could not find a [global] configuration section!"),
1064 filename);
1066 defaults:
1067 if (set_defaults (&tmpconfig))
1068 goto fail;
1070 if (fp)
1071 fclose(fp);
1073 return tmpconfig;
1075 fail:
1076 if (fp)
1077 fclose (fp);
1079 config_free (tmpconfig);
1080 free_section (cur_section);
1081 return NULL;
1084 static void
1085 free_section (struct config_section_s *s)
1087 if (!s)
1088 return;
1090 for (;;)
1092 struct config_param_s *p = slist_nth_data (s->params, 0);
1094 if (!p)
1095 break;
1097 section_remove_param (s, p->name);
1100 s->params = NULL;
1101 xfree (s->name);
1102 s->name = NULL;
1105 void
1106 config_free (struct slist_s *config)
1108 for (;;)
1110 struct config_section_s *s = slist_nth_data (config, 0);
1111 if (!s)
1112 break;
1114 free_section (s);
1115 config = slist_remove (config, s);
1116 xfree (s);