Added get_key_file_double(). Use this in places where needed rather than
[pwmd.git] / src / pwmd.c
blob0cc0651fa51c9aed1297714ebd951ac5888784c2
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 HAVE_GETOPT_LONG
52 #ifdef HAVE_GETOPT_H
53 #include <getopt.h>
54 #endif
55 #else
56 #include "getopt_long.h"
57 #endif
59 #ifdef TM_IN_SYS_TIME
60 #include <sys/time.h>
61 #else
62 #include <time.h>
63 #endif
65 #include "mem.h"
66 #include "xml.h"
67 #include "common.h"
69 #ifdef WITH_PINENTRY
70 #include "pinentry.h"
71 #endif
73 #include "commands.h"
74 #include "pwmd_error.h"
75 #include "cache.h"
76 #include "misc.h"
77 #include "pwmd.h"
78 #include "lock.h"
80 GCRY_THREAD_OPTION_PTH_IMPL;
82 static void clear_rcfile_keys()
84 gsize n;
85 gchar **groups;
86 gchar **p;
88 groups = g_key_file_get_groups(keyfileh, &n);
90 for (p = groups; *p; p++) {
91 GError *rc = NULL;
93 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE)
94 g_key_file_set_string(keyfileh, *p, "key", "");
97 g_strfreev(groups);
100 static void *reload_rcfile_thread(void *arg)
102 gboolean b = disable_list_and_dump;
103 GKeyFile *k;
104 pth_attr_t attr = pth_attr_of(pth_self());
106 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
107 pth_attr_destroy(attr);
108 MUTEX_LOCK(&rcfile_mutex);
109 log_write(N_("reloading configuration file '%s'"), rcfile);
110 k = parse_rcfile(FALSE);
112 if (!k)
113 goto done;
115 g_key_file_free(keyfileh);
116 keyfileh = k;
117 parse_rcfile_keys();
118 clear_rcfile_keys();
119 disable_list_and_dump = b;
120 startStopKeepAlive(FALSE);
121 send_status_all(STATUS_CONFIG);
122 done:
123 MUTEX_UNLOCK(&rcfile_mutex);
124 return NULL;
127 static void reload_rcfile()
129 pth_t tid;
130 pth_attr_t attr = pth_attr_new();
131 gint n;
133 pth_attr_init(attr);
134 pth_attr_set(attr, PTH_ATTR_JOINABLE, 0);
135 tid = pth_spawn(attr, reload_rcfile_thread, NULL);
136 n = errno;
137 pth_attr_destroy(attr);
139 if (!tid)
140 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
141 _gpg_strerror(gpg_error_from_errno(n)));
144 gpg_error_t send_syserror(assuan_context_t ctx, gint e)
146 gpg_error_t n = gpg_error_from_errno(e);
147 struct client_s *client = assuan_get_pointer(ctx);
149 client->last_rc = e;
150 return assuan_process_done(ctx, assuan_set_error(ctx, n, _gpg_strerror(n)));
153 gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e)
155 gpg_err_code_t n = gpg_err_code(e);
156 gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n);
157 struct client_s *client = assuan_get_pointer(ctx);
159 client->last_rc = e;
161 if (!e)
162 return assuan_process_done(ctx, 0);
164 if (!ctx) {
165 log_write("%s", pwmd_strerror(e));
166 return e;
169 if (n == EPWMD_LIBXML_ERROR) {
170 xmlErrorPtr xe = client->xml_error;
172 if (!xe)
173 xe = xmlGetLastError();
175 e = assuan_process_done(ctx, assuan_set_error(ctx, code, xe->message));
176 log_write("%s", xe->message);
178 if (xe == client->xml_error)
179 xmlResetError(xe);
180 else
181 xmlResetLastError();
183 client->xml_error = NULL;
184 return e;
187 return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e)));
190 void log_write(const gchar *fmt, ...)
192 gchar *args, *line;
193 va_list ap;
194 struct tm *tm;
195 time_t now;
196 gchar tbuf[21];
197 gint fd = -1;
198 gchar *name;
199 gchar buf[255];
200 pth_t tid = pth_self();
201 pth_attr_t attr;
203 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
204 return;
206 if (!cmdline && logfile) {
207 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
208 warn("%s", logfile);
209 return;
213 va_start(ap, fmt);
215 if (g_vasprintf(&args, fmt, ap) == -1) {
216 if (logfile)
217 close(fd);
219 va_end(ap);
220 return;
223 va_end(ap);
225 if (cmdline) {
226 fprintf(stderr, "%s\n", args);
227 fflush(stderr);
228 g_free(args);
229 return;
232 attr = pth_attr_of(tid);
234 if (pth_attr_get(attr, PTH_ATTR_NAME, &name) == FALSE)
235 name = "unknown";
237 pth_attr_destroy(attr);
238 name = print_fmt(buf, sizeof(buf), "%s(%p): ", name, tid);
240 if (!cmdline && log_syslog == TRUE)
241 syslog(LOG_INFO, "%s%s", name, args);
243 time(&now);
244 tm = localtime(&now);
245 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
246 tbuf[sizeof(tbuf) - 1] = 0;
248 if (args[strlen(args)-1] == '\n')
249 args[strlen(args)-1] = 0;
251 line = g_strdup_printf("%s %i %s%s\n", tbuf, getpid(), name, args);
252 g_free(args);
254 if (!line) {
255 if (logfile)
256 close(fd);
258 return;
261 if (logfile) {
262 pth_write(fd, line, strlen(line));
263 fsync(fd);
264 close(fd);
267 if (isatty(STDERR_FILENO)) {
268 fprintf(stderr, "%s", line);
269 fflush(stderr);
272 g_free(line);
275 static void usage(gchar *pn, gint rc)
277 g_fprintf(rc == EXIT_FAILURE ? stderr : stdout, N_(
278 "Usage: %s [options] [file1] [...]\n"
279 " --no-fork/-n\n"
280 " run as a foreground process\n"
281 " --rcfile/-f <filename>\n"
282 " load the specified rcfile (~/.pwmd/config)\n"
283 " --convert/-C <filename>\n"
284 " convert a version 1 data file to version 2\n"
285 " --import/-I <filename>\n"
286 " import an XML file\n"
287 " --iterations/-i\n"
288 " encrypt with the specified number of iterations when importing\n"
289 " (default is in the rcfile \"global\" section)\n"
290 " --key-file/-k <filename>\n"
291 " obtain the key from the specified file when importing or converting\n"
292 " --outfile/-o <filename>\n"
293 " output file to use when importing or converting (- for stdout)\n"
294 " --disable-dump/-D\n"
295 " disable use of the LIST, XPATH and DUMP commands\n"
296 " --no-pinentry/-P\n"
297 " disable use of pinentry\n"
298 " --version\n"
299 " --help\n"
300 ), pn);
301 exit(rc);
304 static int gcry_SecureCheck(const void *ptr)
306 return 1;
309 static void setup_gcrypt()
311 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
312 gcry_check_version(GCRYPT_VERSION);
314 gcry_set_allocation_handler(xmalloc, xmalloc, gcry_SecureCheck, xrealloc,
315 xfree);
318 static gint new_connection(struct client_s *cl)
320 gpg_error_t rc;
321 gchar *ver;
323 rc = assuan_init_socket_server_ext(&cl->ctx, cl->thd->fd, 2);
325 if (rc)
326 goto fail;
328 assuan_set_pointer(cl->ctx, cl);
329 ver = g_strdup_printf("%s", PACKAGE_STRING);
330 assuan_set_hello_line(cl->ctx, ver);
331 g_free(ver);
332 rc = register_commands(cl->ctx);
334 if (rc)
335 goto fail;
337 rc = assuan_accept(cl->ctx);
339 if (rc)
340 goto fail;
342 return 0;
344 fail:
345 log_write("%s", _gpg_strerror(rc));
346 close(cl->thd->fd);
347 cl->thd->fd = -1;
348 return 1;
351 static void xml_error_cb(void *data, xmlErrorPtr e)
353 struct client_s *client = data;
356 * Keep the first reported error as the one to show in the error
357 * description. Reset in send_error().
359 if (client->xml_error)
360 return;
362 xmlCopyError(e, client->xml_error);
365 void close_file_header(file_header_internal_t *fh)
367 if (!fh)
368 return;
370 if (fh->fd != -1 || (cmdline == TRUE && fh->fd != STDOUT_FILENO))
371 close(fh->fd);
373 if (fh->doc)
374 gcry_free(fh->doc);
376 g_free(fh);
379 void cleanup_crypto(struct client_crypto_s **c)
381 struct client_crypto_s *cr = *c;
383 if (!cr)
384 return;
386 if (cr->iv) {
387 gcry_free(cr->iv);
388 cr->iv = NULL;
391 if (cr->key) {
392 gcry_free(cr->key);
393 cr->key = NULL;
396 if (cr->tkey) {
397 gcry_free(cr->tkey);
398 cr->tkey = NULL;
401 if (cr->tkey2) {
402 gcry_free(cr->tkey2);
403 cr->tkey2 = NULL;
406 if (cr->inbuf) {
407 gcry_free(cr->inbuf);
408 cr->inbuf = NULL;
411 if (cr->outbuf) {
412 gcry_free(cr->outbuf);
413 cr->outbuf = NULL;
416 close_file_header(cr->fh);
417 cr->fh = NULL;
419 if (cr->gh)
420 gcry_cipher_close(cr->gh);
422 cr->gh = NULL;
423 g_free(cr);
424 *c = NULL;
428 * This is called after a child_thread terminates. Set with
429 * pth_cleanup_push().
431 static void cleanup_cb(void *arg)
433 struct client_thread_s *cn = arg;
434 struct client_s *cl = cn->cl;
436 MUTEX_LOCK(&cn_mutex);
437 cn_thread_list = g_slist_remove(cn_thread_list, cn);
438 MUTEX_UNLOCK(&cn_mutex);
440 if (cn->msg_tid) {
441 MUTEX_LOCK(&cn->mp_mutex);
442 pth_cancel(cn->msg_tid);
443 MUTEX_UNLOCK(&cn->mp_mutex);
446 if (cn->mp) {
447 while (pth_msgport_pending(cn->mp)) {
448 pth_message_t *msg = pth_msgport_get(cn->mp);
450 g_free(msg->m_data);
451 g_free(msg);
454 pth_msgport_destroy(cn->mp);
457 if (!cl) {
458 if (cn->fd != -1)
459 close(cn->fd);
461 goto done;
464 if (!cl->freed)
465 cleanup_client(cl);
467 if (cl->ctx)
468 assuan_deinit_server(cl->ctx);
469 else if (cl->thd && cl->thd->fd != -1)
470 close(cl->thd->fd);
472 #ifdef WITH_PINENTRY
473 if (cl->pinentry)
474 cleanup_pinentry(cl->pinentry);
475 #endif
477 if (cl->crypto)
478 cleanup_crypto(&cl->crypto);
480 g_free(cl);
481 done:
482 log_write(N_("exiting, fd=%i"), cn->fd);
483 g_free(cn);
484 send_status_all(STATUS_CLIENTS);
488 * Called every time a connection is made from init_new_connection(). This is
489 * the thread entry point.
491 static void *client_thread(void *data)
493 struct client_thread_s *thd = data;
494 struct client_s *cl = g_malloc0(sizeof(struct client_s));
495 gpg_error_t rc;
496 pth_attr_t attr;
497 gint n;
500 * Prevent a race condition with init_new_connection() if this thread
501 * fails (returns) for some reason before init_new_connection() releases
502 * the cn_mutex.
504 MUTEX_LOCK(&cn_mutex);
505 MUTEX_UNLOCK(&cn_mutex);
506 pth_cleanup_push(cleanup_cb, thd);
508 if (!cl) {
509 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
510 goto fail;
513 attr = pth_attr_of(pth_self());
514 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
515 pth_attr_destroy(attr);
516 thd->cl = cl;
517 cl->thd = thd;
519 if (new_connection(cl))
520 goto fail;
522 #ifdef WITH_PINENTRY
523 cl->pinentry = pinentry_init();
525 if (!cl->pinentry) {
526 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
527 goto fail;
529 #endif
531 #ifdef HAVE_MLOCKALL
532 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
533 log_write("mlockall(): %s", strerror(errno));
534 goto fail;
536 #endif
538 thd->mp = pth_msgport_create(NULL);
539 pth_mutex_init(&thd->mp_mutex);
540 thd->msg_tid = pth_spawn(NULL, client_msg_thread, thd);
541 n = errno;
543 if (!thd->msg_tid) {
544 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
545 _gpg_strerror(gpg_error_from_errno(n)));
546 goto fail;
549 pth_yield(thd->msg_tid);
550 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
552 if (rc) {
553 log_write("%s", _gpg_strerror(rc));
554 goto fail;
557 send_status_all(STATUS_CLIENTS);
558 xmlSetStructuredErrorFunc(cl, xml_error_cb);
560 for (;;) {
561 #ifdef WITH_PINENTRY
562 pth_event_t pev = NULL;
563 #endif
564 pth_status_t st, wst;
565 pth_event_t wev = NULL;
566 pth_event_t rev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE,
567 cl->thd->fd);
568 pth_event_t ev = rev;
570 #ifdef WITH_PINENTRY
571 if (cl->pinentry->status == PINENTRY_RUNNING) {
572 pev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, cl->pinentry->fd);
573 ev = pth_event_concat(ev, pev, NULL);
575 #endif
577 if (cl->inquire_status == INQUIRE_BUSY) {
578 wev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_WRITEABLE, cl->thd->fd);
579 ev = pth_event_concat(ev, wev, NULL);
582 pth_cleanup_push(cleanup_ev_cb, ev);
583 pth_wait(ev);
584 st = pth_event_status(rev);
585 wst = pth_event_status(wev);
587 if (st == PTH_STATUS_OCCURRED || wst == PTH_STATUS_OCCURRED) {
588 rc = assuan_process_next(cl->ctx);
590 if (rc) {
591 cl->inquire_status = INQUIRE_INIT;
592 pth_cleanup_pop(1);
594 if (gpg_err_code(rc) == GPG_ERR_EOF)
595 goto done;
597 log_write("assuan_process_next(): %s", _gpg_strerror(rc));
598 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
600 if (rc) {
601 log_write("assuan_process_done(): %s", _gpg_strerror(rc));
602 goto done;
605 else {
606 #ifdef WITH_PINENTRY
607 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
608 cl->pinentry->status = PINENTRY_RUNNING;
609 #endif
611 switch (cl->inquire_status) {
612 case INQUIRE_BUSY:
613 case INQUIRE_INIT:
614 break;
615 case INQUIRE_DONE:
616 cl->inquire_status = INQUIRE_INIT;
617 rc = assuan_process_done(cl->ctx, 0);
618 break;
623 #ifdef WITH_PINENTRY
624 if (pev)
625 st = pth_event_status(pev);
627 rc = pinentry_iterate(cl,
628 pev && cl->pinentry->fd != -1 && st == PTH_STATUS_OCCURRED);
629 #endif
630 pth_cleanup_pop(1);
634 * Client cleanup (including XML data) is done in cleanup_cb().
636 done:
637 fail:
638 pth_exit(PTH_CANCELED);
639 return NULL;
642 static void setup_logging(GKeyFile *kf)
644 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
646 if (n == TRUE) {
647 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
649 if (*p == '~') {
650 gchar buf[PATH_MAX];
652 p++;
653 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
654 g_free(p);
656 if (logfile)
657 g_free(logfile);
659 logfile = g_strdup(buf);
661 else {
662 if (logfile)
663 g_free(logfile);
665 logfile = p;
669 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
673 * Make sure all settings are set to either the specified setting or a
674 * default.
676 static void set_rcfile_defaults(GKeyFile *kf)
678 gchar buf[PATH_MAX];
680 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
681 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
682 g_key_file_set_string(kf, "global", "socket_path", buf);
685 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
686 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
687 g_key_file_set_string(kf, "global", "data_directory", buf);
690 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
691 g_key_file_set_boolean(kf, "global", "backup", TRUE);
693 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
694 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
695 g_key_file_set_string(kf, "global", "log_path", buf);
698 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
699 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
701 #ifdef HAVE_MLOCKALL
702 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
703 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
704 #endif
706 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
707 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
709 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
710 g_key_file_get_double(kf, "global", "iterations", 0) < 0ULL)
711 g_key_file_set_double(kf, "global", "iterations", 1ULL);
713 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
714 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
716 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
717 g_key_file_set_double(kf, "global", "iteration_progress", 0ULL);
719 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
720 g_key_file_set_integer(kf, "global", "compression_level", 6);
722 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
723 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
725 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
726 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
728 zlib_bufsize = (uInt)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
730 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
731 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
733 #ifdef HAVE_MLOCKALL
734 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
735 #endif
737 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
738 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
740 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
741 g_key_file_set_integer(kf, "global", "keepalive", DEFAULT_KEEPALIVE_TO);
743 #ifdef WITH_PINENTRY
744 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
745 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
747 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
748 g_key_file_set_integer(kf, "global", "pinentry_timeout",
749 DEFAULT_PIN_TIMEOUT);
751 if (g_key_file_has_key(kf, "global", "pinentry_path", NULL) == FALSE)
752 g_key_file_set_string(kf, "global", "pinentry_path", PINENTRY_PATH);
753 #endif
755 if (g_key_file_has_key(kf, "global", "xfer_progress", NULL) == FALSE)
756 g_key_file_set_integer(kf, "global", "xfer_progress", 8196);
758 if (g_key_file_has_key(kf, "global", "cipher", NULL) == FALSE)
759 g_key_file_set_string(kf, "global", "cipher", "AES256");
761 if (g_key_file_has_key(kf, "global", "log_level", NULL) == FALSE)
762 g_key_file_set_integer(kf, "global", "log_level", 0);
764 setup_logging(kf);
767 static GKeyFile *parse_rcfile(gboolean specified)
769 GKeyFile *kf = g_key_file_new();
770 GError *rc = NULL;
772 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
773 log_write("%s: %s", rcfile, rc->message);
775 if (cmdline && specified) {
776 g_clear_error(&rc);
777 return NULL;
780 if (rc->code == G_FILE_ERROR_NOENT) {
781 g_clear_error(&rc);
782 set_rcfile_defaults(kf);
783 return kf;
786 g_clear_error(&rc);
787 return NULL;
790 set_rcfile_defaults(kf);
791 return kf;
794 static gchar *do_get_password(const gchar *prompt)
796 gchar buf[LINE_MAX] = {0}, *p;
797 struct termios told, tnew;
798 gchar *key;
800 if (tcgetattr(STDIN_FILENO, &told) == -1) {
801 log_write("tcgetattr(): %s", strerror(errno));
802 return NULL;
805 memcpy(&tnew, &told, sizeof(struct termios));
806 tnew.c_lflag &= ~(ECHO);
807 tnew.c_lflag |= ICANON|ECHONL;
809 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
810 log_write("tcsetattr(): %s", strerror(errno));
811 tcsetattr(STDIN_FILENO, TCSANOW, &told);
812 return NULL;
815 fprintf(stderr, "%s", prompt);
817 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
818 tcsetattr(STDIN_FILENO, TCSANOW, &told);
819 return NULL;
822 tcsetattr(STDIN_FILENO, TCSANOW, &told);
823 p[strlen(p) - 1] = 0;
825 if (!buf[0]) {
826 key = gcry_malloc(1);
827 key[0] = 0;
829 else {
830 key = gcry_malloc(strlen(p) + 1);
831 sprintf(key, "%s", p);
834 memset(&buf, 0, sizeof(buf));
835 return key;
838 /* Only used when "enable_pinentry" is "false" or -P. */
839 static gpg_error_t get_input(const gchar *filename,
840 struct client_crypto_s *crypto, guchar *key, pinentry_cmd_t which)
842 gchar *prompt;
844 if (which == PINENTRY_SAVE) {
845 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
846 crypto->tkey = do_get_password(prompt);
847 g_free(prompt);
849 if (!crypto->tkey) {
850 log_write(N_("%s: Skipping file"), filename);
851 return GPG_ERR_BAD_PASSPHRASE;
854 prompt = g_strdup_printf(N_("Repeat passphrase: "));
855 crypto->tkey2 = do_get_password(prompt);
856 g_free(prompt);
858 if (!crypto->tkey2) {
859 log_write(N_("%s: Skipping file"), filename);
860 return GPG_ERR_BAD_PASSPHRASE;
863 if (strcmp(crypto->tkey, crypto->tkey2)) {
864 log_write(N_("%s: Passphrase mismatch"), filename);
865 return EPWMD_BADKEY;
868 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
869 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
870 return 0;
873 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
875 if ((crypto->tkey = do_get_password(prompt)) == NULL) {
876 log_write(N_("%s: Skipping file"), filename);
877 g_free(prompt);
878 return GPG_ERR_BAD_PASSPHRASE;
881 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
882 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
883 g_free(prompt);
884 return 0;
888 * inbuf must have been allocated with gcry_malloc().
890 gpg_error_t export_common(const gchar *filename, struct client_crypto_s *crypto,
891 gpointer inbuf, gulong insize)
893 gpg_error_t rc;
894 gint level, zrc;
895 gulong outsize;
896 gpointer outbuf;
898 rc = update_save_flags(NULL, crypto);
900 if (rc)
901 return rc;
903 level = get_key_file_integer(filename, "compression_level");
905 if (level < 0)
906 level = 0;
908 if (do_compress(NULL, level, inbuf, insize, &outbuf, &outsize, &zrc)
909 == FALSE) {
910 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
913 crypto->inbuf = outbuf;
914 crypto->insize = outsize;
915 rc = do_xml_encrypt(NULL, crypto, filename);
916 return rc;
919 static gpg_error_t get_password(const gchar *filename,
920 struct client_crypto_s *crypto, guchar *md5file, guchar *key,
921 pinentry_cmd_t which)
923 #ifdef WITH_PINENTRY
924 gpg_error_t rc = 0;
926 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
927 == FALSE) {
928 #endif
929 return get_input(filename, crypto, key, which);
930 #ifdef WITH_PINENTRY
932 else {
933 gchar *result = NULL;
934 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
936 pth_mutex_init(&pin->status_mutex);
937 set_pinentry_defaults(pin);
938 pin->which = which;
939 pin->filename = g_strdup(filename);
940 rc = pinentry_getpin(pin, &result);
942 if (rc) {
943 xfree(result);
944 goto done;
947 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, result ? strlen(result) : 1);
948 xfree(result);
949 cleanup_pinentry(pin);
952 done:
953 return rc;
954 #endif
957 static gboolean _getline(const gchar *file, gchar **result, gpg_error_t *rc)
959 FILE *fp;
960 gchar buf[LINE_MAX] = {0}, *p;
961 gchar *str = NULL;
962 gint len;
964 *rc = 0;
966 if ((fp = fopen(file, "r")) == NULL) {
967 *rc = gpg_error_from_syserror();
968 return FALSE;
971 p = fgets(buf, sizeof(buf), fp);
972 fclose(fp);
973 len = strlen(buf);
975 if (len && buf[len - 1] == '\n')
976 buf[--len] = 0;
978 str = gcry_malloc(len + 1);
980 if (!str) {
981 *rc = gpg_error_from_errno(ENOMEM);
982 return FALSE;
985 memcpy(str, buf, len ? len : 1);
986 str[len] = 0;
987 memset(&buf, 0, sizeof(buf));
988 *result = str;
989 return TRUE;
992 static gchar *parse_rcfile_keyfile(const gchar *filename, gboolean import,
993 gpg_error_t *rc)
995 GError *rv = NULL;
996 gchar *t, *file = NULL, *str;
998 *rc = GPG_ERR_UNKNOWN_ERRNO;
1000 if (import == FALSE) {
1001 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
1002 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
1004 if (!file) {
1005 if (rv) {
1006 log_write("%s: key_file: %s", rcfile, rv->message);
1007 g_clear_error(&rv);
1010 return NULL;
1013 t = expand_homedir(file);
1015 if (!t) {
1016 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1017 *rc = gpg_error_from_errno(ENOMEM);
1018 return NULL;
1021 g_free(file);
1022 file = t;
1025 else {
1026 /* -I or -C. The filename is a key file. */
1027 file = g_strdup(filename);
1029 if (!file) {
1030 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1031 *rc = gpg_error_from_errno(ENOMEM);
1032 return NULL;
1036 if (rv) {
1037 log_write("%s: key_file: %s", rcfile, rv->message);
1038 g_clear_error(&rv);
1039 return NULL;
1042 if (!file)
1043 return NULL;
1045 if (_getline(file, &str, rc) == FALSE) {
1046 log_write("%s: %s: %s", filename, file, pwmd_strerror(*rc));
1047 g_free(file);
1048 return NULL;
1051 g_free(file);
1052 *rc = 0;
1053 return str;
1056 static gboolean xml_import(const gchar *filename, const gchar *outfile,
1057 const gchar *keyfile, guint64 iter)
1059 xmlDocPtr doc;
1060 gint fd;
1061 struct stat st;
1062 gint len;
1063 xmlChar *xmlbuf;
1064 xmlChar *xml;
1065 gpg_error_t rc;
1066 struct client_crypto_s *crypto;
1067 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
1069 if (stat(filename, &st) == -1) {
1070 log_write("%s: %s", filename, strerror(errno));
1071 return FALSE;
1074 crypto = init_client_crypto();
1076 if (!crypto)
1077 return FALSE;
1079 crypto->key = gcry_malloc(hashlen);
1080 memset(crypto->key, 0, hashlen);
1082 if (!crypto->key) {
1083 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1084 goto fail;
1087 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
1088 filename, outfile);
1090 if (iter && keyfile) {
1091 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1093 if (!crypto->tkey)
1094 goto fail;
1096 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1097 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1099 else if (iter) {
1100 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
1102 if (rc)
1103 goto fail;
1106 if ((fd = open(filename, O_RDONLY)) == -1) {
1107 log_write("%s: %s", filename, strerror(errno));
1108 goto fail;
1111 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
1112 close(fd);
1113 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1114 goto fail;
1117 if (pth_read(fd, xmlbuf, st.st_size) == -1) {
1118 rc = errno;
1119 close(fd);
1120 errno = rc;
1121 log_write("%s: %s", filename, strerror(errno));
1122 goto fail;
1125 close(fd);
1126 xmlbuf[st.st_size] = 0;
1129 * Make sure the document validates.
1131 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
1132 log_write("xmlReadDoc() failed");
1133 gcry_free(xmlbuf);
1134 goto fail;
1137 gcry_free(xmlbuf);
1138 xmlDocDumpMemory(doc, &xml, &len);
1139 xmlFreeDoc(doc);
1141 if (!iter)
1142 memset(crypto->key, '!', hashlen);
1144 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
1146 if (!crypto->fh) {
1147 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1148 goto fail;
1151 crypto->fh->ver.fh2.iter = iter;
1152 rc = export_common(outfile, crypto, xml, len);
1153 xmlFree(xml);
1155 if (rc) {
1156 send_error(NULL, rc);
1157 goto fail;
1160 cleanup_crypto(&crypto);
1161 return TRUE;
1163 fail:
1164 cleanup_crypto(&crypto);
1165 return FALSE;
1168 gchar *get_key_file_string(const gchar *section, const gchar *what)
1170 gchar *val = NULL;
1171 GError *grc = NULL;
1173 MUTEX_LOCK(&rcfile_mutex);
1175 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1176 val = g_key_file_get_string(keyfileh, section, what, &grc);
1178 if (grc) {
1179 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1180 g_clear_error(&grc);
1183 else {
1184 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1185 val = g_key_file_get_string(keyfileh, "global", what, &grc);
1187 if (grc) {
1188 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1189 g_clear_error(&grc);
1194 MUTEX_UNLOCK(&rcfile_mutex);
1195 return val;
1198 gint get_key_file_integer(const gchar *section, const gchar *what)
1200 gint val = -1;
1201 GError *grc = NULL;
1203 MUTEX_LOCK(&rcfile_mutex);
1205 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
1206 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
1208 if (grc) {
1209 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1210 g_clear_error(&grc);
1213 else {
1214 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1215 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
1217 if (grc) {
1218 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1219 g_clear_error(&grc);
1224 MUTEX_UNLOCK(&rcfile_mutex);
1225 return val;
1228 gdouble get_key_file_double(const gchar *section, const gchar *what)
1230 gdouble val = -1;
1231 GError *grc = NULL;
1233 MUTEX_LOCK(&rcfile_mutex);
1235 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
1236 val = g_key_file_get_double(keyfileh, section ? section : "global", what, &grc);
1238 if (grc) {
1239 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1240 g_clear_error(&grc);
1243 else {
1244 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1245 val = g_key_file_get_double(keyfileh, "global", what, &grc);
1247 if (grc) {
1248 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1249 g_clear_error(&grc);
1254 MUTEX_UNLOCK(&rcfile_mutex);
1255 return val;
1258 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
1260 gboolean val = FALSE;
1261 GError *grc = NULL;
1263 MUTEX_LOCK(&rcfile_mutex);
1265 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL)
1266 == TRUE) {
1267 val = g_key_file_get_boolean(keyfileh, section ? section : "global",
1268 what, &grc);
1270 if (grc) {
1271 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1272 g_clear_error(&grc);
1275 else {
1276 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1277 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
1279 if (grc) {
1280 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1281 g_clear_error(&grc);
1286 MUTEX_UNLOCK(&rcfile_mutex);
1287 return val;
1290 static gboolean parse_rcfile_keys()
1292 gsize n;
1293 gchar **groups;
1294 gchar **p;
1295 gchar *str;
1297 groups = g_key_file_get_groups(keyfileh, &n);
1299 for (p = groups; *p; p++) {
1300 GError *rc = NULL;
1302 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE) {
1303 str = g_key_file_get_string(keyfileh, *p, "key", &rc);
1305 if (!str) {
1306 if (rc) {
1307 log_write("%s: key: %s", rcfile, rc->message);
1308 g_clear_error(&rc);
1310 continue;
1313 do_cache_push(*p, str);
1314 g_free(str);
1315 continue;
1318 if (rc) {
1319 log_write("%s: key: %s", rcfile, rc->message);
1320 g_clear_error(&rc);
1321 continue;
1324 gpg_error_t ret;
1325 str = parse_rcfile_keyfile(*p, FALSE, &ret);
1327 if (!str)
1328 continue;
1330 do_cache_push(*p, str);
1331 gcry_free(str);
1334 g_strfreev(groups);
1335 return TRUE;
1338 static gboolean do_cache_push(const gchar *filename, const gchar *password)
1340 guchar md5file[16];
1341 gint timeout;
1342 const gchar *p = filename;
1343 struct client_crypto_s *crypto;
1344 gpg_error_t rc;
1345 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
1347 while (isspace(*p))
1348 p++;
1350 if (!*p)
1351 return FALSE;
1353 if (valid_filename(p) == FALSE) {
1354 log_write(N_("%s: Invalid characters in filename"), p);
1355 return FALSE;
1358 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1360 if (access(p, R_OK|W_OK) != 0) {
1361 log_write("%s: %s", p, strerror(errno));
1362 return FALSE;
1365 crypto = init_client_crypto();
1367 if (!crypto)
1368 return FALSE;
1370 crypto->fh = read_file_header(filename, FALSE, &rc);
1372 if (!crypto->fh) {
1373 log_write("%s: %s", p, pwmd_strerror(rc));
1374 cleanup_crypto(&crypto);
1375 return FALSE;
1378 crypto->key = gcry_malloc(hashlen);
1380 if (!crypto->key) {
1381 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1382 cleanup_crypto(&crypto);
1383 return FALSE;
1386 log_write(N_("Adding '%s' to the file cache ..."), filename);
1388 if (crypto->fh->ver.fh2.iter <= 0ULL) {
1389 memset(crypto->key, '!', hashlen);
1390 goto try_decrypt;
1393 if (!password) {
1394 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1396 if (rc) {
1397 send_error(NULL, rc);
1398 cleanup_crypto(&crypto);
1399 return FALSE;
1402 gcry_free(crypto->fh->doc);
1403 crypto->fh->doc = NULL;
1405 else
1406 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password,
1407 strlen(password) ? strlen(password) : 1);
1409 try_decrypt:
1410 rc = try_xml_decrypt(NULL, crypto->key, crypto, NULL, NULL);
1412 if (rc) {
1413 log_write("%s: %s", filename, pwmd_strerror(rc));
1414 cleanup_crypto(&crypto);
1415 return FALSE;
1418 if (cache_update_key(md5file, crypto->key) == FALSE) {
1419 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1420 cleanup_crypto(&crypto);
1421 return FALSE;
1424 timeout = get_key_file_integer(p, "cache_timeout");
1425 cache_set_timeout(md5file, timeout);
1426 log_write(N_("File '%s' now cached"), filename);
1427 cleanup_crypto(&crypto);
1428 return TRUE;
1431 static void init_new_connection(gint fd)
1433 pth_attr_t attr;
1434 struct client_thread_s *new;
1435 gint n;
1437 new = g_malloc0(sizeof(struct client_thread_s));
1439 if (!new) {
1440 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1441 close(fd);
1442 return;
1445 MUTEX_LOCK(&cn_mutex);
1446 new->fd = fd;
1447 attr = pth_attr_new();
1448 pth_attr_init(attr);
1449 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1450 new->tid = pth_spawn(attr, client_thread, new);
1451 n = errno;
1452 pth_attr_destroy(attr);
1454 if (!new->tid) {
1455 g_free(new);
1456 close(fd);
1457 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1458 _gpg_strerror(gpg_error_from_errno(n)));
1459 MUTEX_UNLOCK(&cn_mutex);
1460 return;
1463 cn_thread_list = g_slist_append(cn_thread_list, new);
1464 MUTEX_UNLOCK(&cn_mutex);
1465 log_write(N_("new connection: tid=%p, fd=%i"), new->tid, fd);
1468 static void *accept_thread(void *arg)
1470 gint sockfd = (gint)arg;
1471 pth_attr_t attr = pth_attr_of(pth_self());
1473 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1474 pth_attr_destroy(attr);
1476 for (;;) {
1477 socklen_t slen = sizeof(struct sockaddr_un);
1478 struct sockaddr_un raddr;
1479 gint fd = -1;
1481 fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen);
1483 if (fd == -1) {
1484 if (errno != EAGAIN) {
1485 if (!quit) // probably EBADF
1486 log_write("accept(): %s", strerror(errno));
1488 break;
1491 continue;
1494 init_new_connection(fd);
1497 /* Just in case accept() failed for some reason other than EBADF */
1498 quit = 1;
1499 pth_exit(PTH_CANCELED);
1500 return NULL;
1503 static void *adjust_cache_timer_thread(void *arg)
1505 pth_attr_t attr = pth_attr_of(pth_self());
1507 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1508 pth_attr_destroy(attr);
1510 for (;;) {
1511 pth_sleep(1);
1512 CACHE_LOCK(NULL);
1513 cache_adjust_timer();
1514 CACHE_UNLOCK;
1517 return NULL;
1520 void cleanup_mutex_cb(void *arg)
1522 pth_mutex_t *m = arg;
1524 MUTEX_UNLOCK(m);
1527 void cleanup_ev_cb(void *arg)
1529 pth_event_t ev = arg;
1531 pth_event_free(ev, PTH_FREE_ALL);
1534 void cleanup_fd_cb(void *arg)
1536 gint fd = (gint)arg;
1538 close(fd);
1541 void cleanup_unlink_cb(void *arg)
1543 gchar *file = arg;
1545 unlink(file);
1548 void cleanup_cancel_cb(void *arg)
1550 pth_t tid = arg;
1552 pth_cancel(tid);
1555 static void *keepalive_thread(void *arg)
1557 gint to = (gint)arg;
1558 pth_attr_t attr = pth_attr_of(pth_self());
1560 pth_attr_set(attr, PTH_ATTR_NAME, __FUNCTION__);
1561 pth_attr_destroy(attr);
1563 for (;;) {
1564 pth_event_t ev = pth_event(PTH_EVENT_TIME, pth_timeout(to, 0));
1566 pth_cleanup_push(cleanup_ev_cb, ev);
1567 pth_wait(ev);
1568 send_status_all(STATUS_KEEPALIVE);
1569 pth_cleanup_pop(1);
1572 return NULL;
1575 static void startStopKeepAlive(gboolean term)
1577 gint n = get_key_file_integer("global", "keepalive");
1579 if (keepalive_tid)
1580 pth_cancel(keepalive_tid);
1582 keepalive_tid = NULL;
1584 if (term)
1585 return;
1587 if (n > 0) {
1588 gint e;
1589 pth_attr_t attr = pth_attr_new();
1591 pth_attr_init(attr);
1592 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1593 keepalive_tid = pth_spawn(attr, keepalive_thread, (void *)n);
1594 e = errno;
1595 pth_attr_destroy(attr);
1597 if (!keepalive_tid) {
1598 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1599 _gpg_strerror(gpg_error_from_errno(e)));
1600 return;
1603 pth_yield(keepalive_tid);
1607 static gboolean waiting_for_exit()
1609 guint i, t;
1610 pth_event_t evs = NULL;
1612 MUTEX_LOCK(&cn_mutex);
1614 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
1615 struct client_thread_s *thd = g_slist_nth_data(cn_thread_list, i);
1616 pth_event_t ev = pth_event(PTH_EVENT_TID|PTH_UNTIL_TID_DEAD, thd->tid);
1618 if (evs)
1619 evs = pth_event_concat(evs, ev, NULL);
1620 else
1621 evs = ev;
1624 MUTEX_UNLOCK(&cn_mutex);
1626 if (!evs)
1627 return FALSE;
1629 pth_wait(evs);
1630 MUTEX_LOCK(&cn_mutex);
1631 i = g_slist_length(cn_thread_list);
1632 MUTEX_UNLOCK(&cn_mutex);
1633 pth_event_free(evs, PTH_FREE_ALL);
1634 return i ? TRUE : FALSE;
1637 static void server_loop(gint sockfd, gchar **socketpath)
1639 pth_t accept_tid;
1640 guint n;
1641 sigset_t sigset;
1642 pth_attr_t attr;
1643 pth_t cache_timeout_tid;
1645 sigemptyset(&sigset);
1647 /* Termination */
1648 sigaddset(&sigset, SIGTERM);
1649 sigaddset(&sigset, SIGINT);
1651 /* Clears the file cache. */
1652 sigaddset(&sigset, SIGUSR1);
1654 /* Configuration file reloading. */
1655 sigaddset(&sigset, SIGHUP);
1657 /* Clears the cache and exits when something bad happens. */
1658 sigaddset(&sigset, SIGABRT);
1660 /* Ignored everywhere. When a client disconnects abnormally this signal
1661 * gets raised. It isn't needed though because client_thread() will check
1662 * for rcs even after the client disconnects. */
1663 signal(SIGPIPE, SIG_IGN);
1664 sigprocmask(SIG_BLOCK, &sigset, NULL);
1666 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1667 log_write(N_("Listening on %s"), *socketpath);
1668 attr = pth_attr_new();
1669 pth_attr_init(attr);
1670 accept_tid = pth_spawn(attr, accept_thread, (void *)sockfd);
1672 if (!accept_tid) {
1673 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1674 _gpg_strerror(gpg_error_from_errno(errno)));
1675 pth_attr_destroy(attr);
1676 goto done;
1679 pth_yield(accept_tid);
1680 startStopKeepAlive(FALSE);
1681 pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
1682 cache_timeout_tid = pth_spawn(attr, adjust_cache_timer_thread, NULL);
1684 if (!cache_timeout_tid) {
1685 log_write("%s(%i): pth_spawn(): %s", __FILE__, __LINE__,
1686 _gpg_strerror(gpg_error_from_errno(errno)));
1687 pth_attr_destroy(attr);
1688 goto done;
1691 pth_yield(cache_timeout_tid);
1692 pth_attr_destroy(attr);
1694 do {
1695 gint sig;
1697 pth_sigwait(&sigset, &sig);
1698 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1700 /* Caught a signal. */
1701 switch (sig) {
1702 case SIGHUP:
1703 reload_rcfile();
1704 break;
1705 case SIGABRT:
1706 cache_clear(NULL, 2);
1707 #ifndef MEM_DEBUG
1708 xpanic();
1709 #endif
1710 exit(EXIT_FAILURE);
1711 case SIGUSR1:
1712 CACHE_LOCK(NULL);
1713 log_write(N_("clearing file cache"));
1714 cache_clear(NULL, 2);
1715 CACHE_UNLOCK;
1716 break;
1717 default:
1718 quit = 1;
1719 break;
1721 } while (!quit);
1723 done:
1725 * We're out of the main server loop. This happens when a signal was sent
1726 * to terminate the daemon. We'll wait for all clients to disconnect
1727 * before exiting and ignore any following signals.
1729 shutdown(sockfd, SHUT_RDWR);
1730 close(sockfd);
1731 pth_cancel(accept_tid);
1732 pth_join(accept_tid, NULL);
1733 unlink(*socketpath);
1734 g_free(*socketpath);
1735 *socketpath = NULL;
1736 MUTEX_LOCK(&cn_mutex);
1737 n = g_slist_length(cn_thread_list);
1738 MUTEX_UNLOCK(&cn_mutex);
1740 if (n) {
1741 log_write(N_("waiting for all clients to disconnect"));
1743 do {
1744 MUTEX_LOCK(&cn_mutex);
1745 n = g_slist_length(cn_thread_list);
1746 MUTEX_UNLOCK(&cn_mutex);
1747 log_write(N_("%i clients remain"), n);
1748 } while (waiting_for_exit());
1751 startStopKeepAlive(TRUE);
1752 pth_cancel(cache_timeout_tid);
1753 cache_free();
1757 * Only called from pinentry_fork() in the child process.
1759 void free_client_list()
1761 gint i, t = g_slist_length(cn_thread_list);
1763 for (i = 0; i < t; i++) {
1764 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1766 free_client(cn->cl);
1769 cache_free();
1772 static guint pwmd_cipher_to_gcrypt(guint64 flags)
1774 if (flags & PWMD_CIPHER_AES128)
1775 return GCRY_CIPHER_AES128;
1776 else if (flags & PWMD_CIPHER_AES192)
1777 return GCRY_CIPHER_AES192;
1778 else if (flags & PWMD_CIPHER_AES256)
1779 return GCRY_CIPHER_AES256;
1780 else if (flags & PWMD_CIPHER_SERPENT128)
1781 return GCRY_CIPHER_SERPENT128;
1782 else if (flags & PWMD_CIPHER_SERPENT192)
1783 return GCRY_CIPHER_SERPENT192;
1784 else if (flags & PWMD_CIPHER_SERPENT256)
1785 return GCRY_CIPHER_SERPENT256;
1786 else if (flags & PWMD_CIPHER_CAMELLIA128)
1787 return GCRY_CIPHER_CAMELLIA128;
1788 else if (flags & PWMD_CIPHER_CAMELLIA192)
1789 return GCRY_CIPHER_CAMELLIA192;
1790 else if (flags & PWMD_CIPHER_CAMELLIA256)
1791 return GCRY_CIPHER_CAMELLIA256;
1792 else if (flags & PWMD_CIPHER_BLOWFISH)
1793 return GCRY_CIPHER_BLOWFISH;
1794 else if (flags & PWMD_CIPHER_3DES)
1795 return GCRY_CIPHER_3DES;
1796 else if (flags & PWMD_CIPHER_CAST5)
1797 return GCRY_CIPHER_CAST5;
1798 else if (flags & PWMD_CIPHER_TWOFISH)
1799 return GCRY_CIPHER_TWOFISH;
1800 else if (flags & PWMD_CIPHER_TWOFISH128)
1801 return GCRY_CIPHER_TWOFISH128;
1803 /* For backwards compatibility (no flags). */
1804 return GCRY_CIPHER_AES256;
1807 guint pwmd_cipher_str_to_cipher(const gchar *str)
1809 guint64 flags = 0;
1811 if (!g_strcasecmp(str, "aes128"))
1812 flags = PWMD_CIPHER_AES128;
1813 else if (!g_strcasecmp(str, "aes192"))
1814 flags = PWMD_CIPHER_AES192;
1815 else if (!g_strcasecmp(str, "aes256"))
1816 flags = PWMD_CIPHER_AES256;
1817 if (!g_strcasecmp(str, "serpent128"))
1818 flags = PWMD_CIPHER_SERPENT128;
1819 else if (!g_strcasecmp(str, "serpent192"))
1820 flags = PWMD_CIPHER_SERPENT192;
1821 else if (!g_strcasecmp(str, "serpent256"))
1822 flags = PWMD_CIPHER_SERPENT256;
1823 if (!g_strcasecmp(str, "camellia128"))
1824 flags = PWMD_CIPHER_CAMELLIA128;
1825 else if (!g_strcasecmp(str, "camellia192"))
1826 flags = PWMD_CIPHER_CAMELLIA192;
1827 else if (!g_strcasecmp(str, "camellia256"))
1828 flags = PWMD_CIPHER_CAMELLIA256;
1829 else if (!g_strcasecmp(str, "blowfish"))
1830 flags = PWMD_CIPHER_BLOWFISH;
1831 else if (!g_strcasecmp(str, "cast5"))
1832 flags = PWMD_CIPHER_CAST5;
1833 else if (!g_strcasecmp(str, "3des"))
1834 flags = PWMD_CIPHER_3DES;
1835 else if (!g_strcasecmp(str, "twofish256"))
1836 flags = PWMD_CIPHER_TWOFISH;
1837 else if (!g_strcasecmp(str, "twofish128"))
1838 flags = PWMD_CIPHER_TWOFISH128;
1840 return flags;
1843 /* To be called after read_file_header(). This sets the wanted algorithm from
1844 * .flags */
1845 gpg_error_t init_client_crypto2(const char *filename,
1846 struct client_crypto_s *crypto)
1848 gpg_error_t rc;
1849 guint algo;
1851 /* New file or conversion. */
1852 if (crypto->fh->v1)
1853 algo = pwmd_cipher_to_gcrypt(PWMD_CIPHER_AES256);
1854 else if (!crypto->fh->ver.fh2.flags) {
1855 gchar *tmp = get_key_file_string(filename ? filename : "global", "cipher");
1856 guint64 flags;
1858 flags = pwmd_cipher_str_to_cipher(tmp);
1859 g_free(tmp);
1860 algo = pwmd_cipher_to_gcrypt(flags);
1861 crypto->fh->ver.fh2.flags = flags;
1863 else
1864 algo = pwmd_cipher_to_gcrypt(crypto->fh->ver.fh2.flags);
1866 rc = gcry_cipher_algo_info(algo, GCRYCTL_TEST_ALGO, NULL, NULL);
1868 if (rc)
1869 return rc;
1871 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL,
1872 &crypto->keysize);
1874 if (rc)
1875 return rc;
1877 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_BLKLEN, NULL,
1878 &crypto->blocksize);
1880 if (rc)
1881 return rc;
1883 if (crypto->gh)
1884 gcry_cipher_close(crypto->gh);
1886 return gcry_cipher_open(&crypto->gh, algo, GCRY_CIPHER_MODE_CBC, 0);
1889 struct client_crypto_s *init_client_crypto()
1891 struct client_crypto_s *new = g_malloc0(sizeof(struct client_crypto_s));
1893 if (!new) {
1894 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1895 return NULL;
1898 return new;
1901 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
1902 const gchar *outfile)
1904 gpg_error_t rc;
1905 guchar md5file[gcry_md_get_algo_dlen(GCRY_MD_MD5)];
1906 guint64 iter;
1907 struct client_crypto_s *crypto = init_client_crypto();
1908 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
1910 if (!crypto)
1911 return GPG_ERR_ENOMEM;
1913 crypto->key = gcry_malloc(hashlen);
1915 if (!crypto->key) {
1916 cleanup_crypto(&crypto);
1917 return GPG_ERR_ENOMEM;
1920 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
1921 filename);
1922 crypto->fh = read_file_header(filename, TRUE, &rc);
1924 if (!crypto->fh)
1925 goto done;
1927 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
1929 /* The header in version 1 had a bug where the iterations were off-by-one.
1930 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
1931 * header.
1933 if (crypto->fh->ver.fh1.iter >= 0ULL) {
1934 if (keyfile) {
1935 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1937 if (!crypto->tkey)
1938 goto done;
1940 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1941 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1943 else {
1944 rc = get_password(filename, crypto, md5file, crypto->key,
1945 PINENTRY_OPEN);
1947 if (rc)
1948 goto done;
1952 rc = update_save_flags(NULL, crypto);
1954 if (rc)
1955 goto done;
1957 rc = try_xml_decrypt(NULL, crypto->key, crypto, &crypto->fh->doc,
1958 &crypto->fh->len);
1960 if (rc)
1961 goto done;
1963 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
1965 if (rc) {
1966 log_write("%s: %s", filename, pwmd_strerror(rc));
1967 goto done;
1970 crypto->fh->v1 = FALSE;
1971 iter = crypto->fh->ver.fh1.iter;
1972 memset(&crypto->fh->ver.fh2, 0, sizeof(crypto->fh->ver.fh2));
1973 /* Keep the iterations and key from the original file. */
1974 crypto->fh->ver.fh2.iter = iter+1ULL; // Bugfix for v1 data files.
1975 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
1977 done:
1978 if (rc)
1979 send_error(NULL, rc);
1981 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
1982 cleanup_crypto(&crypto);
1983 return rc;
1986 int main(int argc, char *argv[])
1988 gint opt;
1989 struct sockaddr_un addr;
1990 gchar buf[PATH_MAX];
1991 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
1992 gchar *socketarg = NULL;
1993 gchar *datadir = NULL;
1994 gboolean n;
1995 gint x;
1996 gchar *p;
1997 gchar **cache_push = NULL;
1998 gchar *import = NULL, *keyfile = NULL;
1999 guint64 cmd_iterations = -1ULL;
2000 gint default_timeout;
2001 gboolean rcfile_spec = FALSE;
2002 gint estatus = EXIT_FAILURE;
2003 gint sockfd;
2004 gchar *outfile = NULL;
2005 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
2006 gint do_unlink = 1;
2007 gboolean secure = FALSE;
2008 gint background = 1;
2009 gchar *convert = NULL;
2010 gint show_version = 0;
2011 gint show_help = 0;
2012 #ifdef WITH_PINENTRY
2013 gboolean disable_pinentry = FALSE;
2014 #endif
2015 gint opt_index;
2016 const struct option long_opts[] = {
2017 #ifdef WITH_PINENTRY
2018 { "no-pinentry", 0, 0, 'P' },
2019 #endif
2020 { "outfile", 1, 0, 'o' },
2021 { "convert", 1, 0, 'C' },
2022 { "no-fork", 0, 0, 'n' },
2023 { "disable-dump", 0, 0, 'D' },
2024 { "import", 1, 0, 'I' },
2025 { "iterations", 1, 0, 'i' },
2026 { "key-file", 1, 0, 'k' },
2027 { "rcfile", 1, 0, 'f' },
2028 { "version", 0, &show_version, 1 },
2029 { "help", 0, &show_help, 1 },
2030 { 0, 0, 0, 0}
2032 #ifdef WITH_PINENTRY
2033 const gchar *optstring = "Po:C:nDI:i:k:f:";
2034 #else
2035 const gchar *optstring = "o:C:nDI:i:k:f:";
2036 #endif
2037 #ifndef DEBUG
2038 #ifdef HAVE_SETRLIMIT
2039 struct rlimit rl;
2041 rl.rlim_cur = rl.rlim_max = 0;
2043 if (setrlimit(RLIMIT_CORE, &rl) != 0)
2044 err(EXIT_FAILURE, "setrlimit()");
2045 #endif
2046 #endif
2048 #ifdef ENABLE_NLS
2049 setlocale(LC_ALL, "");
2050 bindtextdomain("pwmd", LOCALEDIR);
2051 textdomain("pwmd");
2052 #endif
2054 #ifndef MEM_DEBUG
2055 xmem_init();
2056 #endif
2057 setup_gcrypt();
2058 gpg_err_init();
2059 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
2060 g_mem_set_vtable(&mtable);
2061 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
2062 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
2063 xmlInitMemory();
2064 xmlInitGlobals();
2065 xmlInitParser();
2066 xmlXPathInit();
2067 g_snprintf(buf, sizeof(buf), "%s/.pwmd", g_get_home_dir());
2069 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2070 err(EXIT_FAILURE, "%s", buf);
2072 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", g_get_home_dir());
2074 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2075 err(EXIT_FAILURE, "%s", buf);
2077 cmdline = TRUE;
2079 while ((opt = getopt_long(argc, argv, optstring, long_opts, &opt_index)) != -1) {
2080 switch (opt) {
2081 case 0:
2082 if (show_help)
2083 usage(argv[0], EXIT_SUCCESS);
2085 if (show_version) {
2086 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,
2087 PACKAGE_BUGREPORT,
2088 #ifdef WITH_PINENTRY
2089 "+WITH_PINENTRY\n"
2090 #else
2091 "-WITH_PINENTRY\n"
2092 #endif
2093 #ifdef WITH_QUALITY
2094 "+WITH_QUALITY\n"
2095 #else
2096 "-WITH_QUALITY\n"
2097 #endif
2098 #ifdef WITH_LIBACL
2099 "+WITH_LIBACL\n"
2100 #else
2101 "-WITH_LIBACL\n"
2102 #endif
2103 #ifdef DEBUG
2104 "+DEBUG\n"
2105 #else
2106 "-DEBUG\n"
2107 #endif
2108 #ifdef MEM_DEBUG
2109 "+MEM_DEBUG\n"
2110 #else
2111 "-MEM_DEBUG\n"
2112 #endif
2114 exit(EXIT_SUCCESS);
2116 break;
2117 #ifdef WITH_PINENTRY
2118 case 'P':
2119 disable_pinentry = TRUE;
2120 break;
2121 #endif
2122 case 'o':
2123 outfile = optarg;
2124 break;
2125 case 'C':
2126 convert = optarg;
2127 break;
2128 case 'n':
2129 background = 0;
2130 break;
2131 case 'D':
2132 secure = TRUE;
2133 break;
2134 case 'I':
2135 import = optarg;
2136 break;
2137 case 'i':
2138 cmd_iterations = strtoll(optarg, NULL, 10);
2139 break;
2140 case 'k':
2141 keyfile = optarg;
2142 break;
2143 case 'f':
2144 rcfile = g_strdup(optarg);
2145 rcfile_spec = TRUE;
2146 break;
2147 default:
2148 usage(argv[0], EXIT_FAILURE);
2152 pth_mutex_init(&cn_mutex);
2153 pth_mutex_init(&cache_mutex);
2154 pth_mutex_init(&rcfile_mutex);
2155 #ifdef WITH_PINENTRY
2156 pth_mutex_init(&pin_mutex);
2157 #endif
2159 if (!rcfile)
2160 rcfile = g_strdup_printf("%s/.pwmd/config", g_get_home_dir());
2162 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
2163 exit(EXIT_FAILURE);
2165 #ifdef WITH_PINENTRY
2166 if (disable_pinentry == TRUE)
2167 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
2168 #endif
2170 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
2171 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
2173 if (log_syslog == TRUE)
2174 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
2176 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
2177 x = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
2178 errno = 0;
2180 if (setpriority(PRIO_PROCESS, 0, x) == -1) {
2181 log_write("setpriority(): %s", strerror(errno));
2182 goto do_exit;
2186 #ifdef HAVE_MLOCKALL
2187 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
2188 log_write("mlockall(): %s", strerror(errno));
2189 goto do_exit;
2191 #endif
2193 if (convert) {
2194 if (!outfile)
2195 usage(argv[0], EXIT_FAILURE);
2197 opt = convert_file(convert, keyfile, outfile);
2198 g_key_file_free(keyfileh);
2199 g_free(rcfile);
2200 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
2203 if (import) {
2204 if (!outfile)
2205 usage(argv[0], EXIT_FAILURE);
2207 if (cmd_iterations == -1ULL)
2208 cmd_iterations = (guint64)get_key_file_double("global", "iterations");
2210 opt = xml_import(import, outfile, keyfile, cmd_iterations);
2211 g_key_file_free(keyfileh);
2212 g_free(rcfile);
2213 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
2216 g_key_file_set_list_separator(keyfileh, ',');
2218 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
2219 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
2221 socketarg = expand_homedir(p);
2222 g_free(p);
2224 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
2225 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
2227 datadir = expand_homedir(p);
2228 g_free(p);
2230 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
2231 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
2232 disable_list_and_dump = n;
2234 else
2235 disable_list_and_dump = secure;
2237 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
2238 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
2239 else
2240 default_timeout = -1;
2242 setup_logging(keyfileh);
2244 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2245 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2247 if (argc != optind) {
2248 for (; optind < argc; optind++) {
2249 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2250 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
2254 if (strchr(socketarg, '/') == NULL) {
2255 socketdir = g_get_current_dir();
2256 socketname = g_strdup(socketarg);
2257 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2259 else {
2260 socketname = g_strdup(strrchr(socketarg, '/'));
2261 socketname++;
2262 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2263 socketdir = g_strdup(socketarg);
2264 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2267 if (chdir(datadir)) {
2268 log_write("%s: %s", datadir, strerror(errno));
2269 unlink(socketpath);
2270 goto do_exit;
2273 if (parse_rcfile_keys() == FALSE)
2274 goto do_exit;
2276 clear_rcfile_keys();
2279 * Set the cache entry for a file. Prompts for the password.
2281 if (cache_push) {
2282 for (opt = 0; cache_push[opt]; opt++)
2283 do_cache_push(cache_push[opt], NULL);
2285 g_strfreev(cache_push);
2286 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2290 * bind() doesn't like the full pathname of the socket or any non alphanum
2291 * characters so change to the directory where the socket is wanted then
2292 * create it then change to datadir.
2294 if (chdir(socketdir)) {
2295 log_write("%s: %s", socketdir, strerror(errno));
2296 goto do_exit;
2299 g_free(socketdir);
2301 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2302 log_write("socket(): %s", strerror(errno));
2303 goto do_exit;
2306 addr.sun_family = AF_UNIX;
2307 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2309 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2310 log_write("bind(): %s", strerror(errno));
2312 if (errno == EADDRINUSE)
2313 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2314 "stale socket. Please remove it manually."), socketpath);
2316 do_unlink = 0;
2317 goto do_exit;
2320 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2321 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2322 mode_t mode = strtol(t, NULL, 8);
2323 mode_t mask = umask(0);
2325 g_free(t);
2327 if (chmod(socketname, mode) == -1) {
2328 log_write("%s: %s", socketname, strerror(errno));
2329 close(sockfd);
2330 unlink(socketpath);
2331 umask(mask);
2332 goto do_exit;
2335 umask(mask);
2338 g_free(--socketname);
2340 if (chdir(datadir)) {
2341 log_write("%s: %s", datadir, strerror(errno));
2342 close(sockfd);
2343 unlink(socketpath);
2344 goto do_exit;
2347 g_free(datadir);
2349 if (listen(sockfd, 0) == -1) {
2350 log_write("listen(): %s", strerror(errno));
2351 goto do_exit;
2354 cmdline = FALSE;
2356 if (background) {
2357 switch (fork()) {
2358 case -1:
2359 log_write("fork(): %s", strerror(errno));
2360 goto do_exit;
2361 case 0:
2362 close(0);
2363 close(1);
2364 close(2);
2365 setsid();
2366 break;
2367 default:
2368 exit(EXIT_SUCCESS);
2372 server_loop(sockfd, &socketpath);
2373 estatus = EXIT_SUCCESS;
2375 do_exit:
2376 if (socketpath && do_unlink) {
2377 unlink(socketpath);
2378 g_free(socketpath);
2381 g_key_file_free(keyfileh);
2382 g_free(rcfile);
2383 xmlCleanupParser();
2384 xmlCleanupGlobals();
2386 if (estatus == EXIT_SUCCESS)
2387 log_write(N_("pwmd exiting normally"));
2389 #if defined(DEBUG) && !defined(MEM_DEBUG)
2390 xdump();
2391 #endif
2392 exit(estatus);