tls: Disable TLS1.1 and CBC cipher suites by default.
[pwmd.git] / src / rcfile.c
blobbc7c8744745898f97e7df9729fbc88d32e1d1941
1 /*
2 Copyright (C) 2006-2019 Ben Kibbey <bjk@luxsci.net>
4 This file is part of pwmd.
6 Pwmd is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
11 Pwmd is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <errno.h>
29 #include <ctype.h>
30 #include <pwd.h>
31 #include <grp.h>
33 #include "pwmd-error.h"
34 #include "mutex.h"
35 #include "rcfile.h"
36 #include "util-misc.h"
37 #include "common.h"
38 #include "util-slist.h"
39 #include "util-string.h"
40 #include "mem.h"
42 #define DEFAULT_CACHE_TIMEOUT "600"
43 #define DEFAULT_KEEPALIVE_INTERVAL "60"
44 #define DEFAULT_LOCK_TIMEOUT "50" // MUTEX_TRYLOCK in tenths of a second
45 #define DEFAULT_BACKLOG "128"
46 #define DEFAULT_CIPHER_PRIORITY "SECURE256:SECURE192:SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-AES-128-CBC:-AES-256-CBC"
48 #define INVALID_VALUE(file, line) do { \
49 if (file) \
50 log_write(_("%s(%i): invalid value for parameter."), file, line); \
51 } while (0);
53 enum
55 PARAM_INT, PARAM_CHARP, PARAM_LONG, PARAM_LONGLONG, PARAM_CHARPP,
56 PARAM_BOOL, PARAM_INVALID
59 static struct config_params_s
61 const char *name;
62 int type;
63 const char *value;
64 } config_params[] = {
65 { "backup", PARAM_BOOL, "true"},
66 { "socket_path", PARAM_CHARP, NULL},
67 { "socket_perms", PARAM_CHARP, NULL},
68 { "backlog", PARAM_INT, DEFAULT_BACKLOG},
69 { "passphrase_file", PARAM_CHARP, NULL},
70 { "log_path", PARAM_CHARP, "~/.pwmd/log"},
71 { "enable_logging", PARAM_BOOL, "0"},
72 { "log_keepopen", PARAM_BOOL, "true"},
73 { "log_level", PARAM_INT, "0"},
74 { "disable_mlockall", PARAM_BOOL, "true"},
75 { "cache_timeout", PARAM_LONG, DEFAULT_CACHE_TIMEOUT},
76 { "cache_push", PARAM_CHARPP, NULL},
77 { "disable_list_and_dump", PARAM_BOOL, "false"},
78 { "recursion_depth", PARAM_INT, "100"},
79 { "syslog", PARAM_BOOL, "false"},
80 { "allowed", PARAM_CHARPP, NULL},
81 { "allowed_file", PARAM_CHARP, NULL},
82 { "priority", PARAM_INT, INVALID_PRIORITY},
83 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
84 { "tcp_port", PARAM_INT, "6466"},
85 { "enable_tcp", PARAM_BOOL, "false"},
86 { "tcp_require_key", PARAM_BOOL, "false"},
87 { "tcp_bind", PARAM_CHARP, "any"},
88 { "tcp_interface", PARAM_CHARP, NULL},
89 { "tls_timeout", PARAM_INT, "300"},
90 { "tls_cipher_suite", PARAM_CHARP, DEFAULT_CIPHER_PRIORITY},
91 { "tls_dh_params_file", PARAM_CHARP, NULL},
92 { "tls_use_crl", PARAM_BOOL, "false"},
93 { "require_save_key", PARAM_BOOL, "true"},
94 { "invoking_user", PARAM_CHARPP, NULL},
95 { "invoking_file", PARAM_CHARP, NULL},
96 { "encrypt_to", PARAM_BOOL, "false"},
97 { "always_trust", PARAM_BOOL, "false"},
98 { "gpg_homedir", PARAM_CHARP, NULL},
99 { "strict_kill", PARAM_BOOL, "false"},
100 { "lock_timeout", PARAM_LONG, DEFAULT_LOCK_TIMEOUT},
101 { "kill_scd", PARAM_BOOL, "false"},
102 { "strict_open", PARAM_BOOL, "false"},
103 { NULL, PARAM_INVALID, NULL},
106 struct config_param_s
108 char *name;
109 int type;
110 union
112 int itype;
113 char *cptype;
114 char **cpptype;
115 long ltype;
116 long long lltype;
117 } value;
120 struct config_keep_s
122 char *section;
123 char *name;
124 char *value;
127 static struct config_section_s *config_find_section (struct slist_s *config,
128 const char *name);
129 static int new_param (struct config_section_s *section, const char *filename,
130 int lineno, const char *name, const char *value,
131 int type);
132 static void free_section (struct config_section_s *s);
133 static int set_defaults (struct slist_s **config, int reload);
135 static void
136 section_remove_param (struct config_section_s *section, const char *name)
138 unsigned i, t = slist_length (section->params);
140 for (i = 0; i < t; i++)
142 struct config_param_s *p = slist_nth_data (section->params, i);
144 if (!p)
145 continue;
147 if (!strcmp (p->name, name))
149 switch (p->type)
151 case PARAM_CHARP:
152 xfree (p->value.cptype);
153 break;
154 case PARAM_CHARPP:
155 strv_free (p->value.cpptype);
156 break;
159 section->params = slist_remove (section->params, p);
160 xfree (p->name);
161 xfree (p);
162 break;
167 static struct config_param_s *
168 config_has_param (struct config_section_s *s, const char *what)
170 unsigned i, t = slist_length (s->params);
172 for (i = 0; i < t; i++)
174 struct config_param_s *p = slist_nth_data (s->params, i);
175 if (!p)
176 break;
178 if (!strcmp (p->name, what))
179 return p;
182 return NULL;
185 static struct config_param_s *
186 config_get_param (struct slist_s *config,
187 const char *section, const char *what, int *exists)
189 unsigned i, t = slist_length (config);
191 *exists = 0;
193 for (i = 0; i < t; i++)
195 struct config_param_s *p;
196 struct config_section_s *s = slist_nth_data (config, i);
198 if (!s)
199 break;
201 if (strcmp (s->name, section))
202 continue;
204 p = config_has_param (s, what);
205 if (!p)
206 return NULL;
208 *exists = 1;
209 return p;
212 return NULL;
215 static struct config_section_s *
216 new_section (struct slist_s **config, const char *name)
218 struct slist_s *tmp;
219 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
221 if (!s)
222 return NULL;
224 s->name = str_dup (name);
225 if (!s->name)
227 log_write ("%s", pwmd_strerror (ENOMEM));
228 xfree (s);
229 return NULL;
232 tmp = slist_append (*config, s);
233 if (!tmp)
235 log_write ("%s", pwmd_strerror (ENOMEM));
236 xfree (s->name);
237 xfree (s);
238 return NULL;
241 *config = tmp;
242 return s;
246 config_set_string_param (struct slist_s **config, const char *section,
247 const char *name, const char *value)
249 struct config_section_s *s = config_find_section (*config, section);
251 if (!s)
253 s = new_section (config, section);
254 if (!s)
255 return 1;
258 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
261 char *
262 config_get_string_param (struct slist_s *config, const char *section,
263 const char *what, int *exists)
265 struct config_param_s *p = config_get_param (config, section, what, exists);
266 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
270 config_set_int_param (struct slist_s **config, const char *section,
271 const char *name, const char *value)
273 struct config_section_s *s = config_find_section (*config, section);
275 if (!s)
277 s = new_section (config, section);
278 if (!s)
279 return 1;
282 return new_param (s, NULL, 0, name, value, PARAM_INT);
286 config_get_int_param (struct slist_s *config, const char *section,
287 const char *what, int *exists)
289 struct config_param_s *p = config_get_param (config, section, what, exists);
290 return *exists ? p->value.itype : -1;
294 config_set_bool_param (struct slist_s **config, const char *section,
295 const char *name, const char *value)
297 struct config_section_s *s = config_find_section (*config, section);
299 if (!s)
301 s = new_section (config, section);
302 if (!s)
303 return 1;
306 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
310 config_get_bool_param (struct slist_s *config, const char *section,
311 const char *what, int *exists)
313 return config_get_int_param (config, section, what, exists);
317 config_set_long_param (struct slist_s **config, const char *section,
318 const char *name, const char *value)
320 struct config_section_s *s = config_find_section (*config, section);
322 if (!s)
324 s = new_section (config, section);
325 if (!s)
326 return 1;
329 return new_param (s, NULL, 0, name, value, PARAM_LONG);
332 long
333 config_get_long_param (struct slist_s *config, const char *section,
334 const char *what, int *exists)
336 struct config_param_s *p = config_get_param (config, section, what, exists);
337 return *exists ? p->value.ltype : -1;
341 config_set_longlong_param (struct slist_s **config, const char *section,
342 const char *name, const char *value)
344 struct config_section_s *s = config_find_section (*config, section);
346 if (!s)
348 s = new_section (config, section);
349 if (!s)
350 return 1;
353 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
356 long long
357 config_get_longlong_param (struct slist_s *config,
358 const char *section, const char *what, int *exists)
360 struct config_param_s *p = config_get_param (config, section, what, exists);
361 return *exists ? p->value.lltype : -1;
365 config_set_list_param (struct slist_s **config, const char *section,
366 const char *name, const char *value)
368 struct config_section_s *s = config_find_section (*config, section);
370 if (!s)
372 s = new_section (config, section);
373 if (!s)
374 return 1;
377 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
380 char **
381 config_get_list_param (struct slist_s *config, const char *section,
382 const char *what, int *exists)
384 struct config_param_s *p = config_get_param (config, section, what, exists);
385 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
388 char *
389 config_get_string (const char *section, const char *what)
391 char *val = NULL;
392 const char *where = section ? section : "global";
393 int exists = 0;
395 MUTEX_LOCK (&rcfile_mutex);
396 val = config_get_string_param (global_config, where, what, &exists);
397 if (!exists && strcmp (section ? section : "", "global"))
398 val = config_get_string_param (global_config, "global", what, &exists);
400 MUTEX_UNLOCK (&rcfile_mutex);
401 return val;
404 char **
405 config_get_list (const char *section, const char *what)
407 char **val = NULL;
408 const char *where = section ? section : "global";
409 int exists = 0;
411 MUTEX_LOCK (&rcfile_mutex);
412 val = config_get_list_param (global_config, where, what, &exists);
413 if (!exists && strcmp (section ? section : "", "global"))
414 val = config_get_list_param (global_config, "global", what, &exists);
416 MUTEX_UNLOCK (&rcfile_mutex);
417 return val;
421 config_get_integer (const char *section, const char *what)
423 int val = 0;
424 const char *where = section ? section : "global";
425 int exists = 0;
427 MUTEX_LOCK (&rcfile_mutex);
428 val = config_get_int_param (global_config, where, what, &exists);
429 if (!exists && strcmp (section ? section : "", "global"))
430 val = config_get_int_param (global_config, "global", what, &exists);
432 MUTEX_UNLOCK (&rcfile_mutex);
433 return val;
436 long long
437 config_get_longlong (const char *section, const char *what)
439 long long val = 0;
440 const char *where = section ? section : "global";
441 int exists = 0;
443 MUTEX_LOCK (&rcfile_mutex);
444 val = config_get_longlong_param (global_config, where, what, &exists);
445 if (!exists && strcmp (section ? section : "", "global"))
446 val = config_get_longlong_param (global_config, "global", what, &exists);
448 MUTEX_UNLOCK (&rcfile_mutex);
449 return val;
452 long
453 config_get_long (const char *section, const char *what)
455 long val = 0;
456 const char *where = section ? section : "global";
457 int exists = 0;
459 MUTEX_LOCK (&rcfile_mutex);
460 val = config_get_long_param (global_config, where, what, &exists);
461 if (!exists && strcmp (section ? section : "", "global"))
462 val = config_get_long_param (global_config, "global", what, &exists);
464 MUTEX_UNLOCK (&rcfile_mutex);
465 return val;
469 config_get_boolean (const char *section, const char *what)
471 return config_get_integer (section, what);
474 char *
475 config_get_value (const char *section, const char *what)
477 const char *where = section ? section : "global";
478 int exists = 0;
479 int i;
480 int ival;
481 long lval;
482 long long llval;
483 char *cpval;
484 char **cppval;
485 char *result = NULL;
487 MUTEX_LOCK (&rcfile_mutex);
489 for (i = 0; config_params[i].name; i++)
491 if (!strcmp (config_params[i].name, what))
493 switch (config_params[i].type)
495 case PARAM_BOOL:
496 case PARAM_INT:
497 ival = config_get_int_param (global_config, where, what,
498 &exists);
499 if (!exists && strcmp (section ? section : "", "global"))
500 ival = config_get_int_param (global_config, "global", what,
501 &exists);
502 result = str_asprintf ("%i", ival);
503 break;
504 case PARAM_CHARP:
505 cpval = config_get_string_param (global_config, where, what,
506 &exists);
507 if (!exists && strcmp (section ? section : "", "global"))
508 cpval =
509 config_get_string_param (global_config, "global", what,
510 &exists);
511 result = cpval;
512 break;
513 case PARAM_LONG:
514 lval = config_get_long_param (global_config, where, what,
515 &exists);
516 if (!exists && strcmp (section ? section : "", "global"))
517 lval = config_get_long_param (global_config, "global", what,
518 &exists);
519 result = str_asprintf ("%li", lval);
520 break;
521 case PARAM_LONGLONG:
522 llval = config_get_longlong_param (global_config, where, what,
523 &exists);
524 if (!exists && strcmp (section ? section : "", "global"))
525 llval = config_get_longlong_param (global_config, "global",
526 what, &exists);
527 result = str_asprintf ("%lli", llval);
528 break;
529 case PARAM_CHARPP:
530 cppval = config_get_list_param (global_config, where, what,
531 &exists);
532 if (!exists && strcmp (section ? section : "", "global"))
533 cppval = config_get_list_param (global_config, "global", what,
534 &exists);
536 if (cppval)
537 result = strv_join (",", cppval);
539 strv_free (cppval);
540 break;
545 MUTEX_UNLOCK (&rcfile_mutex);
546 return result;
549 /* 'file' is the list parameter file to load into the list parameter 'what'.
550 * The parsing of the parameter is not done here. */
551 static gpg_error_t
552 parse_list_file (struct slist_s *config, const char *section,
553 const char *file, const char *what)
555 FILE *fp;
556 char buf[LINE_MAX] = {0};
557 int exists;
558 char **list = NULL;
559 char *tmp;
560 char *p = config_get_string_param (config, section, file, &exists);
561 gpg_error_t rc;
563 if (!p || !*p)
565 xfree (p);
566 return 0;
569 tmp = expand_homedir (p);
570 xfree (p);
571 p = tmp;
572 fp = fopen (p, "r");
573 if (!fp)
575 rc = gpg_error_from_errno (errno);
576 log_write ("%s: %s", p, pwmd_strerror (rc));
577 xfree (p);
578 return rc;
581 xfree (p);
582 list = config_get_list_param (config, section, what, &exists);
583 if (!list && exists)
585 fclose (fp);
586 log_write ("%s", pwmd_strerror (ENOMEM));
587 return gpg_error (ENOMEM);
590 while ((p = fgets (buf, sizeof (buf)-1, fp)))
592 char **pp = NULL;
594 if (p[strlen(p)-1] == '\n')
595 p[strlen(p)-1] = 0;
597 while (*p && isspace (*p))
598 p++;
600 if (!*p || *p == ';')
601 continue;
603 tmp = str_dup (p);
604 if (tmp)
605 pp = strv_cat (list, str_dup (p));
607 if (!pp || !tmp)
609 xfree (tmp);
610 strv_free (list);
611 fclose (fp);
612 log_write ("%s", strerror (ENOMEM));
613 return gpg_error (ENOMEM);
616 xfree (tmp);
617 list = pp;
620 fclose(fp);
621 if (!list)
622 return 0;
624 p = strv_join (",", list);
625 strv_free (list);
627 if (!p)
629 log_write ("%s", pwmd_strerror (ENOMEM));
630 return gpg_error (ENOMEM);
633 config_set_list_param (&config, section, what, p);
634 xfree (p);
635 return 0;
638 static int
639 fixup_allowed_once (struct slist_s **config, const char *section)
641 char **list, **pp, *p;
642 int exists;
643 gpg_error_t rc;
645 rc = parse_list_file (*config, section, "allowed_file", "allowed");
646 if (rc)
647 return 1;
649 list = config_get_list_param (*config, section, "allowed", &exists);
650 for (pp = list; pp && *pp; pp++)
652 if (*(*pp) == '#')
654 for (p = *pp; p && *p; p++)
655 *p = toupper(*p);
659 strv_free (list);
660 if (!exists)
662 if (!strcmp (section, "global"))
664 p = get_username (getuid());
666 if (config_set_list_param (config, section, "allowed", p))
668 xfree (p);
669 return 1;
672 xfree (p);
674 else
676 list = config_get_list_param (*config, "global", "allowed", &exists);
677 if (list)
679 p = strv_join (",", list);
680 strv_free (list);
681 if (config_set_list_param (config, section, "allowed", p))
683 xfree (p);
684 return 1;
687 xfree (p);
692 return 0;
695 static int
696 fixup_allowed (struct slist_s **config)
698 int n, t = slist_length (*config);
700 for (n = 0; n < t; n++)
702 struct config_section_s *section;
704 section = slist_nth_data (*config, n);
705 if (fixup_allowed_once (config, section->name))
706 return 1;
709 return 0;
712 static int
713 add_invoking_user (struct invoking_user_s **users, char *id,
714 struct slist_s **config)
716 struct passwd *pwd = NULL;
717 struct group *grp = NULL;
718 struct invoking_user_s *user, *p;
719 int not = 0;
721 if (id && (*id == '!' || *id == '-'))
723 not = 1;
724 id++;
727 errno = 0;
728 if (!id || !*id)
730 pwd = getpwuid (getuid ());
731 if (!pwd)
733 log_write (_("could not set any invoking user: %s"),
734 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
735 return 1;
738 else if (*id == '@')
740 grp = getgrnam (id+1);
741 if (!grp)
743 log_write (_("could not parse group '%s': %s"), id+1,
744 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
745 return 1;
748 else if (*id != '#')
749 pwd = getpwnam (id);
751 if (!grp && !pwd && id && *id != '#')
753 if (id && *id)
754 log_write (_("could not set invoking user '%s': %s"), id,
755 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
756 else
757 log_write (_("could not set any invoking user!"));
759 return 1;
762 user = xcalloc (1, sizeof (struct invoking_user_s));
763 if (!user)
765 log_write ("%s", pwmd_strerror (ENOMEM));
766 return 1;
769 user->not = not;
770 user->type = pwd ? INVOKING_UID : grp ? INVOKING_GID : INVOKING_TLS;
771 if (pwd)
772 user->uid = pwd->pw_uid;
773 else if (grp)
774 user->id = str_dup (id+1);
775 else
777 char *s;
779 for (s = id; s && *s; s++)
780 *s = toupper(*s);
782 user->id = str_dup (id+1);
785 /* Set the default invoking_user since it doesn't exist. */
786 if (pwd && (!id || !*id))
787 config_set_list_param (config, "global", "invoking_user", pwd->pw_name);
789 if (!*users)
791 *users = user;
792 return 0;
795 for (p = *users; p; p = p->next)
797 if (!p->next)
799 p->next = user;
800 break;
804 return 0;
807 static int
808 parse_invoking_users (struct slist_s **config)
810 struct invoking_user_s *users = NULL;
811 int exists;
812 char **list, **l;
814 if (parse_list_file (*config, "global", "invoking_file", "invoking_user"))
815 return 1;
817 list = config_get_list_param (*config, "global", "invoking_user", &exists);
818 for (l = list; l && *l; l++)
820 if (add_invoking_user (&users, *l, config))
822 strv_free (list);
823 free_invoking_users (users);
824 return 1;
828 if (!list || !*list)
830 if (add_invoking_user (&users, NULL, config))
832 strv_free (list);
833 return 1;
837 free_invoking_users (invoking_users);
838 invoking_users = users;
839 strv_free (list);
840 return 0;
843 static int
844 set_defaults (struct slist_s **config, int reload)
846 char *s = NULL;
847 char **list;
848 int exists;
849 int i;
851 for (i = 0; config_params[i].name; i++)
853 switch (config_params[i].type)
855 case PARAM_BOOL:
856 config_get_bool_param (*config, "global", config_params[i].name,
857 &exists);
858 if (!exists)
860 if (config_set_bool_param
861 (config, "global", config_params[i].name,
862 config_params[i].value))
863 goto fail;
865 break;
866 case PARAM_INT:
867 config_get_int_param (*config, "global", config_params[i].name,
868 &exists);
869 if (!exists)
871 if (config_set_int_param
872 (config, "global", config_params[i].name,
873 config_params[i].value))
874 goto fail;
876 break;
877 case PARAM_CHARP:
878 s = config_get_string_param (*config, "global",
879 config_params[i].name, &exists);
880 xfree (s);
881 if (!exists && config_params[i].value)
883 if (config_set_string_param (config, "global",
884 config_params[i].name,
885 config_params[i].value))
886 goto fail;
888 break;
889 case PARAM_CHARPP:
890 list = config_get_list_param (*config, "global",
891 config_params[i].name, &exists);
892 strv_free (list);
893 if (!exists && config_params[i].value)
895 if (config_set_list_param (config, "global",
896 config_params[i].name,
897 config_params[i].value))
898 goto fail;
900 break;
901 case PARAM_LONG:
902 config_get_long_param (*config, "global", config_params[i].name,
903 &exists);
904 if (!exists)
906 if (config_set_long_param
907 (config, "global", config_params[i].name,
908 config_params[i].value))
909 goto fail;
911 break;
912 case PARAM_LONGLONG:
913 config_get_longlong_param (*config, "global", config_params[i].name,
914 &exists);
915 if (!exists)
917 if (config_set_longlong_param (config, "global",
918 config_params[i].name,
919 config_params[i].value))
920 goto fail;
922 break;
926 s = NULL;
927 if (!reload && fixup_allowed (config))
928 goto fail;
930 if (!reload && parse_invoking_users (config))
931 goto fail;
933 log_level = config_get_int_param (*config, "global",
934 "log_level", &exists);
935 log_keepopen = config_get_int_param (*config, "global",
936 "log_keepopen", &exists);
937 max_recursion_depth = config_get_int_param (*config, "global",
938 "recursion_depth", &exists);
939 disable_list_and_dump = config_get_bool_param (*config, "global",
940 "disable_list_and_dump",
941 &exists);
942 #ifdef HAVE_MLOCKALL
943 disable_mlock =
944 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
945 #endif
947 xfree (s);
948 return 0;
950 fail:
951 xfree (s);
952 return 1;
955 static struct config_section_s *
956 config_find_section (struct slist_s *config, const char *name)
958 unsigned i, t = slist_length (config);
960 for (i = 0; i < t; i++)
962 struct config_section_s *s = slist_nth_data (config, i);
964 if (!strcmp (s->name, name))
965 return s;
968 return NULL;
971 /* Append a new parameter to the list of parameters for a file
972 * section. When an existing parameter of the same name exists, its
973 * value is updated.
975 static int
976 new_param (struct config_section_s *section, const char *filename, int lineno,
977 const char *name, const char *value, int type)
979 struct config_param_s *param = NULL;
980 struct slist_s *tmp;
981 char *e;
982 unsigned i, t = slist_length (section->params);
983 int dup = 0;
985 for (i = 0; i < t; i++)
987 struct config_param_s *p = slist_nth_data (section->params, i);
988 if (!p)
989 break;
991 if (!strcmp (name, p->name))
993 param = p;
994 dup = 1;
995 break;
999 if (!param)
1001 param = xcalloc (1, sizeof (struct config_param_s));
1002 if (!param)
1004 log_write ("%s", pwmd_strerror (ENOMEM));
1005 return 1;
1008 param->name = str_dup (name);
1009 if (!param->name)
1011 xfree (param);
1012 log_write ("%s", pwmd_strerror (ENOMEM));
1013 return 1;
1017 param->type = type;
1019 switch (type)
1021 case PARAM_BOOL:
1022 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1023 || !strcasecmp (value, "false"))
1024 param->value.itype = 0;
1025 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1026 || !strcasecmp (value, "true"))
1027 param->value.itype = 1;
1028 else
1030 INVALID_VALUE (filename, lineno);
1031 goto fail;
1033 param->type = PARAM_INT;
1034 break;
1035 case PARAM_CHARP:
1036 xfree (param->value.cptype);
1037 param->value.cptype = NULL;
1038 param->value.cptype = value && *value ? str_dup (value) : NULL;
1039 if (value && *value && !param->value.cptype)
1041 log_write ("%s", pwmd_strerror (ENOMEM));
1042 goto fail;
1044 break;
1045 case PARAM_CHARPP:
1046 strv_free (param->value.cpptype);
1047 param->value.cpptype = NULL;
1048 param->value.cpptype = value && *value ?
1049 str_split_ws (value, ",", 0) : NULL;
1050 if (value && *value && !param->value.cpptype)
1052 log_write ("%s", pwmd_strerror (ENOMEM));
1053 goto fail;
1055 break;
1056 case PARAM_INT:
1057 param->value.itype = strtol (value, &e, 10);
1058 if (e && *e)
1060 INVALID_VALUE (filename, lineno);
1061 goto fail;
1063 break;
1064 case PARAM_LONG:
1065 param->value.ltype = strtol (value, &e, 10);
1066 if (e && *e)
1068 INVALID_VALUE (filename, lineno);
1069 goto fail;
1071 break;
1072 case PARAM_LONGLONG:
1073 param->value.lltype = strtoll (value, &e, 10);
1074 if (e && *e)
1076 INVALID_VALUE (filename, lineno);
1077 goto fail;
1079 break;
1082 if (dup)
1083 return 0;
1085 tmp = slist_append (section->params, param);
1086 if (!tmp)
1088 log_write ("%s", pwmd_strerror (ENOMEM));
1089 goto fail;
1092 section->params = tmp;
1093 return 0;
1095 fail:
1096 xfree (param->name);
1097 xfree (param);
1098 return 1;
1101 struct slist_s *
1102 config_parse (const char *filename, int reload)
1104 struct slist_s *tmpconfig = NULL, *tmp;
1105 struct config_section_s *cur_section = NULL;
1106 char buf[LINE_MAX] = {0};
1107 char *s;
1108 int lineno = 1;
1109 int have_global = 0;
1110 FILE *fp = fopen (filename, "r");
1112 if (!fp)
1114 log_write ("%s: %s", filename,
1115 pwmd_strerror (gpg_error_from_errno (errno)));
1117 if (errno != ENOENT)
1118 return NULL;
1120 log_write (_("Using defaults!"));
1121 goto defaults;
1124 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
1126 char line[LINE_MAX] = { 0 };
1127 size_t len = 0;
1128 int match = 0;
1130 if (*s == '#')
1131 continue;
1133 s = str_chomp (s);
1134 if (!*s)
1135 continue;
1137 /* New file section. */
1138 if (*s == '[')
1140 struct config_section_s *section;
1141 char *p = strchr (++s, ']');
1143 if (!p)
1145 log_write (_("%s(%i): unbalanced braces"), filename, lineno);
1146 goto fail;
1149 if (*(p+1))
1151 log_write (_("%s(%i): trailing characters"), filename, lineno);
1152 goto fail;
1155 len = strlen (s) - strlen (p);
1156 memcpy (line, s, len);
1157 line[len] = 0;
1159 section = config_find_section (tmpconfig, line);
1160 if (section)
1162 log_write (_("%s(%i): section '%s' already exists!"),
1163 filename, lineno, line);
1164 goto fail;
1167 if (!strcmp (line, "global"))
1168 have_global = 1;
1170 section = xcalloc (1, sizeof (struct config_section_s));
1171 section->name = str_dup (line);
1173 if (cur_section)
1175 tmp = slist_append (tmpconfig, cur_section);
1176 if (!tmp)
1178 log_write ("%s", pwmd_strerror (ENOMEM));
1179 goto fail;
1182 tmpconfig = tmp;
1185 cur_section = section;
1186 continue;
1189 if (!cur_section)
1191 log_write (_("%s(%i): parameter outside of section!"), filename,
1192 lineno);
1193 goto fail;
1196 /* Parameters for each section. */
1197 for (int m = 0; config_params[m].name; m++)
1199 len = strlen (config_params[m].name);
1200 if (!strncmp (s, config_params[m].name, len))
1202 char *p = s + len;
1204 while (*p && *p == ' ')
1205 p++;
1207 if (!*p || *p != '=')
1208 continue;
1210 p++;
1211 while (*p && isspace (*p))
1212 p++;
1214 s[len] = 0;
1215 if (new_param (cur_section, filename, lineno, s, p,
1216 config_params[m].type))
1217 goto fail;
1219 match = 1;
1220 break;
1224 if (!match)
1226 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1227 goto fail;
1231 if (cur_section)
1233 tmp = slist_append (tmpconfig, cur_section);
1234 if (!tmp)
1236 log_write ("%s", pwmd_strerror (ENOMEM));
1237 goto fail;
1240 cur_section = NULL;
1241 tmpconfig = tmp;
1244 if (!have_global)
1245 log_write (_
1246 ("WARNING: %s: could not find a [global] configuration section!"),
1247 filename);
1249 defaults:
1250 if (set_defaults (&tmpconfig, reload))
1251 goto fail;
1253 if (fp)
1254 fclose(fp);
1256 return tmpconfig;
1258 fail:
1259 if (fp)
1260 fclose (fp);
1262 config_free (tmpconfig);
1263 free_section (cur_section);
1264 return NULL;
1267 static void
1268 free_section (struct config_section_s *s)
1270 if (!s)
1271 return;
1273 for (;;)
1275 struct config_param_s *p = slist_nth_data (s->params, 0);
1277 if (!p)
1278 break;
1280 section_remove_param (s, p->name);
1283 s->params = NULL;
1284 xfree (s->name);
1285 s->name = NULL;
1288 void
1289 config_free (struct slist_s *config)
1291 for (;;)
1293 struct config_section_s *s = slist_nth_data (config, 0);
1294 if (!s)
1295 break;
1297 free_section (s);
1298 config = slist_remove (config, s);
1299 xfree (s);
1303 void
1304 free_invoking_users (struct invoking_user_s *users)
1306 struct invoking_user_s *p;
1308 for (p = users; p;)
1310 struct invoking_user_s *next = p->next;
1312 if (p->type == INVOKING_TLS || p->type == INVOKING_GID)
1313 xfree (p->id);
1315 xfree (p);
1316 p = next;
1320 static int
1321 param_type (const char *name)
1323 int i;
1325 for (i = 0; config_params[i].name; i++)
1327 if (!strcmp (config_params[i].name, name))
1328 return config_params[i].type;
1331 return PARAM_INVALID;
1334 static int
1335 keep_parse (struct config_keep_s *k, const char *section, const char *key)
1337 int exists;
1338 int ival;
1339 long lval;
1340 long long llval;
1341 char *cpval;
1342 char **cppval;
1343 int type = param_type (key);
1344 void *value = NULL;
1346 switch (type)
1348 case PARAM_BOOL:
1349 case PARAM_INT:
1350 ival = config_get_int_param (global_config, section, key, &exists);
1351 if (exists)
1352 value = str_asprintf ("%i", ival);
1353 break;
1354 case PARAM_LONG:
1355 lval = config_get_long_param (global_config, section, key, &exists);
1356 if (exists)
1357 value = str_asprintf ("%li", lval);
1358 break;
1359 case PARAM_LONGLONG:
1360 llval = config_get_longlong_param (global_config, section, key, &exists);
1361 if (exists)
1362 value = str_asprintf ("%lli", llval);
1363 break;
1364 case PARAM_CHARP:
1365 cpval = config_get_string_param (global_config, section, key, &exists);
1366 if (exists)
1367 value = cpval;
1368 break;
1369 case PARAM_CHARPP:
1370 cppval = config_get_list_param (global_config, section, key, &exists);
1371 if (exists)
1373 char *s = strv_join (",", cppval);
1375 strv_free (cppval);
1376 value = s;
1378 break;
1379 default:
1380 return 1;
1383 if (!value)
1384 return 1;
1386 k->section = str_dup(section);
1387 k->name = str_dup(key);
1388 k->value = value;
1389 return 0;
1392 static struct slist_s *
1393 keep_add (struct slist_s *k, const char *s, const char *key)
1395 int n, t = slist_length (global_config);
1397 for (n = 0; n < t; n++)
1399 struct config_section_s *section;
1400 struct config_keep_s *tmp;
1401 int ret;
1403 section = slist_nth_data (global_config, n);
1404 tmp = xcalloc (1, sizeof(struct config_keep_s));
1406 // Process all sections.
1407 if (!s)
1408 ret = keep_parse (tmp, section->name, key);
1409 else
1410 ret = keep_parse (tmp, s, key);
1412 if (!ret)
1413 k = slist_append (k, tmp);
1414 else
1415 xfree (tmp);
1418 return k;
1421 /* Keep security sensitive settings across SIGHUP. */
1422 struct slist_s *
1423 config_keep_save ()
1425 struct slist_s *keep = NULL;
1427 #ifdef WITH_GNUTLS
1428 keep = keep_add (keep, NULL, "tcp_require_key");
1429 #endif
1430 keep = keep_add (keep, NULL, "require_save_key");
1431 keep = keep_add (keep, NULL, "allowed");
1432 keep = keep_add (keep, NULL, "allowed_file");
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 keep = keep_add (keep, "global", "invoking_file");
1437 keep = keep_add (keep, "global", "gpg_homedir");
1438 return keep;
1441 /* Restore parameters previously saved with config_keep_save(). This will also
1442 * free the 'keep'.
1444 void
1445 config_keep_restore (struct slist_s *keep)
1447 int n, t = slist_length (keep);
1449 for (n = 0; n < t; n++)
1451 struct config_keep_s *k = slist_nth_data (keep, n);
1452 int type = param_type (k->name);
1454 switch (type)
1456 case PARAM_BOOL:
1457 config_set_bool_param (&global_config, k->section, k->name, k->value);
1458 break;
1459 case PARAM_INT:
1460 config_set_int_param (&global_config, k->section, k->name, k->value);
1461 break;
1462 case PARAM_LONG:
1463 config_set_long_param (&global_config, k->section, k->name, k->value);
1464 break;
1465 case PARAM_LONGLONG:
1466 config_set_longlong_param (&global_config, k->section, k->name,
1467 k->value);
1468 break;
1469 case PARAM_CHARP:
1470 config_set_string_param (&global_config, k->section, k->name,
1471 k->value);
1472 break;
1473 case PARAM_CHARPP:
1474 config_set_list_param (&global_config, k->section, k->name, k->value);
1475 break;
1476 default:
1477 break;
1480 xfree (k->section);
1481 xfree (k->name);
1482 xfree (k->value);
1483 xfree (k);
1486 slist_free (keep);