Added command line option -i to specify the number of encryption
[pwmd.git] / src / pwmd.c
blobb4a12a46fa27679b73d7c56b0e348639cdd9ed79
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006-2008 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 02111-1307 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>
46 #ifdef HAVE_SETRLIMIT
47 #include <sys/time.h>
48 #include <sys/resource.h>
49 #endif
51 #ifndef MEM_DEBUG
52 #include "mem.h"
53 #endif
55 #include "xml.h"
56 #include "common.h"
58 #ifdef WITH_PINENTRY
59 #include "pinentry.h"
60 #endif
62 #include "commands.h"
63 #include "pwmd_error.h"
64 #include "cache.h"
65 #include "misc.h"
66 #include "pwmd.h"
68 static void clear_errorfile_key()
70 gsize n;
71 gchar **groups;
72 gchar **p;
74 groups = g_key_file_get_groups(keyfileh, &n);
76 for (p = groups; *p; p++) {
77 GError *rc = NULL;
79 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE)
80 g_key_file_set_string(keyfileh, *p, "key", "");
83 g_strfreev(groups);
86 static void reload_rcfile()
88 log_write(N_("reloading configuration file '%s'"), rcfile);
89 g_key_file_free(keyfileh);
90 keyfileh = parse_rcfile(0);
91 clear_errorfile_key();
94 gpg_error_t send_syserror(assuan_context_t ctx, gint e)
96 gpg_error_t n = gpg_error_from_errno(e);
98 return assuan_process_done(ctx, assuan_set_error(ctx, n, gpg_strerror(n)));
101 gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e)
103 gpg_err_code_t n = gpg_err_code(e);
104 gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n);
105 struct client_s *client = assuan_get_pointer(ctx);
107 if (!e)
108 return assuan_process_done(ctx, 0);
110 if (!ctx) {
111 log_write("%s\n", pwmd_strerror(e));
112 return e;
115 if (n == EPWMD_LIBXML_ERROR) {
116 xmlErrorPtr xe = client->xml_error;
118 if (!xe)
119 xe = xmlGetLastError();
121 e = assuan_process_done(ctx, assuan_set_error(ctx, code, xe->message));
122 log_write("%s", xe->message);
124 if (xe == client->xml_error)
125 xmlResetError(xe);
126 else
127 xmlResetLastError();
129 client->xml_error = NULL;
130 return e;
133 return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e)));
136 void log_write(const gchar *fmt, ...)
138 gchar *args, *line;
139 va_list ap;
140 struct tm *tm;
141 time_t now;
142 gchar tbuf[21];
143 gint fd = -1;
144 pth_attr_t attr;
145 gchar *name;
147 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
148 return;
150 if (logfile) {
151 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
152 warn(N_("logfile"));
153 return;
157 va_start(ap, fmt);
159 if (g_vasprintf(&args, fmt, ap) == -1) {
160 if (logfile)
161 close(fd);
163 va_end(ap);
164 return;
167 attr = pth_attr_of(pth_self());
168 pth_attr_get(attr, PTH_ATTR_NAME, &name);
169 pth_attr_destroy(attr);
171 if (log_syslog == TRUE)
172 syslog(LOG_INFO, "%s: %s", name, args);
174 va_end(ap);
175 time(&now);
176 tm = localtime(&now);
177 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
178 tbuf[sizeof(tbuf) - 1] = 0;
180 if (args[strlen(args)-1] == '\n')
181 args[strlen(args)-1] = 0;
183 line = g_strdup_printf("%s %i %s: %s\n", tbuf, getpid(), name, args);
184 g_free(args);
186 if (!line) {
187 if (logfile)
188 close(fd);
190 return;
193 if (logfile) {
194 write(fd, line, strlen(line));
195 fsync(fd);
196 close(fd);
199 if (isatty(STDERR_FILENO)) {
200 fprintf(stderr, "%s", line);
201 fflush(stderr);
204 g_free(line);
207 static void usage(gchar *pn)
209 g_printf(N_(
210 "Usage: %s [-hvDb] [-f <rcfile>] [-I <filename> [-i <iter>] [file1] [...]\n"
211 " -b run as a background process\n"
212 " -f load the specified rcfile (~/.pwmd/config)\n"
213 " -I import an XML file and write the encrypted data to stdout\n"
214 " -i encrypt with the specified number of iterations when importing\n"
215 " (config default in the \"global\" section)\n"
216 " -D disable use of the LIST and DUMP commands\n"
217 " -v version\n"
218 " -h this help text\n"
219 ), pn);
220 exit(EXIT_SUCCESS);
223 #ifndef MEM_DEBUG
224 static int gcry_SecureCheck(const void *ptr)
226 return 1;
228 #endif
230 static void setup_gcrypt()
232 gcry_check_version(NULL);
234 #ifndef MEM_DEBUG
235 gcry_set_allocation_handler(xmalloc, xmalloc, gcry_SecureCheck, xrealloc,
236 xfree);
237 #endif
239 if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, NULL,
240 NULL) != 0)
241 errx(EXIT_FAILURE, N_("Required AES cipher not supported by libgcrypt."));
243 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_KEYLEN, NULL, &gcrykeysize);
244 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_BLKLEN, NULL, &gcryblocksize);
247 static assuan_context_t new_connection(gint fd)
249 gpg_error_t rc;
250 gchar ver[ASSUAN_LINELENGTH];
251 assuan_context_t ctx;
253 rc = assuan_init_socket_server_ext(&ctx, fd, 2);
255 if (rc)
256 goto fail;
258 g_snprintf(ver, sizeof(ver), "%s", PACKAGE_STRING);
259 assuan_set_hello_line(ctx, ver);
260 assuan_register_post_cmd_notify(ctx, command_finalize);
261 rc = register_commands(ctx);
263 if (rc)
264 goto fail;
266 rc = assuan_accept(ctx);
268 if (rc)
269 goto fail;
271 return ctx;
273 fail:
274 assuan_deinit_server(ctx);
275 log_write("%s", gpg_strerror(rc));
276 return NULL;
279 void send_cache_status_all()
281 guint i, t;
283 pth_mutex_acquire(&cn_mutex, FALSE, NULL);
285 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
286 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
288 if (cn->tid == pth_self()) {
289 send_cache_status(cn->cl->ctx);
290 continue;
293 pth_raise(cn->tid, SIGUSR2);
296 pth_mutex_release(&cn_mutex);
299 static void *keepalive_thread(void *arg)
301 struct client_thread_s *thd = arg;
303 for (;;) {
304 gpg_error_t rc;
305 pth_event_t ev;
306 gint k = get_key_file_integer("global", "keepalive");
308 ev = pth_event(PTH_EVENT_TIME, pth_timeout(k <= 0 ? 1 : k, 0));
309 pth_wait(ev);
310 pth_event_free(ev, PTH_FREE_THIS);
311 pth_cancel_point();
313 if (k <= 0)
314 continue;
316 rc = assuan_write_status(thd->cl->ctx, "KEEPALIVE", NULL);
318 if (rc) {
319 log_write("%s", gpg_strerror(rc));
320 pth_raise(thd->tid, SIGQUIT);
321 break;
325 return NULL;
328 static void xml_error_cb(void *data, xmlErrorPtr e)
330 struct client_s *client = data;
333 * Keep the first reported error as the one to show. Reset in
334 * send_error().
336 if (client->xml_error)
337 return;
339 xmlCopyError(e, client->xml_error);
343 * Called every time a connection is made via pth_spawn(). This is the thread
344 * entry point.
346 static void *client_thread(void *data)
348 struct client_thread_s *thd = data;
349 gint fd = thd->fd;
350 pth_event_t ev;
351 #ifdef WITH_PINENTRY
352 pth_event_t pinentry_ev = NULL;
353 #endif
354 struct client_s *cl = g_malloc0(sizeof(struct client_s));
355 sigset_t set;
356 gpg_error_t rc;
357 pth_attr_t attr;
359 if (!cl) {
360 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
361 goto fail;
364 #ifdef WITH_PINENTRY
365 cl->pinentry = g_malloc0(sizeof(struct pinentry_s));
367 if (!cl->pinentry) {
368 g_free(cl);
369 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
370 goto fail;
373 set_pinentry_defaults(cl->pinentry);
374 #endif
375 thd->cl = cl;
376 cl->thd = thd;
379 * This is a "child" thread. Don't catch any signals. Let the master
380 * thread take care of signals in server_loop().
382 sigfillset(&set);
383 pth_sigmask(SIG_BLOCK, &set, NULL);
384 sigemptyset(&set);
385 /* Sends a cache status message to the client. */
386 sigaddset(&set, SIGUSR2);
387 /* Terminates this thread. Raised from keepalive_thread(). */
388 sigaddset(&set, SIGQUIT);
390 cl->ctx = new_connection(fd);
391 cl->fd = fd;
393 if (!cl->ctx)
394 goto fail;
396 assuan_set_pointer(cl->ctx, cl);
398 #ifdef HAVE_MLOCKALL
399 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
400 log_write("mlockall(): %s", strerror(errno));
401 goto fail;
403 #endif
405 rc = send_cache_status(cl->ctx);
407 if (rc) {
408 log_write("%s", gpg_strerror(rc));
409 goto fail;
412 ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, cl->fd);
413 attr = pth_attr_new();
414 pth_attr_init(attr);
415 pth_attr_set(attr, PTH_ATTR_NAME, "keepalive");
416 thd->keepalive_tid = pth_spawn(attr, keepalive_thread, thd);
417 pth_attr_destroy(attr);
418 xmlInitParser();
419 xmlXPathInit();
420 xmlSetStructuredErrorFunc(cl, xml_error_cb);
422 for (;;) {
423 gint sig = 0;
425 pth_sigwait_ev(&set, &sig, ev);
427 if (sig > 0) {
428 switch (sig) {
429 case SIGUSR2:
430 rc = send_cache_status(cl->ctx);
432 if (rc) {
433 log_write("%s", gpg_strerror(rc));
434 goto done;
437 break;
438 case SIGQUIT:
439 /* pth_raise() from keepalive_thread(). */
440 goto done;
441 default:
442 break;
446 pth_event_isolate(ev);
448 if (pth_event_occurred(ev)) {
449 rc = assuan_process_next(cl->ctx);
451 if (rc) {
452 cl->inquire_status = INQUIRE_INIT;
454 if (gpg_err_code(rc) == GPG_ERR_EOF)
455 goto done;
457 log_write("assuan_process_next(): %s", gpg_strerror(rc));
458 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
460 if (rc) {
461 log_write("assuan_process_done(): %s", gpg_strerror(rc));
462 goto done;
465 else {
466 #ifdef WITH_PINENTRY
467 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT) {
468 pinentry_ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, cl->pinentry->fd);
469 pth_event_concat(ev, pinentry_ev, NULL);
470 cl->pinentry->status = PINENTRY_RUNNING;
472 #endif
474 switch (cl->inquire_status) {
475 case INQUIRE_BUSY:
476 case INQUIRE_INIT:
477 break;
478 case INQUIRE_DONE:
479 cl->inquire_status = INQUIRE_INIT;
480 rc = assuan_process_done(cl->ctx, 0);
481 break;
486 #ifdef WITH_PINENTRY
487 if (cl->pinentry->status == PINENTRY_RUNNING) {
488 pth_event_isolate(pinentry_ev);
490 if (pth_event_occurred(pinentry_ev)) {
491 guchar shakey[gcrykeysize];
492 pinentry_key_s pk;
493 gsize len = pth_read(cl->pinentry->fd, &pk, sizeof(pk));
494 gint status;
496 pth_event_free(pinentry_ev, PTH_FREE_THIS);
497 pinentry_ev = NULL;
498 cl->pinentry->status = PINENTRY_NONE;
500 if (len == sizeof(pk)) {
501 if (pk.error)
502 rc = send_error(cl->ctx, pk.error);
503 else {
504 gcry_md_hash_buffer(GCRY_MD_SHA256, shakey, pk.key,
505 strlen(pk.key) == 0 ? 1 : strlen(pk.key));
506 rc = cl->pinentry->cb(cl->ctx, shakey, FALSE);
507 memset(shakey, 0, sizeof(shakey));
510 else if (len == -1)
511 log_write("%s", strerror(errno));
512 else if (len == 0)
513 log_write("pth_read(): EOF");
514 else
515 log_write(N_("pth_read(): short byte count"));
517 pth_waitpid(cl->pinentry->pid, &status, 0);
518 close(cl->pinentry->fd);
519 cl->pinentry->fd = -1;
520 cl->pinentry->pid = 0;
522 if (pk.error && cl->pinentry->which == PINENTRY_OPEN)
523 cleanup_client(cl);
524 else
525 unlock_file_mutex(cl);
527 memset(&pk, 0, sizeof(pk));
528 unlock_pin_mutex(cl->pinentry);
531 pth_event_concat(ev, pinentry_ev, NULL);
533 #endif
537 * Client cleanup (including XML data) is done in remove_connection() from
538 * the cleanup thread.
540 done:
541 pth_event_free(ev, PTH_FREE_ALL);
543 fail:
544 log_write(N_("exiting, fd=%i"), thd->fd);
545 pth_exit(NULL);
546 return NULL;
549 static void setup_logging(GKeyFile *kf)
551 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
553 if (n == TRUE) {
554 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
556 if (*p == '~') {
557 gchar buf[PATH_MAX];
559 p++;
560 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
561 g_free(p);
563 if (logfile)
564 g_free(logfile);
566 logfile = g_strdup(buf);
568 else {
569 if (logfile)
570 g_free(logfile);
572 logfile = p;
576 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
580 * Make sure all settings are set to either the specified setting or a
581 * default.
583 static void set_rcfile_defaults(GKeyFile *kf)
585 gchar buf[PATH_MAX];
587 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
588 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
589 g_key_file_set_string(kf, "global", "socket_path", buf);
592 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
593 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
594 g_key_file_set_string(kf, "global", "data_directory", buf);
597 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
598 g_key_file_set_boolean(kf, "global", "backup", TRUE);
600 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
601 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
602 g_key_file_set_string(kf, "global", "log_path", buf);
605 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
606 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
608 if (g_key_file_has_key(kf, "global", "cache_size", NULL) == FALSE)
609 g_key_file_set_integer(kf, "global", "cache_size", cache_size);
611 #ifdef HAVE_MLOCKALL
612 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
613 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
614 #endif
616 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
617 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
619 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE)
620 g_key_file_set_integer(kf, "global", "iterations", 0);
622 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
623 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
625 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
626 g_key_file_set_integer(kf, "global", "iteration_progress", 0);
628 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
629 g_key_file_set_integer(kf, "global", "compression_level", 6);
631 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
632 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
634 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
635 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
637 zlib_bufsize = g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
639 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
640 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
642 #ifdef HAVE_MLOCKALL
643 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
644 #endif
646 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
647 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
649 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
650 g_key_file_set_integer(kf, "global", "keepalive", 5);
652 #ifdef WITH_PINENTRY
653 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
654 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
655 #endif
657 setup_logging(kf);
660 static GKeyFile *parse_rcfile(int cmdline)
662 GKeyFile *kf = g_key_file_new();
663 GError *rc = NULL;
665 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
666 log_write("%s: %s", rcfile, rc->message);
668 if (cmdline)
669 exit(EXIT_FAILURE);
671 if (rc->code == G_FILE_ERROR_NOENT) {
672 g_clear_error(&rc);
673 set_rcfile_defaults(kf);
674 return kf;
677 g_clear_error(&rc);
678 return NULL;
680 else
681 set_rcfile_defaults(kf);
683 return kf;
686 static gchar *get_password(const gchar *prompt)
688 gchar buf[LINE_MAX] = {0}, *p;
689 struct termios told, tnew;
690 gchar *key;
692 if (tcgetattr(STDIN_FILENO, &told) == -1)
693 err(EXIT_FAILURE, "tcgetattr()");
695 memcpy(&tnew, &told, sizeof(struct termios));
696 tnew.c_lflag &= ~(ECHO);
697 tnew.c_lflag |= ICANON|ECHONL;
699 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
700 tcsetattr(STDIN_FILENO, TCSANOW, &told);
701 err(EXIT_FAILURE, "tcsetattr()");
704 fprintf(stderr, "%s", prompt);
706 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
707 tcsetattr(STDIN_FILENO, TCSANOW, &told);
708 return NULL;
711 tcsetattr(STDIN_FILENO, TCSANOW, &told);
712 p[strlen(p) - 1] = 0;
714 if (!buf[0]) {
715 key = gcry_malloc(1);
716 key[0] = 0;
718 else {
719 key = gcry_malloc(strlen(p) + 1);
720 sprintf(key, "%s", p);
723 memset(&buf, 0, sizeof(buf));
724 return key;
727 static gboolean do_try_xml_decrypt(const gchar *filename, guchar *key)
729 int fd;
730 struct stat st;
731 gpg_error_t rc;
733 if ((fd = open_file(filename, &st)) == -1) {
734 warn("%s", filename);
735 return FALSE;
738 if (st.st_size == 0) {
739 warnx(N_("%s: skipping empty file"), filename);
740 close(fd);
741 return FALSE;
744 rc = try_xml_decrypt(NULL, fd, st, key);
745 close(fd);
746 return rc ? FALSE : TRUE;
749 static gboolean get_input(const gchar *filename, guchar *key)
751 gint try = 0;
752 gchar *password;
753 gchar *prompt;
755 prompt = g_strdup_printf(N_("Password for '%s': "), filename);
757 again:
758 if ((password = get_password(prompt)) == NULL) {
759 warnx(N_("%s: skipping file"), filename);
760 g_free(prompt);
761 return FALSE;
764 gcry_md_hash_buffer(GCRY_MD_SHA256, key, password, strlen(password) ? strlen(password) : 1);
765 gcry_free(password);
767 if (do_try_xml_decrypt(filename, key) == FALSE) {
768 if (try++ == 2) {
769 warnx(N_("%s: invalid password, skipping"), filename);
770 g_free(prompt);
771 return FALSE;
773 else {
774 warnx(N_("%s: invalid password"), filename);
775 goto again;
779 g_free(prompt);
780 return TRUE;
783 static gboolean xml_import(const gchar *filename, gint iter)
785 xmlDocPtr doc;
786 gint fd;
787 struct stat st;
788 gint len;
789 xmlChar *xmlbuf;
790 xmlChar *xml;
791 gchar *key = NULL;
792 gchar *key2 = NULL;
793 guchar shakey[gcrykeysize];
794 gcry_cipher_hd_t gh;
795 gpg_error_t rc;
796 gint level;
797 glong outsize;
798 gpointer outbuf;
799 gint zrc;
801 if (stat(filename, &st) == -1) {
802 warn("%s", filename);
803 return FALSE;
806 if ((rc = gcry_cipher_open(&gh, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0))) {
807 send_error(NULL, rc);
808 gcry_cipher_close(gh);
809 log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(rc));
810 return FALSE;
813 if (iter == -1)
814 goto done;
816 if ((key = get_password(N_("New password: "))) == NULL) {
817 fprintf(stderr, "%s\n", N_("Invalid password."));
818 gcry_cipher_close(gh);
819 return FALSE;
822 if ((key2 = get_password(N_("Verify password: "))) == NULL) {
823 fprintf(stderr, "%s\n", N_("Passwords do not match."));
824 gcry_free(key);
825 gcry_cipher_close(gh);
826 return FALSE;
829 if (g_utf8_collate(key, key2) != 0) {
830 fprintf(stderr, "%s\n", N_("Passwords do not match."));
831 gcry_free(key);
832 gcry_free(key2);
833 gcry_cipher_close(gh);
834 return FALSE;
837 gcry_free(key2);
839 done:
840 if ((fd = open(filename, O_RDONLY)) == -1) {
841 gcry_free(key);
842 warn("%s", filename);
843 gcry_cipher_close(gh);
844 return FALSE;
847 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
848 gcry_free(key);
849 close(fd);
850 log_write("%s", strerror(ENOMEM));
851 gcry_cipher_close(gh);
852 return FALSE;
855 if (read(fd, xmlbuf, st.st_size) == -1) {
856 rc = errno;
857 close(fd);
858 gcry_free(key);
859 gcry_cipher_close(gh);
860 errno = rc;
861 err(EXIT_FAILURE, "read()");
864 close(fd);
865 xmlbuf[st.st_size] = 0;
868 * Make sure the document validates.
870 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
871 log_write("xmlReadDoc()");
872 close(fd);
873 gcry_free(key);
874 gcry_free(xmlbuf);
875 gcry_cipher_close(gh);
876 return FALSE;
879 gcry_free(xmlbuf);
880 xmlDocDumpMemory(doc, &xml, &len);
881 xmlFreeDoc(doc);
883 level = get_key_file_integer(filename, "compression_level");
885 if (level < 0)
886 level = 0;
888 if (do_compress(NULL, level, xml, len, &outbuf, &outsize, &zrc) == FALSE) {
889 memset(shakey, 0, sizeof(shakey));
890 gcry_free(xml);
892 if (zrc == Z_MEM_ERROR)
893 warnx("%s", strerror(ENOMEM));
894 else
895 warnx("do_compress() failed");
897 gcry_cipher_close(gh);
898 return FALSE;
900 else {
901 gcry_free(xml);
902 xml = outbuf;
903 len = outsize;
906 if (iter == -1)
907 memset(shakey, '!', sizeof(shakey));
908 else{
909 gcry_md_hash_buffer(GCRY_MD_SHA256, shakey, key, strlen(key) ? strlen(key) : 1);
910 gcry_free(key);
913 rc = do_xml_encrypt(NULL, gh, NULL, xml, len, shakey, iter);
914 gcry_cipher_close(gh);
916 if (rc) {
917 memset(shakey, 0, sizeof(shakey));
918 warnx("%s", gpg_strerror(rc));
919 return FALSE;
922 memset(shakey, 0, sizeof(shakey));
923 return TRUE;
926 gchar *get_key_file_string(const gchar *section, const gchar *what)
928 gchar *val = NULL;
929 GError *grc = NULL;
931 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
932 val = g_key_file_get_string(keyfileh, section, what, &grc);
934 if (grc) {
935 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
936 g_clear_error(&grc);
939 else {
940 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
941 val = g_key_file_get_string(keyfileh, "global", what, &grc);
943 if (grc) {
944 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
945 g_clear_error(&grc);
950 return val;
953 gint get_key_file_integer(const gchar *section, const gchar *what)
955 gint val = -1;
956 GError *grc = NULL;
958 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
959 val = g_key_file_get_integer(keyfileh, section, what, &grc);
961 if (grc) {
962 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
963 g_clear_error(&grc);
966 else {
967 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
968 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
970 if (grc) {
971 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
972 g_clear_error(&grc);
977 return val;
980 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
982 gboolean val = FALSE;
983 GError *grc = NULL;
985 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
986 val = g_key_file_get_boolean(keyfileh, section, what, &grc);
988 if (grc) {
989 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
990 g_clear_error(&grc);
993 else {
994 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
995 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
997 if (grc) {
998 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
999 g_clear_error(&grc);
1004 return val;
1007 static gboolean _getline(const gchar *file, gchar **result)
1009 FILE *fp;
1010 gchar buf[LINE_MAX] = {0}, *p;
1011 gchar *str = NULL;
1012 gint len;
1014 if ((fp = fopen(file, "r")) == NULL) {
1015 warn("%s", file);
1016 return FALSE;
1019 p = fgets(buf, sizeof(buf), fp);
1020 fclose(fp);
1021 len = strlen(buf);
1023 if (len && buf[len - 1] == '\n')
1024 buf[--len] = 0;
1026 str = gcry_malloc(len + 1);
1027 memcpy(str, buf, len ? len : 1);
1028 str[len] = 0;
1029 memset(&buf, 0, sizeof(buf));
1030 *result = str;
1031 return TRUE;
1034 static gboolean parse_keyfile_key()
1036 gsize n;
1037 gchar **groups;
1038 gchar **p;
1039 gchar *str;
1041 groups = g_key_file_get_groups(keyfileh, &n);
1043 for (p = groups; *p; p++) {
1044 GError *rc = NULL;
1046 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE) {
1047 str = g_key_file_get_string(keyfileh, *p, "key", &rc);
1049 if (!str) {
1050 if (rc) {
1051 warnx("%s", rc->message);
1052 g_clear_error(&rc);
1055 continue;
1058 do_cache_push(*p, str);
1059 g_free(str);
1060 continue;
1063 if (rc) {
1064 warnx("%s", rc->message);
1065 g_clear_error(&rc);
1066 continue;
1069 if (g_key_file_has_key(keyfileh, *p, "key_file", &rc) == TRUE) {
1070 gchar *t;
1071 gchar *file = g_key_file_get_string(keyfileh, *p, "key_file", &rc);
1073 if (!file) {
1074 if (rc) {
1075 warnx("%s", rc->message);
1076 g_clear_error(&rc);
1079 continue;
1082 t = expand_homedir(file);
1083 g_free(file);
1084 file = t;
1086 if (_getline(file, &str) == FALSE) {
1087 g_free(file);
1088 continue;
1091 g_free(file);
1092 do_cache_push(*p, str);
1093 gcry_free(str);
1094 continue;
1097 if (rc) {
1098 warnx("%s", rc->message);
1099 g_clear_error(&rc);
1103 g_strfreev(groups);
1104 return TRUE;
1107 static gboolean do_cache_push(const gchar *filename, const gchar *password)
1109 guchar *md5file;
1110 guchar *key;
1111 gint timeout;
1112 const gchar *p = filename;
1113 file_header_t file_header;
1114 gpg_error_t rc;
1116 while (isspace(*p))
1117 p++;
1119 if (!*p)
1120 return FALSE;
1122 if (valid_filename(p) == FALSE) {
1123 warnx(N_("%s: invalid characters in filename"), p);
1124 return FALSE;
1127 md5file = gcry_malloc(16);
1128 key = gcry_malloc(gcrykeysize);
1129 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1131 if (cache_iscached(md5file) == TRUE) {
1132 warnx(N_("%s: file already cached, skipping"), p);
1133 gcry_free(md5file);
1134 gcry_free(key);
1135 return FALSE;
1138 if (access(p, R_OK|W_OK) != 0) {
1139 gcry_free(md5file);
1140 gcry_free(key);
1142 if (errno != ENOENT) {
1143 warn("%s", p);
1144 return FALSE;
1147 warn("%s", p);
1148 return TRUE;
1151 rc = read_file_header(filename, &file_header);
1153 if (rc) {
1154 gcry_free(md5file);
1155 gcry_free(key);
1156 warnx("%s", pwmd_strerror(rc));
1157 return FALSE;
1160 if (file_header.iter == -1) {
1161 memset(key, '!', gcrykeysize);
1162 goto try_decrypt;
1165 if (!password) {
1166 #ifdef WITH_PINENTRY
1167 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL) == FALSE) {
1168 #endif
1169 if (get_input(p, key) == FALSE) {
1170 gcry_free(key);
1171 gcry_free(md5file);
1172 return FALSE;
1174 #ifdef WITH_PINENTRY
1176 else {
1177 gchar *result = NULL;
1178 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
1179 gint try = 0;
1181 pin->which = PINENTRY_OPEN;
1182 pin->filename = g_strdup(filename);
1183 again:
1184 rc = pinentry_getpin(pin, &result);
1186 if (rc) {
1187 warnx("%s: %s", filename, gpg_strerror(rc));
1188 cleanup_pinentry(pin);
1189 gcry_free(key);
1190 gcry_free(md5file);
1191 xfree(result);
1192 return FALSE;
1195 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, strlen(result) ? strlen(result) : 1);
1196 xfree(result);
1198 if (do_try_xml_decrypt(filename, key) == FALSE) {
1199 if (try++ == 2) {
1200 cleanup_pinentry(pin);
1201 gcry_free(key);
1202 gcry_free(md5file);
1203 warnx(N_("%s: invalid password, skipping"), filename);
1204 return FALSE;
1206 else {
1207 g_free(pin->title);
1208 pin->title = g_strdup(N_("Incorrect password. Please try again."));
1209 goto again;
1213 cleanup_pinentry(pin);
1215 #endif
1217 else {
1218 gcry_md_hash_buffer(GCRY_MD_SHA256, key, password, strlen(password) ? strlen(password) : 1);
1220 try_decrypt:
1221 if (do_try_xml_decrypt(filename, key) == FALSE) {
1222 warnx(N_("%s: invalid password, skipping"), filename);
1223 gcry_free(key);
1224 gcry_free(md5file);
1225 return FALSE;
1229 if (cache_add_file(md5file, key) == FALSE) {
1230 warnx("%s: %s", p, pwmd_strerror(EPWMD_MAX_SLOTS));
1231 gcry_free(key);
1232 gcry_free(md5file);
1233 return FALSE;
1236 timeout = get_key_file_integer(p, "cache_timeout");
1237 cache_set_timeout(md5file, timeout);
1238 warnx(N_("%s: file added to the cache"), filename);
1239 gcry_free(key);
1240 gcry_free(md5file);
1241 return TRUE;
1244 static GSList *remove_connection(GSList *list, struct client_thread_s *cn)
1246 gpointer value;
1247 struct client_s *cl = cn->cl;
1249 if (cn->keepalive_tid) {
1250 pth_cancel(cn->keepalive_tid);
1251 pth_join(cn->keepalive_tid, &value);
1254 log_write("%p", cn->tid);
1255 pth_join(cn->tid, &value);
1257 if (cl->freed == FALSE)
1258 cleanup_assuan(cl->ctx);
1260 if (cl->ctx)
1261 assuan_deinit_server(cl->ctx);
1263 #ifdef WITH_PINENTRY
1264 if (cl->pinentry)
1265 cleanup_pinentry(cl->pinentry);
1266 #endif
1268 g_free(cl);
1269 pth_event_isolate(cn->ev);
1270 pth_event_free(cn->ev, PTH_FREE_THIS);
1271 list = g_slist_remove(list, cn);
1272 g_free(cn);
1273 return list;
1277 * Can't pth_event_concat() to an empty event.
1279 static int event_ring_hack(void *data)
1281 return FALSE;
1285 * See if any thread has entered the DEAD queue and remove it.
1287 static GSList *cleanup_dead_queue(GSList *threads, pth_event_t tid_events)
1289 guint n, i;
1291 for (n = g_slist_length(threads), i = 0; i < n; i++) {
1292 struct client_thread_s *cn = g_slist_nth_data(threads, i);
1294 if (pth_event_occurred(cn->ev)) {
1295 threads = remove_connection(threads, cn);
1296 return cleanup_dead_queue(threads, tid_events);
1299 pth_event_concat(tid_events, cn->ev, NULL);
1302 return threads;
1305 static void *accept_thread(void *arg)
1307 gint sockfd = (gint)arg;
1309 for (;;) {
1310 socklen_t slen = sizeof(struct sockaddr_un);
1311 struct sockaddr_un raddr;
1312 gint fd = -1;
1313 pth_attr_t attr;
1315 if ((fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen)) == -1) {
1316 if (errno != EAGAIN) {
1317 if (!quit) // probably EBADF
1318 log_write("accept(): %s", strerror(errno));
1320 break;
1324 if (fd >= 0) {
1325 pth_t tid;
1326 struct client_thread_s *new;
1327 gchar buf[41];
1329 new = g_malloc0(sizeof(struct client_thread_s));
1331 if (!new) {
1332 log_write("%s", strerror(ENOMEM));
1333 continue;
1337 * Thread priority is inherited from the calling thread. This
1338 * thread is PTH_PRIO_MAX. Keep the "child" threads at standard
1339 * priority.
1341 new->fd = fd;
1342 attr = pth_attr_new();
1343 pth_attr_set(attr, PTH_ATTR_PRIO, PTH_PRIO_STD);
1344 tid = pth_spawn(attr, client_thread, new);
1345 pth_attr_destroy(attr);
1347 if (!tid) {
1348 g_free(new);
1349 log_write(N_("pth_spawn() failed"));
1350 continue;
1353 g_snprintf(buf, sizeof(buf), "%p", tid);
1354 log_write(N_("new tid=%s, fd=%i"), buf, fd);
1355 attr = pth_attr_of(tid);
1356 pth_attr_set(attr, PTH_ATTR_NAME, buf);
1357 pth_attr_destroy(attr);
1358 new->tid = tid;
1359 new->ev = pth_event(PTH_EVENT_TID|PTH_UNTIL_TID_DEAD, tid);
1360 pth_mutex_acquire(&cn_mutex, FALSE, NULL);
1361 pth_event_concat(cn_events, new->ev, NULL);
1362 cn_thread_list = g_slist_append(cn_thread_list, new);
1363 pth_mutex_release(&cn_mutex);
1367 /* Just in case pth_accept() failed for some reason other than EBADF */
1368 quit = 1;
1369 pth_exit(PTH_CANCELED);
1370 return NULL;
1374 * There needs to be a pth_timeout() here so pth_wait() can wait for new
1375 * cn_events which is updated from cleanup_dead_queue().
1377 static void *cleanup_thread(void *arg)
1379 cn_events = pth_event(PTH_EVENT_TIME, pth_timeout(0, 500000));
1381 for (;;) {
1382 if (pth_wait(cn_events) && pth_event_occurred(cn_events)) {
1383 pth_event_isolate(cn_events);
1384 pth_event_free(cn_events, PTH_FREE_THIS);
1385 pth_cancel_point();
1386 pth_mutex_acquire(&cn_mutex, FALSE, NULL);
1387 cn_events = pth_event(PTH_EVENT_TIME, pth_timeout(0, 500000));
1388 cn_thread_list = cleanup_dead_queue(cn_thread_list, cn_events);
1389 pth_mutex_release(&cn_mutex);
1393 return NULL;
1397 * This thread isn't joinable. For operations that block, these threads will
1398 * stack.
1400 static void *adjust_timer_thread(void *arg)
1402 CACHE_LOCK(NULL);
1403 cache_adjust_timer();
1404 CACHE_UNLOCK;
1405 return NULL;
1408 static void server_loop(gint sockfd, gchar **socketpath)
1410 pth_t accept_tid, cleanup_tid;
1411 guint n, i;
1412 sigset_t set;
1413 gint n_clients = 0;
1414 pth_attr_t attr;
1415 pth_event_t timeout_event;
1416 gpointer value;
1418 pth_mutex_init(&cn_mutex);
1419 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1421 sigemptyset(&set);
1422 sigaddset(&set, SIGTERM);
1423 sigaddset(&set, SIGINT);
1424 sigaddset(&set, SIGUSR1);
1425 sigaddset(&set, SIGHUP);
1426 sigaddset(&set, SIGABRT);
1428 attr = pth_attr_new();
1429 pth_attr_init(attr);
1430 pth_attr_set(attr, PTH_ATTR_PRIO, PTH_PRIO_MAX);
1431 pth_attr_set(attr, PTH_ATTR_NAME, "accept");
1432 accept_tid = pth_spawn(attr, accept_thread, (void *)sockfd);
1433 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1434 pth_attr_set(attr, PTH_ATTR_CANCEL_STATE, PTH_CANCEL_ASYNCHRONOUS);
1435 pth_attr_set(attr, PTH_ATTR_NAME, "cleanup");
1436 cleanup_tid = pth_spawn(attr, cleanup_thread, NULL);
1439 * For the cache_timeout configuration parameter. This replaces the old
1440 * SIGALRM stuff and is safer.
1442 timeout_event = pth_event(PTH_EVENT_TIME, pth_timeout(1, 0));
1443 pth_attr_init(attr);
1444 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1445 pth_attr_set(attr, PTH_ATTR_PRIO, PTH_PRIO_MAX);
1447 do {
1448 gint sig = 0;
1450 pth_sigwait_ev(&set, &sig, timeout_event);
1452 if (pth_event_occurred(timeout_event)) {
1454 * The timer event has expired. Update the file cache. When the
1455 * cache mutex is locked and the timer expires again, the threads
1456 * will stack.
1458 pth_spawn(attr, adjust_timer_thread, NULL);
1459 pth_event_free(timeout_event, PTH_FREE_THIS);
1460 timeout_event = pth_event(PTH_EVENT_TIME, pth_timeout(1, 0));
1463 if (sig > 0) {
1464 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1466 /* Caught a signal. */
1467 switch (sig) {
1468 case SIGUSR1:
1469 reload_rcfile();
1470 break;
1471 case SIGABRT:
1472 CACHE_LOCK(NULL);
1473 cache_clear(NULL, 2);
1474 CACHE_UNLOCK;
1475 #ifndef MEM_DEBUG
1476 xpanic();
1477 #endif
1478 exit(EXIT_FAILURE);
1479 case SIGHUP:
1480 CACHE_LOCK(NULL);
1481 log_write(N_("clearing file cache"));
1482 cache_clear(NULL, 2);
1483 CACHE_UNLOCK;
1484 break;
1485 default:
1486 quit = 1;
1487 shutdown(sockfd, SHUT_RDWR);
1488 close(sockfd);
1489 break;
1492 } while (!quit);
1495 * We're out of the main server loop. This happens when a signal was sent
1496 * to terminate the daemon. We'll wait for all clients to disconnect
1497 * before exiting and ignore any following signals.
1499 pth_join(accept_tid, &value);
1500 pth_attr_destroy(attr);
1501 pth_event_free(timeout_event, PTH_FREE_THIS);
1502 n = pth_ctrl(PTH_CTRL_GETTHREADS);
1503 unlink(*socketpath);
1504 g_free(*socketpath);
1505 *socketpath = NULL;
1507 /* 2 because the cleanup thread still exists, plus self. */
1508 if (n > 2)
1509 log_write(N_("waiting for all threads to terminate"));
1511 while (n > 2) {
1512 gint t;
1513 pth_event_t events;
1515 if (n != n_clients) {
1516 log_write(N_("%i threads remain"), n-2);
1517 n_clients = n;
1520 events = pth_event(PTH_EVENT_FUNC, event_ring_hack, NULL, pth_timeout(1, 0));
1521 pth_mutex_acquire(&cn_mutex, FALSE, NULL);
1523 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
1524 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1526 pth_event_concat(events, cn->ev, NULL);
1529 pth_mutex_release(&cn_mutex);
1531 if (!t)
1532 goto done;
1534 pth_wait(events);
1535 pth_yield(cleanup_tid);
1536 done:
1537 pth_event_isolate(events);
1538 pth_event_free(events, PTH_FREE_THIS);
1539 n = pth_ctrl(PTH_CTRL_GETTHREADS);
1542 pth_cancel(cleanup_tid);
1546 * Called from pinentry_fork() in the child process.
1548 void free_client_list()
1550 gint i, t = g_slist_length(cn_thread_list);
1552 for (i = 0; i < t; i++) {
1553 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1555 free_client(cn->cl);
1558 memset(key_cache, 0, cache_size);
1561 int main(int argc, char *argv[])
1563 gint opt;
1564 struct sockaddr_un addr;
1565 struct passwd *pw = getpwuid(getuid());
1566 gchar buf[PATH_MAX];
1567 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
1568 gchar *socketarg = NULL;
1569 gchar *datadir = NULL;
1570 gboolean n;
1571 gchar *p;
1572 gchar **cache_push = NULL;
1573 gint iter = 0;
1574 gchar *import = NULL;
1575 gint cmd_iterations = -1;
1576 gint default_timeout;
1577 gint rcfile_spec = 0;
1578 gint estatus = EXIT_FAILURE;
1579 gint sockfd;
1580 #ifndef MEM_DEBUG
1581 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
1582 #endif
1583 gint do_unlink = 1;
1584 gboolean secure = FALSE;
1585 guint ptotal = 0;
1586 gint background = 0;
1587 sigset_t set;
1588 #ifndef DEBUG
1589 #ifdef HAVE_SETRLIMIT
1590 struct rlimit rl;
1592 rl.rlim_cur = rl.rlim_max = 0;
1594 if (setrlimit(RLIMIT_CORE, &rl) != 0)
1595 err(EXIT_FAILURE, "setrlimit()");
1596 #endif
1597 #endif
1599 #ifdef ENABLE_NLS
1600 setlocale(LC_ALL, "");
1601 bindtextdomain("pwmd", LOCALEDIR);
1602 textdomain("pwmd");
1603 #endif
1605 gpg_err_init();
1606 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
1607 #ifndef MEM_DEBUG
1608 g_mem_set_vtable(&mtable);
1609 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
1610 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
1611 xmlInitMemory();
1612 #endif
1613 pth_init();
1614 g_snprintf(buf, sizeof(buf), "%s/.pwmd", pw->pw_dir);
1616 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
1617 err(EXIT_FAILURE, "%s", buf);
1619 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", pw->pw_dir);
1621 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
1622 err(EXIT_FAILURE, "%s", buf);
1624 rcfile = g_strdup_printf("%s/.pwmd/config", pw->pw_dir);
1626 if ((page_size = sysconf(_SC_PAGESIZE)) == -1)
1627 err(EXIT_FAILURE, "sysconf()");
1629 cache_size = page_size;
1631 while ((opt = getopt(argc, argv, "bI:i:hvf:D")) != EOF) {
1632 switch (opt) {
1633 case 'b':
1634 background = 1;
1635 break;
1636 case 'D':
1637 secure = TRUE;
1638 break;
1639 case 'I':
1640 import = optarg;
1641 break;
1642 case 'i':
1643 cmd_iterations = atoi(optarg);
1644 break;
1645 case 'f':
1646 g_free(rcfile);
1647 rcfile = g_strdup(optarg);
1648 rcfile_spec = 1;
1649 break;
1650 case 'v':
1651 printf("%s\n%s\n", PACKAGE_STRING, PACKAGE_BUGREPORT);
1652 exit(EXIT_SUCCESS);
1653 case 'h':
1654 default:
1655 usage(argv[0]);
1659 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
1660 exit(EXIT_FAILURE);
1662 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
1663 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
1665 if (log_syslog == TRUE)
1666 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
1668 if (g_key_file_has_key(keyfileh, "global", "iterations", NULL) == TRUE)
1669 iter = g_key_file_get_integer(keyfileh, "global", "iterations", NULL);
1671 #ifdef HAVE_MLOCKALL
1672 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
1673 warn("mlockall()");
1674 goto do_exit;
1676 #endif
1678 setup_gcrypt();
1680 if (import) {
1681 opt = xml_import(import, cmd_iterations < -1 ? iter : cmd_iterations);
1682 g_key_file_free(keyfileh);
1683 g_free(rcfile);
1684 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
1687 g_key_file_set_list_separator(keyfileh, ',');
1689 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
1690 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
1692 if (*p == '~') {
1693 p++;
1694 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
1695 g_free(p);
1696 socketarg = g_strdup(buf);
1698 else
1699 socketarg = p;
1701 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
1702 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
1704 datadir = expand_homedir(p);
1705 g_free(p);
1707 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
1708 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
1709 disable_list_and_dump = n;
1711 else
1712 disable_list_and_dump = secure;
1714 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
1715 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
1716 else
1717 default_timeout = -1;
1719 if (g_key_file_has_key(keyfileh, "global", "cache_size", NULL) == TRUE) {
1720 cache_size = g_key_file_get_integer(keyfileh, "global", "cache_size", NULL);
1722 if (cache_size < page_size || cache_size % page_size)
1723 errx(EXIT_FAILURE, N_("cache size must be in multiples of %li"), page_size);
1726 setup_logging(keyfileh);
1728 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
1729 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
1731 if (argc != optind) {
1732 if (cache_push)
1733 ptotal = g_strv_length(cache_push);
1735 for (; optind < argc; optind++) {
1736 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
1737 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
1741 if (strchr(socketarg, '/') == NULL) {
1742 socketdir = g_get_current_dir();
1743 socketname = g_strdup(socketarg);
1744 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
1746 else {
1747 socketname = g_strdup(strrchr(socketarg, '/'));
1748 socketname++;
1749 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
1750 socketdir = g_strdup(socketarg);
1751 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
1754 if ((key_cache = mmap(NULL, cache_size, PROT_READ|PROT_WRITE,
1755 #ifdef MMAP_ANONYMOUS
1756 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)) == MAP_FAILED) {
1757 #else
1758 MAP_PRIVATE|MAP_ANON, -1, 0)) == MAP_FAILED) {
1759 #endif
1760 err(EXIT_FAILURE, "mmap()");
1763 if (mlock(key_cache, cache_size) == -1)
1764 log_write("mlock(): %s", strerror(errno));
1766 memset(key_cache, 0, cache_size);
1768 if (chdir(datadir)) {
1769 warn("%s", datadir);
1770 unlink(socketpath);
1771 goto do_exit;
1774 if (parse_keyfile_key() == FALSE)
1775 goto do_exit;
1777 clear_errorfile_key();
1780 * Set the cache entry for a file. Prompts for the password.
1782 if (cache_push) {
1783 for (opt = 0; cache_push[opt]; opt++)
1784 do_cache_push(cache_push[opt], NULL);
1786 g_strfreev(cache_push);
1787 warnx(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
1791 * bind() doesn't like the full pathname of the socket or any non alphanum
1792 * characters so change to the directory where the socket is wanted then
1793 * create it then change to datadir.
1795 if (chdir(socketdir)) {
1796 warn("%s", socketdir);
1797 goto do_exit;
1800 g_free(socketdir);
1802 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
1803 warn("socket()");
1804 goto do_exit;
1807 addr.sun_family = AF_UNIX;
1808 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
1810 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
1811 warn("bind()");
1813 if (errno == EADDRINUSE)
1814 warnx(N_("Either there is another pwmd running or '%s' is a \n"
1815 "stale socket. Please remove it manually."), socketpath);
1817 do_unlink = 0;
1818 goto do_exit;
1821 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
1822 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
1823 mode_t mode = strtol(t, NULL, 8);
1824 mode_t mask = umask(0);
1826 g_free(t);
1828 if (chmod(socketname, mode) == -1) {
1829 warn("%s", socketname);
1830 close(sockfd);
1831 unlink(socketpath);
1832 umask(mask);
1833 goto do_exit;
1836 umask(mask);
1839 g_free(--socketname);
1841 if (chdir(datadir)) {
1842 warn("%s", datadir);
1843 close(sockfd);
1844 unlink(socketpath);
1845 goto do_exit;
1848 g_free(datadir);
1849 pth_mutex_init(&cache_mutex);
1850 #ifdef WITH_PINENTRY
1851 pth_mutex_init(&pin_mutex);
1852 #endif
1854 if (listen(sockfd, 0) == -1) {
1855 warn("listen()");
1856 goto do_exit;
1859 if (background) {
1860 switch (fork()) {
1861 case -1:
1862 warn("fork()");
1863 goto do_exit;
1864 case 0:
1865 close(0);
1866 close(1);
1867 close(2);
1868 setsid();
1869 break;
1870 default:
1871 exit(EXIT_SUCCESS);
1876 * These are the signals that we use in threads. libpth can catch signals
1877 * itself so ignore them everywhere else. Note that using
1878 * signal(N, SIG_IGN) doesn't work like you might think.
1880 sigemptyset(&set);
1882 /* Termination */
1883 sigaddset(&set, SIGTERM);
1884 sigaddset(&set, SIGINT);
1886 /* Configuration file reloading. */
1887 sigaddset(&set, SIGUSR1);
1889 /* Clears the file cache. */
1890 sigaddset(&set, SIGHUP);
1892 /* Caught in client_thread(). Sends a cache status message. */
1893 sigaddset(&set, SIGUSR2);
1895 /* Caught in client_thread(). When keepalive_thread() fails, this signal
1896 * is raised to terminate the client. More of a failsafe than anything. */
1897 sigaddset(&set, SIGQUIT);
1899 /* Ignored everywhere. When a client disconnects abnormally this signal
1900 * gets raised. It isn't needed though because client_thread() will check
1901 * for rcs even after the client disconnects. */
1902 signal(SIGPIPE, SIG_IGN);
1903 pth_sigmask(SIG_BLOCK, &set, NULL);
1904 server_loop(sockfd, &socketpath);
1905 estatus = EXIT_SUCCESS;
1907 do_exit:
1908 if (socketpath && do_unlink) {
1909 unlink(socketpath);
1910 g_free(socketpath);
1913 g_key_file_free(keyfileh);
1914 g_free(rcfile);
1915 xmlCleanupParser();
1917 if (key_cache) {
1918 cache_clear(NULL, 2);
1919 memset(key_cache, 0, cache_size);
1922 if (key_cache && munmap(key_cache, cache_size) == -1)
1923 log_write("munmap(): %s", strerror(errno));
1925 if (estatus == EXIT_SUCCESS)
1926 log_write(N_("pwmd exiting normally"));
1928 pth_kill();
1929 #if defined(DEBUG) && !defined(MEM_DEBUG)
1930 xdump();
1931 #endif
1932 exit(estatus);