Fix for the previous commit that wouldn't terminate the client if a
[pwmd.git] / src / pwmd.c
blob85f7e8165d3a1d4469b9e41fd3d161f399d4223b
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006-2009 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <err.h>
27 #include <errno.h>
28 #include <ctype.h>
29 #include <string.h>
30 #include <sys/un.h>
31 #include <signal.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <sys/wait.h>
35 #include <fcntl.h>
36 #include <pwd.h>
37 #include <glib.h>
38 #include <glib/gprintf.h>
39 #include <sys/mman.h>
40 #include <termios.h>
41 #include <assert.h>
42 #include <syslog.h>
43 #include <zlib.h>
44 #include <gcrypt.h>
45 #include <netinet/in.h>
46 #include <arpa/inet.h>
47 #include <netdb.h>
48 #include <sys/time.h>
49 #include <sys/resource.h>
51 #ifdef TM_IN_SYS_TIME
52 #include <sys/time.h>
53 #else
54 #include <time.h>
55 #endif
57 #include "mem.h"
58 #include "xml.h"
59 #include "common.h"
61 #ifdef WITH_PINENTRY
62 #include "pinentry.h"
63 #endif
65 #ifdef WITH_GNUTLS
66 #include "tls.h"
67 #endif
68 #include "commands.h"
69 #include "pwmd_error.h"
70 #include "cache.h"
71 #include "misc.h"
72 #include "pwmd.h"
73 #include "lock.h"
75 GCRY_THREAD_OPTION_PTHREAD_IMPL;
77 static void clear_rcfile_keys()
79 gsize n;
80 gchar **groups;
81 gchar **p;
83 groups = g_key_file_get_groups(keyfileh, &n);
85 for (p = groups; *p; p++) {
86 GError *rc = NULL;
88 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE)
89 g_key_file_set_string(keyfileh, *p, "key", "");
92 g_strfreev(groups);
95 static void *reload_rcfile_thread(void *arg)
97 gboolean b = disable_list_and_dump;
98 GKeyFile *k;
100 pthread_mutex_lock(&reload_rcfile_mutex);
101 log_write(N_("reloading configuration file '%s'"), rcfile);
102 k = parse_rcfile(FALSE);
104 if (!k)
105 goto done;
107 g_key_file_free(keyfileh);
108 keyfileh = k;
109 parse_rcfile_keys();
110 clear_rcfile_keys();
111 disable_list_and_dump = b;
112 #ifdef WITH_GNUTLS
113 startStopTcp(FALSE);
114 #endif
115 startStopKeepAlive(FALSE);
116 send_status_all(STATUS_CONFIG);
117 done:
118 pthread_mutex_unlock(&reload_rcfile_mutex);
119 return NULL;
122 static void reload_rcfile()
124 pthread_t tid;
125 pthread_attr_t attr;
127 pthread_attr_init(&attr);
128 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
129 pthread_create(&tid, &attr, reload_rcfile_thread, NULL);
130 pthread_attr_destroy(&attr);
133 gpg_error_t send_syserror(assuan_context_t ctx, gint e)
135 gpg_error_t n = gpg_error_from_errno(e);
137 pthread_testcancel();
138 return assuan_process_done(ctx, assuan_set_error(ctx, n, gpg_strerror(n)));
141 gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e)
143 gpg_err_code_t n = gpg_err_code(e);
144 gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n);
145 struct client_s *client = assuan_get_pointer(ctx);
147 pthread_testcancel();
149 if (!e)
150 return assuan_process_done(ctx, 0);
152 if (!ctx) {
153 log_write("%s", pwmd_strerror(e));
154 return e;
157 if (n == EPWMD_LIBXML_ERROR) {
158 xmlErrorPtr xe = client->xml_error;
160 if (!xe)
161 xe = xmlGetLastError();
163 e = assuan_process_done(ctx, assuan_set_error(ctx, code, xe->message));
164 log_write("%s", xe->message);
166 if (xe == client->xml_error)
167 xmlResetError(xe);
168 else
169 xmlResetLastError();
171 client->xml_error = NULL;
172 return e;
175 return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e)));
178 static struct client_thread_s *find_cn(pthread_t tid)
180 guint t, i;
182 if (!cn_thread_list)
183 return NULL;
185 pthread_mutex_lock(&cn_mutex);
187 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
188 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
190 if (cn->tid == tid) {
191 pthread_mutex_unlock(&cn_mutex);
192 return cn;
196 pthread_mutex_unlock(&cn_mutex);
197 return NULL;
200 void log_write(const gchar *fmt, ...)
202 gchar *args, *line;
203 va_list ap;
204 struct tm *tm;
205 time_t now;
206 gchar tbuf[21];
207 gint fd = -1;
208 struct client_thread_s *cn;
209 gchar *name = "";
210 gchar buf[255];
212 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
213 return;
215 if (!cmdline && logfile) {
216 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
217 warn("%s", logfile);
218 return;
222 va_start(ap, fmt);
224 if (g_vasprintf(&args, fmt, ap) == -1) {
225 if (logfile)
226 close(fd);
228 va_end(ap);
229 return;
232 va_end(ap);
234 if (cmdline) {
235 fprintf(stderr, "%s\n", args);
236 fflush(stderr);
237 g_free(args);
238 return;
241 cn = find_cn(pthread_self());
243 if (cn) {
244 if (!cn->name)
245 name = print_fmt(buf, sizeof(buf), "%i: ", cn->fd);
246 else
247 name = print_fmt(buf, sizeof(buf), "%s(%i): ", cn->name, cn->fd);
250 if (!cmdline && log_syslog == TRUE)
251 syslog(LOG_INFO, "%s%s", name, args);
253 time(&now);
254 tm = localtime(&now);
255 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
256 tbuf[sizeof(tbuf) - 1] = 0;
258 if (args[strlen(args)-1] == '\n')
259 args[strlen(args)-1] = 0;
261 line = g_strdup_printf("%s %i %s%s\n", tbuf, getpid(), name, args);
262 g_free(args);
264 if (!line) {
265 if (logfile)
266 close(fd);
268 return;
271 if (logfile) {
272 write(fd, line, strlen(line));
273 fsync(fd);
274 close(fd);
277 if (isatty(STDERR_FILENO)) {
278 fprintf(stderr, "%s", line);
279 fflush(stderr);
282 g_free(line);
285 static void usage(gchar *pn)
287 g_fprintf(stderr, N_(
288 "Usage: %s [-hvDnP] [-f <rcfile>] [-C <filename>] "
289 "[-I <filename> [-i <iter>]]\n "
290 "[-k <keyfile>] [-o <outfile>] [file1] [...]\n"
291 " -n run as a foreground process\n"
292 " -f load the specified rcfile (~/.pwmd/config)\n"
293 " -C convert a version 1 data file to version 2\n"
294 " -I import an XML file\n"
295 " -i encrypt with the specified number of iterations when importing\n"
296 " (config default in the \"global\" section)\n"
297 " -k obtain the key from the specified file\n"
298 " -o output file for use with the -C and -I options\n"
299 " -D disable use of the LIST and DUMP commands\n"
300 " -P disable pinentry\n"
301 " -v version\n"
302 " -h this help text\n"
303 ), pn);
304 exit(EXIT_FAILURE);
307 static int gcry_SecureCheck(const void *ptr)
309 return 1;
312 static void setup_gcrypt()
314 gcry_check_version(NULL);
316 gcry_set_allocation_handler(xmalloc, xmalloc, gcry_SecureCheck, xrealloc,
317 xfree);
319 if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, NULL,
320 NULL) != 0)
321 errx(EXIT_FAILURE, N_("Required AES cipher not supported by libgcrypt."));
323 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_KEYLEN, NULL, &gcrykeysize);
324 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_BLKLEN, NULL, &gcryblocksize);
327 static gint new_connection(struct client_s *cl)
329 gpg_error_t rc;
330 gchar ver[ASSUAN_LINELENGTH];
332 rc = assuan_init_socket_server_ext(&cl->ctx, cl->thd->fd, 2);
334 if (rc)
335 goto fail;
337 assuan_set_pointer(cl->ctx, cl);
338 g_snprintf(ver, sizeof(ver), "%s", PACKAGE_STRING);
339 assuan_set_hello_line(cl->ctx, ver);
340 rc = register_commands(cl->ctx);
342 if (rc)
343 goto fail;
345 rc = assuan_accept(cl->ctx);
347 if (rc)
348 goto fail;
350 return 0;
352 fail:
353 log_write("%s", gpg_strerror(rc));
354 return 1;
357 gpg_error_t send_status(assuan_context_t ctx, status_msg_t which,
358 const gchar *fmt, ...)
360 gchar *line = NULL;
361 struct client_s *client = assuan_get_pointer(ctx);
362 gchar buf[ASSUAN_LINELENGTH];
363 gchar *status = NULL;
364 va_list ap;
366 if (fmt) {
367 va_start(ap, fmt);
368 g_vsnprintf(buf, sizeof(buf), fmt, ap);
369 va_end(ap);
370 line = buf;
373 switch (which) {
374 case STATUS_CACHE:
375 CACHE_LOCK(client->ctx);
376 line = print_fmt(buf, sizeof(buf), "%i", cache_file_count());
377 CACHE_UNLOCK;
378 status = "CACHE";
379 break;
380 case STATUS_CLIENTS:
381 MUTEX_LOCK(&cn_mutex);
382 line = print_fmt(buf, sizeof(buf), "%i", g_slist_length(cn_thread_list));
383 MUTEX_UNLOCK(&cn_mutex);
384 status = "CLIENTS";
385 break;
386 case STATUS_CONFIG:
387 status = "CONFIG";
388 break;
389 case STATUS_KEEPALIVE:
390 status = "KEEPALIVE";
391 break;
392 case STATUS_LOCKED:
393 status = "LOCKED";
394 line = N_("Waiting for lock");
395 break;
396 case STATUS_ENCRYPT:
397 status = "ENCRYPT";
398 break;
399 case STATUS_DECRYPT:
400 status = "DECRYPT";
401 break;
402 case STATUS_DECOMPRESS:
403 status = "DECOMPRESS";
404 break;
405 case STATUS_COMPRESS:
406 status = "COMPRESS";
407 break;
410 if (!ctx) {
411 log_write("%s %s", status, line);
412 return 0;
415 return assuan_write_status(ctx, status, line);
418 /* This is needed for FreeBSD systems (and maybe others). I'm guessing here,
419 * but I think it lets the scheduler let other threads do their work. If we
420 * were to do the write() in send_status_all() then write() would return
421 * before the signal was actually sent to client_msg_thread(). This is only
422 * called from send_status_all().
424 static void *write_status_msg(void *arg)
426 struct client_thread_s *cn =arg;
427 size_t len;
429 pthread_cond_signal(&cn->msg_cond);
430 len = write(cn->msg_fd[1], &cn->msg, sizeof(status_msg_t));
432 if (len != sizeof(status_msg_t))
433 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
435 return NULL;
438 void send_status_all(status_msg_t which)
440 guint i, t;
442 MUTEX_LOCK(&cn_mutex);
444 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
445 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
446 pthread_t tid;
448 if (cn->quit)
449 continue;
451 cn->msg = which;
452 pthread_create(&tid, NULL, write_status_msg, cn);
453 pthread_join(tid, NULL);
456 MUTEX_UNLOCK(&cn_mutex);
459 static void xml_error_cb(void *data, xmlErrorPtr e)
461 struct client_s *client = data;
464 * Keep the first reported error as the one to show in the error
465 * description. Reset in send_error().
467 if (client->xml_error)
468 return;
470 xmlCopyError(e, client->xml_error);
473 static void cleanup_crypto_handler(void *arg)
475 struct client_crypto_s **a = (struct client_crypto_s **)arg;
476 struct client_crypto_s *cr = *a;
478 if (cr->fh) {
479 if (cr->fh->fd != -1 ||
480 (cmdline == TRUE && cr->fh->fd != STDOUT_FILENO))
481 close(cr->fh->fd);
483 if (cr->fh->doc)
484 gcry_free(cr->fh->doc);
486 g_free(cr->fh);
489 if (cr->gh)
490 gcry_cipher_close(cr->gh);
492 g_free(cr);
493 *a = NULL;
496 void cleanup_crypto(struct client_crypto_s **c)
498 struct client_crypto_s *cr = *c;
500 if (!cr)
501 return;
503 if (cr->iv)
504 gcry_free(cr->iv);
506 if (cr->key)
507 gcry_free(cr->key);
509 if (cr->tkey)
510 gcry_free(cr->tkey);
512 if (cr->tkey2)
513 gcry_free(cr->tkey2);
515 if (cr->inbuf)
516 gcry_free(cr->inbuf);
518 if (cr->outbuf)
519 gcry_free(cr->outbuf);
521 pthread_cleanup_push(cleanup_crypto_handler, c);
522 pthread_testcancel();
523 pthread_cleanup_pop(1);
527 * This is called after a child_thread terminates. Set with
528 * pthread_cleanup_push().
530 static void cleanup_cb(void *arg)
532 struct client_thread_s *cn = arg;
533 struct client_s *cl = cn->cl;
535 MUTEX_LOCK(&cn_mutex);
536 cn->quit = TRUE;
537 log_write(N_("exiting, fd=%i"), cn->fd);
539 if (cl->thd) {
540 pthread_cancel(cn->msg_tid);
541 pthread_join(cn->msg_tid, NULL);
542 pthread_cancel(cn->msg_sender_tid);
543 pthread_join(cn->msg_sender_tid, NULL);
544 close(cl->thd->msg_fd[0]);
545 close(cl->thd->msg_fd[1]);
548 pthread_join(cn->tid, NULL);
549 pthread_cond_destroy(&cn->msg_cond);
551 if (pthread_mutex_trylock(&cn->msg_sender_mutex) == EBUSY) {
552 MUTEX_UNLOCK(&cn->msg_sender_mutex);
554 else
555 pthread_mutex_unlock(&cn->msg_sender_mutex);
557 pthread_mutex_destroy(&cn->msg_sender_mutex);
558 pthread_cond_destroy(&cn->msg_sender_cond);
560 for (;;) {
561 struct status_msg_s *m = g_slist_nth_data(cn->msg_queue, 0);
563 if (!m)
564 break;
566 cn->msg_queue = g_slist_remove(cn->msg_queue, m);
567 g_free(m);
570 if (cl && cl->freed == FALSE)
571 cleanup_client(cl);
573 #ifdef WITH_GNUTLS
574 if (cn->tls) {
575 gnutls_deinit(cn->tls->ses);
577 if (cn->tls->fp)
578 g_free(cn->tls->fp);
580 g_free(cn->tls);
582 #endif
584 if (cl && cl->ctx)
585 assuan_deinit_server(cl->ctx);
587 #ifdef WITH_PINENTRY
588 if (cl && cl->pinentry)
589 cleanup_pinentry(cl->pinentry);
590 #endif
592 if (cl->crypto)
593 cleanup_crypto(&cl->crypto);
595 g_free(cl);
597 if (cn->name)
598 g_free(cn->name);
600 cn_thread_list = g_slist_remove(cn_thread_list, cn);
601 g_free(cn);
602 MUTEX_UNLOCK(&cn_mutex);
603 send_status_all(STATUS_CLIENTS);
606 /* The msg_sender_mutex should have been locked before calling this thread
607 * entry point. */
608 static void *client_msg_sender_thread(void *arg)
610 struct client_thread_s *thd = arg;
612 for (;;) {
613 struct status_msg_s *msg;
614 gpg_error_t rc;
616 pthread_cond_wait(&thd->msg_sender_cond, &thd->msg_sender_mutex);
617 pthread_testcancel();
619 /* The messages may have been stacked while waiting for send_status()
620 * to return. Send what's in the queue. */
621 for (;;) {
622 msg = g_slist_nth_data(thd->msg_queue, 0);
624 if (!msg)
625 break;
627 /* Unlock to prevent blocking in client_msg_thread(). */
628 MUTEX_UNLOCK(&thd->msg_sender_mutex);
629 rc = send_status(thd->cl->ctx, msg->msg, NULL);
630 MUTEX_LOCK(&thd->msg_sender_mutex);
631 thd->msg_queue = g_slist_remove(thd->msg_queue, msg);
632 g_free(msg);
634 if (rc) {
635 log_write(N_("msg for %i failed: %s"), thd->fd,
636 pwmd_strerror(rc));
637 pthread_cancel(thd->tid);
642 return NULL;
646 * This function waits for a signal from send_status_all() then appends a
647 * message read from a pipe to the clients message queue. The actual sending
648 * of the message is done in client_msg_sender_thread() which waits for a
649 * signal from this function. This prevents blocking in assuan_send_status()
650 * when sending to remote clients. This also avoids duplicate status messages.
651 * If an existing status message in the message queue has the same type as the
652 * current message the the current one will be skipped. This avoids flooding
653 * the client with old status messages.
655 static void *client_msg_thread(void *arg)
657 struct client_thread_s *thd = arg;
658 pthread_mutex_t mu;
660 pthread_mutex_init(&mu, NULL);
661 pthread_mutex_lock(&mu);
663 for (;;) {
664 fd_set rfds;
665 int n;
666 status_msg_t m;
667 size_t len;
668 struct status_msg_s *msg;
670 pthread_cleanup_push(pthread_mutex_destroy, &mu);
671 pthread_cleanup_push(pthread_mutex_unlock, &mu);
672 pthread_cond_wait(&thd->msg_cond, &mu);
673 pthread_testcancel();
674 FD_ZERO(&rfds);
675 FD_SET(thd->msg_fd[0], &rfds);
676 n = select(thd->msg_fd[0]+1, &rfds, NULL, NULL, NULL);
677 pthread_testcancel();
679 if (n <= 0 || !FD_ISSET(thd->msg_fd[0], &rfds))
680 continue;
682 len = read(thd->msg_fd[0], &m, sizeof(status_msg_t));
683 pthread_testcancel();
685 if (len != sizeof(status_msg_t)) {
686 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
687 continue;
690 MUTEX_LOCK(&thd->msg_sender_mutex);
692 for (n = 0; n < g_slist_length(thd->msg_queue); n++) {
693 msg = g_slist_nth_data(thd->msg_queue, n);
695 if (msg->msg == m)
696 goto done;
699 msg = g_malloc(sizeof(struct status_msg_s));
701 if (!msg) {
702 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
703 MUTEX_UNLOCK(&thd->msg_sender_mutex);
704 continue;
707 msg->msg = m;
708 thd->msg_queue = g_slist_append(thd->msg_queue, msg);
709 done:
710 MUTEX_UNLOCK(&thd->msg_sender_mutex);
711 pthread_cond_signal(&thd->msg_sender_cond);
712 pthread_cleanup_pop(0);
713 pthread_cleanup_pop(0);
716 return NULL;
720 * Called every time a connection is made from init_new_connection(). This is
721 * the thread entry point.
723 static void *client_thread(void *data)
725 struct client_thread_s *thd = data;
726 struct client_s *cl = g_malloc0(sizeof(struct client_s));
727 gpg_error_t rc;
728 pthread_attr_t attr;
731 * Prevent a race condition with init_new_connection() if this thread
732 * fails (returns) for some reason before init_new_connection() releases
733 * the cn_mutex.
735 MUTEX_LOCK(&cn_mutex);
736 MUTEX_UNLOCK(&cn_mutex);
737 pthread_cleanup_push(cleanup_cb, thd);
739 if (!cl) {
740 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
741 goto fail;
744 thd->cl = cl;
746 #ifdef WITH_GNUTLS
748 * Do the TLS handshake before anything else.
750 if (thd->remote) {
751 gchar *prio = get_key_file_string("global", "cipher_suite");
753 thd->tls = tls_init(thd->fd, prio);
754 g_free(prio);
756 if (!thd->tls) {
757 close(thd->fd);
758 goto fail;
761 pthread_testcancel();
763 #endif
765 cl->thd = thd;
767 if (new_connection(cl))
768 goto fail;
770 #ifdef WITH_PINENTRY
771 cl->pinentry = pinentry_init();
773 if (!cl->pinentry) {
774 g_free(cl);
775 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
776 goto fail;
779 #ifdef WITH_GNUTLS
780 /* Require the client to explicity set OPTION PINENTRY since the DISPLAY
781 * might be automatically set from the client. Connections to the X11
782 * server usually aren't encrypted and the client might unintentionally
783 * send the passphrase in the clear.
785 if (thd->remote)
786 cl->pinentry->enable = FALSE;
787 #endif
788 #endif
790 #ifdef HAVE_MLOCKALL
791 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
792 log_write("mlockall(): %s", strerror(errno));
793 goto fail;
795 #endif
797 if (pipe(thd->msg_fd) == -1) {
798 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
799 goto fail;
802 pthread_attr_init(&attr);
803 pthread_cond_init(&thd->msg_sender_cond, NULL);
804 pthread_mutex_init(&thd->msg_sender_mutex, NULL);
805 MUTEX_LOCK(&thd->msg_sender_mutex);
806 pthread_create(&thd->msg_sender_tid, &attr, client_msg_sender_thread, thd);
807 pthread_attr_destroy(&attr);
809 pthread_cond_init(&thd->msg_cond, NULL);
810 pthread_attr_init(&attr);
811 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
812 pthread_create(&thd->msg_tid, &attr, client_msg_thread, thd);
813 pthread_attr_destroy(&attr);
815 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
817 if (rc) {
818 log_write("%s", gpg_strerror(rc));
819 goto fail;
822 send_status_all(STATUS_CLIENTS);
823 xmlSetStructuredErrorFunc(cl, xml_error_cb);
825 for (;;) {
826 fd_set rfds;
827 int n;
829 FD_ZERO(&rfds);
830 FD_SET(cl->thd->fd, &rfds);
832 #ifdef WITH_PINENTRY
833 if (cl->pinentry->status == PINENTRY_RUNNING)
834 FD_SET(cl->pinentry->fd, &rfds);
836 n = cl->thd->fd > cl->pinentry->fd ? cl->thd->fd : cl->pinentry->fd;
837 #else
838 n = cl->thd->fd;
839 #endif
840 n = select(n+1, &rfds, NULL, NULL, NULL);
841 pthread_testcancel();
843 if (n <= 0)
844 continue;
846 if (FD_ISSET(cl->thd->fd, &rfds)) {
847 rc = assuan_process_next(cl->ctx);
848 pthread_testcancel();
850 if (rc) {
851 cl->inquire_status = INQUIRE_INIT;
853 if (gpg_err_code(rc) == GPG_ERR_EOF)
854 goto done;
856 log_write("assuan_process_next(): %s", gpg_strerror(rc));
857 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
859 if (rc) {
860 log_write("assuan_process_done(): %s", gpg_strerror(rc));
861 goto done;
864 else {
865 #ifdef WITH_PINENTRY
866 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
867 cl->pinentry->status = PINENTRY_RUNNING;
868 #endif
870 switch (cl->inquire_status) {
871 case INQUIRE_BUSY:
872 case INQUIRE_INIT:
873 break;
874 case INQUIRE_DONE:
875 cl->inquire_status = INQUIRE_INIT;
876 pthread_testcancel();
877 rc = assuan_process_done(cl->ctx, 0);
878 break;
883 #ifdef WITH_PINENTRY
884 pinentry_iterate(cl,
885 cl->pinentry->fd != -1 && FD_ISSET(cl->pinentry->fd, &rfds));
886 #endif
890 * Client cleanup (including XML data) is done in cleanup_cb() from
891 * the cleanup thread.
893 done:
894 fail:
895 if (1) {} // Fixes compile time error with pthread_cleanup_push().
896 pthread_cleanup_pop(1);
897 pthread_exit(PTHREAD_CANCELED);
898 return NULL;
901 static void setup_logging(GKeyFile *kf)
903 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
905 if (n == TRUE) {
906 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
908 if (*p == '~') {
909 gchar buf[PATH_MAX];
911 p++;
912 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
913 g_free(p);
915 if (logfile)
916 g_free(logfile);
918 logfile = g_strdup(buf);
920 else {
921 if (logfile)
922 g_free(logfile);
924 logfile = p;
928 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
932 * Make sure all settings are set to either the specified setting or a
933 * default.
935 static void set_rcfile_defaults(GKeyFile *kf)
937 gchar buf[PATH_MAX];
939 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
940 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
941 g_key_file_set_string(kf, "global", "socket_path", buf);
944 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
945 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
946 g_key_file_set_string(kf, "global", "data_directory", buf);
949 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
950 g_key_file_set_boolean(kf, "global", "backup", TRUE);
952 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
953 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
954 g_key_file_set_string(kf, "global", "log_path", buf);
957 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
958 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
960 #ifdef HAVE_MLOCKALL
961 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
962 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
963 #endif
965 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
966 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
968 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
969 g_key_file_get_integer(kf, "global", "iterations", 0) < 0)
970 g_key_file_set_integer(kf, "global", "iterations", 1);
972 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
973 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
975 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
976 g_key_file_set_integer(kf, "global", "iteration_progress", 0);
978 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
979 g_key_file_set_integer(kf, "global", "compression_level", 6);
981 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
982 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
984 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
985 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
987 zlib_bufsize = (uInt)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
989 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
990 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
992 #ifdef HAVE_MLOCKALL
993 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
994 #endif
996 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
997 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
999 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
1000 g_key_file_set_integer(kf, "global", "keepalive", 30);
1002 #ifdef WITH_PINENTRY
1003 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
1004 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
1006 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
1007 g_key_file_set_integer(kf, "global", "pinentry_timeout", 20);
1008 #endif
1010 #ifdef WITH_GNUTLS
1011 if (g_key_file_has_key(kf, "global", "tcp_port", NULL) == FALSE)
1012 g_key_file_set_integer(kf, "global", "tcp_port", 6466);
1014 if (g_key_file_has_key(kf, "global", "enable_tcp", NULL) == FALSE)
1015 g_key_file_set_boolean(kf, "global", "enable_tcp", FALSE);
1017 if (g_key_file_has_key(kf, "global", "tcp_require_key", NULL) == FALSE)
1018 g_key_file_set_boolean(kf, "global", "tcp_require_key", FALSE);
1020 if (g_key_file_has_key(kf, "global", "tcp_wait", NULL) == FALSE)
1021 g_key_file_set_boolean(kf, "global", "tcp_wait", 3);
1023 if (g_key_file_has_key(kf, "global", "cipher_suite", NULL) == FALSE)
1024 g_key_file_set_string(kf, "global", "cipher_suite", "SECURE256");
1026 if (g_key_file_has_key(kf, "global", "tcp_use_crl", NULL) == FALSE)
1027 g_key_file_set_boolean(kf, "global", "tcp_use_crl", FALSE);
1028 #endif
1030 setup_logging(kf);
1033 static GKeyFile *parse_rcfile(gboolean specified)
1035 GKeyFile *kf = g_key_file_new();
1036 GError *rc = NULL;
1038 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
1039 log_write("%s: %s", rcfile, rc->message);
1041 if (cmdline && specified) {
1042 g_clear_error(&rc);
1043 return NULL;
1046 if (rc->code == G_FILE_ERROR_NOENT) {
1047 g_clear_error(&rc);
1048 set_rcfile_defaults(kf);
1049 return kf;
1052 g_clear_error(&rc);
1053 return NULL;
1056 set_rcfile_defaults(kf);
1057 return kf;
1060 static gchar *do_get_password(const gchar *prompt)
1062 gchar buf[LINE_MAX] = {0}, *p;
1063 struct termios told, tnew;
1064 gchar *key;
1066 if (tcgetattr(STDIN_FILENO, &told) == -1) {
1067 log_write("tcgetattr(): %s", strerror(errno));
1068 return NULL;
1071 memcpy(&tnew, &told, sizeof(struct termios));
1072 tnew.c_lflag &= ~(ECHO);
1073 tnew.c_lflag |= ICANON|ECHONL;
1075 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
1076 log_write("tcsetattr(): %s", strerror(errno));
1077 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1078 return NULL;
1081 fprintf(stderr, "%s", prompt);
1083 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
1084 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1085 return NULL;
1088 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1089 p[strlen(p) - 1] = 0;
1091 if (!buf[0]) {
1092 key = gcry_malloc(1);
1093 key[0] = 0;
1095 else {
1096 key = gcry_malloc(strlen(p) + 1);
1097 sprintf(key, "%s", p);
1100 memset(&buf, 0, sizeof(buf));
1101 return key;
1104 /* Only used when "enable_pinentry" is "false" or -P. */
1105 static gpg_error_t get_input(const gchar *filename,
1106 struct client_crypto_s *crypto, guchar *key, pinentry_cmd_t which)
1108 gchar *prompt;
1110 if (which == PINENTRY_SAVE) {
1111 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
1112 crypto->tkey = do_get_password(prompt);
1113 g_free(prompt);
1115 if (!crypto->tkey) {
1116 log_write(N_("%s: Skipping file"), filename);
1117 return GPG_ERR_BAD_PASSPHRASE;
1120 prompt = g_strdup_printf(N_("Repeat passphrase: "));
1121 crypto->tkey2 = do_get_password(prompt);
1122 g_free(prompt);
1124 if (!crypto->tkey2) {
1125 log_write(N_("%s: Skipping file"), filename);
1126 return GPG_ERR_BAD_PASSPHRASE;
1129 if (strcmp(crypto->tkey, crypto->tkey2)) {
1130 log_write(N_("%s: Passphrase mismatch"), filename);
1131 return EPWMD_BADKEY;
1134 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
1135 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1136 return 0;
1139 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
1141 if ((crypto->tkey = do_get_password(prompt)) == NULL) {
1142 log_write(N_("%s: Skipping file"), filename);
1143 g_free(prompt);
1144 return GPG_ERR_BAD_PASSPHRASE;
1147 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
1148 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1149 g_free(prompt);
1150 return 0;
1154 * inbuf must have been allocated with gcry_malloc().
1156 gpg_error_t export_common(const gchar *filename, struct client_crypto_s *crypto,
1157 gpointer inbuf, gulong insize)
1159 gpg_error_t rc;
1160 gint level, zrc;
1161 gulong outsize;
1162 gpointer outbuf;
1164 level = get_key_file_integer(filename, "compression_level");
1166 if (level < 0)
1167 level = 0;
1169 if (do_compress(NULL, level, inbuf, insize, &outbuf, &outsize, &zrc)
1170 == FALSE) {
1171 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
1174 crypto->inbuf = outbuf;
1175 crypto->insize = outsize;
1176 rc = do_xml_encrypt(NULL, crypto, filename);
1177 return rc;
1180 static gpg_error_t get_password(const gchar *filename,
1181 struct client_crypto_s *crypto, guchar *md5file, guchar *key,
1182 pinentry_cmd_t which)
1184 #ifdef WITH_PINENTRY
1185 gpg_error_t rc = 0;
1187 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
1188 == FALSE) {
1189 #endif
1190 return get_input(filename, crypto, key, which);
1191 #ifdef WITH_PINENTRY
1193 else {
1194 gchar *result = NULL;
1195 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
1197 set_pinentry_defaults(pin);
1198 pin->which = which;
1199 pin->filename = g_strdup(filename);
1200 rc = pinentry_getpin(pin, &result);
1202 if (rc) {
1203 xfree(result);
1204 goto done;
1207 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, strlen(result) ? strlen(result) : 1);
1208 xfree(result);
1209 cleanup_pinentry(pin);
1212 done:
1213 return rc;
1214 #endif
1217 static gboolean _getline(const gchar *file, gchar **result, gpg_error_t *rc)
1219 FILE *fp;
1220 gchar buf[LINE_MAX] = {0}, *p;
1221 gchar *str = NULL;
1222 gint len;
1224 *rc = 0;
1226 if ((fp = fopen(file, "r")) == NULL) {
1227 *rc = gpg_error_from_syserror();
1228 return FALSE;
1231 p = fgets(buf, sizeof(buf), fp);
1232 fclose(fp);
1233 len = strlen(buf);
1235 if (len && buf[len - 1] == '\n')
1236 buf[--len] = 0;
1238 str = gcry_malloc(len + 1);
1240 if (!str) {
1241 *rc = gpg_error_from_errno(ENOMEM);
1242 return FALSE;
1245 memcpy(str, buf, len ? len : 1);
1246 str[len] = 0;
1247 memset(&buf, 0, sizeof(buf));
1248 *result = str;
1249 return TRUE;
1252 static gchar *parse_rcfile_keyfile(const gchar *filename, gboolean import,
1253 gpg_error_t *rc)
1255 GError *rv = NULL;
1256 gchar *t, *file = NULL, *str;
1258 *rc = GPG_ERR_UNKNOWN_ERRNO;
1260 if (import == FALSE) {
1261 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
1262 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
1264 if (!file) {
1265 if (rv) {
1266 log_write("%s: key_file: %s", rcfile, rv->message);
1267 g_clear_error(&rv);
1270 return NULL;
1273 t = expand_homedir(file);
1275 if (!t) {
1276 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1277 *rc = gpg_error_from_errno(ENOMEM);
1278 return NULL;
1281 g_free(file);
1282 file = t;
1285 else {
1286 /* -I or -C. The filename is a key file. */
1287 file = g_strdup(filename);
1289 if (!file) {
1290 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1291 *rc = gpg_error_from_errno(ENOMEM);
1292 return NULL;
1296 if (rv) {
1297 log_write("%s: key_file: %s", rcfile, rv->message);
1298 g_clear_error(&rv);
1299 return NULL;
1302 if (!file)
1303 return NULL;
1305 if (_getline(file, &str, rc) == FALSE) {
1306 log_write("%s: %s: %s", filename, file, pwmd_strerror(*rc));
1307 g_free(file);
1308 return NULL;
1311 g_free(file);
1312 *rc = 0;
1313 return str;
1316 static gboolean xml_import(const gchar *filename, const gchar *outfile,
1317 const gchar *keyfile, guint64 iter)
1319 xmlDocPtr doc;
1320 gint fd;
1321 struct stat st;
1322 gint len;
1323 xmlChar *xmlbuf;
1324 xmlChar *xml;
1325 gpg_error_t rc;
1326 struct client_crypto_s *crypto;
1328 if (stat(filename, &st) == -1) {
1329 log_write("%s: %s", filename, strerror(errno));
1330 return FALSE;
1333 crypto = init_client_crypto();
1335 if (!crypto)
1336 return FALSE;
1338 crypto->key = gcry_malloc(gcrykeysize);
1339 memset(crypto->key, 0, gcrykeysize);
1341 if (!crypto->key) {
1342 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1343 goto fail;
1346 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
1347 filename, outfile);
1349 if (iter && keyfile) {
1350 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1352 if (!crypto->tkey)
1353 goto fail;
1355 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1356 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1358 else if (iter) {
1359 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
1361 if (rc)
1362 goto fail;
1365 if ((fd = open(filename, O_RDONLY)) == -1) {
1366 log_write("%s: %s", filename, strerror(errno));
1367 goto fail;
1370 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
1371 close(fd);
1372 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1373 goto fail;
1376 if (read(fd, xmlbuf, st.st_size) == -1) {
1377 rc = errno;
1378 close(fd);
1379 errno = rc;
1380 log_write("%s: %s", filename, strerror(errno));
1381 goto fail;
1384 close(fd);
1385 xmlbuf[st.st_size] = 0;
1388 * Make sure the document validates.
1390 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
1391 log_write("xmlReadDoc() failed");
1392 gcry_free(xmlbuf);
1393 goto fail;
1396 gcry_free(xmlbuf);
1397 xmlDocDumpMemory(doc, &xml, &len);
1398 xmlFreeDoc(doc);
1400 if (!iter)
1401 memset(crypto->key, '!', gcrykeysize);
1403 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
1405 if (!crypto->fh) {
1406 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1407 goto fail;
1410 crypto->fh->fh2.iter = iter;
1411 rc = export_common(outfile, crypto, xml, len);
1412 xmlFree(xml);
1414 if (rc) {
1415 send_error(NULL, rc);
1416 goto fail;
1419 cleanup_crypto(&crypto);
1420 return TRUE;
1422 fail:
1423 cleanup_crypto(&crypto);
1424 return FALSE;
1427 gchar *get_key_file_string(const gchar *section, const gchar *what)
1429 gchar *val = NULL;
1430 GError *grc = NULL;
1432 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1433 val = g_key_file_get_string(keyfileh, section, what, &grc);
1435 if (grc) {
1436 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1437 g_clear_error(&grc);
1440 else {
1441 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1442 val = g_key_file_get_string(keyfileh, "global", what, &grc);
1444 if (grc) {
1445 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1446 g_clear_error(&grc);
1451 return val;
1454 gint get_key_file_integer(const gchar *section, const gchar *what)
1456 gint val = -1;
1457 GError *grc = NULL;
1459 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
1460 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
1462 if (grc) {
1463 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1464 g_clear_error(&grc);
1467 else {
1468 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1469 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
1471 if (grc) {
1472 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1473 g_clear_error(&grc);
1478 return val;
1481 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
1483 gboolean val = FALSE;
1484 GError *grc = NULL;
1486 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1487 val = g_key_file_get_boolean(keyfileh, section, what, &grc);
1489 if (grc) {
1490 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1491 g_clear_error(&grc);
1494 else {
1495 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1496 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
1498 if (grc) {
1499 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1500 g_clear_error(&grc);
1505 return val;
1508 static gboolean parse_rcfile_keys()
1510 gsize n;
1511 gchar **groups;
1512 gchar **p;
1513 gchar *str;
1515 groups = g_key_file_get_groups(keyfileh, &n);
1517 for (p = groups; *p; p++) {
1518 GError *rc = NULL;
1520 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE) {
1521 str = g_key_file_get_string(keyfileh, *p, "key", &rc);
1523 if (!str) {
1524 if (rc) {
1525 log_write("%s: key: %s", rcfile, rc->message);
1526 g_clear_error(&rc);
1528 continue;
1531 do_cache_push(*p, str);
1532 g_free(str);
1533 continue;
1536 if (rc) {
1537 log_write("%s: key: %s", rcfile, rc->message);
1538 g_clear_error(&rc);
1539 continue;
1542 gpg_error_t ret;
1543 str = parse_rcfile_keyfile(*p, FALSE, &ret);
1545 if (!str)
1546 continue;
1548 do_cache_push(*p, str);
1549 gcry_free(str);
1552 g_strfreev(groups);
1553 return TRUE;
1556 static gboolean do_cache_push(const gchar *filename, const gchar *password)
1558 guchar md5file[16];
1559 gint timeout;
1560 const gchar *p = filename;
1561 struct client_crypto_s *crypto;
1562 gpg_error_t rc;
1564 while (isspace(*p))
1565 p++;
1567 if (!*p)
1568 return FALSE;
1570 if (valid_filename(p) == FALSE) {
1571 log_write(N_("%s: Invalid characters in filename"), p);
1572 return FALSE;
1575 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1577 if (access(p, R_OK|W_OK) != 0) {
1578 log_write("%s: %s", p, strerror(errno));
1579 return FALSE;
1582 crypto = init_client_crypto();
1584 if (!crypto)
1585 return FALSE;
1587 crypto->fh = read_file_header(filename, FALSE, &rc);
1589 if (!crypto->fh) {
1590 log_write("%s: %s", p, pwmd_strerror(rc));
1591 cleanup_crypto(&crypto);
1592 return FALSE;
1595 crypto->key = gcry_malloc(gcrykeysize);
1597 if (!crypto->key) {
1598 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1599 cleanup_crypto(&crypto);
1600 return FALSE;
1603 log_write(N_("Adding '%s' to the file cache ..."), filename);
1605 if (crypto->fh->fh2.iter <= 0) {
1606 memset(crypto->key, '!', gcrykeysize);
1607 goto try_decrypt;
1610 if (!password) {
1611 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1613 if (rc) {
1614 send_error(NULL, rc);
1615 cleanup_crypto(&crypto);
1616 return FALSE;
1619 gcry_free(crypto->fh->doc);
1620 crypto->fh->doc = NULL;
1622 else
1623 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password,
1624 strlen(password) ? strlen(password) : 1);
1626 try_decrypt:
1627 rc = try_xml_decrypt(NULL, crypto->key, crypto, NULL, NULL);
1629 if (rc) {
1630 log_write("%s: %s", filename, pwmd_strerror(rc));
1631 cleanup_crypto(&crypto);
1632 return FALSE;
1635 if (cache_update_key(md5file, crypto->key) == FALSE) {
1636 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1637 cleanup_crypto(&crypto);
1638 return FALSE;
1641 timeout = get_key_file_integer(p, "cache_timeout");
1642 cache_set_timeout(md5file, timeout);
1643 log_write(N_("File '%s' now cached"), filename);
1644 cleanup_crypto(&crypto);
1645 return TRUE;
1648 static void init_new_connection(gint fd, gchar *addr)
1650 pthread_t tid;
1651 pthread_attr_t attr;
1652 struct client_thread_s *new;
1653 int n;
1655 new = g_malloc0(sizeof(struct client_thread_s));
1657 if (!new) {
1658 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1659 return;
1662 MUTEX_LOCK(&cn_mutex);
1663 new->fd = fd;
1665 #ifdef WITH_GNUTLS
1666 if (addr)
1667 new->remote = TRUE;
1668 #endif
1670 pthread_attr_init(&attr);
1671 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1672 n = pthread_create(&tid, &attr, client_thread, new);
1673 pthread_attr_destroy(&attr);
1675 if (n) {
1676 g_free(new);
1677 log_write("pthread_create(): %s", strerror(n));
1678 MUTEX_UNLOCK(&cn_mutex);
1679 return;
1682 new->tid = tid;
1683 cn_thread_list = g_slist_append(cn_thread_list, new);
1684 MUTEX_UNLOCK(&cn_mutex);
1686 if (addr)
1687 log_write(N_("new connection: fd=%i, addr=%s"), fd, addr);
1688 else
1689 log_write(N_("new connection: fd=%i"), fd);
1692 #ifdef WITH_GNUTLS
1693 /* From Beej's Guide to Network Programming. It's a good tutorial. */
1694 static void *get_in_addr(struct sockaddr *sa)
1696 if (sa->sa_family == AF_INET)
1697 return &(((struct sockaddr_in*)sa)->sin_addr);
1699 return &(((struct sockaddr_in6*)sa)->sin6_addr);
1702 static void *tcp_accept_thread(void *arg)
1704 gint sockfd = (gint)arg;
1706 for (;;) {
1707 struct sockaddr_storage raddr;
1708 socklen_t slen = sizeof(raddr);
1709 gint fd = -1;
1710 gulong n;
1711 gchar *t;
1713 fd = accept(sockfd, (struct sockaddr *)&raddr, &slen);
1714 pthread_testcancel();
1716 if (fd == -1) {
1717 if (errno != EAGAIN) {
1718 if (!quit) // probably EBADF
1719 log_write("accept(): %s", strerror(errno));
1721 break;
1724 continue;
1727 if (quit)
1728 break;
1730 if (fd >= 0) {
1731 gchar s[INET6_ADDRSTRLEN];
1733 inet_ntop(raddr.ss_family, get_in_addr((struct sockaddr *)&raddr),
1734 s, sizeof s);
1735 init_new_connection(fd, s);
1738 t = get_key_file_string("global", "tcp_wait");
1739 n = strtol(t, NULL, 10);
1740 g_free(t);
1742 if (n < 0)
1743 n = 0;
1745 usleep(n*100000);
1748 /* Just in case accept() failed for some reason other than EBADF */
1749 quit = 1;
1750 pthread_exit(PTHREAD_CANCELED);
1751 return NULL;
1753 #endif
1755 static void *accept_thread(void *arg)
1757 gint sockfd = (gint)arg;
1759 for (;;) {
1760 socklen_t slen = sizeof(struct sockaddr_un);
1761 struct sockaddr_un raddr;
1762 gint fd = -1;
1764 fd = accept(sockfd, (struct sockaddr *)&raddr, &slen);
1765 pthread_testcancel();
1767 if (fd == -1) {
1768 if (errno != EAGAIN) {
1769 if (!quit) // probably EBADF
1770 log_write("accept(): %s", strerror(errno));
1772 break;
1775 continue;
1778 if (fd >= 0)
1779 init_new_connection(fd, NULL);
1782 /* Just in case accept() failed for some reason other than EBADF */
1783 quit = 1;
1784 pthread_exit(PTHREAD_CANCELED);
1785 return NULL;
1788 static void *adjust_cache_timer_thread(void *arg)
1790 for (;;) {
1791 sleep(1);
1792 pthread_testcancel();
1793 CACHE_LOCK(NULL);
1794 cache_adjust_timer();
1795 CACHE_UNLOCK;
1798 return NULL;
1801 static void *keepalive_thread(void *arg)
1803 struct timespec ts;
1804 gint to = (gint)arg;
1806 for (;;) {
1807 clock_gettime(CLOCK_REALTIME, &ts);
1808 ts.tv_sec += to;
1809 pthread_cond_timedwait(&keepalive_cond, &keepalive_cond_mutex, &ts);
1810 pthread_testcancel();
1811 send_status_all(STATUS_KEEPALIVE);
1814 return NULL;
1817 static void startStopKeepAlive(gboolean term)
1819 pthread_attr_t attr;
1820 gint n = get_key_file_integer("global", "keepalive");
1822 if (keepalive_tid)
1823 pthread_cancel(keepalive_tid);
1825 keepalive_tid = 0;
1826 pthread_mutex_trylock(&keepalive_cond_mutex);
1828 if (term)
1829 return;
1831 if (n > 0) {
1832 pthread_attr_init(&attr);
1833 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1834 pthread_create(&keepalive_tid, &attr, keepalive_thread, (void *)n);
1835 pthread_attr_destroy(&attr);
1839 static void server_loop(gint sockfd, gchar **socketpath)
1841 pthread_t accept_tid;
1842 guint n;
1843 sigset_t sigset;
1844 gint n_clients = 0;
1845 pthread_attr_t attr;
1846 pthread_t cache_timeout_tid;
1847 pthread_mutexattr_t mattr;
1849 sigemptyset(&sigset);
1851 /* Termination */
1852 sigaddset(&sigset, SIGTERM);
1853 sigaddset(&sigset, SIGINT);
1855 /* Clears the file cache. */
1856 sigaddset(&sigset, SIGUSR1);
1858 /* Configuration file reloading. */
1859 sigaddset(&sigset, SIGHUP);
1861 /* Caught in client_thread(). Sends a cache status message. */
1862 sigaddset(&sigset, SIGUSR2);
1864 /* Ignored everywhere. When a client disconnects abnormally this signal
1865 * gets raised. It isn't needed though because client_thread() will check
1866 * for rcs even after the client disconnects. */
1867 signal(SIGPIPE, SIG_IGN);
1868 sigprocmask(SIG_BLOCK, &sigset, NULL);
1870 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1871 pthread_mutexattr_init(&mattr);
1872 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
1873 pthread_mutex_init(&cn_mutex, &mattr);
1874 pthread_mutexattr_destroy(&mattr);
1875 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1876 pthread_attr_init(&attr);
1877 pthread_create(&accept_tid, &attr, accept_thread, (void *)sockfd);
1878 startStopKeepAlive(FALSE);
1879 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1880 pthread_create(&cache_timeout_tid, &attr, adjust_cache_timer_thread, NULL);
1881 pthread_attr_destroy(&attr);
1882 pthread_mutex_init(&reload_rcfile_mutex, NULL);
1884 do {
1885 gint sig;
1887 sigwait(&sigset, &sig);
1888 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1890 /* Caught a signal. */
1891 switch (sig) {
1892 case SIGHUP:
1893 reload_rcfile();
1894 break;
1895 case SIGABRT:
1896 CACHE_LOCK(NULL);
1897 cache_clear(NULL, 2);
1898 CACHE_UNLOCK;
1899 #ifndef MEM_DEBUG
1900 xpanic();
1901 #endif
1902 exit(EXIT_FAILURE);
1903 case SIGUSR1:
1904 CACHE_LOCK(NULL);
1905 log_write(N_("clearing file cache"));
1906 cache_clear(NULL, 2);
1907 CACHE_UNLOCK;
1908 break;
1909 default:
1910 quit = 1;
1911 break;
1913 } while (!quit);
1916 * We're out of the main server loop. This happens when a signal was sent
1917 * to terminate the daemon. We'll wait for all clients to disconnect
1918 * before exiting and ignore any following signals.
1920 shutdown(sockfd, SHUT_RDWR);
1921 close(sockfd);
1922 pthread_cancel(accept_tid);
1923 pthread_join(accept_tid, NULL);
1924 #ifdef WITH_GNUTLS
1925 startStopTcp(TRUE);
1926 #endif
1927 unlink(*socketpath);
1928 g_free(*socketpath);
1929 *socketpath = NULL;
1930 MUTEX_LOCK(&cn_mutex);
1931 n = g_slist_length(cn_thread_list);
1932 MUTEX_UNLOCK(&cn_mutex);
1934 if (n)
1935 log_write(N_("waiting for all clients to disconnect"));
1937 while (n) {
1938 if (n != n_clients) {
1939 log_write(N_("%i clients remain"), n);
1940 n_clients = n;
1943 sleep(1);
1944 MUTEX_LOCK(&cn_mutex);
1945 n = g_slist_length(cn_thread_list);
1946 MUTEX_UNLOCK(&cn_mutex);
1949 startStopKeepAlive(TRUE);
1950 pthread_cancel(cache_timeout_tid);
1951 cache_free();
1955 * Called from pinentry_fork() in the child process.
1957 void free_client_list()
1959 gint i, t = g_slist_length(cn_thread_list);
1961 for (i = 0; i < t; i++) {
1962 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1964 free_client(cn->cl);
1967 cache_free();
1970 struct client_crypto_s *init_client_crypto()
1972 struct client_crypto_s *new = g_malloc0(sizeof(struct client_crypto_s));
1973 gpg_error_t rc;
1975 if (!new) {
1976 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1977 return NULL;
1980 rc = gcry_cipher_open(&new->gh, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
1982 if (rc) {
1983 log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(rc));
1984 g_free(new);
1985 return NULL;
1988 return new;
1991 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
1992 const gchar *outfile)
1994 gpg_error_t rc;
1995 guchar md5file[16];
1996 guint64 iter;
1997 struct client_crypto_s *crypto = init_client_crypto();
1999 if (!crypto)
2000 return GPG_ERR_ENOMEM;
2002 crypto->key = gcry_malloc(gcrykeysize);
2004 if (!crypto->key) {
2005 cleanup_crypto(&crypto);
2006 return GPG_ERR_ENOMEM;
2009 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
2010 filename);
2011 crypto->fh = read_file_header(filename, TRUE, &rc);
2013 if (!crypto->fh)
2014 goto done;
2016 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
2018 /* The header in version 1 had a bug where the iterations were off-by-one.
2019 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
2020 * header.
2022 if (crypto->fh->fh1.iter >= 0) {
2023 if (keyfile) {
2024 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
2026 if (!crypto->tkey)
2027 goto done;
2029 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
2030 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
2032 else {
2033 rc = get_password(filename, crypto, md5file, crypto->key,
2034 PINENTRY_OPEN);
2036 if (rc)
2037 goto done;
2041 rc = try_xml_decrypt(NULL, crypto->key, crypto, &crypto->fh->doc,
2042 &crypto->fh->len);
2044 if (rc)
2045 goto done;
2047 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
2049 if (rc) {
2050 log_write("%s: %s", filename, pwmd_strerror(rc));
2051 goto done;
2054 crypto->fh->v1 = FALSE;
2055 iter = crypto->fh->fh1.iter;
2056 memset(&crypto->fh->fh2, 0, sizeof(crypto->fh->fh2));
2057 /* Keep the iterations and key from the original file. */
2058 crypto->fh->fh2.iter = iter+1; // Bugfix for v1 data files.
2059 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
2061 done:
2062 if (rc)
2063 send_error(NULL, rc);
2065 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
2066 cleanup_crypto(&crypto);
2067 return rc;
2070 #ifdef WITH_GNUTLS
2071 static gboolean startStopTcp(gboolean term)
2073 struct addrinfo hints, *servinfo, *p;
2074 gint port = get_key_file_integer("global", "tcp_port");
2075 char buf[7];
2076 int n;
2077 pthread_attr_t attr;
2079 if (term || get_key_file_boolean("global", "enable_tcp") == FALSE) {
2080 if (tcpSockFd != -1) {
2081 pthread_cancel(tcpAcceptTid);
2082 pthread_join(tcpAcceptTid, NULL);
2083 shutdown(tcpSockFd, SHUT_RDWR);
2084 close(tcpSockFd);
2085 tcpSockFd = -1;
2087 /* A client may still be connected. */
2088 if (!quit)
2089 deinitTlsParams();
2092 return TRUE;
2095 if (tcpSockFd != -1)
2096 return TRUE;
2098 memset(&hints, 0, sizeof(hints));
2099 hints.ai_family = AF_UNSPEC;
2100 hints.ai_socktype = SOCK_STREAM;
2101 hints.ai_flags = AI_PASSIVE;
2103 if ((n = getaddrinfo(NULL, print_fmt(buf, sizeof(buf), "%i", port),
2104 &hints, &servinfo)) == -1) {
2105 log_write("getaddrinfo(): %s", gai_strerror(n));
2106 return FALSE;
2109 for(p = servinfo; p != NULL; p = p->ai_next) {
2110 if ((tcpSockFd = socket(p->ai_family, p->ai_socktype,
2111 p->ai_protocol)) == -1) {
2112 log_write("socket(): %s", strerror(errno));
2113 continue;
2116 n = 1;
2118 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_REUSEADDR, &n,
2119 sizeof(int)) == -1) {
2120 log_write("setsockopt(): %s", strerror(errno));
2121 freeaddrinfo(servinfo);
2122 goto fail;
2125 if (bind(tcpSockFd, p->ai_addr, p->ai_addrlen) == -1) {
2126 close(tcpSockFd);
2127 log_write("bind(): %s", strerror(errno));
2128 continue;
2131 n++;
2132 break;
2135 freeaddrinfo(servinfo);
2137 if (!p) {
2138 log_write("%s", N_("could not bind"));
2139 goto fail;
2142 if (g_key_file_has_key(keyfileh, "global", "tcp_interface", NULL)) {
2143 gchar *tmp = get_key_file_string("global", "tcp_interface");
2145 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_BINDTODEVICE, tmp, 1)
2146 == -1) {
2147 log_write("setsockopt(): %s", strerror(errno));
2148 g_free(tmp);
2149 goto fail;
2152 g_free(tmp);
2155 if (!initTlsParams())
2156 goto fail;
2158 if (listen(tcpSockFd, 0) == -1) {
2159 log_write("listen(): %s", strerror(errno));
2160 goto fail;
2163 pthread_attr_init(&attr);
2164 pthread_create(&tcpAcceptTid, &attr, tcp_accept_thread, (void *)tcpSockFd);
2165 pthread_attr_destroy(&attr);
2166 return TRUE;
2168 fail:
2169 deinitTlsParams();
2171 if (tcpSockFd != -1)
2172 close(tcpSockFd);
2174 tcpSockFd = -1;
2175 return FALSE;
2177 #endif
2179 int main(int argc, char *argv[])
2181 gint opt;
2182 struct sockaddr_un addr;
2183 struct passwd *pw = getpwuid(getuid());
2184 gchar buf[PATH_MAX];
2185 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
2186 gchar *socketarg = NULL;
2187 gchar *datadir = NULL;
2188 gboolean n;
2189 gchar *p;
2190 gchar **cache_push = NULL;
2191 guint64 iter = 0;
2192 gchar *import = NULL, *keyfile = NULL;
2193 guint64 cmd_iterations = -1;
2194 gint default_timeout;
2195 gboolean rcfile_spec = FALSE;
2196 gint estatus = EXIT_FAILURE;
2197 gint sockfd;
2198 gchar *outfile = NULL;
2199 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
2200 gint do_unlink = 1;
2201 gboolean secure = FALSE;
2202 guint ptotal = 0;
2203 gint background = 1;
2204 gchar *convert = NULL;
2205 pthread_mutexattr_t mattr;
2206 #ifdef WITH_PINENTRY
2207 gboolean disable_pinentry = FALSE;
2208 #endif
2209 #ifdef WITH_GNUTLS
2210 struct assuan_io_hooks io_hooks = {read_hook, write_hook};
2211 #endif
2212 #if 0
2213 #ifndef DEBUG
2214 #ifdef HAVE_SETRLIMIT
2215 struct rlimit rl;
2217 rl.rlim_cur = rl.rlim_max = 0;
2219 if (setrlimit(RLIMIT_CORE, &rl) != 0)
2220 err(EXIT_FAILURE, "setrlimit()");
2221 #endif
2222 #endif
2223 #endif
2225 #ifdef ENABLE_NLS
2226 setlocale(LC_ALL, "");
2227 bindtextdomain("pwmd", LOCALEDIR);
2228 textdomain("pwmd");
2229 #endif
2231 #ifndef MEM_DEBUG
2232 xmem_init();
2233 #endif
2234 gpg_err_init();
2235 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
2236 g_mem_set_vtable(&mtable);
2237 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
2238 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
2239 xmlInitMemory();
2240 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
2241 gcry_check_version(GCRYPT_VERSION);
2242 #ifdef WITH_GNUTLS
2243 gnutls_global_set_mem_functions(xmalloc, xmalloc, gcry_SecureCheck,
2244 xrealloc, xfree);
2245 gnutls_global_init();
2246 gnutls_global_set_log_function(tls_log);
2247 gnutls_global_set_log_level(1);
2248 assuan_set_io_hooks(&io_hooks);
2249 #endif
2250 xmlInitGlobals();
2251 xmlInitParser();
2252 xmlXPathInit();
2253 g_snprintf(buf, sizeof(buf), "%s/.pwmd", pw->pw_dir);
2255 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2256 err(EXIT_FAILURE, "%s", buf);
2258 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", pw->pw_dir);
2260 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2261 err(EXIT_FAILURE, "%s", buf);
2263 rcfile = g_strdup_printf("%s/.pwmd/config", pw->pw_dir);
2264 cmdline = TRUE;
2265 #ifdef WITH_GNUTLS
2266 tcpSockFd = -1;
2267 #endif
2269 while ((opt = getopt(argc, argv, "Po:C:nI:i:k:hvf:D")) != EOF) {
2270 switch (opt) {
2271 #ifdef WITH_PINENTRY
2272 case 'P':
2273 disable_pinentry = TRUE;
2274 break;
2275 #endif
2276 case 'o':
2277 outfile = optarg;
2278 break;
2279 case 'C':
2280 convert = optarg;
2281 break;
2282 case 'n':
2283 background = 0;
2284 break;
2285 case 'D':
2286 secure = TRUE;
2287 break;
2288 case 'I':
2289 import = optarg;
2290 break;
2291 case 'i':
2292 cmd_iterations = strtol(optarg, NULL, 10);
2293 break;
2294 case 'k':
2295 keyfile = optarg;
2296 break;
2297 case 'f':
2298 g_free(rcfile);
2299 rcfile = g_strdup(optarg);
2300 rcfile_spec = TRUE;
2301 break;
2302 case 'v':
2303 printf(N_("%s\nCopyright (c) %s\nReleased under the terms of the GPL v2. Use at your own risk.\n\nCompile time features:\n%s"), PACKAGE_STRING,
2304 PACKAGE_BUGREPORT,
2305 #ifdef WITH_PINENTRY
2306 "+WITH_PINENTRY\n"
2307 #else
2308 "-WITH_PINENTRY\n"
2309 #endif
2310 #ifdef WITH_QUALITY
2311 "+WITH_QUALITY\n"
2312 #else
2313 "-WITH_QUALITY\n"
2314 #endif
2315 #ifdef WITH_GNUTLS
2316 "+WITH_GNUTLS\n"
2317 #else
2318 "-WITH_GNUTLS\n"
2319 #endif
2320 #ifdef DEBUG
2321 "+DEBUG\n"
2322 #else
2323 "-DEBUG\n"
2324 #endif
2325 #ifdef MEM_DEBUG
2326 "+MEM_DEBUG\n"
2327 #else
2328 "-MEM_DEBUG\n"
2329 #endif
2331 exit(EXIT_SUCCESS);
2332 case 'h':
2333 default:
2334 usage(argv[0]);
2338 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
2339 exit(EXIT_FAILURE);
2341 #ifdef WITH_PINENTRY
2342 if (disable_pinentry == TRUE)
2343 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
2344 #endif
2346 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
2347 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
2349 if (log_syslog == TRUE)
2350 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
2352 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
2353 iter = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
2354 errno = 0;
2356 if (setpriority(PRIO_PROCESS, 0, iter) == -1) {
2357 log_write("setpriority(): %s", strerror(errno));
2358 goto do_exit;
2362 #ifdef HAVE_MLOCKALL
2363 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
2364 log_write("mlockall(): %s", strerror(errno));
2365 goto do_exit;
2367 #endif
2369 setup_gcrypt();
2371 if (convert) {
2372 if (!outfile)
2373 usage(argv[0]);
2375 opt = convert_file(convert, keyfile, outfile);
2376 g_key_file_free(keyfileh);
2377 g_free(rcfile);
2378 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
2381 if (import) {
2382 if (!outfile)
2383 usage(argv[0]);
2385 if (cmd_iterations == -1)
2386 cmd_iterations = (guint64)get_key_file_integer("global", "iterations");
2388 opt = xml_import(import, outfile, keyfile, cmd_iterations);
2389 g_key_file_free(keyfileh);
2390 g_free(rcfile);
2391 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
2394 g_key_file_set_list_separator(keyfileh, ',');
2396 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
2397 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
2399 if (*p == '~') {
2400 p++;
2401 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
2402 g_free(p);
2403 socketarg = g_strdup(buf);
2405 else
2406 socketarg = p;
2408 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
2409 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
2411 datadir = expand_homedir(p);
2412 g_free(p);
2414 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
2415 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
2416 disable_list_and_dump = n;
2418 else
2419 disable_list_and_dump = secure;
2421 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
2422 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
2423 else
2424 default_timeout = -1;
2426 setup_logging(keyfileh);
2428 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2429 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2431 if (argc != optind) {
2432 if (cache_push)
2433 ptotal = g_strv_length(cache_push);
2435 for (; optind < argc; optind++) {
2436 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2437 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
2441 if (strchr(socketarg, '/') == NULL) {
2442 socketdir = g_get_current_dir();
2443 socketname = g_strdup(socketarg);
2444 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2446 else {
2447 socketname = g_strdup(strrchr(socketarg, '/'));
2448 socketname++;
2449 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2450 socketdir = g_strdup(socketarg);
2451 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2454 if (chdir(datadir)) {
2455 log_write("%s: %s", datadir, strerror(errno));
2456 unlink(socketpath);
2457 goto do_exit;
2460 if (parse_rcfile_keys() == FALSE)
2461 goto do_exit;
2463 clear_rcfile_keys();
2466 * Set the cache entry for a file. Prompts for the password.
2468 if (cache_push) {
2469 for (opt = 0; cache_push[opt]; opt++)
2470 do_cache_push(cache_push[opt], NULL);
2472 g_strfreev(cache_push);
2473 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2477 * bind() doesn't like the full pathname of the socket or any non alphanum
2478 * characters so change to the directory where the socket is wanted then
2479 * create it then change to datadir.
2481 if (chdir(socketdir)) {
2482 log_write("%s: %s", socketdir, strerror(errno));
2483 goto do_exit;
2486 g_free(socketdir);
2488 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2489 log_write("socket(): %s", strerror(errno));
2490 goto do_exit;
2493 addr.sun_family = AF_UNIX;
2494 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2496 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2497 log_write("bind(): %s", strerror(errno));
2499 if (errno == EADDRINUSE)
2500 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2501 "stale socket. Please remove it manually."), socketpath);
2503 do_unlink = 0;
2504 goto do_exit;
2507 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2508 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2509 mode_t mode = strtol(t, NULL, 8);
2510 mode_t mask = umask(0);
2512 g_free(t);
2514 if (chmod(socketname, mode) == -1) {
2515 log_write("%s: %s", socketname, strerror(errno));
2516 close(sockfd);
2517 unlink(socketpath);
2518 umask(mask);
2519 goto do_exit;
2522 umask(mask);
2525 g_free(--socketname);
2527 if (chdir(datadir)) {
2528 log_write("%s: %s", datadir, strerror(errno));
2529 close(sockfd);
2530 unlink(socketpath);
2531 goto do_exit;
2534 g_free(datadir);
2535 pthread_mutexattr_init(&mattr);
2536 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
2537 pthread_mutex_init(&cache_mutex, &mattr);
2538 pthread_mutexattr_destroy(&mattr);
2539 pthread_mutex_init(&keepalive_cond_mutex, NULL);
2540 pthread_cond_init(&keepalive_cond, NULL);
2541 #ifdef WITH_PINENTRY
2542 pthread_mutex_init(&pin_mutex, NULL);
2543 #endif
2545 if (listen(sockfd, 0) == -1) {
2546 log_write("listen(): %s", strerror(errno));
2547 goto do_exit;
2550 cmdline = FALSE;
2552 #ifdef WITH_GNUTLS
2553 if (startStopTcp(FALSE) == FALSE)
2554 goto do_exit;
2555 #endif
2557 if (background) {
2558 switch (fork()) {
2559 case -1:
2560 log_write("fork(): %s", strerror(errno));
2561 goto do_exit;
2562 case 0:
2563 close(0);
2564 close(1);
2565 close(2);
2566 setsid();
2567 break;
2568 default:
2569 exit(EXIT_SUCCESS);
2573 server_loop(sockfd, &socketpath);
2574 estatus = EXIT_SUCCESS;
2576 do_exit:
2577 if (socketpath && do_unlink) {
2578 unlink(socketpath);
2579 g_free(socketpath);
2582 #ifdef WITH_GNUTLS
2583 startStopTcp(TRUE);
2584 gnutls_global_deinit();
2585 #endif
2587 g_key_file_free(keyfileh);
2588 g_free(rcfile);
2589 xmlCleanupParser();
2590 xmlCleanupGlobals();
2592 if (estatus == EXIT_SUCCESS)
2593 log_write(N_("pwmd exiting normally"));
2595 #if defined(DEBUG) && !defined(MEM_DEBUG)
2596 // xdump();
2597 #endif
2598 #ifndef MEM_DEBUG
2599 xmem_deinit();
2600 #endif
2601 exit(estatus);