1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2006-2008 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
38 #include <glib/gprintf.h>
45 #include <netinet/in.h>
46 #include <arpa/inet.h>
51 #include <sys/resource.h>
75 #include "pwmd_error.h"
80 GCRY_THREAD_OPTION_PTH_IMPL
;
82 static void clear_errorfile_key()
88 groups
= g_key_file_get_groups(keyfileh
, &n
);
90 for (p
= groups
; *p
; p
++) {
93 if (g_key_file_has_key(keyfileh
, *p
, "key", &rc
) == TRUE
)
94 g_key_file_set_string(keyfileh
, *p
, "key", "");
100 static void reload_rcfile()
102 log_write(N_("reloading configuration file '%s'"), rcfile
);
103 g_key_file_free(keyfileh
);
104 keyfileh
= parse_rcfile(0);
105 clear_errorfile_key();
106 send_status_all(STATUS_CONFIG
);
109 gpg_error_t
send_syserror(assuan_context_t ctx
, gint e
)
111 gpg_error_t n
= gpg_error_from_errno(e
);
113 return assuan_process_done(ctx
, assuan_set_error(ctx
, n
, gpg_strerror(n
)));
116 gpg_error_t
send_error(assuan_context_t ctx
, gpg_error_t e
)
118 gpg_err_code_t n
= gpg_err_code(e
);
119 gpg_error_t code
= gpg_err_make(PWMD_ERR_SOURCE
, n
);
120 struct client_s
*client
= assuan_get_pointer(ctx
);
123 return assuan_process_done(ctx
, 0);
126 log_write("%s\n", pwmd_strerror(e
));
130 if (n
== EPWMD_LIBXML_ERROR
) {
131 xmlErrorPtr xe
= client
->xml_error
;
134 xe
= xmlGetLastError();
136 e
= assuan_process_done(ctx
, assuan_set_error(ctx
, code
, xe
->message
));
137 log_write("%s", xe
->message
);
139 if (xe
== client
->xml_error
)
144 client
->xml_error
= NULL
;
148 return assuan_process_done(ctx
, assuan_set_error(ctx
, code
, pwmd_strerror(e
)));
151 void log_write(const gchar
*fmt
, ...)
161 pth_t tid
= pth_self();
162 gchar tid_str
[12], *p
;
164 if ((!logfile
&& !isatty(STDERR_FILENO
) && log_syslog
== FALSE
) || !fmt
)
168 if ((fd
= open(logfile
, O_WRONLY
|O_CREAT
|O_APPEND
, 0600)) == -1) {
176 if (g_vasprintf(&args
, fmt
, ap
) == -1) {
184 attr
= pth_attr_of(tid
);
186 if (pth_attr_get(attr
, PTH_ATTR_NAME
, &name
) == FALSE
)
189 pth_attr_destroy(attr
);
190 g_snprintf(tid_str
, sizeof(tid_str
), "(%p)", tid
);
193 if (strncmp(p
+1, name
, 9) == 0)
196 if (log_syslog
== TRUE
)
197 syslog(LOG_INFO
, "%s%s: %s", name
, p
? p
: "", args
);
201 tm
= localtime(&now
);
202 strftime(tbuf
, sizeof(tbuf
), "%b %d %Y %H:%M:%S ", tm
);
203 tbuf
[sizeof(tbuf
) - 1] = 0;
205 if (args
[strlen(args
)-1] == '\n')
206 args
[strlen(args
)-1] = 0;
208 line
= g_strdup_printf("%s %i %s%s: %s\n", tbuf
, getpid(), name
,
220 write(fd
, line
, strlen(line
));
225 if (isatty(STDERR_FILENO
)) {
226 fprintf(stderr
, "%s", line
);
233 static void usage(gchar
*pn
)
235 g_fprintf(stderr
, N_(
236 "Usage: %s [-hvDn] [-f <rcfile>] [-C <filename> -o <outfile>]\n"
237 " [-I <filename> [-i <iter>] -o <outfile>] [file1] [...]\n"
238 " -n run as a foreground process\n"
239 " -f load the specified rcfile (~/.pwmd/config)\n"
240 " -I import an XML file\n"
241 " -i encrypt with the specified number of iterations when importing\n"
242 " (config default in the \"global\" section)\n"
243 " -D disable use of the LIST and DUMP commands\n"
244 " -C convert a version 1 data file to version 2\n"
246 " -h this help text\n"
252 static int gcry_SecureCheck(const void *ptr
)
258 static void setup_gcrypt()
260 gcry_check_version(NULL
);
263 gcry_set_allocation_handler(xmalloc
, xmalloc
, gcry_SecureCheck
, xrealloc
,
267 if (gcry_cipher_algo_info(GCRY_CIPHER_AES256
, GCRYCTL_TEST_ALGO
, NULL
,
269 errx(EXIT_FAILURE
, N_("Required AES cipher not supported by libgcrypt."));
271 gcry_cipher_algo_info(GCRY_CIPHER_AES256
, GCRYCTL_GET_KEYLEN
, NULL
, &gcrykeysize
);
272 gcry_cipher_algo_info(GCRY_CIPHER_AES256
, GCRYCTL_GET_BLKLEN
, NULL
, &gcryblocksize
);
275 static gint
new_connection(struct client_s
*cl
)
278 gchar ver
[ASSUAN_LINELENGTH
];
280 rc
= assuan_init_socket_server_ext(&cl
->ctx
, cl
->thd
->fd
, 2);
285 assuan_set_pointer(cl
->ctx
, cl
);
286 g_snprintf(ver
, sizeof(ver
), "%s", PACKAGE_STRING
);
287 assuan_set_hello_line(cl
->ctx
, ver
);
288 rc
= register_commands(cl
->ctx
);
293 rc
= assuan_accept(cl
->ctx
);
298 fcntl(cl
->thd
->fd
, F_SETFL
, O_NONBLOCK
);
302 log_write("%s", gpg_strerror(rc
));
306 gpg_error_t
send_status(assuan_context_t ctx
, status_msg_t which
)
309 struct client_s
*client
= assuan_get_pointer(ctx
);
310 gchar buf
[ASSUAN_LINELENGTH
];
311 gchar
*status
= NULL
;
315 CACHE_LOCK(client
->ctx
);
316 line
= print_fmt(buf
, sizeof(buf
), "%i %i",
318 (cache_size
% sizeof(file_cache_t
)) ?
319 (cache_size
/ sizeof(file_cache_t
)) - cache_file_count()-1 :
320 (cache_size
/ sizeof(file_cache_t
)) - cache_file_count());
325 pth_mutex_acquire(&cn_mutex
, FALSE
, NULL
);
326 line
= print_fmt(buf
, sizeof(buf
), "%i", g_slist_length(cn_thread_list
));
327 pth_mutex_release(&cn_mutex
);
333 case STATUS_KEEPALIVE
:
334 status
= "KEEPALIVE";
338 line
= N_("Waiting for lock");
342 return assuan_write_status(ctx
, status
, line
);
345 void send_status_all(status_msg_t which
)
349 pth_mutex_acquire(&cn_mutex
, FALSE
, NULL
);
351 for (t
= g_slist_length(cn_thread_list
), i
= 0; i
< t
; i
++) {
352 struct client_thread_s
*cn
= g_slist_nth_data(cn_thread_list
, i
);
353 pth_msgport_t m
= pth_msgport_find(cn
->msg_name
);
356 pth_message_t
*msg
= g_malloc0(sizeof(pth_message_t
));
358 msg
->m_data
= (status_msg_t
*)which
;
359 pth_msgport_put(m
, msg
);
363 pth_mutex_release(&cn_mutex
);
366 static void xml_error_cb(void *data
, xmlErrorPtr e
)
368 struct client_s
*client
= data
;
371 * Keep the first reported error as the one to show in the error
372 * description. Reset in send_error().
374 if (client
->xml_error
)
377 xmlCopyError(e
, client
->xml_error
);
381 * This is called after a child_thread terminates. Set with
382 * pth_cleanup_push().
384 static void cleanup_cb(void *arg
)
386 struct client_thread_s
*cn
= arg
;
388 struct client_s
*cl
= cn
->cl
;
390 pth_mutex_acquire(&cn_mutex
, FALSE
, NULL
);
391 log_write(N_("exiting, fd=%i"), cn
->fd
);
394 pth_cancel(cn
->msg_tid
);
395 pth_join(cn
->msg_tid
, &value
);
396 pth_event_free(cn
->msg_ev
, PTH_FREE_THIS
);
400 g_free(cn
->msg_name
);
403 while (pth_msgport_pending(cn
->msg
) > 0) {
404 pth_message_t
*m
= pth_msgport_get(cn
->msg
);
409 pth_msgport_destroy(cn
->msg
);
412 pth_join(cn
->tid
, &value
);
414 if (cl
&& cl
->freed
== FALSE
)
415 cleanup_assuan(cl
->ctx
);
418 assuan_deinit_server(cl
->ctx
);
421 if (cl
&& cl
->pinentry
)
422 cleanup_pinentry(cl
->pinentry
);
427 gnutls_deinit(cn
->tls
->ses
);
436 cn_thread_list
= g_slist_remove(cn_thread_list
, cn
);
438 pth_mutex_release(&cn_mutex
);
439 send_status_all(STATUS_CLIENTS
);
443 static int read_hook(assuan_context_t ctx
, assuan_fd_t fd
, void *data
,
444 size_t len
, ssize_t
*ret
)
446 struct client_s
*cl
= assuan_get_pointer(ctx
);
448 if (!cl
|| !cl
->thd
->remote
)
449 *ret
= pth_read((int)fd
, data
, len
);
452 *ret
= gnutls_record_recv(cl
->thd
->tls
->ses
, data
, len
);
454 if (*ret
== GNUTLS_E_REHANDSHAKE
) {
455 *ret
= gnutls_rehandshake(cl
->thd
->tls
->ses
);
457 if (*ret
== GNUTLS_E_WARNING_ALERT_RECEIVED
||
458 *ret
== GNUTLS_A_NO_RENEGOTIATION
) {
459 log_write("%s", gnutls_strerror(*ret
));
463 if (*ret
!= GNUTLS_E_SUCCESS
) {
464 log_write("%s", gnutls_strerror(*ret
));
469 *ret
= gnutls_handshake(cl
->thd
->tls
->ses
);
471 if (*ret
!= GNUTLS_E_SUCCESS
) {
472 log_write("%s", gnutls_strerror(*ret
));
479 } while (*ret
== GNUTLS_E_INTERRUPTED
|| *ret
== GNUTLS_E_AGAIN
);
482 return *ret
<= 0 ? 0 : 1;
485 static int write_hook(assuan_context_t ctx
, assuan_fd_t fd
, const void *data
,
486 size_t len
, ssize_t
*ret
)
488 struct client_s
*cl
= assuan_get_pointer(ctx
);
490 if (!cl
|| !cl
->thd
->remote
)
491 *ret
= pth_write((int)fd
, data
, len
);
494 *ret
= gnutls_record_send(cl
->thd
->tls
->ses
, data
, len
);
495 } while (*ret
== GNUTLS_E_INTERRUPTED
|| *ret
== GNUTLS_E_AGAIN
);
498 return *ret
<= 0 ? 0 : 1;
502 static void *client_msg_thread(void *data
)
504 struct client_s
*cl
= data
;
505 pth_status_t ev_status
;
508 pth_wait(cl
->thd
->msg_ev
);
509 ev_status
= pth_event_status(cl
->thd
->msg_ev
);
511 if (ev_status
== PTH_STATUS_FAILED
) {
512 log_write("%s(%i): %s: PTH_STATUS_FAILED", __FILE__
, __LINE__
,
517 if (ev_status
== PTH_STATUS_OCCURRED
) {
518 pth_mutex_acquire(&cn_mutex
, FALSE
, NULL
);
520 while (pth_msgport_pending(cl
->thd
->msg
) > 0) {
521 pth_message_t
*m
= pth_msgport_get(cl
->thd
->msg
);
522 status_msg_t n
= (status_msg_t
)m
->m_data
;
523 gpg_error_t rc
= send_status(cl
->ctx
, n
);
528 pth_mutex_release(&cn_mutex
);
529 log_write("%s", gpg_strerror(rc
));
534 pth_mutex_release(&cn_mutex
);
540 * Called every time a connection is made via pth_spawn(). This is the thread
543 static void *client_thread(void *data
)
545 struct client_thread_s
*thd
= data
;
547 struct client_s
*cl
= g_malloc0(sizeof(struct client_s
));
552 * Prevent a race condition with init_new_connection() if this thread
553 * fails (returns) for some reason before init_new_connection() releases
556 pth_mutex_acquire(&cn_mutex
, FALSE
, NULL
);
557 pth_mutex_release(&cn_mutex
);
560 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
566 pth_cleanup_push(cleanup_cb
, thd
);
570 * Do the TLS handshake before anything else.
573 thd
->tls
= tls_init(thd
->fd
);
583 * This is a "child" thread. Don't catch any signals. Let the master
584 * thread take care of signals in server_loop().
586 if (new_connection(cl
))
590 cl
->pinentry
= pinentry_init();
594 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
599 thd
->msg_name
= g_strdup_printf("%p", thd
->tid
);
601 if (!thd
->msg_name
) {
602 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
606 thd
->msg
= pth_msgport_create(thd
->msg_name
);
609 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
613 thd
->msg_ev
= pth_event(PTH_EVENT_MSG
, thd
->msg
);
614 attr
= pth_attr_new();
615 pth_attr_set(attr
, PTH_ATTR_PRIO
, PTH_PRIO_STD
);
616 thd
->msg_tid
= pth_spawn(attr
, client_msg_thread
, cl
);
617 pth_attr_destroy(attr
);
620 log_write(N_("pth_spawn() failed"));
625 if (disable_mlock
== FALSE
&& mlockall(MCL_FUTURE
) == -1) {
626 log_write("mlockall(): %s", strerror(errno
));
631 rc
= send_status(cl
->ctx
, STATUS_CACHE
);
634 log_write("%s", gpg_strerror(rc
));
638 send_status_all(STATUS_CLIENTS
);
639 ev
= pth_event(PTH_EVENT_FD
|PTH_UNTIL_FD_READABLE
, cl
->thd
->fd
);
642 xmlSetStructuredErrorFunc(cl
, xml_error_cb
);
645 pth_status_t ev_status
;
648 ev_status
= pth_event_status(ev
);
650 if (ev_status
== PTH_STATUS_FAILED
) {
651 log_write("%s(%i): %s: PTH_STATUS_FAILED", __FILE__
, __LINE__
,
655 else if (ev_status
== PTH_STATUS_OCCURRED
) {
656 rc
= assuan_process_next(cl
->ctx
);
659 cl
->inquire_status
= INQUIRE_INIT
;
661 if (gpg_err_code(rc
) == GPG_ERR_EOF
)
664 log_write("assuan_process_next(): %s", gpg_strerror(rc
));
665 rc
= send_error(cl
->ctx
, gpg_err_make(PWMD_ERR_SOURCE
, rc
));
668 log_write("assuan_process_done(): %s", gpg_strerror(rc
));
674 if (cl
->pinentry
->pid
&& cl
->pinentry
->status
== PINENTRY_INIT
) {
675 cl
->pinentry
->ev
= pth_event(PTH_EVENT_FD
|PTH_UNTIL_FD_READABLE
, cl
->pinentry
->fd
);
676 pth_event_concat(ev
, cl
->pinentry
->ev
, NULL
);
677 cl
->pinentry
->status
= PINENTRY_RUNNING
;
681 switch (cl
->inquire_status
) {
686 cl
->inquire_status
= INQUIRE_INIT
;
687 rc
= assuan_process_done(cl
->ctx
, 0);
694 ev
= pinentry_iterate(cl
, ev
);
699 * Client cleanup (including XML data) is done in cleanup_cb() from
700 * the cleanup thread.
703 pth_event_free(ev
, PTH_FREE_ALL
);
710 static void setup_logging(GKeyFile
*kf
)
712 gboolean n
= g_key_file_get_boolean(kf
, "global", "enable_logging", NULL
);
715 gchar
*p
= g_key_file_get_string(kf
, "global", "log_path", NULL
);
721 g_snprintf(buf
, sizeof(buf
), "%s%s", g_get_home_dir(), p
--);
727 logfile
= g_strdup(buf
);
737 log_syslog
= g_key_file_get_boolean(kf
, "global", "syslog", NULL
);
741 * Make sure all settings are set to either the specified setting or a
744 static void set_rcfile_defaults(GKeyFile
*kf
)
748 if (g_key_file_has_key(kf
, "global", "socket_path", NULL
) == FALSE
) {
749 g_snprintf(buf
, sizeof(buf
), "~/.pwmd/socket");
750 g_key_file_set_string(kf
, "global", "socket_path", buf
);
753 if (g_key_file_has_key(kf
, "global", "data_directory", NULL
) == FALSE
) {
754 g_snprintf(buf
, sizeof(buf
), "~/.pwmd/data");
755 g_key_file_set_string(kf
, "global", "data_directory", buf
);
758 if (g_key_file_has_key(kf
, "global", "backup", NULL
) == FALSE
)
759 g_key_file_set_boolean(kf
, "global", "backup", TRUE
);
761 if (g_key_file_has_key(kf
, "global", "log_path", NULL
) == FALSE
) {
762 g_snprintf(buf
, sizeof(buf
), "~/.pwmd/log");
763 g_key_file_set_string(kf
, "global", "log_path", buf
);
766 if (g_key_file_has_key(kf
, "global", "enable_logging", NULL
) == FALSE
)
767 g_key_file_set_boolean(kf
, "global", "enable_logging", FALSE
);
769 if (g_key_file_has_key(kf
, "global", "cache_size", NULL
) == FALSE
)
770 g_key_file_set_integer(kf
, "global", "cache_size", cache_size
);
773 if (g_key_file_has_key(kf
, "global", "disable_mlockall", NULL
) == FALSE
)
774 g_key_file_set_boolean(kf
, "global", "disable_mlockall", TRUE
);
777 if (g_key_file_has_key(kf
, "global", "cache_timeout", NULL
) == FALSE
)
778 g_key_file_set_integer(kf
, "global", "cache_timeout", -1);
780 if (g_key_file_has_key(kf
, "global", "iterations", NULL
) == FALSE
||
781 g_key_file_get_integer(kf
, "global", "iterations", 0) < 0)
782 g_key_file_set_integer(kf
, "global", "iterations", 1);
784 if (g_key_file_has_key(kf
, "global", "disable_list_and_dump", NULL
) == FALSE
)
785 g_key_file_set_boolean(kf
, "global", "disable_list_and_dump", FALSE
);
787 if (g_key_file_has_key(kf
, "global", "iteration_progress", NULL
) == FALSE
)
788 g_key_file_set_integer(kf
, "global", "iteration_progress", 0);
790 if (g_key_file_has_key(kf
, "global", "compression_level", NULL
) == FALSE
)
791 g_key_file_set_integer(kf
, "global", "compression_level", 6);
793 if (g_key_file_has_key(kf
, "global", "recursion_depth", NULL
) == FALSE
)
794 g_key_file_set_integer(kf
, "global", "recursion_depth", DEFAULT_RECURSION_DEPTH
);
796 if (g_key_file_has_key(kf
, "global", "zlib_bufsize", NULL
) == FALSE
)
797 g_key_file_set_integer(kf
, "global", "zlib_bufsize", DEFAULT_ZLIB_BUFSIZE
);
799 zlib_bufsize
= (uInt
)g_key_file_get_integer(kf
, "global", "zlib_bufsize", NULL
);
801 max_recursion_depth
= g_key_file_get_integer(kf
, "global", "recursion_depth", NULL
);
802 disable_list_and_dump
= g_key_file_get_boolean(kf
, "global", "disable_list_and_dump", NULL
);
805 disable_mlock
= g_key_file_get_boolean(kf
, "global", "disable_mlockall", NULL
);
808 if (g_key_file_has_key(kf
, "global", "syslog", NULL
) == FALSE
)
809 g_key_file_set_boolean(kf
, "global", "syslog", FALSE
);
811 if (g_key_file_has_key(kf
, "global", "keepalive", NULL
) == FALSE
)
812 g_key_file_set_integer(kf
, "global", "keepalive", 30);
815 if (g_key_file_has_key(kf
, "global", "enable_pinentry", NULL
) == FALSE
)
816 g_key_file_set_boolean(kf
, "global", "enable_pinentry", TRUE
);
818 if (g_key_file_has_key(kf
, "global", "pinentry_timeout", NULL
) == FALSE
)
819 g_key_file_set_integer(kf
, "global", "pinentry_timeout", 20);
823 if (g_key_file_has_key(kf
, "global", "tcp_port", NULL
) == FALSE
)
824 g_key_file_set_integer(kf
, "global", "tcp_port", 6466);
826 if (g_key_file_has_key(kf
, "global", "enable_tcp", NULL
) == FALSE
)
827 g_key_file_set_boolean(kf
, "global", "enable_tcp", FALSE
);
829 if (g_key_file_has_key(kf
, "global", "tcp_connection_limit", NULL
) == FALSE
)
830 g_key_file_set_integer(kf
, "global", "tcp_connection_limit", 5);
836 static GKeyFile
*parse_rcfile(int cmdline
)
838 GKeyFile
*kf
= g_key_file_new();
841 if (g_key_file_load_from_file(kf
, rcfile
, G_KEY_FILE_NONE
, &rc
) == FALSE
) {
842 log_write("%s: %s", rcfile
, rc
->message
);
847 if (rc
->code
== G_FILE_ERROR_NOENT
) {
849 set_rcfile_defaults(kf
);
857 set_rcfile_defaults(kf
);
862 static gchar
*do_get_password(const gchar
*prompt
)
864 gchar buf
[LINE_MAX
] = {0}, *p
;
865 struct termios told
, tnew
;
868 if (tcgetattr(STDIN_FILENO
, &told
) == -1) {
873 memcpy(&tnew
, &told
, sizeof(struct termios
));
874 tnew
.c_lflag
&= ~(ECHO
);
875 tnew
.c_lflag
|= ICANON
|ECHONL
;
877 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tnew
) == -1) {
879 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
883 fprintf(stderr
, "%s", prompt
);
885 if ((p
= fgets(buf
, sizeof(buf
), stdin
)) == NULL
) {
886 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
890 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
891 p
[strlen(p
) - 1] = 0;
894 key
= gcry_malloc(1);
898 key
= gcry_malloc(strlen(p
) + 1);
899 sprintf(key
, "%s", p
);
902 memset(&buf
, 0, sizeof(buf
));
906 /* Only used when "enable_pinentry" is "false". */
907 static gboolean
get_input(const gchar
*filename
, file_header_internal_t
*fh
,
908 guchar
*key
, pinentry_cmd_t which
)
914 if (which
== PINENTRY_SAVE
) {
917 prompt
= g_strdup_printf(N_("New passphrase for %s: "), filename
);
918 key1
= do_get_password(prompt
);
922 warnx(N_("%s: skipping file"), filename
);
926 prompt
= g_strdup_printf(N_("Repeat passphrase: "));
927 key2
= do_get_password(prompt
);
932 warnx(N_("%s: skipping file"), filename
);
936 if (strcmp(key1
, key2
)) {
939 warnx("passphrase mismatch");
943 gcry_md_hash_buffer(GCRY_MD_SHA256
, key
, key1
,
944 strlen(key1
) ? strlen(key1
) : 1);
950 prompt
= g_strdup_printf(N_("Passphrase required for %s: "), filename
);
955 if ((password
= do_get_password(prompt
)) == NULL
) {
956 warnx(N_("%s: skipping file"), filename
);
961 gcry_md_hash_buffer(GCRY_MD_SHA256
, key
, password
, strlen(password
) ? strlen(password
) : 1);
964 rc
= try_xml_decrypt(NULL
, key
, fh
, &fh
->doc
, &fh
->len
);
969 fprintf(stderr
, N_("%s: Invalid passphrase"), filename
);
975 fprintf(stderr
, N_("%s: Invalid passphrase, skipping"), filename
);
983 * inbuf must have been allocated with gcry_malloc().
985 gpg_error_t
export_common(const gchar
*filename
, file_header_internal_t
*fh
,
986 guchar
*shakey
, gpointer inbuf
, gulong insize
)
994 rc
= gcry_cipher_open(&gh
, GCRY_CIPHER_AES256
, GCRY_CIPHER_MODE_CBC
, 0);
999 level
= get_key_file_integer(filename
, "compression_level");
1004 if (do_compress(NULL
, level
, inbuf
, insize
, &outbuf
, &outsize
, &zrc
)
1006 gcry_cipher_close(gh
);
1007 return zrc
== Z_MEM_ERROR
? GPG_ERR_ENOMEM
: GPG_ERR_COMPR_ALGO
;
1015 rc
= do_xml_encrypt(NULL
, gh
, filename
, inbuf
, insize
, shakey
, fh
->fh2
.iter
);
1016 gcry_cipher_close(gh
);
1020 static gboolean
get_password(const gchar
*filename
, file_header_internal_t
*fh
,
1021 guchar
*md5file
, guchar
*key
, pinentry_cmd_t which
)
1023 #ifdef WITH_PINENTRY
1026 if (g_key_file_get_boolean(keyfileh
, "global", "enable_pinentry", NULL
)
1029 return get_input(filename
, fh
, key
, which
);
1030 #ifdef WITH_PINENTRY
1033 gchar
*result
= NULL
;
1034 struct pinentry_s
*pin
= g_malloc0(sizeof(struct pinentry_s
));
1037 set_pinentry_defaults(pin
);
1039 pin
->filename
= g_strdup(filename
);
1041 rc
= pinentry_getpin(pin
, &result
);
1044 warnx("%s", gpg_strerror(rc
));
1049 gcry_md_hash_buffer(GCRY_MD_SHA256
, key
, result
, strlen(result
) ? strlen(result
) : 1);
1052 if (which
== PINENTRY_SAVE
) {
1053 cleanup_pinentry(pin
);
1057 rc
= try_xml_decrypt(NULL
, key
, fh
, &fh
->doc
, &fh
->len
);
1059 if (rc
== EPWMD_BADKEY
) {
1061 warnx("%s: %s", filename
, pwmd_strerror(rc
));
1064 pin
->title
= g_strdup(N_("Incorrect passphrase. Please try again."));
1069 warnx("%s", pwmd_strerror(rc
));
1071 cleanup_pinentry(pin
);
1075 return rc
? FALSE
: TRUE
;
1079 static gboolean
xml_import(const gchar
*filename
, const gchar
*outfile
,
1088 guchar shakey
[gcrykeysize
];
1090 file_header_internal_t fh
;
1092 if (stat(filename
, &st
) == -1) {
1093 warn("%s", filename
);
1097 if (iter
&& get_password(filename
, NULL
, NULL
, shakey
, PINENTRY_SAVE
)
1101 if ((fd
= open(filename
, O_RDONLY
)) == -1) {
1102 memset(shakey
, 0, sizeof(shakey
));
1103 warn("%s", filename
);
1107 if ((xmlbuf
= gcry_malloc(st
.st_size
+1)) == NULL
) {
1109 memset(shakey
, 0, sizeof(shakey
));
1110 log_write("%s", strerror(ENOMEM
));
1114 if (read(fd
, xmlbuf
, st
.st_size
) == -1) {
1115 memset(shakey
, 0, sizeof(shakey
));
1119 err(EXIT_FAILURE
, "read()");
1123 xmlbuf
[st
.st_size
] = 0;
1126 * Make sure the document validates.
1128 if ((doc
= xmlReadDoc(xmlbuf
, NULL
, "UTF-8", XML_PARSE_NOBLANKS
)) == NULL
) {
1129 log_write("xmlReadDoc()");
1132 memset(shakey
, 0, sizeof(shakey
));
1137 xmlDocDumpMemory(doc
, &xml
, &len
);
1141 memset(shakey
, '!', sizeof(shakey
));
1143 memset(&fh
, 0, sizeof(fh
));
1145 rc
= export_common(outfile
, &fh
, shakey
, xml
, len
);
1146 memset(shakey
, 0, sizeof(shakey
));
1149 send_error(NULL
, rc
);
1151 return rc
? FALSE
: TRUE
;
1154 gchar
*get_key_file_string(const gchar
*section
, const gchar
*what
)
1159 if (g_key_file_has_key(keyfileh
, section
, what
, NULL
) == TRUE
) {
1160 val
= g_key_file_get_string(keyfileh
, section
, what
, &grc
);
1163 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
1164 g_clear_error(&grc
);
1168 if (g_key_file_has_key(keyfileh
, "global", what
, NULL
) == TRUE
) {
1169 val
= g_key_file_get_string(keyfileh
, "global", what
, &grc
);
1172 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
1173 g_clear_error(&grc
);
1181 gint
get_key_file_integer(const gchar
*section
, const gchar
*what
)
1186 if (g_key_file_has_key(keyfileh
, section
? section
: "global", what
, NULL
) == TRUE
) {
1187 val
= g_key_file_get_integer(keyfileh
, section
? section
: "global", what
, &grc
);
1190 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
1191 g_clear_error(&grc
);
1195 if (g_key_file_has_key(keyfileh
, "global", what
, NULL
) == TRUE
) {
1196 val
= g_key_file_get_integer(keyfileh
, "global", what
, &grc
);
1199 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
1200 g_clear_error(&grc
);
1208 gboolean
get_key_file_boolean(const gchar
*section
, const gchar
*what
)
1210 gboolean val
= FALSE
;
1213 if (g_key_file_has_key(keyfileh
, section
, what
, NULL
) == TRUE
) {
1214 val
= g_key_file_get_boolean(keyfileh
, section
, what
, &grc
);
1217 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
1218 g_clear_error(&grc
);
1222 if (g_key_file_has_key(keyfileh
, "global", what
, NULL
) == TRUE
) {
1223 val
= g_key_file_get_boolean(keyfileh
, "global", what
, &grc
);
1226 log_write("%s(%i): %s", __FILE__
, __LINE__
, grc
->message
);
1227 g_clear_error(&grc
);
1235 static gboolean
_getline(const gchar
*file
, gchar
**result
)
1238 gchar buf
[LINE_MAX
] = {0}, *p
;
1242 if ((fp
= fopen(file
, "r")) == NULL
) {
1247 p
= fgets(buf
, sizeof(buf
), fp
);
1251 if (len
&& buf
[len
- 1] == '\n')
1254 str
= gcry_malloc(len
+ 1);
1255 memcpy(str
, buf
, len
? len
: 1);
1257 memset(&buf
, 0, sizeof(buf
));
1262 static gboolean
parse_keyfile_key()
1269 groups
= g_key_file_get_groups(keyfileh
, &n
);
1271 for (p
= groups
; *p
; p
++) {
1274 if (g_key_file_has_key(keyfileh
, *p
, "key", &rc
) == TRUE
) {
1275 str
= g_key_file_get_string(keyfileh
, *p
, "key", &rc
);
1279 warnx("%s", rc
->message
);
1286 do_cache_push(*p
, str
);
1292 warnx("%s", rc
->message
);
1297 if (g_key_file_has_key(keyfileh
, *p
, "key_file", &rc
) == TRUE
) {
1299 gchar
*file
= g_key_file_get_string(keyfileh
, *p
, "key_file", &rc
);
1303 warnx("%s", rc
->message
);
1310 t
= expand_homedir(file
);
1314 if (_getline(file
, &str
) == FALSE
) {
1320 do_cache_push(*p
, str
);
1326 warnx("%s", rc
->message
);
1335 static gboolean
do_cache_push(const gchar
*filename
, const gchar
*password
)
1340 const gchar
*p
= filename
;
1341 file_header_internal_t
*fh
;
1350 if (valid_filename(p
) == FALSE
) {
1351 warnx(N_("%s: invalid characters in filename"), p
);
1355 md5file
= gcry_malloc(16);
1356 key
= gcry_malloc(gcrykeysize
);
1357 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, p
, strlen(p
));
1359 if (cache_iscached(md5file
) == TRUE
) {
1360 warnx(N_("%s: file already cached, skipping"), p
);
1366 if (access(p
, R_OK
|W_OK
) != 0) {
1370 if (errno
!= ENOENT
) {
1379 fh
= read_file_header(filename
, FALSE
, &rc
);
1384 warnx("%s", pwmd_strerror(rc
));
1388 if (fh
->fh2
.iter
<= 0) {
1389 memset(key
, '!', gcrykeysize
);
1394 if (!get_password(p
, fh
, md5file
, key
, PINENTRY_OPEN
)) {
1400 gcry_md_hash_buffer(GCRY_MD_SHA256
, key
, password
,
1401 strlen(password
) ? strlen(password
) : 1);
1404 rc
= try_xml_decrypt(NULL
, key
, fh
, NULL
, NULL
);
1407 warnx("%s: %s", filename
, pwmd_strerror(rc
));
1414 if (cache_add_file(md5file
, key
) == FALSE
) {
1415 warnx("%s: %s", p
, pwmd_strerror(EPWMD_MAX_SLOTS
));
1422 timeout
= get_key_file_integer(p
, "cache_timeout");
1423 cache_set_timeout(md5file
, timeout
);
1424 warnx(N_("%s: file added to the cache"), filename
);
1431 static gboolean
check_host_limit(const gchar
*addr
)
1435 gint limit
= get_key_file_integer("global", "tcp_connection_limit");
1437 pth_mutex_acquire(&cn_mutex
, FALSE
, NULL
);
1439 for (t
= g_slist_length(cn_thread_list
), i
= 0; i
< t
; i
++) {
1440 struct client_thread_s
*cn
= g_slist_nth_data(cn_thread_list
, i
);
1445 if (strcmp(addr
, cn
->addr
) == 0)
1449 if (limit
> 0 && total
> limit
) {
1450 pth_mutex_release(&cn_mutex
);
1454 pth_mutex_release(&cn_mutex
);
1458 static void init_new_connection(gint fd
, gchar
*addr
)
1462 struct client_thread_s
*new;
1465 if (addr
&& check_host_limit(addr
) == FALSE
) {
1466 log_write(N_("host %s exceeds host limit"), addr
);
1471 new = g_malloc0(sizeof(struct client_thread_s
));
1474 log_write("%s", strerror(ENOMEM
));
1479 * Thread priority is inherited from the calling thread. This
1480 * thread is PTH_PRIO_MAX. Keep the "child" threads at standard
1483 pth_mutex_acquire(&cn_mutex
, FALSE
, NULL
);
1488 new->addr
= g_strdup(addr
);
1489 gettimeofday(&new->init
, NULL
);
1492 attr
= pth_attr_new();
1493 pth_attr_set(attr
, PTH_ATTR_PRIO
, PTH_PRIO_STD
);
1494 pth_attr_set(attr
, PTH_ATTR_JOINABLE
, FALSE
);
1495 tid
= pth_spawn(attr
, client_thread
, new);
1496 pth_attr_destroy(attr
);
1500 log_write(N_("pth_spawn() failed"));
1501 pth_mutex_release(&cn_mutex
);
1505 g_snprintf(buf
, sizeof(buf
), "%p", tid
);
1508 log_write(N_("new tid=%s, fd=%i, addr=%s"), buf
, fd
, addr
);
1510 log_write(N_("new tid=%s, fd=%i"), buf
, fd
);
1512 attr
= pth_attr_of(tid
);
1513 pth_attr_set(attr
, PTH_ATTR_NAME
, buf
);
1514 pth_attr_destroy(attr
);
1516 cn_thread_list
= g_slist_append(cn_thread_list
, new);
1517 pth_mutex_release(&cn_mutex
);
1521 /* From Beej's Guide to Network Programming. It's a good tutorial. */
1522 static void *get_in_addr(struct sockaddr
*sa
)
1524 if (sa
->sa_family
== AF_INET
)
1525 return &(((struct sockaddr_in
*)sa
)->sin_addr
);
1527 return &(((struct sockaddr_in6
*)sa
)->sin6_addr
);
1530 static void *tcp_accept_thread(void *arg
)
1532 gint sockfd
= (gint
)arg
;
1535 struct sockaddr_storage raddr
;
1536 socklen_t slen
= sizeof(raddr
);
1539 if ((fd
= pth_accept(sockfd
, (struct sockaddr
*)&raddr
, &slen
)) == -1) {
1540 if (errno
!= EAGAIN
) {
1541 if (!quit
) // probably EBADF
1542 log_write("accept(): %s", strerror(errno
));
1552 gchar s
[INET6_ADDRSTRLEN
];
1554 inet_ntop(raddr
.ss_family
, get_in_addr((struct sockaddr
*)&raddr
),
1556 init_new_connection(fd
, s
);
1560 /* Just in case pth_accept() failed for some reason other than EBADF */
1562 pth_exit(PTH_CANCELED
);
1567 static void *accept_thread(void *arg
)
1569 gint sockfd
= (gint
)arg
;
1572 socklen_t slen
= sizeof(struct sockaddr_un
);
1573 struct sockaddr_un raddr
;
1576 if ((fd
= pth_accept(sockfd
, (struct sockaddr
*)&raddr
, &slen
)) == -1) {
1577 if (errno
!= EAGAIN
) {
1578 if (!quit
) // probably EBADF
1579 log_write("accept(): %s", strerror(errno
));
1586 init_new_connection(fd
, NULL
);
1589 /* Just in case pth_accept() failed for some reason other than EBADF */
1591 pth_exit(PTH_CANCELED
);
1596 * This thread isn't joinable. For operations that block, these threads will
1599 static void *adjust_timer_thread(void *arg
)
1602 cache_adjust_timer();
1607 static pth_event_t
timeout_event_iterate(pth_event_t timeout_ev
,
1610 pth_status_t ev_status
;
1613 pth_event_isolate(timeout_ev
);
1614 ev_status
= pth_event_status(timeout_ev
);
1615 pth_event_free(timeout_ev
, PTH_FREE_THIS
);
1617 if (ev_status
== PTH_STATUS_OCCURRED
) {
1619 * The timer event has expired. Update the file cache. When the
1620 * cache mutex is locked and the timer expires again, the threads
1623 pth_spawn(attr
, adjust_timer_thread
, NULL
);
1627 return pth_event(PTH_EVENT_TIME
, pth_timeout(1, 0));
1630 static pth_event_t
keepalive_event_iterate(pth_event_t keepalive_ev
,
1633 pth_event_t ev
= NULL
;
1634 pth_status_t ev_status
;
1637 pth_event_isolate(keepalive_ev
);
1638 ev_status
= pth_event_status(keepalive_ev
);
1640 if (ev_status
== PTH_STATUS_OCCURRED
|| ev_status
== PTH_STATUS_FAILED
) {
1641 if (ev_status
== PTH_STATUS_OCCURRED
)
1642 send_status_all(STATUS_KEEPALIVE
);
1644 pth_event_free(keepalive_ev
, PTH_FREE_THIS
);
1650 if (keepalive
> 0 && !ev
)
1651 ev
= pth_event(PTH_EVENT_TIME
, pth_timeout(keepalive
, 0));
1656 static void server_loop(gint sockfd
, gint sockfd_r
, gchar
**socketpath
)
1660 pth_t tcp_accept_tid
;
1666 pth_event_t timeout_ev
, keepalive_ev
= NULL
, ev_quit
;
1667 gint keepalive
= get_key_file_integer("global", "keepalive");
1670 pth_mutex_init(&cn_mutex
);
1671 log_write(N_("%s started for user %s"), PACKAGE_STRING
, g_get_user_name());
1673 sigaddset(&set
, SIGTERM
);
1674 sigaddset(&set
, SIGINT
);
1675 sigaddset(&set
, SIGUSR1
);
1676 sigaddset(&set
, SIGHUP
);
1677 sigaddset(&set
, SIGABRT
);
1679 attr
= pth_attr_new();
1680 pth_attr_init(attr
);
1681 pth_attr_set(attr
, PTH_ATTR_PRIO
, PTH_PRIO_MIN
);
1682 pth_attr_set(attr
, PTH_ATTR_NAME
, "accept");
1683 accept_tid
= pth_spawn(attr
, accept_thread
, (void *)sockfd
);
1686 if (sockfd_r
!= -1) {
1687 pth_attr_set(attr
, PTH_ATTR_NAME
, "tcp_accept");
1688 tcp_accept_tid
= pth_spawn(attr
, tcp_accept_thread
, (void *)sockfd_r
);
1692 pth_attr_init(attr
);
1693 pth_attr_set(attr
, PTH_ATTR_JOINABLE
, FALSE
);
1694 pth_attr_set(attr
, PTH_ATTR_PRIO
, PTH_PRIO_MAX
);
1697 * For the cache_timeout configuration parameter.
1699 timeout_ev
= timeout_event_iterate(NULL
, attr
);
1700 keepalive_ev
= keepalive_event_iterate(NULL
, keepalive
);
1701 timeout_ev
= pth_event_concat(timeout_ev
, keepalive_ev
, NULL
);
1706 pth_sigwait_ev(&set
, &sig
, timeout_ev
);
1707 timeout_ev
= timeout_event_iterate(timeout_ev
, attr
);
1708 keepalive_ev
= keepalive_event_iterate(keepalive_ev
, keepalive
);
1709 timeout_ev
= pth_event_concat(timeout_ev
, keepalive_ev
, NULL
);
1712 log_write(N_("caught signal %i (%s)"), sig
, strsignal(sig
));
1714 /* Caught a signal. */
1718 keepalive
= get_key_file_integer("global", "keepalive");
1722 cache_clear(NULL
, 2);
1730 log_write(N_("clearing file cache"));
1731 cache_clear(NULL
, 2);
1736 shutdown(sockfd
, SHUT_RDWR
);
1739 if (sockfd_r
!= -1) {
1740 shutdown(sockfd_r
, SHUT_RDWR
);
1749 * We're out of the main server loop. This happens when a signal was sent
1750 * to terminate the daemon. We'll wait for all clients to disconnect
1751 * before exiting and ignore any following signals.
1753 pth_join(accept_tid
, &value
);
1756 if (sockfd_r
!= -1) {
1757 pth_cancel(tcp_accept_tid
);
1758 pth_join(tcp_accept_tid
, &value
);
1762 n
= pth_ctrl(PTH_CTRL_GETTHREADS
);
1763 unlink(*socketpath
);
1764 g_free(*socketpath
);
1768 log_write(N_("waiting for all threads to terminate"));
1770 ev_quit
= pth_event(PTH_EVENT_TIME
, pth_timeout(0, 500000));
1773 if (n
!= n_clients
) {
1774 log_write(N_("%i threads remain"), n
-1);
1779 pth_event_isolate(ev_quit
);
1780 timeout_ev
= timeout_event_iterate(timeout_ev
, attr
);
1781 keepalive_ev
= keepalive_event_iterate(keepalive_ev
, keepalive
);
1782 ev_quit
= pth_event_concat(ev_quit
, timeout_ev
, keepalive_ev
, NULL
);
1783 n
= pth_ctrl(PTH_CTRL_GETTHREADS
);
1786 pth_event_free(timeout_ev
, PTH_FREE_THIS
);
1787 pth_event_free(keepalive_ev
, PTH_FREE_THIS
);
1788 pth_event_free(ev_quit
, PTH_FREE_THIS
);
1789 pth_attr_destroy(attr
);
1793 * Called from pinentry_fork() in the child process.
1795 void free_client_list()
1797 gint i
, t
= g_slist_length(cn_thread_list
);
1799 for (i
= 0; i
< t
; i
++) {
1800 struct client_thread_s
*cn
= g_slist_nth_data(cn_thread_list
, i
);
1802 free_client(cn
->cl
);
1805 memset(key_cache
, 0, cache_size
);
1808 static gpg_error_t
convert_file(const gchar
*filename
, const gchar
*outfile
)
1810 file_header_internal_t
*fh
;
1816 md5file
= gcry_malloc(16);
1818 return GPG_ERR_ENOMEM
;
1820 shakey
= gcry_malloc(gcrykeysize
);
1823 return GPG_ERR_ENOMEM
;
1826 fh
= read_file_header(filename
, TRUE
, &rc
);
1831 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, filename
, strlen(filename
));
1833 /* The header in version 1 had a bug where the iterations were off-by-one.
1834 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
1837 if (fh
->fh1
.iter
>= 0) {
1838 if (get_password(filename
, fh
, md5file
, shakey
, PINENTRY_OPEN
)
1840 rc
= GPG_ERR_UNKNOWN_ERRNO
;
1846 rc
= try_xml_decrypt(NULL
, shakey
, fh
, &fh
->doc
, &fh
->len
);
1853 rc
= convert_xml((gchar
**)&fh
->doc
, &fh
->len
);
1857 warnx("%s: %s", filename
, pwmd_strerror(rc
));
1862 iter
= fh
->fh1
.iter
;
1863 memset(&fh
->fh2
, 0, sizeof(fh
->fh2
));
1864 /* Keep the iterations and key from the original file. */
1865 fh
->fh2
.iter
= iter
+1;
1866 rc
= export_common(outfile
, fh
, shakey
, fh
->doc
, fh
->len
);
1869 send_error(NULL
, rc
);
1872 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
1879 int main(int argc
, char *argv
[])
1882 struct sockaddr_un addr
;
1883 struct passwd
*pw
= getpwuid(getuid());
1884 gchar buf
[PATH_MAX
];
1885 gchar
*socketpath
= NULL
, *socketdir
, *socketname
= NULL
;
1886 gchar
*socketarg
= NULL
;
1887 gchar
*datadir
= NULL
;
1890 gchar
**cache_push
= NULL
;
1892 gchar
*import
= NULL
;
1893 gulong cmd_iterations
= -1;
1894 gint default_timeout
;
1895 gint rcfile_spec
= 0;
1896 gint estatus
= EXIT_FAILURE
;
1897 gint sockfd
, sockfd_r
= -1;
1898 gchar
*outfile
= NULL
;
1900 GMemVTable mtable
= { xmalloc
, xrealloc
, xfree
, xcalloc
, NULL
, NULL
};
1903 gboolean secure
= FALSE
;
1905 gint background
= 1;
1907 gchar
*convert
= NULL
;
1909 struct assuan_io_hooks io_hooks
= {read_hook
, write_hook
};
1914 #ifdef HAVE_SETRLIMIT
1917 rl
.rlim_cur
= rl
.rlim_max
= 0;
1919 if (setrlimit(RLIMIT_CORE
, &rl
) != 0)
1920 err(EXIT_FAILURE
, "setrlimit()");
1926 setlocale(LC_ALL
, "");
1927 bindtextdomain("pwmd", LOCALEDIR
);
1932 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT
);
1934 g_mem_set_vtable(&mtable
);
1935 assuan_set_malloc_hooks(xmalloc
, xrealloc
, xfree
);
1936 xmlMemSetup(xfree
, xmalloc
, xrealloc
, xstrdup
);
1939 gnutls_global_set_mem_functions(xmalloc
, xmalloc
, gcry_SecureCheck
,
1943 gcry_control(GCRYCTL_SET_THREAD_CBS
, &gcry_threads_pth
);
1945 gnutls_global_init();
1946 gnutls_global_set_log_function(tls_log
);
1947 gnutls_global_set_log_level(1);
1948 assuan_set_io_hooks(&io_hooks
);
1951 g_snprintf(buf
, sizeof(buf
), "%s/.pwmd", pw
->pw_dir
);
1953 if (mkdir(buf
, 0700) == -1 && errno
!= EEXIST
)
1954 err(EXIT_FAILURE
, "%s", buf
);
1956 g_snprintf(buf
, sizeof(buf
), "%s/.pwmd/data", pw
->pw_dir
);
1958 if (mkdir(buf
, 0700) == -1 && errno
!= EEXIST
)
1959 err(EXIT_FAILURE
, "%s", buf
);
1961 rcfile
= g_strdup_printf("%s/.pwmd/config", pw
->pw_dir
);
1963 if ((page_size
= sysconf(_SC_PAGESIZE
)) == -1)
1964 err(EXIT_FAILURE
, "sysconf()");
1966 cache_size
= page_size
;
1968 while ((opt
= getopt(argc
, argv
, "o:C:bnI:i:hvf:D")) != EOF
) {
1977 /* Compatibility for version < 1.11 */
1989 cmd_iterations
= strtol(optarg
, NULL
, 10);
1993 rcfile
= g_strdup(optarg
);
1997 printf("%s\n%s\n", PACKAGE_STRING
, PACKAGE_BUGREPORT
);
2005 if ((keyfileh
= parse_rcfile(rcfile_spec
)) == NULL
)
2008 if (g_key_file_has_key(keyfileh
, "global", "syslog", NULL
) == TRUE
)
2009 log_syslog
= g_key_file_get_boolean(keyfileh
, "global", "syslog", NULL
);
2011 if (log_syslog
== TRUE
)
2012 openlog("pwmd", LOG_NDELAY
|LOG_PID
, LOG_DAEMON
);
2014 if (g_key_file_has_key(keyfileh
, "global", "priority", NULL
)) {
2015 iter
= g_key_file_get_integer(keyfileh
, "global", "priority", NULL
);
2018 if (setpriority(PRIO_PROCESS
, 0, iter
) == -1) {
2019 warn("setpriority()");
2024 #ifdef HAVE_MLOCKALL
2025 if (disable_mlock
== FALSE
&& mlockall(MCL_FUTURE
) == -1) {
2037 opt
= convert_file(convert
, outfile
);
2038 g_key_file_free(keyfileh
);
2040 exit(opt
? EXIT_FAILURE
: EXIT_SUCCESS
);
2047 if (cmd_iterations
== -1)
2048 cmd_iterations
= get_key_file_integer("global", "iterations");
2050 opt
= xml_import(import
, outfile
, cmd_iterations
);
2051 g_key_file_free(keyfileh
);
2053 exit(opt
== FALSE
? EXIT_FAILURE
: EXIT_SUCCESS
);
2056 g_key_file_set_list_separator(keyfileh
, ',');
2058 if ((p
= g_key_file_get_string(keyfileh
, "global", "socket_path", NULL
)) == NULL
)
2059 errx(EXIT_FAILURE
, N_("%s: socket_path not defined"), rcfile
);
2063 g_snprintf(buf
, sizeof(buf
), "%s%s", g_get_home_dir(), p
--);
2065 socketarg
= g_strdup(buf
);
2070 if ((p
= g_key_file_get_string(keyfileh
, "global", "data_directory", NULL
)) == NULL
)
2071 errx(EXIT_FAILURE
, N_("%s: data_directory not defined"), rcfile
);
2073 datadir
= expand_homedir(p
);
2076 if (secure
== FALSE
&& g_key_file_has_key(keyfileh
, "global", "disable_list_and_dump", NULL
) == TRUE
) {
2077 n
= g_key_file_get_boolean(keyfileh
, "global", "disable_list_and_dump", NULL
);
2078 disable_list_and_dump
= n
;
2081 disable_list_and_dump
= secure
;
2083 if (g_key_file_has_key(keyfileh
, "global", "cache_timeout", NULL
) == TRUE
)
2084 default_timeout
= g_key_file_get_integer(keyfileh
, "global", "cache_timeout", NULL
);
2086 default_timeout
= -1;
2088 if (g_key_file_has_key(keyfileh
, "global", "cache_size", NULL
) == TRUE
) {
2089 cache_size
= g_key_file_get_integer(keyfileh
, "global", "cache_size", NULL
);
2091 if (cache_size
< page_size
|| cache_size
% page_size
)
2092 errx(EXIT_FAILURE
, N_("cache size must be in multiples of %li"), page_size
);
2095 setup_logging(keyfileh
);
2097 if (g_key_file_has_key(keyfileh
, "global", "cache_push", NULL
) == TRUE
)
2098 cache_push
= g_key_file_get_string_list(keyfileh
, "global", "cache_push", NULL
, NULL
);
2100 if (argc
!= optind
) {
2102 ptotal
= g_strv_length(cache_push
);
2104 for (; optind
< argc
; optind
++) {
2105 if (strv_printf(&cache_push
, "%s", argv
[optind
]) == FALSE
)
2106 errx(EXIT_FAILURE
, "%s", strerror(ENOMEM
));
2110 if (strchr(socketarg
, '/') == NULL
) {
2111 socketdir
= g_get_current_dir();
2112 socketname
= g_strdup(socketarg
);
2113 socketpath
= g_strdup_printf("%s/%s", socketdir
, socketname
);
2116 socketname
= g_strdup(strrchr(socketarg
, '/'));
2118 socketarg
[strlen(socketarg
) - strlen(socketname
) -1] = 0;
2119 socketdir
= g_strdup(socketarg
);
2120 socketpath
= g_strdup_printf("%s/%s", socketdir
, socketname
);
2123 if ((key_cache
= mmap(NULL
, cache_size
, PROT_READ
|PROT_WRITE
,
2124 #ifdef MMAP_ANONYMOUS
2125 MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0)) == MAP_FAILED
) {
2127 MAP_PRIVATE
|MAP_ANON
, -1, 0)) == MAP_FAILED
) {
2129 err(EXIT_FAILURE
, "mmap()");
2132 if (mlock(key_cache
, cache_size
) == -1)
2133 log_write("mlock(): %s", strerror(errno
));
2135 memset(key_cache
, 0, cache_size
);
2137 if (chdir(datadir
)) {
2138 warn("%s", datadir
);
2143 if (parse_keyfile_key() == FALSE
)
2146 clear_errorfile_key();
2149 * Set the cache entry for a file. Prompts for the password.
2152 for (opt
= 0; cache_push
[opt
]; opt
++)
2153 do_cache_push(cache_push
[opt
], NULL
);
2155 g_strfreev(cache_push
);
2156 warnx(background
? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2160 * bind() doesn't like the full pathname of the socket or any non alphanum
2161 * characters so change to the directory where the socket is wanted then
2162 * create it then change to datadir.
2164 if (chdir(socketdir
)) {
2165 warn("%s", socketdir
);
2171 if ((sockfd
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1) {
2176 addr
.sun_family
= AF_UNIX
;
2177 g_snprintf(addr
.sun_path
, sizeof(addr
.sun_path
), "%s", socketname
);
2179 if (bind(sockfd
, (struct sockaddr
*)&addr
, sizeof(struct sockaddr
)) == -1) {
2182 if (errno
== EADDRINUSE
)
2183 warnx(N_("Either there is another pwmd running or '%s' is a \n"
2184 "stale socket. Please remove it manually."), socketpath
);
2190 if (g_key_file_has_key(keyfileh
, "global", "socket_perms", NULL
) == TRUE
) {
2191 gchar
*t
= g_key_file_get_string(keyfileh
, "global", "socket_perms", NULL
);
2192 mode_t mode
= strtol(t
, NULL
, 8);
2193 mode_t mask
= umask(0);
2197 if (chmod(socketname
, mode
) == -1) {
2198 warn("%s", socketname
);
2208 g_free(--socketname
);
2210 if (chdir(datadir
)) {
2211 warn("%s", datadir
);
2218 pth_mutex_init(&cache_mutex
);
2219 #ifdef WITH_PINENTRY
2220 pth_mutex_init(&pin_mutex
);
2223 if (listen(sockfd
, 0) == -1) {
2229 if (get_key_file_boolean("global", "enable_tcp")) {
2231 struct addrinfo hints
, *servinfo
, *p
;
2232 gint port
= get_key_file_integer("global", "tcp_port");
2235 memset(&hints
, 0, sizeof(hints
));
2236 hints
.ai_family
= AF_UNSPEC
;
2237 hints
.ai_socktype
= SOCK_STREAM
;
2238 hints
.ai_flags
= AI_PASSIVE
;
2240 if ((opt
= getaddrinfo(NULL
, print_fmt(buf
, sizeof(buf
), "%i", port
),
2241 &hints
, &servinfo
)) == -1) {
2242 warnx("getaddrinfo(): %s", gai_strerror(opt
));
2246 for(p
= servinfo
; p
!= NULL
; p
= p
->ai_next
) {
2247 if ((sockfd_r
= socket(p
->ai_family
, p
->ai_socktype
,
2248 p
->ai_protocol
)) == -1) {
2253 if (setsockopt(sockfd_r
, SOL_SOCKET
, SO_REUSEADDR
, &opt
,
2254 sizeof(int)) == -1) {
2255 warn("setsockopt()");
2259 if (bind(sockfd_r
, p
->ai_addr
, p
->ai_addrlen
) == -1) {
2269 freeaddrinfo(servinfo
);
2272 warnx("%s", N_("could not bind"));
2276 if (g_key_file_has_key(keyfileh
, "global", "tcp_interface", NULL
)) {
2277 gchar
*tmp
= get_key_file_string("global", "tcp_interface");
2279 if (setsockopt(sockfd_r
, SOL_SOCKET
, SO_BINDTODEVICE
, tmp
, 1)
2289 ret
= gnutls_certificate_allocate_credentials(&x509_cred
);
2291 if (ret
!= GNUTLS_E_SUCCESS
) {
2292 warnx("%s", gnutls_strerror(ret
));
2296 tmp
= expand_homedir("~/.pwmd/ca-cert.pem");
2299 warnx("%s", strerror(ENOMEM
));
2303 ret
= gnutls_certificate_set_x509_trust_file(x509_cred
, tmp
,
2304 GNUTLS_X509_FMT_PEM
);
2308 warnx("%s", gnutls_strerror(ret
));
2312 tmp
= expand_homedir("~/.pwmd/server-cert.pem");
2315 warnx("%s", strerror(ENOMEM
));
2319 tmp2
= expand_homedir("~/.pwmd/server-key.pem");
2323 warnx("%s", strerror(ENOMEM
));
2327 ret
= gnutls_certificate_set_x509_key_file (x509_cred
, tmp
, tmp2
,
2328 GNUTLS_X509_FMT_PEM
);
2332 if (ret
!= GNUTLS_E_SUCCESS
) {
2333 warnx("%s", gnutls_strerror(ret
));
2356 if (get_key_file_boolean("global", "enable_tcp")) {
2357 log_write("%s", N_("Generating key exchange parameters..."));
2358 ret
= gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM
, 0);
2361 warnx("%s", gpg_strerror(ret
));
2365 ret
= gnutls_dh_params_init(&dh_params
);
2367 if (ret
!= GNUTLS_E_SUCCESS
) {
2368 warnx("%s", gnutls_strerror(ret
));
2372 ret
= gnutls_dh_params_generate2(dh_params
, 1024);
2374 if (ret
!= GNUTLS_E_SUCCESS
) {
2375 warnx("%s", gnutls_strerror(ret
));
2379 gnutls_certificate_set_dh_params (x509_cred
, dh_params
);
2380 gnutls_certificate_set_params_function(x509_cred
, tls_get_params
);
2382 if (listen(sockfd_r
, 0) == -1) {
2390 * These are the signals that we use in threads. libpth can catch signals
2391 * itself so ignore them everywhere else. Note that using
2392 * signal(N, SIG_IGN) doesn't work like you might think.
2397 sigaddset(&set
, SIGTERM
);
2398 sigaddset(&set
, SIGINT
);
2400 /* Configuration file reloading. */
2401 sigaddset(&set
, SIGUSR1
);
2403 /* Clears the file cache. */
2404 sigaddset(&set
, SIGHUP
);
2406 /* Caught in client_thread(). Sends a cache status message. */
2407 sigaddset(&set
, SIGUSR2
);
2409 /* Ignored everywhere. When a client disconnects abnormally this signal
2410 * gets raised. It isn't needed though because client_thread() will check
2411 * for rcs even after the client disconnects. */
2412 signal(SIGPIPE
, SIG_IGN
);
2413 pth_sigmask(SIG_BLOCK
, &set
, NULL
);
2414 server_loop(sockfd
, sockfd_r
, &socketpath
);
2415 estatus
= EXIT_SUCCESS
;
2418 if (socketpath
&& do_unlink
) {
2424 if (sockfd_r
!= -1) {
2425 gnutls_dh_params_deinit(dh_params
);
2428 gnutls_certificate_free_credentials(x509_cred
);
2430 gnutls_global_deinit();
2434 g_key_file_free(keyfileh
);
2439 cache_clear(NULL
, 2);
2440 memset(key_cache
, 0, cache_size
);
2443 if (key_cache
&& munmap(key_cache
, cache_size
) == -1)
2444 log_write("munmap(): %s", strerror(errno
));
2446 if (estatus
== EXIT_SUCCESS
)
2447 log_write(N_("pwmd exiting normally"));
2450 #if defined(DEBUG) && !defined(MEM_DEBUG)