Fix ACL crash for non-existing user.
[pwmd.git] / src / rcfile.c
blob1e8f7a118c8f734c85dc46f6212b50037b5cbd3a
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_LONGLONG, PARAM_CHARPP,
57 PARAM_BOOL, PARAM_ULONG, PARAM_ULONGLONG
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 { "priority", PARAM_INT, INVALID_PRIORITY},
91 { "keepalive_interval", PARAM_INT, DEFAULT_KEEPALIVE_INTERVAL},
92 { "tcp_port", PARAM_INT, "6466"},
93 { "enable_tcp", PARAM_BOOL, "false"},
94 { "tcp_require_key", PARAM_BOOL, "false"},
95 { "tcp_wait", PARAM_INT, "0"},
96 { "tcp_bind", PARAM_CHARP, "any"},
97 { "tcp_interface", PARAM_CHARP, NULL},
98 { "tls_timeout", PARAM_INT, "300"},
99 { "tls_cipher_suite", PARAM_CHARP, "SECURE256:SECURE192:SECURE128:-VERS-SSL3.0"},
100 { "tls_dh_level", PARAM_CHARP, "medium"},
101 { "pinentry_path", PARAM_CHARP, PINENTRY_PATH},
102 { "pinentry_timeout", PARAM_INT, DEFAULT_PINENTRY_TIMEOUT},
103 { "use_agent", PARAM_BOOL, "false"},
104 { "require_save_key", PARAM_BOOL, "true"},
105 { "invoking_user", PARAM_CHARPP, NULL},
106 { "invoking_file", PARAM_CHARP, NULL},
107 { "invoking_tls", PARAM_CHARP, NULL},
108 { "lock_timeout", PARAM_INT, DEFAULT_LOCK_TIMEOUT},
109 { "send_state", PARAM_INT, "2"},
110 { NULL, 0, NULL},
113 struct config_param_s
115 char *name;
116 int type;
117 union
119 int itype;
120 char *cptype;
121 char **cpptype;
122 long ltype;
123 long long lltype;
124 unsigned long ultype;
125 unsigned long long ulltype;
126 } 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 void
170 config_clear_keys ()
172 MUTEX_LOCK (&rcfile_mutex);
173 unsigned i, t = slist_length (global_config);
175 for (i = 0; i < t; i++)
177 struct config_section_s *s = slist_nth_data (global_config, i);
178 if (!s)
179 continue;
181 section_remove_param (s, "passphrase");
184 MUTEX_UNLOCK (&rcfile_mutex);
187 static struct config_param_s *
188 config_has_param (struct config_section_s *s, const char *what)
190 unsigned i, t = slist_length (s->params);
192 for (i = 0; i < t; i++)
194 struct config_param_s *p = slist_nth_data (s->params, i);
195 if (!p)
196 break;
198 if (!strcmp (p->name, what))
199 return p;
202 return NULL;
205 static struct config_param_s *
206 config_get_param (struct slist_s *config,
207 const char *section, const char *what, int *exists)
209 unsigned i, t = slist_length (config);
211 *exists = 0;
213 for (i = 0; i < t; i++)
215 struct config_param_s *p;
216 struct config_section_s *s = slist_nth_data (config, i);
218 if (!s)
219 break;
221 if (strcmp (s->name, section))
222 continue;
224 p = config_has_param (s, what);
225 if (!p)
226 return NULL;
228 *exists = 1;
229 return p;
232 return NULL;
235 static struct config_section_s *
236 new_section (struct slist_s **config, const char *name)
238 struct slist_s *tmp;
239 struct config_section_s *s = xcalloc (1, sizeof (struct config_section_s));
241 if (!s)
242 return NULL;
244 s->name = str_dup (name);
245 if (!s->name)
247 log_write ("%s", pwmd_strerror (ENOMEM));
248 xfree (s);
249 return NULL;
252 tmp = slist_append (*config, s);
253 if (!tmp)
255 log_write ("%s", pwmd_strerror (ENOMEM));
256 xfree (s->name);
257 xfree (s);
258 return NULL;
261 *config = tmp;
262 return s;
266 config_set_string_param (struct slist_s **config, const char *section,
267 const char *name, const char *value)
269 struct config_section_s *s = config_find_section (*config, section);
271 if (!s)
273 s = new_section (config, section);
274 if (!s)
275 return 1;
278 return new_param (s, NULL, 0, name, value, PARAM_CHARP);
281 char *
282 config_get_string_param (struct slist_s *config, const char *section,
283 const char *what, int *exists)
285 struct config_param_s *p = config_get_param (config, section, what, exists);
286 return *exists && p->value.cptype ? str_dup (p->value.cptype) : NULL;
290 config_set_int_param (struct slist_s **config, const char *section,
291 const char *name, const char *value)
293 struct config_section_s *s = config_find_section (*config, section);
295 if (!s)
297 s = new_section (config, section);
298 if (!s)
299 return 1;
302 return new_param (s, NULL, 0, name, value, PARAM_INT);
306 config_get_int_param (struct slist_s *config, const char *section,
307 const char *what, int *exists)
309 struct config_param_s *p = config_get_param (config, section, what, exists);
310 return *exists ? p->value.itype : -1;
314 config_set_bool_param (struct slist_s **config, const char *section,
315 const char *name, const char *value)
317 struct config_section_s *s = config_find_section (*config, section);
319 if (!s)
321 s = new_section (config, section);
322 if (!s)
323 return 1;
326 return new_param (s, NULL, 0, name, value, PARAM_BOOL);
330 config_get_bool_param (struct slist_s *config, const char *section,
331 const char *what, int *exists)
333 return config_get_int_param (config, section, what, exists);
337 config_set_long_param (struct slist_s **config, const char *section,
338 const char *name, const char *value)
340 struct config_section_s *s = config_find_section (*config, section);
342 if (!s)
344 s = new_section (config, section);
345 if (!s)
346 return 1;
349 return new_param (s, NULL, 0, name, value, PARAM_LONG);
352 unsigned long
353 config_get_ulong_param (struct slist_s *config, const char *section,
354 const char *what, int *exists)
356 struct config_param_s *p = config_get_param (config, section, what, exists);
357 return *exists ? p->value.ultype : 0;
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_longlong_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_LONGLONG);
384 long long
385 config_get_longlong_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.lltype : -1;
392 unsigned long long
393 config_get_ulonglong_param (struct slist_s *config,
394 const char *section,
395 const char *what, int *exists)
397 struct config_param_s *p = config_get_param (config, section, what, exists);
398 return *exists ? p->value.ulltype : 0;
402 config_set_list_param (struct slist_s **config, const char *section,
403 const char *name, const char *value)
405 struct config_section_s *s = config_find_section (*config, section);
407 if (!s)
409 s = new_section (config, section);
410 if (!s)
411 return 1;
414 return new_param (s, NULL, 0, name, value, PARAM_CHARPP);
417 char **
418 config_get_list_param (struct slist_s *config, const char *section,
419 const char *what, int *exists)
421 struct config_param_s *p = config_get_param (config, section, what, exists);
422 return *exists && p->value.cpptype ? strv_dup (p->value.cpptype) : NULL;
425 char *
426 config_get_string (const char *section, const char *what)
428 char *val = NULL;
429 const char *where = section ? section : "global";
430 int exists = 0;
432 MUTEX_LOCK (&rcfile_mutex);
433 val = config_get_string_param (global_config, where, what, &exists);
434 if (!exists && strcmp (section ? section : "", "global"))
435 val = config_get_string_param (global_config, "global", what, &exists);
437 MUTEX_UNLOCK (&rcfile_mutex);
438 return val;
441 char **
442 config_get_list (const char *section, const char *what)
444 char **val = NULL;
445 const char *where = section ? section : "global";
446 int exists = 0;
448 MUTEX_LOCK (&rcfile_mutex);
449 val = config_get_list_param (global_config, where, what, &exists);
450 if (!exists && strcmp (section ? section : "", "global"))
451 val = config_get_list_param (global_config, "global", what, &exists);
453 MUTEX_UNLOCK (&rcfile_mutex);
454 return val;
458 config_get_integer (const char *section, const char *what)
460 int val = 0;
461 const char *where = section ? section : "global";
462 int exists = 0;
464 MUTEX_LOCK (&rcfile_mutex);
465 val = config_get_int_param (global_config, where, what, &exists);
466 if (!exists && strcmp (section ? section : "", "global"))
467 val = config_get_int_param (global_config, "global", what, &exists);
469 MUTEX_UNLOCK (&rcfile_mutex);
470 return val;
473 long long
474 config_get_longlong (const char *section, const char *what)
476 long long val = 0;
477 const char *where = section ? section : "global";
478 int exists = 0;
480 MUTEX_LOCK (&rcfile_mutex);
481 val = config_get_longlong_param (global_config, where, what, &exists);
482 if (!exists && strcmp (section ? section : "", "global"))
483 val = config_get_longlong_param (global_config, "global", what, &exists);
485 MUTEX_UNLOCK (&rcfile_mutex);
486 return val;
489 unsigned long long
490 config_get_ulonglong (const char *section, const char *what)
492 unsigned long long val = 0;
493 const char *where = section ? section : "global";
494 int exists = 0;
496 MUTEX_LOCK (&rcfile_mutex);
497 val = config_get_ulonglong_param (global_config, where, what, &exists);
498 if (!exists && strcmp (section ? section : "", "global"))
499 val = config_get_ulonglong_param (global_config, "global", what, &exists);
501 MUTEX_UNLOCK (&rcfile_mutex);
502 return val;
505 long
506 config_get_long (const char *section, const char *what)
508 long val = 0;
509 const char *where = section ? section : "global";
510 int exists = 0;
512 MUTEX_LOCK (&rcfile_mutex);
513 val = config_get_long_param (global_config, where, what, &exists);
514 if (!exists && strcmp (section ? section : "", "global"))
515 val = config_get_long_param (global_config, "global", what, &exists);
517 MUTEX_UNLOCK (&rcfile_mutex);
518 return val;
521 unsigned long
522 config_get_ulong (const char *section, const char *what)
524 unsigned long val = 0;
525 const char *where = section ? section : "global";
526 int exists = 0;
528 MUTEX_LOCK (&rcfile_mutex);
529 val = config_get_ulong_param (global_config, where, what, &exists);
530 if (!exists && strcmp (section ? section : "", "global"))
531 val = config_get_ulong_param (global_config, "global", what, &exists);
533 MUTEX_UNLOCK (&rcfile_mutex);
534 return val;
538 config_get_boolean (const char *section, const char *what)
540 return config_get_integer (section, what);
543 char *
544 config_get_value (const char *section, const char *what)
546 const char *where = section ? section : "global";
547 int exists = 0;
548 int i;
549 int ival;
550 long lval;
551 long long llval;
552 unsigned long ulval;
553 unsigned long long ullval;
554 char *cpval;
555 char **cppval;
556 char *result = NULL;
558 MUTEX_LOCK (&rcfile_mutex);
560 for (i = 0; config_params[i].name; i++)
562 if (!strcmp (config_params[i].name, what))
564 switch (config_params[i].type)
566 case PARAM_BOOL:
567 case PARAM_INT:
568 ival = config_get_int_param (global_config, where, what,
569 &exists);
570 if (!exists && strcmp (section ? section : "", "global"))
571 ival = config_get_int_param (global_config, "global", what,
572 &exists);
573 result = str_asprintf ("%i", ival);
574 break;
575 case PARAM_CHARP:
576 cpval = config_get_string_param (global_config, where, what,
577 &exists);
578 if (!exists && strcmp (section ? section : "", "global"))
579 cpval =
580 config_get_string_param (global_config, "global", what,
581 &exists);
582 result = cpval;
583 break;
584 case PARAM_LONG:
585 lval = config_get_long_param (global_config, where, what,
586 &exists);
587 if (!exists && strcmp (section ? section : "", "global"))
588 lval = config_get_long_param (global_config, "global", what,
589 &exists);
590 result = str_asprintf ("%li", lval);
591 break;
592 case PARAM_ULONG:
593 ulval = config_get_ulong_param (global_config, where, what,
594 &exists);
595 if (!exists && strcmp (section ? section : "", "global"))
596 ulval = config_get_ulong_param (global_config, "global", what,
597 &exists);
598 result = str_asprintf ("%lu", ulval);
599 break;
600 case PARAM_LONGLONG:
601 llval = config_get_longlong_param (global_config, where, what,
602 &exists);
603 if (!exists && strcmp (section ? section : "", "global"))
604 llval = config_get_longlong_param (global_config, "global",
605 what, &exists);
606 result = str_asprintf ("%lli", llval);
607 break;
608 case PARAM_ULONGLONG:
609 ullval = config_get_ulonglong_param (global_config, where, what,
610 &exists);
611 if (!exists && strcmp (section ? section : "", "global"))
612 ullval = config_get_ulonglong_param (global_config, "global",
613 what, &exists);
614 result = str_asprintf ("%llu", ullval);
615 break;
616 case PARAM_CHARPP:
617 cppval = config_get_list_param (global_config, where, what,
618 &exists);
619 if (!exists && strcmp (section ? section : "", "global"))
620 cppval = config_get_list_param (global_config, "global", what,
621 &exists);
623 if (cppval)
624 result = strv_join (",", cppval);
626 strv_free (cppval);
627 break;
632 MUTEX_UNLOCK (&rcfile_mutex);
633 return result;
636 /* 'file' is the list parameter file to load into the list parameter 'what'.
637 * The parsing of the parameter is not done here. */
638 static gpg_error_t
639 parse_list_file (struct slist_s *config, const char *section,
640 const char *file, const char *what)
642 FILE *fp;
643 char buf[LINE_MAX];
644 int exists;
645 char **list = NULL;
646 char *tmp;
647 char *p = config_get_string_param (config, section, file, &exists);
648 gpg_error_t rc;
650 if (!p || !*p)
652 xfree (p);
653 return 0;
656 tmp = expand_homedir (p);
657 xfree (p);
658 p = tmp;
659 fp = fopen (p, "r");
660 if (!fp)
662 rc = gpg_error_from_errno (errno);
663 log_write ("%s: %s", p, pwmd_strerror (rc));
664 xfree (p);
665 return rc;
668 xfree (p);
669 list = config_get_list_param (config, section, what, &exists);
670 if (!list && exists)
672 fclose (fp);
673 log_write ("%s", pwmd_strerror (ENOMEM));
674 return gpg_error (ENOMEM);
677 while ((p = fgets (buf, sizeof (buf), fp)))
679 char **pp = NULL;
681 if (p[strlen(p)-1] == '\n')
682 p[strlen(p)-1] = 0;
684 while (*p && isspace (*p))
685 p++;
687 if (!*p)
688 continue;
690 tmp = str_dup (p);
691 if (tmp)
692 pp = strv_cat (list, str_dup (p));
694 if (!pp || !tmp)
696 xfree (tmp);
697 strv_free (list);
698 fclose (fp);
699 log_write ("%s", strerror (ENOMEM));
700 return gpg_error (ENOMEM);
703 xfree (tmp);
704 list = pp;
707 fclose(fp);
708 if (!list)
709 return 0;
711 p = strv_join (",", list);
712 strv_free (list);
714 if (!p)
716 log_write ("%s", pwmd_strerror (ENOMEM));
717 return gpg_error (ENOMEM);
720 config_set_list_param (&config, section, what, p);
721 xfree (p);
722 return 0;
725 static int
726 fixup_allowed_once (struct slist_s **config, const char *section)
728 char **list, **pp, *p;
729 int exists;
730 gpg_error_t rc;
732 rc = parse_list_file (*config, section, "allowed_file", "allowed");
733 if (rc)
734 return 1;
736 list = config_get_list_param (*config, section, "allowed", &exists);
737 for (pp = list; pp && *pp; pp++)
739 if (*(*pp) == '#')
741 for (p = *pp; p && *p; p++)
742 *p = toupper(*p);
746 strv_free (list);
747 if (!exists)
749 if (!strcmp (section, "global"))
751 p = get_username (getuid());
753 if (config_set_list_param (config, section, "allowed", p))
755 xfree (p);
756 return 1;
759 xfree (p);
761 else
763 list = config_get_list_param (*config, "global", "allowed", &exists);
764 if (list)
766 p = strv_join (",", list);
767 strv_free (list);
768 if (config_set_list_param (config, section, "allowed", p))
770 xfree (p);
771 return 1;
774 xfree (p);
779 return 0;
782 static int
783 fixup_allowed (struct slist_s **config)
785 int n, t = slist_length (*config);
787 for (n = 0; n < t; n++)
789 struct config_section_s *section;
791 section = slist_nth_data (*config, n);
792 if (fixup_allowed_once (config, section->name))
793 return 1;
796 return 0;
799 static int
800 add_invoking_user (struct invoking_user_s **users, char *id,
801 struct slist_s **config)
803 struct passwd *pwd = NULL;
804 struct group *grp = NULL;
805 struct invoking_user_s *user, *p;
806 int not = 0;
808 if (id && (*id == '!' || *id == '-'))
810 not = 1;
811 id++;
814 errno = 0;
815 if (!id || !*id)
817 pwd = getpwuid (getuid ());
818 if (!pwd)
820 log_write (_("could not set any invoking user: %s"),
821 pwmd_strerror (errno));
822 return 1;
825 else if (*id == '@')
827 grp = getgrnam (id+1);
828 if (!grp)
830 log_write (_("could not parse group '%s': %s"), id+1,
831 pwmd_strerror (errno));
832 return 1;
835 else if (*id != '#')
836 pwd = getpwnam (id);
838 if (!grp && !pwd && id && *id != '#')
840 if (id && *id)
841 log_write (_("could not set invoking user '%s': %s"), id,
842 pwmd_strerror (errno));
843 else
844 log_write (_("could not set any invoking user!"));
846 return 1;
849 user = xcalloc (1, sizeof (struct invoking_user_s));
850 if (!user)
852 log_write ("%s", pwmd_strerror (ENOMEM));
853 return 1;
856 user->not = not;
857 user->type = pwd ? INVOKING_UID : grp ? INVOKING_GID : INVOKING_TLS;
858 if (pwd)
859 user->uid = pwd->pw_uid;
860 else if (grp)
861 user->id = str_dup (id+1);
862 else
864 char *s;
866 for (s = id; s && *s; s++)
867 *s = toupper(*s);
869 user->id = str_dup (id+1);
872 /* Set the default invoking_user since it doesn't exist. */
873 if (!id || !*id)
874 config_set_list_param (config, "global", "invoking_user", pwd->pw_name);
876 if (!*users)
878 *users = user;
879 return 0;
882 for (p = *users; p; p = p->next)
884 if (!p->next)
886 p->next = user;
887 break;
891 return 0;
894 static int
895 parse_invoking_users (struct slist_s **config)
897 struct invoking_user_s *users = NULL;
898 int exists;
899 char **list, **l;
901 if (parse_list_file (*config, "global", "invoking_file", "invoking_user"))
902 return 1;
904 list = config_get_list_param(*config, "global", "invoking_user", &exists);
905 for (l = list; l && *l; l++)
907 if (add_invoking_user (&users, *l, config))
909 strv_free (list);
910 free_invoking_users (users);
911 return 1;
915 if (!list || !*list)
917 if (add_invoking_user (&users, NULL, config))
919 strv_free (list);
920 return 1;
923 strv_free (list);
924 list = config_get_list_param(*config, "global", "invoking_user", &exists);
927 #ifdef WITH_GNUTLS
928 /* This option is deprecated. Parse it into invoking_user. */
929 char *tls = config_get_string_param(*config, "global", "invoking_tls",
930 &exists);
931 if (tls)
933 char *p;
934 char **pp;
936 if (add_invoking_user (&users, tls, config))
938 free_invoking_users (users);
939 return 1;
942 pp = strv_cat (list, tls);
943 if (!pp)
945 strv_free (list);
946 free_invoking_users (users);
947 log_write ("%s", pwmd_strerror (ENOMEM));
948 return 1;
951 list = pp;
952 p = strv_join (",", list);
953 strv_free (list);
954 config_set_list_param (config, "global", "invoking_user", p);
955 xfree (p);
957 #endif
959 free_invoking_users (invoking_users);
960 invoking_users = users;
961 return 0;
964 static int
965 set_defaults (struct slist_s **config, int reload)
967 char *s = NULL, *tmp;
968 char **list;
969 int exists;
970 int i;
972 for (i = 0; config_params[i].name; i++)
974 switch (config_params[i].type)
976 case PARAM_BOOL:
977 config_get_bool_param (*config, "global", config_params[i].name,
978 &exists);
979 if (!exists)
981 if (config_set_bool_param
982 (config, "global", config_params[i].name,
983 config_params[i].value))
984 goto fail;
986 break;
987 case PARAM_INT:
988 config_get_int_param (*config, "global", config_params[i].name,
989 &exists);
990 if (!exists)
992 if (config_set_int_param
993 (config, "global", config_params[i].name,
994 config_params[i].value))
995 goto fail;
997 break;
998 case PARAM_CHARP:
999 s = config_get_string_param (*config, "global",
1000 config_params[i].name, &exists);
1001 xfree (s);
1002 if (!exists && config_params[i].value)
1004 if (config_set_string_param (config, "global",
1005 config_params[i].name,
1006 config_params[i].value))
1007 goto fail;
1009 break;
1010 case PARAM_CHARPP:
1011 list = config_get_list_param (*config, "global",
1012 config_params[i].name, &exists);
1013 strv_free (list);
1014 if (!exists && config_params[i].value)
1016 if (config_set_list_param (config, "global",
1017 config_params[i].name,
1018 config_params[i].value))
1019 goto fail;
1021 break;
1022 case PARAM_LONG:
1023 config_get_long_param (*config, "global", config_params[i].name,
1024 &exists);
1025 if (!exists)
1027 if (config_set_long_param
1028 (config, "global", config_params[i].name,
1029 config_params[i].value))
1030 goto fail;
1032 break;
1033 case PARAM_LONGLONG:
1034 config_get_longlong_param (*config, "global", config_params[i].name,
1035 &exists);
1036 if (!exists)
1038 if (config_set_longlong_param (config, "global",
1039 config_params[i].name,
1040 config_params[i].value))
1041 goto fail;
1043 break;
1047 s = NULL;
1048 if (!reload && fixup_allowed (config))
1049 goto fail;
1051 max_recursion_depth = config_get_int_param (*config, "global",
1052 "recursion_depth", &exists);
1053 disable_list_and_dump = config_get_bool_param (*config, "global",
1054 "disable_list_and_dump",
1055 &exists);
1056 #ifdef HAVE_MLOCKALL
1057 disable_mlock =
1058 config_get_bool_param (*config, "global", "disable_mlockall", &exists);
1059 #endif
1061 if (!reload && parse_invoking_users (config))
1062 goto fail;
1064 s = config_get_string_param(*config, "global", "gpg_agent_socket", &exists);
1065 if (!s || !*s)
1067 xfree (s);
1068 s = str_asprintf ("%s/.gnupg/S.gpg-agent", get_home_dir());
1069 config_set_string_param(config, "global", "gpg_agent_socket", s);
1071 else
1073 tmp = expand_homedir (s);
1074 config_set_string_param(config, "global", "gpg_agent_socket", tmp);
1075 xfree (tmp);
1078 xfree (s);
1079 return 0;
1081 fail:
1082 xfree (s);
1083 return 1;
1086 static struct config_section_s *
1087 config_find_section (struct slist_s *config, const char *name)
1089 unsigned i, t = slist_length (config);
1091 for (i = 0; i < t; i++)
1093 struct config_section_s *s = slist_nth_data (config, i);
1095 if (!strcmp (s->name, name))
1096 return s;
1099 return NULL;
1102 /* Append a new parameter to the list of parameters for a file
1103 * section. When an existing parameter of the same name exists, its
1104 * value is updated.
1106 static int
1107 new_param (struct config_section_s *section, const char *filename, int lineno,
1108 const char *name, const char *value, int type)
1110 struct config_param_s *param = NULL;
1111 struct slist_s *tmp;
1112 char *e;
1113 unsigned i, t = slist_length (section->params);
1114 int dup = 0;
1116 for (i = 0; i < t; i++)
1118 struct config_param_s *p = slist_nth_data (section->params, i);
1119 if (!p)
1120 break;
1122 if (!strcmp (name, p->name))
1124 param = p;
1125 dup = 1;
1126 break;
1130 if (!param)
1132 param = xcalloc (1, sizeof (struct config_param_s));
1133 if (!param)
1135 log_write ("%s", pwmd_strerror (ENOMEM));
1136 return 1;
1139 param->name = str_dup (name);
1140 if (!param->name)
1142 xfree (param);
1143 log_write ("%s", pwmd_strerror (ENOMEM));
1144 return 1;
1148 param->type = type;
1150 switch (type)
1152 case PARAM_BOOL:
1153 if (!strcasecmp (value, "no") || !strcasecmp (value, "0")
1154 || !strcasecmp (value, "false"))
1155 param->value.itype = 0;
1156 else if (!strcasecmp (value, "yes") || !strcasecmp (value, "1")
1157 || !strcasecmp (value, "true"))
1158 param->value.itype = 1;
1159 else
1161 INVALID_VALUE (filename, lineno);
1162 goto fail;
1164 param->type = PARAM_INT;
1165 break;
1166 case PARAM_CHARP:
1167 xfree (param->value.cptype);
1168 param->value.cptype = NULL;
1169 param->value.cptype = value && *value ? str_dup (value) : NULL;
1170 if (value && *value && !param->value.cptype)
1172 log_write ("%s", pwmd_strerror (ENOMEM));
1173 goto fail;
1175 break;
1176 case PARAM_CHARPP:
1177 strv_free (param->value.cpptype);
1178 param->value.cpptype = NULL;
1179 param->value.cpptype = value && *value ? str_split (value, ",", 0) : NULL;
1180 if (value && *value && !param->value.cpptype)
1182 log_write ("%s", pwmd_strerror (ENOMEM));
1183 goto fail;
1185 break;
1186 case PARAM_INT:
1187 param->value.itype = strtol (value, &e, 10);
1188 if (e && *e)
1190 INVALID_VALUE (filename, lineno);
1191 goto fail;
1193 break;
1194 case PARAM_LONG:
1195 param->value.ltype = strtol (value, &e, 10);
1196 if (e && *e)
1198 INVALID_VALUE (filename, lineno);
1199 goto fail;
1201 break;
1202 case PARAM_LONGLONG:
1203 param->value.lltype = strtoll (value, &e, 10);
1204 if (e && *e)
1206 INVALID_VALUE (filename, lineno);
1207 goto fail;
1209 break;
1210 case PARAM_ULONGLONG:
1211 param->value.ulltype = strtoull (value, &e, 10);
1212 if (e && *e)
1214 INVALID_VALUE (filename, lineno);
1215 goto fail;
1217 break;
1218 case PARAM_ULONG:
1219 param->value.ultype = strtoul (value, &e, 10);
1220 if (e && *e)
1222 INVALID_VALUE (filename, lineno);
1223 goto fail;
1225 break;
1228 if (dup)
1229 return 0;
1231 tmp = slist_append (section->params, param);
1232 if (!tmp)
1234 log_write ("%s", pwmd_strerror (ENOMEM));
1235 goto fail;
1238 section->params = tmp;
1239 return 0;
1241 fail:
1242 xfree (param->name);
1243 xfree (param);
1244 return 1;
1247 struct slist_s *
1248 config_parse (const char *filename, int reload)
1250 struct slist_s *tmpconfig = NULL, *tmp;
1251 struct config_section_s *cur_section = NULL;
1252 char buf[LINE_MAX];
1253 char *s;
1254 int lineno = 1;
1255 int have_global = 0;
1256 FILE *fp = fopen (filename, "r");
1258 if (!fp)
1260 log_write ("%s: %s", filename,
1261 pwmd_strerror (gpg_error_from_errno (errno)));
1263 if (errno != ENOENT)
1264 return NULL;
1266 log_write (_("Using defaults!"));
1267 goto defaults;
1270 for (; (s = fgets (buf, sizeof (buf), fp)); lineno++)
1272 char line[LINE_MAX] = { 0 };
1273 size_t len = 0;
1275 if (*s == '#')
1276 continue;
1278 s = str_chomp (s);
1279 for (; s && *s; s++)
1281 int match = 0;
1283 /* New file section. */
1284 if (*s == '[')
1286 struct config_section_s *section;
1287 char *p = strchr (++s, ']');
1289 if (!p)
1291 log_write (_("%s(%i): unbalanced braces"), filename,
1292 lineno);
1293 goto fail;
1296 len = strlen (s) - strlen (p);
1297 memcpy (line, s, len);
1298 line[len] = 0;
1300 section = config_find_section (tmpconfig, line);
1301 if (section)
1303 log_write (_("%s(%i): section '%s' already exists!"),
1304 filename, lineno, line);
1305 goto fail;
1308 if (!strcmp (line, "global"))
1309 have_global = 1;
1311 section = xcalloc (1, sizeof (struct config_section_s));
1312 section->name = str_dup (line);
1314 if (cur_section)
1316 tmp = slist_append (tmpconfig, cur_section);
1317 if (!tmp)
1319 log_write ("%s", pwmd_strerror (ENOMEM));
1320 goto fail;
1323 tmpconfig = tmp;
1326 cur_section = section;
1327 break;
1330 if (!cur_section)
1332 log_write (_("%s(%i): parameter outside of section!"), filename,
1333 lineno);
1334 goto fail;
1337 /* Parameters for each section. */
1338 for (int m = 0; config_params[m].name; m++)
1340 size_t len = strlen (config_params[m].name);
1342 if (!strncmp (s, config_params[m].name, len))
1344 char *p = s + len;
1346 while (*p && *p == ' ')
1347 p++;
1349 if (!*p || *p != '=')
1350 continue;
1352 p++;
1353 while (*p && isspace (*p))
1354 p++;
1356 s[len] = 0;
1357 if (new_param (cur_section, filename, lineno, s, p,
1358 config_params[m].type))
1359 goto fail;
1361 match = 1;
1362 break;
1366 if (!match)
1368 log_write (_("%s(%i): unknown parameter"), filename, lineno);
1369 goto fail;
1372 break;
1376 if (cur_section)
1378 tmp = slist_append (tmpconfig, cur_section);
1379 if (!tmp)
1381 log_write ("%s", pwmd_strerror (ENOMEM));
1382 goto fail;
1385 cur_section = NULL;
1386 tmpconfig = tmp;
1389 if (!have_global)
1390 log_write (_
1391 ("WARNING: %s: could not find a [global] configuration section!"),
1392 filename);
1393 else
1395 int exists;
1396 char *tmp = config_get_string_param (tmpconfig, "global", "tls_dh_level",
1397 &exists);
1398 if (tmp)
1400 if (strcasecmp (tmp, "low") && strcasecmp (tmp, "medium")
1401 && strcasecmp (tmp, "high"))
1403 xfree (tmp);
1404 log_write (_("invalid tls_dh_level value"));
1405 goto fail;
1408 xfree (tmp);
1412 defaults:
1413 if (set_defaults (&tmpconfig, reload))
1414 goto fail;
1416 if (fp)
1417 fclose(fp);
1419 return tmpconfig;
1421 fail:
1422 if (fp)
1423 fclose (fp);
1425 config_free (tmpconfig);
1426 free_section (cur_section);
1427 return NULL;
1430 static void
1431 free_section (struct config_section_s *s)
1433 if (!s)
1434 return;
1436 for (;;)
1438 struct config_param_s *p = slist_nth_data (s->params, 0);
1440 if (!p)
1441 break;
1443 section_remove_param (s, p->name);
1446 s->params = NULL;
1447 xfree (s->name);
1448 s->name = NULL;
1451 void
1452 config_free (struct slist_s *config)
1454 for (;;)
1456 struct config_section_s *s = slist_nth_data (config, 0);
1457 if (!s)
1458 break;
1460 free_section (s);
1461 config = slist_remove (config, s);
1462 xfree (s);
1466 void
1467 free_invoking_users (struct invoking_user_s *users)
1469 struct invoking_user_s *p;
1471 for (p = users; p;)
1473 struct invoking_user_s *next = p->next;
1475 if (p->type == INVOKING_TLS || p->type == INVOKING_GID)
1476 xfree (p->id);
1478 xfree (p);
1479 p = next;