Renamed SET parameters: PINENTRY -> ENABLE_PINENTRY,
[pwmd.git] / src / pwmd.c
blobf93590035eb6cbd87373377d31db5074c024e4ef
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006-2009 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 <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <err.h>
27 #include <errno.h>
28 #include <ctype.h>
29 #include <string.h>
30 #include <sys/un.h>
31 #include <signal.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <sys/wait.h>
35 #include <fcntl.h>
36 #include <pwd.h>
37 #include <glib.h>
38 #include <glib/gprintf.h>
39 #include <sys/mman.h>
40 #include <termios.h>
41 #include <assert.h>
42 #include <syslog.h>
43 #include <zlib.h>
44 #include <gcrypt.h>
45 #include <netinet/in.h>
46 #include <arpa/inet.h>
47 #include <netdb.h>
48 #include <sys/time.h>
49 #include <sys/resource.h>
51 #ifdef TM_IN_SYS_TIME
52 #include <sys/time.h>
53 #else
54 #include <time.h>
55 #endif
57 #include "mem.h"
58 #include "xml.h"
59 #include "common.h"
61 #ifdef WITH_PINENTRY
62 #include "pinentry.h"
63 #endif
65 #include "commands.h"
66 #include "pwmd_error.h"
67 #include "cache.h"
68 #include "misc.h"
69 #include "pwmd.h"
70 #include "lock.h"
72 GCRY_THREAD_OPTION_PTH_IMPL;
74 static void clear_rcfile_keys()
76 gsize n;
77 gchar **groups;
78 gchar **p;
80 groups = g_key_file_get_groups(keyfileh, &n);
82 for (p = groups; *p; p++) {
83 GError *rc = NULL;
85 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE)
86 g_key_file_set_string(keyfileh, *p, "key", "");
89 g_strfreev(groups);
92 static void *reload_rcfile_thread(void *arg)
94 gboolean b = disable_list_and_dump;
95 GKeyFile *k;
96 pth_attr_t attr = pth_attr_of(pth_self());
98 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
99 pth_attr_destroy(attr);
100 MUTEX_LOCK(&rcfile_mutex);
101 log_write(N_("reloading configuration file '%s'"), rcfile);
102 k = parse_rcfile(FALSE);
104 if (!k)
105 goto done;
107 g_key_file_free(keyfileh);
108 keyfileh = k;
109 parse_rcfile_keys();
110 clear_rcfile_keys();
111 disable_list_and_dump = b;
112 startStopKeepAlive(FALSE);
113 send_status_all(STATUS_CONFIG);
114 done:
115 MUTEX_UNLOCK(&rcfile_mutex);
116 return NULL;
119 static void reload_rcfile()
121 pth_t tid;
122 pth_attr_t attr = pth_attr_new();
123 gint n;
125 pth_attr_init(attr);
126 pth_attr_set(attr, PTH_ATTR_JOINABLE, 0);
127 tid = pth_spawn(attr, reload_rcfile_thread, NULL);
128 n = errno;
129 pth_attr_destroy(attr);
131 if (!tid)
132 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
133 _gpg_strerror(gpg_error_from_errno(n)));
136 gpg_error_t send_syserror(assuan_context_t ctx, gint e)
138 gpg_error_t n = gpg_error_from_errno(e);
140 return assuan_process_done(ctx, assuan_set_error(ctx, n, _gpg_strerror(n)));
143 gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e)
145 gpg_err_code_t n = gpg_err_code(e);
146 gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n);
147 struct client_s *client = assuan_get_pointer(ctx);
149 if (!e)
150 return assuan_process_done(ctx, 0);
152 if (!ctx) {
153 log_write("%s", pwmd_strerror(e));
154 return e;
157 if (n == EPWMD_LIBXML_ERROR) {
158 xmlErrorPtr xe = client->xml_error;
160 if (!xe)
161 xe = xmlGetLastError();
163 e = assuan_process_done(ctx, assuan_set_error(ctx, code, xe->message));
164 log_write("%s", xe->message);
166 if (xe == client->xml_error)
167 xmlResetError(xe);
168 else
169 xmlResetLastError();
171 client->xml_error = NULL;
172 return e;
175 return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e)));
178 void log_write(const gchar *fmt, ...)
180 gchar *args, *line;
181 va_list ap;
182 struct tm *tm;
183 time_t now;
184 gchar tbuf[21];
185 gint fd = -1;
186 gchar *name;
187 gchar buf[255];
188 pth_t tid = pth_self();
189 pth_attr_t attr;
191 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
192 return;
194 if (!cmdline && logfile) {
195 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
196 warn("%s", logfile);
197 return;
201 va_start(ap, fmt);
203 if (g_vasprintf(&args, fmt, ap) == -1) {
204 if (logfile)
205 close(fd);
207 va_end(ap);
208 return;
211 va_end(ap);
213 if (cmdline) {
214 fprintf(stderr, "%s\n", args);
215 fflush(stderr);
216 g_free(args);
217 return;
220 attr = pth_attr_of(tid);
222 if (pth_attr_get(attr, PTH_ATTR_NAME, &name) == FALSE)
223 name = "unknown";
225 pth_attr_destroy(attr);
226 name = print_fmt(buf, sizeof(buf), "%s(%p): ", name, tid);
228 if (!cmdline && log_syslog == TRUE)
229 syslog(LOG_INFO, "%s%s", name, args);
231 time(&now);
232 tm = localtime(&now);
233 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
234 tbuf[sizeof(tbuf) - 1] = 0;
236 if (args[strlen(args)-1] == '\n')
237 args[strlen(args)-1] = 0;
239 line = g_strdup_printf("%s %i %s%s\n", tbuf, getpid(), name, args);
240 g_free(args);
242 if (!line) {
243 if (logfile)
244 close(fd);
246 return;
249 if (logfile) {
250 pth_write(fd, line, strlen(line));
251 fsync(fd);
252 close(fd);
255 if (isatty(STDERR_FILENO)) {
256 fprintf(stderr, "%s", line);
257 fflush(stderr);
260 g_free(line);
263 static void usage(gchar *pn)
265 g_fprintf(stderr, N_(
266 "Usage: %s [-hvDnP] [-f <rcfile>] [-C <filename>] "
267 "[-I <filename> [-i <iter>]]\n "
268 "[-k <keyfile>] [-o <outfile>] [file1] [...]\n"
269 " -n run as a foreground process\n"
270 " -f load the specified rcfile (~/.pwmd/config)\n"
271 " -C convert a version 1 data file to version 2\n"
272 " -I import an XML file\n"
273 " -i encrypt with the specified number of iterations when importing\n"
274 " (config default in the \"global\" section)\n"
275 " -k obtain the key from the specified file\n"
276 " -o output file for use with the -C and -I options\n"
277 " -D disable use of the LIST and DUMP commands\n"
278 " -P disable pinentry\n"
279 " -v version\n"
280 " -h this help text\n"
281 ), pn);
282 exit(EXIT_FAILURE);
285 static int gcry_SecureCheck(const void *ptr)
287 return 1;
290 static void setup_gcrypt()
292 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
293 gcry_check_version(GCRYPT_VERSION);
295 gcry_set_allocation_handler(xmalloc, xmalloc, gcry_SecureCheck, xrealloc,
296 xfree);
298 if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, NULL,
299 NULL) != 0)
300 errx(EXIT_FAILURE, N_("Required AES cipher not supported by libgcrypt."));
302 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_KEYLEN, NULL, &gcrykeysize);
303 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_BLKLEN, NULL, &gcryblocksize);
306 static gint new_connection(struct client_s *cl)
308 gpg_error_t rc;
309 gchar *ver;
311 rc = assuan_init_socket_server_ext(&cl->ctx, cl->thd->fd, 2);
313 if (rc)
314 goto fail;
316 assuan_set_pointer(cl->ctx, cl);
317 ver = g_strdup_printf("%s", PACKAGE_STRING);
318 assuan_set_hello_line(cl->ctx, ver);
319 g_free(ver);
320 rc = register_commands(cl->ctx);
322 if (rc)
323 goto fail;
325 rc = assuan_accept(cl->ctx);
327 if (rc)
328 goto fail;
330 return 0;
332 fail:
333 log_write("%s", _gpg_strerror(rc));
334 close(cl->thd->fd);
335 cl->thd->fd = -1;
336 return 1;
339 static void xml_error_cb(void *data, xmlErrorPtr e)
341 struct client_s *client = data;
344 * Keep the first reported error as the one to show in the error
345 * description. Reset in send_error().
347 if (client->xml_error)
348 return;
350 xmlCopyError(e, client->xml_error);
353 void close_file_header(file_header_internal_t *fh)
355 if (!fh)
356 return;
358 if (fh->fd != -1 || (cmdline == TRUE && fh->fd != STDOUT_FILENO))
359 close(fh->fd);
361 if (fh->doc)
362 gcry_free(fh->doc);
364 g_free(fh);
367 void cleanup_crypto(struct client_crypto_s **c)
369 struct client_crypto_s *cr = *c;
371 if (!cr)
372 return;
374 if (cr->iv)
375 gcry_free(cr->iv);
377 if (cr->key)
378 gcry_free(cr->key);
380 if (cr->tkey)
381 gcry_free(cr->tkey);
383 if (cr->tkey2)
384 gcry_free(cr->tkey2);
386 if (cr->inbuf)
387 gcry_free(cr->inbuf);
389 if (cr->outbuf)
390 gcry_free(cr->outbuf);
392 close_file_header(cr->fh);
394 if (cr->gh)
395 gcry_cipher_close(cr->gh);
397 g_free(cr);
398 *c = NULL;
402 * This is called after a child_thread terminates. Set with
403 * pth_cleanup_push().
405 static void cleanup_cb(void *arg)
407 struct client_thread_s *cn = arg;
408 struct client_s *cl = cn->cl;
410 MUTEX_LOCK(&cn_mutex);
411 cn_thread_list = g_slist_remove(cn_thread_list, cn);
412 MUTEX_UNLOCK(&cn_mutex);
414 if (cn->msg_tid) {
415 pth_cancel(cn->msg_tid);
416 pth_join(cn->msg_tid, NULL);
419 while (pth_msgport_pending(cn->mp)) {
420 pth_message_t *msg = pth_msgport_get(cn->mp);
422 g_free(msg->m_data);
423 g_free(msg);
426 pth_msgport_destroy(cn->mp);
428 if (!cl)
429 goto done;
431 if (!cl->freed)
432 cleanup_client(cl);
434 if (cl->ctx)
435 assuan_deinit_server(cl->ctx);
436 else if (cl->thd && cl->thd->fd != -1)
437 close(cl->thd->fd);
439 #ifdef WITH_PINENTRY
440 if (cl->pinentry)
441 cleanup_pinentry(cl->pinentry);
442 #endif
444 if (cl->crypto)
445 cleanup_crypto(&cl->crypto);
447 g_free(cl);
448 done:
449 log_write(N_("exiting, fd=%i"), cn->fd);
450 g_free(cn);
451 send_status_all(STATUS_CLIENTS);
455 * Called every time a connection is made from init_new_connection(). This is
456 * the thread entry point.
458 static void *client_thread(void *data)
460 struct client_thread_s *thd = data;
461 struct client_s *cl = g_malloc0(sizeof(struct client_s));
462 gpg_error_t rc;
463 pth_attr_t attr;
464 gint n;
467 * Prevent a race condition with init_new_connection() if this thread
468 * fails (returns) for some reason before init_new_connection() releases
469 * the cn_mutex.
471 MUTEX_LOCK(&cn_mutex);
472 MUTEX_UNLOCK(&cn_mutex);
473 pth_cleanup_push(cleanup_cb, thd);
475 if (!cl) {
476 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
477 goto fail;
480 attr = pth_attr_of(pth_self());
481 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
482 pth_attr_destroy(attr);
483 thd->cl = cl;
484 cl->thd = thd;
486 if (new_connection(cl))
487 goto fail;
489 #ifdef WITH_PINENTRY
490 cl->pinentry = pinentry_init();
492 if (!cl->pinentry) {
493 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
494 goto fail;
496 #endif
498 #ifdef HAVE_MLOCKALL
499 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
500 log_write("mlockall(): %s", strerror(errno));
501 goto fail;
503 #endif
505 //pth_mutex_init(&thd->msg_list_mutex);
506 attr = pth_attr_new();
507 pth_attr_init(attr);
508 pth_attr_set(attr, PTH_ATTR_JOINABLE, TRUE);
509 thd->mp = pth_msgport_create(NULL);
510 thd->msg_tid = pth_spawn(attr, client_msg_thread, thd);
511 n = errno;
512 pth_attr_destroy(attr);
514 if (!thd->msg_tid) {
515 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
516 _gpg_strerror(gpg_error_from_errno(n)));
517 goto fail;
520 pth_yield(thd->msg_tid);
521 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
523 if (rc) {
524 log_write("%s", _gpg_strerror(rc));
525 goto fail;
528 send_status_all(STATUS_CLIENTS);
529 xmlSetStructuredErrorFunc(cl, xml_error_cb);
531 for (;;) {
532 #ifdef WITH_PINENTRY
533 pth_event_t pev = NULL;
534 #endif
535 pth_status_t st, wst;
536 pth_event_t wev = NULL;
537 pth_event_t ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE,
538 cl->thd->fd);
540 #ifdef WITH_PINENTRY
541 if (cl->pinentry->status == PINENTRY_RUNNING) {
542 pev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, cl->pinentry->fd);
543 ev = pth_event_concat(ev, pev, NULL);
545 #endif
547 if (cl->inquire_status == INQUIRE_BUSY) {
548 wev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_WRITEABLE, cl->thd->fd);
549 ev = pth_event_concat(ev, wev, NULL);
552 pth_cleanup_push(cleanup_ev_cb, ev);
553 pth_wait(ev);
554 pth_event_isolate(ev);
555 st = pth_event_status(ev);
556 wst = pth_event_status(wev);
558 if (st == PTH_STATUS_OCCURRED || wst == PTH_STATUS_OCCURRED) {
559 rc = assuan_process_next(cl->ctx);
561 if (rc) {
562 cl->inquire_status = INQUIRE_INIT;
564 if (gpg_err_code(rc) == GPG_ERR_EOF)
565 goto done;
567 log_write("assuan_process_next(): %s", _gpg_strerror(rc));
568 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
570 if (rc) {
571 log_write("assuan_process_done(): %s", _gpg_strerror(rc));
572 goto done;
575 else {
576 #ifdef WITH_PINENTRY
577 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
578 cl->pinentry->status = PINENTRY_RUNNING;
579 #endif
581 switch (cl->inquire_status) {
582 case INQUIRE_BUSY:
583 case INQUIRE_INIT:
584 break;
585 case INQUIRE_DONE:
586 cl->inquire_status = INQUIRE_INIT;
587 rc = assuan_process_done(cl->ctx, 0);
588 break;
593 #ifdef WITH_PINENTRY
594 if (pev)
595 st = pth_event_status(pev);
597 rc = pinentry_iterate(cl,
598 pev && cl->pinentry->fd != -1 && st == PTH_STATUS_OCCURRED);
599 #endif
600 pth_cleanup_pop(1);
604 * Client cleanup (including XML data) is done in cleanup_cb().
606 done:
607 fail:
608 pth_cleanup_pop(1);
609 pth_exit(PTH_CANCELED);
610 return NULL;
613 static void setup_logging(GKeyFile *kf)
615 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
617 if (n == TRUE) {
618 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
620 if (*p == '~') {
621 gchar buf[PATH_MAX];
623 p++;
624 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
625 g_free(p);
627 if (logfile)
628 g_free(logfile);
630 logfile = g_strdup(buf);
632 else {
633 if (logfile)
634 g_free(logfile);
636 logfile = p;
640 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
644 * Make sure all settings are set to either the specified setting or a
645 * default.
647 static void set_rcfile_defaults(GKeyFile *kf)
649 gchar buf[PATH_MAX];
651 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
652 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
653 g_key_file_set_string(kf, "global", "socket_path", buf);
656 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
657 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
658 g_key_file_set_string(kf, "global", "data_directory", buf);
661 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
662 g_key_file_set_boolean(kf, "global", "backup", TRUE);
664 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
665 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
666 g_key_file_set_string(kf, "global", "log_path", buf);
669 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
670 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
672 #ifdef HAVE_MLOCKALL
673 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
674 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
675 #endif
677 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
678 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
680 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
681 g_key_file_get_integer(kf, "global", "iterations", 0) < 0)
682 g_key_file_set_integer(kf, "global", "iterations", 1);
684 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
685 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
687 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
688 g_key_file_set_integer(kf, "global", "iteration_progress", 0);
690 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
691 g_key_file_set_integer(kf, "global", "compression_level", 6);
693 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
694 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
696 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
697 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
699 zlib_bufsize = (uInt)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
701 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
702 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
704 #ifdef HAVE_MLOCKALL
705 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
706 #endif
708 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
709 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
711 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
712 g_key_file_set_integer(kf, "global", "keepalive", DEFAULT_KEEPALIVE_TO);
714 #ifdef WITH_PINENTRY
715 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
716 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
718 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
719 g_key_file_set_integer(kf, "global", "pinentry_timeout",
720 DEFAULT_PIN_TIMEOUT);
722 if (g_key_file_has_key(kf, "global", "pinentry_path", NULL) == FALSE)
723 g_key_file_set_string(kf, "global", "pinentry_path", PINENTRY_PATH);
724 #endif
726 if (g_key_file_has_key(kf, "global", "xfer_progress", NULL) == FALSE)
727 g_key_file_set_integer(kf, "global", "xfer_progress", 8196);
729 setup_logging(kf);
732 static GKeyFile *parse_rcfile(gboolean specified)
734 GKeyFile *kf = g_key_file_new();
735 GError *rc = NULL;
737 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
738 log_write("%s: %s", rcfile, rc->message);
740 if (cmdline && specified) {
741 g_clear_error(&rc);
742 return NULL;
745 if (rc->code == G_FILE_ERROR_NOENT) {
746 g_clear_error(&rc);
747 set_rcfile_defaults(kf);
748 return kf;
751 g_clear_error(&rc);
752 return NULL;
755 set_rcfile_defaults(kf);
756 return kf;
759 static gchar *do_get_password(const gchar *prompt)
761 gchar buf[LINE_MAX] = {0}, *p;
762 struct termios told, tnew;
763 gchar *key;
765 if (tcgetattr(STDIN_FILENO, &told) == -1) {
766 log_write("tcgetattr(): %s", strerror(errno));
767 return NULL;
770 memcpy(&tnew, &told, sizeof(struct termios));
771 tnew.c_lflag &= ~(ECHO);
772 tnew.c_lflag |= ICANON|ECHONL;
774 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
775 log_write("tcsetattr(): %s", strerror(errno));
776 tcsetattr(STDIN_FILENO, TCSANOW, &told);
777 return NULL;
780 fprintf(stderr, "%s", prompt);
782 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
783 tcsetattr(STDIN_FILENO, TCSANOW, &told);
784 return NULL;
787 tcsetattr(STDIN_FILENO, TCSANOW, &told);
788 p[strlen(p) - 1] = 0;
790 if (!buf[0]) {
791 key = gcry_malloc(1);
792 key[0] = 0;
794 else {
795 key = gcry_malloc(strlen(p) + 1);
796 sprintf(key, "%s", p);
799 memset(&buf, 0, sizeof(buf));
800 return key;
803 /* Only used when "enable_pinentry" is "false" or -P. */
804 static gpg_error_t get_input(const gchar *filename,
805 struct client_crypto_s *crypto, guchar *key, pinentry_cmd_t which)
807 gchar *prompt;
809 if (which == PINENTRY_SAVE) {
810 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
811 crypto->tkey = do_get_password(prompt);
812 g_free(prompt);
814 if (!crypto->tkey) {
815 log_write(N_("%s: Skipping file"), filename);
816 return GPG_ERR_BAD_PASSPHRASE;
819 prompt = g_strdup_printf(N_("Repeat passphrase: "));
820 crypto->tkey2 = do_get_password(prompt);
821 g_free(prompt);
823 if (!crypto->tkey2) {
824 log_write(N_("%s: Skipping file"), filename);
825 return GPG_ERR_BAD_PASSPHRASE;
828 if (strcmp(crypto->tkey, crypto->tkey2)) {
829 log_write(N_("%s: Passphrase mismatch"), filename);
830 return EPWMD_BADKEY;
833 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
834 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
835 return 0;
838 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
840 if ((crypto->tkey = do_get_password(prompt)) == NULL) {
841 log_write(N_("%s: Skipping file"), filename);
842 g_free(prompt);
843 return GPG_ERR_BAD_PASSPHRASE;
846 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
847 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
848 g_free(prompt);
849 return 0;
853 * inbuf must have been allocated with gcry_malloc().
855 gpg_error_t export_common(const gchar *filename, struct client_crypto_s *crypto,
856 gpointer inbuf, gulong insize)
858 gpg_error_t rc;
859 gint level, zrc;
860 gulong outsize;
861 gpointer outbuf;
863 level = get_key_file_integer(filename, "compression_level");
865 if (level < 0)
866 level = 0;
868 if (do_compress(NULL, level, inbuf, insize, &outbuf, &outsize, &zrc)
869 == FALSE) {
870 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
873 crypto->inbuf = outbuf;
874 crypto->insize = outsize;
875 rc = do_xml_encrypt(NULL, crypto, filename);
876 return rc;
879 static gpg_error_t get_password(const gchar *filename,
880 struct client_crypto_s *crypto, guchar *md5file, guchar *key,
881 pinentry_cmd_t which)
883 #ifdef WITH_PINENTRY
884 gpg_error_t rc = 0;
886 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
887 == FALSE) {
888 #endif
889 return get_input(filename, crypto, key, which);
890 #ifdef WITH_PINENTRY
892 else {
893 gchar *result = NULL;
894 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
896 pth_mutex_init(&pin->status_mutex);
897 set_pinentry_defaults(pin);
898 pin->which = which;
899 pin->filename = g_strdup(filename);
900 rc = pinentry_getpin(pin, &result);
902 if (rc) {
903 xfree(result);
904 goto done;
907 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, result ? strlen(result) : 1);
908 xfree(result);
909 cleanup_pinentry(pin);
912 done:
913 return rc;
914 #endif
917 static gboolean _getline(const gchar *file, gchar **result, gpg_error_t *rc)
919 FILE *fp;
920 gchar buf[LINE_MAX] = {0}, *p;
921 gchar *str = NULL;
922 gint len;
924 *rc = 0;
926 if ((fp = fopen(file, "r")) == NULL) {
927 *rc = gpg_error_from_syserror();
928 return FALSE;
931 p = fgets(buf, sizeof(buf), fp);
932 fclose(fp);
933 len = strlen(buf);
935 if (len && buf[len - 1] == '\n')
936 buf[--len] = 0;
938 str = gcry_malloc(len + 1);
940 if (!str) {
941 *rc = gpg_error_from_errno(ENOMEM);
942 return FALSE;
945 memcpy(str, buf, len ? len : 1);
946 str[len] = 0;
947 memset(&buf, 0, sizeof(buf));
948 *result = str;
949 return TRUE;
952 static gchar *parse_rcfile_keyfile(const gchar *filename, gboolean import,
953 gpg_error_t *rc)
955 GError *rv = NULL;
956 gchar *t, *file = NULL, *str;
958 *rc = GPG_ERR_UNKNOWN_ERRNO;
960 if (import == FALSE) {
961 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
962 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
964 if (!file) {
965 if (rv) {
966 log_write("%s: key_file: %s", rcfile, rv->message);
967 g_clear_error(&rv);
970 return NULL;
973 t = expand_homedir(file);
975 if (!t) {
976 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
977 *rc = gpg_error_from_errno(ENOMEM);
978 return NULL;
981 g_free(file);
982 file = t;
985 else {
986 /* -I or -C. The filename is a key file. */
987 file = g_strdup(filename);
989 if (!file) {
990 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
991 *rc = gpg_error_from_errno(ENOMEM);
992 return NULL;
996 if (rv) {
997 log_write("%s: key_file: %s", rcfile, rv->message);
998 g_clear_error(&rv);
999 return NULL;
1002 if (!file)
1003 return NULL;
1005 if (_getline(file, &str, rc) == FALSE) {
1006 log_write("%s: %s: %s", filename, file, pwmd_strerror(*rc));
1007 g_free(file);
1008 return NULL;
1011 g_free(file);
1012 *rc = 0;
1013 return str;
1016 static gboolean xml_import(const gchar *filename, const gchar *outfile,
1017 const gchar *keyfile, guint64 iter)
1019 xmlDocPtr doc;
1020 gint fd;
1021 struct stat st;
1022 gint len;
1023 xmlChar *xmlbuf;
1024 xmlChar *xml;
1025 gpg_error_t rc;
1026 struct client_crypto_s *crypto;
1028 if (stat(filename, &st) == -1) {
1029 log_write("%s: %s", filename, strerror(errno));
1030 return FALSE;
1033 crypto = init_client_crypto();
1035 if (!crypto)
1036 return FALSE;
1038 crypto->key = gcry_malloc(gcrykeysize);
1039 memset(crypto->key, 0, gcrykeysize);
1041 if (!crypto->key) {
1042 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1043 goto fail;
1046 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
1047 filename, outfile);
1049 if (iter && keyfile) {
1050 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1052 if (!crypto->tkey)
1053 goto fail;
1055 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1056 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1058 else if (iter) {
1059 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
1061 if (rc)
1062 goto fail;
1065 if ((fd = open(filename, O_RDONLY)) == -1) {
1066 log_write("%s: %s", filename, strerror(errno));
1067 goto fail;
1070 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
1071 close(fd);
1072 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1073 goto fail;
1076 if (pth_read(fd, xmlbuf, st.st_size) == -1) {
1077 rc = errno;
1078 close(fd);
1079 errno = rc;
1080 log_write("%s: %s", filename, strerror(errno));
1081 goto fail;
1084 close(fd);
1085 xmlbuf[st.st_size] = 0;
1088 * Make sure the document validates.
1090 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
1091 log_write("xmlReadDoc() failed");
1092 gcry_free(xmlbuf);
1093 goto fail;
1096 gcry_free(xmlbuf);
1097 xmlDocDumpMemory(doc, &xml, &len);
1098 xmlFreeDoc(doc);
1100 if (!iter)
1101 memset(crypto->key, '!', gcrykeysize);
1103 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
1105 if (!crypto->fh) {
1106 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1107 goto fail;
1110 crypto->fh->fh2.iter = iter;
1111 rc = export_common(outfile, crypto, xml, len);
1112 xmlFree(xml);
1114 if (rc) {
1115 send_error(NULL, rc);
1116 goto fail;
1119 cleanup_crypto(&crypto);
1120 return TRUE;
1122 fail:
1123 cleanup_crypto(&crypto);
1124 return FALSE;
1127 gchar *get_key_file_string(const gchar *section, const gchar *what)
1129 gchar *val = NULL;
1130 GError *grc = NULL;
1132 MUTEX_LOCK(&rcfile_mutex);
1134 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1135 val = g_key_file_get_string(keyfileh, section, what, &grc);
1137 if (grc) {
1138 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1139 g_clear_error(&grc);
1142 else {
1143 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1144 val = g_key_file_get_string(keyfileh, "global", what, &grc);
1146 if (grc) {
1147 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1148 g_clear_error(&grc);
1153 MUTEX_UNLOCK(&rcfile_mutex);
1154 return val;
1157 gint get_key_file_integer(const gchar *section, const gchar *what)
1159 gint val = -1;
1160 GError *grc = NULL;
1162 MUTEX_LOCK(&rcfile_mutex);
1164 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
1165 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
1167 if (grc) {
1168 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1169 g_clear_error(&grc);
1172 else {
1173 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1174 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
1176 if (grc) {
1177 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1178 g_clear_error(&grc);
1183 MUTEX_UNLOCK(&rcfile_mutex);
1184 return val;
1187 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
1189 gboolean val = FALSE;
1190 GError *grc = NULL;
1192 MUTEX_LOCK(&rcfile_mutex);
1194 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL)
1195 == TRUE) {
1196 val = g_key_file_get_boolean(keyfileh, section ? section : "global",
1197 what, &grc);
1199 if (grc) {
1200 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1201 g_clear_error(&grc);
1204 else {
1205 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1206 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
1208 if (grc) {
1209 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1210 g_clear_error(&grc);
1215 MUTEX_UNLOCK(&rcfile_mutex);
1216 return val;
1219 static gboolean parse_rcfile_keys()
1221 gsize n;
1222 gchar **groups;
1223 gchar **p;
1224 gchar *str;
1226 groups = g_key_file_get_groups(keyfileh, &n);
1228 for (p = groups; *p; p++) {
1229 GError *rc = NULL;
1231 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE) {
1232 str = g_key_file_get_string(keyfileh, *p, "key", &rc);
1234 if (!str) {
1235 if (rc) {
1236 log_write("%s: key: %s", rcfile, rc->message);
1237 g_clear_error(&rc);
1239 continue;
1242 do_cache_push(*p, str);
1243 g_free(str);
1244 continue;
1247 if (rc) {
1248 log_write("%s: key: %s", rcfile, rc->message);
1249 g_clear_error(&rc);
1250 continue;
1253 gpg_error_t ret;
1254 str = parse_rcfile_keyfile(*p, FALSE, &ret);
1256 if (!str)
1257 continue;
1259 do_cache_push(*p, str);
1260 gcry_free(str);
1263 g_strfreev(groups);
1264 return TRUE;
1267 static gboolean do_cache_push(const gchar *filename, const gchar *password)
1269 guchar md5file[16];
1270 gint timeout;
1271 const gchar *p = filename;
1272 struct client_crypto_s *crypto;
1273 gpg_error_t rc;
1275 while (isspace(*p))
1276 p++;
1278 if (!*p)
1279 return FALSE;
1281 if (valid_filename(p) == FALSE) {
1282 log_write(N_("%s: Invalid characters in filename"), p);
1283 return FALSE;
1286 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1288 if (access(p, R_OK|W_OK) != 0) {
1289 log_write("%s: %s", p, strerror(errno));
1290 return FALSE;
1293 crypto = init_client_crypto();
1295 if (!crypto)
1296 return FALSE;
1298 crypto->fh = read_file_header(filename, FALSE, &rc);
1300 if (!crypto->fh) {
1301 log_write("%s: %s", p, pwmd_strerror(rc));
1302 cleanup_crypto(&crypto);
1303 return FALSE;
1306 crypto->key = gcry_malloc(gcrykeysize);
1308 if (!crypto->key) {
1309 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1310 cleanup_crypto(&crypto);
1311 return FALSE;
1314 log_write(N_("Adding '%s' to the file cache ..."), filename);
1316 if (crypto->fh->fh2.iter <= 0) {
1317 memset(crypto->key, '!', gcrykeysize);
1318 goto try_decrypt;
1321 if (!password) {
1322 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1324 if (rc) {
1325 send_error(NULL, rc);
1326 cleanup_crypto(&crypto);
1327 return FALSE;
1330 gcry_free(crypto->fh->doc);
1331 crypto->fh->doc = NULL;
1333 else
1334 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password,
1335 strlen(password) ? strlen(password) : 1);
1337 try_decrypt:
1338 rc = try_xml_decrypt(NULL, crypto->key, crypto, NULL, NULL);
1340 if (rc) {
1341 log_write("%s: %s", filename, pwmd_strerror(rc));
1342 cleanup_crypto(&crypto);
1343 return FALSE;
1346 if (cache_update_key(md5file, crypto->key) == FALSE) {
1347 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1348 cleanup_crypto(&crypto);
1349 return FALSE;
1352 timeout = get_key_file_integer(p, "cache_timeout");
1353 cache_set_timeout(md5file, timeout);
1354 log_write(N_("File '%s' now cached"), filename);
1355 cleanup_crypto(&crypto);
1356 return TRUE;
1359 static void init_new_connection(gint fd)
1361 pth_attr_t attr;
1362 struct client_thread_s *new;
1363 gint n;
1365 new = g_malloc0(sizeof(struct client_thread_s));
1367 if (!new) {
1368 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1369 close(fd);
1370 return;
1373 MUTEX_LOCK(&cn_mutex);
1374 new->fd = fd;
1375 attr = pth_attr_new();
1376 pth_attr_init(attr);
1377 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1378 new->tid = pth_spawn(attr, client_thread, new);
1379 n = errno;
1380 pth_attr_destroy(attr);
1382 if (!new->tid) {
1383 g_free(new);
1384 close(fd);
1385 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1386 _gpg_strerror(gpg_error_from_errno(n)));
1387 MUTEX_UNLOCK(&cn_mutex);
1388 return;
1391 cn_thread_list = g_slist_append(cn_thread_list, new);
1392 MUTEX_UNLOCK(&cn_mutex);
1393 log_write(N_("new connection: tid=%p, fd=%i"), new->tid, fd);
1396 static void *accept_thread(void *arg)
1398 gint sockfd = (gint)arg;
1399 pth_attr_t attr = pth_attr_of(pth_self());
1401 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1402 pth_attr_destroy(attr);
1404 for (;;) {
1405 socklen_t slen = sizeof(struct sockaddr_un);
1406 struct sockaddr_un raddr;
1407 gint fd = -1;
1409 fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen);
1411 if (fd == -1) {
1412 if (errno != EAGAIN) {
1413 if (!quit) // probably EBADF
1414 log_write("accept(): %s", strerror(errno));
1416 break;
1419 continue;
1422 init_new_connection(fd);
1425 /* Just in case accept() failed for some reason other than EBADF */
1426 quit = 1;
1427 pth_exit(PTH_CANCELED);
1428 return NULL;
1431 static void *adjust_cache_timer_thread(void *arg)
1433 pth_attr_t attr = pth_attr_of(pth_self());
1435 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1436 pth_attr_destroy(attr);
1438 for (;;) {
1439 pth_sleep(1);
1440 CACHE_LOCK(NULL);
1441 cache_adjust_timer();
1442 CACHE_UNLOCK;
1445 return NULL;
1448 void cleanup_mutex_cb(void *arg)
1450 pth_mutex_t *m = arg;
1452 pth_mutex_release(m);
1455 void cleanup_ev_cb(void *arg)
1457 pth_event_t ev = arg;
1459 pth_event_free(ev, PTH_FREE_ALL);
1462 static void *keepalive_thread(void *arg)
1464 gint to = (gint)arg;
1465 pth_attr_t attr = pth_attr_of(pth_self());
1467 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1468 pth_attr_destroy(attr);
1470 for (;;) {
1471 pth_event_t ev = pth_event(PTH_EVENT_TIME, pth_timeout(to, 0));
1473 pth_cleanup_push(cleanup_ev_cb, ev);
1474 pth_wait(ev);
1475 send_status_all(STATUS_KEEPALIVE);
1476 pth_cleanup_pop(1);
1479 return NULL;
1482 static void startStopKeepAlive(gboolean term)
1484 gint n = get_key_file_integer("global", "keepalive");
1486 if (keepalive_tid)
1487 pth_cancel(keepalive_tid);
1489 keepalive_tid = NULL;
1491 if (term)
1492 return;
1494 if (n > 0) {
1495 gint e;
1496 pth_attr_t attr = pth_attr_new();
1498 pth_attr_init(attr);
1499 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1500 keepalive_tid = pth_spawn(attr, keepalive_thread, (void *)n);
1501 e = errno;
1502 pth_attr_destroy(attr);
1504 if (!keepalive_tid) {
1505 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1506 _gpg_strerror(gpg_error_from_errno(e)));
1507 return;
1510 pth_yield(keepalive_tid);
1514 static gboolean waiting_for_exit()
1516 guint i, t;
1517 pth_event_t evs = NULL;
1519 MUTEX_LOCK(&cn_mutex);
1521 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
1522 struct client_thread_s *thd = g_slist_nth_data(cn_thread_list, i);
1523 pth_event_t ev = pth_event(PTH_EVENT_TID|PTH_UNTIL_TID_DEAD, thd->tid);
1525 if (evs)
1526 evs = pth_event_concat(evs, ev, NULL);
1527 else
1528 evs = ev;
1531 MUTEX_UNLOCK(&cn_mutex);
1533 if (!evs)
1534 return FALSE;
1536 pth_wait(evs);
1537 MUTEX_LOCK(&cn_mutex);
1538 i = g_slist_length(cn_thread_list);
1539 MUTEX_UNLOCK(&cn_mutex);
1540 pth_event_free(evs, PTH_FREE_ALL);
1541 return i ? TRUE : FALSE;
1544 static void server_loop(gint sockfd, gchar **socketpath)
1546 pth_t accept_tid;
1547 guint n;
1548 sigset_t sigset;
1549 pth_attr_t attr;
1550 pth_t cache_timeout_tid;
1552 sigemptyset(&sigset);
1554 /* Termination */
1555 sigaddset(&sigset, SIGTERM);
1556 sigaddset(&sigset, SIGINT);
1558 /* Clears the file cache. */
1559 sigaddset(&sigset, SIGUSR1);
1561 /* Configuration file reloading. */
1562 sigaddset(&sigset, SIGHUP);
1564 /* Clears the cache and exits when something bad happens. */
1565 sigaddset(&sigset, SIGABRT);
1567 /* Ignored everywhere. When a client disconnects abnormally this signal
1568 * gets raised. It isn't needed though because client_thread() will check
1569 * for rcs even after the client disconnects. */
1570 signal(SIGPIPE, SIG_IGN);
1571 sigprocmask(SIG_BLOCK, &sigset, NULL);
1573 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1574 log_write(N_("Listening on %s"), *socketpath);
1575 attr = pth_attr_new();
1576 pth_attr_init(attr);
1577 accept_tid = pth_spawn(attr, accept_thread, (void *)sockfd);
1579 if (!accept_tid) {
1580 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1581 _gpg_strerror(gpg_error_from_errno(errno)));
1582 pth_attr_destroy(attr);
1583 goto done;
1586 pth_yield(accept_tid);
1587 startStopKeepAlive(FALSE);
1588 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1589 cache_timeout_tid = pth_spawn(attr, adjust_cache_timer_thread, NULL);
1591 if (!cache_timeout_tid) {
1592 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1593 _gpg_strerror(gpg_error_from_errno(errno)));
1594 pth_attr_destroy(attr);
1595 goto done;
1598 pth_yield(cache_timeout_tid);
1599 pth_attr_destroy(attr);
1601 do {
1602 gint sig;
1604 pth_sigwait(&sigset, &sig);
1605 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1607 /* Caught a signal. */
1608 switch (sig) {
1609 case SIGHUP:
1610 reload_rcfile();
1611 break;
1612 case SIGABRT:
1613 cache_clear(NULL, 2);
1614 #ifndef MEM_DEBUG
1615 xpanic();
1616 #endif
1617 exit(EXIT_FAILURE);
1618 case SIGUSR1:
1619 CACHE_LOCK(NULL);
1620 log_write(N_("clearing file cache"));
1621 cache_clear(NULL, 2);
1622 CACHE_UNLOCK;
1623 break;
1624 default:
1625 quit = 1;
1626 break;
1628 } while (!quit);
1630 done:
1632 * We're out of the main server loop. This happens when a signal was sent
1633 * to terminate the daemon. We'll wait for all clients to disconnect
1634 * before exiting and ignore any following signals.
1636 shutdown(sockfd, SHUT_RDWR);
1637 close(sockfd);
1638 pth_cancel(accept_tid);
1639 pth_join(accept_tid, NULL);
1640 unlink(*socketpath);
1641 g_free(*socketpath);
1642 *socketpath = NULL;
1643 MUTEX_LOCK(&cn_mutex);
1644 n = g_slist_length(cn_thread_list);
1645 MUTEX_UNLOCK(&cn_mutex);
1647 if (n) {
1648 log_write(N_("waiting for all clients to disconnect"));
1650 do {
1651 MUTEX_LOCK(&cn_mutex);
1652 n = g_slist_length(cn_thread_list);
1653 MUTEX_UNLOCK(&cn_mutex);
1654 log_write(N_("%i clients remain"), n);
1655 } while (waiting_for_exit());
1658 startStopKeepAlive(TRUE);
1659 pth_cancel(cache_timeout_tid);
1660 cache_free();
1664 * Only called from pinentry_fork() in the child process.
1666 void free_client_list()
1668 gint i, t = g_slist_length(cn_thread_list);
1670 for (i = 0; i < t; i++) {
1671 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1673 free_client(cn->cl);
1676 cache_free();
1679 struct client_crypto_s *init_client_crypto()
1681 struct client_crypto_s *new = g_malloc0(sizeof(struct client_crypto_s));
1682 gpg_error_t rc;
1684 if (!new) {
1685 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1686 return NULL;
1689 rc = gcry_cipher_open(&new->gh, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
1691 if (rc) {
1692 log_write("%s(%i): %s", __FUNCTION__, __LINE__, _gpg_strerror(rc));
1693 g_free(new);
1694 return NULL;
1697 return new;
1700 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
1701 const gchar *outfile)
1703 gpg_error_t rc;
1704 guchar md5file[16];
1705 guint64 iter;
1706 struct client_crypto_s *crypto = init_client_crypto();
1708 if (!crypto)
1709 return GPG_ERR_ENOMEM;
1711 crypto->key = gcry_malloc(gcrykeysize);
1713 if (!crypto->key) {
1714 cleanup_crypto(&crypto);
1715 return GPG_ERR_ENOMEM;
1718 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
1719 filename);
1720 crypto->fh = read_file_header(filename, TRUE, &rc);
1722 if (!crypto->fh)
1723 goto done;
1725 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
1727 /* The header in version 1 had a bug where the iterations were off-by-one.
1728 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
1729 * header.
1731 if (crypto->fh->fh1.iter >= 0) {
1732 if (keyfile) {
1733 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1735 if (!crypto->tkey)
1736 goto done;
1738 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1739 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1741 else {
1742 rc = get_password(filename, crypto, md5file, crypto->key,
1743 PINENTRY_OPEN);
1745 if (rc)
1746 goto done;
1750 rc = try_xml_decrypt(NULL, crypto->key, crypto, &crypto->fh->doc,
1751 &crypto->fh->len);
1753 if (rc)
1754 goto done;
1756 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
1758 if (rc) {
1759 log_write("%s: %s", filename, pwmd_strerror(rc));
1760 goto done;
1763 crypto->fh->v1 = FALSE;
1764 iter = crypto->fh->fh1.iter;
1765 memset(&crypto->fh->fh2, 0, sizeof(crypto->fh->fh2));
1766 /* Keep the iterations and key from the original file. */
1767 crypto->fh->fh2.iter = iter+1; // Bugfix for v1 data files.
1768 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
1770 done:
1771 if (rc)
1772 send_error(NULL, rc);
1774 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
1775 cleanup_crypto(&crypto);
1776 return rc;
1779 int main(int argc, char *argv[])
1781 gint opt;
1782 struct sockaddr_un addr;
1783 gchar buf[PATH_MAX];
1784 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
1785 gchar *socketarg = NULL;
1786 gchar *datadir = NULL;
1787 gboolean n;
1788 gint x;
1789 gchar *p;
1790 gchar **cache_push = NULL;
1791 gchar *import = NULL, *keyfile = NULL;
1792 guint64 cmd_iterations = -1;
1793 gint default_timeout;
1794 gboolean rcfile_spec = FALSE;
1795 gint estatus = EXIT_FAILURE;
1796 gint sockfd;
1797 gchar *outfile = NULL;
1798 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
1799 gint do_unlink = 1;
1800 gboolean secure = FALSE;
1801 gint background = 1;
1802 gchar *convert = NULL;
1803 #ifdef WITH_PINENTRY
1804 gboolean disable_pinentry = FALSE;
1805 #endif
1806 #if 0
1807 #ifndef DEBUG
1808 #ifdef HAVE_SETRLIMIT
1809 struct rlimit rl;
1811 rl.rlim_cur = rl.rlim_max = 0;
1813 if (setrlimit(RLIMIT_CORE, &rl) != 0)
1814 err(EXIT_FAILURE, "setrlimit()");
1815 #endif
1816 #endif
1817 #endif
1819 #ifdef ENABLE_NLS
1820 setlocale(LC_ALL, "");
1821 bindtextdomain("pwmd", LOCALEDIR);
1822 textdomain("pwmd");
1823 #endif
1825 #ifndef MEM_DEBUG
1826 xmem_init();
1827 #endif
1828 setup_gcrypt();
1829 gpg_err_init();
1830 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
1831 g_mem_set_vtable(&mtable);
1832 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
1833 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
1834 xmlInitMemory();
1835 xmlInitGlobals();
1836 xmlInitParser();
1837 xmlXPathInit();
1838 g_snprintf(buf, sizeof(buf), "%s/.pwmd", g_get_home_dir());
1840 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
1841 err(EXIT_FAILURE, "%s", buf);
1843 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", g_get_home_dir());
1845 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
1846 err(EXIT_FAILURE, "%s", buf);
1848 cmdline = TRUE;
1850 while ((opt = getopt(argc, argv, "Po:C:nI:i:k:hvf:D")) != EOF) {
1851 switch (opt) {
1852 #ifdef WITH_PINENTRY
1853 case 'P':
1854 disable_pinentry = TRUE;
1855 break;
1856 #endif
1857 case 'o':
1858 outfile = optarg;
1859 break;
1860 case 'C':
1861 convert = optarg;
1862 break;
1863 case 'n':
1864 background = 0;
1865 break;
1866 case 'D':
1867 secure = TRUE;
1868 break;
1869 case 'I':
1870 import = optarg;
1871 break;
1872 case 'i':
1873 cmd_iterations = strtol(optarg, NULL, 10);
1874 break;
1875 case 'k':
1876 keyfile = optarg;
1877 break;
1878 case 'f':
1879 rcfile = g_strdup(optarg);
1880 rcfile_spec = TRUE;
1881 break;
1882 case 'v':
1883 printf(N_("%s\nCopyright (c) %s\nReleased under the terms of the GPL v2. Use at your own risk.\n\nCompile time features:\n%s"), PACKAGE_STRING,
1884 PACKAGE_BUGREPORT,
1885 #ifdef WITH_PINENTRY
1886 "+WITH_PINENTRY\n"
1887 #else
1888 "-WITH_PINENTRY\n"
1889 #endif
1890 #ifdef WITH_QUALITY
1891 "+WITH_QUALITY\n"
1892 #else
1893 "-WITH_QUALITY\n"
1894 #endif
1895 #ifdef DEBUG
1896 "+DEBUG\n"
1897 #else
1898 "-DEBUG\n"
1899 #endif
1900 #ifdef MEM_DEBUG
1901 "+MEM_DEBUG\n"
1902 #else
1903 "-MEM_DEBUG\n"
1904 #endif
1906 exit(EXIT_SUCCESS);
1907 case 'h':
1908 default:
1909 usage(argv[0]);
1913 pth_mutex_init(&cn_mutex);
1914 pth_mutex_init(&cache_mutex);
1915 pth_mutex_init(&rcfile_mutex);
1916 #ifdef WITH_PINENTRY
1917 pth_mutex_init(&pin_mutex);
1918 #endif
1920 if (!rcfile)
1921 rcfile = g_strdup_printf("%s/.pwmd/config", g_get_home_dir());
1923 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
1924 exit(EXIT_FAILURE);
1926 #ifdef WITH_PINENTRY
1927 if (disable_pinentry == TRUE)
1928 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
1929 #endif
1931 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
1932 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
1934 if (log_syslog == TRUE)
1935 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
1937 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
1938 x = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
1939 errno = 0;
1941 if (setpriority(PRIO_PROCESS, 0, x) == -1) {
1942 log_write("setpriority(): %s", strerror(errno));
1943 goto do_exit;
1947 #ifdef HAVE_MLOCKALL
1948 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
1949 log_write("mlockall(): %s", strerror(errno));
1950 goto do_exit;
1952 #endif
1954 if (convert) {
1955 if (!outfile)
1956 usage(argv[0]);
1958 opt = convert_file(convert, keyfile, outfile);
1959 g_key_file_free(keyfileh);
1960 g_free(rcfile);
1961 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
1964 if (import) {
1965 if (!outfile)
1966 usage(argv[0]);
1968 if (cmd_iterations == -1)
1969 cmd_iterations = (guint64)get_key_file_integer("global", "iterations");
1971 opt = xml_import(import, outfile, keyfile, cmd_iterations);
1972 g_key_file_free(keyfileh);
1973 g_free(rcfile);
1974 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
1977 g_key_file_set_list_separator(keyfileh, ',');
1979 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
1980 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
1982 socketarg = expand_homedir(p);
1983 g_free(p);
1985 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
1986 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
1988 datadir = expand_homedir(p);
1989 g_free(p);
1991 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
1992 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
1993 disable_list_and_dump = n;
1995 else
1996 disable_list_and_dump = secure;
1998 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
1999 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
2000 else
2001 default_timeout = -1;
2003 setup_logging(keyfileh);
2005 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2006 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2008 if (argc != optind) {
2009 for (; optind < argc; optind++) {
2010 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2011 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
2015 if (strchr(socketarg, '/') == NULL) {
2016 socketdir = g_get_current_dir();
2017 socketname = g_strdup(socketarg);
2018 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2020 else {
2021 socketname = g_strdup(strrchr(socketarg, '/'));
2022 socketname++;
2023 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2024 socketdir = g_strdup(socketarg);
2025 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2028 if (chdir(datadir)) {
2029 log_write("%s: %s", datadir, strerror(errno));
2030 unlink(socketpath);
2031 goto do_exit;
2034 if (parse_rcfile_keys() == FALSE)
2035 goto do_exit;
2037 clear_rcfile_keys();
2040 * Set the cache entry for a file. Prompts for the password.
2042 if (cache_push) {
2043 for (opt = 0; cache_push[opt]; opt++)
2044 do_cache_push(cache_push[opt], NULL);
2046 g_strfreev(cache_push);
2047 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2051 * bind() doesn't like the full pathname of the socket or any non alphanum
2052 * characters so change to the directory where the socket is wanted then
2053 * create it then change to datadir.
2055 if (chdir(socketdir)) {
2056 log_write("%s: %s", socketdir, strerror(errno));
2057 goto do_exit;
2060 g_free(socketdir);
2062 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2063 log_write("socket(): %s", strerror(errno));
2064 goto do_exit;
2067 addr.sun_family = AF_UNIX;
2068 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2070 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2071 log_write("bind(): %s", strerror(errno));
2073 if (errno == EADDRINUSE)
2074 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2075 "stale socket. Please remove it manually."), socketpath);
2077 do_unlink = 0;
2078 goto do_exit;
2081 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2082 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2083 mode_t mode = strtol(t, NULL, 8);
2084 mode_t mask = umask(0);
2086 g_free(t);
2088 if (chmod(socketname, mode) == -1) {
2089 log_write("%s: %s", socketname, strerror(errno));
2090 close(sockfd);
2091 unlink(socketpath);
2092 umask(mask);
2093 goto do_exit;
2096 umask(mask);
2099 g_free(--socketname);
2101 if (chdir(datadir)) {
2102 log_write("%s: %s", datadir, strerror(errno));
2103 close(sockfd);
2104 unlink(socketpath);
2105 goto do_exit;
2108 g_free(datadir);
2110 if (listen(sockfd, 0) == -1) {
2111 log_write("listen(): %s", strerror(errno));
2112 goto do_exit;
2115 cmdline = FALSE;
2117 if (background) {
2118 switch (fork()) {
2119 case -1:
2120 log_write("fork(): %s", strerror(errno));
2121 goto do_exit;
2122 case 0:
2123 close(0);
2124 close(1);
2125 close(2);
2126 setsid();
2127 break;
2128 default:
2129 exit(EXIT_SUCCESS);
2133 server_loop(sockfd, &socketpath);
2134 estatus = EXIT_SUCCESS;
2136 do_exit:
2137 if (socketpath && do_unlink) {
2138 unlink(socketpath);
2139 g_free(socketpath);
2142 g_key_file_free(keyfileh);
2143 g_free(rcfile);
2144 xmlCleanupParser();
2145 xmlCleanupGlobals();
2147 if (estatus == EXIT_SUCCESS)
2148 log_write(N_("pwmd exiting normally"));
2150 #if defined(DEBUG) && !defined(MEM_DEBUG)
2151 xdump();
2152 #endif
2153 exit(estatus);