Fix cancellation of gpgme without pthread_cancel.
[libpwmd.git] / src / rcfile.c
blob2ef7ccfa317aa02c29bf462dc7fee2d70ea201c5
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <ctype.h>
32 #include <pwd.h>
33 #include <grp.h>
35 #include "pwmd-error.h"
36 #include "mutex.h"
37 #include "rcfile.h"
38 #include "util-misc.h"
39 #include "common.h"
40 #include "util-slist.h"
41 #include "util-string.h"
42 #include "mem.h"
44 #define DEFAULT_CACHE_TIMEOUT "600"
45 #define DEFAULT_KEEPALIVE_INTERVAL "60"
46 #define DEFAULT_LOCK_TIMEOUT "50" // MUTEX_TRYLOCK in tenths of a second
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 char *name;
62 int type;
63 char *value;
64 } config_params[] = {
65 { "backup", PARAM_BOOL, "true"},
66 { "socket_path", PARAM_CHARP, NULL},
67 { "socket_perms", PARAM_CHARP, NULL},
68 { "passphrase_file", PARAM_CHARP, NULL},
69 { "log_path", PARAM_CHARP, "~/.pwmd/log"},
70 { "enable_logging", PARAM_BOOL, "0"},
71 { "log_keepopen", PARAM_BOOL, "true"},
72 { "log_level", PARAM_INT, "0"},
73 { "disable_mlockall", PARAM_BOOL, "true"},
74 { "cache_timeout", PARAM_INT, DEFAULT_CACHE_TIMEOUT},
75 { "cache_push", PARAM_CHARPP, NULL},
76 { "disable_list_and_dump", PARAM_BOOL, "false"},
77 { "recursion_depth", PARAM_INT, "100"},
78 { "syslog", PARAM_BOOL, "false"},
79 { "xfer_progress", PARAM_INT, "8196"},
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, "SECURE256:SECURE192:SECURE128:-VERS-SSL3.0:-VERS-TLS1.0"},
91 { "tls_dh_params_file", PARAM_CHARP, NULL},
92 { "require_save_key", PARAM_BOOL, "true"},
93 { "invoking_user", PARAM_CHARPP, NULL},
94 { "invoking_file", PARAM_CHARP, NULL},
95 { "encrypt_to", PARAM_BOOL, "false"},
96 { "always_trust", PARAM_BOOL, "false"},
97 { "gpg_homedir", PARAM_CHARP, NULL},
98 { "strict_kill", PARAM_BOOL, "false"},
99 { "lock_timeout", PARAM_INT, DEFAULT_LOCK_TIMEOUT},
100 { "send_state", PARAM_INT, "2"},
101 { "kill_scd", PARAM_BOOL, "false"},
102 { NULL, PARAM_INVALID, NULL},
105 struct config_param_s
107 char *name;
108 int type;
109 union
111 int itype;
112 char *cptype;
113 char **cpptype;
114 long ltype;
115 long long lltype;
116 } value;
119 struct config_keep_s
121 char *section;
122 char *name;
123 char *value;
126 static struct config_section_s *config_find_section (struct slist_s *config,
127 const char *name);
128 static int new_param (struct config_section_s *section, const char *filename,
129 int lineno, const char *name, const char *value,
130 int type);
131 static void free_section (struct config_section_s *s);
132 static int set_defaults (struct slist_s **config, int reload);
134 static void
135 section_remove_param (struct config_section_s *section, const char *name)
137 unsigned i, t = slist_length (section->params);
139 for (i = 0; i < t; i++)
141 struct config_param_s *p = slist_nth_data (section->params, i);
143 if (!p)
144 continue;
146 if (!strcmp (p->name, name))
148 switch (p->type)
150 case PARAM_CHARP:
151 xfree (p->value.cptype);
152 break;
153 case PARAM_CHARPP:
154 strv_free (p->value.cpptype);
155 break;
158 section->params = slist_remove (section->params, p);
159 xfree (p->name);
160 xfree (p);
161 break;
166 static struct config_param_s *
167 config_has_param (struct config_section_s *s, const char *what)
169 unsigned i, t = slist_length (s->params);
171 for (i = 0; i < t; i++)
173 struct config_param_s *p = slist_nth_data (s->params, i);
174 if (!p)
175 break;
177 if (!strcmp (p->name, what))
178 return p;
181 return NULL;
184 static struct config_param_s *
185 config_get_param (struct slist_s *config,
186 const char *section, const char *what, int *exists)
188 unsigned i, t = slist_length (config);
190 *exists = 0;
192 for (i = 0; i < t; i++)
194 struct config_param_s *p;
195 struct config_section_s *s = slist_nth_data (config, i);
197 if (!s)
198 break;
200 if (strcmp (s->name, section))
201 continue;
203 p = config_has_param (s, what);
204 if (!p)
205 return NULL;
207 *exists = 1;
208 return p;
211 return NULL;
214 static struct config_section_s *
215 new_section (struct slist_s **config, const char *name)
217 struct slist_s *tmp;
218 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
220 if (!s)
221 return NULL;
223 s->name = str_dup (name);
224 if (!s->name)
226 log_write ("%s", pwmd_strerror (ENOMEM));
227 xfree (s);
228 return NULL;
231 tmp = slist_append (*config, s);
232 if (!tmp)
234 log_write ("%s", pwmd_strerror (ENOMEM));
235 xfree (s->name);
236 xfree (s);
237 return NULL;
240 *config = tmp;
241 return s;
245 config_set_string_param (struct slist_s **config, const char *section,
246 const char *name, const char *value)
248 struct config_section_s *s = config_find_section (*config, section);
250 if (!s)
252 s = new_section (config, section);
253 if (!s)
254 return 1;
257 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
260 char *
261 config_get_string_param (struct slist_s *config, const char *section,
262 const char *what, int *exists)
264 struct config_param_s *p = config_get_param (config, section, what, exists);
265 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
269 config_set_int_param (struct slist_s **config, const char *section,
270 const char *name, const char *value)
272 struct config_section_s *s = config_find_section (*config, section);
274 if (!s)
276 s = new_section (config, section);
277 if (!s)
278 return 1;
281 return new_param (s, NULL, 0, name, value, PARAM_INT);
285 config_get_int_param (struct slist_s *config, const char *section,
286 const char *what, int *exists)
288 struct config_param_s *p = config_get_param (config, section, what, exists);
289 return *exists ? p->value.itype : -1;
293 config_set_bool_param (struct slist_s **config, const char *section,
294 const char *name, const char *value)
296 struct config_section_s *s = config_find_section (*config, section);
298 if (!s)
300 s = new_section (config, section);
301 if (!s)
302 return 1;
305 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
309 config_get_bool_param (struct slist_s *config, const char *section,
310 const char *what, int *exists)
312 return config_get_int_param (config, section, what, exists);
316 config_set_long_param (struct slist_s **config, const char *section,
317 const char *name, const char *value)
319 struct config_section_s *s = config_find_section (*config, section);
321 if (!s)
323 s = new_section (config, section);
324 if (!s)
325 return 1;
328 return new_param (s, NULL, 0, name, value, PARAM_LONG);
331 long
332 config_get_long_param (struct slist_s *config, const char *section,
333 const char *what, int *exists)
335 struct config_param_s *p = config_get_param (config, section, what, exists);
336 return *exists ? p->value.ltype : -1;
340 config_set_longlong_param (struct slist_s **config, const char *section,
341 const char *name, const char *value)
343 struct config_section_s *s = config_find_section (*config, section);
345 if (!s)
347 s = new_section (config, section);
348 if (!s)
349 return 1;
352 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
355 long long
356 config_get_longlong_param (struct slist_s *config,
357 const char *section, const char *what, int *exists)
359 struct config_param_s *p = config_get_param (config, section, what, exists);
360 return *exists ? p->value.lltype : -1;
364 config_set_list_param (struct slist_s **config, const char *section,
365 const char *name, const char *value)
367 struct config_section_s *s = config_find_section (*config, section);
369 if (!s)
371 s = new_section (config, section);
372 if (!s)
373 return 1;
376 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
379 char **
380 config_get_list_param (struct slist_s *config, const char *section,
381 const char *what, int *exists)
383 struct config_param_s *p = config_get_param (config, section, what, exists);
384 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
387 char *
388 config_get_string (const char *section, const char *what)
390 char *val = NULL;
391 const char *where = section ? section : "global";
392 int exists = 0;
394 MUTEX_LOCK (&rcfile_mutex);
395 val = config_get_string_param (global_config, where, what, &exists);
396 if (!exists && strcmp (section ? section : "", "global"))
397 val = config_get_string_param (global_config, "global", what, &exists);
399 MUTEX_UNLOCK (&rcfile_mutex);
400 return val;
403 char **
404 config_get_list (const char *section, const char *what)
406 char **val = NULL;
407 const char *where = section ? section : "global";
408 int exists = 0;
410 MUTEX_LOCK (&rcfile_mutex);
411 val = config_get_list_param (global_config, where, what, &exists);
412 if (!exists && strcmp (section ? section : "", "global"))
413 val = config_get_list_param (global_config, "global", what, &exists);
415 MUTEX_UNLOCK (&rcfile_mutex);
416 return val;
420 config_get_integer (const char *section, const char *what)
422 int val = 0;
423 const char *where = section ? section : "global";
424 int exists = 0;
426 MUTEX_LOCK (&rcfile_mutex);
427 val = config_get_int_param (global_config, where, what, &exists);
428 if (!exists && strcmp (section ? section : "", "global"))
429 val = config_get_int_param (global_config, "global", what, &exists);
431 MUTEX_UNLOCK (&rcfile_mutex);
432 return val;
435 long long
436 config_get_longlong (const char *section, const char *what)
438 long long val = 0;
439 const char *where = section ? section : "global";
440 int exists = 0;
442 MUTEX_LOCK (&rcfile_mutex);
443 val = config_get_longlong_param (global_config, where, what, &exists);
444 if (!exists && strcmp (section ? section : "", "global"))
445 val = config_get_longlong_param (global_config, "global", what, &exists);
447 MUTEX_UNLOCK (&rcfile_mutex);
448 return val;
451 long
452 config_get_long (const char *section, const char *what)
454 long val = 0;
455 const char *where = section ? section : "global";
456 int exists = 0;
458 MUTEX_LOCK (&rcfile_mutex);
459 val = config_get_long_param (global_config, where, what, &exists);
460 if (!exists && strcmp (section ? section : "", "global"))
461 val = config_get_long_param (global_config, "global", what, &exists);
463 MUTEX_UNLOCK (&rcfile_mutex);
464 return val;
468 config_get_boolean (const char *section, const char *what)
470 return config_get_integer (section, what);
473 char *
474 config_get_value (const char *section, const char *what)
476 const char *where = section ? section : "global";
477 int exists = 0;
478 int i;
479 int ival;
480 long lval;
481 long long llval;
482 char *cpval;
483 char **cppval;
484 char *result = NULL;
486 MUTEX_LOCK (&rcfile_mutex);
488 for (i = 0; config_params[i].name; i++)
490 if (!strcmp (config_params[i].name, what))
492 switch (config_params[i].type)
494 case PARAM_BOOL:
495 case PARAM_INT:
496 ival = config_get_int_param (global_config, where, what,
497 &exists);
498 if (!exists && strcmp (section ? section : "", "global"))
499 ival = config_get_int_param (global_config, "global", what,
500 &exists);
501 result = str_asprintf ("%i", ival);
502 break;
503 case PARAM_CHARP:
504 cpval = config_get_string_param (global_config, where, what,
505 &exists);
506 if (!exists && strcmp (section ? section : "", "global"))
507 cpval =
508 config_get_string_param (global_config, "global", what,
509 &exists);
510 result = cpval;
511 break;
512 case PARAM_LONG:
513 lval = config_get_long_param (global_config, where, what,
514 &exists);
515 if (!exists && strcmp (section ? section : "", "global"))
516 lval = config_get_long_param (global_config, "global", what,
517 &exists);
518 result = str_asprintf ("%li", lval);
519 break;
520 case PARAM_LONGLONG:
521 llval = config_get_longlong_param (global_config, where, what,
522 &exists);
523 if (!exists && strcmp (section ? section : "", "global"))
524 llval = config_get_longlong_param (global_config, "global",
525 what, &exists);
526 result = str_asprintf ("%lli", llval);
527 break;
528 case PARAM_CHARPP:
529 cppval = config_get_list_param (global_config, where, what,
530 &exists);
531 if (!exists && strcmp (section ? section : "", "global"))
532 cppval = config_get_list_param (global_config, "global", what,
533 &exists);
535 if (cppval)
536 result = strv_join (",", cppval);
538 strv_free (cppval);
539 break;
544 MUTEX_UNLOCK (&rcfile_mutex);
545 return result;
548 /* 'file' is the list parameter file to load into the list parameter 'what'.
549 * The parsing of the parameter is not done here. */
550 static gpg_error_t
551 parse_list_file (struct slist_s *config, const char *section,
552 const char *file, const char *what)
554 FILE *fp;
555 char buf[LINE_MAX] = {0};
556 int exists;
557 char **list = NULL;
558 char *tmp;
559 char *p = config_get_string_param (config, section, file, &exists);
560 gpg_error_t rc;
562 if (!p || !*p)
564 xfree (p);
565 return 0;
568 tmp = expand_homedir (p);
569 xfree (p);
570 p = tmp;
571 fp = fopen (p, "r");
572 if (!fp)
574 rc = gpg_error_from_errno (errno);
575 log_write ("%s: %s", p, pwmd_strerror (rc));
576 xfree (p);
577 return rc;
580 xfree (p);
581 list = config_get_list_param (config, section, what, &exists);
582 if (!list && exists)
584 fclose (fp);
585 log_write ("%s", pwmd_strerror (ENOMEM));
586 return gpg_error (ENOMEM);
589 while ((p = fgets (buf, sizeof (buf)-1, fp)))
591 char **pp = NULL;
593 if (p[strlen(p)-1] == '\n')
594 p[strlen(p)-1] = 0;
596 while (*p && isspace (*p))
597 p++;
599 if (!*p || *p == ';')
600 continue;
602 tmp = str_dup (p);
603 if (tmp)
604 pp = strv_cat (list, str_dup (p));
606 if (!pp || !tmp)
608 xfree (tmp);
609 strv_free (list);
610 fclose (fp);
611 log_write ("%s", strerror (ENOMEM));
612 return gpg_error (ENOMEM);
615 xfree (tmp);
616 list = pp;
619 fclose(fp);
620 if (!list)
621 return 0;
623 p = strv_join (",", list);
624 strv_free (list);
626 if (!p)
628 log_write ("%s", pwmd_strerror (ENOMEM));
629 return gpg_error (ENOMEM);
632 config_set_list_param (&config, section, what, p);
633 xfree (p);
634 return 0;
637 static int
638 fixup_allowed_once (struct slist_s **config, const char *section)
640 char **list, **pp, *p;
641 int exists;
642 gpg_error_t rc;
644 rc = parse_list_file (*config, section, "allowed_file", "allowed");
645 if (rc)
646 return 1;
648 list = config_get_list_param (*config, section, "allowed", &exists);
649 for (pp = list; pp && *pp; pp++)
651 if (*(*pp) == '#')
653 for (p = *pp; p && *p; p++)
654 *p = toupper(*p);
658 strv_free (list);
659 if (!exists)
661 if (!strcmp (section, "global"))
663 p = get_username (getuid());
665 if (config_set_list_param (config, section, "allowed", p))
667 xfree (p);
668 return 1;
671 xfree (p);
673 else
675 list = config_get_list_param (*config, "global", "allowed", &exists);
676 if (list)
678 p = strv_join (",", list);
679 strv_free (list);
680 if (config_set_list_param (config, section, "allowed", p))
682 xfree (p);
683 return 1;
686 xfree (p);
691 return 0;
694 static int
695 fixup_allowed (struct slist_s **config)
697 int n, t = slist_length (*config);
699 for (n = 0; n < t; n++)
701 struct config_section_s *section;
703 section = slist_nth_data (*config, n);
704 if (fixup_allowed_once (config, section->name))
705 return 1;
708 return 0;
711 static int
712 add_invoking_user (struct invoking_user_s **users, char *id,
713 struct slist_s **config)
715 struct passwd *pwd = NULL;
716 struct group *grp = NULL;
717 struct invoking_user_s *user, *p;
718 int not = 0;
720 if (id && (*id == '!' || *id == '-'))
722 not = 1;
723 id++;
726 errno = 0;
727 if (!id || !*id)
729 pwd = getpwuid (getuid ());
730 if (!pwd)
732 log_write (_("could not set any invoking user: %s"),
733 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
734 return 1;
737 else if (*id == '@')
739 grp = getgrnam (id+1);
740 if (!grp)
742 log_write (_("could not parse group '%s': %s"), id+1,
743 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
744 return 1;
747 else if (*id != '#')
748 pwd = getpwnam (id);
750 if (!grp && !pwd && id && *id != '#')
752 if (id && *id)
753 log_write (_("could not set invoking user '%s': %s"), id,
754 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
755 else
756 log_write (_("could not set any invoking user!"));
758 return 1;
761 user = xcalloc (1, sizeof (struct invoking_user_s));
762 if (!user)
764 log_write ("%s", pwmd_strerror (ENOMEM));
765 return 1;
768 user->not = not;
769 user->type = pwd ? INVOKING_UID : grp ? INVOKING_GID : INVOKING_TLS;
770 if (pwd)
771 user->uid = pwd->pw_uid;
772 else if (grp)
773 user->id = str_dup (id+1);
774 else
776 char *s;
778 for (s = id; s && *s; s++)
779 *s = toupper(*s);
781 user->id = str_dup (id+1);
784 /* Set the default invoking_user since it doesn't exist. */
785 if (!id || !*id)
786 config_set_list_param (config, "global", "invoking_user", pwd->pw_name);
788 if (!*users)
790 *users = user;
791 return 0;
794 for (p = *users; p; p = p->next)
796 if (!p->next)
798 p->next = user;
799 break;
803 return 0;
806 static int
807 parse_invoking_users (struct slist_s **config)
809 struct invoking_user_s *users = NULL;
810 int exists;
811 char **list, **l;
813 if (parse_list_file (*config, "global", "invoking_file", "invoking_user"))
814 return 1;
816 list = config_get_list_param (*config, "global", "invoking_user", &exists);
817 for (l = list; l && *l; l++)
819 if (add_invoking_user (&users, *l, config))
821 strv_free (list);
822 free_invoking_users (users);
823 return 1;
827 if (!list || !*list)
829 if (add_invoking_user (&users, NULL, config))
831 strv_free (list);
832 return 1;
836 free_invoking_users (invoking_users);
837 invoking_users = users;
838 strv_free (list);
839 return 0;
842 static int
843 set_defaults (struct slist_s **config, int reload)
845 char *s = NULL;
846 char **list;
847 int exists;
848 int i;
850 for (i = 0; config_params[i].name; i++)
852 switch (config_params[i].type)
854 case PARAM_BOOL:
855 config_get_bool_param (*config, "global", config_params[i].name,
856 &exists);
857 if (!exists)
859 if (config_set_bool_param
860 (config, "global", config_params[i].name,
861 config_params[i].value))
862 goto fail;
864 break;
865 case PARAM_INT:
866 config_get_int_param (*config, "global", config_params[i].name,
867 &exists);
868 if (!exists)
870 if (config_set_int_param
871 (config, "global", config_params[i].name,
872 config_params[i].value))
873 goto fail;
875 break;
876 case PARAM_CHARP:
877 s = config_get_string_param (*config, "global",
878 config_params[i].name, &exists);
879 xfree (s);
880 if (!exists && config_params[i].value)
882 if (config_set_string_param (config, "global",
883 config_params[i].name,
884 config_params[i].value))
885 goto fail;
887 break;
888 case PARAM_CHARPP:
889 list = config_get_list_param (*config, "global",
890 config_params[i].name, &exists);
891 strv_free (list);
892 if (!exists && config_params[i].value)
894 if (config_set_list_param (config, "global",
895 config_params[i].name,
896 config_params[i].value))
897 goto fail;
899 break;
900 case PARAM_LONG:
901 config_get_long_param (*config, "global", config_params[i].name,
902 &exists);
903 if (!exists)
905 if (config_set_long_param
906 (config, "global", config_params[i].name,
907 config_params[i].value))
908 goto fail;
910 break;
911 case PARAM_LONGLONG:
912 config_get_longlong_param (*config, "global", config_params[i].name,
913 &exists);
914 if (!exists)
916 if (config_set_longlong_param (config, "global",
917 config_params[i].name,
918 config_params[i].value))
919 goto fail;
921 break;
925 s = NULL;
926 if (!reload && fixup_allowed (config))
927 goto fail;
929 if (!reload && parse_invoking_users (config))
930 goto fail;
932 log_level = config_get_int_param (*config, "global",
933 "log_level", &exists);
934 log_keepopen = config_get_int_param (*config, "global",
935 "log_keepopen", &exists);
936 max_recursion_depth = config_get_int_param (*config, "global",
937 "recursion_depth", &exists);
938 disable_list_and_dump = config_get_bool_param (*config, "global",
939 "disable_list_and_dump",
940 &exists);
941 #ifdef HAVE_MLOCKALL
942 disable_mlock =
943 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
944 #endif
946 xfree (s);
947 return 0;
949 fail:
950 xfree (s);
951 return 1;
954 static struct config_section_s *
955 config_find_section (struct slist_s *config, const char *name)
957 unsigned i, t = slist_length (config);
959 for (i = 0; i < t; i++)
961 struct config_section_s *s = slist_nth_data (config, i);
963 if (!strcmp (s->name, name))
964 return s;
967 return NULL;
970 /* Append a new parameter to the list of parameters for a file
971 * section. When an existing parameter of the same name exists, its
972 * value is updated.
974 static int
975 new_param (struct config_section_s *section, const char *filename, int lineno,
976 const char *name, const char *value, int type)
978 struct config_param_s *param = NULL;
979 struct slist_s *tmp;
980 char *e;
981 unsigned i, t = slist_length (section->params);
982 int dup = 0;
984 for (i = 0; i < t; i++)
986 struct config_param_s *p = slist_nth_data (section->params, i);
987 if (!p)
988 break;
990 if (!strcmp (name, p->name))
992 param = p;
993 dup = 1;
994 break;
998 if (!param)
1000 param = xcalloc (1, sizeof (struct config_param_s));
1001 if (!param)
1003 log_write ("%s", pwmd_strerror (ENOMEM));
1004 return 1;
1007 param->name = str_dup (name);
1008 if (!param->name)
1010 xfree (param);
1011 log_write ("%s", pwmd_strerror (ENOMEM));
1012 return 1;
1016 param->type = type;
1018 switch (type)
1020 case PARAM_BOOL:
1021 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1022 || !strcasecmp (value, "false"))
1023 param->value.itype = 0;
1024 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1025 || !strcasecmp (value, "true"))
1026 param->value.itype = 1;
1027 else
1029 INVALID_VALUE (filename, lineno);
1030 goto fail;
1032 param->type = PARAM_INT;
1033 break;
1034 case PARAM_CHARP:
1035 xfree (param->value.cptype);
1036 param->value.cptype = NULL;
1037 param->value.cptype = value && *value ? str_dup (value) : NULL;
1038 if (value && *value && !param->value.cptype)
1040 log_write ("%s", pwmd_strerror (ENOMEM));
1041 goto fail;
1043 break;
1044 case PARAM_CHARPP:
1045 strv_free (param->value.cpptype);
1046 param->value.cpptype = NULL;
1047 param->value.cpptype = value && *value ?
1048 str_split_ws (value, ",", 0) : NULL;
1049 if (value && *value && !param->value.cpptype)
1051 log_write ("%s", pwmd_strerror (ENOMEM));
1052 goto fail;
1054 break;
1055 case PARAM_INT:
1056 param->value.itype = strtol (value, &e, 10);
1057 if (e && *e)
1059 INVALID_VALUE (filename, lineno);
1060 goto fail;
1062 break;
1063 case PARAM_LONG:
1064 param->value.ltype = strtol (value, &e, 10);
1065 if (e && *e)
1067 INVALID_VALUE (filename, lineno);
1068 goto fail;
1070 break;
1071 case PARAM_LONGLONG:
1072 param->value.lltype = strtoll (value, &e, 10);
1073 if (e && *e)
1075 INVALID_VALUE (filename, lineno);
1076 goto fail;
1078 break;
1081 if (dup)
1082 return 0;
1084 tmp = slist_append (section->params, param);
1085 if (!tmp)
1087 log_write ("%s", pwmd_strerror (ENOMEM));
1088 goto fail;
1091 section->params = tmp;
1092 return 0;
1094 fail:
1095 xfree (param->name);
1096 xfree (param);
1097 return 1;
1100 struct slist_s *
1101 config_parse (const char *filename, int reload)
1103 struct slist_s *tmpconfig = NULL, *tmp;
1104 struct config_section_s *cur_section = NULL;
1105 char buf[LINE_MAX] = {0};
1106 char *s;
1107 int lineno = 1;
1108 int have_global = 0;
1109 FILE *fp = fopen (filename, "r");
1111 if (!fp)
1113 log_write ("%s: %s", filename,
1114 pwmd_strerror (gpg_error_from_errno (errno)));
1116 if (errno != ENOENT)
1117 return NULL;
1119 log_write (_("Using defaults!"));
1120 goto defaults;
1123 for (; (s = fgets (buf, sizeof (buf)-1, fp)); lineno++)
1125 char line[LINE_MAX] = { 0 };
1126 size_t len = 0;
1128 if (*s == '#')
1129 continue;
1131 s = str_chomp (s);
1132 for (; s && *s; s++)
1134 int match = 0;
1136 /* New file section. */
1137 if (*s == '[')
1139 struct config_section_s *section;
1140 char *p = strchr (++s, ']');
1142 if (!p)
1144 log_write (_("%s(%i): unbalanced braces"), filename,
1145 lineno);
1146 goto fail;
1149 len = strlen (s) - strlen (p);
1150 memcpy (line, s, len);
1151 line[len] = 0;
1153 section = config_find_section (tmpconfig, line);
1154 if (section)
1156 log_write (_("%s(%i): section '%s' already exists!"),
1157 filename, lineno, line);
1158 goto fail;
1161 if (!strcmp (line, "global"))
1162 have_global = 1;
1164 section = xcalloc (1, sizeof (struct config_section_s));
1165 section->name = str_dup (line);
1167 if (cur_section)
1169 tmp = slist_append (tmpconfig, cur_section);
1170 if (!tmp)
1172 log_write ("%s", pwmd_strerror (ENOMEM));
1173 goto fail;
1176 tmpconfig = tmp;
1179 cur_section = section;
1180 break;
1183 if (!cur_section)
1185 log_write (_("%s(%i): parameter outside of section!"), filename,
1186 lineno);
1187 goto fail;
1190 /* Parameters for each section. */
1191 for (int m = 0; config_params[m].name; m++)
1193 size_t len = strlen (config_params[m].name);
1195 if (!strncmp (s, config_params[m].name, len))
1197 char *p = s + len;
1199 while (*p && *p == ' ')
1200 p++;
1202 if (!*p || *p != '=')
1203 continue;
1205 p++;
1206 while (*p && isspace (*p))
1207 p++;
1209 s[len] = 0;
1210 if (new_param (cur_section, filename, lineno, s, p,
1211 config_params[m].type))
1212 goto fail;
1214 match = 1;
1215 break;
1219 if (!match)
1221 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1222 goto fail;
1225 break;
1229 if (cur_section)
1231 tmp = slist_append (tmpconfig, cur_section);
1232 if (!tmp)
1234 log_write ("%s", pwmd_strerror (ENOMEM));
1235 goto fail;
1238 cur_section = NULL;
1239 tmpconfig = tmp;
1242 if (!have_global)
1243 log_write (_
1244 ("WARNING: %s: could not find a [global] configuration section!"),
1245 filename);
1247 defaults:
1248 if (set_defaults (&tmpconfig, reload))
1249 goto fail;
1251 if (fp)
1252 fclose(fp);
1254 return tmpconfig;
1256 fail:
1257 if (fp)
1258 fclose (fp);
1260 config_free (tmpconfig);
1261 free_section (cur_section);
1262 return NULL;
1265 static void
1266 free_section (struct config_section_s *s)
1268 if (!s)
1269 return;
1271 for (;;)
1273 struct config_param_s *p = slist_nth_data (s->params, 0);
1275 if (!p)
1276 break;
1278 section_remove_param (s, p->name);
1281 s->params = NULL;
1282 xfree (s->name);
1283 s->name = NULL;
1286 void
1287 config_free (struct slist_s *config)
1289 for (;;)
1291 struct config_section_s *s = slist_nth_data (config, 0);
1292 if (!s)
1293 break;
1295 free_section (s);
1296 config = slist_remove (config, s);
1297 xfree (s);
1301 void
1302 free_invoking_users (struct invoking_user_s *users)
1304 struct invoking_user_s *p;
1306 for (p = users; p;)
1308 struct invoking_user_s *next = p->next;
1310 if (p->type == INVOKING_TLS || p->type == INVOKING_GID)
1311 xfree (p->id);
1313 xfree (p);
1314 p = next;
1318 static int
1319 param_type (const char *name)
1321 int i;
1323 for (i = 0; config_params[i].name; i++)
1325 if (!strcmp (config_params[i].name, name))
1326 return config_params[i].type;
1329 return PARAM_INVALID;
1332 static int
1333 keep_parse (struct config_keep_s *k, const char *section, const char *key)
1335 int exists;
1336 int ival;
1337 long lval;
1338 long long llval;
1339 char *cpval;
1340 char **cppval;
1341 int type = param_type (key);
1342 void *value = NULL;
1344 switch (type)
1346 case PARAM_BOOL:
1347 case PARAM_INT:
1348 ival = config_get_int_param (global_config, section, key, &exists);
1349 if (exists)
1350 value = str_asprintf ("%i", ival);
1351 break;
1352 case PARAM_LONG:
1353 lval = config_get_long_param (global_config, section, key, &exists);
1354 if (exists)
1355 value = str_asprintf ("%li", lval);
1356 break;
1357 case PARAM_LONGLONG:
1358 llval = config_get_longlong_param (global_config, section, key, &exists);
1359 if (exists)
1360 value = str_asprintf ("%lli", llval);
1361 break;
1362 case PARAM_CHARP:
1363 cpval = config_get_string_param (global_config, section, key, &exists);
1364 if (exists)
1365 value = cpval;
1366 break;
1367 case PARAM_CHARPP:
1368 cppval = config_get_list_param (global_config, section, key, &exists);
1369 if (exists)
1371 char *s = strv_join (",", cppval);
1373 strv_free (cppval);
1374 value = s;
1376 break;
1377 default:
1378 return 1;
1381 if (!value)
1382 return 1;
1384 k->section = str_dup(section);
1385 k->name = str_dup(key);
1386 k->value = value;
1387 return 0;
1390 static struct slist_s *
1391 keep_add (struct slist_s *k, const char *s, const char *key)
1393 int n, t = slist_length (global_config);
1395 for (n = 0; n < t; n++)
1397 struct config_section_s *section;
1398 struct config_keep_s *tmp;
1399 int ret;
1401 section = slist_nth_data (global_config, n);
1402 tmp = xcalloc (1, sizeof(struct config_keep_s));
1404 // Process all sections.
1405 if (!s)
1406 ret = keep_parse (tmp, section->name, key);
1407 else
1408 ret = keep_parse (tmp, s, key);
1410 if (!ret)
1411 k = slist_append (k, tmp);
1412 else
1413 xfree (tmp);
1416 return k;
1419 /* Keep security sensitive settings across SIGHUP. */
1420 struct slist_s *
1421 config_keep_save ()
1423 struct slist_s *keep = NULL;
1425 #ifdef WITH_GNUTLS
1426 keep = keep_add (keep, NULL, "tcp_require_key");
1427 #endif
1428 keep = keep_add (keep, NULL, "require_save_key");
1429 keep = keep_add (keep, NULL, "allowed");
1430 keep = keep_add (keep, "global", "encrypt_to");
1431 keep = keep_add (keep, "global", "always_trust");
1432 keep = keep_add (keep, "global", "invoking_user");
1433 return keep;
1436 /* Restore parameters previously saved with config_keep_save(). This will also
1437 * free the 'keep'.
1439 void
1440 config_keep_restore (struct slist_s *keep)
1442 int n, t = slist_length (keep);
1444 for (n = 0; n < t; n++)
1446 struct config_keep_s *k = slist_nth_data (keep, n);
1447 int type = param_type (k->name);
1449 switch (type)
1451 case PARAM_BOOL:
1452 config_set_bool_param (&global_config, k->section, k->name, k->value);
1453 break;
1454 case PARAM_INT:
1455 config_set_int_param (&global_config, k->section, k->name, k->value);
1456 break;
1457 case PARAM_LONG:
1458 config_set_long_param (&global_config, k->section, k->name, k->value);
1459 break;
1460 case PARAM_LONGLONG:
1461 config_set_longlong_param (&global_config, k->section, k->name,
1462 k->value);
1463 break;
1464 case PARAM_CHARP:
1465 config_set_string_param (&global_config, k->section, k->name,
1466 k->value);
1467 break;
1468 case PARAM_CHARPP:
1469 config_set_list_param (&global_config, k->section, k->name, k->value);
1470 break;
1471 default:
1472 break;
1475 xfree (k->section);
1476 xfree (k->name);
1477 xfree (k->value);
1478 xfree (k);
1481 slist_free (keep);