A few minor cleanups.
[pwmd.git] / src / pwmd.c
blob9a97eed582509216d3f80e73b4e69244208e6d3f
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 <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 <grp.h>
38 #include <glib.h>
39 #include <glib/gprintf.h>
40 #include <sys/mman.h>
41 #include <termios.h>
42 #include <assert.h>
43 #include <syslog.h>
44 #include <zlib.h>
45 #include <gcrypt.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #include <netdb.h>
49 #include <sys/time.h>
50 #include <sys/resource.h>
52 #ifdef HAVE_GETOPT_LONG
53 #ifdef HAVE_GETOPT_H
54 #include <getopt.h>
55 #endif
56 #else
57 #include "getopt_long.h"
58 #endif
60 #ifdef TM_IN_SYS_TIME
61 #include <sys/time.h>
62 #else
63 #include <time.h>
64 #endif
66 #include "mem.h"
67 #include "xml.h"
68 #include "common.h"
70 #ifdef WITH_PINENTRY
71 #include "pinentry.h"
72 #endif
74 #include "commands.h"
75 #include "pwmd_error.h"
76 #include "cache.h"
77 #include "misc.h"
78 #include "pwmd.h"
79 #include "lock.h"
80 #include "rcfile.h"
82 GCRY_THREAD_OPTION_PTH_IMPL;
84 static void *reload_rcfile_thread(void *arg)
86 gboolean b = disable_list_and_dump;
87 gchar **users = g_key_file_get_string_list(keyfileh, "global", "allowed",
88 NULL, NULL);
89 GKeyFile *k;
90 pth_attr_t attr = pth_attr_of(pth_self());
92 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
93 pth_attr_destroy(attr);
94 MUTEX_LOCK(&rcfile_mutex);
95 log_write(N_("reloading configuration file '%s'"), rcfile);
96 k = parse_rcfile(FALSE);
98 if (!k)
99 goto done;
101 g_key_file_free(keyfileh);
102 keyfileh = k;
103 parse_rcfile_keys();
104 clear_rcfile_keys();
105 startStopKeepAlive(FALSE);
106 send_status_all(STATUS_CONFIG);
107 done:
108 disable_list_and_dump = !disable_list_and_dump ? b : TRUE;
109 g_key_file_set_string_list(keyfileh, "global", "allowed",
110 (const gchar **)users, g_strv_length(users));
111 g_strfreev(users);
112 MUTEX_UNLOCK(&rcfile_mutex);
113 return NULL;
116 static void reload_rcfile()
118 pth_t tid;
119 pth_attr_t attr = pth_attr_new();
120 gint n;
122 pth_attr_init(attr);
123 pth_attr_set(attr, PTH_ATTR_JOINABLE, 0);
124 tid = pth_spawn(attr, reload_rcfile_thread, NULL);
125 n = errno;
126 pth_attr_destroy(attr);
128 if (!tid)
129 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
130 _gpg_strerror(gpg_error_from_errno(n)));
133 gpg_error_t send_syserror(assuan_context_t ctx, gint e)
135 gpg_error_t n = gpg_error_from_errno(e);
136 struct client_s *client = assuan_get_pointer(ctx);
138 client->last_rc = e;
139 return assuan_process_done(ctx, assuan_set_error(ctx, n, _gpg_strerror(n)));
142 gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e)
144 gpg_err_code_t n = gpg_err_code(e);
145 gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n);
146 struct client_s *client = assuan_get_pointer(ctx);
148 if (client)
149 client->last_rc = e;
151 if (!e)
152 return assuan_process_done(ctx, 0);
154 if (!ctx) {
155 log_write("%s", pwmd_strerror(e));
156 return e;
159 if (n == EPWMD_LIBXML_ERROR) {
160 xmlErrorPtr xe = client->xml_error;
162 if (!xe)
163 xe = xmlGetLastError();
165 e = assuan_process_done(ctx, assuan_set_error(ctx, code, xe->message));
166 log_write("%s", xe->message);
168 if (xe == client->xml_error)
169 xmlResetError(xe);
170 else
171 xmlResetLastError();
173 client->xml_error = NULL;
174 return e;
177 return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e)));
180 void log_write(const gchar *fmt, ...)
182 gchar *args, *line;
183 va_list ap;
184 struct tm *tm;
185 time_t now;
186 gchar tbuf[21];
187 gint fd = -1;
188 gchar *name;
189 gchar buf[255];
190 pth_t tid = pth_self();
191 pth_attr_t attr;
193 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
194 return;
196 if (!cmdline && logfile) {
197 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
198 warn("%s", logfile);
199 return;
203 va_start(ap, fmt);
205 if (g_vasprintf(&args, fmt, ap) == -1) {
206 if (logfile)
207 close(fd);
209 va_end(ap);
210 return;
213 va_end(ap);
215 if (cmdline) {
216 fprintf(stderr, "%s\n", args);
217 fflush(stderr);
218 g_free(args);
219 return;
222 attr = pth_attr_of(tid);
224 if (pth_attr_get(attr, PTH_ATTR_NAME, &name) == FALSE)
225 name = "unknown";
227 pth_attr_destroy(attr);
228 name = print_fmt(buf, sizeof(buf), "%s(%p): ", name, tid);
230 if (!cmdline && log_syslog == TRUE)
231 syslog(LOG_INFO, "%s%s", name, args);
233 time(&now);
234 tm = localtime(&now);
235 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
236 tbuf[sizeof(tbuf) - 1] = 0;
238 if (args[strlen(args)-1] == '\n')
239 args[strlen(args)-1] = 0;
241 line = g_strdup_printf("%s %i %s%s\n", tbuf, getpid(), name, args);
242 g_free(args);
244 if (!line) {
245 if (logfile)
246 close(fd);
248 return;
251 if (logfile) {
252 pth_write(fd, line, strlen(line));
253 fsync(fd);
254 close(fd);
257 if (isatty(STDERR_FILENO)) {
258 fprintf(stderr, "%s", line);
259 fflush(stderr);
262 g_free(line);
265 static void usage(gchar *pn, gint rc)
267 g_fprintf(rc == EXIT_FAILURE ? stderr : stdout, N_(
268 "Usage: %s [options] [file1] [...]\n"
269 " --no-fork/-n\n"
270 " run as a foreground process\n"
271 " --rcfile/-f <filename>\n"
272 " load the specified rcfile (~/.pwmd/config)\n"
273 " --convert/-C <filename>\n"
274 " convert a version 1 data file to version 2\n"
275 " --import/-I <filename>\n"
276 " import an XML file\n"
277 " --iterations/-i\n"
278 " encrypt with the specified number of iterations when importing\n"
279 " (default is in the rcfile \"global\" section)\n"
280 " --key-file/-k <filename>\n"
281 " obtain the key from the specified file when importing or converting\n"
282 " --outfile/-o <filename>\n"
283 " output file to use when importing or converting (- for stdout)\n"
284 " --disable-dump/-D\n"
285 " disable use of the LIST, XPATH and DUMP commands\n"
286 " --no-pinentry/-P\n"
287 " disable use of pinentry\n"
288 " --version\n"
289 " --help\n"
290 ), pn);
291 exit(rc);
294 static void setup_gcrypt()
296 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
298 if (!gcry_check_version(GCRYPT_VERSION))
299 errx(EXIT_FAILURE, N_("gcry_check_version(): Incompatible libgcrypt. Wanted %s, got %s."), GCRYPT_VERSION, gcry_check_version(NULL));
301 gcry_set_allocation_handler(xmalloc, xmalloc, NULL, xrealloc, xfree);
304 static gpg_error_t validate_peer(struct client_s *cl)
306 gchar **users;
307 gboolean allowed = FALSE;
308 pid_t pid;
309 gid_t gid;
310 uid_t uid;
311 gpg_error_t rc = assuan_get_peercred(cl->ctx, &pid, &uid, &gid);
313 if (rc)
314 return rc;
316 users = g_key_file_get_string_list(keyfileh, "global", "allowed", NULL, NULL);
318 if (users) {
319 for (gchar **p = users; *p; p++) {
320 struct passwd pw, *result;
321 struct group gr, *gresult;
322 char *buf;
324 if (*(*p) == '@') {
325 size_t len = sysconf(_SC_GETGR_R_SIZE_MAX);
327 if (len == -1)
328 len = 16384;
330 buf = g_malloc(len);
332 if (!buf) {
333 g_strfreev(users);
334 return gpg_error_from_errno(ENOMEM);
337 if (!getgrnam_r(*(p)+1, &gr, buf, len, &gresult) && gresult) {
338 if (gresult->gr_gid == gid) {
339 g_free(buf);
340 allowed = TRUE;
341 break;
344 len = sysconf(_SC_GETPW_R_SIZE_MAX);
346 if (len == -1)
347 len = 16384;
349 gchar *tbuf = g_malloc(len);
351 for (gchar **t = gresult->gr_mem; *t; t++) {
352 if (!getpwnam_r(*t, &pw, tbuf, len, &result) && result) {
353 if (result->pw_uid == uid) {
354 g_free(buf);
355 allowed = TRUE;
356 break;
361 g_free(tbuf);
363 if (allowed)
364 break;
367 else {
368 size_t len = sysconf(_SC_GETPW_R_SIZE_MAX);
370 if (len == -1)
371 len = 16384;
373 buf = g_malloc(len);
375 if (!buf) {
376 g_strfreev(users);
377 return gpg_error_from_errno(ENOMEM);
380 if (!getpwnam_r(*p, &pw, buf, len, &result) && result) {
381 if (result->pw_uid == uid) {
382 g_free(buf);
383 allowed = TRUE;
384 break;
389 g_free(buf);
392 g_strfreev(users);
395 log_write("peer %s: uid=%i, gid=%i, pid=%i",
396 allowed ? N_("accepted") : N_("rejected"), uid, gid,pid);
397 return allowed ? 0 : GPG_ERR_INV_USER_ID;
400 static gboolean new_connection(struct client_s *cl)
402 gpg_error_t rc;
403 gchar *ver;
404 gchar *str;
406 rc = assuan_init_socket_server_ext(&cl->ctx, cl->thd->fd, 2);
408 if (rc)
409 goto fail;
411 assuan_set_pointer(cl->ctx, cl);
412 ver = g_strdup_printf("%s", PACKAGE_STRING);
413 assuan_set_hello_line(cl->ctx, ver);
414 g_free(ver);
415 rc = register_commands(cl->ctx);
417 if (rc)
418 goto fail;
420 rc = assuan_accept(cl->ctx);
422 if (rc)
423 goto fail;
425 rc = validate_peer(cl);
427 /* May not be implemented on all platforms. */
428 if (rc && gpg_err_code(rc) != GPG_ERR_ASS_GENERAL)
429 goto fail;
431 str = get_key_file_string("global", "debug_file");
433 if (debugfp && str)
434 assuan_set_log_stream(cl->ctx, debugfp);
436 if (str)
437 g_free(str);
439 return TRUE;
441 fail:
442 log_write("%s", _gpg_strerror(rc));
443 return FALSE;
446 static void xml_error_cb(void *data, xmlErrorPtr e)
448 struct client_s *client = data;
451 * Keep the first reported error as the one to show in the error
452 * description. Reset in send_error().
454 if (client->xml_error)
455 return;
457 xmlCopyError(e, client->xml_error);
460 void close_file_header(file_header_internal_t *fh)
462 if (!fh)
463 return;
465 if (fh->fd != -1 || (cmdline == TRUE && fh->fd != STDOUT_FILENO))
466 close(fh->fd);
468 if (fh->doc)
469 gcry_free(fh->doc);
471 g_free(fh);
474 void cleanup_crypto(struct crypto_s **c)
476 struct crypto_s *cr = *c;
478 if (!cr)
479 return;
481 if (cr->iv) {
482 gcry_free(cr->iv);
483 cr->iv = NULL;
486 if (cr->key) {
487 gcry_free(cr->key);
488 cr->key = NULL;
491 if (cr->tkey) {
492 gcry_free(cr->tkey);
493 cr->tkey = NULL;
496 if (cr->tkey2) {
497 gcry_free(cr->tkey2);
498 cr->tkey2 = NULL;
501 if (cr->inbuf) {
502 gcry_free(cr->inbuf);
503 cr->inbuf = NULL;
506 if (cr->outbuf) {
507 gcry_free(cr->outbuf);
508 cr->outbuf = NULL;
511 close_file_header(cr->fh);
512 cr->fh = NULL;
514 if (cr->gh)
515 gcry_cipher_close(cr->gh);
517 cr->gh = NULL;
518 g_free(cr);
519 *c = NULL;
523 * This is called after a client_thread terminates. Set with
524 * pth_cleanup_push().
526 static void cleanup_cb(void *arg)
528 struct client_thread_s *cn = arg;
529 struct client_s *cl = cn->cl;
531 MUTEX_LOCK(&cn_mutex);
532 cn_thread_list = g_slist_remove(cn_thread_list, cn);
533 MUTEX_UNLOCK(&cn_mutex);
535 if (cn->msg_tid) {
536 MUTEX_LOCK(&cn->mp_mutex);
537 pth_cancel(cn->msg_tid);
538 MUTEX_UNLOCK(&cn->mp_mutex);
541 if (cn->mp) {
542 while (pth_msgport_pending(cn->mp)) {
543 pth_message_t *msg = pth_msgport_get(cn->mp);
545 g_free(msg->m_data);
546 g_free(msg);
549 pth_msgport_destroy(cn->mp);
552 if (!cl) {
553 if (cn->fd != -1)
554 close(cn->fd);
556 goto done;
559 if (!cl->freed)
560 cleanup_client(cl);
562 if (cl->ctx)
563 assuan_deinit_server(cl->ctx);
564 else if (cl->thd && cl->thd->fd != -1)
565 close(cl->thd->fd);
567 #ifdef WITH_PINENTRY
568 if (cl->pinentry)
569 cleanup_pinentry(cl->pinentry);
570 #endif
572 if (cl->crypto)
573 cleanup_crypto(&cl->crypto);
575 g_free(cl);
576 done:
577 log_write(N_("exiting, fd=%i"), cn->fd);
578 g_free(cn);
579 send_status_all(STATUS_CLIENTS);
583 * Called every time a connection is made from init_new_connection(). This is
584 * the thread entry point.
586 static void *client_thread(void *data)
588 struct client_thread_s *thd = data;
589 struct client_s *cl = g_malloc0(sizeof(struct client_s));
590 gpg_error_t rc;
591 pth_attr_t attr;
592 gint n;
595 * Prevent a race condition with init_new_connection() if this thread
596 * fails (returns) for some reason before init_new_connection() releases
597 * the cn_mutex.
599 MUTEX_LOCK(&cn_mutex);
600 MUTEX_UNLOCK(&cn_mutex);
601 pth_cleanup_push(cleanup_cb, thd);
603 if (!cl) {
604 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
605 goto fail;
608 attr = pth_attr_of(pth_self());
609 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
610 pth_attr_destroy(attr);
611 thd->cl = cl;
612 cl->thd = thd;
614 if (!new_connection(cl))
615 goto fail;
617 #ifdef WITH_PINENTRY
618 cl->pinentry = pinentry_init();
620 if (!cl->pinentry) {
621 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
622 goto fail;
624 #endif
626 #ifdef HAVE_MLOCKALL
627 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
628 log_write("mlockall(): %s", strerror(errno));
629 goto fail;
631 #endif
633 thd->mp = pth_msgport_create(NULL);
634 pth_mutex_init(&thd->mp_mutex);
635 thd->msg_tid = pth_spawn(NULL, client_msg_thread, thd);
636 n = errno;
638 if (!thd->msg_tid) {
639 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
640 _gpg_strerror(gpg_error_from_errno(n)));
641 goto fail;
644 pth_yield(thd->msg_tid);
645 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
647 if (rc) {
648 log_write("%s", _gpg_strerror(rc));
649 goto fail;
652 send_status_all(STATUS_CLIENTS);
653 xmlSetStructuredErrorFunc(cl, xml_error_cb);
655 for (;;) {
656 #ifdef WITH_PINENTRY
657 pth_event_t pev = NULL;
658 #endif
659 pth_status_t st, wst;
660 pth_event_t wev = NULL;
661 pth_event_t rev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE,
662 cl->thd->fd);
663 pth_event_t ev = rev;
665 #ifdef WITH_PINENTRY
666 if (cl->pinentry->status == PINENTRY_RUNNING) {
667 pev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, cl->pinentry->fd);
668 ev = pth_event_concat(ev, pev, NULL);
670 #endif
672 if (cl->inquire_status == INQUIRE_BUSY) {
673 wev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_WRITEABLE, cl->thd->fd);
674 ev = pth_event_concat(ev, wev, NULL);
677 pth_cleanup_push(cleanup_ev_cb, ev);
678 pth_wait(ev);
679 st = pth_event_status(rev);
680 wst = pth_event_status(wev);
682 if (st == PTH_STATUS_OCCURRED || wst == PTH_STATUS_OCCURRED) {
683 rc = assuan_process_next(cl->ctx);
685 if (rc) {
686 cl->inquire_status = INQUIRE_INIT;
687 pth_cleanup_pop(1);
689 if (gpg_err_code(rc) == GPG_ERR_EOF)
690 goto done;
692 log_write("assuan_process_next(): %s", _gpg_strerror(rc));
693 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
695 if (rc) {
696 log_write("assuan_process_done(): %s", _gpg_strerror(rc));
697 goto done;
700 else {
701 #ifdef WITH_PINENTRY
702 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
703 cl->pinentry->status = PINENTRY_RUNNING;
704 #endif
706 switch (cl->inquire_status) {
707 case INQUIRE_BUSY:
708 case INQUIRE_INIT:
709 break;
710 case INQUIRE_DONE:
711 cl->inquire_status = INQUIRE_INIT;
712 rc = assuan_process_done(cl->ctx, 0);
713 break;
718 #ifdef WITH_PINENTRY
719 if (pev)
720 st = pth_event_status(pev);
722 rc = pinentry_iterate(cl,
723 pev && cl->pinentry->fd != -1 && st == PTH_STATUS_OCCURRED);
724 #endif
725 pth_cleanup_pop(1);
729 * Client cleanup (including XML data) is done in cleanup_cb().
731 done:
732 fail:
733 pth_exit(PTH_CANCELED);
734 return NULL;
737 static gchar *do_read_password(const gchar *prompt)
739 gchar buf[LINE_MAX] = {0}, *p;
740 struct termios told, tnew;
741 gchar *key;
743 if (tcgetattr(STDIN_FILENO, &told) == -1) {
744 log_write("tcgetattr(): %s", strerror(errno));
745 return NULL;
748 memcpy(&tnew, &told, sizeof(struct termios));
749 tnew.c_lflag &= ~(ECHO);
750 tnew.c_lflag |= ICANON|ECHONL;
752 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
753 log_write("tcsetattr(): %s", strerror(errno));
754 tcsetattr(STDIN_FILENO, TCSANOW, &told);
755 return NULL;
758 fprintf(stderr, "%s", prompt);
760 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
761 tcsetattr(STDIN_FILENO, TCSANOW, &told);
762 return NULL;
765 tcsetattr(STDIN_FILENO, TCSANOW, &told);
766 p[strlen(p) - 1] = 0;
768 if (!buf[0]) {
769 key = gcry_malloc(1);
770 key[0] = 0;
772 else {
773 key = gcry_malloc(strlen(p) + 1);
774 sprintf(key, "%s", p);
777 memset(&buf, 0, sizeof(buf));
778 return key;
781 /* Only used when "enable_pinentry" is "false" or -P. */
782 static gpg_error_t read_password(const gchar *filename,
783 struct crypto_s *crypto, guchar *key, pinentry_cmd_t which)
785 gchar *prompt;
787 if (which == PINENTRY_SAVE) {
788 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
789 crypto->tkey = do_read_password(prompt);
790 g_free(prompt);
792 if (!crypto->tkey) {
793 log_write(N_("%s: Skipping file"), filename);
794 return GPG_ERR_BAD_PASSPHRASE;
797 prompt = g_strdup_printf(N_("Repeat passphrase: "));
798 crypto->tkey2 = do_read_password(prompt);
799 g_free(prompt);
801 if (!crypto->tkey2) {
802 log_write(N_("%s: Skipping file"), filename);
803 return GPG_ERR_BAD_PASSPHRASE;
806 if (strcmp(crypto->tkey, crypto->tkey2)) {
807 log_write(N_("%s: Passphrase mismatch"), filename);
808 return GPG_ERR_INV_PASSPHRASE;
811 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
812 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
813 return 0;
816 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
818 if ((crypto->tkey = do_read_password(prompt)) == NULL) {
819 log_write(N_("%s: Skipping file"), filename);
820 g_free(prompt);
821 return GPG_ERR_BAD_PASSPHRASE;
824 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
825 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
826 g_free(prompt);
827 return 0;
831 * inbuf must have been allocated with gcry_malloc().
833 gpg_error_t export_common(const gchar *filename, struct crypto_s *crypto,
834 gpointer inbuf, gulong insize)
836 gpg_error_t rc;
837 gint level, zrc;
838 gulong outsize;
839 gpointer outbuf;
841 rc = update_save_flags(NULL, crypto);
843 if (rc)
844 return rc;
846 level = get_key_file_integer(filename, "compression_level");
848 if (level < 0)
849 level = 0;
851 if (do_compress(NULL, level, inbuf, insize, &outbuf, &outsize, &zrc)
852 == FALSE) {
853 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
856 crypto->inbuf = outbuf;
857 crypto->insize = outsize;
858 rc = do_xml_encrypt(NULL, crypto, filename);
859 return rc;
862 static gpg_error_t get_password(const gchar *filename,
863 struct crypto_s *crypto, guchar *md5file, guchar *key,
864 pinentry_cmd_t which)
866 #ifdef WITH_PINENTRY
867 gpg_error_t rc = 0;
869 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
870 == FALSE) {
871 #endif
872 return read_password(filename, crypto, key, which);
873 #ifdef WITH_PINENTRY
875 else {
876 gchar *result = NULL;
877 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
879 pth_mutex_init(&pin->status_mutex);
880 set_pinentry_defaults(pin);
881 pin->which = which;
882 pin->filename = g_strdup(filename);
883 rc = pinentry_getpin(pin, &result);
885 if (rc) {
886 xfree(result);
887 goto done;
890 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, result ? strlen(result) : 1);
891 xfree(result);
892 cleanup_pinentry(pin);
895 done:
896 return rc;
897 #endif
900 static gboolean xml_import(const gchar *filename, const gchar *outfile,
901 const gchar *keyfile, guint64 iter)
903 xmlDocPtr doc;
904 gint fd;
905 struct stat st;
906 gint len;
907 xmlChar *xmlbuf;
908 xmlChar *xml;
909 gpg_error_t rc;
910 struct crypto_s *crypto;
911 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
913 if (stat(filename, &st) == -1) {
914 log_write("%s: %s", filename, strerror(errno));
915 return FALSE;
918 crypto = init_client_crypto();
920 if (!crypto)
921 return FALSE;
923 crypto->key = gcry_malloc(hashlen);
924 memset(crypto->key, 0, hashlen);
926 if (!crypto->key) {
927 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
928 goto fail;
931 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
932 filename, outfile);
934 if (iter && keyfile) {
935 rc = parse_rcfile_keyfile(crypto, keyfile, TRUE);
937 if (rc)
938 goto fail;
940 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
941 crypto->tkey_len);
943 else if (iter) {
944 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
946 if (rc == GPG_ERR_ASSUAN_SERVER_FAULT) {
947 log_write(N_("%s. Maybe disabling pinentry (-P) will help?"),
948 pwmd_strerror(rc));
949 goto fail;
951 else if (rc) {
952 log_write("%s", pwmd_strerror(rc));
953 goto fail;
957 if ((fd = open(filename, O_RDONLY)) == -1) {
958 log_write("%s: %s", filename, strerror(errno));
959 goto fail;
962 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
963 close(fd);
964 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
965 goto fail;
968 if (pth_read(fd, xmlbuf, st.st_size) == -1) {
969 rc = errno;
970 close(fd);
971 errno = rc;
972 log_write("%s: %s", filename, strerror(errno));
973 goto fail;
976 close(fd);
977 xmlbuf[st.st_size] = 0;
980 * Make sure the document validates.
982 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
983 log_write("xmlReadDoc() failed");
984 gcry_free(xmlbuf);
985 goto fail;
988 gcry_free(xmlbuf);
989 xmlNodePtr n = xmlDocGetRootElement(doc);
990 rc = validate_import(n ? n->children : n);
992 if (rc) {
993 log_write("%s", pwmd_strerror(rc));
994 xmlFreeDoc(doc);
995 goto fail;
998 xmlDocDumpMemory(doc, &xml, &len);
999 xmlFreeDoc(doc);
1001 if (!iter)
1002 memset(crypto->key, '!', hashlen);
1004 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
1006 if (!crypto->fh) {
1007 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1008 goto fail;
1011 crypto->fh->ver.fh2.iter = iter;
1012 rc = export_common(outfile, crypto, xml, len);
1013 xmlFree(xml);
1015 if (rc) {
1016 send_error(NULL, rc);
1017 goto fail;
1020 cleanup_crypto(&crypto);
1021 return TRUE;
1023 fail:
1024 cleanup_crypto(&crypto);
1025 return FALSE;
1028 gboolean do_cache_push(const gchar *filename, const void *password,
1029 gsize len)
1031 guchar md5file[16];
1032 gint timeout;
1033 const gchar *p = filename;
1034 struct crypto_s *crypto;
1035 gpg_error_t rc;
1036 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
1038 while (isspace(*p))
1039 p++;
1041 if (!*p)
1042 return FALSE;
1044 if (valid_filename(p) == FALSE) {
1045 log_write(N_("%s: Invalid characters in filename"), p);
1046 return FALSE;
1049 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1051 if (cache_iscached(md5file)) {
1052 log_write(N_("%s: already cached, skipping"), p);
1053 return FALSE;
1056 if (access(p, R_OK|W_OK) != 0) {
1057 log_write("%s: %s", p, strerror(errno));
1058 return FALSE;
1061 crypto = init_client_crypto();
1063 if (!crypto)
1064 return FALSE;
1066 crypto->fh = read_file_header(filename, FALSE, &rc);
1068 if (!crypto->fh) {
1069 log_write("%s: %s", p, pwmd_strerror(rc));
1070 cleanup_crypto(&crypto);
1071 return FALSE;
1074 crypto->key = gcry_malloc(hashlen);
1076 if (!crypto->key) {
1077 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1078 cleanup_crypto(&crypto);
1079 return FALSE;
1082 log_write(N_("Adding '%s' to the file cache ..."), filename);
1084 if (crypto->fh->ver.fh2.iter <= 0ULL) {
1085 memset(crypto->key, '!', hashlen);
1086 goto try_decrypt;
1089 if (!password) {
1090 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1092 if (rc) {
1093 send_error(NULL, rc);
1094 cleanup_crypto(&crypto);
1095 return FALSE;
1098 gcry_free(crypto->fh->doc);
1099 crypto->fh->doc = NULL;
1101 else
1102 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password, len);
1104 try_decrypt:
1105 rc = init_client_crypto2(filename, crypto);
1107 if (rc) {
1108 send_error(NULL, rc);
1109 cleanup_crypto(&crypto);
1110 return FALSE;
1113 rc = try_xml_decrypt(NULL, crypto, NULL, NULL);
1115 if (rc) {
1116 log_write("%s: %s", filename, pwmd_strerror(rc));
1117 cleanup_crypto(&crypto);
1118 return FALSE;
1121 if (cache_update_key(md5file, crypto->key) == FALSE) {
1122 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1123 cleanup_crypto(&crypto);
1124 return FALSE;
1127 timeout = get_key_file_integer(p, "cache_timeout");
1128 cache_set_timeout(md5file, timeout);
1129 log_write(N_("File '%s' now cached"), filename);
1130 cleanup_crypto(&crypto);
1131 return TRUE;
1134 static void init_new_connection(gint fd)
1136 pth_attr_t attr;
1137 struct client_thread_s *new;
1138 gint n;
1140 new = g_malloc0(sizeof(struct client_thread_s));
1142 if (!new) {
1143 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1144 close(fd);
1145 return;
1148 MUTEX_LOCK(&cn_mutex);
1149 new->fd = fd;
1150 attr = pth_attr_new();
1151 pth_attr_init(attr);
1152 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1153 new->tid = pth_spawn(attr, client_thread, new);
1154 n = errno;
1155 pth_attr_destroy(attr);
1157 if (!new->tid) {
1158 g_free(new);
1159 close(fd);
1160 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1161 _gpg_strerror(gpg_error_from_errno(n)));
1162 MUTEX_UNLOCK(&cn_mutex);
1163 return;
1166 cn_thread_list = g_slist_append(cn_thread_list, new);
1167 MUTEX_UNLOCK(&cn_mutex);
1168 log_write(N_("new connection: tid=%p, fd=%i"), new->tid, fd);
1171 static void *accept_thread(void *arg)
1173 gint sockfd = *(gint *)arg;
1174 pth_attr_t attr = pth_attr_of(pth_self());
1176 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1177 pth_attr_destroy(attr);
1179 for (;;) {
1180 socklen_t slen = sizeof(struct sockaddr_un);
1181 struct sockaddr_un raddr;
1182 gint fd = -1;
1184 fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen);
1186 if (fd == -1) {
1187 if (errno != EAGAIN) {
1188 if (!quit) // probably EBADF
1189 log_write("accept(): %s", strerror(errno));
1191 break;
1194 continue;
1197 init_new_connection(fd);
1200 /* Just in case accept() failed for some reason other than EBADF */
1201 quit = 1;
1202 pth_exit(PTH_CANCELED);
1203 return NULL;
1206 static void *adjust_cache_timer_thread(void *arg)
1208 pth_attr_t attr = pth_attr_of(pth_self());
1210 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1211 pth_attr_destroy(attr);
1213 for (;;) {
1214 pth_sleep(1);
1215 CACHE_LOCK(NULL);
1216 cache_adjust_timer();
1217 CACHE_UNLOCK;
1220 return NULL;
1223 void cleanup_mutex_cb(void *arg)
1225 pth_mutex_t *m = arg;
1227 MUTEX_UNLOCK(m);
1230 void cleanup_ev_cb(void *arg)
1232 pth_event_t ev = arg;
1234 pth_event_free(ev, PTH_FREE_ALL);
1237 void cleanup_fd_cb(void *arg)
1239 gint fd = *(gint *)arg;
1241 close(fd);
1244 void cleanup_unlink_cb(void *arg)
1246 gchar *file = arg;
1248 unlink(file);
1251 void cleanup_cancel_cb(void *arg)
1253 pth_t tid = arg;
1254 pth_attr_t attr;
1255 gint join;
1257 attr = pth_attr_of(tid);
1258 pth_attr_get(attr, PTH_ATTR_JOINABLE, &join);
1259 pth_cancel(tid);
1261 if (join) {
1262 void *p;
1264 pth_join(tid, &p);
1265 g_free(p);
1269 static void *keepalive_thread(void *arg)
1271 gint to = *(gint *)arg;
1272 pth_attr_t attr = pth_attr_of(pth_self());
1274 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1275 pth_attr_destroy(attr);
1277 for (;;) {
1278 pth_event_t ev = pth_event(PTH_EVENT_TIME, pth_timeout(to, 0));
1280 pth_cleanup_push(cleanup_ev_cb, ev);
1281 pth_wait(ev);
1282 send_status_all(STATUS_KEEPALIVE);
1283 pth_cleanup_pop(1);
1286 return NULL;
1289 static void startStopKeepAlive(gboolean term)
1291 gint n = get_key_file_integer("global", "keepalive");
1293 if (keepalive_tid)
1294 pth_cancel(keepalive_tid);
1296 keepalive_tid = NULL;
1298 if (term)
1299 return;
1301 if (n > 0) {
1302 gint e;
1303 pth_attr_t attr = pth_attr_new();
1305 pth_attr_init(attr);
1306 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1307 keepalive_tid = pth_spawn(attr, keepalive_thread, &n);
1308 e = errno;
1309 pth_attr_destroy(attr);
1311 if (!keepalive_tid) {
1312 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1313 _gpg_strerror(gpg_error_from_errno(e)));
1314 return;
1317 pth_yield(keepalive_tid);
1321 static gboolean waiting_for_exit()
1323 guint i, t;
1324 pth_event_t evs = NULL;
1326 MUTEX_LOCK(&cn_mutex);
1328 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
1329 struct client_thread_s *thd = g_slist_nth_data(cn_thread_list, i);
1330 pth_event_t ev = pth_event(PTH_EVENT_TID|PTH_UNTIL_TID_DEAD, thd->tid);
1332 if (evs)
1333 evs = pth_event_concat(evs, ev, NULL);
1334 else
1335 evs = ev;
1338 MUTEX_UNLOCK(&cn_mutex);
1340 if (!evs)
1341 return FALSE;
1343 pth_wait(evs);
1344 MUTEX_LOCK(&cn_mutex);
1345 i = g_slist_length(cn_thread_list);
1346 MUTEX_UNLOCK(&cn_mutex);
1347 pth_event_free(evs, PTH_FREE_ALL);
1348 return i ? TRUE : FALSE;
1351 static void catch_sigabrt(int sig)
1353 cache_clear(NULL, 2);
1354 #ifndef MEM_DEBUG
1355 xpanic();
1356 #endif
1359 static void server_loop(gint sockfd, gchar **socketpath)
1361 pth_t accept_tid;
1362 guint n;
1363 sigset_t sigset;
1364 pth_attr_t attr;
1365 pth_t cache_timeout_tid;
1367 sigemptyset(&sigset);
1369 /* Termination */
1370 sigaddset(&sigset, SIGTERM);
1371 sigaddset(&sigset, SIGINT);
1373 /* Clears the file cache. */
1374 sigaddset(&sigset, SIGUSR1);
1376 /* Configuration file reloading. */
1377 sigaddset(&sigset, SIGHUP);
1379 /* Clears the cache and exits when something bad happens. */
1380 signal(SIGABRT, catch_sigabrt);
1381 sigaddset(&sigset, SIGABRT);
1383 /* Ignored everywhere. When a client disconnects abnormally this signal
1384 * gets raised. It isn't needed though because client_thread() will check
1385 * for rcs even after the client disconnects. */
1386 signal(SIGPIPE, SIG_IGN);
1387 sigprocmask(SIG_BLOCK, &sigset, NULL);
1389 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1390 log_write(N_("Listening on %s"), *socketpath);
1391 attr = pth_attr_new();
1392 pth_attr_init(attr);
1393 accept_tid = pth_spawn(attr, accept_thread, &sockfd);
1395 if (!accept_tid) {
1396 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1397 _gpg_strerror(gpg_error_from_errno(errno)));
1398 pth_attr_destroy(attr);
1399 goto done;
1402 pth_yield(accept_tid);
1403 startStopKeepAlive(FALSE);
1404 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1405 cache_timeout_tid = pth_spawn(attr, adjust_cache_timer_thread, NULL);
1407 if (!cache_timeout_tid) {
1408 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1409 _gpg_strerror(gpg_error_from_errno(errno)));
1410 pth_attr_destroy(attr);
1411 goto done;
1414 pth_yield(cache_timeout_tid);
1415 pth_attr_destroy(attr);
1418 gchar *str = get_key_file_string("global", "debug_file");
1420 if (str) {
1421 gchar *f = expand_homedir(str);
1423 g_free(str);
1424 debugfp = fopen(f, "w");
1426 if (!debugfp)
1427 log_write("%s: %s", f, pwmd_strerror(gpg_error_from_errno(errno)));
1428 else
1429 assuan_set_assuan_log_stream(debugfp);
1431 g_free(f);
1435 do {
1436 gint sig;
1438 pth_sigwait(&sigset, &sig);
1439 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1441 /* Caught a signal. */
1442 switch (sig) {
1443 case SIGHUP:
1444 reload_rcfile();
1445 break;
1446 case SIGABRT:
1447 // not really handled here.
1448 catch_sigabrt(SIGABRT);
1449 break;
1450 case SIGUSR1:
1451 CACHE_LOCK(NULL);
1452 log_write(N_("clearing file cache"));
1453 cache_clear(NULL, 2);
1454 CACHE_UNLOCK;
1455 break;
1456 default:
1457 quit = 1;
1458 break;
1460 } while (!quit);
1462 done:
1464 * We're out of the main server loop. This happens when a signal was sent
1465 * to terminate the daemon. We'll wait for all clients to disconnect
1466 * before exiting and ignore any following signals.
1468 shutdown(sockfd, SHUT_RDWR);
1469 close(sockfd);
1470 pth_cancel(accept_tid);
1471 pth_join(accept_tid, NULL);
1472 unlink(*socketpath);
1473 g_free(*socketpath);
1474 *socketpath = NULL;
1475 MUTEX_LOCK(&cn_mutex);
1476 n = g_slist_length(cn_thread_list);
1477 MUTEX_UNLOCK(&cn_mutex);
1479 if (n) {
1480 log_write(N_("waiting for all clients to disconnect"));
1482 do {
1483 MUTEX_LOCK(&cn_mutex);
1484 n = g_slist_length(cn_thread_list);
1485 MUTEX_UNLOCK(&cn_mutex);
1486 log_write(N_("%i clients remain"), n);
1487 } while (waiting_for_exit());
1490 startStopKeepAlive(TRUE);
1491 pth_cancel(cache_timeout_tid);
1492 cache_free();
1496 * Only called from pinentry_fork() in the child process.
1498 void free_client_list()
1500 gint i, t = g_slist_length(cn_thread_list);
1502 for (i = 0; i < t; i++) {
1503 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1505 free_client(cn->cl);
1508 cache_free();
1511 static guint pwmd_cipher_to_gcrypt(guint64 flags)
1513 if (flags & PWMD_CIPHER_AES128)
1514 return GCRY_CIPHER_AES128;
1515 else if (flags & PWMD_CIPHER_AES192)
1516 return GCRY_CIPHER_AES192;
1517 else if (flags & PWMD_CIPHER_AES256)
1518 return GCRY_CIPHER_AES256;
1519 else if (flags & PWMD_CIPHER_SERPENT128)
1520 return GCRY_CIPHER_SERPENT128;
1521 else if (flags & PWMD_CIPHER_SERPENT192)
1522 return GCRY_CIPHER_SERPENT192;
1523 else if (flags & PWMD_CIPHER_SERPENT256)
1524 return GCRY_CIPHER_SERPENT256;
1525 else if (flags & PWMD_CIPHER_CAMELLIA128)
1526 return GCRY_CIPHER_CAMELLIA128;
1527 else if (flags & PWMD_CIPHER_CAMELLIA192)
1528 return GCRY_CIPHER_CAMELLIA192;
1529 else if (flags & PWMD_CIPHER_CAMELLIA256)
1530 return GCRY_CIPHER_CAMELLIA256;
1531 else if (flags & PWMD_CIPHER_BLOWFISH)
1532 return GCRY_CIPHER_BLOWFISH;
1533 else if (flags & PWMD_CIPHER_3DES)
1534 return GCRY_CIPHER_3DES;
1535 else if (flags & PWMD_CIPHER_CAST5)
1536 return GCRY_CIPHER_CAST5;
1537 else if (flags & PWMD_CIPHER_TWOFISH)
1538 return GCRY_CIPHER_TWOFISH;
1539 else if (flags & PWMD_CIPHER_TWOFISH128)
1540 return GCRY_CIPHER_TWOFISH128;
1542 /* For backwards compatibility (no flags). */
1543 return GCRY_CIPHER_AES256;
1546 guint pwmd_cipher_str_to_cipher(const gchar *str)
1548 guint64 flags = 0;
1550 if (!g_strcasecmp(str, "aes128"))
1551 flags = PWMD_CIPHER_AES128;
1552 else if (!g_strcasecmp(str, "aes192"))
1553 flags = PWMD_CIPHER_AES192;
1554 else if (!g_strcasecmp(str, "aes256"))
1555 flags = PWMD_CIPHER_AES256;
1556 if (!g_strcasecmp(str, "serpent128"))
1557 flags = PWMD_CIPHER_SERPENT128;
1558 else if (!g_strcasecmp(str, "serpent192"))
1559 flags = PWMD_CIPHER_SERPENT192;
1560 else if (!g_strcasecmp(str, "serpent256"))
1561 flags = PWMD_CIPHER_SERPENT256;
1562 if (!g_strcasecmp(str, "camellia128"))
1563 flags = PWMD_CIPHER_CAMELLIA128;
1564 else if (!g_strcasecmp(str, "camellia192"))
1565 flags = PWMD_CIPHER_CAMELLIA192;
1566 else if (!g_strcasecmp(str, "camellia256"))
1567 flags = PWMD_CIPHER_CAMELLIA256;
1568 else if (!g_strcasecmp(str, "blowfish"))
1569 flags = PWMD_CIPHER_BLOWFISH;
1570 else if (!g_strcasecmp(str, "cast5"))
1571 flags = PWMD_CIPHER_CAST5;
1572 else if (!g_strcasecmp(str, "3des"))
1573 flags = PWMD_CIPHER_3DES;
1574 else if (!g_strcasecmp(str, "twofish256"))
1575 flags = PWMD_CIPHER_TWOFISH;
1576 else if (!g_strcasecmp(str, "twofish128"))
1577 flags = PWMD_CIPHER_TWOFISH128;
1579 return flags;
1582 const gchar *pwmd_cipher_to_str(guint64 flags)
1584 if (flags & PWMD_CIPHER_AES128)
1585 return "aes128";
1586 else if (flags & PWMD_CIPHER_AES192)
1587 return "aes192";
1588 else if (flags & PWMD_CIPHER_AES256)
1589 return "aes256";
1590 else if (flags & PWMD_CIPHER_SERPENT128)
1591 return "serpent128";
1592 else if (flags & PWMD_CIPHER_SERPENT192)
1593 return "serpent192";
1594 else if (flags & PWMD_CIPHER_SERPENT256)
1595 return "serpent256";
1596 else if (flags & PWMD_CIPHER_CAMELLIA128)
1597 return "camellia128";
1598 else if (flags & PWMD_CIPHER_CAMELLIA192)
1599 return "camellia192";
1600 else if (flags & PWMD_CIPHER_CAMELLIA256)
1601 return "camellia256";
1602 else if (flags & PWMD_CIPHER_BLOWFISH)
1603 return "blowfish";
1604 else if (flags & PWMD_CIPHER_CAST5)
1605 return "cast5";
1606 else if (flags & PWMD_CIPHER_3DES)
1607 return "3des";
1608 else if (flags & PWMD_CIPHER_TWOFISH)
1609 return "twofish256";
1610 else if (flags & PWMD_CIPHER_TWOFISH128)
1611 return "twofish128";
1613 return NULL;
1616 /* To be called after read_file_header(). This sets the wanted algorithm from
1617 * .flags */
1618 gpg_error_t init_client_crypto2(const char *filename,
1619 struct crypto_s *crypto)
1621 gpg_error_t rc;
1622 guint algo;
1624 /* New file or conversion. */
1625 if (crypto->fh->v1)
1626 algo = pwmd_cipher_to_gcrypt(PWMD_CIPHER_AES256);
1627 else if (!crypto->fh->ver.fh2.flags) {
1628 gchar *tmp = get_key_file_string(filename ? filename : "global", "cipher");
1629 guint64 flags;
1631 flags = pwmd_cipher_str_to_cipher(tmp);
1632 g_free(tmp);
1633 algo = pwmd_cipher_to_gcrypt(flags);
1634 crypto->fh->ver.fh2.flags = flags;
1636 else
1637 algo = pwmd_cipher_to_gcrypt(crypto->fh->ver.fh2.flags);
1639 rc = gcry_cipher_algo_info(algo, GCRYCTL_TEST_ALGO, NULL, NULL);
1641 if (rc)
1642 return rc;
1644 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL,
1645 &crypto->keysize);
1647 if (rc)
1648 return rc;
1650 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_BLKLEN, NULL,
1651 &crypto->blocksize);
1653 if (rc)
1654 return rc;
1656 if (crypto->gh)
1657 gcry_cipher_close(crypto->gh);
1659 return gcry_cipher_open(&crypto->gh, algo, GCRY_CIPHER_MODE_CBC, 0);
1662 struct crypto_s *init_client_crypto()
1664 struct crypto_s *new = g_malloc0(sizeof(struct crypto_s));
1666 if (!new) {
1667 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1668 return NULL;
1671 return new;
1674 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
1675 const gchar *outfile)
1677 gpg_error_t rc;
1678 guchar md5file[gcry_md_get_algo_dlen(GCRY_MD_MD5)];
1679 guint64 iter;
1680 struct crypto_s *crypto = init_client_crypto();
1681 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
1683 if (!crypto)
1684 return GPG_ERR_ENOMEM;
1686 crypto->key = gcry_malloc(hashlen);
1688 if (!crypto->key) {
1689 cleanup_crypto(&crypto);
1690 return GPG_ERR_ENOMEM;
1693 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
1694 filename);
1695 crypto->fh = read_file_header(filename, TRUE, &rc);
1697 if (!crypto->fh)
1698 goto done;
1700 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
1702 /* The header in version 1 had a bug where the iterations were off-by-one.
1703 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
1704 * header.
1706 if (crypto->fh->ver.fh1.iter != -1) {
1707 if (keyfile) {
1708 rc = parse_rcfile_keyfile(crypto, keyfile, TRUE);
1710 if (rc)
1711 goto done;
1713 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1714 crypto->tkey_len);
1715 gcry_free(crypto->tkey);
1716 crypto->tkey = NULL;
1718 else {
1719 rc = get_password(filename, crypto, md5file, crypto->key,
1720 PINENTRY_OPEN);
1722 if (rc)
1723 goto done;
1727 rc = init_client_crypto2(NULL, crypto);
1729 if (rc)
1730 goto done;
1732 rc = try_xml_decrypt(NULL, crypto, &crypto->fh->doc, &crypto->fh->len);
1734 if (rc)
1735 goto done;
1737 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
1739 if (rc) {
1740 log_write("%s: %s", filename, pwmd_strerror(rc));
1741 goto done;
1744 crypto->fh->v1 = FALSE;
1746 iter = crypto->fh->ver.fh1.iter+1;
1747 memset(&crypto->fh->ver.fh2, 0, sizeof(crypto->fh->ver.fh2));
1748 /* Keep the iterations and key from the original file. */
1749 crypto->fh->ver.fh2.iter = iter;
1750 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
1752 done:
1753 if (rc)
1754 send_error(NULL, rc);
1756 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
1757 cleanup_crypto(&crypto);
1758 return rc;
1761 int main(int argc, char *argv[])
1763 gint opt;
1764 struct sockaddr_un addr;
1765 gchar buf[PATH_MAX];
1766 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
1767 gchar *socketarg = NULL;
1768 gchar *datadir = NULL;
1769 gboolean n;
1770 gint x;
1771 gchar *p;
1772 gchar **cache_push = NULL;
1773 gchar *import = NULL, *keyfile = NULL;
1774 guint64 cmd_iterations = 0UL;
1775 gboolean iterations_arg = FALSE;
1776 gint default_timeout;
1777 gboolean rcfile_spec = FALSE;
1778 gint estatus = EXIT_FAILURE;
1779 gint sockfd;
1780 gchar *outfile = NULL;
1781 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
1782 gint do_unlink = 1;
1783 gboolean secure = FALSE;
1784 gint background = 1;
1785 gchar *convert = NULL;
1786 gint show_version = 0;
1787 gint show_help = 0;
1788 #ifdef WITH_PINENTRY
1789 gboolean disable_pinentry = FALSE;
1790 #endif
1791 gint opt_index;
1792 const struct option long_opts[] = {
1793 #ifdef WITH_PINENTRY
1794 { "no-pinentry", 0, 0, 'P' },
1795 #endif
1796 { "outfile", 1, 0, 'o' },
1797 { "convert", 1, 0, 'C' },
1798 { "no-fork", 0, 0, 'n' },
1799 { "disable-dump", 0, 0, 'D' },
1800 { "import", 1, 0, 'I' },
1801 { "iterations", 1, 0, 'i' },
1802 { "key-file", 1, 0, 'k' },
1803 { "rcfile", 1, 0, 'f' },
1804 { "version", 0, &show_version, 1 },
1805 { "help", 0, &show_help, 1 },
1806 { 0, 0, 0, 0}
1808 #ifdef WITH_PINENTRY
1809 const gchar *optstring = "Po:C:nDI:i:k:f:";
1810 #else
1811 const gchar *optstring = "o:C:nDI:i:k:f:";
1812 #endif
1813 #ifndef DEBUG
1814 #ifdef HAVE_SETRLIMIT
1815 struct rlimit rl;
1817 rl.rlim_cur = rl.rlim_max = 0;
1819 if (setrlimit(RLIMIT_CORE, &rl) != 0)
1820 err(EXIT_FAILURE, "setrlimit()");
1821 #endif
1822 #endif
1824 #ifdef ENABLE_NLS
1825 setlocale(LC_ALL, "");
1826 bindtextdomain("pwmd", LOCALEDIR);
1827 textdomain("pwmd");
1828 #endif
1830 #ifndef MEM_DEBUG
1831 xmem_init();
1832 #endif
1833 setup_gcrypt();
1834 gpg_err_init();
1835 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
1836 g_mem_set_vtable(&mtable);
1837 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
1838 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
1839 xmlInitMemory();
1840 xmlInitGlobals();
1841 xmlInitParser();
1842 xmlXPathInit();
1843 g_snprintf(buf, sizeof(buf), "%s/.pwmd", g_get_home_dir());
1845 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
1846 err(EXIT_FAILURE, "%s", buf);
1848 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", g_get_home_dir());
1850 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
1851 err(EXIT_FAILURE, "%s", buf);
1853 cmdline = TRUE;
1855 while ((opt = getopt_long(argc, argv, optstring, long_opts, &opt_index)) != -1) {
1856 switch (opt) {
1857 case 0:
1858 if (show_help)
1859 usage(argv[0], EXIT_SUCCESS);
1861 if (show_version) {
1862 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,
1863 PACKAGE_BUGREPORT,
1864 #ifdef WITH_PINENTRY
1865 "+WITH_PINENTRY\n"
1866 #else
1867 "-WITH_PINENTRY\n"
1868 #endif
1869 #ifdef WITH_QUALITY
1870 "+WITH_QUALITY\n"
1871 #else
1872 "-WITH_QUALITY\n"
1873 #endif
1874 #ifdef WITH_LIBACL
1875 "+WITH_LIBACL\n"
1876 #else
1877 "-WITH_LIBACL\n"
1878 #endif
1879 #ifdef DEBUG
1880 "+DEBUG\n"
1881 #else
1882 "-DEBUG\n"
1883 #endif
1884 #ifdef MEM_DEBUG
1885 "+MEM_DEBUG\n"
1886 #else
1887 "-MEM_DEBUG\n"
1888 #endif
1890 exit(EXIT_SUCCESS);
1892 break;
1893 #ifdef WITH_PINENTRY
1894 case 'P':
1895 disable_pinentry = TRUE;
1896 break;
1897 #endif
1898 case 'o':
1899 outfile = optarg;
1900 break;
1901 case 'C':
1902 convert = optarg;
1903 break;
1904 case 'n':
1905 background = 0;
1906 break;
1907 case 'D':
1908 secure = TRUE;
1909 break;
1910 case 'I':
1911 import = optarg;
1912 break;
1913 case 'i':
1914 cmd_iterations = strtoul(optarg, NULL, 10);
1916 if (cmd_iterations == G_MAXULONG) {
1917 log_write("%s", N_("invalid iteration count"));
1918 usage(argv[0], EXIT_FAILURE);
1921 iterations_arg = TRUE;
1922 break;
1923 case 'k':
1924 keyfile = optarg;
1925 break;
1926 case 'f':
1927 rcfile = g_strdup(optarg);
1928 rcfile_spec = TRUE;
1929 break;
1930 default:
1931 usage(argv[0], EXIT_FAILURE);
1935 pth_mutex_init(&cn_mutex);
1936 pth_mutex_init(&cache_mutex);
1937 pth_mutex_init(&rcfile_mutex);
1938 #ifdef WITH_PINENTRY
1939 pth_mutex_init(&pin_mutex);
1940 #endif
1942 if (!rcfile)
1943 rcfile = g_strdup_printf("%s/.pwmd/config", g_get_home_dir());
1945 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
1946 exit(EXIT_FAILURE);
1948 #ifdef WITH_PINENTRY
1949 if (disable_pinentry == TRUE)
1950 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
1951 #endif
1953 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
1954 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
1956 if (log_syslog == TRUE)
1957 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
1959 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
1960 x = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
1961 errno = 0;
1963 if (setpriority(PRIO_PROCESS, 0, x) == -1) {
1964 log_write("setpriority(): %s", strerror(errno));
1965 goto do_exit;
1969 #ifdef HAVE_MLOCKALL
1970 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
1971 log_write("mlockall(): %s", strerror(errno));
1972 goto do_exit;
1974 #endif
1976 if (convert) {
1977 if (!outfile)
1978 usage(argv[0], EXIT_FAILURE);
1980 opt = convert_file(convert, keyfile, outfile);
1981 g_key_file_free(keyfileh);
1982 g_free(rcfile);
1983 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
1986 if (import) {
1987 if (!outfile)
1988 usage(argv[0], EXIT_FAILURE);
1990 if (!iterations_arg)
1991 cmd_iterations = (guint64)get_key_file_double("global", "iterations");
1993 opt = xml_import(import, outfile, keyfile, cmd_iterations);
1994 g_key_file_free(keyfileh);
1995 g_free(rcfile);
1996 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
1999 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
2000 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
2002 socketarg = expand_homedir(p);
2003 g_free(p);
2005 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
2006 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
2008 datadir = expand_homedir(p);
2009 g_free(p);
2011 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
2012 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
2013 disable_list_and_dump = n;
2015 else
2016 disable_list_and_dump = secure;
2018 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
2019 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
2020 else
2021 default_timeout = -1;
2023 setup_logging(keyfileh);
2025 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2026 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2028 if (argc != optind) {
2029 for (; optind < argc; optind++) {
2030 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2031 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
2035 if (strchr(socketarg, '/') == NULL) {
2036 socketdir = g_get_current_dir();
2037 socketname = g_strdup(socketarg);
2038 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2040 else {
2041 socketname = g_strdup(strrchr(socketarg, '/'));
2042 socketname++;
2043 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2044 socketdir = g_strdup(socketarg);
2045 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2048 if (chdir(datadir)) {
2049 log_write("%s: %s", datadir, strerror(errno));
2050 unlink(socketpath);
2051 goto do_exit;
2054 if (parse_rcfile_keys() == FALSE)
2055 goto do_exit;
2057 clear_rcfile_keys();
2060 * Set the cache entry for a file. Prompts for the password.
2062 if (cache_push) {
2063 for (opt = 0; cache_push[opt]; opt++)
2064 do_cache_push(cache_push[opt], NULL, 0);
2066 g_strfreev(cache_push);
2067 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2071 * bind() doesn't like the full pathname of the socket or any non alphanum
2072 * characters so change to the directory where the socket is wanted then
2073 * create it then change to datadir.
2075 if (chdir(socketdir)) {
2076 log_write("%s: %s", socketdir, strerror(errno));
2077 goto do_exit;
2080 g_free(socketdir);
2082 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2083 log_write("socket(): %s", strerror(errno));
2084 goto do_exit;
2087 addr.sun_family = AF_UNIX;
2088 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2090 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2091 log_write("bind(): %s", strerror(errno));
2093 if (errno == EADDRINUSE)
2094 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2095 "stale socket. Please remove it manually."), socketpath);
2097 do_unlink = 0;
2098 goto do_exit;
2101 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2102 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2103 mode_t mode = strtol(t, NULL, 8);
2104 mode_t mask = umask(0);
2106 g_free(t);
2108 if (chmod(socketname, mode) == -1) {
2109 log_write("%s: %s", socketname, strerror(errno));
2110 close(sockfd);
2111 unlink(socketpath);
2112 umask(mask);
2113 goto do_exit;
2116 umask(mask);
2119 g_free(--socketname);
2121 if (chdir(datadir)) {
2122 log_write("%s: %s", datadir, strerror(errno));
2123 close(sockfd);
2124 unlink(socketpath);
2125 goto do_exit;
2128 g_free(datadir);
2130 if (listen(sockfd, 0) == -1) {
2131 log_write("listen(): %s", strerror(errno));
2132 goto do_exit;
2135 cmdline = FALSE;
2136 unsetenv("DISPLAY");
2137 unsetenv("TERM");
2139 if (background) {
2140 switch (fork()) {
2141 case -1:
2142 log_write("fork(): %s", strerror(errno));
2143 goto do_exit;
2144 case 0:
2145 close(0);
2146 close(1);
2147 close(2);
2148 setsid();
2149 break;
2150 default:
2151 exit(EXIT_SUCCESS);
2155 server_loop(sockfd, &socketpath);
2156 estatus = EXIT_SUCCESS;
2158 do_exit:
2159 if (socketpath && do_unlink) {
2160 unlink(socketpath);
2161 g_free(socketpath);
2164 g_free(socketarg);
2165 g_key_file_free(keyfileh);
2166 g_free(rcfile);
2167 xmlCleanupParser();
2168 xmlCleanupGlobals();
2170 if (estatus == EXIT_SUCCESS)
2171 log_write(N_("pwmd exiting normally"));
2173 #if defined(DEBUG) && !defined(MEM_DEBUG)
2174 xdump();
2175 #endif
2176 exit(estatus);