Remove the exiting client from the client list as soon as possible so
[pwmd.git] / src / pwmd.c
blobc6675fd67beaa743f60513fbb590a45b56b1e4c7
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(&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(&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 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
186 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
188 if (cn->tid == tid)
189 return cn;
192 return NULL;
195 void log_write(const gchar *fmt, ...)
197 gchar *args, *line;
198 va_list ap;
199 struct tm *tm;
200 time_t now;
201 gchar tbuf[21];
202 gint fd = -1;
203 struct client_thread_s *cn;
204 gchar *name = "";
205 gchar buf[255];
207 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
208 return;
210 if (!cmdline && logfile) {
211 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
212 warn("%s", logfile);
213 return;
217 va_start(ap, fmt);
219 if (g_vasprintf(&args, fmt, ap) == -1) {
220 if (logfile)
221 close(fd);
223 va_end(ap);
224 return;
227 va_end(ap);
229 if (cmdline) {
230 fprintf(stderr, "%s\n", args);
231 fflush(stderr);
232 g_free(args);
233 return;
236 pthread_mutex_lock(&cn_mutex);
237 cn = find_cn(pthread_self());
239 if (cn) {
240 if (!cn->name)
241 name = print_fmt(buf, sizeof(buf), "%i: ", cn->fd);
242 else
243 name = print_fmt(buf, sizeof(buf), "%s(%i): ", cn->name, cn->fd);
246 pthread_mutex_unlock(&cn_mutex);
248 if (!cmdline && log_syslog == TRUE)
249 syslog(LOG_INFO, "%s%s", name, args);
251 time(&now);
252 tm = localtime(&now);
253 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
254 tbuf[sizeof(tbuf) - 1] = 0;
256 if (args[strlen(args)-1] == '\n')
257 args[strlen(args)-1] = 0;
259 line = g_strdup_printf("%s %i %s%s\n", tbuf, getpid(), name, args);
260 g_free(args);
262 if (!line) {
263 if (logfile)
264 close(fd);
266 return;
269 if (logfile) {
270 write(fd, line, strlen(line));
271 fsync(fd);
272 close(fd);
275 if (isatty(STDERR_FILENO)) {
276 fprintf(stderr, "%s", line);
277 fflush(stderr);
280 g_free(line);
283 static void usage(gchar *pn)
285 g_fprintf(stderr, N_(
286 "Usage: %s [-hvDnP] [-f <rcfile>] [-C <filename>] "
287 "[-I <filename> [-i <iter>]]\n "
288 "[-k <keyfile>] [-o <outfile>] [file1] [...]\n"
289 " -n run as a foreground process\n"
290 " -f load the specified rcfile (~/.pwmd/config)\n"
291 " -C convert a version 1 data file to version 2\n"
292 " -I import an XML file\n"
293 " -i encrypt with the specified number of iterations when importing\n"
294 " (config default in the \"global\" section)\n"
295 " -k obtain the key from the specified file\n"
296 " -o output file for use with the -C and -I options\n"
297 " -D disable use of the LIST and DUMP commands\n"
298 " -P disable pinentry\n"
299 " -v version\n"
300 " -h this help text\n"
301 ), pn);
302 exit(EXIT_FAILURE);
305 static int gcry_SecureCheck(const void *ptr)
307 return 1;
310 static void setup_gcrypt()
312 gcry_check_version(NULL);
314 gcry_set_allocation_handler(xmalloc, xmalloc, gcry_SecureCheck, xrealloc,
315 xfree);
317 if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, NULL,
318 NULL) != 0)
319 errx(EXIT_FAILURE, N_("Required AES cipher not supported by libgcrypt."));
321 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_KEYLEN, NULL, &gcrykeysize);
322 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_BLKLEN, NULL, &gcryblocksize);
325 static gint new_connection(struct client_s *cl)
327 gpg_error_t rc;
328 gchar ver[ASSUAN_LINELENGTH];
330 rc = assuan_init_socket_server_ext(&cl->ctx, cl->thd->fd, 2);
332 if (rc)
333 goto fail;
335 assuan_set_pointer(cl->ctx, cl);
336 g_snprintf(ver, sizeof(ver), "%s", PACKAGE_STRING);
337 assuan_set_hello_line(cl->ctx, ver);
338 rc = register_commands(cl->ctx);
340 if (rc)
341 goto fail;
343 rc = assuan_accept(cl->ctx);
345 if (rc)
346 goto fail;
348 return 0;
350 fail:
351 log_write("%s", gpg_strerror(rc));
352 close(cl->thd->fd);
353 cl->thd->fd = -1;
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 cn->quit = TRUE;
536 log_write(N_("exiting, fd=%i"), cn->fd);
538 if (cl->thd && (cl->thd->msg_fd[0] || cl->thd->msg_fd[1])) {
539 pthread_cancel(cn->msg_tid);
540 pthread_cancel(cn->msg_sender_tid);
541 pthread_join(cn->msg_sender_tid, NULL);
542 pthread_cond_destroy(&cn->msg_cond);
543 close(cl->thd->msg_fd[0]);
544 close(cl->thd->msg_fd[1]);
547 pthread_join(cn->tid, NULL);
548 MUTEX_LOCK(&cn_mutex);
549 cn_thread_list = g_slist_remove(cn_thread_list, cn);
550 MUTEX_UNLOCK(&cn_mutex);
552 if (pthread_mutex_trylock(&cn->msg_sender_mutex) == EBUSY) {
553 MUTEX_UNLOCK(&cn->msg_sender_mutex);
555 else
556 pthread_mutex_unlock(&cn->msg_sender_mutex);
558 pthread_mutex_destroy(&cn->msg_sender_mutex);
559 pthread_cond_destroy(&cn->msg_sender_cond);
561 for (;;) {
562 struct status_msg_s *m = g_slist_nth_data(cn->msg_queue, 0);
564 if (!m)
565 break;
567 cn->msg_queue = g_slist_remove(cn->msg_queue, m);
568 g_free(m);
571 if (cl && cl->freed == FALSE)
572 cleanup_client(cl);
574 #ifdef WITH_GNUTLS
575 if (cn->tls) {
576 gnutls_deinit(cn->tls->ses);
578 if (cn->tls->fp)
579 g_free(cn->tls->fp);
581 g_free(cn->tls);
583 #endif
585 if (cl && cl->ctx)
586 assuan_deinit_server(cl->ctx);
587 else if (cl && cl->thd && cl->thd->fd != -1)
588 close(cl->thd->fd);
590 #ifdef WITH_PINENTRY
591 if (cl && cl->pinentry)
592 cleanup_pinentry(cl->pinentry);
593 #endif
595 if (cl->crypto)
596 cleanup_crypto(&cl->crypto);
598 g_free(cl);
600 if (cn->name)
601 g_free(cn->name);
603 g_free(cn);
604 send_status_all(STATUS_CLIENTS);
607 /* The msg_sender_mutex should have been locked before calling this thread
608 * entry point. */
609 static void *client_msg_sender_thread(void *arg)
611 struct client_thread_s *thd = arg;
613 for (;;) {
614 struct status_msg_s *msg;
615 gpg_error_t rc;
617 pthread_cond_wait(&thd->msg_sender_cond, &thd->msg_sender_mutex);
618 pthread_testcancel();
620 /* The messages may have been stacked while waiting for send_status()
621 * to return. Send what's in the queue. */
622 for (;;) {
623 msg = g_slist_nth_data(thd->msg_queue, 0);
625 if (!msg)
626 break;
628 /* Unlock to prevent blocking in client_msg_thread(). */
629 MUTEX_UNLOCK(&thd->msg_sender_mutex);
630 rc = send_status(thd->cl->ctx, msg->msg, NULL);
631 MUTEX_LOCK(&thd->msg_sender_mutex);
632 thd->msg_queue = g_slist_remove(thd->msg_queue, msg);
633 g_free(msg);
634 pthread_testcancel();
636 if (rc) {
637 log_write(N_("msg for %i failed: %s"), thd->fd,
638 pwmd_strerror(rc));
639 pthread_cancel(thd->tid);
640 break;
645 return NULL;
649 * This function waits for a signal from send_status_all() then appends a
650 * message read from a pipe to the clients message queue. The actual sending
651 * of the message is done in client_msg_sender_thread() which waits for a
652 * signal from this function. This prevents blocking in assuan_send_status()
653 * when sending to remote clients. This also avoids duplicate status messages.
654 * If an existing status message in the message queue has the same type as the
655 * current message the the current one will be skipped. This avoids flooding
656 * the client with old status messages.
658 static void *client_msg_thread(void *arg)
660 struct client_thread_s *thd = arg;
661 pthread_mutex_t mu;
663 pthread_mutex_init(&mu, NULL);
664 pthread_mutex_lock(&mu);
666 for (;;) {
667 fd_set rfds;
668 int n;
669 status_msg_t m;
670 size_t len;
671 struct status_msg_s *msg;
673 pthread_cleanup_push(pthread_mutex_destroy, &mu);
674 pthread_cleanup_push(pthread_mutex_unlock, &mu);
675 pthread_cond_wait(&thd->msg_cond, &mu);
676 pthread_testcancel();
677 FD_ZERO(&rfds);
678 FD_SET(thd->msg_fd[0], &rfds);
679 n = select(thd->msg_fd[0]+1, &rfds, NULL, NULL, NULL);
680 pthread_testcancel();
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);
715 pthread_cleanup_pop(0);
716 pthread_cleanup_pop(0);
719 return NULL;
723 * Called every time a connection is made from init_new_connection(). This is
724 * the thread entry point.
726 static void *client_thread(void *data)
728 struct client_thread_s *thd = data;
729 struct client_s *cl = g_malloc0(sizeof(struct client_s));
730 gpg_error_t rc;
731 pthread_attr_t attr;
734 * Prevent a race condition with init_new_connection() if this thread
735 * fails (returns) for some reason before init_new_connection() releases
736 * the cn_mutex.
738 MUTEX_LOCK(&cn_mutex);
739 MUTEX_UNLOCK(&cn_mutex);
740 pthread_cleanup_push(cleanup_cb, thd);
742 if (!cl) {
743 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
744 goto fail;
747 thd->cl = cl;
749 #ifdef WITH_GNUTLS
751 * Do the TLS handshake before anything else.
753 if (thd->remote) {
754 gchar *prio = get_key_file_string("global", "cipher_suite");
756 thd->tls = tls_init(thd->fd, prio);
757 g_free(prio);
759 if (!thd->tls) {
760 close(thd->fd);
761 thd->fd = -1;
762 goto fail;
765 pthread_testcancel();
767 #endif
769 cl->thd = thd;
771 if (new_connection(cl))
772 goto fail;
774 #ifdef WITH_PINENTRY
775 cl->pinentry = pinentry_init();
777 if (!cl->pinentry) {
778 g_free(cl);
779 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
780 goto fail;
783 #ifdef WITH_GNUTLS
784 /* Require the client to explicity set OPTION PINENTRY since the DISPLAY
785 * might be automatically set from the client. Connections to the X11
786 * server usually aren't encrypted and the client might unintentionally
787 * send the passphrase in the clear.
789 if (thd->remote)
790 cl->pinentry->enable = FALSE;
791 #endif
792 #endif
794 #ifdef HAVE_MLOCKALL
795 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
796 log_write("mlockall(): %s", strerror(errno));
797 goto fail;
799 #endif
801 if (pipe(thd->msg_fd) == -1) {
802 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
803 goto fail;
806 pthread_attr_init(&attr);
807 pthread_cond_init(&thd->msg_sender_cond, NULL);
808 pthread_mutex_init(&thd->msg_sender_mutex, NULL);
809 MUTEX_LOCK(&thd->msg_sender_mutex);
810 pthread_create(&thd->msg_sender_tid, &attr, client_msg_sender_thread, thd);
811 pthread_attr_destroy(&attr);
813 pthread_cond_init(&thd->msg_cond, NULL);
814 pthread_attr_init(&attr);
815 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
816 pthread_create(&thd->msg_tid, &attr, client_msg_thread, thd);
817 pthread_attr_destroy(&attr);
819 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
821 if (rc) {
822 log_write("%s", gpg_strerror(rc));
823 goto fail;
826 send_status_all(STATUS_CLIENTS);
827 xmlSetStructuredErrorFunc(cl, xml_error_cb);
829 for (;;) {
830 fd_set rfds;
831 int n;
833 FD_ZERO(&rfds);
834 FD_SET(cl->thd->fd, &rfds);
836 #ifdef WITH_PINENTRY
837 if (cl->pinentry->status == PINENTRY_RUNNING)
838 FD_SET(cl->pinentry->fd, &rfds);
840 n = cl->thd->fd > cl->pinentry->fd ? cl->thd->fd : cl->pinentry->fd;
841 #else
842 n = cl->thd->fd;
843 #endif
844 n = select(n+1, &rfds, NULL, NULL, NULL);
845 pthread_testcancel();
847 if (n <= 0)
848 continue;
850 if (FD_ISSET(cl->thd->fd, &rfds)) {
851 rc = assuan_process_next(cl->ctx);
852 pthread_testcancel();
854 if (rc) {
855 cl->inquire_status = INQUIRE_INIT;
857 if (gpg_err_code(rc) == GPG_ERR_EOF)
858 goto done;
860 log_write("assuan_process_next(): %s", gpg_strerror(rc));
861 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
863 if (rc) {
864 log_write("assuan_process_done(): %s", gpg_strerror(rc));
865 goto done;
868 else {
869 #ifdef WITH_PINENTRY
870 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
871 cl->pinentry->status = PINENTRY_RUNNING;
872 #endif
874 switch (cl->inquire_status) {
875 case INQUIRE_BUSY:
876 case INQUIRE_INIT:
877 break;
878 case INQUIRE_DONE:
879 cl->inquire_status = INQUIRE_INIT;
880 pthread_testcancel();
881 rc = assuan_process_done(cl->ctx, 0);
882 break;
887 #ifdef WITH_PINENTRY
888 pinentry_iterate(cl,
889 cl->pinentry->fd != -1 && FD_ISSET(cl->pinentry->fd, &rfds));
890 #endif
894 * Client cleanup (including XML data) is done in cleanup_cb() from
895 * the cleanup thread.
897 done:
898 fail:
899 if (1) {} // Fixes compile time error with pthread_cleanup_push().
900 pthread_cleanup_pop(1);
901 pthread_exit(PTHREAD_CANCELED);
902 return NULL;
905 static void setup_logging(GKeyFile *kf)
907 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
909 if (n == TRUE) {
910 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
912 if (*p == '~') {
913 gchar buf[PATH_MAX];
915 p++;
916 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
917 g_free(p);
919 if (logfile)
920 g_free(logfile);
922 logfile = g_strdup(buf);
924 else {
925 if (logfile)
926 g_free(logfile);
928 logfile = p;
932 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
936 * Make sure all settings are set to either the specified setting or a
937 * default.
939 static void set_rcfile_defaults(GKeyFile *kf)
941 gchar buf[PATH_MAX];
943 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
944 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
945 g_key_file_set_string(kf, "global", "socket_path", buf);
948 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
949 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
950 g_key_file_set_string(kf, "global", "data_directory", buf);
953 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
954 g_key_file_set_boolean(kf, "global", "backup", TRUE);
956 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
957 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
958 g_key_file_set_string(kf, "global", "log_path", buf);
961 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
962 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
964 #ifdef HAVE_MLOCKALL
965 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
966 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
967 #endif
969 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
970 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
972 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
973 g_key_file_get_integer(kf, "global", "iterations", 0) < 0)
974 g_key_file_set_integer(kf, "global", "iterations", 1);
976 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
977 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
979 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
980 g_key_file_set_integer(kf, "global", "iteration_progress", 0);
982 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
983 g_key_file_set_integer(kf, "global", "compression_level", 6);
985 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
986 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
988 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
989 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
991 zlib_bufsize = (uInt)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
993 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
994 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
996 #ifdef HAVE_MLOCKALL
997 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
998 #endif
1000 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
1001 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
1003 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
1004 g_key_file_set_integer(kf, "global", "keepalive", 30);
1006 #ifdef WITH_PINENTRY
1007 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
1008 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
1010 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
1011 g_key_file_set_integer(kf, "global", "pinentry_timeout", 20);
1012 #endif
1014 #ifdef WITH_GNUTLS
1015 if (g_key_file_has_key(kf, "global", "tcp_port", NULL) == FALSE)
1016 g_key_file_set_integer(kf, "global", "tcp_port", 6466);
1018 if (g_key_file_has_key(kf, "global", "enable_tcp", NULL) == FALSE)
1019 g_key_file_set_boolean(kf, "global", "enable_tcp", FALSE);
1021 if (g_key_file_has_key(kf, "global", "tcp_require_key", NULL) == FALSE)
1022 g_key_file_set_boolean(kf, "global", "tcp_require_key", FALSE);
1024 if (g_key_file_has_key(kf, "global", "tcp_wait", NULL) == FALSE)
1025 g_key_file_set_boolean(kf, "global", "tcp_wait", 3);
1027 if (g_key_file_has_key(kf, "global", "cipher_suite", NULL) == FALSE)
1028 g_key_file_set_string(kf, "global", "cipher_suite", "SECURE256");
1030 if (g_key_file_has_key(kf, "global", "tcp_use_crl", NULL) == FALSE)
1031 g_key_file_set_boolean(kf, "global", "tcp_use_crl", FALSE);
1032 #endif
1034 setup_logging(kf);
1037 static GKeyFile *parse_rcfile(gboolean specified)
1039 GKeyFile *kf = g_key_file_new();
1040 GError *rc = NULL;
1042 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
1043 log_write("%s: %s", rcfile, rc->message);
1045 if (cmdline && specified) {
1046 g_clear_error(&rc);
1047 return NULL;
1050 if (rc->code == G_FILE_ERROR_NOENT) {
1051 g_clear_error(&rc);
1052 set_rcfile_defaults(kf);
1053 return kf;
1056 g_clear_error(&rc);
1057 return NULL;
1060 set_rcfile_defaults(kf);
1061 return kf;
1064 static gchar *do_get_password(const gchar *prompt)
1066 gchar buf[LINE_MAX] = {0}, *p;
1067 struct termios told, tnew;
1068 gchar *key;
1070 if (tcgetattr(STDIN_FILENO, &told) == -1) {
1071 log_write("tcgetattr(): %s", strerror(errno));
1072 return NULL;
1075 memcpy(&tnew, &told, sizeof(struct termios));
1076 tnew.c_lflag &= ~(ECHO);
1077 tnew.c_lflag |= ICANON|ECHONL;
1079 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
1080 log_write("tcsetattr(): %s", strerror(errno));
1081 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1082 return NULL;
1085 fprintf(stderr, "%s", prompt);
1087 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
1088 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1089 return NULL;
1092 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1093 p[strlen(p) - 1] = 0;
1095 if (!buf[0]) {
1096 key = gcry_malloc(1);
1097 key[0] = 0;
1099 else {
1100 key = gcry_malloc(strlen(p) + 1);
1101 sprintf(key, "%s", p);
1104 memset(&buf, 0, sizeof(buf));
1105 return key;
1108 /* Only used when "enable_pinentry" is "false" or -P. */
1109 static gpg_error_t get_input(const gchar *filename,
1110 struct client_crypto_s *crypto, guchar *key, pinentry_cmd_t which)
1112 gchar *prompt;
1114 if (which == PINENTRY_SAVE) {
1115 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
1116 crypto->tkey = do_get_password(prompt);
1117 g_free(prompt);
1119 if (!crypto->tkey) {
1120 log_write(N_("%s: Skipping file"), filename);
1121 return GPG_ERR_BAD_PASSPHRASE;
1124 prompt = g_strdup_printf(N_("Repeat passphrase: "));
1125 crypto->tkey2 = do_get_password(prompt);
1126 g_free(prompt);
1128 if (!crypto->tkey2) {
1129 log_write(N_("%s: Skipping file"), filename);
1130 return GPG_ERR_BAD_PASSPHRASE;
1133 if (strcmp(crypto->tkey, crypto->tkey2)) {
1134 log_write(N_("%s: Passphrase mismatch"), filename);
1135 return EPWMD_BADKEY;
1138 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
1139 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1140 return 0;
1143 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
1145 if ((crypto->tkey = do_get_password(prompt)) == NULL) {
1146 log_write(N_("%s: Skipping file"), filename);
1147 g_free(prompt);
1148 return GPG_ERR_BAD_PASSPHRASE;
1151 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
1152 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1153 g_free(prompt);
1154 return 0;
1158 * inbuf must have been allocated with gcry_malloc().
1160 gpg_error_t export_common(const gchar *filename, struct client_crypto_s *crypto,
1161 gpointer inbuf, gulong insize)
1163 gpg_error_t rc;
1164 gint level, zrc;
1165 gulong outsize;
1166 gpointer outbuf;
1168 level = get_key_file_integer(filename, "compression_level");
1170 if (level < 0)
1171 level = 0;
1173 if (do_compress(NULL, level, inbuf, insize, &outbuf, &outsize, &zrc)
1174 == FALSE) {
1175 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
1178 crypto->inbuf = outbuf;
1179 crypto->insize = outsize;
1180 rc = do_xml_encrypt(NULL, crypto, filename);
1181 return rc;
1184 static gpg_error_t get_password(const gchar *filename,
1185 struct client_crypto_s *crypto, guchar *md5file, guchar *key,
1186 pinentry_cmd_t which)
1188 #ifdef WITH_PINENTRY
1189 gpg_error_t rc = 0;
1191 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
1192 == FALSE) {
1193 #endif
1194 return get_input(filename, crypto, key, which);
1195 #ifdef WITH_PINENTRY
1197 else {
1198 gchar *result = NULL;
1199 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
1201 set_pinentry_defaults(pin);
1202 pin->which = which;
1203 pin->filename = g_strdup(filename);
1204 rc = pinentry_getpin(pin, &result);
1206 if (rc) {
1207 xfree(result);
1208 goto done;
1211 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, strlen(result) ? strlen(result) : 1);
1212 xfree(result);
1213 cleanup_pinentry(pin);
1216 done:
1217 return rc;
1218 #endif
1221 static gboolean _getline(const gchar *file, gchar **result, gpg_error_t *rc)
1223 FILE *fp;
1224 gchar buf[LINE_MAX] = {0}, *p;
1225 gchar *str = NULL;
1226 gint len;
1228 *rc = 0;
1230 if ((fp = fopen(file, "r")) == NULL) {
1231 *rc = gpg_error_from_syserror();
1232 return FALSE;
1235 p = fgets(buf, sizeof(buf), fp);
1236 fclose(fp);
1237 len = strlen(buf);
1239 if (len && buf[len - 1] == '\n')
1240 buf[--len] = 0;
1242 str = gcry_malloc(len + 1);
1244 if (!str) {
1245 *rc = gpg_error_from_errno(ENOMEM);
1246 return FALSE;
1249 memcpy(str, buf, len ? len : 1);
1250 str[len] = 0;
1251 memset(&buf, 0, sizeof(buf));
1252 *result = str;
1253 return TRUE;
1256 static gchar *parse_rcfile_keyfile(const gchar *filename, gboolean import,
1257 gpg_error_t *rc)
1259 GError *rv = NULL;
1260 gchar *t, *file = NULL, *str;
1262 *rc = GPG_ERR_UNKNOWN_ERRNO;
1264 if (import == FALSE) {
1265 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
1266 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
1268 if (!file) {
1269 if (rv) {
1270 log_write("%s: key_file: %s", rcfile, rv->message);
1271 g_clear_error(&rv);
1274 return NULL;
1277 t = expand_homedir(file);
1279 if (!t) {
1280 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1281 *rc = gpg_error_from_errno(ENOMEM);
1282 return NULL;
1285 g_free(file);
1286 file = t;
1289 else {
1290 /* -I or -C. The filename is a key file. */
1291 file = g_strdup(filename);
1293 if (!file) {
1294 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1295 *rc = gpg_error_from_errno(ENOMEM);
1296 return NULL;
1300 if (rv) {
1301 log_write("%s: key_file: %s", rcfile, rv->message);
1302 g_clear_error(&rv);
1303 return NULL;
1306 if (!file)
1307 return NULL;
1309 if (_getline(file, &str, rc) == FALSE) {
1310 log_write("%s: %s: %s", filename, file, pwmd_strerror(*rc));
1311 g_free(file);
1312 return NULL;
1315 g_free(file);
1316 *rc = 0;
1317 return str;
1320 static gboolean xml_import(const gchar *filename, const gchar *outfile,
1321 const gchar *keyfile, guint64 iter)
1323 xmlDocPtr doc;
1324 gint fd;
1325 struct stat st;
1326 gint len;
1327 xmlChar *xmlbuf;
1328 xmlChar *xml;
1329 gpg_error_t rc;
1330 struct client_crypto_s *crypto;
1332 if (stat(filename, &st) == -1) {
1333 log_write("%s: %s", filename, strerror(errno));
1334 return FALSE;
1337 crypto = init_client_crypto();
1339 if (!crypto)
1340 return FALSE;
1342 crypto->key = gcry_malloc(gcrykeysize);
1343 memset(crypto->key, 0, gcrykeysize);
1345 if (!crypto->key) {
1346 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1347 goto fail;
1350 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
1351 filename, outfile);
1353 if (iter && keyfile) {
1354 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1356 if (!crypto->tkey)
1357 goto fail;
1359 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1360 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1362 else if (iter) {
1363 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
1365 if (rc)
1366 goto fail;
1369 if ((fd = open(filename, O_RDONLY)) == -1) {
1370 log_write("%s: %s", filename, strerror(errno));
1371 goto fail;
1374 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
1375 close(fd);
1376 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1377 goto fail;
1380 if (read(fd, xmlbuf, st.st_size) == -1) {
1381 rc = errno;
1382 close(fd);
1383 errno = rc;
1384 log_write("%s: %s", filename, strerror(errno));
1385 goto fail;
1388 close(fd);
1389 xmlbuf[st.st_size] = 0;
1392 * Make sure the document validates.
1394 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
1395 log_write("xmlReadDoc() failed");
1396 gcry_free(xmlbuf);
1397 goto fail;
1400 gcry_free(xmlbuf);
1401 xmlDocDumpMemory(doc, &xml, &len);
1402 xmlFreeDoc(doc);
1404 if (!iter)
1405 memset(crypto->key, '!', gcrykeysize);
1407 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
1409 if (!crypto->fh) {
1410 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1411 goto fail;
1414 crypto->fh->fh2.iter = iter;
1415 rc = export_common(outfile, crypto, xml, len);
1416 xmlFree(xml);
1418 if (rc) {
1419 send_error(NULL, rc);
1420 goto fail;
1423 cleanup_crypto(&crypto);
1424 return TRUE;
1426 fail:
1427 cleanup_crypto(&crypto);
1428 return FALSE;
1431 gchar *get_key_file_string(const gchar *section, const gchar *what)
1433 gchar *val = NULL;
1434 GError *grc = NULL;
1436 MUTEX_LOCK(&rcfile_mutex);
1438 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1439 val = g_key_file_get_string(keyfileh, section, what, &grc);
1441 if (grc) {
1442 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1443 g_clear_error(&grc);
1446 else {
1447 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1448 val = g_key_file_get_string(keyfileh, "global", what, &grc);
1450 if (grc) {
1451 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1452 g_clear_error(&grc);
1457 MUTEX_UNLOCK(&rcfile_mutex);
1458 return val;
1461 gint get_key_file_integer(const gchar *section, const gchar *what)
1463 gint val = -1;
1464 GError *grc = NULL;
1466 MUTEX_LOCK(&rcfile_mutex);
1468 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
1469 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
1471 if (grc) {
1472 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1473 g_clear_error(&grc);
1476 else {
1477 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1478 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
1480 if (grc) {
1481 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1482 g_clear_error(&grc);
1487 MUTEX_UNLOCK(&rcfile_mutex);
1488 return val;
1491 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
1493 gboolean val = FALSE;
1494 GError *grc = NULL;
1496 MUTEX_LOCK(&rcfile_mutex);
1498 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1499 val = g_key_file_get_boolean(keyfileh, section, what, &grc);
1501 if (grc) {
1502 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1503 g_clear_error(&grc);
1506 else {
1507 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1508 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
1510 if (grc) {
1511 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1512 g_clear_error(&grc);
1517 MUTEX_UNLOCK(&rcfile_mutex);
1518 return val;
1521 static gboolean parse_rcfile_keys()
1523 gsize n;
1524 gchar **groups;
1525 gchar **p;
1526 gchar *str;
1528 groups = g_key_file_get_groups(keyfileh, &n);
1530 for (p = groups; *p; p++) {
1531 GError *rc = NULL;
1533 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE) {
1534 str = g_key_file_get_string(keyfileh, *p, "key", &rc);
1536 if (!str) {
1537 if (rc) {
1538 log_write("%s: key: %s", rcfile, rc->message);
1539 g_clear_error(&rc);
1541 continue;
1544 do_cache_push(*p, str);
1545 g_free(str);
1546 continue;
1549 if (rc) {
1550 log_write("%s: key: %s", rcfile, rc->message);
1551 g_clear_error(&rc);
1552 continue;
1555 gpg_error_t ret;
1556 str = parse_rcfile_keyfile(*p, FALSE, &ret);
1558 if (!str)
1559 continue;
1561 do_cache_push(*p, str);
1562 gcry_free(str);
1565 g_strfreev(groups);
1566 return TRUE;
1569 static gboolean do_cache_push(const gchar *filename, const gchar *password)
1571 guchar md5file[16];
1572 gint timeout;
1573 const gchar *p = filename;
1574 struct client_crypto_s *crypto;
1575 gpg_error_t rc;
1577 while (isspace(*p))
1578 p++;
1580 if (!*p)
1581 return FALSE;
1583 if (valid_filename(p) == FALSE) {
1584 log_write(N_("%s: Invalid characters in filename"), p);
1585 return FALSE;
1588 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1590 if (access(p, R_OK|W_OK) != 0) {
1591 log_write("%s: %s", p, strerror(errno));
1592 return FALSE;
1595 crypto = init_client_crypto();
1597 if (!crypto)
1598 return FALSE;
1600 crypto->fh = read_file_header(filename, FALSE, &rc);
1602 if (!crypto->fh) {
1603 log_write("%s: %s", p, pwmd_strerror(rc));
1604 cleanup_crypto(&crypto);
1605 return FALSE;
1608 crypto->key = gcry_malloc(gcrykeysize);
1610 if (!crypto->key) {
1611 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1612 cleanup_crypto(&crypto);
1613 return FALSE;
1616 log_write(N_("Adding '%s' to the file cache ..."), filename);
1618 if (crypto->fh->fh2.iter <= 0) {
1619 memset(crypto->key, '!', gcrykeysize);
1620 goto try_decrypt;
1623 if (!password) {
1624 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1626 if (rc) {
1627 send_error(NULL, rc);
1628 cleanup_crypto(&crypto);
1629 return FALSE;
1632 gcry_free(crypto->fh->doc);
1633 crypto->fh->doc = NULL;
1635 else
1636 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password,
1637 strlen(password) ? strlen(password) : 1);
1639 try_decrypt:
1640 rc = try_xml_decrypt(NULL, crypto->key, crypto, NULL, NULL);
1642 if (rc) {
1643 log_write("%s: %s", filename, pwmd_strerror(rc));
1644 cleanup_crypto(&crypto);
1645 return FALSE;
1648 if (cache_update_key(md5file, crypto->key) == FALSE) {
1649 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1650 cleanup_crypto(&crypto);
1651 return FALSE;
1654 timeout = get_key_file_integer(p, "cache_timeout");
1655 cache_set_timeout(md5file, timeout);
1656 log_write(N_("File '%s' now cached"), filename);
1657 cleanup_crypto(&crypto);
1658 return TRUE;
1661 static void init_new_connection(gint fd, gchar *addr)
1663 pthread_t tid;
1664 pthread_attr_t attr;
1665 struct client_thread_s *new;
1666 int n;
1668 new = g_malloc0(sizeof(struct client_thread_s));
1670 if (!new) {
1671 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1672 close(fd);
1673 return;
1676 MUTEX_LOCK(&cn_mutex);
1677 new->fd = fd;
1679 #ifdef WITH_GNUTLS
1680 if (addr)
1681 new->remote = TRUE;
1682 #endif
1684 pthread_attr_init(&attr);
1685 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1686 n = pthread_create(&tid, &attr, client_thread, new);
1687 pthread_attr_destroy(&attr);
1689 if (n) {
1690 g_free(new);
1691 close(fd);
1692 log_write("pthread_create(): %s", strerror(n));
1693 MUTEX_UNLOCK(&cn_mutex);
1694 return;
1697 new->tid = tid;
1698 cn_thread_list = g_slist_append(cn_thread_list, new);
1699 MUTEX_UNLOCK(&cn_mutex);
1701 if (addr)
1702 log_write(N_("new connection: fd=%i, addr=%s"), fd, addr);
1703 else
1704 log_write(N_("new connection: fd=%i"), fd);
1707 #ifdef WITH_GNUTLS
1708 /* From Beej's Guide to Network Programming. It's a good tutorial. */
1709 static void *get_in_addr(struct sockaddr *sa)
1711 if (sa->sa_family == AF_INET)
1712 return &(((struct sockaddr_in*)sa)->sin_addr);
1714 return &(((struct sockaddr_in6*)sa)->sin6_addr);
1717 static void *tcp_accept_thread(void *arg)
1719 gint sockfd = (gint)arg;
1721 for (;;) {
1722 struct sockaddr_storage raddr;
1723 socklen_t slen = sizeof(raddr);
1724 gint fd = -1;
1725 gulong n;
1726 gchar *t;
1728 fd = accept(sockfd, (struct sockaddr *)&raddr, &slen);
1729 pthread_testcancel();
1731 if (fd == -1) {
1732 if (errno != EAGAIN) {
1733 if (!quit) // probably EBADF
1734 log_write("accept(): %s", strerror(errno));
1736 break;
1739 continue;
1742 if (quit)
1743 break;
1745 if (fd >= 0) {
1746 gchar s[INET6_ADDRSTRLEN];
1748 inet_ntop(raddr.ss_family, get_in_addr((struct sockaddr *)&raddr),
1749 s, sizeof s);
1750 init_new_connection(fd, s);
1753 t = get_key_file_string("global", "tcp_wait");
1754 n = strtol(t, NULL, 10);
1755 g_free(t);
1757 if (n < 0)
1758 n = 0;
1760 usleep(n*100000);
1763 /* Just in case accept() failed for some reason other than EBADF */
1764 quit = 1;
1765 pthread_exit(PTHREAD_CANCELED);
1766 return NULL;
1768 #endif
1770 static void *accept_thread(void *arg)
1772 gint sockfd = (gint)arg;
1774 for (;;) {
1775 socklen_t slen = sizeof(struct sockaddr_un);
1776 struct sockaddr_un raddr;
1777 gint fd = -1;
1779 fd = accept(sockfd, (struct sockaddr *)&raddr, &slen);
1780 pthread_testcancel();
1782 if (fd == -1) {
1783 if (errno != EAGAIN) {
1784 if (!quit) // probably EBADF
1785 log_write("accept(): %s", strerror(errno));
1787 break;
1790 continue;
1793 if (fd >= 0)
1794 init_new_connection(fd, NULL);
1797 /* Just in case accept() failed for some reason other than EBADF */
1798 quit = 1;
1799 pthread_exit(PTHREAD_CANCELED);
1800 return NULL;
1803 static void *adjust_cache_timer_thread(void *arg)
1805 for (;;) {
1806 sleep(1);
1807 pthread_testcancel();
1808 CACHE_LOCK(NULL);
1809 cache_adjust_timer();
1810 CACHE_UNLOCK;
1813 return NULL;
1816 static void *keepalive_thread(void *arg)
1818 struct timespec ts;
1819 gint to = (gint)arg;
1821 for (;;) {
1822 clock_gettime(CLOCK_REALTIME, &ts);
1823 ts.tv_sec += to;
1824 pthread_cond_timedwait(&keepalive_cond, &keepalive_cond_mutex, &ts);
1825 pthread_testcancel();
1826 send_status_all(STATUS_KEEPALIVE);
1829 return NULL;
1832 static void startStopKeepAlive(gboolean term)
1834 pthread_attr_t attr;
1835 gint n = get_key_file_integer("global", "keepalive");
1837 if (keepalive_tid)
1838 pthread_cancel(keepalive_tid);
1840 keepalive_tid = 0;
1841 pthread_mutex_trylock(&keepalive_cond_mutex);
1843 if (term)
1844 return;
1846 if (n > 0) {
1847 pthread_attr_init(&attr);
1848 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1849 pthread_create(&keepalive_tid, &attr, keepalive_thread, (void *)n);
1850 pthread_attr_destroy(&attr);
1854 static void server_loop(gint sockfd, gchar **socketpath)
1856 pthread_t accept_tid;
1857 guint n;
1858 sigset_t sigset;
1859 gint n_clients = 0;
1860 pthread_attr_t attr;
1861 pthread_t cache_timeout_tid;
1862 pthread_mutexattr_t mattr;
1864 sigemptyset(&sigset);
1866 /* Termination */
1867 sigaddset(&sigset, SIGTERM);
1868 sigaddset(&sigset, SIGINT);
1870 /* Clears the file cache. */
1871 sigaddset(&sigset, SIGUSR1);
1873 /* Configuration file reloading. */
1874 sigaddset(&sigset, SIGHUP);
1876 /* Caught in client_thread(). Sends a cache status message. */
1877 sigaddset(&sigset, SIGUSR2);
1879 /* Ignored everywhere. When a client disconnects abnormally this signal
1880 * gets raised. It isn't needed though because client_thread() will check
1881 * for rcs even after the client disconnects. */
1882 signal(SIGPIPE, SIG_IGN);
1883 sigprocmask(SIG_BLOCK, &sigset, NULL);
1885 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1886 pthread_mutexattr_init(&mattr);
1887 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
1888 pthread_mutex_init(&cn_mutex, &mattr);
1889 pthread_mutexattr_destroy(&mattr);
1890 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1891 pthread_attr_init(&attr);
1892 pthread_create(&accept_tid, &attr, accept_thread, (void *)sockfd);
1893 startStopKeepAlive(FALSE);
1894 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1895 pthread_create(&cache_timeout_tid, &attr, adjust_cache_timer_thread, NULL);
1896 pthread_attr_destroy(&attr);
1898 do {
1899 gint sig;
1901 sigwait(&sigset, &sig);
1902 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1904 /* Caught a signal. */
1905 switch (sig) {
1906 case SIGHUP:
1907 reload_rcfile();
1908 break;
1909 case SIGABRT:
1910 CACHE_LOCK(NULL);
1911 cache_clear(NULL, 2);
1912 CACHE_UNLOCK;
1913 #ifndef MEM_DEBUG
1914 xpanic();
1915 #endif
1916 exit(EXIT_FAILURE);
1917 case SIGUSR1:
1918 CACHE_LOCK(NULL);
1919 log_write(N_("clearing file cache"));
1920 cache_clear(NULL, 2);
1921 CACHE_UNLOCK;
1922 break;
1923 default:
1924 quit = 1;
1925 break;
1927 } while (!quit);
1930 * We're out of the main server loop. This happens when a signal was sent
1931 * to terminate the daemon. We'll wait for all clients to disconnect
1932 * before exiting and ignore any following signals.
1934 shutdown(sockfd, SHUT_RDWR);
1935 close(sockfd);
1936 pthread_cancel(accept_tid);
1937 pthread_join(accept_tid, NULL);
1938 #ifdef WITH_GNUTLS
1939 startStopTcp(TRUE);
1940 #endif
1941 unlink(*socketpath);
1942 g_free(*socketpath);
1943 *socketpath = NULL;
1944 MUTEX_LOCK(&cn_mutex);
1945 n = g_slist_length(cn_thread_list);
1946 MUTEX_UNLOCK(&cn_mutex);
1948 if (n)
1949 log_write(N_("waiting for all clients to disconnect"));
1951 while (n) {
1952 if (n != n_clients) {
1953 log_write(N_("%i clients remain"), n);
1954 n_clients = n;
1957 sleep(1);
1958 MUTEX_LOCK(&cn_mutex);
1959 n = g_slist_length(cn_thread_list);
1960 MUTEX_UNLOCK(&cn_mutex);
1963 startStopKeepAlive(TRUE);
1964 pthread_cancel(cache_timeout_tid);
1965 cache_free();
1969 * Called from pinentry_fork() in the child process.
1971 void free_client_list()
1973 gint i, t = g_slist_length(cn_thread_list);
1975 for (i = 0; i < t; i++) {
1976 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1978 free_client(cn->cl);
1981 cache_free();
1984 struct client_crypto_s *init_client_crypto()
1986 struct client_crypto_s *new = g_malloc0(sizeof(struct client_crypto_s));
1987 gpg_error_t rc;
1989 if (!new) {
1990 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1991 return NULL;
1994 rc = gcry_cipher_open(&new->gh, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
1996 if (rc) {
1997 log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(rc));
1998 g_free(new);
1999 return NULL;
2002 return new;
2005 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
2006 const gchar *outfile)
2008 gpg_error_t rc;
2009 guchar md5file[16];
2010 guint64 iter;
2011 struct client_crypto_s *crypto = init_client_crypto();
2013 if (!crypto)
2014 return GPG_ERR_ENOMEM;
2016 crypto->key = gcry_malloc(gcrykeysize);
2018 if (!crypto->key) {
2019 cleanup_crypto(&crypto);
2020 return GPG_ERR_ENOMEM;
2023 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
2024 filename);
2025 crypto->fh = read_file_header(filename, TRUE, &rc);
2027 if (!crypto->fh)
2028 goto done;
2030 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
2032 /* The header in version 1 had a bug where the iterations were off-by-one.
2033 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
2034 * header.
2036 if (crypto->fh->fh1.iter >= 0) {
2037 if (keyfile) {
2038 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
2040 if (!crypto->tkey)
2041 goto done;
2043 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
2044 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
2046 else {
2047 rc = get_password(filename, crypto, md5file, crypto->key,
2048 PINENTRY_OPEN);
2050 if (rc)
2051 goto done;
2055 rc = try_xml_decrypt(NULL, crypto->key, crypto, &crypto->fh->doc,
2056 &crypto->fh->len);
2058 if (rc)
2059 goto done;
2061 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
2063 if (rc) {
2064 log_write("%s: %s", filename, pwmd_strerror(rc));
2065 goto done;
2068 crypto->fh->v1 = FALSE;
2069 iter = crypto->fh->fh1.iter;
2070 memset(&crypto->fh->fh2, 0, sizeof(crypto->fh->fh2));
2071 /* Keep the iterations and key from the original file. */
2072 crypto->fh->fh2.iter = iter+1; // Bugfix for v1 data files.
2073 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
2075 done:
2076 if (rc)
2077 send_error(NULL, rc);
2079 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
2080 cleanup_crypto(&crypto);
2081 return rc;
2084 #ifdef WITH_GNUTLS
2085 static gboolean startStopTcp(gboolean term)
2087 struct addrinfo hints, *servinfo, *p;
2088 gint port = get_key_file_integer("global", "tcp_port");
2089 char buf[7];
2090 int n;
2091 pthread_attr_t attr;
2093 if (term || get_key_file_boolean("global", "enable_tcp") == FALSE) {
2094 if (tcpSockFd != -1) {
2095 pthread_cancel(tcpAcceptTid);
2096 pthread_join(tcpAcceptTid, NULL);
2097 shutdown(tcpSockFd, SHUT_RDWR);
2098 close(tcpSockFd);
2099 tcpSockFd = -1;
2101 /* A client may still be connected. */
2102 if (!quit)
2103 deinitTlsParams();
2106 return TRUE;
2109 if (tcpSockFd != -1)
2110 return TRUE;
2112 memset(&hints, 0, sizeof(hints));
2113 hints.ai_family = AF_UNSPEC;
2114 hints.ai_socktype = SOCK_STREAM;
2115 hints.ai_flags = AI_PASSIVE;
2117 if ((n = getaddrinfo(NULL, print_fmt(buf, sizeof(buf), "%i", port),
2118 &hints, &servinfo)) == -1) {
2119 log_write("getaddrinfo(): %s", gai_strerror(n));
2120 return FALSE;
2123 for(p = servinfo; p != NULL; p = p->ai_next) {
2124 if ((tcpSockFd = socket(p->ai_family, p->ai_socktype,
2125 p->ai_protocol)) == -1) {
2126 log_write("socket(): %s", strerror(errno));
2127 continue;
2130 n = 1;
2132 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_REUSEADDR, &n,
2133 sizeof(int)) == -1) {
2134 log_write("setsockopt(): %s", strerror(errno));
2135 freeaddrinfo(servinfo);
2136 goto fail;
2139 if (bind(tcpSockFd, p->ai_addr, p->ai_addrlen) == -1) {
2140 close(tcpSockFd);
2141 log_write("bind(): %s", strerror(errno));
2142 continue;
2145 n++;
2146 break;
2149 freeaddrinfo(servinfo);
2151 if (!p) {
2152 log_write("%s", N_("could not bind"));
2153 goto fail;
2156 if (g_key_file_has_key(keyfileh, "global", "tcp_interface", NULL)) {
2157 gchar *tmp = get_key_file_string("global", "tcp_interface");
2159 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_BINDTODEVICE, tmp, 1)
2160 == -1) {
2161 log_write("setsockopt(): %s", strerror(errno));
2162 g_free(tmp);
2163 goto fail;
2166 g_free(tmp);
2169 if (!initTlsParams())
2170 goto fail;
2172 if (listen(tcpSockFd, 0) == -1) {
2173 log_write("listen(): %s", strerror(errno));
2174 goto fail;
2177 pthread_attr_init(&attr);
2178 pthread_create(&tcpAcceptTid, &attr, tcp_accept_thread, (void *)tcpSockFd);
2179 pthread_attr_destroy(&attr);
2180 return TRUE;
2182 fail:
2183 deinitTlsParams();
2185 if (tcpSockFd != -1)
2186 close(tcpSockFd);
2188 tcpSockFd = -1;
2189 return FALSE;
2191 #endif
2193 int main(int argc, char *argv[])
2195 gint opt;
2196 struct sockaddr_un addr;
2197 struct passwd *pw = getpwuid(getuid());
2198 gchar buf[PATH_MAX];
2199 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
2200 gchar *socketarg = NULL;
2201 gchar *datadir = NULL;
2202 gboolean n;
2203 gchar *p;
2204 gchar **cache_push = NULL;
2205 guint64 iter = 0;
2206 gchar *import = NULL, *keyfile = NULL;
2207 guint64 cmd_iterations = -1;
2208 gint default_timeout;
2209 gboolean rcfile_spec = FALSE;
2210 gint estatus = EXIT_FAILURE;
2211 gint sockfd;
2212 gchar *outfile = NULL;
2213 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
2214 gint do_unlink = 1;
2215 gboolean secure = FALSE;
2216 guint ptotal = 0;
2217 gint background = 1;
2218 gchar *convert = NULL;
2219 pthread_mutexattr_t mattr;
2220 #ifdef WITH_PINENTRY
2221 gboolean disable_pinentry = FALSE;
2222 #endif
2223 #ifdef WITH_GNUTLS
2224 struct assuan_io_hooks io_hooks = {read_hook, write_hook};
2225 #endif
2226 #if 0
2227 #ifndef DEBUG
2228 #ifdef HAVE_SETRLIMIT
2229 struct rlimit rl;
2231 rl.rlim_cur = rl.rlim_max = 0;
2233 if (setrlimit(RLIMIT_CORE, &rl) != 0)
2234 err(EXIT_FAILURE, "setrlimit()");
2235 #endif
2236 #endif
2237 #endif
2239 #ifdef ENABLE_NLS
2240 setlocale(LC_ALL, "");
2241 bindtextdomain("pwmd", LOCALEDIR);
2242 textdomain("pwmd");
2243 #endif
2245 #ifndef MEM_DEBUG
2246 xmem_init();
2247 #endif
2248 gpg_err_init();
2249 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
2250 g_mem_set_vtable(&mtable);
2251 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
2252 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
2253 xmlInitMemory();
2254 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
2255 gcry_check_version(GCRYPT_VERSION);
2256 #ifdef WITH_GNUTLS
2257 gnutls_global_set_mem_functions(xmalloc, xmalloc, gcry_SecureCheck,
2258 xrealloc, xfree);
2259 gnutls_global_init();
2260 gnutls_global_set_log_function(tls_log);
2261 gnutls_global_set_log_level(1);
2262 assuan_set_io_hooks(&io_hooks);
2263 #endif
2264 xmlInitGlobals();
2265 xmlInitParser();
2266 xmlXPathInit();
2267 g_snprintf(buf, sizeof(buf), "%s/.pwmd", pw->pw_dir);
2269 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2270 err(EXIT_FAILURE, "%s", buf);
2272 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", pw->pw_dir);
2274 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2275 err(EXIT_FAILURE, "%s", buf);
2277 rcfile = g_strdup_printf("%s/.pwmd/config", pw->pw_dir);
2278 cmdline = TRUE;
2279 #ifdef WITH_GNUTLS
2280 tcpSockFd = -1;
2281 #endif
2283 while ((opt = getopt(argc, argv, "Po:C:nI:i:k:hvf:D")) != EOF) {
2284 switch (opt) {
2285 #ifdef WITH_PINENTRY
2286 case 'P':
2287 disable_pinentry = TRUE;
2288 break;
2289 #endif
2290 case 'o':
2291 outfile = optarg;
2292 break;
2293 case 'C':
2294 convert = optarg;
2295 break;
2296 case 'n':
2297 background = 0;
2298 break;
2299 case 'D':
2300 secure = TRUE;
2301 break;
2302 case 'I':
2303 import = optarg;
2304 break;
2305 case 'i':
2306 cmd_iterations = strtol(optarg, NULL, 10);
2307 break;
2308 case 'k':
2309 keyfile = optarg;
2310 break;
2311 case 'f':
2312 g_free(rcfile);
2313 rcfile = g_strdup(optarg);
2314 rcfile_spec = TRUE;
2315 break;
2316 case 'v':
2317 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,
2318 PACKAGE_BUGREPORT,
2319 #ifdef WITH_PINENTRY
2320 "+WITH_PINENTRY\n"
2321 #else
2322 "-WITH_PINENTRY\n"
2323 #endif
2324 #ifdef WITH_QUALITY
2325 "+WITH_QUALITY\n"
2326 #else
2327 "-WITH_QUALITY\n"
2328 #endif
2329 #ifdef WITH_GNUTLS
2330 "+WITH_GNUTLS\n"
2331 #else
2332 "-WITH_GNUTLS\n"
2333 #endif
2334 #ifdef DEBUG
2335 "+DEBUG\n"
2336 #else
2337 "-DEBUG\n"
2338 #endif
2339 #ifdef MEM_DEBUG
2340 "+MEM_DEBUG\n"
2341 #else
2342 "-MEM_DEBUG\n"
2343 #endif
2345 exit(EXIT_SUCCESS);
2346 case 'h':
2347 default:
2348 usage(argv[0]);
2352 pthread_mutexattr_init(&mattr);
2353 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
2354 pthread_mutex_init(&rcfile_mutex, &mattr);
2355 pthread_mutexattr_destroy(&mattr);
2357 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
2358 exit(EXIT_FAILURE);
2360 #ifdef WITH_PINENTRY
2361 if (disable_pinentry == TRUE)
2362 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
2363 #endif
2365 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
2366 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
2368 if (log_syslog == TRUE)
2369 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
2371 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
2372 iter = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
2373 errno = 0;
2375 if (setpriority(PRIO_PROCESS, 0, iter) == -1) {
2376 log_write("setpriority(): %s", strerror(errno));
2377 goto do_exit;
2381 #ifdef HAVE_MLOCKALL
2382 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
2383 log_write("mlockall(): %s", strerror(errno));
2384 goto do_exit;
2386 #endif
2388 setup_gcrypt();
2390 if (convert) {
2391 if (!outfile)
2392 usage(argv[0]);
2394 opt = convert_file(convert, keyfile, outfile);
2395 g_key_file_free(keyfileh);
2396 g_free(rcfile);
2397 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
2400 if (import) {
2401 if (!outfile)
2402 usage(argv[0]);
2404 if (cmd_iterations == -1)
2405 cmd_iterations = (guint64)get_key_file_integer("global", "iterations");
2407 opt = xml_import(import, outfile, keyfile, cmd_iterations);
2408 g_key_file_free(keyfileh);
2409 g_free(rcfile);
2410 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
2413 g_key_file_set_list_separator(keyfileh, ',');
2415 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
2416 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
2418 if (*p == '~') {
2419 p++;
2420 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
2421 g_free(p);
2422 socketarg = g_strdup(buf);
2424 else
2425 socketarg = p;
2427 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
2428 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
2430 datadir = expand_homedir(p);
2431 g_free(p);
2433 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
2434 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
2435 disable_list_and_dump = n;
2437 else
2438 disable_list_and_dump = secure;
2440 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
2441 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
2442 else
2443 default_timeout = -1;
2445 setup_logging(keyfileh);
2447 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2448 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2450 if (argc != optind) {
2451 if (cache_push)
2452 ptotal = g_strv_length(cache_push);
2454 for (; optind < argc; optind++) {
2455 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2456 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
2460 if (strchr(socketarg, '/') == NULL) {
2461 socketdir = g_get_current_dir();
2462 socketname = g_strdup(socketarg);
2463 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2465 else {
2466 socketname = g_strdup(strrchr(socketarg, '/'));
2467 socketname++;
2468 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2469 socketdir = g_strdup(socketarg);
2470 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2473 if (chdir(datadir)) {
2474 log_write("%s: %s", datadir, strerror(errno));
2475 unlink(socketpath);
2476 goto do_exit;
2479 if (parse_rcfile_keys() == FALSE)
2480 goto do_exit;
2482 clear_rcfile_keys();
2485 * Set the cache entry for a file. Prompts for the password.
2487 if (cache_push) {
2488 for (opt = 0; cache_push[opt]; opt++)
2489 do_cache_push(cache_push[opt], NULL);
2491 g_strfreev(cache_push);
2492 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2496 * bind() doesn't like the full pathname of the socket or any non alphanum
2497 * characters so change to the directory where the socket is wanted then
2498 * create it then change to datadir.
2500 if (chdir(socketdir)) {
2501 log_write("%s: %s", socketdir, strerror(errno));
2502 goto do_exit;
2505 g_free(socketdir);
2507 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2508 log_write("socket(): %s", strerror(errno));
2509 goto do_exit;
2512 addr.sun_family = AF_UNIX;
2513 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2515 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2516 log_write("bind(): %s", strerror(errno));
2518 if (errno == EADDRINUSE)
2519 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2520 "stale socket. Please remove it manually."), socketpath);
2522 do_unlink = 0;
2523 goto do_exit;
2526 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2527 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2528 mode_t mode = strtol(t, NULL, 8);
2529 mode_t mask = umask(0);
2531 g_free(t);
2533 if (chmod(socketname, mode) == -1) {
2534 log_write("%s: %s", socketname, strerror(errno));
2535 close(sockfd);
2536 unlink(socketpath);
2537 umask(mask);
2538 goto do_exit;
2541 umask(mask);
2544 g_free(--socketname);
2546 if (chdir(datadir)) {
2547 log_write("%s: %s", datadir, strerror(errno));
2548 close(sockfd);
2549 unlink(socketpath);
2550 goto do_exit;
2553 g_free(datadir);
2554 pthread_mutexattr_init(&mattr);
2555 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
2556 pthread_mutex_init(&cache_mutex, &mattr);
2557 pthread_mutexattr_destroy(&mattr);
2558 pthread_mutex_init(&keepalive_cond_mutex, NULL);
2559 pthread_cond_init(&keepalive_cond, NULL);
2560 #ifdef WITH_PINENTRY
2561 pthread_mutex_init(&pin_mutex, NULL);
2562 #endif
2564 if (listen(sockfd, 0) == -1) {
2565 log_write("listen(): %s", strerror(errno));
2566 goto do_exit;
2569 cmdline = FALSE;
2571 #ifdef WITH_GNUTLS
2572 if (startStopTcp(FALSE) == FALSE)
2573 goto do_exit;
2574 #endif
2576 if (background) {
2577 switch (fork()) {
2578 case -1:
2579 log_write("fork(): %s", strerror(errno));
2580 goto do_exit;
2581 case 0:
2582 close(0);
2583 close(1);
2584 close(2);
2585 setsid();
2586 break;
2587 default:
2588 exit(EXIT_SUCCESS);
2592 server_loop(sockfd, &socketpath);
2593 estatus = EXIT_SUCCESS;
2595 do_exit:
2596 if (socketpath && do_unlink) {
2597 unlink(socketpath);
2598 g_free(socketpath);
2601 #ifdef WITH_GNUTLS
2602 startStopTcp(TRUE);
2603 gnutls_global_deinit();
2604 #endif
2606 g_key_file_free(keyfileh);
2607 g_free(rcfile);
2608 xmlCleanupParser();
2609 xmlCleanupGlobals();
2611 if (estatus == EXIT_SUCCESS)
2612 log_write(N_("pwmd exiting normally"));
2614 #if defined(DEBUG) && !defined(MEM_DEBUG)
2615 xdump();
2616 #endif
2617 #ifndef MEM_DEBUG
2618 xmem_deinit();
2619 #endif
2620 exit(estatus);