1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
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
23 #include <sys/types.h>
26 #include <gpg-error.h>
29 #include "pwmd_error.h"
34 gboolean
do_cache_push(const gchar
*filename
, const void *password
, gsize
);
36 void clear_rcfile_keys()
42 groups
= g_key_file_get_groups(keyfileh
, &n
);
44 for (p
= groups
; *p
; p
++) {
47 if (g_key_file_has_key(keyfileh
, *p
, "key", &rc
) == TRUE
)
48 g_key_file_set_string(keyfileh
, *p
, "key", "");
54 static gpg_error_t
_getline(struct crypto_s
*crypto
, const gchar
*file
)
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
);
67 return GPG_ERR_ENOMEM
;
69 fd
= open(file
, O_RDONLY
);
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
;
82 if (crypto
->fh
&& (crypto
->fh
->v1
|| crypto
->fh
->ver
.fh2
.version
<= 0x213)) {
83 unsigned char *p
= crypto
->tkey
;
86 for (i
= 0; i
< crypto
->tkey_len
; i
++) {
87 if (p
[i
] == '\0' || p
[i
] == '\n')
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
);
100 gpg_error_t
parse_rcfile_keyfile(struct crypto_s
*crypto
, const gchar
*filename
,
104 gchar
*t
, *file
= NULL
;
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
);
114 log_write("%s: key_file: %s", rcfile
, rv
->message
);
118 return GPG_ERR_ENFILE
;
121 t
= expand_homedir(file
);
125 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
126 return GPG_ERR_ENOMEM
;
134 log_write("%s: key_file: %s", rcfile
, rv
->message
);
140 return GPG_ERR_UNKNOWN_ERRNO
;
144 /* -I or -C. The filename is a key file. */
145 file
= g_strdup(filename
);
148 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
149 return GPG_ERR_ENOMEM
;
154 return GPG_ERR_ENFILE
;
156 rc
= _getline(crypto
, file
);
159 log_write("%s: %s: %s", filename
, file
, pwmd_strerror(rc
));
165 gchar
*get_key_file_string(const gchar
*section
, const gchar
*what
)
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
);
176 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
181 if (g_key_file_has_key(keyfileh
, "global", what
, NULL
) == TRUE
) {
182 val
= g_key_file_get_string(keyfileh
, "global", what
, &grc
);
185 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
191 MUTEX_UNLOCK(&rcfile_mutex
);
195 gint
get_key_file_integer(const gchar
*section
, const gchar
*what
)
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
);
206 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
211 if (g_key_file_has_key(keyfileh
, "global", what
, NULL
) == TRUE
) {
212 val
= g_key_file_get_integer(keyfileh
, "global", what
, &grc
);
215 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
221 MUTEX_UNLOCK(&rcfile_mutex
);
225 gdouble
get_key_file_double(const gchar
*section
, const gchar
*what
)
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
);
236 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
241 if (g_key_file_has_key(keyfileh
, "global", what
, NULL
) == TRUE
) {
242 val
= g_key_file_get_double(keyfileh
, "global", what
, &grc
);
245 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
251 MUTEX_UNLOCK(&rcfile_mutex
);
255 gboolean
get_key_file_boolean(const gchar
*section
, const gchar
*what
)
257 gboolean val
= FALSE
;
260 MUTEX_LOCK(&rcfile_mutex
);
262 if (g_key_file_has_key(keyfileh
, section
? section
: "global", what
, NULL
)
264 val
= g_key_file_get_boolean(keyfileh
, section
? section
: "global",
268 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
273 if (g_key_file_has_key(keyfileh
, "global", what
, NULL
) == TRUE
) {
274 val
= g_key_file_get_boolean(keyfileh
, "global", what
, &grc
);
277 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
283 MUTEX_UNLOCK(&rcfile_mutex
);
287 gboolean
parse_rcfile_keys()
294 groups
= g_key_file_get_groups(keyfileh
, &n
);
296 for (p
= groups
; *p
; p
++) {
299 if (!strcmp(*p
, "global"))
302 if (g_key_file_has_key(keyfileh
, *p
, "key", &rv
) == TRUE
) {
303 str
= g_key_file_get_string(keyfileh
, *p
, "key", &rv
);
307 log_write("%s: key: %s", rcfile
, rv
->message
);
314 do_cache_push(*p
, str
, strlen(str
));
320 log_write("%s: key: %s", rcfile
, rv
->message
);
325 struct crypto_s
*crypto
= init_client_crypto();
331 crypto
->fh
= read_file_header(*p
, FALSE
, &rc
);
334 log_write("%s: %s", *p
, pwmd_strerror(rc
));
335 cleanup_crypto(&crypto
);
339 rc
= parse_rcfile_keyfile(crypto
, *p
, FALSE
);
342 cleanup_crypto(&crypto
);
346 do_cache_push(*p
, crypto
->tkey
, crypto
->tkey_len
);
347 cleanup_crypto(&crypto
);
354 GKeyFile
*parse_rcfile(gboolean specified
)
356 GKeyFile
*kf
= g_key_file_new();
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
) {
369 if (rc
->code
&& rc
->code
!= G_FILE_ERROR_NOENT
) {
375 set_rcfile_defaults(kf
);
379 void setup_logging(GKeyFile
*kf
)
381 gboolean n
= g_key_file_get_boolean(kf
, "global", "enable_logging", NULL
);
384 gchar
*p
= g_key_file_get_string(kf
, "global", "log_path", NULL
);
390 g_snprintf(buf
, sizeof(buf
), "%s%s", g_get_home_dir(), p
--);
396 logfile
= g_strdup(buf
);
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
413 void set_rcfile_defaults(GKeyFile
*kf
)
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
);
439 if (g_key_file_has_key(kf
, "global", "disable_mlockall", NULL
) == FALSE
)
440 g_key_file_set_boolean(kf
, "global", "disable_mlockall", TRUE
);
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
);
471 disable_mlock
= g_key_file_get_boolean(kf
, "global", "disable_mlockall", NULL
);
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
);
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
);
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);