Fixed status messages to use the new iteration type.
[pwmd.git] / src / pwmd.c
blobbf40b50956be3620bbe75f9c07c6e653938a7ad7
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);
550 if (pthread_mutex_trylock(&cn->msg_mutex) == EBUSY) {
551 MUTEX_UNLOCK(&cn->msg_mutex);
553 else
554 pthread_mutex_unlock(&cn->msg_mutex);
556 pthread_mutex_destroy(&cn->msg_mutex);
557 pthread_cond_destroy(&cn->msg_cond);
559 if (pthread_mutex_trylock(&cn->msg_sender_mutex) == EBUSY) {
560 MUTEX_UNLOCK(&cn->msg_sender_mutex);
562 else
563 pthread_mutex_unlock(&cn->msg_sender_mutex);
565 pthread_mutex_destroy(&cn->msg_sender_mutex);
566 pthread_cond_destroy(&cn->msg_sender_cond);
568 for (;;) {
569 struct status_msg_s *m = g_slist_nth_data(cn->msg_queue, 0);
571 if (!m)
572 break;
574 cn->msg_queue = g_slist_remove(cn->msg_queue, m);
575 g_free(m);
578 if (cl && cl->freed == FALSE)
579 cleanup_client(cl);
581 #ifdef WITH_GNUTLS
582 if (cn->tls) {
583 gnutls_deinit(cn->tls->ses);
585 if (cn->tls->fp)
586 g_free(cn->tls->fp);
588 g_free(cn->tls);
590 #endif
592 if (cl && cl->ctx)
593 assuan_deinit_server(cl->ctx);
595 #ifdef WITH_PINENTRY
596 if (cl && cl->pinentry)
597 cleanup_pinentry(cl->pinentry);
598 #endif
600 if (cl->crypto)
601 cleanup_crypto(&cl->crypto);
603 g_free(cl);
605 if (cn->name)
606 g_free(cn->name);
608 cn_thread_list = g_slist_remove(cn_thread_list, cn);
609 g_free(cn);
610 MUTEX_UNLOCK(&cn_mutex);
611 send_status_all(STATUS_CLIENTS);
614 static void *client_msg_sender_thread(void *arg)
616 struct client_thread_s *thd = arg;
618 MUTEX_LOCK(&thd->msg_sender_mutex);
620 for (;;) {
621 struct status_msg_s *msg;
622 gpg_error_t rc;
624 pthread_cond_wait(&thd->msg_sender_cond, &thd->msg_sender_mutex);
625 pthread_testcancel();
627 /* The messages may have been stacked while waiting for send_status()
628 * to return. Send what's in the queue. */
629 for (;;) {
630 msg = g_slist_nth_data(thd->msg_queue, 0);
632 if (!msg)
633 break;
635 /* Unlock to prevent blocking in client_msg_thread(). */
636 MUTEX_UNLOCK(&thd->msg_sender_mutex);
637 rc = send_status(thd->cl->ctx, msg->msg, NULL);
638 MUTEX_LOCK(&thd->msg_sender_mutex);
639 thd->msg_queue = g_slist_remove(thd->msg_queue, msg);
640 g_free(msg);
642 if (rc) {
643 log_write(N_("msg for %i failed: %s"), thd->fd,
644 pwmd_strerror(rc));
645 pthread_cancel(thd->tid);
650 return NULL;
654 * This function waits for a signal from send_status_all() then appends a
655 * message read from a pipe to the clients message queue. The actual sending
656 * of the message is done in client_msg_sender_thread() which waits for a
657 * signal from this function. This prevents blocking in assuan_send_status()
658 * when sending to remote clients. This also avoids duplicate status messages.
659 * If an existing status message in the message queue has the same type as the
660 * current message the the current one will be skipped. This avoids flooding
661 * the client with old status messages.
663 static void *client_msg_thread(void *arg)
665 struct client_thread_s *thd = arg;
667 MUTEX_LOCK(&thd->msg_mutex);
669 for (;;) {
670 fd_set rfds;
671 int n;
672 status_msg_t m;
673 size_t len;
674 struct status_msg_s *msg;
676 pthread_cond_wait(&thd->msg_cond, &thd->msg_mutex);
677 pthread_testcancel();
678 FD_ZERO(&rfds);
679 FD_SET(thd->msg_fd[0], &rfds);
680 n = select(thd->msg_fd[0]+1, &rfds, NULL, NULL, NULL);
682 if (n <= 0 || !FD_ISSET(thd->msg_fd[0], &rfds))
683 continue;
685 len = read(thd->msg_fd[0], &m, sizeof(status_msg_t));
686 pthread_testcancel();
688 if (len != sizeof(status_msg_t)) {
689 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
690 continue;
693 MUTEX_LOCK(&thd->msg_sender_mutex);
695 for (n = 0; n < g_slist_length(thd->msg_queue); n++) {
696 msg = g_slist_nth_data(thd->msg_queue, n);
698 if (msg->msg == m)
699 goto done;
702 msg = g_malloc(sizeof(struct status_msg_s));
704 if (!msg) {
705 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
706 MUTEX_UNLOCK(&thd->msg_sender_mutex);
707 continue;
710 msg->msg = m;
711 thd->msg_queue = g_slist_append(thd->msg_queue, msg);
712 done:
713 MUTEX_UNLOCK(&thd->msg_sender_mutex);
714 pthread_cond_signal(&thd->msg_sender_cond);
717 return NULL;
721 * Called every time a connection is made from init_new_connection(). This is
722 * the thread entry point.
724 static void *client_thread(void *data)
726 struct client_thread_s *thd = data;
727 struct client_s *cl = g_malloc0(sizeof(struct client_s));
728 gpg_error_t rc;
729 pthread_attr_t attr;
732 * Prevent a race condition with init_new_connection() if this thread
733 * fails (returns) for some reason before init_new_connection() releases
734 * the cn_mutex.
736 MUTEX_LOCK(&cn_mutex);
737 MUTEX_UNLOCK(&cn_mutex);
738 pthread_cleanup_push(cleanup_cb, thd);
740 if (!cl) {
741 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
742 goto fail;
745 thd->cl = cl;
747 #ifdef WITH_GNUTLS
749 * Do the TLS handshake before anything else.
751 if (thd->remote) {
752 gchar *prio = get_key_file_string("global", "cipher_suite");
754 thd->tls = tls_init(thd->fd, prio);
755 g_free(prio);
757 if (!thd->tls) {
758 close(thd->fd);
759 goto fail;
762 pthread_testcancel();
764 #endif
766 cl->thd = thd;
768 if (new_connection(cl))
769 goto fail;
771 #ifdef WITH_PINENTRY
772 cl->pinentry = pinentry_init();
774 if (!cl->pinentry) {
775 g_free(cl);
776 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
777 goto fail;
780 #ifdef WITH_GNUTLS
781 /* Require the client to explicity set OPTION PINENTRY since the DISPLAY
782 * might be automatically set from the client. Connections to the X11
783 * server usually aren't encrypted and the client might unintentionally
784 * send the passphrase in the clear.
786 if (thd->remote)
787 cl->pinentry->enable = FALSE;
788 #endif
789 #endif
791 #ifdef HAVE_MLOCKALL
792 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
793 log_write("mlockall(): %s", strerror(errno));
794 goto fail;
796 #endif
798 if (pipe(thd->msg_fd) == -1) {
799 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
800 goto fail;
803 pthread_cond_init(&thd->msg_cond, NULL);
804 pthread_mutex_init(&thd->msg_mutex, NULL);
805 pthread_attr_init(&attr);
806 pthread_create(&thd->msg_tid, &attr, client_msg_thread, thd);
808 pthread_cond_init(&thd->msg_sender_cond, NULL);
809 pthread_mutex_init(&thd->msg_sender_mutex, NULL);
810 pthread_create(&thd->msg_sender_tid, &attr, client_msg_sender_thread, thd);
811 pthread_attr_destroy(&attr);
812 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
814 if (rc) {
815 log_write("%s", gpg_strerror(rc));
816 goto fail;
819 send_status_all(STATUS_CLIENTS);
820 xmlSetStructuredErrorFunc(cl, xml_error_cb);
822 for (;;) {
823 fd_set rfds;
824 int n;
826 FD_ZERO(&rfds);
827 FD_SET(cl->thd->fd, &rfds);
829 #ifdef WITH_PINENTRY
830 if (cl->pinentry->status == PINENTRY_RUNNING)
831 FD_SET(cl->pinentry->fd, &rfds);
833 n = cl->thd->fd > cl->pinentry->fd ? cl->thd->fd : cl->pinentry->fd;
834 #else
835 n = cl->thd->fd;
836 #endif
837 n = select(n+1, &rfds, NULL, NULL, NULL);
838 pthread_testcancel();
840 if (n <= 0)
841 continue;
843 if (FD_ISSET(cl->thd->fd, &rfds)) {
844 rc = assuan_process_next(cl->ctx);
845 pthread_testcancel();
847 if (rc) {
848 cl->inquire_status = INQUIRE_INIT;
850 if (gpg_err_code(rc) == GPG_ERR_EOF)
851 goto done;
853 log_write("assuan_process_next(): %s", gpg_strerror(rc));
854 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
856 if (rc) {
857 log_write("assuan_process_done(): %s", gpg_strerror(rc));
858 goto done;
861 else {
862 #ifdef WITH_PINENTRY
863 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
864 cl->pinentry->status = PINENTRY_RUNNING;
865 #endif
867 switch (cl->inquire_status) {
868 case INQUIRE_BUSY:
869 case INQUIRE_INIT:
870 break;
871 case INQUIRE_DONE:
872 cl->inquire_status = INQUIRE_INIT;
873 pthread_testcancel();
874 rc = assuan_process_done(cl->ctx, 0);
875 break;
880 #ifdef WITH_PINENTRY
881 pinentry_iterate(cl,
882 cl->pinentry->fd != -1 && FD_ISSET(cl->pinentry->fd, &rfds));
883 #endif
887 * Client cleanup (including XML data) is done in cleanup_cb() from
888 * the cleanup thread.
890 done:
891 fail:
892 if (1) {} // Fixes compile time error with pthread_cleanup_push().
893 pthread_cleanup_pop(1);
894 pthread_exit(PTHREAD_CANCELED);
895 return NULL;
898 static void setup_logging(GKeyFile *kf)
900 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
902 if (n == TRUE) {
903 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
905 if (*p == '~') {
906 gchar buf[PATH_MAX];
908 p++;
909 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
910 g_free(p);
912 if (logfile)
913 g_free(logfile);
915 logfile = g_strdup(buf);
917 else {
918 if (logfile)
919 g_free(logfile);
921 logfile = p;
925 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
929 * Make sure all settings are set to either the specified setting or a
930 * default.
932 static void set_rcfile_defaults(GKeyFile *kf)
934 gchar buf[PATH_MAX];
936 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
937 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
938 g_key_file_set_string(kf, "global", "socket_path", buf);
941 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
942 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
943 g_key_file_set_string(kf, "global", "data_directory", buf);
946 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
947 g_key_file_set_boolean(kf, "global", "backup", TRUE);
949 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
950 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
951 g_key_file_set_string(kf, "global", "log_path", buf);
954 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
955 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
957 #ifdef HAVE_MLOCKALL
958 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
959 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
960 #endif
962 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
963 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
965 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
966 g_key_file_get_integer(kf, "global", "iterations", 0) < 0)
967 g_key_file_set_integer(kf, "global", "iterations", 1);
969 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
970 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
972 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
973 g_key_file_set_integer(kf, "global", "iteration_progress", 0);
975 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
976 g_key_file_set_integer(kf, "global", "compression_level", 6);
978 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
979 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
981 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
982 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
984 zlib_bufsize = (uInt)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
986 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
987 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
989 #ifdef HAVE_MLOCKALL
990 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
991 #endif
993 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
994 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
996 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
997 g_key_file_set_integer(kf, "global", "keepalive", 30);
999 #ifdef WITH_PINENTRY
1000 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
1001 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
1003 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
1004 g_key_file_set_integer(kf, "global", "pinentry_timeout", 20);
1005 #endif
1007 #ifdef WITH_GNUTLS
1008 if (g_key_file_has_key(kf, "global", "tcp_port", NULL) == FALSE)
1009 g_key_file_set_integer(kf, "global", "tcp_port", 6466);
1011 if (g_key_file_has_key(kf, "global", "enable_tcp", NULL) == FALSE)
1012 g_key_file_set_boolean(kf, "global", "enable_tcp", FALSE);
1014 if (g_key_file_has_key(kf, "global", "tcp_require_key", NULL) == FALSE)
1015 g_key_file_set_boolean(kf, "global", "tcp_require_key", FALSE);
1017 if (g_key_file_has_key(kf, "global", "tcp_wait", NULL) == FALSE)
1018 g_key_file_set_boolean(kf, "global", "tcp_wait", 3);
1020 if (g_key_file_has_key(kf, "global", "cipher_suite", NULL) == FALSE)
1021 g_key_file_set_string(kf, "global", "cipher_suite", "SECURE256");
1023 if (g_key_file_has_key(kf, "global", "tcp_use_crl", NULL) == FALSE)
1024 g_key_file_set_boolean(kf, "global", "tcp_use_crl", FALSE);
1025 #endif
1027 setup_logging(kf);
1030 static GKeyFile *parse_rcfile(gboolean specified)
1032 GKeyFile *kf = g_key_file_new();
1033 GError *rc = NULL;
1035 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
1036 log_write("%s: %s", rcfile, rc->message);
1038 if (cmdline && specified) {
1039 g_clear_error(&rc);
1040 return NULL;
1043 if (rc->code == G_FILE_ERROR_NOENT) {
1044 g_clear_error(&rc);
1045 set_rcfile_defaults(kf);
1046 return kf;
1049 g_clear_error(&rc);
1050 return NULL;
1053 set_rcfile_defaults(kf);
1054 return kf;
1057 static gchar *do_get_password(const gchar *prompt)
1059 gchar buf[LINE_MAX] = {0}, *p;
1060 struct termios told, tnew;
1061 gchar *key;
1063 if (tcgetattr(STDIN_FILENO, &told) == -1) {
1064 log_write("tcgetattr(): %s", strerror(errno));
1065 return NULL;
1068 memcpy(&tnew, &told, sizeof(struct termios));
1069 tnew.c_lflag &= ~(ECHO);
1070 tnew.c_lflag |= ICANON|ECHONL;
1072 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
1073 log_write("tcsetattr(): %s", strerror(errno));
1074 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1075 return NULL;
1078 fprintf(stderr, "%s", prompt);
1080 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
1081 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1082 return NULL;
1085 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1086 p[strlen(p) - 1] = 0;
1088 if (!buf[0]) {
1089 key = gcry_malloc(1);
1090 key[0] = 0;
1092 else {
1093 key = gcry_malloc(strlen(p) + 1);
1094 sprintf(key, "%s", p);
1097 memset(&buf, 0, sizeof(buf));
1098 return key;
1101 /* Only used when "enable_pinentry" is "false" or -P. */
1102 static gpg_error_t get_input(const gchar *filename,
1103 struct client_crypto_s *crypto, guchar *key, pinentry_cmd_t which)
1105 gchar *prompt;
1107 if (which == PINENTRY_SAVE) {
1108 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
1109 crypto->tkey = do_get_password(prompt);
1110 g_free(prompt);
1112 if (!crypto->tkey) {
1113 log_write(N_("%s: Skipping file"), filename);
1114 return GPG_ERR_BAD_PASSPHRASE;
1117 prompt = g_strdup_printf(N_("Repeat passphrase: "));
1118 crypto->tkey2 = do_get_password(prompt);
1119 g_free(prompt);
1121 if (!crypto->tkey2) {
1122 log_write(N_("%s: Skipping file"), filename);
1123 return GPG_ERR_BAD_PASSPHRASE;
1126 if (strcmp(crypto->tkey, crypto->tkey2)) {
1127 log_write(N_("%s: Passphrase mismatch"), filename);
1128 return EPWMD_BADKEY;
1131 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
1132 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1133 return 0;
1136 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
1138 if ((crypto->tkey = do_get_password(prompt)) == NULL) {
1139 log_write(N_("%s: Skipping file"), filename);
1140 g_free(prompt);
1141 return GPG_ERR_BAD_PASSPHRASE;
1144 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
1145 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1146 g_free(prompt);
1147 return 0;
1151 * inbuf must have been allocated with gcry_malloc().
1153 gpg_error_t export_common(const gchar *filename, struct client_crypto_s *crypto,
1154 gpointer inbuf, gulong insize)
1156 gpg_error_t rc;
1157 gint level, zrc;
1158 gulong outsize;
1159 gpointer outbuf;
1161 level = get_key_file_integer(filename, "compression_level");
1163 if (level < 0)
1164 level = 0;
1166 if (do_compress(NULL, level, inbuf, insize, &outbuf, &outsize, &zrc)
1167 == FALSE) {
1168 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
1171 crypto->inbuf = outbuf;
1172 crypto->insize = outsize;
1173 rc = do_xml_encrypt(NULL, crypto, filename);
1174 return rc;
1177 static gpg_error_t get_password(const gchar *filename,
1178 struct client_crypto_s *crypto, guchar *md5file, guchar *key,
1179 pinentry_cmd_t which)
1181 #ifdef WITH_PINENTRY
1182 gpg_error_t rc = 0;
1184 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
1185 == FALSE) {
1186 #endif
1187 return get_input(filename, crypto, key, which);
1188 #ifdef WITH_PINENTRY
1190 else {
1191 gchar *result = NULL;
1192 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
1194 set_pinentry_defaults(pin);
1195 pin->which = which;
1196 pin->filename = g_strdup(filename);
1197 rc = pinentry_getpin(pin, &result);
1199 if (rc) {
1200 xfree(result);
1201 goto done;
1204 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, strlen(result) ? strlen(result) : 1);
1205 xfree(result);
1206 cleanup_pinentry(pin);
1209 done:
1210 return rc;
1211 #endif
1214 static gboolean _getline(const gchar *file, gchar **result, gpg_error_t *rc)
1216 FILE *fp;
1217 gchar buf[LINE_MAX] = {0}, *p;
1218 gchar *str = NULL;
1219 gint len;
1221 *rc = 0;
1223 if ((fp = fopen(file, "r")) == NULL) {
1224 *rc = gpg_error_from_syserror();
1225 return FALSE;
1228 p = fgets(buf, sizeof(buf), fp);
1229 fclose(fp);
1230 len = strlen(buf);
1232 if (len && buf[len - 1] == '\n')
1233 buf[--len] = 0;
1235 str = gcry_malloc(len + 1);
1237 if (!str) {
1238 *rc = gpg_error_from_errno(ENOMEM);
1239 return FALSE;
1242 memcpy(str, buf, len ? len : 1);
1243 str[len] = 0;
1244 memset(&buf, 0, sizeof(buf));
1245 *result = str;
1246 return TRUE;
1249 static gchar *parse_rcfile_keyfile(const gchar *filename, gboolean import,
1250 gpg_error_t *rc)
1252 GError *rv = NULL;
1253 gchar *t, *file = NULL, *str;
1255 *rc = GPG_ERR_UNKNOWN_ERRNO;
1257 if (import == FALSE) {
1258 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
1259 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
1261 if (!file) {
1262 if (rv) {
1263 log_write("%s: key_file: %s", rcfile, rv->message);
1264 g_clear_error(&rv);
1267 return NULL;
1270 t = expand_homedir(file);
1272 if (!t) {
1273 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1274 *rc = gpg_error_from_errno(ENOMEM);
1275 return NULL;
1278 g_free(file);
1279 file = t;
1282 else {
1283 /* -I or -C. The filename is a key file. */
1284 file = g_strdup(filename);
1286 if (!file) {
1287 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1288 *rc = gpg_error_from_errno(ENOMEM);
1289 return NULL;
1293 if (rv) {
1294 log_write("%s: key_file: %s", rcfile, rv->message);
1295 g_clear_error(&rv);
1296 return NULL;
1299 if (!file)
1300 return NULL;
1302 if (_getline(file, &str, rc) == FALSE) {
1303 log_write("%s: %s: %s", filename, file, pwmd_strerror(*rc));
1304 g_free(file);
1305 return NULL;
1308 g_free(file);
1309 *rc = 0;
1310 return str;
1313 static gboolean xml_import(const gchar *filename, const gchar *outfile,
1314 const gchar *keyfile, guint64 iter)
1316 xmlDocPtr doc;
1317 gint fd;
1318 struct stat st;
1319 gint len;
1320 xmlChar *xmlbuf;
1321 xmlChar *xml;
1322 gpg_error_t rc;
1323 struct client_crypto_s *crypto;
1325 if (stat(filename, &st) == -1) {
1326 log_write("%s: %s", filename, strerror(errno));
1327 return FALSE;
1330 crypto = init_client_crypto();
1332 if (!crypto)
1333 return FALSE;
1335 crypto->key = gcry_malloc(gcrykeysize);
1336 memset(crypto->key, 0, gcrykeysize);
1338 if (!crypto->key) {
1339 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1340 goto fail;
1343 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
1344 filename, outfile);
1346 if (iter && keyfile) {
1347 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1349 if (!crypto->tkey)
1350 goto fail;
1352 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1353 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1355 else if (iter) {
1356 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
1358 if (rc)
1359 goto fail;
1362 if ((fd = open(filename, O_RDONLY)) == -1) {
1363 log_write("%s: %s", filename, strerror(errno));
1364 goto fail;
1367 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
1368 close(fd);
1369 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1370 goto fail;
1373 if (read(fd, xmlbuf, st.st_size) == -1) {
1374 rc = errno;
1375 close(fd);
1376 errno = rc;
1377 log_write("%s: %s", filename, strerror(errno));
1378 goto fail;
1381 close(fd);
1382 xmlbuf[st.st_size] = 0;
1385 * Make sure the document validates.
1387 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
1388 log_write("xmlReadDoc() failed");
1389 gcry_free(xmlbuf);
1390 goto fail;
1393 gcry_free(xmlbuf);
1394 xmlDocDumpMemory(doc, &xml, &len);
1395 xmlFreeDoc(doc);
1397 if (!iter)
1398 memset(crypto->key, '!', gcrykeysize);
1400 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
1402 if (!crypto->fh) {
1403 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1404 goto fail;
1407 crypto->fh->fh2.iter = iter;
1408 rc = export_common(outfile, crypto, xml, len);
1409 xmlFree(xml);
1411 if (rc) {
1412 send_error(NULL, rc);
1413 goto fail;
1416 cleanup_crypto(&crypto);
1417 return TRUE;
1419 fail:
1420 cleanup_crypto(&crypto);
1421 return FALSE;
1424 gchar *get_key_file_string(const gchar *section, const gchar *what)
1426 gchar *val = NULL;
1427 GError *grc = NULL;
1429 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1430 val = g_key_file_get_string(keyfileh, section, what, &grc);
1432 if (grc) {
1433 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1434 g_clear_error(&grc);
1437 else {
1438 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1439 val = g_key_file_get_string(keyfileh, "global", what, &grc);
1441 if (grc) {
1442 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1443 g_clear_error(&grc);
1448 return val;
1451 gint get_key_file_integer(const gchar *section, const gchar *what)
1453 gint val = -1;
1454 GError *grc = NULL;
1456 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
1457 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
1459 if (grc) {
1460 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1461 g_clear_error(&grc);
1464 else {
1465 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1466 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
1468 if (grc) {
1469 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1470 g_clear_error(&grc);
1475 return val;
1478 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
1480 gboolean val = FALSE;
1481 GError *grc = NULL;
1483 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1484 val = g_key_file_get_boolean(keyfileh, section, what, &grc);
1486 if (grc) {
1487 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1488 g_clear_error(&grc);
1491 else {
1492 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1493 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
1495 if (grc) {
1496 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1497 g_clear_error(&grc);
1502 return val;
1505 static gboolean parse_rcfile_keys()
1507 gsize n;
1508 gchar **groups;
1509 gchar **p;
1510 gchar *str;
1512 groups = g_key_file_get_groups(keyfileh, &n);
1514 for (p = groups; *p; p++) {
1515 GError *rc = NULL;
1517 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE) {
1518 str = g_key_file_get_string(keyfileh, *p, "key", &rc);
1520 if (!str) {
1521 if (rc) {
1522 log_write("%s: key: %s", rcfile, rc->message);
1523 g_clear_error(&rc);
1525 continue;
1528 do_cache_push(*p, str);
1529 g_free(str);
1530 continue;
1533 if (rc) {
1534 log_write("%s: key: %s", rcfile, rc->message);
1535 g_clear_error(&rc);
1536 continue;
1539 gpg_error_t ret;
1540 str = parse_rcfile_keyfile(*p, FALSE, &ret);
1542 if (!str)
1543 continue;
1545 do_cache_push(*p, str);
1546 gcry_free(str);
1549 g_strfreev(groups);
1550 return TRUE;
1553 static gboolean do_cache_push(const gchar *filename, const gchar *password)
1555 guchar md5file[16];
1556 gint timeout;
1557 const gchar *p = filename;
1558 struct client_crypto_s *crypto;
1559 gpg_error_t rc;
1561 while (isspace(*p))
1562 p++;
1564 if (!*p)
1565 return FALSE;
1567 if (valid_filename(p) == FALSE) {
1568 log_write(N_("%s: Invalid characters in filename"), p);
1569 return FALSE;
1572 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1574 if (access(p, R_OK|W_OK) != 0) {
1575 log_write("%s: %s", p, strerror(errno));
1576 return FALSE;
1579 crypto = init_client_crypto();
1581 if (!crypto)
1582 return FALSE;
1584 crypto->fh = read_file_header(filename, FALSE, &rc);
1586 if (!crypto->fh) {
1587 log_write("%s: %s", p, pwmd_strerror(rc));
1588 cleanup_crypto(&crypto);
1589 return FALSE;
1592 crypto->key = gcry_malloc(gcrykeysize);
1594 if (!crypto->key) {
1595 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1596 cleanup_crypto(&crypto);
1597 return FALSE;
1600 log_write(N_("Adding '%s' to the file cache ..."), filename);
1602 if (crypto->fh->fh2.iter <= 0) {
1603 memset(crypto->key, '!', gcrykeysize);
1604 goto try_decrypt;
1607 if (!password) {
1608 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1610 if (rc) {
1611 send_error(NULL, rc);
1612 cleanup_crypto(&crypto);
1613 return FALSE;
1616 gcry_free(crypto->fh->doc);
1617 crypto->fh->doc = NULL;
1619 else
1620 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password,
1621 strlen(password) ? strlen(password) : 1);
1623 try_decrypt:
1624 rc = try_xml_decrypt(NULL, crypto->key, crypto, NULL, NULL);
1626 if (rc) {
1627 log_write("%s: %s", filename, pwmd_strerror(rc));
1628 cleanup_crypto(&crypto);
1629 return FALSE;
1632 if (cache_update_key(md5file, crypto->key) == FALSE) {
1633 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1634 cleanup_crypto(&crypto);
1635 return FALSE;
1638 timeout = get_key_file_integer(p, "cache_timeout");
1639 cache_set_timeout(md5file, timeout);
1640 log_write(N_("File '%s' now cached"), filename);
1641 cleanup_crypto(&crypto);
1642 return TRUE;
1645 static void init_new_connection(gint fd, gchar *addr)
1647 pthread_t tid;
1648 pthread_attr_t attr;
1649 struct client_thread_s *new;
1650 int n;
1652 new = g_malloc0(sizeof(struct client_thread_s));
1654 if (!new) {
1655 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1656 return;
1659 MUTEX_LOCK(&cn_mutex);
1660 new->fd = fd;
1662 #ifdef WITH_GNUTLS
1663 if (addr)
1664 new->remote = TRUE;
1665 #endif
1667 pthread_attr_init(&attr);
1668 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1669 n = pthread_create(&tid, &attr, client_thread, new);
1670 pthread_attr_destroy(&attr);
1672 if (n) {
1673 g_free(new);
1674 log_write("pthread_create(): %s", strerror(n));
1675 MUTEX_UNLOCK(&cn_mutex);
1676 return;
1679 new->tid = tid;
1680 cn_thread_list = g_slist_append(cn_thread_list, new);
1681 MUTEX_UNLOCK(&cn_mutex);
1683 if (addr)
1684 log_write(N_("new connection: fd=%i, addr=%s"), fd, addr);
1685 else
1686 log_write(N_("new connection: fd=%i"), fd);
1689 #ifdef WITH_GNUTLS
1690 /* From Beej's Guide to Network Programming. It's a good tutorial. */
1691 static void *get_in_addr(struct sockaddr *sa)
1693 if (sa->sa_family == AF_INET)
1694 return &(((struct sockaddr_in*)sa)->sin_addr);
1696 return &(((struct sockaddr_in6*)sa)->sin6_addr);
1699 static void *tcp_accept_thread(void *arg)
1701 gint sockfd = (gint)arg;
1703 for (;;) {
1704 struct sockaddr_storage raddr;
1705 socklen_t slen = sizeof(raddr);
1706 gint fd = -1;
1707 gulong n;
1708 gchar *t;
1710 fd = accept(sockfd, (struct sockaddr *)&raddr, &slen);
1711 pthread_testcancel();
1713 if (fd == -1) {
1714 if (errno != EAGAIN) {
1715 if (!quit) // probably EBADF
1716 log_write("accept(): %s", strerror(errno));
1718 break;
1721 continue;
1724 if (quit)
1725 break;
1727 if (fd >= 0) {
1728 gchar s[INET6_ADDRSTRLEN];
1730 inet_ntop(raddr.ss_family, get_in_addr((struct sockaddr *)&raddr),
1731 s, sizeof s);
1732 init_new_connection(fd, s);
1735 t = get_key_file_string("global", "tcp_wait");
1736 n = strtol(t, NULL, 10);
1737 g_free(t);
1739 if (n < 0)
1740 n = 0;
1742 usleep(n*100000);
1745 /* Just in case accept() failed for some reason other than EBADF */
1746 quit = 1;
1747 pthread_exit(PTHREAD_CANCELED);
1748 return NULL;
1750 #endif
1752 static void *accept_thread(void *arg)
1754 gint sockfd = (gint)arg;
1756 for (;;) {
1757 socklen_t slen = sizeof(struct sockaddr_un);
1758 struct sockaddr_un raddr;
1759 gint fd = -1;
1761 fd = accept(sockfd, (struct sockaddr *)&raddr, &slen);
1762 pthread_testcancel();
1764 if (fd == -1) {
1765 if (errno != EAGAIN) {
1766 if (!quit) // probably EBADF
1767 log_write("accept(): %s", strerror(errno));
1769 break;
1772 continue;
1775 if (fd >= 0)
1776 init_new_connection(fd, NULL);
1779 /* Just in case accept() failed for some reason other than EBADF */
1780 quit = 1;
1781 pthread_exit(PTHREAD_CANCELED);
1782 return NULL;
1785 static void *adjust_cache_timer_thread(void *arg)
1787 for (;;) {
1788 sleep(1);
1789 pthread_testcancel();
1790 CACHE_LOCK(NULL);
1791 cache_adjust_timer();
1792 CACHE_UNLOCK;
1795 return NULL;
1798 static void *keepalive_thread(void *arg)
1800 struct timespec ts;
1801 gint to = (gint)arg;
1803 for (;;) {
1804 clock_gettime(CLOCK_REALTIME, &ts);
1805 ts.tv_sec += to;
1806 pthread_cond_timedwait(&keepalive_cond, &keepalive_cond_mutex, &ts);
1807 pthread_testcancel();
1808 send_status_all(STATUS_KEEPALIVE);
1811 return NULL;
1814 static void startStopKeepAlive(gboolean term)
1816 pthread_attr_t attr;
1817 gint n = get_key_file_integer("global", "keepalive");
1819 if (keepalive_tid)
1820 pthread_cancel(keepalive_tid);
1822 keepalive_tid = 0;
1823 pthread_mutex_trylock(&keepalive_cond_mutex);
1825 if (term)
1826 return;
1828 if (n > 0) {
1829 pthread_attr_init(&attr);
1830 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1831 pthread_create(&keepalive_tid, &attr, keepalive_thread, (void *)n);
1832 pthread_attr_destroy(&attr);
1836 static void server_loop(gint sockfd, gchar **socketpath)
1838 pthread_t accept_tid;
1839 guint n;
1840 sigset_t sigset;
1841 gint n_clients = 0;
1842 pthread_attr_t attr;
1843 pthread_t cache_timeout_tid;
1844 pthread_mutexattr_t mattr;
1846 sigemptyset(&sigset);
1848 /* Termination */
1849 sigaddset(&sigset, SIGTERM);
1850 sigaddset(&sigset, SIGINT);
1852 /* Clears the file cache. */
1853 sigaddset(&sigset, SIGUSR1);
1855 /* Configuration file reloading. */
1856 sigaddset(&sigset, SIGHUP);
1858 /* Caught in client_thread(). Sends a cache status message. */
1859 sigaddset(&sigset, SIGUSR2);
1861 /* Ignored everywhere. When a client disconnects abnormally this signal
1862 * gets raised. It isn't needed though because client_thread() will check
1863 * for rcs even after the client disconnects. */
1864 signal(SIGPIPE, SIG_IGN);
1865 sigprocmask(SIG_BLOCK, &sigset, NULL);
1867 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1868 pthread_mutexattr_init(&mattr);
1869 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
1870 pthread_mutex_init(&cn_mutex, &mattr);
1871 pthread_mutexattr_destroy(&mattr);
1872 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1873 pthread_attr_init(&attr);
1874 pthread_create(&accept_tid, &attr, accept_thread, (void *)sockfd);
1875 startStopKeepAlive(FALSE);
1876 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1877 pthread_create(&cache_timeout_tid, &attr, adjust_cache_timer_thread, NULL);
1878 pthread_attr_destroy(&attr);
1879 pthread_mutex_init(&reload_rcfile_mutex, NULL);
1881 do {
1882 gint sig;
1884 sigwait(&sigset, &sig);
1885 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1887 /* Caught a signal. */
1888 switch (sig) {
1889 case SIGHUP:
1890 reload_rcfile();
1891 break;
1892 case SIGABRT:
1893 CACHE_LOCK(NULL);
1894 cache_clear(NULL, 2);
1895 CACHE_UNLOCK;
1896 #ifndef MEM_DEBUG
1897 xpanic();
1898 #endif
1899 exit(EXIT_FAILURE);
1900 case SIGUSR1:
1901 CACHE_LOCK(NULL);
1902 log_write(N_("clearing file cache"));
1903 cache_clear(NULL, 2);
1904 CACHE_UNLOCK;
1905 break;
1906 default:
1907 quit = 1;
1908 break;
1910 } while (!quit);
1913 * We're out of the main server loop. This happens when a signal was sent
1914 * to terminate the daemon. We'll wait for all clients to disconnect
1915 * before exiting and ignore any following signals.
1917 shutdown(sockfd, SHUT_RDWR);
1918 close(sockfd);
1919 pthread_cancel(accept_tid);
1920 pthread_join(accept_tid, NULL);
1921 #ifdef WITH_GNUTLS
1922 startStopTcp(TRUE);
1923 #endif
1924 unlink(*socketpath);
1925 g_free(*socketpath);
1926 *socketpath = NULL;
1927 MUTEX_LOCK(&cn_mutex);
1928 n = g_slist_length(cn_thread_list);
1929 MUTEX_UNLOCK(&cn_mutex);
1931 if (n)
1932 log_write(N_("waiting for all clients to disconnect"));
1934 while (n) {
1935 if (n != n_clients) {
1936 log_write(N_("%i clients remain"), n);
1937 n_clients = n;
1940 sleep(1);
1941 MUTEX_LOCK(&cn_mutex);
1942 n = g_slist_length(cn_thread_list);
1943 MUTEX_UNLOCK(&cn_mutex);
1946 startStopKeepAlive(TRUE);
1947 pthread_cancel(cache_timeout_tid);
1948 cache_free();
1952 * Called from pinentry_fork() in the child process.
1954 void free_client_list()
1956 gint i, t = g_slist_length(cn_thread_list);
1958 for (i = 0; i < t; i++) {
1959 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1961 free_client(cn->cl);
1964 cache_free();
1967 struct client_crypto_s *init_client_crypto()
1969 struct client_crypto_s *new = g_malloc0(sizeof(struct client_crypto_s));
1970 gpg_error_t rc;
1972 if (!new) {
1973 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1974 return NULL;
1977 rc = gcry_cipher_open(&new->gh, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
1979 if (rc) {
1980 log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(rc));
1981 g_free(new);
1982 return NULL;
1985 return new;
1988 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
1989 const gchar *outfile)
1991 gpg_error_t rc;
1992 guchar md5file[16];
1993 guint64 iter;
1994 struct client_crypto_s *crypto = init_client_crypto();
1996 if (!crypto)
1997 return GPG_ERR_ENOMEM;
1999 crypto->key = gcry_malloc(gcrykeysize);
2001 if (!crypto->key) {
2002 cleanup_crypto(&crypto);
2003 return GPG_ERR_ENOMEM;
2006 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
2007 filename);
2008 crypto->fh = read_file_header(filename, TRUE, &rc);
2010 if (!crypto->fh)
2011 goto done;
2013 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
2015 /* The header in version 1 had a bug where the iterations were off-by-one.
2016 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
2017 * header.
2019 if (crypto->fh->fh1.iter >= 0) {
2020 if (keyfile) {
2021 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
2023 if (!crypto->tkey)
2024 goto done;
2026 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
2027 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
2029 else {
2030 rc = get_password(filename, crypto, md5file, crypto->key,
2031 PINENTRY_OPEN);
2033 if (rc)
2034 goto done;
2038 rc = try_xml_decrypt(NULL, crypto->key, crypto, &crypto->fh->doc,
2039 &crypto->fh->len);
2041 if (rc)
2042 goto done;
2044 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
2046 if (rc) {
2047 log_write("%s: %s", filename, pwmd_strerror(rc));
2048 goto done;
2051 crypto->fh->v1 = FALSE;
2052 iter = crypto->fh->fh1.iter;
2053 memset(&crypto->fh->fh2, 0, sizeof(crypto->fh->fh2));
2054 /* Keep the iterations and key from the original file. */
2055 crypto->fh->fh2.iter = iter+1; // Bugfix for v1 data files.
2056 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
2058 done:
2059 if (rc)
2060 send_error(NULL, rc);
2062 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
2063 cleanup_crypto(&crypto);
2064 return rc;
2067 #ifdef WITH_GNUTLS
2068 static gboolean startStopTcp(gboolean term)
2070 struct addrinfo hints, *servinfo, *p;
2071 gint port = get_key_file_integer("global", "tcp_port");
2072 char buf[7];
2073 int n;
2074 pthread_attr_t attr;
2076 if (term || get_key_file_boolean("global", "enable_tcp") == FALSE) {
2077 if (tcpSockFd != -1) {
2078 pthread_cancel(tcpAcceptTid);
2079 pthread_join(tcpAcceptTid, NULL);
2080 shutdown(tcpSockFd, SHUT_RDWR);
2081 close(tcpSockFd);
2082 tcpSockFd = -1;
2084 /* A client may still be connected. */
2085 if (!quit)
2086 deinitTlsParams();
2089 return TRUE;
2092 if (tcpSockFd != -1)
2093 return TRUE;
2095 memset(&hints, 0, sizeof(hints));
2096 hints.ai_family = AF_UNSPEC;
2097 hints.ai_socktype = SOCK_STREAM;
2098 hints.ai_flags = AI_PASSIVE;
2100 if ((n = getaddrinfo(NULL, print_fmt(buf, sizeof(buf), "%i", port),
2101 &hints, &servinfo)) == -1) {
2102 log_write("getaddrinfo(): %s", gai_strerror(n));
2103 return FALSE;
2106 for(p = servinfo; p != NULL; p = p->ai_next) {
2107 if ((tcpSockFd = socket(p->ai_family, p->ai_socktype,
2108 p->ai_protocol)) == -1) {
2109 log_write("socket(): %s", strerror(errno));
2110 continue;
2113 n = 1;
2115 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_REUSEADDR, &n,
2116 sizeof(int)) == -1) {
2117 log_write("setsockopt(): %s", strerror(errno));
2118 freeaddrinfo(servinfo);
2119 goto fail;
2122 if (bind(tcpSockFd, p->ai_addr, p->ai_addrlen) == -1) {
2123 close(tcpSockFd);
2124 log_write("bind(): %s", strerror(errno));
2125 continue;
2128 n++;
2129 break;
2132 freeaddrinfo(servinfo);
2134 if (!p) {
2135 log_write("%s", N_("could not bind"));
2136 goto fail;
2139 if (g_key_file_has_key(keyfileh, "global", "tcp_interface", NULL)) {
2140 gchar *tmp = get_key_file_string("global", "tcp_interface");
2142 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_BINDTODEVICE, tmp, 1)
2143 == -1) {
2144 log_write("setsockopt(): %s", strerror(errno));
2145 g_free(tmp);
2146 goto fail;
2149 g_free(tmp);
2152 if (!initTlsParams())
2153 goto fail;
2155 if (listen(tcpSockFd, 0) == -1) {
2156 log_write("listen(): %s", strerror(errno));
2157 goto fail;
2160 pthread_attr_init(&attr);
2161 pthread_create(&tcpAcceptTid, &attr, tcp_accept_thread, (void *)tcpSockFd);
2162 pthread_attr_destroy(&attr);
2163 return TRUE;
2165 fail:
2166 deinitTlsParams();
2168 if (tcpSockFd != -1)
2169 close(tcpSockFd);
2171 tcpSockFd = -1;
2172 return FALSE;
2174 #endif
2176 int main(int argc, char *argv[])
2178 gint opt;
2179 struct sockaddr_un addr;
2180 struct passwd *pw = getpwuid(getuid());
2181 gchar buf[PATH_MAX];
2182 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
2183 gchar *socketarg = NULL;
2184 gchar *datadir = NULL;
2185 gboolean n;
2186 gchar *p;
2187 gchar **cache_push = NULL;
2188 guint64 iter = 0;
2189 gchar *import = NULL, *keyfile = NULL;
2190 guint64 cmd_iterations = -1;
2191 gint default_timeout;
2192 gboolean rcfile_spec = FALSE;
2193 gint estatus = EXIT_FAILURE;
2194 gint sockfd;
2195 gchar *outfile = NULL;
2196 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
2197 gint do_unlink = 1;
2198 gboolean secure = FALSE;
2199 guint ptotal = 0;
2200 gint background = 1;
2201 gchar *convert = NULL;
2202 pthread_mutexattr_t mattr;
2203 #ifdef WITH_PINENTRY
2204 gboolean disable_pinentry = FALSE;
2205 #endif
2206 #ifdef WITH_GNUTLS
2207 struct assuan_io_hooks io_hooks = {read_hook, write_hook};
2208 #endif
2209 #if 0
2210 #ifndef DEBUG
2211 #ifdef HAVE_SETRLIMIT
2212 struct rlimit rl;
2214 rl.rlim_cur = rl.rlim_max = 0;
2216 if (setrlimit(RLIMIT_CORE, &rl) != 0)
2217 err(EXIT_FAILURE, "setrlimit()");
2218 #endif
2219 #endif
2220 #endif
2222 #ifdef ENABLE_NLS
2223 setlocale(LC_ALL, "");
2224 bindtextdomain("pwmd", LOCALEDIR);
2225 textdomain("pwmd");
2226 #endif
2228 #ifndef MEM_DEBUG
2229 xmem_init();
2230 #endif
2231 gpg_err_init();
2232 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
2233 g_mem_set_vtable(&mtable);
2234 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
2235 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
2236 xmlInitMemory();
2237 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
2238 gcry_check_version(GCRYPT_VERSION);
2239 #ifdef WITH_GNUTLS
2240 gnutls_global_set_mem_functions(xmalloc, xmalloc, gcry_SecureCheck,
2241 xrealloc, xfree);
2242 gnutls_global_init();
2243 gnutls_global_set_log_function(tls_log);
2244 gnutls_global_set_log_level(1);
2245 assuan_set_io_hooks(&io_hooks);
2246 #endif
2247 xmlInitGlobals();
2248 xmlInitParser();
2249 xmlXPathInit();
2250 g_snprintf(buf, sizeof(buf), "%s/.pwmd", pw->pw_dir);
2252 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2253 err(EXIT_FAILURE, "%s", buf);
2255 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", pw->pw_dir);
2257 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2258 err(EXIT_FAILURE, "%s", buf);
2260 rcfile = g_strdup_printf("%s/.pwmd/config", pw->pw_dir);
2261 cmdline = TRUE;
2262 #ifdef WITH_GNUTLS
2263 tcpSockFd = -1;
2264 #endif
2266 while ((opt = getopt(argc, argv, "Po:C:nI:i:k:hvf:D")) != EOF) {
2267 switch (opt) {
2268 #ifdef WITH_PINENTRY
2269 case 'P':
2270 disable_pinentry = TRUE;
2271 break;
2272 #endif
2273 case 'o':
2274 outfile = optarg;
2275 break;
2276 case 'C':
2277 convert = optarg;
2278 break;
2279 case 'n':
2280 background = 0;
2281 break;
2282 case 'D':
2283 secure = TRUE;
2284 break;
2285 case 'I':
2286 import = optarg;
2287 break;
2288 case 'i':
2289 cmd_iterations = strtol(optarg, NULL, 10);
2290 break;
2291 case 'k':
2292 keyfile = optarg;
2293 break;
2294 case 'f':
2295 g_free(rcfile);
2296 rcfile = g_strdup(optarg);
2297 rcfile_spec = TRUE;
2298 break;
2299 case 'v':
2300 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,
2301 PACKAGE_BUGREPORT,
2302 #ifdef WITH_PINENTRY
2303 "+WITH_PINENTRY\n"
2304 #else
2305 "-WITH_PINENTRY\n"
2306 #endif
2307 #ifdef WITH_QUALITY
2308 "+WITH_QUALITY\n"
2309 #else
2310 "-WITH_QUALITY\n"
2311 #endif
2312 #ifdef WITH_GNUTLS
2313 "+WITH_GNUTLS\n"
2314 #else
2315 "-WITH_GNUTLS\n"
2316 #endif
2317 #ifdef DEBUG
2318 "+DEBUG\n"
2319 #else
2320 "-DEBUG\n"
2321 #endif
2322 #ifdef MEM_DEBUG
2323 "+MEM_DEBUG\n"
2324 #else
2325 "-MEM_DEBUG\n"
2326 #endif
2328 exit(EXIT_SUCCESS);
2329 case 'h':
2330 default:
2331 usage(argv[0]);
2335 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
2336 exit(EXIT_FAILURE);
2338 #ifdef WITH_PINENTRY
2339 if (disable_pinentry == TRUE)
2340 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
2341 #endif
2343 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
2344 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
2346 if (log_syslog == TRUE)
2347 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
2349 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
2350 iter = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
2351 errno = 0;
2353 if (setpriority(PRIO_PROCESS, 0, iter) == -1) {
2354 log_write("setpriority(): %s", strerror(errno));
2355 goto do_exit;
2359 #ifdef HAVE_MLOCKALL
2360 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
2361 log_write("mlockall(): %s", strerror(errno));
2362 goto do_exit;
2364 #endif
2366 setup_gcrypt();
2368 if (convert) {
2369 if (!outfile)
2370 usage(argv[0]);
2372 opt = convert_file(convert, keyfile, outfile);
2373 g_key_file_free(keyfileh);
2374 g_free(rcfile);
2375 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
2378 if (import) {
2379 if (!outfile)
2380 usage(argv[0]);
2382 if (cmd_iterations == -1)
2383 cmd_iterations = (guint64)get_key_file_integer("global", "iterations");
2385 opt = xml_import(import, outfile, keyfile, cmd_iterations);
2386 g_key_file_free(keyfileh);
2387 g_free(rcfile);
2388 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
2391 g_key_file_set_list_separator(keyfileh, ',');
2393 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
2394 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
2396 if (*p == '~') {
2397 p++;
2398 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
2399 g_free(p);
2400 socketarg = g_strdup(buf);
2402 else
2403 socketarg = p;
2405 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
2406 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
2408 datadir = expand_homedir(p);
2409 g_free(p);
2411 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
2412 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
2413 disable_list_and_dump = n;
2415 else
2416 disable_list_and_dump = secure;
2418 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
2419 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
2420 else
2421 default_timeout = -1;
2423 setup_logging(keyfileh);
2425 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2426 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2428 if (argc != optind) {
2429 if (cache_push)
2430 ptotal = g_strv_length(cache_push);
2432 for (; optind < argc; optind++) {
2433 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2434 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
2438 if (strchr(socketarg, '/') == NULL) {
2439 socketdir = g_get_current_dir();
2440 socketname = g_strdup(socketarg);
2441 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2443 else {
2444 socketname = g_strdup(strrchr(socketarg, '/'));
2445 socketname++;
2446 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2447 socketdir = g_strdup(socketarg);
2448 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2451 if (chdir(datadir)) {
2452 log_write("%s: %s", datadir, strerror(errno));
2453 unlink(socketpath);
2454 goto do_exit;
2457 if (parse_rcfile_keys() == FALSE)
2458 goto do_exit;
2460 clear_rcfile_keys();
2463 * Set the cache entry for a file. Prompts for the password.
2465 if (cache_push) {
2466 for (opt = 0; cache_push[opt]; opt++)
2467 do_cache_push(cache_push[opt], NULL);
2469 g_strfreev(cache_push);
2470 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2474 * bind() doesn't like the full pathname of the socket or any non alphanum
2475 * characters so change to the directory where the socket is wanted then
2476 * create it then change to datadir.
2478 if (chdir(socketdir)) {
2479 log_write("%s: %s", socketdir, strerror(errno));
2480 goto do_exit;
2483 g_free(socketdir);
2485 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2486 log_write("socket(): %s", strerror(errno));
2487 goto do_exit;
2490 addr.sun_family = AF_UNIX;
2491 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2493 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2494 log_write("bind(): %s", strerror(errno));
2496 if (errno == EADDRINUSE)
2497 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2498 "stale socket. Please remove it manually."), socketpath);
2500 do_unlink = 0;
2501 goto do_exit;
2504 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2505 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2506 mode_t mode = strtol(t, NULL, 8);
2507 mode_t mask = umask(0);
2509 g_free(t);
2511 if (chmod(socketname, mode) == -1) {
2512 log_write("%s: %s", socketname, strerror(errno));
2513 close(sockfd);
2514 unlink(socketpath);
2515 umask(mask);
2516 goto do_exit;
2519 umask(mask);
2522 g_free(--socketname);
2524 if (chdir(datadir)) {
2525 log_write("%s: %s", datadir, strerror(errno));
2526 close(sockfd);
2527 unlink(socketpath);
2528 goto do_exit;
2531 g_free(datadir);
2532 pthread_mutexattr_init(&mattr);
2533 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
2534 pthread_mutex_init(&cache_mutex, &mattr);
2535 pthread_mutexattr_destroy(&mattr);
2536 pthread_mutex_init(&keepalive_cond_mutex, NULL);
2537 pthread_cond_init(&keepalive_cond, NULL);
2538 #ifdef WITH_PINENTRY
2539 pthread_mutex_init(&pin_mutex, NULL);
2540 #endif
2542 if (listen(sockfd, 0) == -1) {
2543 log_write("listen(): %s", strerror(errno));
2544 goto do_exit;
2547 cmdline = FALSE;
2549 #ifdef WITH_GNUTLS
2550 if (startStopTcp(FALSE) == FALSE)
2551 goto do_exit;
2552 #endif
2554 if (background) {
2555 switch (fork()) {
2556 case -1:
2557 log_write("fork(): %s", strerror(errno));
2558 goto do_exit;
2559 case 0:
2560 close(0);
2561 close(1);
2562 close(2);
2563 setsid();
2564 break;
2565 default:
2566 exit(EXIT_SUCCESS);
2570 server_loop(sockfd, &socketpath);
2571 estatus = EXIT_SUCCESS;
2573 do_exit:
2574 if (socketpath && do_unlink) {
2575 unlink(socketpath);
2576 g_free(socketpath);
2579 #ifdef WITH_GNUTLS
2580 startStopTcp(TRUE);
2581 gnutls_global_deinit();
2582 #endif
2584 g_key_file_free(keyfileh);
2585 g_free(rcfile);
2586 xmlCleanupParser();
2587 xmlCleanupGlobals();
2589 if (estatus == EXIT_SUCCESS)
2590 log_write(N_("pwmd exiting normally"));
2592 #if defined(DEBUG) && !defined(MEM_DEBUG)
2593 // xdump();
2594 #endif
2595 #ifndef MEM_DEBUG
2596 xmem_deinit();
2597 #endif
2598 exit(estatus);