Remove unused find_sibling_node ().
[pwmd.git] / src / rcfile.c
blob4de4c2dd0047c1d48c1cf2dcb7bd5a28831e8371
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <ctype.h>
32 #include <pwd.h>
33 #include <grp.h>
35 #include "pwmd-error.h"
36 #include "mutex.h"
37 #include "rcfile.h"
38 #include "util-misc.h"
39 #include "common.h"
40 #include "util-slist.h"
41 #include "util-string.h"
42 #include "mem.h"
44 #define DEFAULT_CACHE_TIMEOUT "600"
45 #define DEFAULT_KEEPALIVE_INTERVAL "60"
46 #define DEFAULT_LOCK_TIMEOUT "50" // MUTEX_TRYLOCK in tenths of a second
47 #define DEFAULT_TLS_KX_REGEN_INTERVAL "43200" // 12 hours
49 #define INVALID_VALUE(file, line) do { \
50 if (file) \
51 log_write(_("%s(%i): invalid value for parameter."), file, line); \
52 } while (0);
54 enum
56 PARAM_INT, PARAM_CHARP, PARAM_LONG, PARAM_LONGLONG, PARAM_CHARPP,
57 PARAM_BOOL, PARAM_INVALID
60 static struct config_params_s
62 char *name;
63 int type;
64 char *value;
65 } config_params[] = {
66 { "backup", PARAM_BOOL, "true"},
67 { "socket_path", PARAM_CHARP, NULL},
68 { "socket_perms", PARAM_CHARP, NULL},
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_INT, 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 { "xfer_progress", PARAM_INT, "8196"},
81 { "allowed", PARAM_CHARPP, NULL},
82 { "allowed_file", PARAM_CHARP, NULL},
83 { "priority", PARAM_INT, INVALID_PRIORITY},
84 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
85 { "tcp_port", PARAM_INT, "6466"},
86 { "enable_tcp", PARAM_BOOL, "false"},
87 { "tcp_require_key", PARAM_BOOL, "false"},
88 { "tcp_wait", PARAM_INT, "0"},
89 { "tcp_bind", PARAM_CHARP, "any"},
90 { "tcp_interface", PARAM_CHARP, NULL},
91 { "tls_timeout", PARAM_INT, "300"},
92 { "tls_cipher_suite", PARAM_CHARP, "SECURE256:SECURE192:SECURE128:-VERS-SSL3.0:-VERS-TLS1.0"},
93 { "tls_dh_level", PARAM_CHARP, "medium"},
94 { "tls_regen_interval", PARAM_INT, DEFAULT_TLS_KX_REGEN_INTERVAL},
95 { "require_save_key", PARAM_BOOL, "true"},
96 { "invoking_user", PARAM_CHARPP, NULL},
97 { "invoking_file", PARAM_CHARP, NULL},
98 { "encrypt_to", PARAM_BOOL, "false"},
99 { "always_trust", PARAM_BOOL, "false"},
100 { "gpg_homedir", PARAM_CHARP, NULL},
101 { "strict_kill", PARAM_BOOL, "false"},
102 { "lock_timeout", PARAM_INT, DEFAULT_LOCK_TIMEOUT},
103 { "send_state", PARAM_INT, "2"},
104 { "kill_scd", PARAM_BOOL, "false"},
105 { NULL, PARAM_INVALID, NULL},
108 struct config_param_s
110 char *name;
111 int type;
112 union
114 int itype;
115 char *cptype;
116 char **cpptype;
117 long ltype;
118 long long lltype;
119 } value;
122 struct config_keep_s
124 char *section;
125 char *name;
126 char *value;
129 static struct config_section_s *config_find_section (struct slist_s *config,
130 const char *name);
131 static int new_param (struct config_section_s *section, const char *filename,
132 int lineno, const char *name, const char *value,
133 int type);
134 static void free_section (struct config_section_s *s);
135 static int set_defaults (struct slist_s **config, int reload);
137 static void
138 section_remove_param (struct config_section_s *section, const char *name)
140 unsigned i, t = slist_length (section->params);
142 for (i = 0; i < t; i++)
144 struct config_param_s *p = slist_nth_data (section->params, i);
146 if (!p)
147 continue;
149 if (!strcmp (p->name, name))
151 switch (p->type)
153 case PARAM_CHARP:
154 xfree (p->value.cptype);
155 break;
156 case PARAM_CHARPP:
157 strv_free (p->value.cpptype);
158 break;
161 section->params = slist_remove (section->params, p);
162 xfree (p->name);
163 xfree (p);
164 break;
169 static struct config_param_s *
170 config_has_param (struct config_section_s *s, const char *what)
172 unsigned i, t = slist_length (s->params);
174 for (i = 0; i < t; i++)
176 struct config_param_s *p = slist_nth_data (s->params, i);
177 if (!p)
178 break;
180 if (!strcmp (p->name, what))
181 return p;
184 return NULL;
187 static struct config_param_s *
188 config_get_param (struct slist_s *config,
189 const char *section, const char *what, int *exists)
191 unsigned i, t = slist_length (config);
193 *exists = 0;
195 for (i = 0; i < t; i++)
197 struct config_param_s *p;
198 struct config_section_s *s = slist_nth_data (config, i);
200 if (!s)
201 break;
203 if (strcmp (s->name, section))
204 continue;
206 p = config_has_param (s, what);
207 if (!p)
208 return NULL;
210 *exists = 1;
211 return p;
214 return NULL;
217 static struct config_section_s *
218 new_section (struct slist_s **config, const char *name)
220 struct slist_s *tmp;
221 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
223 if (!s)
224 return NULL;
226 s->name = str_dup (name);
227 if (!s->name)
229 log_write ("%s", pwmd_strerror (ENOMEM));
230 xfree (s);
231 return NULL;
234 tmp = slist_append (*config, s);
235 if (!tmp)
237 log_write ("%s", pwmd_strerror (ENOMEM));
238 xfree (s->name);
239 xfree (s);
240 return NULL;
243 *config = tmp;
244 return s;
248 config_set_string_param (struct slist_s **config, const char *section,
249 const char *name, const char *value)
251 struct config_section_s *s = config_find_section (*config, section);
253 if (!s)
255 s = new_section (config, section);
256 if (!s)
257 return 1;
260 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
263 char *
264 config_get_string_param (struct slist_s *config, const char *section,
265 const char *what, int *exists)
267 struct config_param_s *p = config_get_param (config, section, what, exists);
268 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
272 config_set_int_param (struct slist_s **config, const char *section,
273 const char *name, const char *value)
275 struct config_section_s *s = config_find_section (*config, section);
277 if (!s)
279 s = new_section (config, section);
280 if (!s)
281 return 1;
284 return new_param (s, NULL, 0, name, value, PARAM_INT);
288 config_get_int_param (struct slist_s *config, const char *section,
289 const char *what, int *exists)
291 struct config_param_s *p = config_get_param (config, section, what, exists);
292 return *exists ? p->value.itype : -1;
296 config_set_bool_param (struct slist_s **config, const char *section,
297 const char *name, const char *value)
299 struct config_section_s *s = config_find_section (*config, section);
301 if (!s)
303 s = new_section (config, section);
304 if (!s)
305 return 1;
308 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
312 config_get_bool_param (struct slist_s *config, const char *section,
313 const char *what, int *exists)
315 return config_get_int_param (config, section, what, exists);
319 config_set_long_param (struct slist_s **config, const char *section,
320 const char *name, const char *value)
322 struct config_section_s *s = config_find_section (*config, section);
324 if (!s)
326 s = new_section (config, section);
327 if (!s)
328 return 1;
331 return new_param (s, NULL, 0, name, value, PARAM_LONG);
334 long
335 config_get_long_param (struct slist_s *config, const char *section,
336 const char *what, int *exists)
338 struct config_param_s *p = config_get_param (config, section, what, exists);
339 return *exists ? p->value.ltype : -1;
343 config_set_longlong_param (struct slist_s **config, const char *section,
344 const char *name, const char *value)
346 struct config_section_s *s = config_find_section (*config, section);
348 if (!s)
350 s = new_section (config, section);
351 if (!s)
352 return 1;
355 return new_param (s, NULL, 0, name, value, PARAM_LONGLONG);
358 long long
359 config_get_longlong_param (struct slist_s *config,
360 const char *section, const char *what, int *exists)
362 struct config_param_s *p = config_get_param (config, section, what, exists);
363 return *exists ? p->value.lltype : -1;
367 config_set_list_param (struct slist_s **config, const char *section,
368 const char *name, const char *value)
370 struct config_section_s *s = config_find_section (*config, section);
372 if (!s)
374 s = new_section (config, section);
375 if (!s)
376 return 1;
379 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
382 char **
383 config_get_list_param (struct slist_s *config, const char *section,
384 const char *what, int *exists)
386 struct config_param_s *p = config_get_param (config, section, what, exists);
387 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
390 char *
391 config_get_string (const char *section, const char *what)
393 char *val = NULL;
394 const char *where = section ? section : "global";
395 int exists = 0;
397 MUTEX_LOCK (&rcfile_mutex);
398 val = config_get_string_param (global_config, where, what, &exists);
399 if (!exists && strcmp (section ? section : "", "global"))
400 val = config_get_string_param (global_config, "global", what, &exists);
402 MUTEX_UNLOCK (&rcfile_mutex);
403 return val;
406 char **
407 config_get_list (const char *section, const char *what)
409 char **val = NULL;
410 const char *where = section ? section : "global";
411 int exists = 0;
413 MUTEX_LOCK (&rcfile_mutex);
414 val = config_get_list_param (global_config, where, what, &exists);
415 if (!exists && strcmp (section ? section : "", "global"))
416 val = config_get_list_param (global_config, "global", what, &exists);
418 MUTEX_UNLOCK (&rcfile_mutex);
419 return val;
423 config_get_integer (const char *section, const char *what)
425 int val = 0;
426 const char *where = section ? section : "global";
427 int exists = 0;
429 MUTEX_LOCK (&rcfile_mutex);
430 val = config_get_int_param (global_config, where, what, &exists);
431 if (!exists && strcmp (section ? section : "", "global"))
432 val = config_get_int_param (global_config, "global", what, &exists);
434 MUTEX_UNLOCK (&rcfile_mutex);
435 return val;
438 long long
439 config_get_longlong (const char *section, const char *what)
441 long long val = 0;
442 const char *where = section ? section : "global";
443 int exists = 0;
445 MUTEX_LOCK (&rcfile_mutex);
446 val = config_get_longlong_param (global_config, where, what, &exists);
447 if (!exists && strcmp (section ? section : "", "global"))
448 val = config_get_longlong_param (global_config, "global", what, &exists);
450 MUTEX_UNLOCK (&rcfile_mutex);
451 return val;
454 long
455 config_get_long (const char *section, const char *what)
457 long val = 0;
458 const char *where = section ? section : "global";
459 int exists = 0;
461 MUTEX_LOCK (&rcfile_mutex);
462 val = config_get_long_param (global_config, where, what, &exists);
463 if (!exists && strcmp (section ? section : "", "global"))
464 val = config_get_long_param (global_config, "global", what, &exists);
466 MUTEX_UNLOCK (&rcfile_mutex);
467 return val;
471 config_get_boolean (const char *section, const char *what)
473 return config_get_integer (section, what);
476 char *
477 config_get_value (const char *section, const char *what)
479 const char *where = section ? section : "global";
480 int exists = 0;
481 int i;
482 int ival;
483 long lval;
484 long long llval;
485 char *cpval;
486 char **cppval;
487 char *result = NULL;
489 MUTEX_LOCK (&rcfile_mutex);
491 for (i = 0; config_params[i].name; i++)
493 if (!strcmp (config_params[i].name, what))
495 switch (config_params[i].type)
497 case PARAM_BOOL:
498 case PARAM_INT:
499 ival = config_get_int_param (global_config, where, what,
500 &exists);
501 if (!exists && strcmp (section ? section : "", "global"))
502 ival = config_get_int_param (global_config, "global", what,
503 &exists);
504 result = str_asprintf ("%i", ival);
505 break;
506 case PARAM_CHARP:
507 cpval = config_get_string_param (global_config, where, what,
508 &exists);
509 if (!exists && strcmp (section ? section : "", "global"))
510 cpval =
511 config_get_string_param (global_config, "global", what,
512 &exists);
513 result = cpval;
514 break;
515 case PARAM_LONG:
516 lval = config_get_long_param (global_config, where, what,
517 &exists);
518 if (!exists && strcmp (section ? section : "", "global"))
519 lval = config_get_long_param (global_config, "global", what,
520 &exists);
521 result = str_asprintf ("%li", lval);
522 break;
523 case PARAM_LONGLONG:
524 llval = config_get_longlong_param (global_config, where, what,
525 &exists);
526 if (!exists && strcmp (section ? section : "", "global"))
527 llval = config_get_longlong_param (global_config, "global",
528 what, &exists);
529 result = str_asprintf ("%lli", llval);
530 break;
531 case PARAM_CHARPP:
532 cppval = config_get_list_param (global_config, where, what,
533 &exists);
534 if (!exists && strcmp (section ? section : "", "global"))
535 cppval = config_get_list_param (global_config, "global", what,
536 &exists);
538 if (cppval)
539 result = strv_join (",", cppval);
541 strv_free (cppval);
542 break;
547 MUTEX_UNLOCK (&rcfile_mutex);
548 return result;
551 /* 'file' is the list parameter file to load into the list parameter 'what'.
552 * The parsing of the parameter is not done here. */
553 static gpg_error_t
554 parse_list_file (struct slist_s *config, const char *section,
555 const char *file, const char *what)
557 FILE *fp;
558 char buf[LINE_MAX] = {0};
559 int exists;
560 char **list = NULL;
561 char *tmp;
562 char *p = config_get_string_param (config, section, file, &exists);
563 gpg_error_t rc;
565 if (!p || !*p)
567 xfree (p);
568 return 0;
571 tmp = expand_homedir (p);
572 xfree (p);
573 p = tmp;
574 fp = fopen (p, "r");
575 if (!fp)
577 rc = gpg_error_from_errno (errno);
578 log_write ("%s: %s", p, pwmd_strerror (rc));
579 xfree (p);
580 return rc;
583 xfree (p);
584 list = config_get_list_param (config, section, what, &exists);
585 if (!list && exists)
587 fclose (fp);
588 log_write ("%s", pwmd_strerror (ENOMEM));
589 return gpg_error (ENOMEM);
592 while ((p = fgets (buf, sizeof (buf)-1, fp)))
594 char **pp = NULL;
596 if (p[strlen(p)-1] == '\n')
597 p[strlen(p)-1] = 0;
599 while (*p && isspace (*p))
600 p++;
602 if (!*p || *p == ';')
603 continue;
605 tmp = str_dup (p);
606 if (tmp)
607 pp = strv_cat (list, str_dup (p));
609 if (!pp || !tmp)
611 xfree (tmp);
612 strv_free (list);
613 fclose (fp);
614 log_write ("%s", strerror (ENOMEM));
615 return gpg_error (ENOMEM);
618 xfree (tmp);
619 list = pp;
622 fclose(fp);
623 if (!list)
624 return 0;
626 p = strv_join (",", list);
627 strv_free (list);
629 if (!p)
631 log_write ("%s", pwmd_strerror (ENOMEM));
632 return gpg_error (ENOMEM);
635 config_set_list_param (&config, section, what, p);
636 xfree (p);
637 return 0;
640 static int
641 fixup_allowed_once (struct slist_s **config, const char *section)
643 char **list, **pp, *p;
644 int exists;
645 gpg_error_t rc;
647 rc = parse_list_file (*config, section, "allowed_file", "allowed");
648 if (rc)
649 return 1;
651 list = config_get_list_param (*config, section, "allowed", &exists);
652 for (pp = list; pp && *pp; pp++)
654 if (*(*pp) == '#')
656 for (p = *pp; p && *p; p++)
657 *p = toupper(*p);
661 strv_free (list);
662 if (!exists)
664 if (!strcmp (section, "global"))
666 p = get_username (getuid());
668 if (config_set_list_param (config, section, "allowed", p))
670 xfree (p);
671 return 1;
674 xfree (p);
676 else
678 list = config_get_list_param (*config, "global", "allowed", &exists);
679 if (list)
681 p = strv_join (",", list);
682 strv_free (list);
683 if (config_set_list_param (config, section, "allowed", p))
685 xfree (p);
686 return 1;
689 xfree (p);
694 return 0;
697 static int
698 fixup_allowed (struct slist_s **config)
700 int n, t = slist_length (*config);
702 for (n = 0; n < t; n++)
704 struct config_section_s *section;
706 section = slist_nth_data (*config, n);
707 if (fixup_allowed_once (config, section->name))
708 return 1;
711 return 0;
714 static int
715 add_invoking_user (struct invoking_user_s **users, char *id,
716 struct slist_s **config)
718 struct passwd *pwd = NULL;
719 struct group *grp = NULL;
720 struct invoking_user_s *user, *p;
721 int not = 0;
723 if (id && (*id == '!' || *id == '-'))
725 not = 1;
726 id++;
729 errno = 0;
730 if (!id || !*id)
732 pwd = getpwuid (getuid ());
733 if (!pwd)
735 log_write (_("could not set any invoking user: %s"),
736 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
737 return 1;
740 else if (*id == '@')
742 grp = getgrnam (id+1);
743 if (!grp)
745 log_write (_("could not parse group '%s': %s"), id+1,
746 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
747 return 1;
750 else if (*id != '#')
751 pwd = getpwnam (id);
753 if (!grp && !pwd && id && *id != '#')
755 if (id && *id)
756 log_write (_("could not set invoking user '%s': %s"), id,
757 pwmd_strerror (errno ? errno : GPG_ERR_INV_VALUE));
758 else
759 log_write (_("could not set any invoking user!"));
761 return 1;
764 user = xcalloc (1, sizeof (struct invoking_user_s));
765 if (!user)
767 log_write ("%s", pwmd_strerror (ENOMEM));
768 return 1;
771 user->not = not;
772 user->type = pwd ? INVOKING_UID : grp ? INVOKING_GID : INVOKING_TLS;
773 if (pwd)
774 user->uid = pwd->pw_uid;
775 else if (grp)
776 user->id = str_dup (id+1);
777 else
779 char *s;
781 for (s = id; s && *s; s++)
782 *s = toupper(*s);
784 user->id = str_dup (id+1);
787 /* Set the default invoking_user since it doesn't exist. */
788 if (!id || !*id)
789 config_set_list_param (config, "global", "invoking_user", pwd->pw_name);
791 if (!*users)
793 *users = user;
794 return 0;
797 for (p = *users; p; p = p->next)
799 if (!p->next)
801 p->next = user;
802 break;
806 return 0;
809 static int
810 parse_invoking_users (struct slist_s **config)
812 struct invoking_user_s *users = NULL;
813 int exists;
814 char **list, **l;
816 if (parse_list_file (*config, "global", "invoking_file", "invoking_user"))
817 return 1;
819 list = config_get_list_param (*config, "global", "invoking_user", &exists);
820 for (l = list; l && *l; l++)
822 if (add_invoking_user (&users, *l, config))
824 strv_free (list);
825 free_invoking_users (users);
826 return 1;
830 if (!list || !*list)
832 if (add_invoking_user (&users, NULL, config))
834 strv_free (list);
835 return 1;
839 free_invoking_users (invoking_users);
840 invoking_users = users;
841 strv_free (list);
842 return 0;
845 static int
846 set_defaults (struct slist_s **config, int reload)
848 char *s = NULL;
849 char **list;
850 int exists;
851 int i;
853 for (i = 0; config_params[i].name; i++)
855 switch (config_params[i].type)
857 case PARAM_BOOL:
858 config_get_bool_param (*config, "global", config_params[i].name,
859 &exists);
860 if (!exists)
862 if (config_set_bool_param
863 (config, "global", config_params[i].name,
864 config_params[i].value))
865 goto fail;
867 break;
868 case PARAM_INT:
869 config_get_int_param (*config, "global", config_params[i].name,
870 &exists);
871 if (!exists)
873 if (config_set_int_param
874 (config, "global", config_params[i].name,
875 config_params[i].value))
876 goto fail;
878 break;
879 case PARAM_CHARP:
880 s = config_get_string_param (*config, "global",
881 config_params[i].name, &exists);
882 xfree (s);
883 if (!exists && config_params[i].value)
885 if (config_set_string_param (config, "global",
886 config_params[i].name,
887 config_params[i].value))
888 goto fail;
890 break;
891 case PARAM_CHARPP:
892 list = config_get_list_param (*config, "global",
893 config_params[i].name, &exists);
894 strv_free (list);
895 if (!exists && config_params[i].value)
897 if (config_set_list_param (config, "global",
898 config_params[i].name,
899 config_params[i].value))
900 goto fail;
902 break;
903 case PARAM_LONG:
904 config_get_long_param (*config, "global", config_params[i].name,
905 &exists);
906 if (!exists)
908 if (config_set_long_param
909 (config, "global", config_params[i].name,
910 config_params[i].value))
911 goto fail;
913 break;
914 case PARAM_LONGLONG:
915 config_get_longlong_param (*config, "global", config_params[i].name,
916 &exists);
917 if (!exists)
919 if (config_set_longlong_param (config, "global",
920 config_params[i].name,
921 config_params[i].value))
922 goto fail;
924 break;
928 s = NULL;
929 if (!reload && fixup_allowed (config))
930 goto fail;
932 if (!reload && parse_invoking_users (config))
933 goto fail;
935 s = config_get_string_param(*config, "global", "gpg_agent_socket", &exists);
936 if (!s || !*s)
938 xfree (s);
939 s = str_asprintf ("%s/.gnupg/S.gpg-agent", get_home_dir());
940 config_set_string_param(config, "global", "gpg_agent_socket", s);
942 else
944 char *tmp = expand_homedir (s);
945 config_set_string_param(config, "global", "gpg_agent_socket", tmp);
946 xfree (tmp);
949 log_level = config_get_int_param (*config, "global",
950 "log_level", &exists);
951 log_keepopen = config_get_int_param (*config, "global",
952 "log_keepopen", &exists);
953 max_recursion_depth = config_get_int_param (*config, "global",
954 "recursion_depth", &exists);
955 disable_list_and_dump = config_get_bool_param (*config, "global",
956 "disable_list_and_dump",
957 &exists);
958 #ifdef HAVE_MLOCKALL
959 disable_mlock =
960 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
961 #endif
963 xfree (s);
964 return 0;
966 fail:
967 xfree (s);
968 return 1;
971 static struct config_section_s *
972 config_find_section (struct slist_s *config, const char *name)
974 unsigned i, t = slist_length (config);
976 for (i = 0; i < t; i++)
978 struct config_section_s *s = slist_nth_data (config, i);
980 if (!strcmp (s->name, name))
981 return s;
984 return NULL;
987 /* Append a new parameter to the list of parameters for a file
988 * section. When an existing parameter of the same name exists, its
989 * value is updated.
991 static int
992 new_param (struct config_section_s *section, const char *filename, int lineno,
993 const char *name, const char *value, int type)
995 struct config_param_s *param = NULL;
996 struct slist_s *tmp;
997 char *e;
998 unsigned i, t = slist_length (section->params);
999 int dup = 0;
1001 for (i = 0; i < t; i++)
1003 struct config_param_s *p = slist_nth_data (section->params, i);
1004 if (!p)
1005 break;
1007 if (!strcmp (name, p->name))
1009 param = p;
1010 dup = 1;
1011 break;
1015 if (!param)
1017 param = xcalloc (1, sizeof (struct config_param_s));
1018 if (!param)
1020 log_write ("%s", pwmd_strerror (ENOMEM));
1021 return 1;
1024 param->name = str_dup (name);
1025 if (!param->name)
1027 xfree (param);
1028 log_write ("%s", pwmd_strerror (ENOMEM));
1029 return 1;
1033 param->type = type;
1035 switch (type)
1037 case PARAM_BOOL:
1038 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1039 || !strcasecmp (value, "false"))
1040 param->value.itype = 0;
1041 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1042 || !strcasecmp (value, "true"))
1043 param->value.itype = 1;
1044 else
1046 INVALID_VALUE (filename, lineno);
1047 goto fail;
1049 param->type = PARAM_INT;
1050 break;
1051 case PARAM_CHARP:
1052 xfree (param->value.cptype);
1053 param->value.cptype = NULL;
1054 param->value.cptype = value && *value ? str_dup (value) : NULL;
1055 if (value && *value && !param->value.cptype)
1057 log_write ("%s", pwmd_strerror (ENOMEM));
1058 goto fail;
1060 break;
1061 case PARAM_CHARPP:
1062 strv_free (param->value.cpptype);
1063 param->value.cpptype = NULL;
1064 param->value.cpptype = value && *value ?
1065 str_split_ws (value, ",", 0) : NULL;
1066 if (value && *value && !param->value.cpptype)
1068 log_write ("%s", pwmd_strerror (ENOMEM));
1069 goto fail;
1071 break;
1072 case PARAM_INT:
1073 param->value.itype = strtol (value, &e, 10);
1074 if (e && *e)
1076 INVALID_VALUE (filename, lineno);
1077 goto fail;
1079 break;
1080 case PARAM_LONG:
1081 param->value.ltype = strtol (value, &e, 10);
1082 if (e && *e)
1084 INVALID_VALUE (filename, lineno);
1085 goto fail;
1087 break;
1088 case PARAM_LONGLONG:
1089 param->value.lltype = strtoll (value, &e, 10);
1090 if (e && *e)
1092 INVALID_VALUE (filename, lineno);
1093 goto fail;
1095 break;
1098 if (dup)
1099 return 0;
1101 tmp = slist_append (section->params, param);
1102 if (!tmp)
1104 log_write ("%s", pwmd_strerror (ENOMEM));
1105 goto fail;
1108 section->params = tmp;
1109 return 0;
1111 fail:
1112 xfree (param->name);
1113 xfree (param);
1114 return 1;
1117 struct slist_s *
1118 config_parse (const char *filename, int reload)
1120 struct slist_s *tmpconfig = NULL, *tmp;
1121 struct config_section_s *cur_section = NULL;
1122 char buf[LINE_MAX] = {0};
1123 char *s;
1124 int lineno = 1;
1125 int have_global = 0;
1126 FILE *fp = fopen (filename, "r");
1128 if (!fp)
1130 log_write ("%s: %s", filename,
1131 pwmd_strerror (gpg_error_from_errno (errno)));
1133 if (errno != ENOENT)
1134 return NULL;
1136 log_write (_("Using defaults!"));
1137 goto defaults;
1140 for (; (s = fgets (buf, sizeof (buf)-1, fp)); lineno++)
1142 char line[LINE_MAX] = { 0 };
1143 size_t len = 0;
1145 if (*s == '#')
1146 continue;
1148 s = str_chomp (s);
1149 for (; s && *s; s++)
1151 int match = 0;
1153 /* New file section. */
1154 if (*s == '[')
1156 struct config_section_s *section;
1157 char *p = strchr (++s, ']');
1159 if (!p)
1161 log_write (_("%s(%i): unbalanced braces"), filename,
1162 lineno);
1163 goto fail;
1166 len = strlen (s) - strlen (p);
1167 memcpy (line, s, len);
1168 line[len] = 0;
1170 section = config_find_section (tmpconfig, line);
1171 if (section)
1173 log_write (_("%s(%i): section '%s' already exists!"),
1174 filename, lineno, line);
1175 goto fail;
1178 if (!strcmp (line, "global"))
1179 have_global = 1;
1181 section = xcalloc (1, sizeof (struct config_section_s));
1182 section->name = str_dup (line);
1184 if (cur_section)
1186 tmp = slist_append (tmpconfig, cur_section);
1187 if (!tmp)
1189 log_write ("%s", pwmd_strerror (ENOMEM));
1190 goto fail;
1193 tmpconfig = tmp;
1196 cur_section = section;
1197 break;
1200 if (!cur_section)
1202 log_write (_("%s(%i): parameter outside of section!"), filename,
1203 lineno);
1204 goto fail;
1207 /* Parameters for each section. */
1208 for (int m = 0; config_params[m].name; m++)
1210 size_t len = strlen (config_params[m].name);
1212 if (!strncmp (s, config_params[m].name, len))
1214 char *p = s + len;
1216 while (*p && *p == ' ')
1217 p++;
1219 if (!*p || *p != '=')
1220 continue;
1222 p++;
1223 while (*p && isspace (*p))
1224 p++;
1226 s[len] = 0;
1227 if (new_param (cur_section, filename, lineno, s, p,
1228 config_params[m].type))
1229 goto fail;
1231 match = 1;
1232 break;
1236 if (!match)
1238 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1239 goto fail;
1242 break;
1246 if (cur_section)
1248 tmp = slist_append (tmpconfig, cur_section);
1249 if (!tmp)
1251 log_write ("%s", pwmd_strerror (ENOMEM));
1252 goto fail;
1255 cur_section = NULL;
1256 tmpconfig = tmp;
1259 if (!have_global)
1260 log_write (_
1261 ("WARNING: %s: could not find a [global] configuration section!"),
1262 filename);
1263 else
1265 int exists;
1266 char *tmp = config_get_string_param (tmpconfig, "global", "tls_dh_level",
1267 &exists);
1268 if (tmp)
1270 if (strcasecmp (tmp, "low") && strcasecmp (tmp, "medium")
1271 && strcasecmp (tmp, "high"))
1273 xfree (tmp);
1274 log_write (_("invalid tls_dh_level value"));
1275 goto fail;
1278 xfree (tmp);
1282 defaults:
1283 if (set_defaults (&tmpconfig, reload))
1284 goto fail;
1286 if (fp)
1287 fclose(fp);
1289 return tmpconfig;
1291 fail:
1292 if (fp)
1293 fclose (fp);
1295 config_free (tmpconfig);
1296 free_section (cur_section);
1297 return NULL;
1300 static void
1301 free_section (struct config_section_s *s)
1303 if (!s)
1304 return;
1306 for (;;)
1308 struct config_param_s *p = slist_nth_data (s->params, 0);
1310 if (!p)
1311 break;
1313 section_remove_param (s, p->name);
1316 s->params = NULL;
1317 xfree (s->name);
1318 s->name = NULL;
1321 void
1322 config_free (struct slist_s *config)
1324 for (;;)
1326 struct config_section_s *s = slist_nth_data (config, 0);
1327 if (!s)
1328 break;
1330 free_section (s);
1331 config = slist_remove (config, s);
1332 xfree (s);
1336 void
1337 free_invoking_users (struct invoking_user_s *users)
1339 struct invoking_user_s *p;
1341 for (p = users; p;)
1343 struct invoking_user_s *next = p->next;
1345 if (p->type == INVOKING_TLS || p->type == INVOKING_GID)
1346 xfree (p->id);
1348 xfree (p);
1349 p = next;
1353 static int
1354 param_type (const char *name)
1356 int i;
1358 for (i = 0; config_params[i].name; i++)
1360 if (!strcmp (config_params[i].name, name))
1361 return config_params[i].type;
1364 return PARAM_INVALID;
1367 static int
1368 keep_parse (struct config_keep_s *k, const char *section, const char *key)
1370 int exists;
1371 int ival;
1372 long lval;
1373 long long llval;
1374 char *cpval;
1375 char **cppval;
1376 int type = param_type (key);
1377 void *value = NULL;
1379 switch (type)
1381 case PARAM_BOOL:
1382 case PARAM_INT:
1383 ival = config_get_int_param (global_config, section, key, &exists);
1384 if (exists)
1385 value = str_asprintf ("%i", ival);
1386 break;
1387 case PARAM_LONG:
1388 lval = config_get_long_param (global_config, section, key, &exists);
1389 if (exists)
1390 value = str_asprintf ("%li", lval);
1391 break;
1392 case PARAM_LONGLONG:
1393 llval = config_get_longlong_param (global_config, section, key, &exists);
1394 if (exists)
1395 value = str_asprintf ("%lli", llval);
1396 break;
1397 case PARAM_CHARP:
1398 cpval = config_get_string_param (global_config, section, key, &exists);
1399 if (exists)
1400 value = cpval;
1401 break;
1402 case PARAM_CHARPP:
1403 cppval = config_get_list_param (global_config, section, key, &exists);
1404 if (exists)
1406 char *s = strv_join (",", cppval);
1408 strv_free (cppval);
1409 value = s;
1411 break;
1412 default:
1413 return 1;
1416 if (!value)
1417 return 1;
1419 k->section = str_dup(section);
1420 k->name = str_dup(key);
1421 k->value = value;
1422 return 0;
1425 static struct slist_s *
1426 keep_add (struct slist_s *k, const char *s, const char *key)
1428 int n, t = slist_length (global_config);
1430 for (n = 0; n < t; n++)
1432 struct config_section_s *section;
1433 struct config_keep_s *tmp;
1434 int ret;
1436 section = slist_nth_data (global_config, n);
1437 tmp = xcalloc (1, sizeof(struct config_keep_s));
1439 // Process all sections.
1440 if (!s)
1441 ret = keep_parse (tmp, section->name, key);
1442 else
1443 ret = keep_parse (tmp, s, key);
1445 if (!ret)
1446 k = slist_append (k, tmp);
1447 else
1448 xfree (tmp);
1451 return k;
1454 /* Keep security sensitive settings across SIGHUP. */
1455 struct slist_s *
1456 config_keep_save ()
1458 struct slist_s *keep = NULL;
1460 #ifdef WITH_GNUTLS
1461 keep = keep_add (keep, NULL, "tcp_require_key");
1462 keep = keep_add (keep, "global", "tls_regen_interval");
1463 #endif
1464 keep = keep_add (keep, NULL, "require_save_key");
1465 keep = keep_add (keep, NULL, "allowed");
1466 keep = keep_add (keep, "global", "encrypt_to");
1467 keep = keep_add (keep, "global", "always_trust");
1468 keep = keep_add (keep, "global", "invoking_user");
1469 return keep;
1472 /* Restore parameters previously saved with config_keep_save(). This will also
1473 * free the 'keep'.
1475 void
1476 config_keep_restore (struct slist_s *keep)
1478 int n, t = slist_length (keep);
1480 for (n = 0; n < t; n++)
1482 struct config_keep_s *k = slist_nth_data (keep, n);
1483 int type = param_type (k->name);
1485 switch (type)
1487 case PARAM_BOOL:
1488 config_set_bool_param (&global_config, k->section, k->name, k->value);
1489 break;
1490 case PARAM_INT:
1491 config_set_int_param (&global_config, k->section, k->name, k->value);
1492 break;
1493 case PARAM_LONG:
1494 config_set_long_param (&global_config, k->section, k->name, k->value);
1495 break;
1496 case PARAM_LONGLONG:
1497 config_set_longlong_param (&global_config, k->section, k->name,
1498 k->value);
1499 break;
1500 case PARAM_CHARP:
1501 config_set_string_param (&global_config, k->section, k->name,
1502 k->value);
1503 break;
1504 case PARAM_CHARPP:
1505 config_set_list_param (&global_config, k->section, k->name, k->value);
1506 break;
1507 default:
1508 break;
1511 xfree (k->section);
1512 xfree (k->name);
1513 xfree (k->value);
1514 xfree (k);
1517 slist_free (keep);