Fixed some comple time conditionals.
[pwmd.git] / src / pwmd.c
blob93c3204a702bfd00432ae6eaca09f56aae4b6919
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 #include "mem.h"
61 #include "xml.h"
62 #include "common.h"
64 #ifdef WITH_PINENTRY
65 #include "pinentry.h"
66 #endif
68 #ifdef WITH_GNUTLS
69 #include "tls.h"
70 #endif
71 #include "commands.h"
72 #include "pwmd_error.h"
73 #include "cache.h"
74 #include "misc.h"
75 #include "pwmd.h"
77 GCRY_THREAD_OPTION_PTHREAD_IMPL;
79 static void clear_rcfile_keys()
81 gsize n;
82 gchar **groups;
83 gchar **p;
85 groups = g_key_file_get_groups(keyfileh, &n);
87 for (p = groups; *p; p++) {
88 GError *rc = NULL;
90 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE)
91 g_key_file_set_string(keyfileh, *p, "key", "");
94 g_strfreev(groups);
97 static void reload_rcfile()
99 gboolean b = disable_list_and_dump;
100 GKeyFile *k;
102 log_write(N_("reloading configuration file '%s'"), rcfile);
103 k = parse_rcfile(FALSE);
105 if (!k)
106 return;
108 g_key_file_free(keyfileh);
109 keyfileh = k;
110 parse_rcfile_keys();
111 clear_rcfile_keys();
112 disable_list_and_dump = b;
113 #ifdef WITH_GNUTLS
114 startStopTcp(FALSE);
115 #endif
116 startStopKeepAlive(FALSE);
117 send_status_all(STATUS_CONFIG);
120 gpg_error_t send_syserror(assuan_context_t ctx, gint e)
122 gpg_error_t n = gpg_error_from_errno(e);
124 return assuan_process_done(ctx, assuan_set_error(ctx, n, gpg_strerror(n)));
127 gpg_error_t send_error(assuan_context_t ctx, gpg_error_t e)
129 gpg_err_code_t n = gpg_err_code(e);
130 gpg_error_t code = gpg_err_make(PWMD_ERR_SOURCE, n);
131 struct client_s *client = assuan_get_pointer(ctx);
133 if (!e)
134 return assuan_process_done(ctx, 0);
136 if (!ctx) {
137 log_write("%s", pwmd_strerror(e));
138 return e;
141 if (n == EPWMD_LIBXML_ERROR) {
142 xmlErrorPtr xe = client->xml_error;
144 if (!xe)
145 xe = xmlGetLastError();
147 e = assuan_process_done(ctx, assuan_set_error(ctx, code, xe->message));
148 log_write("%s", xe->message);
150 if (xe == client->xml_error)
151 xmlResetError(xe);
152 else
153 xmlResetLastError();
155 client->xml_error = NULL;
156 return e;
159 return assuan_process_done(ctx, assuan_set_error(ctx, code, pwmd_strerror(e)));
162 static struct client_thread_s *find_cn(pthread_t tid)
164 guint t, i;
166 pthread_mutex_lock(&cn_mutex);
168 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
169 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
171 if (cn->tid == tid) {
172 pthread_mutex_unlock(&cn_mutex);
173 return cn;
177 pthread_mutex_unlock(&cn_mutex);
178 return NULL;
181 void log_write(const gchar *fmt, ...)
183 gchar *args, *line;
184 va_list ap;
185 struct tm *tm;
186 time_t now;
187 gchar tbuf[21];
188 gint fd = -1;
189 struct client_thread_s *cn;
190 gchar *name = "";
191 gchar buf[255];
193 if ((!logfile && !isatty(STDERR_FILENO) && log_syslog == FALSE) || !fmt)
194 return;
196 if (!cmdline && logfile) {
197 if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
198 warn("%s", logfile);
199 return;
203 va_start(ap, fmt);
205 if (g_vasprintf(&args, fmt, ap) == -1) {
206 if (logfile)
207 close(fd);
209 va_end(ap);
210 return;
213 va_end(ap);
215 if (cmdline) {
216 fprintf(stderr, "%s\n", args);
217 fflush(stderr);
218 g_free(args);
219 return;
222 cn = find_cn(pthread_self());
224 if (cn) {
225 if (!cn->name)
226 name = print_fmt(buf, sizeof(buf), "%i: ", cn->fd);
227 else
228 name = print_fmt(buf, sizeof(buf), "%s(%i): ", cn->name, cn->fd);
231 if (!cmdline && log_syslog == TRUE)
232 syslog(LOG_INFO, "%s%s", name, args);
234 time(&now);
235 tm = localtime(&now);
236 strftime(tbuf, sizeof(tbuf), "%b %d %Y %H:%M:%S ", tm);
237 tbuf[sizeof(tbuf) - 1] = 0;
239 if (args[strlen(args)-1] == '\n')
240 args[strlen(args)-1] = 0;
242 line = g_strdup_printf("%s %i %s%s\n", tbuf, getpid(), name, args);
243 g_free(args);
245 if (!line) {
246 if (logfile)
247 close(fd);
249 return;
252 if (logfile) {
253 write(fd, line, strlen(line));
254 fsync(fd);
255 close(fd);
258 if (isatty(STDERR_FILENO)) {
259 fprintf(stderr, "%s", line);
260 fflush(stderr);
263 g_free(line);
266 static void usage(gchar *pn)
268 g_fprintf(stderr, N_(
269 "Usage: %s [-hvDnP] [-f <rcfile>] [-C <filename>] "
270 "[-I <filename> [-i <iter>]]\n "
271 "[-k <keyfile>] [-o <outfile>] [file1] [...]\n"
272 " -n run as a foreground process\n"
273 " -f load the specified rcfile (~/.pwmd/config)\n"
274 " -C convert a version 1 data file to version 2\n"
275 " -I import an XML file\n"
276 " -i encrypt with the specified number of iterations when importing\n"
277 " (config default in the \"global\" section)\n"
278 " -k obtain the key from the specified file\n"
279 " -o output file for use with the -C and -I options\n"
280 " -D disable use of the LIST and DUMP commands\n"
281 " -P disable pinentry\n"
282 " -v version\n"
283 " -h this help text\n"
284 ), pn);
285 exit(EXIT_FAILURE);
288 static int gcry_SecureCheck(const void *ptr)
290 return 1;
293 static void setup_gcrypt()
295 gcry_check_version(NULL);
297 gcry_set_allocation_handler(xmalloc, xmalloc, gcry_SecureCheck, xrealloc,
298 xfree);
300 if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, NULL,
301 NULL) != 0)
302 errx(EXIT_FAILURE, N_("Required AES cipher not supported by libgcrypt."));
304 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_KEYLEN, NULL, &gcrykeysize);
305 gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_GET_BLKLEN, NULL, &gcryblocksize);
308 static gint new_connection(struct client_s *cl)
310 gpg_error_t rc;
311 gchar ver[ASSUAN_LINELENGTH];
313 rc = assuan_init_socket_server_ext(&cl->ctx, cl->thd->fd, 2);
315 if (rc)
316 goto fail;
318 assuan_set_pointer(cl->ctx, cl);
319 g_snprintf(ver, sizeof(ver), "%s", PACKAGE_STRING);
320 assuan_set_hello_line(cl->ctx, ver);
321 rc = register_commands(cl->ctx);
323 if (rc)
324 goto fail;
326 rc = assuan_accept(cl->ctx);
328 if (rc)
329 goto fail;
331 return 0;
333 fail:
334 log_write("%s", gpg_strerror(rc));
335 return 1;
338 gpg_error_t send_status(assuan_context_t ctx, status_msg_t which,
339 const gchar *fmt, ...)
341 gchar *line = NULL;
342 struct client_s *client = assuan_get_pointer(ctx);
343 gchar buf[ASSUAN_LINELENGTH];
344 gchar *status = NULL;
345 va_list ap;
347 if (fmt) {
348 va_start(ap, fmt);
349 g_vsnprintf(buf, sizeof(buf), fmt, ap);
350 va_end(ap);
351 line = buf;
354 switch (which) {
355 case STATUS_CACHE:
356 CACHE_LOCK(client->ctx);
357 line = print_fmt(buf, sizeof(buf), "%i", cache_file_count());
358 CACHE_UNLOCK;
359 status = "CACHE";
360 break;
361 case STATUS_CLIENTS:
362 pthread_mutex_lock(&cn_mutex);
363 line = print_fmt(buf, sizeof(buf), "%i", g_slist_length(cn_thread_list));
364 pthread_mutex_unlock(&cn_mutex);
365 status = "CLIENTS";
366 break;
367 case STATUS_CONFIG:
368 status = "CONFIG";
369 break;
370 case STATUS_KEEPALIVE:
371 status = "KEEPALIVE";
372 break;
373 case STATUS_LOCKED:
374 status = "LOCKED";
375 line = N_("Waiting for lock");
376 break;
377 case STATUS_ENCRYPT:
378 status = "ENCRYPT";
379 break;
380 case STATUS_DECRYPT:
381 status = "DECRYPT";
382 break;
383 case STATUS_DECOMPRESS:
384 status = "DECOMPRESS";
385 break;
386 case STATUS_COMPRESS:
387 status = "COMPRESS";
388 break;
391 if (!ctx) {
392 log_write("%s %s", status, line);
393 return 0;
396 return assuan_write_status(ctx, status, line);
399 void send_status_all(status_msg_t which)
401 guint i, t;
403 pthread_mutex_lock(&cn_mutex);
405 for (t = g_slist_length(cn_thread_list), i = 0; i < t; i++) {
406 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
407 size_t len;
409 pthread_cond_signal(&cn->msg_cond);
410 len = write(cn->msg_fd[1], &which, sizeof(status_msg_t));
412 if (len != sizeof(status_msg_t))
413 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
416 pthread_mutex_unlock(&cn_mutex);
419 static void xml_error_cb(void *data, xmlErrorPtr e)
421 struct client_s *client = data;
424 * Keep the first reported error as the one to show in the error
425 * description. Reset in send_error().
427 if (client->xml_error)
428 return;
430 xmlCopyError(e, client->xml_error);
433 void cleanup_crypto(struct client_crypto_s **c)
435 struct client_crypto_s *cr = *c;
437 if (!cr)
438 return;
440 if (cr->iv)
441 gcry_free(cr->iv);
443 if (cr->key)
444 gcry_free(cr->key);
446 if (cr->tkey)
447 gcry_free(cr->tkey);
449 if (cr->tkey2)
450 gcry_free(cr->tkey2);
452 if (cr->inbuf)
453 gcry_free(cr->inbuf);
455 if (cr->outbuf)
456 gcry_free(cr->outbuf);
458 if (cr->fh) {
459 if (cr->fh->fd != -1 ||
460 (cmdline == TRUE && cr->fh->fd != STDOUT_FILENO))
461 close(cr->fh->fd);
463 if (cr->fh->doc)
464 gcry_free(cr->fh->doc);
466 g_free(cr->fh);
469 if (cr->gh)
470 gcry_cipher_close(cr->gh);
472 g_free(cr);
473 *c = NULL;
477 * This is called after a child_thread terminates. Set with
478 * pthread_cleanup_push().
480 static void cleanup_cb(void *arg)
482 struct client_thread_s *cn = arg;
483 struct client_s *cl = cn->cl;
485 pthread_mutex_lock(&cn_mutex);
486 log_write(N_("exiting, fd=%i"), cn->fd);
488 if (cl->thd) {
489 pthread_cancel(cn->msg_tid);
490 pthread_join(cn->msg_tid, NULL);
491 pthread_cancel(cn->msg_sender_tid);
492 pthread_join(cn->msg_sender_tid, NULL);
493 close(cl->thd->msg_fd[0]);
494 close(cl->thd->msg_fd[1]);
497 pthread_join(cn->tid, NULL);
499 if (cl && cl->freed == FALSE)
500 cleanup_client(cl);
502 #ifdef WITH_GNUTLS
503 if (cn->tls) {
504 gnutls_deinit(cn->tls->ses);
506 if (cn->tls->fp)
507 g_free(cn->tls->fp);
509 g_free(cn->tls);
511 #endif
513 if (cl && cl->ctx)
514 assuan_deinit_server(cl->ctx);
516 #ifdef WITH_PINENTRY
517 if (cl && cl->pinentry)
518 cleanup_pinentry(cl->pinentry);
519 #endif
521 if (cl->crypto)
522 cleanup_crypto(&cl->crypto);
524 g_free(cl);
526 if (cn->name)
527 g_free(cn->name);
529 if (pthread_mutex_trylock(&cn->msg_mutex) == EBUSY)
530 pthread_mutex_unlock(&cn->msg_mutex);
531 else
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_sender_mutex) == EBUSY)
538 pthread_mutex_unlock(&cn->msg_sender_mutex);
539 else
540 pthread_mutex_unlock(&cn->msg_sender_mutex);
542 pthread_mutex_destroy(&cn->msg_sender_mutex);
543 pthread_cond_destroy(&cn->msg_sender_cond);
545 for (;;) {
546 struct status_msg_s *m = g_slist_nth_data(cn->msg_queue, 0);
548 if (!m)
549 break;
551 cn->msg_queue = g_slist_remove(cn->msg_queue, m);
552 g_free(m);
555 cn_thread_list = g_slist_remove(cn_thread_list, cn);
556 g_free(cn);
557 pthread_mutex_unlock(&cn_mutex);
558 send_status_all(STATUS_CLIENTS);
561 static void *client_msg_sender_thread(void *arg)
563 struct client_thread_s *thd = arg;
565 pthread_mutex_lock(&thd->msg_sender_mutex);
567 for (;;) {
568 struct status_msg_s *msg;
569 gpg_error_t rc;
571 pthread_cond_wait(&thd->msg_sender_cond, &thd->msg_sender_mutex);
572 pthread_testcancel();
574 /* The messages may have been stacked while waiting for send_status()
575 * to return. Send what's in the queue. */
576 for (;;) {
577 msg = g_slist_nth_data(thd->msg_queue, 0);
579 if (!msg)
580 break;
582 /* Unlock to prevent blocking in client_msg_thread(). */
583 pthread_mutex_unlock(&thd->msg_sender_mutex);
584 rc = send_status(thd->cl->ctx, msg->msg, NULL);
585 pthread_mutex_lock(&thd->msg_sender_mutex);
586 thd->msg_queue = g_slist_remove(thd->msg_queue, msg);
587 g_free(msg);
588 pthread_testcancel();
590 if (rc) {
591 //FIXME
596 return NULL;
600 * This function waits for a signal from send_status_all() then appends a
601 * message read from a pipe to the clients message queue. The actual sending
602 * of the message is done in client_msg_sender_thread() which waits for a
603 * signal from this function. This prevents blocking in assuan_send_status()
604 * when sending to remote clients. The messages are sent in order that they
605 * arrive which wouldn't be guaranteed if a thread was created here instead.
607 static void *client_msg_thread(void *arg)
609 struct client_thread_s *thd = arg;
611 pthread_mutex_lock(&thd->msg_mutex);
613 for (;;) {
614 fd_set rfds;
615 int n;
616 status_msg_t m;
617 size_t len;
618 struct status_msg_s *msg;
620 pthread_cond_wait(&thd->msg_cond, &thd->msg_mutex);
621 pthread_testcancel();
622 FD_ZERO(&rfds);
623 FD_SET(thd->msg_fd[0], &rfds);
624 n = select(thd->msg_fd[0]+1, &rfds, NULL, NULL, NULL);
626 if (n <= 0 || !FD_ISSET(thd->msg_fd[0], &rfds))
627 continue;
629 len = read(thd->msg_fd[0], &m, sizeof(status_msg_t));
630 pthread_testcancel();
632 if (len != sizeof(status_msg_t)) {
633 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
634 continue;
637 pthread_mutex_lock(&thd->msg_sender_mutex);
639 /* Don't append duplicate status messages. If the client is lagged and
640 * there are a bunch of status messages needing to be sent, only send
641 * the latest unique ones. */
642 for (n = 0; n < g_slist_length(thd->msg_queue); n++) {
643 msg = g_slist_nth_data(thd->msg_queue, n);
645 if (msg->msg == m)
646 goto done;
649 msg = g_malloc(sizeof(struct status_msg_s));
651 if (!msg) {
652 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
653 pthread_mutex_unlock(&thd->msg_sender_mutex);
654 continue;
657 msg->msg = m;
658 thd->msg_queue = g_slist_append(thd->msg_queue, msg);
659 done:
660 pthread_mutex_unlock(&thd->msg_sender_mutex);
661 pthread_cond_signal(&thd->msg_sender_cond);
664 return NULL;
668 * Called every time a connection is made via pthread_create(). This is the
669 * thread entry point.
671 static void *client_thread(void *data)
673 struct client_thread_s *thd = data;
674 struct client_s *cl = g_malloc0(sizeof(struct client_s));
675 gpg_error_t rc;
676 pthread_attr_t attr;
679 * Prevent a race condition with init_new_connection() if this thread
680 * fails (returns) for some reason before init_new_connection() releases
681 * the cn_mutex.
683 pthread_mutex_lock(&cn_mutex);
684 pthread_mutex_unlock(&cn_mutex);
685 pthread_cleanup_push(cleanup_cb, thd);
687 if (!cl) {
688 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
689 goto fail;
692 thd->cl = cl;
694 #ifdef WITH_GNUTLS
696 * Do the TLS handshake before anything else.
698 if (thd->remote) {
699 gchar *prio = get_key_file_string("global", "cipher_suite");
701 thd->tls = tls_init(thd->fd, prio);
702 g_free(prio);
704 if (!thd->tls) {
705 close(thd->fd);
706 goto fail;
709 #endif
711 cl->thd = thd;
714 * This is a "child" thread. Don't catch any signals. Let the master
715 * thread take care of signals in server_loop().
717 if (new_connection(cl))
718 goto fail;
720 #ifdef WITH_PINENTRY
721 cl->pinentry = pinentry_init();
723 if (!cl->pinentry) {
724 g_free(cl);
725 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
726 goto fail;
729 #ifdef WITH_GNUTLS
730 if (thd->remote)
731 cl->pinentry->enable = FALSE;
732 #endif
733 #endif
735 #ifdef HAVE_MLOCKALL
736 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
737 log_write("mlockall(): %s", strerror(errno));
738 goto fail;
740 #endif
742 if (pipe(thd->msg_fd) == -1) {
743 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(errno));
744 goto fail;
747 pthread_cond_init(&thd->msg_cond, NULL);
748 pthread_mutex_init(&thd->msg_mutex, NULL);
749 pthread_attr_init(&attr);
750 pthread_create(&thd->msg_tid, &attr, client_msg_thread, thd);
752 pthread_cond_init(&thd->msg_sender_cond, NULL);
753 pthread_mutex_init(&thd->msg_sender_mutex, NULL);
754 pthread_create(&thd->msg_sender_tid, &attr, client_msg_sender_thread, thd);
755 pthread_attr_destroy(&attr);
756 rc = send_status(cl->ctx, STATUS_CACHE, NULL);
758 if (rc) {
759 log_write("%s", gpg_strerror(rc));
760 goto fail;
763 send_status_all(STATUS_CLIENTS);
764 xmlSetStructuredErrorFunc(cl, xml_error_cb);
766 for (;;) {
767 fd_set rfds;
768 int n;
769 struct timeval tv = {1,0};
771 FD_ZERO(&rfds);
772 FD_SET(cl->thd->fd, &rfds);
774 #ifdef WITH_PINENTRY
775 if (cl->pinentry->status == PINENTRY_RUNNING)
776 FD_SET(cl->pinentry->fd, &rfds);
778 n = cl->thd->fd > cl->pinentry->fd ? cl->thd->fd : cl->pinentry->fd;
779 #else
780 n = cl->thd->fd;
781 #endif
782 n = select(n+1, &rfds, NULL, NULL, &tv);
784 if (n <= 0)
785 continue;
787 if (FD_ISSET(cl->thd->fd, &rfds)) {
788 rc = assuan_process_next(cl->ctx);
790 if (rc) {
791 cl->inquire_status = INQUIRE_INIT;
793 if (gpg_err_code(rc) == GPG_ERR_EOF)
794 goto done;
796 log_write("assuan_process_next(): %s", gpg_strerror(rc));
797 rc = send_error(cl->ctx, gpg_err_make(PWMD_ERR_SOURCE, rc));
799 if (rc) {
800 log_write("assuan_process_done(): %s", gpg_strerror(rc));
801 goto done;
804 else {
805 #ifdef WITH_PINENTRY
806 if (cl->pinentry->pid && cl->pinentry->status == PINENTRY_INIT)
807 cl->pinentry->status = PINENTRY_RUNNING;
808 #endif
810 switch (cl->inquire_status) {
811 case INQUIRE_BUSY:
812 case INQUIRE_INIT:
813 break;
814 case INQUIRE_DONE:
815 cl->inquire_status = INQUIRE_INIT;
816 rc = assuan_process_done(cl->ctx, 0);
817 break;
822 #ifdef WITH_PINENTRY
823 pinentry_iterate(cl,
824 cl->pinentry->fd != -1 && FD_ISSET(cl->pinentry->fd, &rfds));
825 #endif
829 * Client cleanup (including XML data) is done in cleanup_cb() from
830 * the cleanup thread.
832 done:
833 fail:
834 if (1) {} // Fixes compile time error with pthread_cleanup_push().
835 pthread_cleanup_pop(1);
836 pthread_exit(PTHREAD_CANCELED);
837 return NULL;
840 static void setup_logging(GKeyFile *kf)
842 gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL);
844 if (n == TRUE) {
845 gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL);
847 if (*p == '~') {
848 gchar buf[PATH_MAX];
850 p++;
851 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
852 g_free(p);
854 if (logfile)
855 g_free(logfile);
857 logfile = g_strdup(buf);
859 else {
860 if (logfile)
861 g_free(logfile);
863 logfile = p;
867 log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL);
871 * Make sure all settings are set to either the specified setting or a
872 * default.
874 static void set_rcfile_defaults(GKeyFile *kf)
876 gchar buf[PATH_MAX];
878 if (g_key_file_has_key(kf, "global", "socket_path", NULL) == FALSE) {
879 g_snprintf(buf, sizeof(buf), "~/.pwmd/socket");
880 g_key_file_set_string(kf, "global", "socket_path", buf);
883 if (g_key_file_has_key(kf, "global", "data_directory", NULL) == FALSE) {
884 g_snprintf(buf, sizeof(buf), "~/.pwmd/data");
885 g_key_file_set_string(kf, "global", "data_directory", buf);
888 if (g_key_file_has_key(kf, "global", "backup", NULL) == FALSE)
889 g_key_file_set_boolean(kf, "global", "backup", TRUE);
891 if (g_key_file_has_key(kf, "global", "log_path", NULL) == FALSE) {
892 g_snprintf(buf, sizeof(buf), "~/.pwmd/log");
893 g_key_file_set_string(kf, "global", "log_path", buf);
896 if (g_key_file_has_key(kf, "global", "enable_logging", NULL) == FALSE)
897 g_key_file_set_boolean(kf, "global", "enable_logging", FALSE);
899 #ifdef HAVE_MLOCKALL
900 if (g_key_file_has_key(kf, "global", "disable_mlockall", NULL) == FALSE)
901 g_key_file_set_boolean(kf, "global", "disable_mlockall", TRUE);
902 #endif
904 if (g_key_file_has_key(kf, "global", "cache_timeout", NULL) == FALSE)
905 g_key_file_set_integer(kf, "global", "cache_timeout", -1);
907 if (g_key_file_has_key(kf, "global", "iterations", NULL) == FALSE ||
908 g_key_file_get_integer(kf, "global", "iterations", 0) < 0)
909 g_key_file_set_integer(kf, "global", "iterations", 1);
911 if (g_key_file_has_key(kf, "global", "disable_list_and_dump", NULL) == FALSE)
912 g_key_file_set_boolean(kf, "global", "disable_list_and_dump", FALSE);
914 if (g_key_file_has_key(kf, "global", "iteration_progress", NULL) == FALSE)
915 g_key_file_set_integer(kf, "global", "iteration_progress", 0);
917 if (g_key_file_has_key(kf, "global", "compression_level", NULL) == FALSE)
918 g_key_file_set_integer(kf, "global", "compression_level", 6);
920 if (g_key_file_has_key(kf, "global", "recursion_depth", NULL) == FALSE)
921 g_key_file_set_integer(kf, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH);
923 if (g_key_file_has_key(kf, "global", "zlib_bufsize", NULL) == FALSE)
924 g_key_file_set_integer(kf, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE);
926 zlib_bufsize = (uInt)g_key_file_get_integer(kf, "global", "zlib_bufsize", NULL);
928 max_recursion_depth = g_key_file_get_integer(kf, "global", "recursion_depth", NULL);
929 disable_list_and_dump = g_key_file_get_boolean(kf, "global", "disable_list_and_dump", NULL);
931 #ifdef HAVE_MLOCKALL
932 disable_mlock = g_key_file_get_boolean(kf, "global", "disable_mlockall", NULL);
933 #endif
935 if (g_key_file_has_key(kf, "global", "syslog", NULL) == FALSE)
936 g_key_file_set_boolean(kf, "global", "syslog", FALSE);
938 if (g_key_file_has_key(kf, "global", "keepalive", NULL) == FALSE)
939 g_key_file_set_integer(kf, "global", "keepalive", 30);
941 #ifdef WITH_PINENTRY
942 if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE)
943 g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE);
945 if (g_key_file_has_key(kf, "global", "pinentry_timeout", NULL) == FALSE)
946 g_key_file_set_integer(kf, "global", "pinentry_timeout", 20);
947 #endif
949 #ifdef WITH_GNUTLS
950 if (g_key_file_has_key(kf, "global", "tcp_port", NULL) == FALSE)
951 g_key_file_set_integer(kf, "global", "tcp_port", 6466);
953 if (g_key_file_has_key(kf, "global", "enable_tcp", NULL) == FALSE)
954 g_key_file_set_boolean(kf, "global", "enable_tcp", FALSE);
956 if (g_key_file_has_key(kf, "global", "tcp_require_key", NULL) == FALSE)
957 g_key_file_set_boolean(kf, "global", "tcp_require_key", FALSE);
959 if (g_key_file_has_key(kf, "global", "tcp_wait", NULL) == FALSE)
960 g_key_file_set_boolean(kf, "global", "tcp_wait", 3);
962 if (g_key_file_has_key(kf, "global", "cipher_suite", NULL) == FALSE)
963 g_key_file_set_string(kf, "global", "cipher_suite", "SECURE256");
964 #endif
966 setup_logging(kf);
969 static GKeyFile *parse_rcfile(gboolean specified)
971 GKeyFile *kf = g_key_file_new();
972 GError *rc = NULL;
974 if (g_key_file_load_from_file(kf, rcfile, G_KEY_FILE_NONE, &rc) == FALSE) {
975 log_write("%s: %s", rcfile, rc->message);
977 if (cmdline && specified) {
978 g_clear_error(&rc);
979 return NULL;
982 if (rc->code == G_FILE_ERROR_NOENT) {
983 g_clear_error(&rc);
984 set_rcfile_defaults(kf);
985 return kf;
988 g_clear_error(&rc);
989 return NULL;
992 set_rcfile_defaults(kf);
993 return kf;
996 static gchar *do_get_password(const gchar *prompt)
998 gchar buf[LINE_MAX] = {0}, *p;
999 struct termios told, tnew;
1000 gchar *key;
1002 if (tcgetattr(STDIN_FILENO, &told) == -1) {
1003 log_write("tcgetattr(): %s", strerror(errno));
1004 return NULL;
1007 memcpy(&tnew, &told, sizeof(struct termios));
1008 tnew.c_lflag &= ~(ECHO);
1009 tnew.c_lflag |= ICANON|ECHONL;
1011 if (tcsetattr(STDIN_FILENO, TCSANOW, &tnew) == -1) {
1012 log_write("tcsetattr(): %s", strerror(errno));
1013 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1014 return NULL;
1017 fprintf(stderr, "%s", prompt);
1019 if ((p = fgets(buf, sizeof(buf), stdin)) == NULL) {
1020 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1021 return NULL;
1024 tcsetattr(STDIN_FILENO, TCSANOW, &told);
1025 p[strlen(p) - 1] = 0;
1027 if (!buf[0]) {
1028 key = gcry_malloc(1);
1029 key[0] = 0;
1031 else {
1032 key = gcry_malloc(strlen(p) + 1);
1033 sprintf(key, "%s", p);
1036 memset(&buf, 0, sizeof(buf));
1037 return key;
1040 /* Only used when "enable_pinentry" is "false" or -P. */
1041 static gpg_error_t get_input(const gchar *filename,
1042 struct client_crypto_s *crypto, guchar *key, pinentry_cmd_t which)
1044 gchar *prompt;
1046 if (which == PINENTRY_SAVE) {
1047 prompt = g_strdup_printf(N_("New passphrase for file %s: "), filename);
1048 crypto->tkey = do_get_password(prompt);
1049 g_free(prompt);
1051 if (!crypto->tkey) {
1052 log_write(N_("%s: Skipping file"), filename);
1053 return GPG_ERR_BAD_PASSPHRASE;
1056 prompt = g_strdup_printf(N_("Repeat passphrase: "));
1057 crypto->tkey2 = do_get_password(prompt);
1058 g_free(prompt);
1060 if (!crypto->tkey2) {
1061 log_write(N_("%s: Skipping file"), filename);
1062 return GPG_ERR_BAD_PASSPHRASE;
1065 if (strcmp(crypto->tkey, crypto->tkey2)) {
1066 log_write(N_("%s: Passphrase mismatch"), filename);
1067 return EPWMD_BADKEY;
1070 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
1071 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1072 return 0;
1075 prompt = g_strdup_printf(N_("Passphrase required for %s: "), filename);
1077 if ((crypto->tkey = do_get_password(prompt)) == NULL) {
1078 log_write(N_("%s: Skipping file"), filename);
1079 g_free(prompt);
1080 return GPG_ERR_BAD_PASSPHRASE;
1083 gcry_md_hash_buffer(GCRY_MD_SHA256, key, crypto->tkey,
1084 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1085 g_free(prompt);
1086 return 0;
1090 * inbuf must have been allocated with gcry_malloc().
1092 gpg_error_t export_common(const gchar *filename, struct client_crypto_s *crypto,
1093 gpointer inbuf, gulong insize)
1095 gpg_error_t rc;
1096 gint level, zrc;
1097 gulong outsize;
1098 gpointer outbuf;
1100 level = get_key_file_integer(filename, "compression_level");
1102 if (level < 0)
1103 level = 0;
1105 if (do_compress(NULL, level, inbuf, insize, &outbuf, &outsize, &zrc)
1106 == FALSE) {
1107 return zrc == Z_MEM_ERROR ? GPG_ERR_ENOMEM : GPG_ERR_COMPR_ALGO;
1110 rc = do_xml_encrypt(NULL, crypto, filename, outbuf, outsize);
1111 return rc;
1114 static gpg_error_t get_password(const gchar *filename,
1115 struct client_crypto_s *crypto, guchar *md5file, guchar *key,
1116 pinentry_cmd_t which)
1118 #ifdef WITH_PINENTRY
1119 gpg_error_t rc = 0;
1121 if (g_key_file_get_boolean(keyfileh, "global", "enable_pinentry", NULL)
1122 == FALSE) {
1123 #endif
1124 return get_input(filename, crypto, key, which);
1125 #ifdef WITH_PINENTRY
1127 else {
1128 gchar *result = NULL;
1129 struct pinentry_s *pin = g_malloc0(sizeof(struct pinentry_s));
1131 set_pinentry_defaults(pin);
1132 pin->which = which;
1133 pin->filename = g_strdup(filename);
1134 rc = pinentry_getpin(pin, &result);
1136 if (rc) {
1137 xfree(result);
1138 goto done;
1141 gcry_md_hash_buffer(GCRY_MD_SHA256, key, result, strlen(result) ? strlen(result) : 1);
1142 xfree(result);
1143 cleanup_pinentry(pin);
1146 done:
1147 return rc;
1148 #endif
1151 static gboolean _getline(const gchar *file, gchar **result, gpg_error_t *rc)
1153 FILE *fp;
1154 gchar buf[LINE_MAX] = {0}, *p;
1155 gchar *str = NULL;
1156 gint len;
1158 *rc = 0;
1160 if ((fp = fopen(file, "r")) == NULL) {
1161 *rc = gpg_error_from_syserror();
1162 return FALSE;
1165 p = fgets(buf, sizeof(buf), fp);
1166 fclose(fp);
1167 len = strlen(buf);
1169 if (len && buf[len - 1] == '\n')
1170 buf[--len] = 0;
1172 str = gcry_malloc(len + 1);
1174 if (!str) {
1175 *rc = gpg_error_from_errno(ENOMEM);
1176 return FALSE;
1179 memcpy(str, buf, len ? len : 1);
1180 str[len] = 0;
1181 memset(&buf, 0, sizeof(buf));
1182 *result = str;
1183 return TRUE;
1186 static gchar *parse_rcfile_keyfile(const gchar *filename, gboolean import,
1187 gpg_error_t *rc)
1189 GError *rv = NULL;
1190 gchar *t, *file = NULL, *str;
1192 *rc = GPG_ERR_UNKNOWN_ERRNO;
1194 if (import == FALSE) {
1195 if (g_key_file_has_key(keyfileh, filename, "key_file", &rv) == TRUE) {
1196 file = g_key_file_get_string(keyfileh, filename, "key_file", &rv);
1198 if (!file) {
1199 if (rv) {
1200 log_write("%s: key_file: %s", rcfile, rv->message);
1201 g_clear_error(&rv);
1204 return NULL;
1207 t = expand_homedir(file);
1209 if (!t) {
1210 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1211 *rc = gpg_error_from_errno(ENOMEM);
1212 return NULL;
1215 g_free(file);
1216 file = t;
1219 else {
1220 /* -I or -C. The filename is a key file. */
1221 file = g_strdup(filename);
1223 if (!file) {
1224 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1225 *rc = gpg_error_from_errno(ENOMEM);
1226 return NULL;
1230 if (rv) {
1231 log_write("%s: key_file: %s", rcfile, rv->message);
1232 g_clear_error(&rv);
1233 return NULL;
1236 if (!file)
1237 return NULL;
1239 if (_getline(file, &str, rc) == FALSE) {
1240 log_write("%s: %s: %s", filename, file, pwmd_strerror(*rc));
1241 g_free(file);
1242 return NULL;
1245 g_free(file);
1246 *rc = 0;
1247 return str;
1250 static gboolean xml_import(const gchar *filename, const gchar *outfile,
1251 const gchar *keyfile, gulong iter)
1253 xmlDocPtr doc;
1254 gint fd;
1255 struct stat st;
1256 gint len;
1257 xmlChar *xmlbuf;
1258 xmlChar *xml;
1259 gpg_error_t rc;
1260 struct client_crypto_s *crypto;
1262 if (stat(filename, &st) == -1) {
1263 log_write("%s: %s", filename, strerror(errno));
1264 return FALSE;
1267 crypto = init_client_crypto();
1269 if (!crypto)
1270 return FALSE;
1272 crypto->key = gcry_malloc(gcrykeysize);
1273 memset(crypto->key, 0, gcrykeysize);
1275 if (!crypto->key) {
1276 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1277 goto fail;
1280 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
1281 filename, outfile);
1283 if (iter && keyfile) {
1284 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1286 if (!crypto->tkey)
1287 goto fail;
1289 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1290 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1292 else if (iter) {
1293 rc = get_password(outfile, crypto, NULL, crypto->key, PINENTRY_SAVE);
1295 if (rc)
1296 goto fail;
1299 if ((fd = open(filename, O_RDONLY)) == -1) {
1300 log_write("%s: %s", filename, strerror(errno));
1301 goto fail;
1304 if ((xmlbuf = gcry_malloc(st.st_size+1)) == NULL) {
1305 close(fd);
1306 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1307 goto fail;
1310 if (read(fd, xmlbuf, st.st_size) == -1) {
1311 rc = errno;
1312 close(fd);
1313 errno = rc;
1314 log_write("%s: %s", filename, strerror(errno));
1315 goto fail;
1318 close(fd);
1319 xmlbuf[st.st_size] = 0;
1322 * Make sure the document validates.
1324 if ((doc = xmlReadDoc(xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS)) == NULL) {
1325 log_write("xmlReadDoc() failed");
1326 gcry_free(xmlbuf);
1327 goto fail;
1330 gcry_free(xmlbuf);
1331 xmlDocDumpMemory(doc, &xml, &len);
1332 xmlFreeDoc(doc);
1334 if (!iter)
1335 memset(crypto->key, '!', gcrykeysize);
1337 crypto->fh = g_malloc0(sizeof(file_header_internal_t));
1339 if (!crypto->fh) {
1340 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1341 goto fail;
1344 crypto->fh->fh2.iter = iter;
1345 rc = export_common(outfile, crypto, xml, len);
1346 xmlFree(xml);
1348 if (rc) {
1349 send_error(NULL, rc);
1350 goto fail;
1353 cleanup_crypto(&crypto);
1354 return TRUE;
1356 fail:
1357 cleanup_crypto(&crypto);
1358 return FALSE;
1361 gchar *get_key_file_string(const gchar *section, const gchar *what)
1363 gchar *val = NULL;
1364 GError *grc = NULL;
1366 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1367 val = g_key_file_get_string(keyfileh, section, what, &grc);
1369 if (grc) {
1370 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1371 g_clear_error(&grc);
1374 else {
1375 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1376 val = g_key_file_get_string(keyfileh, "global", what, &grc);
1378 if (grc) {
1379 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1380 g_clear_error(&grc);
1385 return val;
1388 gint get_key_file_integer(const gchar *section, const gchar *what)
1390 gint val = -1;
1391 GError *grc = NULL;
1393 if (g_key_file_has_key(keyfileh, section ? section : "global", what, NULL) == TRUE) {
1394 val = g_key_file_get_integer(keyfileh, section ? section : "global", what, &grc);
1396 if (grc) {
1397 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1398 g_clear_error(&grc);
1401 else {
1402 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1403 val = g_key_file_get_integer(keyfileh, "global", what, &grc);
1405 if (grc) {
1406 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1407 g_clear_error(&grc);
1412 return val;
1415 gboolean get_key_file_boolean(const gchar *section, const gchar *what)
1417 gboolean val = FALSE;
1418 GError *grc = NULL;
1420 if (g_key_file_has_key(keyfileh, section, what, NULL) == TRUE) {
1421 val = g_key_file_get_boolean(keyfileh, section, what, &grc);
1423 if (grc) {
1424 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1425 g_clear_error(&grc);
1428 else {
1429 if (g_key_file_has_key(keyfileh, "global", what, NULL) == TRUE) {
1430 val = g_key_file_get_boolean(keyfileh, "global", what, &grc);
1432 if (grc) {
1433 log_write("%s(%i): %s", __FILE__, __LINE__, grc->message);
1434 g_clear_error(&grc);
1439 return val;
1442 static gboolean parse_rcfile_keys()
1444 gsize n;
1445 gchar **groups;
1446 gchar **p;
1447 gchar *str;
1449 groups = g_key_file_get_groups(keyfileh, &n);
1451 for (p = groups; *p; p++) {
1452 GError *rc = NULL;
1454 if (g_key_file_has_key(keyfileh, *p, "key", &rc) == TRUE) {
1455 str = g_key_file_get_string(keyfileh, *p, "key", &rc);
1457 if (!str) {
1458 if (rc) {
1459 log_write("%s: key: %s", rcfile, rc->message);
1460 g_clear_error(&rc);
1462 continue;
1465 do_cache_push(*p, str);
1466 g_free(str);
1467 continue;
1470 if (rc) {
1471 log_write("%s: key: %s", rcfile, rc->message);
1472 g_clear_error(&rc);
1473 continue;
1476 gpg_error_t ret;
1477 str = parse_rcfile_keyfile(*p, FALSE, &ret);
1479 if (!str)
1480 continue;
1482 do_cache_push(*p, str);
1483 gcry_free(str);
1486 g_strfreev(groups);
1487 return TRUE;
1490 static gboolean do_cache_push(const gchar *filename, const gchar *password)
1492 guchar md5file[16];
1493 gint timeout;
1494 const gchar *p = filename;
1495 struct client_crypto_s *crypto;
1496 gpg_error_t rc;
1498 while (isspace(*p))
1499 p++;
1501 if (!*p)
1502 return FALSE;
1504 if (valid_filename(p) == FALSE) {
1505 log_write(N_("%s: Invalid characters in filename"), p);
1506 return FALSE;
1509 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, p, strlen(p));
1511 if (access(p, R_OK|W_OK) != 0) {
1512 log_write("%s: %s", p, strerror(errno));
1513 return FALSE;
1516 crypto = init_client_crypto();
1518 if (!crypto)
1519 return FALSE;
1521 crypto->fh = read_file_header(filename, FALSE, &rc);
1523 if (!crypto->fh) {
1524 log_write("%s: %s", p, pwmd_strerror(rc));
1525 cleanup_crypto(&crypto);
1526 return FALSE;
1529 crypto->key = gcry_malloc(gcrykeysize);
1531 if (!crypto->key) {
1532 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1533 cleanup_crypto(&crypto);
1534 return FALSE;
1537 log_write(N_("Adding '%s' to the file cache ..."), filename);
1539 if (crypto->fh->fh2.iter <= 0) {
1540 memset(crypto->key, '!', gcrykeysize);
1541 goto try_decrypt;
1544 if (!password) {
1545 rc = get_password(p, crypto, md5file, crypto->key, PINENTRY_OPEN);
1547 if (rc) {
1548 send_error(NULL, rc);
1549 cleanup_crypto(&crypto);
1550 return FALSE;
1553 gcry_free(crypto->fh->doc);
1554 crypto->fh->doc = NULL;
1556 else
1557 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, password,
1558 strlen(password) ? strlen(password) : 1);
1560 try_decrypt:
1561 rc = try_xml_decrypt(NULL, crypto->key, crypto, NULL, NULL);
1563 if (rc) {
1564 log_write("%s: %s", filename, pwmd_strerror(rc));
1565 cleanup_crypto(&crypto);
1566 return FALSE;
1569 if (cache_update_key(md5file, crypto->key) == FALSE) {
1570 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1571 cleanup_crypto(&crypto);
1572 return FALSE;
1575 timeout = get_key_file_integer(p, "cache_timeout");
1576 cache_set_timeout(md5file, timeout);
1577 log_write(N_("File '%s' now cached"), filename);
1578 cleanup_crypto(&crypto);
1579 return TRUE;
1582 static void init_new_connection(gint fd, gchar *addr)
1584 pthread_t tid;
1585 pthread_attr_t attr;
1586 struct client_thread_s *new;
1587 int n;
1589 new = g_malloc0(sizeof(struct client_thread_s));
1591 if (!new) {
1592 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1593 return;
1596 pthread_mutex_lock(&cn_mutex);
1597 new->fd = fd;
1599 #ifdef WITH_GNUTLS
1600 if (addr)
1601 new->remote = TRUE;
1602 #endif
1604 pthread_attr_init(&attr);
1605 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1606 n = pthread_create(&tid, &attr, client_thread, new);
1607 pthread_attr_destroy(&attr);
1609 if (n) {
1610 g_free(new);
1611 log_write("pthread_create(): %s", strerror(n));
1612 pthread_mutex_unlock(&cn_mutex);
1613 return;
1616 new->tid = tid;
1617 cn_thread_list = g_slist_append(cn_thread_list, new);
1618 pthread_mutex_unlock(&cn_mutex);
1620 if (addr)
1621 log_write(N_("new connection: fd=%i, addr=%s"), fd, addr);
1622 else
1623 log_write(N_("new connection: fd=%i"), fd);
1626 #ifdef WITH_GNUTLS
1627 /* From Beej's Guide to Network Programming. It's a good tutorial. */
1628 static void *get_in_addr(struct sockaddr *sa)
1630 if (sa->sa_family == AF_INET)
1631 return &(((struct sockaddr_in*)sa)->sin_addr);
1633 return &(((struct sockaddr_in6*)sa)->sin6_addr);
1636 static void *tcp_accept_thread(void *arg)
1638 gint sockfd = (gint)arg;
1640 for (;;) {
1641 struct sockaddr_storage raddr;
1642 socklen_t slen = sizeof(raddr);
1643 gint fd = -1;
1644 gulong n;
1645 gchar *t;
1647 if ((fd = accept(sockfd, (struct sockaddr *)&raddr, &slen)) == -1) {
1648 if (errno != EAGAIN) {
1649 if (!quit) // probably EBADF
1650 log_write("accept(): %s", strerror(errno));
1652 break;
1656 if (quit)
1657 break;
1659 if (fd >= 0) {
1660 gchar s[INET6_ADDRSTRLEN];
1662 inet_ntop(raddr.ss_family, get_in_addr((struct sockaddr *)&raddr),
1663 s, sizeof s);
1664 init_new_connection(fd, s);
1667 t = get_key_file_string("global", "tcp_wait");
1668 n = strtol(t, NULL, 10);
1669 g_free(t);
1671 if (n < 0)
1672 n = 0;
1674 usleep(n*100000);
1677 /* Just in case accept() failed for some reason other than EBADF */
1678 quit = 1;
1679 pthread_exit(PTHREAD_CANCELED);
1680 return NULL;
1682 #endif
1684 static void *accept_thread(void *arg)
1686 gint sockfd = (gint)arg;
1688 for (;;) {
1689 socklen_t slen = sizeof(struct sockaddr_un);
1690 struct sockaddr_un raddr;
1691 gint fd = -1;
1693 if ((fd = accept(sockfd, (struct sockaddr *)&raddr, &slen)) == -1) {
1694 if (errno != EAGAIN) {
1695 if (!quit) // probably EBADF
1696 log_write("accept(): %s", strerror(errno));
1698 break;
1702 if (fd >= 0)
1703 init_new_connection(fd, NULL);
1706 /* Just in case accept() failed for some reason other than EBADF */
1707 quit = 1;
1708 pthread_exit(PTHREAD_CANCELED);
1709 return NULL;
1712 static void *adjust_cache_timer_thread(void *arg)
1714 for (;;) {
1715 sleep(1);
1716 pthread_testcancel();
1717 CACHE_LOCK(NULL);
1718 cache_adjust_timer();
1719 CACHE_UNLOCK;
1722 return NULL;
1725 static void *keepalive_thread(void *arg)
1727 struct timespec ts;
1728 gint to = (gint)arg;
1730 for (;;) {
1731 clock_gettime(CLOCK_REALTIME, &ts);
1732 ts.tv_sec += to;
1733 pthread_cond_timedwait(&keepalive_cond, &keepalive_cond_mutex, &ts);
1734 pthread_testcancel();
1735 send_status_all(STATUS_KEEPALIVE);
1738 return NULL;
1741 static void startStopKeepAlive(gboolean term)
1743 pthread_attr_t attr;
1744 gint n = get_key_file_integer("global", "keepalive");
1746 if (keepalive_tid)
1747 pthread_cancel(keepalive_tid);
1749 keepalive_tid = 0;
1750 pthread_mutex_trylock(&keepalive_cond_mutex);
1752 if (term)
1753 return;
1755 if (n > 0) {
1756 pthread_attr_init(&attr);
1757 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1758 pthread_create(&keepalive_tid, &attr, keepalive_thread, (void *)n);
1759 pthread_attr_destroy(&attr);
1763 static void server_loop(gint sockfd, gchar **socketpath)
1765 pthread_t accept_tid;
1766 guint n;
1767 sigset_t sigset;
1768 gint n_clients = 0;
1769 pthread_attr_t attr;
1770 pthread_t cache_timeout_tid;
1771 pthread_mutexattr_t mattr;
1773 pthread_mutexattr_init(&mattr);
1774 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE_NP);
1775 pthread_mutex_init(&cn_mutex, &mattr);
1776 pthread_mutexattr_destroy(&mattr);
1777 log_write(N_("%s started for user %s"), PACKAGE_STRING, g_get_user_name());
1778 pthread_attr_init(&attr);
1779 pthread_create(&accept_tid, &attr, accept_thread, (void *)sockfd);
1780 startStopKeepAlive(FALSE);
1781 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1782 pthread_create(&cache_timeout_tid, &attr, adjust_cache_timer_thread, NULL);
1783 sigemptyset(&sigset);
1785 /* Termination */
1786 sigaddset(&sigset, SIGTERM);
1787 sigaddset(&sigset, SIGINT);
1789 /* Clears the file cache. */
1790 sigaddset(&sigset, SIGUSR1);
1792 /* Configuration file reloading. */
1793 sigaddset(&sigset, SIGHUP);
1795 /* Caught in client_thread(). Sends a cache status message. */
1796 sigaddset(&sigset, SIGUSR2);
1798 /* Ignored everywhere. When a client disconnects abnormally this signal
1799 * gets raised. It isn't needed though because client_thread() will check
1800 * for rcs even after the client disconnects. */
1801 signal(SIGPIPE, SIG_IGN);
1802 pthread_sigmask(SIG_BLOCK, &sigset, NULL);
1804 do {
1805 gint sig;
1807 sigwait(&sigset, &sig);
1808 log_write(N_("caught signal %i (%s)"), sig, strsignal(sig));
1810 /* Caught a signal. */
1811 switch (sig) {
1812 case SIGHUP:
1813 reload_rcfile();
1814 break;
1815 case SIGABRT:
1816 CACHE_LOCK(NULL);
1817 cache_clear(NULL, 2);
1818 CACHE_UNLOCK;
1819 #ifndef MEM_DEBUG
1820 xpanic();
1821 #endif
1822 exit(EXIT_FAILURE);
1823 case SIGUSR1:
1824 CACHE_LOCK(NULL);
1825 log_write(N_("clearing file cache"));
1826 cache_clear(NULL, 2);
1827 CACHE_UNLOCK;
1828 break;
1829 default:
1830 quit = 1;
1831 shutdown(sockfd, SHUT_RDWR);
1832 close(sockfd);
1834 #ifdef WITH_GNUTLS
1835 if (tcpSockFd != -1) {
1836 shutdown(tcpSockFd, SHUT_RDWR);
1837 close(tcpSockFd);
1839 #endif
1840 break;
1842 } while (!quit);
1845 * We're out of the main server loop. This happens when a signal was sent
1846 * to terminate the daemon. We'll wait for all clients to disconnect
1847 * before exiting and ignore any following signals.
1849 pthread_join(accept_tid, NULL);
1850 pthread_attr_destroy(&attr);
1851 #ifdef WITH_GNUTLS
1852 startStopTcp(TRUE);
1853 #endif
1854 unlink(*socketpath);
1855 g_free(*socketpath);
1856 *socketpath = NULL;
1857 pthread_mutex_lock(&cn_mutex);
1858 n = g_slist_length(cn_thread_list);
1859 pthread_mutex_unlock(&cn_mutex);
1861 if (n)
1862 log_write(N_("waiting for all clients to disconnect"));
1864 while (n) {
1865 if (n != n_clients) {
1866 log_write(N_("%i clients remain"), n);
1867 n_clients = n;
1870 sleep(1);
1871 pthread_mutex_lock(&cn_mutex);
1872 n = g_slist_length(cn_thread_list);
1873 pthread_mutex_unlock(&cn_mutex);
1876 startStopKeepAlive(TRUE);
1877 pthread_cancel(cache_timeout_tid);
1878 cache_free();
1882 * Called from pinentry_fork() in the child process.
1884 void free_client_list()
1886 gint i, t = g_slist_length(cn_thread_list);
1888 for (i = 0; i < t; i++) {
1889 struct client_thread_s *cn = g_slist_nth_data(cn_thread_list, i);
1891 free_client(cn->cl);
1894 cache_free();
1897 struct client_crypto_s *init_client_crypto()
1899 struct client_crypto_s *new = g_malloc0(sizeof(struct client_crypto_s));
1900 gpg_error_t rc;
1902 if (!new) {
1903 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
1904 return NULL;
1907 rc = gcry_cipher_open(&new->gh, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
1909 if (rc) {
1910 log_write("%s(%i): %s", __FUNCTION__, __LINE__, gcry_strerror(rc));
1911 g_free(new);
1912 return NULL;
1915 return new;
1918 static gpg_error_t convert_file(const gchar *filename, const gchar *keyfile,
1919 const gchar *outfile)
1921 gpg_error_t rc;
1922 guchar md5file[16];
1923 guint iter;
1924 struct client_crypto_s *crypto = init_client_crypto();
1926 if (!crypto)
1927 return GPG_ERR_ENOMEM;
1929 crypto->key = gcry_malloc(gcrykeysize);
1931 if (!crypto->key) {
1932 cleanup_crypto(&crypto);
1933 return GPG_ERR_ENOMEM;
1936 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
1937 filename);
1938 crypto->fh = read_file_header(filename, TRUE, &rc);
1940 if (!crypto->fh)
1941 goto done;
1943 gcry_md_hash_buffer(GCRY_MD_MD5, md5file, filename, strlen(filename));
1945 /* The header in version 1 had a bug where the iterations were off-by-one.
1946 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
1947 * header.
1949 if (crypto->fh->fh1.iter >= 0) {
1950 if (keyfile) {
1951 crypto->tkey = parse_rcfile_keyfile(keyfile, TRUE, &rc);
1953 if (!crypto->tkey)
1954 goto done;
1956 gcry_md_hash_buffer(GCRY_MD_SHA256, crypto->key, crypto->tkey,
1957 strlen(crypto->tkey) ? strlen(crypto->tkey) : 1);
1959 else {
1960 rc = get_password(filename, crypto, md5file, crypto->key,
1961 PINENTRY_OPEN);
1963 if (rc)
1964 goto done;
1968 rc = try_xml_decrypt(NULL, crypto->key, crypto, &crypto->fh->doc,
1969 &crypto->fh->len);
1971 if (rc)
1972 goto done;
1974 rc = convert_xml((gchar **)&crypto->fh->doc, &crypto->fh->len);
1976 if (rc) {
1977 log_write("%s: %s", filename, pwmd_strerror(rc));
1978 goto done;
1981 crypto->fh->v1 = FALSE;
1982 iter = crypto->fh->fh1.iter;
1983 memset(&crypto->fh->fh2, 0, sizeof(crypto->fh->fh2));
1984 /* Keep the iterations and key from the original file. */
1985 crypto->fh->fh2.iter = iter+1; // Bugfix for v1 data files.
1986 rc = export_common(outfile, crypto, crypto->fh->doc, crypto->fh->len);
1988 done:
1989 if (rc)
1990 send_error(NULL, rc);
1992 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
1993 cleanup_crypto(&crypto);
1994 return rc;
1997 #ifdef WITH_GNUTLS
1998 static gboolean initTlsParams()
2000 int n;
2001 gchar *tmp, *tmp2;
2003 n = gnutls_certificate_allocate_credentials(&x509_cred);
2005 if (n != GNUTLS_E_SUCCESS) {
2006 log_write("%s", gnutls_strerror(n));
2007 x509_cred = NULL;
2008 goto fail;
2011 tmp = expand_homedir("~/.pwmd/ca-cert.pem");
2013 if (!tmp) {
2014 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
2015 goto fail;
2018 n = gnutls_certificate_set_x509_trust_file(x509_cred, tmp,
2019 GNUTLS_X509_FMT_PEM);
2020 g_free(tmp);
2022 if (n < 0) {
2023 log_write("%s", gnutls_strerror(n));
2024 goto fail;
2027 tmp = expand_homedir("~/.pwmd/server-cert.pem");
2029 if (!tmp) {
2030 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
2031 goto fail;
2034 tmp2 = expand_homedir("~/.pwmd/server-key.pem");
2036 if (!tmp2) {
2037 g_free(tmp);
2038 log_write("%s(%i): %s", __FILE__, __LINE__, strerror(ENOMEM));
2039 goto fail;
2042 n = gnutls_certificate_set_x509_key_file (x509_cred, tmp, tmp2,
2043 GNUTLS_X509_FMT_PEM);
2044 g_free(tmp);
2045 g_free(tmp2);
2047 if (n != GNUTLS_E_SUCCESS) {
2048 log_write("%s", gnutls_strerror(n));
2049 goto fail;
2052 log_write("%s", N_("Generating key exchange parameters..."));
2053 n = gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
2055 if (n) {
2056 log_write("%s", gpg_strerror(n));
2057 goto fail;
2060 n = gnutls_dh_params_init(&dh_params);
2062 if (n != GNUTLS_E_SUCCESS) {
2063 log_write("%s", gnutls_strerror(n));
2064 goto fail;
2067 n = gnutls_dh_params_generate2(dh_params, 1024);
2069 if (n != GNUTLS_E_SUCCESS) {
2070 log_write("%s", gnutls_strerror(n));
2071 goto fail;
2074 gnutls_certificate_set_dh_params(x509_cred, dh_params);
2075 n = gnutls_rsa_params_init(&rsa_params);
2077 if (n != GNUTLS_E_SUCCESS) {
2078 log_write("%s", gnutls_strerror(n));
2079 goto fail;
2082 n = gnutls_rsa_params_generate2(rsa_params, 512);
2084 if (n != GNUTLS_E_SUCCESS) {
2085 log_write("%s", gnutls_strerror(n));
2086 goto fail;
2089 gnutls_certificate_set_rsa_export_params(x509_cred, rsa_params);
2090 gnutls_certificate_set_params_function(x509_cred, tls_get_params);
2091 return TRUE;
2093 fail:
2094 return FALSE;
2097 static void deinitTlsParams()
2099 if (dh_params) {
2100 gnutls_dh_params_deinit(dh_params);
2101 dh_params = NULL;
2104 if (rsa_params) {
2105 gnutls_rsa_params_deinit(rsa_params);
2106 rsa_params = NULL;
2109 if (x509_cred) {
2110 gnutls_certificate_free_credentials(x509_cred);
2111 x509_cred = NULL;
2115 static gboolean startStopTcp(gboolean term)
2117 struct addrinfo hints, *servinfo, *p;
2118 gint port = get_key_file_integer("global", "tcp_port");
2119 char buf[7];
2120 int n;
2121 pthread_attr_t attr;
2123 if (term || get_key_file_boolean("global", "enable_tcp") == FALSE) {
2124 if (tcpSockFd != -1) {
2125 pthread_cancel(tcpAcceptTid);
2126 pthread_join(tcpAcceptTid, NULL);
2127 close(tcpSockFd);
2128 tcpSockFd = -1;
2130 /* A client may still be connected. */
2131 if (!quit)
2132 deinitTlsParams();
2135 return TRUE;
2138 if (tcpSockFd != -1)
2139 return TRUE;
2141 memset(&hints, 0, sizeof(hints));
2142 hints.ai_family = AF_UNSPEC;
2143 hints.ai_socktype = SOCK_STREAM;
2144 hints.ai_flags = AI_PASSIVE;
2146 if ((n = getaddrinfo(NULL, print_fmt(buf, sizeof(buf), "%i", port),
2147 &hints, &servinfo)) == -1) {
2148 log_write("getaddrinfo(): %s", gai_strerror(n));
2149 return FALSE;
2152 for(p = servinfo; p != NULL; p = p->ai_next) {
2153 if ((tcpSockFd = socket(p->ai_family, p->ai_socktype,
2154 p->ai_protocol)) == -1) {
2155 log_write("socket(): %s", strerror(errno));
2156 continue;
2159 n = 1;
2161 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_REUSEADDR, &n,
2162 sizeof(int)) == -1) {
2163 log_write("setsockopt(): %s", strerror(errno));
2164 freeaddrinfo(servinfo);
2165 goto fail;
2168 if (bind(tcpSockFd, p->ai_addr, p->ai_addrlen) == -1) {
2169 close(tcpSockFd);
2170 log_write("bind(): %s", strerror(errno));
2171 continue;
2174 n++;
2175 break;
2178 freeaddrinfo(servinfo);
2180 if (!p) {
2181 log_write("%s", N_("could not bind"));
2182 goto fail;
2185 if (g_key_file_has_key(keyfileh, "global", "tcp_interface", NULL)) {
2186 gchar *tmp = get_key_file_string("global", "tcp_interface");
2188 if (setsockopt(tcpSockFd, SOL_SOCKET, SO_BINDTODEVICE, tmp, 1)
2189 == -1) {
2190 log_write("setsockopt(): %s", strerror(errno));
2191 g_free(tmp);
2192 goto fail;
2195 g_free(tmp);
2198 if (!initTlsParams())
2199 goto fail;
2201 if (listen(tcpSockFd, 0) == -1) {
2202 log_write("listen(): %s", strerror(errno));
2203 goto fail;
2206 pthread_attr_init(&attr);
2207 pthread_create(&tcpAcceptTid, &attr, tcp_accept_thread, (void *)tcpSockFd);
2208 pthread_attr_destroy(&attr);
2209 return TRUE;
2211 fail:
2212 deinitTlsParams();
2214 if (tcpSockFd != -1)
2215 close(tcpSockFd);
2217 tcpSockFd = -1;
2218 return FALSE;
2220 #endif
2222 int main(int argc, char *argv[])
2224 gint opt;
2225 struct sockaddr_un addr;
2226 struct passwd *pw = getpwuid(getuid());
2227 gchar buf[PATH_MAX];
2228 gchar *socketpath = NULL, *socketdir, *socketname = NULL;
2229 gchar *socketarg = NULL;
2230 gchar *datadir = NULL;
2231 gboolean n;
2232 gchar *p;
2233 gchar **cache_push = NULL;
2234 gint iter = 0;
2235 gchar *import = NULL, *keyfile = NULL;
2236 gulong cmd_iterations = -1;
2237 gint default_timeout;
2238 gboolean rcfile_spec = FALSE;
2239 gint estatus = EXIT_FAILURE;
2240 gint sockfd;
2241 gchar *outfile = NULL;
2242 GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL };
2243 gint do_unlink = 1;
2244 gboolean secure = FALSE;
2245 guint ptotal = 0;
2246 gint background = 1;
2247 gchar *convert = NULL;
2248 pthread_mutexattr_t mattr;
2249 #ifdef WITH_PINENTRY
2250 gboolean disable_pinentry = FALSE;
2251 #endif
2252 #ifdef WITH_GNUTLS
2253 struct assuan_io_hooks io_hooks = {read_hook, write_hook};
2254 #endif
2255 #if 0
2256 #ifndef DEBUG
2257 #ifdef HAVE_SETRLIMIT
2258 struct rlimit rl;
2260 rl.rlim_cur = rl.rlim_max = 0;
2262 if (setrlimit(RLIMIT_CORE, &rl) != 0)
2263 err(EXIT_FAILURE, "setrlimit()");
2264 #endif
2265 #endif
2266 #endif
2268 #ifdef ENABLE_NLS
2269 setlocale(LC_ALL, "");
2270 bindtextdomain("pwmd", LOCALEDIR);
2271 textdomain("pwmd");
2272 #endif
2274 gpg_err_init();
2275 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT);
2276 g_mem_set_vtable(&mtable);
2277 assuan_set_malloc_hooks(xmalloc, xrealloc, xfree);
2278 xmlMemSetup(xfree, xmalloc, xrealloc, xstrdup);
2279 xmlInitMemory();
2280 #ifdef WITH_GNUTLS
2281 gnutls_global_set_mem_functions(xmalloc, xmalloc, gcry_SecureCheck,
2282 xrealloc, xfree);
2283 #endif
2284 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
2285 #ifdef WITH_GNUTLS
2286 gnutls_global_init();
2287 gnutls_global_set_log_function(tls_log);
2288 gnutls_global_set_log_level(1);
2289 assuan_set_io_hooks(&io_hooks);
2290 #endif
2291 xmlInitGlobals();
2292 xmlInitParser();
2293 xmlXPathInit();
2294 g_snprintf(buf, sizeof(buf), "%s/.pwmd", pw->pw_dir);
2296 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2297 err(EXIT_FAILURE, "%s", buf);
2299 g_snprintf(buf, sizeof(buf), "%s/.pwmd/data", pw->pw_dir);
2301 if (mkdir(buf, 0700) == -1 && errno != EEXIST)
2302 err(EXIT_FAILURE, "%s", buf);
2304 rcfile = g_strdup_printf("%s/.pwmd/config", pw->pw_dir);
2305 cmdline = TRUE;
2306 #ifdef WITH_GNUTLS
2307 tcpSockFd = -1;
2308 #endif
2310 while ((opt = getopt(argc, argv, "Po:C:bnI:i:k:hvf:D")) != EOF) {
2311 switch (opt) {
2312 #ifdef WITH_PINENTRY
2313 case 'P':
2314 disable_pinentry = TRUE;
2315 break;
2316 #endif
2317 case 'o':
2318 outfile = optarg;
2319 break;
2320 case 'C':
2321 convert = optarg;
2322 break;
2323 case 'b':
2324 /* Compatibility for version < 1.11 */
2325 break;
2326 case 'n':
2327 background = 0;
2328 break;
2329 case 'D':
2330 secure = TRUE;
2331 break;
2332 case 'I':
2333 import = optarg;
2334 break;
2335 case 'i':
2336 cmd_iterations = strtol(optarg, NULL, 10);
2337 break;
2338 case 'k':
2339 keyfile = optarg;
2340 break;
2341 case 'f':
2342 g_free(rcfile);
2343 rcfile = g_strdup(optarg);
2344 rcfile_spec = TRUE;
2345 break;
2346 case 'v':
2347 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,
2348 PACKAGE_BUGREPORT,
2349 #ifdef WITH_PINENTRY
2350 "+WITH_PINENTRY\n"
2351 #else
2352 "-WITH_PINENTRY\n"
2353 #endif
2354 #ifdef WITH_QUALITY
2355 "+WITH_QUALITY\n"
2356 #else
2357 "-WITH_QUALITY\n"
2358 #endif
2359 #ifdef WITH_GNUTLS
2360 "+WITH_GNUTLS\n"
2361 #else
2362 "-WITH_GNUTLS\n"
2363 #endif
2364 #ifdef DEBUG
2365 "+DEBUG\n"
2366 #else
2367 "-DEBUG\n"
2368 #endif
2369 #ifdef MEM_DEBUG
2370 "+MEM_DEBUG\n"
2371 #else
2372 "-MEM_DEBUG\n"
2373 #endif
2375 exit(EXIT_SUCCESS);
2376 case 'h':
2377 default:
2378 usage(argv[0]);
2382 if ((keyfileh = parse_rcfile(rcfile_spec)) == NULL)
2383 exit(EXIT_FAILURE);
2385 #ifdef WITH_PINENTRY
2386 if (disable_pinentry == TRUE)
2387 g_key_file_set_boolean(keyfileh, "global", "enable_pinentry", FALSE);
2388 #endif
2390 if (g_key_file_has_key(keyfileh, "global", "syslog", NULL) == TRUE)
2391 log_syslog = g_key_file_get_boolean(keyfileh, "global", "syslog", NULL);
2393 if (log_syslog == TRUE)
2394 openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
2396 if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) {
2397 iter = g_key_file_get_integer(keyfileh, "global", "priority", NULL);
2398 errno = 0;
2400 if (setpriority(PRIO_PROCESS, 0, iter) == -1) {
2401 log_write("setpriority(): %s", strerror(errno));
2402 goto do_exit;
2406 #ifdef HAVE_MLOCKALL
2407 if (disable_mlock == FALSE && mlockall(MCL_FUTURE) == -1) {
2408 log_write("mlockall(): %s", strerror(errno));
2409 goto do_exit;
2411 #endif
2413 setup_gcrypt();
2415 if (convert) {
2416 if (!outfile)
2417 usage(argv[0]);
2419 opt = convert_file(convert, keyfile, outfile);
2420 g_key_file_free(keyfileh);
2421 g_free(rcfile);
2422 exit(opt ? EXIT_FAILURE : EXIT_SUCCESS);
2425 if (import) {
2426 if (!outfile)
2427 usage(argv[0]);
2429 if (cmd_iterations == -1)
2430 cmd_iterations = get_key_file_integer("global", "iterations");
2432 opt = xml_import(import, outfile, keyfile, cmd_iterations);
2433 g_key_file_free(keyfileh);
2434 g_free(rcfile);
2435 exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS);
2438 g_key_file_set_list_separator(keyfileh, ',');
2440 if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL)
2441 errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile);
2443 if (*p == '~') {
2444 p++;
2445 g_snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--);
2446 g_free(p);
2447 socketarg = g_strdup(buf);
2449 else
2450 socketarg = p;
2452 if ((p = g_key_file_get_string(keyfileh, "global", "data_directory", NULL)) == NULL)
2453 errx(EXIT_FAILURE, N_("%s: data_directory not defined"), rcfile);
2455 datadir = expand_homedir(p);
2456 g_free(p);
2458 if (secure == FALSE && g_key_file_has_key(keyfileh, "global", "disable_list_and_dump", NULL) == TRUE) {
2459 n = g_key_file_get_boolean(keyfileh, "global", "disable_list_and_dump", NULL);
2460 disable_list_and_dump = n;
2462 else
2463 disable_list_and_dump = secure;
2465 if (g_key_file_has_key(keyfileh, "global", "cache_timeout", NULL) == TRUE)
2466 default_timeout = g_key_file_get_integer(keyfileh, "global", "cache_timeout", NULL);
2467 else
2468 default_timeout = -1;
2470 setup_logging(keyfileh);
2472 if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE)
2473 cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL);
2475 if (argc != optind) {
2476 if (cache_push)
2477 ptotal = g_strv_length(cache_push);
2479 for (; optind < argc; optind++) {
2480 if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE)
2481 errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
2485 if (strchr(socketarg, '/') == NULL) {
2486 socketdir = g_get_current_dir();
2487 socketname = g_strdup(socketarg);
2488 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2490 else {
2491 socketname = g_strdup(strrchr(socketarg, '/'));
2492 socketname++;
2493 socketarg[strlen(socketarg) - strlen(socketname) -1] = 0;
2494 socketdir = g_strdup(socketarg);
2495 socketpath = g_strdup_printf("%s/%s", socketdir, socketname);
2498 if (chdir(datadir)) {
2499 log_write("%s: %s", datadir, strerror(errno));
2500 unlink(socketpath);
2501 goto do_exit;
2504 if (parse_rcfile_keys() == FALSE)
2505 goto do_exit;
2507 clear_rcfile_keys();
2510 * Set the cache entry for a file. Prompts for the password.
2512 if (cache_push) {
2513 for (opt = 0; cache_push[opt]; opt++)
2514 do_cache_push(cache_push[opt], NULL);
2516 g_strfreev(cache_push);
2517 log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2521 * bind() doesn't like the full pathname of the socket or any non alphanum
2522 * characters so change to the directory where the socket is wanted then
2523 * create it then change to datadir.
2525 if (chdir(socketdir)) {
2526 log_write("%s: %s", socketdir, strerror(errno));
2527 goto do_exit;
2530 g_free(socketdir);
2532 if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
2533 log_write("socket(): %s", strerror(errno));
2534 goto do_exit;
2537 addr.sun_family = AF_UNIX;
2538 g_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketname);
2540 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
2541 log_write("bind(): %s", strerror(errno));
2543 if (errno == EADDRINUSE)
2544 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2545 "stale socket. Please remove it manually."), socketpath);
2547 do_unlink = 0;
2548 goto do_exit;
2551 if (g_key_file_has_key(keyfileh, "global", "socket_perms", NULL) == TRUE) {
2552 gchar *t = g_key_file_get_string(keyfileh, "global", "socket_perms", NULL);
2553 mode_t mode = strtol(t, NULL, 8);
2554 mode_t mask = umask(0);
2556 g_free(t);
2558 if (chmod(socketname, mode) == -1) {
2559 log_write("%s: %s", socketname, strerror(errno));
2560 close(sockfd);
2561 unlink(socketpath);
2562 umask(mask);
2563 goto do_exit;
2566 umask(mask);
2569 g_free(--socketname);
2571 if (chdir(datadir)) {
2572 log_write("%s: %s", datadir, strerror(errno));
2573 close(sockfd);
2574 unlink(socketpath);
2575 goto do_exit;
2578 g_free(datadir);
2579 pthread_mutexattr_init(&mattr);
2580 pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE_NP);
2581 pthread_mutex_init(&cache_mutex, &mattr);
2582 pthread_mutexattr_destroy(&mattr);
2583 pthread_mutex_init(&keepalive_cond_mutex, NULL);
2584 pthread_cond_init(&keepalive_cond, NULL);
2585 #ifdef WITH_PINENTRY
2586 pthread_mutex_init(&pin_mutex, NULL);
2587 #endif
2589 if (listen(sockfd, 0) == -1) {
2590 log_write("listen(): %s", strerror(errno));
2591 goto do_exit;
2594 cmdline = FALSE;
2596 #ifdef WITH_GNUTLS
2597 if (startStopTcp(FALSE) == FALSE)
2598 goto do_exit;
2599 #endif
2601 if (background) {
2602 switch (fork()) {
2603 case -1:
2604 log_write("fork(): %s", strerror(errno));
2605 goto do_exit;
2606 case 0:
2607 close(0);
2608 close(1);
2609 close(2);
2610 setsid();
2611 break;
2612 default:
2613 exit(EXIT_SUCCESS);
2617 server_loop(sockfd, &socketpath);
2618 estatus = EXIT_SUCCESS;
2620 do_exit:
2621 if (socketpath && do_unlink) {
2622 unlink(socketpath);
2623 g_free(socketpath);
2626 #ifdef WITH_GNUTLS
2627 startStopTcp(TRUE);
2628 gnutls_global_deinit();
2629 #endif
2631 g_key_file_free(keyfileh);
2632 g_free(rcfile);
2633 xmlCleanupParser();
2634 xmlCleanupGlobals();
2636 if (estatus == EXIT_SUCCESS)
2637 log_write(N_("pwmd exiting normally"));
2639 #if defined(DEBUG) && !defined(MEM_DEBUG)
2640 xdump();
2641 #endif
2642 exit(estatus);