Cleanup of command_startup().
[pwmd.git] / src / pwmd.c
blob33705d524a347742b6fa8b22ffebf5ac5118996d
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006-2010 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <err.h>
27 #include <ctype.h>
28 #include <string.h>
29 #include <sys/un.h>
30 #include <signal.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <sys/wait.h>
34 #include <fcntl.h>
35 #include <pwd.h>
36 #include <grp.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 HAVE_GETOPT_LONG
52 #ifdef HAVE_GETOPT_H
53 #include <getopt.h>
54 #endif
55 #else
56 #include "getopt_long.h"
57 #endif
59 #ifdef TM_IN_SYS_TIME
60 #include <sys/time.h>
61 #else
62 #include <time.h>
63 #endif
65 #include "mem.h"
66 #include "xml.h"
67 #include "common.h"
69 #ifdef WITH_PINENTRY
70 #include "pinentry.h"
71 #endif
73 #include "commands.h"
74 #include "pwmd_error.h"
75 #include "cache.h"
76 #include "misc.h"
77 #include "pwmd.h"
78 #include "mutex.h"
79 #include "rcfile.h"
81 GCRY_THREAD_OPTION_PTH_IMPL;
83 static void *reload_rcfile_thread(void *arg)
85 gboolean b = disable_list_and_dump;
86 gchar **users = g_key_file_get_string_list(keyfileh, "global", "allowed",
87 NULL, NULL);
88 GKeyFile *k;
89 pth_attr_t attr = pth_attr_of(pth_self());
91 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
92 pth_attr_destroy(attr);
93 MUTEX_LOCK(&rcfile_mutex);
94 log_write(N_("reloading configuration file '%s'"), rcfile);
95 k = parse_rcfile(FALSE);
97 if (!k)
98 goto done;
100 g_key_file_free(keyfileh);
101 keyfileh = k;
102 parse_rcfile_keys();
103 clear_rcfile_keys();
104 startStopKeepAlive(FALSE);
105 send_status_all(STATUS_CONFIG);
106 done:
107 disable_list_and_dump = !disable_list_and_dump ? b : TRUE;
108 g_key_file_set_string_list(keyfileh, "global", "allowed",
109 (const gchar **)users, g_strv_length(users));
110 g_strfreev(users);
111 MUTEX_UNLOCK(&rcfile_mutex);
112 return NULL;
115 static void reload_rcfile()
117 pth_t tid;
118 pth_attr_t attr = pth_attr_new();
119 gpg_error_t rc;
121 pth_attr_init(attr);
122 pth_attr_set(attr, PTH_ATTR_JOINABLE, 0);
123 tid = pth_spawn(attr, reload_rcfile_thread, NULL);
124 rc = gpg_error_from_syserror();
125 pth_attr_destroy(attr);
127 if (!tid)
128 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
129 pwmd_strerror(rc));
132 gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e)
134 gpg_err_code_t n = gpg_err_code(e);
135 gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n);
136 struct client_s *client = assuan_get_pointer(ctx);
138 if (client)
139 client->last_rc = e;
141 if (!e)
142 return assuan_process_done(ctx, 0);
144 if (!ctx) {
145 log_write("%s", pwmd_strerror(e));
146 return e;
149 if (n == EPWMD_LIBXML_ERROR) {
150 xmlErrorPtr xe = client->xml_error;
152 if (!xe)
153 xe = xmlGetLastError();
155 e = assuan_process_done(ctx, assuan_set_error(ctx, code, xe->message));
156 log_write("%s", xe->message);
158 if (xe == client->xml_error)
159 xmlResetError(xe);
160 else
161 xmlResetLastError();
163 client->xml_error = NULL;
164 return e;
167 return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e)));
170 void log_write(const gchar *fmt, ...)
172 gchar *args, *line;
173 va_list ap;
174 struct tm *tm;
175 time_t now;
176 gchar tbuf[21];
177 gint fd = -1;
178 gchar *name;
179 gchar buf[255];
180 pth_t tid = pth_self();
181 pth_attr_t attr;
183 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
184 return;
186 if (!cmdline && logfile) {
187 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
188 warn("%s", logfile);
190 if (!log_syslog)
191 return;
195 va_start(ap, fmt);
197 if (g_vasprintf(&args, fmt, ap) == -1) {
198 if (logfile && fd != -1)
199 close(fd);
201 va_end(ap);
202 return;
205 va_end(ap);
207 if (cmdline) {
208 fprintf(stderr, "%s\n", args);
209 fflush(stderr);
210 g_free(args);
211 return;
214 attr = pth_attr_of(tid);
216 if (pth_attr_get(attr, PTH_ATTR_NAME, &name) == FALSE)
217 name = "unknown";
219 pth_attr_destroy(attr);
220 name = print_fmt(buf, sizeof(buf), "%s(%p): ", name, tid);
222 if (!cmdline && log_syslog == TRUE)
223 syslog(LOG_INFO, "%s%s", name, args);
225 time(&now);
226 tm = localtime(&now);
227 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
228 tbuf[sizeof(tbuf) - 1] = 0;
230 if (args[strlen(args)-1] == '\n')
231 args[strlen(args)-1] = 0;
233 line = g_strdup_printf("%s %i %s%s\n", tbuf, getpid(), name, args);
234 g_free(args);
236 if (!line) {
237 if (logfile && fd != -1)
238 close(fd);
240 return;
243 if (logfile && fd != -1) {
244 pth_write(fd, line, strlen(line));
245 fsync(fd);
246 close(fd);
249 if (isatty(STDERR_FILENO)) {
250 fprintf(stderr, "%s", line);
251 fflush(stderr);
254 g_free(line);
257 static void usage(gchar *pn, gint rc)
259 g_fprintf(rc == EXIT_FAILURE ? stderr : stdout, N_(
260 "Usage: %s [options] [file1] [...]\n"
261 " --no-fork/-n\n"
262 " run as a foreground process\n"
263 " --rcfile/-f <filename>\n"
264 " load the specified rcfile (~/.pwmd/config)\n"
265 " --convert/-C <filename>\n"
266 " convert a version 1 data file to version 2\n"
267 " --import/-I <filename>\n"
268 " import an XML file\n"
269 " --iterations/-i\n"
270 " encrypt with the specified number of iterations when importing\n"
271 " (default is in the rcfile \"global\" section)\n"
272 " --key-file/-k <filename>\n"
273 " obtain the key from the specified file when importing or converting\n"
274 " --outfile/-o <filename>\n"
275 " output file to use when importing or converting (- for stdout)\n"
276 " --disable-dump/-D\n"
277 " disable use of the LIST, XPATH and DUMP commands\n"
278 " --no-pinentry/-P\n"
279 " disable use of pinentry\n"
280 " --version\n"
281 " --help\n"
282 ), pn);
283 exit(rc);
286 static void setup_gcrypt()
288 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
290 if (!gcry_check_version(GCRYPT_VERSION))
291 errx(EXIT_FAILURE, N_("gcry_check_version(): Incompatible libgcrypt. Wanted %s, got %s."), GCRYPT_VERSION, gcry_check_version(NULL));
293 gcry_set_allocation_handler(xmalloc, xmalloc, NULL, xrealloc, xfree);
296 static gpg_error_t validate_peer(struct client_s *cl)
298 gchar **users;
299 gboolean allowed = FALSE;
300 pid_t pid;
301 gid_t gid;
302 uid_t uid;
303 gpg_error_t rc = assuan_get_peercred(cl->ctx, &pid, &uid, &gid);
305 if (rc)
306 return rc;
308 users = g_key_file_get_string_list(keyfileh, "global", "allowed", NULL, NULL);
310 if (users) {
311 for (gchar **p = users; *p; p++) {
312 struct passwd pw, *result;
313 struct group gr, *gresult;
314 char *buf;
316 if (*(*p) == '@') {
317 size_t len = sysconf(_SC_GETGR_R_SIZE_MAX);
319 if (len == -1)
320 len = 16384;
322 buf = g_malloc(len);
324 if (!buf) {
325 g_strfreev(users);
326 return GPG_ERR_ENOMEM;
329 if (!getgrnam_r(*(p)+1, &gr, buf, len, &gresult) && gresult) {
330 if (gresult->gr_gid == gid) {
331 g_free(buf);
332 allowed = TRUE;
333 break;
336 len = sysconf(_SC_GETPW_R_SIZE_MAX);
338 if (len == -1)
339 len = 16384;
341 gchar *tbuf = g_malloc(len);
343 for (gchar **t = gresult->gr_mem; *t; t++) {
344 if (!getpwnam_r(*t, &pw, tbuf, len, &result) && result) {
345 if (result->pw_uid == uid) {
346 g_free(buf);
347 allowed = TRUE;
348 break;
353 g_free(tbuf);
355 if (allowed)
356 break;
359 else {
360 size_t len = sysconf(_SC_GETPW_R_SIZE_MAX);
362 if (len == -1)
363 len = 16384;
365 buf = g_malloc(len);
367 if (!buf) {
368 g_strfreev(users);
369 return GPG_ERR_ENOMEM;
372 if (!getpwnam_r(*p, &pw, buf, len, &result) && result) {
373 if (result->pw_uid == uid) {
374 g_free(buf);
375 allowed = TRUE;
376 break;
381 g_free(buf);
384 g_strfreev(users);
387 log_write("peer %s: uid=%i, gid=%i, pid=%i",
388 allowed ? N_("accepted") : N_("rejected"), uid, gid,pid);
389 return allowed ? 0 : GPG_ERR_INV_USER_ID;
392 static gboolean new_connection(struct client_s *cl)
394 gpg_error_t rc;
395 gchar *ver;
396 gchar *str;
398 rc = assuan_init_socket_server_ext(&cl->ctx, cl->thd->fd, 2);
400 if (rc)
401 goto fail;
403 assuan_set_pointer(cl->ctx, cl);
404 ver = g_strdup_printf("%s", PACKAGE_STRING);
405 assuan_set_hello_line(cl->ctx, ver);
406 g_free(ver);
407 rc = register_commands(cl->ctx);
409 if (rc)
410 goto fail;
412 rc = assuan_accept(cl->ctx);
414 if (rc)
415 goto fail;
417 rc = validate_peer(cl);
419 /* May not be implemented on all platforms. */
420 if (rc && gpg_err_code(rc) != GPG_ERR_ASS_GENERAL)
421 goto fail;
423 str = get_key_file_string("global", "debug_file");
425 if (debugfp && str)
426 assuan_set_log_stream(cl->ctx, debugfp);
428 if (str)
429 g_free(str);
431 return TRUE;
433 fail:
434 log_write("%s", pwmd_strerror(rc));
435 return FALSE;
438 static void xml_error_cb(void *data, xmlErrorPtr e)
440 struct client_s *client = data;
443 * Keep the first reported error as the one to show in the error
444 * description. Reset in send_error().
446 if (client->xml_error)
447 return;
449 xmlCopyError(e, client->xml_error);
452 void close_file_header(file_header_internal_t *fh)
454 if (!fh)
455 return;
457 if (fh->fd != -1 || (cmdline == TRUE && fh->fd != STDOUT_FILENO))
458 close(fh->fd);
460 if (fh->doc)
461 gcry_free(fh->doc);
463 g_free(fh);
466 void cleanup_crypto(struct crypto_s **c)
468 struct crypto_s *cr = *c;
470 if (!cr)
471 return;
473 if (cr->iv) {
474 gcry_free(cr->iv);
475 cr->iv = NULL;
478 if (cr->key) {
479 gcry_free(cr->key);
480 cr->key = NULL;
483 if (cr->tkey) {
484 gcry_free(cr->tkey);
485 cr->tkey = NULL;
488 if (cr->tkey2) {
489 gcry_free(cr->tkey2);
490 cr->tkey2 = NULL;
493 if (cr->inbuf) {
494 gcry_free(cr->inbuf);
495 cr->inbuf = NULL;
498 if (cr->outbuf) {
499 gcry_free(cr->outbuf);
500 cr->outbuf = NULL;
503 close_file_header(cr->fh);
504 cr->fh = NULL;
506 if (cr->gh)
507 gcry_cipher_close(cr->gh);
509 cr->gh = NULL;
510 g_free(cr);
511 *c = NULL;
515 * This is called after a client_thread terminates. Set with
516 * pth_cleanup_push().
518 static void cleanup_cb(void *arg)
520 struct client_thread_s *cn = arg;
521 struct client_s *cl = cn->cl;
523 MUTEX_LOCK(&cn_mutex);
524 cn_thread_list = g_slist_remove(cn_thread_list, cn);
525 MUTEX_UNLOCK(&cn_mutex);
527 if (cn->msg_tid) {
528 MUTEX_LOCK(&cn->mp_mutex);
529 pth_cancel(cn->msg_tid);
530 MUTEX_UNLOCK(&cn->mp_mutex);
533 if (cn->mp) {
534 while (pth_msgport_pending(cn->mp)) {
535 pth_message_t *msg = pth_msgport_get(cn->mp);
537 g_free(msg->m_data);
538 g_free(msg);
541 pth_msgport_destroy(cn->mp);
544 if (!cl) {
545 if (cn->fd != -1)
546 close(cn->fd);
548 goto done;
551 if (!cl->freed)
552 cleanup_client(cl);
554 if (cl->ctx)
555 assuan_deinit_server(cl->ctx);
556 else if (cl->thd && cl->thd->fd != -1)
557 close(cl->thd->fd);
559 #ifdef WITH_PINENTRY
560 if (cl->pinentry)
561 cleanup_pinentry(cl->pinentry);
562 #endif
564 if (cl->crypto)
565 cleanup_crypto(&cl->crypto);
567 g_free(cl);
568 done:
569 log_write(N_("exiting, fd=%i"), cn->fd);
570 g_free(cn);
571 send_status_all(STATUS_CLIENTS);
575 * Called every time a connection is made from init_new_connection(). This is
576 * the thread entry point.
578 static void *client_thread(void *data)
580 struct client_thread_s *thd = data;
581 struct client_s *cl = g_malloc0(sizeof(struct client_s));
582 gpg_error_t rc;
583 pth_attr_t attr;
586 * Prevent a race condition with init_new_connection() if this thread
587 * fails (returns) for some reason before init_new_connection() releases
588 * the cn_mutex.
590 MUTEX_LOCK(&cn_mutex);
591 MUTEX_UNLOCK(&cn_mutex);
592 pth_cleanup_push(cleanup_cb, thd);
594 if (!cl) {
595 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
596 goto fail;
599 attr = pth_attr_of(pth_self());
600 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
601 pth_attr_destroy(attr);
602 thd->cl = cl;
603 cl->thd = thd;
605 if (!new_connection(cl))
606 goto fail;
608 #ifdef WITH_PINENTRY
609 cl->pinentry = pinentry_init();
611 if (!cl->pinentry) {
612 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
613 goto fail;
615 #endif
617 thd->mp = pth_msgport_create(NULL);
618 pth_mutex_init(&thd->mp_mutex);
619 thd->msg_tid = pth_spawn(NULL, client_msg_thread, thd);
620 rc = gpg_error_from_syserror();
622 if (!thd->msg_tid) {
623 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
624 pwmd_strerror(rc));
625 goto fail;
628 pth_yield(thd->msg_tid);
629 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
631 if (rc) {
632 log_write("%s", pwmd_strerror(rc));
633 goto fail;
636 send_status_all(STATUS_CLIENTS);
637 xmlSetStructuredErrorFunc(cl, xml_error_cb);
639 for (;;) {
640 #ifdef WITH_PINENTRY
641 pth_event_t pev = NULL;
642 #endif
643 pth_status_t st, wst;
644 pth_event_t wev = NULL;
645 pth_event_t rev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE,
646 cl->thd->fd);
647 pth_event_t ev = rev;
649 #ifdef WITH_PINENTRY
650 if (cl->pinentry->status == PINENTRY_RUNNING) {
651 pev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, cl->pinentry->fd);
652 ev = pth_event_concat(ev, pev, NULL);
654 #endif
656 if (cl->inquire_status == INQUIRE_BUSY) {
657 wev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_WRITEABLE, cl->thd->fd);
658 ev = pth_event_concat(ev, wev, NULL);
661 pth_cleanup_push(cleanup_ev_cb, ev);
662 pth_wait(ev);
663 st = pth_event_status(rev);
664 wst = pth_event_status(wev);
666 if (st == PTH_STATUS_OCCURRED || wst == PTH_STATUS_OCCURRED) {
667 rc = assuan_process_next(cl->ctx);
669 if (rc) {
670 cl->inquire_status = INQUIRE_INIT;
671 pth_cleanup_pop(1);
673 if (gpg_err_code(rc) == GPG_ERR_EOF)
674 goto done;
676 log_write("assuan_process_next(): %s", pwmd_strerror(rc));
677 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
679 if (rc) {
680 log_write("assuan_process_done(): %s", pwmd_strerror(rc));
681 goto done;
684 else {
685 #ifdef WITH_PINENTRY
686 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
687 cl->pinentry->status = PINENTRY_RUNNING;
688 #endif
690 switch (cl->inquire_status) {
691 case INQUIRE_BUSY:
692 case INQUIRE_INIT:
693 break;
694 case INQUIRE_DONE:
695 cl->inquire_status = INQUIRE_INIT;
696 rc = assuan_process_done(cl->ctx, 0);
697 break;
702 #ifdef WITH_PINENTRY
703 if (pev)
704 st = pth_event_status(pev);
706 rc = pinentry_iterate(cl,
707 pev && cl->pinentry->fd != -1 && st == PTH_STATUS_OCCURRED);
708 #endif
709 pth_cleanup_pop(1);
713 * Client cleanup (including XML data) is done in cleanup_cb().
715 done:
716 fail:
717 pth_exit(PTH_CANCELED);
718 return NULL;
721 static gchar *do_read_password(const gchar *prompt)
723 gchar buf[LINE_MAX] = {0}, *p;
724 struct termios told, tnew;
725 gchar *key;
727 if (tcgetattr(STDIN_FILENO, &told) == -1) {
728 log_write("tcgetattr(): %s", pwmd_strerror(gpg_error_from_syserror()));
729 return NULL;
732 memcpy(&tnew, &told, sizeof(struct termios));
733 tnew.c_lflag &= ~(ECHO);
734 tnew.c_lflag |= ICANON|ECHONL;
736 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
737 log_write("tcsetattr(): %s", pwmd_strerror(gpg_error_from_syserror()));
738 tcsetattr(STDIN_FILENO, TCSANOW, &told);
739 return NULL;
742 fprintf(stderr, "%s", prompt);
744 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
745 tcsetattr(STDIN_FILENO, TCSANOW, &told);
746 return NULL;
749 tcsetattr(STDIN_FILENO, TCSANOW, &told);
750 p[strlen(p) - 1] = 0;
752 if (!buf[0]) {
753 key = gcry_malloc(1);
754 key[0] = 0;
756 else {
757 key = gcry_malloc(strlen(p) + 1);
758 sprintf(key, "%s", p);
761 memset(&buf, 0, sizeof(buf));
762 return key;
765 /* Only used when "enable_pinentry" is "false" or -P. */
766 static gpg_error_t read_password(const gchar *filename,
767 struct crypto_s *crypto, guchar *key, pinentry_cmd_t which)
769 gchar *prompt;
771 if (which == PINENTRY_SAVE) {
772 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
773 crypto->tkey = do_read_password(prompt);
774 g_free(prompt);
776 if (!crypto->tkey) {
777 log_write(N_("%s: Skipping file"), filename);
778 return GPG_ERR_BAD_PASSPHRASE;
781 prompt = g_strdup_printf(N_("Repeat passphrase: "));
782 crypto->tkey2 = do_read_password(prompt);
783 g_free(prompt);
785 if (!crypto->tkey2) {
786 log_write(N_("%s: Skipping file"), filename);
787 return GPG_ERR_BAD_PASSPHRASE;
790 if (strcmp(crypto->tkey, crypto->tkey2)) {
791 log_write(N_("%s: Passphrase mismatch"), filename);
792 return GPG_ERR_INV_PASSPHRASE;
795 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
796 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
797 return 0;
800 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
802 if ((crypto->tkey = do_read_password(prompt)) == NULL) {
803 log_write(N_("%s: Skipping file"), filename);
804 g_free(prompt);
805 return GPG_ERR_BAD_PASSPHRASE;
808 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
809 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
810 g_free(prompt);
811 return 0;
815 * inbuf must have been allocated with gcry_malloc().
817 gpg_error_t export_common(const gchar *filename, struct crypto_s *crypto,
818 gpointer inbuf, gulong insize)
820 gpg_error_t rc;
821 gint level;
822 gulong outsize;
823 gpointer outbuf;
825 rc = update_save_flags(NULL, crypto);
827 if (rc)
828 return rc;
830 level = get_key_file_integer(filename, "compression_level");
832 if (level < 0)
833 level = 0;
835 rc = do_compress(NULL, level, inbuf, insize, &outbuf, &outsize);
837 if (rc)
838 return rc;
840 crypto->inbuf = outbuf;
841 crypto->insize = outsize;
842 rc = do_xml_encrypt(NULL, crypto, filename);
843 return rc;
846 static gpg_error_t get_password(const gchar *filename,
847 struct crypto_s *crypto, guchar *md5file, guchar *key,
848 pinentry_cmd_t which)
850 #ifdef WITH_PINENTRY
851 gpg_error_t rc = 0;
853 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
854 == FALSE) {
855 #endif
856 return read_password(filename, crypto, key, which);
857 #ifdef WITH_PINENTRY
859 else {
860 gchar *result = NULL;
861 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
863 pth_mutex_init(&pin->status_mutex);
864 set_pinentry_defaults(pin);
865 pin->which = which;
866 pin->filename = g_strdup(filename);
867 rc = pinentry_getpin(pin, &result);
869 if (rc) {
870 xfree(result);
871 goto done;
874 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, result ? strlen(result) : 1);
875 xfree(result);
876 cleanup_pinentry(pin);
879 done:
880 return rc;
881 #endif
884 static gboolean xml_import(const gchar *filename, const gchar *outfile,
885 const gchar *keyfile, guint64 iter)
887 xmlDocPtr doc;
888 gint fd;
889 struct stat st;
890 gint len;
891 xmlChar *xmlbuf;
892 xmlChar *xml;
893 gpg_error_t rc;
894 struct crypto_s *crypto;
895 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
897 if (stat(filename, &st) == -1) {
898 log_write("%s: %s", filename, pwmd_strerror(gpg_error_from_syserror()));
899 return FALSE;
902 crypto = init_client_crypto();
904 if (!crypto)
905 return FALSE;
907 crypto->key = gcry_malloc(hashlen);
908 memset(crypto->key, 0, hashlen);
910 if (!crypto->key) {
911 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
912 goto fail;
915 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
916 filename, outfile);
918 if (iter && keyfile) {
919 rc = parse_rcfile_keyfile(crypto, keyfile, TRUE);
921 if (rc)
922 goto fail;
924 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
925 crypto->tkey_len);
927 else if (iter) {
928 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
930 if (rc == GPG_ERR_ASSUAN_SERVER_FAULT) {
931 log_write(N_("%s. Maybe disabling pinentry (-P) will help?"),
932 pwmd_strerror(rc));
933 goto fail;
935 else if (rc) {
936 log_write("%s", pwmd_strerror(rc));
937 goto fail;
941 if ((fd = open(filename, O_RDONLY)) == -1) {
942 log_write("%s: %s", filename, pwmd_strerror(gpg_error_from_syserror()));
943 goto fail;
946 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
947 close(fd);
948 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
949 goto fail;
952 if (pth_read(fd, xmlbuf, st.st_size) == -1) {
953 rc = gpg_error_from_syserror();
954 close(fd);
955 log_write("%s: %s", filename, pwmd_strerror(rc));
956 goto fail;
959 close(fd);
960 xmlbuf[st.st_size] = 0;
963 * Make sure the document validates.
965 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
966 log_write("xmlReadDoc() failed");
967 gcry_free(xmlbuf);
968 goto fail;
971 gcry_free(xmlbuf);
972 xmlNodePtr n = xmlDocGetRootElement(doc);
973 rc = validate_import(n ? n->children : n);
975 if (rc) {
976 log_write("%s", pwmd_strerror(rc));
977 xmlFreeDoc(doc);
978 goto fail;
981 xmlDocDumpMemory(doc, &xml, &len);
982 xmlFreeDoc(doc);
984 if (!iter)
985 memset(crypto->key, '!', hashlen);
987 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
989 if (!crypto->fh) {
990 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
991 goto fail;
994 crypto->fh->ver.fh2.iter = iter;
995 rc = export_common(outfile, crypto, xml, len);
996 xmlFree(xml);
998 if (rc) {
999 send_error(NULL, rc);
1000 goto fail;
1003 cleanup_crypto(&crypto);
1004 return TRUE;
1006 fail:
1007 cleanup_crypto(&crypto);
1008 return FALSE;
1011 gboolean do_cache_push(const gchar *filename, const void *password,
1012 gsize len)
1014 guchar md5file[16];
1015 gint timeout;
1016 const gchar *p = filename;
1017 struct crypto_s *crypto;
1018 gpg_error_t rc;
1019 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
1021 while (isspace(*p))
1022 p++;
1024 if (!*p)
1025 return FALSE;
1027 if (valid_filename(p) == FALSE) {
1028 log_write(N_("%s: Invalid characters in filename"), p);
1029 return FALSE;
1032 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1034 if (cache_iscached(md5file)) {
1035 log_write(N_("%s: already cached, skipping"), p);
1036 return FALSE;
1039 if (access(p, R_OK|W_OK) != 0) {
1040 log_write("%s: %s", p, pwmd_strerror(gpg_error_from_syserror()));
1041 return FALSE;
1044 crypto = init_client_crypto();
1046 if (!crypto)
1047 return FALSE;
1049 crypto->fh = read_file_header(filename, FALSE, &rc);
1051 if (!crypto->fh) {
1052 log_write("%s: %s", p, pwmd_strerror(rc));
1053 cleanup_crypto(&crypto);
1054 return FALSE;
1057 crypto->key = gcry_malloc(hashlen);
1059 if (!crypto->key) {
1060 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
1061 cleanup_crypto(&crypto);
1062 return FALSE;
1065 log_write(N_("Adding '%s' to the file cache ..."), filename);
1067 if (crypto->fh->ver.fh2.iter <= 0ULL) {
1068 memset(crypto->key, '!', hashlen);
1069 goto try_decrypt;
1072 if (!password) {
1073 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1075 if (rc) {
1076 send_error(NULL, rc);
1077 cleanup_crypto(&crypto);
1078 return FALSE;
1081 gcry_free(crypto->fh->doc);
1082 crypto->fh->doc = NULL;
1084 else
1085 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password, len);
1087 try_decrypt:
1088 rc = init_client_crypto2(filename, crypto);
1090 if (rc) {
1091 send_error(NULL, rc);
1092 cleanup_crypto(&crypto);
1093 return FALSE;
1096 rc = try_xml_decrypt(NULL, crypto, NULL, NULL);
1098 if (rc) {
1099 log_write("%s: %s", filename, pwmd_strerror(rc));
1100 cleanup_crypto(&crypto);
1101 return FALSE;
1104 if (cache_update_key(md5file, crypto->key) == FALSE) {
1105 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
1106 cleanup_crypto(&crypto);
1107 return FALSE;
1110 timeout = get_key_file_integer(p, "cache_timeout");
1111 cache_set_timeout(md5file, timeout);
1112 log_write(N_("File '%s' now cached"), filename);
1113 cleanup_crypto(&crypto);
1114 return TRUE;
1117 static void init_new_connection(gint fd)
1119 pth_attr_t attr;
1120 struct client_thread_s *new;
1121 gpg_error_t rc;
1123 new = g_malloc0(sizeof(struct client_thread_s));
1125 if (!new) {
1126 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
1127 close(fd);
1128 return;
1131 MUTEX_LOCK(&cn_mutex);
1132 new->fd = fd;
1133 attr = pth_attr_new();
1134 pth_attr_init(attr);
1135 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1136 new->tid = pth_spawn(attr, client_thread, new);
1137 rc = gpg_error_from_syserror();
1138 pth_attr_destroy(attr);
1140 if (!new->tid) {
1141 g_free(new);
1142 close(fd);
1143 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1144 pwmd_strerror(rc));
1145 MUTEX_UNLOCK(&cn_mutex);
1146 return;
1149 cn_thread_list = g_slist_append(cn_thread_list, new);
1150 MUTEX_UNLOCK(&cn_mutex);
1151 log_write(N_("new connection: tid=%p, fd=%i"), new->tid, fd);
1154 static void *accept_thread(void *arg)
1156 gint sockfd = *(gint *)arg;
1157 pth_attr_t attr = pth_attr_of(pth_self());
1159 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1160 pth_attr_destroy(attr);
1162 for (;;) {
1163 socklen_t slen = sizeof(struct sockaddr_un);
1164 struct sockaddr_un raddr;
1165 gint fd = -1;
1167 fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen);
1169 if (fd == -1) {
1170 if (errno != EAGAIN) {
1171 if (!quit) // probably EBADF
1172 log_write("accept(): %s", pwmd_strerror(gpg_error_from_syserror()));
1174 break;
1177 continue;
1180 init_new_connection(fd);
1183 /* Just in case accept() failed for some reason other than EBADF */
1184 quit = 1;
1185 pth_exit(PTH_CANCELED);
1186 return NULL;
1189 static void *adjust_cache_timer_thread(void *arg)
1191 pth_attr_t attr = pth_attr_of(pth_self());
1193 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1194 pth_attr_destroy(attr);
1196 for (;;) {
1197 pth_sleep(1);
1198 CACHE_LOCK(NULL);
1199 cache_adjust_timer();
1200 CACHE_UNLOCK;
1203 return NULL;
1206 void cleanup_mutex_cb(void *arg)
1208 pth_mutex_t *m = arg;
1210 MUTEX_UNLOCK(m);
1213 void cleanup_ev_cb(void *arg)
1215 pth_event_t ev = arg;
1217 pth_event_free(ev, PTH_FREE_ALL);
1220 void cleanup_fd_cb(void *arg)
1222 gint fd = *(gint *)arg;
1224 close(fd);
1227 void cleanup_unlink_cb(void *arg)
1229 gchar *file = arg;
1231 unlink(file);
1234 void cleanup_cancel_cb(void *arg)
1236 pth_t tid = arg;
1237 pth_attr_t attr;
1238 gint join;
1240 attr = pth_attr_of(tid);
1241 pth_attr_get(attr, PTH_ATTR_JOINABLE, &join);
1242 pth_cancel(tid);
1244 if (join) {
1245 void *p;
1247 pth_join(tid, &p);
1248 g_free(p);
1252 static void *keepalive_thread(void *arg)
1254 gint to = *(gint *)arg;
1255 pth_attr_t attr = pth_attr_of(pth_self());
1257 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1258 pth_attr_destroy(attr);
1260 for (;;) {
1261 pth_event_t ev = pth_event(PTH_EVENT_TIME, pth_timeout(to, 0));
1263 pth_cleanup_push(cleanup_ev_cb, ev);
1264 pth_wait(ev);
1265 send_status_all(STATUS_KEEPALIVE);
1266 pth_cleanup_pop(1);
1269 return NULL;
1272 static void startStopKeepAlive(gboolean term)
1274 gint n = get_key_file_integer("global", "keepalive");
1276 if (keepalive_tid)
1277 pth_cancel(keepalive_tid);
1279 keepalive_tid = NULL;
1281 if (term)
1282 return;
1284 if (n > 0) {
1285 pth_attr_t attr = pth_attr_new();
1286 gpg_error_t rc;
1288 pth_attr_init(attr);
1289 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1290 keepalive_tid = pth_spawn(attr, keepalive_thread, &n);
1291 rc = gpg_error_from_syserror();
1292 pth_attr_destroy(attr);
1294 if (!keepalive_tid) {
1295 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1296 pwmd_strerror(rc));
1297 return;
1300 pth_yield(keepalive_tid);
1304 static gboolean waiting_for_exit()
1306 guint i, t;
1307 pth_event_t evs = NULL;
1309 MUTEX_LOCK(&cn_mutex);
1311 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
1312 struct client_thread_s *thd = g_slist_nth_data(cn_thread_list, i);
1313 pth_event_t ev = pth_event(PTH_EVENT_TID|PTH_UNTIL_TID_DEAD, thd->tid);
1315 if (evs)
1316 evs = pth_event_concat(evs, ev, NULL);
1317 else
1318 evs = ev;
1321 MUTEX_UNLOCK(&cn_mutex);
1323 if (!evs)
1324 return FALSE;
1326 pth_wait(evs);
1327 MUTEX_LOCK(&cn_mutex);
1328 i = g_slist_length(cn_thread_list);
1329 MUTEX_UNLOCK(&cn_mutex);
1330 pth_event_free(evs, PTH_FREE_ALL);
1331 return i ? TRUE : FALSE;
1334 static void catch_sigabrt(int sig)
1336 cache_clear(NULL, 2);
1337 #ifndef MEM_DEBUG
1338 xpanic();
1339 #endif
1342 static void server_loop(gint sockfd, gchar **socketpath)
1344 pth_t accept_tid;
1345 guint n;
1346 sigset_t sigset;
1347 pth_attr_t attr;
1348 pth_t cache_timeout_tid;
1349 gpg_error_t rc;
1351 init_commands();
1352 sigemptyset(&sigset);
1354 /* Termination */
1355 sigaddset(&sigset, SIGTERM);
1356 sigaddset(&sigset, SIGINT);
1358 /* Clears the file cache. */
1359 sigaddset(&sigset, SIGUSR1);
1361 /* Configuration file reloading. */
1362 sigaddset(&sigset, SIGHUP);
1364 /* Clears the cache and exits when something bad happens. */
1365 signal(SIGABRT, catch_sigabrt);
1366 sigaddset(&sigset, SIGABRT);
1368 /* Ignored everywhere. When a client disconnects abnormally this signal
1369 * gets raised. It isn't needed though because client_thread() will check
1370 * for rcs even after the client disconnects. */
1371 signal(SIGPIPE, SIG_IGN);
1372 sigprocmask(SIG_BLOCK, &sigset, NULL);
1374 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1375 log_write(N_("Listening on %s"), *socketpath);
1376 #ifndef HAVE_SO_PEERCRED
1377 log_write(N_("Peer credential checking is NOT supported on this OS."));
1378 #endif
1379 attr = pth_attr_new();
1380 pth_attr_init(attr);
1381 accept_tid = pth_spawn(attr, accept_thread, &sockfd);
1382 rc = gpg_error_from_syserror();
1384 if (!accept_tid) {
1385 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1386 pwmd_strerror(rc));
1387 pth_attr_destroy(attr);
1388 goto done;
1391 pth_yield(accept_tid);
1392 startStopKeepAlive(FALSE);
1393 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1394 cache_timeout_tid = pth_spawn(attr, adjust_cache_timer_thread, NULL);
1395 rc = gpg_error_from_syserror();
1397 if (!cache_timeout_tid) {
1398 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1399 pwmd_strerror(rc));
1400 pth_attr_destroy(attr);
1401 goto done;
1404 pth_yield(cache_timeout_tid);
1405 pth_attr_destroy(attr);
1408 gchar *str = get_key_file_string("global", "debug_file");
1410 if (str) {
1411 gchar *f = expand_homedir(str);
1413 g_free(str);
1414 debugfp = fopen(f, "w");
1416 if (!debugfp)
1417 log_write("%s: %s", f, pwmd_strerror(gpg_error_from_syserror()));
1418 else
1419 assuan_set_assuan_log_stream(debugfp);
1421 g_free(f);
1425 do {
1426 gint sig;
1428 pth_sigwait(&sigset, &sig);
1429 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1431 /* Caught a signal. */
1432 switch (sig) {
1433 case SIGHUP:
1434 reload_rcfile();
1435 break;
1436 case SIGABRT:
1437 // not really handled here.
1438 catch_sigabrt(SIGABRT);
1439 break;
1440 case SIGUSR1:
1441 CACHE_LOCK(NULL);
1442 log_write(N_("clearing file cache"));
1443 cache_clear(NULL, 2);
1444 CACHE_UNLOCK;
1445 break;
1446 default:
1447 quit = 1;
1448 break;
1450 } while (!quit);
1452 done:
1454 * We're out of the main server loop. This happens when a signal was sent
1455 * to terminate the daemon. We'll wait for all clients to disconnect
1456 * before exiting and ignore any following signals.
1458 shutdown(sockfd, SHUT_RDWR);
1459 close(sockfd);
1460 pth_cancel(accept_tid);
1461 pth_join(accept_tid, NULL);
1462 unlink(*socketpath);
1463 g_free(*socketpath);
1464 *socketpath = NULL;
1465 MUTEX_LOCK(&cn_mutex);
1466 n = g_slist_length(cn_thread_list);
1467 MUTEX_UNLOCK(&cn_mutex);
1469 if (n) {
1470 log_write(N_("waiting for all clients to disconnect"));
1472 do {
1473 MUTEX_LOCK(&cn_mutex);
1474 n = g_slist_length(cn_thread_list);
1475 MUTEX_UNLOCK(&cn_mutex);
1476 log_write(N_("%i clients remain"), n);
1477 } while (waiting_for_exit());
1480 startStopKeepAlive(TRUE);
1481 pth_cancel(cache_timeout_tid);
1482 cache_free();
1483 deinit_commands();
1487 * Only called from pinentry_fork() in the child process.
1489 void free_client_list()
1491 gint i, t = g_slist_length(cn_thread_list);
1493 for (i = 0; i < t; i++) {
1494 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1496 free_client(cn->cl);
1499 cache_free();
1502 static guint pwmd_cipher_to_gcrypt(guint64 flags)
1504 if (flags & PWMD_CIPHER_AES128)
1505 return GCRY_CIPHER_AES128;
1506 else if (flags & PWMD_CIPHER_AES192)
1507 return GCRY_CIPHER_AES192;
1508 else if (flags & PWMD_CIPHER_AES256)
1509 return GCRY_CIPHER_AES256;
1510 else if (flags & PWMD_CIPHER_SERPENT128)
1511 return GCRY_CIPHER_SERPENT128;
1512 else if (flags & PWMD_CIPHER_SERPENT192)
1513 return GCRY_CIPHER_SERPENT192;
1514 else if (flags & PWMD_CIPHER_SERPENT256)
1515 return GCRY_CIPHER_SERPENT256;
1516 else if (flags & PWMD_CIPHER_CAMELLIA128)
1517 return GCRY_CIPHER_CAMELLIA128;
1518 else if (flags & PWMD_CIPHER_CAMELLIA192)
1519 return GCRY_CIPHER_CAMELLIA192;
1520 else if (flags & PWMD_CIPHER_CAMELLIA256)
1521 return GCRY_CIPHER_CAMELLIA256;
1522 else if (flags & PWMD_CIPHER_BLOWFISH)
1523 return GCRY_CIPHER_BLOWFISH;
1524 else if (flags & PWMD_CIPHER_3DES)
1525 return GCRY_CIPHER_3DES;
1526 else if (flags & PWMD_CIPHER_CAST5)
1527 return GCRY_CIPHER_CAST5;
1528 else if (flags & PWMD_CIPHER_TWOFISH)
1529 return GCRY_CIPHER_TWOFISH;
1530 else if (flags & PWMD_CIPHER_TWOFISH128)
1531 return GCRY_CIPHER_TWOFISH128;
1533 /* For backwards compatibility (no flags). */
1534 return GCRY_CIPHER_AES256;
1537 guint pwmd_cipher_str_to_cipher(const gchar *str)
1539 guint64 flags = 0;
1541 if (!g_strcasecmp(str, "aes128"))
1542 flags = PWMD_CIPHER_AES128;
1543 else if (!g_strcasecmp(str, "aes192"))
1544 flags = PWMD_CIPHER_AES192;
1545 else if (!g_strcasecmp(str, "aes256"))
1546 flags = PWMD_CIPHER_AES256;
1547 if (!g_strcasecmp(str, "serpent128"))
1548 flags = PWMD_CIPHER_SERPENT128;
1549 else if (!g_strcasecmp(str, "serpent192"))
1550 flags = PWMD_CIPHER_SERPENT192;
1551 else if (!g_strcasecmp(str, "serpent256"))
1552 flags = PWMD_CIPHER_SERPENT256;
1553 if (!g_strcasecmp(str, "camellia128"))
1554 flags = PWMD_CIPHER_CAMELLIA128;
1555 else if (!g_strcasecmp(str, "camellia192"))
1556 flags = PWMD_CIPHER_CAMELLIA192;
1557 else if (!g_strcasecmp(str, "camellia256"))
1558 flags = PWMD_CIPHER_CAMELLIA256;
1559 else if (!g_strcasecmp(str, "blowfish"))
1560 flags = PWMD_CIPHER_BLOWFISH;
1561 else if (!g_strcasecmp(str, "cast5"))
1562 flags = PWMD_CIPHER_CAST5;
1563 else if (!g_strcasecmp(str, "3des"))
1564 flags = PWMD_CIPHER_3DES;
1565 else if (!g_strcasecmp(str, "twofish256"))
1566 flags = PWMD_CIPHER_TWOFISH;
1567 else if (!g_strcasecmp(str, "twofish128"))
1568 flags = PWMD_CIPHER_TWOFISH128;
1570 return flags;
1573 const gchar *pwmd_cipher_to_str(guint64 flags)
1575 if (flags & PWMD_CIPHER_AES128)
1576 return "aes128";
1577 else if (flags & PWMD_CIPHER_AES192)
1578 return "aes192";
1579 else if (flags & PWMD_CIPHER_AES256)
1580 return "aes256";
1581 else if (flags & PWMD_CIPHER_SERPENT128)
1582 return "serpent128";
1583 else if (flags & PWMD_CIPHER_SERPENT192)
1584 return "serpent192";
1585 else if (flags & PWMD_CIPHER_SERPENT256)
1586 return "serpent256";
1587 else if (flags & PWMD_CIPHER_CAMELLIA128)
1588 return "camellia128";
1589 else if (flags & PWMD_CIPHER_CAMELLIA192)
1590 return "camellia192";
1591 else if (flags & PWMD_CIPHER_CAMELLIA256)
1592 return "camellia256";
1593 else if (flags & PWMD_CIPHER_BLOWFISH)
1594 return "blowfish";
1595 else if (flags & PWMD_CIPHER_CAST5)
1596 return "cast5";
1597 else if (flags & PWMD_CIPHER_3DES)
1598 return "3des";
1599 else if (flags & PWMD_CIPHER_TWOFISH)
1600 return "twofish256";
1601 else if (flags & PWMD_CIPHER_TWOFISH128)
1602 return "twofish128";
1604 return NULL;
1607 /* To be called after read_file_header(). This sets the wanted algorithm from
1608 * .flags */
1609 gpg_error_t init_client_crypto2(const char *filename,
1610 struct crypto_s *crypto)
1612 gpg_error_t rc;
1613 guint algo;
1615 /* New file or conversion. */
1616 if (crypto->fh->v1)
1617 algo = pwmd_cipher_to_gcrypt(PWMD_CIPHER_AES256);
1618 else if (!crypto->fh->ver.fh2.flags) {
1619 gchar *tmp = get_key_file_string(filename ? filename : "global", "cipher");
1620 guint64 flags;
1622 flags = pwmd_cipher_str_to_cipher(tmp);
1623 g_free(tmp);
1624 algo = pwmd_cipher_to_gcrypt(flags);
1625 crypto->fh->ver.fh2.flags = flags;
1627 else
1628 algo = pwmd_cipher_to_gcrypt(crypto->fh->ver.fh2.flags);
1630 rc = gcry_cipher_algo_info(algo, GCRYCTL_TEST_ALGO, NULL, NULL);
1632 if (rc)
1633 return rc;
1635 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL,
1636 &crypto->keysize);
1638 if (rc)
1639 return rc;
1641 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_BLKLEN, NULL,
1642 &crypto->blocksize);
1644 if (rc)
1645 return rc;
1647 if (crypto->gh)
1648 gcry_cipher_close(crypto->gh);
1650 return gcry_cipher_open(&crypto->gh, algo, GCRY_CIPHER_MODE_CBC, 0);
1653 struct crypto_s *init_client_crypto()
1655 struct crypto_s *new = g_malloc0(sizeof(struct crypto_s));
1657 if (!new) {
1658 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
1659 return NULL;
1662 return new;
1665 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
1666 const gchar *outfile)
1668 gpg_error_t rc;
1669 guchar md5file[gcry_md_get_algo_dlen(GCRY_MD_MD5)];
1670 guint64 iter;
1671 struct crypto_s *crypto = init_client_crypto();
1672 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
1674 if (!crypto)
1675 return GPG_ERR_ENOMEM;
1677 crypto->key = gcry_malloc(hashlen);
1679 if (!crypto->key) {
1680 cleanup_crypto(&crypto);
1681 return GPG_ERR_ENOMEM;
1684 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
1685 filename);
1686 crypto->fh = read_file_header(filename, TRUE, &rc);
1688 if (!crypto->fh)
1689 goto done;
1691 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
1693 /* The header in version 1 had a bug where the iterations were off-by-one.
1694 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
1695 * header.
1697 if (crypto->fh->ver.fh1.iter != -1) {
1698 if (keyfile) {
1699 rc = parse_rcfile_keyfile(crypto, keyfile, TRUE);
1701 if (rc)
1702 goto done;
1704 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1705 crypto->tkey_len);
1706 gcry_free(crypto->tkey);
1707 crypto->tkey = NULL;
1709 else {
1710 rc = get_password(filename, crypto, md5file, crypto->key,
1711 PINENTRY_OPEN);
1713 if (rc)
1714 goto done;
1718 rc = init_client_crypto2(NULL, crypto);
1720 if (rc)
1721 goto done;
1723 rc = try_xml_decrypt(NULL, crypto, &crypto->fh->doc, &crypto->fh->len);
1725 if (rc)
1726 goto done;
1728 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
1730 if (rc) {
1731 log_write("%s: %s", filename, pwmd_strerror(rc));
1732 goto done;
1735 crypto->fh->v1 = FALSE;
1737 iter = crypto->fh->ver.fh1.iter+1;
1738 memset(&crypto->fh->ver.fh2, 0, sizeof(crypto->fh->ver.fh2));
1739 /* Keep the iterations and key from the original file. */
1740 crypto->fh->ver.fh2.iter = iter;
1741 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
1743 done:
1744 if (rc)
1745 send_error(NULL, rc);
1747 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
1748 cleanup_crypto(&crypto);
1749 return rc;
1752 int main(int argc, char *argv[])
1754 gint opt;
1755 struct sockaddr_un addr;
1756 gchar buf[PATH_MAX];
1757 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
1758 gchar *socketarg = NULL;
1759 gchar *datadir = NULL;
1760 gboolean n;
1761 gint x;
1762 gchar *p;
1763 gchar **cache_push = NULL;
1764 gchar *import = NULL, *keyfile = NULL;
1765 guint64 cmd_iterations = 0UL;
1766 gboolean iterations_arg = FALSE;
1767 gint default_timeout;
1768 gboolean rcfile_spec = FALSE;
1769 gint estatus = EXIT_FAILURE;
1770 gint sockfd;
1771 gchar *outfile = NULL;
1772 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
1773 gint do_unlink = 1;
1774 gboolean secure = FALSE;
1775 gint background = 1;
1776 gchar *convert = NULL;
1777 gint show_version = 0;
1778 gint show_help = 0;
1779 #ifdef WITH_PINENTRY
1780 gboolean disable_pinentry = FALSE;
1781 #endif
1782 gint opt_index;
1783 const struct option long_opts[] = {
1784 #ifdef WITH_PINENTRY
1785 { "no-pinentry", 0, 0, 'P' },
1786 #endif
1787 { "outfile", 1, 0, 'o' },
1788 { "convert", 1, 0, 'C' },
1789 { "no-fork", 0, 0, 'n' },
1790 { "disable-dump", 0, 0, 'D' },
1791 { "import", 1, 0, 'I' },
1792 { "iterations", 1, 0, 'i' },
1793 { "key-file", 1, 0, 'k' },
1794 { "rcfile", 1, 0, 'f' },
1795 { "version", 0, &show_version, 1 },
1796 { "help", 0, &show_help, 1 },
1797 { 0, 0, 0, 0}
1799 #ifdef WITH_PINENTRY
1800 const gchar *optstring = "Po:C:nDI:i:k:f:";
1801 #else
1802 const gchar *optstring = "o:C:nDI:i:k:f:";
1803 #endif
1804 #ifndef DEBUG
1805 #ifdef HAVE_SETRLIMIT
1806 struct rlimit rl;
1808 rl.rlim_cur = rl.rlim_max = 0;
1810 if (setrlimit(RLIMIT_CORE, &rl) != 0)
1811 err(EXIT_FAILURE, "setrlimit()");
1812 #endif
1813 #endif
1815 #ifdef ENABLE_NLS
1816 setlocale(LC_ALL, "");
1817 bindtextdomain("pwmd", LOCALEDIR);
1818 textdomain("pwmd");
1819 #endif
1821 #ifndef MEM_DEBUG
1822 xmem_init();
1823 #endif
1824 setup_gcrypt();
1825 gpg_err_init();
1826 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
1827 g_mem_set_vtable(&mtable);
1828 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
1829 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
1830 xmlInitMemory();
1831 xmlInitGlobals();
1832 xmlInitParser();
1833 xmlXPathInit();
1834 g_snprintf(buf, sizeof(buf), "%s/.pwmd", g_get_home_dir());
1836 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
1837 err(EXIT_FAILURE, "%s", buf);
1839 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", g_get_home_dir());
1841 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
1842 err(EXIT_FAILURE, "%s", buf);
1844 cmdline = TRUE;
1846 while ((opt = getopt_long(argc, argv, optstring, long_opts, &opt_index)) != -1) {
1847 switch (opt) {
1848 case 0:
1849 if (show_help)
1850 usage(argv[0], EXIT_SUCCESS);
1852 if (show_version) {
1853 printf(N_("%s\nCopyright (C) 2010 %s\nReleased under the terms of the GPL v2. Use at your own risk.\n\nCompile time features:\n%s"), PACKAGE_STRING,
1854 PACKAGE_BUGREPORT,
1855 #ifdef WITH_PINENTRY
1856 "+WITH_PINENTRY\n"
1857 #else
1858 "-WITH_PINENTRY\n"
1859 #endif
1860 #ifdef WITH_QUALITY
1861 "+WITH_QUALITY\n"
1862 #else
1863 "-WITH_QUALITY\n"
1864 #endif
1865 #ifdef WITH_LIBACL
1866 "+WITH_LIBACL\n"
1867 #else
1868 "-WITH_LIBACL\n"
1869 #endif
1870 #ifdef DEBUG
1871 "+DEBUG\n"
1872 #else
1873 "-DEBUG\n"
1874 #endif
1875 #ifdef MEM_DEBUG
1876 "+MEM_DEBUG\n"
1877 #else
1878 "-MEM_DEBUG\n"
1879 #endif
1880 #ifdef MUTEX_DEBUG
1881 "+MUTEX_DEBUG\n"
1882 #else
1883 "-MUTEX_DEBUG\n"
1884 #endif
1886 exit(EXIT_SUCCESS);
1888 break;
1889 #ifdef WITH_PINENTRY
1890 case 'P':
1891 disable_pinentry = TRUE;
1892 break;
1893 #endif
1894 case 'o':
1895 outfile = optarg;
1896 break;
1897 case 'C':
1898 convert = optarg;
1899 break;
1900 case 'n':
1901 background = 0;
1902 break;
1903 case 'D':
1904 secure = TRUE;
1905 break;
1906 case 'I':
1907 import = optarg;
1908 break;
1909 case 'i':
1910 cmd_iterations = strtoul(optarg, NULL, 10);
1912 if (cmd_iterations == G_MAXULONG) {
1913 log_write("%s", N_("invalid iteration count"));
1914 usage(argv[0], EXIT_FAILURE);
1917 iterations_arg = TRUE;
1918 break;
1919 case 'k':
1920 keyfile = optarg;
1921 break;
1922 case 'f':
1923 rcfile = g_strdup(optarg);
1924 rcfile_spec = TRUE;
1925 break;
1926 default:
1927 usage(argv[0], EXIT_FAILURE);
1931 pth_mutex_init(&cn_mutex);
1932 pth_mutex_init(&cache_mutex);
1933 pth_mutex_init(&rcfile_mutex);
1934 #ifdef WITH_PINENTRY
1935 pth_mutex_init(&pin_mutex);
1936 #endif
1938 if (!rcfile)
1939 rcfile = g_strdup_printf("%s/.pwmd/config", g_get_home_dir());
1941 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
1942 exit(EXIT_FAILURE);
1944 #ifdef WITH_PINENTRY
1945 if (disable_pinentry == TRUE)
1946 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
1947 #endif
1949 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
1950 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
1952 if (log_syslog == TRUE)
1953 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
1955 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
1956 x = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
1957 errno = 0;
1959 if (setpriority(PRIO_PROCESS, 0, x) == -1) {
1960 log_write("setpriority(): %s", pwmd_strerror(gpg_error_from_syserror()));
1961 goto do_exit;
1965 #ifdef HAVE_MLOCKALL
1966 if (disable_mlock == FALSE && mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
1967 log_write("mlockall(): %s", pwmd_strerror(gpg_error_from_syserror()));
1968 goto do_exit;
1970 #endif
1972 if (convert) {
1973 if (!outfile)
1974 usage(argv[0], EXIT_FAILURE);
1976 opt = convert_file(convert, keyfile, outfile);
1977 g_key_file_free(keyfileh);
1978 g_free(rcfile);
1979 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
1982 if (import) {
1983 if (!outfile)
1984 usage(argv[0], EXIT_FAILURE);
1986 if (!iterations_arg)
1987 cmd_iterations = (guint64)get_key_file_double("global", "iterations");
1989 opt = xml_import(import, outfile, keyfile, cmd_iterations);
1990 g_key_file_free(keyfileh);
1991 g_free(rcfile);
1992 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
1995 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
1996 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
1998 socketarg = expand_homedir(p);
1999 g_free(p);
2001 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
2002 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
2004 datadir = expand_homedir(p);
2005 g_free(p);
2007 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
2008 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
2009 disable_list_and_dump = n;
2011 else
2012 disable_list_and_dump = secure;
2014 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
2015 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
2016 else
2017 default_timeout = -1;
2019 setup_logging(keyfileh);
2021 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2022 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2024 if (argc != optind) {
2025 for (; optind < argc; optind++) {
2026 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2027 errx(EXIT_FAILURE, "%s", pwmd_strerror(GPG_ERR_ENOMEM));
2031 if (strchr(socketarg, '/') == NULL) {
2032 socketdir = g_get_current_dir();
2033 socketname = g_strdup(socketarg);
2034 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2036 else {
2037 socketname = g_strdup(strrchr(socketarg, '/'));
2038 socketname++;
2039 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2040 socketdir = g_strdup(socketarg);
2041 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2044 if (chdir(datadir)) {
2045 log_write("%s: %s", datadir, pwmd_strerror(gpg_error_from_syserror()));
2046 unlink(socketpath);
2047 goto do_exit;
2050 if (parse_rcfile_keys() == FALSE)
2051 goto do_exit;
2053 clear_rcfile_keys();
2056 * Set the cache entry for a file. Prompts for the password.
2058 if (cache_push) {
2059 for (opt = 0; cache_push[opt]; opt++)
2060 do_cache_push(cache_push[opt], NULL, 0);
2062 g_strfreev(cache_push);
2063 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2067 * bind() doesn't like the full pathname of the socket or any non alphanum
2068 * characters so change to the directory where the socket is wanted then
2069 * create it then change to datadir.
2071 if (chdir(socketdir)) {
2072 log_write("%s: %s", socketdir, pwmd_strerror(gpg_error_from_syserror()));
2073 goto do_exit;
2076 g_free(socketdir);
2078 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2079 log_write("socket(): %s", pwmd_strerror(gpg_error_from_syserror()));
2080 goto do_exit;
2083 addr.sun_family = AF_UNIX;
2084 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2086 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2087 log_write("bind(): %s", pwmd_strerror(gpg_error_from_syserror()));
2089 if (errno == EADDRINUSE)
2090 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2091 "stale socket. Please remove it manually."), socketpath);
2093 do_unlink = 0;
2094 goto do_exit;
2097 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2098 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2099 mode_t mode = strtol(t, NULL, 8);
2100 mode_t mask = umask(0);
2102 g_free(t);
2104 if (chmod(socketname, mode) == -1) {
2105 log_write("%s: %s", socketname, pwmd_strerror(gpg_error_from_syserror()));
2106 close(sockfd);
2107 unlink(socketpath);
2108 umask(mask);
2109 goto do_exit;
2112 umask(mask);
2115 g_free(--socketname);
2117 if (chdir(datadir)) {
2118 log_write("%s: %s", datadir, pwmd_strerror(gpg_error_from_syserror()));
2119 close(sockfd);
2120 unlink(socketpath);
2121 goto do_exit;
2124 g_free(datadir);
2126 if (listen(sockfd, 0) == -1) {
2127 log_write("listen(): %s", pwmd_strerror(gpg_error_from_syserror()));
2128 goto do_exit;
2131 cmdline = FALSE;
2132 unsetenv("DISPLAY");
2133 unsetenv("TERM");
2135 if (background) {
2136 switch (fork()) {
2137 case -1:
2138 log_write("fork(): %s", pwmd_strerror(gpg_error_from_syserror()));
2139 goto do_exit;
2140 case 0:
2141 close(0);
2142 close(1);
2143 close(2);
2144 setsid();
2145 break;
2146 default:
2147 exit(EXIT_SUCCESS);
2151 server_loop(sockfd, &socketpath);
2152 estatus = EXIT_SUCCESS;
2154 do_exit:
2155 if (socketpath && do_unlink) {
2156 unlink(socketpath);
2157 g_free(socketpath);
2160 g_free(socketarg);
2161 g_key_file_free(keyfileh);
2162 g_free(rcfile);
2163 xmlCleanupParser();
2164 xmlCleanupGlobals();
2166 if (estatus == EXIT_SUCCESS)
2167 log_write(N_("pwmd exiting normally"));
2169 #if defined(DEBUG) && !defined(MEM_DEBUG)
2170 xdump();
2171 #endif
2172 exit(estatus);