Check for EDEADLK in MUTEX_UNLOCK. It can be ignored since EDEADLK in
[pwmd.git] / src / pwmd.c
blob6b1e5dab8fb9ebb236fb9ff1d89ca4114a3c2cee
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_PTH_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;
99 pth_attr_t attr = pth_attr_of(pth_self());
101 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
102 pth_attr_destroy(attr);
103 MUTEX_LOCK(&rcfile_mutex);
104 log_write(N_("reloading configuration file '%s'"), rcfile);
105 k = parse_rcfile(FALSE);
107 if (!k)
108 goto done;
110 g_key_file_free(keyfileh);
111 keyfileh = k;
112 parse_rcfile_keys();
113 clear_rcfile_keys();
114 disable_list_and_dump = b;
115 #ifdef WITH_GNUTLS
116 startStopTcp(FALSE);
117 #endif
118 startStopKeepAlive(FALSE);
119 send_status_all(STATUS_CONFIG);
120 done:
121 MUTEX_UNLOCK(&rcfile_mutex);
122 return NULL;
125 static void reload_rcfile()
127 pth_t tid;
128 pth_attr_t attr = pth_attr_new();
129 gint n;
131 pth_attr_init(attr);
132 pth_attr_set(attr, PTH_ATTR_JOINABLE, 0);
133 tid = pth_spawn(attr, reload_rcfile_thread, NULL);
134 n = errno;
135 pth_attr_destroy(attr);
137 if (!tid)
138 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
139 _gpg_strerror(gpg_error_from_errno(n)));
142 gpg_error_t send_syserror(assuan_context_t ctx, gint e)
144 gpg_error_t n = gpg_error_from_errno(e);
146 pth_cancel_point();
147 return assuan_process_done(ctx, assuan_set_error(ctx, n, _gpg_strerror(n)));
150 gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e)
152 gpg_err_code_t n = gpg_err_code(e);
153 gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n);
154 struct client_s *client = assuan_get_pointer(ctx);
156 pth_cancel_point();
158 if (!e)
159 return assuan_process_done(ctx, 0);
161 if (!ctx) {
162 log_write("%s", pwmd_strerror(e));
163 return e;
166 if (n == EPWMD_LIBXML_ERROR) {
167 xmlErrorPtr xe = client->xml_error;
169 if (!xe)
170 xe = xmlGetLastError();
172 e = assuan_process_done(ctx, assuan_set_error(ctx, code, xe->message));
173 log_write("%s", xe->message);
175 if (xe == client->xml_error)
176 xmlResetError(xe);
177 else
178 xmlResetLastError();
180 client->xml_error = NULL;
181 return e;
184 return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e)));
187 void log_write(const gchar *fmt, ...)
189 gchar *args, *line;
190 va_list ap;
191 struct tm *tm;
192 time_t now;
193 gchar tbuf[21];
194 gint fd = -1;
195 gchar *name;
196 gchar buf[255];
197 pth_t tid = pth_self();
198 pth_attr_t attr;
200 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
201 return;
203 if (!cmdline && logfile) {
204 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
205 warn("%s", logfile);
206 return;
210 va_start(ap, fmt);
212 if (g_vasprintf(&args, fmt, ap) == -1) {
213 if (logfile)
214 close(fd);
216 va_end(ap);
217 return;
220 va_end(ap);
222 if (cmdline) {
223 fprintf(stderr, "%s\n", args);
224 fflush(stderr);
225 g_free(args);
226 return;
229 attr = pth_attr_of(tid);
231 if (pth_attr_get(attr, PTH_ATTR_NAME, &name) == FALSE)
232 name = "unknown";
234 pth_attr_destroy(attr);
235 name = print_fmt(buf, sizeof(buf), "%s(%p): ", name, tid);
237 if (!cmdline && log_syslog == TRUE)
238 syslog(LOG_INFO, "%s%s", name, args);
240 time(&now);
241 tm = localtime(&now);
242 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
243 tbuf[sizeof(tbuf) - 1] = 0;
245 if (args[strlen(args)-1] == '\n')
246 args[strlen(args)-1] = 0;
248 line = g_strdup_printf("%s %i %s%s\n", tbuf, getpid(), name, args);
249 g_free(args);
251 if (!line) {
252 if (logfile)
253 close(fd);
255 return;
258 if (logfile) {
259 write(fd, line, strlen(line));
260 fsync(fd);
261 close(fd);
264 if (isatty(STDERR_FILENO)) {
265 fprintf(stderr, "%s", line);
266 fflush(stderr);
269 g_free(line);
272 static void usage(gchar *pn)
274 g_fprintf(stderr, N_(
275 "Usage: %s [-hvDnP] [-f <rcfile>] [-C <filename>] "
276 "[-I <filename> [-i <iter>]]\n "
277 "[-k <keyfile>] [-o <outfile>] [file1] [...]\n"
278 " -n run as a foreground process\n"
279 " -f load the specified rcfile (~/.pwmd/config)\n"
280 " -C convert a version 1 data file to version 2\n"
281 " -I import an XML file\n"
282 " -i encrypt with the specified number of iterations when importing\n"
283 " (config default in the \"global\" section)\n"
284 " -k obtain the key from the specified file\n"
285 " -o output file for use with the -C and -I options\n"
286 " -D disable use of the LIST and DUMP commands\n"
287 " -P disable pinentry\n"
288 " -v version\n"
289 " -h this help text\n"
290 ), pn);
291 exit(EXIT_FAILURE);
294 static int gcry_SecureCheck(const void *ptr)
296 return 1;
299 static void setup_gcrypt()
301 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
302 gcry_check_version(GCRYPT_VERSION);
304 gcry_set_allocation_handler(xmalloc, xmalloc, gcry_SecureCheck, xrealloc,
305 xfree);
307 if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, NULL,
308 NULL) != 0)
309 errx(EXIT_FAILURE, N_("Required AES cipher not supported by libgcrypt."));
311 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_KEYLEN, NULL, &gcrykeysize);
312 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_BLKLEN, NULL, &gcryblocksize);
315 static gint new_connection(struct client_s *cl)
317 gpg_error_t rc;
318 gchar *ver;
320 rc = assuan_init_socket_server_ext(&cl->ctx, cl->thd->fd, 2);
322 if (rc)
323 goto fail;
325 assuan_set_pointer(cl->ctx, cl);
326 ver = g_strdup_printf("%s", PACKAGE_STRING);
327 assuan_set_hello_line(cl->ctx, ver);
328 g_free(ver);
329 rc = register_commands(cl->ctx);
331 if (rc)
332 goto fail;
334 rc = assuan_accept(cl->ctx);
336 if (rc)
337 goto fail;
339 return 0;
341 fail:
342 log_write("%s", _gpg_strerror(rc));
343 close(cl->thd->fd);
344 cl->thd->fd = -1;
345 return 1;
348 static void xml_error_cb(void *data, xmlErrorPtr e)
350 struct client_s *client = data;
353 * Keep the first reported error as the one to show in the error
354 * description. Reset in send_error().
356 if (client->xml_error)
357 return;
359 xmlCopyError(e, client->xml_error);
362 static void cleanup_crypto_handler(void *arg)
364 struct client_crypto_s **a = (struct client_crypto_s **)arg;
365 struct client_crypto_s *cr = *a;
367 if (cr->fh) {
368 if (cr->fh->fd != -1 ||
369 (cmdline == TRUE && cr->fh->fd != STDOUT_FILENO))
370 close(cr->fh->fd);
372 if (cr->fh->doc)
373 gcry_free(cr->fh->doc);
375 g_free(cr->fh);
378 if (cr->gh)
379 gcry_cipher_close(cr->gh);
381 g_free(cr);
382 *a = NULL;
385 void cleanup_crypto(struct client_crypto_s **c)
387 struct client_crypto_s *cr = *c;
389 if (!cr)
390 return;
392 if (cr->iv)
393 gcry_free(cr->iv);
395 if (cr->key)
396 gcry_free(cr->key);
398 if (cr->tkey)
399 gcry_free(cr->tkey);
401 if (cr->tkey2)
402 gcry_free(cr->tkey2);
404 if (cr->inbuf)
405 gcry_free(cr->inbuf);
407 if (cr->outbuf)
408 gcry_free(cr->outbuf);
410 cleanup_crypto_handler(c);
414 * This is called after a child_thread terminates. Set with
415 * pth_cleanup_push().
417 static void cleanup_cb(void *arg)
419 struct client_thread_s *cn = arg;
420 struct client_s *cl = cn->cl;
422 MUTEX_LOCK(&cn_mutex);
423 cn_thread_list = g_slist_remove(cn_thread_list, cn);
424 MUTEX_UNLOCK(&cn_mutex);
426 if (cn->msg_tid) {
427 pth_cancel(cn->msg_tid);
428 pth_join(cn->msg_tid, NULL);
431 for (;;) {
432 struct status_msg_s *m = g_slist_nth_data(cn->msg_list, 0);
434 if (!m)
435 break;
437 cn->msg_list = g_slist_remove(cn->msg_list, m);
438 g_free(m);
441 if (cl && cl->freed == FALSE)
442 cleanup_client(cl);
444 #ifdef WITH_GNUTLS
445 if (cn->tls) {
446 gnutls_deinit(cn->tls->ses);
448 if (cn->tls->fp)
449 g_free(cn->tls->fp);
451 g_free(cn->tls);
453 #endif
455 if (cl && cl->ctx)
456 assuan_deinit_server(cl->ctx);
457 else if (cl && cl->thd && cl->thd->fd != -1)
458 close(cl->thd->fd);
460 #ifdef WITH_PINENTRY
461 if (cl && cl->pinentry)
462 cleanup_pinentry(cl->pinentry);
463 #endif
465 if (cl->crypto)
466 cleanup_crypto(&cl->crypto);
468 g_free(cl);
469 log_write(N_("exiting, fd=%i"), cn->fd);
470 g_free(cn);
471 send_status_all(STATUS_CLIENTS);
475 * Called every time a connection is made from init_new_connection(). This is
476 * the thread entry point.
478 static void *client_thread(void *data)
480 struct client_thread_s *thd = data;
481 struct client_s *cl = g_malloc0(sizeof(struct client_s));
482 gpg_error_t rc;
483 pth_attr_t attr = pth_attr_of(pth_self());
484 gint n;
486 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
487 pth_attr_destroy(attr);
490 * Prevent a race condition with init_new_connection() if this thread
491 * fails (returns) for some reason before init_new_connection() releases
492 * the cn_mutex.
494 MUTEX_LOCK(&cn_mutex);
495 MUTEX_UNLOCK(&cn_mutex);
496 pth_cleanup_push(cleanup_cb, thd);
498 if (!cl) {
499 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
500 goto fail;
503 thd->cl = cl;
505 #ifdef WITH_GNUTLS
507 * Do the TLS handshake before anything else.
509 if (thd->remote) {
510 gchar *prio = get_key_file_string("global", "cipher_suite");
512 thd->tls = tls_init(thd->fd, prio);
513 g_free(prio);
515 if (!thd->tls) {
516 close(thd->fd);
517 thd->fd = -1;
518 goto fail;
521 pth_cancel_point();
523 #endif
525 cl->thd = thd;
527 if (new_connection(cl))
528 goto fail;
530 #ifdef WITH_PINENTRY
531 cl->pinentry = pinentry_init();
533 if (!cl->pinentry) {
534 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
535 goto fail;
538 #ifdef WITH_GNUTLS
539 /* Require the client to explicity set OPTION PINENTRY since the DISPLAY
540 * might be automatically set from the client. Connections to the X11
541 * server usually aren't encrypted and the client might unintentionally
542 * send the passphrase in the clear.
544 if (thd->remote)
545 cl->pinentry->enable = FALSE;
546 #endif
547 #endif
549 #ifdef HAVE_MLOCKALL
550 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
551 log_write("mlockall(): %s", strerror(errno));
552 goto fail;
554 #endif
556 pth_mutex_init(&thd->msg_list_mutex);
557 attr = pth_attr_new();
558 pth_attr_init(attr);
559 thd->msg_tid = pth_spawn(attr, client_msg_thread, thd);
560 n = errno;
561 pth_attr_destroy(attr);
563 if (!thd->msg_tid) {
564 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
565 _gpg_strerror(gpg_error_from_errno(n)));
566 goto fail;
569 pth_yield(thd->msg_tid);
570 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
572 if (rc) {
573 log_write("%s", _gpg_strerror(rc));
574 goto fail;
577 send_status_all(STATUS_CLIENTS);
578 xmlSetStructuredErrorFunc(cl, xml_error_cb);
580 for (;;) {
581 #ifdef WITH_PINENTRY
582 pth_event_t pev = NULL;
583 #endif
584 pth_status_t st;
585 pth_event_t ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE,
586 cl->thd->fd);
588 #ifdef WITH_PINENTRY
589 if (cl->pinentry->status == PINENTRY_RUNNING) {
590 pev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, cl->pinentry->fd);
591 ev = pth_event_concat(ev, pev, NULL);
593 #endif
595 pth_wait(ev);
596 pth_event_isolate(ev);
597 st = pth_event_status(ev);
599 if (st == PTH_STATUS_OCCURRED) {
600 rc = assuan_process_next(cl->ctx);
601 pth_cancel_point();
603 if (rc) {
604 cl->inquire_status = INQUIRE_INIT;
606 if (gpg_err_code(rc) == GPG_ERR_EOF)
607 goto done;
609 log_write("assuan_process_next(): %s", _gpg_strerror(rc));
610 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
612 if (rc) {
613 log_write("assuan_process_done(): %s", _gpg_strerror(rc));
614 goto done;
617 else {
618 #ifdef WITH_PINENTRY
619 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
620 cl->pinentry->status = PINENTRY_RUNNING;
621 #endif
623 switch (cl->inquire_status) {
624 case INQUIRE_BUSY:
625 case INQUIRE_INIT:
626 break;
627 case INQUIRE_DONE:
628 cl->inquire_status = INQUIRE_INIT;
629 rc = assuan_process_done(cl->ctx, 0);
630 pth_cancel_point();
631 break;
636 pth_event_free(ev, PTH_FREE_THIS);
638 #ifdef WITH_PINENTRY
639 if (pev) {
640 pth_event_isolate(pev);
641 st = pth_event_status(pev);
642 pth_event_free(pev, PTH_FREE_THIS);
645 rc = pinentry_iterate(cl,
646 pev && cl->pinentry->fd != -1 && st == PTH_STATUS_OCCURRED);
647 #endif
651 * Client cleanup (including XML data) is done in cleanup_cb() from
652 * the cleanup thread.
654 done:
655 fail:
656 pth_cleanup_pop(1);
657 pth_exit(PTH_CANCELED);
658 return NULL;
661 static void setup_logging(GKeyFile *kf)
663 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
665 if (n == TRUE) {
666 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
668 if (*p == '~') {
669 gchar buf[PATH_MAX];
671 p++;
672 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
673 g_free(p);
675 if (logfile)
676 g_free(logfile);
678 logfile = g_strdup(buf);
680 else {
681 if (logfile)
682 g_free(logfile);
684 logfile = p;
688 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
692 * Make sure all settings are set to either the specified setting or a
693 * default.
695 static void set_rcfile_defaults(GKeyFile *kf)
697 gchar buf[PATH_MAX];
699 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
700 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
701 g_key_file_set_string(kf, "global", "socket_path", buf);
704 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
705 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
706 g_key_file_set_string(kf, "global", "data_directory", buf);
709 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
710 g_key_file_set_boolean(kf, "global", "backup", TRUE);
712 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
713 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
714 g_key_file_set_string(kf, "global", "log_path", buf);
717 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
718 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
720 #ifdef HAVE_MLOCKALL
721 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
722 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
723 #endif
725 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
726 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
728 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
729 g_key_file_get_integer(kf, "global", "iterations", 0) < 0)
730 g_key_file_set_integer(kf, "global", "iterations", 1);
732 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
733 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
735 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
736 g_key_file_set_integer(kf, "global", "iteration_progress", 0);
738 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
739 g_key_file_set_integer(kf, "global", "compression_level", 6);
741 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
742 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
744 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
745 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
747 zlib_bufsize = (uInt)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
749 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
750 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
752 #ifdef HAVE_MLOCKALL
753 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
754 #endif
756 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
757 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
759 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
760 g_key_file_set_integer(kf, "global", "keepalive", DEFAULT_KEEPALIVE_TO);
762 #ifdef WITH_PINENTRY
763 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
764 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
766 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
767 g_key_file_set_integer(kf, "global", "pinentry_timeout", 20);
768 #endif
770 #ifdef WITH_GNUTLS
771 if (g_key_file_has_key(kf, "global", "tcp_port", NULL) == FALSE)
772 g_key_file_set_integer(kf, "global", "tcp_port", 6466);
774 if (g_key_file_has_key(kf, "global", "enable_tcp", NULL) == FALSE)
775 g_key_file_set_boolean(kf, "global", "enable_tcp", FALSE);
777 if (g_key_file_has_key(kf, "global", "tcp_require_key", NULL) == FALSE)
778 g_key_file_set_boolean(kf, "global", "tcp_require_key", FALSE);
780 if (g_key_file_has_key(kf, "global", "tcp_wait", NULL) == FALSE)
781 g_key_file_set_boolean(kf, "global", "tcp_wait", 3);
783 if (g_key_file_has_key(kf, "global", "cipher_suite", NULL) == FALSE)
784 g_key_file_set_string(kf, "global", "cipher_suite", "SECURE256");
786 if (g_key_file_has_key(kf, "global", "tcp_use_crl", NULL) == FALSE)
787 g_key_file_set_boolean(kf, "global", "tcp_use_crl", FALSE);
788 #endif
790 setup_logging(kf);
793 static GKeyFile *parse_rcfile(gboolean specified)
795 GKeyFile *kf = g_key_file_new();
796 GError *rc = NULL;
798 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
799 log_write("%s: %s", rcfile, rc->message);
801 if (cmdline && specified) {
802 g_clear_error(&rc);
803 return NULL;
806 if (rc->code == G_FILE_ERROR_NOENT) {
807 g_clear_error(&rc);
808 set_rcfile_defaults(kf);
809 return kf;
812 g_clear_error(&rc);
813 return NULL;
816 set_rcfile_defaults(kf);
817 return kf;
820 static gchar *do_get_password(const gchar *prompt)
822 gchar buf[LINE_MAX] = {0}, *p;
823 struct termios told, tnew;
824 gchar *key;
826 if (tcgetattr(STDIN_FILENO, &told) == -1) {
827 log_write("tcgetattr(): %s", strerror(errno));
828 return NULL;
831 memcpy(&tnew, &told, sizeof(struct termios));
832 tnew.c_lflag &= ~(ECHO);
833 tnew.c_lflag |= ICANON|ECHONL;
835 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
836 log_write("tcsetattr(): %s", strerror(errno));
837 tcsetattr(STDIN_FILENO, TCSANOW, &told);
838 return NULL;
841 fprintf(stderr, "%s", prompt);
843 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
844 tcsetattr(STDIN_FILENO, TCSANOW, &told);
845 return NULL;
848 tcsetattr(STDIN_FILENO, TCSANOW, &told);
849 p[strlen(p) - 1] = 0;
851 if (!buf[0]) {
852 key = gcry_malloc(1);
853 key[0] = 0;
855 else {
856 key = gcry_malloc(strlen(p) + 1);
857 sprintf(key, "%s", p);
860 memset(&buf, 0, sizeof(buf));
861 return key;
864 /* Only used when "enable_pinentry" is "false" or -P. */
865 static gpg_error_t get_input(const gchar *filename,
866 struct client_crypto_s *crypto, guchar *key, pinentry_cmd_t which)
868 gchar *prompt;
870 if (which == PINENTRY_SAVE) {
871 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
872 crypto->tkey = do_get_password(prompt);
873 g_free(prompt);
875 if (!crypto->tkey) {
876 log_write(N_("%s: Skipping file"), filename);
877 return GPG_ERR_BAD_PASSPHRASE;
880 prompt = g_strdup_printf(N_("Repeat passphrase: "));
881 crypto->tkey2 = do_get_password(prompt);
882 g_free(prompt);
884 if (!crypto->tkey2) {
885 log_write(N_("%s: Skipping file"), filename);
886 return GPG_ERR_BAD_PASSPHRASE;
889 if (strcmp(crypto->tkey, crypto->tkey2)) {
890 log_write(N_("%s: Passphrase mismatch"), filename);
891 return EPWMD_BADKEY;
894 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
895 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
896 return 0;
899 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
901 if ((crypto->tkey = do_get_password(prompt)) == NULL) {
902 log_write(N_("%s: Skipping file"), filename);
903 g_free(prompt);
904 return GPG_ERR_BAD_PASSPHRASE;
907 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
908 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
909 g_free(prompt);
910 return 0;
914 * inbuf must have been allocated with gcry_malloc().
916 gpg_error_t export_common(const gchar *filename, struct client_crypto_s *crypto,
917 gpointer inbuf, gulong insize)
919 gpg_error_t rc;
920 gint level, zrc;
921 gulong outsize;
922 gpointer outbuf;
924 level = get_key_file_integer(filename, "compression_level");
926 if (level < 0)
927 level = 0;
929 if (do_compress(NULL, level, inbuf, insize, &outbuf, &outsize, &zrc)
930 == FALSE) {
931 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
934 crypto->inbuf = outbuf;
935 crypto->insize = outsize;
936 rc = do_xml_encrypt(NULL, crypto, filename);
937 return rc;
940 static gpg_error_t get_password(const gchar *filename,
941 struct client_crypto_s *crypto, guchar *md5file, guchar *key,
942 pinentry_cmd_t which)
944 #ifdef WITH_PINENTRY
945 gpg_error_t rc = 0;
947 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
948 == FALSE) {
949 #endif
950 return get_input(filename, crypto, key, which);
951 #ifdef WITH_PINENTRY
953 else {
954 gchar *result = NULL;
955 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
957 set_pinentry_defaults(pin);
958 pin->which = which;
959 pin->filename = g_strdup(filename);
960 rc = pinentry_getpin(pin, &result);
962 if (rc) {
963 xfree(result);
964 goto done;
967 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, strlen(result) ? strlen(result) : 1);
968 xfree(result);
969 cleanup_pinentry(pin);
972 done:
973 return rc;
974 #endif
977 static gboolean _getline(const gchar *file, gchar **result, gpg_error_t *rc)
979 FILE *fp;
980 gchar buf[LINE_MAX] = {0}, *p;
981 gchar *str = NULL;
982 gint len;
984 *rc = 0;
986 if ((fp = fopen(file, "r")) == NULL) {
987 *rc = gpg_error_from_syserror();
988 return FALSE;
991 p = fgets(buf, sizeof(buf), fp);
992 fclose(fp);
993 len = strlen(buf);
995 if (len && buf[len - 1] == '\n')
996 buf[--len] = 0;
998 str = gcry_malloc(len + 1);
1000 if (!str) {
1001 *rc = gpg_error_from_errno(ENOMEM);
1002 return FALSE;
1005 memcpy(str, buf, len ? len : 1);
1006 str[len] = 0;
1007 memset(&buf, 0, sizeof(buf));
1008 *result = str;
1009 return TRUE;
1012 static gchar *parse_rcfile_keyfile(const gchar *filename, gboolean import,
1013 gpg_error_t *rc)
1015 GError *rv = NULL;
1016 gchar *t, *file = NULL, *str;
1018 *rc = GPG_ERR_UNKNOWN_ERRNO;
1020 if (import == FALSE) {
1021 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
1022 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
1024 if (!file) {
1025 if (rv) {
1026 log_write("%s: key_file: %s", rcfile, rv->message);
1027 g_clear_error(&rv);
1030 return NULL;
1033 t = expand_homedir(file);
1035 if (!t) {
1036 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1037 *rc = gpg_error_from_errno(ENOMEM);
1038 return NULL;
1041 g_free(file);
1042 file = t;
1045 else {
1046 /* -I or -C. The filename is a key file. */
1047 file = g_strdup(filename);
1049 if (!file) {
1050 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1051 *rc = gpg_error_from_errno(ENOMEM);
1052 return NULL;
1056 if (rv) {
1057 log_write("%s: key_file: %s", rcfile, rv->message);
1058 g_clear_error(&rv);
1059 return NULL;
1062 if (!file)
1063 return NULL;
1065 if (_getline(file, &str, rc) == FALSE) {
1066 log_write("%s: %s: %s", filename, file, pwmd_strerror(*rc));
1067 g_free(file);
1068 return NULL;
1071 g_free(file);
1072 *rc = 0;
1073 return str;
1076 static gboolean xml_import(const gchar *filename, const gchar *outfile,
1077 const gchar *keyfile, guint64 iter)
1079 xmlDocPtr doc;
1080 gint fd;
1081 struct stat st;
1082 gint len;
1083 xmlChar *xmlbuf;
1084 xmlChar *xml;
1085 gpg_error_t rc;
1086 struct client_crypto_s *crypto;
1088 if (stat(filename, &st) == -1) {
1089 log_write("%s: %s", filename, strerror(errno));
1090 return FALSE;
1093 crypto = init_client_crypto();
1095 if (!crypto)
1096 return FALSE;
1098 crypto->key = gcry_malloc(gcrykeysize);
1099 memset(crypto->key, 0, gcrykeysize);
1101 if (!crypto->key) {
1102 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1103 goto fail;
1106 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
1107 filename, outfile);
1109 if (iter && keyfile) {
1110 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1112 if (!crypto->tkey)
1113 goto fail;
1115 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1116 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1118 else if (iter) {
1119 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
1121 if (rc)
1122 goto fail;
1125 if ((fd = open(filename, O_RDONLY)) == -1) {
1126 log_write("%s: %s", filename, strerror(errno));
1127 goto fail;
1130 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
1131 close(fd);
1132 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1133 goto fail;
1136 if (pth_read(fd, xmlbuf, st.st_size) == -1) {
1137 rc = errno;
1138 close(fd);
1139 errno = rc;
1140 log_write("%s: %s", filename, strerror(errno));
1141 goto fail;
1144 close(fd);
1145 xmlbuf[st.st_size] = 0;
1148 * Make sure the document validates.
1150 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
1151 log_write("xmlReadDoc() failed");
1152 gcry_free(xmlbuf);
1153 goto fail;
1156 gcry_free(xmlbuf);
1157 xmlDocDumpMemory(doc, &xml, &len);
1158 xmlFreeDoc(doc);
1160 if (!iter)
1161 memset(crypto->key, '!', gcrykeysize);
1163 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
1165 if (!crypto->fh) {
1166 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1167 goto fail;
1170 crypto->fh->fh2.iter = iter;
1171 rc = export_common(outfile, crypto, xml, len);
1172 xmlFree(xml);
1174 if (rc) {
1175 send_error(NULL, rc);
1176 goto fail;
1179 cleanup_crypto(&crypto);
1180 return TRUE;
1182 fail:
1183 cleanup_crypto(&crypto);
1184 return FALSE;
1187 gchar *get_key_file_string(const gchar *section, const gchar *what)
1189 gchar *val = NULL;
1190 GError *grc = NULL;
1192 MUTEX_LOCK(&rcfile_mutex);
1194 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1195 val = g_key_file_get_string(keyfileh, section, what, &grc);
1197 if (grc) {
1198 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1199 g_clear_error(&grc);
1202 else {
1203 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1204 val = g_key_file_get_string(keyfileh, "global", what, &grc);
1206 if (grc) {
1207 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1208 g_clear_error(&grc);
1213 MUTEX_UNLOCK(&rcfile_mutex);
1214 return val;
1217 gint get_key_file_integer(const gchar *section, const gchar *what)
1219 gint val = -1;
1220 GError *grc = NULL;
1222 MUTEX_LOCK(&rcfile_mutex);
1224 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
1225 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
1227 if (grc) {
1228 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1229 g_clear_error(&grc);
1232 else {
1233 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1234 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
1236 if (grc) {
1237 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1238 g_clear_error(&grc);
1243 MUTEX_UNLOCK(&rcfile_mutex);
1244 return val;
1247 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
1249 gboolean val = FALSE;
1250 GError *grc = NULL;
1252 MUTEX_LOCK(&rcfile_mutex);
1254 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1255 val = g_key_file_get_boolean(keyfileh, section, what, &grc);
1257 if (grc) {
1258 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1259 g_clear_error(&grc);
1262 else {
1263 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1264 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
1266 if (grc) {
1267 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1268 g_clear_error(&grc);
1273 MUTEX_UNLOCK(&rcfile_mutex);
1274 return val;
1277 static gboolean parse_rcfile_keys()
1279 gsize n;
1280 gchar **groups;
1281 gchar **p;
1282 gchar *str;
1284 groups = g_key_file_get_groups(keyfileh, &n);
1286 for (p = groups; *p; p++) {
1287 GError *rc = NULL;
1289 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE) {
1290 str = g_key_file_get_string(keyfileh, *p, "key", &rc);
1292 if (!str) {
1293 if (rc) {
1294 log_write("%s: key: %s", rcfile, rc->message);
1295 g_clear_error(&rc);
1297 continue;
1300 do_cache_push(*p, str);
1301 g_free(str);
1302 continue;
1305 if (rc) {
1306 log_write("%s: key: %s", rcfile, rc->message);
1307 g_clear_error(&rc);
1308 continue;
1311 gpg_error_t ret;
1312 str = parse_rcfile_keyfile(*p, FALSE, &ret);
1314 if (!str)
1315 continue;
1317 do_cache_push(*p, str);
1318 gcry_free(str);
1321 g_strfreev(groups);
1322 return TRUE;
1325 static gboolean do_cache_push(const gchar *filename, const gchar *password)
1327 guchar md5file[16];
1328 gint timeout;
1329 const gchar *p = filename;
1330 struct client_crypto_s *crypto;
1331 gpg_error_t rc;
1333 while (isspace(*p))
1334 p++;
1336 if (!*p)
1337 return FALSE;
1339 if (valid_filename(p) == FALSE) {
1340 log_write(N_("%s: Invalid characters in filename"), p);
1341 return FALSE;
1344 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1346 if (access(p, R_OK|W_OK) != 0) {
1347 log_write("%s: %s", p, strerror(errno));
1348 return FALSE;
1351 crypto = init_client_crypto();
1353 if (!crypto)
1354 return FALSE;
1356 crypto->fh = read_file_header(filename, FALSE, &rc);
1358 if (!crypto->fh) {
1359 log_write("%s: %s", p, pwmd_strerror(rc));
1360 cleanup_crypto(&crypto);
1361 return FALSE;
1364 crypto->key = gcry_malloc(gcrykeysize);
1366 if (!crypto->key) {
1367 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1368 cleanup_crypto(&crypto);
1369 return FALSE;
1372 log_write(N_("Adding '%s' to the file cache ..."), filename);
1374 if (crypto->fh->fh2.iter <= 0) {
1375 memset(crypto->key, '!', gcrykeysize);
1376 goto try_decrypt;
1379 if (!password) {
1380 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1382 if (rc) {
1383 send_error(NULL, rc);
1384 cleanup_crypto(&crypto);
1385 return FALSE;
1388 gcry_free(crypto->fh->doc);
1389 crypto->fh->doc = NULL;
1391 else
1392 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password,
1393 strlen(password) ? strlen(password) : 1);
1395 try_decrypt:
1396 rc = try_xml_decrypt(NULL, crypto->key, crypto, NULL, NULL);
1398 if (rc) {
1399 log_write("%s: %s", filename, pwmd_strerror(rc));
1400 cleanup_crypto(&crypto);
1401 return FALSE;
1404 if (cache_update_key(md5file, crypto->key) == FALSE) {
1405 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1406 cleanup_crypto(&crypto);
1407 return FALSE;
1410 timeout = get_key_file_integer(p, "cache_timeout");
1411 cache_set_timeout(md5file, timeout);
1412 log_write(N_("File '%s' now cached"), filename);
1413 cleanup_crypto(&crypto);
1414 return TRUE;
1417 static void init_new_connection(gint fd, gchar *addr)
1419 pth_attr_t attr;
1420 struct client_thread_s *new;
1421 gint n;
1423 new = g_malloc0(sizeof(struct client_thread_s));
1425 if (!new) {
1426 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1427 close(fd);
1428 return;
1431 MUTEX_LOCK(&cn_mutex);
1432 new->fd = fd;
1434 #ifdef WITH_GNUTLS
1435 if (addr)
1436 new->remote = TRUE;
1437 #endif
1439 attr = pth_attr_new();
1440 pth_attr_init(attr);
1441 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1442 new->tid = pth_spawn(attr, client_thread, new);
1443 n = errno;
1444 pth_attr_destroy(attr);
1446 if (!new->tid) {
1447 g_free(new);
1448 close(fd);
1449 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1450 _gpg_strerror(gpg_error_from_errno(n)));
1451 MUTEX_UNLOCK(&cn_mutex);
1452 return;
1455 cn_thread_list = g_slist_append(cn_thread_list, new);
1456 MUTEX_UNLOCK(&cn_mutex);
1458 if (addr)
1459 log_write(N_("new connection: tid=%p, fd=%i, addr=%s"), new->tid, fd,
1460 addr);
1461 else
1462 log_write(N_("new connection: tid=%p, fd=%i"), new->tid, fd);
1465 #ifdef WITH_GNUTLS
1466 /* From Beej's Guide to Network Programming. It's a good tutorial. */
1467 static void *get_in_addr(struct sockaddr *sa)
1469 if (sa->sa_family == AF_INET)
1470 return &(((struct sockaddr_in*)sa)->sin_addr);
1472 return &(((struct sockaddr_in6*)sa)->sin6_addr);
1475 static void *tcp_accept_thread(void *arg)
1477 gint sockfd = (gint)arg;
1478 pth_attr_t attr = pth_attr_of(pth_self());
1480 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1481 pth_attr_destroy(attr);
1483 for (;;) {
1484 struct sockaddr_storage raddr;
1485 socklen_t slen = sizeof(raddr);
1486 gint fd = -1;
1487 gulong n;
1488 gchar *t;
1489 gchar s[INET6_ADDRSTRLEN];
1491 fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen);
1492 pth_cancel_point();
1494 if (fd == -1) {
1495 if (errno != EAGAIN) {
1496 if (!quit) // probably EBADF
1497 log_write("accept(): %s", strerror(errno));
1499 break;
1502 continue;
1505 if (quit)
1506 break;
1508 inet_ntop(raddr.ss_family, get_in_addr((struct sockaddr *)&raddr),
1509 s, sizeof s);
1510 init_new_connection(fd, s);
1511 t = get_key_file_string("global", "tcp_wait");
1512 n = strtol(t, NULL, 10);
1513 g_free(t);
1515 if (n < 0)
1516 n = 0;
1518 pth_usleep(n*100000);
1521 /* Just in case accept() failed for some reason other than EBADF */
1522 quit = 1;
1523 pth_exit(PTH_CANCELED);
1524 return NULL;
1526 #endif
1528 static void *accept_thread(void *arg)
1530 gint sockfd = (gint)arg;
1531 pth_attr_t attr = pth_attr_of(pth_self());
1533 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1534 pth_attr_destroy(attr);
1536 for (;;) {
1537 socklen_t slen = sizeof(struct sockaddr_un);
1538 struct sockaddr_un raddr;
1539 gint fd = -1;
1541 fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen);
1542 pth_cancel_point();
1544 if (fd == -1) {
1545 if (errno != EAGAIN) {
1546 if (!quit) // probably EBADF
1547 log_write("accept(): %s", strerror(errno));
1549 break;
1552 continue;
1555 init_new_connection(fd, NULL);
1558 /* Just in case accept() failed for some reason other than EBADF */
1559 quit = 1;
1560 pth_exit(PTH_CANCELED);
1561 return NULL;
1564 static void *adjust_cache_timer_thread(void *arg)
1566 pth_attr_t attr = pth_attr_of(pth_self());
1568 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1569 pth_attr_destroy(attr);
1571 for (;;) {
1572 pth_sleep(1);
1573 pth_cancel_point();
1574 CACHE_LOCK(NULL);
1575 cache_adjust_timer();
1576 CACHE_UNLOCK;
1579 return NULL;
1582 static void keepalive_cleanup(void *arg)
1584 pth_event_t ev = arg;
1586 pth_event_free(ev, PTH_FREE_ALL);
1589 static void *keepalive_thread(void *arg)
1591 gint to = (gint)arg;
1592 pth_mutex_t m;
1593 pth_cond_t cond;
1594 pth_attr_t attr = pth_attr_of(pth_self());
1596 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1597 pth_attr_destroy(attr);
1598 pth_cond_init(&cond);
1599 pth_mutex_init(&m);
1600 pth_mutex_acquire(&m, FALSE, NULL);
1602 for (;;) {
1603 pth_event_t ev = pth_event(PTH_EVENT_TIME, pth_timeout(to, 0));
1604 pth_cleanup_push(keepalive_cleanup, ev);
1605 pth_cond_await(&cond, &m, ev);
1606 pth_cancel_point();
1607 send_status_all(STATUS_KEEPALIVE);
1608 pth_cleanup_pop(1);
1611 return NULL;
1614 static void startStopKeepAlive(gboolean term)
1616 gint n = get_key_file_integer("global", "keepalive");
1618 if (keepalive_tid)
1619 pth_cancel(keepalive_tid);
1621 keepalive_tid = NULL;
1623 if (term)
1624 return;
1626 if (n > 0) {
1627 gint e;
1628 pth_attr_t attr = pth_attr_new();
1629 pth_attr_init(attr);
1630 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1631 keepalive_tid = pth_spawn(attr, keepalive_thread, (void *)n);
1632 e = errno;
1633 pth_attr_destroy(attr);
1635 if (!keepalive_tid) {
1636 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1637 _gpg_strerror(gpg_error_from_errno(e)));
1638 return;
1641 pth_yield(keepalive_tid);
1645 static gboolean waiting_for_exit()
1647 guint i, t;
1648 pth_event_t evs = NULL;
1650 MUTEX_LOCK(&cn_mutex);
1652 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
1653 struct client_thread_s *thd = g_slist_nth_data(cn_thread_list, i);
1654 pth_event_t ev = pth_event(PTH_EVENT_TID|PTH_UNTIL_TID_DEAD, thd->tid);
1656 if (evs)
1657 evs = pth_event_concat(evs, ev, NULL);
1658 else
1659 evs = ev;
1662 MUTEX_UNLOCK(&cn_mutex);
1664 if (!evs)
1665 return FALSE;
1667 pth_wait(evs);
1668 MUTEX_LOCK(&cn_mutex);
1669 i = g_slist_length(cn_thread_list);
1670 MUTEX_UNLOCK(&cn_mutex);
1671 return i ? TRUE : FALSE;
1674 static void server_loop(gint sockfd, gchar **socketpath)
1676 pth_t accept_tid;
1677 guint n;
1678 sigset_t sigset;
1679 pth_attr_t attr;
1680 pth_t cache_timeout_tid;
1682 sigemptyset(&sigset);
1684 /* Termination */
1685 sigaddset(&sigset, SIGTERM);
1686 sigaddset(&sigset, SIGINT);
1688 /* Clears the file cache. */
1689 sigaddset(&sigset, SIGUSR1);
1691 /* Configuration file reloading. */
1692 sigaddset(&sigset, SIGHUP);
1694 /* Clears the cache and exits when something bad happens. */
1695 sigaddset(&sigset, SIGABRT);
1697 /* Ignored everywhere. When a client disconnects abnormally this signal
1698 * gets raised. It isn't needed though because client_thread() will check
1699 * for rcs even after the client disconnects. */
1700 signal(SIGPIPE, SIG_IGN);
1701 sigprocmask(SIG_BLOCK, &sigset, NULL);
1703 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1704 attr = pth_attr_new();
1705 pth_attr_init(attr);
1706 accept_tid = pth_spawn(attr, accept_thread, (void *)sockfd);
1708 if (!accept_tid) {
1709 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1710 _gpg_strerror(gpg_error_from_errno(errno)));
1711 goto done;
1714 pth_yield(accept_tid);
1715 startStopKeepAlive(FALSE);
1716 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1717 cache_timeout_tid = pth_spawn(attr, adjust_cache_timer_thread, NULL);
1719 if (!cache_timeout_tid) {
1720 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1721 _gpg_strerror(gpg_error_from_errno(errno)));
1722 goto done;
1725 pth_yield(cache_timeout_tid);
1726 pth_attr_destroy(attr);
1728 do {
1729 gint sig;
1731 pth_sigwait(&sigset, &sig);
1732 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1734 /* Caught a signal. */
1735 switch (sig) {
1736 case SIGHUP:
1737 reload_rcfile();
1738 break;
1739 case SIGABRT:
1740 cache_clear(NULL, 2);
1741 #ifndef MEM_DEBUG
1742 xpanic();
1743 #endif
1744 exit(EXIT_FAILURE);
1745 case SIGUSR1:
1746 CACHE_LOCK(NULL);
1747 log_write(N_("clearing file cache"));
1748 cache_clear(NULL, 2);
1749 CACHE_UNLOCK;
1750 break;
1751 default:
1752 quit = 1;
1753 break;
1755 } while (!quit);
1757 done:
1759 * We're out of the main server loop. This happens when a signal was sent
1760 * to terminate the daemon. We'll wait for all clients to disconnect
1761 * before exiting and ignore any following signals.
1763 shutdown(sockfd, SHUT_RDWR);
1764 close(sockfd);
1765 pth_cancel(accept_tid);
1766 pth_join(accept_tid, NULL);
1767 #ifdef WITH_GNUTLS
1768 startStopTcp(TRUE);
1769 #endif
1770 unlink(*socketpath);
1771 g_free(*socketpath);
1772 *socketpath = NULL;
1773 MUTEX_LOCK(&cn_mutex);
1774 n = g_slist_length(cn_thread_list);
1775 MUTEX_UNLOCK(&cn_mutex);
1777 if (n) {
1778 log_write(N_("waiting for all clients to disconnect"));
1780 do {
1781 MUTEX_LOCK(&cn_mutex);
1782 n = g_slist_length(cn_thread_list);
1783 MUTEX_UNLOCK(&cn_mutex);
1784 log_write(N_("%i clients remain"), n);
1785 } while (waiting_for_exit());
1788 startStopKeepAlive(TRUE);
1789 pth_cancel(cache_timeout_tid);
1790 cache_free();
1794 * Called from pinentry_fork() in the child process.
1796 void free_client_list()
1798 gint i, t = g_slist_length(cn_thread_list);
1800 for (i = 0; i < t; i++) {
1801 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1803 free_client(cn->cl);
1806 cache_free();
1809 struct client_crypto_s *init_client_crypto()
1811 struct client_crypto_s *new = g_malloc0(sizeof(struct client_crypto_s));
1812 gpg_error_t rc;
1814 if (!new) {
1815 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1816 return NULL;
1819 rc = gcry_cipher_open(&new->gh, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
1821 if (rc) {
1822 log_write("%s(%i): %s", __FUNCTION__, __LINE__, _gpg_strerror(rc));
1823 g_free(new);
1824 return NULL;
1827 return new;
1830 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
1831 const gchar *outfile)
1833 gpg_error_t rc;
1834 guchar md5file[16];
1835 guint64 iter;
1836 struct client_crypto_s *crypto = init_client_crypto();
1838 if (!crypto)
1839 return GPG_ERR_ENOMEM;
1841 crypto->key = gcry_malloc(gcrykeysize);
1843 if (!crypto->key) {
1844 cleanup_crypto(&crypto);
1845 return GPG_ERR_ENOMEM;
1848 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
1849 filename);
1850 crypto->fh = read_file_header(filename, TRUE, &rc);
1852 if (!crypto->fh)
1853 goto done;
1855 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
1857 /* The header in version 1 had a bug where the iterations were off-by-one.
1858 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
1859 * header.
1861 if (crypto->fh->fh1.iter >= 0) {
1862 if (keyfile) {
1863 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1865 if (!crypto->tkey)
1866 goto done;
1868 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1869 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1871 else {
1872 rc = get_password(filename, crypto, md5file, crypto->key,
1873 PINENTRY_OPEN);
1875 if (rc)
1876 goto done;
1880 rc = try_xml_decrypt(NULL, crypto->key, crypto, &crypto->fh->doc,
1881 &crypto->fh->len);
1883 if (rc)
1884 goto done;
1886 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
1888 if (rc) {
1889 log_write("%s: %s", filename, pwmd_strerror(rc));
1890 goto done;
1893 crypto->fh->v1 = FALSE;
1894 iter = crypto->fh->fh1.iter;
1895 memset(&crypto->fh->fh2, 0, sizeof(crypto->fh->fh2));
1896 /* Keep the iterations and key from the original file. */
1897 crypto->fh->fh2.iter = iter+1; // Bugfix for v1 data files.
1898 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
1900 done:
1901 if (rc)
1902 send_error(NULL, rc);
1904 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
1905 cleanup_crypto(&crypto);
1906 return rc;
1909 #ifdef WITH_GNUTLS
1910 static gboolean startStopTcp(gboolean term)
1912 struct addrinfo hints, *servinfo, *p;
1913 gint port = get_key_file_integer("global", "tcp_port");
1914 gchar buf[7];
1915 gint n;
1917 if (term || get_key_file_boolean("global", "enable_tcp") == FALSE) {
1918 if (tcpSockFd != -1) {
1919 pth_cancel(tcpAcceptTid);
1920 pth_join(tcpAcceptTid, NULL);
1921 shutdown(tcpSockFd, SHUT_RDWR);
1922 close(tcpSockFd);
1923 tcpSockFd = -1;
1925 /* A client may still be connected. */
1926 if (!quit)
1927 deinitTlsParams();
1930 return TRUE;
1933 if (tcpSockFd != -1)
1934 return TRUE;
1936 memset(&hints, 0, sizeof(hints));
1937 hints.ai_family = AF_UNSPEC;
1938 hints.ai_socktype = SOCK_STREAM;
1939 hints.ai_flags = AI_PASSIVE;
1941 if ((n = getaddrinfo(NULL, print_fmt(buf, sizeof(buf), "%i", port),
1942 &hints, &servinfo)) == -1) {
1943 log_write("getaddrinfo(): %s", gai_strerror(n));
1944 return FALSE;
1947 for(p = servinfo; p != NULL; p = p->ai_next) {
1948 if ((tcpSockFd = socket(p->ai_family, p->ai_socktype,
1949 p->ai_protocol)) == -1) {
1950 log_write("socket(): %s", strerror(errno));
1951 continue;
1954 n = 1;
1956 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_REUSEADDR, &n,
1957 sizeof(int)) == -1) {
1958 log_write("setsockopt(): %s", strerror(errno));
1959 freeaddrinfo(servinfo);
1960 goto fail;
1963 if (bind(tcpSockFd, p->ai_addr, p->ai_addrlen) == -1) {
1964 close(tcpSockFd);
1965 log_write("bind(): %s", strerror(errno));
1966 continue;
1969 n++;
1970 break;
1973 freeaddrinfo(servinfo);
1975 if (!p) {
1976 log_write("%s", N_("could not bind"));
1977 goto fail;
1980 if (g_key_file_has_key(keyfileh, "global", "tcp_interface", NULL)) {
1981 gchar *tmp = get_key_file_string("global", "tcp_interface");
1983 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_BINDTODEVICE, tmp, 1)
1984 == -1) {
1985 log_write("setsockopt(): %s", strerror(errno));
1986 g_free(tmp);
1987 goto fail;
1990 g_free(tmp);
1993 if (!initTlsParams())
1994 goto fail;
1996 if (listen(tcpSockFd, 0) == -1) {
1997 log_write("listen(): %s", strerror(errno));
1998 goto fail;
2001 tcpAcceptTid = pth_spawn(NULL, tcp_accept_thread, (void *)tcpSockFd);
2003 if (!tcpAcceptTid) {
2004 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
2005 _gpg_strerror(gpg_error_from_errno(errno)));
2006 goto fail;
2009 pth_yield(tcpAcceptTid);
2010 return TRUE;
2012 fail:
2013 deinitTlsParams();
2015 if (tcpSockFd != -1)
2016 close(tcpSockFd);
2018 tcpSockFd = -1;
2019 return FALSE;
2021 #endif
2023 int main(int argc, char *argv[])
2025 gint opt;
2026 struct sockaddr_un addr;
2027 struct passwd *pw = getpwuid(getuid());
2028 gchar buf[PATH_MAX];
2029 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
2030 gchar *socketarg = NULL;
2031 gchar *datadir = NULL;
2032 gboolean n;
2033 gchar *p;
2034 gchar **cache_push = NULL;
2035 guint64 iter = 0;
2036 gchar *import = NULL, *keyfile = NULL;
2037 guint64 cmd_iterations = -1;
2038 gint default_timeout;
2039 gboolean rcfile_spec = FALSE;
2040 gint estatus = EXIT_FAILURE;
2041 gint sockfd;
2042 gchar *outfile = NULL;
2043 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
2044 gint do_unlink = 1;
2045 gboolean secure = FALSE;
2046 guint ptotal = 0;
2047 gint background = 1;
2048 gchar *convert = NULL;
2049 #ifdef WITH_PINENTRY
2050 gboolean disable_pinentry = FALSE;
2051 #endif
2052 #ifdef WITH_GNUTLS
2053 struct assuan_io_hooks io_hooks = {read_hook, write_hook};
2054 #endif
2055 #if 0
2056 #ifndef DEBUG
2057 #ifdef HAVE_SETRLIMIT
2058 struct rlimit rl;
2060 rl.rlim_cur = rl.rlim_max = 0;
2062 if (setrlimit(RLIMIT_CORE, &rl) != 0)
2063 err(EXIT_FAILURE, "setrlimit()");
2064 #endif
2065 #endif
2066 #endif
2068 #ifdef ENABLE_NLS
2069 setlocale(LC_ALL, "");
2070 bindtextdomain("pwmd", LOCALEDIR);
2071 textdomain("pwmd");
2072 #endif
2074 #ifndef MEM_DEBUG
2075 xmem_init();
2076 #endif
2077 setup_gcrypt();
2078 gpg_err_init();
2079 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
2080 g_mem_set_vtable(&mtable);
2081 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
2082 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
2083 xmlInitMemory();
2084 #ifdef WITH_GNUTLS
2085 gnutls_global_set_mem_functions(xmalloc, xmalloc, gcry_SecureCheck,
2086 xrealloc, xfree);
2087 gnutls_global_init();
2088 gnutls_global_set_log_function(tls_log);
2089 gnutls_global_set_log_level(1);
2090 assuan_set_io_hooks(&io_hooks);
2091 #endif
2092 xmlInitGlobals();
2093 xmlInitParser();
2094 xmlXPathInit();
2095 g_snprintf(buf, sizeof(buf), "%s/.pwmd", pw->pw_dir);
2097 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2098 err(EXIT_FAILURE, "%s", buf);
2100 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", pw->pw_dir);
2102 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2103 err(EXIT_FAILURE, "%s", buf);
2105 rcfile = g_strdup_printf("%s/.pwmd/config", pw->pw_dir);
2106 cmdline = TRUE;
2107 #ifdef WITH_GNUTLS
2108 tcpSockFd = -1;
2109 #endif
2111 while ((opt = getopt(argc, argv, "Po:C:nI:i:k:hvf:D")) != EOF) {
2112 switch (opt) {
2113 #ifdef WITH_PINENTRY
2114 case 'P':
2115 disable_pinentry = TRUE;
2116 break;
2117 #endif
2118 case 'o':
2119 outfile = optarg;
2120 break;
2121 case 'C':
2122 convert = optarg;
2123 break;
2124 case 'n':
2125 background = 0;
2126 break;
2127 case 'D':
2128 secure = TRUE;
2129 break;
2130 case 'I':
2131 import = optarg;
2132 break;
2133 case 'i':
2134 cmd_iterations = strtol(optarg, NULL, 10);
2135 break;
2136 case 'k':
2137 keyfile = optarg;
2138 break;
2139 case 'f':
2140 g_free(rcfile);
2141 rcfile = g_strdup(optarg);
2142 rcfile_spec = TRUE;
2143 break;
2144 case 'v':
2145 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,
2146 PACKAGE_BUGREPORT,
2147 #ifdef WITH_PINENTRY
2148 "+WITH_PINENTRY\n"
2149 #else
2150 "-WITH_PINENTRY\n"
2151 #endif
2152 #ifdef WITH_QUALITY
2153 "+WITH_QUALITY\n"
2154 #else
2155 "-WITH_QUALITY\n"
2156 #endif
2157 #ifdef WITH_GNUTLS
2158 "+WITH_GNUTLS\n"
2159 #else
2160 "-WITH_GNUTLS\n"
2161 #endif
2162 #ifdef DEBUG
2163 "+DEBUG\n"
2164 #else
2165 "-DEBUG\n"
2166 #endif
2167 #ifdef MEM_DEBUG
2168 "+MEM_DEBUG\n"
2169 #else
2170 "-MEM_DEBUG\n"
2171 #endif
2173 exit(EXIT_SUCCESS);
2174 case 'h':
2175 default:
2176 usage(argv[0]);
2180 pth_mutex_init(&cn_mutex);
2181 pth_mutex_init(&cache_mutex);
2182 pth_mutex_init(&rcfile_mutex);
2183 #ifdef WITH_PINENTRY
2184 pth_mutex_init(&pin_mutex);
2185 #endif
2187 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
2188 exit(EXIT_FAILURE);
2190 #ifdef WITH_PINENTRY
2191 if (disable_pinentry == TRUE)
2192 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
2193 #endif
2195 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
2196 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
2198 if (log_syslog == TRUE)
2199 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
2201 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
2202 iter = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
2203 errno = 0;
2205 if (setpriority(PRIO_PROCESS, 0, iter) == -1) {
2206 log_write("setpriority(): %s", strerror(errno));
2207 goto do_exit;
2211 #ifdef HAVE_MLOCKALL
2212 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
2213 log_write("mlockall(): %s", strerror(errno));
2214 goto do_exit;
2216 #endif
2218 if (convert) {
2219 if (!outfile)
2220 usage(argv[0]);
2222 opt = convert_file(convert, keyfile, outfile);
2223 g_key_file_free(keyfileh);
2224 g_free(rcfile);
2225 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
2228 if (import) {
2229 if (!outfile)
2230 usage(argv[0]);
2232 if (cmd_iterations == -1)
2233 cmd_iterations = (guint64)get_key_file_integer("global", "iterations");
2235 opt = xml_import(import, outfile, keyfile, cmd_iterations);
2236 g_key_file_free(keyfileh);
2237 g_free(rcfile);
2238 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
2241 g_key_file_set_list_separator(keyfileh, ',');
2243 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
2244 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
2246 if (*p == '~') {
2247 p++;
2248 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
2249 g_free(p);
2250 socketarg = g_strdup(buf);
2252 else
2253 socketarg = p;
2255 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
2256 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
2258 datadir = expand_homedir(p);
2259 g_free(p);
2261 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
2262 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
2263 disable_list_and_dump = n;
2265 else
2266 disable_list_and_dump = secure;
2268 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
2269 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
2270 else
2271 default_timeout = -1;
2273 setup_logging(keyfileh);
2275 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2276 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2278 if (argc != optind) {
2279 if (cache_push)
2280 ptotal = g_strv_length(cache_push);
2282 for (; optind < argc; optind++) {
2283 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2284 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
2288 if (strchr(socketarg, '/') == NULL) {
2289 socketdir = g_get_current_dir();
2290 socketname = g_strdup(socketarg);
2291 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2293 else {
2294 socketname = g_strdup(strrchr(socketarg, '/'));
2295 socketname++;
2296 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2297 socketdir = g_strdup(socketarg);
2298 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2301 if (chdir(datadir)) {
2302 log_write("%s: %s", datadir, strerror(errno));
2303 unlink(socketpath);
2304 goto do_exit;
2307 if (parse_rcfile_keys() == FALSE)
2308 goto do_exit;
2310 clear_rcfile_keys();
2313 * Set the cache entry for a file. Prompts for the password.
2315 if (cache_push) {
2316 for (opt = 0; cache_push[opt]; opt++)
2317 do_cache_push(cache_push[opt], NULL);
2319 g_strfreev(cache_push);
2320 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2324 * bind() doesn't like the full pathname of the socket or any non alphanum
2325 * characters so change to the directory where the socket is wanted then
2326 * create it then change to datadir.
2328 if (chdir(socketdir)) {
2329 log_write("%s: %s", socketdir, strerror(errno));
2330 goto do_exit;
2333 g_free(socketdir);
2335 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2336 log_write("socket(): %s", strerror(errno));
2337 goto do_exit;
2340 addr.sun_family = AF_UNIX;
2341 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2343 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2344 log_write("bind(): %s", strerror(errno));
2346 if (errno == EADDRINUSE)
2347 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2348 "stale socket. Please remove it manually."), socketpath);
2350 do_unlink = 0;
2351 goto do_exit;
2354 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2355 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2356 mode_t mode = strtol(t, NULL, 8);
2357 mode_t mask = umask(0);
2359 g_free(t);
2361 if (chmod(socketname, mode) == -1) {
2362 log_write("%s: %s", socketname, strerror(errno));
2363 close(sockfd);
2364 unlink(socketpath);
2365 umask(mask);
2366 goto do_exit;
2369 umask(mask);
2372 g_free(--socketname);
2374 if (chdir(datadir)) {
2375 log_write("%s: %s", datadir, strerror(errno));
2376 close(sockfd);
2377 unlink(socketpath);
2378 goto do_exit;
2381 g_free(datadir);
2383 if (listen(sockfd, 0) == -1) {
2384 log_write("listen(): %s", strerror(errno));
2385 goto do_exit;
2388 cmdline = FALSE;
2390 #ifdef WITH_GNUTLS
2391 if (startStopTcp(FALSE) == FALSE)
2392 goto do_exit;
2393 #endif
2395 if (background) {
2396 switch (fork()) {
2397 case -1:
2398 log_write("fork(): %s", strerror(errno));
2399 goto do_exit;
2400 case 0:
2401 close(0);
2402 close(1);
2403 close(2);
2404 setsid();
2405 break;
2406 default:
2407 exit(EXIT_SUCCESS);
2411 server_loop(sockfd, &socketpath);
2412 estatus = EXIT_SUCCESS;
2414 do_exit:
2415 if (socketpath && do_unlink) {
2416 unlink(socketpath);
2417 g_free(socketpath);
2420 #ifdef WITH_GNUTLS
2421 startStopTcp(TRUE);
2422 gnutls_global_deinit();
2423 #endif
2425 g_key_file_free(keyfileh);
2426 g_free(rcfile);
2427 xmlCleanupParser();
2428 xmlCleanupGlobals();
2430 if (estatus == EXIT_SUCCESS)
2431 log_write(N_("pwmd exiting normally"));
2433 #if defined(DEBUG) && !defined(MEM_DEBUG)
2434 xdump();
2435 #endif
2436 exit(estatus);