Fix previous commit.
[pwmd.git] / src / rcfile.c
blob60a0292f9073b876fa7f2dc4ccdf3f64459dd50e
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016, 2017
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_LONG, 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_LONG, DEFAULT_LOCK_TIMEOUT},
103 { "kill_scd", PARAM_BOOL, "false"},
104 { "strict_open", PARAM_BOOL, "false"},
105 { NULL, PARAM_INVALID, NULL},
108 struct config_param_s
110 char *name;
111 int type;
112 union
114 int itype;
115 char *cptype;
116 char **cpptype;
117 long ltype;
118 long long lltype;
119 } value;
122 struct config_keep_s
124 char *section;
125 char *name;
126 char *value;
129 static struct config_section_s *config_find_section (struct slist_s *config,
130 const char *name);
131 static int new_param (struct config_section_s *section, const char *filename,
132 int lineno, const char *name, const char *value,
133 int type);
134 static void free_section (struct config_section_s *s);
135 static int set_defaults (struct slist_s **config, int reload);
137 static void
138 section_remove_param (struct config_section_s *section, const char *name)
140 unsigned i, t = slist_length (section->params);
142 for (i = 0; i < t; i++)
144 struct config_param_s *p = slist_nth_data (section->params, i);
146 if (!p)
147 continue;
149 if (!strcmp (p->name, name))
151 switch (p->type)
153 case PARAM_CHARP:
154 xfree (p->value.cptype);
155 break;
156 case PARAM_CHARPP:
157 strv_free (p->value.cpptype);
158 break;
161 section->params = slist_remove (section->params, p);
162 xfree (p->name);
163 xfree (p);
164 break;
169 static struct config_param_s *
170 config_has_param (struct config_section_s *s, const char *what)
172 unsigned i, t = slist_length (s->params);
174 for (i = 0; i < t; i++)
176 struct config_param_s *p = slist_nth_data (s->params, i);
177 if (!p)
178 break;
180 if (!strcmp (p->name, what))
181 return p;
184 return NULL;
187 static struct config_param_s *
188 config_get_param (struct slist_s *config,
189 const char *section, const char *what, int *exists)
191 unsigned i, t = slist_length (config);
193 *exists = 0;
195 for (i = 0; i < t; i++)
197 struct config_param_s *p;
198 struct config_section_s *s = slist_nth_data (config, i);
200 if (!s)
201 break;
203 if (strcmp (s->name, section))
204 continue;
206 p = config_has_param (s, what);
207 if (!p)
208 return NULL;
210 *exists = 1;
211 return p;
214 return NULL;
217 static struct config_section_s *
218 new_section (struct slist_s **config, const char *name)
220 struct slist_s *tmp;
221 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
223 if (!s)
224 return NULL;
226 s->name = str_dup (name);
227 if (!s->name)
229 log_write ("%s", pwmd_strerror (ENOMEM));
230 xfree (s);
231 return NULL;
234 tmp = slist_append (*config, s);
235 if (!tmp)
237 log_write ("%s", pwmd_strerror (ENOMEM));
238 xfree (s->name);
239 xfree (s);
240 return NULL;
243 *config = tmp;
244 return s;
248 config_set_string_param (struct slist_s **config, const char *section,
249 const char *name, const char *value)
251 struct config_section_s *s = config_find_section (*config, section);
253 if (!s)
255 s = new_section (config, section);
256 if (!s)
257 return 1;
260 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
263 char *
264 config_get_string_param (struct slist_s *config, const char *section,
265 const char *what, int *exists)
267 struct config_param_s *p = config_get_param (config, section, what, exists);
268 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
272 config_set_int_param (struct slist_s **config, const char *section,
273 const char *name, const char *value)
275 struct config_section_s *s = config_find_section (*config, section);
277 if (!s)
279 s = new_section (config, section);
280 if (!s)
281 return 1;
284 return new_param (s, NULL, 0, name, value, PARAM_INT);
288 config_get_int_param (struct slist_s *config, const char *section,
289 const char *what, int *exists)
291 struct config_param_s *p = config_get_param (config, section, what, exists);
292 return *exists ? p->value.itype : -1;
296 config_set_bool_param (struct slist_s **config, const char *section,
297 const char *name, const char *value)
299 struct config_section_s *s = config_find_section (*config, section);
301 if (!s)
303 s = new_section (config, section);
304 if (!s)
305 return 1;
308 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
312 config_get_bool_param (struct slist_s *config, const char *section,
313 const char *what, int *exists)
315 return config_get_int_param (config, section, what, exists);
319 config_set_long_param (struct slist_s **config, const char *section,
320 const char *name, const char *value)
322 struct config_section_s *s = config_find_section (*config, section);
324 if (!s)
326 s = new_section (config, section);
327 if (!s)
328 return 1;
331 return new_param (s, NULL, 0, name, value, PARAM_LONG);
334 long
335 config_get_long_param (struct slist_s *config, const char *section,
336 const char *what, int *exists)
338 struct config_param_s *p = config_get_param (config, section, what, exists);
339 return *exists ? p->value.ltype : -1;
343 config_set_longlong_param (struct slist_s **config, const char *section,
344 const char *name, const char *value)
346 struct config_section_s *s = config_find_section (*config, section);
348 if (!s)
350 s = new_section (config, section);
351 if (!s)
352 return 1;
355 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
358 long long
359 config_get_longlong_param (struct slist_s *config,
360 const char *section, const char *what, int *exists)
362 struct config_param_s *p = config_get_param (config, section, what, exists);
363 return *exists ? p->value.lltype : -1;
367 config_set_list_param (struct slist_s **config, const char *section,
368 const char *name, const char *value)
370 struct config_section_s *s = config_find_section (*config, section);
372 if (!s)
374 s = new_section (config, section);
375 if (!s)
376 return 1;
379 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
382 char **
383 config_get_list_param (struct slist_s *config, const char *section,
384 const char *what, int *exists)
386 struct config_param_s *p = config_get_param (config, section, what, exists);
387 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
390 char *
391 config_get_string (const char *section, const char *what)
393 char *val = NULL;
394 const char *where = section ? section : "global";
395 int exists = 0;
397 MUTEX_LOCK (&rcfile_mutex);
398 val = config_get_string_param (global_config, where, what, &exists);
399 if (!exists && strcmp (section ? section : "", "global"))
400 val = config_get_string_param (global_config, "global", what, &exists);
402 MUTEX_UNLOCK (&rcfile_mutex);
403 return val;
406 char **
407 config_get_list (const char *section, const char *what)
409 char **val = NULL;
410 const char *where = section ? section : "global";
411 int exists = 0;
413 MUTEX_LOCK (&rcfile_mutex);
414 val = config_get_list_param (global_config, where, what, &exists);
415 if (!exists && strcmp (section ? section : "", "global"))
416 val = config_get_list_param (global_config, "global", what, &exists);
418 MUTEX_UNLOCK (&rcfile_mutex);
419 return val;
423 config_get_integer (const char *section, const char *what)
425 int val = 0;
426 const char *where = section ? section : "global";
427 int exists = 0;
429 MUTEX_LOCK (&rcfile_mutex);
430 val = config_get_int_param (global_config, where, what, &exists);
431 if (!exists && strcmp (section ? section : "", "global"))
432 val = config_get_int_param (global_config, "global", what, &exists);
434 MUTEX_UNLOCK (&rcfile_mutex);
435 return val;
438 long long
439 config_get_longlong (const char *section, const char *what)
441 long long val = 0;
442 const char *where = section ? section : "global";
443 int exists = 0;
445 MUTEX_LOCK (&rcfile_mutex);
446 val = config_get_longlong_param (global_config, where, what, &exists);
447 if (!exists && strcmp (section ? section : "", "global"))
448 val = config_get_longlong_param (global_config, "global", what, &exists);
450 MUTEX_UNLOCK (&rcfile_mutex);
451 return val;
454 long
455 config_get_long (const char *section, const char *what)
457 long val = 0;
458 const char *where = section ? section : "global";
459 int exists = 0;
461 MUTEX_LOCK (&rcfile_mutex);
462 val = config_get_long_param (global_config, where, what, &exists);
463 if (!exists && strcmp (section ? section : "", "global"))
464 val = config_get_long_param (global_config, "global", what, &exists);
466 MUTEX_UNLOCK (&rcfile_mutex);
467 return val;
471 config_get_boolean (const char *section, const char *what)
473 return config_get_integer (section, what);
476 char *
477 config_get_value (const char *section, const char *what)
479 const char *where = section ? section : "global";
480 int exists = 0;
481 int i;
482 int ival;
483 long lval;
484 long long llval;
485 char *cpval;
486 char **cppval;
487 char *result = NULL;
489 MUTEX_LOCK (&rcfile_mutex);
491 for (i = 0; config_params[i].name; i++)
493 if (!strcmp (config_params[i].name, what))
495 switch (config_params[i].type)
497 case PARAM_BOOL:
498 case PARAM_INT:
499 ival = config_get_int_param (global_config, where, what,
500 &exists);
501 if (!exists && strcmp (section ? section : "", "global"))
502 ival = config_get_int_param (global_config, "global", what,
503 &exists);
504 result = str_asprintf ("%i", ival);
505 break;
506 case PARAM_CHARP:
507 cpval = config_get_string_param (global_config, where, what,
508 &exists);
509 if (!exists && strcmp (section ? section : "", "global"))
510 cpval =
511 config_get_string_param (global_config, "global", what,
512 &exists);
513 result = cpval;
514 break;
515 case PARAM_LONG:
516 lval = config_get_long_param (global_config, where, what,
517 &exists);
518 if (!exists && strcmp (section ? section : "", "global"))
519 lval = config_get_long_param (global_config, "global", what,
520 &exists);
521 result = str_asprintf ("%li", lval);
522 break;
523 case PARAM_LONGLONG:
524 llval = config_get_longlong_param (global_config, where, what,
525 &exists);
526 if (!exists && strcmp (section ? section : "", "global"))
527 llval = config_get_longlong_param (global_config, "global",
528 what, &exists);
529 result = str_asprintf ("%lli", llval);
530 break;
531 case PARAM_CHARPP:
532 cppval = config_get_list_param (global_config, where, what,
533 &exists);
534 if (!exists && strcmp (section ? section : "", "global"))
535 cppval = config_get_list_param (global_config, "global", what,
536 &exists);
538 if (cppval)
539 result = strv_join (",", cppval);
541 strv_free (cppval);
542 break;
547 MUTEX_UNLOCK (&rcfile_mutex);
548 return result;
551 /* 'file' is the list parameter file to load into the list parameter 'what'.
552 * The parsing of the parameter is not done here. */
553 static gpg_error_t
554 parse_list_file (struct slist_s *config, const char *section,
555 const char *file, const char *what)
557 FILE *fp;
558 char buf[LINE_MAX] = {0};
559 int exists;
560 char **list = NULL;
561 char *tmp;
562 char *p = config_get_string_param (config, section, file, &exists);
563 gpg_error_t rc;
565 if (!p || !*p)
567 xfree (p);
568 return 0;
571 tmp = expand_homedir (p);
572 xfree (p);
573 p = tmp;
574 fp = fopen (p, "r");
575 if (!fp)
577 rc = gpg_error_from_errno (errno);
578 log_write ("%s: %s", p, pwmd_strerror (rc));
579 xfree (p);
580 return rc;
583 xfree (p);
584 list = config_get_list_param (config, section, what, &exists);
585 if (!list && exists)
587 fclose (fp);
588 log_write ("%s", pwmd_strerror (ENOMEM));
589 return gpg_error (ENOMEM);
592 while ((p = fgets (buf, sizeof (buf)-1, fp)))
594 char **pp = NULL;
596 if (p[strlen(p)-1] == '\n')
597 p[strlen(p)-1] = 0;
599 while (*p && isspace (*p))
600 p++;
602 if (!*p || *p == ';')
603 continue;
605 tmp = str_dup (p);
606 if (tmp)
607 pp = strv_cat (list, str_dup (p));
609 if (!pp || !tmp)
611 xfree (tmp);
612 strv_free (list);
613 fclose (fp);
614 log_write ("%s", strerror (ENOMEM));
615 return gpg_error (ENOMEM);
618 xfree (tmp);
619 list = pp;
622 fclose(fp);
623 if (!list)
624 return 0;
626 p = strv_join (",", list);
627 strv_free (list);
629 if (!p)
631 log_write ("%s", pwmd_strerror (ENOMEM));
632 return gpg_error (ENOMEM);
635 config_set_list_param (&config, section, what, p);
636 xfree (p);
637 return 0;
640 static int
641 fixup_allowed_once (struct slist_s **config, const char *section)
643 char **list, **pp, *p;
644 int exists;
645 gpg_error_t rc;
647 rc = parse_list_file (*config, section, "allowed_file", "allowed");
648 if (rc)
649 return 1;
651 list = config_get_list_param (*config, section, "allowed", &exists);
652 for (pp = list; pp && *pp; pp++)
654 if (*(*pp) == '#')
656 for (p = *pp; p && *p; p++)
657 *p = toupper(*p);
661 strv_free (list);
662 if (!exists)
664 if (!strcmp (section, "global"))
666 p = get_username (getuid());
668 if (config_set_list_param (config, section, "allowed", p))
670 xfree (p);
671 return 1;
674 xfree (p);
676 else
678 list = config_get_list_param (*config, "global", "allowed", &exists);
679 if (list)
681 p = strv_join (",", list);
682 strv_free (list);
683 if (config_set_list_param (config, section, "allowed", p))
685 xfree (p);
686 return 1;
689 xfree (p);
694 return 0;
697 static int
698 fixup_allowed (struct slist_s **config)
700 int n, t = slist_length (*config);
702 for (n = 0; n < t; n++)
704 struct config_section_s *section;
706 section = slist_nth_data (*config, n);
707 if (fixup_allowed_once (config, section->name))
708 return 1;
711 return 0;
714 static int
715 add_invoking_user (struct invoking_user_s **users, char *id,
716 struct slist_s **config)
718 struct passwd *pwd = NULL;
719 struct group *grp = NULL;
720 struct invoking_user_s *user, *p;
721 int not = 0;
723 if (id && (*id == '!' || *id == '-'))
725 not = 1;
726 id++;
729 errno = 0;
730 if (!id || !*id)
732 pwd = getpwuid (getuid ());
733 if (!pwd)
735 log_write (_("could not set any invoking user: %s"),
736 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
737 return 1;
740 else if (*id == '@')
742 grp = getgrnam (id+1);
743 if (!grp)
745 log_write (_("could not parse group '%s': %s"), id+1,
746 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
747 return 1;
750 else if (*id != '#')
751 pwd = getpwnam (id);
753 if (!grp && !pwd && id && *id != '#')
755 if (id && *id)
756 log_write (_("could not set invoking user '%s': %s"), id,
757 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
758 else
759 log_write (_("could not set any invoking user!"));
761 return 1;
764 user = xcalloc (1, sizeof (struct invoking_user_s));
765 if (!user)
767 log_write ("%s", pwmd_strerror (ENOMEM));
768 return 1;
771 user->not = not;
772 user->type = pwd ? INVOKING_UID : grp ? INVOKING_GID : INVOKING_TLS;
773 if (pwd)
774 user->uid = pwd->pw_uid;
775 else if (grp)
776 user->id = str_dup (id+1);
777 else
779 char *s;
781 for (s = id; s && *s; s++)
782 *s = toupper(*s);
784 user->id = str_dup (id+1);
787 /* Set the default invoking_user since it doesn't exist. */
788 if (pwd && (!id || !*id))
789 config_set_list_param (config, "global", "invoking_user", pwd->pw_name);
791 if (!*users)
793 *users = user;
794 return 0;
797 for (p = *users; p; p = p->next)
799 if (!p->next)
801 p->next = user;
802 break;
806 return 0;
809 static int
810 parse_invoking_users (struct slist_s **config)
812 struct invoking_user_s *users = NULL;
813 int exists;
814 char **list, **l;
816 if (parse_list_file (*config, "global", "invoking_file", "invoking_user"))
817 return 1;
819 list = config_get_list_param (*config, "global", "invoking_user", &exists);
820 for (l = list; l && *l; l++)
822 if (add_invoking_user (&users, *l, config))
824 strv_free (list);
825 free_invoking_users (users);
826 return 1;
830 if (!list || !*list)
832 if (add_invoking_user (&users, NULL, config))
834 strv_free (list);
835 return 1;
839 free_invoking_users (invoking_users);
840 invoking_users = users;
841 strv_free (list);
842 return 0;
845 static int
846 set_defaults (struct slist_s **config, int reload)
848 char *s = NULL;
849 char **list;
850 int exists;
851 int i;
853 for (i = 0; config_params[i].name; i++)
855 switch (config_params[i].type)
857 case PARAM_BOOL:
858 config_get_bool_param (*config, "global", config_params[i].name,
859 &exists);
860 if (!exists)
862 if (config_set_bool_param
863 (config, "global", config_params[i].name,
864 config_params[i].value))
865 goto fail;
867 break;
868 case PARAM_INT:
869 config_get_int_param (*config, "global", config_params[i].name,
870 &exists);
871 if (!exists)
873 if (config_set_int_param
874 (config, "global", config_params[i].name,
875 config_params[i].value))
876 goto fail;
878 break;
879 case PARAM_CHARP:
880 s = config_get_string_param (*config, "global",
881 config_params[i].name, &exists);
882 xfree (s);
883 if (!exists && config_params[i].value)
885 if (config_set_string_param (config, "global",
886 config_params[i].name,
887 config_params[i].value))
888 goto fail;
890 break;
891 case PARAM_CHARPP:
892 list = config_get_list_param (*config, "global",
893 config_params[i].name, &exists);
894 strv_free (list);
895 if (!exists && config_params[i].value)
897 if (config_set_list_param (config, "global",
898 config_params[i].name,
899 config_params[i].value))
900 goto fail;
902 break;
903 case PARAM_LONG:
904 config_get_long_param (*config, "global", config_params[i].name,
905 &exists);
906 if (!exists)
908 if (config_set_long_param
909 (config, "global", config_params[i].name,
910 config_params[i].value))
911 goto fail;
913 break;
914 case PARAM_LONGLONG:
915 config_get_longlong_param (*config, "global", config_params[i].name,
916 &exists);
917 if (!exists)
919 if (config_set_longlong_param (config, "global",
920 config_params[i].name,
921 config_params[i].value))
922 goto fail;
924 break;
928 s = NULL;
929 if (!reload && fixup_allowed (config))
930 goto fail;
932 if (!reload && parse_invoking_users (config))
933 goto fail;
935 log_level = config_get_int_param (*config, "global",
936 "log_level", &exists);
937 log_keepopen = config_get_int_param (*config, "global",
938 "log_keepopen", &exists);
939 max_recursion_depth = config_get_int_param (*config, "global",
940 "recursion_depth", &exists);
941 disable_list_and_dump = config_get_bool_param (*config, "global",
942 "disable_list_and_dump",
943 &exists);
944 #ifdef HAVE_MLOCKALL
945 disable_mlock =
946 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
947 #endif
949 xfree (s);
950 return 0;
952 fail:
953 xfree (s);
954 return 1;
957 static struct config_section_s *
958 config_find_section (struct slist_s *config, const char *name)
960 unsigned i, t = slist_length (config);
962 for (i = 0; i < t; i++)
964 struct config_section_s *s = slist_nth_data (config, i);
966 if (!strcmp (s->name, name))
967 return s;
970 return NULL;
973 /* Append a new parameter to the list of parameters for a file
974 * section. When an existing parameter of the same name exists, its
975 * value is updated.
977 static int
978 new_param (struct config_section_s *section, const char *filename, int lineno,
979 const char *name, const char *value, int type)
981 struct config_param_s *param = NULL;
982 struct slist_s *tmp;
983 char *e;
984 unsigned i, t = slist_length (section->params);
985 int dup = 0;
987 for (i = 0; i < t; i++)
989 struct config_param_s *p = slist_nth_data (section->params, i);
990 if (!p)
991 break;
993 if (!strcmp (name, p->name))
995 param = p;
996 dup = 1;
997 break;
1001 if (!param)
1003 param = xcalloc (1, sizeof (struct config_param_s));
1004 if (!param)
1006 log_write ("%s", pwmd_strerror (ENOMEM));
1007 return 1;
1010 param->name = str_dup (name);
1011 if (!param->name)
1013 xfree (param);
1014 log_write ("%s", pwmd_strerror (ENOMEM));
1015 return 1;
1019 param->type = type;
1021 switch (type)
1023 case PARAM_BOOL:
1024 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1025 || !strcasecmp (value, "false"))
1026 param->value.itype = 0;
1027 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1028 || !strcasecmp (value, "true"))
1029 param->value.itype = 1;
1030 else
1032 INVALID_VALUE (filename, lineno);
1033 goto fail;
1035 param->type = PARAM_INT;
1036 break;
1037 case PARAM_CHARP:
1038 xfree (param->value.cptype);
1039 param->value.cptype = NULL;
1040 param->value.cptype = value && *value ? str_dup (value) : NULL;
1041 if (value && *value && !param->value.cptype)
1043 log_write ("%s", pwmd_strerror (ENOMEM));
1044 goto fail;
1046 break;
1047 case PARAM_CHARPP:
1048 strv_free (param->value.cpptype);
1049 param->value.cpptype = NULL;
1050 param->value.cpptype = value && *value ?
1051 str_split_ws (value, ",", 0) : NULL;
1052 if (value && *value && !param->value.cpptype)
1054 log_write ("%s", pwmd_strerror (ENOMEM));
1055 goto fail;
1057 break;
1058 case PARAM_INT:
1059 param->value.itype = strtol (value, &e, 10);
1060 if (e && *e)
1062 INVALID_VALUE (filename, lineno);
1063 goto fail;
1065 break;
1066 case PARAM_LONG:
1067 param->value.ltype = strtol (value, &e, 10);
1068 if (e && *e)
1070 INVALID_VALUE (filename, lineno);
1071 goto fail;
1073 break;
1074 case PARAM_LONGLONG:
1075 param->value.lltype = strtoll (value, &e, 10);
1076 if (e && *e)
1078 INVALID_VALUE (filename, lineno);
1079 goto fail;
1081 break;
1084 if (dup)
1085 return 0;
1087 tmp = slist_append (section->params, param);
1088 if (!tmp)
1090 log_write ("%s", pwmd_strerror (ENOMEM));
1091 goto fail;
1094 section->params = tmp;
1095 return 0;
1097 fail:
1098 xfree (param->name);
1099 xfree (param);
1100 return 1;
1103 struct slist_s *
1104 config_parse (const char *filename, int reload)
1106 struct slist_s *tmpconfig = NULL, *tmp;
1107 struct config_section_s *cur_section = NULL;
1108 char buf[LINE_MAX] = {0};
1109 char *s;
1110 int lineno = 1;
1111 int have_global = 0;
1112 FILE *fp = fopen (filename, "r");
1114 if (!fp)
1116 log_write ("%s: %s", filename,
1117 pwmd_strerror (gpg_error_from_errno (errno)));
1119 if (errno != ENOENT)
1120 return NULL;
1122 log_write (_("Using defaults!"));
1123 goto defaults;
1126 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
1128 char line[LINE_MAX] = { 0 };
1129 size_t len = 0;
1130 int match = 0;
1132 if (*s == '#')
1133 continue;
1135 s = str_chomp (s);
1136 if (!*s)
1137 continue;
1139 /* New file section. */
1140 if (*s == '[')
1142 struct config_section_s *section;
1143 char *p = strchr (++s, ']');
1145 if (!p)
1147 log_write (_("%s(%i): unbalanced braces"), filename, lineno);
1148 goto fail;
1151 if (*(p+1))
1153 log_write (_("%s(%i): trailing characters"), filename, lineno);
1154 goto fail;
1157 len = strlen (s) - strlen (p);
1158 memcpy (line, s, len);
1159 line[len] = 0;
1161 section = config_find_section (tmpconfig, line);
1162 if (section)
1164 log_write (_("%s(%i): section '%s' already exists!"),
1165 filename, lineno, line);
1166 goto fail;
1169 if (!strcmp (line, "global"))
1170 have_global = 1;
1172 section = xcalloc (1, sizeof (struct config_section_s));
1173 section->name = str_dup (line);
1175 if (cur_section)
1177 tmp = slist_append (tmpconfig, cur_section);
1178 if (!tmp)
1180 log_write ("%s", pwmd_strerror (ENOMEM));
1181 goto fail;
1184 tmpconfig = tmp;
1187 cur_section = section;
1188 continue;
1191 if (!cur_section)
1193 log_write (_("%s(%i): parameter outside of section!"), filename,
1194 lineno);
1195 goto fail;
1198 /* Parameters for each section. */
1199 for (int m = 0; config_params[m].name; m++)
1201 len = strlen (config_params[m].name);
1202 if (!strncmp (s, config_params[m].name, len))
1204 char *p = s + len;
1206 while (*p && *p == ' ')
1207 p++;
1209 if (!*p || *p != '=')
1210 continue;
1212 p++;
1213 while (*p && isspace (*p))
1214 p++;
1216 s[len] = 0;
1217 if (new_param (cur_section, filename, lineno, s, p,
1218 config_params[m].type))
1219 goto fail;
1221 match = 1;
1222 break;
1226 if (!match)
1228 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1229 goto fail;
1233 if (cur_section)
1235 tmp = slist_append (tmpconfig, cur_section);
1236 if (!tmp)
1238 log_write ("%s", pwmd_strerror (ENOMEM));
1239 goto fail;
1242 cur_section = NULL;
1243 tmpconfig = tmp;
1246 if (!have_global)
1247 log_write (_
1248 ("WARNING: %s: could not find a [global] configuration section!"),
1249 filename);
1251 defaults:
1252 if (set_defaults (&tmpconfig, reload))
1253 goto fail;
1255 if (fp)
1256 fclose(fp);
1258 return tmpconfig;
1260 fail:
1261 if (fp)
1262 fclose (fp);
1264 config_free (tmpconfig);
1265 free_section (cur_section);
1266 return NULL;
1269 static void
1270 free_section (struct config_section_s *s)
1272 if (!s)
1273 return;
1275 for (;;)
1277 struct config_param_s *p = slist_nth_data (s->params, 0);
1279 if (!p)
1280 break;
1282 section_remove_param (s, p->name);
1285 s->params = NULL;
1286 xfree (s->name);
1287 s->name = NULL;
1290 void
1291 config_free (struct slist_s *config)
1293 for (;;)
1295 struct config_section_s *s = slist_nth_data (config, 0);
1296 if (!s)
1297 break;
1299 free_section (s);
1300 config = slist_remove (config, s);
1301 xfree (s);
1305 void
1306 free_invoking_users (struct invoking_user_s *users)
1308 struct invoking_user_s *p;
1310 for (p = users; p;)
1312 struct invoking_user_s *next = p->next;
1314 if (p->type == INVOKING_TLS || p->type == INVOKING_GID)
1315 xfree (p->id);
1317 xfree (p);
1318 p = next;
1322 static int
1323 param_type (const char *name)
1325 int i;
1327 for (i = 0; config_params[i].name; i++)
1329 if (!strcmp (config_params[i].name, name))
1330 return config_params[i].type;
1333 return PARAM_INVALID;
1336 static int
1337 keep_parse (struct config_keep_s *k, const char *section, const char *key)
1339 int exists;
1340 int ival;
1341 long lval;
1342 long long llval;
1343 char *cpval;
1344 char **cppval;
1345 int type = param_type (key);
1346 void *value = NULL;
1348 switch (type)
1350 case PARAM_BOOL:
1351 case PARAM_INT:
1352 ival = config_get_int_param (global_config, section, key, &exists);
1353 if (exists)
1354 value = str_asprintf ("%i", ival);
1355 break;
1356 case PARAM_LONG:
1357 lval = config_get_long_param (global_config, section, key, &exists);
1358 if (exists)
1359 value = str_asprintf ("%li", lval);
1360 break;
1361 case PARAM_LONGLONG:
1362 llval = config_get_longlong_param (global_config, section, key, &exists);
1363 if (exists)
1364 value = str_asprintf ("%lli", llval);
1365 break;
1366 case PARAM_CHARP:
1367 cpval = config_get_string_param (global_config, section, key, &exists);
1368 if (exists)
1369 value = cpval;
1370 break;
1371 case PARAM_CHARPP:
1372 cppval = config_get_list_param (global_config, section, key, &exists);
1373 if (exists)
1375 char *s = strv_join (",", cppval);
1377 strv_free (cppval);
1378 value = s;
1380 break;
1381 default:
1382 return 1;
1385 if (!value)
1386 return 1;
1388 k->section = str_dup(section);
1389 k->name = str_dup(key);
1390 k->value = value;
1391 return 0;
1394 static struct slist_s *
1395 keep_add (struct slist_s *k, const char *s, const char *key)
1397 int n, t = slist_length (global_config);
1399 for (n = 0; n < t; n++)
1401 struct config_section_s *section;
1402 struct config_keep_s *tmp;
1403 int ret;
1405 section = slist_nth_data (global_config, n);
1406 tmp = xcalloc (1, sizeof(struct config_keep_s));
1408 // Process all sections.
1409 if (!s)
1410 ret = keep_parse (tmp, section->name, key);
1411 else
1412 ret = keep_parse (tmp, s, key);
1414 if (!ret)
1415 k = slist_append (k, tmp);
1416 else
1417 xfree (tmp);
1420 return k;
1423 /* Keep security sensitive settings across SIGHUP. */
1424 struct slist_s *
1425 config_keep_save ()
1427 struct slist_s *keep = NULL;
1429 #ifdef WITH_GNUTLS
1430 keep = keep_add (keep, NULL, "tcp_require_key");
1431 #endif
1432 keep = keep_add (keep, NULL, "require_save_key");
1433 keep = keep_add (keep, NULL, "allowed");
1434 keep = keep_add (keep, NULL, "allowed_file");
1435 keep = keep_add (keep, "global", "encrypt_to");
1436 keep = keep_add (keep, "global", "always_trust");
1437 keep = keep_add (keep, "global", "invoking_user");
1438 keep = keep_add (keep, "global", "invoking_file");
1439 keep = keep_add (keep, "global", "gpg_homedir");
1440 return keep;
1443 /* Restore parameters previously saved with config_keep_save(). This will also
1444 * free the 'keep'.
1446 void
1447 config_keep_restore (struct slist_s *keep)
1449 int n, t = slist_length (keep);
1451 for (n = 0; n < t; n++)
1453 struct config_keep_s *k = slist_nth_data (keep, n);
1454 int type = param_type (k->name);
1456 switch (type)
1458 case PARAM_BOOL:
1459 config_set_bool_param (&global_config, k->section, k->name, k->value);
1460 break;
1461 case PARAM_INT:
1462 config_set_int_param (&global_config, k->section, k->name, k->value);
1463 break;
1464 case PARAM_LONG:
1465 config_set_long_param (&global_config, k->section, k->name, k->value);
1466 break;
1467 case PARAM_LONGLONG:
1468 config_set_longlong_param (&global_config, k->section, k->name,
1469 k->value);
1470 break;
1471 case PARAM_CHARP:
1472 config_set_string_param (&global_config, k->section, k->name,
1473 k->value);
1474 break;
1475 case PARAM_CHARPP:
1476 config_set_list_param (&global_config, k->section, k->name, k->value);
1477 break;
1478 default:
1479 break;
1482 xfree (k->section);
1483 xfree (k->name);
1484 xfree (k->value);
1485 xfree (k);
1488 slist_free (keep);