Create the client_msg_thread and client_msg_sender_thread as joinable
[pwmd.git] / src / pwmd.c
blobce32f6235cdcea64d7ea67871ad414aae644bd7d
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>
49 #ifdef HAVE_SETRLIMIT
50 #include <sys/time.h>
51 #include <sys/resource.h>
52 #endif
54 #ifdef TM_IN_SYS_TIME
55 #include <sys/time.h>
56 #else
57 #include <time.h>
58 #endif
60 #ifndef MEM_DEBUG
61 #include "mem.h"
62 #endif
64 #include "xml.h"
65 #include "common.h"
67 #ifdef WITH_PINENTRY
68 #include "pinentry.h"
69 #endif
71 #ifdef WITH_GNUTLS
72 #include "tls.h"
73 #endif
74 #include "commands.h"
75 #include "pwmd_error.h"
76 #include "cache.h"
77 #include "misc.h"
78 #include "pwmd.h"
80 GCRY_THREAD_OPTION_PTHREAD_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 gboolean startStopTcp(gboolean term);
101 static void reload_rcfile()
103 gboolean b = disable_list_and_dump;
104 GKeyFile *k;
106 log_write(N_("reloading configuration file '%s'"), rcfile);
107 k = parse_rcfile(FALSE);
109 if (!k)
110 return;
112 g_key_file_free(keyfileh);
113 keyfileh = k;
114 parse_rcfile_keys();
115 clear_rcfile_keys();
116 disable_list_and_dump = b;
117 startStopTcp(FALSE);
118 //FIXME keepalive thread restart
119 send_status_all(STATUS_CONFIG);
122 gpg_error_t send_syserror(assuan_context_t ctx, gint e)
124 gpg_error_t n = gpg_error_from_errno(e);
126 return assuan_process_done(ctx, assuan_set_error(ctx, n, gpg_strerror(n)));
129 gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e)
131 gpg_err_code_t n = gpg_err_code(e);
132 gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n);
133 struct client_s *client = assuan_get_pointer(ctx);
135 if (!e)
136 return assuan_process_done(ctx, 0);
138 if (!ctx) {
139 log_write("%s", pwmd_strerror(e));
140 return e;
143 if (n == EPWMD_LIBXML_ERROR) {
144 xmlErrorPtr xe = client->xml_error;
146 if (!xe)
147 xe = xmlGetLastError();
149 e = assuan_process_done(ctx, assuan_set_error(ctx, code, xe->message));
150 log_write("%s", xe->message);
152 if (xe == client->xml_error)
153 xmlResetError(xe);
154 else
155 xmlResetLastError();
157 client->xml_error = NULL;
158 return e;
161 return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e)));
164 static struct client_thread_s *find_thread(pthread_t tid)
166 guint t, i;
168 pthread_mutex_lock(&cn_mutex);
170 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
171 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
173 if (cn->tid == tid) {
174 pthread_mutex_unlock(&cn_mutex);
175 return cn;
179 pthread_mutex_unlock(&cn_mutex);
180 return NULL;
183 void log_write(const gchar *fmt, ...)
185 gchar *args, *line;
186 va_list ap;
187 struct tm *tm;
188 time_t now;
189 gchar tbuf[21];
190 gint fd = -1;
191 struct client_thread_s *cn;
192 gchar *name = "";
193 gchar buf[255];
195 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
196 return;
198 if (!cmdline && logfile) {
199 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
200 warn("%s", logfile);
201 return;
205 va_start(ap, fmt);
207 if (g_vasprintf(&args, fmt, ap) == -1) {
208 if (logfile)
209 close(fd);
211 va_end(ap);
212 return;
215 va_end(ap);
217 if (cmdline) {
218 fprintf(stderr, "%s\n", args);
219 fflush(stderr);
220 g_free(args);
221 return;
224 cn = find_thread(pthread_self());
226 if (cn) {
227 if (!cn->name)
228 name = print_fmt(buf, sizeof(buf), "%i: ", cn->fd);
229 else
230 name = print_fmt(buf, sizeof(buf), "%s(%i): ", cn->name, cn->fd);
233 if (!cmdline && log_syslog == TRUE)
234 syslog(LOG_INFO, "%s%s", name, args);
236 time(&now);
237 tm = localtime(&now);
238 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
239 tbuf[sizeof(tbuf) - 1] = 0;
241 if (args[strlen(args)-1] == '\n')
242 args[strlen(args)-1] = 0;
244 line = g_strdup_printf("%s %i %s%s\n", tbuf, getpid(), name, args);
245 g_free(args);
247 if (!line) {
248 if (logfile)
249 close(fd);
251 return;
254 if (logfile) {
255 write(fd, line, strlen(line));
256 fsync(fd);
257 close(fd);
260 if (isatty(STDERR_FILENO)) {
261 fprintf(stderr, "%s", line);
262 fflush(stderr);
265 g_free(line);
268 static void usage(gchar *pn)
270 g_fprintf(stderr, N_(
271 "Usage: %s [-hvDnP] [-f <rcfile>] [-C <filename>] "
272 "[-I <filename> [-i <iter>]]\n "
273 "[-k <keyfile>] [-o <outfile>] [file1] [...]\n"
274 " -n run as a foreground process\n"
275 " -f load the specified rcfile (~/.pwmd/config)\n"
276 " -C convert a version 1 data file to version 2\n"
277 " -I import an XML file\n"
278 " -i encrypt with the specified number of iterations when importing\n"
279 " (config default in the \"global\" section)\n"
280 " -k obtain the key from the specified file\n"
281 " -o output file for use with the -C and -I options\n"
282 " -D disable use of the LIST and DUMP commands\n"
283 " -P disable pinentry\n"
284 " -v version\n"
285 " -h this help text\n"
286 ), pn);
287 exit(EXIT_FAILURE);
290 #ifndef MEM_DEBUG
291 static int gcry_SecureCheck(const void *ptr)
293 return 1;
295 #endif
297 static void setup_gcrypt()
299 gcry_check_version(NULL);
301 #ifndef MEM_DEBUG
302 gcry_set_allocation_handler(xmalloc, xmalloc, gcry_SecureCheck, xrealloc,
303 xfree);
304 #endif
306 if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, NULL,
307 NULL) != 0)
308 errx(EXIT_FAILURE, N_("Required AES cipher not supported by libgcrypt."));
310 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_KEYLEN, NULL, &gcrykeysize);
311 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_BLKLEN, NULL, &gcryblocksize);
314 static gint new_connection(struct client_s *cl)
316 gpg_error_t rc;
317 gchar ver[ASSUAN_LINELENGTH];
319 rc = assuan_init_socket_server_ext(&cl->ctx, cl->thd->fd, 2);
321 if (rc)
322 goto fail;
324 assuan_set_pointer(cl->ctx, cl);
325 g_snprintf(ver, sizeof(ver), "%s", PACKAGE_STRING);
326 assuan_set_hello_line(cl->ctx, ver);
327 rc = register_commands(cl->ctx);
329 if (rc)
330 goto fail;
332 rc = assuan_accept(cl->ctx);
334 if (rc)
335 goto fail;
337 return 0;
339 fail:
340 log_write("%s", gpg_strerror(rc));
341 return 1;
344 gpg_error_t send_status(assuan_context_t ctx, status_msg_t which,
345 const gchar *fmt, ...)
347 gchar *line = NULL;
348 struct client_s *client = assuan_get_pointer(ctx);
349 gchar buf[ASSUAN_LINELENGTH];
350 gchar *status = NULL;
351 va_list ap;
353 if (fmt) {
354 va_start(ap, fmt);
355 g_vsnprintf(buf, sizeof(buf), fmt, ap);
356 va_end(ap);
357 line = buf;
360 switch (which) {
361 case STATUS_CACHE:
362 CACHE_LOCK(client->ctx);
363 line = print_fmt(buf, sizeof(buf), "%i", cache_file_count());
364 CACHE_UNLOCK;
365 status = "CACHE";
366 break;
367 case STATUS_CLIENTS:
368 pthread_mutex_lock(&cn_mutex);
369 line = print_fmt(buf, sizeof(buf), "%i", g_slist_length(cn_thread_list));
370 pthread_mutex_unlock(&cn_mutex);
371 status = "CLIENTS";
372 break;
373 case STATUS_CONFIG:
374 status = "CONFIG";
375 break;
376 case STATUS_KEEPALIVE:
377 status = "KEEPALIVE";
378 break;
379 case STATUS_LOCKED:
380 status = "LOCKED";
381 line = N_("Waiting for lock");
382 break;
383 case STATUS_ENCRYPT:
384 status = "ENCRYPT";
385 break;
386 case STATUS_DECRYPT:
387 status = "DECRYPT";
388 break;
389 case STATUS_DECOMPRESS:
390 status = "DECOMPRESS";
391 break;
392 case STATUS_COMPRESS:
393 status = "COMPRESS";
394 break;
397 if (!ctx) {
398 log_write("%s %s", status, line);
399 return 0;
402 return assuan_write_status(ctx, status, line);
405 void send_status_all(status_msg_t which)
407 guint i, t;
409 pthread_mutex_lock(&cn_mutex);
411 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
412 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
413 size_t len;
415 pthread_cond_signal(&cn->msg_cond);
416 len = write(cn->msg_fd[1], &which, sizeof(status_msg_t));
418 if (len != sizeof(status_msg_t))
419 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
422 pthread_mutex_unlock(&cn_mutex);
425 static void xml_error_cb(void *data, xmlErrorPtr e)
427 struct client_s *client = data;
430 * Keep the first reported error as the one to show in the error
431 * description. Reset in send_error().
433 if (client->xml_error)
434 return;
436 xmlCopyError(e, client->xml_error);
439 void cleanup_crypto(struct client_crypto_s **c)
441 struct client_crypto_s *cr = *c;
443 if (!cr)
444 return;
446 if (cr->iv)
447 gcry_free(cr->iv);
449 if (cr->key)
450 gcry_free(cr->key);
452 if (cr->tkey)
453 gcry_free(cr->tkey);
455 if (cr->tkey2)
456 gcry_free(cr->tkey2);
458 if (cr->inbuf)
459 gcry_free(cr->inbuf);
461 if (cr->outbuf)
462 gcry_free(cr->outbuf);
464 if (cr->fh) {
465 if (cr->fh->fd != -1 ||
466 (cmdline == TRUE && cr->fh->fd != STDOUT_FILENO))
467 close(cr->fh->fd);
469 if (cr->fh->doc)
470 gcry_free(cr->fh->doc);
472 g_free(cr->fh);
475 if (cr->gh)
476 gcry_cipher_close(cr->gh);
478 g_free(cr);
479 *c = NULL;
483 * This is called after a child_thread terminates. Set with
484 * pthread_cleanup_push().
486 static void cleanup_cb(void *arg)
488 struct client_thread_s *cn = arg;
489 struct client_s *cl = cn->cl;
491 pthread_mutex_lock(&cn_mutex);
492 log_write(N_("exiting, fd=%i"), cn->fd);
493 pthread_cancel(cn->msg_tid);
494 pthread_join(cn->msg_tid, NULL);
495 pthread_cancel(cn->msg_sender_tid);
496 pthread_join(cn->msg_sender_tid, NULL);
497 close(cl->thd->msg_fd[0]);
498 close(cl->thd->msg_fd[1]);
499 pthread_join(cn->tid, NULL);
501 if (cl && cl->freed == FALSE)
502 cleanup_client(cl);
504 #ifdef WITH_GNUTLS
505 if (cn->tls) {
506 gnutls_deinit(cn->tls->ses);
508 if (cn->tls->fp)
509 g_free(cn->tls->fp);
511 g_free(cn->tls);
513 #endif
515 if (cl && cl->ctx)
516 assuan_deinit_server(cl->ctx);
518 #ifdef WITH_PINENTRY
519 if (cl && cl->pinentry)
520 cleanup_pinentry(cl->pinentry);
521 #endif
523 if (cl->crypto)
524 cleanup_crypto(&cl->crypto);
526 g_free(cl);
528 if (cn->name)
529 g_free(cn->name);
531 if (pthread_mutex_trylock(&cn->msg_mutex) == EBUSY)
532 pthread_mutex_unlock(&cn->msg_mutex);
534 pthread_mutex_destroy(&cn->msg_mutex);
535 pthread_cond_destroy(&cn->msg_cond);
537 if (pthread_mutex_trylock(&cn->msg_mutex) == EBUSY)
538 pthread_mutex_unlock(&cn->msg_sender_mutex);
540 pthread_mutex_destroy(&cn->msg_sender_mutex);
541 pthread_cond_destroy(&cn->msg_sender_cond);
543 for (;;) {
544 struct status_msg_s *m = g_slist_nth_data(cn->msg_queue, 0);
546 if (!m)
547 break;
549 cn->msg_queue = g_slist_remove(cn->msg_queue, m);
550 g_free(m);
553 cn_thread_list = g_slist_remove(cn_thread_list, cn);
554 g_free(cn);
555 pthread_mutex_unlock(&cn_mutex);
556 send_status_all(STATUS_CLIENTS);
559 static void *client_msg_sender_thread(void *arg)
561 struct client_thread_s *thd = arg;
563 pthread_mutex_lock(&thd->msg_sender_mutex);
565 for (;;) {
566 struct status_msg_s *msg;
567 gpg_error_t rc;
569 pthread_cond_wait(&thd->msg_sender_cond, &thd->msg_sender_mutex);
570 pthread_testcancel();
572 /* The messages may have been stacked while waiting for send_status()
573 * to return. Send what's in the queue. */
574 for (;;) {
575 msg = g_slist_nth_data(thd->msg_queue, 0);
577 if (!msg)
578 break;
580 /* Unlock to prevent blocking in client_msg_thread(). */
581 pthread_mutex_unlock(&thd->msg_sender_mutex);
582 rc = send_status(thd->cl->ctx, msg->msg, NULL);
583 pthread_mutex_lock(&thd->msg_sender_mutex);
584 thd->msg_queue = g_slist_remove(thd->msg_queue, msg);
585 g_free(msg);
586 pthread_testcancel();
588 if (rc) {
589 //FIXME
594 return NULL;
598 * This function waits for a signal from send_status_all() then appends a
599 * message read from a pipe to the clients message queue. The actual sending
600 * of the message is done in client_msg_sender_thread() which waits for a
601 * signal from this function. This prevents blocking in assuan_send_status()
602 * when sending to remote clients. The messages are sent in order that they
603 * arrive which wouldn't be guaranteed if a thread was created here instead.
605 static void *client_msg_thread(void *arg)
607 struct client_thread_s *thd = arg;
609 pthread_mutex_lock(&thd->msg_mutex);
611 for (;;) {
612 fd_set rfds;
613 int n;
614 status_msg_t m;
615 size_t len;
616 struct status_msg_s *msg;
618 pthread_cond_wait(&thd->msg_cond, &thd->msg_mutex);
619 pthread_testcancel();
620 FD_ZERO(&rfds);
621 FD_SET(thd->msg_fd[0], &rfds);
622 n = select(thd->msg_fd[0]+1, &rfds, NULL, NULL, NULL);
624 if (n <= 0 || !FD_ISSET(thd->msg_fd[0], &rfds))
625 continue;
627 len = read(thd->msg_fd[0], &m, sizeof(status_msg_t));
628 pthread_testcancel();
630 if (len != sizeof(status_msg_t)) {
631 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
632 continue;
635 pthread_mutex_lock(&thd->msg_sender_mutex);
637 /* Don't append duplicate status messages. If the client is lagged and
638 * there are a bunch of status messages needing to be sent, only send
639 * the latest unique ones. */
640 for (n = 0; n < g_slist_length(thd->msg_queue); n++) {
641 msg = g_slist_nth_data(thd->msg_queue, n);
643 if (msg->msg == m)
644 goto done;
647 msg = g_malloc(sizeof(struct status_msg_s));
649 if (!msg) {
650 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
651 pthread_mutex_unlock(&thd->msg_sender_mutex);
652 continue;
655 msg->msg = m;
656 thd->msg_queue = g_slist_append(thd->msg_queue, msg);
657 done:
658 pthread_mutex_unlock(&thd->msg_sender_mutex);
659 pthread_cond_signal(&thd->msg_sender_cond);
662 return NULL;
666 * Called every time a connection is made via pthread_create(). This is the
667 * thread entry point.
669 static void *client_thread(void *data)
671 struct client_thread_s *thd = data;
672 struct client_s *cl = g_malloc0(sizeof(struct client_s));
673 gpg_error_t rc;
674 pthread_attr_t attr;
677 * Prevent a race condition with init_new_connection() if this thread
678 * fails (returns) for some reason before init_new_connection() releases
679 * the cn_mutex.
681 pthread_mutex_lock(&cn_mutex);
682 pthread_mutex_unlock(&cn_mutex);
684 if (!cl) {
685 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
686 goto fail;
689 thd->cl = cl;
690 cl->thd = thd;
691 pthread_cleanup_push(cleanup_cb, thd);
693 #ifdef WITH_GNUTLS
695 * Do the TLS handshake before anything else.
697 if (thd->remote) {
698 gchar *prio = get_key_file_string("global", "cipher_suite");
700 thd->tls = tls_init(thd->fd, prio);
701 g_free(prio);
703 if (!thd->tls) {
704 close(thd->fd);
705 goto fail;
708 #endif
711 * This is a "child" thread. Don't catch any signals. Let the master
712 * thread take care of signals in server_loop().
714 if (new_connection(cl))
715 goto fail;
717 #ifdef WITH_PINENTRY
718 cl->pinentry = pinentry_init();
720 if (!cl->pinentry) {
721 g_free(cl);
722 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
723 goto fail;
725 #endif
727 #ifdef HAVE_MLOCKALL
728 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
729 log_write("mlockall(): %s", strerror(errno));
730 goto fail;
732 #endif
734 if (pipe(thd->msg_fd) == -1) {
735 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
736 goto fail;
739 pthread_cond_init(&thd->msg_cond, NULL);
740 pthread_mutex_init(&thd->msg_mutex, NULL);
741 pthread_attr_init(&attr);
742 pthread_create(&thd->msg_tid, &attr, client_msg_thread, thd);
744 pthread_cond_init(&thd->msg_sender_cond, NULL);
745 pthread_mutex_init(&thd->msg_sender_mutex, NULL);
746 pthread_create(&thd->msg_sender_tid, &attr, client_msg_sender_thread, thd);
747 pthread_attr_destroy(&attr);
748 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
750 if (rc) {
751 log_write("%s", gpg_strerror(rc));
752 goto fail;
755 send_status_all(STATUS_CLIENTS);
756 xmlSetStructuredErrorFunc(cl, xml_error_cb);
758 for (;;) {
759 fd_set rfds;
760 int n;
761 struct timeval tv = {1,0};
763 FD_ZERO(&rfds);
764 FD_SET(cl->thd->fd, &rfds);
766 #ifdef WITH_PINENTRY
767 if (cl->pinentry->status == PINENTRY_RUNNING)
768 FD_SET(cl->pinentry->fd, &rfds);
770 n = cl->thd->fd > cl->pinentry->fd ? cl->thd->fd : cl->pinentry->fd;
771 #else
772 n = cl->thd->fd;
773 #endif
774 n = select(n+1, &rfds, NULL, NULL, &tv);
776 if (n <= 0)
777 continue;
779 if (FD_ISSET(cl->thd->fd, &rfds)) {
780 rc = assuan_process_next(cl->ctx);
782 if (rc) {
783 cl->inquire_status = INQUIRE_INIT;
785 if (gpg_err_code(rc) == GPG_ERR_EOF)
786 goto done;
788 log_write("assuan_process_next(): %s", gpg_strerror(rc));
789 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
791 if (rc) {
792 log_write("assuan_process_done(): %s", gpg_strerror(rc));
793 goto done;
796 else {
797 #ifdef WITH_PINENTRY
798 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
799 cl->pinentry->status = PINENTRY_RUNNING;
800 #endif
802 switch (cl->inquire_status) {
803 case INQUIRE_BUSY:
804 case INQUIRE_INIT:
805 break;
806 case INQUIRE_DONE:
807 cl->inquire_status = INQUIRE_INIT;
808 rc = assuan_process_done(cl->ctx, 0);
809 break;
814 #ifdef WITH_PINENTRY
815 pinentry_iterate(cl,
816 cl->pinentry->fd != -1 && FD_ISSET(cl->pinentry->fd, &rfds));
817 #endif
821 * Client cleanup (including XML data) is done in cleanup_cb() from
822 * the cleanup thread.
824 done:
825 fail:
826 if (1) {} // Fixes compile time error with pthread_cleanup_push().
827 pthread_cleanup_pop(1);
828 pthread_exit(PTHREAD_CANCELED);
829 return NULL;
832 static void setup_logging(GKeyFile *kf)
834 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
836 if (n == TRUE) {
837 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
839 if (*p == '~') {
840 gchar buf[PATH_MAX];
842 p++;
843 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
844 g_free(p);
846 if (logfile)
847 g_free(logfile);
849 logfile = g_strdup(buf);
851 else {
852 if (logfile)
853 g_free(logfile);
855 logfile = p;
859 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
863 * Make sure all settings are set to either the specified setting or a
864 * default.
866 static void set_rcfile_defaults(GKeyFile *kf)
868 gchar buf[PATH_MAX];
870 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
871 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
872 g_key_file_set_string(kf, "global", "socket_path", buf);
875 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
876 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
877 g_key_file_set_string(kf, "global", "data_directory", buf);
880 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
881 g_key_file_set_boolean(kf, "global", "backup", TRUE);
883 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
884 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
885 g_key_file_set_string(kf, "global", "log_path", buf);
888 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
889 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
891 #ifdef HAVE_MLOCKALL
892 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
893 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
894 #endif
896 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
897 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
899 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
900 g_key_file_get_integer(kf, "global", "iterations", 0) < 0)
901 g_key_file_set_integer(kf, "global", "iterations", 1);
903 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
904 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
906 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
907 g_key_file_set_integer(kf, "global", "iteration_progress", 0);
909 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
910 g_key_file_set_integer(kf, "global", "compression_level", 6);
912 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
913 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
915 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
916 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
918 zlib_bufsize = (uInt)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
920 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
921 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
923 #ifdef HAVE_MLOCKALL
924 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
925 #endif
927 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
928 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
930 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
931 g_key_file_set_integer(kf, "global", "keepalive", 30);
933 #ifdef WITH_PINENTRY
934 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
935 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
937 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
938 g_key_file_set_integer(kf, "global", "pinentry_timeout", 20);
939 #endif
941 #ifdef WITH_GNUTLS
942 if (g_key_file_has_key(kf, "global", "tcp_port", NULL) == FALSE)
943 g_key_file_set_integer(kf, "global", "tcp_port", 6466);
945 if (g_key_file_has_key(kf, "global", "enable_tcp", NULL) == FALSE)
946 g_key_file_set_boolean(kf, "global", "enable_tcp", FALSE);
948 if (g_key_file_has_key(kf, "global", "tcp_require_key", NULL) == FALSE)
949 g_key_file_set_boolean(kf, "global", "tcp_require_key", FALSE);
951 if (g_key_file_has_key(kf, "global", "tcp_wait", NULL) == FALSE)
952 g_key_file_set_boolean(kf, "global", "tcp_wait", 3);
954 if (g_key_file_has_key(kf, "global", "cipher_suite", NULL) == FALSE)
955 g_key_file_set_string(kf, "global", "cipher_suite", "SECURE256");
956 #endif
958 setup_logging(kf);
961 static GKeyFile *parse_rcfile(gboolean specified)
963 GKeyFile *kf = g_key_file_new();
964 GError *rc = NULL;
966 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
967 log_write("%s: %s", rcfile, rc->message);
969 if (cmdline && specified) {
970 g_clear_error(&rc);
971 return NULL;
974 if (rc->code == G_FILE_ERROR_NOENT) {
975 g_clear_error(&rc);
976 set_rcfile_defaults(kf);
977 return kf;
980 g_clear_error(&rc);
981 return NULL;
984 set_rcfile_defaults(kf);
985 return kf;
988 static gchar *do_get_password(const gchar *prompt)
990 gchar buf[LINE_MAX] = {0}, *p;
991 struct termios told, tnew;
992 gchar *key;
994 if (tcgetattr(STDIN_FILENO, &told) == -1) {
995 log_write("tcgetattr(): %s", strerror(errno));
996 return NULL;
999 memcpy(&tnew, &told, sizeof(struct termios));
1000 tnew.c_lflag &= ~(ECHO);
1001 tnew.c_lflag |= ICANON|ECHONL;
1003 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
1004 log_write("tcsetattr(): %s", strerror(errno));
1005 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1006 return NULL;
1009 fprintf(stderr, "%s", prompt);
1011 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
1012 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1013 return NULL;
1016 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1017 p[strlen(p) - 1] = 0;
1019 if (!buf[0]) {
1020 key = gcry_malloc(1);
1021 key[0] = 0;
1023 else {
1024 key = gcry_malloc(strlen(p) + 1);
1025 sprintf(key, "%s", p);
1028 memset(&buf, 0, sizeof(buf));
1029 return key;
1032 /* Only used when "enable_pinentry" is "false" or -P. */
1033 static gpg_error_t get_input(const gchar *filename,
1034 struct client_crypto_s *crypto, guchar *key, pinentry_cmd_t which)
1036 gchar *prompt;
1038 if (which == PINENTRY_SAVE) {
1039 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
1040 crypto->tkey = do_get_password(prompt);
1041 g_free(prompt);
1043 if (!crypto->tkey) {
1044 log_write(N_("%s: Skipping file"), filename);
1045 return GPG_ERR_BAD_PASSPHRASE;
1048 prompt = g_strdup_printf(N_("Repeat passphrase: "));
1049 crypto->tkey2 = do_get_password(prompt);
1050 g_free(prompt);
1052 if (!crypto->tkey2) {
1053 log_write(N_("%s: Skipping file"), filename);
1054 return GPG_ERR_BAD_PASSPHRASE;
1057 if (strcmp(crypto->tkey, crypto->tkey2)) {
1058 log_write(N_("%s: Passphrase mismatch"), filename);
1059 return EPWMD_BADKEY;
1062 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
1063 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1064 return 0;
1067 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
1069 if ((crypto->tkey = do_get_password(prompt)) == NULL) {
1070 log_write(N_("%s: Skipping file"), filename);
1071 g_free(prompt);
1072 return GPG_ERR_BAD_PASSPHRASE;
1075 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
1076 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1077 g_free(prompt);
1078 return 0;
1082 * inbuf must have been allocated with gcry_malloc().
1084 gpg_error_t export_common(const gchar *filename, struct client_crypto_s *crypto,
1085 gpointer inbuf, gulong insize)
1087 gpg_error_t rc;
1088 gint level, zrc;
1089 gulong outsize;
1090 gpointer outbuf;
1092 level = get_key_file_integer(filename, "compression_level");
1094 if (level < 0)
1095 level = 0;
1097 if (do_compress(NULL, level, inbuf, insize, &outbuf, &outsize, &zrc)
1098 == FALSE) {
1099 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
1102 rc = do_xml_encrypt(NULL, crypto, filename, outbuf, outsize);
1103 return rc;
1106 static gpg_error_t get_password(const gchar *filename,
1107 struct client_crypto_s *crypto, guchar *md5file, guchar *key,
1108 pinentry_cmd_t which)
1110 #ifdef WITH_PINENTRY
1111 gpg_error_t rc = 0;
1113 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
1114 == FALSE) {
1115 #endif
1116 return get_input(filename, crypto, key, which);
1117 #ifdef WITH_PINENTRY
1119 else {
1120 gchar *result = NULL;
1121 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
1123 set_pinentry_defaults(pin);
1124 pin->which = which;
1125 pin->filename = g_strdup(filename);
1126 rc = pinentry_getpin(pin, &result);
1128 if (rc) {
1129 xfree(result);
1130 goto done;
1133 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, strlen(result) ? strlen(result) : 1);
1134 xfree(result);
1135 cleanup_pinentry(pin);
1138 done:
1139 return rc;
1140 #endif
1143 static gboolean _getline(const gchar *file, gchar **result, gpg_error_t *rc)
1145 FILE *fp;
1146 gchar buf[LINE_MAX] = {0}, *p;
1147 gchar *str = NULL;
1148 gint len;
1150 *rc = 0;
1152 if ((fp = fopen(file, "r")) == NULL) {
1153 *rc = gpg_error_from_syserror();
1154 return FALSE;
1157 p = fgets(buf, sizeof(buf), fp);
1158 fclose(fp);
1159 len = strlen(buf);
1161 if (len && buf[len - 1] == '\n')
1162 buf[--len] = 0;
1164 str = gcry_malloc(len + 1);
1166 if (!str) {
1167 *rc = gpg_error_from_errno(ENOMEM);
1168 return FALSE;
1171 memcpy(str, buf, len ? len : 1);
1172 str[len] = 0;
1173 memset(&buf, 0, sizeof(buf));
1174 *result = str;
1175 return TRUE;
1178 static gchar *parse_rcfile_keyfile(const gchar *filename, gboolean import,
1179 gpg_error_t *rc)
1181 GError *rv = NULL;
1182 gchar *t, *file = NULL, *str;
1184 *rc = GPG_ERR_UNKNOWN_ERRNO;
1186 if (import == FALSE) {
1187 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
1188 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
1190 if (!file) {
1191 if (rv) {
1192 log_write("%s: key_file: %s", rcfile, rv->message);
1193 g_clear_error(&rv);
1196 return NULL;
1199 t = expand_homedir(file);
1201 if (!t) {
1202 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1203 *rc = gpg_error_from_errno(ENOMEM);
1204 return NULL;
1207 g_free(file);
1208 file = t;
1211 else {
1212 /* -I or -C. The filename is a key file. */
1213 file = g_strdup(filename);
1215 if (!file) {
1216 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1217 *rc = gpg_error_from_errno(ENOMEM);
1218 return NULL;
1222 if (rv) {
1223 log_write("%s: key_file: %s", rcfile, rv->message);
1224 g_clear_error(&rv);
1225 return NULL;
1228 if (!file)
1229 return NULL;
1231 if (_getline(file, &str, rc) == FALSE) {
1232 log_write("%s: %s: %s", filename, file, pwmd_strerror(*rc));
1233 g_free(file);
1234 return NULL;
1237 g_free(file);
1238 *rc = 0;
1239 return str;
1242 static gboolean xml_import(const gchar *filename, const gchar *outfile,
1243 const gchar *keyfile, gulong iter)
1245 xmlDocPtr doc;
1246 gint fd;
1247 struct stat st;
1248 gint len;
1249 xmlChar *xmlbuf;
1250 xmlChar *xml;
1251 gpg_error_t rc;
1252 struct client_crypto_s *crypto;
1254 if (stat(filename, &st) == -1) {
1255 log_write("%s: %s", filename, strerror(errno));
1256 return FALSE;
1259 crypto = init_client_crypto();
1261 if (!crypto)
1262 return FALSE;
1264 crypto->key = gcry_malloc(gcrykeysize);
1265 memset(crypto->key, 0, gcrykeysize);
1267 if (!crypto->key) {
1268 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1269 goto fail;
1272 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
1273 filename, outfile);
1275 if (iter && keyfile) {
1276 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1278 if (!crypto->tkey)
1279 goto fail;
1281 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1282 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1284 else if (iter) {
1285 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
1287 if (rc)
1288 goto fail;
1291 if ((fd = open(filename, O_RDONLY)) == -1) {
1292 log_write("%s: %s", filename, strerror(errno));
1293 goto fail;
1296 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
1297 close(fd);
1298 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1299 goto fail;
1302 if (read(fd, xmlbuf, st.st_size) == -1) {
1303 rc = errno;
1304 close(fd);
1305 errno = rc;
1306 log_write("%s: %s", filename, strerror(errno));
1307 goto fail;
1310 close(fd);
1311 xmlbuf[st.st_size] = 0;
1314 * Make sure the document validates.
1316 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
1317 log_write("xmlReadDoc() failed");
1318 gcry_free(xmlbuf);
1319 goto fail;
1322 gcry_free(xmlbuf);
1323 xmlDocDumpMemory(doc, &xml, &len);
1324 xmlFreeDoc(doc);
1326 if (!iter)
1327 memset(crypto->key, '!', gcrykeysize);
1329 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
1331 if (!crypto->fh) {
1332 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1333 goto fail;
1336 crypto->fh->fh2.iter = iter;
1337 rc = export_common(outfile, crypto, xml, len);
1338 xmlFree(xml);
1340 if (rc) {
1341 send_error(NULL, rc);
1342 goto fail;
1345 cleanup_crypto(&crypto);
1346 return TRUE;
1348 fail:
1349 cleanup_crypto(&crypto);
1350 return FALSE;
1353 gchar *get_key_file_string(const gchar *section, const gchar *what)
1355 gchar *val = NULL;
1356 GError *grc = NULL;
1358 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1359 val = g_key_file_get_string(keyfileh, section, what, &grc);
1361 if (grc) {
1362 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1363 g_clear_error(&grc);
1366 else {
1367 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1368 val = g_key_file_get_string(keyfileh, "global", what, &grc);
1370 if (grc) {
1371 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1372 g_clear_error(&grc);
1377 return val;
1380 gint get_key_file_integer(const gchar *section, const gchar *what)
1382 gint val = -1;
1383 GError *grc = NULL;
1385 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
1386 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
1388 if (grc) {
1389 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1390 g_clear_error(&grc);
1393 else {
1394 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1395 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
1397 if (grc) {
1398 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1399 g_clear_error(&grc);
1404 return val;
1407 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
1409 gboolean val = FALSE;
1410 GError *grc = NULL;
1412 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1413 val = g_key_file_get_boolean(keyfileh, section, what, &grc);
1415 if (grc) {
1416 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1417 g_clear_error(&grc);
1420 else {
1421 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1422 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
1424 if (grc) {
1425 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1426 g_clear_error(&grc);
1431 return val;
1434 static gboolean parse_rcfile_keys()
1436 gsize n;
1437 gchar **groups;
1438 gchar **p;
1439 gchar *str;
1441 groups = g_key_file_get_groups(keyfileh, &n);
1443 for (p = groups; *p; p++) {
1444 GError *rc = NULL;
1446 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE) {
1447 str = g_key_file_get_string(keyfileh, *p, "key", &rc);
1449 if (!str) {
1450 if (rc) {
1451 log_write("%s: key: %s", rcfile, rc->message);
1452 g_clear_error(&rc);
1454 continue;
1457 do_cache_push(*p, str);
1458 g_free(str);
1459 continue;
1462 if (rc) {
1463 log_write("%s: key: %s", rcfile, rc->message);
1464 g_clear_error(&rc);
1465 continue;
1468 gpg_error_t ret;
1469 str = parse_rcfile_keyfile(*p, FALSE, &ret);
1471 if (!str)
1472 continue;
1474 do_cache_push(*p, str);
1475 gcry_free(str);
1478 g_strfreev(groups);
1479 return TRUE;
1482 static gboolean do_cache_push(const gchar *filename, const gchar *password)
1484 guchar md5file[16];
1485 gint timeout;
1486 const gchar *p = filename;
1487 struct client_crypto_s *crypto;
1488 gpg_error_t rc;
1490 while (isspace(*p))
1491 p++;
1493 if (!*p)
1494 return FALSE;
1496 if (valid_filename(p) == FALSE) {
1497 log_write(N_("%s: Invalid characters in filename"), p);
1498 return FALSE;
1501 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1503 if (access(p, R_OK|W_OK) != 0) {
1504 log_write("%s: %s", p, strerror(errno));
1505 return FALSE;
1508 crypto = init_client_crypto();
1510 if (!crypto)
1511 return FALSE;
1513 crypto->fh = read_file_header(filename, FALSE, &rc);
1515 if (!crypto->fh) {
1516 log_write("%s: %s", p, pwmd_strerror(rc));
1517 cleanup_crypto(&crypto);
1518 return FALSE;
1521 crypto->key = gcry_malloc(gcrykeysize);
1523 if (!crypto->key) {
1524 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1525 cleanup_crypto(&crypto);
1526 return FALSE;
1529 log_write(N_("Adding '%s' to the file cache ..."), filename);
1531 if (crypto->fh->fh2.iter <= 0) {
1532 memset(crypto->key, '!', gcrykeysize);
1533 goto try_decrypt;
1536 if (!password) {
1537 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1539 if (rc) {
1540 send_error(NULL, rc);
1541 cleanup_crypto(&crypto);
1542 return FALSE;
1545 gcry_free(crypto->fh->doc);
1546 crypto->fh->doc = NULL;
1548 else
1549 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password,
1550 strlen(password) ? strlen(password) : 1);
1552 try_decrypt:
1553 rc = try_xml_decrypt(NULL, crypto->key, crypto, NULL, NULL);
1555 if (rc) {
1556 log_write("%s: %s", filename, pwmd_strerror(rc));
1557 cleanup_crypto(&crypto);
1558 return FALSE;
1561 if (cache_update_key(md5file, crypto->key) == FALSE) {
1562 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1563 cleanup_crypto(&crypto);
1564 return FALSE;
1567 timeout = get_key_file_integer(p, "cache_timeout");
1568 cache_set_timeout(md5file, timeout);
1569 log_write(N_("File '%s' now cached"), filename);
1570 cleanup_crypto(&crypto);
1571 return TRUE;
1574 static void init_new_connection(gint fd, gchar *addr)
1576 pthread_t tid;
1577 pthread_attr_t attr;
1578 struct client_thread_s *new;
1579 int n;
1581 new = g_malloc0(sizeof(struct client_thread_s));
1583 if (!new) {
1584 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1585 return;
1588 pthread_mutex_lock(&cn_mutex);
1589 new->fd = fd;
1591 #ifdef WITH_GNUTLS
1592 if (addr)
1593 new->remote = TRUE;
1594 #endif
1596 pthread_attr_init(&attr);
1597 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1598 n = pthread_create(&tid, &attr, client_thread, new);
1599 pthread_attr_destroy(&attr);
1601 if (n) {
1602 g_free(new);
1603 log_write("pthread_create(): %s", strerror(n));
1604 pthread_mutex_unlock(&cn_mutex);
1605 return;
1608 new->tid = tid;
1609 cn_thread_list = g_slist_append(cn_thread_list, new);
1610 pthread_mutex_unlock(&cn_mutex);
1612 if (addr)
1613 log_write(N_("new connection: fd=%i, addr=%s"), fd, addr);
1614 else
1615 log_write(N_("new connection: fd=%i"), fd);
1618 #ifdef WITH_GNUTLS
1619 /* From Beej's Guide to Network Programming. It's a good tutorial. */
1620 static void *get_in_addr(struct sockaddr *sa)
1622 if (sa->sa_family == AF_INET)
1623 return &(((struct sockaddr_in*)sa)->sin_addr);
1625 return &(((struct sockaddr_in6*)sa)->sin6_addr);
1628 static void *tcp_accept_thread(void *arg)
1630 gint sockfd = (gint)arg;
1632 for (;;) {
1633 struct sockaddr_storage raddr;
1634 socklen_t slen = sizeof(raddr);
1635 gint fd = -1;
1636 gulong n;
1637 gchar *t;
1639 if ((fd = accept(sockfd, (struct sockaddr *)&raddr, &slen)) == -1) {
1640 if (errno != EAGAIN) {
1641 if (!quit) // probably EBADF
1642 log_write("accept(): %s", strerror(errno));
1644 break;
1648 if (quit)
1649 break;
1651 if (fd >= 0) {
1652 gchar s[INET6_ADDRSTRLEN];
1654 inet_ntop(raddr.ss_family, get_in_addr((struct sockaddr *)&raddr),
1655 s, sizeof s);
1656 init_new_connection(fd, s);
1659 t = get_key_file_string("global", "tcp_wait");
1660 n = strtol(t, NULL, 10);
1661 g_free(t);
1663 if (n < 0)
1664 n = 0;
1666 usleep(n*100000);
1669 /* Just in case accept() failed for some reason other than EBADF */
1670 quit = 1;
1671 pthread_exit(PTHREAD_CANCELED);
1672 return NULL;
1674 #endif
1676 static void *accept_thread(void *arg)
1678 gint sockfd = (gint)arg;
1680 for (;;) {
1681 socklen_t slen = sizeof(struct sockaddr_un);
1682 struct sockaddr_un raddr;
1683 gint fd = -1;
1685 if ((fd = accept(sockfd, (struct sockaddr *)&raddr, &slen)) == -1) {
1686 if (errno != EAGAIN) {
1687 if (!quit) // probably EBADF
1688 log_write("accept(): %s", strerror(errno));
1690 break;
1694 if (fd >= 0)
1695 init_new_connection(fd, NULL);
1698 /* Just in case accept() failed for some reason other than EBADF */
1699 quit = 1;
1700 pthread_exit(PTHREAD_CANCELED);
1701 return NULL;
1704 static void *adjust_cache_timer_thread(void *arg)
1706 for (;;) {
1707 sleep(1);
1708 pthread_testcancel();
1709 CACHE_LOCK(NULL);
1710 cache_adjust_timer();
1711 CACHE_UNLOCK;
1714 return NULL;
1717 static void *keepalive_thread(void *arg)
1719 struct timespec ts;
1721 pthread_mutex_lock(&quit_mutex);
1723 for (;;) {
1724 gint n = get_key_file_integer("global", "keepalive");
1726 /* Check for rcfile reloading. */
1727 if (n <= 0) {
1728 pthread_mutex_unlock(&quit_mutex);
1729 break;
1732 clock_gettime(CLOCK_REALTIME, &ts);
1733 ts.tv_sec += n;
1735 /* This is a cancellation point. */
1736 pthread_cond_timedwait(&quit_cond, &quit_mutex, &ts);
1738 if (global_quit) {
1739 pthread_mutex_unlock(&quit_mutex);
1740 break;
1743 send_status_all(STATUS_KEEPALIVE);
1746 return NULL;
1749 static void server_loop(gint sockfd, gchar **socketpath)
1751 pthread_t accept_tid;
1752 guint n;
1753 sigset_t sigset;
1754 gint n_clients = 0;
1755 pthread_attr_t attr;
1756 pthread_t keepalive_tid;
1757 pthread_t cache_timeout_tid;
1758 pthread_mutexattr_t mattr;
1760 pthread_mutexattr_init(&mattr);
1761 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE_NP);
1762 pthread_mutex_init(&cn_mutex, &mattr);
1763 pthread_mutexattr_destroy(&mattr);
1764 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1765 pthread_attr_init(&attr);
1766 pthread_create(&accept_tid, &attr, accept_thread, (void *)sockfd);
1768 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1769 pthread_create(&keepalive_tid, &attr, keepalive_thread, NULL);
1770 pthread_create(&cache_timeout_tid, &attr, adjust_cache_timer_thread, NULL);
1771 sigemptyset(&sigset);
1773 /* Termination */
1774 sigaddset(&sigset, SIGTERM);
1775 sigaddset(&sigset, SIGINT);
1777 /* Clears the file cache. */
1778 sigaddset(&sigset, SIGUSR1);
1780 /* Configuration file reloading. */
1781 sigaddset(&sigset, SIGHUP);
1783 /* Caught in client_thread(). Sends a cache status message. */
1784 sigaddset(&sigset, SIGUSR2);
1786 /* Ignored everywhere. When a client disconnects abnormally this signal
1787 * gets raised. It isn't needed though because client_thread() will check
1788 * for rcs even after the client disconnects. */
1789 signal(SIGPIPE, SIG_IGN);
1790 pthread_sigmask(SIG_BLOCK, &sigset, NULL);
1792 do {
1793 gint sig;
1795 sigwait(&sigset, &sig);
1796 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1798 /* Caught a signal. */
1799 switch (sig) {
1800 case SIGHUP:
1801 reload_rcfile();
1802 break;
1803 case SIGABRT:
1804 CACHE_LOCK(NULL);
1805 cache_clear(NULL, 2);
1806 CACHE_UNLOCK;
1807 #ifndef MEM_DEBUG
1808 xpanic();
1809 #endif
1810 exit(EXIT_FAILURE);
1811 case SIGUSR1:
1812 CACHE_LOCK(NULL);
1813 log_write(N_("clearing file cache"));
1814 cache_clear(NULL, 2);
1815 CACHE_UNLOCK;
1816 break;
1817 default:
1818 quit = 1;
1819 shutdown(sockfd, SHUT_RDWR);
1820 close(sockfd);
1822 if (tcpSockFd != -1) {
1823 shutdown(tcpSockFd, SHUT_RDWR);
1824 close(tcpSockFd);
1826 break;
1828 } while (!quit);
1831 * We're out of the main server loop. This happens when a signal was sent
1832 * to terminate the daemon. We'll wait for all clients to disconnect
1833 * before exiting and ignore any following signals.
1835 pthread_join(accept_tid, NULL);
1836 pthread_attr_destroy(&attr);
1838 #if 0
1839 #ifdef WITH_GNUTLS
1840 if (tcpSockFd != -1) {
1841 pthread_cancel(tcpAcceptTid);
1842 pthread_join(tcpAcceptTid, NULL);
1844 #endif
1845 #endif
1847 unlink(*socketpath);
1848 g_free(*socketpath);
1849 *socketpath = NULL;
1850 pthread_mutex_lock(&cn_mutex);
1851 n = g_slist_length(cn_thread_list);
1852 pthread_mutex_unlock(&cn_mutex);
1854 if (n)
1855 log_write(N_("waiting for all clients to disconnect"));
1857 while (n) {
1858 if (n != n_clients) {
1859 log_write(N_("%i clients remain"), n);
1860 n_clients = n;
1863 sleep(1);
1864 pthread_mutex_lock(&cn_mutex);
1865 n = g_slist_length(cn_thread_list);
1866 pthread_mutex_unlock(&cn_mutex);
1869 global_quit = 1;
1870 pthread_cancel(keepalive_tid);
1871 pthread_cancel(cache_timeout_tid);
1872 cache_free();
1876 * Called from pinentry_fork() in the child process.
1878 void free_client_list()
1880 gint i, t = g_slist_length(cn_thread_list);
1882 for (i = 0; i < t; i++) {
1883 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1885 free_client(cn->cl);
1888 cache_free();
1891 struct client_crypto_s *init_client_crypto()
1893 struct client_crypto_s *new = g_malloc0(sizeof(struct client_crypto_s));
1894 gpg_error_t rc;
1896 if (!new) {
1897 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1898 return NULL;
1901 rc = gcry_cipher_open(&new->gh, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
1903 if (rc) {
1904 log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(rc));
1905 g_free(new);
1906 return NULL;
1909 return new;
1912 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
1913 const gchar *outfile)
1915 gpg_error_t rc;
1916 guchar md5file[16];
1917 guint iter;
1918 struct client_crypto_s *crypto = init_client_crypto();
1920 if (!crypto)
1921 return GPG_ERR_ENOMEM;
1923 crypto->key = gcry_malloc(gcrykeysize);
1925 if (!crypto->key) {
1926 cleanup_crypto(&crypto);
1927 return GPG_ERR_ENOMEM;
1930 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
1931 filename);
1932 crypto->fh = read_file_header(filename, TRUE, &rc);
1934 if (!crypto->fh)
1935 goto done;
1937 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
1939 /* The header in version 1 had a bug where the iterations were off-by-one.
1940 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
1941 * header.
1943 if (crypto->fh->fh1.iter >= 0) {
1944 if (keyfile) {
1945 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1947 if (!crypto->tkey)
1948 goto done;
1950 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1951 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1953 else {
1954 rc = get_password(filename, crypto, md5file, crypto->key,
1955 PINENTRY_OPEN);
1957 if (rc)
1958 goto done;
1962 rc = try_xml_decrypt(NULL, crypto->key, crypto, &crypto->fh->doc,
1963 &crypto->fh->len);
1965 if (rc)
1966 goto done;
1968 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
1970 if (rc) {
1971 log_write("%s: %s", filename, pwmd_strerror(rc));
1972 goto done;
1975 crypto->fh->v1 = FALSE;
1976 iter = crypto->fh->fh1.iter;
1977 memset(&crypto->fh->fh2, 0, sizeof(crypto->fh->fh2));
1978 /* Keep the iterations and key from the original file. */
1979 crypto->fh->fh2.iter = iter+1; // Bugfix for v1 data files.
1980 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
1982 done:
1983 if (rc)
1984 send_error(NULL, rc);
1986 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
1987 cleanup_crypto(&crypto);
1988 return rc;
1991 #ifdef WITH_GNUTLS
1992 static gboolean initTlsParams()
1994 int n;
1995 gchar *tmp, *tmp2;
1997 n = gnutls_certificate_allocate_credentials(&x509_cred);
1999 if (n != GNUTLS_E_SUCCESS) {
2000 log_write("%s", gnutls_strerror(n));
2001 x509_cred = NULL;
2002 goto fail;
2005 tmp = expand_homedir("~/.pwmd/ca-cert.pem");
2007 if (!tmp) {
2008 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
2009 goto fail;
2012 n = gnutls_certificate_set_x509_trust_file(x509_cred, tmp,
2013 GNUTLS_X509_FMT_PEM);
2014 g_free(tmp);
2016 if (n < 0) {
2017 log_write("%s", gnutls_strerror(n));
2018 goto fail;
2021 tmp = expand_homedir("~/.pwmd/server-cert.pem");
2023 if (!tmp) {
2024 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
2025 goto fail;
2028 tmp2 = expand_homedir("~/.pwmd/server-key.pem");
2030 if (!tmp2) {
2031 g_free(tmp);
2032 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
2033 goto fail;
2036 n = gnutls_certificate_set_x509_key_file (x509_cred, tmp, tmp2,
2037 GNUTLS_X509_FMT_PEM);
2038 g_free(tmp);
2039 g_free(tmp2);
2041 if (n != GNUTLS_E_SUCCESS) {
2042 log_write("%s", gnutls_strerror(n));
2043 goto fail;
2046 log_write("%s", N_("Generating key exchange parameters..."));
2047 n = gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
2049 if (n) {
2050 log_write("%s", gpg_strerror(n));
2051 goto fail;
2054 n = gnutls_dh_params_init(&dh_params);
2056 if (n != GNUTLS_E_SUCCESS) {
2057 log_write("%s", gnutls_strerror(n));
2058 goto fail;
2061 n = gnutls_dh_params_generate2(dh_params, 1024);
2063 if (n != GNUTLS_E_SUCCESS) {
2064 log_write("%s", gnutls_strerror(n));
2065 goto fail;
2068 gnutls_certificate_set_dh_params(x509_cred, dh_params);
2069 n = gnutls_rsa_params_init(&rsa_params);
2071 if (n != GNUTLS_E_SUCCESS) {
2072 log_write("%s", gnutls_strerror(n));
2073 goto fail;
2076 n = gnutls_rsa_params_generate2(rsa_params, 512);
2078 if (n != GNUTLS_E_SUCCESS) {
2079 log_write("%s", gnutls_strerror(n));
2080 goto fail;
2083 gnutls_certificate_set_rsa_export_params(x509_cred, rsa_params);
2084 gnutls_certificate_set_params_function(x509_cred, tls_get_params);
2085 return TRUE;
2087 fail:
2088 return FALSE;
2091 static void deinitTlsParams()
2093 if (dh_params)
2094 gnutls_dh_params_deinit(dh_params);
2096 if (rsa_params)
2097 gnutls_rsa_params_deinit(rsa_params);
2099 if (x509_cred) {
2100 gnutls_certificate_free_credentials(x509_cred);
2101 x509_cred = NULL;
2105 static gboolean startStopTcp(gboolean term)
2107 struct addrinfo hints, *servinfo, *p;
2108 gint port = get_key_file_integer("global", "tcp_port");
2109 char buf[7];
2110 int n;
2111 pthread_attr_t attr;
2113 if (term || get_key_file_boolean("global", "enable_tcp") == FALSE) {
2114 if (tcpSockFd != -1) {
2115 pthread_cancel(tcpAcceptTid);
2116 pthread_join(tcpAcceptTid, NULL);
2117 close(tcpSockFd);
2118 tcpSockFd = -1;
2119 deinitTlsParams();
2122 return TRUE;
2125 if (tcpSockFd != -1)
2126 return TRUE;
2128 memset(&hints, 0, sizeof(hints));
2129 hints.ai_family = AF_UNSPEC;
2130 hints.ai_socktype = SOCK_STREAM;
2131 hints.ai_flags = AI_PASSIVE;
2133 if ((n = getaddrinfo(NULL, print_fmt(buf, sizeof(buf), "%i", port),
2134 &hints, &servinfo)) == -1) {
2135 log_write("getaddrinfo(): %s", gai_strerror(n));
2136 return FALSE;
2139 for(p = servinfo; p != NULL; p = p->ai_next) {
2140 if ((tcpSockFd = socket(p->ai_family, p->ai_socktype,
2141 p->ai_protocol)) == -1) {
2142 log_write("socket(): %s", strerror(errno));
2143 continue;
2146 n = 1;
2148 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_REUSEADDR, &n,
2149 sizeof(int)) == -1) {
2150 log_write("setsockopt(): %s", strerror(errno));
2151 freeaddrinfo(servinfo);
2152 goto fail;
2155 if (bind(tcpSockFd, p->ai_addr, p->ai_addrlen) == -1) {
2156 close(tcpSockFd);
2157 log_write("bind(): %s", strerror(errno));
2158 continue;
2161 n++;
2162 break;
2165 freeaddrinfo(servinfo);
2167 if (!p) {
2168 log_write("%s", N_("could not bind"));
2169 goto fail;
2172 if (g_key_file_has_key(keyfileh, "global", "tcp_interface", NULL)) {
2173 gchar *tmp = get_key_file_string("global", "tcp_interface");
2175 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_BINDTODEVICE, tmp, 1)
2176 == -1) {
2177 log_write("setsockopt(): %s", strerror(errno));
2178 g_free(tmp);
2179 goto fail;
2182 g_free(tmp);
2185 if (!initTlsParams())
2186 goto fail;
2188 if (listen(tcpSockFd, 0) == -1) {
2189 log_write("listen(): %s", strerror(errno));
2190 goto fail;
2193 pthread_attr_init(&attr);
2194 pthread_create(&tcpAcceptTid, &attr, tcp_accept_thread, (void *)tcpSockFd);
2195 pthread_attr_destroy(&attr);
2196 return TRUE;
2198 fail:
2199 deinitTlsParams();
2201 if (tcpSockFd != -1)
2202 close(tcpSockFd);
2204 tcpSockFd = -1;
2205 return FALSE;
2207 #endif
2209 int main(int argc, char *argv[])
2211 gint opt;
2212 struct sockaddr_un addr;
2213 struct passwd *pw = getpwuid(getuid());
2214 gchar buf[PATH_MAX];
2215 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
2216 gchar *socketarg = NULL;
2217 gchar *datadir = NULL;
2218 gboolean n;
2219 gchar *p;
2220 gchar **cache_push = NULL;
2221 gint iter = 0;
2222 gchar *import = NULL, *keyfile = NULL;
2223 gulong cmd_iterations = -1;
2224 gint default_timeout;
2225 gboolean rcfile_spec = FALSE;
2226 gint estatus = EXIT_FAILURE;
2227 gint sockfd;
2228 gchar *outfile = NULL;
2229 #ifndef MEM_DEBUG
2230 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
2231 #endif
2232 gint do_unlink = 1;
2233 gboolean secure = FALSE;
2234 guint ptotal = 0;
2235 gint background = 1;
2236 gchar *convert = NULL;
2237 pthread_mutexattr_t mattr;
2238 #ifdef WITH_PINENTRY
2239 gboolean disable_pinentry = FALSE;
2240 #endif
2241 #ifdef WITH_GNUTLS
2242 struct assuan_io_hooks io_hooks = {read_hook, write_hook};
2243 #endif
2244 #if 0
2245 #ifndef DEBUG
2246 #ifdef HAVE_SETRLIMIT
2247 struct rlimit rl;
2249 rl.rlim_cur = rl.rlim_max = 0;
2251 if (setrlimit(RLIMIT_CORE, &rl) != 0)
2252 err(EXIT_FAILURE, "setrlimit()");
2253 #endif
2254 #endif
2255 #endif
2257 #ifdef ENABLE_NLS
2258 setlocale(LC_ALL, "");
2259 bindtextdomain("pwmd", LOCALEDIR);
2260 textdomain("pwmd");
2261 #endif
2263 gpg_err_init();
2264 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
2265 #ifndef MEM_DEBUG
2266 g_mem_set_vtable(&mtable);
2267 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
2268 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
2269 xmlInitMemory();
2270 #ifdef WITH_GNUTLS
2271 gnutls_global_set_mem_functions(xmalloc, xmalloc, gcry_SecureCheck,
2272 xrealloc, xfree);
2273 #endif
2274 #endif
2275 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
2276 #ifdef WITH_GNUTLS
2277 gnutls_global_init();
2278 gnutls_global_set_log_function(tls_log);
2279 gnutls_global_set_log_level(1);
2280 assuan_set_io_hooks(&io_hooks);
2281 #endif
2282 xmlInitGlobals();
2283 xmlInitParser();
2284 xmlXPathInit();
2285 g_snprintf(buf, sizeof(buf), "%s/.pwmd", pw->pw_dir);
2287 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2288 err(EXIT_FAILURE, "%s", buf);
2290 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", pw->pw_dir);
2292 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2293 err(EXIT_FAILURE, "%s", buf);
2295 rcfile = g_strdup_printf("%s/.pwmd/config", pw->pw_dir);
2296 cmdline = TRUE;
2297 tcpSockFd = -1;
2299 while ((opt = getopt(argc, argv, "Po:C:bnI:i:k:hvf:D")) != EOF) {
2300 switch (opt) {
2301 #ifdef WITH_PINENTRY
2302 case 'P':
2303 disable_pinentry = TRUE;
2304 break;
2305 #endif
2306 case 'o':
2307 outfile = optarg;
2308 break;
2309 case 'C':
2310 convert = optarg;
2311 break;
2312 case 'b':
2313 /* Compatibility for version < 1.11 */
2314 break;
2315 case 'n':
2316 background = 0;
2317 break;
2318 case 'D':
2319 secure = TRUE;
2320 break;
2321 case 'I':
2322 import = optarg;
2323 break;
2324 case 'i':
2325 cmd_iterations = strtol(optarg, NULL, 10);
2326 break;
2327 case 'k':
2328 keyfile = optarg;
2329 break;
2330 case 'f':
2331 g_free(rcfile);
2332 rcfile = g_strdup(optarg);
2333 rcfile_spec = TRUE;
2334 break;
2335 case 'v':
2336 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,
2337 PACKAGE_BUGREPORT,
2338 #ifdef WITH_PINENTRY
2339 "+WITH_PINENTRY\n"
2340 #else
2341 "-WITH_PINENTRY\n"
2342 #endif
2343 #ifdef WITH_QUALITY
2344 "+WITH_QUALITY\n"
2345 #else
2346 "-WITH_QUALITY\n"
2347 #endif
2348 #ifdef WITH_GNUTLS
2349 "+WITH_GNUTLS\n"
2350 #else
2351 "-WITH_GNUTLS\n"
2352 #endif
2353 #ifdef DEBUG
2354 "+DEBUG\n"
2355 #else
2356 "-DEBUG\n"
2357 #endif
2358 #ifdef MEM_DEBUG
2359 "+MEM_DEBUG\n"
2360 #else
2361 "-MEM_DEBUG\n"
2362 #endif
2364 exit(EXIT_SUCCESS);
2365 case 'h':
2366 default:
2367 usage(argv[0]);
2371 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
2372 exit(EXIT_FAILURE);
2374 #ifdef WITH_PINENTRY
2375 if (disable_pinentry == TRUE)
2376 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
2377 #endif
2379 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
2380 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
2382 if (log_syslog == TRUE)
2383 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
2385 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
2386 iter = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
2387 errno = 0;
2389 if (setpriority(PRIO_PROCESS, 0, iter) == -1) {
2390 log_write("setpriority(): %s", strerror(errno));
2391 goto do_exit;
2395 #ifdef HAVE_MLOCKALL
2396 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
2397 log_write("mlockall(): %s", strerror(errno));
2398 goto do_exit;
2400 #endif
2402 setup_gcrypt();
2404 if (convert) {
2405 if (!outfile)
2406 usage(argv[0]);
2408 opt = convert_file(convert, keyfile, outfile);
2409 g_key_file_free(keyfileh);
2410 g_free(rcfile);
2411 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
2414 if (import) {
2415 if (!outfile)
2416 usage(argv[0]);
2418 if (cmd_iterations == -1)
2419 cmd_iterations = get_key_file_integer("global", "iterations");
2421 opt = xml_import(import, outfile, keyfile, cmd_iterations);
2422 g_key_file_free(keyfileh);
2423 g_free(rcfile);
2424 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
2427 g_key_file_set_list_separator(keyfileh, ',');
2429 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
2430 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
2432 if (*p == '~') {
2433 p++;
2434 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
2435 g_free(p);
2436 socketarg = g_strdup(buf);
2438 else
2439 socketarg = p;
2441 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
2442 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
2444 datadir = expand_homedir(p);
2445 g_free(p);
2447 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
2448 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
2449 disable_list_and_dump = n;
2451 else
2452 disable_list_and_dump = secure;
2454 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
2455 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
2456 else
2457 default_timeout = -1;
2459 setup_logging(keyfileh);
2461 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2462 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2464 if (argc != optind) {
2465 if (cache_push)
2466 ptotal = g_strv_length(cache_push);
2468 for (; optind < argc; optind++) {
2469 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2470 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
2474 if (strchr(socketarg, '/') == NULL) {
2475 socketdir = g_get_current_dir();
2476 socketname = g_strdup(socketarg);
2477 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2479 else {
2480 socketname = g_strdup(strrchr(socketarg, '/'));
2481 socketname++;
2482 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2483 socketdir = g_strdup(socketarg);
2484 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2487 if (chdir(datadir)) {
2488 log_write("%s: %s", datadir, strerror(errno));
2489 unlink(socketpath);
2490 goto do_exit;
2493 if (parse_rcfile_keys() == FALSE)
2494 goto do_exit;
2496 clear_rcfile_keys();
2499 * Set the cache entry for a file. Prompts for the password.
2501 if (cache_push) {
2502 for (opt = 0; cache_push[opt]; opt++)
2503 do_cache_push(cache_push[opt], NULL);
2505 g_strfreev(cache_push);
2506 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2510 * bind() doesn't like the full pathname of the socket or any non alphanum
2511 * characters so change to the directory where the socket is wanted then
2512 * create it then change to datadir.
2514 if (chdir(socketdir)) {
2515 log_write("%s: %s", socketdir, strerror(errno));
2516 goto do_exit;
2519 g_free(socketdir);
2521 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2522 log_write("socket(): %s", strerror(errno));
2523 goto do_exit;
2526 addr.sun_family = AF_UNIX;
2527 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2529 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2530 log_write("bind(): %s", strerror(errno));
2532 if (errno == EADDRINUSE)
2533 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2534 "stale socket. Please remove it manually."), socketpath);
2536 do_unlink = 0;
2537 goto do_exit;
2540 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2541 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2542 mode_t mode = strtol(t, NULL, 8);
2543 mode_t mask = umask(0);
2545 g_free(t);
2547 if (chmod(socketname, mode) == -1) {
2548 log_write("%s: %s", socketname, strerror(errno));
2549 close(sockfd);
2550 unlink(socketpath);
2551 umask(mask);
2552 goto do_exit;
2555 umask(mask);
2558 g_free(--socketname);
2560 if (chdir(datadir)) {
2561 log_write("%s: %s", datadir, strerror(errno));
2562 close(sockfd);
2563 unlink(socketpath);
2564 goto do_exit;
2567 g_free(datadir);
2568 pthread_mutexattr_init(&mattr);
2569 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE_NP);
2570 pthread_mutex_init(&cache_mutex, &mattr);
2571 pthread_mutexattr_destroy(&mattr);
2572 pthread_mutex_init(&quit_mutex, NULL);
2573 pthread_cond_init(&quit_cond, NULL);
2574 #ifdef WITH_PINENTRY
2575 pthread_mutex_init(&pin_mutex, NULL);
2576 #endif
2578 if (listen(sockfd, 0) == -1) {
2579 log_write("listen(): %s", strerror(errno));
2580 goto do_exit;
2583 cmdline = FALSE;
2585 if (startStopTcp(FALSE) == FALSE)
2586 goto do_exit;
2588 if (background) {
2589 switch (fork()) {
2590 case -1:
2591 log_write("fork(): %s", strerror(errno));
2592 goto do_exit;
2593 case 0:
2594 close(0);
2595 close(1);
2596 close(2);
2597 setsid();
2598 break;
2599 default:
2600 exit(EXIT_SUCCESS);
2604 server_loop(sockfd, &socketpath);
2605 estatus = EXIT_SUCCESS;
2607 do_exit:
2608 if (socketpath && do_unlink) {
2609 unlink(socketpath);
2610 g_free(socketpath);
2613 #ifdef WITH_GNUTLS
2614 startStopTcp(TRUE);
2615 gnutls_global_deinit();
2616 #endif
2618 g_key_file_free(keyfileh);
2619 g_free(rcfile);
2620 xmlCleanupParser();
2621 xmlCleanupGlobals();
2623 if (estatus == EXIT_SUCCESS)
2624 log_write(N_("pwmd exiting normally"));
2626 #if defined(DEBUG) && !defined(MEM_DEBUG)
2627 xdump();
2628 #endif
2629 exit(estatus);