keepalive_thread() cleanup. Also fixes a segfault when doing a SIGHUP.
[pwmd.git] / src / pwmd.c
blob313926f69458e237fc1de9dbb3a620b21ec67142
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 pth_cancel_point();
141 return assuan_process_done(ctx, assuan_set_error(ctx, n, _gpg_strerror(n)));
144 gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e)
146 gpg_err_code_t n = gpg_err_code(e);
147 gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n);
148 struct client_s *client = assuan_get_pointer(ctx);
150 pth_cancel_point();
152 if (!e)
153 return assuan_process_done(ctx, 0);
155 if (!ctx) {
156 log_write("%s", pwmd_strerror(e));
157 return e;
160 if (n == EPWMD_LIBXML_ERROR) {
161 xmlErrorPtr xe = client->xml_error;
163 if (!xe)
164 xe = xmlGetLastError();
166 e = assuan_process_done(ctx, assuan_set_error(ctx, code, xe->message));
167 log_write("%s", xe->message);
169 if (xe == client->xml_error)
170 xmlResetError(xe);
171 else
172 xmlResetLastError();
174 client->xml_error = NULL;
175 return e;
178 return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e)));
181 void log_write(const gchar *fmt, ...)
183 gchar *args, *line;
184 va_list ap;
185 struct tm *tm;
186 time_t now;
187 gchar tbuf[21];
188 gint fd = -1;
189 gchar *name;
190 gchar buf[255];
191 pth_t tid = pth_self();
192 pth_attr_t attr;
194 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
195 return;
197 if (!cmdline && logfile) {
198 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
199 warn("%s", logfile);
200 return;
204 va_start(ap, fmt);
206 if (g_vasprintf(&args, fmt, ap) == -1) {
207 if (logfile)
208 close(fd);
210 va_end(ap);
211 return;
214 va_end(ap);
216 if (cmdline) {
217 fprintf(stderr, "%s\n", args);
218 fflush(stderr);
219 g_free(args);
220 return;
223 attr = pth_attr_of(tid);
225 if (pth_attr_get(attr, PTH_ATTR_NAME, &name) == FALSE)
226 name = "unknown";
228 pth_attr_destroy(attr);
229 name = print_fmt(buf, sizeof(buf), "%s(%p): ", name, tid);
231 if (!cmdline && log_syslog == TRUE)
232 syslog(LOG_INFO, "%s%s", name, args);
234 time(&now);
235 tm = localtime(&now);
236 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
237 tbuf[sizeof(tbuf) - 1] = 0;
239 if (args[strlen(args)-1] == '\n')
240 args[strlen(args)-1] = 0;
242 line = g_strdup_printf("%s %i %s%s\n", tbuf, getpid(), name, args);
243 g_free(args);
245 if (!line) {
246 if (logfile)
247 close(fd);
249 return;
252 if (logfile) {
253 write(fd, line, strlen(line));
254 fsync(fd);
255 close(fd);
258 if (isatty(STDERR_FILENO)) {
259 fprintf(stderr, "%s", line);
260 fflush(stderr);
263 g_free(line);
266 static void usage(gchar *pn)
268 g_fprintf(stderr, N_(
269 "Usage: %s [-hvDnP] [-f <rcfile>] [-C <filename>] "
270 "[-I <filename> [-i <iter>]]\n "
271 "[-k <keyfile>] [-o <outfile>] [file1] [...]\n"
272 " -n run as a foreground process\n"
273 " -f load the specified rcfile (~/.pwmd/config)\n"
274 " -C convert a version 1 data file to version 2\n"
275 " -I import an XML file\n"
276 " -i encrypt with the specified number of iterations when importing\n"
277 " (config default in the \"global\" section)\n"
278 " -k obtain the key from the specified file\n"
279 " -o output file for use with the -C and -I options\n"
280 " -D disable use of the LIST and DUMP commands\n"
281 " -P disable pinentry\n"
282 " -v version\n"
283 " -h this help text\n"
284 ), pn);
285 exit(EXIT_FAILURE);
288 static int gcry_SecureCheck(const void *ptr)
290 return 1;
293 static void setup_gcrypt()
295 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
296 gcry_check_version(GCRYPT_VERSION);
298 gcry_set_allocation_handler(xmalloc, xmalloc, gcry_SecureCheck, xrealloc,
299 xfree);
301 if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, NULL,
302 NULL) != 0)
303 errx(EXIT_FAILURE, N_("Required AES cipher not supported by libgcrypt."));
305 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_KEYLEN, NULL, &gcrykeysize);
306 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_BLKLEN, NULL, &gcryblocksize);
309 static gint new_connection(struct client_s *cl)
311 gpg_error_t rc;
312 gchar *ver;
314 rc = assuan_init_socket_server_ext(&cl->ctx, cl->thd->fd, 2);
316 if (rc)
317 goto fail;
319 assuan_set_pointer(cl->ctx, cl);
320 ver = g_strdup_printf("%s", PACKAGE_STRING);
321 assuan_set_hello_line(cl->ctx, ver);
322 g_free(ver);
323 rc = register_commands(cl->ctx);
325 if (rc)
326 goto fail;
328 rc = assuan_accept(cl->ctx);
330 if (rc)
331 goto fail;
333 return 0;
335 fail:
336 log_write("%s", _gpg_strerror(rc));
337 close(cl->thd->fd);
338 cl->thd->fd = -1;
339 return 1;
342 static void xml_error_cb(void *data, xmlErrorPtr e)
344 struct client_s *client = data;
347 * Keep the first reported error as the one to show in the error
348 * description. Reset in send_error().
350 if (client->xml_error)
351 return;
353 xmlCopyError(e, client->xml_error);
356 void close_file_header(file_header_internal_t *fh)
358 if (!fh)
359 return;
361 if (fh) {
362 if (fh->fd != -1 || (cmdline == TRUE && fh->fd != STDOUT_FILENO))
363 close(fh->fd);
365 if (fh->doc)
366 gcry_free(fh->doc);
368 g_free(fh);
372 void cleanup_crypto(struct client_crypto_s **c)
374 struct client_crypto_s *cr = *c;
376 if (!cr)
377 return;
379 if (cr->iv)
380 gcry_free(cr->iv);
382 if (cr->key)
383 gcry_free(cr->key);
385 if (cr->tkey)
386 gcry_free(cr->tkey);
388 if (cr->tkey2)
389 gcry_free(cr->tkey2);
391 if (cr->inbuf)
392 gcry_free(cr->inbuf);
394 if (cr->outbuf)
395 gcry_free(cr->outbuf);
397 close_file_header(cr->fh);
399 if (cr->gh)
400 gcry_cipher_close(cr->gh);
402 g_free(cr);
403 *c = NULL;
407 * This is called after a child_thread terminates. Set with
408 * pth_cleanup_push().
410 static void cleanup_cb(void *arg)
412 struct client_thread_s *cn = arg;
413 struct client_s *cl = cn->cl;
415 MUTEX_LOCK(&cn_mutex);
416 cn_thread_list = g_slist_remove(cn_thread_list, cn);
417 MUTEX_UNLOCK(&cn_mutex);
419 if (cn->msg_tid) {
420 pth_cancel(cn->msg_tid);
421 pth_join(cn->msg_tid, NULL);
424 for (;;) {
425 struct status_msg_s *m = g_slist_nth_data(cn->msg_list, 0);
427 if (!m)
428 break;
430 cn->msg_list = g_slist_remove(cn->msg_list, m);
431 g_free(m);
434 if (cl && cl->freed == FALSE)
435 cleanup_client(cl);
437 if (cl && cl->ctx)
438 assuan_deinit_server(cl->ctx);
439 else if (cl && cl->thd && cl->thd->fd != -1)
440 close(cl->thd->fd);
442 #ifdef WITH_PINENTRY
443 if (cl && cl->pinentry)
444 cleanup_pinentry(cl->pinentry);
445 #endif
447 if (cl->crypto)
448 cleanup_crypto(&cl->crypto);
450 g_free(cl);
451 log_write(N_("exiting, fd=%i"), cn->fd);
452 g_free(cn);
453 send_status_all(STATUS_CLIENTS);
457 * Called every time a connection is made from init_new_connection(). This is
458 * the thread entry point.
460 static void *client_thread(void *data)
462 struct client_thread_s *thd = data;
463 struct client_s *cl = g_malloc0(sizeof(struct client_s));
464 gpg_error_t rc;
465 pth_attr_t attr;
466 gint n;
469 * Prevent a race condition with init_new_connection() if this thread
470 * fails (returns) for some reason before init_new_connection() releases
471 * the cn_mutex.
473 MUTEX_LOCK(&cn_mutex);
474 MUTEX_UNLOCK(&cn_mutex);
475 pth_cleanup_push(cleanup_cb, thd);
477 if (!cl) {
478 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
479 goto fail;
482 attr = pth_attr_of(pth_self());
483 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
484 pth_attr_destroy(attr);
485 thd->cl = cl;
486 cl->thd = thd;
488 if (new_connection(cl))
489 goto fail;
491 #ifdef WITH_PINENTRY
492 cl->pinentry = pinentry_init();
494 if (!cl->pinentry) {
495 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
496 goto fail;
498 #endif
500 #ifdef HAVE_MLOCKALL
501 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
502 log_write("mlockall(): %s", strerror(errno));
503 goto fail;
505 #endif
507 pth_mutex_init(&thd->msg_list_mutex);
508 attr = pth_attr_new();
509 pth_attr_init(attr);
510 pth_attr_set(attr, PTH_ATTR_JOINABLE, TRUE);
511 thd->msg_tid = pth_spawn(attr, client_msg_thread, thd);
512 n = errno;
513 pth_attr_destroy(attr);
515 if (!thd->msg_tid) {
516 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
517 _gpg_strerror(gpg_error_from_errno(n)));
518 goto fail;
521 pth_yield(thd->msg_tid);
522 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
524 if (rc) {
525 log_write("%s", _gpg_strerror(rc));
526 goto fail;
529 send_status_all(STATUS_CLIENTS);
530 xmlSetStructuredErrorFunc(cl, xml_error_cb);
532 for (;;) {
533 #ifdef WITH_PINENTRY
534 pth_event_t pev = NULL;
535 #endif
536 pth_status_t st, wst;
537 pth_event_t wev = NULL;
538 pth_event_t ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE,
539 cl->thd->fd);
541 #ifdef WITH_PINENTRY
542 if (cl->pinentry->status == PINENTRY_RUNNING) {
543 pev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, cl->pinentry->fd);
544 ev = pth_event_concat(ev, pev, NULL);
546 #endif
548 if (cl->inquire_status == INQUIRE_BUSY) {
549 wev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_WRITEABLE, cl->thd->fd);
550 ev = pth_event_concat(ev, wev, NULL);
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);
560 pth_cancel_point();
562 if (rc) {
563 cl->inquire_status = INQUIRE_INIT;
565 if (gpg_err_code(rc) == GPG_ERR_EOF)
566 goto done;
568 log_write("assuan_process_next(): %s", _gpg_strerror(rc));
569 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
571 if (rc) {
572 log_write("assuan_process_done(): %s", _gpg_strerror(rc));
573 goto done;
576 else {
577 #ifdef WITH_PINENTRY
578 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
579 cl->pinentry->status = PINENTRY_RUNNING;
580 #endif
582 switch (cl->inquire_status) {
583 case INQUIRE_BUSY:
584 case INQUIRE_INIT:
585 break;
586 case INQUIRE_DONE:
587 cl->inquire_status = INQUIRE_INIT;
588 rc = assuan_process_done(cl->ctx, 0);
589 pth_cancel_point();
590 break;
595 if (wev)
596 pth_event_free(wev, PTH_FREE_THIS);
598 pth_event_free(ev, PTH_FREE_THIS);
600 #ifdef WITH_PINENTRY
601 if (pev) {
602 pth_event_isolate(pev);
603 st = pth_event_status(pev);
604 pth_event_free(pev, PTH_FREE_THIS);
607 rc = pinentry_iterate(cl,
608 pev && cl->pinentry->fd != -1 && st == PTH_STATUS_OCCURRED);
609 #endif
613 * Client cleanup (including XML data) is done in cleanup_cb() from
614 * the cleanup thread.
616 done:
617 fail:
618 pth_cleanup_pop(1);
619 pth_exit(PTH_CANCELED);
620 return NULL;
623 static void setup_logging(GKeyFile *kf)
625 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
627 if (n == TRUE) {
628 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
630 if (*p == '~') {
631 gchar buf[PATH_MAX];
633 p++;
634 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
635 g_free(p);
637 if (logfile)
638 g_free(logfile);
640 logfile = g_strdup(buf);
642 else {
643 if (logfile)
644 g_free(logfile);
646 logfile = p;
650 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
654 * Make sure all settings are set to either the specified setting or a
655 * default.
657 static void set_rcfile_defaults(GKeyFile *kf)
659 gchar buf[PATH_MAX];
661 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
662 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
663 g_key_file_set_string(kf, "global", "socket_path", buf);
666 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
667 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
668 g_key_file_set_string(kf, "global", "data_directory", buf);
671 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
672 g_key_file_set_boolean(kf, "global", "backup", TRUE);
674 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
675 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
676 g_key_file_set_string(kf, "global", "log_path", buf);
679 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
680 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
682 #ifdef HAVE_MLOCKALL
683 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
684 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
685 #endif
687 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
688 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
690 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
691 g_key_file_get_integer(kf, "global", "iterations", 0) < 0)
692 g_key_file_set_integer(kf, "global", "iterations", 1);
694 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
695 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
697 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
698 g_key_file_set_integer(kf, "global", "iteration_progress", 0);
700 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
701 g_key_file_set_integer(kf, "global", "compression_level", 6);
703 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
704 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
706 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
707 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
709 zlib_bufsize = (uInt)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
711 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
712 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
714 #ifdef HAVE_MLOCKALL
715 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
716 #endif
718 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
719 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
721 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
722 g_key_file_set_integer(kf, "global", "keepalive", DEFAULT_KEEPALIVE_TO);
724 #ifdef WITH_PINENTRY
725 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
726 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
728 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
729 g_key_file_set_integer(kf, "global", "pinentry_timeout", 20);
730 #endif
732 if (g_key_file_has_key(kf, "global", "xfer_progress", NULL) == FALSE)
733 g_key_file_set_integer(kf, "global", "xfer_progress", 8196);
735 setup_logging(kf);
738 static GKeyFile *parse_rcfile(gboolean specified)
740 GKeyFile *kf = g_key_file_new();
741 GError *rc = NULL;
743 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
744 log_write("%s: %s", rcfile, rc->message);
746 if (cmdline && specified) {
747 g_clear_error(&rc);
748 return NULL;
751 if (rc->code == G_FILE_ERROR_NOENT) {
752 g_clear_error(&rc);
753 set_rcfile_defaults(kf);
754 return kf;
757 g_clear_error(&rc);
758 return NULL;
761 set_rcfile_defaults(kf);
762 return kf;
765 static gchar *do_get_password(const gchar *prompt)
767 gchar buf[LINE_MAX] = {0}, *p;
768 struct termios told, tnew;
769 gchar *key;
771 if (tcgetattr(STDIN_FILENO, &told) == -1) {
772 log_write("tcgetattr(): %s", strerror(errno));
773 return NULL;
776 memcpy(&tnew, &told, sizeof(struct termios));
777 tnew.c_lflag &= ~(ECHO);
778 tnew.c_lflag |= ICANON|ECHONL;
780 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
781 log_write("tcsetattr(): %s", strerror(errno));
782 tcsetattr(STDIN_FILENO, TCSANOW, &told);
783 return NULL;
786 fprintf(stderr, "%s", prompt);
788 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
789 tcsetattr(STDIN_FILENO, TCSANOW, &told);
790 return NULL;
793 tcsetattr(STDIN_FILENO, TCSANOW, &told);
794 p[strlen(p) - 1] = 0;
796 if (!buf[0]) {
797 key = gcry_malloc(1);
798 key[0] = 0;
800 else {
801 key = gcry_malloc(strlen(p) + 1);
802 sprintf(key, "%s", p);
805 memset(&buf, 0, sizeof(buf));
806 return key;
809 /* Only used when "enable_pinentry" is "false" or -P. */
810 static gpg_error_t get_input(const gchar *filename,
811 struct client_crypto_s *crypto, guchar *key, pinentry_cmd_t which)
813 gchar *prompt;
815 if (which == PINENTRY_SAVE) {
816 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
817 crypto->tkey = do_get_password(prompt);
818 g_free(prompt);
820 if (!crypto->tkey) {
821 log_write(N_("%s: Skipping file"), filename);
822 return GPG_ERR_BAD_PASSPHRASE;
825 prompt = g_strdup_printf(N_("Repeat passphrase: "));
826 crypto->tkey2 = do_get_password(prompt);
827 g_free(prompt);
829 if (!crypto->tkey2) {
830 log_write(N_("%s: Skipping file"), filename);
831 return GPG_ERR_BAD_PASSPHRASE;
834 if (strcmp(crypto->tkey, crypto->tkey2)) {
835 log_write(N_("%s: Passphrase mismatch"), filename);
836 return EPWMD_BADKEY;
839 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
840 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
841 return 0;
844 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
846 if ((crypto->tkey = do_get_password(prompt)) == NULL) {
847 log_write(N_("%s: Skipping file"), filename);
848 g_free(prompt);
849 return GPG_ERR_BAD_PASSPHRASE;
852 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
853 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
854 g_free(prompt);
855 return 0;
859 * inbuf must have been allocated with gcry_malloc().
861 gpg_error_t export_common(const gchar *filename, struct client_crypto_s *crypto,
862 gpointer inbuf, gulong insize)
864 gpg_error_t rc;
865 gint level, zrc;
866 gulong outsize;
867 gpointer outbuf;
869 level = get_key_file_integer(filename, "compression_level");
871 if (level < 0)
872 level = 0;
874 if (do_compress(NULL, level, inbuf, insize, &outbuf, &outsize, &zrc)
875 == FALSE) {
876 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
879 crypto->inbuf = outbuf;
880 crypto->insize = outsize;
881 rc = do_xml_encrypt(NULL, crypto, filename);
882 return rc;
885 static gpg_error_t get_password(const gchar *filename,
886 struct client_crypto_s *crypto, guchar *md5file, guchar *key,
887 pinentry_cmd_t which)
889 #ifdef WITH_PINENTRY
890 gpg_error_t rc = 0;
892 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
893 == FALSE) {
894 #endif
895 return get_input(filename, crypto, key, which);
896 #ifdef WITH_PINENTRY
898 else {
899 gchar *result = NULL;
900 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
902 pth_mutex_init(&pin->status_mutex);
903 set_pinentry_defaults(pin);
904 pin->which = which;
905 pin->filename = g_strdup(filename);
906 rc = pinentry_getpin(pin, &result);
908 if (rc) {
909 xfree(result);
910 goto done;
913 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, result ? strlen(result) : 1);
914 xfree(result);
915 cleanup_pinentry(pin);
918 done:
919 return rc;
920 #endif
923 static gboolean _getline(const gchar *file, gchar **result, gpg_error_t *rc)
925 FILE *fp;
926 gchar buf[LINE_MAX] = {0}, *p;
927 gchar *str = NULL;
928 gint len;
930 *rc = 0;
932 if ((fp = fopen(file, "r")) == NULL) {
933 *rc = gpg_error_from_syserror();
934 return FALSE;
937 p = fgets(buf, sizeof(buf), fp);
938 fclose(fp);
939 len = strlen(buf);
941 if (len && buf[len - 1] == '\n')
942 buf[--len] = 0;
944 str = gcry_malloc(len + 1);
946 if (!str) {
947 *rc = gpg_error_from_errno(ENOMEM);
948 return FALSE;
951 memcpy(str, buf, len ? len : 1);
952 str[len] = 0;
953 memset(&buf, 0, sizeof(buf));
954 *result = str;
955 return TRUE;
958 static gchar *parse_rcfile_keyfile(const gchar *filename, gboolean import,
959 gpg_error_t *rc)
961 GError *rv = NULL;
962 gchar *t, *file = NULL, *str;
964 *rc = GPG_ERR_UNKNOWN_ERRNO;
966 if (import == FALSE) {
967 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
968 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
970 if (!file) {
971 if (rv) {
972 log_write("%s: key_file: %s", rcfile, rv->message);
973 g_clear_error(&rv);
976 return NULL;
979 t = expand_homedir(file);
981 if (!t) {
982 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
983 *rc = gpg_error_from_errno(ENOMEM);
984 return NULL;
987 g_free(file);
988 file = t;
991 else {
992 /* -I or -C. The filename is a key file. */
993 file = g_strdup(filename);
995 if (!file) {
996 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
997 *rc = gpg_error_from_errno(ENOMEM);
998 return NULL;
1002 if (rv) {
1003 log_write("%s: key_file: %s", rcfile, rv->message);
1004 g_clear_error(&rv);
1005 return NULL;
1008 if (!file)
1009 return NULL;
1011 if (_getline(file, &str, rc) == FALSE) {
1012 log_write("%s: %s: %s", filename, file, pwmd_strerror(*rc));
1013 g_free(file);
1014 return NULL;
1017 g_free(file);
1018 *rc = 0;
1019 return str;
1022 static gboolean xml_import(const gchar *filename, const gchar *outfile,
1023 const gchar *keyfile, guint64 iter)
1025 xmlDocPtr doc;
1026 gint fd;
1027 struct stat st;
1028 gint len;
1029 xmlChar *xmlbuf;
1030 xmlChar *xml;
1031 gpg_error_t rc;
1032 struct client_crypto_s *crypto;
1034 if (stat(filename, &st) == -1) {
1035 log_write("%s: %s", filename, strerror(errno));
1036 return FALSE;
1039 crypto = init_client_crypto();
1041 if (!crypto)
1042 return FALSE;
1044 crypto->key = gcry_malloc(gcrykeysize);
1045 memset(crypto->key, 0, gcrykeysize);
1047 if (!crypto->key) {
1048 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1049 goto fail;
1052 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
1053 filename, outfile);
1055 if (iter && keyfile) {
1056 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1058 if (!crypto->tkey)
1059 goto fail;
1061 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1062 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1064 else if (iter) {
1065 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
1067 if (rc)
1068 goto fail;
1071 if ((fd = open(filename, O_RDONLY)) == -1) {
1072 log_write("%s: %s", filename, strerror(errno));
1073 goto fail;
1076 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
1077 close(fd);
1078 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1079 goto fail;
1082 if (pth_read(fd, xmlbuf, st.st_size) == -1) {
1083 rc = errno;
1084 close(fd);
1085 errno = rc;
1086 log_write("%s: %s", filename, strerror(errno));
1087 goto fail;
1090 close(fd);
1091 xmlbuf[st.st_size] = 0;
1094 * Make sure the document validates.
1096 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
1097 log_write("xmlReadDoc() failed");
1098 gcry_free(xmlbuf);
1099 goto fail;
1102 gcry_free(xmlbuf);
1103 xmlDocDumpMemory(doc, &xml, &len);
1104 xmlFreeDoc(doc);
1106 if (!iter)
1107 memset(crypto->key, '!', gcrykeysize);
1109 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
1111 if (!crypto->fh) {
1112 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1113 goto fail;
1116 crypto->fh->fh2.iter = iter;
1117 rc = export_common(outfile, crypto, xml, len);
1118 xmlFree(xml);
1120 if (rc) {
1121 send_error(NULL, rc);
1122 goto fail;
1125 cleanup_crypto(&crypto);
1126 return TRUE;
1128 fail:
1129 cleanup_crypto(&crypto);
1130 return FALSE;
1133 gchar *get_key_file_string(const gchar *section, const gchar *what)
1135 gchar *val = NULL;
1136 GError *grc = NULL;
1138 MUTEX_LOCK(&rcfile_mutex);
1140 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1141 val = g_key_file_get_string(keyfileh, section, what, &grc);
1143 if (grc) {
1144 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1145 g_clear_error(&grc);
1148 else {
1149 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1150 val = g_key_file_get_string(keyfileh, "global", what, &grc);
1152 if (grc) {
1153 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1154 g_clear_error(&grc);
1159 MUTEX_UNLOCK(&rcfile_mutex);
1160 return val;
1163 gint get_key_file_integer(const gchar *section, const gchar *what)
1165 gint val = -1;
1166 GError *grc = NULL;
1168 MUTEX_LOCK(&rcfile_mutex);
1170 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
1171 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
1173 if (grc) {
1174 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1175 g_clear_error(&grc);
1178 else {
1179 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1180 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
1182 if (grc) {
1183 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1184 g_clear_error(&grc);
1189 MUTEX_UNLOCK(&rcfile_mutex);
1190 return val;
1193 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
1195 gboolean val = FALSE;
1196 GError *grc = NULL;
1198 MUTEX_LOCK(&rcfile_mutex);
1200 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1201 val = g_key_file_get_boolean(keyfileh, section, what, &grc);
1203 if (grc) {
1204 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1205 g_clear_error(&grc);
1208 else {
1209 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1210 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
1212 if (grc) {
1213 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1214 g_clear_error(&grc);
1219 MUTEX_UNLOCK(&rcfile_mutex);
1220 return val;
1223 static gboolean parse_rcfile_keys()
1225 gsize n;
1226 gchar **groups;
1227 gchar **p;
1228 gchar *str;
1230 groups = g_key_file_get_groups(keyfileh, &n);
1232 for (p = groups; *p; p++) {
1233 GError *rc = NULL;
1235 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE) {
1236 str = g_key_file_get_string(keyfileh, *p, "key", &rc);
1238 if (!str) {
1239 if (rc) {
1240 log_write("%s: key: %s", rcfile, rc->message);
1241 g_clear_error(&rc);
1243 continue;
1246 do_cache_push(*p, str);
1247 g_free(str);
1248 continue;
1251 if (rc) {
1252 log_write("%s: key: %s", rcfile, rc->message);
1253 g_clear_error(&rc);
1254 continue;
1257 gpg_error_t ret;
1258 str = parse_rcfile_keyfile(*p, FALSE, &ret);
1260 if (!str)
1261 continue;
1263 do_cache_push(*p, str);
1264 gcry_free(str);
1267 g_strfreev(groups);
1268 return TRUE;
1271 static gboolean do_cache_push(const gchar *filename, const gchar *password)
1273 guchar md5file[16];
1274 gint timeout;
1275 const gchar *p = filename;
1276 struct client_crypto_s *crypto;
1277 gpg_error_t rc;
1279 while (isspace(*p))
1280 p++;
1282 if (!*p)
1283 return FALSE;
1285 if (valid_filename(p) == FALSE) {
1286 log_write(N_("%s: Invalid characters in filename"), p);
1287 return FALSE;
1290 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1292 if (access(p, R_OK|W_OK) != 0) {
1293 log_write("%s: %s", p, strerror(errno));
1294 return FALSE;
1297 crypto = init_client_crypto();
1299 if (!crypto)
1300 return FALSE;
1302 crypto->fh = read_file_header(filename, FALSE, &rc);
1304 if (!crypto->fh) {
1305 log_write("%s: %s", p, pwmd_strerror(rc));
1306 cleanup_crypto(&crypto);
1307 return FALSE;
1310 crypto->key = gcry_malloc(gcrykeysize);
1312 if (!crypto->key) {
1313 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1314 cleanup_crypto(&crypto);
1315 return FALSE;
1318 log_write(N_("Adding '%s' to the file cache ..."), filename);
1320 if (crypto->fh->fh2.iter <= 0) {
1321 memset(crypto->key, '!', gcrykeysize);
1322 goto try_decrypt;
1325 if (!password) {
1326 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1328 if (rc) {
1329 send_error(NULL, rc);
1330 cleanup_crypto(&crypto);
1331 return FALSE;
1334 gcry_free(crypto->fh->doc);
1335 crypto->fh->doc = NULL;
1337 else
1338 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password,
1339 strlen(password) ? strlen(password) : 1);
1341 try_decrypt:
1342 rc = try_xml_decrypt(NULL, crypto->key, crypto, NULL, NULL);
1344 if (rc) {
1345 log_write("%s: %s", filename, pwmd_strerror(rc));
1346 cleanup_crypto(&crypto);
1347 return FALSE;
1350 if (cache_update_key(md5file, crypto->key) == FALSE) {
1351 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1352 cleanup_crypto(&crypto);
1353 return FALSE;
1356 timeout = get_key_file_integer(p, "cache_timeout");
1357 cache_set_timeout(md5file, timeout);
1358 log_write(N_("File '%s' now cached"), filename);
1359 cleanup_crypto(&crypto);
1360 return TRUE;
1363 static void init_new_connection(gint fd)
1365 pth_attr_t attr;
1366 struct client_thread_s *new;
1367 gint n;
1369 new = g_malloc0(sizeof(struct client_thread_s));
1371 if (!new) {
1372 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1373 close(fd);
1374 return;
1377 MUTEX_LOCK(&cn_mutex);
1378 new->fd = fd;
1379 attr = pth_attr_new();
1380 pth_attr_init(attr);
1381 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1382 new->tid = pth_spawn(attr, client_thread, new);
1383 n = errno;
1384 pth_attr_destroy(attr);
1386 if (!new->tid) {
1387 g_free(new);
1388 close(fd);
1389 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1390 _gpg_strerror(gpg_error_from_errno(n)));
1391 MUTEX_UNLOCK(&cn_mutex);
1392 return;
1395 cn_thread_list = g_slist_append(cn_thread_list, new);
1396 MUTEX_UNLOCK(&cn_mutex);
1397 log_write(N_("new connection: tid=%p, fd=%i"), new->tid, fd);
1400 static void *accept_thread(void *arg)
1402 gint sockfd = (gint)arg;
1403 pth_attr_t attr = pth_attr_of(pth_self());
1405 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1406 pth_attr_destroy(attr);
1408 for (;;) {
1409 socklen_t slen = sizeof(struct sockaddr_un);
1410 struct sockaddr_un raddr;
1411 gint fd = -1;
1413 fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen);
1414 pth_cancel_point();
1416 if (fd == -1) {
1417 if (errno != EAGAIN) {
1418 if (!quit) // probably EBADF
1419 log_write("accept(): %s", strerror(errno));
1421 break;
1424 continue;
1427 init_new_connection(fd);
1430 /* Just in case accept() failed for some reason other than EBADF */
1431 quit = 1;
1432 pth_exit(PTH_CANCELED);
1433 return NULL;
1436 static void *adjust_cache_timer_thread(void *arg)
1438 pth_attr_t attr = pth_attr_of(pth_self());
1440 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1441 pth_attr_destroy(attr);
1443 for (;;) {
1444 pth_sleep(1);
1445 pth_cancel_point();
1446 CACHE_LOCK(NULL);
1447 cache_adjust_timer();
1448 CACHE_UNLOCK;
1451 return NULL;
1454 static void keepalive_cleanup(void *arg)
1456 pth_event_t ev = arg;
1458 pth_event_free(ev, PTH_FREE_ALL);
1461 static void *keepalive_thread(void *arg)
1463 gint to = (gint)arg;
1464 pth_attr_t attr = pth_attr_of(pth_self());
1466 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1467 pth_attr_destroy(attr);
1469 for (;;) {
1470 pth_event_t ev = pth_event(PTH_EVENT_TIME, pth_timeout(to, 0));
1472 pth_cleanup_push(keepalive_cleanup, ev);
1473 pth_wait(ev);
1474 send_status_all(STATUS_KEEPALIVE);
1475 pth_cleanup_pop(1);
1478 return NULL;
1481 static void startStopKeepAlive(gboolean term)
1483 gint n = get_key_file_integer("global", "keepalive");
1485 if (keepalive_tid)
1486 pth_cancel(keepalive_tid);
1488 keepalive_tid = NULL;
1490 if (term)
1491 return;
1493 if (n > 0) {
1494 gint e;
1495 pth_attr_t attr = pth_attr_new();
1496 pth_attr_init(attr);
1497 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1498 keepalive_tid = pth_spawn(attr, keepalive_thread, (void *)n);
1499 e = errno;
1500 pth_attr_destroy(attr);
1502 if (!keepalive_tid) {
1503 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1504 _gpg_strerror(gpg_error_from_errno(e)));
1505 return;
1508 pth_yield(keepalive_tid);
1512 static gboolean waiting_for_exit()
1514 guint i, t;
1515 pth_event_t evs = NULL;
1517 MUTEX_LOCK(&cn_mutex);
1519 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
1520 struct client_thread_s *thd = g_slist_nth_data(cn_thread_list, i);
1521 pth_event_t ev = pth_event(PTH_EVENT_TID|PTH_UNTIL_TID_DEAD, thd->tid);
1523 if (evs)
1524 evs = pth_event_concat(evs, ev, NULL);
1525 else
1526 evs = ev;
1529 MUTEX_UNLOCK(&cn_mutex);
1531 if (!evs)
1532 return FALSE;
1534 pth_wait(evs);
1535 MUTEX_LOCK(&cn_mutex);
1536 i = g_slist_length(cn_thread_list);
1537 MUTEX_UNLOCK(&cn_mutex);
1538 return i ? TRUE : FALSE;
1541 static void server_loop(gint sockfd, gchar **socketpath)
1543 pth_t accept_tid;
1544 guint n;
1545 sigset_t sigset;
1546 pth_attr_t attr;
1547 pth_t cache_timeout_tid;
1549 sigemptyset(&sigset);
1551 /* Termination */
1552 sigaddset(&sigset, SIGTERM);
1553 sigaddset(&sigset, SIGINT);
1555 /* Clears the file cache. */
1556 sigaddset(&sigset, SIGUSR1);
1558 /* Configuration file reloading. */
1559 sigaddset(&sigset, SIGHUP);
1561 /* Clears the cache and exits when something bad happens. */
1562 sigaddset(&sigset, SIGABRT);
1564 /* Ignored everywhere. When a client disconnects abnormally this signal
1565 * gets raised. It isn't needed though because client_thread() will check
1566 * for rcs even after the client disconnects. */
1567 signal(SIGPIPE, SIG_IGN);
1568 sigprocmask(SIG_BLOCK, &sigset, NULL);
1570 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1571 log_write(N_("Listening on %s"), *socketpath);
1572 attr = pth_attr_new();
1573 pth_attr_init(attr);
1574 accept_tid = pth_spawn(attr, accept_thread, (void *)sockfd);
1576 if (!accept_tid) {
1577 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1578 _gpg_strerror(gpg_error_from_errno(errno)));
1579 goto done;
1582 pth_yield(accept_tid);
1583 startStopKeepAlive(FALSE);
1584 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1585 cache_timeout_tid = pth_spawn(attr, adjust_cache_timer_thread, NULL);
1587 if (!cache_timeout_tid) {
1588 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1589 _gpg_strerror(gpg_error_from_errno(errno)));
1590 goto done;
1593 pth_yield(cache_timeout_tid);
1594 pth_attr_destroy(attr);
1596 do {
1597 gint sig;
1599 pth_sigwait(&sigset, &sig);
1600 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1602 /* Caught a signal. */
1603 switch (sig) {
1604 case SIGHUP:
1605 reload_rcfile();
1606 break;
1607 case SIGABRT:
1608 cache_clear(NULL, 2);
1609 #ifndef MEM_DEBUG
1610 xpanic();
1611 #endif
1612 exit(EXIT_FAILURE);
1613 case SIGUSR1:
1614 CACHE_LOCK(NULL);
1615 log_write(N_("clearing file cache"));
1616 cache_clear(NULL, 2);
1617 CACHE_UNLOCK;
1618 break;
1619 default:
1620 quit = 1;
1621 break;
1623 } while (!quit);
1625 done:
1627 * We're out of the main server loop. This happens when a signal was sent
1628 * to terminate the daemon. We'll wait for all clients to disconnect
1629 * before exiting and ignore any following signals.
1631 shutdown(sockfd, SHUT_RDWR);
1632 close(sockfd);
1633 pth_cancel(accept_tid);
1634 pth_join(accept_tid, NULL);
1635 unlink(*socketpath);
1636 g_free(*socketpath);
1637 *socketpath = NULL;
1638 MUTEX_LOCK(&cn_mutex);
1639 n = g_slist_length(cn_thread_list);
1640 MUTEX_UNLOCK(&cn_mutex);
1642 if (n) {
1643 log_write(N_("waiting for all clients to disconnect"));
1645 do {
1646 MUTEX_LOCK(&cn_mutex);
1647 n = g_slist_length(cn_thread_list);
1648 MUTEX_UNLOCK(&cn_mutex);
1649 log_write(N_("%i clients remain"), n);
1650 } while (waiting_for_exit());
1653 startStopKeepAlive(TRUE);
1654 pth_cancel(cache_timeout_tid);
1655 cache_free();
1659 * Only called from pinentry_fork() in the child process.
1661 void free_client_list()
1663 gint i, t = g_slist_length(cn_thread_list);
1665 for (i = 0; i < t; i++) {
1666 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1668 free_client(cn->cl);
1671 cache_free();
1674 struct client_crypto_s *init_client_crypto()
1676 struct client_crypto_s *new = g_malloc0(sizeof(struct client_crypto_s));
1677 gpg_error_t rc;
1679 if (!new) {
1680 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1681 return NULL;
1684 rc = gcry_cipher_open(&new->gh, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
1686 if (rc) {
1687 log_write("%s(%i): %s", __FUNCTION__, __LINE__, _gpg_strerror(rc));
1688 g_free(new);
1689 return NULL;
1692 return new;
1695 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
1696 const gchar *outfile)
1698 gpg_error_t rc;
1699 guchar md5file[16];
1700 guint64 iter;
1701 struct client_crypto_s *crypto = init_client_crypto();
1703 if (!crypto)
1704 return GPG_ERR_ENOMEM;
1706 crypto->key = gcry_malloc(gcrykeysize);
1708 if (!crypto->key) {
1709 cleanup_crypto(&crypto);
1710 return GPG_ERR_ENOMEM;
1713 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
1714 filename);
1715 crypto->fh = read_file_header(filename, TRUE, &rc);
1717 if (!crypto->fh)
1718 goto done;
1720 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
1722 /* The header in version 1 had a bug where the iterations were off-by-one.
1723 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
1724 * header.
1726 if (crypto->fh->fh1.iter >= 0) {
1727 if (keyfile) {
1728 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1730 if (!crypto->tkey)
1731 goto done;
1733 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1734 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1736 else {
1737 rc = get_password(filename, crypto, md5file, crypto->key,
1738 PINENTRY_OPEN);
1740 if (rc)
1741 goto done;
1745 rc = try_xml_decrypt(NULL, crypto->key, crypto, &crypto->fh->doc,
1746 &crypto->fh->len);
1748 if (rc)
1749 goto done;
1751 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
1753 if (rc) {
1754 log_write("%s: %s", filename, pwmd_strerror(rc));
1755 goto done;
1758 crypto->fh->v1 = FALSE;
1759 iter = crypto->fh->fh1.iter;
1760 memset(&crypto->fh->fh2, 0, sizeof(crypto->fh->fh2));
1761 /* Keep the iterations and key from the original file. */
1762 crypto->fh->fh2.iter = iter+1; // Bugfix for v1 data files.
1763 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
1765 done:
1766 if (rc)
1767 send_error(NULL, rc);
1769 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
1770 cleanup_crypto(&crypto);
1771 return rc;
1774 int main(int argc, char *argv[])
1776 gint opt;
1777 struct sockaddr_un addr;
1778 gchar buf[PATH_MAX];
1779 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
1780 gchar *socketarg = NULL;
1781 gchar *datadir = NULL;
1782 gboolean n;
1783 gint x;
1784 gchar *p;
1785 gchar **cache_push = NULL;
1786 gchar *import = NULL, *keyfile = NULL;
1787 guint64 cmd_iterations = -1;
1788 gint default_timeout;
1789 gboolean rcfile_spec = FALSE;
1790 gint estatus = EXIT_FAILURE;
1791 gint sockfd;
1792 gchar *outfile = NULL;
1793 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
1794 gint do_unlink = 1;
1795 gboolean secure = FALSE;
1796 gint background = 1;
1797 gchar *convert = NULL;
1798 #ifdef WITH_PINENTRY
1799 gboolean disable_pinentry = FALSE;
1800 #endif
1801 #if 0
1802 #ifndef DEBUG
1803 #ifdef HAVE_SETRLIMIT
1804 struct rlimit rl;
1806 rl.rlim_cur = rl.rlim_max = 0;
1808 if (setrlimit(RLIMIT_CORE, &rl) != 0)
1809 err(EXIT_FAILURE, "setrlimit()");
1810 #endif
1811 #endif
1812 #endif
1814 #ifdef ENABLE_NLS
1815 setlocale(LC_ALL, "");
1816 bindtextdomain("pwmd", LOCALEDIR);
1817 textdomain("pwmd");
1818 #endif
1820 #ifndef MEM_DEBUG
1821 xmem_init();
1822 #endif
1823 setup_gcrypt();
1824 gpg_err_init();
1825 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
1826 g_mem_set_vtable(&mtable);
1827 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
1828 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
1829 xmlInitMemory();
1830 xmlInitGlobals();
1831 xmlInitParser();
1832 xmlXPathInit();
1833 g_snprintf(buf, sizeof(buf), "%s/.pwmd", g_get_home_dir());
1835 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
1836 err(EXIT_FAILURE, "%s", buf);
1838 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", g_get_home_dir());
1840 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
1841 err(EXIT_FAILURE, "%s", buf);
1843 cmdline = TRUE;
1845 while ((opt = getopt(argc, argv, "Po:C:nI:i:k:hvf:D")) != EOF) {
1846 switch (opt) {
1847 #ifdef WITH_PINENTRY
1848 case 'P':
1849 disable_pinentry = TRUE;
1850 break;
1851 #endif
1852 case 'o':
1853 outfile = optarg;
1854 break;
1855 case 'C':
1856 convert = optarg;
1857 break;
1858 case 'n':
1859 background = 0;
1860 break;
1861 case 'D':
1862 secure = TRUE;
1863 break;
1864 case 'I':
1865 import = optarg;
1866 break;
1867 case 'i':
1868 cmd_iterations = strtol(optarg, NULL, 10);
1869 break;
1870 case 'k':
1871 keyfile = optarg;
1872 break;
1873 case 'f':
1874 rcfile = g_strdup(optarg);
1875 rcfile_spec = TRUE;
1876 break;
1877 case 'v':
1878 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,
1879 PACKAGE_BUGREPORT,
1880 #ifdef WITH_PINENTRY
1881 "+WITH_PINENTRY\n"
1882 #else
1883 "-WITH_PINENTRY\n"
1884 #endif
1885 #ifdef WITH_QUALITY
1886 "+WITH_QUALITY\n"
1887 #else
1888 "-WITH_QUALITY\n"
1889 #endif
1890 #ifdef DEBUG
1891 "+DEBUG\n"
1892 #else
1893 "-DEBUG\n"
1894 #endif
1895 #ifdef MEM_DEBUG
1896 "+MEM_DEBUG\n"
1897 #else
1898 "-MEM_DEBUG\n"
1899 #endif
1901 exit(EXIT_SUCCESS);
1902 case 'h':
1903 default:
1904 usage(argv[0]);
1908 pth_mutex_init(&cn_mutex);
1909 pth_mutex_init(&cache_mutex);
1910 pth_mutex_init(&rcfile_mutex);
1911 #ifdef WITH_PINENTRY
1912 pth_mutex_init(&pin_mutex);
1913 #endif
1915 if (!rcfile)
1916 rcfile = g_strdup_printf("%s/.pwmd/config", g_get_home_dir());
1918 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
1919 exit(EXIT_FAILURE);
1921 #ifdef WITH_PINENTRY
1922 if (disable_pinentry == TRUE)
1923 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
1924 #endif
1926 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
1927 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
1929 if (log_syslog == TRUE)
1930 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
1932 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
1933 x = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
1934 errno = 0;
1936 if (setpriority(PRIO_PROCESS, 0, x) == -1) {
1937 log_write("setpriority(): %s", strerror(errno));
1938 goto do_exit;
1942 #ifdef HAVE_MLOCKALL
1943 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
1944 log_write("mlockall(): %s", strerror(errno));
1945 goto do_exit;
1947 #endif
1949 if (convert) {
1950 if (!outfile)
1951 usage(argv[0]);
1953 opt = convert_file(convert, keyfile, outfile);
1954 g_key_file_free(keyfileh);
1955 g_free(rcfile);
1956 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
1959 if (import) {
1960 if (!outfile)
1961 usage(argv[0]);
1963 if (cmd_iterations == -1)
1964 cmd_iterations = (guint64)get_key_file_integer("global", "iterations");
1966 opt = xml_import(import, outfile, keyfile, cmd_iterations);
1967 g_key_file_free(keyfileh);
1968 g_free(rcfile);
1969 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
1972 g_key_file_set_list_separator(keyfileh, ',');
1974 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
1975 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
1977 socketarg = expand_homedir(p);
1978 g_free(p);
1980 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
1981 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
1983 datadir = expand_homedir(p);
1984 g_free(p);
1986 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
1987 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
1988 disable_list_and_dump = n;
1990 else
1991 disable_list_and_dump = secure;
1993 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
1994 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
1995 else
1996 default_timeout = -1;
1998 setup_logging(keyfileh);
2000 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2001 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2003 if (argc != optind) {
2004 for (; optind < argc; optind++) {
2005 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2006 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
2010 if (strchr(socketarg, '/') == NULL) {
2011 socketdir = g_get_current_dir();
2012 socketname = g_strdup(socketarg);
2013 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2015 else {
2016 socketname = g_strdup(strrchr(socketarg, '/'));
2017 socketname++;
2018 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2019 socketdir = g_strdup(socketarg);
2020 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2023 if (chdir(datadir)) {
2024 log_write("%s: %s", datadir, strerror(errno));
2025 unlink(socketpath);
2026 goto do_exit;
2029 if (parse_rcfile_keys() == FALSE)
2030 goto do_exit;
2032 clear_rcfile_keys();
2035 * Set the cache entry for a file. Prompts for the password.
2037 if (cache_push) {
2038 for (opt = 0; cache_push[opt]; opt++)
2039 do_cache_push(cache_push[opt], NULL);
2041 g_strfreev(cache_push);
2042 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2046 * bind() doesn't like the full pathname of the socket or any non alphanum
2047 * characters so change to the directory where the socket is wanted then
2048 * create it then change to datadir.
2050 if (chdir(socketdir)) {
2051 log_write("%s: %s", socketdir, strerror(errno));
2052 goto do_exit;
2055 g_free(socketdir);
2057 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2058 log_write("socket(): %s", strerror(errno));
2059 goto do_exit;
2062 addr.sun_family = AF_UNIX;
2063 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2065 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2066 log_write("bind(): %s", strerror(errno));
2068 if (errno == EADDRINUSE)
2069 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2070 "stale socket. Please remove it manually."), socketpath);
2072 do_unlink = 0;
2073 goto do_exit;
2076 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2077 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2078 mode_t mode = strtol(t, NULL, 8);
2079 mode_t mask = umask(0);
2081 g_free(t);
2083 if (chmod(socketname, mode) == -1) {
2084 log_write("%s: %s", socketname, strerror(errno));
2085 close(sockfd);
2086 unlink(socketpath);
2087 umask(mask);
2088 goto do_exit;
2091 umask(mask);
2094 g_free(--socketname);
2096 if (chdir(datadir)) {
2097 log_write("%s: %s", datadir, strerror(errno));
2098 close(sockfd);
2099 unlink(socketpath);
2100 goto do_exit;
2103 g_free(datadir);
2105 if (listen(sockfd, 0) == -1) {
2106 log_write("listen(): %s", strerror(errno));
2107 goto do_exit;
2110 cmdline = FALSE;
2112 if (background) {
2113 switch (fork()) {
2114 case -1:
2115 log_write("fork(): %s", strerror(errno));
2116 goto do_exit;
2117 case 0:
2118 close(0);
2119 close(1);
2120 close(2);
2121 setsid();
2122 break;
2123 default:
2124 exit(EXIT_SUCCESS);
2128 server_loop(sockfd, &socketpath);
2129 estatus = EXIT_SUCCESS;
2131 do_exit:
2132 if (socketpath && do_unlink) {
2133 unlink(socketpath);
2134 g_free(socketpath);
2137 g_key_file_free(keyfileh);
2138 g_free(rcfile);
2139 xmlCleanupParser();
2140 xmlCleanupGlobals();
2142 if (estatus == EXIT_SUCCESS)
2143 log_write(N_("pwmd exiting normally"));
2145 #if defined(DEBUG) && !defined(MEM_DEBUG)
2146 xdump();
2147 #endif
2148 exit(estatus);