Fix commit 3c72e54.
[pwmd.git] / src / pwmd.c
blob676020ef966422e1e86aa779704f92c460ca6dbd
1 /*
2 Copyright (C) 2006-2020 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 as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
11 Pwmd is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
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 <ctype.h>
28 #include <string.h>
29 #include <sys/socket.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 <grp.h>
38 #include <pthread.h>
39 #include <sys/mman.h>
40 #include <termios.h>
41 #include <assert.h>
42 #include <syslog.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <netdb.h>
46 #include <sys/time.h>
47 #include <sys/resource.h>
48 #include <setjmp.h>
49 #include <errno.h>
50 #include <poll.h>
52 #ifdef TM_IN_SYS_TIME
53 #include <sys/time.h>
54 #else
55 #include <time.h>
56 #endif
58 #ifdef HAVE_LIMITS_H
59 #include <limits.h>
60 #endif
62 #ifdef HAVE_GETOPT_LONG
63 #ifdef HAVE_GETOPT_H
64 #include <getopt.h>
65 #endif
66 #else
67 #include "getopt_long.h"
68 #endif
70 #ifdef HAVE_PR_SET_NAME
71 #include <sys/prctl.h>
72 #endif
74 #include "pwmd-error.h"
75 #include <gcrypt.h>
77 #include "util-misc.h"
78 #include "mem.h"
79 #include "xml.h"
80 #include "common.h"
81 #include "commands.h"
82 #include "cache.h"
83 #include "util-string.h"
84 #include "mutex.h"
85 #include "rcfile.h"
86 #include "crypto.h"
87 #include "acl.h"
88 #include "version.h"
90 static int quit;
91 static int cmdline;
92 static jmp_buf jmp;
93 static int nofork;
94 static int log_fd;
95 static unsigned assuan_level;
97 #ifndef HAVE_PTHREAD_CANCEL
98 #define INIT_SIGNAL(s, cb) do { \
99 int *n = xmalloc (sizeof (int)); \
100 *n = 0; \
101 pthread_setspecific (signal_thread_key, n); \
102 struct sigaction act; \
103 sigset_t sigset; \
104 sigemptyset (&sigset); \
105 sigaddset (&sigset, s); \
106 pthread_sigmask (SIG_UNBLOCK, &sigset, NULL); \
107 memset (&act, 0, sizeof(act)); \
108 act.sa_flags = SA_SIGINFO; \
109 act.sa_mask = sigset; \
110 act.sa_sigaction = cb; \
111 sigaction (s, &act, NULL); \
112 } while (0)
114 static void
115 catch_thread_signal (int sig, siginfo_t *info, void *ctx)
117 int *n = (int *) pthread_getspecific (signal_thread_key);
119 *n = 1;
121 #endif
123 static void
124 setup_logging ()
126 int n = config_get_boolean ("global", "enable_logging");
128 if (n)
130 char *p = config_get_string ("global", "log_path");
132 if (!p || (logfile && p && log_fd != -1 && strcmp(p, logfile)))
134 if (log_fd != -1)
135 close (log_fd);
137 log_fd = -1;
140 xfree (logfile);
141 logfile = NULL;
142 if (p)
143 logfile = expand_homedir (p);
144 xfree (p);
146 else
148 xfree (logfile);
149 logfile = NULL;
150 if (log_fd != -1)
151 close(log_fd);
153 log_fd = -1;
154 closelog ();
157 log_syslog = config_get_boolean ("global", "syslog");
158 if (log_syslog == 1)
159 openlog ("pwmd", LOG_NDELAY | LOG_PID, LOG_DAEMON);
162 static void *
163 reload_rcfile_thread (void *arg)
165 #ifndef HAVE_PTHREAD_CANCEL
166 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
167 #endif
169 #ifdef HAVE_PR_SET_NAME
170 prctl (PR_SET_NAME, "reload rcfile");
171 #endif
172 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
173 MUTEX_LOCK (&rcfile_mutex);
175 (void)arg;
177 for (;;)
179 struct slist_s *keep = NULL;
180 struct slist_s *config;
181 int b = disable_list_and_dump;
182 #ifdef WITH_GNUTLS
183 char *prio;
184 char *prio2 = NULL;
185 #endif
187 pthread_cleanup_push (release_mutex_cb, &rcfile_mutex);
188 pthread_cond_wait (&rcfile_cond, &rcfile_mutex);
189 TEST_CANCEL ();
190 keep = config_keep_save ();
191 log_write (_("reloading configuration file '%s'"), rcfile);
193 #ifdef WITH_GNUTLS
194 prio = config_get_string ("global", "tls_cipher_suite");
195 #endif
196 config = config_parse (rcfile, 1);
197 if (config)
199 config_free (global_config);
200 global_config = config;
201 setup_logging ();
204 config_keep_restore (keep);
205 disable_list_and_dump = !disable_list_and_dump ? b : 1;
207 #ifdef WITH_GNUTLS
208 /* Restart listening sockets since they may have changed. */
209 tls_start_stop (1);
210 tls_start_stop (0);
212 prio2 = config_get_string ("global", "tls_cipher_suite");
213 if ((prio2 && (!prio || strcmp (prio, prio2))) || (prio && !prio2))
214 tls_rehandshake ();
216 xfree (prio2);
217 xfree (prio);
218 #endif
219 crypto_set_keepalive ();
220 pthread_cleanup_pop (0);
223 MUTEX_UNLOCK (&rcfile_mutex);
224 return NULL;
227 #define PROCESS_DONE(client,rc) (client && client->bulk_p) ? rc : \
228 assuan_process_done (client ? client->ctx : NULL, rc)
229 gpg_error_t
230 send_error (assuan_context_t ctx, gpg_error_t e)
232 struct client_s *client = assuan_get_pointer (ctx);
234 if (gpg_err_source (e) == GPG_ERR_SOURCE_UNKNOWN)
235 e = gpg_error (e);
237 if (client)
238 client->last_rc = e;
240 if (!e)
241 return PROCESS_DONE (client, 0);
243 if (!ctx)
245 log_write ("ERR %i: %s", e, pwmd_strerror (e));
246 return e;
249 if (client && client->xml_error)
251 log_write ("%s", client->xml_error->message);
252 xfree (client->last_error);
253 client->last_error = NULL;
254 if (client->xml_error->message)
255 client->last_error = str_dup (client->xml_error->message);
257 e = PROCESS_DONE (client, assuan_set_error (ctx, e,
258 client->xml_error->message
259 ? client->xml_error->message
260 : NULL));
261 xmlResetLastError ();
262 xmlResetError (client->xml_error);
263 xfree (client->xml_error);
264 client->xml_error = NULL;
265 return e;
268 return PROCESS_DONE (client, assuan_set_error (ctx, e, pwmd_strerror (e)));
271 void
272 log_write (const char *fmt, ...)
274 char *args;
275 va_list ap;
276 time_t now;
277 char buf[255];
278 pthread_t tid = pthread_self ();
279 static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
281 if ((!logfile && !nofork && !log_syslog && !cmdline) || !fmt)
282 return;
284 MUTEX_LOCK (&m);
285 pthread_cleanup_push (release_mutex_cb, &m);
287 if (!cmdline && logfile && log_fd == -1)
289 log_fd = open (logfile, O_WRONLY | O_CREAT | O_APPEND, 0600);
290 if (log_fd == -1)
291 warn ("%s", logfile);
294 va_start (ap, fmt);
296 if (str_vasprintf (&args, fmt, ap) != -1)
298 pthread_cleanup_push (xfree, args);
299 if (cmdline)
301 fprintf (stderr, "pwmd: %s\n", args);
302 fflush (stderr);
304 else
306 char *name = pthread_getspecific (thread_name_key);
307 char *line;
309 if (name)
311 if (*name == '!')
312 snprintf (buf, sizeof (buf), "%s: ", name+1);
313 else
314 snprintf (buf, sizeof (buf), "%s(%p): ", name,
315 (pthread_t *)tid);
317 else
318 snprintf (buf, sizeof (buf), "%p: ", (pthread_t *)tid);
320 name = buf;
321 if (!cmdline && log_syslog && !nofork)
322 syslog (LOG_INFO, "%s%s", name, args);
324 time (&now);
325 struct tm *tm = localtime (&now);
326 char tbuf[21];
327 strftime (tbuf, sizeof (tbuf), "%b %d %Y %H:%M:%S ", tm);
328 tbuf[sizeof (tbuf) - 1] = 0;
330 if (args[strlen (args) - 1] == '\n')
331 args[strlen (args) - 1] = 0;
333 line = str_asprintf ("%s %i %s%s\n", tbuf, getpid (), name, args);
334 if (line)
336 pthread_cleanup_push (xfree, line);
337 if (logfile && log_fd != -1)
339 ssize_t ret = write (log_fd, line, strlen (line));
340 (void)ret;
341 fsync (log_fd);
344 if (nofork)
346 fprintf (stdout, "%s", line);
347 fflush (stdout);
350 pthread_cleanup_pop (1);
353 pthread_cleanup_pop (1);
356 va_end (ap);
358 if (log_fd != -1 && log_keepopen <= 0)
360 close(log_fd);
361 log_fd = -1;
364 pthread_cleanup_pop (1);
367 static gpg_error_t
368 setup_crypto ()
370 gpg_error_t rc;
372 if (!gpgrt_check_version (REQUIRE_LIBGPGERROR_VERSION))
374 fprintf (stderr, _("gpgrt_check_version(): Incompatible libgpg-error. "
375 "Wanted %s, got %s.\n"), REQUIRE_LIBGPGERROR_VERSION,
376 gpgrt_check_version (NULL));
377 return GPG_ERR_UNKNOWN_VERSION;
380 gpgrt_init ();
381 gpgrt_set_alloc_func (xrealloc_gpgrt);
383 if (!assuan_check_version (REQUIRE_LIBASSUAN_VERSION))
385 fprintf (stderr, _("assuan_check_version(): Incompatible libassuan. "
386 "Wanted %s, got %s.\n"), REQUIRE_LIBASSUAN_VERSION,
387 assuan_check_version (NULL));
388 return GPG_ERR_UNKNOWN_VERSION;
391 if (!gcry_check_version (REQUIRE_LIBGCRYPT_VERSION))
393 fprintf (stderr, _("gcry_check_version(): Incompatible libgcrypt. "
394 "Wanted %s, got %s.\n"), REQUIRE_LIBGCRYPT_VERSION,
395 gcry_check_version (NULL));
396 return GPG_ERR_UNKNOWN_VERSION;
399 gcry_set_allocation_handler (xmalloc, xmalloc, NULL, xrealloc, xfree);
401 if (!gpgme_check_version (REQUIRE_LIBGPGME_VERSION))
403 fprintf (stderr, _("gpgme_check_version(): Incompatible libgpgme. "
404 "Wanted %s, got %s.\n"), REQUIRE_LIBGPGME_VERSION,
405 gpgme_check_version (NULL));
406 return GPG_ERR_UNKNOWN_VERSION;
409 rc = gpgme_engine_check_version (GPGME_PROTOCOL_OPENPGP);
410 if (rc)
412 fprintf (stderr, _("gpgme_engine_check_version(GPGME_PROTOCOL_OPENPGP): %s"), gpgme_strerror (rc));
413 return GPG_ERR_UNKNOWN_VERSION;
416 //gpgme_set_global_flag ("require-gnupg", REQUIRE_GNUPG_VERSION);
417 #ifdef ENABLE_NLS
418 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
419 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
420 #endif
422 #ifdef WITH_GNUTLS
423 if (gnutls_global_init ())
425 fprintf(stderr, _("gnutls_global_init() failed.\n"));
426 return GPG_ERR_UNKNOWN_VERSION;
429 if (!gnutls_check_version (REQUIRE_LIBGNUTLS_VERSION))
431 fprintf (stderr, _("gnutls_check_version(): Incompatible libgnutls. "
432 "Wanted %s, got %s.\n"), REQUIRE_LIBGNUTLS_VERSION,
433 gnutls_check_version (NULL));
434 return GPG_ERR_UNKNOWN_VERSION;
437 gnutls_global_set_log_function (tls_log);
438 gnutls_global_set_audit_log_function (tls_audit_log);
439 #endif
440 return 0;
443 static void
444 xml_error_cb (void *data, xmlErrorPtr e)
446 struct client_s *client = data;
449 * Keep the first reported error as the one to show in the error
450 * description. Reset in send_error().
452 if (client->xml_error)
453 return;
455 client->xml_error = xcalloc (1, sizeof(xmlError));
456 xmlCopyError (e, client->xml_error);
459 static pid_t
460 hook_waitpid (assuan_context_t ctx, pid_t pid, int action,
461 int *status, int options)
463 (void)ctx;
464 (void)action;
465 return waitpid (pid, status, options);
468 static ssize_t
469 hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
471 TEST_CANCEL ();
472 #ifdef WITH_GNUTLS
473 struct client_s *client = assuan_get_pointer (ctx);
475 if (client->thd->remote)
476 return tls_read_hook (ctx, (int) fd, data, len);
477 #else
478 (void)ctx;
479 #endif
480 return read ((int) fd, data, len);
483 static ssize_t
484 hook_write (assuan_context_t ctx, assuan_fd_t fd,
485 const void *data, size_t len)
487 TEST_CANCEL ();
488 #ifdef WITH_GNUTLS
489 struct client_s *client = assuan_get_pointer (ctx);
491 if (client->thd->remote)
492 return tls_write_hook (ctx, (int) fd, data, len);
493 #else
494 (void)ctx;
495 #endif
496 return write ((int) fd, data, len);
500 assuan_log_cb (assuan_context_t ctx, void *data, unsigned cat,
501 const char *msg)
503 struct client_s *client = data;
504 const char *str = NULL;
506 (void)client;
507 (void)ctx;
509 if (!(assuan_level & cat))
510 return 0;
512 if (!msg)
513 return 1;
515 switch (cat)
517 case ASSUAN_LOG_INIT:
518 str = "ASSUAN[INIT]";
519 break;
520 case ASSUAN_LOG_CTX:
521 str = "ASSUAN[CTX]";
522 break;
523 case ASSUAN_LOG_ENGINE:
524 str = "ASSUAN[ENGINE]";
525 break;
526 case ASSUAN_LOG_DATA:
527 str = "ASSUAN[DATA]";
528 break;
529 case ASSUAN_LOG_SYSIO:
530 str = "ASSUAN[SYSIO]";
531 break;
532 case ASSUAN_LOG_CONTROL:
533 str = "ASSUAN[CONTROL]";
534 break;
535 default:
536 str = "ASSUAN[UNKNOWN]";
537 break;
540 log_write ("%s: %s", str, msg);
541 return 1;
544 static int
545 new_connection (struct client_s *cl)
547 gpg_error_t rc;
548 static struct assuan_malloc_hooks mhooks = { xmalloc, xrealloc, xfree };
549 static struct assuan_system_hooks shooks = {
550 ASSUAN_SYSTEM_HOOKS_VERSION,
551 __assuan_usleep,
552 __assuan_pipe,
553 __assuan_close,
554 hook_read,
555 hook_write,
556 //FIXME
557 NULL, //recvmsg
558 NULL, //sendmsg both are used for FD passing
559 __assuan_spawn,
560 hook_waitpid,
561 __assuan_socketpair,
562 __assuan_socket,
563 __assuan_connect
566 #ifdef WITH_GNUTLS
567 if (cl->thd->remote)
569 char *prio = config_get_string ("global", "tls_cipher_suite");
571 cl->thd->timeout = config_get_integer ("global", "tls_timeout");
572 if (fcntl (cl->thd->fd, F_SETFL, O_NONBLOCK) == -1)
573 return 0;
575 cl->thd->tls = tls_init_client (cl->thd->fd, cl->thd->timeout, prio);
576 xfree (prio);
577 if (!cl->thd->tls)
578 return 0;
580 #endif
582 rc = assuan_new_ext (&cl->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks,
583 assuan_log_cb, cl);
584 if (rc)
585 goto fail;
587 assuan_ctx_set_system_hooks (cl->ctx, &shooks);
588 rc = assuan_init_socket_server (cl->ctx, cl->thd->fd,
589 ASSUAN_SOCKET_SERVER_ACCEPTED);
590 if (rc)
591 goto fail;
593 assuan_set_pointer (cl->ctx, cl);
594 assuan_set_hello_line (cl->ctx, PACKAGE_STRING PWMD_GIT_HASH);
595 rc = register_commands (cl->ctx);
596 if (rc)
597 goto fail;
599 rc = assuan_accept (cl->ctx);
600 if (rc)
601 goto fail;
603 rc = validate_peer (cl);
604 /* May not be implemented on all platforms. */
605 if (rc && gpg_err_code (rc) != GPG_ERR_ASS_GENERAL)
606 goto fail;
608 MUTEX_LOCK (&cn_mutex);
609 cl->thd->state = CLIENT_STATE_INIT;
610 MUTEX_UNLOCK (&cn_mutex);
611 cl->lock_timeout = config_get_integer ("global", "lock_timeout");
612 xmlSetStructuredErrorFunc (cl, xml_error_cb);
613 return 1;
615 fail:
616 log_write ("%s", pwmd_strerror (rc));
617 return 0;
621 * This is called after a client is cancelled or disconnects. Set with
622 * pthread_cleanup_push().
624 static void
625 free_client_cb (void *arg)
627 struct client_thread_s *cn = arg;
628 struct client_s *cl = cn->cl;
629 char *tmp = NULL;
631 #ifndef HAVE_PTHREAD_CANCEL
632 tmp = pthread_getspecific (signal_thread_key);
633 xfree (tmp);
634 pthread_setspecific (signal_thread_key, NULL);
635 #endif
637 MUTEX_LOCK (&cn_mutex);
638 cn_thread_list = slist_remove (cn_thread_list, cn);
639 MUTEX_UNLOCK (&cn_mutex);
641 if (cl)
643 unlock_flock (&cl->flock_fd);
644 reset_client (cl);
645 if (cl->xml_error)
646 xmlResetError (cl->xml_error);
648 xfree (cl->xml_error);
650 #ifdef WITH_GNUTLS
651 if (cn->tls)
653 gnutls_deinit (cn->tls->ses);
654 xfree (cn->tls->fp);
655 xfree (cn->tls);
657 #endif
659 if (cl->ctx)
660 assuan_release (cl->ctx);
661 else if (cl->thd && cl->thd->fd != -1)
662 close (cl->thd->fd);
664 if (cl->crypto)
665 crypto_free (cl->crypto);
667 cl->crypto = NULL;
668 xfree (cl);
670 else
672 if (cn->fd != -1)
673 close (cn->fd);
676 while (cn->msg_queue)
678 struct status_msg_s *msg = cn->msg_queue;
680 cn->msg_queue = msg->next;
681 xfree (msg->line);
682 xfree (msg);
685 if (cn->status_msg_pipe[0] != -1)
686 close (cn->status_msg_pipe[0]);
688 if (cn->status_msg_pipe[1] != -1)
689 close (cn->status_msg_pipe[1]);
691 pthread_mutex_destroy (&cn->status_mutex);
692 log_write (_("exiting, fd=%i"), cn->fd);
693 send_status_all (STATUS_CLIENTS, NULL);
695 xfree (cn->name);
696 #ifdef WITH_GNUTLS
697 xfree (cn->peeraddr);
698 #endif
700 if (cn->eof) // Not pthread_exit() or pthread_cancel().
702 tmp = pthread_getspecific (thread_name_key);
703 xfree (tmp);
704 pthread_setspecific (thread_name_key, NULL);
707 (void)cache_kill_scd ();
708 xfree (cn);
711 static void
712 free_all_clients ()
714 MUTEX_LOCK (&cn_mutex);
715 pthread_cleanup_push (release_mutex_cb, &cn_mutex);
717 while (slist_length (cn_thread_list))
719 struct client_thread_s *thd = slist_nth_data (cn_thread_list, 0);
721 free_client_cb (thd);
722 thd->eof = 1;
725 pthread_cleanup_pop (1);
728 static gpg_error_t
729 send_msg_queue (struct client_thread_s *thd)
731 MUTEX_LOCK (&thd->status_mutex);
732 gpg_error_t rc = 0;
733 char c;
734 ssize_t ret;
736 ret = read (thd->status_msg_pipe[0], &c, 1);
737 rc = gpg_error_from_syserror ();
738 if (ret == -1 && gpg_err_code (rc) != GPG_ERR_EAGAIN)
739 log_write ("%s (%i): %s", __FUNCTION__, __LINE__, pwmd_strerror (rc));
740 else
741 rc = 0;
743 thd->wrote_status = 0;
745 while (thd->msg_queue)
747 struct status_msg_s *msg = thd->msg_queue;
749 thd->msg_queue = thd->msg_queue->next;
750 MUTEX_UNLOCK (&thd->status_mutex);
751 pthread_cleanup_push (xfree, msg);
752 pthread_cleanup_push (xfree, msg->line);
753 rc = send_status (thd->cl->ctx, msg->s, msg->line);
754 pthread_cleanup_pop (1);
755 pthread_cleanup_pop (1);
756 MUTEX_LOCK (&thd->status_mutex);
757 if (rc)
758 break;
761 MUTEX_UNLOCK (&thd->status_mutex);
762 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
763 log_write ("%s (%i): %s", __FUNCTION__, __LINE__, pwmd_strerror (rc));
765 return rc;
768 static void *
769 client_thread (void *data)
771 struct client_thread_s *thd = data;
772 struct client_s *cl = xcalloc (1, sizeof (struct client_s));
773 struct slist_s *list;
774 gpg_error_t rc = 0;
775 #ifndef HAVE_PTHREAD_CANCEL
776 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
777 #endif
779 #ifdef HAVE_PR_SET_NAME
780 prctl (PR_SET_NAME, "client");
781 #endif
782 pthread_setspecific (thread_name_key, str_dup (__FUNCTION__));
784 if (!cl)
786 log_write ("%s(%i): %s", __FILE__, __LINE__,
787 pwmd_strerror (GPG_ERR_ENOMEM));
788 return NULL;
791 MUTEX_LOCK (&cn_mutex);
792 pthread_cleanup_push (free_client_cb, thd);
793 thd->cl = cl;
794 cl->thd = thd;
795 cl->flock_fd = -1;
797 list = slist_append (cn_thread_list, thd);
798 if (list)
799 cn_thread_list = list;
800 else
802 log_write ("%s(%i): %s", __FILE__, __LINE__,
803 pwmd_strerror (GPG_ERR_ENOMEM));
804 MUTEX_UNLOCK (&cn_mutex);
805 return NULL;
808 if (fcntl (thd->status_msg_pipe[0], F_SETFL, O_NONBLOCK) == -1)
809 rc = gpg_error_from_errno (errno);
811 if (!rc)
812 if (fcntl (thd->status_msg_pipe[1], F_SETFL, O_NONBLOCK) == -1)
813 rc = gpg_error_from_errno (errno);
815 MUTEX_UNLOCK (&cn_mutex);
817 if (rc)
819 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
820 goto done;
823 if (new_connection (cl))
825 struct pollfd fds[2];
827 fds[0].fd = thd->fd;
828 fds[0].events = POLLIN;
829 fds[1].fd = thd->status_msg_pipe[0];
830 fds[1].events = POLLIN;
832 send_status_all (STATUS_CLIENTS, NULL);
833 rc = send_status (cl->ctx, STATUS_CACHE, NULL);
834 if (rc)
836 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
837 goto done;
840 for (;;)
842 int n;
843 int eof;
845 n = poll (fds, sizeof(fds)/sizeof(fds[0]), 100);
846 if (n == -1)
848 log_write ("%s", strerror (errno));
849 break;
852 #ifdef WITH_GNUTLS
853 if (thd->remote && thd->tls && thd->tls->rehandshake)
855 char *prio;
856 int ret;
857 const char *e;
859 if (thd->tls->rehandshake == 1)
861 prio = config_get_string ("global", "tls_cipher_suite");
862 if (!prio)
864 thd->tls->rehandshake = 0;
865 continue;
868 ret = gnutls_priority_set_direct (thd->tls->ses, prio, &e);
869 if (ret == GNUTLS_E_SUCCESS)
871 rc = send_status (cl->ctx, STATUS_REHANDSHAKE, NULL);
872 if (!rc)
874 rc = assuan_send_data (cl->ctx, NULL, 0);
875 if (!rc)
877 ret = gnutls_rehandshake (thd->tls->ses);
878 if (ret)
880 log_write ("%s", gnutls_strerror (ret));
881 thd->tls->rehandshake = 0;
883 else
884 thd->tls->rehandshake = 2;
888 if (rc)
889 log_write ("%s", pwmd_strerror (rc));
891 else
892 log_write ("%s: %s", gnutls_strerror (ret), e);
894 xfree (prio);
895 continue;
898 #endif
900 if (!n)
901 continue;
903 if (fds[1].revents & POLLIN)
905 #ifdef WITH_GNUTLS
906 if (!thd->remote || (thd->tls && !thd->tls->rehandshake))
907 #endif
909 rc = send_msg_queue (thd);
910 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
911 break;
915 #ifdef HAVE_PTHREAD_CANCEL
916 if (!(fds[0].revents & POLLIN))
917 #else
918 if (thd->fd != -1 && !(fds[0].revents & POLLIN))
919 #endif
920 continue;
922 rc = assuan_process_next (cl->ctx, &eof);
923 if (rc || eof)
925 if (gpg_err_code (rc) == GPG_ERR_EOF || eof)
926 break;
928 log_write ("assuan_process_next(): rc=%u %s", rc,
929 pwmd_strerror (rc));
930 if (rc == gpg_error (GPG_ERR_ETIMEDOUT))
931 break;
933 rc = send_error (cl->ctx, rc);
934 if (rc)
936 log_write ("assuan_process_done(): rc=%u %s", rc,
937 pwmd_strerror (rc));
938 break;
942 /* Since the msg queue pipe fd's are non-blocking, check for
943 * pending status msgs here. GPG_ERR_EPIPE can be seen when the
944 * client has already disconnected and will be converted to
945 * GPG_ERR_EOF during assuan_process_next().
947 #ifdef WITH_GNUTLS
948 if (!thd->remote || (thd->tls && !thd->tls->rehandshake))
949 #endif
951 rc = send_msg_queue (thd);
952 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
953 break;
958 done:
959 /* Don't do pthread_exit() here because any set pthread_cleanup_push
960 * functions would be called after a command failed but then the client
961 * exited normally which may lead to a double free. */
962 thd->eof = 1;
963 pthread_cleanup_pop (1);
964 return NULL;
967 static gpg_error_t
968 xml_import (const char *filename, const char *outfile, char **keyid,
969 char *sign_keyid, char *keyfile, const char *userid,
970 const char *algo, long expire, int no_passphrase, int symmetric)
972 xmlDocPtr doc;
973 int fd;
974 struct stat st;
975 int len;
976 xmlChar *xmlbuf = NULL;
977 gpg_error_t rc = 0;
978 struct crypto_s *crypto = NULL;
980 if (strcmp (filename, "-"))
982 rc = open_check_file (filename, &fd, &st, 0);
983 if (rc)
984 return rc;
986 xmlbuf = xmalloc (st.st_size + 1);
987 if (!xmlbuf)
989 close (fd);
990 return GPG_ERR_ENOMEM;
993 if (read (fd, xmlbuf, st.st_size) == -1)
995 rc = gpg_error_from_errno (errno);
996 close (fd);
997 xfree (xmlbuf);
998 return rc;
1001 xmlbuf[st.st_size] = 0;
1002 close (fd);
1004 else
1006 #define BUFSIZE 8196
1007 size_t size = 0, xlen = 0;
1009 for (;;)
1011 size_t ret;
1012 xmlChar *tmp;
1014 tmp = xrealloc (xmlbuf, size+BUFSIZE+1);
1015 if (!tmp)
1017 xfree (xmlbuf);
1018 return GPG_ERR_ENOMEM;
1021 xmlbuf = tmp;
1022 size += BUFSIZE;
1023 ret = read (STDIN_FILENO, &xmlbuf[xlen], BUFSIZE);
1024 if (ret == -1)
1026 rc = gpg_error_from_syserror ();
1027 xfree (xmlbuf);
1028 return rc;
1031 xlen += ret;
1032 if (!ret || ret < BUFSIZE)
1033 break;
1036 xmlbuf[xlen] = 0;
1039 doc = xmlReadDoc (xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS);
1040 xfree (xmlbuf);
1041 if (!doc)
1042 return GPG_ERR_BAD_DATA;
1044 xmlNodePtr n = xmlDocGetRootElement (doc);
1045 if (n && !xmlStrEqual (n->name, (xmlChar *) "pwmd"))
1046 rc = GPG_ERR_BAD_DATA;
1048 if (!rc)
1050 rc = xml_validate_import (NULL, n ? n->children : n);
1051 if (!rc)
1053 rc = crypto_init (&crypto, NULL, filename, keyfile != NULL, keyfile);
1054 if (!rc)
1056 if (keyfile)
1058 crypto->flags |= CRYPTO_FLAG_KEYFILE;
1059 crypto->keyfile = str_dup (keyfile);
1062 xmlDocDumpMemory (doc, &crypto->plaintext, &len);
1063 if (len > 0)
1064 crypto->plaintext_size = len;
1065 else
1066 rc = GPG_ERR_ENOMEM;
1071 if (!rc)
1073 if (!symmetric && !keyid)
1075 crypto->save.userid = str_dup (userid);
1076 crypto->save.algo = algo ? str_dup (algo) : NULL;
1077 crypto->save.expire = expire;
1078 if (no_passphrase)
1079 crypto->save.flags |= GPGME_CREATE_NOPASSWD;
1081 rc = crypto_genkey (NULL, crypto);
1083 else
1085 if (keyid)
1086 crypto->save.pubkey = strv_dup (keyid);
1088 if (sign_keyid)
1089 crypto->save.sigkey = str_dup (sign_keyid);
1092 if (!rc)
1094 crypto->flags |= symmetric ? CRYPTO_FLAG_SYMMETRIC : 0;
1095 rc = crypto_encrypt (NULL, crypto);
1099 if (!rc)
1101 if (!strcmp (outfile, "-"))
1102 outfile = NULL;
1104 xfree (crypto->plaintext);
1105 crypto->plaintext = NULL;
1106 xfree (crypto->filename);
1107 crypto->filename = outfile ? str_dup (outfile) : NULL;
1108 rc = crypto_write_file (crypto, NULL, NULL);
1111 xmlFreeDoc (doc);
1112 crypto_free (crypto);
1113 return rc;
1116 static gpg_error_t
1117 do_cache_push (struct crypto_s *crypto)
1119 gpg_error_t rc;
1120 xmlDocPtr doc;
1121 struct cache_data_s *cdata;
1122 unsigned char *crc;
1123 size_t len;
1124 int fd = -1;
1126 log_write (_("Adding '%s' to the cache..."),
1127 crypto->filename);
1129 if (valid_filename (crypto->filename) == 0)
1131 log_write (_("%s: Invalid characters in filename"), crypto->filename);
1132 return GPG_ERR_INV_VALUE;
1135 rc = lock_flock (NULL, crypto->filename, LOCK_SH, &fd);
1136 if (!rc)
1137 rc = crypto_decrypt (NULL, crypto);
1138 if (rc)
1140 unlock_flock (&fd);
1141 return rc;
1144 rc = xml_parse_doc ((char *) crypto->plaintext, crypto->plaintext_size, &doc);
1145 if (rc)
1147 unlock_flock (&fd);
1148 log_write ("%s", pwmd_strerror (rc));
1149 return rc;
1152 cdata = xcalloc (1, sizeof (struct cache_data_s));
1153 if (!cdata)
1155 unlock_flock (&fd);
1156 xmlFreeDoc (doc);
1157 return GPG_ERR_ENOMEM;
1160 rc = get_checksum (crypto->filename, &crc, &len);
1161 unlock_flock (&fd);
1162 if (rc)
1164 xmlFreeDoc (doc);
1165 cache_free_data_once (cdata);
1166 return rc;
1169 cdata->crc = crc;
1170 rc = cache_encrypt (crypto);
1171 if (!rc)
1173 cdata->doc = crypto->plaintext;
1174 cdata->size = crypto->plaintext_size;
1175 crypto->plaintext = NULL;
1176 cdata->pubkey = crypto->pubkey;
1177 cdata->sigkey = crypto->sigkey;
1178 crypto->pubkey = NULL;
1179 crypto->sigkey = NULL;
1181 else
1183 xmlFreeDoc (doc);
1184 cache_free_data_once (cdata);
1185 return rc;
1188 long timeout = config_get_long (crypto->filename, "cache_timeout");
1189 rc = cache_add_file (crypto->filename, cdata, timeout);
1190 return rc;
1193 static gpg_error_t
1194 init_client (int fd, const char *addr)
1196 gpg_error_t rc = 0;
1197 struct client_thread_s *new = xcalloc (1, sizeof (struct client_thread_s));
1199 if (!new)
1201 close (fd);
1202 log_write ("%s: %s", __FUNCTION__, pwmd_strerror (ENOMEM));
1203 return GPG_ERR_ENOMEM;
1206 MUTEX_LOCK (&cn_mutex);
1207 pthread_cleanup_push (release_mutex_cb, &cn_mutex);
1208 new->conntime = time (NULL);
1210 if (pipe (new->status_msg_pipe) == -1)
1211 rc = gpg_error_from_errno (errno);
1212 else
1213 pthread_mutex_init (&new->status_mutex, NULL);
1215 if (!rc)
1217 #ifdef WITH_GNUTLS
1218 new->remote = addr ? 1 : 0;
1219 if (addr)
1220 new->peeraddr = str_dup (addr);
1221 #endif
1222 new->fd = fd;
1223 rc = create_thread (client_thread, new, &new->tid, 1);
1224 if (rc)
1226 close (new->status_msg_pipe[0]);
1227 close (new->status_msg_pipe[1]);
1228 pthread_mutex_destroy (&new->status_mutex);
1232 if (!rc)
1234 if (addr)
1235 log_write (_("new connection: tid=%p, fd=%i, addr=%s"),
1236 (pthread_t *) new->tid, fd, addr);
1237 else
1238 log_write (_("new connection: tid=%p, fd=%i"),
1239 (pthread_t *) new->tid, fd);
1242 pthread_cleanup_pop (1);
1244 if (rc)
1246 xfree (new);
1247 close (fd);
1248 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
1250 return rc;
1253 #ifdef WITH_GNUTLS
1254 static gpg_error_t
1255 do_tls_accept (struct pollfd *fds)
1257 struct sockaddr_storage raddr;
1258 socklen_t slen = sizeof (raddr);
1259 int fd;
1260 char s[INET6_ADDRSTRLEN];
1262 if (!(fds->revents & POLLIN))
1263 return 0;
1265 memset (&raddr, 0, sizeof (raddr));
1266 fd = accept (fds->fd, (struct sockaddr *) &raddr, &slen);
1267 if (fd == -1)
1269 int e = errno;
1271 if (errno != EAGAIN && !quit)
1272 log_write ("%s: %s", __FUNCTION__,
1273 pwmd_strerror (gpg_error_from_syserror()));
1275 return gpg_error_from_errno (e);
1278 inet_ntop (raddr.ss_family, get_in_addr ((struct sockaddr *) &raddr), s,
1279 sizeof s);
1280 (void) init_client (fd, s);
1281 return 0;
1283 #endif
1285 static void *
1286 accept_thread (void *arg)
1288 int sockfd = *(int *) arg;
1289 #ifndef HAVE_PTHREAD_CANCEL
1290 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
1291 #endif
1293 #ifdef HAVE_PR_SET_NAME
1294 prctl (PR_SET_NAME, "accept");
1295 #endif
1296 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
1298 for (;;)
1300 socklen_t slen = sizeof (struct sockaddr_un);
1301 struct sockaddr_un raddr;
1302 int fd, s = 0;
1303 struct pollfd fds[3];
1305 TEST_CANCEL ();
1306 memset (fds, 0, sizeof (fds));
1307 fds[s].fd = sockfd;
1308 fds[s++].events = POLLIN;
1310 #ifdef WITH_GNUTLS
1311 if (tls_fd != -1)
1313 fds[s].fd = tls_fd;
1314 fds[s++].events = POLLIN;
1316 else
1317 fds[s].fd = tls_fd;
1319 if (tls6_fd != -1)
1321 fds[s].fd = tls6_fd;
1322 fds[s++].events = POLLIN;
1324 else
1325 fds[s].fd = tls6_fd;
1326 #endif
1328 s = poll (fds, s, 500);
1329 if (s == -1)
1331 if (errno != EINTR)
1332 log_write ("%s", strerror (errno));
1333 break;
1335 else if (s == 0)
1336 continue;
1338 if (fds[0].revents & POLLIN)
1340 fd = accept (sockfd, (struct sockaddr *) &raddr, &slen);
1341 if (fd == -1)
1343 if (errno == EMFILE || errno == ENFILE)
1344 log_write ("%s: %s", __FUNCTION__,
1345 pwmd_strerror (gpg_error_from_errno (errno)));
1346 else if (errno != EAGAIN && errno != EINTR)
1348 if (!quit) // probably EBADF
1349 log_write ("%s: %s", __FUNCTION__,
1350 pwmd_strerror (gpg_error_from_errno (errno)));
1352 break;
1355 continue;
1358 (void) init_client (fd, NULL);
1361 #ifdef WITH_GNUTLS
1362 if (tls_fd != -1 && fds[1].fd == tls_fd)
1363 (void)do_tls_accept (&fds[1]);
1365 if (tls6_fd != -1 && fds[1].fd == tls6_fd)
1366 (void)do_tls_accept (&fds[1]);
1368 if (tls6_fd != -1 && fds[2].fd == tls6_fd)
1369 (void)do_tls_accept (&fds[2]);
1370 #endif
1373 /* Just in case accept() failed for some reason other than EBADF */
1374 quit = 1;
1375 return NULL;
1378 static void *
1379 cache_timer_thread (void *arg)
1381 unsigned k = 0;
1382 #ifndef HAVE_PTHREAD_CANCEL
1383 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
1384 #endif
1386 (void)arg;
1388 #ifdef HAVE_PR_SET_NAME
1389 prctl (PR_SET_NAME, "timer");
1390 #endif
1391 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
1393 for (;;)
1395 struct timeval tv = { 1, 0 };
1396 unsigned keepalive = config_get_integer ("global", "keepalive_interval");
1398 TEST_CANCEL ();
1399 select (0, NULL, NULL, NULL, &tv);
1400 cache_adjust_timeout ();
1402 if (keepalive && ++k >= keepalive)
1404 send_status_all (STATUS_KEEPALIVE, NULL);
1405 k = 0;
1409 return NULL;
1412 static int
1413 signal_loop (sigset_t sigset)
1415 int done = 0;
1419 int sig;
1421 sigwait (&sigset, &sig);
1422 log_write (_("caught signal %i (%s)"), sig, strsignal (sig));
1424 switch (sig)
1426 case SIGHUP:
1427 pthread_cond_signal (&rcfile_cond);
1428 break;
1429 case SIGUSR1:
1430 log_write (_("clearing file cache"));
1431 cache_clear (NULL, NULL, 1, 0);
1432 send_status_all (STATUS_CACHE, NULL);
1433 break;
1434 default:
1435 done = 1;
1436 break;
1439 while (!done);
1441 return done;
1444 static void
1445 catchsig (int sig)
1447 log_write (_ ("Caught signal %i (%s). Exiting."), sig, strsignal (sig));
1448 #ifdef HAVE_BACKTRACE
1449 BACKTRACE (__FUNCTION__);
1450 #endif
1451 longjmp (jmp, 1);
1454 static void
1455 cancel_all_clients ()
1457 unsigned i, t;
1459 MUTEX_LOCK (&cn_mutex);
1460 t = slist_length (cn_thread_list);
1461 for (i = 0; i < t; i++)
1463 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
1465 #ifdef HAVE_PTHREAD_CANCEL
1466 pthread_cancel (thd->tid);
1467 #else
1468 pthread_kill (thd->tid, SIGUSR2);
1469 #endif
1472 while (slist_length (cn_thread_list))
1474 MUTEX_UNLOCK (&cn_mutex);
1475 usleep (50000);
1476 MUTEX_LOCK (&cn_mutex);
1479 MUTEX_UNLOCK (&cn_mutex);
1482 static int
1483 server_loop (int sockfd, char **socketpath)
1485 pthread_t cache_timeout_tid;
1486 pthread_t accept_tid;
1487 int cancel_timeout_thread = 0;
1488 int cancel_accept_thread = 0;
1489 int cancel_rcfile_thread = 0;
1490 sigset_t sigset;
1491 int n;
1492 int segv = 0;
1493 gpg_error_t rc;
1495 init_commands ();
1496 sigemptyset (&sigset);
1498 /* Termination */
1499 sigaddset (&sigset, SIGTERM);
1500 sigaddset (&sigset, SIGINT);
1502 /* Clears the file cache. */
1503 sigaddset (&sigset, SIGUSR1);
1505 /* Configuration file reloading. */
1506 sigaddset (&sigset, SIGHUP);
1508 #ifndef HAVE_PTHREAD_CANCEL
1510 The socket, cache and rcfile threads use this signal when
1511 pthread_cancel() is unavailable. Prevent the main thread from
1512 catching this signal from another process.
1514 sigaddset (&sigset, SIGUSR2);
1515 #endif
1517 /* An assertion failure. */
1518 signal (SIGABRT, catchsig);
1520 sigaddset (&sigset, SIGABRT);
1521 sigprocmask (SIG_BLOCK, &sigset, NULL);
1523 #ifndef HAVE_PTHREAD_CANCEL
1524 /* Remove this signal from the watched signals in signal_loop(). */
1525 sigdelset (&sigset, SIGUSR2);
1526 #endif
1528 /* Can show a backtrace of the stack in the log. */
1529 signal (SIGSEGV, catchsig);
1531 char *p = get_username (getuid());
1532 log_write (_("%s started for user %s"), PACKAGE_STRING PWMD_GIT_HASH, p);
1533 xfree (p);
1535 #ifdef WITH_GNUTLS
1536 if (config_get_boolean ("global", "enable_tcp"))
1537 log_write (_("Listening on %s and TCP port %i"), *socketpath,
1538 config_get_integer ("global", "tcp_port"));
1539 else
1540 log_write (_("Listening on %s"), *socketpath);
1541 #else
1542 log_write (_("Listening on %s"), *socketpath);
1543 #endif
1545 rc = create_thread (reload_rcfile_thread, NULL, &rcfile_tid, 0);
1546 if (rc)
1548 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1549 pwmd_strerror (rc));
1550 goto done;
1553 cancel_rcfile_thread = 1;
1554 rc = create_thread (cache_timer_thread, NULL, &cache_timeout_tid, 0);
1555 if (rc)
1557 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1558 pwmd_strerror (rc));
1559 goto done;
1562 cancel_timeout_thread = 1;
1563 rc = create_thread (accept_thread, &sockfd, &accept_tid, 0);
1564 if (rc)
1566 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1567 pwmd_strerror (rc));
1568 goto done;
1571 cancel_accept_thread = 1;
1572 if (!setjmp (jmp))
1573 signal_loop (sigset);
1574 else
1575 segv = 1;
1577 done:
1579 * We're out of the main server loop. This happens when a signal was sent
1580 * to terminate the daemon. Cancel all clients and exit.
1582 if (cancel_accept_thread)
1584 #ifdef HAVE_PTHREAD_CANCEL
1585 n = pthread_cancel (accept_tid);
1586 #else
1587 n = pthread_kill (accept_tid, SIGUSR2);
1588 #endif
1589 if (!n)
1590 pthread_join (accept_tid, NULL);
1593 if (cancel_timeout_thread)
1595 #ifdef HAVE_PTHREAD_CANCEL
1596 n = pthread_cancel (cache_timeout_tid);
1597 #else
1598 n = pthread_kill (cache_timeout_tid, SIGUSR2);
1599 #endif
1600 if (!n)
1601 pthread_join (cache_timeout_tid, NULL);
1604 #ifdef WITH_GNUTLS
1605 tls_start_stop (1);
1606 #endif
1607 shutdown (sockfd, SHUT_RDWR);
1608 close (sockfd);
1609 unlink (*socketpath);
1610 xfree (*socketpath);
1611 *socketpath = NULL;
1612 MUTEX_LOCK (&cn_mutex);
1613 n = slist_length (cn_thread_list);
1614 MUTEX_UNLOCK (&cn_mutex);
1616 if (n && !segv)
1617 cancel_all_clients ();
1618 else
1619 free_all_clients ();
1621 if (cancel_rcfile_thread)
1623 #ifdef HAVE_PTHREAD_CANCEL
1624 pthread_cancel (rcfile_tid);
1625 #else
1626 pthread_kill (rcfile_tid, SIGUSR2);
1627 pthread_cond_signal (&rcfile_cond);
1628 #endif
1629 pthread_join (rcfile_tid, NULL);
1632 cache_deinit ();
1633 deinit_commands ();
1634 return segv ? EXIT_FAILURE : EXIT_SUCCESS;
1637 static void
1638 usage (const char *pn, int status)
1640 FILE *fp = status == EXIT_FAILURE ? stderr : stdout;
1642 fprintf (fp, _("Usage: %s [OPTIONS] [file1] [...]\n"
1643 " --homedir alternate pwmd home directory (~/.pwmd)\n"
1644 " -f, --rcfile=filename load the specified configuration file\n"
1645 " (~/.pwmd/config)\n"
1646 " --kill terminate an existing instance of pwmd\n"
1647 " -n, --no-fork run as a foreground process\n"
1648 " --disable-dump disable the LIST, XPATH and DUMP commands\n"
1649 " --ignore, --force ignore cache pushing errors during startup\n"
1650 " -I, --import=filename import a pwmd DTD formatted XML file)\n"
1651 " -k, --passphrase-file=file for use when importing\n"
1652 " -o, --outfile=filename output file when importing\n"
1653 " --keyid=fpr[,..] public key to use when encrypting\n"
1654 " --sign-keyid=fpr fingerprint of the signing key to use\n"
1655 " -s, --symmetric use conventional encryption with optional signer\n"
1656 " --userid=string name and email address to use when importing\n"
1657 " --algo=string algorithm to use when importing (engine default)\n"
1658 " --expire=seconds key expiry time when importing (3 years)\n"
1659 " --no-passphrase don't require a passphrase when importing\n"
1660 " --debug=[a:..][,g:N][,t:N] enable debugging (a:[ixedsc],g:[1-9],t:[0-N])\n"
1661 " --help this help text\n"
1662 " --version show version and compile time features\n"),
1663 pn);
1664 exit (status);
1667 static void
1668 unlink_stale_socket (const char *sock, const char *pidfile)
1670 log_write (_ ("removing stale socket %s"), sock);
1671 unlink (sock);
1672 unlink (pidfile);
1675 static int
1676 test_pidfile (const char *path, const char *sock, char *buf, size_t buflen,
1677 char **pidfile, int create, mode_t mode, int terminate)
1679 pid_t pid;
1680 int fd;
1681 size_t len;
1683 if (!create)
1685 snprintf (buf, buflen, "%s/%s.pid", homedir, sock);
1686 *pidfile = str_dup (buf);
1687 fd = open (buf, O_RDONLY);
1689 else
1690 fd = open (*pidfile, O_CREAT|O_WRONLY|O_TRUNC, mode);
1692 if (fd == -1)
1694 if (!create && errno != ENOENT)
1696 log_write ("%s: %s", buf, pwmd_strerror (errno));
1697 xfree (*pidfile);
1698 *pidfile = NULL;
1699 return -1;
1701 else if (!create && !terminate)
1702 return 0;
1704 log_write ("%s: %s", *pidfile, strerror (errno));
1705 return -1;
1708 if (create)
1710 snprintf (buf, buflen, "%i", getpid ());
1711 ssize_t ret = write (fd, buf, strlen (buf));
1712 if (ret == -1)
1713 log_write ("%s (%i): %s", __FUNCTION__, __LINE__,
1714 pwmd_strerror (gpg_error_from_syserror ()));
1715 close (fd);
1716 return 0;
1719 if (buflen < 8)
1721 close (fd);
1722 log_write ("%s (%i): %s", __FUNCTION__, __LINE__,
1723 pwmd_strerror (GPG_ERR_BUFFER_TOO_SHORT));
1724 return -1;
1727 len = read (fd, buf, buflen);
1728 close (fd);
1729 if (len == 0)
1731 unlink_stale_socket (path, *pidfile);
1732 return 0;
1735 if (sscanf (buf, "%li", &pid) != 1 || pid == 0)
1737 if (!terminate)
1739 unlink_stale_socket (path, *pidfile);
1740 return 0;
1744 if (kill (pid, 0) == -1)
1746 unlink_stale_socket (path, *pidfile);
1747 return 0;
1750 if (terminate)
1752 if (kill (pid, SIGTERM) == -1)
1753 log_write ("%s: %s", path, pwmd_strerror (errno));
1755 else
1756 log_write (_ ("an instance for socket %s is already running"), path);
1758 xfree (*pidfile);
1759 *pidfile = NULL;
1760 return 1;
1763 static unsigned
1764 parse_debug_level (const char *str, unsigned *debug, int *gpgme, int *tls)
1766 const char *p;
1767 unsigned level = 0;
1768 int gl = 0, tl = 0;
1770 for (p = str; p && *p; p++)
1772 if (*p == 'a') // assuan debug flags
1774 if (*++p != ':')
1775 return 1;
1777 while (*++p)
1779 switch (*p)
1781 case 'i':
1782 level |= ASSUAN_LOG_INIT;
1783 break;
1784 case 'x':
1785 level |= ASSUAN_LOG_CTX;
1786 break;
1787 case 'e':
1788 level |= ASSUAN_LOG_ENGINE;
1789 break;
1790 case 'd':
1791 level |= ASSUAN_LOG_DATA;
1792 break;
1793 case 's':
1794 level |= ASSUAN_LOG_SYSIO;
1795 break;
1796 case 'c':
1797 level |= ASSUAN_LOG_CONTROL;
1798 break;
1799 case ',':
1800 break;
1801 default:
1802 return 1;
1805 if (*p == ',')
1806 break;
1809 if (!*p)
1810 break;
1812 else if (*p == 'g' || *p == 't') // gpgme and TLS debug level
1814 int t = *p == 't';
1815 int n;
1817 if (*++p != ':')
1818 return 1;
1820 if (!isdigit (*++p))
1821 return 1;
1823 n = atoi (p);
1824 if (t)
1825 tl = n;
1826 else
1827 gl = n;
1829 if (tl < 0 || gl < 0 || gl > 9)
1830 return 1;
1832 while (isdigit (*p))
1833 p++;
1835 p--;
1836 if (*(p+1) && *(p+1) != ',')
1837 return 1;
1838 else if (*(p+1))
1839 p++;
1841 else
1842 return 1;
1845 if (tl)
1846 *tls = tl;
1848 if (gl)
1849 *gpgme = gl;
1851 *debug = level;
1852 return 0;
1856 main (int argc, char *argv[])
1858 int opt;
1859 struct sockaddr_un addr;
1860 char buf[PATH_MAX];
1861 char *socketpath = NULL, *socketdir, *socketname = NULL;
1862 char *socketarg = NULL;
1863 char *datadir = NULL;
1864 char *pidfile = NULL;
1865 mode_t mode = 0600;
1866 int x;
1867 char *p;
1868 char **cache_push = NULL;
1869 char *import = NULL, *keyid = NULL, *sign_keyid = NULL;
1870 char *userid = NULL;
1871 char *algo = NULL;
1872 long expire = 0;
1873 int no_passphrase = 0;
1874 int estatus = EXIT_FAILURE;
1875 int sockfd;
1876 char *outfile = NULL;
1877 int do_unlink = 0;
1878 int secure = 0;
1879 int show_version = 0;
1880 int force = 0;
1881 gpg_error_t rc;
1882 char *keyfile = NULL;
1883 int exists;
1884 int optindex;
1885 int terminate = 0;
1886 int sym = 0;
1887 int gpgme_level = -1;
1888 int tls_level = -1;
1889 int backlog = 0;
1890 /* Must maintain the same order as longopts[] */
1891 enum
1893 OPT_VERSION, OPT_HELP, OPT_HOMEDIR, OPT_NO_FORK, OPT_DISABLE_DUMP,
1894 OPT_FORCE, OPT_RCFILE, OPT_PASSPHRASE_FILE, OPT_IMPORT, OPT_OUTFILE,
1895 OPT_KEYID, OPT_SIGN_KEYID, OPT_SYMMETRIC, OPT_USERID, OPT_ALGO, OPT_EXPIRE,
1896 OPT_NOPASSPHRASE, OPT_KILL, OPT_DEBUG
1898 const char *optstring = "nf:C:k:I:o:s";
1899 const struct option longopts[] = {
1900 {"version", no_argument, 0, 0},
1901 {"help", no_argument, 0, 0},
1902 {"homedir", required_argument, 0, 0},
1903 {"no-fork", no_argument, 0, 'n'},
1904 {"disable_dump", no_argument, 0, 0},
1905 {"force", no_argument, 0, 0},
1906 {"rcfile", required_argument, 0, 'f'},
1907 {"passphrase-file", required_argument, 0, 'k'},
1908 {"import", required_argument, 0, 'I'},
1909 {"outfile", required_argument, 0, 'o'},
1910 {"keyid", required_argument, 0, 0},
1911 {"sign-keyid", required_argument, 0, 0},
1912 {"symmetric", no_argument, 0, 's'},
1913 {"userid", required_argument, 0, 0},
1914 {"algo", required_argument, 0, 0},
1915 {"expire", required_argument, 0, 0},
1916 {"no-passphrase", no_argument, 0, 0},
1917 {"kill", no_argument, 0, 0},
1918 {"debug", required_argument, 0, 0},
1919 {0, 0, 0, 0}
1922 log_fd = -1;
1923 cmdline = 1;
1924 expire = time (NULL) + DEFAULT_EXPIRE;
1926 #ifndef DEBUG
1927 #ifdef HAVE_SETRLIMIT
1928 struct rlimit rl;
1930 rl.rlim_cur = rl.rlim_max = 0;
1932 if (setrlimit (RLIMIT_CORE, &rl) != 0)
1933 err (EXIT_FAILURE, "setrlimit()");
1934 #endif
1936 #ifdef HAVE_PR_SET_DUMPABLE
1937 prctl (PR_SET_DUMPABLE, 0);
1938 #endif
1939 #endif
1941 #ifdef ENABLE_NLS
1942 setlocale (LC_ALL, "");
1943 bindtextdomain ("pwmd", LOCALEDIR);
1944 textdomain ("pwmd");
1945 #endif
1947 while ((opt = getopt_long (argc, argv, optstring, longopts, &optindex))
1948 != -1)
1950 switch (opt)
1952 case 'I':
1953 import = optarg;
1954 break;
1955 case 'k':
1956 keyfile = optarg;
1957 break;
1958 case 'o':
1959 outfile = optarg;
1960 break;
1961 case 'n':
1962 nofork = 1;
1963 break;
1964 case 'f':
1965 rcfile = str_dup (optarg);
1966 break;
1967 case 's':
1968 sym = 1;
1969 break;
1970 default:
1971 usage (argv[0], EXIT_FAILURE);
1972 break;
1973 case 0:
1974 switch (optindex)
1976 case OPT_DEBUG:
1977 if (parse_debug_level (optarg, &assuan_level, &gpgme_level,
1978 &tls_level))
1979 usage (argv[0], EXIT_FAILURE);
1980 break;
1981 case OPT_SYMMETRIC:
1982 sym = 1;
1983 break;
1984 case OPT_VERSION:
1985 show_version = 1;
1986 break;
1987 case OPT_HELP:
1988 usage (argv[0], EXIT_SUCCESS);
1989 break;
1990 case OPT_HOMEDIR:
1991 homedir = str_dup (optarg);
1992 break;
1993 case OPT_NO_FORK:
1994 nofork = 1;
1995 break;
1996 case OPT_DISABLE_DUMP:
1997 secure = 1;
1998 break;
1999 case OPT_FORCE:
2000 force = 1;
2001 break;
2002 case OPT_RCFILE:
2003 rcfile = str_dup (optarg);
2004 break;
2005 case OPT_PASSPHRASE_FILE:
2006 keyfile = optarg;
2007 break;
2008 case OPT_IMPORT:
2009 import = optarg;
2010 break;
2011 case OPT_OUTFILE:
2012 outfile = optarg;
2013 break;
2014 case OPT_KEYID:
2015 keyid = optarg;
2016 break;
2017 case OPT_SIGN_KEYID:
2018 sign_keyid = optarg;
2019 break;
2020 case OPT_USERID:
2021 userid = optarg;
2022 break;
2023 case OPT_ALGO:
2024 algo = optarg;
2025 break;
2026 case OPT_EXPIRE:
2027 errno = rc = 0;
2028 expire = strtoul (optarg, &p, 10);
2030 if (!errno && p && *p)
2031 rc = GPG_ERR_INV_VALUE;
2032 else if (expire == ULONG_MAX)
2033 rc = GPG_ERR_INV_VALUE;
2034 else if (errno)
2035 rc = gpg_error_from_syserror ();
2037 if (rc)
2038 usage (argv[0], EXIT_FAILURE);
2039 break;
2040 case OPT_NOPASSPHRASE:
2041 no_passphrase = 1;
2042 break;
2043 case OPT_KILL:
2044 terminate = 1;
2045 break;
2046 default:
2047 usage (argv[0], EXIT_FAILURE);
2052 if (show_version)
2054 printf (_("%s\n\n"
2055 "Copyright (C) 2006-2020\n"
2056 "%s\n"
2057 "Released under the terms of the GPL v2.\n\n"
2058 "Compile time features:\n%s"), PACKAGE_STRING PWMD_GIT_HASH,
2059 PACKAGE_BUGREPORT,
2060 #ifdef PWMD_HOMEDIR
2061 "+PWMD_HOMEDIR=" PWMD_HOMEDIR "\n"
2062 #endif
2063 #ifdef WITH_GNUTLS
2064 "+WITH_GNUTLS\n"
2065 #else
2066 "-WITH_GNUTLS\n"
2067 #endif
2068 #ifdef WITH_LIBACL
2069 "+WITH_LIBACL\n"
2070 #else
2071 "-WITH_LIBACL\n"
2072 #endif
2073 #ifdef DEBUG
2074 "+DEBUG\n"
2075 #else
2076 "-DEBUG\n"
2077 #endif
2078 #ifdef MEM_DEBUG
2079 "+MEM_DEBUG\n"
2080 #else
2081 "-MEM_DEBUG\n"
2082 #endif
2083 #ifdef MUTEX_DEBUG
2084 "+MUTEX_DEBUG\n"
2085 #else
2086 "-MUTEX_DEBUG\n"
2087 #endif
2089 exit (EXIT_SUCCESS);
2092 if (gpgme_level != -1)
2094 char s[2] = { gpgme_level + '0', 0 };
2096 if (getenv ("GPGME_DEBUG"))
2097 log_write (_ ("Overriding GPGME_DEBUG environment with level %u!"),
2098 gpgme_level);
2100 gpgme_set_global_flag ("debug", s);
2103 if (setup_crypto ())
2104 exit (EXIT_FAILURE);
2106 #ifdef WITH_GNUTLS
2107 tls_level = tls_level == -1 ? 1 : tls_level;
2108 gnutls_global_set_log_level (tls_level);
2109 tls_fd = -1;
2110 tls6_fd = -1;
2111 #endif
2112 rc = xml_init ();
2113 if (rc)
2114 errx (EXIT_FAILURE, "%s", "xml_init() failed");
2116 if (!homedir)
2117 #ifdef PWMD_HOMEDIR
2118 homedir = str_dup(PWMD_HOMEDIR);
2119 #else
2120 homedir = str_asprintf ("%s/.pwmd", get_home_dir());
2121 #endif
2123 if (mkdir (homedir, 0700) == -1 && errno != EEXIST)
2124 err (EXIT_FAILURE, "%s", homedir);
2126 if (!rcfile)
2127 rcfile = str_asprintf ("%s/config", homedir);
2129 pthread_key_create (&last_error_key, free_key);
2130 #ifndef HAVE_PTHREAD_CANCEL
2131 pthread_key_create (&signal_thread_key, free_key);
2132 #endif
2134 pthread_mutexattr_t attr;
2135 pthread_mutexattr_init (&attr);
2136 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
2137 pthread_mutex_init (&rcfile_mutex, &attr);
2138 global_config = config_parse (rcfile, 0);
2139 if (!global_config)
2141 pthread_mutexattr_destroy (&attr);
2142 pthread_mutex_destroy (&rcfile_mutex);
2143 exit (EXIT_FAILURE);
2146 p = config_get_string ("global", "gpg_homedir");
2147 if (!p)
2148 datadir = str_asprintf ("%s/.gnupg", homedir);
2149 else
2150 datadir = expand_homedir (p);
2152 xfree (p);
2153 if (mkdir (datadir, 0700) == -1 && errno != EEXIST)
2154 err (EXIT_FAILURE, "%s", datadir);
2156 rc = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, NULL, datadir);
2157 if (rc)
2158 errx (EXIT_FAILURE, "%s: %s", datadir, pwmd_strerror (rc));
2159 xfree (datadir);
2161 snprintf (buf, sizeof (buf), "%s/data", homedir);
2162 if (mkdir (buf, 0700) == -1 && errno != EEXIST)
2163 err (EXIT_FAILURE, "%s", buf);
2165 datadir = str_dup (buf);
2166 pthread_cond_init (&rcfile_cond, NULL);
2167 pthread_mutex_init (&cn_mutex, &attr);
2168 pthread_mutexattr_destroy (&attr);
2170 setup_logging ();
2172 x = config_get_int_param (global_config, "global", "priority", &exists);
2173 if (exists && x != atoi(INVALID_PRIORITY))
2175 errno = 0;
2176 if (setpriority (PRIO_PROCESS, 0, x) == -1)
2178 log_write ("setpriority(): %s",
2179 pwmd_strerror (gpg_error_from_errno (errno)));
2180 goto do_exit;
2183 #ifdef HAVE_MLOCKALL
2184 if (disable_mlock == 0 && mlockall (MCL_CURRENT | MCL_FUTURE) == -1)
2186 log_write ("mlockall(): %s",
2187 pwmd_strerror (gpg_error_from_errno (errno)));
2188 goto do_exit;
2190 #endif
2192 rc = cache_init ();
2193 if (rc)
2195 log_write ("pwmd: ERR %i: %s", rc, pwmd_strerror (rc));
2196 exit (EXIT_FAILURE);
2199 if (import)
2201 char **keyids = NULL;
2203 if (!outfile || !*outfile || argc != optind)
2204 usage (argv[0], EXIT_FAILURE);
2206 if (keyid)
2207 keyids = str_split (keyid, ",", 0);
2208 else if (!userid && !sym)
2209 usage (argv[0], EXIT_FAILURE);
2211 rc = xml_import (import, outfile, keyids, sign_keyid, keyfile, userid,
2212 algo, expire, no_passphrase, sym);
2213 strv_free (keyids);
2214 if (rc)
2216 if (gpg_err_source (rc) == GPG_ERR_SOURCE_UNKNOWN)
2217 rc = gpg_error (rc);
2219 log_write ("%s: %u: %s", import, rc, pwmd_strerror (rc));
2222 config_free (global_config);
2223 xfree (rcfile);
2224 exit (rc ? EXIT_FAILURE : EXIT_SUCCESS);
2227 p = config_get_string ("global", "socket_path");
2228 if (!p)
2229 p = str_asprintf ("%s/socket", homedir);
2231 socketarg = expand_homedir (p);
2232 xfree (p);
2234 if (!secure)
2235 disable_list_and_dump = config_get_boolean ("global",
2236 "disable_list_and_dump");
2237 else
2238 disable_list_and_dump = secure;
2240 cache_push = config_get_list ("global", "cache_push");
2242 while (optind < argc)
2244 if (strv_printf (&cache_push, "%s", argv[optind++]) == 0)
2245 errx (EXIT_FAILURE, "%s", pwmd_strerror (GPG_ERR_ENOMEM));
2248 if (!strchr (socketarg, '/'))
2250 socketdir = getcwd (buf, sizeof (buf));
2251 socketname = str_dup (socketarg);
2252 socketpath = str_asprintf ("%s/%s", socketdir, socketname);
2254 else
2256 socketname = str_dup (strrchr (socketarg, '/')+1);
2257 socketarg[strlen (socketarg) - strlen (socketname) - 1] = 0;
2258 socketdir = str_dup (socketarg);
2259 socketpath = str_asprintf ("%s/%s", socketdir, socketname);
2262 if (chdir (datadir))
2264 log_write ("%s: %s", datadir,
2265 pwmd_strerror (gpg_error_from_errno (errno)));
2266 unlink (socketpath);
2267 goto do_exit;
2270 x = test_pidfile (socketpath, socketname, buf, sizeof(buf), &pidfile, 0,
2271 mode, terminate);
2272 if (!terminate && x)
2273 goto do_exit;
2274 else if (terminate)
2276 estatus = x != 1 ? EXIT_FAILURE : EXIT_SUCCESS;
2277 goto do_exit;
2281 * bind() doesn't like the full pathname of the socket or any non alphanum
2282 * characters so change to the directory where the socket is wanted then
2283 * create it then change to datadir.
2285 if (chdir (socketdir))
2287 log_write ("%s: %s", socketdir,
2288 pwmd_strerror (gpg_error_from_errno (errno)));
2289 goto do_exit;
2292 xfree (socketdir);
2294 if ((sockfd = socket (PF_UNIX, SOCK_STREAM, 0)) == -1)
2296 log_write ("socket(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2297 goto do_exit;
2300 addr.sun_family = AF_UNIX;
2301 snprintf (addr.sun_path, sizeof (addr.sun_path), "%s", socketname);
2302 do_unlink = 1;
2303 if (bind (sockfd, (struct sockaddr *) &addr, sizeof (struct sockaddr)) ==
2306 log_write ("bind(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2308 if (errno == EADDRINUSE)
2310 do_unlink = 0;
2311 log_write (_("Either there is another pwmd running or '%s' is a \n"
2312 "stale socket. Please remove it manually."), socketpath);
2315 goto do_exit;
2319 char *t = config_get_string ("global", "socket_perms");
2320 mode_t mask;
2322 if (t)
2324 mode = strtol (t, NULL, 8);
2325 mask = umask (0);
2326 xfree (t);
2328 if (chmod (socketname, mode) == -1)
2330 log_write ("%s: %s", socketname,
2331 pwmd_strerror (gpg_error_from_errno (errno)));
2332 close (sockfd);
2333 umask (mask);
2334 goto do_exit;
2337 umask (mask);
2341 if (chdir (datadir))
2343 log_write ("%s: %s", datadir,
2344 pwmd_strerror (gpg_error_from_errno (errno)));
2345 close (sockfd);
2346 goto do_exit;
2349 xfree (datadir);
2350 #ifdef WITH_GNUTLS
2351 if (config_get_boolean ("global", "enable_tcp"))
2353 if (!tls_start_stop (0))
2355 close (sockfd);
2356 goto do_exit;
2359 #endif
2362 * Set the cache entry for a file. Prompts for the password.
2364 if (cache_push)
2366 for (opt = 0; cache_push[opt]; opt++)
2368 struct crypto_s *crypto = NULL;
2369 char *pw_file = config_get_string (cache_push[opt],
2370 "passphrase_file");
2371 rc = crypto_init (&crypto, NULL, cache_push[opt], pw_file != NULL,
2372 pw_file);
2374 if (!rc)
2376 crypto->flags |= pw_file ? CRYPTO_FLAG_KEYFILE : 0;
2377 crypto->keyfile = pw_file;
2379 else
2380 xfree (pw_file);
2382 if (rc)
2384 estatus = EXIT_FAILURE;
2385 goto do_exit;
2388 rc = do_cache_push (crypto);
2389 if (rc && !force)
2391 log_write ("ERR %u: %s", rc, pwmd_strerror(rc));
2392 strv_free (cache_push);
2393 log_write (_ ("Failed to add a file to the cache. Use --force to force startup. Exiting."));
2394 cache_clear (NULL, NULL, 1, 0);
2395 estatus = EXIT_FAILURE;
2396 crypto_free (crypto);
2397 (void)cache_kill_scd ();
2398 goto do_exit;
2400 else if (rc)
2401 log_write ("%s: %s", crypto->filename, pwmd_strerror(rc));
2402 else
2403 log_write (_("Successfully added '%s' to the cache."),
2404 crypto->filename);
2406 crypto_free (crypto);
2409 (void)cache_kill_scd ();
2410 strv_free (cache_push);
2411 log_write (!nofork ? _("Done. Daemonizing...") :
2412 _("Done. Waiting for connections..."));
2415 backlog = config_get_integer ("global", "backlog");
2416 if (listen (sockfd, backlog) == -1)
2418 log_write ("listen(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2419 goto do_exit;
2422 /* A client should set these with the OPTION command. */
2423 unsetenv ("DISPLAY");
2424 unsetenv ("GPG_TTY");
2425 unsetenv ("TERM");
2427 if (!nofork)
2429 switch (fork ())
2431 case -1:
2432 log_write ("fork(): %s",
2433 pwmd_strerror (gpg_error_from_errno (errno)));
2434 goto do_exit;
2435 case 0:
2436 close (0);
2437 close (1);
2438 close (2);
2439 setsid ();
2440 break;
2441 default:
2442 _exit (EXIT_SUCCESS);
2446 (void)test_pidfile (socketpath, socketname, buf, sizeof(buf), &pidfile, 1,
2447 mode, 0);
2448 xfree (socketname);
2449 cmdline = 0;
2450 pthread_key_create (&thread_name_key, free_key);
2451 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
2452 estatus = server_loop (sockfd, &socketpath);
2454 do_exit:
2455 if (socketpath && do_unlink)
2457 unlink (socketpath);
2458 xfree (socketpath);
2461 xfree (socketarg);
2462 #ifdef WITH_GNUTLS
2463 gnutls_global_deinit ();
2464 tls_deinit_params ();
2465 #endif
2466 pthread_cond_destroy (&rcfile_cond);
2467 pthread_mutex_destroy (&rcfile_mutex);
2468 pthread_key_delete (last_error_key);
2469 #ifndef HAVE_PTHREAD_CANCEL
2470 pthread_key_delete (signal_thread_key);
2471 #endif
2473 if (global_config)
2474 config_free (global_config);
2476 free_invoking_users (invoking_users);
2477 xfree (rcfile);
2478 xfree (home_directory);
2479 xfree (homedir);
2480 xml_deinit ();
2482 if (pidfile)
2483 unlink (pidfile);
2484 xfree (pidfile);
2486 if (estatus == EXIT_SUCCESS && !terminate)
2487 log_write (_("pwmd exiting normally"));
2489 pthread_key_delete (thread_name_key);
2490 closelog ();
2492 if (log_fd != -1)
2493 close (log_fd);
2495 xfree (logfile);
2496 exit (estatus);
2499 gpg_error_t lock_flock (assuan_context_t ctx, const char *filename,
2500 int type, int *fd)
2502 gpg_error_t rc = 0;
2504 #ifdef HAVE_FLOCK
2505 rc = open_check_file (filename, fd, NULL, 1);
2506 if (rc)
2507 return rc;
2509 TRY_FLOCK (ctx, *fd, type, rc);
2510 if (rc)
2512 close (*fd);
2513 *fd = -1;
2515 #endif
2517 return rc;
2520 void unlock_flock (int *fd)
2522 #ifdef HAVE_FLOCK
2523 if (*fd != -1)
2524 close (*fd);
2526 *fd = -1;
2527 #endif