Require GnuTLS >= 3.3.0.
[pwmd.git] / src / rcfile.c
blob2576fb145bc3e6f1e2989aab96f394f3e0514705
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
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"
46 #define DEFAULT_LOCK_TIMEOUT "50" // MUTEX_TRYLOCK in tenths of a second
48 #define INVALID_VALUE(file, line) do { \
49 if (file) \
50 log_write(_("%s(%i): invalid value for parameter."), file, line); \
51 } while (0);
53 enum
55 PARAM_INT, PARAM_CHARP, PARAM_LONG, PARAM_LONGLONG, PARAM_CHARPP,
56 PARAM_BOOL, PARAM_ULONG, PARAM_ULONGLONG
59 static struct config_params_s
61 char *name;
62 int type;
63 char *value;
64 } config_params[] = {
65 { "backup", PARAM_BOOL, "true"},
66 { "socket_path", PARAM_CHARP, NULL},
67 { "socket_perms", PARAM_CHARP, NULL},
68 { "passphrase", PARAM_CHARP, NULL},
69 { "passphrase_file", PARAM_CHARP, NULL},
70 { "gpg_agent_socket", PARAM_CHARP, NULL},
71 { "log_path", PARAM_CHARP, "~/.pwmd/log"},
72 { "enable_logging", PARAM_BOOL, "0"},
73 { "log_keepopen", PARAM_BOOL, "true"},
74 { "log_level", PARAM_INT, "0"},
75 { "disable_mlockall", PARAM_BOOL, "true"},
76 { "cache_timeout", PARAM_INT, DEFAULT_CACHE_TIMEOUT},
77 { "cache_push", PARAM_CHARPP, NULL},
78 { "disable_list_and_dump", PARAM_BOOL, "false"},
79 { "recursion_depth", PARAM_INT, "100"},
80 { "syslog", PARAM_BOOL, "false"},
81 { "xfer_progress", PARAM_INT, "8196"},
82 { "allowed", PARAM_CHARPP, NULL},
83 { "allowed_file", PARAM_CHARP, NULL},
84 { "keyparam", PARAM_CHARP, "(genkey (rsa (nbits 4:2048)))"},
85 { "cipher", PARAM_CHARP, "aes256"},
86 { "kill_scd", PARAM_BOOL, "false"},
87 { "cipher_iterations", PARAM_ULONGLONG, "0"},
88 { "cipher_progress", PARAM_LONG, DEFAULT_ITERATION_PROGRESS},
89 { "priority", PARAM_INT, INVALID_PRIORITY},
90 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
91 { "tcp_port", PARAM_INT, "6466"},
92 { "enable_tcp", PARAM_BOOL, "false"},
93 { "tcp_require_key", PARAM_BOOL, "false"},
94 { "tcp_wait", PARAM_INT, "0"},
95 { "tcp_bind", PARAM_CHARP, "any"},
96 { "tcp_interface", PARAM_CHARP, NULL},
97 { "tls_timeout", PARAM_INT, "300"},
98 { "tls_cipher_suite", PARAM_CHARP, "SECURE256:SECURE192:SECURE128:-VERS-SSL3.0"},
99 { "tls_dh_level", PARAM_CHARP, "medium"},
100 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
101 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
102 { "use_agent", PARAM_BOOL, "false"},
103 { "require_save_key", PARAM_BOOL, "true"},
104 { "invoking_user", PARAM_CHARP, NULL},
105 { "invoking_tls", PARAM_CHARP, NULL},
106 { "lock_timeout", PARAM_INT, DEFAULT_LOCK_TIMEOUT},
107 { "send_state", PARAM_INT, "2"},
108 { NULL, 0, NULL},
111 struct config_param_s
113 char *name;
114 int type;
115 union
117 int itype;
118 char *cptype;
119 char **cpptype;
120 long ltype;
121 long long lltype;
122 unsigned long ultype;
123 unsigned long long ulltype;
124 } value;
127 static struct config_section_s *config_find_section (struct slist_s *config,
128 const char *name);
129 static int new_param (struct config_section_s *section, const char *filename,
130 int lineno, const char *name, const char *value,
131 int type);
132 static void free_section (struct config_section_s *s);
133 static int set_defaults (struct slist_s **config);
135 static void
136 section_remove_param (struct config_section_s *section, const char *name)
138 unsigned i, t = slist_length (section->params);
140 for (i = 0; i < t; i++)
142 struct config_param_s *p = slist_nth_data (section->params, i);
144 if (!p)
145 continue;
147 if (!strcmp (p->name, name))
149 switch (p->type)
151 case PARAM_CHARP:
152 xfree (p->value.cptype);
153 break;
154 case PARAM_CHARPP:
155 strv_free (p->value.cpptype);
156 break;
159 section->params = slist_remove (section->params, p);
160 xfree (p->name);
161 xfree (p);
162 break;
167 void
168 config_clear_keys ()
170 MUTEX_LOCK (&rcfile_mutex);
171 unsigned i, t = slist_length (global_config);
173 for (i = 0; i < t; i++)
175 struct config_section_s *s = slist_nth_data (global_config, i);
176 if (!s)
177 continue;
179 section_remove_param (s, "passphrase");
182 MUTEX_UNLOCK (&rcfile_mutex);
185 static struct config_param_s *
186 config_has_param (struct config_section_s *s, const char *what)
188 unsigned i, t = slist_length (s->params);
190 for (i = 0; i < t; i++)
192 struct config_param_s *p = slist_nth_data (s->params, i);
193 if (!p)
194 break;
196 if (!strcmp (p->name, what))
197 return p;
200 return NULL;
203 static struct config_param_s *
204 config_get_param (struct slist_s *config,
205 const char *section, const char *what, int *exists)
207 unsigned i, t = slist_length (config);
209 *exists = 0;
211 for (i = 0; i < t; i++)
213 struct config_param_s *p;
214 struct config_section_s *s = slist_nth_data (config, i);
216 if (!s)
217 break;
219 if (strcmp (s->name, section))
220 continue;
222 p = config_has_param (s, what);
223 if (!p)
224 return NULL;
226 *exists = 1;
227 return p;
230 return NULL;
233 static struct config_section_s *
234 new_section (struct slist_s **config, const char *name)
236 struct slist_s *tmp;
237 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
239 if (!s)
240 return NULL;
242 s->name = str_dup (name);
243 if (!s->name)
245 log_write ("%s", pwmd_strerror (ENOMEM));
246 xfree (s);
247 return NULL;
250 tmp = slist_append (*config, s);
251 if (!tmp)
253 log_write ("%s", pwmd_strerror (ENOMEM));
254 xfree (s->name);
255 xfree (s);
256 return NULL;
259 *config = tmp;
260 return s;
264 config_set_string_param (struct slist_s **config, const char *section,
265 const char *name, const char *value)
267 struct config_section_s *s = config_find_section (*config, section);
269 if (!s)
271 s = new_section (config, section);
272 if (!s)
273 return 1;
276 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
279 char *
280 config_get_string_param (struct slist_s *config, const char *section,
281 const char *what, int *exists)
283 struct config_param_s *p = config_get_param (config, section, what, exists);
284 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
288 config_set_int_param (struct slist_s **config, const char *section,
289 const char *name, const char *value)
291 struct config_section_s *s = config_find_section (*config, section);
293 if (!s)
295 s = new_section (config, section);
296 if (!s)
297 return 1;
300 return new_param (s, NULL, 0, name, value, PARAM_INT);
304 config_get_int_param (struct slist_s *config, const char *section,
305 const char *what, int *exists)
307 struct config_param_s *p = config_get_param (config, section, what, exists);
308 return *exists ? p->value.itype : -1;
312 config_set_bool_param (struct slist_s **config, const char *section,
313 const char *name, const char *value)
315 struct config_section_s *s = config_find_section (*config, section);
317 if (!s)
319 s = new_section (config, section);
320 if (!s)
321 return 1;
324 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
328 config_get_bool_param (struct slist_s *config, const char *section,
329 const char *what, int *exists)
331 return config_get_int_param (config, section, what, exists);
335 config_set_long_param (struct slist_s **config, const char *section,
336 const char *name, const char *value)
338 struct config_section_s *s = config_find_section (*config, section);
340 if (!s)
342 s = new_section (config, section);
343 if (!s)
344 return 1;
347 return new_param (s, NULL, 0, name, value, PARAM_LONG);
350 unsigned long
351 config_get_ulong_param (struct slist_s *config, const char *section,
352 const char *what, int *exists)
354 struct config_param_s *p = config_get_param (config, section, what, exists);
355 return *exists ? p->value.ultype : 0;
358 long
359 config_get_long_param (struct slist_s *config, const char *section,
360 const char *what, int *exists)
362 struct config_param_s *p = config_get_param (config, section, what, exists);
363 return *exists ? p->value.ltype : -1;
367 config_set_longlong_param (struct slist_s **config, const char *section,
368 const char *name, const char *value)
370 struct config_section_s *s = config_find_section (*config, section);
372 if (!s)
374 s = new_section (config, section);
375 if (!s)
376 return 1;
379 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
382 long long
383 config_get_longlong_param (struct slist_s *config,
384 const char *section, const char *what, int *exists)
386 struct config_param_s *p = config_get_param (config, section, what, exists);
387 return *exists ? p->value.lltype : -1;
390 unsigned long long
391 config_get_ulonglong_param (struct slist_s *config,
392 const char *section,
393 const char *what, int *exists)
395 struct config_param_s *p = config_get_param (config, section, what, exists);
396 return *exists ? p->value.ulltype : 0;
400 config_set_list_param (struct slist_s **config, const char *section,
401 const char *name, const char *value)
403 struct config_section_s *s = config_find_section (*config, section);
405 if (!s)
407 s = new_section (config, section);
408 if (!s)
409 return 1;
412 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
415 char **
416 config_get_list_param (struct slist_s *config, const char *section,
417 const char *what, int *exists)
419 struct config_param_s *p = config_get_param (config, section, what, exists);
420 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
423 char *
424 config_get_string (const char *section, const char *what)
426 char *val = NULL;
427 const char *where = section ? section : "global";
428 int exists = 0;
430 MUTEX_LOCK (&rcfile_mutex);
431 val = config_get_string_param (global_config, where, what, &exists);
432 if (!exists && strcmp (section ? section : "", "global"))
433 val = config_get_string_param (global_config, "global", what, &exists);
435 MUTEX_UNLOCK (&rcfile_mutex);
436 return val;
439 char **
440 config_get_list (const char *section, const char *what)
442 char **val = NULL;
443 const char *where = section ? section : "global";
444 int exists = 0;
446 MUTEX_LOCK (&rcfile_mutex);
447 val = config_get_list_param (global_config, where, what, &exists);
448 if (!exists && strcmp (section ? section : "", "global"))
449 val = config_get_list_param (global_config, "global", what, &exists);
451 MUTEX_UNLOCK (&rcfile_mutex);
452 return val;
456 config_get_integer (const char *section, const char *what)
458 int val = 0;
459 const char *where = section ? section : "global";
460 int exists = 0;
462 MUTEX_LOCK (&rcfile_mutex);
463 val = config_get_int_param (global_config, where, what, &exists);
464 if (!exists && strcmp (section ? section : "", "global"))
465 val = config_get_int_param (global_config, "global", what, &exists);
467 MUTEX_UNLOCK (&rcfile_mutex);
468 return val;
471 long long
472 config_get_longlong (const char *section, const char *what)
474 long long val = 0;
475 const char *where = section ? section : "global";
476 int exists = 0;
478 MUTEX_LOCK (&rcfile_mutex);
479 val = config_get_longlong_param (global_config, where, what, &exists);
480 if (!exists && strcmp (section ? section : "", "global"))
481 val = config_get_longlong_param (global_config, "global", what, &exists);
483 MUTEX_UNLOCK (&rcfile_mutex);
484 return val;
487 unsigned long long
488 config_get_ulonglong (const char *section, const char *what)
490 unsigned long long val = 0;
491 const char *where = section ? section : "global";
492 int exists = 0;
494 MUTEX_LOCK (&rcfile_mutex);
495 val = config_get_ulonglong_param (global_config, where, what, &exists);
496 if (!exists && strcmp (section ? section : "", "global"))
497 val = config_get_ulonglong_param (global_config, "global", what, &exists);
499 MUTEX_UNLOCK (&rcfile_mutex);
500 return val;
503 long
504 config_get_long (const char *section, const char *what)
506 long val = 0;
507 const char *where = section ? section : "global";
508 int exists = 0;
510 MUTEX_LOCK (&rcfile_mutex);
511 val = config_get_long_param (global_config, where, what, &exists);
512 if (!exists && strcmp (section ? section : "", "global"))
513 val = config_get_long_param (global_config, "global", what, &exists);
515 MUTEX_UNLOCK (&rcfile_mutex);
516 return val;
519 unsigned long
520 config_get_ulong (const char *section, const char *what)
522 unsigned long val = 0;
523 const char *where = section ? section : "global";
524 int exists = 0;
526 MUTEX_LOCK (&rcfile_mutex);
527 val = config_get_ulong_param (global_config, where, what, &exists);
528 if (!exists && strcmp (section ? section : "", "global"))
529 val = config_get_ulong_param (global_config, "global", what, &exists);
531 MUTEX_UNLOCK (&rcfile_mutex);
532 return val;
536 config_get_boolean (const char *section, const char *what)
538 return config_get_integer (section, what);
541 char *
542 config_get_value (const char *section, const char *what)
544 const char *where = section ? section : "global";
545 int exists = 0;
546 int i;
547 int ival;
548 long lval;
549 long long llval;
550 unsigned long ulval;
551 unsigned long long ullval;
552 char *cpval;
553 char **cppval;
554 char *result = NULL;
556 MUTEX_LOCK (&rcfile_mutex);
558 for (i = 0; config_params[i].name; i++)
560 if (!strcmp (config_params[i].name, what))
562 switch (config_params[i].type)
564 case PARAM_BOOL:
565 case PARAM_INT:
566 ival = config_get_int_param (global_config, where, what,
567 &exists);
568 if (!exists && strcmp (section ? section : "", "global"))
569 ival = config_get_int_param (global_config, "global", what,
570 &exists);
571 result = str_asprintf ("%i", ival);
572 break;
573 case PARAM_CHARP:
574 cpval = config_get_string_param (global_config, where, what,
575 &exists);
576 if (!exists && strcmp (section ? section : "", "global"))
577 cpval =
578 config_get_string_param (global_config, "global", what,
579 &exists);
580 result = cpval;
581 break;
582 case PARAM_LONG:
583 lval = config_get_long_param (global_config, where, what,
584 &exists);
585 if (!exists && strcmp (section ? section : "", "global"))
586 lval = config_get_long_param (global_config, "global", what,
587 &exists);
588 result = str_asprintf ("%li", lval);
589 break;
590 case PARAM_ULONG:
591 ulval = config_get_ulong_param (global_config, where, what,
592 &exists);
593 if (!exists && strcmp (section ? section : "", "global"))
594 ulval = config_get_ulong_param (global_config, "global", what,
595 &exists);
596 result = str_asprintf ("%lu", ulval);
597 break;
598 case PARAM_LONGLONG:
599 llval = config_get_longlong_param (global_config, where, what,
600 &exists);
601 if (!exists && strcmp (section ? section : "", "global"))
602 llval = config_get_longlong_param (global_config, "global",
603 what, &exists);
604 result = str_asprintf ("%lli", llval);
605 break;
606 case PARAM_ULONGLONG:
607 ullval = config_get_ulonglong_param (global_config, where, what,
608 &exists);
609 if (!exists && strcmp (section ? section : "", "global"))
610 ullval = config_get_ulonglong_param (global_config, "global",
611 what, &exists);
612 result = str_asprintf ("%llu", ullval);
613 break;
614 case PARAM_CHARPP:
615 cppval = config_get_list_param (global_config, where, what,
616 &exists);
617 if (!exists && strcmp (section ? section : "", "global"))
618 cppval = config_get_list_param (global_config, "global", what,
619 &exists);
621 if (cppval)
622 result = strv_join (",", cppval);
624 strv_free (cppval);
625 break;
630 MUTEX_UNLOCK (&rcfile_mutex);
631 return result;
634 static void
635 parse_allowed_file (struct slist_s *config, const char *section)
637 FILE *fp;
638 char buf[LINE_MAX];
639 int exists;
640 char **list = NULL;
641 char *tmp;
642 char *p = config_get_string_param (config, section, "allowed_file", &exists);
644 if (!p || !*p)
646 xfree (p);
647 return;
650 tmp = expand_homedir (p);
651 xfree (p);
652 p = tmp;
653 fp = fopen (p, "r");
654 if (!fp)
656 log_write ("%s: %s", p, strerror (errno));
657 xfree (p);
658 return;
661 xfree (p);
662 list = config_get_list_param (config, section, "allowed", &exists);
663 if (!list && exists)
665 fclose (fp);
666 log_write ("%s", strerror (ENOMEM));
667 return;
670 while ((p = fgets (buf, sizeof (buf), fp)))
672 char **pp = NULL;
674 if (p[strlen(p)-1] == '\n')
675 p[strlen(p)-1] = 0;
677 while (*p && isspace (*p))
678 p++;
680 if (!*p)
681 continue;
683 tmp = str_dup (p);
684 if (tmp)
685 pp = strv_cat (list, str_dup (p));
687 if (!pp || !tmp)
689 xfree (tmp);
690 strv_free (list);
691 fclose (fp);
692 log_write ("%s", strerror (ENOMEM));
693 return;
696 xfree (tmp);
697 list = pp;
700 fclose(fp);
701 if (!list)
702 return;
704 p = strv_join (",", list);
705 strv_free (list);
707 if (!p)
709 log_write ("%s", strerror (ENOMEM));
710 return;
713 config_set_list_param (&config, section, "allowed", p);
714 xfree (p);
717 static int
718 fixup_allowed_once (struct slist_s **config, const char *section)
720 char **list, **pp, *p;
721 int exists;
723 parse_allowed_file (*config, section);
724 list = config_get_list_param (*config, section, "allowed", &exists);
725 for (pp = list; pp && *pp; pp++)
727 if (*(*pp) == '#')
729 for (p = *pp; p && *p; p++)
730 *p = toupper(*p);
734 strv_free (list);
735 if (!exists)
737 if (!strcmp (section, "global"))
739 p = get_username (getuid());
741 if (config_set_list_param (config, section, "allowed", p))
743 xfree (p);
744 return 1;
747 xfree (p);
749 else
751 list = config_get_list_param (*config, "global", "allowed", &exists);
752 if (list)
754 p = strv_join (",", list);
755 strv_free (list);
756 if (config_set_list_param (config, section, "allowed", p))
758 xfree (p);
759 return 1;
762 xfree (p);
767 return 0;
770 static int
771 fixup_allowed (struct slist_s **config)
773 int n, t = slist_length (*config);
775 for (n = 0; n < t; n++)
777 struct config_section_s *section;
779 section = slist_nth_data (*config, n);
780 if (fixup_allowed_once (config, section->name))
781 return 1;
784 return 0;
787 static int
788 set_defaults (struct slist_s **config)
790 char *s = NULL, *tmp;
791 char **list;
792 int exists;
793 int i;
794 struct passwd *pwd;
796 for (i = 0; config_params[i].name; i++)
798 switch (config_params[i].type)
800 case PARAM_BOOL:
801 config_get_bool_param (*config, "global", config_params[i].name,
802 &exists);
803 if (!exists)
805 if (config_set_bool_param
806 (config, "global", config_params[i].name,
807 config_params[i].value))
808 goto fail;
810 break;
811 case PARAM_INT:
812 config_get_int_param (*config, "global", config_params[i].name,
813 &exists);
814 if (!exists)
816 if (config_set_int_param
817 (config, "global", config_params[i].name,
818 config_params[i].value))
819 goto fail;
821 break;
822 case PARAM_CHARP:
823 s = config_get_string_param (*config, "global",
824 config_params[i].name, &exists);
825 xfree (s);
826 if (!exists && config_params[i].value)
828 if (config_set_string_param (config, "global",
829 config_params[i].name,
830 config_params[i].value))
831 goto fail;
833 break;
834 case PARAM_CHARPP:
835 list = config_get_list_param (*config, "global",
836 config_params[i].name, &exists);
837 strv_free (list);
838 if (!exists && config_params[i].value)
840 if (config_set_list_param (config, "global",
841 config_params[i].name,
842 config_params[i].value))
843 goto fail;
845 break;
846 case PARAM_LONG:
847 config_get_long_param (*config, "global", config_params[i].name,
848 &exists);
849 if (!exists)
851 if (config_set_long_param
852 (config, "global", config_params[i].name,
853 config_params[i].value))
854 goto fail;
856 break;
857 case PARAM_LONGLONG:
858 config_get_longlong_param (*config, "global", config_params[i].name,
859 &exists);
860 if (!exists)
862 if (config_set_longlong_param (config, "global",
863 config_params[i].name,
864 config_params[i].value))
865 goto fail;
867 break;
871 s = NULL;
872 if (fixup_allowed (config))
873 goto fail;
875 max_recursion_depth = config_get_int_param (*config, "global",
876 "recursion_depth", &exists);
877 disable_list_and_dump = config_get_bool_param (*config, "global",
878 "disable_list_and_dump",
879 &exists);
880 #ifdef HAVE_MLOCKALL
881 disable_mlock =
882 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
883 #endif
885 s = config_get_string_param(*config, "global", "invoking_user", &exists);
886 errno = 0;
887 if (!s || !*s)
888 pwd = getpwuid(getuid());
889 else
890 pwd = getpwnam(s);
892 if (!pwd)
894 log_write (_("could not set invoking user: user '%s' is invalid"), s);
895 goto fail;
898 xfree (s);
899 config_set_string_param(config, "global", "invoking_user", pwd->pw_name);
900 #ifdef WITH_GNUTLS
901 invoking_tls = config_get_string_param(*config, "global", "invoking_tls",
902 &exists);
903 for (char *p = invoking_tls; p && *p; p++)
904 *p = toupper(*p);
906 config_set_string_param(config, "global", "invoking_tls", invoking_tls);
907 #endif
908 invoking_uid = pwd->pw_uid;
909 invoking_gid = pwd->pw_gid;
911 s = config_get_string_param(*config, "global", "gpg_agent_socket", &exists);
912 if (!s || !*s)
914 xfree (s);
915 s = str_asprintf ("%s/.gnupg/S.gpg-agent", get_home_dir());
916 config_set_string_param(config, "global", "gpg_agent_socket", s);
918 else
920 tmp = expand_homedir (s);
921 config_set_string_param(config, "global", "gpg_agent_socket", tmp);
922 xfree (tmp);
925 xfree (s);
926 return 0;
928 fail:
929 xfree (s);
930 return 1;
933 static struct config_section_s *
934 config_find_section (struct slist_s *config, const char *name)
936 unsigned i, t = slist_length (config);
938 for (i = 0; i < t; i++)
940 struct config_section_s *s = slist_nth_data (config, i);
942 if (!strcmp (s->name, name))
943 return s;
946 return NULL;
949 /* Append a new parameter to the list of parameters for a file
950 * section. When an existing parameter of the same name exists, its
951 * value is updated.
953 static int
954 new_param (struct config_section_s *section, const char *filename, int lineno,
955 const char *name, const char *value, int type)
957 struct config_param_s *param = NULL;
958 struct slist_s *tmp;
959 char *e;
960 unsigned i, t = slist_length (section->params);
961 int dup = 0;
963 for (i = 0; i < t; i++)
965 struct config_param_s *p = slist_nth_data (section->params, i);
966 if (!p)
967 break;
969 if (!strcmp (name, p->name))
971 param = p;
972 dup = 1;
973 break;
977 if (!param)
979 param = xcalloc (1, sizeof (struct config_param_s));
980 if (!param)
982 log_write ("%s", pwmd_strerror (ENOMEM));
983 return 1;
986 param->name = str_dup (name);
987 if (!param->name)
989 xfree (param);
990 log_write ("%s", pwmd_strerror (ENOMEM));
991 return 1;
995 param->type = type;
997 switch (type)
999 case PARAM_BOOL:
1000 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1001 || !strcasecmp (value, "false"))
1002 param->value.itype = 0;
1003 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1004 || !strcasecmp (value, "true"))
1005 param->value.itype = 1;
1006 else
1008 INVALID_VALUE (filename, lineno);
1009 goto fail;
1011 param->type = PARAM_INT;
1012 break;
1013 case PARAM_CHARP:
1014 xfree (param->value.cptype);
1015 param->value.cptype = NULL;
1016 param->value.cptype = value && *value ? str_dup (value) : NULL;
1017 if (value && *value && !param->value.cptype)
1019 log_write ("%s", pwmd_strerror (ENOMEM));
1020 goto fail;
1022 break;
1023 case PARAM_CHARPP:
1024 strv_free (param->value.cpptype);
1025 param->value.cpptype = NULL;
1026 param->value.cpptype = value && *value ? str_split (value, ",", 0) : NULL;
1027 if (value && *value && !param->value.cpptype)
1029 log_write ("%s", pwmd_strerror (ENOMEM));
1030 goto fail;
1032 break;
1033 case PARAM_INT:
1034 param->value.itype = strtol (value, &e, 10);
1035 if (e && *e)
1037 INVALID_VALUE (filename, lineno);
1038 goto fail;
1040 break;
1041 case PARAM_LONG:
1042 param->value.ltype = strtol (value, &e, 10);
1043 if (e && *e)
1045 INVALID_VALUE (filename, lineno);
1046 goto fail;
1048 break;
1049 case PARAM_LONGLONG:
1050 param->value.lltype = strtoll (value, &e, 10);
1051 if (e && *e)
1053 INVALID_VALUE (filename, lineno);
1054 goto fail;
1056 break;
1057 case PARAM_ULONGLONG:
1058 param->value.ulltype = strtoull (value, &e, 10);
1059 if (e && *e)
1061 INVALID_VALUE (filename, lineno);
1062 goto fail;
1064 break;
1065 case PARAM_ULONG:
1066 param->value.ultype = strtoul (value, &e, 10);
1067 if (e && *e)
1069 INVALID_VALUE (filename, lineno);
1070 goto fail;
1072 break;
1075 if (dup)
1076 return 0;
1078 tmp = slist_append (section->params, param);
1079 if (!tmp)
1081 log_write ("%s", pwmd_strerror (ENOMEM));
1082 goto fail;
1085 section->params = tmp;
1086 return 0;
1088 fail:
1089 xfree (param->name);
1090 xfree (param);
1091 return 1;
1094 struct slist_s *
1095 config_parse (const char *filename)
1097 struct slist_s *tmpconfig = NULL, *tmp;
1098 struct config_section_s *cur_section = NULL;
1099 char buf[LINE_MAX];
1100 char *s;
1101 int lineno = 1;
1102 int have_global = 0;
1103 FILE *fp = fopen (filename, "r");
1105 if (!fp)
1107 log_write ("%s: %s", filename,
1108 pwmd_strerror (gpg_error_from_errno (errno)));
1110 if (errno != ENOENT)
1111 return NULL;
1113 log_write (_("Using defaults!"));
1114 goto defaults;
1117 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
1119 char line[LINE_MAX] = { 0 };
1120 size_t len = 0;
1122 if (*s == '#')
1123 continue;
1125 s = str_chomp (s);
1126 for (; s && *s; s++)
1128 int match = 0;
1130 /* New file section. */
1131 if (*s == '[')
1133 struct config_section_s *section;
1134 char *p = strchr (++s, ']');
1136 if (!p)
1138 log_write (_("%s(%i): unbalanced braces"), filename,
1139 lineno);
1140 goto fail;
1143 len = strlen (s) - strlen (p);
1144 memcpy (line, s, len);
1145 line[len] = 0;
1147 section = config_find_section (tmpconfig, line);
1148 if (section)
1150 log_write (_("%s(%i): section '%s' already exists!"),
1151 filename, lineno, line);
1152 goto fail;
1155 if (!strcmp (line, "global"))
1156 have_global = 1;
1158 section = xcalloc (1, sizeof (struct config_section_s));
1159 section->name = str_dup (line);
1161 if (cur_section)
1163 tmp = slist_append (tmpconfig, cur_section);
1164 if (!tmp)
1166 log_write ("%s", pwmd_strerror (ENOMEM));
1167 goto fail;
1170 tmpconfig = tmp;
1173 cur_section = section;
1174 break;
1177 if (!cur_section)
1179 log_write (_("%s(%i): parameter outside of section!"), filename,
1180 lineno);
1181 goto fail;
1184 /* Parameters for each section. */
1185 for (int m = 0; config_params[m].name; m++)
1187 size_t len = strlen (config_params[m].name);
1189 if (!strncmp (s, config_params[m].name, len))
1191 char *p = s + len;
1193 while (*p && *p == ' ')
1194 p++;
1196 if (!*p || *p != '=')
1197 continue;
1199 p++;
1200 while (*p && isspace (*p))
1201 p++;
1203 s[len] = 0;
1204 if (new_param (cur_section, filename, lineno, s, p,
1205 config_params[m].type))
1206 goto fail;
1208 match = 1;
1209 break;
1213 if (!match)
1215 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1216 goto fail;
1219 break;
1223 if (cur_section)
1225 tmp = slist_append (tmpconfig, cur_section);
1226 if (!tmp)
1228 log_write ("%s", pwmd_strerror (ENOMEM));
1229 goto fail;
1232 cur_section = NULL;
1233 tmpconfig = tmp;
1236 if (!have_global)
1237 log_write (_
1238 ("WARNING: %s: could not find a [global] configuration section!"),
1239 filename);
1240 else
1242 int exists;
1243 char *tmp = config_get_string_param (tmpconfig, "global", "tls_dh_level",
1244 &exists);
1245 if (tmp)
1247 if (strcasecmp (tmp, "low") && strcasecmp (tmp, "medium")
1248 && strcasecmp (tmp, "high"))
1250 xfree (tmp);
1251 log_write (_("invalid tls_dh_level value"));
1252 goto fail;
1255 xfree (tmp);
1259 defaults:
1260 if (set_defaults (&tmpconfig))
1261 goto fail;
1263 if (fp)
1264 fclose(fp);
1266 return tmpconfig;
1268 fail:
1269 if (fp)
1270 fclose (fp);
1272 config_free (tmpconfig);
1273 free_section (cur_section);
1274 return NULL;
1277 static void
1278 free_section (struct config_section_s *s)
1280 if (!s)
1281 return;
1283 for (;;)
1285 struct config_param_s *p = slist_nth_data (s->params, 0);
1287 if (!p)
1288 break;
1290 section_remove_param (s, p->name);
1293 s->params = NULL;
1294 xfree (s->name);
1295 s->name = NULL;
1298 void
1299 config_free (struct slist_s *config)
1301 for (;;)
1303 struct config_section_s *s = slist_nth_data (config, 0);
1304 if (!s)
1305 break;
1307 free_section (s);
1308 config = slist_remove (config, s);
1309 xfree (s);