Let the COPY command update the _mtime of the destination element path.
[pwmd.git] / src / rcfile.c
blob95595fc6e8e324390dfd9df3090393a7b17da021
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);
81 // Converting.
82 if (crypto->fh && (crypto->fh->v1 || crypto->fh->ver.fh2.version <= 0x213)) {
83 unsigned char *p = crypto->tkey;
84 unsigned i;
86 for (i = 0; i < crypto->tkey_len; i++) {
87 if (p[i] == '\0' || p[i] == '\n')
88 break;
91 if (i != crypto->tkey_len)
92 log_write(N_("%s: warning: key file data truncated at byte %i. Wanted key data length is %i bytes."), file, i, crypto->tkey_len);
94 crypto->tkey_len = i;
97 return rc;
100 gpg_error_t parse_rcfile_keyfile(struct crypto_s *crypto, const gchar *filename,
101 gboolean import)
103 GError *rv = NULL;
104 gchar *t, *file = NULL;
105 gpg_error_t rc = 0;
107 // parse_rcfile_keys()
108 if (import == FALSE) {
109 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
110 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
112 if (!file) {
113 if (rv) {
114 log_write("%s: key_file: %s", rcfile, rv->message);
115 g_clear_error(&rv);
118 return GPG_ERR_ENFILE;
121 t = expand_homedir(file);
123 if (!t) {
124 g_free(file);
125 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
126 return GPG_ERR_ENOMEM;
129 g_free(file);
130 file = t;
133 if (rv) {
134 log_write("%s: key_file: %s", rcfile, rv->message);
136 if (file)
137 g_free(file);
139 g_clear_error(&rv);
140 return GPG_ERR_UNKNOWN_ERRNO;
143 else {
144 /* -I or -C. The filename is a key file. */
145 file = g_strdup(filename);
147 if (!file) {
148 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
149 return GPG_ERR_ENOMEM;
153 if (!file)
154 return GPG_ERR_ENFILE;
156 rc = _getline(crypto, file);
158 if (rc)
159 log_write("%s: %s: %s", filename, file, pwmd_strerror(rc));
161 g_free(file);
162 return rc;
165 gchar *get_key_file_string(const gchar *section, const gchar *what)
167 gchar *val = NULL;
168 GError *grc = NULL;
170 MUTEX_LOCK(&rcfile_mutex);
172 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
173 val = g_key_file_get_string(keyfileh, section, what, &grc);
175 if (grc) {
176 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
177 g_clear_error(&grc);
180 else {
181 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
182 val = g_key_file_get_string(keyfileh, "global", what, &grc);
184 if (grc) {
185 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
186 g_clear_error(&grc);
191 MUTEX_UNLOCK(&rcfile_mutex);
192 return val;
195 gint get_key_file_integer(const gchar *section, const gchar *what)
197 gint val = -1;
198 GError *grc = NULL;
200 MUTEX_LOCK(&rcfile_mutex);
202 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
203 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
205 if (grc) {
206 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
207 g_clear_error(&grc);
210 else {
211 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
212 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
214 if (grc) {
215 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
216 g_clear_error(&grc);
221 MUTEX_UNLOCK(&rcfile_mutex);
222 return val;
225 gdouble get_key_file_double(const gchar *section, const gchar *what)
227 gdouble val = -1;
228 GError *grc = NULL;
230 MUTEX_LOCK(&rcfile_mutex);
232 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
233 val = g_key_file_get_double(keyfileh, section ? section : "global", what, &grc);
235 if (grc) {
236 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
237 g_clear_error(&grc);
240 else {
241 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
242 val = g_key_file_get_double(keyfileh, "global", what, &grc);
244 if (grc) {
245 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
246 g_clear_error(&grc);
251 MUTEX_UNLOCK(&rcfile_mutex);
252 return val;
255 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
257 gboolean val = FALSE;
258 GError *grc = NULL;
260 MUTEX_LOCK(&rcfile_mutex);
262 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL)
263 == TRUE) {
264 val = g_key_file_get_boolean(keyfileh, section ? section : "global",
265 what, &grc);
267 if (grc) {
268 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
269 g_clear_error(&grc);
272 else {
273 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
274 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
276 if (grc) {
277 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
278 g_clear_error(&grc);
283 MUTEX_UNLOCK(&rcfile_mutex);
284 return val;
287 gboolean parse_rcfile_keys()
289 gsize n;
290 gchar **groups;
291 gchar **p;
292 gchar *str;
294 groups = g_key_file_get_groups(keyfileh, &n);
296 for (p = groups; *p; p++) {
297 GError *rv = NULL;
299 if (!strcmp(*p, "global"))
300 continue;
302 if (g_key_file_has_key(keyfileh, *p, "key", &rv) == TRUE) {
303 str = g_key_file_get_string(keyfileh, *p, "key", &rv);
305 if (!str) {
306 if (rv) {
307 log_write("%s: key: %s", rcfile, rv->message);
308 g_clear_error(&rv);
311 continue;
314 do_cache_push(*p, str, strlen(str));
315 g_free(str);
316 continue;
319 if (rv) {
320 log_write("%s: key: %s", rcfile, rv->message);
321 g_clear_error(&rv);
322 continue;
325 struct crypto_s *crypto = init_client_crypto();
326 gpg_error_t rc;
328 if (!crypto)
329 return FALSE;
331 crypto->fh = read_file_header(*p, FALSE, &rc);
333 if (!crypto->fh) {
334 log_write("%s: %s", *p, pwmd_strerror(rc));
335 cleanup_crypto(&crypto);
336 continue;
339 rc = parse_rcfile_keyfile(crypto, *p, FALSE);
341 if (rc) {
342 cleanup_crypto(&crypto);
343 continue;
346 do_cache_push(*p, crypto->tkey, crypto->tkey_len);
347 cleanup_crypto(&crypto);
350 g_strfreev(groups);
351 return TRUE;
354 GKeyFile *parse_rcfile(gboolean specified)
356 GKeyFile *kf = g_key_file_new();
357 GError *rc = NULL;
359 g_key_file_set_list_separator(kf, ',');
361 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
362 log_write("%s: %s", rcfile, rc->message);
364 if (cmdline && specified) {
365 g_clear_error(&rc);
366 return NULL;
369 if (rc->code && rc->code != G_FILE_ERROR_NOENT) {
370 g_clear_error(&rc);
371 return NULL;
375 set_rcfile_defaults(kf);
376 return kf;
379 void setup_logging(GKeyFile *kf)
381 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
383 if (n == TRUE) {
384 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
386 if (*p == '~') {
387 gchar buf[PATH_MAX];
389 p++;
390 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
391 g_free(p);
393 if (logfile)
394 g_free(logfile);
396 logfile = g_strdup(buf);
398 else {
399 if (logfile)
400 g_free(logfile);
402 logfile = p;
406 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
410 * Make sure all settings are set to either the specified setting or a
411 * default.
413 void set_rcfile_defaults(GKeyFile *kf)
415 gchar buf[PATH_MAX];
417 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
418 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
419 g_key_file_set_string(kf, "global", "socket_path", buf);
422 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
423 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
424 g_key_file_set_string(kf, "global", "data_directory", buf);
427 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
428 g_key_file_set_boolean(kf, "global", "backup", TRUE);
430 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
431 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
432 g_key_file_set_string(kf, "global", "log_path", buf);
435 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
436 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
438 #ifdef HAVE_MLOCKALL
439 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
440 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
441 #endif
443 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
444 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
446 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
447 g_key_file_get_double(kf, "global", "iterations", 0) < 0L)
448 g_key_file_set_double(kf, "global", "iterations", 1UL);
450 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
451 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
453 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
454 g_key_file_set_double(kf, "global", "iteration_progress", 1000ULL);
456 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
457 g_key_file_set_integer(kf, "global", "compression_level", 6);
459 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
460 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
462 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
463 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
465 zlib_bufsize = (guint)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
467 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
468 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
470 #ifdef HAVE_MLOCKALL
471 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
472 #endif
474 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
475 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
477 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
478 g_key_file_set_integer(kf, "global", "keepalive", DEFAULT_KEEPALIVE_TO);
480 #ifdef WITH_PINENTRY
481 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
482 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
484 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
485 g_key_file_set_integer(kf, "global", "pinentry_timeout",
486 DEFAULT_PIN_TIMEOUT);
488 if (g_key_file_has_key(kf, "global", "pinentry_path", NULL) == FALSE)
489 g_key_file_set_string(kf, "global", "pinentry_path", PINENTRY_PATH);
490 #endif
492 if (g_key_file_has_key(kf, "global", "xfer_progress", NULL) == FALSE)
493 g_key_file_set_integer(kf, "global", "xfer_progress", 8196);
495 if (g_key_file_has_key(kf, "global", "cipher", NULL) == FALSE)
496 g_key_file_set_string(kf, "global", "cipher", "AES256");
498 if (g_key_file_has_key(kf, "global", "log_level", NULL) == FALSE)
499 g_key_file_set_integer(kf, "global", "log_level", 0);
501 if (!g_key_file_has_key(kf, "global", "allowed", NULL)) {
502 const gchar *users[] = { g_get_user_name(), NULL};
504 g_key_file_set_string_list(kf, "global", "allowed", users, 1);
507 setup_logging(kf);