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/>.
26 #include <sys/types.h>
33 #include "pwmd-error.h"
37 #include "util-misc.h"
39 #include "util-slist.h"
40 #include "util-string.h"
43 #define DEFAULT_PINENTRY_TIMEOUT "30"
44 #define DEFAULT_CACHE_TIMEOUT "600"
45 #define DEFAULT_KEEPALIVE_INTERVAL "60"
46 #define DEFAULT_LOCK_TIMEOUT "50" // MUTEX_TRYLOCK in tenths of a second
48 #define INVALID_VALUE(file, line) do { \
50 log_write(_("%s(%i): invalid value for parameter."), file, line); \
55 PARAM_INT
, PARAM_CHARP
, PARAM_LONG
, PARAM_LONGLONG
, PARAM_CHARPP
,
56 PARAM_BOOL
, PARAM_ULONG
, PARAM_ULONGLONG
59 static struct config_params_s
65 { "backup", PARAM_BOOL
, "true"},
66 { "socket_path", PARAM_CHARP
, NULL
},
67 { "socket_perms", PARAM_CHARP
, NULL
},
68 { "passphrase", PARAM_CHARP
, NULL
},
69 { "passphrase_file", PARAM_CHARP
, NULL
},
70 { "gpg_agent_socket", PARAM_CHARP
, NULL
},
71 { "log_path", PARAM_CHARP
, "~/.pwmd/log"},
72 { "enable_logging", PARAM_BOOL
, "0"},
73 { "log_keepopen", PARAM_BOOL
, "true"},
74 { "log_level", PARAM_INT
, "0"},
75 { "disable_mlockall", PARAM_BOOL
, "true"},
76 { "cache_timeout", PARAM_INT
, DEFAULT_CACHE_TIMEOUT
},
77 { "cache_push", PARAM_CHARPP
, NULL
},
78 { "disable_list_and_dump", PARAM_BOOL
, "false"},
79 { "recursion_depth", PARAM_INT
, "100"},
80 { "syslog", PARAM_BOOL
, "false"},
81 { "xfer_progress", PARAM_INT
, "8196"},
82 { "allowed", PARAM_CHARPP
, NULL
},
83 { "allowed_file", PARAM_CHARP
, NULL
},
84 { "keyparam", PARAM_CHARP
, "(genkey (rsa (nbits 4:2048)))"},
85 { "cipher", PARAM_CHARP
, "aes256"},
86 { "kill_scd", PARAM_BOOL
, "false"},
87 { "cipher_iterations", PARAM_ULONGLONG
, "0"},
88 { "cipher_progress", PARAM_LONG
, DEFAULT_ITERATION_PROGRESS
},
89 { "priority", PARAM_INT
, INVALID_PRIORITY
},
90 { "keepalive_interval", PARAM_INT
, DEFAULT_KEEPALIVE_INTERVAL
},
91 { "tcp_port", PARAM_INT
, "6466"},
92 { "enable_tcp", PARAM_BOOL
, "false"},
93 { "tcp_require_key", PARAM_BOOL
, "false"},
94 { "tcp_wait", PARAM_INT
, "0"},
95 { "tcp_bind", PARAM_CHARP
, "any"},
96 { "tcp_interface", PARAM_CHARP
, NULL
},
97 { "tls_timeout", PARAM_INT
, "300"},
98 { "tls_cipher_suite", PARAM_CHARP
, "SECURE256:SECURE192:SECURE128:-VERS-SSL3.0"},
99 { "tls_dh_level", PARAM_CHARP
, "medium"},
100 { "pinentry_path", PARAM_CHARP
, PINENTRY_PATH
},
101 { "pinentry_timeout", PARAM_INT
, DEFAULT_PINENTRY_TIMEOUT
},
102 { "use_agent", PARAM_BOOL
, "false"},
103 { "require_save_key", PARAM_BOOL
, "true"},
104 { "invoking_user", PARAM_CHARP
, NULL
},
105 { "invoking_tls", PARAM_CHARP
, NULL
},
106 { "lock_timeout", PARAM_INT
, DEFAULT_LOCK_TIMEOUT
},
107 { "send_state", PARAM_INT
, "2"},
111 struct config_param_s
122 unsigned long ultype
;
123 unsigned long long ulltype
;
127 static struct config_section_s
*config_find_section (struct slist_s
*config
,
129 static int new_param (struct config_section_s
*section
, const char *filename
,
130 int lineno
, const char *name
, const char *value
,
132 static void free_section (struct config_section_s
*s
);
133 static int set_defaults (struct slist_s
**config
);
136 section_remove_param (struct config_section_s
*section
, const char *name
)
138 unsigned i
, t
= slist_length (section
->params
);
140 for (i
= 0; i
< t
; i
++)
142 struct config_param_s
*p
= slist_nth_data (section
->params
, i
);
147 if (!strcmp (p
->name
, name
))
152 xfree (p
->value
.cptype
);
155 strv_free (p
->value
.cpptype
);
159 section
->params
= slist_remove (section
->params
, p
);
170 MUTEX_LOCK (&rcfile_mutex
);
171 unsigned i
, t
= slist_length (global_config
);
173 for (i
= 0; i
< t
; i
++)
175 struct config_section_s
*s
= slist_nth_data (global_config
, i
);
179 section_remove_param (s
, "passphrase");
182 MUTEX_UNLOCK (&rcfile_mutex
);
185 static struct config_param_s
*
186 config_has_param (struct config_section_s
*s
, const char *what
)
188 unsigned i
, t
= slist_length (s
->params
);
190 for (i
= 0; i
< t
; i
++)
192 struct config_param_s
*p
= slist_nth_data (s
->params
, i
);
196 if (!strcmp (p
->name
, what
))
203 static struct config_param_s
*
204 config_get_param (struct slist_s
*config
,
205 const char *section
, const char *what
, int *exists
)
207 unsigned i
, t
= slist_length (config
);
211 for (i
= 0; i
< t
; i
++)
213 struct config_param_s
*p
;
214 struct config_section_s
*s
= slist_nth_data (config
, i
);
219 if (strcmp (s
->name
, section
))
222 p
= config_has_param (s
, what
);
233 static struct config_section_s
*
234 new_section (struct slist_s
**config
, const char *name
)
237 struct config_section_s
*s
= xcalloc (1, sizeof (struct config_section_s
));
242 s
->name
= str_dup (name
);
245 log_write ("%s", pwmd_strerror (ENOMEM
));
250 tmp
= slist_append (*config
, s
);
253 log_write ("%s", pwmd_strerror (ENOMEM
));
264 config_set_string_param (struct slist_s
**config
, const char *section
,
265 const char *name
, const char *value
)
267 struct config_section_s
*s
= config_find_section (*config
, section
);
271 s
= new_section (config
, section
);
276 return new_param (s
, NULL
, 0, name
, value
, PARAM_CHARP
);
280 config_get_string_param (struct slist_s
*config
, const char *section
,
281 const char *what
, int *exists
)
283 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
284 return *exists
&& p
->value
.cptype
? str_dup (p
->value
.cptype
) : NULL
;
288 config_set_int_param (struct slist_s
**config
, const char *section
,
289 const char *name
, const char *value
)
291 struct config_section_s
*s
= config_find_section (*config
, section
);
295 s
= new_section (config
, section
);
300 return new_param (s
, NULL
, 0, name
, value
, PARAM_INT
);
304 config_get_int_param (struct slist_s
*config
, const char *section
,
305 const char *what
, int *exists
)
307 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
308 return *exists
? p
->value
.itype
: -1;
312 config_set_bool_param (struct slist_s
**config
, const char *section
,
313 const char *name
, const char *value
)
315 struct config_section_s
*s
= config_find_section (*config
, section
);
319 s
= new_section (config
, section
);
324 return new_param (s
, NULL
, 0, name
, value
, PARAM_BOOL
);
328 config_get_bool_param (struct slist_s
*config
, const char *section
,
329 const char *what
, int *exists
)
331 return config_get_int_param (config
, section
, what
, exists
);
335 config_set_long_param (struct slist_s
**config
, const char *section
,
336 const char *name
, const char *value
)
338 struct config_section_s
*s
= config_find_section (*config
, section
);
342 s
= new_section (config
, section
);
347 return new_param (s
, NULL
, 0, name
, value
, PARAM_LONG
);
351 config_get_ulong_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
.ultype
: 0;
359 config_get_long_param (struct slist_s
*config
, const char *section
,
360 const char *what
, int *exists
)
362 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
363 return *exists
? p
->value
.ltype
: -1;
367 config_set_longlong_param (struct slist_s
**config
, const char *section
,
368 const char *name
, const char *value
)
370 struct config_section_s
*s
= config_find_section (*config
, section
);
374 s
= new_section (config
, section
);
379 return new_param (s
, NULL
, 0, name
, value
, PARAM_LONGLONG
);
383 config_get_longlong_param (struct slist_s
*config
,
384 const char *section
, const char *what
, int *exists
)
386 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
387 return *exists
? p
->value
.lltype
: -1;
391 config_get_ulonglong_param (struct slist_s
*config
,
393 const char *what
, int *exists
)
395 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
396 return *exists
? p
->value
.ulltype
: 0;
400 config_set_list_param (struct slist_s
**config
, const char *section
,
401 const char *name
, const char *value
)
403 struct config_section_s
*s
= config_find_section (*config
, section
);
407 s
= new_section (config
, section
);
412 return new_param (s
, NULL
, 0, name
, value
, PARAM_CHARPP
);
416 config_get_list_param (struct slist_s
*config
, const char *section
,
417 const char *what
, int *exists
)
419 struct config_param_s
*p
= config_get_param (config
, section
, what
, exists
);
420 return *exists
&& p
->value
.cpptype
? strv_dup (p
->value
.cpptype
) : NULL
;
424 config_get_string (const char *section
, const char *what
)
427 const char *where
= section
? section
: "global";
430 MUTEX_LOCK (&rcfile_mutex
);
431 val
= config_get_string_param (global_config
, where
, what
, &exists
);
432 if (!exists
&& strcmp (section
? section
: "", "global"))
433 val
= config_get_string_param (global_config
, "global", what
, &exists
);
435 MUTEX_UNLOCK (&rcfile_mutex
);
440 config_get_list (const char *section
, const char *what
)
443 const char *where
= section
? section
: "global";
446 MUTEX_LOCK (&rcfile_mutex
);
447 val
= config_get_list_param (global_config
, where
, what
, &exists
);
448 if (!exists
&& strcmp (section
? section
: "", "global"))
449 val
= config_get_list_param (global_config
, "global", what
, &exists
);
451 MUTEX_UNLOCK (&rcfile_mutex
);
456 config_get_integer (const char *section
, const char *what
)
459 const char *where
= section
? section
: "global";
462 MUTEX_LOCK (&rcfile_mutex
);
463 val
= config_get_int_param (global_config
, where
, what
, &exists
);
464 if (!exists
&& strcmp (section
? section
: "", "global"))
465 val
= config_get_int_param (global_config
, "global", what
, &exists
);
467 MUTEX_UNLOCK (&rcfile_mutex
);
472 config_get_longlong (const char *section
, const char *what
)
475 const char *where
= section
? section
: "global";
478 MUTEX_LOCK (&rcfile_mutex
);
479 val
= config_get_longlong_param (global_config
, where
, what
, &exists
);
480 if (!exists
&& strcmp (section
? section
: "", "global"))
481 val
= config_get_longlong_param (global_config
, "global", what
, &exists
);
483 MUTEX_UNLOCK (&rcfile_mutex
);
488 config_get_ulonglong (const char *section
, const char *what
)
490 unsigned long long val
= 0;
491 const char *where
= section
? section
: "global";
494 MUTEX_LOCK (&rcfile_mutex
);
495 val
= config_get_ulonglong_param (global_config
, where
, what
, &exists
);
496 if (!exists
&& strcmp (section
? section
: "", "global"))
497 val
= config_get_ulonglong_param (global_config
, "global", what
, &exists
);
499 MUTEX_UNLOCK (&rcfile_mutex
);
504 config_get_long (const char *section
, const char *what
)
507 const char *where
= section
? section
: "global";
510 MUTEX_LOCK (&rcfile_mutex
);
511 val
= config_get_long_param (global_config
, where
, what
, &exists
);
512 if (!exists
&& strcmp (section
? section
: "", "global"))
513 val
= config_get_long_param (global_config
, "global", what
, &exists
);
515 MUTEX_UNLOCK (&rcfile_mutex
);
520 config_get_ulong (const char *section
, const char *what
)
522 unsigned long val
= 0;
523 const char *where
= section
? section
: "global";
526 MUTEX_LOCK (&rcfile_mutex
);
527 val
= config_get_ulong_param (global_config
, where
, what
, &exists
);
528 if (!exists
&& strcmp (section
? section
: "", "global"))
529 val
= config_get_ulong_param (global_config
, "global", what
, &exists
);
531 MUTEX_UNLOCK (&rcfile_mutex
);
536 config_get_boolean (const char *section
, const char *what
)
538 return config_get_integer (section
, what
);
542 config_get_value (const char *section
, const char *what
)
544 const char *where
= section
? section
: "global";
551 unsigned long long ullval
;
556 MUTEX_LOCK (&rcfile_mutex
);
558 for (i
= 0; config_params
[i
].name
; i
++)
560 if (!strcmp (config_params
[i
].name
, what
))
562 switch (config_params
[i
].type
)
566 ival
= config_get_int_param (global_config
, where
, what
,
568 if (!exists
&& strcmp (section
? section
: "", "global"))
569 ival
= config_get_int_param (global_config
, "global", what
,
571 result
= str_asprintf ("%i", ival
);
574 cpval
= config_get_string_param (global_config
, where
, what
,
576 if (!exists
&& strcmp (section
? section
: "", "global"))
578 config_get_string_param (global_config
, "global", what
,
583 lval
= config_get_long_param (global_config
, where
, what
,
585 if (!exists
&& strcmp (section
? section
: "", "global"))
586 lval
= config_get_long_param (global_config
, "global", what
,
588 result
= str_asprintf ("%li", lval
);
591 ulval
= config_get_ulong_param (global_config
, where
, what
,
593 if (!exists
&& strcmp (section
? section
: "", "global"))
594 ulval
= config_get_ulong_param (global_config
, "global", what
,
596 result
= str_asprintf ("%lu", ulval
);
599 llval
= config_get_longlong_param (global_config
, where
, what
,
601 if (!exists
&& strcmp (section
? section
: "", "global"))
602 llval
= config_get_longlong_param (global_config
, "global",
604 result
= str_asprintf ("%lli", llval
);
606 case PARAM_ULONGLONG
:
607 ullval
= config_get_ulonglong_param (global_config
, where
, what
,
609 if (!exists
&& strcmp (section
? section
: "", "global"))
610 ullval
= config_get_ulonglong_param (global_config
, "global",
612 result
= str_asprintf ("%llu", ullval
);
615 cppval
= config_get_list_param (global_config
, where
, what
,
617 if (!exists
&& strcmp (section
? section
: "", "global"))
618 cppval
= config_get_list_param (global_config
, "global", what
,
622 result
= strv_join (",", cppval
);
630 MUTEX_UNLOCK (&rcfile_mutex
);
635 parse_allowed_file (struct slist_s
*config
, const char *section
)
642 char *p
= config_get_string_param (config
, section
, "allowed_file", &exists
);
650 tmp
= expand_homedir (p
);
656 log_write ("%s: %s", p
, strerror (errno
));
662 list
= config_get_list_param (config
, section
, "allowed", &exists
);
666 log_write ("%s", strerror (ENOMEM
));
670 while ((p
= fgets (buf
, sizeof (buf
), fp
)))
674 if (p
[strlen(p
)-1] == '\n')
677 while (*p
&& isspace (*p
))
685 pp
= strv_cat (list
, str_dup (p
));
692 log_write ("%s", strerror (ENOMEM
));
704 p
= strv_join (",", list
);
709 log_write ("%s", strerror (ENOMEM
));
713 config_set_list_param (&config
, section
, "allowed", p
);
718 fixup_allowed_once (struct slist_s
**config
, const char *section
)
720 char **list
, **pp
, *p
;
723 parse_allowed_file (*config
, section
);
724 list
= config_get_list_param (*config
, section
, "allowed", &exists
);
725 for (pp
= list
; pp
&& *pp
; pp
++)
729 for (p
= *pp
; p
&& *p
; p
++)
737 if (!strcmp (section
, "global"))
739 p
= get_username (getuid());
741 if (config_set_list_param (config
, section
, "allowed", p
))
751 list
= config_get_list_param (*config
, "global", "allowed", &exists
);
754 p
= strv_join (",", list
);
756 if (config_set_list_param (config
, section
, "allowed", p
))
771 fixup_allowed (struct slist_s
**config
)
773 int n
, t
= slist_length (*config
);
775 for (n
= 0; n
< t
; n
++)
777 struct config_section_s
*section
;
779 section
= slist_nth_data (*config
, n
);
780 if (fixup_allowed_once (config
, section
->name
))
788 set_defaults (struct slist_s
**config
)
790 char *s
= NULL
, *tmp
;
796 for (i
= 0; config_params
[i
].name
; i
++)
798 switch (config_params
[i
].type
)
801 config_get_bool_param (*config
, "global", config_params
[i
].name
,
805 if (config_set_bool_param
806 (config
, "global", config_params
[i
].name
,
807 config_params
[i
].value
))
812 config_get_int_param (*config
, "global", config_params
[i
].name
,
816 if (config_set_int_param
817 (config
, "global", config_params
[i
].name
,
818 config_params
[i
].value
))
823 s
= config_get_string_param (*config
, "global",
824 config_params
[i
].name
, &exists
);
826 if (!exists
&& config_params
[i
].value
)
828 if (config_set_string_param (config
, "global",
829 config_params
[i
].name
,
830 config_params
[i
].value
))
835 list
= config_get_list_param (*config
, "global",
836 config_params
[i
].name
, &exists
);
838 if (!exists
&& config_params
[i
].value
)
840 if (config_set_list_param (config
, "global",
841 config_params
[i
].name
,
842 config_params
[i
].value
))
847 config_get_long_param (*config
, "global", config_params
[i
].name
,
851 if (config_set_long_param
852 (config
, "global", config_params
[i
].name
,
853 config_params
[i
].value
))
858 config_get_longlong_param (*config
, "global", config_params
[i
].name
,
862 if (config_set_longlong_param (config
, "global",
863 config_params
[i
].name
,
864 config_params
[i
].value
))
872 if (fixup_allowed (config
))
875 max_recursion_depth
= config_get_int_param (*config
, "global",
876 "recursion_depth", &exists
);
877 disable_list_and_dump
= config_get_bool_param (*config
, "global",
878 "disable_list_and_dump",
882 config_get_bool_param (*config
, "global", "disable_mlockall", &exists
);
885 s
= config_get_string_param(*config
, "global", "invoking_user", &exists
);
888 pwd
= getpwuid(getuid());
894 log_write (_("could not set invoking user: user '%s' is invalid"), s
);
899 config_set_string_param(config
, "global", "invoking_user", pwd
->pw_name
);
901 invoking_tls
= config_get_string_param(*config
, "global", "invoking_tls",
903 for (char *p
= invoking_tls
; p
&& *p
; p
++)
906 config_set_string_param(config
, "global", "invoking_tls", invoking_tls
);
908 invoking_uid
= pwd
->pw_uid
;
909 invoking_gid
= pwd
->pw_gid
;
911 s
= config_get_string_param(*config
, "global", "gpg_agent_socket", &exists
);
915 s
= str_asprintf ("%s/.gnupg/S.gpg-agent", get_home_dir());
916 config_set_string_param(config
, "global", "gpg_agent_socket", s
);
920 tmp
= expand_homedir (s
);
921 config_set_string_param(config
, "global", "gpg_agent_socket", tmp
);
933 static struct config_section_s
*
934 config_find_section (struct slist_s
*config
, const char *name
)
936 unsigned i
, t
= slist_length (config
);
938 for (i
= 0; i
< t
; i
++)
940 struct config_section_s
*s
= slist_nth_data (config
, i
);
942 if (!strcmp (s
->name
, name
))
949 /* Append a new parameter to the list of parameters for a file
950 * section. When an existing parameter of the same name exists, its
954 new_param (struct config_section_s
*section
, const char *filename
, int lineno
,
955 const char *name
, const char *value
, int type
)
957 struct config_param_s
*param
= NULL
;
960 unsigned i
, t
= slist_length (section
->params
);
963 for (i
= 0; i
< t
; i
++)
965 struct config_param_s
*p
= slist_nth_data (section
->params
, i
);
969 if (!strcmp (name
, p
->name
))
979 param
= xcalloc (1, sizeof (struct config_param_s
));
982 log_write ("%s", pwmd_strerror (ENOMEM
));
986 param
->name
= str_dup (name
);
990 log_write ("%s", pwmd_strerror (ENOMEM
));
1000 if (!strcasecmp (value
, "no") || !strcasecmp (value
, "0")
1001 || !strcasecmp (value
, "false"))
1002 param
->value
.itype
= 0;
1003 else if (!strcasecmp (value
, "yes") || !strcasecmp (value
, "1")
1004 || !strcasecmp (value
, "true"))
1005 param
->value
.itype
= 1;
1008 INVALID_VALUE (filename
, lineno
);
1011 param
->type
= PARAM_INT
;
1014 xfree (param
->value
.cptype
);
1015 param
->value
.cptype
= NULL
;
1016 param
->value
.cptype
= value
&& *value
? str_dup (value
) : NULL
;
1017 if (value
&& *value
&& !param
->value
.cptype
)
1019 log_write ("%s", pwmd_strerror (ENOMEM
));
1024 strv_free (param
->value
.cpptype
);
1025 param
->value
.cpptype
= NULL
;
1026 param
->value
.cpptype
= value
&& *value
? str_split (value
, ",", 0) : NULL
;
1027 if (value
&& *value
&& !param
->value
.cpptype
)
1029 log_write ("%s", pwmd_strerror (ENOMEM
));
1034 param
->value
.itype
= strtol (value
, &e
, 10);
1037 INVALID_VALUE (filename
, lineno
);
1042 param
->value
.ltype
= strtol (value
, &e
, 10);
1045 INVALID_VALUE (filename
, lineno
);
1049 case PARAM_LONGLONG
:
1050 param
->value
.lltype
= strtoll (value
, &e
, 10);
1053 INVALID_VALUE (filename
, lineno
);
1057 case PARAM_ULONGLONG
:
1058 param
->value
.ulltype
= strtoull (value
, &e
, 10);
1061 INVALID_VALUE (filename
, lineno
);
1066 param
->value
.ultype
= strtoul (value
, &e
, 10);
1069 INVALID_VALUE (filename
, lineno
);
1078 tmp
= slist_append (section
->params
, param
);
1081 log_write ("%s", pwmd_strerror (ENOMEM
));
1085 section
->params
= tmp
;
1089 xfree (param
->name
);
1095 config_parse (const char *filename
)
1097 struct slist_s
*tmpconfig
= NULL
, *tmp
;
1098 struct config_section_s
*cur_section
= NULL
;
1102 int have_global
= 0;
1103 FILE *fp
= fopen (filename
, "r");
1107 log_write ("%s: %s", filename
,
1108 pwmd_strerror (gpg_error_from_errno (errno
)));
1110 if (errno
!= ENOENT
)
1113 log_write (_("Using defaults!"));
1117 for (; (s
= fgets (buf
, sizeof (buf
), fp
)); lineno
++)
1119 char line
[LINE_MAX
] = { 0 };
1126 for (; s
&& *s
; s
++)
1130 /* New file section. */
1133 struct config_section_s
*section
;
1134 char *p
= strchr (++s
, ']');
1138 log_write (_("%s(%i): unbalanced braces"), filename
,
1143 len
= strlen (s
) - strlen (p
);
1144 memcpy (line
, s
, len
);
1147 section
= config_find_section (tmpconfig
, line
);
1150 log_write (_("%s(%i): section '%s' already exists!"),
1151 filename
, lineno
, line
);
1155 if (!strcmp (line
, "global"))
1158 section
= xcalloc (1, sizeof (struct config_section_s
));
1159 section
->name
= str_dup (line
);
1163 tmp
= slist_append (tmpconfig
, cur_section
);
1166 log_write ("%s", pwmd_strerror (ENOMEM
));
1173 cur_section
= section
;
1179 log_write (_("%s(%i): parameter outside of section!"), filename
,
1184 /* Parameters for each section. */
1185 for (int m
= 0; config_params
[m
].name
; m
++)
1187 size_t len
= strlen (config_params
[m
].name
);
1189 if (!strncmp (s
, config_params
[m
].name
, len
))
1193 while (*p
&& *p
== ' ')
1196 if (!*p
|| *p
!= '=')
1200 while (*p
&& isspace (*p
))
1204 if (new_param (cur_section
, filename
, lineno
, s
, p
,
1205 config_params
[m
].type
))
1215 log_write (_("%s(%i): unknown parameter"), filename
, lineno
);
1225 tmp
= slist_append (tmpconfig
, cur_section
);
1228 log_write ("%s", pwmd_strerror (ENOMEM
));
1238 ("WARNING: %s: could not find a [global] configuration section!"),
1243 char *tmp
= config_get_string_param (tmpconfig
, "global", "tls_dh_level",
1247 if (strcasecmp (tmp
, "low") && strcasecmp (tmp
, "medium")
1248 && strcasecmp (tmp
, "high"))
1251 log_write (_("invalid tls_dh_level value"));
1260 if (set_defaults (&tmpconfig
))
1272 config_free (tmpconfig
);
1273 free_section (cur_section
);
1278 free_section (struct config_section_s
*s
)
1285 struct config_param_s
*p
= slist_nth_data (s
->params
, 0);
1290 section_remove_param (s
, p
->name
);
1299 config_free (struct slist_s
*config
)
1303 struct config_section_s
*s
= slist_nth_data (config
, 0);
1308 config
= slist_remove (config
, s
);