Append current git commit hash to version string.
[pwmd.git] / src / pwmd.c
blobb63e834353aede7e7bd3aa942ce72f1bd8a88dea
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"
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->bulk_p ? rc : assuan_process_done (client->ctx,rc)
228 gpg_error_t
229 send_error (assuan_context_t ctx, gpg_error_t e)
231 struct client_s *client = assuan_get_pointer (ctx);
233 if (gpg_err_source (e) == GPG_ERR_SOURCE_UNKNOWN)
234 e = gpg_error (e);
236 if (client)
237 client->last_rc = e;
239 if (!e)
240 return PROCESS_DONE (client, 0);
242 if (!ctx)
244 log_write ("ERR %i: %s", e, pwmd_strerror (e));
245 return e;
248 if (client && client->xml_error)
250 log_write ("%s", client->xml_error->message);
251 xfree (client->last_error);
252 client->last_error = NULL;
253 if (client->xml_error->message)
254 client->last_error = str_dup (client->xml_error->message);
256 e = PROCESS_DONE (client, assuan_set_error (ctx, e,
257 client->xml_error->message
258 ? client->xml_error->message
259 : NULL));
260 xmlResetLastError ();
261 xmlResetError (client->xml_error);
262 xfree (client->xml_error);
263 client->xml_error = NULL;
264 return e;
267 return PROCESS_DONE (client, assuan_set_error (ctx, e, pwmd_strerror (e)));
270 void
271 log_write (const char *fmt, ...)
273 char *args;
274 va_list ap;
275 time_t now;
276 char buf[255];
277 pthread_t tid = pthread_self ();
278 static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
280 if ((!logfile && !isatty (STDERR_FILENO) && !log_syslog) || !fmt)
281 return;
283 MUTEX_LOCK (&m);
284 pthread_cleanup_push (release_mutex_cb, &m);
286 if (!cmdline && logfile && log_fd == -1)
288 log_fd = open (logfile, O_WRONLY | O_CREAT | O_APPEND, 0600);
289 if (log_fd == -1)
290 warn ("%s", logfile);
293 va_start (ap, fmt);
295 if (str_vasprintf (&args, fmt, ap) != -1)
297 pthread_cleanup_push (xfree, args);
298 if (cmdline)
300 fprintf (stderr, "pwmd: %s\n", args);
301 fflush (stderr);
303 else
305 char *name = pthread_getspecific (thread_name_key);
306 char *line;
308 if (name)
310 if (*name == '!')
311 snprintf (buf, sizeof (buf), "%s: ", name+1);
312 else
313 snprintf (buf, sizeof (buf), "%s(%p): ", name,
314 (pthread_t *)tid);
316 else
317 snprintf (buf, sizeof (buf), "%p: ", (pthread_t *)tid);
319 name = buf;
320 if (!cmdline && log_syslog && !nofork)
321 syslog (LOG_INFO, "%s%s", name, args);
323 time (&now);
324 struct tm *tm = localtime (&now);
325 char tbuf[21];
326 strftime (tbuf, sizeof (tbuf), "%b %d %Y %H:%M:%S ", tm);
327 tbuf[sizeof (tbuf) - 1] = 0;
329 if (args[strlen (args) - 1] == '\n')
330 args[strlen (args) - 1] = 0;
332 line = str_asprintf ("%s %i %s%s\n", tbuf, getpid (), name, args);
333 if (line)
335 pthread_cleanup_push (xfree, line);
336 if (logfile && log_fd != -1)
338 ssize_t ret = write (log_fd, line, strlen (line));
339 (void)ret;
340 fsync (log_fd);
343 if (nofork)
345 fprintf (stdout, "%s", line);
346 fflush (stdout);
349 pthread_cleanup_pop (1);
352 pthread_cleanup_pop (1);
355 va_end (ap);
357 if (log_fd != -1 && log_keepopen <= 0)
359 close(log_fd);
360 log_fd = -1;
363 pthread_cleanup_pop (1);
366 static gpg_error_t
367 setup_crypto ()
369 gpg_error_t rc;
371 if (!gpgrt_check_version (REQUIRE_LIBGPGERROR_VERSION))
373 fprintf (stderr, _("gpgrt_check_version(): Incompatible libgpg-error. "
374 "Wanted %s, got %s.\n"), REQUIRE_LIBGPGERROR_VERSION,
375 gpgrt_check_version (NULL));
376 return GPG_ERR_UNKNOWN_VERSION;
379 gpgrt_init ();
380 gpgrt_set_alloc_func (xrealloc_gpgrt);
382 if (!assuan_check_version (REQUIRE_LIBASSUAN_VERSION))
384 fprintf (stderr, _("assuan_check_version(): Incompatible libassuan. "
385 "Wanted %s, got %s.\n"), REQUIRE_LIBASSUAN_VERSION,
386 assuan_check_version (NULL));
387 return GPG_ERR_UNKNOWN_VERSION;
390 if (!gcry_check_version (REQUIRE_LIBGCRYPT_VERSION))
392 fprintf (stderr, _("gcry_check_version(): Incompatible libgcrypt. "
393 "Wanted %s, got %s.\n"), REQUIRE_LIBGCRYPT_VERSION,
394 gcry_check_version (NULL));
395 return GPG_ERR_UNKNOWN_VERSION;
398 gcry_set_allocation_handler (xmalloc, xmalloc, NULL, xrealloc, xfree);
400 if (!gpgme_check_version (REQUIRE_LIBGPGME_VERSION))
402 fprintf (stderr, _("gpgme_check_version(): Incompatible libgpgme. "
403 "Wanted %s, got %s.\n"), REQUIRE_LIBGPGME_VERSION,
404 gpgme_check_version (NULL));
405 return GPG_ERR_UNKNOWN_VERSION;
408 rc = gpgme_engine_check_version (GPGME_PROTOCOL_OPENPGP);
409 if (rc)
411 fprintf (stderr, _("gpgme_engine_check_version(GPGME_PROTOCOL_OPENPGP): %s"), gpgme_strerror (rc));
412 return GPG_ERR_UNKNOWN_VERSION;
415 //gpgme_set_global_flag ("require-gnupg", REQUIRE_GNUPG_VERSION);
416 #ifdef ENABLE_NLS
417 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
418 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
419 #endif
421 #ifdef WITH_GNUTLS
422 if (gnutls_global_init ())
424 fprintf(stderr, _("gnutls_global_init() failed.\n"));
425 return GPG_ERR_UNKNOWN_VERSION;
428 if (!gnutls_check_version (REQUIRE_LIBGNUTLS_VERSION))
430 fprintf (stderr, _("gnutls_check_version(): Incompatible libgnutls. "
431 "Wanted %s, got %s.\n"), REQUIRE_LIBGNUTLS_VERSION,
432 gnutls_check_version (NULL));
433 return GPG_ERR_UNKNOWN_VERSION;
436 gnutls_global_set_log_function (tls_log);
437 gnutls_global_set_audit_log_function (tls_audit_log);
438 #endif
439 return 0;
442 static void
443 xml_error_cb (void *data, xmlErrorPtr e)
445 struct client_s *client = data;
448 * Keep the first reported error as the one to show in the error
449 * description. Reset in send_error().
451 if (client->xml_error)
452 return;
454 client->xml_error = xcalloc (1, sizeof(xmlError));
455 xmlCopyError (e, client->xml_error);
458 static pid_t
459 hook_waitpid (assuan_context_t ctx, pid_t pid, int action,
460 int *status, int options)
462 (void)ctx;
463 (void)action;
464 return waitpid (pid, status, options);
467 static ssize_t
468 hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len)
470 TEST_CANCEL ();
471 #ifdef WITH_GNUTLS
472 struct client_s *client = assuan_get_pointer (ctx);
474 if (client->thd->remote)
475 return tls_read_hook (ctx, (int) fd, data, len);
476 #else
477 (void)ctx;
478 #endif
479 return read ((int) fd, data, len);
482 static ssize_t
483 hook_write (assuan_context_t ctx, assuan_fd_t fd,
484 const void *data, size_t len)
486 TEST_CANCEL ();
487 #ifdef WITH_GNUTLS
488 struct client_s *client = assuan_get_pointer (ctx);
490 if (client->thd->remote)
491 return tls_write_hook (ctx, (int) fd, data, len);
492 #else
493 (void)ctx;
494 #endif
495 return write ((int) fd, data, len);
499 assuan_log_cb (assuan_context_t ctx, void *data, unsigned cat,
500 const char *msg)
502 struct client_s *client = data;
503 const char *str = NULL;
505 (void)client;
506 (void)ctx;
508 if (!(assuan_level & cat))
509 return 0;
511 if (!msg)
512 return 1;
514 switch (cat)
516 case ASSUAN_LOG_INIT:
517 str = "ASSUAN[INIT]";
518 break;
519 case ASSUAN_LOG_CTX:
520 str = "ASSUAN[CTX]";
521 break;
522 case ASSUAN_LOG_ENGINE:
523 str = "ASSUAN[ENGINE]";
524 break;
525 case ASSUAN_LOG_DATA:
526 str = "ASSUAN[DATA]";
527 break;
528 case ASSUAN_LOG_SYSIO:
529 str = "ASSUAN[SYSIO]";
530 break;
531 case ASSUAN_LOG_CONTROL:
532 str = "ASSUAN[CONTROL]";
533 break;
534 default:
535 str = "ASSUAN[UNKNOWN]";
536 break;
539 log_write ("%s: %s", str, msg);
540 return 1;
543 static int
544 new_connection (struct client_s *cl)
546 gpg_error_t rc;
547 static struct assuan_malloc_hooks mhooks = { xmalloc, xrealloc, xfree };
548 static struct assuan_system_hooks shooks = {
549 ASSUAN_SYSTEM_HOOKS_VERSION,
550 __assuan_usleep,
551 __assuan_pipe,
552 __assuan_close,
553 hook_read,
554 hook_write,
555 //FIXME
556 NULL, //recvmsg
557 NULL, //sendmsg both are used for FD passing
558 __assuan_spawn,
559 hook_waitpid,
560 __assuan_socketpair,
561 __assuan_socket,
562 __assuan_connect
565 #ifdef WITH_GNUTLS
566 if (cl->thd->remote)
568 char *prio = config_get_string ("global", "tls_cipher_suite");
570 cl->thd->timeout = config_get_integer ("global", "tls_timeout");
571 if (fcntl (cl->thd->fd, F_SETFL, O_NONBLOCK) == -1)
572 return 0;
574 cl->thd->tls = tls_init_client (cl->thd->fd, cl->thd->timeout, prio);
575 xfree (prio);
576 if (!cl->thd->tls)
577 return 0;
579 #endif
581 rc = assuan_new_ext (&cl->ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks,
582 assuan_log_cb, cl);
583 if (rc)
584 goto fail;
586 assuan_ctx_set_system_hooks (cl->ctx, &shooks);
587 rc = assuan_init_socket_server (cl->ctx, cl->thd->fd,
588 ASSUAN_SOCKET_SERVER_ACCEPTED);
589 if (rc)
590 goto fail;
592 assuan_set_pointer (cl->ctx, cl);
593 assuan_set_hello_line (cl->ctx, PACKAGE_STRING PWMD_GIT_HASH);
594 rc = register_commands (cl->ctx);
595 if (rc)
596 goto fail;
598 rc = assuan_accept (cl->ctx);
599 if (rc)
600 goto fail;
602 rc = validate_peer (cl);
603 /* May not be implemented on all platforms. */
604 if (rc && gpg_err_code (rc) != GPG_ERR_ASS_GENERAL)
605 goto fail;
607 MUTEX_LOCK (&cn_mutex);
608 cl->thd->state = CLIENT_STATE_INIT;
609 MUTEX_UNLOCK (&cn_mutex);
610 cl->lock_timeout = config_get_integer ("global", "lock_timeout");
611 xmlSetStructuredErrorFunc (cl, xml_error_cb);
612 return 1;
614 fail:
615 log_write ("%s", pwmd_strerror (rc));
616 return 0;
620 * This is called after a client is cancelled or disconnects. Set with
621 * pthread_cleanup_push().
623 static void
624 free_client_cb (void *arg)
626 struct client_thread_s *cn = arg;
627 struct client_s *cl = cn->cl;
628 char *tmp = NULL;
630 #ifndef HAVE_PTHREAD_CANCEL
631 tmp = pthread_getspecific (signal_thread_key);
632 xfree (tmp);
633 pthread_setspecific (signal_thread_key, NULL);
634 #endif
636 MUTEX_LOCK (&cn_mutex);
637 cn_thread_list = slist_remove (cn_thread_list, cn);
638 MUTEX_UNLOCK (&cn_mutex);
640 if (cl)
642 unlock_flock (&cl->flock_fd);
643 reset_client (cl);
644 if (cl->xml_error)
645 xmlResetError (cl->xml_error);
647 xfree (cl->xml_error);
649 #ifdef WITH_GNUTLS
650 if (cn->tls)
652 gnutls_deinit (cn->tls->ses);
653 xfree (cn->tls->fp);
654 xfree (cn->tls);
656 #endif
658 if (cl->ctx)
659 assuan_release (cl->ctx);
660 else if (cl->thd && cl->thd->fd != -1)
661 close (cl->thd->fd);
663 if (cl->crypto)
664 crypto_free (cl->crypto);
666 cl->crypto = NULL;
667 xfree (cl);
669 else
671 if (cn->fd != -1)
672 close (cn->fd);
675 while (cn->msg_queue)
677 struct status_msg_s *msg = cn->msg_queue;
679 cn->msg_queue = msg->next;
680 xfree (msg->line);
681 xfree (msg);
684 if (cn->status_msg_pipe[0] != -1)
685 close (cn->status_msg_pipe[0]);
687 if (cn->status_msg_pipe[1] != -1)
688 close (cn->status_msg_pipe[1]);
690 pthread_mutex_destroy (&cn->status_mutex);
691 log_write (_("exiting, fd=%i"), cn->fd);
692 send_status_all (STATUS_CLIENTS, NULL);
694 xfree (cn->name);
695 #ifdef WITH_GNUTLS
696 xfree (cn->peeraddr);
697 #endif
699 if (cn->eof) // Not pthread_exit() or pthread_cancel().
701 tmp = pthread_getspecific (thread_name_key);
702 xfree (tmp);
703 pthread_setspecific (thread_name_key, NULL);
706 (void)cache_kill_scd ();
707 xfree (cn);
710 static void
711 free_all_clients ()
713 MUTEX_LOCK (&cn_mutex);
714 pthread_cleanup_push (release_mutex_cb, &cn_mutex);
716 while (slist_length (cn_thread_list))
718 struct client_thread_s *thd = slist_nth_data (cn_thread_list, 0);
720 free_client_cb (thd);
721 thd->eof = 1;
724 pthread_cleanup_pop (1);
727 static gpg_error_t
728 send_msg_queue (struct client_thread_s *thd)
730 MUTEX_LOCK (&thd->status_mutex);
731 gpg_error_t rc = 0;
732 char c;
733 ssize_t ret;
735 ret = read (thd->status_msg_pipe[0], &c, 1);
736 rc = gpg_error_from_syserror ();
737 if (ret == -1 && gpg_err_code (rc) != GPG_ERR_EAGAIN)
738 log_write ("%s (%i): %s", __FUNCTION__, __LINE__, pwmd_strerror (rc));
739 else
740 rc = 0;
742 thd->wrote_status = 0;
744 while (thd->msg_queue)
746 struct status_msg_s *msg = thd->msg_queue;
748 thd->msg_queue = thd->msg_queue->next;
749 MUTEX_UNLOCK (&thd->status_mutex);
750 pthread_cleanup_push (xfree, msg);
751 pthread_cleanup_push (xfree, msg->line);
752 rc = send_status (thd->cl->ctx, msg->s, msg->line);
753 pthread_cleanup_pop (1);
754 pthread_cleanup_pop (1);
755 MUTEX_LOCK (&thd->status_mutex);
756 if (rc)
757 break;
760 MUTEX_UNLOCK (&thd->status_mutex);
761 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
762 log_write ("%s (%i): %s", __FUNCTION__, __LINE__, pwmd_strerror (rc));
764 return rc;
767 static void *
768 client_thread (void *data)
770 struct client_thread_s *thd = data;
771 struct client_s *cl = xcalloc (1, sizeof (struct client_s));
772 struct slist_s *list;
773 gpg_error_t rc = 0;
774 #ifndef HAVE_PTHREAD_CANCEL
775 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
776 #endif
778 #ifdef HAVE_PR_SET_NAME
779 prctl (PR_SET_NAME, "client");
780 #endif
781 pthread_setspecific (thread_name_key, str_dup (__FUNCTION__));
783 if (!cl)
785 log_write ("%s(%i): %s", __FILE__, __LINE__,
786 pwmd_strerror (GPG_ERR_ENOMEM));
787 return NULL;
790 MUTEX_LOCK (&cn_mutex);
791 pthread_cleanup_push (free_client_cb, thd);
792 thd->cl = cl;
793 cl->thd = thd;
794 cl->flock_fd = -1;
796 list = slist_append (cn_thread_list, thd);
797 if (list)
798 cn_thread_list = list;
799 else
801 log_write ("%s(%i): %s", __FILE__, __LINE__,
802 pwmd_strerror (GPG_ERR_ENOMEM));
803 MUTEX_UNLOCK (&cn_mutex);
804 return NULL;
807 if (fcntl (thd->status_msg_pipe[0], F_SETFL, O_NONBLOCK) == -1)
808 rc = gpg_error_from_errno (errno);
810 if (!rc)
811 if (fcntl (thd->status_msg_pipe[1], F_SETFL, O_NONBLOCK) == -1)
812 rc = gpg_error_from_errno (errno);
814 MUTEX_UNLOCK (&cn_mutex);
816 if (rc)
818 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
819 goto done;
822 if (new_connection (cl))
824 struct pollfd fds[2];
826 fds[0].fd = thd->fd;
827 fds[0].events = POLLIN;
828 fds[1].fd = thd->status_msg_pipe[0];
829 fds[1].events = POLLIN;
831 send_status_all (STATUS_CLIENTS, NULL);
832 rc = send_status (cl->ctx, STATUS_CACHE, NULL);
833 if (rc)
835 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
836 goto done;
839 for (;;)
841 int n;
842 int eof;
844 n = poll (fds, sizeof(fds)/sizeof(fds[0]), 100);
845 if (n == -1)
847 log_write ("%s", strerror (errno));
848 break;
851 #ifdef WITH_GNUTLS
852 if (thd->remote && thd->tls && thd->tls->rehandshake)
854 char *prio;
855 int ret;
856 const char *e;
858 if (thd->tls->rehandshake == 1)
860 prio = config_get_string ("global", "tls_cipher_suite");
861 if (!prio)
863 thd->tls->rehandshake = 0;
864 continue;
867 ret = gnutls_priority_set_direct (thd->tls->ses, prio, &e);
868 if (ret == GNUTLS_E_SUCCESS)
870 rc = send_status (cl->ctx, STATUS_REHANDSHAKE, NULL);
871 if (!rc)
873 rc = assuan_send_data (cl->ctx, NULL, 0);
874 if (!rc)
876 ret = gnutls_rehandshake (thd->tls->ses);
877 if (ret)
879 log_write ("%s", gnutls_strerror (ret));
880 thd->tls->rehandshake = 0;
882 else
883 thd->tls->rehandshake = 2;
887 if (rc)
888 log_write ("%s", pwmd_strerror (rc));
890 else
891 log_write ("%s: %s", gnutls_strerror (ret), e);
893 xfree (prio);
894 continue;
897 #endif
899 if (!n)
900 continue;
902 if (fds[1].revents & POLLIN)
904 #ifdef WITH_GNUTLS
905 if (!thd->remote || (thd->tls && !thd->tls->rehandshake))
906 #endif
908 rc = send_msg_queue (thd);
909 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
910 break;
914 #ifdef HAVE_PTHREAD_CANCEL
915 if (!(fds[0].revents & POLLIN))
916 #else
917 if (thd->fd != -1 && !(fds[0].revents & POLLIN))
918 #endif
919 continue;
921 rc = assuan_process_next (cl->ctx, &eof);
922 if (rc || eof)
924 if (gpg_err_code (rc) == GPG_ERR_EOF || eof)
925 break;
927 log_write ("assuan_process_next(): rc=%u %s", rc,
928 pwmd_strerror (rc));
929 if (rc == gpg_error (GPG_ERR_ETIMEDOUT))
930 break;
932 rc = send_error (cl->ctx, rc);
933 if (rc)
935 log_write ("assuan_process_done(): rc=%u %s", rc,
936 pwmd_strerror (rc));
937 break;
941 /* Since the msg queue pipe fd's are non-blocking, check for
942 * pending status msgs here. GPG_ERR_EPIPE can be seen when the
943 * client has already disconnected and will be converted to
944 * GPG_ERR_EOF during assuan_process_next().
946 #ifdef WITH_GNUTLS
947 if (!thd->remote || (thd->tls && !thd->tls->rehandshake))
948 #endif
950 rc = send_msg_queue (thd);
951 if (rc && gpg_err_code (rc) != GPG_ERR_EPIPE)
952 break;
957 done:
958 /* Don't do pthread_exit() here because any set pthread_cleanup_push
959 * functions would be called after a command failed but then the client
960 * exited normally which may lead to a double free. */
961 thd->eof = 1;
962 pthread_cleanup_pop (1);
963 return NULL;
966 static gpg_error_t
967 xml_import (const char *filename, const char *outfile, char **keyid,
968 char *sign_keyid, char *keyfile, const char *userid,
969 const char *algo, long expire, int no_passphrase, int symmetric)
971 xmlDocPtr doc;
972 int fd;
973 struct stat st;
974 int len;
975 xmlChar *xmlbuf = NULL;
976 gpg_error_t rc = 0;
977 struct crypto_s *crypto = NULL;
979 if (strcmp (filename, "-"))
981 rc = open_check_file (filename, &fd, &st, 0);
982 if (rc)
983 return rc;
985 xmlbuf = xmalloc (st.st_size + 1);
986 if (!xmlbuf)
988 close (fd);
989 return GPG_ERR_ENOMEM;
992 if (read (fd, xmlbuf, st.st_size) == -1)
994 rc = gpg_error_from_errno (errno);
995 close (fd);
996 xfree (xmlbuf);
997 return rc;
1000 xmlbuf[st.st_size] = 0;
1001 close (fd);
1003 else
1005 #define BUFSIZE 8196
1006 size_t size = 0, xlen = 0;
1008 for (;;)
1010 size_t ret;
1011 xmlChar *tmp;
1013 tmp = xrealloc (xmlbuf, size+BUFSIZE+1);
1014 if (!tmp)
1016 xfree (xmlbuf);
1017 return GPG_ERR_ENOMEM;
1020 xmlbuf = tmp;
1021 size += BUFSIZE;
1022 ret = read (STDIN_FILENO, &xmlbuf[xlen], BUFSIZE);
1023 if (ret == -1)
1025 rc = gpg_error_from_syserror ();
1026 xfree (xmlbuf);
1027 return rc;
1030 xlen += ret;
1031 if (!ret || ret < BUFSIZE)
1032 break;
1035 xmlbuf[xlen] = 0;
1038 doc = xmlReadDoc (xmlbuf, NULL, "UTF-8", XML_PARSE_NOBLANKS);
1039 xfree (xmlbuf);
1040 if (!doc)
1041 return GPG_ERR_BAD_DATA;
1043 xmlNodePtr n = xmlDocGetRootElement (doc);
1044 if (n && !xmlStrEqual (n->name, (xmlChar *) "pwmd"))
1045 rc = GPG_ERR_BAD_DATA;
1047 if (!rc)
1049 rc = xml_validate_import (NULL, n ? n->children : n);
1050 if (!rc)
1052 rc = crypto_init (&crypto, NULL, filename, keyfile != NULL, keyfile);
1053 if (!rc)
1055 if (keyfile)
1057 crypto->flags |= CRYPTO_FLAG_KEYFILE;
1058 crypto->keyfile = str_dup (keyfile);
1061 xmlDocDumpMemory (doc, &crypto->plaintext, &len);
1062 if (len > 0)
1063 crypto->plaintext_size = len;
1064 else
1065 rc = GPG_ERR_ENOMEM;
1070 if (!rc)
1072 if (!symmetric && !keyid)
1074 crypto->save.userid = str_dup (userid);
1075 crypto->save.algo = algo ? str_dup (algo) : NULL;
1076 crypto->save.expire = expire;
1077 if (no_passphrase)
1078 crypto->save.flags |= GPGME_CREATE_NOPASSWD;
1080 rc = crypto_genkey (NULL, crypto);
1082 else
1084 if (keyid)
1085 crypto->save.pubkey = strv_dup (keyid);
1087 if (sign_keyid)
1088 crypto->save.sigkey = str_dup (sign_keyid);
1091 if (!rc)
1093 crypto->flags |= symmetric ? CRYPTO_FLAG_SYMMETRIC : 0;
1094 rc = crypto_encrypt (NULL, crypto);
1098 if (!rc)
1100 if (!strcmp (outfile, "-"))
1101 outfile = NULL;
1103 xfree (crypto->plaintext);
1104 crypto->plaintext = NULL;
1105 xfree (crypto->filename);
1106 crypto->filename = outfile ? str_dup (outfile) : NULL;
1107 rc = crypto_write_file (crypto, NULL, NULL);
1110 xmlFreeDoc (doc);
1111 crypto_free (crypto);
1112 return rc;
1115 static gpg_error_t
1116 do_cache_push (struct crypto_s *crypto)
1118 gpg_error_t rc;
1119 xmlDocPtr doc;
1120 struct cache_data_s *cdata;
1121 unsigned char *crc;
1122 size_t len;
1123 int fd = -1;
1125 log_write (_("Adding '%s' to the cache..."),
1126 crypto->filename);
1128 if (valid_filename (crypto->filename) == 0)
1130 log_write (_("%s: Invalid characters in filename"), crypto->filename);
1131 return GPG_ERR_INV_VALUE;
1134 rc = lock_flock (NULL, crypto->filename, LOCK_SH, &fd);
1135 if (!rc)
1136 rc = crypto_decrypt (NULL, crypto);
1137 if (rc)
1139 unlock_flock (&fd);
1140 return rc;
1143 rc = xml_parse_doc ((char *) crypto->plaintext, crypto->plaintext_size, &doc);
1144 if (rc)
1146 unlock_flock (&fd);
1147 log_write ("%s", pwmd_strerror (rc));
1148 return rc;
1151 cdata = xcalloc (1, sizeof (struct cache_data_s));
1152 if (!cdata)
1154 unlock_flock (&fd);
1155 xmlFreeDoc (doc);
1156 return GPG_ERR_ENOMEM;
1159 rc = get_checksum (crypto->filename, &crc, &len);
1160 unlock_flock (&fd);
1161 if (rc)
1163 xmlFreeDoc (doc);
1164 cache_free_data_once (cdata);
1165 return rc;
1168 cdata->crc = crc;
1169 rc = cache_encrypt (crypto);
1170 if (!rc)
1172 cdata->doc = crypto->plaintext;
1173 cdata->size = crypto->plaintext_size;
1174 crypto->plaintext = NULL;
1175 cdata->pubkey = crypto->pubkey;
1176 cdata->sigkey = crypto->sigkey;
1177 crypto->pubkey = NULL;
1178 crypto->sigkey = NULL;
1180 else
1182 xmlFreeDoc (doc);
1183 cache_free_data_once (cdata);
1184 return rc;
1187 long timeout = config_get_long (crypto->filename, "cache_timeout");
1188 rc = cache_add_file (crypto->filename, cdata, timeout);
1189 return rc;
1192 static gpg_error_t
1193 init_client (int fd, const char *addr)
1195 gpg_error_t rc = 0;
1196 struct client_thread_s *new = xcalloc (1, sizeof (struct client_thread_s));
1198 if (!new)
1200 close (fd);
1201 log_write ("%s: %s", __FUNCTION__, pwmd_strerror (ENOMEM));
1202 return GPG_ERR_ENOMEM;
1205 MUTEX_LOCK (&cn_mutex);
1206 pthread_cleanup_push (release_mutex_cb, &cn_mutex);
1207 new->conntime = time (NULL);
1209 if (pipe (new->status_msg_pipe) == -1)
1210 rc = gpg_error_from_errno (errno);
1211 else
1212 pthread_mutex_init (&new->status_mutex, NULL);
1214 if (!rc)
1216 #ifdef WITH_GNUTLS
1217 new->remote = addr ? 1 : 0;
1218 if (addr)
1219 new->peeraddr = str_dup (addr);
1220 #endif
1221 new->fd = fd;
1222 rc = create_thread (client_thread, new, &new->tid, 1);
1223 if (rc)
1225 close (new->status_msg_pipe[0]);
1226 close (new->status_msg_pipe[1]);
1227 pthread_mutex_destroy (&new->status_mutex);
1231 if (!rc)
1233 if (addr)
1234 log_write (_("new connection: tid=%p, fd=%i, addr=%s"),
1235 (pthread_t *) new->tid, fd, addr);
1236 else
1237 log_write (_("new connection: tid=%p, fd=%i"),
1238 (pthread_t *) new->tid, fd);
1241 pthread_cleanup_pop (1);
1243 if (rc)
1245 xfree (new);
1246 close (fd);
1247 log_write ("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror (rc));
1249 return rc;
1252 #ifdef WITH_GNUTLS
1253 static gpg_error_t
1254 do_tls_accept (struct pollfd *fds)
1256 struct sockaddr_storage raddr;
1257 socklen_t slen = sizeof (raddr);
1258 int fd;
1259 char s[INET6_ADDRSTRLEN];
1261 if (!(fds->revents & POLLIN))
1262 return 0;
1264 memset (&raddr, 0, sizeof (raddr));
1265 fd = accept (fds->fd, (struct sockaddr *) &raddr, &slen);
1266 if (fd == -1)
1268 int e = errno;
1270 if (errno != EAGAIN && !quit)
1271 log_write ("%s: %s", __FUNCTION__,
1272 pwmd_strerror (gpg_error_from_syserror()));
1274 return gpg_error_from_errno (e);
1277 inet_ntop (raddr.ss_family, get_in_addr ((struct sockaddr *) &raddr), s,
1278 sizeof s);
1279 (void) init_client (fd, s);
1280 return 0;
1282 #endif
1284 static void *
1285 accept_thread (void *arg)
1287 int sockfd = *(int *) arg;
1288 #ifndef HAVE_PTHREAD_CANCEL
1289 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
1290 #endif
1292 #ifdef HAVE_PR_SET_NAME
1293 prctl (PR_SET_NAME, "accept");
1294 #endif
1295 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
1297 for (;;)
1299 socklen_t slen = sizeof (struct sockaddr_un);
1300 struct sockaddr_un raddr;
1301 int fd, s = 0;
1302 struct pollfd fds[3];
1304 TEST_CANCEL ();
1305 memset (fds, 0, sizeof (fds));
1306 fds[s].fd = sockfd;
1307 fds[s++].events = POLLIN;
1309 #ifdef WITH_GNUTLS
1310 if (tls_fd != -1)
1312 fds[s].fd = tls_fd;
1313 fds[s++].events = POLLIN;
1315 else
1316 fds[s].fd = tls_fd;
1318 if (tls6_fd != -1)
1320 fds[s].fd = tls6_fd;
1321 fds[s++].events = POLLIN;
1323 else
1324 fds[s].fd = tls6_fd;
1325 #endif
1327 s = poll (fds, s, 500);
1328 if (s == -1)
1330 if (errno != EINTR)
1331 log_write ("%s", strerror (errno));
1332 break;
1334 else if (s == 0)
1335 continue;
1337 if (fds[0].revents & POLLIN)
1339 fd = accept (sockfd, (struct sockaddr *) &raddr, &slen);
1340 if (fd == -1)
1342 if (errno == EMFILE || errno == ENFILE)
1343 log_write ("%s: %s", __FUNCTION__,
1344 pwmd_strerror (gpg_error_from_errno (errno)));
1345 else if (errno != EAGAIN && errno != EINTR)
1347 if (!quit) // probably EBADF
1348 log_write ("%s: %s", __FUNCTION__,
1349 pwmd_strerror (gpg_error_from_errno (errno)));
1351 break;
1354 continue;
1357 (void) init_client (fd, NULL);
1360 #ifdef WITH_GNUTLS
1361 if (tls_fd != -1 && fds[1].fd == tls_fd)
1362 (void)do_tls_accept (&fds[1]);
1364 if (tls6_fd != -1 && fds[1].fd == tls6_fd)
1365 (void)do_tls_accept (&fds[1]);
1367 if (tls6_fd != -1 && fds[2].fd == tls6_fd)
1368 (void)do_tls_accept (&fds[2]);
1369 #endif
1372 /* Just in case accept() failed for some reason other than EBADF */
1373 quit = 1;
1374 return NULL;
1377 static void *
1378 cache_timer_thread (void *arg)
1380 unsigned k = 0;
1381 #ifndef HAVE_PTHREAD_CANCEL
1382 INIT_SIGNAL (SIGUSR2, catch_thread_signal);
1383 #endif
1385 (void)arg;
1387 #ifdef HAVE_PR_SET_NAME
1388 prctl (PR_SET_NAME, "timer");
1389 #endif
1390 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
1392 for (;;)
1394 struct timeval tv = { 1, 0 };
1395 unsigned keepalive = config_get_integer ("global", "keepalive_interval");
1397 TEST_CANCEL ();
1398 select (0, NULL, NULL, NULL, &tv);
1399 cache_adjust_timeout ();
1401 if (keepalive && ++k >= keepalive)
1403 send_status_all (STATUS_KEEPALIVE, NULL);
1404 k = 0;
1408 return NULL;
1411 static int
1412 signal_loop (sigset_t sigset)
1414 int done = 0;
1418 int sig;
1420 sigwait (&sigset, &sig);
1421 log_write (_("caught signal %i (%s)"), sig, strsignal (sig));
1423 switch (sig)
1425 case SIGHUP:
1426 pthread_cond_signal (&rcfile_cond);
1427 break;
1428 case SIGUSR1:
1429 log_write (_("clearing file cache"));
1430 cache_clear (NULL, NULL, 1, 0);
1431 send_status_all (STATUS_CACHE, NULL);
1432 break;
1433 default:
1434 done = 1;
1435 break;
1438 while (!done);
1440 return done;
1443 static void
1444 catchsig (int sig)
1446 log_write (_ ("Caught signal %i (%s). Exiting."), sig, strsignal (sig));
1447 #ifdef HAVE_BACKTRACE
1448 BACKTRACE (__FUNCTION__);
1449 #endif
1450 longjmp (jmp, 1);
1453 static void
1454 cancel_all_clients ()
1456 unsigned i, t;
1458 MUTEX_LOCK (&cn_mutex);
1459 t = slist_length (cn_thread_list);
1460 for (i = 0; i < t; i++)
1462 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
1464 #ifdef HAVE_PTHREAD_CANCEL
1465 pthread_cancel (thd->tid);
1466 #else
1467 pthread_kill (thd->tid, SIGUSR2);
1468 #endif
1471 while (slist_length (cn_thread_list))
1473 MUTEX_UNLOCK (&cn_mutex);
1474 usleep (50000);
1475 MUTEX_LOCK (&cn_mutex);
1478 MUTEX_UNLOCK (&cn_mutex);
1481 static int
1482 server_loop (int sockfd, char **socketpath)
1484 pthread_t cache_timeout_tid;
1485 pthread_t accept_tid;
1486 int cancel_timeout_thread = 0;
1487 int cancel_accept_thread = 0;
1488 int cancel_rcfile_thread = 0;
1489 sigset_t sigset;
1490 int n;
1491 int segv = 0;
1492 gpg_error_t rc;
1494 init_commands ();
1495 sigemptyset (&sigset);
1497 /* Termination */
1498 sigaddset (&sigset, SIGTERM);
1499 sigaddset (&sigset, SIGINT);
1501 /* Clears the file cache. */
1502 sigaddset (&sigset, SIGUSR1);
1504 /* Configuration file reloading. */
1505 sigaddset (&sigset, SIGHUP);
1507 #ifndef HAVE_PTHREAD_CANCEL
1509 The socket, cache and rcfile threads use this signal when
1510 pthread_cancel() is unavailable. Prevent the main thread from
1511 catching this signal from another process.
1513 sigaddset (&sigset, SIGUSR2);
1514 #endif
1516 /* An assertion failure. */
1517 signal (SIGABRT, catchsig);
1519 sigaddset (&sigset, SIGABRT);
1520 sigprocmask (SIG_BLOCK, &sigset, NULL);
1522 #ifndef HAVE_PTHREAD_CANCEL
1523 /* Remove this signal from the watched signals in signal_loop(). */
1524 sigdelset (&sigset, SIGUSR2);
1525 #endif
1527 /* Can show a backtrace of the stack in the log. */
1528 signal (SIGSEGV, catchsig);
1530 char *p = get_username (getuid());
1531 log_write (_("%s started for user %s"), PACKAGE_STRING PWMD_GIT_HASH, p);
1532 xfree (p);
1534 #ifdef WITH_GNUTLS
1535 if (config_get_boolean ("global", "enable_tcp"))
1536 log_write (_("Listening on %s and TCP port %i"), *socketpath,
1537 config_get_integer ("global", "tcp_port"));
1538 else
1539 log_write (_("Listening on %s"), *socketpath);
1540 #else
1541 log_write (_("Listening on %s"), *socketpath);
1542 #endif
1544 rc = create_thread (reload_rcfile_thread, NULL, &rcfile_tid, 0);
1545 if (rc)
1547 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1548 pwmd_strerror (rc));
1549 goto done;
1552 cancel_rcfile_thread = 1;
1553 rc = create_thread (cache_timer_thread, NULL, &cache_timeout_tid, 0);
1554 if (rc)
1556 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1557 pwmd_strerror (rc));
1558 goto done;
1561 cancel_timeout_thread = 1;
1562 rc = create_thread (accept_thread, &sockfd, &accept_tid, 0);
1563 if (rc)
1565 log_write ("%s(%i): pthread_create(): %s", __FILE__, __LINE__,
1566 pwmd_strerror (rc));
1567 goto done;
1570 cancel_accept_thread = 1;
1571 if (!setjmp (jmp))
1572 signal_loop (sigset);
1573 else
1574 segv = 1;
1576 done:
1578 * We're out of the main server loop. This happens when a signal was sent
1579 * to terminate the daemon. Cancel all clients and exit.
1581 if (cancel_accept_thread)
1583 #ifdef HAVE_PTHREAD_CANCEL
1584 n = pthread_cancel (accept_tid);
1585 #else
1586 n = pthread_kill (accept_tid, SIGUSR2);
1587 #endif
1588 if (!n)
1589 pthread_join (accept_tid, NULL);
1592 if (cancel_timeout_thread)
1594 #ifdef HAVE_PTHREAD_CANCEL
1595 n = pthread_cancel (cache_timeout_tid);
1596 #else
1597 n = pthread_kill (cache_timeout_tid, SIGUSR2);
1598 #endif
1599 if (!n)
1600 pthread_join (cache_timeout_tid, NULL);
1603 #ifdef WITH_GNUTLS
1604 tls_start_stop (1);
1605 #endif
1606 shutdown (sockfd, SHUT_RDWR);
1607 close (sockfd);
1608 unlink (*socketpath);
1609 xfree (*socketpath);
1610 *socketpath = NULL;
1611 MUTEX_LOCK (&cn_mutex);
1612 n = slist_length (cn_thread_list);
1613 MUTEX_UNLOCK (&cn_mutex);
1615 if (n && !segv)
1616 cancel_all_clients ();
1617 else
1618 free_all_clients ();
1620 if (cancel_rcfile_thread)
1622 #ifdef HAVE_PTHREAD_CANCEL
1623 pthread_cancel (rcfile_tid);
1624 #else
1625 pthread_kill (rcfile_tid, SIGUSR2);
1626 pthread_cond_signal (&rcfile_cond);
1627 #endif
1628 pthread_join (rcfile_tid, NULL);
1631 cache_deinit ();
1632 deinit_commands ();
1633 return segv ? EXIT_FAILURE : EXIT_SUCCESS;
1636 static void
1637 usage (const char *pn, int status)
1639 FILE *fp = status == EXIT_FAILURE ? stderr : stdout;
1641 fprintf (fp, _("Usage: %s [OPTIONS] [file1] [...]\n"
1642 " --homedir alternate pwmd home directory (~/.pwmd)\n"
1643 " -f, --rcfile=filename load the specfied configuration file\n"
1644 " (~/.pwmd/config)\n"
1645 " --kill terminate an existing instance of pwmd\n"
1646 " -n, --no-fork run as a foreground process\n"
1647 " --disable-dump disable the LIST, XPATH and DUMP commands\n"
1648 " --ignore, --force ignore cache pushing errors during startup\n"
1649 " -I, --import=filename import a pwmd DTD formatted XML file)\n"
1650 " -k, --passphrase-file=file for use when importing\n"
1651 " -o, --outfile=filename output file when importing\n"
1652 " --keyid=fpr[,..] public key to use when encrypting\n"
1653 " --sign-keyid=fpr fingerprint of the signing key to use\n"
1654 " -s, --symmetric use conventional encryption with optional signer\n"
1655 " --userid=string name and email address to use when importing\n"
1656 " --algo=string algorithm to use when importing (engine default)\n"
1657 " --expire=seconds key expiry time when importing (3 years)\n"
1658 " --no-passphrase don't require a passphrase when importing\n"
1659 " --debug=[a:..][,g:N][,t:N] enable debugging (a:[ixedsc],g:[1-9],t:[0-N])\n"
1660 " --help this help text\n"
1661 " --version show version and compile time features\n"),
1662 pn);
1663 exit (status);
1666 static void
1667 unlink_stale_socket (const char *sock, const char *pidfile)
1669 log_write (_ ("removing stale socket %s"), sock);
1670 unlink (sock);
1671 unlink (pidfile);
1674 static int
1675 test_pidfile (const char *path, const char *sock, char *buf, size_t buflen,
1676 char **pidfile, int create, mode_t mode, int terminate)
1678 pid_t pid;
1679 int fd;
1680 size_t len;
1682 if (!create)
1684 snprintf (buf, buflen, "%s/%s.pid", homedir, sock);
1685 *pidfile = str_dup (buf);
1686 fd = open (buf, O_RDONLY);
1688 else
1689 fd = open (*pidfile, O_CREAT|O_WRONLY|O_TRUNC, mode);
1691 if (fd == -1)
1693 if (!create && errno != ENOENT)
1695 log_write ("%s: %s", buf, pwmd_strerror (errno));
1696 xfree (*pidfile);
1697 *pidfile = NULL;
1698 return -1;
1700 else if (!create && !terminate)
1701 return 0;
1703 log_write ("%s: %s", *pidfile, strerror (errno));
1704 return -1;
1707 if (create)
1709 snprintf (buf, buflen, "%i", getpid ());
1710 ssize_t ret = write (fd, buf, strlen (buf));
1711 if (ret == -1)
1712 log_write ("%s (%i): %s", __FUNCTION__, __LINE__,
1713 pwmd_strerror (gpg_error_from_syserror ()));
1714 close (fd);
1715 return 0;
1718 len = read (fd, buf, buflen);
1719 close (fd);
1720 if (len == 0)
1722 unlink_stale_socket (path, *pidfile);
1723 return 0;
1726 if (sscanf (buf, "%5i", &pid) != 1 || pid == 0)
1728 if (!terminate)
1730 unlink_stale_socket (path, *pidfile);
1731 return 0;
1735 if (kill (pid, 0) == -1)
1737 unlink_stale_socket (path, *pidfile);
1738 return 0;
1741 if (terminate)
1743 if (kill (pid, SIGTERM) == -1)
1744 log_write ("%s: %s", path, pwmd_strerror (errno));
1746 else
1747 log_write (_ ("an instance for socket %s is already running"), path);
1749 xfree (*pidfile);
1750 *pidfile = NULL;
1751 return 1;
1754 static unsigned
1755 parse_debug_level (const char *str, unsigned *debug, int *gpgme, int *tls)
1757 const char *p;
1758 unsigned level = 0;
1759 int gl = 0, tl = 0;
1761 for (p = str; p && *p; p++)
1763 if (*p == 'a') // assuan debug flags
1765 if (*++p != ':')
1766 return 1;
1768 while (*++p)
1770 switch (*p)
1772 case 'i':
1773 level |= ASSUAN_LOG_INIT;
1774 break;
1775 case 'x':
1776 level |= ASSUAN_LOG_CTX;
1777 break;
1778 case 'e':
1779 level |= ASSUAN_LOG_ENGINE;
1780 break;
1781 case 'd':
1782 level |= ASSUAN_LOG_DATA;
1783 break;
1784 case 's':
1785 level |= ASSUAN_LOG_SYSIO;
1786 break;
1787 case 'c':
1788 level |= ASSUAN_LOG_CONTROL;
1789 break;
1790 case ',':
1791 break;
1792 default:
1793 return 1;
1796 if (*p == ',')
1797 break;
1800 if (!*p)
1801 break;
1803 else if (*p == 'g' || *p == 't') // gpgme and TLS debug level
1805 int t = *p == 't';
1806 int n;
1808 if (*++p != ':')
1809 return 1;
1811 if (!isdigit (*++p))
1812 return 1;
1814 n = atoi (p);
1815 if (t)
1816 tl = n;
1817 else
1818 gl = n;
1820 if (tl < 0 || gl < 0 || gl > 9)
1821 return 1;
1823 while (isdigit (*p))
1824 p++;
1826 p--;
1827 if (*(p+1) && *(p+1) != ',')
1828 return 1;
1829 else if (*(p+1))
1830 p++;
1832 else
1833 return 1;
1836 if (tl)
1837 *tls = tl;
1839 if (gl)
1840 *gpgme = gl;
1842 *debug = level;
1843 return 0;
1847 main (int argc, char *argv[])
1849 int opt;
1850 struct sockaddr_un addr;
1851 char buf[PATH_MAX];
1852 char *socketpath = NULL, *socketdir, *socketname = NULL;
1853 char *socketarg = NULL;
1854 char *datadir = NULL;
1855 char *pidfile = NULL;
1856 mode_t mode = 0600;
1857 int x;
1858 char *p;
1859 char **cache_push = NULL;
1860 char *import = NULL, *keyid = NULL, *sign_keyid = NULL;
1861 char *userid = NULL;
1862 char *algo = NULL;
1863 long expire = 0;
1864 int no_passphrase = 0;
1865 int estatus = EXIT_FAILURE;
1866 int sockfd;
1867 char *outfile = NULL;
1868 int do_unlink = 0;
1869 int secure = 0;
1870 int show_version = 0;
1871 int force = 0;
1872 gpg_error_t rc;
1873 char *keyfile = NULL;
1874 int exists;
1875 int optindex;
1876 int terminate = 0;
1877 int sym = 0;
1878 int gpgme_level = -1;
1879 int tls_level = -1;
1880 int backlog = 0;
1881 /* Must maintain the same order as longopts[] */
1882 enum
1884 OPT_VERSION, OPT_HELP, OPT_HOMEDIR, OPT_NO_FORK, OPT_DISABLE_DUMP,
1885 OPT_FORCE, OPT_RCFILE, OPT_PASSPHRASE_FILE, OPT_IMPORT, OPT_OUTFILE,
1886 OPT_KEYID, OPT_SIGN_KEYID, OPT_SYMMETRIC, OPT_USERID, OPT_ALGO, OPT_EXPIRE,
1887 OPT_NOPASSPHRASE, OPT_KILL, OPT_DEBUG
1889 const char *optstring = "nf:C:k:I:o:s";
1890 const struct option longopts[] = {
1891 {"version", no_argument, 0, 0},
1892 {"help", no_argument, 0, 0},
1893 {"homedir", required_argument, 0, 0},
1894 {"no-fork", no_argument, 0, 'n'},
1895 {"disable_dump", no_argument, 0, 0},
1896 {"force", no_argument, 0, 0},
1897 {"rcfile", required_argument, 0, 'f'},
1898 {"passphrase-file", required_argument, 0, 'k'},
1899 {"import", required_argument, 0, 'I'},
1900 {"outfile", required_argument, 0, 'o'},
1901 {"keyid", required_argument, 0, 0},
1902 {"sign-keyid", required_argument, 0, 0},
1903 {"symmetric", no_argument, 0, 's'},
1904 {"userid", required_argument, 0, 0},
1905 {"algo", required_argument, 0, 0},
1906 {"expire", required_argument, 0, 0},
1907 {"no-passphrase", no_argument, 0, 0},
1908 {"kill", no_argument, 0, 0},
1909 {"debug", required_argument, 0, 0},
1910 {0, 0, 0, 0}
1913 log_fd = -1;
1914 cmdline = 1;
1915 expire = time (NULL) + DEFAULT_EXPIRE;
1917 #ifndef DEBUG
1918 #ifdef HAVE_SETRLIMIT
1919 struct rlimit rl;
1921 rl.rlim_cur = rl.rlim_max = 0;
1923 if (setrlimit (RLIMIT_CORE, &rl) != 0)
1924 err (EXIT_FAILURE, "setrlimit()");
1925 #endif
1927 #ifdef HAVE_PR_SET_DUMPABLE
1928 prctl (PR_SET_DUMPABLE, 0);
1929 #endif
1930 #endif
1932 #ifdef ENABLE_NLS
1933 setlocale (LC_ALL, "");
1934 bindtextdomain ("pwmd", LOCALEDIR);
1935 textdomain ("pwmd");
1936 #endif
1938 while ((opt = getopt_long (argc, argv, optstring, longopts, &optindex))
1939 != -1)
1941 switch (opt)
1943 case 'I':
1944 import = optarg;
1945 break;
1946 case 'k':
1947 keyfile = optarg;
1948 break;
1949 case 'o':
1950 outfile = optarg;
1951 break;
1952 case 'n':
1953 nofork = 1;
1954 break;
1955 case 'f':
1956 rcfile = str_dup (optarg);
1957 break;
1958 case 's':
1959 sym = 1;
1960 break;
1961 default:
1962 usage (argv[0], EXIT_FAILURE);
1963 break;
1964 case 0:
1965 switch (optindex)
1967 case OPT_DEBUG:
1968 if (parse_debug_level (optarg, &assuan_level, &gpgme_level,
1969 &tls_level))
1970 usage (argv[0], EXIT_FAILURE);
1971 break;
1972 case OPT_SYMMETRIC:
1973 sym = 1;
1974 break;
1975 case OPT_VERSION:
1976 show_version = 1;
1977 break;
1978 case OPT_HELP:
1979 usage (argv[0], EXIT_SUCCESS);
1980 break;
1981 case OPT_HOMEDIR:
1982 homedir = str_dup (optarg);
1983 break;
1984 case OPT_NO_FORK:
1985 nofork = 1;
1986 break;
1987 case OPT_DISABLE_DUMP:
1988 secure = 1;
1989 break;
1990 case OPT_FORCE:
1991 force = 1;
1992 break;
1993 case OPT_RCFILE:
1994 rcfile = str_dup (optarg);
1995 break;
1996 case OPT_PASSPHRASE_FILE:
1997 keyfile = optarg;
1998 break;
1999 case OPT_IMPORT:
2000 import = optarg;
2001 break;
2002 case OPT_OUTFILE:
2003 outfile = optarg;
2004 break;
2005 case OPT_KEYID:
2006 keyid = optarg;
2007 break;
2008 case OPT_SIGN_KEYID:
2009 sign_keyid = optarg;
2010 break;
2011 case OPT_USERID:
2012 userid = optarg;
2013 break;
2014 case OPT_ALGO:
2015 algo = optarg;
2016 break;
2017 case OPT_EXPIRE:
2018 errno = rc = 0;
2019 expire = strtoul (optarg, &p, 10);
2021 if (!errno && p && *p)
2022 rc = GPG_ERR_INV_VALUE;
2023 else if (expire == ULONG_MAX)
2024 rc = GPG_ERR_INV_VALUE;
2025 else if (errno)
2026 rc = gpg_error_from_syserror ();
2028 if (rc)
2029 usage (argv[0], EXIT_FAILURE);
2030 break;
2031 case OPT_NOPASSPHRASE:
2032 no_passphrase = 1;
2033 break;
2034 case OPT_KILL:
2035 terminate = 1;
2036 break;
2037 default:
2038 usage (argv[0], EXIT_FAILURE);
2043 if (show_version)
2045 printf (_("%s\n\n"
2046 "Copyright (C) 2006-2019\n"
2047 "%s\n"
2048 "Released under the terms of the GPL v2.\n\n"
2049 "Compile time features:\n%s"), PACKAGE_STRING PWMD_GIT_HASH,
2050 PACKAGE_BUGREPORT,
2051 #ifdef PWMD_HOMEDIR
2052 "+PWMD_HOMEDIR=" PWMD_HOMEDIR "\n"
2053 #endif
2054 #ifdef WITH_GNUTLS
2055 "+WITH_GNUTLS\n"
2056 #else
2057 "-WITH_GNUTLS\n"
2058 #endif
2059 #ifdef WITH_LIBACL
2060 "+WITH_LIBACL\n"
2061 #else
2062 "-WITH_LIBACL\n"
2063 #endif
2064 #ifdef DEBUG
2065 "+DEBUG\n"
2066 #else
2067 "-DEBUG\n"
2068 #endif
2069 #ifdef MEM_DEBUG
2070 "+MEM_DEBUG\n"
2071 #else
2072 "-MEM_DEBUG\n"
2073 #endif
2074 #ifdef MUTEX_DEBUG
2075 "+MUTEX_DEBUG\n"
2076 #else
2077 "-MUTEX_DEBUG\n"
2078 #endif
2080 exit (EXIT_SUCCESS);
2083 if (gpgme_level != -1)
2085 char s[2] = { gpgme_level + '0', 0 };
2087 if (getenv ("GPGME_DEBUG"))
2088 log_write (_ ("Overriding GPGME_DEBUG environment with level %u!"),
2089 gpgme_level);
2091 gpgme_set_global_flag ("debug", s);
2094 if (setup_crypto ())
2095 exit (EXIT_FAILURE);
2097 #ifdef WITH_GNUTLS
2098 tls_level = tls_level == -1 ? 1 : tls_level;
2099 gnutls_global_set_log_level (tls_level);
2100 tls_fd = -1;
2101 tls6_fd = -1;
2102 #endif
2103 xmlMemSetup (xfree, xmalloc, xrealloc, str_dup);
2104 xmlInitMemory ();
2105 xmlInitGlobals ();
2106 xmlInitParser ();
2107 xmlXPathInit ();
2109 if (!homedir)
2110 #ifdef PWMD_HOMEDIR
2111 homedir = str_dup(PWMD_HOMEDIR);
2112 #else
2113 homedir = str_asprintf ("%s/.pwmd", get_home_dir());
2114 #endif
2116 if (mkdir (homedir, 0700) == -1 && errno != EEXIST)
2117 err (EXIT_FAILURE, "%s", homedir);
2119 if (!rcfile)
2120 rcfile = str_asprintf ("%s/config", homedir);
2122 pthread_key_create (&last_error_key, free_key);
2123 #ifndef HAVE_PTHREAD_CANCEL
2124 pthread_key_create (&signal_thread_key, free_key);
2125 #endif
2127 pthread_mutexattr_t attr;
2128 pthread_mutexattr_init (&attr);
2129 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
2130 pthread_mutex_init (&rcfile_mutex, &attr);
2131 global_config = config_parse (rcfile, 0);
2132 if (!global_config)
2134 pthread_mutexattr_destroy (&attr);
2135 pthread_mutex_destroy (&rcfile_mutex);
2136 exit (EXIT_FAILURE);
2139 p = config_get_string ("global", "gpg_homedir");
2140 if (!p)
2141 datadir = str_asprintf ("%s/.gnupg", homedir);
2142 else
2143 datadir = expand_homedir (p);
2145 xfree (p);
2146 if (mkdir (datadir, 0700) == -1 && errno != EEXIST)
2147 err (EXIT_FAILURE, "%s", datadir);
2149 rc = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP, NULL, datadir);
2150 if (rc)
2151 errx (EXIT_FAILURE, "%s: %s", datadir, pwmd_strerror (rc));
2152 xfree (datadir);
2154 snprintf (buf, sizeof (buf), "%s/data", homedir);
2155 if (mkdir (buf, 0700) == -1 && errno != EEXIST)
2156 err (EXIT_FAILURE, "%s", buf);
2158 datadir = str_dup (buf);
2159 pthread_cond_init (&rcfile_cond, NULL);
2160 pthread_mutex_init (&cn_mutex, &attr);
2161 pthread_mutexattr_destroy (&attr);
2163 setup_logging ();
2165 x = config_get_int_param (global_config, "global", "priority", &exists);
2166 if (exists && x != atoi(INVALID_PRIORITY))
2168 errno = 0;
2169 if (setpriority (PRIO_PROCESS, 0, x) == -1)
2171 log_write ("setpriority(): %s",
2172 pwmd_strerror (gpg_error_from_errno (errno)));
2173 goto do_exit;
2176 #ifdef HAVE_MLOCKALL
2177 if (disable_mlock == 0 && mlockall (MCL_CURRENT | MCL_FUTURE) == -1)
2179 log_write ("mlockall(): %s",
2180 pwmd_strerror (gpg_error_from_errno (errno)));
2181 goto do_exit;
2183 #endif
2185 rc = cache_init ();
2186 if (rc)
2188 log_write ("pwmd: ERR %i: %s", rc, pwmd_strerror (rc));
2189 exit (EXIT_FAILURE);
2192 if (import)
2194 char **keyids = NULL;
2196 if (!outfile || !*outfile || argc != optind)
2197 usage (argv[0], EXIT_FAILURE);
2199 if (keyid)
2200 keyids = str_split (keyid, ",", 0);
2201 else if (!userid && !sym)
2202 usage (argv[0], EXIT_FAILURE);
2204 rc = xml_import (import, outfile, keyids, sign_keyid, keyfile, userid,
2205 algo, expire, no_passphrase, sym);
2206 strv_free (keyids);
2207 if (rc)
2209 if (gpg_err_source (rc) == GPG_ERR_SOURCE_UNKNOWN)
2210 rc = gpg_error (rc);
2212 log_write ("%s: %u: %s", import, rc, pwmd_strerror (rc));
2215 config_free (global_config);
2216 xfree (rcfile);
2217 exit (rc ? EXIT_FAILURE : EXIT_SUCCESS);
2220 p = config_get_string ("global", "socket_path");
2221 if (!p)
2222 p = str_asprintf ("%s/socket", homedir);
2224 socketarg = expand_homedir (p);
2225 xfree (p);
2227 if (!secure)
2228 disable_list_and_dump = config_get_boolean ("global",
2229 "disable_list_and_dump");
2230 else
2231 disable_list_and_dump = secure;
2233 cache_push = config_get_list ("global", "cache_push");
2235 while (optind < argc)
2237 if (strv_printf (&cache_push, "%s", argv[optind++]) == 0)
2238 errx (EXIT_FAILURE, "%s", pwmd_strerror (GPG_ERR_ENOMEM));
2241 if (!strchr (socketarg, '/'))
2243 socketdir = getcwd (buf, sizeof (buf));
2244 socketname = str_dup (socketarg);
2245 socketpath = str_asprintf ("%s/%s", socketdir, socketname);
2247 else
2249 socketname = str_dup (strrchr (socketarg, '/')+1);
2250 socketarg[strlen (socketarg) - strlen (socketname) - 1] = 0;
2251 socketdir = str_dup (socketarg);
2252 socketpath = str_asprintf ("%s/%s", socketdir, socketname);
2255 if (chdir (datadir))
2257 log_write ("%s: %s", datadir,
2258 pwmd_strerror (gpg_error_from_errno (errno)));
2259 unlink (socketpath);
2260 goto do_exit;
2263 x = test_pidfile (socketpath, socketname, buf, sizeof(buf), &pidfile, 0,
2264 mode, terminate);
2265 if (!terminate && x)
2266 goto do_exit;
2267 else if (terminate)
2269 estatus = x != 1 ? EXIT_FAILURE : EXIT_SUCCESS;
2270 goto do_exit;
2274 * bind() doesn't like the full pathname of the socket or any non alphanum
2275 * characters so change to the directory where the socket is wanted then
2276 * create it then change to datadir.
2278 if (chdir (socketdir))
2280 log_write ("%s: %s", socketdir,
2281 pwmd_strerror (gpg_error_from_errno (errno)));
2282 goto do_exit;
2285 xfree (socketdir);
2287 if ((sockfd = socket (PF_UNIX, SOCK_STREAM, 0)) == -1)
2289 log_write ("socket(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2290 goto do_exit;
2293 addr.sun_family = AF_UNIX;
2294 snprintf (addr.sun_path, sizeof (addr.sun_path), "%s", socketname);
2295 do_unlink = 1;
2296 if (bind (sockfd, (struct sockaddr *) &addr, sizeof (struct sockaddr)) ==
2299 log_write ("bind(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2301 if (errno == EADDRINUSE)
2303 do_unlink = 0;
2304 log_write (_("Either there is another pwmd running or '%s' is a \n"
2305 "stale socket. Please remove it manually."), socketpath);
2308 goto do_exit;
2312 char *t = config_get_string ("global", "socket_perms");
2313 mode_t mask;
2315 if (t)
2317 mode = strtol (t, NULL, 8);
2318 mask = umask (0);
2319 xfree (t);
2321 if (chmod (socketname, mode) == -1)
2323 log_write ("%s: %s", socketname,
2324 pwmd_strerror (gpg_error_from_errno (errno)));
2325 close (sockfd);
2326 umask (mask);
2327 goto do_exit;
2330 umask (mask);
2334 if (chdir (datadir))
2336 log_write ("%s: %s", datadir,
2337 pwmd_strerror (gpg_error_from_errno (errno)));
2338 close (sockfd);
2339 goto do_exit;
2342 xfree (datadir);
2343 #ifdef WITH_GNUTLS
2344 if (config_get_boolean ("global", "enable_tcp"))
2346 if (!tls_start_stop (0))
2348 close (sockfd);
2349 goto do_exit;
2352 #endif
2355 * Set the cache entry for a file. Prompts for the password.
2357 if (cache_push)
2359 for (opt = 0; cache_push[opt]; opt++)
2361 struct crypto_s *crypto = NULL;
2362 char *pw_file = config_get_string (cache_push[opt],
2363 "passphrase_file");
2364 rc = crypto_init (&crypto, NULL, cache_push[opt], pw_file != NULL,
2365 pw_file);
2367 if (!rc)
2369 crypto->flags |= pw_file ? CRYPTO_FLAG_KEYFILE : 0;
2370 crypto->keyfile = pw_file;
2372 else
2373 xfree (pw_file);
2375 if (rc)
2377 estatus = EXIT_FAILURE;
2378 goto do_exit;
2381 rc = do_cache_push (crypto);
2382 if (rc && !force)
2384 log_write ("ERR %u: %s", rc, pwmd_strerror(rc));
2385 strv_free (cache_push);
2386 log_write (_ ("Failed to add a file to the cache. Use --force to force startup. Exiting."));
2387 cache_clear (NULL, NULL, 1, 0);
2388 estatus = EXIT_FAILURE;
2389 crypto_free (crypto);
2390 (void)cache_kill_scd ();
2391 goto do_exit;
2393 else if (rc)
2394 log_write ("%s: %s", crypto->filename, pwmd_strerror(rc));
2395 else
2396 log_write (_("Successfully added '%s' to the cache."),
2397 crypto->filename);
2399 crypto_free (crypto);
2402 (void)cache_kill_scd ();
2403 strv_free (cache_push);
2404 log_write (!nofork ? _("Done. Daemonizing...") :
2405 _("Done. Waiting for connections..."));
2408 backlog = config_get_integer ("global", "backlog");
2409 if (listen (sockfd, backlog) == -1)
2411 log_write ("listen(): %s", pwmd_strerror (gpg_error_from_errno (errno)));
2412 goto do_exit;
2415 /* A client should set these with the OPTION command. */
2416 unsetenv ("DISPLAY");
2417 unsetenv ("GPG_TTY");
2418 unsetenv ("TERM");
2420 if (!nofork)
2422 switch (fork ())
2424 case -1:
2425 log_write ("fork(): %s",
2426 pwmd_strerror (gpg_error_from_errno (errno)));
2427 goto do_exit;
2428 case 0:
2429 close (0);
2430 close (1);
2431 close (2);
2432 setsid ();
2433 break;
2434 default:
2435 _exit (EXIT_SUCCESS);
2439 (void)test_pidfile (socketpath, socketname, buf, sizeof(buf), &pidfile, 1,
2440 mode, 0);
2441 xfree (socketname);
2442 cmdline = 0;
2443 pthread_key_create (&thread_name_key, free_key);
2444 pthread_setspecific (thread_name_key, str_asprintf ("!%s", __FUNCTION__));
2445 estatus = server_loop (sockfd, &socketpath);
2447 do_exit:
2448 if (socketpath && do_unlink)
2450 unlink (socketpath);
2451 xfree (socketpath);
2454 xfree (socketarg);
2455 #ifdef WITH_GNUTLS
2456 gnutls_global_deinit ();
2457 tls_deinit_params ();
2458 #endif
2459 pthread_cond_destroy (&rcfile_cond);
2460 pthread_mutex_destroy (&rcfile_mutex);
2461 pthread_key_delete (last_error_key);
2462 #ifndef HAVE_PTHREAD_CANCEL
2463 pthread_key_delete (signal_thread_key);
2464 #endif
2466 if (global_config)
2467 config_free (global_config);
2469 free_invoking_users (invoking_users);
2470 xfree (rcfile);
2471 xfree (home_directory);
2472 xfree (homedir);
2473 xmlCleanupParser ();
2474 xmlCleanupGlobals ();
2476 if (pidfile)
2477 unlink (pidfile);
2478 xfree (pidfile);
2480 if (estatus == EXIT_SUCCESS && !terminate)
2481 log_write (_("pwmd exiting normally"));
2483 pthread_key_delete (thread_name_key);
2484 closelog ();
2486 if (log_fd != -1)
2487 close (log_fd);
2489 xfree (logfile);
2490 exit (estatus);
2493 gpg_error_t lock_flock (assuan_context_t ctx, const char *filename,
2494 int type, int *fd)
2496 gpg_error_t rc = 0;
2498 #ifdef HAVE_FLOCK
2499 rc = open_check_file (filename, fd, NULL, 1);
2500 if (rc)
2501 return rc;
2503 TRY_FLOCK (ctx, *fd, type, rc);
2504 if (rc)
2506 close (*fd);
2507 *fd = -1;
2509 #endif
2511 return rc;
2514 void unlock_flock (int *fd)
2516 #ifdef HAVE_FLOCK
2517 if (*fd != -1)
2518 close (*fd);
2520 *fd = -1;
2521 #endif