Update doc/yat2m.c.
[pwmd.git] / src / rcfile.c
blob3851a106a0bbd38d5b0e9190c4c7fa3d6b4014c9
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <ctype.h>
31 #include <pwd.h>
32 #include <grp.h>
34 #include "pwmd-error.h"
35 #include <gcrypt.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_PINENTRY_TIMEOUT "30"
45 #define DEFAULT_CACHE_TIMEOUT "600"
46 #define DEFAULT_KEEPALIVE_INTERVAL "60"
47 #define DEFAULT_LOCK_TIMEOUT "50" // MUTEX_TRYLOCK in tenths of a second
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_ULONGLONG, 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", PARAM_CHARP, NULL},
70 { "passphrase_file", PARAM_CHARP, NULL},
71 { "gpg_agent_socket", PARAM_CHARP, NULL},
72 { "log_path", PARAM_CHARP, "~/.pwmd/log"},
73 { "enable_logging", PARAM_BOOL, "0"},
74 { "log_keepopen", PARAM_BOOL, "true"},
75 { "log_level", PARAM_INT, "0"},
76 { "disable_mlockall", PARAM_BOOL, "true"},
77 { "cache_timeout", PARAM_INT, DEFAULT_CACHE_TIMEOUT},
78 { "cache_push", PARAM_CHARPP, NULL},
79 { "disable_list_and_dump", PARAM_BOOL, "false"},
80 { "recursion_depth", PARAM_INT, "100"},
81 { "syslog", PARAM_BOOL, "false"},
82 { "xfer_progress", PARAM_INT, "8196"},
83 { "allowed", PARAM_CHARPP, NULL},
84 { "allowed_file", PARAM_CHARP, NULL},
85 { "keyparam", PARAM_CHARP, "(genkey (rsa (nbits 4:2048)))"},
86 { "cipher", PARAM_CHARP, "aes256"},
87 { "kill_scd", PARAM_BOOL, "false"},
88 { "cipher_iterations", PARAM_ULONGLONG, "0"},
89 { "cipher_progress", PARAM_LONG, DEFAULT_ITERATION_PROGRESS},
90 { "s2k_count", PARAM_ULONGLONG, "0"},
91 { "priority", PARAM_INT, INVALID_PRIORITY},
92 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
93 { "tcp_port", PARAM_INT, "6466"},
94 { "enable_tcp", PARAM_BOOL, "false"},
95 { "tcp_require_key", PARAM_BOOL, "false"},
96 { "tcp_wait", PARAM_INT, "0"},
97 { "tcp_bind", PARAM_CHARP, "any"},
98 { "tcp_interface", PARAM_CHARP, NULL},
99 { "tls_timeout", PARAM_INT, "300"},
100 { "tls_cipher_suite", PARAM_CHARP, "SECURE256:SECURE192:SECURE128:-VERS-SSL3.0:-VERS-TLS1.0"},
101 { "tls_dh_level", PARAM_CHARP, "medium"},
102 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
103 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
104 { "use_agent", PARAM_BOOL, "false"},
105 { "require_save_key", PARAM_BOOL, "true"},
106 { "invoking_user", PARAM_CHARPP, NULL},
107 { "invoking_file", PARAM_CHARP, NULL},
108 { "strict_kill", PARAM_BOOL, "false"},
109 { "lock_timeout", PARAM_INT, DEFAULT_LOCK_TIMEOUT},
110 { "send_state", PARAM_INT, "2"},
111 { NULL, PARAM_INVALID, NULL},
114 struct config_param_s
116 char *name;
117 int type;
118 union
120 int itype;
121 char *cptype;
122 char **cpptype;
123 long ltype;
124 long long lltype;
125 unsigned long ultype;
126 unsigned long long ulltype;
127 } value;
130 struct config_keep_s
132 char *section;
133 char *name;
134 char *value;
137 static struct config_section_s *config_find_section (struct slist_s *config,
138 const char *name);
139 static int new_param (struct config_section_s *section, const char *filename,
140 int lineno, const char *name, const char *value,
141 int type);
142 static void free_section (struct config_section_s *s);
143 static int set_defaults (struct slist_s **config, int reload);
145 static void
146 section_remove_param (struct config_section_s *section, const char *name)
148 unsigned i, t = slist_length (section->params);
150 for (i = 0; i < t; i++)
152 struct config_param_s *p = slist_nth_data (section->params, i);
154 if (!p)
155 continue;
157 if (!strcmp (p->name, name))
159 switch (p->type)
161 case PARAM_CHARP:
162 xfree (p->value.cptype);
163 break;
164 case PARAM_CHARPP:
165 strv_free (p->value.cpptype);
166 break;
169 section->params = slist_remove (section->params, p);
170 xfree (p->name);
171 xfree (p);
172 break;
177 void
178 config_clear_keys ()
180 MUTEX_LOCK (&rcfile_mutex);
181 unsigned i, t = slist_length (global_config);
183 for (i = 0; i < t; i++)
185 struct config_section_s *s = slist_nth_data (global_config, i);
186 if (!s)
187 continue;
189 section_remove_param (s, "passphrase");
192 MUTEX_UNLOCK (&rcfile_mutex);
195 static struct config_param_s *
196 config_has_param (struct config_section_s *s, const char *what)
198 unsigned i, t = slist_length (s->params);
200 for (i = 0; i < t; i++)
202 struct config_param_s *p = slist_nth_data (s->params, i);
203 if (!p)
204 break;
206 if (!strcmp (p->name, what))
207 return p;
210 return NULL;
213 static struct config_param_s *
214 config_get_param (struct slist_s *config,
215 const char *section, const char *what, int *exists)
217 unsigned i, t = slist_length (config);
219 *exists = 0;
221 for (i = 0; i < t; i++)
223 struct config_param_s *p;
224 struct config_section_s *s = slist_nth_data (config, i);
226 if (!s)
227 break;
229 if (strcmp (s->name, section))
230 continue;
232 p = config_has_param (s, what);
233 if (!p)
234 return NULL;
236 *exists = 1;
237 return p;
240 return NULL;
243 static struct config_section_s *
244 new_section (struct slist_s **config, const char *name)
246 struct slist_s *tmp;
247 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
249 if (!s)
250 return NULL;
252 s->name = str_dup (name);
253 if (!s->name)
255 log_write ("%s", pwmd_strerror (ENOMEM));
256 xfree (s);
257 return NULL;
260 tmp = slist_append (*config, s);
261 if (!tmp)
263 log_write ("%s", pwmd_strerror (ENOMEM));
264 xfree (s->name);
265 xfree (s);
266 return NULL;
269 *config = tmp;
270 return s;
274 config_set_string_param (struct slist_s **config, const char *section,
275 const char *name, const char *value)
277 struct config_section_s *s = config_find_section (*config, section);
279 if (!s)
281 s = new_section (config, section);
282 if (!s)
283 return 1;
286 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
289 char *
290 config_get_string_param (struct slist_s *config, const char *section,
291 const char *what, int *exists)
293 struct config_param_s *p = config_get_param (config, section, what, exists);
294 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
298 config_set_int_param (struct slist_s **config, const char *section,
299 const char *name, const char *value)
301 struct config_section_s *s = config_find_section (*config, section);
303 if (!s)
305 s = new_section (config, section);
306 if (!s)
307 return 1;
310 return new_param (s, NULL, 0, name, value, PARAM_INT);
314 config_get_int_param (struct slist_s *config, const char *section,
315 const char *what, int *exists)
317 struct config_param_s *p = config_get_param (config, section, what, exists);
318 return *exists ? p->value.itype : -1;
322 config_set_bool_param (struct slist_s **config, const char *section,
323 const char *name, const char *value)
325 struct config_section_s *s = config_find_section (*config, section);
327 if (!s)
329 s = new_section (config, section);
330 if (!s)
331 return 1;
334 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
338 config_get_bool_param (struct slist_s *config, const char *section,
339 const char *what, int *exists)
341 return config_get_int_param (config, section, what, exists);
345 config_set_long_param (struct slist_s **config, const char *section,
346 const char *name, const char *value)
348 struct config_section_s *s = config_find_section (*config, section);
350 if (!s)
352 s = new_section (config, section);
353 if (!s)
354 return 1;
357 return new_param (s, NULL, 0, name, value, PARAM_LONG);
360 long
361 config_get_long_param (struct slist_s *config, const char *section,
362 const char *what, int *exists)
364 struct config_param_s *p = config_get_param (config, section, what, exists);
365 return *exists ? p->value.ltype : -1;
369 config_set_ulonglong_param (struct slist_s **config, const char *section,
370 const char *name, const char *value)
372 struct config_section_s *s = config_find_section (*config, section);
374 if (!s)
376 s = new_section (config, section);
377 if (!s)
378 return 1;
381 return new_param (s, NULL, 0, name, value, PARAM_ULONGLONG);
384 unsigned long long
385 config_get_ulonglong_param (struct slist_s *config,
386 const char *section, const char *what, int *exists)
388 struct config_param_s *p = config_get_param (config, section, what, exists);
389 return *exists ? p->value.ulltype : -1;
393 config_set_list_param (struct slist_s **config, const char *section,
394 const char *name, const char *value)
396 struct config_section_s *s = config_find_section (*config, section);
398 if (!s)
400 s = new_section (config, section);
401 if (!s)
402 return 1;
405 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
408 char **
409 config_get_list_param (struct slist_s *config, const char *section,
410 const char *what, int *exists)
412 struct config_param_s *p = config_get_param (config, section, what, exists);
413 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
416 char *
417 config_get_string (const char *section, const char *what)
419 char *val = NULL;
420 const char *where = section ? section : "global";
421 int exists = 0;
423 MUTEX_LOCK (&rcfile_mutex);
424 val = config_get_string_param (global_config, where, what, &exists);
425 if (!exists && strcmp (section ? section : "", "global"))
426 val = config_get_string_param (global_config, "global", what, &exists);
428 MUTEX_UNLOCK (&rcfile_mutex);
429 return val;
432 char **
433 config_get_list (const char *section, const char *what)
435 char **val = NULL;
436 const char *where = section ? section : "global";
437 int exists = 0;
439 MUTEX_LOCK (&rcfile_mutex);
440 val = config_get_list_param (global_config, where, what, &exists);
441 if (!exists && strcmp (section ? section : "", "global"))
442 val = config_get_list_param (global_config, "global", what, &exists);
444 MUTEX_UNLOCK (&rcfile_mutex);
445 return val;
449 config_get_integer (const char *section, const char *what)
451 int val = 0;
452 const char *where = section ? section : "global";
453 int exists = 0;
455 MUTEX_LOCK (&rcfile_mutex);
456 val = config_get_int_param (global_config, where, what, &exists);
457 if (!exists && strcmp (section ? section : "", "global"))
458 val = config_get_int_param (global_config, "global", what, &exists);
460 MUTEX_UNLOCK (&rcfile_mutex);
461 return val;
464 unsigned long long
465 config_get_ulonglong (const char *section, const char *what)
467 unsigned long long val = 0;
468 const char *where = section ? section : "global";
469 int exists = 0;
471 MUTEX_LOCK (&rcfile_mutex);
472 val = config_get_ulonglong_param (global_config, where, what, &exists);
473 if (!exists && strcmp (section ? section : "", "global"))
474 val = config_get_ulonglong_param (global_config, "global", what, &exists);
476 MUTEX_UNLOCK (&rcfile_mutex);
477 return val;
480 long
481 config_get_long (const char *section, const char *what)
483 long val = 0;
484 const char *where = section ? section : "global";
485 int exists = 0;
487 MUTEX_LOCK (&rcfile_mutex);
488 val = config_get_long_param (global_config, where, what, &exists);
489 if (!exists && strcmp (section ? section : "", "global"))
490 val = config_get_long_param (global_config, "global", what, &exists);
492 MUTEX_UNLOCK (&rcfile_mutex);
493 return val;
497 config_get_boolean (const char *section, const char *what)
499 return config_get_integer (section, what);
502 char *
503 config_get_value (const char *section, const char *what)
505 const char *where = section ? section : "global";
506 int exists = 0;
507 int i;
508 int ival;
509 long lval;
510 unsigned long long ullval;
511 char *cpval;
512 char **cppval;
513 char *result = NULL;
515 MUTEX_LOCK (&rcfile_mutex);
517 for (i = 0; config_params[i].name; i++)
519 if (!strcmp (config_params[i].name, what))
521 switch (config_params[i].type)
523 case PARAM_BOOL:
524 case PARAM_INT:
525 ival = config_get_int_param (global_config, where, what,
526 &exists);
527 if (!exists && strcmp (section ? section : "", "global"))
528 ival = config_get_int_param (global_config, "global", what,
529 &exists);
530 result = str_asprintf ("%i", ival);
531 break;
532 case PARAM_CHARP:
533 cpval = config_get_string_param (global_config, where, what,
534 &exists);
535 if (!exists && strcmp (section ? section : "", "global"))
536 cpval =
537 config_get_string_param (global_config, "global", what,
538 &exists);
539 result = cpval;
540 break;
541 case PARAM_LONG:
542 lval = config_get_long_param (global_config, where, what,
543 &exists);
544 if (!exists && strcmp (section ? section : "", "global"))
545 lval = config_get_long_param (global_config, "global", what,
546 &exists);
547 result = str_asprintf ("%li", lval);
548 break;
549 case PARAM_ULONGLONG:
550 ullval = config_get_ulonglong_param (global_config, where, what,
551 &exists);
552 if (!exists && strcmp (section ? section : "", "global"))
553 ullval = config_get_ulonglong_param (global_config, "global",
554 what, &exists);
555 result = str_asprintf ("%llu", ullval);
556 break;
557 case PARAM_CHARPP:
558 cppval = config_get_list_param (global_config, where, what,
559 &exists);
560 if (!exists && strcmp (section ? section : "", "global"))
561 cppval = config_get_list_param (global_config, "global", what,
562 &exists);
564 if (cppval)
565 result = strv_join (",", cppval);
567 strv_free (cppval);
568 break;
573 MUTEX_UNLOCK (&rcfile_mutex);
574 return result;
577 /* 'file' is the list parameter file to load into the list parameter 'what'.
578 * The parsing of the parameter is not done here. */
579 static gpg_error_t
580 parse_list_file (struct slist_s *config, const char *section,
581 const char *file, const char *what)
583 FILE *fp;
584 char buf[LINE_MAX];
585 int exists;
586 char **list = NULL;
587 char *tmp;
588 char *p = config_get_string_param (config, section, file, &exists);
589 gpg_error_t rc;
591 if (!p || !*p)
593 xfree (p);
594 return 0;
597 tmp = expand_homedir (p);
598 xfree (p);
599 p = tmp;
600 fp = fopen (p, "r");
601 if (!fp)
603 rc = gpg_error_from_errno (errno);
604 log_write ("%s: %s", p, pwmd_strerror (rc));
605 xfree (p);
606 return rc;
609 xfree (p);
610 list = config_get_list_param (config, section, what, &exists);
611 if (!list && exists)
613 fclose (fp);
614 log_write ("%s", pwmd_strerror (ENOMEM));
615 return gpg_error (ENOMEM);
618 while ((p = fgets (buf, sizeof (buf), fp)))
620 char **pp = NULL;
622 if (!*p || *p == ';')
623 continue;
625 if (p[strlen(p)-1] == '\n')
626 p[strlen(p)-1] = 0;
628 while (*p && isspace (*p))
629 p++;
631 if (!*p)
632 continue;
634 tmp = str_dup (p);
635 if (tmp)
636 pp = strv_cat (list, str_dup (p));
638 if (!pp || !tmp)
640 xfree (tmp);
641 strv_free (list);
642 fclose (fp);
643 log_write ("%s", strerror (ENOMEM));
644 return gpg_error (ENOMEM);
647 xfree (tmp);
648 list = pp;
651 fclose(fp);
652 if (!list)
653 return 0;
655 p = strv_join (",", list);
656 strv_free (list);
658 if (!p)
660 log_write ("%s", pwmd_strerror (ENOMEM));
661 return gpg_error (ENOMEM);
664 config_set_list_param (&config, section, what, p);
665 xfree (p);
666 return 0;
669 static int
670 fixup_allowed_once (struct slist_s **config, const char *section)
672 char **list, **pp, *p;
673 int exists;
674 gpg_error_t rc;
676 rc = parse_list_file (*config, section, "allowed_file", "allowed");
677 if (rc)
678 return 1;
680 list = config_get_list_param (*config, section, "allowed", &exists);
681 for (pp = list; pp && *pp; pp++)
683 if (*(*pp) == '#')
685 for (p = *pp; p && *p; p++)
686 *p = toupper(*p);
690 strv_free (list);
691 if (!exists)
693 if (!strcmp (section, "global"))
695 p = get_username (getuid());
697 if (config_set_list_param (config, section, "allowed", p))
699 xfree (p);
700 return 1;
703 xfree (p);
705 else
707 list = config_get_list_param (*config, "global", "allowed", &exists);
708 if (list)
710 p = strv_join (",", list);
711 strv_free (list);
712 if (config_set_list_param (config, section, "allowed", p))
714 xfree (p);
715 return 1;
718 xfree (p);
723 return 0;
726 static int
727 fixup_allowed (struct slist_s **config)
729 int n, t = slist_length (*config);
731 for (n = 0; n < t; n++)
733 struct config_section_s *section;
735 section = slist_nth_data (*config, n);
736 if (fixup_allowed_once (config, section->name))
737 return 1;
740 return 0;
743 static int
744 add_invoking_user (struct invoking_user_s **users, char *id,
745 struct slist_s **config)
747 struct passwd *pwd = NULL;
748 struct group *grp = NULL;
749 struct invoking_user_s *user, *p;
750 int not = 0;
752 if (id && (*id == '!' || *id == '-'))
754 not = 1;
755 id++;
758 errno = 0;
759 if (!id || !*id)
761 pwd = getpwuid (getuid ());
762 if (!pwd)
764 log_write (_("could not set any invoking user: %s"),
765 pwmd_strerror (errno));
766 return 1;
769 else if (*id == '@')
771 grp = getgrnam (id+1);
772 if (!grp)
774 log_write (_("could not parse group '%s': %s"), id+1,
775 pwmd_strerror (errno));
776 return 1;
779 else if (*id != '#')
780 pwd = getpwnam (id);
782 if (!grp && !pwd && id && *id != '#')
784 if (id && *id)
785 log_write (_("could not set invoking user '%s': %s"), id,
786 pwmd_strerror (errno));
787 else
788 log_write (_("could not set any invoking user!"));
790 return 1;
793 user = xcalloc (1, sizeof (struct invoking_user_s));
794 if (!user)
796 log_write ("%s", pwmd_strerror (ENOMEM));
797 return 1;
800 user->not = not;
801 user->type = pwd ? INVOKING_UID : grp ? INVOKING_GID : INVOKING_TLS;
802 if (pwd)
803 user->uid = pwd->pw_uid;
804 else if (grp)
805 user->id = str_dup (id+1);
806 else
808 char *s;
810 for (s = id; s && *s; s++)
811 *s = toupper(*s);
813 user->id = str_dup (id+1);
816 /* Set the default invoking_user since it doesn't exist. */
817 if (!id || !*id)
818 config_set_list_param (config, "global", "invoking_user", pwd->pw_name);
820 if (!*users)
822 *users = user;
823 return 0;
826 for (p = *users; p; p = p->next)
828 if (!p->next)
830 p->next = user;
831 break;
835 return 0;
838 static int
839 parse_invoking_users (struct slist_s **config)
841 struct invoking_user_s *users = NULL;
842 int exists;
843 char **list, **l;
845 if (parse_list_file (*config, "global", "invoking_file", "invoking_user"))
846 return 1;
848 list = config_get_list_param(*config, "global", "invoking_user", &exists);
849 for (l = list; l && *l; l++)
851 if (add_invoking_user (&users, *l, config))
853 strv_free (list);
854 free_invoking_users (users);
855 return 1;
859 if (!list || !*list)
861 if (add_invoking_user (&users, NULL, config))
863 strv_free (list);
864 return 1;
867 strv_free (list);
870 free_invoking_users (invoking_users);
871 invoking_users = users;
872 return 0;
875 static int
876 set_defaults (struct slist_s **config, int reload)
878 char *s = NULL, *tmp;
879 char **list;
880 int exists;
881 int i;
883 for (i = 0; config_params[i].name; i++)
885 switch (config_params[i].type)
887 case PARAM_BOOL:
888 config_get_bool_param (*config, "global", config_params[i].name,
889 &exists);
890 if (!exists)
892 if (config_set_bool_param
893 (config, "global", config_params[i].name,
894 config_params[i].value))
895 goto fail;
897 break;
898 case PARAM_INT:
899 config_get_int_param (*config, "global", config_params[i].name,
900 &exists);
901 if (!exists)
903 if (config_set_int_param
904 (config, "global", config_params[i].name,
905 config_params[i].value))
906 goto fail;
908 break;
909 case PARAM_CHARP:
910 s = config_get_string_param (*config, "global",
911 config_params[i].name, &exists);
912 xfree (s);
913 if (!exists && config_params[i].value)
915 if (config_set_string_param (config, "global",
916 config_params[i].name,
917 config_params[i].value))
918 goto fail;
920 break;
921 case PARAM_CHARPP:
922 list = config_get_list_param (*config, "global",
923 config_params[i].name, &exists);
924 strv_free (list);
925 if (!exists && config_params[i].value)
927 if (config_set_list_param (config, "global",
928 config_params[i].name,
929 config_params[i].value))
930 goto fail;
932 break;
933 case PARAM_LONG:
934 config_get_long_param (*config, "global", config_params[i].name,
935 &exists);
936 if (!exists)
938 if (config_set_long_param
939 (config, "global", config_params[i].name,
940 config_params[i].value))
941 goto fail;
943 break;
944 case PARAM_ULONGLONG:
945 config_get_ulonglong_param (*config, "global", config_params[i].name,
946 &exists);
947 if (!exists)
949 if (config_set_ulonglong_param (config, "global",
950 config_params[i].name,
951 config_params[i].value))
952 goto fail;
954 break;
958 s = NULL;
959 if (!reload && fixup_allowed (config))
960 goto fail;
962 if (!reload && parse_invoking_users (config))
963 goto fail;
965 s = config_get_string_param(*config, "global", "gpg_agent_socket", &exists);
966 if (!s || !*s)
968 xfree (s);
969 s = str_asprintf ("%s/.gnupg/S.gpg-agent", get_home_dir());
970 config_set_string_param(config, "global", "gpg_agent_socket", s);
972 else
974 tmp = expand_homedir (s);
975 config_set_string_param(config, "global", "gpg_agent_socket", tmp);
976 xfree (tmp);
979 log_level = config_get_int_param (*config, "global",
980 "log_level", &exists);
981 log_keepopen = config_get_int_param (*config, "global",
982 "log_keepopen", &exists);
983 max_recursion_depth = config_get_int_param (*config, "global",
984 "recursion_depth", &exists);
985 disable_list_and_dump = config_get_bool_param (*config, "global",
986 "disable_list_and_dump",
987 &exists);
988 #ifdef HAVE_MLOCKALL
989 disable_mlock =
990 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
991 #endif
993 xfree (s);
994 return 0;
996 fail:
997 xfree (s);
998 return 1;
1001 static struct config_section_s *
1002 config_find_section (struct slist_s *config, const char *name)
1004 unsigned i, t = slist_length (config);
1006 for (i = 0; i < t; i++)
1008 struct config_section_s *s = slist_nth_data (config, i);
1010 if (!strcmp (s->name, name))
1011 return s;
1014 return NULL;
1017 /* Append a new parameter to the list of parameters for a file
1018 * section. When an existing parameter of the same name exists, its
1019 * value is updated.
1021 static int
1022 new_param (struct config_section_s *section, const char *filename, int lineno,
1023 const char *name, const char *value, int type)
1025 struct config_param_s *param = NULL;
1026 struct slist_s *tmp;
1027 char *e;
1028 unsigned i, t = slist_length (section->params);
1029 int dup = 0;
1031 for (i = 0; i < t; i++)
1033 struct config_param_s *p = slist_nth_data (section->params, i);
1034 if (!p)
1035 break;
1037 if (!strcmp (name, p->name))
1039 param = p;
1040 dup = 1;
1041 break;
1045 if (!param)
1047 param = xcalloc (1, sizeof (struct config_param_s));
1048 if (!param)
1050 log_write ("%s", pwmd_strerror (ENOMEM));
1051 return 1;
1054 param->name = str_dup (name);
1055 if (!param->name)
1057 xfree (param);
1058 log_write ("%s", pwmd_strerror (ENOMEM));
1059 return 1;
1063 param->type = type;
1065 switch (type)
1067 case PARAM_BOOL:
1068 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1069 || !strcasecmp (value, "false"))
1070 param->value.itype = 0;
1071 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1072 || !strcasecmp (value, "true"))
1073 param->value.itype = 1;
1074 else
1076 INVALID_VALUE (filename, lineno);
1077 goto fail;
1079 param->type = PARAM_INT;
1080 break;
1081 case PARAM_CHARP:
1082 xfree (param->value.cptype);
1083 param->value.cptype = NULL;
1084 param->value.cptype = value && *value ? str_dup (value) : NULL;
1085 if (value && *value && !param->value.cptype)
1087 log_write ("%s", pwmd_strerror (ENOMEM));
1088 goto fail;
1090 break;
1091 case PARAM_CHARPP:
1092 strv_free (param->value.cpptype);
1093 param->value.cpptype = NULL;
1094 param->value.cpptype = value && *value ?
1095 str_split_ws (value, ",", 0) : NULL;
1096 if (value && *value && !param->value.cpptype)
1098 log_write ("%s", pwmd_strerror (ENOMEM));
1099 goto fail;
1101 break;
1102 case PARAM_INT:
1103 param->value.itype = strtol (value, &e, 10);
1104 if (e && *e)
1106 INVALID_VALUE (filename, lineno);
1107 goto fail;
1109 break;
1110 case PARAM_LONG:
1111 param->value.ltype = strtol (value, &e, 10);
1112 if (e && *e)
1114 INVALID_VALUE (filename, lineno);
1115 goto fail;
1117 break;
1118 case PARAM_ULONGLONG:
1119 param->value.ulltype = strtoll (value, &e, 10);
1120 if (e && *e)
1122 INVALID_VALUE (filename, lineno);
1123 goto fail;
1125 break;
1128 if (dup)
1129 return 0;
1131 tmp = slist_append (section->params, param);
1132 if (!tmp)
1134 log_write ("%s", pwmd_strerror (ENOMEM));
1135 goto fail;
1138 section->params = tmp;
1139 return 0;
1141 fail:
1142 xfree (param->name);
1143 xfree (param);
1144 return 1;
1147 struct slist_s *
1148 config_parse (const char *filename, int reload)
1150 struct slist_s *tmpconfig = NULL, *tmp;
1151 struct config_section_s *cur_section = NULL;
1152 char buf[LINE_MAX];
1153 char *s;
1154 int lineno = 1;
1155 int have_global = 0;
1156 FILE *fp = fopen (filename, "r");
1158 if (!fp)
1160 log_write ("%s: %s", filename,
1161 pwmd_strerror (gpg_error_from_errno (errno)));
1163 if (errno != ENOENT)
1164 return NULL;
1166 log_write (_("Using defaults!"));
1167 goto defaults;
1170 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
1172 char line[LINE_MAX] = { 0 };
1173 size_t len = 0;
1175 if (*s == '#')
1176 continue;
1178 s = str_chomp (s);
1179 for (; s && *s; s++)
1181 int match = 0;
1183 /* New file section. */
1184 if (*s == '[')
1186 struct config_section_s *section;
1187 char *p = strchr (++s, ']');
1189 if (!p)
1191 log_write (_("%s(%i): unbalanced braces"), filename,
1192 lineno);
1193 goto fail;
1196 len = strlen (s) - strlen (p);
1197 memcpy (line, s, len);
1198 line[len] = 0;
1200 section = config_find_section (tmpconfig, line);
1201 if (section)
1203 log_write (_("%s(%i): section '%s' already exists!"),
1204 filename, lineno, line);
1205 goto fail;
1208 if (!strcmp (line, "global"))
1209 have_global = 1;
1211 section = xcalloc (1, sizeof (struct config_section_s));
1212 section->name = str_dup (line);
1214 if (cur_section)
1216 tmp = slist_append (tmpconfig, cur_section);
1217 if (!tmp)
1219 log_write ("%s", pwmd_strerror (ENOMEM));
1220 goto fail;
1223 tmpconfig = tmp;
1226 cur_section = section;
1227 break;
1230 if (!cur_section)
1232 log_write (_("%s(%i): parameter outside of section!"), filename,
1233 lineno);
1234 goto fail;
1237 /* Parameters for each section. */
1238 for (int m = 0; config_params[m].name; m++)
1240 size_t len = strlen (config_params[m].name);
1242 if (!strncmp (s, config_params[m].name, len))
1244 char *p = s + len;
1246 while (*p && *p == ' ')
1247 p++;
1249 if (!*p || *p != '=')
1250 continue;
1252 p++;
1253 while (*p && isspace (*p))
1254 p++;
1256 s[len] = 0;
1257 if (new_param (cur_section, filename, lineno, s, p,
1258 config_params[m].type))
1259 goto fail;
1261 match = 1;
1262 break;
1266 if (!match)
1268 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1269 goto fail;
1272 break;
1276 if (cur_section)
1278 tmp = slist_append (tmpconfig, cur_section);
1279 if (!tmp)
1281 log_write ("%s", pwmd_strerror (ENOMEM));
1282 goto fail;
1285 cur_section = NULL;
1286 tmpconfig = tmp;
1289 if (!have_global)
1290 log_write (_
1291 ("WARNING: %s: could not find a [global] configuration section!"),
1292 filename);
1293 else
1295 int exists;
1296 char *tmp = config_get_string_param (tmpconfig, "global", "tls_dh_level",
1297 &exists);
1298 if (tmp)
1300 if (strcasecmp (tmp, "low") && strcasecmp (tmp, "medium")
1301 && strcasecmp (tmp, "high"))
1303 xfree (tmp);
1304 log_write (_("invalid tls_dh_level value"));
1305 goto fail;
1308 xfree (tmp);
1312 defaults:
1313 if (set_defaults (&tmpconfig, reload))
1314 goto fail;
1316 if (fp)
1317 fclose(fp);
1319 return tmpconfig;
1321 fail:
1322 if (fp)
1323 fclose (fp);
1325 config_free (tmpconfig);
1326 free_section (cur_section);
1327 return NULL;
1330 static void
1331 free_section (struct config_section_s *s)
1333 if (!s)
1334 return;
1336 for (;;)
1338 struct config_param_s *p = slist_nth_data (s->params, 0);
1340 if (!p)
1341 break;
1343 section_remove_param (s, p->name);
1346 s->params = NULL;
1347 xfree (s->name);
1348 s->name = NULL;
1351 void
1352 config_free (struct slist_s *config)
1354 for (;;)
1356 struct config_section_s *s = slist_nth_data (config, 0);
1357 if (!s)
1358 break;
1360 free_section (s);
1361 config = slist_remove (config, s);
1362 xfree (s);
1366 void
1367 free_invoking_users (struct invoking_user_s *users)
1369 struct invoking_user_s *p;
1371 for (p = users; p;)
1373 struct invoking_user_s *next = p->next;
1375 if (p->type == INVOKING_TLS || p->type == INVOKING_GID)
1376 xfree (p->id);
1378 xfree (p);
1379 p = next;
1383 static int
1384 param_type (const char *name)
1386 int i;
1388 for (i = 0; config_params[i].name; i++)
1390 if (!strcmp (config_params[i].name, name))
1391 return config_params[i].type;
1394 return PARAM_INVALID;
1397 static int
1398 keep_parse (struct config_keep_s *k, const char *section, const char *key)
1400 int exists;
1401 int ival;
1402 long lval;
1403 unsigned long long ullval;
1404 char *cpval;
1405 char **cppval;
1406 int type = param_type (key);
1407 void *value = NULL;
1409 switch (type)
1411 case PARAM_BOOL:
1412 case PARAM_INT:
1413 ival = config_get_int_param (global_config, section, key, &exists);
1414 if (exists)
1415 value = str_asprintf ("%i", ival);
1416 break;
1417 case PARAM_LONG:
1418 lval = config_get_long_param (global_config, section, key, &exists);
1419 if (exists)
1420 value = str_asprintf ("%li", lval);
1421 break;
1422 case PARAM_ULONGLONG:
1423 ullval = config_get_ulonglong_param (global_config, section, key,
1424 &exists);
1425 if (exists)
1426 value = str_asprintf ("%llu", ullval);
1427 break;
1428 case PARAM_CHARP:
1429 cpval = config_get_string_param (global_config, section, key, &exists);
1430 if (exists)
1431 value = cpval;
1432 break;
1433 case PARAM_CHARPP:
1434 cppval = config_get_list_param (global_config, section, key, &exists);
1435 if (exists)
1437 char *s = strv_join (",", cppval);
1439 strv_free (cppval);
1440 value = s;
1442 break;
1443 default:
1444 return 1;
1447 if (!value)
1448 return 1;
1450 k->section = str_dup(section);
1451 k->name = str_dup(key);
1452 k->value = value;
1453 return 0;
1456 static struct slist_s *
1457 keep_add (struct slist_s *k, const char *s, const char *key)
1459 int n, t = slist_length (global_config);
1461 for (n = 0; n < t; n++)
1463 struct config_section_s *section;
1464 struct config_keep_s *tmp;
1465 int ret;
1467 section = slist_nth_data (global_config, n);
1468 tmp = xcalloc (1, sizeof(struct config_keep_s));
1470 // Process all sections.
1471 if (!s)
1472 ret = keep_parse (tmp, section->name, key);
1473 else
1474 ret = keep_parse (tmp, s, key);
1476 if (!ret)
1477 k = slist_append (k, tmp);
1478 else
1479 xfree (tmp);
1482 return k;
1485 /* Keep security sensitive settings across SIGHUP. */
1486 struct slist_s *
1487 config_keep_save ()
1489 struct slist_s *keep = NULL;
1491 #ifdef WITH_GNUTLS
1492 keep = keep_add (keep, NULL, "tcp_require_key");
1493 #endif
1494 keep = keep_add (keep, NULL, "require_save_key");
1495 keep = keep_add (keep, NULL, "allowed");
1496 keep = keep_add (keep, "global", "invoking_user");
1497 return keep;
1500 /* Restore parameters previously saved with config_keep_save(). This will also
1501 * free the 'keep'.
1503 void
1504 config_keep_restore (struct slist_s *keep)
1506 int n, t = slist_length (keep);
1508 for (n = 0; n < t; n++)
1510 struct config_keep_s *k = slist_nth_data (keep, n);
1511 int type = param_type (k->name);
1513 switch (type)
1515 case PARAM_BOOL:
1516 config_set_bool_param (&global_config, k->section, k->name, k->value);
1517 break;
1518 case PARAM_INT:
1519 config_set_int_param (&global_config, k->section, k->name, k->value);
1520 break;
1521 case PARAM_LONG:
1522 config_set_long_param (&global_config, k->section, k->name, k->value);
1523 break;
1524 case PARAM_ULONGLONG:
1525 config_set_ulonglong_param (&global_config, k->section, k->name,
1526 k->value);
1527 break;
1528 case PARAM_CHARP:
1529 config_set_string_param (&global_config, k->section, k->name,
1530 k->value);
1531 break;
1532 case PARAM_CHARPP:
1533 config_set_list_param (&global_config, k->section, k->name, k->value);
1534 break;
1535 default:
1536 break;
1539 xfree (k->section);
1540 xfree (k->name);
1541 xfree (k->value);
1544 slist_free (keep);