Rename client_crypto_s to crypto_s.
[pwmd.git] / src / rcfile.c
blobe00435b3dd3b18844f870a60d71a7e6eba719d24
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006-2010 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <gpg-error.h>
27 #include <errno.h>
28 #include <glib.h>
29 #include "pwmd_error.h"
30 #include "lock.h"
31 #include "common.h"
32 #include "rcfile.h"
34 gboolean do_cache_push(const gchar *filename, const void *password, gsize);
36 void clear_rcfile_keys()
38 gsize n;
39 gchar **groups;
40 gchar **p;
42 groups = g_key_file_get_groups(keyfileh, &n);
44 for (p = groups; *p; p++) {
45 GError *rc = NULL;
47 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE)
48 g_key_file_set_string(keyfileh, *p, "key", "");
51 g_strfreev(groups);
54 static gpg_error_t _getline(struct crypto_s *crypto, const gchar *file)
56 gint fd;
57 struct stat st;
58 gpg_error_t rc = 0;
60 if (stat(file, &st) == -1)
61 return gpg_error_from_errno(errno);
63 crypto->tkey_len = st.st_size;
64 crypto->tkey = gcry_malloc(crypto->tkey_len);
66 if (!crypto->tkey)
67 return GPG_ERR_ENOMEM;
69 fd = open(file, O_RDONLY);
71 if (fd == -1)
72 return gpg_error_from_errno(errno);
74 gsize len = read(fd, crypto->tkey, crypto->tkey_len);
76 if (len != crypto->tkey_len)
77 rc = GPG_ERR_INCOMPLETE_LINE;
79 close(fd);
80 return rc;
83 gpg_error_t parse_rcfile_keyfile(struct crypto_s *crypto, const gchar *filename,
84 gboolean import)
86 GError *rv = NULL;
87 gchar *t, *file = NULL;
88 gpg_error_t rc = 0;
90 // parse_rcfile_keys()
91 if (import == FALSE) {
92 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
93 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
95 if (!file) {
96 if (rv) {
97 log_write("%s: key_file: %s", rcfile, rv->message);
98 g_clear_error(&rv);
101 return GPG_ERR_ENFILE;
104 t = expand_homedir(file);
106 if (!t) {
107 g_free(file);
108 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
109 return GPG_ERR_ENOMEM;
112 g_free(file);
113 file = t;
116 if (rv) {
117 log_write("%s: key_file: %s", rcfile, rv->message);
119 if (file)
120 g_free(file);
122 g_clear_error(&rv);
123 return GPG_ERR_UNKNOWN_ERRNO;
126 else {
127 /* -I or -C. The filename is a key file. */
128 file = g_strdup(filename);
130 if (!file) {
131 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
132 return GPG_ERR_ENOMEM;
136 if (!file)
137 return GPG_ERR_ENFILE;
139 rc = _getline(crypto, file);
141 if (rc)
142 log_write("%s: %s: %s", filename, file, pwmd_strerror(rc));
144 g_free(file);
145 return rc;
148 gchar *get_key_file_string(const gchar *section, const gchar *what)
150 gchar *val = NULL;
151 GError *grc = NULL;
153 MUTEX_LOCK(&rcfile_mutex);
155 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
156 val = g_key_file_get_string(keyfileh, section, what, &grc);
158 if (grc) {
159 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
160 g_clear_error(&grc);
163 else {
164 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
165 val = g_key_file_get_string(keyfileh, "global", what, &grc);
167 if (grc) {
168 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
169 g_clear_error(&grc);
174 MUTEX_UNLOCK(&rcfile_mutex);
175 return val;
178 gint get_key_file_integer(const gchar *section, const gchar *what)
180 gint val = -1;
181 GError *grc = NULL;
183 MUTEX_LOCK(&rcfile_mutex);
185 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
186 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
188 if (grc) {
189 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
190 g_clear_error(&grc);
193 else {
194 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
195 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
197 if (grc) {
198 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
199 g_clear_error(&grc);
204 MUTEX_UNLOCK(&rcfile_mutex);
205 return val;
208 gdouble get_key_file_double(const gchar *section, const gchar *what)
210 gdouble val = -1;
211 GError *grc = NULL;
213 MUTEX_LOCK(&rcfile_mutex);
215 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
216 val = g_key_file_get_double(keyfileh, section ? section : "global", what, &grc);
218 if (grc) {
219 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
220 g_clear_error(&grc);
223 else {
224 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
225 val = g_key_file_get_double(keyfileh, "global", what, &grc);
227 if (grc) {
228 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
229 g_clear_error(&grc);
234 MUTEX_UNLOCK(&rcfile_mutex);
235 return val;
238 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
240 gboolean val = FALSE;
241 GError *grc = NULL;
243 MUTEX_LOCK(&rcfile_mutex);
245 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL)
246 == TRUE) {
247 val = g_key_file_get_boolean(keyfileh, section ? section : "global",
248 what, &grc);
250 if (grc) {
251 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
252 g_clear_error(&grc);
255 else {
256 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
257 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
259 if (grc) {
260 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
261 g_clear_error(&grc);
266 MUTEX_UNLOCK(&rcfile_mutex);
267 return val;
270 gboolean parse_rcfile_keys()
272 gsize n;
273 gchar **groups;
274 gchar **p;
275 gchar *str;
277 groups = g_key_file_get_groups(keyfileh, &n);
279 for (p = groups; *p; p++) {
280 GError *rv = NULL;
282 if (g_key_file_has_key(keyfileh, *p, "key", &rv) == TRUE) {
283 str = g_key_file_get_string(keyfileh, *p, "key", &rv);
285 if (!str) {
286 if (rv) {
287 log_write("%s: key: %s", rcfile, rv->message);
288 g_clear_error(&rv);
291 continue;
294 do_cache_push(*p, str, strlen(str));
295 g_free(str);
296 continue;
299 if (rv) {
300 log_write("%s: key: %s", rcfile, rv->message);
301 g_clear_error(&rv);
302 continue;
305 struct crypto_s *crypto = g_malloc0(sizeof(struct crypto_s));
306 gpg_error_t rc = parse_rcfile_keyfile(crypto, *p, FALSE);
308 if (rc) {
309 cleanup_crypto(&crypto);
310 continue;
313 do_cache_push(*p, crypto->tkey, crypto->tkey_len);
314 cleanup_crypto(&crypto);
317 g_strfreev(groups);
318 return TRUE;
321 GKeyFile *parse_rcfile(gboolean specified)
323 GKeyFile *kf = g_key_file_new();
324 GError *rc = NULL;
326 g_key_file_set_list_separator(kf, ',');
328 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
329 log_write("%s: %s", rcfile, rc->message);
331 if (cmdline && specified) {
332 g_clear_error(&rc);
333 return NULL;
336 if (rc->code && rc->code != G_FILE_ERROR_NOENT) {
337 g_clear_error(&rc);
338 return NULL;
342 set_rcfile_defaults(kf);
343 return kf;
346 void setup_logging(GKeyFile *kf)
348 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
350 if (n == TRUE) {
351 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
353 if (*p == '~') {
354 gchar buf[PATH_MAX];
356 p++;
357 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
358 g_free(p);
360 if (logfile)
361 g_free(logfile);
363 logfile = g_strdup(buf);
365 else {
366 if (logfile)
367 g_free(logfile);
369 logfile = p;
373 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
377 * Make sure all settings are set to either the specified setting or a
378 * default.
380 void set_rcfile_defaults(GKeyFile *kf)
382 gchar buf[PATH_MAX];
384 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
385 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
386 g_key_file_set_string(kf, "global", "socket_path", buf);
389 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
390 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
391 g_key_file_set_string(kf, "global", "data_directory", buf);
394 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
395 g_key_file_set_boolean(kf, "global", "backup", TRUE);
397 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
398 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
399 g_key_file_set_string(kf, "global", "log_path", buf);
402 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
403 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
405 #ifdef HAVE_MLOCKALL
406 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
407 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
408 #endif
410 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
411 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
413 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
414 g_key_file_get_double(kf, "global", "iterations", 0) < 0L)
415 g_key_file_set_double(kf, "global", "iterations", 1UL);
417 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
418 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
420 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
421 g_key_file_set_double(kf, "global", "iteration_progress", 1000ULL);
423 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
424 g_key_file_set_integer(kf, "global", "compression_level", 6);
426 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
427 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
429 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
430 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
432 zlib_bufsize = (guint)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
434 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
435 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
437 #ifdef HAVE_MLOCKALL
438 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
439 #endif
441 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
442 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
444 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
445 g_key_file_set_integer(kf, "global", "keepalive", DEFAULT_KEEPALIVE_TO);
447 #ifdef WITH_PINENTRY
448 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
449 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
451 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
452 g_key_file_set_integer(kf, "global", "pinentry_timeout",
453 DEFAULT_PIN_TIMEOUT);
455 if (g_key_file_has_key(kf, "global", "pinentry_path", NULL) == FALSE)
456 g_key_file_set_string(kf, "global", "pinentry_path", PINENTRY_PATH);
457 #endif
459 if (g_key_file_has_key(kf, "global", "xfer_progress", NULL) == FALSE)
460 g_key_file_set_integer(kf, "global", "xfer_progress", 8196);
462 if (g_key_file_has_key(kf, "global", "cipher", NULL) == FALSE)
463 g_key_file_set_string(kf, "global", "cipher", "AES256");
465 if (g_key_file_has_key(kf, "global", "log_level", NULL) == FALSE)
466 g_key_file_set_integer(kf, "global", "log_level", 0);
468 if (!g_key_file_has_key(kf, "global", "allowed", NULL)) {
469 const gchar *users[] = { g_get_user_name(), NULL};
471 g_key_file_set_string_list(kf, "global", "allowed", users, 1);
474 setup_logging(kf);