Update m4 macros.
[libpwmd.git] / src / rcfile.c
blobf10929c857460445f2591b274a1f010df6d7a653
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <ctype.h>
32 #include <pwd.h>
33 #include <grp.h>
35 #include "pwmd-error.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_CACHE_TIMEOUT "600"
45 #define DEFAULT_KEEPALIVE_INTERVAL "60"
46 #define DEFAULT_LOCK_TIMEOUT "50" // MUTEX_TRYLOCK in tenths of a second
47 #define DEFAULT_BACKLOG "128"
48 #define DEFAULT_CIPHER_PRIORITY "SECURE256:SECURE192:SECURE128:-VERS-SSL3.0:-VERS-TLS1.0"
50 #define INVALID_VALUE(file, line) do { \
51 if (file) \
52 log_write(_("%s(%i): invalid value for parameter."), file, line); \
53 } while (0);
55 enum
57 PARAM_INT, PARAM_CHARP, PARAM_LONG, PARAM_LONGLONG, PARAM_CHARPP,
58 PARAM_BOOL, PARAM_INVALID
61 static struct config_params_s
63 const char *name;
64 int type;
65 const char *value;
66 } config_params[] = {
67 { "backup", PARAM_BOOL, "true"},
68 { "socket_path", PARAM_CHARP, NULL},
69 { "socket_perms", PARAM_CHARP, NULL},
70 { "backlog", PARAM_INT, DEFAULT_BACKLOG},
71 { "passphrase_file", 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 { "priority", PARAM_INT, INVALID_PRIORITY},
86 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
87 { "tcp_port", PARAM_INT, "6466"},
88 { "enable_tcp", PARAM_BOOL, "false"},
89 { "tcp_require_key", PARAM_BOOL, "false"},
90 { "tcp_bind", PARAM_CHARP, "any"},
91 { "tcp_interface", PARAM_CHARP, NULL},
92 { "tls_timeout", PARAM_INT, "300"},
93 { "tls_cipher_suite", PARAM_CHARP, DEFAULT_CIPHER_PRIORITY},
94 { "tls_dh_params_file", PARAM_CHARP, NULL},
95 { "require_save_key", PARAM_BOOL, "true"},
96 { "invoking_user", PARAM_CHARPP, NULL},
97 { "invoking_file", PARAM_CHARP, NULL},
98 { "encrypt_to", PARAM_BOOL, "false"},
99 { "always_trust", PARAM_BOOL, "false"},
100 { "gpg_homedir", PARAM_CHARP, NULL},
101 { "strict_kill", PARAM_BOOL, "false"},
102 { "lock_timeout", PARAM_INT, DEFAULT_LOCK_TIMEOUT},
103 { "kill_scd", PARAM_BOOL, "false"},
104 { NULL, PARAM_INVALID, NULL},
107 struct config_param_s
109 char *name;
110 int type;
111 union
113 int itype;
114 char *cptype;
115 char **cpptype;
116 long ltype;
117 long long lltype;
118 } value;
121 struct config_keep_s
123 char *section;
124 char *name;
125 char *value;
128 static struct config_section_s *config_find_section (struct slist_s *config,
129 const char *name);
130 static int new_param (struct config_section_s *section, const char *filename,
131 int lineno, const char *name, const char *value,
132 int type);
133 static void free_section (struct config_section_s *s);
134 static int set_defaults (struct slist_s **config, int reload);
136 static void
137 section_remove_param (struct config_section_s *section, const char *name)
139 unsigned i, t = slist_length (section->params);
141 for (i = 0; i < t; i++)
143 struct config_param_s *p = slist_nth_data (section->params, i);
145 if (!p)
146 continue;
148 if (!strcmp (p->name, name))
150 switch (p->type)
152 case PARAM_CHARP:
153 xfree (p->value.cptype);
154 break;
155 case PARAM_CHARPP:
156 strv_free (p->value.cpptype);
157 break;
160 section->params = slist_remove (section->params, p);
161 xfree (p->name);
162 xfree (p);
163 break;
168 static struct config_param_s *
169 config_has_param (struct config_section_s *s, const char *what)
171 unsigned i, t = slist_length (s->params);
173 for (i = 0; i < t; i++)
175 struct config_param_s *p = slist_nth_data (s->params, i);
176 if (!p)
177 break;
179 if (!strcmp (p->name, what))
180 return p;
183 return NULL;
186 static struct config_param_s *
187 config_get_param (struct slist_s *config,
188 const char *section, const char *what, int *exists)
190 unsigned i, t = slist_length (config);
192 *exists = 0;
194 for (i = 0; i < t; i++)
196 struct config_param_s *p;
197 struct config_section_s *s = slist_nth_data (config, i);
199 if (!s)
200 break;
202 if (strcmp (s->name, section))
203 continue;
205 p = config_has_param (s, what);
206 if (!p)
207 return NULL;
209 *exists = 1;
210 return p;
213 return NULL;
216 static struct config_section_s *
217 new_section (struct slist_s **config, const char *name)
219 struct slist_s *tmp;
220 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
222 if (!s)
223 return NULL;
225 s->name = str_dup (name);
226 if (!s->name)
228 log_write ("%s", pwmd_strerror (ENOMEM));
229 xfree (s);
230 return NULL;
233 tmp = slist_append (*config, s);
234 if (!tmp)
236 log_write ("%s", pwmd_strerror (ENOMEM));
237 xfree (s->name);
238 xfree (s);
239 return NULL;
242 *config = tmp;
243 return s;
247 config_set_string_param (struct slist_s **config, const char *section,
248 const char *name, const char *value)
250 struct config_section_s *s = config_find_section (*config, section);
252 if (!s)
254 s = new_section (config, section);
255 if (!s)
256 return 1;
259 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
262 char *
263 config_get_string_param (struct slist_s *config, const char *section,
264 const char *what, int *exists)
266 struct config_param_s *p = config_get_param (config, section, what, exists);
267 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
271 config_set_int_param (struct slist_s **config, const char *section,
272 const char *name, const char *value)
274 struct config_section_s *s = config_find_section (*config, section);
276 if (!s)
278 s = new_section (config, section);
279 if (!s)
280 return 1;
283 return new_param (s, NULL, 0, name, value, PARAM_INT);
287 config_get_int_param (struct slist_s *config, const char *section,
288 const char *what, int *exists)
290 struct config_param_s *p = config_get_param (config, section, what, exists);
291 return *exists ? p->value.itype : -1;
295 config_set_bool_param (struct slist_s **config, const char *section,
296 const char *name, const char *value)
298 struct config_section_s *s = config_find_section (*config, section);
300 if (!s)
302 s = new_section (config, section);
303 if (!s)
304 return 1;
307 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
311 config_get_bool_param (struct slist_s *config, const char *section,
312 const char *what, int *exists)
314 return config_get_int_param (config, section, what, exists);
318 config_set_long_param (struct slist_s **config, const char *section,
319 const char *name, const char *value)
321 struct config_section_s *s = config_find_section (*config, section);
323 if (!s)
325 s = new_section (config, section);
326 if (!s)
327 return 1;
330 return new_param (s, NULL, 0, name, value, PARAM_LONG);
333 long
334 config_get_long_param (struct slist_s *config, const char *section,
335 const char *what, int *exists)
337 struct config_param_s *p = config_get_param (config, section, what, exists);
338 return *exists ? p->value.ltype : -1;
342 config_set_longlong_param (struct slist_s **config, const char *section,
343 const char *name, const char *value)
345 struct config_section_s *s = config_find_section (*config, section);
347 if (!s)
349 s = new_section (config, section);
350 if (!s)
351 return 1;
354 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
357 long long
358 config_get_longlong_param (struct slist_s *config,
359 const char *section, const char *what, int *exists)
361 struct config_param_s *p = config_get_param (config, section, what, exists);
362 return *exists ? p->value.lltype : -1;
366 config_set_list_param (struct slist_s **config, const char *section,
367 const char *name, const char *value)
369 struct config_section_s *s = config_find_section (*config, section);
371 if (!s)
373 s = new_section (config, section);
374 if (!s)
375 return 1;
378 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
381 char **
382 config_get_list_param (struct slist_s *config, const char *section,
383 const char *what, int *exists)
385 struct config_param_s *p = config_get_param (config, section, what, exists);
386 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
389 char *
390 config_get_string (const char *section, const char *what)
392 char *val = NULL;
393 const char *where = section ? section : "global";
394 int exists = 0;
396 MUTEX_LOCK (&rcfile_mutex);
397 val = config_get_string_param (global_config, where, what, &exists);
398 if (!exists && strcmp (section ? section : "", "global"))
399 val = config_get_string_param (global_config, "global", what, &exists);
401 MUTEX_UNLOCK (&rcfile_mutex);
402 return val;
405 char **
406 config_get_list (const char *section, const char *what)
408 char **val = NULL;
409 const char *where = section ? section : "global";
410 int exists = 0;
412 MUTEX_LOCK (&rcfile_mutex);
413 val = config_get_list_param (global_config, where, what, &exists);
414 if (!exists && strcmp (section ? section : "", "global"))
415 val = config_get_list_param (global_config, "global", what, &exists);
417 MUTEX_UNLOCK (&rcfile_mutex);
418 return val;
422 config_get_integer (const char *section, const char *what)
424 int val = 0;
425 const char *where = section ? section : "global";
426 int exists = 0;
428 MUTEX_LOCK (&rcfile_mutex);
429 val = config_get_int_param (global_config, where, what, &exists);
430 if (!exists && strcmp (section ? section : "", "global"))
431 val = config_get_int_param (global_config, "global", what, &exists);
433 MUTEX_UNLOCK (&rcfile_mutex);
434 return val;
437 long long
438 config_get_longlong (const char *section, const char *what)
440 long long val = 0;
441 const char *where = section ? section : "global";
442 int exists = 0;
444 MUTEX_LOCK (&rcfile_mutex);
445 val = config_get_longlong_param (global_config, where, what, &exists);
446 if (!exists && strcmp (section ? section : "", "global"))
447 val = config_get_longlong_param (global_config, "global", what, &exists);
449 MUTEX_UNLOCK (&rcfile_mutex);
450 return val;
453 long
454 config_get_long (const char *section, const char *what)
456 long val = 0;
457 const char *where = section ? section : "global";
458 int exists = 0;
460 MUTEX_LOCK (&rcfile_mutex);
461 val = config_get_long_param (global_config, where, what, &exists);
462 if (!exists && strcmp (section ? section : "", "global"))
463 val = config_get_long_param (global_config, "global", what, &exists);
465 MUTEX_UNLOCK (&rcfile_mutex);
466 return val;
470 config_get_boolean (const char *section, const char *what)
472 return config_get_integer (section, what);
475 char *
476 config_get_value (const char *section, const char *what)
478 const char *where = section ? section : "global";
479 int exists = 0;
480 int i;
481 int ival;
482 long lval;
483 long long llval;
484 char *cpval;
485 char **cppval;
486 char *result = NULL;
488 MUTEX_LOCK (&rcfile_mutex);
490 for (i = 0; config_params[i].name; i++)
492 if (!strcmp (config_params[i].name, what))
494 switch (config_params[i].type)
496 case PARAM_BOOL:
497 case PARAM_INT:
498 ival = config_get_int_param (global_config, where, what,
499 &exists);
500 if (!exists && strcmp (section ? section : "", "global"))
501 ival = config_get_int_param (global_config, "global", what,
502 &exists);
503 result = str_asprintf ("%i", ival);
504 break;
505 case PARAM_CHARP:
506 cpval = config_get_string_param (global_config, where, what,
507 &exists);
508 if (!exists && strcmp (section ? section : "", "global"))
509 cpval =
510 config_get_string_param (global_config, "global", what,
511 &exists);
512 result = cpval;
513 break;
514 case PARAM_LONG:
515 lval = config_get_long_param (global_config, where, what,
516 &exists);
517 if (!exists && strcmp (section ? section : "", "global"))
518 lval = config_get_long_param (global_config, "global", what,
519 &exists);
520 result = str_asprintf ("%li", lval);
521 break;
522 case PARAM_LONGLONG:
523 llval = config_get_longlong_param (global_config, where, what,
524 &exists);
525 if (!exists && strcmp (section ? section : "", "global"))
526 llval = config_get_longlong_param (global_config, "global",
527 what, &exists);
528 result = str_asprintf ("%lli", llval);
529 break;
530 case PARAM_CHARPP:
531 cppval = config_get_list_param (global_config, where, what,
532 &exists);
533 if (!exists && strcmp (section ? section : "", "global"))
534 cppval = config_get_list_param (global_config, "global", what,
535 &exists);
537 if (cppval)
538 result = strv_join (",", cppval);
540 strv_free (cppval);
541 break;
546 MUTEX_UNLOCK (&rcfile_mutex);
547 return result;
550 /* 'file' is the list parameter file to load into the list parameter 'what'.
551 * The parsing of the parameter is not done here. */
552 static gpg_error_t
553 parse_list_file (struct slist_s *config, const char *section,
554 const char *file, const char *what)
556 FILE *fp;
557 char buf[LINE_MAX] = {0};
558 int exists;
559 char **list = NULL;
560 char *tmp;
561 char *p = config_get_string_param (config, section, file, &exists);
562 gpg_error_t rc;
564 if (!p || !*p)
566 xfree (p);
567 return 0;
570 tmp = expand_homedir (p);
571 xfree (p);
572 p = tmp;
573 fp = fopen (p, "r");
574 if (!fp)
576 rc = gpg_error_from_errno (errno);
577 log_write ("%s: %s", p, pwmd_strerror (rc));
578 xfree (p);
579 return rc;
582 xfree (p);
583 list = config_get_list_param (config, section, what, &exists);
584 if (!list && exists)
586 fclose (fp);
587 log_write ("%s", pwmd_strerror (ENOMEM));
588 return gpg_error (ENOMEM);
591 while ((p = fgets (buf, sizeof (buf)-1, fp)))
593 char **pp = NULL;
595 if (p[strlen(p)-1] == '\n')
596 p[strlen(p)-1] = 0;
598 while (*p && isspace (*p))
599 p++;
601 if (!*p || *p == ';')
602 continue;
604 tmp = str_dup (p);
605 if (tmp)
606 pp = strv_cat (list, str_dup (p));
608 if (!pp || !tmp)
610 xfree (tmp);
611 strv_free (list);
612 fclose (fp);
613 log_write ("%s", strerror (ENOMEM));
614 return gpg_error (ENOMEM);
617 xfree (tmp);
618 list = pp;
621 fclose(fp);
622 if (!list)
623 return 0;
625 p = strv_join (",", list);
626 strv_free (list);
628 if (!p)
630 log_write ("%s", pwmd_strerror (ENOMEM));
631 return gpg_error (ENOMEM);
634 config_set_list_param (&config, section, what, p);
635 xfree (p);
636 return 0;
639 static int
640 fixup_allowed_once (struct slist_s **config, const char *section)
642 char **list, **pp, *p;
643 int exists;
644 gpg_error_t rc;
646 rc = parse_list_file (*config, section, "allowed_file", "allowed");
647 if (rc)
648 return 1;
650 list = config_get_list_param (*config, section, "allowed", &exists);
651 for (pp = list; pp && *pp; pp++)
653 if (*(*pp) == '#')
655 for (p = *pp; p && *p; p++)
656 *p = toupper(*p);
660 strv_free (list);
661 if (!exists)
663 if (!strcmp (section, "global"))
665 p = get_username (getuid());
667 if (config_set_list_param (config, section, "allowed", p))
669 xfree (p);
670 return 1;
673 xfree (p);
675 else
677 list = config_get_list_param (*config, "global", "allowed", &exists);
678 if (list)
680 p = strv_join (",", list);
681 strv_free (list);
682 if (config_set_list_param (config, section, "allowed", p))
684 xfree (p);
685 return 1;
688 xfree (p);
693 return 0;
696 static int
697 fixup_allowed (struct slist_s **config)
699 int n, t = slist_length (*config);
701 for (n = 0; n < t; n++)
703 struct config_section_s *section;
705 section = slist_nth_data (*config, n);
706 if (fixup_allowed_once (config, section->name))
707 return 1;
710 return 0;
713 static int
714 add_invoking_user (struct invoking_user_s **users, char *id,
715 struct slist_s **config)
717 struct passwd *pwd = NULL;
718 struct group *grp = NULL;
719 struct invoking_user_s *user, *p;
720 int not = 0;
722 if (id && (*id == '!' || *id == '-'))
724 not = 1;
725 id++;
728 errno = 0;
729 if (!id || !*id)
731 pwd = getpwuid (getuid ());
732 if (!pwd)
734 log_write (_("could not set any invoking user: %s"),
735 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
736 return 1;
739 else if (*id == '@')
741 grp = getgrnam (id+1);
742 if (!grp)
744 log_write (_("could not parse group '%s': %s"), id+1,
745 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
746 return 1;
749 else if (*id != '#')
750 pwd = getpwnam (id);
752 if (!grp && !pwd && id && *id != '#')
754 if (id && *id)
755 log_write (_("could not set invoking user '%s': %s"), id,
756 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
757 else
758 log_write (_("could not set any invoking user!"));
760 return 1;
763 user = xcalloc (1, sizeof (struct invoking_user_s));
764 if (!user)
766 log_write ("%s", pwmd_strerror (ENOMEM));
767 return 1;
770 user->not = not;
771 user->type = pwd ? INVOKING_UID : grp ? INVOKING_GID : INVOKING_TLS;
772 if (pwd)
773 user->uid = pwd->pw_uid;
774 else if (grp)
775 user->id = str_dup (id+1);
776 else
778 char *s;
780 for (s = id; s && *s; s++)
781 *s = toupper(*s);
783 user->id = str_dup (id+1);
786 /* Set the default invoking_user since it doesn't exist. */
787 if (!id || !*id)
788 config_set_list_param (config, "global", "invoking_user", pwd->pw_name);
790 if (!*users)
792 *users = user;
793 return 0;
796 for (p = *users; p; p = p->next)
798 if (!p->next)
800 p->next = user;
801 break;
805 return 0;
808 static int
809 parse_invoking_users (struct slist_s **config)
811 struct invoking_user_s *users = NULL;
812 int exists;
813 char **list, **l;
815 if (parse_list_file (*config, "global", "invoking_file", "invoking_user"))
816 return 1;
818 list = config_get_list_param (*config, "global", "invoking_user", &exists);
819 for (l = list; l && *l; l++)
821 if (add_invoking_user (&users, *l, config))
823 strv_free (list);
824 free_invoking_users (users);
825 return 1;
829 if (!list || !*list)
831 if (add_invoking_user (&users, NULL, config))
833 strv_free (list);
834 return 1;
838 free_invoking_users (invoking_users);
839 invoking_users = users;
840 strv_free (list);
841 return 0;
844 static int
845 set_defaults (struct slist_s **config, int reload)
847 char *s = NULL;
848 char **list;
849 int exists;
850 int i;
852 for (i = 0; config_params[i].name; i++)
854 switch (config_params[i].type)
856 case PARAM_BOOL:
857 config_get_bool_param (*config, "global", config_params[i].name,
858 &exists);
859 if (!exists)
861 if (config_set_bool_param
862 (config, "global", config_params[i].name,
863 config_params[i].value))
864 goto fail;
866 break;
867 case PARAM_INT:
868 config_get_int_param (*config, "global", config_params[i].name,
869 &exists);
870 if (!exists)
872 if (config_set_int_param
873 (config, "global", config_params[i].name,
874 config_params[i].value))
875 goto fail;
877 break;
878 case PARAM_CHARP:
879 s = config_get_string_param (*config, "global",
880 config_params[i].name, &exists);
881 xfree (s);
882 if (!exists && config_params[i].value)
884 if (config_set_string_param (config, "global",
885 config_params[i].name,
886 config_params[i].value))
887 goto fail;
889 break;
890 case PARAM_CHARPP:
891 list = config_get_list_param (*config, "global",
892 config_params[i].name, &exists);
893 strv_free (list);
894 if (!exists && config_params[i].value)
896 if (config_set_list_param (config, "global",
897 config_params[i].name,
898 config_params[i].value))
899 goto fail;
901 break;
902 case PARAM_LONG:
903 config_get_long_param (*config, "global", config_params[i].name,
904 &exists);
905 if (!exists)
907 if (config_set_long_param
908 (config, "global", config_params[i].name,
909 config_params[i].value))
910 goto fail;
912 break;
913 case PARAM_LONGLONG:
914 config_get_longlong_param (*config, "global", config_params[i].name,
915 &exists);
916 if (!exists)
918 if (config_set_longlong_param (config, "global",
919 config_params[i].name,
920 config_params[i].value))
921 goto fail;
923 break;
927 s = NULL;
928 if (!reload && fixup_allowed (config))
929 goto fail;
931 if (!reload && parse_invoking_users (config))
932 goto fail;
934 log_level = config_get_int_param (*config, "global",
935 "log_level", &exists);
936 log_keepopen = config_get_int_param (*config, "global",
937 "log_keepopen", &exists);
938 max_recursion_depth = config_get_int_param (*config, "global",
939 "recursion_depth", &exists);
940 disable_list_and_dump = config_get_bool_param (*config, "global",
941 "disable_list_and_dump",
942 &exists);
943 #ifdef HAVE_MLOCKALL
944 disable_mlock =
945 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
946 #endif
948 xfree (s);
949 return 0;
951 fail:
952 xfree (s);
953 return 1;
956 static struct config_section_s *
957 config_find_section (struct slist_s *config, const char *name)
959 unsigned i, t = slist_length (config);
961 for (i = 0; i < t; i++)
963 struct config_section_s *s = slist_nth_data (config, i);
965 if (!strcmp (s->name, name))
966 return s;
969 return NULL;
972 /* Append a new parameter to the list of parameters for a file
973 * section. When an existing parameter of the same name exists, its
974 * value is updated.
976 static int
977 new_param (struct config_section_s *section, const char *filename, int lineno,
978 const char *name, const char *value, int type)
980 struct config_param_s *param = NULL;
981 struct slist_s *tmp;
982 char *e;
983 unsigned i, t = slist_length (section->params);
984 int dup = 0;
986 for (i = 0; i < t; i++)
988 struct config_param_s *p = slist_nth_data (section->params, i);
989 if (!p)
990 break;
992 if (!strcmp (name, p->name))
994 param = p;
995 dup = 1;
996 break;
1000 if (!param)
1002 param = xcalloc (1, sizeof (struct config_param_s));
1003 if (!param)
1005 log_write ("%s", pwmd_strerror (ENOMEM));
1006 return 1;
1009 param->name = str_dup (name);
1010 if (!param->name)
1012 xfree (param);
1013 log_write ("%s", pwmd_strerror (ENOMEM));
1014 return 1;
1018 param->type = type;
1020 switch (type)
1022 case PARAM_BOOL:
1023 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1024 || !strcasecmp (value, "false"))
1025 param->value.itype = 0;
1026 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1027 || !strcasecmp (value, "true"))
1028 param->value.itype = 1;
1029 else
1031 INVALID_VALUE (filename, lineno);
1032 goto fail;
1034 param->type = PARAM_INT;
1035 break;
1036 case PARAM_CHARP:
1037 xfree (param->value.cptype);
1038 param->value.cptype = NULL;
1039 param->value.cptype = value && *value ? str_dup (value) : NULL;
1040 if (value && *value && !param->value.cptype)
1042 log_write ("%s", pwmd_strerror (ENOMEM));
1043 goto fail;
1045 break;
1046 case PARAM_CHARPP:
1047 strv_free (param->value.cpptype);
1048 param->value.cpptype = NULL;
1049 param->value.cpptype = value && *value ?
1050 str_split_ws (value, ",", 0) : NULL;
1051 if (value && *value && !param->value.cpptype)
1053 log_write ("%s", pwmd_strerror (ENOMEM));
1054 goto fail;
1056 break;
1057 case PARAM_INT:
1058 param->value.itype = strtol (value, &e, 10);
1059 if (e && *e)
1061 INVALID_VALUE (filename, lineno);
1062 goto fail;
1064 break;
1065 case PARAM_LONG:
1066 param->value.ltype = strtol (value, &e, 10);
1067 if (e && *e)
1069 INVALID_VALUE (filename, lineno);
1070 goto fail;
1072 break;
1073 case PARAM_LONGLONG:
1074 param->value.lltype = strtoll (value, &e, 10);
1075 if (e && *e)
1077 INVALID_VALUE (filename, lineno);
1078 goto fail;
1080 break;
1083 if (dup)
1084 return 0;
1086 tmp = slist_append (section->params, param);
1087 if (!tmp)
1089 log_write ("%s", pwmd_strerror (ENOMEM));
1090 goto fail;
1093 section->params = tmp;
1094 return 0;
1096 fail:
1097 xfree (param->name);
1098 xfree (param);
1099 return 1;
1102 struct slist_s *
1103 config_parse (const char *filename, int reload)
1105 struct slist_s *tmpconfig = NULL, *tmp;
1106 struct config_section_s *cur_section = NULL;
1107 char buf[LINE_MAX] = {0};
1108 char *s;
1109 int lineno = 1;
1110 int have_global = 0;
1111 FILE *fp = fopen (filename, "r");
1113 if (!fp)
1115 log_write ("%s: %s", filename,
1116 pwmd_strerror (gpg_error_from_errno (errno)));
1118 if (errno != ENOENT)
1119 return NULL;
1121 log_write (_("Using defaults!"));
1122 goto defaults;
1125 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
1127 char line[LINE_MAX] = { 0 };
1128 size_t len = 0;
1129 int match = 0;
1131 if (*s == '#')
1132 continue;
1134 s = str_chomp (s);
1135 if (!*s)
1136 continue;
1138 /* New file section. */
1139 if (*s == '[')
1141 struct config_section_s *section;
1142 char *p = strchr (++s, ']');
1144 if (!p)
1146 log_write (_("%s(%i): unbalanced braces"), filename, lineno);
1147 goto fail;
1150 if (*(p+1))
1152 log_write (_("%s(%i): trailing characters"), filename, lineno);
1153 goto fail;
1156 len = strlen (s) - strlen (p);
1157 memcpy (line, s, len);
1158 line[len] = 0;
1160 section = config_find_section (tmpconfig, line);
1161 if (section)
1163 log_write (_("%s(%i): section '%s' already exists!"),
1164 filename, lineno, line);
1165 goto fail;
1168 if (!strcmp (line, "global"))
1169 have_global = 1;
1171 section = xcalloc (1, sizeof (struct config_section_s));
1172 section->name = str_dup (line);
1174 if (cur_section)
1176 tmp = slist_append (tmpconfig, cur_section);
1177 if (!tmp)
1179 log_write ("%s", pwmd_strerror (ENOMEM));
1180 goto fail;
1183 tmpconfig = tmp;
1186 cur_section = section;
1187 continue;
1190 if (!cur_section)
1192 log_write (_("%s(%i): parameter outside of section!"), filename,
1193 lineno);
1194 goto fail;
1197 /* Parameters for each section. */
1198 for (int m = 0; config_params[m].name; m++)
1200 len = strlen (config_params[m].name);
1201 if (!strncmp (s, config_params[m].name, len))
1203 char *p = s + len;
1205 while (*p && *p == ' ')
1206 p++;
1208 if (!*p || *p != '=')
1209 continue;
1211 p++;
1212 while (*p && isspace (*p))
1213 p++;
1215 s[len] = 0;
1216 if (new_param (cur_section, filename, lineno, s, p,
1217 config_params[m].type))
1218 goto fail;
1220 match = 1;
1221 break;
1225 if (!match)
1227 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1228 goto fail;
1232 if (cur_section)
1234 tmp = slist_append (tmpconfig, cur_section);
1235 if (!tmp)
1237 log_write ("%s", pwmd_strerror (ENOMEM));
1238 goto fail;
1241 cur_section = NULL;
1242 tmpconfig = tmp;
1245 if (!have_global)
1246 log_write (_
1247 ("WARNING: %s: could not find a [global] configuration section!"),
1248 filename);
1250 defaults:
1251 if (set_defaults (&tmpconfig, reload))
1252 goto fail;
1254 if (fp)
1255 fclose(fp);
1257 return tmpconfig;
1259 fail:
1260 if (fp)
1261 fclose (fp);
1263 config_free (tmpconfig);
1264 free_section (cur_section);
1265 return NULL;
1268 static void
1269 free_section (struct config_section_s *s)
1271 if (!s)
1272 return;
1274 for (;;)
1276 struct config_param_s *p = slist_nth_data (s->params, 0);
1278 if (!p)
1279 break;
1281 section_remove_param (s, p->name);
1284 s->params = NULL;
1285 xfree (s->name);
1286 s->name = NULL;
1289 void
1290 config_free (struct slist_s *config)
1292 for (;;)
1294 struct config_section_s *s = slist_nth_data (config, 0);
1295 if (!s)
1296 break;
1298 free_section (s);
1299 config = slist_remove (config, s);
1300 xfree (s);
1304 void
1305 free_invoking_users (struct invoking_user_s *users)
1307 struct invoking_user_s *p;
1309 for (p = users; p;)
1311 struct invoking_user_s *next = p->next;
1313 if (p->type == INVOKING_TLS || p->type == INVOKING_GID)
1314 xfree (p->id);
1316 xfree (p);
1317 p = next;
1321 static int
1322 param_type (const char *name)
1324 int i;
1326 for (i = 0; config_params[i].name; i++)
1328 if (!strcmp (config_params[i].name, name))
1329 return config_params[i].type;
1332 return PARAM_INVALID;
1335 static int
1336 keep_parse (struct config_keep_s *k, const char *section, const char *key)
1338 int exists;
1339 int ival;
1340 long lval;
1341 long long llval;
1342 char *cpval;
1343 char **cppval;
1344 int type = param_type (key);
1345 void *value = NULL;
1347 switch (type)
1349 case PARAM_BOOL:
1350 case PARAM_INT:
1351 ival = config_get_int_param (global_config, section, key, &exists);
1352 if (exists)
1353 value = str_asprintf ("%i", ival);
1354 break;
1355 case PARAM_LONG:
1356 lval = config_get_long_param (global_config, section, key, &exists);
1357 if (exists)
1358 value = str_asprintf ("%li", lval);
1359 break;
1360 case PARAM_LONGLONG:
1361 llval = config_get_longlong_param (global_config, section, key, &exists);
1362 if (exists)
1363 value = str_asprintf ("%lli", llval);
1364 break;
1365 case PARAM_CHARP:
1366 cpval = config_get_string_param (global_config, section, key, &exists);
1367 if (exists)
1368 value = cpval;
1369 break;
1370 case PARAM_CHARPP:
1371 cppval = config_get_list_param (global_config, section, key, &exists);
1372 if (exists)
1374 char *s = strv_join (",", cppval);
1376 strv_free (cppval);
1377 value = s;
1379 break;
1380 default:
1381 return 1;
1384 if (!value)
1385 return 1;
1387 k->section = str_dup(section);
1388 k->name = str_dup(key);
1389 k->value = value;
1390 return 0;
1393 static struct slist_s *
1394 keep_add (struct slist_s *k, const char *s, const char *key)
1396 int n, t = slist_length (global_config);
1398 for (n = 0; n < t; n++)
1400 struct config_section_s *section;
1401 struct config_keep_s *tmp;
1402 int ret;
1404 section = slist_nth_data (global_config, n);
1405 tmp = xcalloc (1, sizeof(struct config_keep_s));
1407 // Process all sections.
1408 if (!s)
1409 ret = keep_parse (tmp, section->name, key);
1410 else
1411 ret = keep_parse (tmp, s, key);
1413 if (!ret)
1414 k = slist_append (k, tmp);
1415 else
1416 xfree (tmp);
1419 return k;
1422 /* Keep security sensitive settings across SIGHUP. */
1423 struct slist_s *
1424 config_keep_save ()
1426 struct slist_s *keep = NULL;
1428 #ifdef WITH_GNUTLS
1429 keep = keep_add (keep, NULL, "tcp_require_key");
1430 #endif
1431 keep = keep_add (keep, NULL, "require_save_key");
1432 keep = keep_add (keep, NULL, "allowed");
1433 keep = keep_add (keep, "global", "encrypt_to");
1434 keep = keep_add (keep, "global", "always_trust");
1435 keep = keep_add (keep, "global", "invoking_user");
1436 return keep;
1439 /* Restore parameters previously saved with config_keep_save(). This will also
1440 * free the 'keep'.
1442 void
1443 config_keep_restore (struct slist_s *keep)
1445 int n, t = slist_length (keep);
1447 for (n = 0; n < t; n++)
1449 struct config_keep_s *k = slist_nth_data (keep, n);
1450 int type = param_type (k->name);
1452 switch (type)
1454 case PARAM_BOOL:
1455 config_set_bool_param (&global_config, k->section, k->name, k->value);
1456 break;
1457 case PARAM_INT:
1458 config_set_int_param (&global_config, k->section, k->name, k->value);
1459 break;
1460 case PARAM_LONG:
1461 config_set_long_param (&global_config, k->section, k->name, k->value);
1462 break;
1463 case PARAM_LONGLONG:
1464 config_set_longlong_param (&global_config, k->section, k->name,
1465 k->value);
1466 break;
1467 case PARAM_CHARP:
1468 config_set_string_param (&global_config, k->section, k->name,
1469 k->value);
1470 break;
1471 case PARAM_CHARPP:
1472 config_set_list_param (&global_config, k->section, k->name, k->value);
1473 break;
1474 default:
1475 break;
1478 xfree (k->section);
1479 xfree (k->name);
1480 xfree (k->value);
1481 xfree (k);
1484 slist_free (keep);