Fix potential mismatch of runtime configuration.
[pwmd.git] / src / rcfile.c
blob09fb4ce83b3355caa558999e72ce6cc987d30501
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>
32 #include <grp.h>
34 #include "pwmd-error.h"
35 #include <gcrypt.h>
36 #include "mutex.h"
37 #include "rcfile.h"
38 #include "util-misc.h"
39 #include "common.h"
40 #include "util-slist.h"
41 #include "util-string.h"
42 #include "mem.h"
44 #define DEFAULT_PINENTRY_TIMEOUT "30"
45 #define DEFAULT_CACHE_TIMEOUT "600"
46 #define DEFAULT_KEEPALIVE_INTERVAL "60"
47 #define DEFAULT_LOCK_TIMEOUT "50" // MUTEX_TRYLOCK in tenths of a second
49 #define INVALID_VALUE(file, line) do { \
50 if (file) \
51 log_write(_("%s(%i): invalid value for parameter."), file, line); \
52 } while (0);
54 enum
56 PARAM_INT, PARAM_CHARP, PARAM_LONG, PARAM_ULONGLONG, PARAM_CHARPP,
57 PARAM_BOOL, PARAM_INVALID
60 static struct config_params_s
62 char *name;
63 int type;
64 char *value;
65 } config_params[] = {
66 { "backup", PARAM_BOOL, "true"},
67 { "socket_path", PARAM_CHARP, NULL},
68 { "socket_perms", PARAM_CHARP, NULL},
69 { "passphrase", PARAM_CHARP, NULL},
70 { "passphrase_file", PARAM_CHARP, NULL},
71 { "gpg_agent_socket", PARAM_CHARP, NULL},
72 { "log_path", PARAM_CHARP, "~/.pwmd/log"},
73 { "enable_logging", PARAM_BOOL, "0"},
74 { "log_keepopen", PARAM_BOOL, "true"},
75 { "log_level", PARAM_INT, "0"},
76 { "disable_mlockall", PARAM_BOOL, "true"},
77 { "cache_timeout", PARAM_INT, DEFAULT_CACHE_TIMEOUT},
78 { "cache_push", PARAM_CHARPP, NULL},
79 { "disable_list_and_dump", PARAM_BOOL, "false"},
80 { "recursion_depth", PARAM_INT, "100"},
81 { "syslog", PARAM_BOOL, "false"},
82 { "xfer_progress", PARAM_INT, "8196"},
83 { "allowed", PARAM_CHARPP, NULL},
84 { "allowed_file", PARAM_CHARP, NULL},
85 { "keyparam", PARAM_CHARP, "(genkey (rsa (nbits 4:2048)))"},
86 { "cipher", PARAM_CHARP, "aes256"},
87 { "kill_scd", PARAM_BOOL, "false"},
88 { "cipher_iterations", PARAM_ULONGLONG, "0"},
89 { "cipher_progress", PARAM_LONG, DEFAULT_ITERATION_PROGRESS},
90 { "s2k_count", PARAM_ULONGLONG, "0"},
91 { "priority", PARAM_INT, INVALID_PRIORITY},
92 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
93 { "tcp_port", PARAM_INT, "6466"},
94 { "enable_tcp", PARAM_BOOL, "false"},
95 { "tcp_require_key", PARAM_BOOL, "false"},
96 { "tcp_wait", PARAM_INT, "0"},
97 { "tcp_bind", PARAM_CHARP, "any"},
98 { "tcp_interface", PARAM_CHARP, NULL},
99 { "tls_timeout", PARAM_INT, "300"},
100 { "tls_cipher_suite", PARAM_CHARP, "SECURE256:SECURE192:SECURE128:-VERS-SSL3.0"},
101 { "tls_dh_level", PARAM_CHARP, "medium"},
102 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
103 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
104 { "use_agent", PARAM_BOOL, "false"},
105 { "require_save_key", PARAM_BOOL, "true"},
106 { "invoking_user", PARAM_CHARPP, NULL},
107 { "invoking_file", PARAM_CHARP, NULL},
108 { "strict_kill", PARAM_BOOL, "false"},
109 { "lock_timeout", PARAM_INT, DEFAULT_LOCK_TIMEOUT},
110 { "send_state", PARAM_INT, "2"},
111 { NULL, PARAM_INVALID, NULL},
114 struct config_param_s
116 char *name;
117 int type;
118 union
120 int itype;
121 char *cptype;
122 char **cpptype;
123 long ltype;
124 long long lltype;
125 unsigned long ultype;
126 unsigned long long ulltype;
127 } value;
130 struct config_keep_s
132 char *section;
133 char *name;
134 char *value;
137 static struct config_section_s *config_find_section (struct slist_s *config,
138 const char *name);
139 static int new_param (struct config_section_s *section, const char *filename,
140 int lineno, const char *name, const char *value,
141 int type);
142 static void free_section (struct config_section_s *s);
143 static int set_defaults (struct slist_s **config, int reload);
145 static void
146 section_remove_param (struct config_section_s *section, const char *name)
148 unsigned i, t = slist_length (section->params);
150 for (i = 0; i < t; i++)
152 struct config_param_s *p = slist_nth_data (section->params, i);
154 if (!p)
155 continue;
157 if (!strcmp (p->name, name))
159 switch (p->type)
161 case PARAM_CHARP:
162 xfree (p->value.cptype);
163 break;
164 case PARAM_CHARPP:
165 strv_free (p->value.cpptype);
166 break;
169 section->params = slist_remove (section->params, p);
170 xfree (p->name);
171 xfree (p);
172 break;
177 void
178 config_clear_keys ()
180 MUTEX_LOCK (&rcfile_mutex);
181 unsigned i, t = slist_length (global_config);
183 for (i = 0; i < t; i++)
185 struct config_section_s *s = slist_nth_data (global_config, i);
186 if (!s)
187 continue;
189 section_remove_param (s, "passphrase");
192 MUTEX_UNLOCK (&rcfile_mutex);
195 static struct config_param_s *
196 config_has_param (struct config_section_s *s, const char *what)
198 unsigned i, t = slist_length (s->params);
200 for (i = 0; i < t; i++)
202 struct config_param_s *p = slist_nth_data (s->params, i);
203 if (!p)
204 break;
206 if (!strcmp (p->name, what))
207 return p;
210 return NULL;
213 static struct config_param_s *
214 config_get_param (struct slist_s *config,
215 const char *section, const char *what, int *exists)
217 unsigned i, t = slist_length (config);
219 *exists = 0;
221 for (i = 0; i < t; i++)
223 struct config_param_s *p;
224 struct config_section_s *s = slist_nth_data (config, i);
226 if (!s)
227 break;
229 if (strcmp (s->name, section))
230 continue;
232 p = config_has_param (s, what);
233 if (!p)
234 return NULL;
236 *exists = 1;
237 return p;
240 return NULL;
243 static struct config_section_s *
244 new_section (struct slist_s **config, const char *name)
246 struct slist_s *tmp;
247 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
249 if (!s)
250 return NULL;
252 s->name = str_dup (name);
253 if (!s->name)
255 log_write ("%s", pwmd_strerror (ENOMEM));
256 xfree (s);
257 return NULL;
260 tmp = slist_append (*config, s);
261 if (!tmp)
263 log_write ("%s", pwmd_strerror (ENOMEM));
264 xfree (s->name);
265 xfree (s);
266 return NULL;
269 *config = tmp;
270 return s;
274 config_set_string_param (struct slist_s **config, const char *section,
275 const char *name, const char *value)
277 struct config_section_s *s = config_find_section (*config, section);
279 if (!s)
281 s = new_section (config, section);
282 if (!s)
283 return 1;
286 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
289 char *
290 config_get_string_param (struct slist_s *config, const char *section,
291 const char *what, int *exists)
293 struct config_param_s *p = config_get_param (config, section, what, exists);
294 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
298 config_set_int_param (struct slist_s **config, const char *section,
299 const char *name, const char *value)
301 struct config_section_s *s = config_find_section (*config, section);
303 if (!s)
305 s = new_section (config, section);
306 if (!s)
307 return 1;
310 return new_param (s, NULL, 0, name, value, PARAM_INT);
314 config_get_int_param (struct slist_s *config, const char *section,
315 const char *what, int *exists)
317 struct config_param_s *p = config_get_param (config, section, what, exists);
318 return *exists ? p->value.itype : -1;
322 config_set_bool_param (struct slist_s **config, const char *section,
323 const char *name, const char *value)
325 struct config_section_s *s = config_find_section (*config, section);
327 if (!s)
329 s = new_section (config, section);
330 if (!s)
331 return 1;
334 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
338 config_get_bool_param (struct slist_s *config, const char *section,
339 const char *what, int *exists)
341 return config_get_int_param (config, section, what, exists);
345 config_set_long_param (struct slist_s **config, const char *section,
346 const char *name, const char *value)
348 struct config_section_s *s = config_find_section (*config, section);
350 if (!s)
352 s = new_section (config, section);
353 if (!s)
354 return 1;
357 return new_param (s, NULL, 0, name, value, PARAM_LONG);
360 long
361 config_get_long_param (struct slist_s *config, const char *section,
362 const char *what, int *exists)
364 struct config_param_s *p = config_get_param (config, section, what, exists);
365 return *exists ? p->value.ltype : -1;
369 config_set_ulonglong_param (struct slist_s **config, const char *section,
370 const char *name, const char *value)
372 struct config_section_s *s = config_find_section (*config, section);
374 if (!s)
376 s = new_section (config, section);
377 if (!s)
378 return 1;
381 return new_param (s, NULL, 0, name, value, PARAM_ULONGLONG);
384 unsigned long long
385 config_get_ulonglong_param (struct slist_s *config,
386 const char *section, const char *what, int *exists)
388 struct config_param_s *p = config_get_param (config, section, what, exists);
389 return *exists ? p->value.ulltype : -1;
393 config_set_list_param (struct slist_s **config, const char *section,
394 const char *name, const char *value)
396 struct config_section_s *s = config_find_section (*config, section);
398 if (!s)
400 s = new_section (config, section);
401 if (!s)
402 return 1;
405 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
408 char **
409 config_get_list_param (struct slist_s *config, const char *section,
410 const char *what, int *exists)
412 struct config_param_s *p = config_get_param (config, section, what, exists);
413 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
416 char *
417 config_get_string (const char *section, const char *what)
419 char *val = NULL;
420 const char *where = section ? section : "global";
421 int exists = 0;
423 MUTEX_LOCK (&rcfile_mutex);
424 val = config_get_string_param (global_config, where, what, &exists);
425 if (!exists && strcmp (section ? section : "", "global"))
426 val = config_get_string_param (global_config, "global", what, &exists);
428 MUTEX_UNLOCK (&rcfile_mutex);
429 return val;
432 char **
433 config_get_list (const char *section, const char *what)
435 char **val = NULL;
436 const char *where = section ? section : "global";
437 int exists = 0;
439 MUTEX_LOCK (&rcfile_mutex);
440 val = config_get_list_param (global_config, where, what, &exists);
441 if (!exists && strcmp (section ? section : "", "global"))
442 val = config_get_list_param (global_config, "global", what, &exists);
444 MUTEX_UNLOCK (&rcfile_mutex);
445 return val;
449 config_get_integer (const char *section, const char *what)
451 int val = 0;
452 const char *where = section ? section : "global";
453 int exists = 0;
455 MUTEX_LOCK (&rcfile_mutex);
456 val = config_get_int_param (global_config, where, what, &exists);
457 if (!exists && strcmp (section ? section : "", "global"))
458 val = config_get_int_param (global_config, "global", what, &exists);
460 MUTEX_UNLOCK (&rcfile_mutex);
461 return val;
464 unsigned long long
465 config_get_ulonglong (const char *section, const char *what)
467 unsigned long long val = 0;
468 const char *where = section ? section : "global";
469 int exists = 0;
471 MUTEX_LOCK (&rcfile_mutex);
472 val = config_get_ulonglong_param (global_config, where, what, &exists);
473 if (!exists && strcmp (section ? section : "", "global"))
474 val = config_get_ulonglong_param (global_config, "global", what, &exists);
476 MUTEX_UNLOCK (&rcfile_mutex);
477 return val;
480 long
481 config_get_long (const char *section, const char *what)
483 long val = 0;
484 const char *where = section ? section : "global";
485 int exists = 0;
487 MUTEX_LOCK (&rcfile_mutex);
488 val = config_get_long_param (global_config, where, what, &exists);
489 if (!exists && strcmp (section ? section : "", "global"))
490 val = config_get_long_param (global_config, "global", what, &exists);
492 MUTEX_UNLOCK (&rcfile_mutex);
493 return val;
497 config_get_boolean (const char *section, const char *what)
499 return config_get_integer (section, what);
502 char *
503 config_get_value (const char *section, const char *what)
505 const char *where = section ? section : "global";
506 int exists = 0;
507 int i;
508 int ival;
509 long lval;
510 unsigned long long ullval;
511 char *cpval;
512 char **cppval;
513 char *result = NULL;
515 MUTEX_LOCK (&rcfile_mutex);
517 for (i = 0; config_params[i].name; i++)
519 if (!strcmp (config_params[i].name, what))
521 switch (config_params[i].type)
523 case PARAM_BOOL:
524 case PARAM_INT:
525 ival = config_get_int_param (global_config, where, what,
526 &exists);
527 if (!exists && strcmp (section ? section : "", "global"))
528 ival = config_get_int_param (global_config, "global", what,
529 &exists);
530 result = str_asprintf ("%i", ival);
531 break;
532 case PARAM_CHARP:
533 cpval = config_get_string_param (global_config, where, what,
534 &exists);
535 if (!exists && strcmp (section ? section : "", "global"))
536 cpval =
537 config_get_string_param (global_config, "global", what,
538 &exists);
539 result = cpval;
540 break;
541 case PARAM_LONG:
542 lval = config_get_long_param (global_config, where, what,
543 &exists);
544 if (!exists && strcmp (section ? section : "", "global"))
545 lval = config_get_long_param (global_config, "global", what,
546 &exists);
547 result = str_asprintf ("%li", lval);
548 break;
549 case PARAM_ULONGLONG:
550 ullval = config_get_ulonglong_param (global_config, where, what,
551 &exists);
552 if (!exists && strcmp (section ? section : "", "global"))
553 ullval = config_get_ulonglong_param (global_config, "global",
554 what, &exists);
555 result = str_asprintf ("%llu", ullval);
556 break;
557 case PARAM_CHARPP:
558 cppval = config_get_list_param (global_config, where, what,
559 &exists);
560 if (!exists && strcmp (section ? section : "", "global"))
561 cppval = config_get_list_param (global_config, "global", what,
562 &exists);
564 if (cppval)
565 result = strv_join (",", cppval);
567 strv_free (cppval);
568 break;
573 MUTEX_UNLOCK (&rcfile_mutex);
574 return result;
577 /* 'file' is the list parameter file to load into the list parameter 'what'.
578 * The parsing of the parameter is not done here. */
579 static gpg_error_t
580 parse_list_file (struct slist_s *config, const char *section,
581 const char *file, const char *what)
583 FILE *fp;
584 char buf[LINE_MAX];
585 int exists;
586 char **list = NULL;
587 char *tmp;
588 char *p = config_get_string_param (config, section, file, &exists);
589 gpg_error_t rc;
591 if (!p || !*p)
593 xfree (p);
594 return 0;
597 tmp = expand_homedir (p);
598 xfree (p);
599 p = tmp;
600 fp = fopen (p, "r");
601 if (!fp)
603 rc = gpg_error_from_errno (errno);
604 log_write ("%s: %s", p, pwmd_strerror (rc));
605 xfree (p);
606 return rc;
609 xfree (p);
610 list = config_get_list_param (config, section, what, &exists);
611 if (!list && exists)
613 fclose (fp);
614 log_write ("%s", pwmd_strerror (ENOMEM));
615 return gpg_error (ENOMEM);
618 while ((p = fgets (buf, sizeof (buf), fp)))
620 char **pp = NULL;
622 if (!*p || *p == ';')
623 continue;
625 if (p[strlen(p)-1] == '\n')
626 p[strlen(p)-1] = 0;
628 while (*p && isspace (*p))
629 p++;
631 if (!*p)
632 continue;
634 tmp = str_dup (p);
635 if (tmp)
636 pp = strv_cat (list, str_dup (p));
638 if (!pp || !tmp)
640 xfree (tmp);
641 strv_free (list);
642 fclose (fp);
643 log_write ("%s", strerror (ENOMEM));
644 return gpg_error (ENOMEM);
647 xfree (tmp);
648 list = pp;
651 fclose(fp);
652 if (!list)
653 return 0;
655 p = strv_join (",", list);
656 strv_free (list);
658 if (!p)
660 log_write ("%s", pwmd_strerror (ENOMEM));
661 return gpg_error (ENOMEM);
664 config_set_list_param (&config, section, what, p);
665 xfree (p);
666 return 0;
669 static int
670 fixup_allowed_once (struct slist_s **config, const char *section)
672 char **list, **pp, *p;
673 int exists;
674 gpg_error_t rc;
676 rc = parse_list_file (*config, section, "allowed_file", "allowed");
677 if (rc)
678 return 1;
680 list = config_get_list_param (*config, section, "allowed", &exists);
681 for (pp = list; pp && *pp; pp++)
683 if (*(*pp) == '#')
685 for (p = *pp; p && *p; p++)
686 *p = toupper(*p);
690 strv_free (list);
691 if (!exists)
693 if (!strcmp (section, "global"))
695 p = get_username (getuid());
697 if (config_set_list_param (config, section, "allowed", p))
699 xfree (p);
700 return 1;
703 xfree (p);
705 else
707 list = config_get_list_param (*config, "global", "allowed", &exists);
708 if (list)
710 p = strv_join (",", list);
711 strv_free (list);
712 if (config_set_list_param (config, section, "allowed", p))
714 xfree (p);
715 return 1;
718 xfree (p);
723 return 0;
726 static int
727 fixup_allowed (struct slist_s **config)
729 int n, t = slist_length (*config);
731 for (n = 0; n < t; n++)
733 struct config_section_s *section;
735 section = slist_nth_data (*config, n);
736 if (fixup_allowed_once (config, section->name))
737 return 1;
740 return 0;
743 static int
744 add_invoking_user (struct invoking_user_s **users, char *id,
745 struct slist_s **config)
747 struct passwd *pwd = NULL;
748 struct group *grp = NULL;
749 struct invoking_user_s *user, *p;
750 int not = 0;
752 if (id && (*id == '!' || *id == '-'))
754 not = 1;
755 id++;
758 errno = 0;
759 if (!id || !*id)
761 pwd = getpwuid (getuid ());
762 if (!pwd)
764 log_write (_("could not set any invoking user: %s"),
765 pwmd_strerror (errno));
766 return 1;
769 else if (*id == '@')
771 grp = getgrnam (id+1);
772 if (!grp)
774 log_write (_("could not parse group '%s': %s"), id+1,
775 pwmd_strerror (errno));
776 return 1;
779 else if (*id != '#')
780 pwd = getpwnam (id);
782 if (!grp && !pwd && id && *id != '#')
784 if (id && *id)
785 log_write (_("could not set invoking user '%s': %s"), id,
786 pwmd_strerror (errno));
787 else
788 log_write (_("could not set any invoking user!"));
790 return 1;
793 user = xcalloc (1, sizeof (struct invoking_user_s));
794 if (!user)
796 log_write ("%s", pwmd_strerror (ENOMEM));
797 return 1;
800 user->not = not;
801 user->type = pwd ? INVOKING_UID : grp ? INVOKING_GID : INVOKING_TLS;
802 if (pwd)
803 user->uid = pwd->pw_uid;
804 else if (grp)
805 user->id = str_dup (id+1);
806 else
808 char *s;
810 for (s = id; s && *s; s++)
811 *s = toupper(*s);
813 user->id = str_dup (id+1);
816 /* Set the default invoking_user since it doesn't exist. */
817 if (!id || !*id)
818 config_set_list_param (config, "global", "invoking_user", pwd->pw_name);
820 if (!*users)
822 *users = user;
823 return 0;
826 for (p = *users; p; p = p->next)
828 if (!p->next)
830 p->next = user;
831 break;
835 return 0;
838 static int
839 parse_invoking_users (struct slist_s **config)
841 struct invoking_user_s *users = NULL;
842 int exists;
843 char **list, **l;
845 if (parse_list_file (*config, "global", "invoking_file", "invoking_user"))
846 return 1;
848 list = config_get_list_param(*config, "global", "invoking_user", &exists);
849 for (l = list; l && *l; l++)
851 if (add_invoking_user (&users, *l, config))
853 strv_free (list);
854 free_invoking_users (users);
855 return 1;
859 if (!list || !*list)
861 if (add_invoking_user (&users, NULL, config))
863 strv_free (list);
864 return 1;
867 strv_free (list);
868 list = config_get_list_param(*config, "global", "invoking_user", &exists);
871 free_invoking_users (invoking_users);
872 invoking_users = users;
873 return 0;
876 static int
877 set_defaults (struct slist_s **config, int reload)
879 char *s = NULL, *tmp;
880 char **list;
881 int exists;
882 int i;
884 for (i = 0; config_params[i].name; i++)
886 switch (config_params[i].type)
888 case PARAM_BOOL:
889 config_get_bool_param (*config, "global", config_params[i].name,
890 &exists);
891 if (!exists)
893 if (config_set_bool_param
894 (config, "global", config_params[i].name,
895 config_params[i].value))
896 goto fail;
898 break;
899 case PARAM_INT:
900 config_get_int_param (*config, "global", config_params[i].name,
901 &exists);
902 if (!exists)
904 if (config_set_int_param
905 (config, "global", config_params[i].name,
906 config_params[i].value))
907 goto fail;
909 break;
910 case PARAM_CHARP:
911 s = config_get_string_param (*config, "global",
912 config_params[i].name, &exists);
913 xfree (s);
914 if (!exists && config_params[i].value)
916 if (config_set_string_param (config, "global",
917 config_params[i].name,
918 config_params[i].value))
919 goto fail;
921 break;
922 case PARAM_CHARPP:
923 list = config_get_list_param (*config, "global",
924 config_params[i].name, &exists);
925 strv_free (list);
926 if (!exists && config_params[i].value)
928 if (config_set_list_param (config, "global",
929 config_params[i].name,
930 config_params[i].value))
931 goto fail;
933 break;
934 case PARAM_LONG:
935 config_get_long_param (*config, "global", config_params[i].name,
936 &exists);
937 if (!exists)
939 if (config_set_long_param
940 (config, "global", config_params[i].name,
941 config_params[i].value))
942 goto fail;
944 break;
945 case PARAM_ULONGLONG:
946 config_get_ulonglong_param (*config, "global", config_params[i].name,
947 &exists);
948 if (!exists)
950 if (config_set_ulonglong_param (config, "global",
951 config_params[i].name,
952 config_params[i].value))
953 goto fail;
955 break;
959 s = NULL;
960 if (!reload && fixup_allowed (config))
961 goto fail;
963 if (!reload && parse_invoking_users (config))
964 goto fail;
966 s = config_get_string_param(*config, "global", "gpg_agent_socket", &exists);
967 if (!s || !*s)
969 xfree (s);
970 s = str_asprintf ("%s/.gnupg/S.gpg-agent", get_home_dir());
971 config_set_string_param(config, "global", "gpg_agent_socket", s);
973 else
975 tmp = expand_homedir (s);
976 config_set_string_param(config, "global", "gpg_agent_socket", tmp);
977 xfree (tmp);
980 log_level = config_get_int_param (*config, "global",
981 "log_level", &exists);
982 log_keepopen = config_get_int_param (*config, "global",
983 "log_keepopen", &exists);
984 max_recursion_depth = config_get_int_param (*config, "global",
985 "recursion_depth", &exists);
986 disable_list_and_dump = config_get_bool_param (*config, "global",
987 "disable_list_and_dump",
988 &exists);
989 #ifdef HAVE_MLOCKALL
990 disable_mlock =
991 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
992 #endif
994 xfree (s);
995 return 0;
997 fail:
998 xfree (s);
999 return 1;
1002 static struct config_section_s *
1003 config_find_section (struct slist_s *config, const char *name)
1005 unsigned i, t = slist_length (config);
1007 for (i = 0; i < t; i++)
1009 struct config_section_s *s = slist_nth_data (config, i);
1011 if (!strcmp (s->name, name))
1012 return s;
1015 return NULL;
1018 /* Append a new parameter to the list of parameters for a file
1019 * section. When an existing parameter of the same name exists, its
1020 * value is updated.
1022 static int
1023 new_param (struct config_section_s *section, const char *filename, int lineno,
1024 const char *name, const char *value, int type)
1026 struct config_param_s *param = NULL;
1027 struct slist_s *tmp;
1028 char *e;
1029 unsigned i, t = slist_length (section->params);
1030 int dup = 0;
1032 for (i = 0; i < t; i++)
1034 struct config_param_s *p = slist_nth_data (section->params, i);
1035 if (!p)
1036 break;
1038 if (!strcmp (name, p->name))
1040 param = p;
1041 dup = 1;
1042 break;
1046 if (!param)
1048 param = xcalloc (1, sizeof (struct config_param_s));
1049 if (!param)
1051 log_write ("%s", pwmd_strerror (ENOMEM));
1052 return 1;
1055 param->name = str_dup (name);
1056 if (!param->name)
1058 xfree (param);
1059 log_write ("%s", pwmd_strerror (ENOMEM));
1060 return 1;
1064 param->type = type;
1066 switch (type)
1068 case PARAM_BOOL:
1069 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1070 || !strcasecmp (value, "false"))
1071 param->value.itype = 0;
1072 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1073 || !strcasecmp (value, "true"))
1074 param->value.itype = 1;
1075 else
1077 INVALID_VALUE (filename, lineno);
1078 goto fail;
1080 param->type = PARAM_INT;
1081 break;
1082 case PARAM_CHARP:
1083 xfree (param->value.cptype);
1084 param->value.cptype = NULL;
1085 param->value.cptype = value && *value ? str_dup (value) : NULL;
1086 if (value && *value && !param->value.cptype)
1088 log_write ("%s", pwmd_strerror (ENOMEM));
1089 goto fail;
1091 break;
1092 case PARAM_CHARPP:
1093 strv_free (param->value.cpptype);
1094 param->value.cpptype = NULL;
1095 param->value.cpptype = value && *value ?
1096 str_split_ws (value, ",", 0) : NULL;
1097 if (value && *value && !param->value.cpptype)
1099 log_write ("%s", pwmd_strerror (ENOMEM));
1100 goto fail;
1102 break;
1103 case PARAM_INT:
1104 param->value.itype = strtol (value, &e, 10);
1105 if (e && *e)
1107 INVALID_VALUE (filename, lineno);
1108 goto fail;
1110 break;
1111 case PARAM_LONG:
1112 param->value.ltype = strtol (value, &e, 10);
1113 if (e && *e)
1115 INVALID_VALUE (filename, lineno);
1116 goto fail;
1118 break;
1119 case PARAM_ULONGLONG:
1120 param->value.ulltype = strtoll (value, &e, 10);
1121 if (e && *e)
1123 INVALID_VALUE (filename, lineno);
1124 goto fail;
1126 break;
1129 if (dup)
1130 return 0;
1132 tmp = slist_append (section->params, param);
1133 if (!tmp)
1135 log_write ("%s", pwmd_strerror (ENOMEM));
1136 goto fail;
1139 section->params = tmp;
1140 return 0;
1142 fail:
1143 xfree (param->name);
1144 xfree (param);
1145 return 1;
1148 struct slist_s *
1149 config_parse (const char *filename, int reload)
1151 struct slist_s *tmpconfig = NULL, *tmp;
1152 struct config_section_s *cur_section = NULL;
1153 char buf[LINE_MAX];
1154 char *s;
1155 int lineno = 1;
1156 int have_global = 0;
1157 FILE *fp = fopen (filename, "r");
1159 if (!fp)
1161 log_write ("%s: %s", filename,
1162 pwmd_strerror (gpg_error_from_errno (errno)));
1164 if (errno != ENOENT)
1165 return NULL;
1167 log_write (_("Using defaults!"));
1168 goto defaults;
1171 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
1173 char line[LINE_MAX] = { 0 };
1174 size_t len = 0;
1176 if (*s == '#')
1177 continue;
1179 s = str_chomp (s);
1180 for (; s && *s; s++)
1182 int match = 0;
1184 /* New file section. */
1185 if (*s == '[')
1187 struct config_section_s *section;
1188 char *p = strchr (++s, ']');
1190 if (!p)
1192 log_write (_("%s(%i): unbalanced braces"), filename,
1193 lineno);
1194 goto fail;
1197 len = strlen (s) - strlen (p);
1198 memcpy (line, s, len);
1199 line[len] = 0;
1201 section = config_find_section (tmpconfig, line);
1202 if (section)
1204 log_write (_("%s(%i): section '%s' already exists!"),
1205 filename, lineno, line);
1206 goto fail;
1209 if (!strcmp (line, "global"))
1210 have_global = 1;
1212 section = xcalloc (1, sizeof (struct config_section_s));
1213 section->name = str_dup (line);
1215 if (cur_section)
1217 tmp = slist_append (tmpconfig, cur_section);
1218 if (!tmp)
1220 log_write ("%s", pwmd_strerror (ENOMEM));
1221 goto fail;
1224 tmpconfig = tmp;
1227 cur_section = section;
1228 break;
1231 if (!cur_section)
1233 log_write (_("%s(%i): parameter outside of section!"), filename,
1234 lineno);
1235 goto fail;
1238 /* Parameters for each section. */
1239 for (int m = 0; config_params[m].name; m++)
1241 size_t len = strlen (config_params[m].name);
1243 if (!strncmp (s, config_params[m].name, len))
1245 char *p = s + len;
1247 while (*p && *p == ' ')
1248 p++;
1250 if (!*p || *p != '=')
1251 continue;
1253 p++;
1254 while (*p && isspace (*p))
1255 p++;
1257 s[len] = 0;
1258 if (new_param (cur_section, filename, lineno, s, p,
1259 config_params[m].type))
1260 goto fail;
1262 match = 1;
1263 break;
1267 if (!match)
1269 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1270 goto fail;
1273 break;
1277 if (cur_section)
1279 tmp = slist_append (tmpconfig, cur_section);
1280 if (!tmp)
1282 log_write ("%s", pwmd_strerror (ENOMEM));
1283 goto fail;
1286 cur_section = NULL;
1287 tmpconfig = tmp;
1290 if (!have_global)
1291 log_write (_
1292 ("WARNING: %s: could not find a [global] configuration section!"),
1293 filename);
1294 else
1296 int exists;
1297 char *tmp = config_get_string_param (tmpconfig, "global", "tls_dh_level",
1298 &exists);
1299 if (tmp)
1301 if (strcasecmp (tmp, "low") && strcasecmp (tmp, "medium")
1302 && strcasecmp (tmp, "high"))
1304 xfree (tmp);
1305 log_write (_("invalid tls_dh_level value"));
1306 goto fail;
1309 xfree (tmp);
1313 defaults:
1314 if (set_defaults (&tmpconfig, reload))
1315 goto fail;
1317 if (fp)
1318 fclose(fp);
1320 return tmpconfig;
1322 fail:
1323 if (fp)
1324 fclose (fp);
1326 config_free (tmpconfig);
1327 free_section (cur_section);
1328 return NULL;
1331 static void
1332 free_section (struct config_section_s *s)
1334 if (!s)
1335 return;
1337 for (;;)
1339 struct config_param_s *p = slist_nth_data (s->params, 0);
1341 if (!p)
1342 break;
1344 section_remove_param (s, p->name);
1347 s->params = NULL;
1348 xfree (s->name);
1349 s->name = NULL;
1352 void
1353 config_free (struct slist_s *config)
1355 for (;;)
1357 struct config_section_s *s = slist_nth_data (config, 0);
1358 if (!s)
1359 break;
1361 free_section (s);
1362 config = slist_remove (config, s);
1363 xfree (s);
1367 void
1368 free_invoking_users (struct invoking_user_s *users)
1370 struct invoking_user_s *p;
1372 for (p = users; p;)
1374 struct invoking_user_s *next = p->next;
1376 if (p->type == INVOKING_TLS || p->type == INVOKING_GID)
1377 xfree (p->id);
1379 xfree (p);
1380 p = next;
1384 static int
1385 param_type (const char *name)
1387 int i;
1389 for (i = 0; config_params[i].name; i++)
1391 if (!strcmp (config_params[i].name, name))
1392 return config_params[i].type;
1395 return PARAM_INVALID;
1398 static int
1399 keep_parse (struct config_keep_s *k, const char *section, const char *key)
1401 int exists;
1402 int ival;
1403 long lval;
1404 unsigned long long ullval;
1405 char *cpval;
1406 char **cppval;
1407 int type = param_type (key);
1408 void *value = NULL;
1410 switch (type)
1412 case PARAM_BOOL:
1413 case PARAM_INT:
1414 ival = config_get_int_param (global_config, section, key, &exists);
1415 if (exists)
1416 value = str_asprintf ("%i", ival);
1417 break;
1418 case PARAM_LONG:
1419 lval = config_get_long_param (global_config, section, key, &exists);
1420 if (exists)
1421 value = str_asprintf ("%li", lval);
1422 break;
1423 case PARAM_ULONGLONG:
1424 ullval = config_get_ulonglong_param (global_config, section, key,
1425 &exists);
1426 if (exists)
1427 value = str_asprintf ("%llu", ullval);
1428 break;
1429 case PARAM_CHARP:
1430 cpval = config_get_string_param (global_config, section, key, &exists);
1431 if (exists)
1432 value = cpval;
1433 break;
1434 case PARAM_CHARPP:
1435 cppval = config_get_list_param (global_config, section, key, &exists);
1436 if (exists)
1438 char *s = strv_join (",", cppval);
1440 strv_free (cppval);
1441 value = s;
1443 break;
1444 default:
1445 return 1;
1448 if (!value)
1449 return 1;
1451 k->section = str_dup(section);
1452 k->name = str_dup(key);
1453 k->value = value;
1454 return 0;
1457 static struct slist_s *
1458 keep_add (struct slist_s *k, const char *s, const char *key)
1460 int n, t = slist_length (global_config);
1462 for (n = 0; n < t; n++)
1464 struct config_section_s *section;
1465 struct config_keep_s *tmp;
1466 int ret;
1468 section = slist_nth_data (global_config, n);
1469 tmp = xcalloc (1, sizeof(struct config_keep_s));
1471 // Process all sections.
1472 if (!s)
1473 ret = keep_parse (tmp, section->name, key);
1474 else
1475 ret = keep_parse (tmp, s, key);
1477 if (!ret)
1478 k = slist_append (k, tmp);
1479 else
1480 xfree (tmp);
1483 return k;
1486 /* Keep security sensitive settings across SIGHUP. */
1487 struct slist_s *
1488 config_keep_save ()
1490 struct slist_s *keep = NULL;
1492 #ifdef WITH_GNUTLS
1493 keep = keep_add (keep, NULL, "tcp_require_key");
1494 #endif
1495 keep = keep_add (keep, NULL, "require_save_key");
1496 keep = keep_add (keep, NULL, "allowed");
1497 keep = keep_add (keep, "global", "invoking_user");
1498 return keep;
1501 /* Restore parameters previously saved with config_keep_save(). This will also
1502 * free the 'keep'.
1504 void
1505 config_keep_restore (struct slist_s *keep)
1507 int n, t = slist_length (keep);
1509 for (n = 0; n < t; n++)
1511 struct config_keep_s *k = slist_nth_data (keep, n);
1512 int type = param_type (k->name);
1514 switch (type)
1516 case PARAM_BOOL:
1517 config_set_bool_param (&global_config, k->section, k->name, k->value);
1518 break;
1519 case PARAM_INT:
1520 config_set_int_param (&global_config, k->section, k->name, k->value);
1521 break;
1522 case PARAM_LONG:
1523 config_set_long_param (&global_config, k->section, k->name, k->value);
1524 break;
1525 case PARAM_ULONGLONG:
1526 config_set_ulonglong_param (&global_config, k->section, k->name,
1527 k->value);
1528 break;
1529 case PARAM_CHARP:
1530 config_set_string_param (&global_config, k->section, k->name,
1531 k->value);
1532 break;
1533 case PARAM_CHARPP:
1534 config_set_list_param (&global_config, k->section, k->name, k->value);
1535 break;
1536 default:
1537 break;
1540 xfree (k->section);
1541 xfree (k->name);
1542 xfree (k->value);
1545 slist_free (keep);