2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
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/>.
26 #include <sys/types.h>
32 #include "pwmd-error.h"
36 #include "util-misc.h"
38 #include "util-slist.h"
39 #include "util-string.h"
42 #define DEFAULT_PINENTRY_TIMEOUT "30"
43 #define DEFAULT_CACHE_TIMEOUT "600"
44 #define DEFAULT_KEEPALIVE_INTERVAL "60"
46 #define INVALID_VALUE(file, line) do { \
48 log_write(_("%s(%i): invalid value for parameter."), file, line); \
53 PARAM_INT
, PARAM_CHARP
, PARAM_LONG
, PARAM_LONGLONG
, PARAM_CHARPP
,
54 PARAM_BOOL
, PARAM_ULONG
, PARAM_ULONGLONG
57 static struct config_params_s
63 { "backup", PARAM_BOOL
, "true"},
64 { "socket_path", PARAM_CHARP
, NULL
},
65 { "socket_perms", PARAM_CHARP
, NULL
},
66 { "passphrase", PARAM_CHARP
, NULL
},
67 { "passphrase_file", PARAM_CHARP
, NULL
},
68 { "agent_env_file", PARAM_CHARP
, NULL
},
69 { "log_path", PARAM_CHARP
, "~/.pwmd/log"},
70 { "enable_logging", PARAM_BOOL
, "0"},
71 { "log_keepopen", PARAM_BOOL
, "true"},
72 { "log_level", PARAM_INT
, "0"},
73 { "disable_mlockall", PARAM_BOOL
, "true"},
74 { "cache_timeout", PARAM_INT
, DEFAULT_CACHE_TIMEOUT
},
75 { "cache_push", PARAM_CHARPP
, NULL
},
76 { "disable_list_and_dump", PARAM_BOOL
, "false"},
77 { "recursion_depth", PARAM_INT
, "100"},
78 { "syslog", PARAM_BOOL
, "false"},
79 { "xfer_progress", PARAM_INT
, "8196"},
80 { "allowed", PARAM_CHARPP
, NULL
},
81 { "keyparam", PARAM_CHARP
, "(genkey (rsa (nbits 4:2048)))"},
82 { "cipher", PARAM_CHARP
, "aes256"},
83 { "kill_scd", PARAM_BOOL
, "false"},
84 { "cipher_iterations", PARAM_ULONGLONG
, "0"},
85 { "cipher_progress", PARAM_LONG
, DEFAULT_ITERATION_PROGRESS
},
86 { "priority", PARAM_INT
, INVALID_PRIORITY
},
87 { "keepalive_interval", PARAM_INT
, DEFAULT_KEEPALIVE_INTERVAL
},
88 { "tcp_port", PARAM_INT
, "6466"},
89 { "enable_tcp", PARAM_BOOL
, "false"},
90 { "tcp_require_key", PARAM_BOOL
, "false"},
91 { "tcp_wait", PARAM_INT
, "0"},
92 { "tcp_bind", PARAM_CHARP
, "any"},
93 { "tcp_interface", PARAM_CHARP
, NULL
},
94 { "tls_timeout", PARAM_INT
, "300"},
95 { "tls_cipher_suite", PARAM_CHARP
, "SECURE256"},
96 { "tls_access", PARAM_CHARPP
, NULL
},
97 { "pinentry_path", PARAM_CHARP
, PINENTRY_PATH
},
98 { "pinentry_timeout", PARAM_INT
, DEFAULT_PINENTRY_TIMEOUT
},
99 { "use_agent", PARAM_BOOL
, "false"},
100 { "require_save_key", PARAM_BOOL
, "true"},
104 struct config_param_s
115 unsigned long ultype
;
116 unsigned long long ulltype
;
120 static struct config_section_s
*config_find_section (struct slist_s
*config
,
122 static int new_param (struct config_section_s
*section
, const char *filename
,
123 int lineno
, const char *name
, const char *value
,
125 static void free_section (struct config_section_s
*s
);
126 static int set_defaults (struct slist_s
**config
);
129 section_remove_param (struct config_section_s
*section
, const char *name
)
131 unsigned i
, t
= slist_length (section
->params
);
133 for (i
= 0; i
< t
; i
++)
135 struct config_param_s
*p
= slist_nth_data (section
->params
, i
);
140 if (!strcmp (p
->name
, name
))
145 xfree (p
->value
.cptype
);
148 strv_free (p
->value
.cpptype
);
152 section
->params
= slist_remove (section
->params
, p
);
163 MUTEX_LOCK (&rcfile_mutex
);
164 unsigned i
, t
= slist_length (global_config
);
166 for (i
= 0; i
< t
; i
++)
168 struct config_section_s
*s
= slist_nth_data (global_config
, i
);
172 section_remove_param (s
, "passphrase");
175 MUTEX_UNLOCK (&rcfile_mutex
);
178 static struct config_param_s
*
179 config_has_param (struct config_section_s
*s
, const char *what
)
181 unsigned i
, t
= slist_length (s
->params
);
183 for (i
= 0; i
< t
; i
++)
185 struct config_param_s
*p
= slist_nth_data (s
->params
, i
);
189 if (!strcmp (p
->name
, what
))
196 static struct config_param_s
*
197 config_get_param (struct slist_s
*config
,
198 const char *section
, const char *what
, int *exists
)
200 unsigned i
, t
= slist_length (config
);
204 for (i
= 0; i
< t
; i
++)
206 struct config_param_s
*p
;
207 struct config_section_s
*s
= slist_nth_data (config
, i
);
212 if (strcmp (s
->name
, section
))
215 p
= config_has_param (s
, what
);
226 static struct config_section_s
*
227 new_section (struct slist_s
**config
, const char *name
)
230 struct config_section_s
*s
= xcalloc (1, sizeof (struct config_section_s
));
235 s
->name
= str_dup (name
);
238 log_write ("%s", pwmd_strerror (ENOMEM
));
243 tmp
= slist_append (*config
, s
);
246 log_write ("%s", pwmd_strerror (ENOMEM
));
257 config_set_string_param (struct slist_s
**config
, const char *section
,
258 const char *name
, const char *value
)
260 struct config_section_s
*s
= config_find_section (*config
, section
);
264 s
= new_section (config
, section
);
269 return new_param (s
, NULL
, 0, name
, value
, PARAM_CHARP
);
273 config_get_string_param (struct slist_s
*config
, const char *section
,
274 const char *what
, int *exists
)
276 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
277 return *exists
&& p
->value
.cptype
? str_dup (p
->value
.cptype
) : NULL
;
281 config_set_int_param (struct slist_s
**config
, const char *section
,
282 const char *name
, const char *value
)
284 struct config_section_s
*s
= config_find_section (*config
, section
);
288 s
= new_section (config
, section
);
293 return new_param (s
, NULL
, 0, name
, value
, PARAM_INT
);
297 config_get_int_param (struct slist_s
*config
, const char *section
,
298 const char *what
, int *exists
)
300 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
301 return *exists
? p
->value
.itype
: -1;
305 config_set_bool_param (struct slist_s
**config
, const char *section
,
306 const char *name
, const char *value
)
308 struct config_section_s
*s
= config_find_section (*config
, section
);
312 s
= new_section (config
, section
);
317 return new_param (s
, NULL
, 0, name
, value
, PARAM_BOOL
);
321 config_get_bool_param (struct slist_s
*config
, const char *section
,
322 const char *what
, int *exists
)
324 return config_get_int_param (config
, section
, what
, exists
);
328 config_set_long_param (struct slist_s
**config
, const char *section
,
329 const char *name
, const char *value
)
331 struct config_section_s
*s
= config_find_section (*config
, section
);
335 s
= new_section (config
, section
);
340 return new_param (s
, NULL
, 0, name
, value
, PARAM_LONG
);
344 config_get_ulong_param (struct slist_s
*config
, const char *section
,
345 const char *what
, int *exists
)
347 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
348 return *exists
? p
->value
.ultype
: 0;
352 config_get_long_param (struct slist_s
*config
, const char *section
,
353 const char *what
, int *exists
)
355 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
356 return *exists
? p
->value
.ltype
: -1;
360 config_set_longlong_param (struct slist_s
**config
, const char *section
,
361 const char *name
, const char *value
)
363 struct config_section_s
*s
= config_find_section (*config
, section
);
367 s
= new_section (config
, section
);
372 return new_param (s
, NULL
, 0, name
, value
, PARAM_LONGLONG
);
376 config_get_longlong_param (struct slist_s
*config
,
377 const char *section
, const char *what
, int *exists
)
379 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
380 return *exists
? p
->value
.lltype
: -1;
384 config_get_ulonglong_param (struct slist_s
*config
,
386 const char *what
, int *exists
)
388 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
389 return *exists
? p
->value
.ulltype
: 0;
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
);
400 s
= new_section (config
, section
);
405 return new_param (s
, NULL
, 0, name
, value
, PARAM_CHARPP
);
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
;
417 config_get_string (const char *section
, const char *what
)
420 const char *where
= section
? section
: "global";
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
);
433 config_get_list (const char *section
, const char *what
)
436 const char *where
= section
? section
: "global";
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
);
449 config_get_integer (const char *section
, const char *what
)
452 const char *where
= section
? section
: "global";
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
);
465 config_get_longlong (const char *section
, const char *what
)
468 const char *where
= section
? section
: "global";
471 MUTEX_LOCK (&rcfile_mutex
);
472 val
= config_get_longlong_param (global_config
, where
, what
, &exists
);
473 if (!exists
&& strcmp (section
? section
: "", "global"))
474 val
= config_get_longlong_param (global_config
, "global", what
, &exists
);
476 MUTEX_UNLOCK (&rcfile_mutex
);
481 config_get_ulonglong (const char *section
, const char *what
)
483 unsigned long long val
= 0;
484 const char *where
= section
? section
: "global";
487 MUTEX_LOCK (&rcfile_mutex
);
488 val
= config_get_ulonglong_param (global_config
, where
, what
, &exists
);
489 if (!exists
&& strcmp (section
? section
: "", "global"))
490 val
= config_get_ulonglong_param (global_config
, "global", what
, &exists
);
492 MUTEX_UNLOCK (&rcfile_mutex
);
497 config_get_long (const char *section
, const char *what
)
500 const char *where
= section
? section
: "global";
503 MUTEX_LOCK (&rcfile_mutex
);
504 val
= config_get_long_param (global_config
, where
, what
, &exists
);
505 if (!exists
&& strcmp (section
? section
: "", "global"))
506 val
= config_get_long_param (global_config
, "global", what
, &exists
);
508 MUTEX_UNLOCK (&rcfile_mutex
);
513 config_get_ulong (const char *section
, const char *what
)
515 unsigned long val
= 0;
516 const char *where
= section
? section
: "global";
519 MUTEX_LOCK (&rcfile_mutex
);
520 val
= config_get_ulong_param (global_config
, where
, what
, &exists
);
521 if (!exists
&& strcmp (section
? section
: "", "global"))
522 val
= config_get_ulong_param (global_config
, "global", what
, &exists
);
524 MUTEX_UNLOCK (&rcfile_mutex
);
529 config_get_boolean (const char *section
, const char *what
)
531 return config_get_integer (section
, what
);
535 config_get_value (const char *section
, const char *what
)
537 const char *where
= section
? section
: "global";
544 unsigned long long ullval
;
549 MUTEX_LOCK (&rcfile_mutex
);
551 for (i
= 0; config_params
[i
].name
; i
++)
553 if (!strcmp (config_params
[i
].name
, what
))
555 switch (config_params
[i
].type
)
559 ival
= config_get_int_param (global_config
, where
, what
,
561 if (!exists
&& strcmp (section
? section
: "", "global"))
562 ival
= config_get_int_param (global_config
, "global", what
,
564 result
= str_asprintf ("%i", ival
);
567 cpval
= config_get_string_param (global_config
, where
, what
,
569 if (!exists
&& strcmp (section
? section
: "", "global"))
571 config_get_string_param (global_config
, "global", what
,
576 lval
= config_get_long_param (global_config
, where
, what
,
578 if (!exists
&& strcmp (section
? section
: "", "global"))
579 lval
= config_get_long_param (global_config
, "global", what
,
581 result
= str_asprintf ("%li", lval
);
584 ulval
= config_get_ulong_param (global_config
, where
, what
,
586 if (!exists
&& strcmp (section
? section
: "", "global"))
587 ulval
= config_get_ulong_param (global_config
, "global", what
,
589 result
= str_asprintf ("%lu", ulval
);
592 llval
= config_get_longlong_param (global_config
, where
, what
,
594 if (!exists
&& strcmp (section
? section
: "", "global"))
595 llval
= config_get_longlong_param (global_config
, "global",
597 result
= str_asprintf ("%lli", llval
);
599 case PARAM_ULONGLONG
:
600 ullval
= config_get_ulonglong_param (global_config
, where
, what
,
602 if (!exists
&& strcmp (section
? section
: "", "global"))
603 ullval
= config_get_ulonglong_param (global_config
, "global",
605 result
= str_asprintf ("%llu", ullval
);
608 cppval
= config_get_list_param (global_config
, where
, what
,
610 if (!exists
&& strcmp (section
? section
: "", "global"))
611 cppval
= config_get_list_param (global_config
, "global", what
,
615 result
= strv_join (",", cppval
);
623 MUTEX_UNLOCK (&rcfile_mutex
);
628 set_defaults (struct slist_s
**config
)
635 for (i
= 0; config_params
[i
].name
; i
++)
637 switch (config_params
[i
].type
)
640 config_get_bool_param (*config
, "global", config_params
[i
].name
,
644 if (config_set_bool_param
645 (config
, "global", config_params
[i
].name
,
646 config_params
[i
].value
))
651 config_get_int_param (*config
, "global", config_params
[i
].name
,
655 if (config_set_int_param
656 (config
, "global", config_params
[i
].name
,
657 config_params
[i
].value
))
662 s
= config_get_string_param (*config
, "global",
663 config_params
[i
].name
, &exists
);
665 if (!exists
&& config_params
[i
].value
)
667 if (config_set_string_param (config
, "global",
668 config_params
[i
].name
,
669 config_params
[i
].value
))
674 list
= config_get_list_param (*config
, "global",
675 config_params
[i
].name
, &exists
);
677 if (!exists
&& config_params
[i
].value
)
679 if (config_set_list_param (config
, "global",
680 config_params
[i
].name
,
681 config_params
[i
].value
))
686 config_get_long_param (*config
, "global", config_params
[i
].name
,
690 if (config_set_long_param
691 (config
, "global", config_params
[i
].name
,
692 config_params
[i
].value
))
697 config_get_longlong_param (*config
, "global", config_params
[i
].name
,
701 if (config_set_longlong_param (config
, "global",
702 config_params
[i
].name
,
703 config_params
[i
].value
))
710 list
= config_get_list_param (*config
, "global", "allowed", &exists
);
714 if (config_set_list_param
715 (config
, "global", "allowed", get_username ()))
719 max_recursion_depth
= config_get_int_param (*config
, "global",
720 "recursion_depth", &exists
);
721 disable_list_and_dump
= config_get_bool_param (*config
, "global",
722 "disable_list_and_dump",
726 config_get_bool_param (*config
, "global", "disable_mlockall", &exists
);
734 static struct config_section_s
*
735 config_find_section (struct slist_s
*config
, const char *name
)
737 unsigned i
, t
= slist_length (config
);
739 for (i
= 0; i
< t
; i
++)
741 struct config_section_s
*s
= slist_nth_data (config
, i
);
743 if (!strcmp (s
->name
, name
))
750 /* Append a new parameter to the list of parameters for a file
751 * section. When an existing parameter of the same name exists, its
755 new_param (struct config_section_s
*section
, const char *filename
, int lineno
,
756 const char *name
, const char *value
, int type
)
758 struct config_param_s
*param
= NULL
;
761 unsigned i
, t
= slist_length (section
->params
);
764 for (i
= 0; i
< t
; i
++)
766 struct config_param_s
*p
= slist_nth_data (section
->params
, i
);
770 if (!strcmp (name
, p
->name
))
780 param
= xcalloc (1, sizeof (struct config_param_s
));
783 log_write ("%s", pwmd_strerror (ENOMEM
));
787 param
->name
= str_dup (name
);
791 log_write ("%s", pwmd_strerror (ENOMEM
));
801 if (!strcasecmp (value
, "no") || !strcasecmp (value
, "0")
802 || !strcasecmp (value
, "false"))
803 param
->value
.itype
= 0;
804 else if (!strcasecmp (value
, "yes") || !strcasecmp (value
, "1")
805 || !strcasecmp (value
, "true"))
806 param
->value
.itype
= 1;
809 INVALID_VALUE (filename
, lineno
);
812 param
->type
= PARAM_INT
;
815 xfree (param
->value
.cptype
);
816 param
->value
.cptype
= value
? str_dup (value
) : NULL
;
817 if (value
&& !param
->value
.cptype
)
819 log_write ("%s", pwmd_strerror (ENOMEM
));
824 strv_free (param
->value
.cpptype
);
825 param
->value
.cpptype
= value
? str_split (value
, ",", 0) : NULL
;
826 if (value
&& !param
->value
.cpptype
)
828 log_write ("%s", pwmd_strerror (ENOMEM
));
833 param
->value
.itype
= strtol (value
, &e
, 10);
836 INVALID_VALUE (filename
, lineno
);
841 param
->value
.ltype
= strtol (value
, &e
, 10);
844 INVALID_VALUE (filename
, lineno
);
849 param
->value
.lltype
= strtoll (value
, &e
, 10);
852 INVALID_VALUE (filename
, lineno
);
856 case PARAM_ULONGLONG
:
857 param
->value
.ulltype
= strtoull (value
, &e
, 10);
860 INVALID_VALUE (filename
, lineno
);
865 param
->value
.ultype
= strtoul (value
, &e
, 10);
868 INVALID_VALUE (filename
, lineno
);
877 tmp
= slist_append (section
->params
, param
);
880 log_write ("%s", pwmd_strerror (ENOMEM
));
884 section
->params
= tmp
;
894 config_parse (const char *filename
)
896 struct slist_s
*tmpconfig
= NULL
, *tmp
;
897 struct config_section_s
*cur_section
= NULL
;
902 FILE *fp
= fopen (filename
, "r");
906 log_write ("%s: %s", filename
,
907 pwmd_strerror (gpg_error_from_errno (errno
)));
912 log_write (_("Using defaults!"));
916 for (; (s
= fgets (buf
, sizeof (buf
), fp
)); lineno
++)
918 char line
[LINE_MAX
] = { 0 };
929 /* New file section. */
932 struct config_section_s
*section
;
933 char *p
= strchr (++s
, ']');
937 log_write (_("%s(%i): unbalanced braces"), filename
,
942 len
= strlen (s
) - strlen (p
);
943 memcpy (line
, s
, len
);
946 section
= config_find_section (tmpconfig
, line
);
949 log_write (_("%s(%i): section '%s' already exists!"),
950 filename
, lineno
, line
);
954 if (!strcmp (line
, "global"))
957 section
= xcalloc (1, sizeof (struct config_section_s
));
958 section
->name
= str_dup (line
);
962 tmp
= slist_append (tmpconfig
, cur_section
);
965 log_write ("%s", pwmd_strerror (ENOMEM
));
972 cur_section
= section
;
978 log_write (_("%s(%i): parameter outside of section!"), filename
,
983 /* Parameters for each section. */
984 for (int m
= 0; config_params
[m
].name
; m
++)
986 size_t len
= strlen (config_params
[m
].name
);
988 if (!strncmp (s
, config_params
[m
].name
, len
))
992 while (*p
&& *p
== ' ')
995 if (!*p
|| *p
!= '=')
999 while (*p
&& isspace (*p
))
1003 if (new_param (cur_section
, filename
, lineno
, s
, p
,
1004 config_params
[m
].type
))
1014 log_write (_("%s(%i): unknown parameter"), filename
, lineno
);
1024 tmp
= slist_append (tmpconfig
, cur_section
);
1027 log_write ("%s", pwmd_strerror (ENOMEM
));
1037 ("WARNING: %s: could not find a [global] configuration section!"),
1041 if (set_defaults (&tmpconfig
))
1053 config_free (tmpconfig
);
1054 free_section (cur_section
);
1059 free_section (struct config_section_s
*s
)
1066 struct config_param_s
*p
= slist_nth_data (s
->params
, 0);
1071 section_remove_param (s
, p
->name
);
1080 config_free (struct slist_s
*config
)
1084 struct config_section_s
*s
= slist_nth_data (config
, 0);
1089 config
= slist_remove (config
, s
);