Update copyright year.
[pwmd.git] / src / pwmd.c
blob659f4f0c54498b4a54ce732bf9660edf91b814a2
1 /*
2 Copyright (C) 2006-2019 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"
89 static int quit;
90 static int cmdline;
91 static jmp_buf jmp;
92 static int nofork;
93 static int log_fd;
94 static unsigned assuan_level;
96 #ifndef HAVE_PTHREAD_CANCEL
97 #define INIT_SIGNAL(s, cb) do { \
98 int *n = xmalloc (sizeof (int)); \
99 *n = 0; \
100 pthread_setspecific (signal_thread_key, n); \
101 struct sigaction act; \
102 sigset_t sigset; \
103 sigemptyset (&sigset); \
104 sigaddset (&sigset, s); \
105 pthread_sigmask (SIG_UNBLOCK, &sigset, NULL); \
106 memset (&act, 0, sizeof(act)); \
107 act.sa_flags = SA_SIGINFO; \
108 act.sa_mask = sigset; \
109 act.sa_sigaction = cb; \
110 sigaction (s, &act, NULL); \
111 } while (0)
113 static void
114 catch_thread_signal (int sig, siginfo_t *info, void *ctx)
116 int *n = (int *) pthread_getspecific (signal_thread_key);
118 *n = 1;
120 #endif
122 static void
123 setup_logging ()
125 int n = config_get_boolean ("global", "enable_logging");
127 if (n)
129 char *p = config_get_string ("global", "log_path");
131 if (!p || (logfile && p && log_fd != -1 && strcmp(p, logfile)))
133 if (log_fd != -1)
134 close (log_fd);
136 log_fd = -1;
139 xfree (logfile);
140 logfile = NULL;
141 if (p)
142 logfile = expand_homedir (p);
143 xfree (p);
145 else
147 xfree (logfile);
148 logfile = NULL;
149 if (log_fd != -1)
150 close(log_fd);
152 log_fd = -1;
153 closelog ();
156 log_syslog = config_get_boolean ("global", "syslog");
157 if (log_syslog == 1)
158 openlog ("pwmd", LOG_NDELAY | LOG_PID, LOG_DAEMON);
161 static void *
162 reload_rcfile_thread (void *arg)
164 #ifndef HAVE_PTHREAD_CANCEL
165 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
166 #endif
168 #ifdef HAVE_PR_SET_NAME
169 prctl (PR_SET_NAME, "reload rcfile");
170 #endif
171 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
172 MUTEX_LOCK (&rcfile_mutex);
174 (void)arg;
176 for (;;)
178 struct slist_s *keep = NULL;
179 struct slist_s *config;
180 int b = disable_list_and_dump;
181 #ifdef WITH_GNUTLS
182 char *prio;
183 char *prio2 = NULL;
184 #endif
186 pthread_cleanup_push (release_mutex_cb, &rcfile_mutex);
187 pthread_cond_wait (&rcfile_cond, &rcfile_mutex);
188 TEST_CANCEL ();
189 keep = config_keep_save ();
190 log_write (_("reloading configuration file '%s'"), rcfile);
192 #ifdef WITH_GNUTLS
193 prio = config_get_string ("global", "tls_cipher_suite");
194 #endif
195 config = config_parse (rcfile, 1);
196 if (config)
198 config_free (global_config);
199 global_config = config;
200 setup_logging ();
203 config_keep_restore (keep);
204 disable_list_and_dump = !disable_list_and_dump ? b : 1;
206 #ifdef WITH_GNUTLS
207 /* Restart listening sockets since they may have changed. */
208 tls_start_stop (1);
209 tls_start_stop (0);
211 prio2 = config_get_string ("global", "tls_cipher_suite");
212 if ((prio2 && (!prio || strcmp (prio, prio2))) || (prio && !prio2))
213 tls_rehandshake ();
215 xfree (prio2);
216 xfree (prio);
217 #endif
218 crypto_set_keepalive ();
219 pthread_cleanup_pop (0);
222 MUTEX_UNLOCK (&rcfile_mutex);
223 return NULL;
226 #define PROCESS_DONE(client,rc) client->bulk_p ? rc : assuan_process_done (client->ctx,rc)
227 gpg_error_t
228 send_error (assuan_context_t ctx, gpg_error_t e)
230 struct client_s *client = assuan_get_pointer (ctx);
232 if (gpg_err_source (e) == GPG_ERR_SOURCE_UNKNOWN)
233 e = gpg_error (e);
235 if (client)
236 client->last_rc = e;
238 if (!e)
239 return PROCESS_DONE (client, 0);
241 if (!ctx)
243 log_write ("ERR %i: %s", e, pwmd_strerror (e));
244 return e;
247 if (client && client->xml_error)
249 log_write ("%s", client->xml_error->message);
250 xfree (client->last_error);
251 client->last_error = NULL;
252 if (client->xml_error->message)
253 client->last_error = str_dup (client->xml_error->message);
255 e = PROCESS_DONE (client, assuan_set_error (ctx, e,
256 client->xml_error->message
257 ? client->xml_error->message
258 : NULL));
259 xmlResetLastError ();
260 xmlResetError (client->xml_error);
261 xfree (client->xml_error);
262 client->xml_error = NULL;
263 return e;
266 return PROCESS_DONE (client, assuan_set_error (ctx, e, pwmd_strerror (e)));
269 void
270 log_write (const char *fmt, ...)
272 char *args;
273 va_list ap;
274 time_t now;
275 char buf[255];
276 pthread_t tid = pthread_self ();
277 static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
279 if ((!logfile && !isatty (STDERR_FILENO) && !log_syslog) || !fmt)
280 return;
282 MUTEX_LOCK (&m);
283 pthread_cleanup_push (release_mutex_cb, &m);
285 if (!cmdline && logfile && log_fd == -1)
287 log_fd = open (logfile, O_WRONLY | O_CREAT | O_APPEND, 0600);
288 if (log_fd == -1)
289 warn ("%s", logfile);
292 va_start (ap, fmt);
294 if (str_vasprintf (&args, fmt, ap) != -1)
296 pthread_cleanup_push (xfree, args);
297 if (cmdline)
299 fprintf (stderr, "pwmd: %s\n", args);
300 fflush (stderr);
302 else
304 char *name = pthread_getspecific (thread_name_key);
305 char *line;
307 if (name)
309 if (*name == '!')
310 snprintf (buf, sizeof (buf), "%s: ", name+1);
311 else
312 snprintf (buf, sizeof (buf), "%s(%p): ", name,
313 (pthread_t *)tid);
315 else
316 snprintf (buf, sizeof (buf), "%p: ", (pthread_t *)tid);
318 name = buf;
319 if (!cmdline && log_syslog && !nofork)
320 syslog (LOG_INFO, "%s%s", name, args);
322 time (&now);
323 struct tm *tm = localtime (&now);
324 char tbuf[21];
325 strftime (tbuf, sizeof (tbuf), "%b %d %Y %H:%M:%S ", tm);
326 tbuf[sizeof (tbuf) - 1] = 0;
328 if (args[strlen (args) - 1] == '\n')
329 args[strlen (args) - 1] = 0;
331 line = str_asprintf ("%s %i %s%s\n", tbuf, getpid (), name, args);
332 if (line)
334 pthread_cleanup_push (xfree, line);
335 if (logfile && log_fd != -1)
337 ssize_t ret = write (log_fd, line, strlen (line));
338 (void)ret;
339 fsync (log_fd);
342 if (nofork)
344 fprintf (stdout, "%s", line);
345 fflush (stdout);
348 pthread_cleanup_pop (1);
351 pthread_cleanup_pop (1);
354 va_end (ap);
356 if (log_fd != -1 && log_keepopen <= 0)
358 close(log_fd);
359 log_fd = -1;
362 pthread_cleanup_pop (1);
365 static gpg_error_t
366 setup_crypto ()
368 gpg_error_t rc;
370 if (!gpgrt_check_version (REQUIRE_LIBGPGERROR_VERSION))
372 fprintf (stderr, _("gpgrt_check_version(): Incompatible libgpg-error. "
373 "Wanted %s, got %s.\n"), REQUIRE_LIBGPGERROR_VERSION,
374 gpgrt_check_version (NULL));
375 return GPG_ERR_UNKNOWN_VERSION;
378 gpgrt_init ();
379 gpgrt_set_alloc_func (xrealloc_gpgrt);
381 if (!assuan_check_version (REQUIRE_LIBASSUAN_VERSION))
383 fprintf (stderr, _("assuan_check_version(): Incompatible libassuan. "
384 "Wanted %s, got %s.\n"), REQUIRE_LIBASSUAN_VERSION,
385 assuan_check_version (NULL));
386 return GPG_ERR_UNKNOWN_VERSION;
389 if (!gcry_check_version (REQUIRE_LIBGCRYPT_VERSION))
391 fprintf (stderr, _("gcry_check_version(): Incompatible libgcrypt. "
392 "Wanted %s, got %s.\n"), REQUIRE_LIBGCRYPT_VERSION,
393 gcry_check_version (NULL));
394 return GPG_ERR_UNKNOWN_VERSION;
397 gcry_set_allocation_handler (xmalloc, xmalloc, NULL, xrealloc, xfree);
399 if (!gpgme_check_version (REQUIRE_LIBGPGME_VERSION))
401 fprintf (stderr, _("gpgme_check_version(): Incompatible libgpgme. "
402 "Wanted %s, got %s.\n"), REQUIRE_LIBGPGME_VERSION,
403 gpgme_check_version (NULL));
404 return GPG_ERR_UNKNOWN_VERSION;
407 rc = gpgme_engine_check_version (GPGME_PROTOCOL_OPENPGP);
408 if (rc)
410 fprintf (stderr, _("gpgme_engine_check_version(GPGME_PROTOCOL_OPENPGP): %s"), gpgme_strerror (rc));
411 return GPG_ERR_UNKNOWN_VERSION;
414 //gpgme_set_global_flag ("require-gnupg", REQUIRE_GNUPG_VERSION);
415 #ifdef ENABLE_NLS
416 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
417 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
418 #endif
420 #ifdef WITH_GNUTLS
421 if (gnutls_global_init ())
423 fprintf(stderr, _("gnutls_global_init() failed.\n"));
424 return GPG_ERR_UNKNOWN_VERSION;
427 if (!gnutls_check_version (REQUIRE_LIBGNUTLS_VERSION))
429 fprintf (stderr, _("gnutls_check_version(): Incompatible libgnutls. "
430 "Wanted %s, got %s.\n"), REQUIRE_LIBGNUTLS_VERSION,
431 gnutls_check_version (NULL));
432 return GPG_ERR_UNKNOWN_VERSION;
435 gnutls_global_set_log_function (tls_log);
436 gnutls_global_set_audit_log_function (tls_audit_log);
437 #endif
438 return 0;
441 static void
442 xml_error_cb (void *data, xmlErrorPtr e)
444 struct client_s *client = data;
447 * Keep the first reported error as the one to show in the error
448 * description. Reset in send_error().
450 if (client->xml_error)
451 return;
453 client->xml_error = xcalloc (1, sizeof(xmlError));
454 xmlCopyError (e, client->xml_error);
457 static pid_t
458 hook_waitpid (assuan_context_t ctx, pid_t pid, int action,
459 int *status, int options)
461 (void)ctx;
462 (void)action;
463 return waitpid (pid, status, options);
466 static ssize_t
467 hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
469 TEST_CANCEL ();
470 #ifdef WITH_GNUTLS
471 struct client_s *client = assuan_get_pointer (ctx);
473 if (client->thd->remote)
474 return tls_read_hook (ctx, (int) fd, data, len);
475 #else
476 (void)ctx;
477 #endif
478 return read ((int) fd, data, len);
481 static ssize_t
482 hook_write (assuan_context_t ctx, assuan_fd_t fd,
483 const void *data, size_t len)
485 TEST_CANCEL ();
486 #ifdef WITH_GNUTLS
487 struct client_s *client = assuan_get_pointer (ctx);
489 if (client->thd->remote)
490 return tls_write_hook (ctx, (int) fd, data, len);
491 #else
492 (void)ctx;
493 #endif
494 return write ((int) fd, data, len);
498 assuan_log_cb (assuan_context_t ctx, void *data, unsigned cat,
499 const char *msg)
501 struct client_s *client = data;
502 const char *str = NULL;
504 (void)client;
505 (void)ctx;
507 if (!(assuan_level & cat))
508 return 0;
510 if (!msg)
511 return 1;
513 switch (cat)
515 case ASSUAN_LOG_INIT:
516 str = "ASSUAN[INIT]";
517 break;
518 case ASSUAN_LOG_CTX:
519 str = "ASSUAN[CTX]";
520 break;
521 case ASSUAN_LOG_ENGINE:
522 str = "ASSUAN[ENGINE]";
523 break;
524 case ASSUAN_LOG_DATA:
525 str = "ASSUAN[DATA]";
526 break;
527 case ASSUAN_LOG_SYSIO:
528 str = "ASSUAN[SYSIO]";
529 break;
530 case ASSUAN_LOG_CONTROL:
531 str = "ASSUAN[CONTROL]";
532 break;
533 default:
534 str = "ASSUAN[UNKNOWN]";
535 break;
538 log_write ("%s: %s", str, msg);
539 return 1;
542 static int
543 new_connection (struct client_s *cl)
545 gpg_error_t rc;
546 static struct assuan_malloc_hooks mhooks = { xmalloc, xrealloc, xfree };
547 static struct assuan_system_hooks shooks = {
548 ASSUAN_SYSTEM_HOOKS_VERSION,
549 __assuan_usleep,
550 __assuan_pipe,
551 __assuan_close,
552 hook_read,
553 hook_write,
554 //FIXME
555 NULL, //recvmsg
556 NULL, //sendmsg both are used for FD passing
557 __assuan_spawn,
558 hook_waitpid,
559 __assuan_socketpair,
560 __assuan_socket,
561 __assuan_connect
564 #ifdef WITH_GNUTLS
565 if (cl->thd->remote)
567 char *prio = config_get_string ("global", "tls_cipher_suite");
569 cl->thd->timeout = config_get_integer ("global", "tls_timeout");
570 if (fcntl (cl->thd->fd, F_SETFL, O_NONBLOCK) == -1)
571 return 0;
573 cl->thd->tls = tls_init_client (cl->thd->fd, cl->thd->timeout, prio);
574 xfree (prio);
575 if (!cl->thd->tls)
576 return 0;
578 #endif
580 rc = assuan_new_ext (&cl->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks,
581 assuan_log_cb, cl);
582 if (rc)
583 goto fail;
585 assuan_ctx_set_system_hooks (cl->ctx, &shooks);
586 rc = assuan_init_socket_server (cl->ctx, cl->thd->fd,
587 ASSUAN_SOCKET_SERVER_ACCEPTED);
588 if (rc)
589 goto fail;
591 assuan_set_pointer (cl->ctx, cl);
592 assuan_set_hello_line (cl->ctx, PACKAGE_STRING);
593 rc = register_commands (cl->ctx);
594 if (rc)
595 goto fail;
597 rc = assuan_accept (cl->ctx);
598 if (rc)
599 goto fail;
601 rc = validate_peer (cl);
602 /* May not be implemented on all platforms. */
603 if (rc && gpg_err_code (rc) != GPG_ERR_ASS_GENERAL)
604 goto fail;
606 MUTEX_LOCK (&cn_mutex);
607 cl->thd->state = CLIENT_STATE_INIT;
608 MUTEX_UNLOCK (&cn_mutex);
609 cl->lock_timeout = config_get_integer ("global", "lock_timeout");
610 xmlSetStructuredErrorFunc (cl, xml_error_cb);
611 return 1;
613 fail:
614 log_write ("%s", pwmd_strerror (rc));
615 return 0;
619 * This is called after a client is cancelled or disconnects. Set with
620 * pthread_cleanup_push().
622 static void
623 free_client_cb (void *arg)
625 struct client_thread_s *cn = arg;
626 struct client_s *cl = cn->cl;
627 char *tmp = NULL;
629 #ifndef HAVE_PTHREAD_CANCEL
630 tmp = pthread_getspecific (signal_thread_key);
631 xfree (tmp);
632 pthread_setspecific (signal_thread_key, NULL);
633 #endif
635 MUTEX_LOCK (&cn_mutex);
636 cn_thread_list = slist_remove (cn_thread_list, cn);
637 MUTEX_UNLOCK (&cn_mutex);
639 if (cl)
641 unlock_flock (&cl->flock_fd);
642 reset_client (cl);
643 if (cl->xml_error)
644 xmlResetError (cl->xml_error);
646 xfree (cl->xml_error);
648 #ifdef WITH_GNUTLS
649 if (cn->tls)
651 gnutls_deinit (cn->tls->ses);
652 xfree (cn->tls->fp);
653 xfree (cn->tls);
655 #endif
657 if (cl->ctx)
658 assuan_release (cl->ctx);
659 else if (cl->thd && cl->thd->fd != -1)
660 close (cl->thd->fd);
662 if (cl->crypto)
663 crypto_free (cl->crypto);
665 cl->crypto = NULL;
666 xfree (cl);
668 else
670 if (cn->fd != -1)
671 close (cn->fd);
674 while (cn->msg_queue)
676 struct status_msg_s *msg = cn->msg_queue;
678 cn->msg_queue = msg->next;
679 xfree (msg->line);
680 xfree (msg);
683 if (cn->status_msg_pipe[0] != -1)
684 close (cn->status_msg_pipe[0]);
686 if (cn->status_msg_pipe[1] != -1)
687 close (cn->status_msg_pipe[1]);
689 pthread_mutex_destroy (&cn->status_mutex);
690 log_write (_("exiting, fd=%i"), cn->fd);
691 send_status_all (STATUS_CLIENTS, NULL);
693 xfree (cn->name);
694 #ifdef WITH_GNUTLS
695 xfree (cn->peeraddr);
696 #endif
698 if (cn->eof) // Not pthread_exit() or pthread_cancel().
700 tmp = pthread_getspecific (thread_name_key);
701 xfree (tmp);
702 pthread_setspecific (thread_name_key, NULL);
705 (void)cache_kill_scd ();
706 xfree (cn);
709 static void
710 free_all_clients ()
712 MUTEX_LOCK (&cn_mutex);
713 pthread_cleanup_push (release_mutex_cb, &cn_mutex);
715 while (slist_length (cn_thread_list))
717 struct client_thread_s *thd = slist_nth_data (cn_thread_list, 0);
719 free_client_cb (thd);
720 thd->eof = 1;
723 pthread_cleanup_pop (1);
726 static gpg_error_t
727 send_msg_queue (struct client_thread_s *thd)
729 MUTEX_LOCK (&thd->status_mutex);
730 gpg_error_t rc = 0;
731 char c;
732 ssize_t ret;
734 ret = read (thd->status_msg_pipe[0], &c, 1);
735 rc = gpg_error_from_syserror ();
736 if (ret == -1 && gpg_err_code (rc) != GPG_ERR_EAGAIN)
737 log_write ("%s (%i): %s", __FUNCTION__, __LINE__, pwmd_strerror (rc));
738 else
739 rc = 0;
741 thd->wrote_status = 0;
743 while (thd->msg_queue)
745 struct status_msg_s *msg = thd->msg_queue;
747 thd->msg_queue = thd->msg_queue->next;
748 MUTEX_UNLOCK (&thd->status_mutex);
749 pthread_cleanup_push (xfree, msg);
750 pthread_cleanup_push (xfree, msg->line);
751 rc = send_status (thd->cl->ctx, msg->s, msg->line);
752 pthread_cleanup_pop (1);
753 pthread_cleanup_pop (1);
754 MUTEX_LOCK (&thd->status_mutex);
755 if (rc)
756 break;
759 MUTEX_UNLOCK (&thd->status_mutex);
760 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
761 log_write ("%s (%i): %s", __FUNCTION__, __LINE__, pwmd_strerror (rc));
763 return rc;
766 static void *
767 client_thread (void *data)
769 struct client_thread_s *thd = data;
770 struct client_s *cl = xcalloc (1, sizeof (struct client_s));
771 struct slist_s *list;
772 gpg_error_t rc = 0;
773 #ifndef HAVE_PTHREAD_CANCEL
774 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
775 #endif
777 #ifdef HAVE_PR_SET_NAME
778 prctl (PR_SET_NAME, "client");
779 #endif
780 pthread_setspecific (thread_name_key, str_dup (__FUNCTION__));
782 if (!cl)
784 log_write ("%s(%i): %s", __FILE__, __LINE__,
785 pwmd_strerror (GPG_ERR_ENOMEM));
786 return NULL;
789 MUTEX_LOCK (&cn_mutex);
790 pthread_cleanup_push (free_client_cb, thd);
791 thd->cl = cl;
792 cl->thd = thd;
793 cl->flock_fd = -1;
795 list = slist_append (cn_thread_list, thd);
796 if (list)
797 cn_thread_list = list;
798 else
800 log_write ("%s(%i): %s", __FILE__, __LINE__,
801 pwmd_strerror (GPG_ERR_ENOMEM));
802 MUTEX_UNLOCK (&cn_mutex);
803 return NULL;
806 if (fcntl (thd->status_msg_pipe[0], F_SETFL, O_NONBLOCK) == -1)
807 rc = gpg_error_from_errno (errno);
809 if (!rc)
810 if (fcntl (thd->status_msg_pipe[1], F_SETFL, O_NONBLOCK) == -1)
811 rc = gpg_error_from_errno (errno);
813 MUTEX_UNLOCK (&cn_mutex);
815 if (rc)
817 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
818 goto done;
821 if (new_connection (cl))
823 struct pollfd fds[2];
825 fds[0].fd = thd->fd;
826 fds[0].events = POLLIN;
827 fds[1].fd = thd->status_msg_pipe[0];
828 fds[1].events = POLLIN;
830 send_status_all (STATUS_CLIENTS, NULL);
831 rc = send_status (cl->ctx, STATUS_CACHE, NULL);
832 if (rc)
834 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
835 goto done;
838 for (;;)
840 int n;
841 int eof;
843 n = poll (fds, sizeof(fds)/sizeof(fds[0]), 100);
844 if (n == -1)
846 log_write ("%s", strerror (errno));
847 break;
850 #ifdef WITH_GNUTLS
851 if (thd->remote && thd->tls && thd->tls->rehandshake)
853 char *prio;
854 int ret;
855 const char *e;
857 if (thd->tls->rehandshake == 1)
859 prio = config_get_string ("global", "tls_cipher_suite");
860 if (!prio)
862 thd->tls->rehandshake = 0;
863 continue;
866 ret = gnutls_priority_set_direct (thd->tls->ses, prio, &e);
867 if (ret == GNUTLS_E_SUCCESS)
869 rc = send_status (cl->ctx, STATUS_REHANDSHAKE, NULL);
870 if (!rc)
872 rc = assuan_send_data (cl->ctx, NULL, 0);
873 if (!rc)
875 ret = gnutls_rehandshake (thd->tls->ses);
876 if (ret)
878 log_write ("%s", gnutls_strerror (ret));
879 thd->tls->rehandshake = 0;
881 else
882 thd->tls->rehandshake = 2;
886 if (rc)
887 log_write ("%s", pwmd_strerror (rc));
889 else
890 log_write ("%s: %s", gnutls_strerror (ret), e);
892 xfree (prio);
893 continue;
896 #endif
898 if (!n)
899 continue;
901 if (fds[1].revents & POLLIN)
903 #ifdef WITH_GNUTLS
904 if (!thd->remote || (thd->tls && !thd->tls->rehandshake))
905 #endif
907 rc = send_msg_queue (thd);
908 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
909 break;
913 #ifdef HAVE_PTHREAD_CANCEL
914 if (!(fds[0].revents & POLLIN))
915 #else
916 if (thd->fd != -1 && !(fds[0].revents & POLLIN))
917 #endif
918 continue;
920 rc = assuan_process_next (cl->ctx, &eof);
921 if (rc || eof)
923 if (gpg_err_code (rc) == GPG_ERR_EOF || eof)
924 break;
926 log_write ("assuan_process_next(): rc=%u %s", rc,
927 pwmd_strerror (rc));
928 if (rc == gpg_error (GPG_ERR_ETIMEDOUT))
929 break;
931 rc = send_error (cl->ctx, rc);
932 if (rc)
934 log_write ("assuan_process_done(): rc=%u %s", rc,
935 pwmd_strerror (rc));
936 break;
940 /* Since the msg queue pipe fd's are non-blocking, check for
941 * pending status msgs here. GPG_ERR_EPIPE can be seen when the
942 * client has already disconnected and will be converted to
943 * GPG_ERR_EOF during assuan_process_next().
945 #ifdef WITH_GNUTLS
946 if (!thd->remote || (thd->tls && !thd->tls->rehandshake))
947 #endif
949 rc = send_msg_queue (thd);
950 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
951 break;
956 done:
957 /* Don't do pthread_exit() here because any set pthread_cleanup_push
958 * functions would be called after a command failed but then the client
959 * exited normally which may lead to a double free. */
960 thd->eof = 1;
961 pthread_cleanup_pop (1);
962 return NULL;
965 static gpg_error_t
966 xml_import (const char *filename, const char *outfile, char **keyid,
967 char *sign_keyid, char *keyfile, const char *userid,
968 const char *algo, long expire, int no_passphrase, int symmetric)
970 xmlDocPtr doc;
971 int fd;
972 struct stat st;
973 int len;
974 xmlChar *xmlbuf = NULL;
975 gpg_error_t rc = 0;
976 struct crypto_s *crypto = NULL;
978 if (strcmp (filename, "-"))
980 rc = open_check_file (filename, &fd, &st, 0);
981 if (rc)
982 return rc;
984 xmlbuf = xmalloc (st.st_size + 1);
985 if (!xmlbuf)
987 close (fd);
988 return GPG_ERR_ENOMEM;
991 if (read (fd, xmlbuf, st.st_size) == -1)
993 rc = gpg_error_from_errno (errno);
994 close (fd);
995 xfree (xmlbuf);
996 return rc;
999 xmlbuf[st.st_size] = 0;
1000 close (fd);
1002 else
1004 #define BUFSIZE 8196
1005 size_t size = 0, xlen = 0;
1007 for (;;)
1009 size_t ret;
1010 xmlChar *tmp;
1012 tmp = xrealloc (xmlbuf, size+BUFSIZE+1);
1013 if (!tmp)
1015 xfree (xmlbuf);
1016 return GPG_ERR_ENOMEM;
1019 xmlbuf = tmp;
1020 size += BUFSIZE;
1021 ret = read (STDIN_FILENO, &xmlbuf[xlen], BUFSIZE);
1022 if (ret == -1)
1024 rc = gpg_error_from_syserror ();
1025 xfree (xmlbuf);
1026 return rc;
1029 xlen += ret;
1030 if (!ret || ret < BUFSIZE)
1031 break;
1034 xmlbuf[xlen] = 0;
1037 doc = xmlReadDoc (xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS);
1038 xfree (xmlbuf);
1039 if (!doc)
1040 return GPG_ERR_BAD_DATA;
1042 xmlNodePtr n = xmlDocGetRootElement (doc);
1043 if (n && !xmlStrEqual (n->name, (xmlChar *) "pwmd"))
1044 rc = GPG_ERR_BAD_DATA;
1046 if (!rc)
1048 rc = xml_validate_import (NULL, n ? n->children : n);
1049 if (!rc)
1051 rc = crypto_init (&crypto, NULL, filename, keyfile != NULL, keyfile);
1052 if (!rc)
1054 if (keyfile)
1056 crypto->flags |= CRYPTO_FLAG_KEYFILE;
1057 crypto->keyfile = str_dup (keyfile);
1060 xmlDocDumpMemory (doc, &crypto->plaintext, &len);
1061 if (len > 0)
1062 crypto->plaintext_size = len;
1063 else
1064 rc = GPG_ERR_ENOMEM;
1069 if (!rc)
1071 if (!symmetric && !keyid)
1073 crypto->save.userid = str_dup (userid);
1074 crypto->save.algo = algo ? str_dup (algo) : NULL;
1075 crypto->save.expire = expire;
1076 if (no_passphrase)
1077 crypto->save.flags |= GPGME_CREATE_NOPASSWD;
1079 rc = crypto_genkey (NULL, crypto);
1081 else
1083 if (keyid)
1084 crypto->save.pubkey = strv_dup (keyid);
1086 if (sign_keyid)
1087 crypto->save.sigkey = str_dup (sign_keyid);
1090 if (!rc)
1092 crypto->flags |= symmetric ? CRYPTO_FLAG_SYMMETRIC : 0;
1093 rc = crypto_encrypt (NULL, crypto);
1097 if (!rc)
1099 if (!strcmp (outfile, "-"))
1100 outfile = NULL;
1102 xfree (crypto->plaintext);
1103 crypto->plaintext = NULL;
1104 xfree (crypto->filename);
1105 crypto->filename = outfile ? str_dup (outfile) : NULL;
1106 rc = crypto_write_file (crypto, NULL, NULL);
1109 xmlFreeDoc (doc);
1110 crypto_free (crypto);
1111 return rc;
1114 static gpg_error_t
1115 do_cache_push (struct crypto_s *crypto)
1117 gpg_error_t rc;
1118 xmlDocPtr doc;
1119 struct cache_data_s *cdata;
1120 unsigned char *crc;
1121 size_t len;
1122 int fd = -1;
1124 log_write (_("Adding '%s' to the cache..."),
1125 crypto->filename);
1127 if (valid_filename (crypto->filename) == 0)
1129 log_write (_("%s: Invalid characters in filename"), crypto->filename);
1130 return GPG_ERR_INV_VALUE;
1133 rc = lock_flock (NULL, crypto->filename, LOCK_SH, &fd);
1134 if (!rc)
1135 rc = crypto_decrypt (NULL, crypto);
1136 if (rc)
1138 unlock_flock (&fd);
1139 return rc;
1142 rc = xml_parse_doc ((char *) crypto->plaintext, crypto->plaintext_size, &doc);
1143 if (rc)
1145 unlock_flock (&fd);
1146 log_write ("%s", pwmd_strerror (rc));
1147 return rc;
1150 cdata = xcalloc (1, sizeof (struct cache_data_s));
1151 if (!cdata)
1153 unlock_flock (&fd);
1154 xmlFreeDoc (doc);
1155 return GPG_ERR_ENOMEM;
1158 rc = get_checksum (crypto->filename, &crc, &len);
1159 unlock_flock (&fd);
1160 if (rc)
1162 xmlFreeDoc (doc);
1163 cache_free_data_once (cdata);
1164 return rc;
1167 cdata->crc = crc;
1168 rc = cache_encrypt (crypto);
1169 if (!rc)
1171 cdata->doc = crypto->plaintext;
1172 cdata->size = crypto->plaintext_size;
1173 crypto->plaintext = NULL;
1174 cdata->pubkey = crypto->pubkey;
1175 cdata->sigkey = crypto->sigkey;
1176 crypto->pubkey = NULL;
1177 crypto->sigkey = NULL;
1179 else
1181 xmlFreeDoc (doc);
1182 cache_free_data_once (cdata);
1183 return rc;
1186 long timeout = config_get_long (crypto->filename, "cache_timeout");
1187 rc = cache_add_file (crypto->filename, cdata, timeout);
1188 return rc;
1191 static gpg_error_t
1192 init_client (int fd, const char *addr)
1194 gpg_error_t rc = 0;
1195 struct client_thread_s *new = xcalloc (1, sizeof (struct client_thread_s));
1197 if (!new)
1199 close (fd);
1200 log_write ("%s: %s", __FUNCTION__, pwmd_strerror (ENOMEM));
1201 return GPG_ERR_ENOMEM;
1204 MUTEX_LOCK (&cn_mutex);
1205 pthread_cleanup_push (release_mutex_cb, &cn_mutex);
1206 new->conntime = time (NULL);
1208 if (pipe (new->status_msg_pipe) == -1)
1209 rc = gpg_error_from_errno (errno);
1210 else
1211 pthread_mutex_init (&new->status_mutex, NULL);
1213 if (!rc)
1215 #ifdef WITH_GNUTLS
1216 new->remote = addr ? 1 : 0;
1217 if (addr)
1218 new->peeraddr = str_dup (addr);
1219 #endif
1220 new->fd = fd;
1221 rc = create_thread (client_thread, new, &new->tid, 1);
1222 if (rc)
1224 close (new->status_msg_pipe[0]);
1225 close (new->status_msg_pipe[1]);
1226 pthread_mutex_destroy (&new->status_mutex);
1230 if (!rc)
1232 if (addr)
1233 log_write (_("new connection: tid=%p, fd=%i, addr=%s"),
1234 (pthread_t *) new->tid, fd, addr);
1235 else
1236 log_write (_("new connection: tid=%p, fd=%i"),
1237 (pthread_t *) new->tid, fd);
1240 pthread_cleanup_pop (1);
1242 if (rc)
1244 xfree (new);
1245 close (fd);
1246 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
1248 return rc;
1251 #ifdef WITH_GNUTLS
1252 static gpg_error_t
1253 do_tls_accept (struct pollfd *fds)
1255 struct sockaddr_storage raddr;
1256 socklen_t slen = sizeof (raddr);
1257 int fd;
1258 char s[INET6_ADDRSTRLEN];
1260 if (!(fds->revents & POLLIN))
1261 return 0;
1263 memset (&raddr, 0, sizeof (raddr));
1264 fd = accept (fds->fd, (struct sockaddr *) &raddr, &slen);
1265 if (fd == -1)
1267 int e = errno;
1269 if (errno != EAGAIN && !quit)
1270 log_write ("%s: %s", __FUNCTION__,
1271 pwmd_strerror (gpg_error_from_syserror()));
1273 return gpg_error_from_errno (e);
1276 inet_ntop (raddr.ss_family, get_in_addr ((struct sockaddr *) &raddr), s,
1277 sizeof s);
1278 (void) init_client (fd, s);
1279 return 0;
1281 #endif
1283 static void *
1284 accept_thread (void *arg)
1286 int sockfd = *(int *) arg;
1287 #ifndef HAVE_PTHREAD_CANCEL
1288 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
1289 #endif
1291 #ifdef HAVE_PR_SET_NAME
1292 prctl (PR_SET_NAME, "accept");
1293 #endif
1294 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
1296 for (;;)
1298 socklen_t slen = sizeof (struct sockaddr_un);
1299 struct sockaddr_un raddr;
1300 int fd, s = 0;
1301 struct pollfd fds[3];
1303 TEST_CANCEL ();
1304 memset (fds, 0, sizeof (fds));
1305 fds[s].fd = sockfd;
1306 fds[s++].events = POLLIN;
1308 #ifdef WITH_GNUTLS
1309 if (tls_fd != -1)
1311 fds[s].fd = tls_fd;
1312 fds[s++].events = POLLIN;
1314 else
1315 fds[s].fd = tls_fd;
1317 if (tls6_fd != -1)
1319 fds[s].fd = tls6_fd;
1320 fds[s++].events = POLLIN;
1322 else
1323 fds[s].fd = tls6_fd;
1324 #endif
1326 s = poll (fds, s, 500);
1327 if (s == -1)
1329 if (errno != EINTR)
1330 log_write ("%s", strerror (errno));
1331 break;
1333 else if (s == 0)
1334 continue;
1336 if (fds[0].revents & POLLIN)
1338 fd = accept (sockfd, (struct sockaddr *) &raddr, &slen);
1339 if (fd == -1)
1341 if (errno == EMFILE || errno == ENFILE)
1342 log_write ("%s: %s", __FUNCTION__,
1343 pwmd_strerror (gpg_error_from_errno (errno)));
1344 else if (errno != EAGAIN && errno != EINTR)
1346 if (!quit) // probably EBADF
1347 log_write ("%s: %s", __FUNCTION__,
1348 pwmd_strerror (gpg_error_from_errno (errno)));
1350 break;
1353 continue;
1356 (void) init_client (fd, NULL);
1359 #ifdef WITH_GNUTLS
1360 if (tls_fd != -1 && fds[1].fd == tls_fd)
1361 (void)do_tls_accept (&fds[1]);
1363 if (tls6_fd != -1 && fds[1].fd == tls6_fd)
1364 (void)do_tls_accept (&fds[1]);
1366 if (tls6_fd != -1 && fds[2].fd == tls6_fd)
1367 (void)do_tls_accept (&fds[2]);
1368 #endif
1371 /* Just in case accept() failed for some reason other than EBADF */
1372 quit = 1;
1373 return NULL;
1376 static void *
1377 cache_timer_thread (void *arg)
1379 unsigned k = 0;
1380 #ifndef HAVE_PTHREAD_CANCEL
1381 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
1382 #endif
1384 (void)arg;
1386 #ifdef HAVE_PR_SET_NAME
1387 prctl (PR_SET_NAME, "timer");
1388 #endif
1389 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
1391 for (;;)
1393 struct timeval tv = { 1, 0 };
1394 unsigned keepalive = config_get_integer ("global", "keepalive_interval");
1396 TEST_CANCEL ();
1397 select (0, NULL, NULL, NULL, &tv);
1398 cache_adjust_timeout ();
1400 if (keepalive && ++k >= keepalive)
1402 send_status_all (STATUS_KEEPALIVE, NULL);
1403 k = 0;
1407 return NULL;
1410 static int
1411 signal_loop (sigset_t sigset)
1413 int done = 0;
1417 int sig;
1419 sigwait (&sigset, &sig);
1420 log_write (_("caught signal %i (%s)"), sig, strsignal (sig));
1422 switch (sig)
1424 case SIGHUP:
1425 pthread_cond_signal (&rcfile_cond);
1426 break;
1427 case SIGUSR1:
1428 log_write (_("clearing file cache"));
1429 cache_clear (NULL, NULL, 1, 0);
1430 send_status_all (STATUS_CACHE, NULL);
1431 break;
1432 default:
1433 done = 1;
1434 break;
1437 while (!done);
1439 return done;
1442 static void
1443 catchsig (int sig)
1445 log_write (_ ("Caught signal %i (%s). Exiting."), sig, strsignal (sig));
1446 #ifdef HAVE_BACKTRACE
1447 BACKTRACE (__FUNCTION__);
1448 #endif
1449 longjmp (jmp, 1);
1452 static void
1453 cancel_all_clients ()
1455 unsigned i, t;
1457 MUTEX_LOCK (&cn_mutex);
1458 t = slist_length (cn_thread_list);
1459 for (i = 0; i < t; i++)
1461 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
1463 #ifdef HAVE_PTHREAD_CANCEL
1464 pthread_cancel (thd->tid);
1465 #else
1466 pthread_kill (thd->tid, SIGUSR2);
1467 #endif
1470 while (slist_length (cn_thread_list))
1472 MUTEX_UNLOCK (&cn_mutex);
1473 usleep (50000);
1474 MUTEX_LOCK (&cn_mutex);
1477 MUTEX_UNLOCK (&cn_mutex);
1480 static int
1481 server_loop (int sockfd, char **socketpath)
1483 pthread_t cache_timeout_tid;
1484 pthread_t accept_tid;
1485 int cancel_timeout_thread = 0;
1486 int cancel_accept_thread = 0;
1487 int cancel_rcfile_thread = 0;
1488 sigset_t sigset;
1489 int n;
1490 int segv = 0;
1491 gpg_error_t rc;
1493 init_commands ();
1494 sigemptyset (&sigset);
1496 /* Termination */
1497 sigaddset (&sigset, SIGTERM);
1498 sigaddset (&sigset, SIGINT);
1500 /* Clears the file cache. */
1501 sigaddset (&sigset, SIGUSR1);
1503 /* Configuration file reloading. */
1504 sigaddset (&sigset, SIGHUP);
1506 #ifndef HAVE_PTHREAD_CANCEL
1508 The socket, cache and rcfile threads use this signal when
1509 pthread_cancel() is unavailable. Prevent the main thread from
1510 catching this signal from another process.
1512 sigaddset (&sigset, SIGUSR2);
1513 #endif
1515 /* An assertion failure. */
1516 signal (SIGABRT, catchsig);
1518 sigaddset (&sigset, SIGABRT);
1519 sigprocmask (SIG_BLOCK, &sigset, NULL);
1521 #ifndef HAVE_PTHREAD_CANCEL
1522 /* Remove this signal from the watched signals in signal_loop(). */
1523 sigdelset (&sigset, SIGUSR2);
1524 #endif
1526 /* Can show a backtrace of the stack in the log. */
1527 signal (SIGSEGV, catchsig);
1529 char *p = get_username (getuid());
1530 log_write (_("%s started for user %s"), PACKAGE_STRING, p);
1531 xfree (p);
1533 #ifdef WITH_GNUTLS
1534 if (config_get_boolean ("global", "enable_tcp"))
1535 log_write (_("Listening on %s and TCP port %i"), *socketpath,
1536 config_get_integer ("global", "tcp_port"));
1537 else
1538 log_write (_("Listening on %s"), *socketpath);
1539 #else
1540 log_write (_("Listening on %s"), *socketpath);
1541 #endif
1543 rc = create_thread (reload_rcfile_thread, NULL, &rcfile_tid, 0);
1544 if (rc)
1546 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1547 pwmd_strerror (rc));
1548 goto done;
1551 cancel_rcfile_thread = 1;
1552 rc = create_thread (cache_timer_thread, NULL, &cache_timeout_tid, 0);
1553 if (rc)
1555 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1556 pwmd_strerror (rc));
1557 goto done;
1560 cancel_timeout_thread = 1;
1561 rc = create_thread (accept_thread, &sockfd, &accept_tid, 0);
1562 if (rc)
1564 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1565 pwmd_strerror (rc));
1566 goto done;
1569 cancel_accept_thread = 1;
1570 if (!setjmp (jmp))
1571 signal_loop (sigset);
1572 else
1573 segv = 1;
1575 done:
1577 * We're out of the main server loop. This happens when a signal was sent
1578 * to terminate the daemon. Cancel all clients and exit.
1580 if (cancel_accept_thread)
1582 #ifdef HAVE_PTHREAD_CANCEL
1583 n = pthread_cancel (accept_tid);
1584 #else
1585 n = pthread_kill (accept_tid, SIGUSR2);
1586 #endif
1587 if (!n)
1588 pthread_join (accept_tid, NULL);
1591 if (cancel_timeout_thread)
1593 #ifdef HAVE_PTHREAD_CANCEL
1594 n = pthread_cancel (cache_timeout_tid);
1595 #else
1596 n = pthread_kill (cache_timeout_tid, SIGUSR2);
1597 #endif
1598 if (!n)
1599 pthread_join (cache_timeout_tid, NULL);
1602 #ifdef WITH_GNUTLS
1603 tls_start_stop (1);
1604 #endif
1605 shutdown (sockfd, SHUT_RDWR);
1606 close (sockfd);
1607 unlink (*socketpath);
1608 xfree (*socketpath);
1609 *socketpath = NULL;
1610 MUTEX_LOCK (&cn_mutex);
1611 n = slist_length (cn_thread_list);
1612 MUTEX_UNLOCK (&cn_mutex);
1614 if (n && !segv)
1615 cancel_all_clients ();
1616 else
1617 free_all_clients ();
1619 if (cancel_rcfile_thread)
1621 #ifdef HAVE_PTHREAD_CANCEL
1622 pthread_cancel (rcfile_tid);
1623 #else
1624 pthread_kill (rcfile_tid, SIGUSR2);
1625 pthread_cond_signal (&rcfile_cond);
1626 #endif
1627 pthread_join (rcfile_tid, NULL);
1630 cache_deinit ();
1631 deinit_commands ();
1632 return segv ? EXIT_FAILURE : EXIT_SUCCESS;
1635 static void
1636 usage (const char *pn, int status)
1638 FILE *fp = status == EXIT_FAILURE ? stderr : stdout;
1640 fprintf (fp, _("Usage: %s [OPTIONS] [file1] [...]\n"
1641 " --homedir alternate pwmd home directory (~/.pwmd)\n"
1642 " -f, --rcfile=filename load the specfied configuration file\n"
1643 " (~/.pwmd/config)\n"
1644 " --kill terminate an existing instance of pwmd\n"
1645 " -n, --no-fork run as a foreground process\n"
1646 " --disable-dump disable the LIST, XPATH and DUMP commands\n"
1647 " --ignore, --force ignore cache pushing errors during startup\n"
1648 " -I, --import=filename import a pwmd DTD formatted XML file)\n"
1649 " -k, --passphrase-file=file for use when importing\n"
1650 " -o, --outfile=filename output file when importing\n"
1651 " --keyid=fpr[,..] public key to use when encrypting\n"
1652 " --sign-keyid=fpr fingerprint of the signing key to use\n"
1653 " -s, --symmetric use conventional encryption with optional signer\n"
1654 " --userid=string name and email address to use when importing\n"
1655 " --algo=string algorithm to use when importing (engine default)\n"
1656 " --expire=seconds key expiry time when importing (3 years)\n"
1657 " --no-passphrase don't require a passphrase when importing\n"
1658 " --debug=[a:..][,g:N][,t:N] enable debugging (a:[ixedsc],g:[1-9],t:[0-N])\n"
1659 " --help this help text\n"
1660 " --version show version and compile time features\n"),
1661 pn);
1662 exit (status);
1665 static void
1666 unlink_stale_socket (const char *sock, const char *pidfile)
1668 log_write (_ ("removing stale socket %s"), sock);
1669 unlink (sock);
1670 unlink (pidfile);
1673 static int
1674 test_pidfile (const char *path, const char *sock, char *buf, size_t buflen,
1675 char **pidfile, int create, mode_t mode, int terminate)
1677 pid_t pid;
1678 int fd;
1679 size_t len;
1681 if (!create)
1683 snprintf (buf, buflen, "%s/%s.pid", homedir, sock);
1684 *pidfile = str_dup (buf);
1685 fd = open (buf, O_RDONLY);
1687 else
1688 fd = open (*pidfile, O_CREAT|O_WRONLY|O_TRUNC, mode);
1690 if (fd == -1)
1692 if (!create && errno != ENOENT)
1694 log_write ("%s: %s", buf, pwmd_strerror (errno));
1695 xfree (*pidfile);
1696 *pidfile = NULL;
1697 return -1;
1699 else if (!create && !terminate)
1700 return 0;
1702 log_write ("%s: %s", *pidfile, strerror (errno));
1703 return -1;
1706 if (create)
1708 snprintf (buf, buflen, "%i", getpid ());
1709 ssize_t ret = write (fd, buf, strlen (buf));
1710 if (ret == -1)
1711 log_write ("%s (%i): %s", __FUNCTION__, __LINE__,
1712 pwmd_strerror (gpg_error_from_syserror ()));
1713 close (fd);
1714 return 0;
1717 len = read (fd, buf, buflen);
1718 close (fd);
1719 if (len == 0)
1721 unlink_stale_socket (path, *pidfile);
1722 return 0;
1725 if (sscanf (buf, "%5i", &pid) != 1 || pid == 0)
1727 if (!terminate)
1729 unlink_stale_socket (path, *pidfile);
1730 return 0;
1734 if (kill (pid, 0) == -1)
1736 unlink_stale_socket (path, *pidfile);
1737 return 0;
1740 if (terminate)
1742 if (kill (pid, SIGTERM) == -1)
1743 log_write ("%s: %s", path, pwmd_strerror (errno));
1745 else
1746 log_write (_ ("an instance for socket %s is already running"), path);
1748 xfree (*pidfile);
1749 *pidfile = NULL;
1750 return 1;
1753 static unsigned
1754 parse_debug_level (const char *str, unsigned *debug, int *gpgme, int *tls)
1756 const char *p;
1757 unsigned level = 0;
1758 int gl = 0, tl = 0;
1760 for (p = str; p && *p; p++)
1762 if (*p == 'a') // assuan debug flags
1764 if (*++p != ':')
1765 return 1;
1767 while (*++p)
1769 switch (*p)
1771 case 'i':
1772 level |= ASSUAN_LOG_INIT;
1773 break;
1774 case 'x':
1775 level |= ASSUAN_LOG_CTX;
1776 break;
1777 case 'e':
1778 level |= ASSUAN_LOG_ENGINE;
1779 break;
1780 case 'd':
1781 level |= ASSUAN_LOG_DATA;
1782 break;
1783 case 's':
1784 level |= ASSUAN_LOG_SYSIO;
1785 break;
1786 case 'c':
1787 level |= ASSUAN_LOG_CONTROL;
1788 break;
1789 case ',':
1790 break;
1791 default:
1792 return 1;
1795 if (*p == ',')
1796 break;
1799 if (!*p)
1800 break;
1802 else if (*p == 'g' || *p == 't') // gpgme and TLS debug level
1804 int t = *p == 't';
1805 int n;
1807 if (*++p != ':')
1808 return 1;
1810 if (!isdigit (*++p))
1811 return 1;
1813 n = atoi (p);
1814 if (t)
1815 tl = n;
1816 else
1817 gl = n;
1819 if (tl < 0 || gl < 0 || gl > 9)
1820 return 1;
1822 while (isdigit (*p))
1823 p++;
1825 p--;
1826 if (*(p+1) && *(p+1) != ',')
1827 return 1;
1828 else if (*(p+1))
1829 p++;
1831 else
1832 return 1;
1835 if (tl)
1836 *tls = tl;
1838 if (gl)
1839 *gpgme = gl;
1841 *debug = level;
1842 return 0;
1846 main (int argc, char *argv[])
1848 int opt;
1849 struct sockaddr_un addr;
1850 char buf[PATH_MAX];
1851 char *socketpath = NULL, *socketdir, *socketname = NULL;
1852 char *socketarg = NULL;
1853 char *datadir = NULL;
1854 char *pidfile = NULL;
1855 mode_t mode = 0600;
1856 int x;
1857 char *p;
1858 char **cache_push = NULL;
1859 char *import = NULL, *keyid = NULL, *sign_keyid = NULL;
1860 char *userid = NULL;
1861 char *algo = NULL;
1862 long expire = 0;
1863 int no_passphrase = 0;
1864 int estatus = EXIT_FAILURE;
1865 int sockfd;
1866 char *outfile = NULL;
1867 int do_unlink = 0;
1868 int secure = 0;
1869 int show_version = 0;
1870 int force = 0;
1871 gpg_error_t rc;
1872 char *keyfile = NULL;
1873 int exists;
1874 int optindex;
1875 int terminate = 0;
1876 int sym = 0;
1877 int gpgme_level = -1;
1878 int tls_level = -1;
1879 int backlog = 0;
1880 /* Must maintain the same order as longopts[] */
1881 enum
1883 OPT_VERSION, OPT_HELP, OPT_HOMEDIR, OPT_NO_FORK, OPT_DISABLE_DUMP,
1884 OPT_FORCE, OPT_RCFILE, OPT_PASSPHRASE_FILE, OPT_IMPORT, OPT_OUTFILE,
1885 OPT_KEYID, OPT_SIGN_KEYID, OPT_SYMMETRIC, OPT_USERID, OPT_ALGO, OPT_EXPIRE,
1886 OPT_NOPASSPHRASE, OPT_KILL, OPT_DEBUG
1888 const char *optstring = "nf:C:k:I:o:s";
1889 const struct option longopts[] = {
1890 {"version", no_argument, 0, 0},
1891 {"help", no_argument, 0, 0},
1892 {"homedir", required_argument, 0, 0},
1893 {"no-fork", no_argument, 0, 'n'},
1894 {"disable_dump", no_argument, 0, 0},
1895 {"force", no_argument, 0, 0},
1896 {"rcfile", required_argument, 0, 'f'},
1897 {"passphrase-file", required_argument, 0, 'k'},
1898 {"import", required_argument, 0, 'I'},
1899 {"outfile", required_argument, 0, 'o'},
1900 {"keyid", required_argument, 0, 0},
1901 {"sign-keyid", required_argument, 0, 0},
1902 {"symmetric", no_argument, 0, 's'},
1903 {"userid", required_argument, 0, 0},
1904 {"algo", required_argument, 0, 0},
1905 {"expire", required_argument, 0, 0},
1906 {"no-passphrase", no_argument, 0, 0},
1907 {"kill", no_argument, 0, 0},
1908 {"debug", required_argument, 0, 0},
1909 {0, 0, 0, 0}
1912 log_fd = -1;
1913 cmdline = 1;
1914 expire = time (NULL) + DEFAULT_EXPIRE;
1916 #ifndef DEBUG
1917 #ifdef HAVE_SETRLIMIT
1918 struct rlimit rl;
1920 rl.rlim_cur = rl.rlim_max = 0;
1922 if (setrlimit (RLIMIT_CORE, &rl) != 0)
1923 err (EXIT_FAILURE, "setrlimit()");
1924 #endif
1926 #ifdef HAVE_PR_SET_DUMPABLE
1927 prctl (PR_SET_DUMPABLE, 0);
1928 #endif
1929 #endif
1931 #ifdef ENABLE_NLS
1932 setlocale (LC_ALL, "");
1933 bindtextdomain ("pwmd", LOCALEDIR);
1934 textdomain ("pwmd");
1935 #endif
1937 while ((opt = getopt_long (argc, argv, optstring, longopts, &optindex))
1938 != -1)
1940 switch (opt)
1942 case 'I':
1943 import = optarg;
1944 break;
1945 case 'k':
1946 keyfile = optarg;
1947 break;
1948 case 'o':
1949 outfile = optarg;
1950 break;
1951 case 'n':
1952 nofork = 1;
1953 break;
1954 case 'f':
1955 rcfile = str_dup (optarg);
1956 break;
1957 case 's':
1958 sym = 1;
1959 break;
1960 default:
1961 usage (argv[0], EXIT_FAILURE);
1962 break;
1963 case 0:
1964 switch (optindex)
1966 case OPT_DEBUG:
1967 if (parse_debug_level (optarg, &assuan_level, &gpgme_level,
1968 &tls_level))
1969 usage (argv[0], EXIT_FAILURE);
1970 break;
1971 case OPT_SYMMETRIC:
1972 sym = 1;
1973 break;
1974 case OPT_VERSION:
1975 show_version = 1;
1976 break;
1977 case OPT_HELP:
1978 usage (argv[0], EXIT_SUCCESS);
1979 break;
1980 case OPT_HOMEDIR:
1981 homedir = str_dup (optarg);
1982 break;
1983 case OPT_NO_FORK:
1984 nofork = 1;
1985 break;
1986 case OPT_DISABLE_DUMP:
1987 secure = 1;
1988 break;
1989 case OPT_FORCE:
1990 force = 1;
1991 break;
1992 case OPT_RCFILE:
1993 rcfile = str_dup (optarg);
1994 break;
1995 case OPT_PASSPHRASE_FILE:
1996 keyfile = optarg;
1997 break;
1998 case OPT_IMPORT:
1999 import = optarg;
2000 break;
2001 case OPT_OUTFILE:
2002 outfile = optarg;
2003 break;
2004 case OPT_KEYID:
2005 keyid = optarg;
2006 break;
2007 case OPT_SIGN_KEYID:
2008 sign_keyid = optarg;
2009 break;
2010 case OPT_USERID:
2011 userid = optarg;
2012 break;
2013 case OPT_ALGO:
2014 algo = optarg;
2015 break;
2016 case OPT_EXPIRE:
2017 errno = rc = 0;
2018 expire = strtoul (optarg, &p, 10);
2020 if (!errno && p && *p)
2021 rc = GPG_ERR_INV_VALUE;
2022 else if (expire == ULONG_MAX)
2023 rc = GPG_ERR_INV_VALUE;
2024 else if (errno)
2025 rc = gpg_error_from_syserror ();
2027 if (rc)
2028 usage (argv[0], EXIT_FAILURE);
2029 break;
2030 case OPT_NOPASSPHRASE:
2031 no_passphrase = 1;
2032 break;
2033 case OPT_KILL:
2034 terminate = 1;
2035 break;
2036 default:
2037 usage (argv[0], EXIT_FAILURE);
2042 if (show_version)
2044 printf (_("%s\n\n"
2045 "Copyright (C) 2006-2019\n"
2046 "%s\n"
2047 "Released under the terms of the GPL v2.\n\n"
2048 "Compile time features:\n%s"), PACKAGE_STRING,
2049 PACKAGE_BUGREPORT,
2050 #ifdef PWMD_HOMEDIR
2051 "+PWMD_HOMEDIR=" PWMD_HOMEDIR "\n"
2052 #endif
2053 #ifdef WITH_GNUTLS
2054 "+WITH_GNUTLS\n"
2055 #else
2056 "-WITH_GNUTLS\n"
2057 #endif
2058 #ifdef WITH_LIBACL
2059 "+WITH_LIBACL\n"
2060 #else
2061 "-WITH_LIBACL\n"
2062 #endif
2063 #ifdef DEBUG
2064 "+DEBUG\n"
2065 #else
2066 "-DEBUG\n"
2067 #endif
2068 #ifdef MEM_DEBUG
2069 "+MEM_DEBUG\n"
2070 #else
2071 "-MEM_DEBUG\n"
2072 #endif
2073 #ifdef MUTEX_DEBUG
2074 "+MUTEX_DEBUG\n"
2075 #else
2076 "-MUTEX_DEBUG\n"
2077 #endif
2079 exit (EXIT_SUCCESS);
2082 if (gpgme_level != -1)
2084 char s[2] = { gpgme_level + '0', 0 };
2086 if (getenv ("GPGME_DEBUG"))
2087 log_write (_ ("Overriding GPGME_DEBUG environment with level %u!"),
2088 gpgme_level);
2090 gpgme_set_global_flag ("debug", s);
2093 if (setup_crypto ())
2094 exit (EXIT_FAILURE);
2096 #ifdef WITH_GNUTLS
2097 tls_level = tls_level == -1 ? 1 : tls_level;
2098 gnutls_global_set_log_level (tls_level);
2099 tls_fd = -1;
2100 tls6_fd = -1;
2101 #endif
2102 xmlMemSetup (xfree, xmalloc, xrealloc, str_dup);
2103 xmlInitMemory ();
2104 xmlInitGlobals ();
2105 xmlInitParser ();
2106 xmlXPathInit ();
2108 if (!homedir)
2109 #ifdef PWMD_HOMEDIR
2110 homedir = str_dup(PWMD_HOMEDIR);
2111 #else
2112 homedir = str_asprintf ("%s/.pwmd", get_home_dir());
2113 #endif
2115 if (mkdir (homedir, 0700) == -1 && errno != EEXIST)
2116 err (EXIT_FAILURE, "%s", homedir);
2118 if (!rcfile)
2119 rcfile = str_asprintf ("%s/config", homedir);
2121 pthread_key_create (&last_error_key, free_key);
2122 #ifndef HAVE_PTHREAD_CANCEL
2123 pthread_key_create (&signal_thread_key, free_key);
2124 #endif
2126 pthread_mutexattr_t attr;
2127 pthread_mutexattr_init (&attr);
2128 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
2129 pthread_mutex_init (&rcfile_mutex, &attr);
2130 global_config = config_parse (rcfile, 0);
2131 if (!global_config)
2133 pthread_mutexattr_destroy (&attr);
2134 pthread_mutex_destroy (&rcfile_mutex);
2135 exit (EXIT_FAILURE);
2138 p = config_get_string ("global", "gpg_homedir");
2139 if (!p)
2140 datadir = str_asprintf ("%s/.gnupg", homedir);
2141 else
2142 datadir = expand_homedir (p);
2144 xfree (p);
2145 if (mkdir (datadir, 0700) == -1 && errno != EEXIST)
2146 err (EXIT_FAILURE, "%s", datadir);
2148 rc = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, NULL, datadir);
2149 if (rc)
2150 errx (EXIT_FAILURE, "%s: %s", datadir, pwmd_strerror (rc));
2151 xfree (datadir);
2153 snprintf (buf, sizeof (buf), "%s/data", homedir);
2154 if (mkdir (buf, 0700) == -1 && errno != EEXIST)
2155 err (EXIT_FAILURE, "%s", buf);
2157 datadir = str_dup (buf);
2158 pthread_cond_init (&rcfile_cond, NULL);
2159 pthread_mutex_init (&cn_mutex, &attr);
2160 pthread_mutexattr_destroy (&attr);
2162 setup_logging ();
2164 x = config_get_int_param (global_config, "global", "priority", &exists);
2165 if (exists && x != atoi(INVALID_PRIORITY))
2167 errno = 0;
2168 if (setpriority (PRIO_PROCESS, 0, x) == -1)
2170 log_write ("setpriority(): %s",
2171 pwmd_strerror (gpg_error_from_errno (errno)));
2172 goto do_exit;
2175 #ifdef HAVE_MLOCKALL
2176 if (disable_mlock == 0 && mlockall (MCL_CURRENT | MCL_FUTURE) == -1)
2178 log_write ("mlockall(): %s",
2179 pwmd_strerror (gpg_error_from_errno (errno)));
2180 goto do_exit;
2182 #endif
2184 rc = cache_init ();
2185 if (rc)
2187 log_write ("pwmd: ERR %i: %s", rc, pwmd_strerror (rc));
2188 exit (EXIT_FAILURE);
2191 if (import)
2193 char **keyids = NULL;
2195 if (!outfile || !*outfile || argc != optind)
2196 usage (argv[0], EXIT_FAILURE);
2198 if (keyid)
2199 keyids = str_split (keyid, ",", 0);
2200 else if (!userid && !sym)
2201 usage (argv[0], EXIT_FAILURE);
2203 rc = xml_import (import, outfile, keyids, sign_keyid, keyfile, userid,
2204 algo, expire, no_passphrase, sym);
2205 strv_free (keyids);
2206 if (rc)
2208 if (gpg_err_source (rc) == GPG_ERR_SOURCE_UNKNOWN)
2209 rc = gpg_error (rc);
2211 log_write ("%s: %u: %s", import, rc, pwmd_strerror (rc));
2214 config_free (global_config);
2215 xfree (rcfile);
2216 exit (rc ? EXIT_FAILURE : EXIT_SUCCESS);
2219 p = config_get_string ("global", "socket_path");
2220 if (!p)
2221 p = str_asprintf ("%s/socket", homedir);
2223 socketarg = expand_homedir (p);
2224 xfree (p);
2226 if (!secure)
2227 disable_list_and_dump = config_get_boolean ("global",
2228 "disable_list_and_dump");
2229 else
2230 disable_list_and_dump = secure;
2232 cache_push = config_get_list ("global", "cache_push");
2234 while (optind < argc)
2236 if (strv_printf (&cache_push, "%s", argv[optind++]) == 0)
2237 errx (EXIT_FAILURE, "%s", pwmd_strerror (GPG_ERR_ENOMEM));
2240 if (!strchr (socketarg, '/'))
2242 socketdir = getcwd (buf, sizeof (buf));
2243 socketname = str_dup (socketarg);
2244 socketpath = str_asprintf ("%s/%s", socketdir, socketname);
2246 else
2248 socketname = str_dup (strrchr (socketarg, '/')+1);
2249 socketarg[strlen (socketarg) - strlen (socketname) - 1] = 0;
2250 socketdir = str_dup (socketarg);
2251 socketpath = str_asprintf ("%s/%s", socketdir, socketname);
2254 if (chdir (datadir))
2256 log_write ("%s: %s", datadir,
2257 pwmd_strerror (gpg_error_from_errno (errno)));
2258 unlink (socketpath);
2259 goto do_exit;
2262 x = test_pidfile (socketpath, socketname, buf, sizeof(buf), &pidfile, 0,
2263 mode, terminate);
2264 if (!terminate && x)
2265 goto do_exit;
2266 else if (terminate)
2268 estatus = x != 1 ? EXIT_FAILURE : EXIT_SUCCESS;
2269 goto do_exit;
2273 * bind() doesn't like the full pathname of the socket or any non alphanum
2274 * characters so change to the directory where the socket is wanted then
2275 * create it then change to datadir.
2277 if (chdir (socketdir))
2279 log_write ("%s: %s", socketdir,
2280 pwmd_strerror (gpg_error_from_errno (errno)));
2281 goto do_exit;
2284 xfree (socketdir);
2286 if ((sockfd = socket (PF_UNIX, SOCK_STREAM, 0)) == -1)
2288 log_write ("socket(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2289 goto do_exit;
2292 addr.sun_family = AF_UNIX;
2293 snprintf (addr.sun_path, sizeof (addr.sun_path), "%s", socketname);
2294 do_unlink = 1;
2295 if (bind (sockfd, (struct sockaddr *) &addr, sizeof (struct sockaddr)) ==
2298 log_write ("bind(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2300 if (errno == EADDRINUSE)
2302 do_unlink = 0;
2303 log_write (_("Either there is another pwmd running or '%s' is a \n"
2304 "stale socket. Please remove it manually."), socketpath);
2307 goto do_exit;
2311 char *t = config_get_string ("global", "socket_perms");
2312 mode_t mask;
2314 if (t)
2316 mode = strtol (t, NULL, 8);
2317 mask = umask (0);
2318 xfree (t);
2320 if (chmod (socketname, mode) == -1)
2322 log_write ("%s: %s", socketname,
2323 pwmd_strerror (gpg_error_from_errno (errno)));
2324 close (sockfd);
2325 umask (mask);
2326 goto do_exit;
2329 umask (mask);
2333 if (chdir (datadir))
2335 log_write ("%s: %s", datadir,
2336 pwmd_strerror (gpg_error_from_errno (errno)));
2337 close (sockfd);
2338 goto do_exit;
2341 xfree (datadir);
2342 #ifdef WITH_GNUTLS
2343 if (config_get_boolean ("global", "enable_tcp"))
2345 if (!tls_start_stop (0))
2347 close (sockfd);
2348 goto do_exit;
2351 #endif
2354 * Set the cache entry for a file. Prompts for the password.
2356 if (cache_push)
2358 for (opt = 0; cache_push[opt]; opt++)
2360 struct crypto_s *crypto = NULL;
2361 char *pw_file = config_get_string (cache_push[opt],
2362 "passphrase_file");
2363 rc = crypto_init (&crypto, NULL, cache_push[opt], pw_file != NULL,
2364 pw_file);
2366 if (!rc)
2368 crypto->flags |= pw_file ? CRYPTO_FLAG_KEYFILE : 0;
2369 crypto->keyfile = pw_file;
2371 else
2372 xfree (pw_file);
2374 if (rc)
2376 estatus = EXIT_FAILURE;
2377 goto do_exit;
2380 rc = do_cache_push (crypto);
2381 if (rc && !force)
2383 log_write ("ERR %u: %s", rc, pwmd_strerror(rc));
2384 strv_free (cache_push);
2385 log_write (_ ("Failed to add a file to the cache. Use --force to force startup. Exiting."));
2386 cache_clear (NULL, NULL, 1, 0);
2387 estatus = EXIT_FAILURE;
2388 crypto_free (crypto);
2389 (void)cache_kill_scd ();
2390 goto do_exit;
2392 else if (rc)
2393 log_write ("%s: %s", crypto->filename, pwmd_strerror(rc));
2394 else
2395 log_write (_("Successfully added '%s' to the cache."),
2396 crypto->filename);
2398 crypto_free (crypto);
2401 (void)cache_kill_scd ();
2402 strv_free (cache_push);
2403 log_write (!nofork ? _("Done. Daemonizing...") :
2404 _("Done. Waiting for connections..."));
2407 backlog = config_get_integer ("global", "backlog");
2408 if (listen (sockfd, backlog) == -1)
2410 log_write ("listen(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2411 goto do_exit;
2414 /* A client should set these with the OPTION command. */
2415 unsetenv ("DISPLAY");
2416 unsetenv ("GPG_TTY");
2417 unsetenv ("TERM");
2419 if (!nofork)
2421 switch (fork ())
2423 case -1:
2424 log_write ("fork(): %s",
2425 pwmd_strerror (gpg_error_from_errno (errno)));
2426 goto do_exit;
2427 case 0:
2428 close (0);
2429 close (1);
2430 close (2);
2431 setsid ();
2432 break;
2433 default:
2434 _exit (EXIT_SUCCESS);
2438 (void)test_pidfile (socketpath, socketname, buf, sizeof(buf), &pidfile, 1,
2439 mode, 0);
2440 xfree (socketname);
2441 cmdline = 0;
2442 pthread_key_create (&thread_name_key, free_key);
2443 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
2444 estatus = server_loop (sockfd, &socketpath);
2446 do_exit:
2447 if (socketpath && do_unlink)
2449 unlink (socketpath);
2450 xfree (socketpath);
2453 xfree (socketarg);
2454 #ifdef WITH_GNUTLS
2455 gnutls_global_deinit ();
2456 tls_deinit_params ();
2457 #endif
2458 pthread_cond_destroy (&rcfile_cond);
2459 pthread_mutex_destroy (&rcfile_mutex);
2460 pthread_key_delete (last_error_key);
2461 #ifndef HAVE_PTHREAD_CANCEL
2462 pthread_key_delete (signal_thread_key);
2463 #endif
2465 if (global_config)
2466 config_free (global_config);
2468 free_invoking_users (invoking_users);
2469 xfree (rcfile);
2470 xfree (home_directory);
2471 xfree (homedir);
2472 xmlCleanupParser ();
2473 xmlCleanupGlobals ();
2475 if (pidfile)
2476 unlink (pidfile);
2477 xfree (pidfile);
2479 if (estatus == EXIT_SUCCESS && !terminate)
2480 log_write (_("pwmd exiting normally"));
2482 pthread_key_delete (thread_name_key);
2483 closelog ();
2485 if (log_fd != -1)
2486 close (log_fd);
2488 exit (estatus);
2491 gpg_error_t lock_flock (assuan_context_t ctx, const char *filename,
2492 int type, int *fd)
2494 gpg_error_t rc = 0;
2496 #ifdef HAVE_FLOCK
2497 rc = open_check_file (filename, fd, NULL, 1);
2498 if (rc)
2499 return rc;
2501 TRY_FLOCK (ctx, *fd, type, rc);
2502 if (rc)
2504 close (*fd);
2505 *fd = -1;
2507 #endif
2509 return rc;
2512 void unlock_flock (int *fd)
2514 #ifdef HAVE_FLOCK
2515 if (*fd != -1)
2516 close (*fd);
2518 *fd = -1;
2519 #endif