Use pthread_sigmask().
[pwmd.git] / src / rcfile.c
blob589755f984dc34af694e35d9f28b172c65df0fde
1 /*
2 Copyright (C) 2006-2023 Ben Kibbey <bjk@luxsci.net>
4 This file is part of pwmd.
6 Pwmd is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 Pwmd is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <ctype.h>
29 #include <pwd.h>
30 #include <grp.h>
32 #include "pwmd-error.h"
33 #include "mutex.h"
34 #include "rcfile.h"
35 #include "util-misc.h"
36 #include "common.h"
37 #include "util-slist.h"
38 #include "util-string.h"
39 #include "mem.h"
41 #ifdef HAVE_MLOCKALL
42 int disable_mlock;
43 #endif
44 char *logfile;
45 char *rcfile;
46 char *homedir;
47 int max_recursion_depth;
48 int disable_list_and_dump;
49 struct slist_s *global_config;
50 int log_syslog;
51 pthread_mutex_t rcfile_mutex;
52 pthread_cond_t rcfile_cond;
53 pthread_t rcfile_tid;
54 struct invoking_user_s *invoking_users;
55 int log_keepopen;
56 int log_level;
58 #define DEFAULT_CACHE_TIMEOUT "600"
59 #define DEFAULT_KEEPALIVE_INTERVAL "60"
60 #define DEFAULT_LOCK_TIMEOUT "50" // MUTEX_TRYLOCK in tenths of a second
61 #define DEFAULT_BACKLOG "128"
62 #define DEFAULT_CIPHER_PRIORITY "SECURE256:SECURE192:SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-AES-128-CBC:-AES-256-CBC"
64 #define INVALID_VALUE(file, line) do { \
65 if (file) \
66 log_write(_("%s(%i): invalid value for parameter."), file, line); \
67 } while (0);
69 enum
71 PARAM_INT, PARAM_CHARP, PARAM_LONG, PARAM_LONGLONG, PARAM_CHARPP,
72 PARAM_BOOL, PARAM_INVALID
75 static struct config_params_s
77 const char *name;
78 int type;
79 const char *value;
80 } config_params[] = {
81 { "backup", PARAM_BOOL, "true"},
82 { "socket_path", PARAM_CHARP, NULL},
83 { "socket_perms", PARAM_CHARP, NULL},
84 { "backlog", PARAM_INT, DEFAULT_BACKLOG},
85 { "passphrase_file", PARAM_CHARP, NULL},
86 { "log_path", PARAM_CHARP, "~/.pwmd/log"},
87 { "enable_logging", PARAM_BOOL, "0"},
88 { "log_keepopen", PARAM_BOOL, "true"},
89 { "log_level", PARAM_INT, "0"},
90 { "disable_mlockall", PARAM_BOOL, "true"},
91 { "cache_timeout", PARAM_LONG, DEFAULT_CACHE_TIMEOUT},
92 { "cache_push", PARAM_CHARPP, NULL},
93 { "disable_list_and_dump", PARAM_BOOL, "false"},
94 { "recursion_depth", PARAM_INT, "100"},
95 { "syslog", PARAM_BOOL, "false"},
96 { "allowed", PARAM_CHARPP, NULL},
97 { "allowed_file", PARAM_CHARP, NULL},
98 { "priority", PARAM_INT, INVALID_PRIORITY},
99 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
100 { "tcp_port", PARAM_INT, "6466"},
101 { "enable_tcp", PARAM_BOOL, "false"},
102 { "tcp_require_key", PARAM_BOOL, "false"},
103 { "tcp_bind", PARAM_CHARP, "any"},
104 { "tcp_interface", PARAM_CHARP, NULL},
105 { "tls_timeout", PARAM_INT, "300"},
106 { "tls_cipher_suite", PARAM_CHARP, DEFAULT_CIPHER_PRIORITY},
107 { "tls_dh_params_file", PARAM_CHARP, NULL},
108 { "tls_use_crl", PARAM_BOOL, "false"},
109 { "tls_crl_file", PARAM_CHARP, NULL},
110 { "tls_ca_file", PARAM_CHARP, NULL},
111 { "tls_server_cert_file", PARAM_CHARP, NULL},
112 { "tls_server_key_file", PARAM_CHARP, NULL},
113 { "require_save_key", PARAM_BOOL, "true"},
114 { "invoking_user", PARAM_CHARPP, NULL},
115 { "invoking_file", PARAM_CHARP, NULL},
116 { "encrypt_to", PARAM_BOOL, "false"},
117 { "always_trust", PARAM_BOOL, "false"},
118 { "gpg_homedir", PARAM_CHARP, NULL},
119 { "strict_kill", PARAM_BOOL, "false"},
120 { "lock_timeout", PARAM_LONG, DEFAULT_LOCK_TIMEOUT},
121 { "kill_scd", PARAM_BOOL, "false"},
122 { "strict_open", PARAM_BOOL, "false"},
123 { NULL, PARAM_INVALID, NULL},
126 struct config_param_s
128 char *name;
129 int type;
130 union
132 int itype;
133 char *cptype;
134 char **cpptype;
135 long ltype;
136 long long lltype;
137 } value;
140 struct config_keep_s
142 char *section;
143 char *name;
144 char *value;
147 static struct config_section_s *config_find_section (struct slist_s *config,
148 const char *name);
149 static int new_param (struct config_section_s *section, const char *filename,
150 int lineno, const char *name, const char *value,
151 int type);
152 static void free_section (struct config_section_s *s);
153 static int set_defaults (struct slist_s **config, int reload);
155 static void
156 section_remove_param (struct config_section_s *section, const char *name)
158 unsigned i, t = slist_length (section->params);
160 for (i = 0; i < t; i++)
162 struct config_param_s *p = slist_nth_data (section->params, i);
164 if (!p)
165 continue;
167 if (!strcmp (p->name, name))
169 switch (p->type)
171 case PARAM_CHARP:
172 xfree (p->value.cptype);
173 break;
174 case PARAM_CHARPP:
175 strv_free (p->value.cpptype);
176 break;
179 section->params = slist_remove (section->params, p);
180 xfree (p->name);
181 xfree (p);
182 break;
187 static struct config_param_s *
188 config_has_param (struct config_section_s *s, const char *what)
190 unsigned i, t = slist_length (s->params);
192 for (i = 0; i < t; i++)
194 struct config_param_s *p = slist_nth_data (s->params, i);
195 if (!p)
196 break;
198 if (!strcmp (p->name, what))
199 return p;
202 return NULL;
205 static struct config_param_s *
206 config_get_param (struct slist_s *config,
207 const char *section, const char *what, int *exists)
209 unsigned i, t = slist_length (config);
211 *exists = 0;
213 for (i = 0; i < t; i++)
215 struct config_param_s *p;
216 struct config_section_s *s = slist_nth_data (config, i);
218 if (!s)
219 break;
221 if (strcmp (s->name, section))
222 continue;
224 p = config_has_param (s, what);
225 if (!p)
226 return NULL;
228 *exists = 1;
229 return p;
232 return NULL;
235 static struct config_section_s *
236 new_section (struct slist_s **config, const char *name)
238 struct slist_s *tmp;
239 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
241 if (!s)
242 return NULL;
244 s->name = str_dup (name);
245 if (!s->name)
247 log_write ("%s", pwmd_strerror (ENOMEM));
248 xfree (s);
249 return NULL;
252 tmp = slist_append (*config, s);
253 if (!tmp)
255 log_write ("%s", pwmd_strerror (ENOMEM));
256 xfree (s->name);
257 xfree (s);
258 return NULL;
261 *config = tmp;
262 return s;
266 config_set_string_param (struct slist_s **config, const char *section,
267 const char *name, const char *value)
269 struct config_section_s *s = config_find_section (*config, section);
271 if (!s)
273 s = new_section (config, section);
274 if (!s)
275 return 1;
278 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
281 char *
282 config_get_string_param (struct slist_s *config, const char *section,
283 const char *what, int *exists)
285 struct config_param_s *p = config_get_param (config, section, what, exists);
286 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
290 config_set_int_param (struct slist_s **config, const char *section,
291 const char *name, const char *value)
293 struct config_section_s *s = config_find_section (*config, section);
295 if (!s)
297 s = new_section (config, section);
298 if (!s)
299 return 1;
302 return new_param (s, NULL, 0, name, value, PARAM_INT);
306 config_get_int_param (struct slist_s *config, const char *section,
307 const char *what, int *exists)
309 struct config_param_s *p = config_get_param (config, section, what, exists);
310 return *exists ? p->value.itype : -1;
314 config_set_bool_param (struct slist_s **config, const char *section,
315 const char *name, const char *value)
317 struct config_section_s *s = config_find_section (*config, section);
319 if (!s)
321 s = new_section (config, section);
322 if (!s)
323 return 1;
326 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
330 config_get_bool_param (struct slist_s *config, const char *section,
331 const char *what, int *exists)
333 return config_get_int_param (config, section, what, exists);
337 config_set_long_param (struct slist_s **config, const char *section,
338 const char *name, const char *value)
340 struct config_section_s *s = config_find_section (*config, section);
342 if (!s)
344 s = new_section (config, section);
345 if (!s)
346 return 1;
349 return new_param (s, NULL, 0, name, value, PARAM_LONG);
352 long
353 config_get_long_param (struct slist_s *config, const char *section,
354 const char *what, int *exists)
356 struct config_param_s *p = config_get_param (config, section, what, exists);
357 return *exists ? p->value.ltype : -1;
361 config_set_longlong_param (struct slist_s **config, const char *section,
362 const char *name, const char *value)
364 struct config_section_s *s = config_find_section (*config, section);
366 if (!s)
368 s = new_section (config, section);
369 if (!s)
370 return 1;
373 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
376 long long
377 config_get_longlong_param (struct slist_s *config,
378 const char *section, const char *what, int *exists)
380 struct config_param_s *p = config_get_param (config, section, what, exists);
381 return *exists ? p->value.lltype : -1;
385 config_set_list_param (struct slist_s **config, const char *section,
386 const char *name, const char *value)
388 struct config_section_s *s = config_find_section (*config, section);
390 if (!s)
392 s = new_section (config, section);
393 if (!s)
394 return 1;
397 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
400 char **
401 config_get_list_param (struct slist_s *config, const char *section,
402 const char *what, int *exists)
404 struct config_param_s *p = config_get_param (config, section, what, exists);
405 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
408 char *
409 config_get_string (const char *section, const char *what)
411 char *val = NULL;
412 const char *where = section ? section : "global";
413 int exists = 0;
415 MUTEX_LOCK (&rcfile_mutex);
416 val = config_get_string_param (global_config, where, what, &exists);
417 if (!exists && strcmp (section ? section : "", "global"))
418 val = config_get_string_param (global_config, "global", what, &exists);
420 MUTEX_UNLOCK (&rcfile_mutex);
421 return val;
424 char **
425 config_get_list (const char *section, const char *what)
427 char **val = NULL;
428 const char *where = section ? section : "global";
429 int exists = 0;
431 MUTEX_LOCK (&rcfile_mutex);
432 val = config_get_list_param (global_config, where, what, &exists);
433 if (!exists && strcmp (section ? section : "", "global"))
434 val = config_get_list_param (global_config, "global", what, &exists);
436 MUTEX_UNLOCK (&rcfile_mutex);
437 return val;
441 config_get_integer (const char *section, const char *what)
443 int val = 0;
444 const char *where = section ? section : "global";
445 int exists = 0;
447 MUTEX_LOCK (&rcfile_mutex);
448 val = config_get_int_param (global_config, where, what, &exists);
449 if (!exists && strcmp (section ? section : "", "global"))
450 val = config_get_int_param (global_config, "global", what, &exists);
452 MUTEX_UNLOCK (&rcfile_mutex);
453 return val;
456 long long
457 config_get_longlong (const char *section, const char *what)
459 long long val = 0;
460 const char *where = section ? section : "global";
461 int exists = 0;
463 MUTEX_LOCK (&rcfile_mutex);
464 val = config_get_longlong_param (global_config, where, what, &exists);
465 if (!exists && strcmp (section ? section : "", "global"))
466 val = config_get_longlong_param (global_config, "global", what, &exists);
468 MUTEX_UNLOCK (&rcfile_mutex);
469 return val;
472 long
473 config_get_long (const char *section, const char *what)
475 long val = 0;
476 const char *where = section ? section : "global";
477 int exists = 0;
479 MUTEX_LOCK (&rcfile_mutex);
480 val = config_get_long_param (global_config, where, what, &exists);
481 if (!exists && strcmp (section ? section : "", "global"))
482 val = config_get_long_param (global_config, "global", what, &exists);
484 MUTEX_UNLOCK (&rcfile_mutex);
485 return val;
489 config_get_boolean (const char *section, const char *what)
491 return config_get_integer (section, what);
494 char *
495 config_get_value (const char *section, const char *what)
497 const char *where = section ? section : "global";
498 int exists = 0;
499 int i;
500 int ival;
501 long lval;
502 long long llval;
503 char *cpval;
504 char **cppval;
505 char *result = NULL;
507 MUTEX_LOCK (&rcfile_mutex);
509 for (i = 0; config_params[i].name; i++)
511 if (!strcmp (config_params[i].name, what))
513 switch (config_params[i].type)
515 case PARAM_BOOL:
516 case PARAM_INT:
517 ival = config_get_int_param (global_config, where, what,
518 &exists);
519 if (!exists && strcmp (section ? section : "", "global"))
520 ival = config_get_int_param (global_config, "global", what,
521 &exists);
522 result = str_asprintf ("%i", ival);
523 break;
524 case PARAM_CHARP:
525 cpval = config_get_string_param (global_config, where, what,
526 &exists);
527 if (!exists && strcmp (section ? section : "", "global"))
528 cpval =
529 config_get_string_param (global_config, "global", what,
530 &exists);
531 result = cpval;
532 break;
533 case PARAM_LONG:
534 lval = config_get_long_param (global_config, where, what,
535 &exists);
536 if (!exists && strcmp (section ? section : "", "global"))
537 lval = config_get_long_param (global_config, "global", what,
538 &exists);
539 result = str_asprintf ("%li", lval);
540 break;
541 case PARAM_LONGLONG:
542 llval = config_get_longlong_param (global_config, where, what,
543 &exists);
544 if (!exists && strcmp (section ? section : "", "global"))
545 llval = config_get_longlong_param (global_config, "global",
546 what, &exists);
547 result = str_asprintf ("%lli", llval);
548 break;
549 case PARAM_CHARPP:
550 cppval = config_get_list_param (global_config, where, what,
551 &exists);
552 if (!exists && strcmp (section ? section : "", "global"))
553 cppval = config_get_list_param (global_config, "global", what,
554 &exists);
556 if (cppval)
557 result = strv_join (",", cppval);
559 strv_free (cppval);
560 break;
565 MUTEX_UNLOCK (&rcfile_mutex);
566 return result;
569 /* 'file' is the list parameter file to load into the list parameter 'what'.
570 * The parsing of the parameter is not done here. */
571 static gpg_error_t
572 parse_list_file (struct slist_s *config, const char *section,
573 const char *file, const char *what)
575 FILE *fp;
576 char buf[LINE_MAX] = {0};
577 int exists;
578 char **list = NULL;
579 char *tmp;
580 char *p = config_get_string_param (config, section, file, &exists);
581 gpg_error_t rc;
583 if (!p || !*p)
585 xfree (p);
586 return 0;
589 tmp = expand_homedir (p);
590 xfree (p);
591 p = tmp;
592 fp = fopen (p, "r");
593 if (!fp)
595 rc = gpg_error_from_errno (errno);
596 log_write ("%s: %s", p, pwmd_strerror (rc));
597 xfree (p);
598 return rc;
601 xfree (p);
602 list = config_get_list_param (config, section, what, &exists);
603 if (!list && exists)
605 fclose (fp);
606 log_write ("%s", pwmd_strerror (ENOMEM));
607 return gpg_error (ENOMEM);
610 while ((p = fgets (buf, sizeof (buf)-1, fp)))
612 char **pp = NULL;
614 if (p[strlen(p)-1] == '\n')
615 p[strlen(p)-1] = 0;
617 while (*p && isspace (*p))
618 p++;
620 if (!*p || *p == ';')
621 continue;
623 tmp = str_dup (p);
624 if (tmp)
625 pp = strv_cat (list, str_dup (p));
627 if (!pp || !tmp)
629 xfree (tmp);
630 strv_free (list);
631 fclose (fp);
632 log_write ("%s", strerror (ENOMEM));
633 return gpg_error (ENOMEM);
636 xfree (tmp);
637 list = pp;
640 fclose(fp);
641 if (!list)
642 return 0;
644 p = strv_join (",", list);
645 strv_free (list);
647 if (!p)
649 log_write ("%s", pwmd_strerror (ENOMEM));
650 return gpg_error (ENOMEM);
653 config_set_list_param (&config, section, what, p);
654 xfree (p);
655 return 0;
658 static int
659 fixup_allowed_once (struct slist_s **config, const char *section)
661 char **list, **pp, *p;
662 int exists;
663 gpg_error_t rc;
665 rc = parse_list_file (*config, section, "allowed_file", "allowed");
666 if (rc)
667 return 1;
669 list = config_get_list_param (*config, section, "allowed", &exists);
670 for (pp = list; pp && *pp; pp++)
672 if (*(*pp) == '#')
674 for (p = *pp; p && *p; p++)
675 *p = toupper(*p);
679 strv_free (list);
680 if (!exists)
682 if (!strcmp (section, "global"))
684 p = get_username (getuid());
686 if (config_set_list_param (config, section, "allowed", p))
688 xfree (p);
689 return 1;
692 xfree (p);
694 else
696 list = config_get_list_param (*config, "global", "allowed", &exists);
697 if (list)
699 p = strv_join (",", list);
700 strv_free (list);
701 if (config_set_list_param (config, section, "allowed", p))
703 xfree (p);
704 return 1;
707 xfree (p);
712 return 0;
715 static int
716 fixup_allowed (struct slist_s **config)
718 int n, t = slist_length (*config);
720 for (n = 0; n < t; n++)
722 struct config_section_s *section;
724 section = slist_nth_data (*config, n);
725 if (fixup_allowed_once (config, section->name))
726 return 1;
729 return 0;
732 static int
733 add_invoking_user (struct invoking_user_s **users, char *id,
734 struct slist_s **config)
736 struct passwd *pwd = NULL;
737 struct group *grp = NULL;
738 struct invoking_user_s *user, *p;
739 int not = 0;
741 if (id && (*id == '!' || *id == '-'))
743 not = 1;
744 id++;
747 errno = 0;
748 if (!id || !*id)
750 pwd = getpwuid (getuid ());
751 if (!pwd)
753 log_write (_("could not set any invoking user: %s"),
754 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
755 return 1;
758 else if (*id == '@')
760 grp = getgrnam (id+1);
761 if (!grp)
763 log_write (_("could not parse group '%s': %s"), id+1,
764 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
765 return 1;
768 else if (*id != '#')
769 pwd = getpwnam (id);
771 if (!grp && !pwd && id && *id != '#')
773 if (id && *id)
774 log_write (_("could not set invoking user '%s': %s"), id,
775 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
776 else
777 log_write (_("could not set any invoking user!"));
779 return 1;
782 user = xcalloc (1, sizeof (struct invoking_user_s));
783 if (!user)
785 log_write ("%s", pwmd_strerror (ENOMEM));
786 return 1;
789 user->not = not;
790 user->type = pwd ? INVOKING_UID : grp ? INVOKING_GID : INVOKING_TLS;
791 if (pwd)
792 user->uid = pwd->pw_uid;
793 else if (grp)
794 user->id = str_dup (id+1);
795 else
797 char *s;
799 for (s = id; s && *s; s++)
800 *s = toupper(*s);
802 user->id = str_dup (id+1);
805 /* Set the default invoking_user since it doesn't exist. */
806 if (pwd && (!id || !*id))
807 config_set_list_param (config, "global", "invoking_user", pwd->pw_name);
809 if (!*users)
811 *users = user;
812 return 0;
815 for (p = *users; p; p = p->next)
817 if (!p->next)
819 p->next = user;
820 break;
824 return 0;
827 static int
828 parse_invoking_users (struct slist_s **config)
830 struct invoking_user_s *users = NULL;
831 int exists;
832 char **list, **l;
834 if (parse_list_file (*config, "global", "invoking_file", "invoking_user"))
835 return 1;
837 list = config_get_list_param (*config, "global", "invoking_user", &exists);
838 for (l = list; l && *l; l++)
840 if (add_invoking_user (&users, *l, config))
842 strv_free (list);
843 free_invoking_users (users);
844 return 1;
848 if (!list || !*list)
850 config_set_list_param (config, "global", "invoking_user", DEFAULT_INVOKER);
851 if (add_invoking_user (&users, (char *)DEFAULT_INVOKER, config))
853 strv_free (list);
854 return 1;
858 free_invoking_users (invoking_users);
859 invoking_users = users;
860 strv_free (list);
861 return 0;
864 static int
865 set_defaults (struct slist_s **config, int reload)
867 char *s = NULL;
868 char **list;
869 int exists;
870 int i;
872 for (i = 0; config_params[i].name; i++)
874 switch (config_params[i].type)
876 case PARAM_BOOL:
877 config_get_bool_param (*config, "global", config_params[i].name,
878 &exists);
879 if (!exists)
881 if (config_set_bool_param
882 (config, "global", config_params[i].name,
883 config_params[i].value))
884 goto fail;
886 break;
887 case PARAM_INT:
888 config_get_int_param (*config, "global", config_params[i].name,
889 &exists);
890 if (!exists)
892 if (config_set_int_param
893 (config, "global", config_params[i].name,
894 config_params[i].value))
895 goto fail;
897 break;
898 case PARAM_CHARP:
899 s = config_get_string_param (*config, "global",
900 config_params[i].name, &exists);
901 xfree (s);
902 if (!exists && config_params[i].value)
904 if (config_set_string_param (config, "global",
905 config_params[i].name,
906 config_params[i].value))
907 goto fail;
909 break;
910 case PARAM_CHARPP:
911 list = config_get_list_param (*config, "global",
912 config_params[i].name, &exists);
913 strv_free (list);
914 if (!exists && config_params[i].value)
916 if (config_set_list_param (config, "global",
917 config_params[i].name,
918 config_params[i].value))
919 goto fail;
921 break;
922 case PARAM_LONG:
923 config_get_long_param (*config, "global", config_params[i].name,
924 &exists);
925 if (!exists)
927 if (config_set_long_param
928 (config, "global", config_params[i].name,
929 config_params[i].value))
930 goto fail;
932 break;
933 case PARAM_LONGLONG:
934 config_get_longlong_param (*config, "global", config_params[i].name,
935 &exists);
936 if (!exists)
938 if (config_set_longlong_param (config, "global",
939 config_params[i].name,
940 config_params[i].value))
941 goto fail;
943 break;
947 s = NULL;
948 if (!reload && fixup_allowed (config))
949 goto fail;
951 if (!reload && parse_invoking_users (config))
952 goto fail;
954 log_level = config_get_int_param (*config, "global",
955 "log_level", &exists);
956 log_keepopen = config_get_int_param (*config, "global",
957 "log_keepopen", &exists);
958 max_recursion_depth = config_get_int_param (*config, "global",
959 "recursion_depth", &exists);
960 disable_list_and_dump = config_get_bool_param (*config, "global",
961 "disable_list_and_dump",
962 &exists);
963 #ifdef HAVE_MLOCKALL
964 disable_mlock =
965 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
966 #endif
968 xfree (s);
969 return 0;
971 fail:
972 xfree (s);
973 return 1;
976 static struct config_section_s *
977 config_find_section (struct slist_s *config, const char *name)
979 unsigned i, t = slist_length (config);
981 for (i = 0; i < t; i++)
983 struct config_section_s *s = slist_nth_data (config, i);
985 if (!strcmp (s->name, name))
986 return s;
989 return NULL;
992 /* Append a new parameter to the list of parameters for a file
993 * section. When an existing parameter of the same name exists, its
994 * value is updated.
996 static int
997 new_param (struct config_section_s *section, const char *filename, int lineno,
998 const char *name, const char *value, int type)
1000 struct config_param_s *param = NULL;
1001 struct slist_s *tmp;
1002 char *e;
1003 unsigned i, t = slist_length (section->params);
1004 int dup = 0;
1006 for (i = 0; i < t; i++)
1008 struct config_param_s *p = slist_nth_data (section->params, i);
1009 if (!p)
1010 break;
1012 if (!strcmp (name, p->name))
1014 param = p;
1015 dup = 1;
1016 break;
1020 if (!param)
1022 param = xcalloc (1, sizeof (struct config_param_s));
1023 if (!param)
1025 log_write ("%s", pwmd_strerror (ENOMEM));
1026 return 1;
1029 param->name = str_dup (name);
1030 if (!param->name)
1032 xfree (param);
1033 log_write ("%s", pwmd_strerror (ENOMEM));
1034 return 1;
1038 param->type = type;
1040 switch (type)
1042 case PARAM_BOOL:
1043 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1044 || !strcasecmp (value, "false"))
1045 param->value.itype = 0;
1046 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1047 || !strcasecmp (value, "true"))
1048 param->value.itype = 1;
1049 else
1051 INVALID_VALUE (filename, lineno);
1052 goto fail;
1054 param->type = PARAM_INT;
1055 break;
1056 case PARAM_CHARP:
1057 xfree (param->value.cptype);
1058 param->value.cptype = NULL;
1059 param->value.cptype = value && *value ? str_dup (value) : NULL;
1060 if (value && *value && !param->value.cptype)
1062 log_write ("%s", pwmd_strerror (ENOMEM));
1063 goto fail;
1065 break;
1066 case PARAM_CHARPP:
1067 strv_free (param->value.cpptype);
1068 param->value.cpptype = NULL;
1069 param->value.cpptype = value && *value ?
1070 str_split_ws (value, ",", 0) : NULL;
1071 if (value && *value && !param->value.cpptype)
1073 log_write ("%s", pwmd_strerror (ENOMEM));
1074 goto fail;
1076 break;
1077 case PARAM_INT:
1078 param->value.itype = strtol (value, &e, 10);
1079 if (e && *e)
1081 INVALID_VALUE (filename, lineno);
1082 goto fail;
1084 break;
1085 case PARAM_LONG:
1086 param->value.ltype = strtol (value, &e, 10);
1087 if (e && *e)
1089 INVALID_VALUE (filename, lineno);
1090 goto fail;
1092 break;
1093 case PARAM_LONGLONG:
1094 param->value.lltype = strtoll (value, &e, 10);
1095 if (e && *e)
1097 INVALID_VALUE (filename, lineno);
1098 goto fail;
1100 break;
1103 if (dup)
1104 return 0;
1106 tmp = slist_append (section->params, param);
1107 if (!tmp)
1109 log_write ("%s", pwmd_strerror (ENOMEM));
1110 goto fail;
1113 section->params = tmp;
1114 return 0;
1116 fail:
1117 xfree (param->name);
1118 xfree (param);
1119 return 1;
1122 struct slist_s *
1123 config_parse (const char *filename, int reload)
1125 struct slist_s *tmpconfig = NULL, *tmp;
1126 struct config_section_s *cur_section = NULL;
1127 char buf[LINE_MAX] = {0};
1128 char *s;
1129 int lineno = 1;
1130 int have_global = 0;
1131 FILE *fp = fopen (filename, "r");
1133 if (!fp)
1135 log_write ("%s: %s", filename,
1136 pwmd_strerror (gpg_error_from_errno (errno)));
1138 if (errno != ENOENT)
1139 return NULL;
1141 log_write (_("Using defaults!"));
1142 goto defaults;
1145 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
1147 char line[LINE_MAX] = { 0 };
1148 size_t len = 0;
1149 int match = 0;
1151 if (*s == '#')
1152 continue;
1154 s = str_chomp (s);
1155 if (!*s)
1156 continue;
1158 /* New file section. */
1159 if (*s == '[')
1161 struct config_section_s *section;
1162 char *p = strchr (++s, ']');
1164 if (!p)
1166 log_write (_("%s(%i): unbalanced braces"), filename, lineno);
1167 goto fail;
1170 if (*(p+1))
1172 log_write (_("%s(%i): trailing characters"), filename, lineno);
1173 goto fail;
1176 len = strlen (s) - strlen (p);
1177 memcpy (line, s, len);
1178 line[len] = 0;
1180 section = config_find_section (tmpconfig, line);
1181 if (section)
1183 log_write (_("%s(%i): section '%s' already exists!"),
1184 filename, lineno, line);
1185 goto fail;
1188 if (!strcmp (line, "global"))
1189 have_global = 1;
1191 section = xcalloc (1, sizeof (struct config_section_s));
1192 section->name = str_dup (line);
1194 if (cur_section)
1196 tmp = slist_append (tmpconfig, cur_section);
1197 if (!tmp)
1199 log_write ("%s", pwmd_strerror (ENOMEM));
1200 goto fail;
1203 tmpconfig = tmp;
1206 cur_section = section;
1207 continue;
1210 if (!cur_section)
1212 log_write (_("%s(%i): parameter outside of section!"), filename,
1213 lineno);
1214 goto fail;
1217 /* Parameters for each section. */
1218 for (int m = 0; config_params[m].name; m++)
1220 len = strlen (config_params[m].name);
1221 if (!strncmp (s, config_params[m].name, len))
1223 char *p = s + len;
1225 while (*p && *p == ' ')
1226 p++;
1228 if (!*p || *p != '=')
1229 continue;
1231 p++;
1232 while (*p && isspace (*p))
1233 p++;
1235 s[len] = 0;
1236 if (new_param (cur_section, filename, lineno, s, p,
1237 config_params[m].type))
1238 goto fail;
1240 match = 1;
1241 break;
1245 if (!match)
1247 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1248 goto fail;
1252 if (cur_section)
1254 tmp = slist_append (tmpconfig, cur_section);
1255 if (!tmp)
1257 log_write ("%s", pwmd_strerror (ENOMEM));
1258 goto fail;
1261 cur_section = NULL;
1262 tmpconfig = tmp;
1265 if (!have_global)
1266 log_write (_
1267 ("WARNING: %s: could not find a [global] configuration section!"),
1268 filename);
1270 defaults:
1271 if (set_defaults (&tmpconfig, reload))
1272 goto fail;
1274 if (fp)
1275 fclose(fp);
1277 return tmpconfig;
1279 fail:
1280 if (fp)
1281 fclose (fp);
1283 config_free (tmpconfig);
1284 free_section (cur_section);
1285 return NULL;
1288 static void
1289 free_section (struct config_section_s *s)
1291 if (!s)
1292 return;
1294 for (;;)
1296 struct config_param_s *p = slist_nth_data (s->params, 0);
1298 if (!p)
1299 break;
1301 section_remove_param (s, p->name);
1304 s->params = NULL;
1305 xfree (s->name);
1306 s->name = NULL;
1309 void
1310 config_free (struct slist_s *config)
1312 for (;;)
1314 struct config_section_s *s = slist_nth_data (config, 0);
1315 if (!s)
1316 break;
1318 free_section (s);
1319 config = slist_remove (config, s);
1320 xfree (s);
1324 void
1325 free_invoking_users (struct invoking_user_s *users)
1327 struct invoking_user_s *p;
1329 for (p = users; p;)
1331 struct invoking_user_s *next = p->next;
1333 if (p->type == INVOKING_TLS || p->type == INVOKING_GID)
1334 xfree (p->id);
1336 xfree (p);
1337 p = next;
1341 static int
1342 param_type (const char *name)
1344 int i;
1346 for (i = 0; config_params[i].name; i++)
1348 if (!strcmp (config_params[i].name, name))
1349 return config_params[i].type;
1352 return PARAM_INVALID;
1355 static int
1356 keep_parse (struct config_keep_s *k, const char *section, const char *key)
1358 int exists;
1359 int ival;
1360 long lval;
1361 long long llval;
1362 char *cpval;
1363 char **cppval;
1364 int type = param_type (key);
1365 void *value = NULL;
1367 switch (type)
1369 case PARAM_BOOL:
1370 case PARAM_INT:
1371 ival = config_get_int_param (global_config, section, key, &exists);
1372 if (exists)
1373 value = str_asprintf ("%i", ival);
1374 break;
1375 case PARAM_LONG:
1376 lval = config_get_long_param (global_config, section, key, &exists);
1377 if (exists)
1378 value = str_asprintf ("%li", lval);
1379 break;
1380 case PARAM_LONGLONG:
1381 llval = config_get_longlong_param (global_config, section, key, &exists);
1382 if (exists)
1383 value = str_asprintf ("%lli", llval);
1384 break;
1385 case PARAM_CHARP:
1386 cpval = config_get_string_param (global_config, section, key, &exists);
1387 if (exists)
1388 value = cpval;
1389 break;
1390 case PARAM_CHARPP:
1391 cppval = config_get_list_param (global_config, section, key, &exists);
1392 if (exists)
1394 char *s = strv_join (",", cppval);
1396 strv_free (cppval);
1397 value = s;
1399 break;
1400 default:
1401 return 1;
1404 if (!value)
1405 return 1;
1407 k->section = str_dup(section);
1408 k->name = str_dup(key);
1409 k->value = value;
1410 return 0;
1413 static struct slist_s *
1414 keep_add (struct slist_s *k, const char *s, const char *key)
1416 int n, t = slist_length (global_config);
1418 for (n = 0; n < t; n++)
1420 struct config_section_s *section;
1421 struct config_keep_s *tmp;
1422 int ret;
1424 section = slist_nth_data (global_config, n);
1425 tmp = xcalloc (1, sizeof(struct config_keep_s));
1427 // Process all sections.
1428 if (!s)
1429 ret = keep_parse (tmp, section->name, key);
1430 else
1431 ret = keep_parse (tmp, s, key);
1433 if (!ret)
1434 k = slist_append (k, tmp);
1435 else
1436 xfree (tmp);
1439 return k;
1442 /* Keep security sensitive settings across SIGHUP. */
1443 struct slist_s *
1444 config_keep_save ()
1446 struct slist_s *keep = NULL;
1448 #ifdef WITH_GNUTLS
1449 keep = keep_add (keep, NULL, "tcp_require_key");
1450 #endif
1451 keep = keep_add (keep, NULL, "require_save_key");
1452 keep = keep_add (keep, NULL, "allowed");
1453 keep = keep_add (keep, NULL, "allowed_file");
1454 keep = keep_add (keep, "global", "encrypt_to");
1455 keep = keep_add (keep, "global", "always_trust");
1456 keep = keep_add (keep, "global", "invoking_user");
1457 keep = keep_add (keep, "global", "invoking_file");
1458 keep = keep_add (keep, "global", "gpg_homedir");
1459 return keep;
1462 /* Restore parameters previously saved with config_keep_save(). This will also
1463 * free the 'keep'.
1465 void
1466 config_keep_restore (struct slist_s *keep)
1468 int n, t = slist_length (keep);
1470 for (n = 0; n < t; n++)
1472 struct config_keep_s *k = slist_nth_data (keep, n);
1473 int type = param_type (k->name);
1475 switch (type)
1477 case PARAM_BOOL:
1478 config_set_bool_param (&global_config, k->section, k->name, k->value);
1479 break;
1480 case PARAM_INT:
1481 config_set_int_param (&global_config, k->section, k->name, k->value);
1482 break;
1483 case PARAM_LONG:
1484 config_set_long_param (&global_config, k->section, k->name, k->value);
1485 break;
1486 case PARAM_LONGLONG:
1487 config_set_longlong_param (&global_config, k->section, k->name,
1488 k->value);
1489 break;
1490 case PARAM_CHARP:
1491 config_set_string_param (&global_config, k->section, k->name,
1492 k->value);
1493 break;
1494 case PARAM_CHARPP:
1495 config_set_list_param (&global_config, k->section, k->name, k->value);
1496 break;
1497 default:
1498 break;
1501 xfree (k->section);
1502 xfree (k->name);
1503 xfree (k->value);
1504 xfree (k);
1507 slist_free (keep);