Fix some warnings found by Valgrind (helgrind tool).
[pwmd.git] / src / pwmd.c
blobc9b4eeed5f72014dabc3dece87613afe5e9eb2d5
1 /*
2 Copyright (C) 2006-2021 Ben Kibbey <bjk@luxsci.net>
4 This file is part of pwmd.
6 Pwmd is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 Pwmd 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 Pwmd. If not, see <http://www.gnu.org/licenses/>.
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
22 #include <stdio.h>
23 #include <stdlib.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #include <err.h>
28 #include <ctype.h>
29 #include <string.h>
30 #ifdef HAVE_SYS_SOCKET_H
31 #include <sys/socket.h>
32 #endif
33 #include <sys/un.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <sys/wait.h>
37 #ifdef HAVE_FCNTL_H
38 #include <fcntl.h>
39 #endif
40 #include <pwd.h>
41 #include <grp.h>
42 #include <pthread.h>
43 #include <sys/mman.h>
44 #ifdef HAVE_TERMIOS_H
45 #include <termios.h>
46 #endif
47 #include <assert.h>
48 #ifdef HAVE_SYSLOG_H
49 #include <syslog.h>
50 #endif
51 #ifdef HAVE_NETINET_IN_H
52 #include <netinet/in.h>
53 #endif
54 #ifdef HAVE_ARPA_INET_H
55 #include <arpa/inet.h>
56 #endif
57 #ifdef HAVE_NETDB_H
58 #include <netdb.h>
59 #endif
60 #ifdef HAVE_SYS_TIME_H
61 #include <sys/time.h>
62 #endif
63 #include <sys/resource.h>
64 #include <setjmp.h>
65 #include <errno.h>
66 #include <poll.h>
68 #ifdef TM_IN_SYS_TIME
69 #include <sys/time.h>
70 #else
71 #include <time.h>
72 #endif
74 #ifdef HAVE_LIMITS_H
75 #include <limits.h>
76 #endif
78 #ifdef HAVE_GETOPT_LONG
79 #ifdef HAVE_GETOPT_H
80 #include <getopt.h>
81 #endif
82 #else
83 #include "getopt_long.h"
84 #endif
86 #ifdef HAVE_PR_SET_NAME
87 #include <sys/prctl.h>
88 #endif
90 #include "pwmd-error.h"
91 #include <gcrypt.h>
93 #include "util-misc.h"
94 #include "mem.h"
95 #include "xml.h"
96 #include "common.h"
97 #include "commands.h"
98 #include "cache.h"
99 #include "util-string.h"
100 #include "mutex.h"
101 #include "rcfile.h"
102 #include "crypto.h"
103 #include "acl.h"
104 #include "version.h"
106 static int quit;
107 static int cmdline;
108 static jmp_buf jmp;
109 static int nofork;
110 static int log_fd;
111 static unsigned assuan_level;
112 pthread_key_t thread_name_key;
113 pthread_mutex_t cn_mutex;
114 struct slist_s *cn_thread_list;
116 #ifndef HAVE_PTHREAD_CANCEL
117 pthread_key_t signal_thread_key;
119 #define INIT_SIGNAL(s, cb) do { \
120 int *n = xmalloc (sizeof (int)); \
121 *n = 0; \
122 pthread_setspecific (signal_thread_key, n); \
123 struct sigaction act; \
124 sigset_t sigset; \
125 sigemptyset (&sigset); \
126 sigaddset (&sigset, s); \
127 pthread_sigmask (SIG_UNBLOCK, &sigset, NULL); \
128 memset (&act, 0, sizeof(act)); \
129 act.sa_flags = SA_SIGINFO; \
130 act.sa_mask = sigset; \
131 act.sa_sigaction = cb; \
132 sigaction (s, &act, NULL); \
133 } while (0)
135 static void
136 catch_thread_signal (int sig, siginfo_t *info, void *ctx)
138 int *n = (int *) pthread_getspecific (signal_thread_key);
140 *n = 1;
142 #endif
144 static void
145 setup_logging ()
147 int n = config_get_boolean ("global", "enable_logging");
149 if (n)
151 char *p = config_get_string ("global", "log_path");
153 if (!p || (logfile && p && log_fd != -1 && strcmp(p, logfile)))
155 if (log_fd != -1)
156 close (log_fd);
158 log_fd = -1;
161 xfree (logfile);
162 logfile = NULL;
163 if (p)
164 logfile = expand_homedir (p);
165 xfree (p);
167 else
169 xfree (logfile);
170 logfile = NULL;
171 if (log_fd != -1)
172 close(log_fd);
174 log_fd = -1;
175 closelog ();
178 log_syslog = config_get_boolean ("global", "syslog");
179 if (log_syslog == 1)
180 openlog ("pwmd", LOG_NDELAY | LOG_PID, LOG_DAEMON);
183 static void *
184 reload_rcfile_thread (void *arg)
186 #ifndef HAVE_PTHREAD_CANCEL
187 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
188 #endif
190 #ifdef HAVE_PR_SET_NAME
191 prctl (PR_SET_NAME, "reload rcfile");
192 #endif
193 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
194 MUTEX_LOCK (&rcfile_mutex);
196 (void)arg;
198 for (;;)
200 struct slist_s *keep = NULL;
201 struct slist_s *config;
202 int b = disable_list_and_dump;
203 #ifdef WITH_GNUTLS
204 char *prio;
205 char *prio2 = NULL;
206 #endif
208 pthread_cond_wait (&rcfile_cond, &rcfile_mutex);
209 pthread_cleanup_push (release_mutex_cb, &rcfile_mutex);
210 TEST_CANCEL ();
211 keep = config_keep_save ();
212 log_write (_("reloading configuration file '%s'"), rcfile);
214 #ifdef WITH_GNUTLS
215 prio = config_get_string ("global", "tls_cipher_suite");
216 #endif
217 config = config_parse (rcfile, 1);
218 if (config)
220 config_free (global_config);
221 global_config = config;
222 setup_logging ();
225 config_keep_restore (keep);
226 disable_list_and_dump = !disable_list_and_dump ? b : 1;
228 #ifdef WITH_GNUTLS
229 /* Restart listening sockets since they may have changed. */
230 tls_start_stop (1);
231 tls_start_stop (0);
233 prio2 = config_get_string ("global", "tls_cipher_suite");
234 if ((prio2 && (!prio || strcmp (prio, prio2))) || (prio && !prio2))
235 tls_rehandshake ();
237 xfree (prio2);
238 xfree (prio);
239 #endif
240 crypto_set_keepalive ();
241 pthread_cleanup_pop (0);
244 MUTEX_UNLOCK (&rcfile_mutex);
245 return NULL;
248 #define PROCESS_DONE(client,rc) (client && client->bulk_p) ? rc : \
249 assuan_process_done (client ? client->ctx : NULL, rc)
250 gpg_error_t
251 send_error (assuan_context_t ctx, gpg_error_t e)
253 struct client_s *client = assuan_get_pointer (ctx);
255 if (gpg_err_source (e) == GPG_ERR_SOURCE_UNKNOWN)
256 e = gpg_error (e);
258 if (client)
259 client->last_rc = e;
261 if (!e)
262 return PROCESS_DONE (client, 0);
264 if (!ctx)
266 log_write ("ERR %i: %s", e, pwmd_strerror (e));
267 return e;
270 if (client && client->xml_error)
272 log_write ("%s", client->xml_error->message);
273 xfree (client->last_error);
274 client->last_error = NULL;
275 if (client->xml_error->message)
276 client->last_error = str_dup (client->xml_error->message);
278 e = PROCESS_DONE (client, assuan_set_error (ctx, e,
279 client->xml_error->message
280 ? client->xml_error->message
281 : NULL));
282 xmlResetLastError ();
283 xmlResetError (client->xml_error);
284 xfree (client->xml_error);
285 client->xml_error = NULL;
286 return e;
289 return PROCESS_DONE (client, assuan_set_error (ctx, e, pwmd_strerror (e)));
292 void
293 log_write (const char *fmt, ...)
295 char *args;
296 va_list ap;
297 time_t now;
298 char buf[255];
299 pthread_t tid = pthread_self ();
300 static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
302 if ((!logfile && !nofork && !log_syslog && !cmdline) || !fmt)
303 return;
305 MUTEX_LOCK (&m);
306 pthread_cleanup_push (release_mutex_cb, &m);
308 if (!cmdline && logfile && log_fd == -1)
310 log_fd = open (logfile, O_WRONLY | O_CREAT | O_APPEND, 0600);
311 if (log_fd == -1)
312 warn ("%s", logfile);
315 va_start (ap, fmt);
317 if (str_vasprintf (&args, fmt, ap) != -1)
319 pthread_cleanup_push (xfree, args);
320 if (cmdline)
322 fprintf (stderr, "pwmd: %s\n", args);
323 fflush (stderr);
325 else
327 char *name = pthread_getspecific (thread_name_key);
328 char *line;
330 if (name)
332 if (*name == '!')
333 snprintf (buf, sizeof (buf), "%s: ", name+1);
334 else
335 snprintf (buf, sizeof (buf), "%s(%p): ", name,
336 (pthread_t *)tid);
338 else
339 snprintf (buf, sizeof (buf), "%p: ", (pthread_t *)tid);
341 name = buf;
342 if (!cmdline && log_syslog && !nofork)
343 syslog (LOG_INFO, "%s%s", name, args);
345 time (&now);
346 struct tm *tm = localtime (&now);
347 char tbuf[21];
348 strftime (tbuf, sizeof (tbuf), "%b %d %Y %H:%M:%S ", tm);
349 tbuf[sizeof (tbuf) - 1] = 0;
351 if (args[strlen (args) - 1] == '\n')
352 args[strlen (args) - 1] = 0;
354 line = str_asprintf ("%s %i %s%s\n", tbuf, getpid (), name, args);
355 if (line)
357 pthread_cleanup_push (xfree, line);
358 if (logfile && log_fd != -1)
360 ssize_t ret = write (log_fd, line, strlen (line));
361 (void)ret;
362 fsync (log_fd);
365 if (nofork)
367 fprintf (stdout, "%s", line);
368 fflush (stdout);
371 pthread_cleanup_pop (1);
374 pthread_cleanup_pop (1);
377 va_end (ap);
379 if (log_fd != -1 && log_keepopen <= 0)
381 close(log_fd);
382 log_fd = -1;
385 pthread_cleanup_pop (1);
388 static gpg_error_t
389 setup_crypto ()
391 gpg_error_t rc;
393 if (!gpgrt_check_version (REQUIRE_LIBGPGERROR_VERSION))
395 fprintf (stderr, _("gpgrt_check_version(): Incompatible libgpg-error. "
396 "Wanted %s, got %s.\n"), REQUIRE_LIBGPGERROR_VERSION,
397 gpgrt_check_version (NULL));
398 return GPG_ERR_UNKNOWN_VERSION;
401 gpgrt_init ();
402 gpgrt_set_alloc_func (xrealloc_gpgrt);
404 if (!assuan_check_version (REQUIRE_LIBASSUAN_VERSION))
406 fprintf (stderr, _("assuan_check_version(): Incompatible libassuan. "
407 "Wanted %s, got %s.\n"), REQUIRE_LIBASSUAN_VERSION,
408 assuan_check_version (NULL));
409 return GPG_ERR_UNKNOWN_VERSION;
412 if (!gcry_check_version (REQUIRE_LIBGCRYPT_VERSION))
414 fprintf (stderr, _("gcry_check_version(): Incompatible libgcrypt. "
415 "Wanted %s, got %s.\n"), REQUIRE_LIBGCRYPT_VERSION,
416 gcry_check_version (NULL));
417 return GPG_ERR_UNKNOWN_VERSION;
420 gcry_set_allocation_handler (xmalloc, xmalloc, NULL, xrealloc, xfree);
422 if (!gpgme_check_version (REQUIRE_LIBGPGME_VERSION))
424 fprintf (stderr, _("gpgme_check_version(): Incompatible libgpgme. "
425 "Wanted %s, got %s.\n"), REQUIRE_LIBGPGME_VERSION,
426 gpgme_check_version (NULL));
427 return GPG_ERR_UNKNOWN_VERSION;
430 rc = gpgme_engine_check_version (GPGME_PROTOCOL_OPENPGP);
431 if (rc)
433 fprintf (stderr, _("gpgme_engine_check_version(GPGME_PROTOCOL_OPENPGP): %s"), gpgme_strerror (rc));
434 return GPG_ERR_UNKNOWN_VERSION;
437 //gpgme_set_global_flag ("require-gnupg", REQUIRE_GNUPG_VERSION);
438 #ifdef ENABLE_NLS
439 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
440 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
441 #endif
443 #ifdef WITH_GNUTLS
444 if (gnutls_global_init ())
446 fprintf(stderr, _("gnutls_global_init() failed.\n"));
447 return GPG_ERR_UNKNOWN_VERSION;
450 if (!gnutls_check_version (REQUIRE_LIBGNUTLS_VERSION))
452 fprintf (stderr, _("gnutls_check_version(): Incompatible libgnutls. "
453 "Wanted %s, got %s.\n"), REQUIRE_LIBGNUTLS_VERSION,
454 gnutls_check_version (NULL));
455 return GPG_ERR_UNKNOWN_VERSION;
458 gnutls_global_set_log_function (tls_log);
459 gnutls_global_set_audit_log_function (tls_audit_log);
460 #endif
461 return 0;
464 static void
465 xml_error_cb (void *data, xmlErrorPtr e)
467 struct client_s *client = data;
470 * Keep the first reported error as the one to show in the error
471 * description. Reset in send_error().
473 if (client->xml_error)
474 return;
476 client->xml_error = xcalloc (1, sizeof(xmlError));
477 xmlCopyError (e, client->xml_error);
480 static pid_t
481 hook_waitpid (assuan_context_t ctx, pid_t pid, int action,
482 int *status, int options)
484 (void)ctx;
485 (void)action;
486 return waitpid (pid, status, options);
489 static ssize_t
490 hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
492 TEST_CANCEL ();
493 #ifdef WITH_GNUTLS
494 struct client_s *client = assuan_get_pointer (ctx);
496 if (client->thd->remote)
497 return tls_read_hook (ctx, (int) fd, data, len);
498 #else
499 (void)ctx;
500 #endif
501 return read ((int) fd, data, len);
504 static ssize_t
505 hook_write (assuan_context_t ctx, assuan_fd_t fd,
506 const void *data, size_t len)
508 TEST_CANCEL ();
509 #ifdef WITH_GNUTLS
510 struct client_s *client = assuan_get_pointer (ctx);
512 if (client->thd->remote)
513 return tls_write_hook (ctx, (int) fd, data, len);
514 #else
515 (void)ctx;
516 #endif
517 return write ((int) fd, data, len);
521 assuan_log_cb (assuan_context_t ctx, void *data, unsigned cat,
522 const char *msg)
524 struct client_s *client = data;
525 const char *str = NULL;
527 (void)client;
528 (void)ctx;
530 if (!(assuan_level & cat))
531 return 0;
533 if (!msg)
534 return 1;
536 switch (cat)
538 case ASSUAN_LOG_INIT:
539 str = "ASSUAN[INIT]";
540 break;
541 case ASSUAN_LOG_CTX:
542 str = "ASSUAN[CTX]";
543 break;
544 case ASSUAN_LOG_ENGINE:
545 str = "ASSUAN[ENGINE]";
546 break;
547 case ASSUAN_LOG_DATA:
548 str = "ASSUAN[DATA]";
549 break;
550 case ASSUAN_LOG_SYSIO:
551 str = "ASSUAN[SYSIO]";
552 break;
553 case ASSUAN_LOG_CONTROL:
554 str = "ASSUAN[CONTROL]";
555 break;
556 default:
557 str = "ASSUAN[UNKNOWN]";
558 break;
561 log_write ("%s: %s", str, msg);
562 return 1;
565 static int
566 new_connection (struct client_s *cl)
568 gpg_error_t rc;
569 static struct assuan_malloc_hooks mhooks = { xmalloc, xrealloc, xfree };
570 static struct assuan_system_hooks shooks = {
571 ASSUAN_SYSTEM_HOOKS_VERSION,
572 __assuan_usleep,
573 __assuan_pipe,
574 __assuan_close,
575 hook_read,
576 hook_write,
577 //FIXME
578 NULL, //recvmsg
579 NULL, //sendmsg both are used for FD passing
580 __assuan_spawn,
581 hook_waitpid,
582 __assuan_socketpair,
583 __assuan_socket,
584 __assuan_connect
587 #ifdef WITH_GNUTLS
588 if (cl->thd->remote)
590 char *prio = config_get_string ("global", "tls_cipher_suite");
592 cl->thd->timeout = config_get_integer ("global", "tls_timeout");
593 if (fcntl (cl->thd->fd, F_SETFL, O_NONBLOCK) == -1)
594 return 0;
596 cl->thd->tls = tls_init_client (cl->thd->fd, cl->thd->timeout, prio);
597 xfree (prio);
598 if (!cl->thd->tls)
599 return 0;
601 #endif
603 rc = assuan_new_ext (&cl->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks,
604 assuan_log_cb, cl);
605 if (rc)
606 goto fail;
608 assuan_ctx_set_system_hooks (cl->ctx, &shooks);
609 rc = assuan_init_socket_server (cl->ctx, cl->thd->fd,
610 ASSUAN_SOCKET_SERVER_ACCEPTED);
611 if (rc)
612 goto fail;
614 assuan_set_pointer (cl->ctx, cl);
615 assuan_set_hello_line (cl->ctx, PACKAGE_STRING PWMD_GIT_HASH);
616 rc = register_commands (cl->ctx);
617 if (rc)
618 goto fail;
620 rc = assuan_accept (cl->ctx);
621 if (rc)
622 goto fail;
624 rc = validate_peer (cl);
625 /* May not be implemented on all platforms. */
626 if (rc && gpg_err_code (rc) != GPG_ERR_ASS_GENERAL)
627 goto fail;
629 MUTEX_LOCK (&cn_mutex);
630 cl->thd->state = CLIENT_STATE_INIT;
631 MUTEX_UNLOCK (&cn_mutex);
632 cl->lock_timeout = config_get_integer ("global", "lock_timeout");
633 xmlSetStructuredErrorFunc (cl, xml_error_cb);
634 return 1;
636 fail:
637 log_write ("%s", pwmd_strerror (rc));
638 return 0;
642 * This is called after a client is cancelled or disconnects. Set with
643 * pthread_cleanup_push().
645 static void
646 free_client_cb (void *arg)
648 struct client_thread_s *cn = arg;
649 struct client_s *cl = cn->cl;
650 char *tmp = NULL;
652 #ifndef HAVE_PTHREAD_CANCEL
653 tmp = pthread_getspecific (signal_thread_key);
654 xfree (tmp);
655 pthread_setspecific (signal_thread_key, NULL);
656 #endif
658 MUTEX_LOCK (&cn_mutex);
659 cn_thread_list = slist_remove (cn_thread_list, cn);
660 MUTEX_UNLOCK (&cn_mutex);
662 if (cl)
664 unlock_flock (&cl->flock_fd);
665 reset_client (cl);
666 if (cl->xml_error)
667 xmlResetError (cl->xml_error);
669 xfree (cl->xml_error);
671 #ifdef WITH_GNUTLS
672 if (cn->tls)
674 gnutls_deinit (cn->tls->ses);
675 xfree (cn->tls->fp);
676 xfree (cn->tls);
678 #endif
680 if (cl->ctx)
681 assuan_release (cl->ctx);
682 else if (cl->thd && cl->thd->fd != -1)
683 close (cl->thd->fd);
685 if (cl->crypto)
686 crypto_free (cl->crypto);
688 cl->crypto = NULL;
689 xfree (cl);
691 else
693 if (cn->fd != -1)
694 close (cn->fd);
697 while (cn->msg_queue)
699 struct status_msg_s *msg = cn->msg_queue;
701 cn->msg_queue = msg->next;
702 xfree (msg->line);
703 xfree (msg);
706 if (cn->status_msg_pipe[0] != -1)
707 close (cn->status_msg_pipe[0]);
709 if (cn->status_msg_pipe[1] != -1)
710 close (cn->status_msg_pipe[1]);
712 pthread_mutex_destroy (&cn->status_mutex);
713 log_write (_("exiting, fd=%i"), cn->fd);
714 send_status_all (STATUS_CLIENTS, NULL);
716 xfree (cn->name);
717 #ifdef WITH_GNUTLS
718 xfree (cn->peeraddr);
719 #endif
721 if (cn->eof) // Not pthread_exit() or pthread_cancel().
723 tmp = pthread_getspecific (thread_name_key);
724 xfree (tmp);
725 pthread_setspecific (thread_name_key, NULL);
728 (void)cache_kill_scd ();
729 xfree (cn);
732 static void
733 free_all_clients ()
735 MUTEX_LOCK (&cn_mutex);
736 pthread_cleanup_push (release_mutex_cb, &cn_mutex);
738 while (slist_length (cn_thread_list))
740 struct client_thread_s *thd = slist_nth_data (cn_thread_list, 0);
742 free_client_cb (thd);
743 thd->eof = 1;
746 pthread_cleanup_pop (1);
749 static gpg_error_t
750 send_msg_queue (struct client_thread_s *thd)
752 MUTEX_LOCK (&thd->status_mutex);
753 gpg_error_t rc = 0;
754 char c;
755 ssize_t ret;
757 ret = read (thd->status_msg_pipe[0], &c, 1);
758 rc = gpg_error_from_syserror ();
759 if (ret == -1 && gpg_err_code (rc) != GPG_ERR_EAGAIN)
760 log_write ("%s (%i): %s", __FUNCTION__, __LINE__, pwmd_strerror (rc));
761 else
762 rc = 0;
764 thd->wrote_status = 0;
766 while (thd->msg_queue)
768 struct status_msg_s *msg = thd->msg_queue;
770 thd->msg_queue = thd->msg_queue->next;
771 MUTEX_UNLOCK (&thd->status_mutex);
772 pthread_cleanup_push (xfree, msg);
773 pthread_cleanup_push (xfree, msg->line);
774 rc = send_status (thd->cl->ctx, msg->s, msg->line);
775 pthread_cleanup_pop (1);
776 pthread_cleanup_pop (1);
777 MUTEX_LOCK (&thd->status_mutex);
778 if (rc)
779 break;
782 MUTEX_UNLOCK (&thd->status_mutex);
783 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
784 log_write ("%s (%i): %s", __FUNCTION__, __LINE__, pwmd_strerror (rc));
786 return rc;
789 static void *
790 client_thread (void *data)
792 struct client_thread_s *thd = data;
793 struct client_s *cl = xcalloc (1, sizeof (struct client_s));
794 struct slist_s *list;
795 gpg_error_t rc = 0;
796 #ifndef HAVE_PTHREAD_CANCEL
797 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
798 #endif
800 #ifdef HAVE_PR_SET_NAME
801 prctl (PR_SET_NAME, "client");
802 #endif
803 pthread_setspecific (thread_name_key, str_dup (__FUNCTION__));
805 if (!cl)
807 log_write ("%s(%i): %s", __FILE__, __LINE__,
808 pwmd_strerror (GPG_ERR_ENOMEM));
809 return NULL;
812 MUTEX_LOCK (&cn_mutex);
813 pthread_cleanup_push (free_client_cb, thd);
814 thd->cl = cl;
815 cl->thd = thd;
816 cl->flock_fd = -1;
818 list = slist_append (cn_thread_list, thd);
819 if (list)
820 cn_thread_list = list;
821 else
823 log_write ("%s(%i): %s", __FILE__, __LINE__,
824 pwmd_strerror (GPG_ERR_ENOMEM));
825 MUTEX_UNLOCK (&cn_mutex);
826 return NULL;
829 if (fcntl (thd->status_msg_pipe[0], F_SETFL, O_NONBLOCK) == -1)
830 rc = gpg_error_from_errno (errno);
832 if (!rc)
833 if (fcntl (thd->status_msg_pipe[1], F_SETFL, O_NONBLOCK) == -1)
834 rc = gpg_error_from_errno (errno);
836 MUTEX_UNLOCK (&cn_mutex);
838 if (rc)
840 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
841 goto done;
844 if (new_connection (cl))
846 struct pollfd fds[2];
848 fds[0].fd = thd->fd;
849 fds[0].events = POLLIN;
850 fds[1].fd = thd->status_msg_pipe[0];
851 fds[1].events = POLLIN;
853 send_status_all (STATUS_CLIENTS, NULL);
854 rc = send_status (cl->ctx, STATUS_CACHE, NULL);
855 if (rc)
857 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
858 goto done;
861 for (;;)
863 int n;
864 int eof;
866 n = poll (fds, sizeof(fds)/sizeof(fds[0]), 100);
867 if (n == -1)
869 log_write ("%s", strerror (errno));
870 break;
873 #ifdef WITH_GNUTLS
874 if (thd->remote && thd->tls && thd->tls->rehandshake)
876 char *prio;
877 int ret;
878 const char *e;
880 if (thd->tls->rehandshake == 1)
882 prio = config_get_string ("global", "tls_cipher_suite");
883 if (!prio)
885 thd->tls->rehandshake = 0;
886 continue;
889 ret = gnutls_priority_set_direct (thd->tls->ses, prio, &e);
890 if (ret == GNUTLS_E_SUCCESS)
892 rc = send_status (cl->ctx, STATUS_REHANDSHAKE, NULL);
893 if (!rc)
895 rc = assuan_send_data (cl->ctx, NULL, 0);
896 if (!rc)
898 ret = gnutls_rehandshake (thd->tls->ses);
899 if (ret)
901 log_write ("%s", gnutls_strerror (ret));
902 thd->tls->rehandshake = 0;
904 else
905 thd->tls->rehandshake = 2;
909 if (rc)
910 log_write ("%s", pwmd_strerror (rc));
912 else
913 log_write ("%s: %s", gnutls_strerror (ret), e);
915 xfree (prio);
916 continue;
919 #endif
921 if (!n)
922 continue;
924 if (fds[1].revents & POLLIN)
926 #ifdef WITH_GNUTLS
927 if (!thd->remote || (thd->tls && !thd->tls->rehandshake))
928 #endif
930 rc = send_msg_queue (thd);
931 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
932 break;
936 #ifdef HAVE_PTHREAD_CANCEL
937 if (!(fds[0].revents & POLLIN))
938 #else
939 if (thd->fd != -1 && !(fds[0].revents & POLLIN))
940 #endif
941 continue;
943 rc = assuan_process_next (cl->ctx, &eof);
944 if (rc || eof)
946 if (gpg_err_code (rc) == GPG_ERR_EOF || eof)
947 break;
949 log_write ("assuan_process_next(): rc=%u %s", rc,
950 pwmd_strerror (rc));
951 if (rc == gpg_error (GPG_ERR_ETIMEDOUT))
952 break;
954 rc = send_error (cl->ctx, rc);
955 if (rc)
957 log_write ("assuan_process_done(): rc=%u %s", rc,
958 pwmd_strerror (rc));
959 break;
963 /* Since the msg queue pipe fd's are non-blocking, check for
964 * pending status msgs here. GPG_ERR_EPIPE can be seen when the
965 * client has already disconnected and will be converted to
966 * GPG_ERR_EOF during assuan_process_next().
968 #ifdef WITH_GNUTLS
969 if (!thd->remote || (thd->tls && !thd->tls->rehandshake))
970 #endif
972 rc = send_msg_queue (thd);
973 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
974 break;
979 done:
980 /* Don't do pthread_exit() here because any set pthread_cleanup_push
981 * functions would be called after a command failed but then the client
982 * exited normally which may lead to a double free. */
983 thd->eof = 1;
984 pthread_cleanup_pop (1);
985 return NULL;
988 static gpg_error_t
989 xml_import (const char *filename, const char *outfile, char **keyid,
990 char *sign_keyid, char *keyfile, const char *userid,
991 const char *algo, long expire, int no_passphrase, int symmetric)
993 xmlDocPtr doc;
994 int fd;
995 struct stat st;
996 int len;
997 xmlChar *xmlbuf = NULL;
998 gpg_error_t rc = 0;
999 struct crypto_s *crypto = NULL;
1001 if (strcmp (filename, "-"))
1003 rc = open_check_file (filename, &fd, &st, 0);
1004 if (rc)
1005 return rc;
1007 xmlbuf = xmalloc (st.st_size + 1);
1008 if (!xmlbuf)
1010 close (fd);
1011 return GPG_ERR_ENOMEM;
1014 if (read (fd, xmlbuf, st.st_size) == -1)
1016 rc = gpg_error_from_errno (errno);
1017 close (fd);
1018 xfree (xmlbuf);
1019 return rc;
1022 xmlbuf[st.st_size] = 0;
1023 close (fd);
1025 else
1027 #define BUFSIZE 8196
1028 size_t size = 0, xlen = 0;
1030 for (;;)
1032 size_t ret;
1033 xmlChar *tmp;
1035 tmp = xrealloc (xmlbuf, size+BUFSIZE+1);
1036 if (!tmp)
1038 xfree (xmlbuf);
1039 return GPG_ERR_ENOMEM;
1042 xmlbuf = tmp;
1043 size += BUFSIZE;
1044 ret = read (STDIN_FILENO, &xmlbuf[xlen], BUFSIZE);
1045 if (ret == -1)
1047 rc = gpg_error_from_syserror ();
1048 xfree (xmlbuf);
1049 return rc;
1052 xlen += ret;
1053 if (!ret || ret < BUFSIZE)
1054 break;
1057 xmlbuf[xlen] = 0;
1060 doc = xmlReadDoc (xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS);
1061 xfree (xmlbuf);
1062 if (!doc)
1063 return GPG_ERR_BAD_DATA;
1065 xmlNodePtr n = xmlDocGetRootElement (doc);
1066 if (n && !xmlStrEqual (n->name, (xmlChar *) "pwmd"))
1067 rc = GPG_ERR_BAD_DATA;
1069 if (!rc)
1071 rc = xml_validate_import (NULL, n ? n->children : n);
1072 if (!rc)
1074 rc = crypto_init (&crypto, NULL, filename, keyfile != NULL, keyfile);
1075 if (!rc)
1077 if (keyfile)
1079 crypto->flags |= CRYPTO_FLAG_KEYFILE;
1080 crypto->keyfile = str_dup (keyfile);
1083 xmlDocDumpMemory (doc, &crypto->plaintext, &len);
1084 if (len > 0)
1085 crypto->plaintext_size = len;
1086 else
1087 rc = GPG_ERR_ENOMEM;
1092 if (!rc)
1094 if (!symmetric && !keyid)
1096 crypto->save.userid = str_dup (userid);
1097 crypto->save.algo = algo ? str_dup (algo) : NULL;
1098 crypto->save.expire = expire;
1099 if (no_passphrase)
1100 crypto->save.flags |= GPGME_CREATE_NOPASSWD;
1102 rc = crypto_genkey (NULL, crypto);
1104 else
1106 if (keyid)
1107 crypto->save.pubkey = strv_dup (keyid);
1109 if (sign_keyid)
1110 crypto->save.sigkey = str_dup (sign_keyid);
1113 if (!rc)
1115 crypto->flags |= symmetric ? CRYPTO_FLAG_SYMMETRIC : 0;
1116 rc = crypto_encrypt (NULL, crypto);
1120 if (!rc)
1122 if (!strcmp (outfile, "-"))
1123 outfile = NULL;
1125 xfree (crypto->plaintext);
1126 crypto->plaintext = NULL;
1127 xfree (crypto->filename);
1128 crypto->filename = outfile ? str_dup (outfile) : NULL;
1129 rc = crypto_write_file (crypto, NULL, NULL);
1132 xmlFreeDoc (doc);
1133 crypto_free (crypto);
1134 return rc;
1137 static gpg_error_t
1138 do_cache_push (struct crypto_s *crypto)
1140 gpg_error_t rc;
1141 xmlDocPtr doc;
1142 struct cache_data_s *cdata;
1143 unsigned char *crc;
1144 size_t len;
1145 int fd = -1;
1147 log_write (_("Adding '%s' to the cache..."),
1148 crypto->filename);
1150 if (valid_filename (crypto->filename) == 0)
1152 log_write (_("%s: Invalid characters in filename"), crypto->filename);
1153 return GPG_ERR_INV_VALUE;
1156 rc = lock_flock (NULL, crypto->filename, LOCK_SH, &fd);
1157 if (!rc)
1158 rc = crypto_decrypt (NULL, crypto);
1159 if (rc)
1161 unlock_flock (&fd);
1162 return rc;
1165 rc = xml_parse_doc ((char *) crypto->plaintext, crypto->plaintext_size, &doc);
1166 if (rc)
1168 unlock_flock (&fd);
1169 log_write ("%s", pwmd_strerror (rc));
1170 return rc;
1173 cdata = xcalloc (1, sizeof (struct cache_data_s));
1174 if (!cdata)
1176 unlock_flock (&fd);
1177 xmlFreeDoc (doc);
1178 return GPG_ERR_ENOMEM;
1181 rc = get_checksum (crypto->filename, &crc, &len);
1182 unlock_flock (&fd);
1183 if (rc)
1185 xmlFreeDoc (doc);
1186 cache_free_data_once (cdata);
1187 return rc;
1190 cdata->crc = crc;
1191 rc = cache_encrypt (crypto);
1192 if (!rc)
1194 cdata->doc = crypto->plaintext;
1195 cdata->size = crypto->plaintext_size;
1196 crypto->plaintext = NULL;
1197 cdata->pubkey = crypto->pubkey;
1198 cdata->sigkey = crypto->sigkey;
1199 crypto->pubkey = NULL;
1200 crypto->sigkey = NULL;
1202 else
1204 xmlFreeDoc (doc);
1205 cache_free_data_once (cdata);
1206 return rc;
1209 long timeout = config_get_long (crypto->filename, "cache_timeout");
1210 rc = cache_add_file (crypto->filename, cdata, timeout);
1211 return rc;
1214 static gpg_error_t
1215 init_client (int fd, const char *addr)
1217 gpg_error_t rc = 0;
1218 struct client_thread_s *new = xcalloc (1, sizeof (struct client_thread_s));
1220 if (!new)
1222 close (fd);
1223 log_write ("%s: %s", __FUNCTION__, pwmd_strerror (ENOMEM));
1224 return GPG_ERR_ENOMEM;
1227 MUTEX_LOCK (&cn_mutex);
1228 pthread_cleanup_push (release_mutex_cb, &cn_mutex);
1229 new->conntime = time (NULL);
1231 if (pipe (new->status_msg_pipe) == -1)
1232 rc = gpg_error_from_errno (errno);
1233 else
1234 pthread_mutex_init (&new->status_mutex, NULL);
1236 if (!rc)
1238 #ifdef WITH_GNUTLS
1239 new->remote = addr ? 1 : 0;
1240 if (addr)
1241 new->peeraddr = str_dup (addr);
1242 #endif
1243 new->fd = fd;
1244 rc = create_thread (client_thread, new, &new->tid, 1);
1245 if (rc)
1247 close (new->status_msg_pipe[0]);
1248 close (new->status_msg_pipe[1]);
1249 pthread_mutex_destroy (&new->status_mutex);
1253 if (!rc)
1255 if (addr)
1256 log_write (_("new connection: tid=%p, fd=%i, addr=%s"),
1257 (pthread_t *) new->tid, fd, addr);
1258 else
1259 log_write (_("new connection: tid=%p, fd=%i"),
1260 (pthread_t *) new->tid, fd);
1263 pthread_cleanup_pop (1);
1265 if (rc)
1267 xfree (new);
1268 close (fd);
1269 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
1271 return rc;
1274 #ifdef WITH_GNUTLS
1275 static gpg_error_t
1276 do_tls_accept (struct pollfd *fds)
1278 struct sockaddr_storage raddr;
1279 socklen_t slen = sizeof (raddr);
1280 int fd;
1281 char s[INET6_ADDRSTRLEN];
1283 if (!(fds->revents & POLLIN))
1284 return 0;
1286 memset (&raddr, 0, sizeof (raddr));
1287 fd = accept (fds->fd, (struct sockaddr *) &raddr, &slen);
1288 if (fd == -1)
1290 int e = errno;
1292 if (errno != EAGAIN && !quit)
1293 log_write ("%s: %s", __FUNCTION__,
1294 pwmd_strerror (gpg_error_from_syserror()));
1296 return gpg_error_from_errno (e);
1299 inet_ntop (raddr.ss_family, get_in_addr ((struct sockaddr *) &raddr), s,
1300 sizeof s);
1301 (void) init_client (fd, s);
1302 return 0;
1304 #endif
1306 static void *
1307 accept_thread (void *arg)
1309 int sockfd = *(int *) arg;
1310 #ifndef HAVE_PTHREAD_CANCEL
1311 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
1312 #endif
1314 #ifdef HAVE_PR_SET_NAME
1315 prctl (PR_SET_NAME, "accept");
1316 #endif
1317 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
1319 for (;;)
1321 socklen_t slen = sizeof (struct sockaddr_un);
1322 struct sockaddr_un raddr;
1323 int fd, s = 0;
1324 struct pollfd fds[3];
1326 TEST_CANCEL ();
1327 memset (fds, 0, sizeof (fds));
1328 fds[s].fd = sockfd;
1329 fds[s++].events = POLLIN;
1331 #ifdef WITH_GNUTLS
1332 if (tls_fd != -1)
1334 fds[s].fd = tls_fd;
1335 fds[s++].events = POLLIN;
1337 else
1338 fds[s].fd = tls_fd;
1340 if (tls6_fd != -1)
1342 fds[s].fd = tls6_fd;
1343 fds[s++].events = POLLIN;
1345 else
1346 fds[s].fd = tls6_fd;
1347 #endif
1349 s = poll (fds, s, 500);
1350 if (s == -1)
1352 if (errno != EINTR)
1353 log_write ("%s", strerror (errno));
1354 break;
1356 else if (s == 0)
1357 continue;
1359 if (fds[0].revents & POLLIN)
1361 fd = accept (sockfd, (struct sockaddr *) &raddr, &slen);
1362 if (fd == -1)
1364 if (errno == EMFILE || errno == ENFILE)
1365 log_write ("%s: %s", __FUNCTION__,
1366 pwmd_strerror (gpg_error_from_errno (errno)));
1367 else if (errno != EAGAIN && errno != EINTR)
1369 if (!quit) // probably EBADF
1370 log_write ("%s: %s", __FUNCTION__,
1371 pwmd_strerror (gpg_error_from_errno (errno)));
1373 break;
1376 continue;
1379 (void) init_client (fd, NULL);
1382 #ifdef WITH_GNUTLS
1383 if (tls_fd != -1 && fds[1].fd == tls_fd)
1384 (void)do_tls_accept (&fds[1]);
1386 if (tls6_fd != -1 && fds[1].fd == tls6_fd)
1387 (void)do_tls_accept (&fds[1]);
1389 if (tls6_fd != -1 && fds[2].fd == tls6_fd)
1390 (void)do_tls_accept (&fds[2]);
1391 #endif
1394 /* Just in case accept() failed for some reason other than EBADF */
1395 quit = 1;
1396 return NULL;
1399 static void *
1400 cache_timer_thread (void *arg)
1402 unsigned k = 0;
1403 #ifndef HAVE_PTHREAD_CANCEL
1404 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
1405 #endif
1407 (void)arg;
1409 #ifdef HAVE_PR_SET_NAME
1410 prctl (PR_SET_NAME, "timer");
1411 #endif
1412 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
1414 for (;;)
1416 struct timeval tv = { 1, 0 };
1417 unsigned keepalive = config_get_integer ("global", "keepalive_interval");
1419 TEST_CANCEL ();
1420 select (0, NULL, NULL, NULL, &tv);
1421 cache_adjust_timeout ();
1423 if (keepalive && ++k >= keepalive)
1425 send_status_all (STATUS_KEEPALIVE, NULL);
1426 k = 0;
1430 return NULL;
1433 static int
1434 signal_loop (sigset_t sigset)
1436 int done = 0;
1440 siginfo_t info;
1442 memset (&info, 0, sizeof (info));
1443 sigwaitinfo (&sigset, &info);
1444 log_write (_("caught signal %i (%s), sender: pid=%li, uid=%u"),
1445 info.si_signo, strsignal (info.si_signo),
1446 info.si_pid <= 0 ? getpid () : info.si_pid,
1447 info.si_uid <= 0 ? getuid () : info.si_uid);
1449 switch (info.si_signo)
1451 case SIGHUP:
1452 pthread_cond_signal (&rcfile_cond);
1453 break;
1454 case SIGUSR1:
1455 log_write (_("clearing file cache"));
1456 cache_clear (NULL, NULL, 1, 0);
1457 send_status_all (STATUS_CACHE, NULL);
1458 break;
1459 default:
1460 done = 1;
1461 break;
1464 while (!done);
1466 return done;
1469 static void
1470 catchsig (int sig)
1472 log_write (_ ("Caught signal %i (%s). Exiting."), sig, strsignal (sig));
1473 #ifdef HAVE_BACKTRACE
1474 BACKTRACE (__FUNCTION__);
1475 #endif
1476 longjmp (jmp, 1);
1479 static void
1480 cancel_all_clients ()
1482 unsigned i, t;
1484 MUTEX_LOCK (&cn_mutex);
1485 t = slist_length (cn_thread_list);
1486 for (i = 0; i < t; i++)
1488 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
1490 #ifdef HAVE_PTHREAD_CANCEL
1491 pthread_cancel (thd->tid);
1492 #else
1493 pthread_kill (thd->tid, SIGUSR2);
1494 #endif
1497 while (slist_length (cn_thread_list))
1499 MUTEX_UNLOCK (&cn_mutex);
1500 usleep (50000);
1501 MUTEX_LOCK (&cn_mutex);
1504 MUTEX_UNLOCK (&cn_mutex);
1507 static int
1508 server_loop (int sockfd, char **socketpath)
1510 pthread_t cache_timeout_tid;
1511 pthread_t accept_tid;
1512 int cancel_timeout_thread = 0;
1513 int cancel_accept_thread = 0;
1514 int cancel_rcfile_thread = 0;
1515 sigset_t sigset;
1516 int n;
1517 int segv = 0;
1518 gpg_error_t rc;
1520 init_commands ();
1521 sigemptyset (&sigset);
1523 /* Termination */
1524 sigaddset (&sigset, SIGTERM);
1525 sigaddset (&sigset, SIGINT);
1527 /* Clears the file cache. */
1528 sigaddset (&sigset, SIGUSR1);
1530 /* Configuration file reloading. */
1531 sigaddset (&sigset, SIGHUP);
1533 #ifndef HAVE_PTHREAD_CANCEL
1535 The socket, cache and rcfile threads use this signal when
1536 pthread_cancel() is unavailable. Prevent the main thread from
1537 catching this signal from another process.
1539 sigaddset (&sigset, SIGUSR2);
1540 #endif
1542 /* An assertion failure. */
1543 signal (SIGABRT, catchsig);
1545 sigaddset (&sigset, SIGABRT);
1546 sigprocmask (SIG_BLOCK, &sigset, NULL);
1548 #ifndef HAVE_PTHREAD_CANCEL
1549 /* Remove this signal from the watched signals in signal_loop(). */
1550 sigdelset (&sigset, SIGUSR2);
1551 #endif
1553 /* Can show a backtrace of the stack in the log. */
1554 signal (SIGSEGV, catchsig);
1556 char *p = get_username (getuid());
1557 log_write (_("%s started for user %s"), PACKAGE_STRING PWMD_GIT_HASH, p);
1558 xfree (p);
1560 #ifdef WITH_GNUTLS
1561 if (config_get_boolean ("global", "enable_tcp"))
1562 log_write (_("Listening on %s and TCP port %i"), *socketpath,
1563 config_get_integer ("global", "tcp_port"));
1564 else
1565 log_write (_("Listening on %s"), *socketpath);
1566 #else
1567 log_write (_("Listening on %s"), *socketpath);
1568 #endif
1570 rc = create_thread (reload_rcfile_thread, NULL, &rcfile_tid, 0);
1571 if (rc)
1573 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1574 pwmd_strerror (rc));
1575 goto done;
1578 cancel_rcfile_thread = 1;
1579 rc = create_thread (cache_timer_thread, NULL, &cache_timeout_tid, 0);
1580 if (rc)
1582 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1583 pwmd_strerror (rc));
1584 goto done;
1587 cancel_timeout_thread = 1;
1588 rc = create_thread (accept_thread, &sockfd, &accept_tid, 0);
1589 if (rc)
1591 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1592 pwmd_strerror (rc));
1593 goto done;
1596 cancel_accept_thread = 1;
1597 if (!setjmp (jmp))
1598 signal_loop (sigset);
1599 else
1600 segv = 1;
1602 done:
1604 * We're out of the main server loop. This happens when a signal was sent
1605 * to terminate the daemon. Cancel all clients and exit.
1607 if (cancel_accept_thread)
1609 #ifdef HAVE_PTHREAD_CANCEL
1610 n = pthread_cancel (accept_tid);
1611 #else
1612 n = pthread_kill (accept_tid, SIGUSR2);
1613 #endif
1614 if (!n)
1615 pthread_join (accept_tid, NULL);
1618 if (cancel_timeout_thread)
1620 #ifdef HAVE_PTHREAD_CANCEL
1621 n = pthread_cancel (cache_timeout_tid);
1622 #else
1623 n = pthread_kill (cache_timeout_tid, SIGUSR2);
1624 #endif
1625 if (!n)
1626 pthread_join (cache_timeout_tid, NULL);
1629 #ifdef WITH_GNUTLS
1630 tls_start_stop (1);
1631 #endif
1632 shutdown (sockfd, SHUT_RDWR);
1633 close (sockfd);
1634 unlink (*socketpath);
1635 xfree (*socketpath);
1636 *socketpath = NULL;
1637 MUTEX_LOCK (&cn_mutex);
1638 n = slist_length (cn_thread_list);
1639 MUTEX_UNLOCK (&cn_mutex);
1641 if (n && !segv)
1642 cancel_all_clients ();
1643 else
1644 free_all_clients ();
1646 if (cancel_rcfile_thread)
1648 #ifdef HAVE_PTHREAD_CANCEL
1649 pthread_cancel (rcfile_tid);
1650 #else
1651 pthread_kill (rcfile_tid, SIGUSR2);
1652 pthread_cond_signal (&rcfile_cond);
1653 #endif
1654 pthread_join (rcfile_tid, NULL);
1657 cache_deinit ();
1658 deinit_commands ();
1659 return segv ? EXIT_FAILURE : EXIT_SUCCESS;
1662 static void
1663 usage (const char *pn, int status)
1665 FILE *fp = status == EXIT_FAILURE ? stderr : stdout;
1667 fprintf (fp, _("Usage: %s [OPTIONS] [file1] [...]\n"
1668 " --homedir alternate pwmd home directory (~/.pwmd)\n"
1669 " -f, --rcfile=filename load the specified configuration file\n"
1670 " (~/.pwmd/config)\n"
1671 " --kill terminate an existing instance of pwmd\n"
1672 " -n, --no-fork run as a foreground process\n"
1673 " --disable-dump disable the LIST, XPATH and DUMP commands\n"
1674 " --ignore, --force ignore cache pushing errors during startup\n"
1675 " -I, --import=filename import a pwmd DTD formatted XML file)\n"
1676 " -k, --passphrase-file=file for use when importing\n"
1677 " -o, --outfile=filename output file when importing\n"
1678 " --keyid=fpr[,..] public key to use when encrypting\n"
1679 " --sign-keyid=fpr fingerprint of the signing key to use\n"
1680 " -s, --symmetric use conventional encryption with optional signer\n"
1681 " --userid=string name and email address to use when importing\n"
1682 " --algo=string algorithm to use when importing (engine default)\n"
1683 " --expire=seconds key expiry time when importing (3 years)\n"
1684 " --no-passphrase don't require a passphrase when importing\n"
1685 " --debug=[a:..][,g:N][,t:N] enable debugging (a:[ixedsc],g:[1-9],t:[0-N])\n"
1686 " --help this help text\n"
1687 " --version show version and compile time features\n"),
1688 pn);
1689 exit (status);
1692 static void
1693 unlink_stale_socket (const char *sock, const char *pidfile)
1695 log_write (_ ("removing stale socket %s"), sock);
1696 unlink (sock);
1697 unlink (pidfile);
1700 static int
1701 test_pidfile (const char *path, const char *sock, char *buf, size_t buflen,
1702 char **pidfile, int create, mode_t mode, int terminate)
1704 long pid;
1705 int fd;
1706 size_t len;
1708 if (!create)
1710 snprintf (buf, buflen, "%s.pid", path);
1711 *pidfile = str_dup (buf);
1712 fd = open (buf, O_RDONLY);
1714 else
1715 fd = open (*pidfile, O_CREAT|O_WRONLY|O_TRUNC, mode);
1717 if (fd == -1)
1719 if (!create && errno != ENOENT)
1721 log_write ("%s: %s", buf, pwmd_strerror (errno));
1722 xfree (*pidfile);
1723 *pidfile = NULL;
1724 return -1;
1726 else if (!create && !terminate)
1727 return 0;
1729 log_write ("%s: %s", *pidfile, strerror (errno));
1730 return -1;
1733 if (create)
1735 pid = getpid();
1736 snprintf (buf, buflen, "%li", pid);
1737 ssize_t ret = write (fd, buf, strlen (buf));
1738 if (ret == -1)
1739 log_write ("%s (%i): %s", __FUNCTION__, __LINE__,
1740 pwmd_strerror (gpg_error_from_syserror ()));
1741 close (fd);
1742 return 0;
1745 if (buflen < 8)
1747 close (fd);
1748 log_write ("%s (%i): %s", __FUNCTION__, __LINE__,
1749 pwmd_strerror (GPG_ERR_BUFFER_TOO_SHORT));
1750 return -1;
1753 len = read (fd, buf, buflen);
1754 close (fd);
1755 if (len == 0)
1757 unlink_stale_socket (path, *pidfile);
1758 return 0;
1761 if (sscanf (buf, "%li", &pid) != 1 || pid == 0)
1763 if (!terminate)
1765 unlink_stale_socket (path, *pidfile);
1766 return 0;
1770 if (kill (pid, 0) == -1)
1772 unlink_stale_socket (path, *pidfile);
1773 return 0;
1776 if (terminate)
1778 if (kill (pid, SIGTERM) == -1)
1779 log_write ("%s: %s", path, pwmd_strerror (errno));
1781 else
1782 log_write (_ ("an instance for socket %s is already running"), path);
1784 xfree (*pidfile);
1785 *pidfile = NULL;
1786 return 1;
1789 static unsigned
1790 parse_debug_level (const char *str, unsigned *debug, int *gpgme, int *tls)
1792 const char *p;
1793 unsigned level = 0;
1794 int gl = 0, tl = 0;
1796 for (p = str; p && *p; p++)
1798 if (*p == 'a') // assuan debug flags
1800 if (*++p != ':')
1801 return 1;
1803 while (*++p)
1805 switch (*p)
1807 case 'i':
1808 level |= ASSUAN_LOG_INIT;
1809 break;
1810 case 'x':
1811 level |= ASSUAN_LOG_CTX;
1812 break;
1813 case 'e':
1814 level |= ASSUAN_LOG_ENGINE;
1815 break;
1816 case 'd':
1817 level |= ASSUAN_LOG_DATA;
1818 break;
1819 case 's':
1820 level |= ASSUAN_LOG_SYSIO;
1821 break;
1822 case 'c':
1823 level |= ASSUAN_LOG_CONTROL;
1824 break;
1825 case ',':
1826 break;
1827 default:
1828 return 1;
1831 if (*p == ',')
1832 break;
1835 if (!*p)
1836 break;
1838 else if (*p == 'g' || *p == 't') // gpgme and TLS debug level
1840 int t = *p == 't';
1841 int n;
1843 if (*++p != ':')
1844 return 1;
1846 if (!isdigit (*++p))
1847 return 1;
1849 n = atoi (p);
1850 if (t)
1851 tl = n;
1852 else
1853 gl = n;
1855 if (tl < 0 || gl < 0 || gl > 9)
1856 return 1;
1858 while (isdigit (*p))
1859 p++;
1861 p--;
1862 if (*(p+1) && *(p+1) != ',')
1863 return 1;
1864 else if (*(p+1))
1865 p++;
1867 else
1868 return 1;
1871 if (tl)
1872 *tls = tl;
1874 if (gl)
1875 *gpgme = gl;
1877 *debug = level;
1878 return 0;
1882 main (int argc, char *argv[])
1884 int opt;
1885 struct sockaddr_un addr;
1886 char buf[PATH_MAX];
1887 char *socketpath = NULL, *socketdir, *socketname = NULL;
1888 char *socketarg = NULL;
1889 char *datadir = NULL;
1890 char *pidfile = NULL;
1891 mode_t mode = 0600;
1892 int x;
1893 char *p;
1894 char **cache_push = NULL;
1895 char *import = NULL, *keyid = NULL, *sign_keyid = NULL;
1896 char *userid = NULL;
1897 char *algo = NULL;
1898 long expire = 0;
1899 int no_passphrase = 0;
1900 int estatus = EXIT_FAILURE;
1901 int sockfd;
1902 char *outfile = NULL;
1903 int do_unlink = 0;
1904 int secure = 0;
1905 int show_version = 0;
1906 int force = 0;
1907 gpg_error_t rc;
1908 char *keyfile = NULL;
1909 int exists;
1910 int optindex;
1911 int terminate = 0;
1912 int sym = 0;
1913 int gpgme_level = -1;
1914 int tls_level = -1;
1915 int backlog = 0;
1916 /* Must maintain the same order as longopts[] */
1917 enum
1919 OPT_VERSION, OPT_HELP, OPT_HOMEDIR, OPT_NO_FORK, OPT_DISABLE_DUMP,
1920 OPT_FORCE, OPT_RCFILE, OPT_PASSPHRASE_FILE, OPT_IMPORT, OPT_OUTFILE,
1921 OPT_KEYID, OPT_SIGN_KEYID, OPT_SYMMETRIC, OPT_USERID, OPT_ALGO, OPT_EXPIRE,
1922 OPT_NOPASSPHRASE, OPT_KILL, OPT_DEBUG
1924 const char *optstring = "nf:C:k:I:o:s";
1925 const struct option longopts[] = {
1926 {"version", no_argument, 0, 0},
1927 {"help", no_argument, 0, 0},
1928 {"homedir", required_argument, 0, 0},
1929 {"no-fork", no_argument, 0, 'n'},
1930 {"disable_dump", no_argument, 0, 0},
1931 {"force", no_argument, 0, 0},
1932 {"rcfile", required_argument, 0, 'f'},
1933 {"passphrase-file", required_argument, 0, 'k'},
1934 {"import", required_argument, 0, 'I'},
1935 {"outfile", required_argument, 0, 'o'},
1936 {"keyid", required_argument, 0, 0},
1937 {"sign-keyid", required_argument, 0, 0},
1938 {"symmetric", no_argument, 0, 's'},
1939 {"userid", required_argument, 0, 0},
1940 {"algo", required_argument, 0, 0},
1941 {"expire", required_argument, 0, 0},
1942 {"no-passphrase", no_argument, 0, 0},
1943 {"kill", no_argument, 0, 0},
1944 {"debug", required_argument, 0, 0},
1945 {0, 0, 0, 0}
1948 log_fd = -1;
1949 cmdline = 1;
1950 expire = time (NULL) + DEFAULT_EXPIRE;
1952 #ifndef DEBUG
1953 #ifdef HAVE_SETRLIMIT
1954 struct rlimit rl;
1956 rl.rlim_cur = rl.rlim_max = 0;
1958 if (setrlimit (RLIMIT_CORE, &rl) != 0)
1959 err (EXIT_FAILURE, "setrlimit()");
1960 #endif
1962 #ifdef HAVE_PR_SET_DUMPABLE
1963 prctl (PR_SET_DUMPABLE, 0);
1964 #endif
1965 #endif
1967 #ifdef ENABLE_NLS
1968 setlocale (LC_ALL, "");
1969 bindtextdomain ("pwmd", LOCALEDIR);
1970 textdomain ("pwmd");
1971 #endif
1973 while ((opt = getopt_long (argc, argv, optstring, longopts, &optindex))
1974 != -1)
1976 switch (opt)
1978 case 'I':
1979 import = optarg;
1980 break;
1981 case 'k':
1982 keyfile = optarg;
1983 break;
1984 case 'o':
1985 outfile = optarg;
1986 break;
1987 case 'n':
1988 nofork = 1;
1989 break;
1990 case 'f':
1991 rcfile = str_dup (optarg);
1992 break;
1993 case 's':
1994 sym = 1;
1995 break;
1996 default:
1997 usage (argv[0], EXIT_FAILURE);
1998 break;
1999 case 0:
2000 switch (optindex)
2002 case OPT_DEBUG:
2003 if (parse_debug_level (optarg, &assuan_level, &gpgme_level,
2004 &tls_level))
2005 usage (argv[0], EXIT_FAILURE);
2006 break;
2007 case OPT_SYMMETRIC:
2008 sym = 1;
2009 break;
2010 case OPT_VERSION:
2011 show_version = 1;
2012 break;
2013 case OPT_HELP:
2014 usage (argv[0], EXIT_SUCCESS);
2015 break;
2016 case OPT_HOMEDIR:
2017 homedir = str_dup (optarg);
2018 break;
2019 case OPT_NO_FORK:
2020 nofork = 1;
2021 break;
2022 case OPT_DISABLE_DUMP:
2023 secure = 1;
2024 break;
2025 case OPT_FORCE:
2026 force = 1;
2027 break;
2028 case OPT_RCFILE:
2029 rcfile = str_dup (optarg);
2030 break;
2031 case OPT_PASSPHRASE_FILE:
2032 keyfile = optarg;
2033 break;
2034 case OPT_IMPORT:
2035 import = optarg;
2036 break;
2037 case OPT_OUTFILE:
2038 outfile = optarg;
2039 break;
2040 case OPT_KEYID:
2041 keyid = optarg;
2042 break;
2043 case OPT_SIGN_KEYID:
2044 sign_keyid = optarg;
2045 break;
2046 case OPT_USERID:
2047 userid = optarg;
2048 break;
2049 case OPT_ALGO:
2050 algo = optarg;
2051 break;
2052 case OPT_EXPIRE:
2053 errno = rc = 0;
2054 expire = strtoul (optarg, &p, 10);
2056 if (!errno && p && *p)
2057 rc = GPG_ERR_INV_VALUE;
2058 else if (expire == ULONG_MAX)
2059 rc = GPG_ERR_INV_VALUE;
2060 else if (errno)
2061 rc = gpg_error_from_syserror ();
2063 if (rc)
2064 usage (argv[0], EXIT_FAILURE);
2065 break;
2066 case OPT_NOPASSPHRASE:
2067 no_passphrase = 1;
2068 break;
2069 case OPT_KILL:
2070 terminate = 1;
2071 break;
2072 default:
2073 usage (argv[0], EXIT_FAILURE);
2078 if (show_version)
2080 printf (_("%s\n\n"
2081 "Copyright (C) 2006-2021\n"
2082 "%s\n"
2083 "Released under the terms of the GPL v2.\n\n"
2084 "Compile time features:\n%s"), PACKAGE_STRING PWMD_GIT_HASH,
2085 PACKAGE_BUGREPORT,
2086 #ifdef PWMD_HOMEDIR
2087 "+PWMD_HOMEDIR=" PWMD_HOMEDIR "\n"
2088 #endif
2089 #ifdef WITH_GNUTLS
2090 "+WITH_GNUTLS\n"
2091 #else
2092 "-WITH_GNUTLS\n"
2093 #endif
2094 #ifdef WITH_LIBACL
2095 "+WITH_LIBACL\n"
2096 #else
2097 "-WITH_LIBACL\n"
2098 #endif
2099 #ifdef DEBUG
2100 "+DEBUG\n"
2101 #else
2102 "-DEBUG\n"
2103 #endif
2104 #ifdef MEM_DEBUG
2105 "+MEM_DEBUG\n"
2106 #else
2107 "-MEM_DEBUG\n"
2108 #endif
2109 #ifdef MUTEX_DEBUG
2110 "+MUTEX_DEBUG\n"
2111 #else
2112 "-MUTEX_DEBUG\n"
2113 #endif
2115 exit (EXIT_SUCCESS);
2118 if (gpgme_level != -1)
2120 char s[2] = { gpgme_level + '0', 0 };
2122 if (getenv ("GPGME_DEBUG"))
2123 log_write (_ ("Overriding GPGME_DEBUG environment with level %u!"),
2124 gpgme_level);
2126 gpgme_set_global_flag ("debug", s);
2129 if (setup_crypto ())
2130 exit (EXIT_FAILURE);
2132 #ifdef WITH_GNUTLS
2133 tls_level = tls_level == -1 ? 1 : tls_level;
2134 gnutls_global_set_log_level (tls_level);
2135 tls_fd = -1;
2136 tls6_fd = -1;
2137 #endif
2138 rc = xml_init ();
2139 if (rc)
2140 errx (EXIT_FAILURE, "%s", "xml_init() failed");
2142 if (!homedir)
2143 #ifdef PWMD_HOMEDIR
2144 homedir = str_dup(PWMD_HOMEDIR);
2145 #else
2146 homedir = str_asprintf ("%s/.pwmd", get_home_dir());
2147 #endif
2149 if (mkdir (homedir, 0700) == -1 && errno != EEXIST)
2150 err (EXIT_FAILURE, "%s", homedir);
2152 if (!rcfile)
2153 rcfile = str_asprintf ("%s/config", homedir);
2155 pthread_key_create (&last_error_key, free_key);
2156 #ifndef HAVE_PTHREAD_CANCEL
2157 pthread_key_create (&signal_thread_key, free_key);
2158 #endif
2160 pthread_mutexattr_t attr;
2161 pthread_mutexattr_init (&attr);
2162 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
2163 pthread_mutex_init (&rcfile_mutex, &attr);
2164 global_config = config_parse (rcfile, 0);
2165 if (!global_config)
2167 pthread_mutexattr_destroy (&attr);
2168 pthread_mutex_destroy (&rcfile_mutex);
2169 exit (EXIT_FAILURE);
2172 p = config_get_string ("global", "gpg_homedir");
2173 if (!p)
2174 datadir = str_asprintf ("%s/.gnupg", homedir);
2175 else
2176 datadir = expand_homedir (p);
2178 xfree (p);
2179 if (mkdir (datadir, 0700) == -1 && errno != EEXIST)
2180 err (EXIT_FAILURE, "%s", datadir);
2182 rc = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, NULL, datadir);
2183 if (rc)
2184 errx (EXIT_FAILURE, "%s: %s", datadir, pwmd_strerror (rc));
2185 xfree (datadir);
2187 snprintf (buf, sizeof (buf), "%s/data", homedir);
2188 if (mkdir (buf, 0700) == -1 && errno != EEXIST)
2189 err (EXIT_FAILURE, "%s", buf);
2191 datadir = str_dup (buf);
2192 pthread_cond_init (&rcfile_cond, NULL);
2193 pthread_mutex_init (&cn_mutex, &attr);
2194 pthread_mutexattr_destroy (&attr);
2196 setup_logging ();
2198 x = config_get_int_param (global_config, "global", "priority", &exists);
2199 if (exists && x != atoi(INVALID_PRIORITY))
2201 errno = 0;
2202 if (setpriority (PRIO_PROCESS, 0, x) == -1)
2204 log_write ("setpriority(): %s",
2205 pwmd_strerror (gpg_error_from_errno (errno)));
2206 goto do_exit;
2209 #ifdef HAVE_MLOCKALL
2210 if (disable_mlock == 0 && mlockall (MCL_CURRENT | MCL_FUTURE) == -1)
2212 log_write ("mlockall(): %s",
2213 pwmd_strerror (gpg_error_from_errno (errno)));
2214 goto do_exit;
2216 #endif
2218 rc = cache_init ();
2219 if (rc)
2221 log_write ("pwmd: ERR %i: %s", rc, pwmd_strerror (rc));
2222 exit (EXIT_FAILURE);
2225 if (import)
2227 char **keyids = NULL;
2229 if (!outfile || !*outfile || argc != optind)
2230 usage (argv[0], EXIT_FAILURE);
2232 if (keyid)
2233 keyids = str_split (keyid, ",", 0);
2234 else if (!userid && !sym)
2235 usage (argv[0], EXIT_FAILURE);
2237 rc = xml_import (import, outfile, keyids, sign_keyid, keyfile, userid,
2238 algo, expire, no_passphrase, sym);
2239 strv_free (keyids);
2240 if (rc)
2242 if (gpg_err_source (rc) == GPG_ERR_SOURCE_UNKNOWN)
2243 rc = gpg_error (rc);
2245 log_write ("%s: %u: %s", import, rc, pwmd_strerror (rc));
2248 config_free (global_config);
2249 xfree (rcfile);
2250 exit (rc ? EXIT_FAILURE : EXIT_SUCCESS);
2253 p = config_get_string ("global", "socket_path");
2254 if (!p)
2255 p = str_asprintf ("%s/socket", homedir);
2257 socketarg = expand_homedir (p);
2258 xfree (p);
2260 if (!secure)
2261 disable_list_and_dump = config_get_boolean ("global",
2262 "disable_list_and_dump");
2263 else
2264 disable_list_and_dump = secure;
2266 cache_push = config_get_list ("global", "cache_push");
2268 while (optind < argc)
2270 if (strv_printf (&cache_push, "%s", argv[optind++]) == 0)
2271 errx (EXIT_FAILURE, "%s", pwmd_strerror (GPG_ERR_ENOMEM));
2274 if (!strchr (socketarg, '/'))
2276 socketdir = getcwd (buf, sizeof (buf));
2277 socketname = str_dup (socketarg);
2278 socketpath = str_asprintf ("%s/%s", socketdir, socketname);
2280 else
2282 socketname = str_dup (strrchr (socketarg, '/')+1);
2283 socketarg[strlen (socketarg) - strlen (socketname) - 1] = 0;
2284 socketdir = str_dup (socketarg);
2285 socketpath = str_asprintf ("%s/%s", socketdir, socketname);
2288 if (chdir (datadir))
2290 log_write ("%s: %s", datadir,
2291 pwmd_strerror (gpg_error_from_errno (errno)));
2292 unlink (socketpath);
2293 goto do_exit;
2296 x = test_pidfile (socketpath, socketname, buf, sizeof(buf), &pidfile, 0,
2297 mode, terminate);
2298 if (!terminate && x)
2299 goto do_exit;
2300 else if (terminate)
2302 estatus = x != 1 ? EXIT_FAILURE : EXIT_SUCCESS;
2303 goto do_exit;
2307 * bind() doesn't like the full pathname of the socket or any non alphanum
2308 * characters so change to the directory where the socket is wanted then
2309 * create it then change to datadir.
2311 if (chdir (socketdir))
2313 log_write ("%s: %s", socketdir,
2314 pwmd_strerror (gpg_error_from_errno (errno)));
2315 goto do_exit;
2318 xfree (socketdir);
2320 if ((sockfd = socket (PF_UNIX, SOCK_STREAM, 0)) == -1)
2322 log_write ("socket(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2323 goto do_exit;
2326 addr.sun_family = AF_UNIX;
2327 snprintf (addr.sun_path, sizeof (addr.sun_path), "%s", socketname);
2328 do_unlink = 1;
2329 if (bind (sockfd, (struct sockaddr *) &addr, sizeof (struct sockaddr)) ==
2332 log_write ("bind(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2334 if (errno == EADDRINUSE)
2336 do_unlink = 0;
2337 log_write (_("Either there is another pwmd running or '%s' is a \n"
2338 "stale socket. Please remove it manually."), socketpath);
2341 goto do_exit;
2345 char *t = config_get_string ("global", "socket_perms");
2346 mode_t mask;
2348 if (t)
2350 mode = strtol (t, NULL, 8);
2351 mask = umask (0);
2352 xfree (t);
2354 if (chmod (socketname, mode) == -1)
2356 log_write ("%s: %s", socketname,
2357 pwmd_strerror (gpg_error_from_errno (errno)));
2358 close (sockfd);
2359 umask (mask);
2360 goto do_exit;
2363 umask (mask);
2367 if (chdir (datadir))
2369 log_write ("%s: %s", datadir,
2370 pwmd_strerror (gpg_error_from_errno (errno)));
2371 close (sockfd);
2372 goto do_exit;
2375 xfree (datadir);
2376 #ifdef WITH_GNUTLS
2377 if (config_get_boolean ("global", "enable_tcp"))
2379 if (!tls_start_stop (0))
2381 close (sockfd);
2382 goto do_exit;
2385 #endif
2388 * Set the cache entry for a file. Prompts for the password.
2390 if (cache_push)
2392 for (opt = 0; cache_push[opt]; opt++)
2394 struct crypto_s *crypto = NULL;
2395 char *pw_file = config_get_string (cache_push[opt],
2396 "passphrase_file");
2397 rc = crypto_init (&crypto, NULL, cache_push[opt], pw_file != NULL,
2398 pw_file);
2400 if (!rc)
2402 crypto->flags |= pw_file ? CRYPTO_FLAG_KEYFILE : 0;
2403 crypto->keyfile = pw_file;
2405 else
2406 xfree (pw_file);
2408 if (rc)
2410 estatus = EXIT_FAILURE;
2411 goto do_exit;
2414 rc = do_cache_push (crypto);
2415 if (rc && !force)
2417 log_write ("ERR %u: %s", rc, pwmd_strerror(rc));
2418 strv_free (cache_push);
2419 log_write (_ ("Failed to add a file to the cache. Use --force to force startup. Exiting."));
2420 cache_clear (NULL, NULL, 1, 0);
2421 estatus = EXIT_FAILURE;
2422 crypto_free (crypto);
2423 (void)cache_kill_scd ();
2424 goto do_exit;
2426 else if (rc)
2427 log_write ("%s: %s", crypto->filename, pwmd_strerror(rc));
2428 else
2429 log_write (_("Successfully added '%s' to the cache."),
2430 crypto->filename);
2432 crypto_free (crypto);
2435 (void)cache_kill_scd ();
2436 strv_free (cache_push);
2437 log_write (!nofork ? _("Done. Daemonizing...") :
2438 _("Done. Waiting for connections..."));
2441 backlog = config_get_integer ("global", "backlog");
2442 if (listen (sockfd, backlog) == -1)
2444 log_write ("listen(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2445 goto do_exit;
2448 /* A client should set these with the OPTION command. */
2449 unsetenv ("DISPLAY");
2450 unsetenv ("GPG_TTY");
2451 unsetenv ("TERM");
2453 if (!nofork)
2455 switch (fork ())
2457 case -1:
2458 log_write ("fork(): %s",
2459 pwmd_strerror (gpg_error_from_errno (errno)));
2460 goto do_exit;
2461 case 0:
2462 close (0);
2463 close (1);
2464 close (2);
2465 setsid ();
2466 break;
2467 default:
2468 _exit (EXIT_SUCCESS);
2472 (void)test_pidfile (socketpath, socketname, buf, sizeof(buf), &pidfile, 1,
2473 mode, 0);
2474 xfree (socketname);
2475 cmdline = 0;
2476 pthread_key_create (&thread_name_key, free_key);
2477 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
2478 estatus = server_loop (sockfd, &socketpath);
2480 do_exit:
2481 if (socketpath && do_unlink)
2483 unlink (socketpath);
2484 xfree (socketpath);
2487 xfree (socketarg);
2488 #ifdef WITH_GNUTLS
2489 gnutls_global_deinit ();
2490 tls_deinit_params ();
2491 #endif
2492 pthread_cond_destroy (&rcfile_cond);
2493 pthread_mutex_destroy (&rcfile_mutex);
2494 pthread_key_delete (last_error_key);
2495 #ifndef HAVE_PTHREAD_CANCEL
2496 pthread_key_delete (signal_thread_key);
2497 #endif
2499 if (global_config)
2500 config_free (global_config);
2502 free_invoking_users (invoking_users);
2503 xfree (rcfile);
2504 xfree (home_directory);
2505 xfree (homedir);
2506 xml_deinit ();
2508 if (pidfile)
2509 unlink (pidfile);
2510 xfree (pidfile);
2512 if (estatus == EXIT_SUCCESS && !terminate)
2513 log_write (_("pwmd exiting normally"));
2515 pthread_key_delete (thread_name_key);
2516 closelog ();
2518 if (log_fd != -1)
2519 close (log_fd);
2521 xfree (logfile);
2522 exit (estatus);
2525 gpg_error_t lock_flock (assuan_context_t ctx, const char *filename,
2526 int type, int *fd)
2528 gpg_error_t rc = 0;
2530 #ifdef HAVE_FLOCK
2531 rc = open_check_file (filename, fd, NULL, 1);
2532 if (rc)
2533 return rc;
2535 TRY_FLOCK (ctx, *fd, type, rc);
2536 if (rc)
2538 close (*fd);
2539 *fd = -1;
2541 #endif
2543 return rc;
2546 void unlock_flock (int *fd)
2548 #ifdef HAVE_FLOCK
2549 if (*fd != -1)
2550 close (*fd);
2552 *fd = -1;
2553 #endif