Revert "Remove the "tls_use_crl" configuration parameter."
[pwmd.git] / src / rcfile.c
blobc59745e0fe489159523ece9354295a1ed43eac63
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 { "tls_use_crl", PARAM_BOOL, "1"},
96 { "require_save_key", PARAM_BOOL, "true"},
97 { "invoking_user", PARAM_CHARPP, NULL},
98 { "invoking_file", PARAM_CHARP, NULL},
99 { "encrypt_to", PARAM_BOOL, "false"},
100 { "always_trust", PARAM_BOOL, "false"},
101 { "gpg_homedir", PARAM_CHARP, NULL},
102 { "strict_kill", PARAM_BOOL, "false"},
103 { "lock_timeout", PARAM_LONG, DEFAULT_LOCK_TIMEOUT},
104 { "kill_scd", PARAM_BOOL, "false"},
105 { "strict_open", PARAM_BOOL, "false"},
106 { NULL, PARAM_INVALID, NULL},
109 struct config_param_s
111 char *name;
112 int type;
113 union
115 int itype;
116 char *cptype;
117 char **cpptype;
118 long ltype;
119 long long lltype;
120 } value;
123 struct config_keep_s
125 char *section;
126 char *name;
127 char *value;
130 static struct config_section_s *config_find_section (struct slist_s *config,
131 const char *name);
132 static int new_param (struct config_section_s *section, const char *filename,
133 int lineno, const char *name, const char *value,
134 int type);
135 static void free_section (struct config_section_s *s);
136 static int set_defaults (struct slist_s **config, int reload);
138 static void
139 section_remove_param (struct config_section_s *section, const char *name)
141 unsigned i, t = slist_length (section->params);
143 for (i = 0; i < t; i++)
145 struct config_param_s *p = slist_nth_data (section->params, i);
147 if (!p)
148 continue;
150 if (!strcmp (p->name, name))
152 switch (p->type)
154 case PARAM_CHARP:
155 xfree (p->value.cptype);
156 break;
157 case PARAM_CHARPP:
158 strv_free (p->value.cpptype);
159 break;
162 section->params = slist_remove (section->params, p);
163 xfree (p->name);
164 xfree (p);
165 break;
170 static struct config_param_s *
171 config_has_param (struct config_section_s *s, const char *what)
173 unsigned i, t = slist_length (s->params);
175 for (i = 0; i < t; i++)
177 struct config_param_s *p = slist_nth_data (s->params, i);
178 if (!p)
179 break;
181 if (!strcmp (p->name, what))
182 return p;
185 return NULL;
188 static struct config_param_s *
189 config_get_param (struct slist_s *config,
190 const char *section, const char *what, int *exists)
192 unsigned i, t = slist_length (config);
194 *exists = 0;
196 for (i = 0; i < t; i++)
198 struct config_param_s *p;
199 struct config_section_s *s = slist_nth_data (config, i);
201 if (!s)
202 break;
204 if (strcmp (s->name, section))
205 continue;
207 p = config_has_param (s, what);
208 if (!p)
209 return NULL;
211 *exists = 1;
212 return p;
215 return NULL;
218 static struct config_section_s *
219 new_section (struct slist_s **config, const char *name)
221 struct slist_s *tmp;
222 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
224 if (!s)
225 return NULL;
227 s->name = str_dup (name);
228 if (!s->name)
230 log_write ("%s", pwmd_strerror (ENOMEM));
231 xfree (s);
232 return NULL;
235 tmp = slist_append (*config, s);
236 if (!tmp)
238 log_write ("%s", pwmd_strerror (ENOMEM));
239 xfree (s->name);
240 xfree (s);
241 return NULL;
244 *config = tmp;
245 return s;
249 config_set_string_param (struct slist_s **config, const char *section,
250 const char *name, const char *value)
252 struct config_section_s *s = config_find_section (*config, section);
254 if (!s)
256 s = new_section (config, section);
257 if (!s)
258 return 1;
261 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
264 char *
265 config_get_string_param (struct slist_s *config, const char *section,
266 const char *what, int *exists)
268 struct config_param_s *p = config_get_param (config, section, what, exists);
269 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
273 config_set_int_param (struct slist_s **config, const char *section,
274 const char *name, const char *value)
276 struct config_section_s *s = config_find_section (*config, section);
278 if (!s)
280 s = new_section (config, section);
281 if (!s)
282 return 1;
285 return new_param (s, NULL, 0, name, value, PARAM_INT);
289 config_get_int_param (struct slist_s *config, const char *section,
290 const char *what, int *exists)
292 struct config_param_s *p = config_get_param (config, section, what, exists);
293 return *exists ? p->value.itype : -1;
297 config_set_bool_param (struct slist_s **config, const char *section,
298 const char *name, const char *value)
300 struct config_section_s *s = config_find_section (*config, section);
302 if (!s)
304 s = new_section (config, section);
305 if (!s)
306 return 1;
309 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
313 config_get_bool_param (struct slist_s *config, const char *section,
314 const char *what, int *exists)
316 return config_get_int_param (config, section, what, exists);
320 config_set_long_param (struct slist_s **config, const char *section,
321 const char *name, const char *value)
323 struct config_section_s *s = config_find_section (*config, section);
325 if (!s)
327 s = new_section (config, section);
328 if (!s)
329 return 1;
332 return new_param (s, NULL, 0, name, value, PARAM_LONG);
335 long
336 config_get_long_param (struct slist_s *config, const char *section,
337 const char *what, int *exists)
339 struct config_param_s *p = config_get_param (config, section, what, exists);
340 return *exists ? p->value.ltype : -1;
344 config_set_longlong_param (struct slist_s **config, const char *section,
345 const char *name, const char *value)
347 struct config_section_s *s = config_find_section (*config, section);
349 if (!s)
351 s = new_section (config, section);
352 if (!s)
353 return 1;
356 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
359 long long
360 config_get_longlong_param (struct slist_s *config,
361 const char *section, const char *what, int *exists)
363 struct config_param_s *p = config_get_param (config, section, what, exists);
364 return *exists ? p->value.lltype : -1;
368 config_set_list_param (struct slist_s **config, const char *section,
369 const char *name, const char *value)
371 struct config_section_s *s = config_find_section (*config, section);
373 if (!s)
375 s = new_section (config, section);
376 if (!s)
377 return 1;
380 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
383 char **
384 config_get_list_param (struct slist_s *config, const char *section,
385 const char *what, int *exists)
387 struct config_param_s *p = config_get_param (config, section, what, exists);
388 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
391 char *
392 config_get_string (const char *section, const char *what)
394 char *val = NULL;
395 const char *where = section ? section : "global";
396 int exists = 0;
398 MUTEX_LOCK (&rcfile_mutex);
399 val = config_get_string_param (global_config, where, what, &exists);
400 if (!exists && strcmp (section ? section : "", "global"))
401 val = config_get_string_param (global_config, "global", what, &exists);
403 MUTEX_UNLOCK (&rcfile_mutex);
404 return val;
407 char **
408 config_get_list (const char *section, const char *what)
410 char **val = NULL;
411 const char *where = section ? section : "global";
412 int exists = 0;
414 MUTEX_LOCK (&rcfile_mutex);
415 val = config_get_list_param (global_config, where, what, &exists);
416 if (!exists && strcmp (section ? section : "", "global"))
417 val = config_get_list_param (global_config, "global", what, &exists);
419 MUTEX_UNLOCK (&rcfile_mutex);
420 return val;
424 config_get_integer (const char *section, const char *what)
426 int val = 0;
427 const char *where = section ? section : "global";
428 int exists = 0;
430 MUTEX_LOCK (&rcfile_mutex);
431 val = config_get_int_param (global_config, where, what, &exists);
432 if (!exists && strcmp (section ? section : "", "global"))
433 val = config_get_int_param (global_config, "global", what, &exists);
435 MUTEX_UNLOCK (&rcfile_mutex);
436 return val;
439 long long
440 config_get_longlong (const char *section, const char *what)
442 long long val = 0;
443 const char *where = section ? section : "global";
444 int exists = 0;
446 MUTEX_LOCK (&rcfile_mutex);
447 val = config_get_longlong_param (global_config, where, what, &exists);
448 if (!exists && strcmp (section ? section : "", "global"))
449 val = config_get_longlong_param (global_config, "global", what, &exists);
451 MUTEX_UNLOCK (&rcfile_mutex);
452 return val;
455 long
456 config_get_long (const char *section, const char *what)
458 long val = 0;
459 const char *where = section ? section : "global";
460 int exists = 0;
462 MUTEX_LOCK (&rcfile_mutex);
463 val = config_get_long_param (global_config, where, what, &exists);
464 if (!exists && strcmp (section ? section : "", "global"))
465 val = config_get_long_param (global_config, "global", what, &exists);
467 MUTEX_UNLOCK (&rcfile_mutex);
468 return val;
472 config_get_boolean (const char *section, const char *what)
474 return config_get_integer (section, what);
477 char *
478 config_get_value (const char *section, const char *what)
480 const char *where = section ? section : "global";
481 int exists = 0;
482 int i;
483 int ival;
484 long lval;
485 long long llval;
486 char *cpval;
487 char **cppval;
488 char *result = NULL;
490 MUTEX_LOCK (&rcfile_mutex);
492 for (i = 0; config_params[i].name; i++)
494 if (!strcmp (config_params[i].name, what))
496 switch (config_params[i].type)
498 case PARAM_BOOL:
499 case PARAM_INT:
500 ival = config_get_int_param (global_config, where, what,
501 &exists);
502 if (!exists && strcmp (section ? section : "", "global"))
503 ival = config_get_int_param (global_config, "global", what,
504 &exists);
505 result = str_asprintf ("%i", ival);
506 break;
507 case PARAM_CHARP:
508 cpval = config_get_string_param (global_config, where, what,
509 &exists);
510 if (!exists && strcmp (section ? section : "", "global"))
511 cpval =
512 config_get_string_param (global_config, "global", what,
513 &exists);
514 result = cpval;
515 break;
516 case PARAM_LONG:
517 lval = config_get_long_param (global_config, where, what,
518 &exists);
519 if (!exists && strcmp (section ? section : "", "global"))
520 lval = config_get_long_param (global_config, "global", what,
521 &exists);
522 result = str_asprintf ("%li", lval);
523 break;
524 case PARAM_LONGLONG:
525 llval = config_get_longlong_param (global_config, where, what,
526 &exists);
527 if (!exists && strcmp (section ? section : "", "global"))
528 llval = config_get_longlong_param (global_config, "global",
529 what, &exists);
530 result = str_asprintf ("%lli", llval);
531 break;
532 case PARAM_CHARPP:
533 cppval = config_get_list_param (global_config, where, what,
534 &exists);
535 if (!exists && strcmp (section ? section : "", "global"))
536 cppval = config_get_list_param (global_config, "global", what,
537 &exists);
539 if (cppval)
540 result = strv_join (",", cppval);
542 strv_free (cppval);
543 break;
548 MUTEX_UNLOCK (&rcfile_mutex);
549 return result;
552 /* 'file' is the list parameter file to load into the list parameter 'what'.
553 * The parsing of the parameter is not done here. */
554 static gpg_error_t
555 parse_list_file (struct slist_s *config, const char *section,
556 const char *file, const char *what)
558 FILE *fp;
559 char buf[LINE_MAX] = {0};
560 int exists;
561 char **list = NULL;
562 char *tmp;
563 char *p = config_get_string_param (config, section, file, &exists);
564 gpg_error_t rc;
566 if (!p || !*p)
568 xfree (p);
569 return 0;
572 tmp = expand_homedir (p);
573 xfree (p);
574 p = tmp;
575 fp = fopen (p, "r");
576 if (!fp)
578 rc = gpg_error_from_errno (errno);
579 log_write ("%s: %s", p, pwmd_strerror (rc));
580 xfree (p);
581 return rc;
584 xfree (p);
585 list = config_get_list_param (config, section, what, &exists);
586 if (!list && exists)
588 fclose (fp);
589 log_write ("%s", pwmd_strerror (ENOMEM));
590 return gpg_error (ENOMEM);
593 while ((p = fgets (buf, sizeof (buf)-1, fp)))
595 char **pp = NULL;
597 if (p[strlen(p)-1] == '\n')
598 p[strlen(p)-1] = 0;
600 while (*p && isspace (*p))
601 p++;
603 if (!*p || *p == ';')
604 continue;
606 tmp = str_dup (p);
607 if (tmp)
608 pp = strv_cat (list, str_dup (p));
610 if (!pp || !tmp)
612 xfree (tmp);
613 strv_free (list);
614 fclose (fp);
615 log_write ("%s", strerror (ENOMEM));
616 return gpg_error (ENOMEM);
619 xfree (tmp);
620 list = pp;
623 fclose(fp);
624 if (!list)
625 return 0;
627 p = strv_join (",", list);
628 strv_free (list);
630 if (!p)
632 log_write ("%s", pwmd_strerror (ENOMEM));
633 return gpg_error (ENOMEM);
636 config_set_list_param (&config, section, what, p);
637 xfree (p);
638 return 0;
641 static int
642 fixup_allowed_once (struct slist_s **config, const char *section)
644 char **list, **pp, *p;
645 int exists;
646 gpg_error_t rc;
648 rc = parse_list_file (*config, section, "allowed_file", "allowed");
649 if (rc)
650 return 1;
652 list = config_get_list_param (*config, section, "allowed", &exists);
653 for (pp = list; pp && *pp; pp++)
655 if (*(*pp) == '#')
657 for (p = *pp; p && *p; p++)
658 *p = toupper(*p);
662 strv_free (list);
663 if (!exists)
665 if (!strcmp (section, "global"))
667 p = get_username (getuid());
669 if (config_set_list_param (config, section, "allowed", p))
671 xfree (p);
672 return 1;
675 xfree (p);
677 else
679 list = config_get_list_param (*config, "global", "allowed", &exists);
680 if (list)
682 p = strv_join (",", list);
683 strv_free (list);
684 if (config_set_list_param (config, section, "allowed", p))
686 xfree (p);
687 return 1;
690 xfree (p);
695 return 0;
698 static int
699 fixup_allowed (struct slist_s **config)
701 int n, t = slist_length (*config);
703 for (n = 0; n < t; n++)
705 struct config_section_s *section;
707 section = slist_nth_data (*config, n);
708 if (fixup_allowed_once (config, section->name))
709 return 1;
712 return 0;
715 static int
716 add_invoking_user (struct invoking_user_s **users, char *id,
717 struct slist_s **config)
719 struct passwd *pwd = NULL;
720 struct group *grp = NULL;
721 struct invoking_user_s *user, *p;
722 int not = 0;
724 if (id && (*id == '!' || *id == '-'))
726 not = 1;
727 id++;
730 errno = 0;
731 if (!id || !*id)
733 pwd = getpwuid (getuid ());
734 if (!pwd)
736 log_write (_("could not set any invoking user: %s"),
737 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
738 return 1;
741 else if (*id == '@')
743 grp = getgrnam (id+1);
744 if (!grp)
746 log_write (_("could not parse group '%s': %s"), id+1,
747 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
748 return 1;
751 else if (*id != '#')
752 pwd = getpwnam (id);
754 if (!grp && !pwd && id && *id != '#')
756 if (id && *id)
757 log_write (_("could not set invoking user '%s': %s"), id,
758 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
759 else
760 log_write (_("could not set any invoking user!"));
762 return 1;
765 user = xcalloc (1, sizeof (struct invoking_user_s));
766 if (!user)
768 log_write ("%s", pwmd_strerror (ENOMEM));
769 return 1;
772 user->not = not;
773 user->type = pwd ? INVOKING_UID : grp ? INVOKING_GID : INVOKING_TLS;
774 if (pwd)
775 user->uid = pwd->pw_uid;
776 else if (grp)
777 user->id = str_dup (id+1);
778 else
780 char *s;
782 for (s = id; s && *s; s++)
783 *s = toupper(*s);
785 user->id = str_dup (id+1);
788 /* Set the default invoking_user since it doesn't exist. */
789 if (pwd && (!id || !*id))
790 config_set_list_param (config, "global", "invoking_user", pwd->pw_name);
792 if (!*users)
794 *users = user;
795 return 0;
798 for (p = *users; p; p = p->next)
800 if (!p->next)
802 p->next = user;
803 break;
807 return 0;
810 static int
811 parse_invoking_users (struct slist_s **config)
813 struct invoking_user_s *users = NULL;
814 int exists;
815 char **list, **l;
817 if (parse_list_file (*config, "global", "invoking_file", "invoking_user"))
818 return 1;
820 list = config_get_list_param (*config, "global", "invoking_user", &exists);
821 for (l = list; l && *l; l++)
823 if (add_invoking_user (&users, *l, config))
825 strv_free (list);
826 free_invoking_users (users);
827 return 1;
831 if (!list || !*list)
833 if (add_invoking_user (&users, NULL, config))
835 strv_free (list);
836 return 1;
840 free_invoking_users (invoking_users);
841 invoking_users = users;
842 strv_free (list);
843 return 0;
846 static int
847 set_defaults (struct slist_s **config, int reload)
849 char *s = NULL;
850 char **list;
851 int exists;
852 int i;
854 for (i = 0; config_params[i].name; i++)
856 switch (config_params[i].type)
858 case PARAM_BOOL:
859 config_get_bool_param (*config, "global", config_params[i].name,
860 &exists);
861 if (!exists)
863 if (config_set_bool_param
864 (config, "global", config_params[i].name,
865 config_params[i].value))
866 goto fail;
868 break;
869 case PARAM_INT:
870 config_get_int_param (*config, "global", config_params[i].name,
871 &exists);
872 if (!exists)
874 if (config_set_int_param
875 (config, "global", config_params[i].name,
876 config_params[i].value))
877 goto fail;
879 break;
880 case PARAM_CHARP:
881 s = config_get_string_param (*config, "global",
882 config_params[i].name, &exists);
883 xfree (s);
884 if (!exists && config_params[i].value)
886 if (config_set_string_param (config, "global",
887 config_params[i].name,
888 config_params[i].value))
889 goto fail;
891 break;
892 case PARAM_CHARPP:
893 list = config_get_list_param (*config, "global",
894 config_params[i].name, &exists);
895 strv_free (list);
896 if (!exists && config_params[i].value)
898 if (config_set_list_param (config, "global",
899 config_params[i].name,
900 config_params[i].value))
901 goto fail;
903 break;
904 case PARAM_LONG:
905 config_get_long_param (*config, "global", config_params[i].name,
906 &exists);
907 if (!exists)
909 if (config_set_long_param
910 (config, "global", config_params[i].name,
911 config_params[i].value))
912 goto fail;
914 break;
915 case PARAM_LONGLONG:
916 config_get_longlong_param (*config, "global", config_params[i].name,
917 &exists);
918 if (!exists)
920 if (config_set_longlong_param (config, "global",
921 config_params[i].name,
922 config_params[i].value))
923 goto fail;
925 break;
929 s = NULL;
930 if (!reload && fixup_allowed (config))
931 goto fail;
933 if (!reload && parse_invoking_users (config))
934 goto fail;
936 log_level = config_get_int_param (*config, "global",
937 "log_level", &exists);
938 log_keepopen = config_get_int_param (*config, "global",
939 "log_keepopen", &exists);
940 max_recursion_depth = config_get_int_param (*config, "global",
941 "recursion_depth", &exists);
942 disable_list_and_dump = config_get_bool_param (*config, "global",
943 "disable_list_and_dump",
944 &exists);
945 #ifdef HAVE_MLOCKALL
946 disable_mlock =
947 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
948 #endif
950 xfree (s);
951 return 0;
953 fail:
954 xfree (s);
955 return 1;
958 static struct config_section_s *
959 config_find_section (struct slist_s *config, const char *name)
961 unsigned i, t = slist_length (config);
963 for (i = 0; i < t; i++)
965 struct config_section_s *s = slist_nth_data (config, i);
967 if (!strcmp (s->name, name))
968 return s;
971 return NULL;
974 /* Append a new parameter to the list of parameters for a file
975 * section. When an existing parameter of the same name exists, its
976 * value is updated.
978 static int
979 new_param (struct config_section_s *section, const char *filename, int lineno,
980 const char *name, const char *value, int type)
982 struct config_param_s *param = NULL;
983 struct slist_s *tmp;
984 char *e;
985 unsigned i, t = slist_length (section->params);
986 int dup = 0;
988 for (i = 0; i < t; i++)
990 struct config_param_s *p = slist_nth_data (section->params, i);
991 if (!p)
992 break;
994 if (!strcmp (name, p->name))
996 param = p;
997 dup = 1;
998 break;
1002 if (!param)
1004 param = xcalloc (1, sizeof (struct config_param_s));
1005 if (!param)
1007 log_write ("%s", pwmd_strerror (ENOMEM));
1008 return 1;
1011 param->name = str_dup (name);
1012 if (!param->name)
1014 xfree (param);
1015 log_write ("%s", pwmd_strerror (ENOMEM));
1016 return 1;
1020 param->type = type;
1022 switch (type)
1024 case PARAM_BOOL:
1025 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1026 || !strcasecmp (value, "false"))
1027 param->value.itype = 0;
1028 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1029 || !strcasecmp (value, "true"))
1030 param->value.itype = 1;
1031 else
1033 INVALID_VALUE (filename, lineno);
1034 goto fail;
1036 param->type = PARAM_INT;
1037 break;
1038 case PARAM_CHARP:
1039 xfree (param->value.cptype);
1040 param->value.cptype = NULL;
1041 param->value.cptype = value && *value ? str_dup (value) : NULL;
1042 if (value && *value && !param->value.cptype)
1044 log_write ("%s", pwmd_strerror (ENOMEM));
1045 goto fail;
1047 break;
1048 case PARAM_CHARPP:
1049 strv_free (param->value.cpptype);
1050 param->value.cpptype = NULL;
1051 param->value.cpptype = value && *value ?
1052 str_split_ws (value, ",", 0) : NULL;
1053 if (value && *value && !param->value.cpptype)
1055 log_write ("%s", pwmd_strerror (ENOMEM));
1056 goto fail;
1058 break;
1059 case PARAM_INT:
1060 param->value.itype = strtol (value, &e, 10);
1061 if (e && *e)
1063 INVALID_VALUE (filename, lineno);
1064 goto fail;
1066 break;
1067 case PARAM_LONG:
1068 param->value.ltype = strtol (value, &e, 10);
1069 if (e && *e)
1071 INVALID_VALUE (filename, lineno);
1072 goto fail;
1074 break;
1075 case PARAM_LONGLONG:
1076 param->value.lltype = strtoll (value, &e, 10);
1077 if (e && *e)
1079 INVALID_VALUE (filename, lineno);
1080 goto fail;
1082 break;
1085 if (dup)
1086 return 0;
1088 tmp = slist_append (section->params, param);
1089 if (!tmp)
1091 log_write ("%s", pwmd_strerror (ENOMEM));
1092 goto fail;
1095 section->params = tmp;
1096 return 0;
1098 fail:
1099 xfree (param->name);
1100 xfree (param);
1101 return 1;
1104 struct slist_s *
1105 config_parse (const char *filename, int reload)
1107 struct slist_s *tmpconfig = NULL, *tmp;
1108 struct config_section_s *cur_section = NULL;
1109 char buf[LINE_MAX] = {0};
1110 char *s;
1111 int lineno = 1;
1112 int have_global = 0;
1113 FILE *fp = fopen (filename, "r");
1115 if (!fp)
1117 log_write ("%s: %s", filename,
1118 pwmd_strerror (gpg_error_from_errno (errno)));
1120 if (errno != ENOENT)
1121 return NULL;
1123 log_write (_("Using defaults!"));
1124 goto defaults;
1127 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
1129 char line[LINE_MAX] = { 0 };
1130 size_t len = 0;
1131 int match = 0;
1133 if (*s == '#')
1134 continue;
1136 s = str_chomp (s);
1137 if (!*s)
1138 continue;
1140 /* New file section. */
1141 if (*s == '[')
1143 struct config_section_s *section;
1144 char *p = strchr (++s, ']');
1146 if (!p)
1148 log_write (_("%s(%i): unbalanced braces"), filename, lineno);
1149 goto fail;
1152 if (*(p+1))
1154 log_write (_("%s(%i): trailing characters"), filename, lineno);
1155 goto fail;
1158 len = strlen (s) - strlen (p);
1159 memcpy (line, s, len);
1160 line[len] = 0;
1162 section = config_find_section (tmpconfig, line);
1163 if (section)
1165 log_write (_("%s(%i): section '%s' already exists!"),
1166 filename, lineno, line);
1167 goto fail;
1170 if (!strcmp (line, "global"))
1171 have_global = 1;
1173 section = xcalloc (1, sizeof (struct config_section_s));
1174 section->name = str_dup (line);
1176 if (cur_section)
1178 tmp = slist_append (tmpconfig, cur_section);
1179 if (!tmp)
1181 log_write ("%s", pwmd_strerror (ENOMEM));
1182 goto fail;
1185 tmpconfig = tmp;
1188 cur_section = section;
1189 continue;
1192 if (!cur_section)
1194 log_write (_("%s(%i): parameter outside of section!"), filename,
1195 lineno);
1196 goto fail;
1199 /* Parameters for each section. */
1200 for (int m = 0; config_params[m].name; m++)
1202 len = strlen (config_params[m].name);
1203 if (!strncmp (s, config_params[m].name, len))
1205 char *p = s + len;
1207 while (*p && *p == ' ')
1208 p++;
1210 if (!*p || *p != '=')
1211 continue;
1213 p++;
1214 while (*p && isspace (*p))
1215 p++;
1217 s[len] = 0;
1218 if (new_param (cur_section, filename, lineno, s, p,
1219 config_params[m].type))
1220 goto fail;
1222 match = 1;
1223 break;
1227 if (!match)
1229 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1230 goto fail;
1234 if (cur_section)
1236 tmp = slist_append (tmpconfig, cur_section);
1237 if (!tmp)
1239 log_write ("%s", pwmd_strerror (ENOMEM));
1240 goto fail;
1243 cur_section = NULL;
1244 tmpconfig = tmp;
1247 if (!have_global)
1248 log_write (_
1249 ("WARNING: %s: could not find a [global] configuration section!"),
1250 filename);
1252 defaults:
1253 if (set_defaults (&tmpconfig, reload))
1254 goto fail;
1256 if (fp)
1257 fclose(fp);
1259 return tmpconfig;
1261 fail:
1262 if (fp)
1263 fclose (fp);
1265 config_free (tmpconfig);
1266 free_section (cur_section);
1267 return NULL;
1270 static void
1271 free_section (struct config_section_s *s)
1273 if (!s)
1274 return;
1276 for (;;)
1278 struct config_param_s *p = slist_nth_data (s->params, 0);
1280 if (!p)
1281 break;
1283 section_remove_param (s, p->name);
1286 s->params = NULL;
1287 xfree (s->name);
1288 s->name = NULL;
1291 void
1292 config_free (struct slist_s *config)
1294 for (;;)
1296 struct config_section_s *s = slist_nth_data (config, 0);
1297 if (!s)
1298 break;
1300 free_section (s);
1301 config = slist_remove (config, s);
1302 xfree (s);
1306 void
1307 free_invoking_users (struct invoking_user_s *users)
1309 struct invoking_user_s *p;
1311 for (p = users; p;)
1313 struct invoking_user_s *next = p->next;
1315 if (p->type == INVOKING_TLS || p->type == INVOKING_GID)
1316 xfree (p->id);
1318 xfree (p);
1319 p = next;
1323 static int
1324 param_type (const char *name)
1326 int i;
1328 for (i = 0; config_params[i].name; i++)
1330 if (!strcmp (config_params[i].name, name))
1331 return config_params[i].type;
1334 return PARAM_INVALID;
1337 static int
1338 keep_parse (struct config_keep_s *k, const char *section, const char *key)
1340 int exists;
1341 int ival;
1342 long lval;
1343 long long llval;
1344 char *cpval;
1345 char **cppval;
1346 int type = param_type (key);
1347 void *value = NULL;
1349 switch (type)
1351 case PARAM_BOOL:
1352 case PARAM_INT:
1353 ival = config_get_int_param (global_config, section, key, &exists);
1354 if (exists)
1355 value = str_asprintf ("%i", ival);
1356 break;
1357 case PARAM_LONG:
1358 lval = config_get_long_param (global_config, section, key, &exists);
1359 if (exists)
1360 value = str_asprintf ("%li", lval);
1361 break;
1362 case PARAM_LONGLONG:
1363 llval = config_get_longlong_param (global_config, section, key, &exists);
1364 if (exists)
1365 value = str_asprintf ("%lli", llval);
1366 break;
1367 case PARAM_CHARP:
1368 cpval = config_get_string_param (global_config, section, key, &exists);
1369 if (exists)
1370 value = cpval;
1371 break;
1372 case PARAM_CHARPP:
1373 cppval = config_get_list_param (global_config, section, key, &exists);
1374 if (exists)
1376 char *s = strv_join (",", cppval);
1378 strv_free (cppval);
1379 value = s;
1381 break;
1382 default:
1383 return 1;
1386 if (!value)
1387 return 1;
1389 k->section = str_dup(section);
1390 k->name = str_dup(key);
1391 k->value = value;
1392 return 0;
1395 static struct slist_s *
1396 keep_add (struct slist_s *k, const char *s, const char *key)
1398 int n, t = slist_length (global_config);
1400 for (n = 0; n < t; n++)
1402 struct config_section_s *section;
1403 struct config_keep_s *tmp;
1404 int ret;
1406 section = slist_nth_data (global_config, n);
1407 tmp = xcalloc (1, sizeof(struct config_keep_s));
1409 // Process all sections.
1410 if (!s)
1411 ret = keep_parse (tmp, section->name, key);
1412 else
1413 ret = keep_parse (tmp, s, key);
1415 if (!ret)
1416 k = slist_append (k, tmp);
1417 else
1418 xfree (tmp);
1421 return k;
1424 /* Keep security sensitive settings across SIGHUP. */
1425 struct slist_s *
1426 config_keep_save ()
1428 struct slist_s *keep = NULL;
1430 #ifdef WITH_GNUTLS
1431 keep = keep_add (keep, NULL, "tcp_require_key");
1432 #endif
1433 keep = keep_add (keep, NULL, "require_save_key");
1434 keep = keep_add (keep, NULL, "allowed");
1435 keep = keep_add (keep, NULL, "allowed_file");
1436 keep = keep_add (keep, "global", "encrypt_to");
1437 keep = keep_add (keep, "global", "always_trust");
1438 keep = keep_add (keep, "global", "invoking_user");
1439 keep = keep_add (keep, "global", "invoking_file");
1440 keep = keep_add (keep, "global", "gpg_homedir");
1441 return keep;
1444 /* Restore parameters previously saved with config_keep_save(). This will also
1445 * free the 'keep'.
1447 void
1448 config_keep_restore (struct slist_s *keep)
1450 int n, t = slist_length (keep);
1452 for (n = 0; n < t; n++)
1454 struct config_keep_s *k = slist_nth_data (keep, n);
1455 int type = param_type (k->name);
1457 switch (type)
1459 case PARAM_BOOL:
1460 config_set_bool_param (&global_config, k->section, k->name, k->value);
1461 break;
1462 case PARAM_INT:
1463 config_set_int_param (&global_config, k->section, k->name, k->value);
1464 break;
1465 case PARAM_LONG:
1466 config_set_long_param (&global_config, k->section, k->name, k->value);
1467 break;
1468 case PARAM_LONGLONG:
1469 config_set_longlong_param (&global_config, k->section, k->name,
1470 k->value);
1471 break;
1472 case PARAM_CHARP:
1473 config_set_string_param (&global_config, k->section, k->name,
1474 k->value);
1475 break;
1476 case PARAM_CHARPP:
1477 config_set_list_param (&global_config, k->section, k->name, k->value);
1478 break;
1479 default:
1480 break;
1483 xfree (k->section);
1484 xfree (k->name);
1485 xfree (k->value);
1486 xfree (k);
1489 slist_free (keep);