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_level", PARAM_INT
, "0"},
72 { "disable_mlockall", PARAM_BOOL
, "true"},
73 { "cache_timeout", PARAM_INT
, DEFAULT_CACHE_TIMEOUT
},
74 { "cache_push", PARAM_CHARPP
, NULL
},
75 { "disable_list_and_dump", PARAM_BOOL
, "false"},
76 { "recursion_depth", PARAM_INT
, "100"},
77 { "syslog", PARAM_BOOL
, "false"},
78 { "xfer_progress", PARAM_INT
, "8196"},
79 { "allowed", PARAM_CHARPP
, NULL
},
80 { "keyparam", PARAM_CHARP
, "(genkey (rsa (nbits 4:2048)))"},
81 { "cipher", PARAM_CHARP
, "aes256"},
82 { "kill_scd", PARAM_BOOL
, "false"},
83 { "cipher_iterations", PARAM_ULONGLONG
, "0"},
84 { "cipher_progress", PARAM_LONG
, DEFAULT_ITERATION_PROGRESS
},
85 { "priority", PARAM_INT
, INVALID_PRIORITY
},
86 { "keepalive_interval", PARAM_INT
, DEFAULT_KEEPALIVE_INTERVAL
},
87 { "tcp_port", PARAM_INT
, "6466"},
88 { "enable_tcp", PARAM_BOOL
, "false"},
89 { "tcp_require_key", PARAM_BOOL
, "false"},
90 { "tcp_wait", PARAM_INT
, "0"},
91 { "tcp_bind", PARAM_CHARP
, "any"},
92 { "tcp_interface", PARAM_CHARP
, NULL
},
93 { "tls_timeout", PARAM_INT
, "300"},
94 { "tls_cipher_suite", PARAM_CHARP
, "SECURE256"},
95 { "tls_access", PARAM_CHARPP
, NULL
},
96 { "pinentry_path", PARAM_CHARP
, PINENTRY_PATH
},
97 { "pinentry_timeout", PARAM_INT
, DEFAULT_PINENTRY_TIMEOUT
},
98 { "use_agent", PARAM_BOOL
, "false"},
99 { "require_save_key", PARAM_BOOL
, "true"},
103 struct config_param_s
114 unsigned long ultype
;
115 unsigned long long ulltype
;
119 static struct config_section_s
*config_find_section (struct slist_s
*config
,
121 static int new_param (struct config_section_s
*section
, const char *filename
,
122 int lineno
, const char *name
, const char *value
,
124 static void free_section (struct config_section_s
*s
);
125 static int set_defaults (struct slist_s
**config
);
128 section_remove_param (struct config_section_s
*section
, const char *name
)
130 unsigned i
, t
= slist_length (section
->params
);
132 for (i
= 0; i
< t
; i
++)
134 struct config_param_s
*p
= slist_nth_data (section
->params
, i
);
139 if (!strcmp (p
->name
, name
))
144 xfree (p
->value
.cptype
);
147 strv_free (p
->value
.cpptype
);
151 section
->params
= slist_remove (section
->params
, p
);
162 MUTEX_LOCK (&rcfile_mutex
);
163 unsigned i
, t
= slist_length (global_config
);
165 for (i
= 0; i
< t
; i
++)
167 struct config_section_s
*s
= slist_nth_data (global_config
, i
);
171 section_remove_param (s
, "passphrase");
174 MUTEX_UNLOCK (&rcfile_mutex
);
177 static struct config_param_s
*
178 config_has_param (struct config_section_s
*s
, const char *what
)
180 unsigned i
, t
= slist_length (s
->params
);
182 for (i
= 0; i
< t
; i
++)
184 struct config_param_s
*p
= slist_nth_data (s
->params
, i
);
188 if (!strcmp (p
->name
, what
))
195 static struct config_param_s
*
196 config_get_param (struct slist_s
*config
,
197 const char *section
, const char *what
, int *exists
)
199 unsigned i
, t
= slist_length (config
);
203 for (i
= 0; i
< t
; i
++)
205 struct config_param_s
*p
;
206 struct config_section_s
*s
= slist_nth_data (config
, i
);
211 if (strcmp (s
->name
, section
))
214 p
= config_has_param (s
, what
);
225 static struct config_section_s
*
226 new_section (struct slist_s
**config
, const char *name
)
229 struct config_section_s
*s
= xcalloc (1, sizeof (struct config_section_s
));
234 s
->name
= str_dup (name
);
237 log_write ("%s", pwmd_strerror (ENOMEM
));
242 tmp
= slist_append (*config
, s
);
245 log_write ("%s", pwmd_strerror (ENOMEM
));
256 config_set_string_param (struct slist_s
**config
, const char *section
,
257 const char *name
, const char *value
)
259 struct config_section_s
*s
= config_find_section (*config
, section
);
263 s
= new_section (config
, section
);
268 return new_param (s
, NULL
, 0, name
, value
, PARAM_CHARP
);
272 config_get_string_param (struct slist_s
*config
, const char *section
,
273 const char *what
, int *exists
)
275 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
276 return *exists
&& p
->value
.cptype
? str_dup (p
->value
.cptype
) : NULL
;
280 config_set_int_param (struct slist_s
**config
, const char *section
,
281 const char *name
, const char *value
)
283 struct config_section_s
*s
= config_find_section (*config
, section
);
287 s
= new_section (config
, section
);
292 return new_param (s
, NULL
, 0, name
, value
, PARAM_INT
);
296 config_get_int_param (struct slist_s
*config
, const char *section
,
297 const char *what
, int *exists
)
299 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
300 return *exists
? p
->value
.itype
: -1;
304 config_set_bool_param (struct slist_s
**config
, const char *section
,
305 const char *name
, const char *value
)
307 struct config_section_s
*s
= config_find_section (*config
, section
);
311 s
= new_section (config
, section
);
316 return new_param (s
, NULL
, 0, name
, value
, PARAM_BOOL
);
320 config_get_bool_param (struct slist_s
*config
, const char *section
,
321 const char *what
, int *exists
)
323 return config_get_int_param (config
, section
, what
, exists
);
327 config_set_long_param (struct slist_s
**config
, const char *section
,
328 const char *name
, const char *value
)
330 struct config_section_s
*s
= config_find_section (*config
, section
);
334 s
= new_section (config
, section
);
339 return new_param (s
, NULL
, 0, name
, value
, PARAM_LONG
);
343 config_get_ulong_param (struct slist_s
*config
, const char *section
,
344 const char *what
, int *exists
)
346 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
347 return *exists
? p
->value
.ultype
: 0;
351 config_get_long_param (struct slist_s
*config
, const char *section
,
352 const char *what
, int *exists
)
354 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
355 return *exists
? p
->value
.ltype
: -1;
359 config_set_longlong_param (struct slist_s
**config
, const char *section
,
360 const char *name
, const char *value
)
362 struct config_section_s
*s
= config_find_section (*config
, section
);
366 s
= new_section (config
, section
);
371 return new_param (s
, NULL
, 0, name
, value
, PARAM_LONGLONG
);
375 config_get_longlong_param (struct slist_s
*config
,
376 const char *section
, const char *what
, int *exists
)
378 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
379 return *exists
? p
->value
.lltype
: -1;
383 config_get_ulonglong_param (struct slist_s
*config
,
385 const char *what
, int *exists
)
387 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
388 return *exists
? p
->value
.ulltype
: 0;
392 config_set_list_param (struct slist_s
**config
, const char *section
,
393 const char *name
, const char *value
)
395 struct config_section_s
*s
= config_find_section (*config
, section
);
399 s
= new_section (config
, section
);
404 return new_param (s
, NULL
, 0, name
, value
, PARAM_CHARPP
);
408 config_get_list_param (struct slist_s
*config
, const char *section
,
409 const char *what
, int *exists
)
411 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
412 return *exists
&& p
->value
.cpptype
? strv_dup (p
->value
.cpptype
) : NULL
;
416 config_get_string (const char *section
, const char *what
)
419 const char *where
= section
? section
: "global";
422 MUTEX_LOCK (&rcfile_mutex
);
423 val
= config_get_string_param (global_config
, where
, what
, &exists
);
424 if (!exists
&& strcmp (section
? section
: "", "global"))
425 val
= config_get_string_param (global_config
, "global", what
, &exists
);
427 MUTEX_UNLOCK (&rcfile_mutex
);
432 config_get_list (const char *section
, const char *what
)
435 const char *where
= section
? section
: "global";
438 MUTEX_LOCK (&rcfile_mutex
);
439 val
= config_get_list_param (global_config
, where
, what
, &exists
);
440 if (!exists
&& strcmp (section
? section
: "", "global"))
441 val
= config_get_list_param (global_config
, "global", what
, &exists
);
443 MUTEX_UNLOCK (&rcfile_mutex
);
448 config_get_integer (const char *section
, const char *what
)
451 const char *where
= section
? section
: "global";
454 MUTEX_LOCK (&rcfile_mutex
);
455 val
= config_get_int_param (global_config
, where
, what
, &exists
);
456 if (!exists
&& strcmp (section
? section
: "", "global"))
457 val
= config_get_int_param (global_config
, "global", what
, &exists
);
459 MUTEX_UNLOCK (&rcfile_mutex
);
464 config_get_longlong (const char *section
, const char *what
)
467 const char *where
= section
? section
: "global";
470 MUTEX_LOCK (&rcfile_mutex
);
471 val
= config_get_longlong_param (global_config
, where
, what
, &exists
);
472 if (!exists
&& strcmp (section
? section
: "", "global"))
473 val
= config_get_longlong_param (global_config
, "global", what
, &exists
);
475 MUTEX_UNLOCK (&rcfile_mutex
);
480 config_get_ulonglong (const char *section
, const char *what
)
482 unsigned long long val
= 0;
483 const char *where
= section
? section
: "global";
486 MUTEX_LOCK (&rcfile_mutex
);
487 val
= config_get_ulonglong_param (global_config
, where
, what
, &exists
);
488 if (!exists
&& strcmp (section
? section
: "", "global"))
489 val
= config_get_ulonglong_param (global_config
, "global", what
, &exists
);
491 MUTEX_UNLOCK (&rcfile_mutex
);
496 config_get_long (const char *section
, const char *what
)
499 const char *where
= section
? section
: "global";
502 MUTEX_LOCK (&rcfile_mutex
);
503 val
= config_get_long_param (global_config
, where
, what
, &exists
);
504 if (!exists
&& strcmp (section
? section
: "", "global"))
505 val
= config_get_long_param (global_config
, "global", what
, &exists
);
507 MUTEX_UNLOCK (&rcfile_mutex
);
512 config_get_ulong (const char *section
, const char *what
)
514 unsigned long val
= 0;
515 const char *where
= section
? section
: "global";
518 MUTEX_LOCK (&rcfile_mutex
);
519 val
= config_get_ulong_param (global_config
, where
, what
, &exists
);
520 if (!exists
&& strcmp (section
? section
: "", "global"))
521 val
= config_get_ulong_param (global_config
, "global", what
, &exists
);
523 MUTEX_UNLOCK (&rcfile_mutex
);
528 config_get_boolean (const char *section
, const char *what
)
530 return config_get_integer (section
, what
);
534 config_get_value (const char *section
, const char *what
)
536 const char *where
= section
? section
: "global";
543 unsigned long long ullval
;
548 MUTEX_LOCK (&rcfile_mutex
);
550 for (i
= 0; config_params
[i
].name
; i
++)
552 if (!strcmp (config_params
[i
].name
, what
))
554 switch (config_params
[i
].type
)
558 ival
= config_get_int_param (global_config
, where
, what
,
560 if (!exists
&& strcmp (section
? section
: "", "global"))
561 ival
= config_get_int_param (global_config
, "global", what
,
563 result
= str_asprintf ("%i", ival
);
566 cpval
= config_get_string_param (global_config
, where
, what
,
568 if (!exists
&& strcmp (section
? section
: "", "global"))
570 config_get_string_param (global_config
, "global", what
,
575 lval
= config_get_long_param (global_config
, where
, what
,
577 if (!exists
&& strcmp (section
? section
: "", "global"))
578 lval
= config_get_long_param (global_config
, "global", what
,
580 result
= str_asprintf ("%li", lval
);
583 ulval
= config_get_ulong_param (global_config
, where
, what
,
585 if (!exists
&& strcmp (section
? section
: "", "global"))
586 ulval
= config_get_ulong_param (global_config
, "global", what
,
588 result
= str_asprintf ("%lu", ulval
);
591 llval
= config_get_longlong_param (global_config
, where
, what
,
593 if (!exists
&& strcmp (section
? section
: "", "global"))
594 llval
= config_get_longlong_param (global_config
, "global",
596 result
= str_asprintf ("%lli", llval
);
598 case PARAM_ULONGLONG
:
599 ullval
= config_get_ulonglong_param (global_config
, where
, what
,
601 if (!exists
&& strcmp (section
? section
: "", "global"))
602 ullval
= config_get_ulonglong_param (global_config
, "global",
604 result
= str_asprintf ("%llu", ullval
);
607 cppval
= config_get_list_param (global_config
, where
, what
,
609 if (!exists
&& strcmp (section
? section
: "", "global"))
610 cppval
= config_get_list_param (global_config
, "global", what
,
614 result
= strv_join (",", cppval
);
622 MUTEX_UNLOCK (&rcfile_mutex
);
627 set_defaults (struct slist_s
**config
)
634 for (i
= 0; config_params
[i
].name
; i
++)
636 switch (config_params
[i
].type
)
639 config_get_bool_param (*config
, "global", config_params
[i
].name
,
643 if (config_set_bool_param
644 (config
, "global", config_params
[i
].name
,
645 config_params
[i
].value
))
650 config_get_int_param (*config
, "global", config_params
[i
].name
,
654 if (config_set_int_param
655 (config
, "global", config_params
[i
].name
,
656 config_params
[i
].value
))
661 s
= config_get_string_param (*config
, "global",
662 config_params
[i
].name
, &exists
);
664 if (!exists
&& config_params
[i
].value
)
666 if (config_set_string_param (config
, "global",
667 config_params
[i
].name
,
668 config_params
[i
].value
))
673 list
= config_get_list_param (*config
, "global",
674 config_params
[i
].name
, &exists
);
676 if (!exists
&& config_params
[i
].value
)
678 if (config_set_list_param (config
, "global",
679 config_params
[i
].name
,
680 config_params
[i
].value
))
685 config_get_long_param (*config
, "global", config_params
[i
].name
,
689 if (config_set_long_param
690 (config
, "global", config_params
[i
].name
,
691 config_params
[i
].value
))
696 config_get_longlong_param (*config
, "global", config_params
[i
].name
,
700 if (config_set_longlong_param (config
, "global",
701 config_params
[i
].name
,
702 config_params
[i
].value
))
709 list
= config_get_list_param (*config
, "global", "allowed", &exists
);
713 if (config_set_list_param
714 (config
, "global", "allowed", get_username ()))
718 max_recursion_depth
= config_get_int_param (*config
, "global",
719 "recursion_depth", &exists
);
720 disable_list_and_dump
= config_get_bool_param (*config
, "global",
721 "disable_list_and_dump",
725 config_get_bool_param (*config
, "global", "disable_mlockall", &exists
);
733 static struct config_section_s
*
734 config_find_section (struct slist_s
*config
, const char *name
)
736 unsigned i
, t
= slist_length (config
);
738 for (i
= 0; i
< t
; i
++)
740 struct config_section_s
*s
= slist_nth_data (config
, i
);
742 if (!strcmp (s
->name
, name
))
749 /* Append a new parameter to the list of parameters for a file
750 * section. When an existing parameter of the same name exists, its
754 new_param (struct config_section_s
*section
, const char *filename
, int lineno
,
755 const char *name
, const char *value
, int type
)
757 struct config_param_s
*param
= NULL
;
760 unsigned i
, t
= slist_length (section
->params
);
763 for (i
= 0; i
< t
; i
++)
765 struct config_param_s
*p
= slist_nth_data (section
->params
, i
);
769 if (!strcmp (name
, p
->name
))
779 param
= xcalloc (1, sizeof (struct config_param_s
));
782 log_write ("%s", pwmd_strerror (ENOMEM
));
786 param
->name
= str_dup (name
);
790 log_write ("%s", pwmd_strerror (ENOMEM
));
800 if (!strcasecmp (value
, "no") || !strcasecmp (value
, "0")
801 || !strcasecmp (value
, "false"))
802 param
->value
.itype
= 0;
803 else if (!strcasecmp (value
, "yes") || !strcasecmp (value
, "1")
804 || !strcasecmp (value
, "true"))
805 param
->value
.itype
= 1;
808 INVALID_VALUE (filename
, lineno
);
811 param
->type
= PARAM_INT
;
814 xfree (param
->value
.cptype
);
815 param
->value
.cptype
= value
? str_dup (value
) : NULL
;
816 if (value
&& !param
->value
.cptype
)
818 log_write ("%s", pwmd_strerror (ENOMEM
));
823 strv_free (param
->value
.cpptype
);
824 param
->value
.cpptype
= value
? str_split (value
, ",", 0) : NULL
;
825 if (value
&& !param
->value
.cpptype
)
827 log_write ("%s", pwmd_strerror (ENOMEM
));
832 param
->value
.itype
= strtol (value
, &e
, 10);
835 INVALID_VALUE (filename
, lineno
);
840 param
->value
.ltype
= strtol (value
, &e
, 10);
843 INVALID_VALUE (filename
, lineno
);
848 param
->value
.lltype
= strtoll (value
, &e
, 10);
851 INVALID_VALUE (filename
, lineno
);
855 case PARAM_ULONGLONG
:
856 param
->value
.ulltype
= strtoull (value
, &e
, 10);
859 INVALID_VALUE (filename
, lineno
);
864 param
->value
.ultype
= strtoul (value
, &e
, 10);
867 INVALID_VALUE (filename
, lineno
);
876 tmp
= slist_append (section
->params
, param
);
879 log_write ("%s", pwmd_strerror (ENOMEM
));
883 section
->params
= tmp
;
893 config_parse (const char *filename
)
895 struct slist_s
*tmpconfig
= NULL
, *tmp
;
896 struct config_section_s
*cur_section
= NULL
;
901 FILE *fp
= fopen (filename
, "r");
905 log_write ("%s: %s", filename
,
906 pwmd_strerror (gpg_error_from_errno (errno
)));
911 log_write (_("Using defaults!"));
915 for (; (s
= fgets (buf
, sizeof (buf
), fp
)); lineno
++)
917 char line
[LINE_MAX
] = { 0 };
928 /* New file section. */
931 struct config_section_s
*section
;
932 char *p
= strchr (++s
, ']');
936 log_write (_("%s(%i): unbalanced braces"), filename
,
941 len
= strlen (s
) - strlen (p
);
942 memcpy (line
, s
, len
);
945 section
= config_find_section (tmpconfig
, line
);
948 log_write (_("%s(%i): section '%s' already exists!"),
949 filename
, lineno
, line
);
953 if (!strcmp (line
, "global"))
956 section
= xcalloc (1, sizeof (struct config_section_s
));
957 section
->name
= str_dup (line
);
961 tmp
= slist_append (tmpconfig
, cur_section
);
964 log_write ("%s", pwmd_strerror (ENOMEM
));
971 cur_section
= section
;
977 log_write (_("%s(%i): parameter outside of section!"), filename
,
982 /* Parameters for each section. */
983 for (int m
= 0; config_params
[m
].name
; m
++)
985 size_t len
= strlen (config_params
[m
].name
);
987 if (!strncmp (s
, config_params
[m
].name
, len
))
991 while (*p
&& *p
== ' ')
994 if (!*p
|| *p
!= '=')
998 while (*p
&& isspace (*p
))
1002 if (new_param (cur_section
, filename
, lineno
, s
, p
,
1003 config_params
[m
].type
))
1013 log_write (_("%s(%i): unknown parameter"), filename
, lineno
);
1025 tmp
= slist_append (tmpconfig
, cur_section
);
1028 log_write ("%s", pwmd_strerror (ENOMEM
));
1038 ("WARNING: %s: could not find a [global] configuration section!"),
1042 if (set_defaults (&tmpconfig
))
1049 config_free (tmpconfig
);
1050 free_section (cur_section
);
1055 free_section (struct config_section_s
*s
)
1062 struct config_param_s
*p
= slist_nth_data (s
->params
, 0);
1067 section_remove_param (s
, p
->name
);
1076 config_free (struct slist_s
*config
)
1080 struct config_section_s
*s
= slist_nth_data (config
, 0);
1085 config
= slist_remove (config
, s
);