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"
44 #define INVALID_VALUE(file, line) do { \
46 log_write(_("%s(%i): invalid value for parameter."), file, line); \
51 PARAM_INT
, PARAM_CHARP
, PARAM_LONG
, PARAM_LONGLONG
, PARAM_CHARPP
,
52 PARAM_BOOL
, PARAM_ULONG
, PARAM_ULONGLONG
55 static struct config_params_s
61 { "backup", PARAM_BOOL
, "1"},
62 { "socket_path", PARAM_CHARP
, NULL
},
63 { "socket_perms", PARAM_CHARP
, NULL
},
64 { "passphrase", PARAM_CHARP
, NULL
},
65 { "passphrase_file", PARAM_CHARP
, NULL
},
66 { "agent_env_file", PARAM_CHARP
, NULL
},
67 { "log_path", PARAM_CHARP
, "~/.pwmd/log"},
68 { "enable_logging", PARAM_BOOL
, "0"},
69 { "log_level", PARAM_INT
, "0"},
70 { "disable_mlockall", PARAM_BOOL
, "1"},
71 { "cache_timeout", PARAM_INT
, "-1"},
72 { "cache_push", PARAM_CHARPP
, NULL
},
73 { "disable_list_and_dump", PARAM_BOOL
, "0"},
74 { "recursion_depth", PARAM_INT
, "100"},
75 { "syslog", PARAM_BOOL
, "0"},
76 { "xfer_progress", PARAM_INT
, "8196"},
77 { "allowed", PARAM_CHARPP
, NULL
},
78 { "nbits", PARAM_INT
, "2048"},
79 { "algo", PARAM_CHARP
, "rsa"},
80 { "cipher", PARAM_CHARP
, "aes256"},
81 { "kill_scd", PARAM_BOOL
, "0"},
82 { "cipher_iterations", PARAM_ULONGLONG
, "0"},
83 { "cipher_progress", PARAM_LONG
, DEFAULT_ITERATION_PROGRESS
},
84 { "priority", PARAM_INT
, INVALID_PRIORITY
},
85 { "keepalive_interval", PARAM_INT
, "5"},
86 { "tcp_port", PARAM_INT
, "6466"},
87 { "enable_tcp", PARAM_BOOL
, "0"},
88 { "tcp_require_key", PARAM_BOOL
, "0"},
89 { "tcp_wait", PARAM_INT
, "0"},
90 { "tcp_bind", PARAM_CHARP
, "any"},
91 { "tcp_interface", PARAM_CHARP
, NULL
},
92 { "tls_timeout", PARAM_INT
, "300"},
93 { "tls_cipher_suite", PARAM_CHARP
, "SECURE256"},
94 { "tls_access", PARAM_CHARPP
, NULL
},
95 { "pinentry_path", PARAM_CHARP
, PINENTRY_PATH
},
96 { "pinentry_timeout", PARAM_INT
, DEFAULT_PINENTRY_TIMEOUT
},
111 unsigned long ultype
;
112 unsigned long long ulltype
;
119 struct slist_s
*params
;
122 static struct section_s
*config_find_section (struct slist_s
*config
,
124 static int new_param (struct section_s
*section
, const char *filename
,
125 int lineno
, const char *name
, const char *value
,
127 static void free_section (struct section_s
*s
);
128 static int set_defaults (struct slist_s
**config
);
131 section_remove_param (struct section_s
*section
, const char *name
)
133 unsigned i
, t
= slist_length (section
->params
);
135 for (i
= 0; i
< t
; i
++)
137 struct param_s
*p
= slist_nth_data (section
->params
, i
);
142 if (!strcmp (p
->name
, name
))
147 xfree (p
->value
.cptype
);
150 strv_free (p
->value
.cpptype
);
154 section
->params
= slist_remove (section
->params
, p
);
164 MUTEX_LOCK (&rcfile_mutex
);
165 unsigned i
, t
= slist_length (global_config
);
167 for (i
= 0; i
< t
; i
++)
169 struct section_s
*s
= slist_nth_data (global_config
, i
);
173 section_remove_param (s
, "passphrase");
176 MUTEX_UNLOCK (&rcfile_mutex
);
179 static struct param_s
*
180 config_has_param (struct section_s
*s
, const char *what
)
182 unsigned i
, t
= slist_length (s
->params
);
184 for (i
= 0; i
< t
; i
++)
186 struct param_s
*p
= slist_nth_data (s
->params
, i
);
190 if (!strcmp (p
->name
, what
))
197 static struct param_s
*
198 config_get_param (struct slist_s
*config
,
199 const char *section
, const char *what
, int *exists
)
201 unsigned i
, t
= slist_length (config
);
205 for (i
= 0; i
< t
; i
++)
208 struct section_s
*s
= slist_nth_data (config
, i
);
213 if (strcmp (s
->name
, section
))
216 p
= config_has_param (s
, what
);
227 static struct section_s
*
228 new_section (struct slist_s
**config
, const char *name
)
231 struct section_s
*s
= xcalloc (1, sizeof (struct section_s
));
236 s
->name
= str_dup (name
);
239 log_write ("%s", pwmd_strerror (ENOMEM
));
244 tmp
= slist_append (*config
, s
);
247 log_write ("%s", pwmd_strerror (ENOMEM
));
258 config_set_string_param (struct slist_s
**config
, const char *section
,
259 const char *name
, const char *value
)
261 struct section_s
*s
= config_find_section (*config
, section
);
265 s
= new_section (config
, section
);
270 return new_param (s
, NULL
, 0, name
, value
, PARAM_CHARP
);
274 config_get_string_param (struct slist_s
*config
, const char *section
,
275 const char *what
, int *exists
)
277 struct param_s
*p
= config_get_param (config
, section
, what
, exists
);
278 return *exists
&& p
->value
.cptype
? str_dup (p
->value
.cptype
) : NULL
;
282 config_set_int_param (struct slist_s
**config
, const char *section
,
283 const char *name
, const char *value
)
285 struct section_s
*s
= config_find_section (*config
, section
);
289 s
= new_section (config
, section
);
294 return new_param (s
, NULL
, 0, name
, value
, PARAM_INT
);
298 config_get_int_param (struct slist_s
*config
, const char *section
,
299 const char *what
, int *exists
)
301 struct param_s
*p
= config_get_param (config
, section
, what
, exists
);
302 return *exists
? p
->value
.itype
: -1;
306 config_set_bool_param (struct slist_s
**config
, const char *section
,
307 const char *name
, const char *value
)
309 struct section_s
*s
= config_find_section (*config
, section
);
313 s
= new_section (config
, section
);
318 return new_param (s
, NULL
, 0, name
, value
, PARAM_BOOL
);
322 config_get_bool_param (struct slist_s
*config
, const char *section
,
323 const char *what
, int *exists
)
325 return config_get_int_param (config
, section
, what
, exists
);
329 config_set_long_param (struct slist_s
**config
, const char *section
,
330 const char *name
, const char *value
)
332 struct section_s
*s
= config_find_section (*config
, section
);
336 s
= new_section (config
, section
);
341 return new_param (s
, NULL
, 0, name
, value
, PARAM_LONG
);
345 config_get_ulong_param (struct slist_s
*config
, const char *section
,
346 const char *what
, int *exists
)
348 struct param_s
*p
= config_get_param (config
, section
, what
, exists
);
349 return *exists
? p
->value
.ultype
: 0;
353 config_get_long_param (struct slist_s
*config
, const char *section
,
354 const char *what
, int *exists
)
356 struct param_s
*p
= config_get_param (config
, section
, what
, exists
);
357 return *exists
? p
->value
.ltype
: -1;
361 config_set_longlong_param (struct slist_s
**config
, const char *section
,
362 const char *name
, const char *value
)
364 struct section_s
*s
= config_find_section (*config
, section
);
368 s
= new_section (config
, section
);
373 return new_param (s
, NULL
, 0, name
, value
, PARAM_LONGLONG
);
377 config_get_longlong_param (struct slist_s
*config
,
378 const char *section
, const char *what
, int *exists
)
380 struct param_s
*p
= config_get_param (config
, section
, what
, exists
);
381 return *exists
? p
->value
.lltype
: -1;
385 config_get_ulonglong_param (struct slist_s
*config
,
387 const char *what
, int *exists
)
389 struct param_s
*p
= config_get_param (config
, section
, what
, exists
);
390 return *exists
? p
->value
.ulltype
: 0;
394 config_set_list_param (struct slist_s
**config
, const char *section
,
395 const char *name
, const char *value
)
397 struct section_s
*s
= config_find_section (*config
, section
);
401 s
= new_section (config
, section
);
406 return new_param (s
, NULL
, 0, name
, value
, PARAM_CHARPP
);
410 config_get_list_param (struct slist_s
*config
, const char *section
,
411 const char *what
, int *exists
)
413 struct param_s
*p
= config_get_param (config
, section
, what
, exists
);
414 return *exists
&& p
->value
.cpptype
? strv_dup (p
->value
.cpptype
) : NULL
;
418 config_get_string (const char *section
, const char *what
)
421 const char *where
= section
? section
: "global";
424 MUTEX_LOCK (&rcfile_mutex
);
425 val
= config_get_string_param (global_config
, where
, what
, &exists
);
426 if (!exists
&& strcmp (section
? section
: "", "global"))
427 val
= config_get_string_param (global_config
, "global", what
, &exists
);
429 MUTEX_UNLOCK (&rcfile_mutex
);
434 config_get_list (const char *section
, const char *what
)
437 const char *where
= section
? section
: "global";
440 MUTEX_LOCK (&rcfile_mutex
);
441 val
= config_get_list_param (global_config
, where
, what
, &exists
);
442 if (!exists
&& strcmp (section
? section
: "", "global"))
443 val
= config_get_list_param (global_config
, "global", what
, &exists
);
445 MUTEX_UNLOCK (&rcfile_mutex
);
450 config_get_integer (const char *section
, const char *what
)
453 const char *where
= section
? section
: "global";
456 MUTEX_LOCK (&rcfile_mutex
);
457 val
= config_get_int_param (global_config
, where
, what
, &exists
);
458 if (!exists
&& strcmp (section
? section
: "", "global"))
459 val
= config_get_int_param (global_config
, "global", what
, &exists
);
461 MUTEX_UNLOCK (&rcfile_mutex
);
466 config_get_longlong (const char *section
, const char *what
)
469 const char *where
= section
? section
: "global";
472 MUTEX_LOCK (&rcfile_mutex
);
473 val
= config_get_longlong_param (global_config
, where
, what
, &exists
);
474 if (!exists
&& strcmp (section
? section
: "", "global"))
475 val
= config_get_longlong_param (global_config
, "global", what
, &exists
);
477 MUTEX_UNLOCK (&rcfile_mutex
);
482 config_get_ulonglong (const char *section
, const char *what
)
484 unsigned long long val
= 0;
485 const char *where
= section
? section
: "global";
488 MUTEX_LOCK (&rcfile_mutex
);
489 val
= config_get_ulonglong_param (global_config
, where
, what
, &exists
);
490 if (!exists
&& strcmp (section
? section
: "", "global"))
491 val
= config_get_ulonglong_param (global_config
, "global", what
, &exists
);
493 MUTEX_UNLOCK (&rcfile_mutex
);
498 config_get_long (const char *section
, const char *what
)
501 const char *where
= section
? section
: "global";
504 MUTEX_LOCK (&rcfile_mutex
);
505 val
= config_get_long_param (global_config
, where
, what
, &exists
);
506 if (!exists
&& strcmp (section
? section
: "", "global"))
507 val
= config_get_long_param (global_config
, "global", what
, &exists
);
509 MUTEX_UNLOCK (&rcfile_mutex
);
514 config_get_ulong (const char *section
, const char *what
)
516 unsigned long val
= 0;
517 const char *where
= section
? section
: "global";
520 MUTEX_LOCK (&rcfile_mutex
);
521 val
= config_get_ulong_param (global_config
, where
, what
, &exists
);
522 if (!exists
&& strcmp (section
? section
: "", "global"))
523 val
= config_get_ulong_param (global_config
, "global", what
, &exists
);
525 MUTEX_UNLOCK (&rcfile_mutex
);
530 config_get_boolean (const char *section
, const char *what
)
532 return config_get_integer (section
, what
);
536 config_get_value (const char *section
, const char *what
)
538 const char *where
= section
? section
: "global";
545 unsigned long long ullval
;
550 MUTEX_LOCK (&rcfile_mutex
);
552 for (i
= 0; config_params
[i
].name
; i
++)
554 if (!strcmp (config_params
[i
].name
, what
))
556 switch (config_params
[i
].type
)
560 ival
= config_get_int_param (global_config
, where
, what
,
562 if (!exists
&& strcmp (section
? section
: "", "global"))
563 ival
= config_get_int_param (global_config
, "global", what
,
565 result
= str_asprintf ("%i", ival
);
568 cpval
= config_get_string_param (global_config
, where
, what
,
570 if (!exists
&& strcmp (section
? section
: "", "global"))
572 config_get_string_param (global_config
, "global", what
,
577 lval
= config_get_long_param (global_config
, where
, what
,
579 if (!exists
&& strcmp (section
? section
: "", "global"))
580 lval
= config_get_long_param (global_config
, "global", what
,
582 result
= str_asprintf ("%li", lval
);
585 ulval
= config_get_ulong_param (global_config
, where
, what
,
587 if (!exists
&& strcmp (section
? section
: "", "global"))
588 ulval
= config_get_ulong_param (global_config
, "global", what
,
590 result
= str_asprintf ("%lu", ulval
);
593 llval
= config_get_longlong_param (global_config
, where
, what
,
595 if (!exists
&& strcmp (section
? section
: "", "global"))
596 llval
= config_get_longlong_param (global_config
, "global",
598 result
= str_asprintf ("%lli", llval
);
600 case PARAM_ULONGLONG
:
601 ullval
= config_get_ulonglong_param (global_config
, where
, what
,
603 if (!exists
&& strcmp (section
? section
: "", "global"))
604 ullval
= config_get_ulonglong_param (global_config
, "global",
606 result
= str_asprintf ("%llu", ullval
);
609 cppval
= config_get_list_param (global_config
, where
, what
,
611 if (!exists
&& strcmp (section
? section
: "", "global"))
612 cppval
= config_get_list_param (global_config
, "global", what
,
616 result
= strv_join (",", cppval
);
624 MUTEX_UNLOCK (&rcfile_mutex
);
629 set_defaults (struct slist_s
**config
)
636 for (i
= 0; config_params
[i
].name
; i
++)
638 switch (config_params
[i
].type
)
641 config_get_bool_param (*config
, "global", config_params
[i
].name
,
645 if (config_set_bool_param
646 (config
, "global", config_params
[i
].name
,
647 config_params
[i
].value
))
652 config_get_int_param (*config
, "global", config_params
[i
].name
,
656 if (config_set_int_param
657 (config
, "global", config_params
[i
].name
,
658 config_params
[i
].value
))
663 s
= config_get_string_param (*config
, "global",
664 config_params
[i
].name
, &exists
);
666 if (!exists
&& config_params
[i
].value
)
668 if (config_set_string_param (config
, "global",
669 config_params
[i
].name
,
670 config_params
[i
].value
))
675 list
= config_get_list_param (*config
, "global",
676 config_params
[i
].name
, &exists
);
678 if (!exists
&& config_params
[i
].value
)
680 if (config_set_list_param (config
, "global",
681 config_params
[i
].name
,
682 config_params
[i
].value
))
687 config_get_long_param (*config
, "global", config_params
[i
].name
,
691 if (config_set_long_param
692 (config
, "global", config_params
[i
].name
,
693 config_params
[i
].value
))
698 config_get_longlong_param (*config
, "global", config_params
[i
].name
,
702 if (config_set_longlong_param (config
, "global",
703 config_params
[i
].name
,
704 config_params
[i
].value
))
711 list
= config_get_list_param (*config
, "global", "allowed", &exists
);
715 if (config_set_list_param
716 (config
, "global", "allowed", get_username ()))
720 max_recursion_depth
= config_get_int_param (*config
, "global",
721 "recursion_depth", &exists
);
722 disable_list_and_dump
= config_get_bool_param (*config
, "global",
723 "disable_list_and_dump",
727 config_get_bool_param (*config
, "global", "disable_mlockall", &exists
);
735 static struct section_s
*
736 config_find_section (struct slist_s
*config
, const char *name
)
738 unsigned i
, t
= slist_length (config
);
740 for (i
= 0; i
< t
; i
++)
742 struct section_s
*s
= slist_nth_data (config
, i
);
744 if (!strcmp (s
->name
, name
))
751 /* Append a new parameter to the list of parameters for a file
752 * section. When an existing parameter of the same name exists, its
756 new_param (struct section_s
*section
, const char *filename
, int lineno
,
757 const char *name
, const char *value
, int type
)
759 struct param_s
*param
= NULL
;
762 unsigned i
, t
= slist_length (section
->params
);
765 for (i
= 0; i
< t
; i
++)
767 struct param_s
*p
= slist_nth_data (section
->params
, i
);
771 if (!strcmp (name
, p
->name
))
781 param
= xcalloc (1, sizeof (struct param_s
));
784 log_write ("%s", pwmd_strerror (ENOMEM
));
788 param
->name
= str_dup (name
);
792 log_write ("%s", pwmd_strerror (ENOMEM
));
802 if (!strcasecmp (value
, "no") || !strcasecmp (value
, "0")
803 || !strcasecmp (value
, "false"))
804 param
->value
.itype
= 0;
805 else if (!strcasecmp (value
, "yes") || !strcasecmp (value
, "1")
806 || !strcasecmp (value
, "true"))
807 param
->value
.itype
= 1;
810 INVALID_VALUE (filename
, lineno
);
813 param
->type
= PARAM_INT
;
816 xfree (param
->value
.cptype
);
817 param
->value
.cptype
= value
? str_dup (value
) : NULL
;
818 if (value
&& !param
->value
.cptype
)
820 log_write ("%s", pwmd_strerror (ENOMEM
));
825 strv_free (param
->value
.cpptype
);
826 param
->value
.cpptype
= value
? str_split (value
, ",", 0) : NULL
;
827 if (value
&& !param
->value
.cpptype
)
829 log_write ("%s", pwmd_strerror (ENOMEM
));
834 param
->value
.itype
= strtol (value
, &e
, 10);
837 INVALID_VALUE (filename
, lineno
);
842 param
->value
.ltype
= strtol (value
, &e
, 10);
845 INVALID_VALUE (filename
, lineno
);
850 param
->value
.lltype
= strtoll (value
, &e
, 10);
853 INVALID_VALUE (filename
, lineno
);
857 case PARAM_ULONGLONG
:
858 param
->value
.ulltype
= strtoull (value
, &e
, 10);
861 INVALID_VALUE (filename
, lineno
);
866 param
->value
.ultype
= strtoul (value
, &e
, 10);
869 INVALID_VALUE (filename
, lineno
);
878 tmp
= slist_append (section
->params
, param
);
881 log_write ("%s", pwmd_strerror (ENOMEM
));
885 section
->params
= tmp
;
895 config_parse (const char *filename
)
897 struct slist_s
*tmpconfig
= NULL
, *tmp
;
898 struct section_s
*cur_section
= NULL
;
903 FILE *fp
= fopen (filename
, "r");
907 log_write ("%s: %s", filename
,
908 pwmd_strerror (gpg_error_from_syserror ()));
913 log_write (_("Using defaults!"));
917 for (; (s
= fgets (buf
, sizeof (buf
), fp
)); lineno
++)
919 char line
[LINE_MAX
] = { 0 };
930 /* New file section. */
933 struct section_s
*section
;
934 char *p
= strchr (++s
, ']');
938 log_write (_("%s(%i): unbalanced braces"), filename
,
943 len
= strlen (s
) - strlen (p
);
944 memcpy (line
, s
, len
);
947 section
= config_find_section (tmpconfig
, line
);
950 log_write (_("%s(%i): section '%s' already exists!"),
951 filename
, lineno
, line
);
955 if (!strcmp (line
, "global"))
958 section
= xcalloc (1, sizeof (struct section_s
));
959 section
->name
= str_dup (line
);
963 tmp
= slist_append (tmpconfig
, cur_section
);
966 log_write ("%s", pwmd_strerror (ENOMEM
));
973 cur_section
= section
;
979 log_write (_("%s(%i): parameter outside of section!"), filename
,
984 /* Parameters for each section. */
985 for (int m
= 0; config_params
[m
].name
; m
++)
987 size_t len
= strlen (config_params
[m
].name
);
989 if (!strncmp (s
, config_params
[m
].name
, len
))
993 while (*p
&& *p
== ' ')
996 if (!*p
|| *p
!= '=')
1000 while (*p
&& isspace (*p
))
1004 if (new_param (cur_section
, filename
, lineno
, s
, p
,
1005 config_params
[m
].type
))
1015 log_write (_("%s(%i): unknown parameter"), filename
, lineno
);
1027 tmp
= slist_append (tmpconfig
, cur_section
);
1030 log_write ("%s", pwmd_strerror (ENOMEM
));
1040 ("WARNING: %s: could not find a [global] configuration section!"),
1044 if (set_defaults (&tmpconfig
))
1051 config_free (tmpconfig
);
1052 free_section (cur_section
);
1057 free_section (struct section_s
*s
)
1064 struct param_s
*p
= slist_nth_data (s
->params
, 0);
1069 section_remove_param (s
, p
->name
);
1076 config_free (struct slist_s
*config
)
1080 struct section_s
*s
= slist_nth_data (config
, 0);
1085 config
= slist_remove (config
, s
);