1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2006-2010 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>
49 #include <sys/resource.h>
51 #ifdef HAVE_GETOPT_LONG
56 #include "getopt_long.h"
74 #include "pwmd_error.h"
81 GCRY_THREAD_OPTION_PTH_IMPL
;
83 static void *reload_rcfile_thread(void *arg
)
85 gboolean b
= disable_list_and_dump
;
86 gchar
**users
= g_key_file_get_string_list(keyfileh
, "global", "allowed",
89 pth_attr_t attr
= pth_attr_of(pth_self());
91 pth_attr_set(attr
, PTH_ATTR_NAME
, __FUNCTION__
);
92 pth_attr_destroy(attr
);
93 MUTEX_LOCK(&rcfile_mutex
);
94 log_write(N_("reloading configuration file '%s'"), rcfile
);
95 k
= parse_rcfile(FALSE
);
100 g_key_file_free(keyfileh
);
104 startStopKeepAlive(FALSE
);
105 send_status_all(STATUS_CONFIG
);
107 disable_list_and_dump
= !disable_list_and_dump
? b
: TRUE
;
108 g_key_file_set_string_list(keyfileh
, "global", "allowed",
109 (const gchar
**)users
, g_strv_length(users
));
111 MUTEX_UNLOCK(&rcfile_mutex
);
115 static void reload_rcfile()
118 pth_attr_t attr
= pth_attr_new();
122 pth_attr_set(attr
, PTH_ATTR_JOINABLE
, 0);
123 tid
= pth_spawn(attr
, reload_rcfile_thread
, NULL
);
124 rc
= gpg_error_from_syserror();
125 pth_attr_destroy(attr
);
128 log_write("%s(%i): pth_spawn(): %s", __FILE__
, __LINE__
,
132 gpg_error_t
send_error(assuan_context_t ctx
, gpg_error_t e
)
134 gpg_err_code_t n
= gpg_err_code(e
);
135 gpg_error_t code
= gpg_err_make(PWMD_ERR_SOURCE
, n
);
136 struct client_s
*client
= assuan_get_pointer(ctx
);
142 return assuan_process_done(ctx
, 0);
145 log_write("%s", pwmd_strerror(e
));
149 if (n
== EPWMD_LIBXML_ERROR
) {
150 xmlErrorPtr xe
= client
->xml_error
;
153 xe
= xmlGetLastError();
155 e
= assuan_process_done(ctx
, assuan_set_error(ctx
, code
, xe
->message
));
156 log_write("%s", xe
->message
);
158 if (xe
== client
->xml_error
)
163 client
->xml_error
= NULL
;
167 return assuan_process_done(ctx
, assuan_set_error(ctx
, code
, pwmd_strerror(e
)));
170 void log_write(const gchar
*fmt
, ...)
180 pth_t tid
= pth_self();
183 if ((!logfile
&& !isatty(STDERR_FILENO
) && log_syslog
== FALSE
) || !fmt
)
186 if (!cmdline
&& logfile
) {
187 if ((fd
= open(logfile
, O_WRONLY
|O_CREAT
|O_APPEND
, 0600)) == -1) {
197 if (g_vasprintf(&args
, fmt
, ap
) == -1) {
198 if (logfile
&& fd
!= -1)
208 fprintf(stderr
, "%s\n", args
);
214 attr
= pth_attr_of(tid
);
216 if (pth_attr_get(attr
, PTH_ATTR_NAME
, &name
) == FALSE
)
219 pth_attr_destroy(attr
);
220 name
= print_fmt(buf
, sizeof(buf
), "%s(%p): ", name
, tid
);
222 if (!cmdline
&& log_syslog
== TRUE
)
223 syslog(LOG_INFO
, "%s%s", name
, args
);
226 tm
= localtime(&now
);
227 strftime(tbuf
, sizeof(tbuf
), "%b %d %Y %H:%M:%S ", tm
);
228 tbuf
[sizeof(tbuf
) - 1] = 0;
230 if (args
[strlen(args
)-1] == '\n')
231 args
[strlen(args
)-1] = 0;
233 line
= g_strdup_printf("%s %i %s%s\n", tbuf
, getpid(), name
, args
);
237 if (logfile
&& fd
!= -1)
243 if (logfile
&& fd
!= -1) {
244 pth_write(fd
, line
, strlen(line
));
249 if (isatty(STDERR_FILENO
)) {
250 fprintf(stderr
, "%s", line
);
257 static void usage(gchar
*pn
, gint rc
)
259 g_fprintf(rc
== EXIT_FAILURE
? stderr
: stdout
, N_(
260 "Usage: %s [options] [file1] [...]\n"
262 " run as a foreground process\n"
263 " --rcfile/-f <filename>\n"
264 " load the specified rcfile (~/.pwmd/config)\n"
265 " --convert/-C <filename>\n"
266 " convert a version 1 data file to version 2\n"
267 " --import/-I <filename>\n"
268 " import an XML file\n"
270 " encrypt with the specified number of iterations when importing\n"
271 " (default is in the rcfile \"global\" section)\n"
272 " --key-file/-k <filename>\n"
273 " obtain the key from the specified file when importing or converting\n"
274 " --outfile/-o <filename>\n"
275 " output file to use when importing or converting (- for stdout)\n"
276 " --disable-dump/-D\n"
277 " disable use of the LIST, XPATH and DUMP commands\n"
278 " --no-pinentry/-P\n"
279 " disable use of pinentry\n"
286 static void setup_gcrypt()
288 gcry_control(GCRYCTL_SET_THREAD_CBS
, &gcry_threads_pth
);
290 if (!gcry_check_version(GCRYPT_VERSION
))
291 errx(EXIT_FAILURE
, N_("gcry_check_version(): Incompatible libgcrypt. Wanted %s, got %s."), GCRYPT_VERSION
, gcry_check_version(NULL
));
293 gcry_set_allocation_handler(xmalloc
, xmalloc
, NULL
, xrealloc
, xfree
);
296 static gpg_error_t
validate_peer(struct client_s
*cl
)
299 gboolean allowed
= FALSE
;
303 gpg_error_t rc
= assuan_get_peercred(cl
->ctx
, &pid
, &uid
, &gid
);
308 users
= g_key_file_get_string_list(keyfileh
, "global", "allowed", NULL
, NULL
);
311 for (gchar
**p
= users
; *p
; p
++) {
312 struct passwd pw
, *result
;
313 struct group gr
, *gresult
;
317 size_t len
= sysconf(_SC_GETGR_R_SIZE_MAX
);
326 return GPG_ERR_ENOMEM
;
329 if (!getgrnam_r(*(p
)+1, &gr
, buf
, len
, &gresult
) && gresult
) {
330 if (gresult
->gr_gid
== gid
) {
336 len
= sysconf(_SC_GETPW_R_SIZE_MAX
);
341 gchar
*tbuf
= g_malloc(len
);
343 for (gchar
**t
= gresult
->gr_mem
; *t
; t
++) {
344 if (!getpwnam_r(*t
, &pw
, tbuf
, len
, &result
) && result
) {
345 if (result
->pw_uid
== uid
) {
360 size_t len
= sysconf(_SC_GETPW_R_SIZE_MAX
);
369 return GPG_ERR_ENOMEM
;
372 if (!getpwnam_r(*p
, &pw
, buf
, len
, &result
) && result
) {
373 if (result
->pw_uid
== uid
) {
387 log_write("peer %s: uid=%i, gid=%i, pid=%i",
388 allowed
? N_("accepted") : N_("rejected"), uid
, gid
,pid
);
389 return allowed
? 0 : GPG_ERR_INV_USER_ID
;
392 static gboolean
new_connection(struct client_s
*cl
)
398 rc
= assuan_init_socket_server_ext(&cl
->ctx
, cl
->thd
->fd
, 2);
403 assuan_set_pointer(cl
->ctx
, cl
);
404 ver
= g_strdup_printf("%s", PACKAGE_STRING
);
405 assuan_set_hello_line(cl
->ctx
, ver
);
407 rc
= register_commands(cl
->ctx
);
412 rc
= assuan_accept(cl
->ctx
);
417 rc
= validate_peer(cl
);
419 /* May not be implemented on all platforms. */
420 if (rc
&& gpg_err_code(rc
) != GPG_ERR_ASS_GENERAL
)
423 str
= get_key_file_string("global", "debug_file");
426 assuan_set_log_stream(cl
->ctx
, debugfp
);
434 log_write("%s", pwmd_strerror(rc
));
438 static void xml_error_cb(void *data
, xmlErrorPtr e
)
440 struct client_s
*client
= data
;
443 * Keep the first reported error as the one to show in the error
444 * description. Reset in send_error().
446 if (client
->xml_error
)
449 xmlCopyError(e
, client
->xml_error
);
452 void close_file_header(file_header_internal_t
*fh
)
457 if (fh
->fd
!= -1 || (cmdline
== TRUE
&& fh
->fd
!= STDOUT_FILENO
))
466 void cleanup_crypto(struct crypto_s
**c
)
468 struct crypto_s
*cr
= *c
;
489 gcry_free(cr
->tkey2
);
494 gcry_free(cr
->inbuf
);
499 gcry_free(cr
->outbuf
);
503 close_file_header(cr
->fh
);
507 gcry_cipher_close(cr
->gh
);
515 * This is called after a client_thread terminates. Set with
516 * pth_cleanup_push().
518 static void cleanup_cb(void *arg
)
520 struct client_thread_s
*cn
= arg
;
521 struct client_s
*cl
= cn
->cl
;
523 MUTEX_LOCK(&cn_mutex
);
524 cn_thread_list
= g_slist_remove(cn_thread_list
, cn
);
525 MUTEX_UNLOCK(&cn_mutex
);
528 MUTEX_LOCK(&cn
->mp_mutex
);
529 pth_cancel(cn
->msg_tid
);
530 MUTEX_UNLOCK(&cn
->mp_mutex
);
534 while (pth_msgport_pending(cn
->mp
)) {
535 pth_message_t
*msg
= pth_msgport_get(cn
->mp
);
541 pth_msgport_destroy(cn
->mp
);
555 assuan_deinit_server(cl
->ctx
);
556 else if (cl
->thd
&& cl
->thd
->fd
!= -1)
561 cleanup_pinentry(cl
->pinentry
);
565 cleanup_crypto(&cl
->crypto
);
569 log_write(N_("exiting, fd=%i"), cn
->fd
);
571 send_status_all(STATUS_CLIENTS
);
575 * Called every time a connection is made from init_new_connection(). This is
576 * the thread entry point.
578 static void *client_thread(void *data
)
580 struct client_thread_s
*thd
= data
;
581 struct client_s
*cl
= g_malloc0(sizeof(struct client_s
));
586 * Prevent a race condition with init_new_connection() if this thread
587 * fails (returns) for some reason before init_new_connection() releases
590 MUTEX_LOCK(&cn_mutex
);
591 MUTEX_UNLOCK(&cn_mutex
);
592 pth_cleanup_push(cleanup_cb
, thd
);
595 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
599 attr
= pth_attr_of(pth_self());
600 pth_attr_set(attr
, PTH_ATTR_NAME
, __FUNCTION__
);
601 pth_attr_destroy(attr
);
605 if (!new_connection(cl
))
609 cl
->pinentry
= pinentry_init();
612 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
617 thd
->mp
= pth_msgport_create(NULL
);
618 pth_mutex_init(&thd
->mp_mutex
);
619 thd
->msg_tid
= pth_spawn(NULL
, client_msg_thread
, thd
);
620 rc
= gpg_error_from_syserror();
623 log_write("%s(%i): pth_spawn(): %s", __FILE__
, __LINE__
,
628 pth_yield(thd
->msg_tid
);
629 rc
= send_status(cl
->ctx
, STATUS_CACHE
, NULL
);
632 log_write("%s", pwmd_strerror(rc
));
636 send_status_all(STATUS_CLIENTS
);
637 xmlSetStructuredErrorFunc(cl
, xml_error_cb
);
641 pth_event_t pev
= NULL
;
643 pth_status_t st
, wst
;
644 pth_event_t wev
= NULL
;
645 pth_event_t rev
= pth_event(PTH_EVENT_FD
|PTH_UNTIL_FD_READABLE
,
647 pth_event_t ev
= rev
;
650 if (cl
->pinentry
->status
== PINENTRY_RUNNING
) {
651 pev
= pth_event(PTH_EVENT_FD
|PTH_UNTIL_FD_READABLE
, cl
->pinentry
->fd
);
652 ev
= pth_event_concat(ev
, pev
, NULL
);
656 if (cl
->inquire_status
== INQUIRE_BUSY
) {
657 wev
= pth_event(PTH_EVENT_FD
|PTH_UNTIL_FD_WRITEABLE
, cl
->thd
->fd
);
658 ev
= pth_event_concat(ev
, wev
, NULL
);
661 pth_cleanup_push(cleanup_ev_cb
, ev
);
663 st
= pth_event_status(rev
);
664 wst
= pth_event_status(wev
);
666 if (st
== PTH_STATUS_OCCURRED
|| wst
== PTH_STATUS_OCCURRED
) {
667 rc
= assuan_process_next(cl
->ctx
);
670 cl
->inquire_status
= INQUIRE_INIT
;
673 if (gpg_err_code(rc
) == GPG_ERR_EOF
)
676 log_write("assuan_process_next(): %s", pwmd_strerror(rc
));
677 rc
= send_error(cl
->ctx
, gpg_err_make(PWMD_ERR_SOURCE
, rc
));
680 log_write("assuan_process_done(): %s", pwmd_strerror(rc
));
686 if (cl
->pinentry
->pid
&& cl
->pinentry
->status
== PINENTRY_INIT
)
687 cl
->pinentry
->status
= PINENTRY_RUNNING
;
690 switch (cl
->inquire_status
) {
695 cl
->inquire_status
= INQUIRE_INIT
;
696 rc
= assuan_process_done(cl
->ctx
, 0);
704 st
= pth_event_status(pev
);
706 rc
= pinentry_iterate(cl
,
707 pev
&& cl
->pinentry
->fd
!= -1 && st
== PTH_STATUS_OCCURRED
);
713 * Client cleanup (including XML data) is done in cleanup_cb().
717 pth_exit(PTH_CANCELED
);
721 static gchar
*do_read_password(const gchar
*prompt
)
723 gchar buf
[LINE_MAX
] = {0}, *p
;
724 struct termios told
, tnew
;
727 if (tcgetattr(STDIN_FILENO
, &told
) == -1) {
728 log_write("tcgetattr(): %s", pwmd_strerror(gpg_error_from_syserror()));
732 memcpy(&tnew
, &told
, sizeof(struct termios
));
733 tnew
.c_lflag
&= ~(ECHO
);
734 tnew
.c_lflag
|= ICANON
|ECHONL
;
736 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tnew
) == -1) {
737 log_write("tcsetattr(): %s", pwmd_strerror(gpg_error_from_syserror()));
738 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
742 fprintf(stderr
, "%s", prompt
);
744 if ((p
= fgets(buf
, sizeof(buf
), stdin
)) == NULL
) {
745 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
749 tcsetattr(STDIN_FILENO
, TCSANOW
, &told
);
750 p
[strlen(p
) - 1] = 0;
753 key
= gcry_malloc(1);
757 key
= gcry_malloc(strlen(p
) + 1);
758 sprintf(key
, "%s", p
);
761 memset(&buf
, 0, sizeof(buf
));
765 /* Only used when "enable_pinentry" is "false" or -P. */
766 static gpg_error_t
read_password(const gchar
*filename
,
767 struct crypto_s
*crypto
, guchar
*key
, pinentry_cmd_t which
)
771 if (which
== PINENTRY_SAVE
) {
772 prompt
= g_strdup_printf(N_("New passphrase for file %s: "), filename
);
773 crypto
->tkey
= do_read_password(prompt
);
777 log_write(N_("%s: Skipping file"), filename
);
778 return GPG_ERR_BAD_PASSPHRASE
;
781 prompt
= g_strdup_printf(N_("Repeat passphrase: "));
782 crypto
->tkey2
= do_read_password(prompt
);
785 if (!crypto
->tkey2
) {
786 log_write(N_("%s: Skipping file"), filename
);
787 return GPG_ERR_BAD_PASSPHRASE
;
790 if (strcmp(crypto
->tkey
, crypto
->tkey2
)) {
791 log_write(N_("%s: Passphrase mismatch"), filename
);
792 return GPG_ERR_INV_PASSPHRASE
;
795 gcry_md_hash_buffer(GCRY_MD_SHA256
, key
, crypto
->tkey
,
796 strlen(crypto
->tkey
) ? strlen(crypto
->tkey
) : 1);
800 prompt
= g_strdup_printf(N_("Passphrase required for %s: "), filename
);
802 if ((crypto
->tkey
= do_read_password(prompt
)) == NULL
) {
803 log_write(N_("%s: Skipping file"), filename
);
805 return GPG_ERR_BAD_PASSPHRASE
;
808 gcry_md_hash_buffer(GCRY_MD_SHA256
, key
, crypto
->tkey
,
809 strlen(crypto
->tkey
) ? strlen(crypto
->tkey
) : 1);
815 * inbuf must have been allocated with gcry_malloc().
817 gpg_error_t
export_common(const gchar
*filename
, struct crypto_s
*crypto
,
818 gpointer inbuf
, gulong insize
)
825 rc
= update_save_flags(NULL
, crypto
);
830 level
= get_key_file_integer(filename
, "compression_level");
835 rc
= do_compress(NULL
, level
, inbuf
, insize
, &outbuf
, &outsize
);
840 crypto
->inbuf
= outbuf
;
841 crypto
->insize
= outsize
;
842 rc
= do_xml_encrypt(NULL
, crypto
, filename
);
846 static gpg_error_t
get_password(const gchar
*filename
,
847 struct crypto_s
*crypto
, guchar
*md5file
, guchar
*key
,
848 pinentry_cmd_t which
)
853 if (g_key_file_get_boolean(keyfileh
, "global", "enable_pinentry", NULL
)
856 return read_password(filename
, crypto
, key
, which
);
860 gchar
*result
= NULL
;
861 struct pinentry_s
*pin
= g_malloc0(sizeof(struct pinentry_s
));
863 pth_mutex_init(&pin
->status_mutex
);
864 set_pinentry_defaults(pin
);
866 pin
->filename
= g_strdup(filename
);
867 rc
= pinentry_getpin(pin
, &result
);
874 gcry_md_hash_buffer(GCRY_MD_SHA256
, key
, result
, result
? strlen(result
) : 1);
876 cleanup_pinentry(pin
);
884 static gboolean
xml_import(const gchar
*filename
, const gchar
*outfile
,
885 const gchar
*keyfile
, guint64 iter
)
894 struct crypto_s
*crypto
;
895 guint hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
897 if (stat(filename
, &st
) == -1) {
898 log_write("%s: %s", filename
, pwmd_strerror(gpg_error_from_syserror()));
902 crypto
= init_client_crypto();
907 crypto
->key
= gcry_malloc(hashlen
);
908 memset(crypto
->key
, 0, hashlen
);
911 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
915 log_write(N_("Importing XML from '%s'. Output will be written to '%s' ..."),
918 if (iter
&& keyfile
) {
919 rc
= parse_rcfile_keyfile(crypto
, keyfile
, TRUE
);
924 gcry_md_hash_buffer(GCRY_MD_SHA256
, crypto
->key
, crypto
->tkey
,
928 rc
= get_password(outfile
, crypto
, NULL
, crypto
->key
, PINENTRY_SAVE
);
930 if (rc
== GPG_ERR_ASSUAN_SERVER_FAULT
) {
931 log_write(N_("%s. Maybe disabling pinentry (-P) will help?"),
936 log_write("%s", pwmd_strerror(rc
));
941 if ((fd
= open(filename
, O_RDONLY
)) == -1) {
942 log_write("%s: %s", filename
, pwmd_strerror(gpg_error_from_syserror()));
946 if ((xmlbuf
= gcry_malloc(st
.st_size
+1)) == NULL
) {
948 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
952 if (pth_read(fd
, xmlbuf
, st
.st_size
) == -1) {
953 rc
= gpg_error_from_syserror();
955 log_write("%s: %s", filename
, pwmd_strerror(rc
));
960 xmlbuf
[st
.st_size
] = 0;
963 * Make sure the document validates.
965 if ((doc
= xmlReadDoc(xmlbuf
, NULL
, "UTF-8", XML_PARSE_NOBLANKS
)) == NULL
) {
966 log_write("xmlReadDoc() failed");
972 xmlNodePtr n
= xmlDocGetRootElement(doc
);
973 rc
= validate_import(n
? n
->children
: n
);
976 log_write("%s", pwmd_strerror(rc
));
981 xmlDocDumpMemory(doc
, &xml
, &len
);
985 memset(crypto
->key
, '!', hashlen
);
987 crypto
->fh
= g_malloc0(sizeof(file_header_internal_t
));
990 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
994 crypto
->fh
->ver
.fh2
.iter
= iter
;
995 rc
= export_common(outfile
, crypto
, xml
, len
);
999 send_error(NULL
, rc
);
1003 cleanup_crypto(&crypto
);
1007 cleanup_crypto(&crypto
);
1011 gboolean
do_cache_push(const gchar
*filename
, const void *password
,
1016 const gchar
*p
= filename
;
1017 struct crypto_s
*crypto
;
1019 guint hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
1027 if (valid_filename(p
) == FALSE
) {
1028 log_write(N_("%s: Invalid characters in filename"), p
);
1032 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, p
, strlen(p
));
1034 if (cache_iscached(md5file
)) {
1035 log_write(N_("%s: already cached, skipping"), p
);
1039 if (access(p
, R_OK
|W_OK
) != 0) {
1040 log_write("%s: %s", p
, pwmd_strerror(gpg_error_from_syserror()));
1044 crypto
= init_client_crypto();
1049 crypto
->fh
= read_file_header(filename
, FALSE
, &rc
);
1052 log_write("%s: %s", p
, pwmd_strerror(rc
));
1053 cleanup_crypto(&crypto
);
1057 crypto
->key
= gcry_malloc(hashlen
);
1060 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
1061 cleanup_crypto(&crypto
);
1065 log_write(N_("Adding '%s' to the file cache ..."), filename
);
1067 if (crypto
->fh
->ver
.fh2
.iter
<= 0ULL) {
1068 memset(crypto
->key
, '!', hashlen
);
1073 rc
= get_password(p
, crypto
, md5file
, crypto
->key
, PINENTRY_OPEN
);
1076 send_error(NULL
, rc
);
1077 cleanup_crypto(&crypto
);
1081 gcry_free(crypto
->fh
->doc
);
1082 crypto
->fh
->doc
= NULL
;
1085 gcry_md_hash_buffer(GCRY_MD_SHA256
, crypto
->key
, password
, len
);
1088 rc
= init_client_crypto2(filename
, crypto
);
1091 send_error(NULL
, rc
);
1092 cleanup_crypto(&crypto
);
1096 rc
= try_xml_decrypt(NULL
, crypto
, NULL
, NULL
);
1099 log_write("%s: %s", filename
, pwmd_strerror(rc
));
1100 cleanup_crypto(&crypto
);
1104 if (cache_update_key(md5file
, crypto
->key
) == FALSE
) {
1105 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
1106 cleanup_crypto(&crypto
);
1110 timeout
= get_key_file_integer(p
, "cache_timeout");
1111 cache_set_timeout(md5file
, timeout
);
1112 log_write(N_("File '%s' now cached"), filename
);
1113 cleanup_crypto(&crypto
);
1117 static void init_new_connection(gint fd
)
1120 struct client_thread_s
*new;
1123 new = g_malloc0(sizeof(struct client_thread_s
));
1126 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
1131 MUTEX_LOCK(&cn_mutex
);
1133 attr
= pth_attr_new();
1134 pth_attr_init(attr
);
1135 pth_attr_set(attr
, PTH_ATTR_JOINABLE
, FALSE
);
1136 new->tid
= pth_spawn(attr
, client_thread
, new);
1137 rc
= gpg_error_from_syserror();
1138 pth_attr_destroy(attr
);
1143 log_write("%s(%i): pth_spawn(): %s", __FILE__
, __LINE__
,
1145 MUTEX_UNLOCK(&cn_mutex
);
1149 cn_thread_list
= g_slist_append(cn_thread_list
, new);
1150 MUTEX_UNLOCK(&cn_mutex
);
1151 log_write(N_("new connection: tid=%p, fd=%i"), new->tid
, fd
);
1154 static void *accept_thread(void *arg
)
1156 gint sockfd
= *(gint
*)arg
;
1157 pth_attr_t attr
= pth_attr_of(pth_self());
1159 pth_attr_set(attr
, PTH_ATTR_NAME
, __FUNCTION__
);
1160 pth_attr_destroy(attr
);
1163 socklen_t slen
= sizeof(struct sockaddr_un
);
1164 struct sockaddr_un raddr
;
1167 fd
= pth_accept(sockfd
, (struct sockaddr
*)&raddr
, &slen
);
1170 if (errno
!= EAGAIN
) {
1171 if (!quit
) // probably EBADF
1172 log_write("accept(): %s", pwmd_strerror(gpg_error_from_syserror()));
1180 init_new_connection(fd
);
1183 /* Just in case accept() failed for some reason other than EBADF */
1185 pth_exit(PTH_CANCELED
);
1189 static void *adjust_cache_timer_thread(void *arg
)
1191 pth_attr_t attr
= pth_attr_of(pth_self());
1193 pth_attr_set(attr
, PTH_ATTR_NAME
, __FUNCTION__
);
1194 pth_attr_destroy(attr
);
1199 cache_adjust_timer();
1206 void cleanup_mutex_cb(void *arg
)
1208 pth_mutex_t
*m
= arg
;
1213 void cleanup_ev_cb(void *arg
)
1215 pth_event_t ev
= arg
;
1217 pth_event_free(ev
, PTH_FREE_ALL
);
1220 void cleanup_fd_cb(void *arg
)
1222 gint fd
= *(gint
*)arg
;
1227 void cleanup_unlink_cb(void *arg
)
1234 void cleanup_cancel_cb(void *arg
)
1240 attr
= pth_attr_of(tid
);
1241 pth_attr_get(attr
, PTH_ATTR_JOINABLE
, &join
);
1252 static void *keepalive_thread(void *arg
)
1254 gint to
= *(gint
*)arg
;
1255 pth_attr_t attr
= pth_attr_of(pth_self());
1257 pth_attr_set(attr
, PTH_ATTR_NAME
, __FUNCTION__
);
1258 pth_attr_destroy(attr
);
1261 pth_event_t ev
= pth_event(PTH_EVENT_TIME
, pth_timeout(to
, 0));
1263 pth_cleanup_push(cleanup_ev_cb
, ev
);
1265 send_status_all(STATUS_KEEPALIVE
);
1272 static void startStopKeepAlive(gboolean term
)
1274 gint n
= get_key_file_integer("global", "keepalive");
1277 pth_cancel(keepalive_tid
);
1279 keepalive_tid
= NULL
;
1285 pth_attr_t attr
= pth_attr_new();
1288 pth_attr_init(attr
);
1289 pth_attr_set(attr
, PTH_ATTR_JOINABLE
, FALSE
);
1290 keepalive_tid
= pth_spawn(attr
, keepalive_thread
, &n
);
1291 rc
= gpg_error_from_syserror();
1292 pth_attr_destroy(attr
);
1294 if (!keepalive_tid
) {
1295 log_write("%s(%i): pth_spawn(): %s", __FILE__
, __LINE__
,
1300 pth_yield(keepalive_tid
);
1304 static gboolean
waiting_for_exit()
1307 pth_event_t evs
= NULL
;
1309 MUTEX_LOCK(&cn_mutex
);
1311 for (t
= g_slist_length(cn_thread_list
), i
= 0; i
< t
; i
++) {
1312 struct client_thread_s
*thd
= g_slist_nth_data(cn_thread_list
, i
);
1313 pth_event_t ev
= pth_event(PTH_EVENT_TID
|PTH_UNTIL_TID_DEAD
, thd
->tid
);
1316 evs
= pth_event_concat(evs
, ev
, NULL
);
1321 MUTEX_UNLOCK(&cn_mutex
);
1327 MUTEX_LOCK(&cn_mutex
);
1328 i
= g_slist_length(cn_thread_list
);
1329 MUTEX_UNLOCK(&cn_mutex
);
1330 pth_event_free(evs
, PTH_FREE_ALL
);
1331 return i
? TRUE
: FALSE
;
1334 static void catch_sigabrt(int sig
)
1336 cache_clear(NULL
, 2);
1342 static void server_loop(gint sockfd
, gchar
**socketpath
)
1348 pth_t cache_timeout_tid
;
1352 sigemptyset(&sigset
);
1355 sigaddset(&sigset
, SIGTERM
);
1356 sigaddset(&sigset
, SIGINT
);
1358 /* Clears the file cache. */
1359 sigaddset(&sigset
, SIGUSR1
);
1361 /* Configuration file reloading. */
1362 sigaddset(&sigset
, SIGHUP
);
1364 /* Clears the cache and exits when something bad happens. */
1365 signal(SIGABRT
, catch_sigabrt
);
1366 sigaddset(&sigset
, SIGABRT
);
1368 /* Ignored everywhere. When a client disconnects abnormally this signal
1369 * gets raised. It isn't needed though because client_thread() will check
1370 * for rcs even after the client disconnects. */
1371 signal(SIGPIPE
, SIG_IGN
);
1372 sigprocmask(SIG_BLOCK
, &sigset
, NULL
);
1374 log_write(N_("%s started for user %s"), PACKAGE_STRING
, g_get_user_name());
1375 log_write(N_("Listening on %s"), *socketpath
);
1376 #ifndef HAVE_SO_PEERCRED
1377 log_write(N_("Peer credential checking is NOT supported on this OS."));
1379 attr
= pth_attr_new();
1380 pth_attr_init(attr
);
1381 accept_tid
= pth_spawn(attr
, accept_thread
, &sockfd
);
1382 rc
= gpg_error_from_syserror();
1385 log_write("%s(%i): pth_spawn(): %s", __FILE__
, __LINE__
,
1387 pth_attr_destroy(attr
);
1391 pth_yield(accept_tid
);
1392 startStopKeepAlive(FALSE
);
1393 pth_attr_set(attr
, PTH_ATTR_JOINABLE
, FALSE
);
1394 cache_timeout_tid
= pth_spawn(attr
, adjust_cache_timer_thread
, NULL
);
1395 rc
= gpg_error_from_syserror();
1397 if (!cache_timeout_tid
) {
1398 log_write("%s(%i): pth_spawn(): %s", __FILE__
, __LINE__
,
1400 pth_attr_destroy(attr
);
1404 pth_yield(cache_timeout_tid
);
1405 pth_attr_destroy(attr
);
1408 gchar
*str
= get_key_file_string("global", "debug_file");
1411 gchar
*f
= expand_homedir(str
);
1414 debugfp
= fopen(f
, "w");
1417 log_write("%s: %s", f
, pwmd_strerror(gpg_error_from_syserror()));
1419 assuan_set_assuan_log_stream(debugfp
);
1428 pth_sigwait(&sigset
, &sig
);
1429 log_write(N_("caught signal %i (%s)"), sig
, strsignal(sig
));
1431 /* Caught a signal. */
1437 // not really handled here.
1438 catch_sigabrt(SIGABRT
);
1442 log_write(N_("clearing file cache"));
1443 cache_clear(NULL
, 2);
1454 * We're out of the main server loop. This happens when a signal was sent
1455 * to terminate the daemon. We'll wait for all clients to disconnect
1456 * before exiting and ignore any following signals.
1458 shutdown(sockfd
, SHUT_RDWR
);
1460 pth_cancel(accept_tid
);
1461 pth_join(accept_tid
, NULL
);
1462 unlink(*socketpath
);
1463 g_free(*socketpath
);
1465 MUTEX_LOCK(&cn_mutex
);
1466 n
= g_slist_length(cn_thread_list
);
1467 MUTEX_UNLOCK(&cn_mutex
);
1470 log_write(N_("waiting for all clients to disconnect"));
1473 MUTEX_LOCK(&cn_mutex
);
1474 n
= g_slist_length(cn_thread_list
);
1475 MUTEX_UNLOCK(&cn_mutex
);
1476 log_write(N_("%i clients remain"), n
);
1477 } while (waiting_for_exit());
1480 startStopKeepAlive(TRUE
);
1481 pth_cancel(cache_timeout_tid
);
1487 * Only called from pinentry_fork() in the child process.
1489 void free_client_list()
1491 gint i
, t
= g_slist_length(cn_thread_list
);
1493 for (i
= 0; i
< t
; i
++) {
1494 struct client_thread_s
*cn
= g_slist_nth_data(cn_thread_list
, i
);
1496 free_client(cn
->cl
);
1502 static guint
pwmd_cipher_to_gcrypt(guint64 flags
)
1504 if (flags
& PWMD_CIPHER_AES128
)
1505 return GCRY_CIPHER_AES128
;
1506 else if (flags
& PWMD_CIPHER_AES192
)
1507 return GCRY_CIPHER_AES192
;
1508 else if (flags
& PWMD_CIPHER_AES256
)
1509 return GCRY_CIPHER_AES256
;
1510 else if (flags
& PWMD_CIPHER_SERPENT128
)
1511 return GCRY_CIPHER_SERPENT128
;
1512 else if (flags
& PWMD_CIPHER_SERPENT192
)
1513 return GCRY_CIPHER_SERPENT192
;
1514 else if (flags
& PWMD_CIPHER_SERPENT256
)
1515 return GCRY_CIPHER_SERPENT256
;
1516 else if (flags
& PWMD_CIPHER_CAMELLIA128
)
1517 return GCRY_CIPHER_CAMELLIA128
;
1518 else if (flags
& PWMD_CIPHER_CAMELLIA192
)
1519 return GCRY_CIPHER_CAMELLIA192
;
1520 else if (flags
& PWMD_CIPHER_CAMELLIA256
)
1521 return GCRY_CIPHER_CAMELLIA256
;
1522 else if (flags
& PWMD_CIPHER_BLOWFISH
)
1523 return GCRY_CIPHER_BLOWFISH
;
1524 else if (flags
& PWMD_CIPHER_3DES
)
1525 return GCRY_CIPHER_3DES
;
1526 else if (flags
& PWMD_CIPHER_CAST5
)
1527 return GCRY_CIPHER_CAST5
;
1528 else if (flags
& PWMD_CIPHER_TWOFISH
)
1529 return GCRY_CIPHER_TWOFISH
;
1530 else if (flags
& PWMD_CIPHER_TWOFISH128
)
1531 return GCRY_CIPHER_TWOFISH128
;
1533 /* For backwards compatibility (no flags). */
1534 return GCRY_CIPHER_AES256
;
1537 guint
pwmd_cipher_str_to_cipher(const gchar
*str
)
1541 if (!g_strcasecmp(str
, "aes128"))
1542 flags
= PWMD_CIPHER_AES128
;
1543 else if (!g_strcasecmp(str
, "aes192"))
1544 flags
= PWMD_CIPHER_AES192
;
1545 else if (!g_strcasecmp(str
, "aes256"))
1546 flags
= PWMD_CIPHER_AES256
;
1547 if (!g_strcasecmp(str
, "serpent128"))
1548 flags
= PWMD_CIPHER_SERPENT128
;
1549 else if (!g_strcasecmp(str
, "serpent192"))
1550 flags
= PWMD_CIPHER_SERPENT192
;
1551 else if (!g_strcasecmp(str
, "serpent256"))
1552 flags
= PWMD_CIPHER_SERPENT256
;
1553 if (!g_strcasecmp(str
, "camellia128"))
1554 flags
= PWMD_CIPHER_CAMELLIA128
;
1555 else if (!g_strcasecmp(str
, "camellia192"))
1556 flags
= PWMD_CIPHER_CAMELLIA192
;
1557 else if (!g_strcasecmp(str
, "camellia256"))
1558 flags
= PWMD_CIPHER_CAMELLIA256
;
1559 else if (!g_strcasecmp(str
, "blowfish"))
1560 flags
= PWMD_CIPHER_BLOWFISH
;
1561 else if (!g_strcasecmp(str
, "cast5"))
1562 flags
= PWMD_CIPHER_CAST5
;
1563 else if (!g_strcasecmp(str
, "3des"))
1564 flags
= PWMD_CIPHER_3DES
;
1565 else if (!g_strcasecmp(str
, "twofish256"))
1566 flags
= PWMD_CIPHER_TWOFISH
;
1567 else if (!g_strcasecmp(str
, "twofish128"))
1568 flags
= PWMD_CIPHER_TWOFISH128
;
1573 const gchar
*pwmd_cipher_to_str(guint64 flags
)
1575 if (flags
& PWMD_CIPHER_AES128
)
1577 else if (flags
& PWMD_CIPHER_AES192
)
1579 else if (flags
& PWMD_CIPHER_AES256
)
1581 else if (flags
& PWMD_CIPHER_SERPENT128
)
1582 return "serpent128";
1583 else if (flags
& PWMD_CIPHER_SERPENT192
)
1584 return "serpent192";
1585 else if (flags
& PWMD_CIPHER_SERPENT256
)
1586 return "serpent256";
1587 else if (flags
& PWMD_CIPHER_CAMELLIA128
)
1588 return "camellia128";
1589 else if (flags
& PWMD_CIPHER_CAMELLIA192
)
1590 return "camellia192";
1591 else if (flags
& PWMD_CIPHER_CAMELLIA256
)
1592 return "camellia256";
1593 else if (flags
& PWMD_CIPHER_BLOWFISH
)
1595 else if (flags
& PWMD_CIPHER_CAST5
)
1597 else if (flags
& PWMD_CIPHER_3DES
)
1599 else if (flags
& PWMD_CIPHER_TWOFISH
)
1600 return "twofish256";
1601 else if (flags
& PWMD_CIPHER_TWOFISH128
)
1602 return "twofish128";
1607 /* To be called after read_file_header(). This sets the wanted algorithm from
1609 gpg_error_t
init_client_crypto2(const char *filename
,
1610 struct crypto_s
*crypto
)
1615 /* New file or conversion. */
1617 algo
= pwmd_cipher_to_gcrypt(PWMD_CIPHER_AES256
);
1618 else if (!crypto
->fh
->ver
.fh2
.flags
) {
1619 gchar
*tmp
= get_key_file_string(filename
? filename
: "global", "cipher");
1622 flags
= pwmd_cipher_str_to_cipher(tmp
);
1624 algo
= pwmd_cipher_to_gcrypt(flags
);
1625 crypto
->fh
->ver
.fh2
.flags
= flags
;
1628 algo
= pwmd_cipher_to_gcrypt(crypto
->fh
->ver
.fh2
.flags
);
1630 rc
= gcry_cipher_algo_info(algo
, GCRYCTL_TEST_ALGO
, NULL
, NULL
);
1635 rc
= gcry_cipher_algo_info(algo
, GCRYCTL_GET_KEYLEN
, NULL
,
1641 rc
= gcry_cipher_algo_info(algo
, GCRYCTL_GET_BLKLEN
, NULL
,
1642 &crypto
->blocksize
);
1648 gcry_cipher_close(crypto
->gh
);
1650 return gcry_cipher_open(&crypto
->gh
, algo
, GCRY_CIPHER_MODE_CBC
, 0);
1653 struct crypto_s
*init_client_crypto()
1655 struct crypto_s
*new = g_malloc0(sizeof(struct crypto_s
));
1658 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(GPG_ERR_ENOMEM
));
1665 static gpg_error_t
convert_file(const gchar
*filename
, const gchar
*keyfile
,
1666 const gchar
*outfile
)
1669 guchar md5file
[gcry_md_get_algo_dlen(GCRY_MD_MD5
)];
1671 struct crypto_s
*crypto
= init_client_crypto();
1672 guint hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
1675 return GPG_ERR_ENOMEM
;
1677 crypto
->key
= gcry_malloc(hashlen
);
1680 cleanup_crypto(&crypto
);
1681 return GPG_ERR_ENOMEM
;
1684 log_write(N_("Converting version 1 data file '%s' to version 2 ..."),
1686 crypto
->fh
= read_file_header(filename
, TRUE
, &rc
);
1691 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, filename
, strlen(filename
));
1693 /* The header in version 1 had a bug where the iterations were off-by-one.
1694 * So 0 iterations was really -1 in the header. This is fixed in v2 of the
1697 if (crypto
->fh
->ver
.fh1
.iter
!= -1) {
1699 rc
= parse_rcfile_keyfile(crypto
, keyfile
, TRUE
);
1704 gcry_md_hash_buffer(GCRY_MD_SHA256
, crypto
->key
, crypto
->tkey
,
1706 gcry_free(crypto
->tkey
);
1707 crypto
->tkey
= NULL
;
1710 rc
= get_password(filename
, crypto
, md5file
, crypto
->key
,
1718 rc
= init_client_crypto2(NULL
, crypto
);
1723 rc
= try_xml_decrypt(NULL
, crypto
, &crypto
->fh
->doc
, &crypto
->fh
->len
);
1728 rc
= convert_xml((gchar
**)&crypto
->fh
->doc
, &crypto
->fh
->len
);
1731 log_write("%s: %s", filename
, pwmd_strerror(rc
));
1735 crypto
->fh
->v1
= FALSE
;
1737 iter
= crypto
->fh
->ver
.fh1
.iter
+1;
1738 memset(&crypto
->fh
->ver
.fh2
, 0, sizeof(crypto
->fh
->ver
.fh2
));
1739 /* Keep the iterations and key from the original file. */
1740 crypto
->fh
->ver
.fh2
.iter
= iter
;
1741 rc
= export_common(outfile
, crypto
, crypto
->fh
->doc
, crypto
->fh
->len
);
1745 send_error(NULL
, rc
);
1747 /* fh->doc is freed from do_xml_decrypt() via the inbuf pointer. */
1748 cleanup_crypto(&crypto
);
1752 int main(int argc
, char *argv
[])
1755 struct sockaddr_un addr
;
1756 gchar buf
[PATH_MAX
];
1757 gchar
*socketpath
= NULL
, *socketdir
, *socketname
= NULL
;
1758 gchar
*socketarg
= NULL
;
1759 gchar
*datadir
= NULL
;
1763 gchar
**cache_push
= NULL
;
1764 gchar
*import
= NULL
, *keyfile
= NULL
;
1765 guint64 cmd_iterations
= 0UL;
1766 gboolean iterations_arg
= FALSE
;
1767 gint default_timeout
;
1768 gboolean rcfile_spec
= FALSE
;
1769 gint estatus
= EXIT_FAILURE
;
1771 gchar
*outfile
= NULL
;
1772 GMemVTable mtable
= { xmalloc
, xrealloc
, xfree
, xcalloc
, NULL
, NULL
};
1774 gboolean secure
= FALSE
;
1775 gint background
= 1;
1776 gchar
*convert
= NULL
;
1777 gint show_version
= 0;
1779 #ifdef WITH_PINENTRY
1780 gboolean disable_pinentry
= FALSE
;
1783 const struct option long_opts
[] = {
1784 #ifdef WITH_PINENTRY
1785 { "no-pinentry", 0, 0, 'P' },
1787 { "outfile", 1, 0, 'o' },
1788 { "convert", 1, 0, 'C' },
1789 { "no-fork", 0, 0, 'n' },
1790 { "disable-dump", 0, 0, 'D' },
1791 { "import", 1, 0, 'I' },
1792 { "iterations", 1, 0, 'i' },
1793 { "key-file", 1, 0, 'k' },
1794 { "rcfile", 1, 0, 'f' },
1795 { "version", 0, &show_version
, 1 },
1796 { "help", 0, &show_help
, 1 },
1799 #ifdef WITH_PINENTRY
1800 const gchar
*optstring
= "Po:C:nDI:i:k:f:";
1802 const gchar
*optstring
= "o:C:nDI:i:k:f:";
1805 #ifdef HAVE_SETRLIMIT
1808 rl
.rlim_cur
= rl
.rlim_max
= 0;
1810 if (setrlimit(RLIMIT_CORE
, &rl
) != 0)
1811 err(EXIT_FAILURE
, "setrlimit()");
1816 setlocale(LC_ALL
, "");
1817 bindtextdomain("pwmd", LOCALEDIR
);
1826 assuan_set_assuan_err_source(GPG_ERR_SOURCE_DEFAULT
);
1827 g_mem_set_vtable(&mtable
);
1828 assuan_set_malloc_hooks(xmalloc
, xrealloc
, xfree
);
1829 xmlMemSetup(xfree
, xmalloc
, xrealloc
, xstrdup
);
1834 g_snprintf(buf
, sizeof(buf
), "%s/.pwmd", g_get_home_dir());
1836 if (mkdir(buf
, 0700) == -1 && errno
!= EEXIST
)
1837 err(EXIT_FAILURE
, "%s", buf
);
1839 g_snprintf(buf
, sizeof(buf
), "%s/.pwmd/data", g_get_home_dir());
1841 if (mkdir(buf
, 0700) == -1 && errno
!= EEXIST
)
1842 err(EXIT_FAILURE
, "%s", buf
);
1846 while ((opt
= getopt_long(argc
, argv
, optstring
, long_opts
, &opt_index
)) != -1) {
1850 usage(argv
[0], EXIT_SUCCESS
);
1853 printf(N_("%s\nCopyright (C) 2010 %s\nReleased under the terms of the GPL v2. Use at your own risk.\n\nCompile time features:\n%s"), PACKAGE_STRING
,
1855 #ifdef WITH_PINENTRY
1889 #ifdef WITH_PINENTRY
1891 disable_pinentry
= TRUE
;
1910 cmd_iterations
= strtoul(optarg
, NULL
, 10);
1912 if (cmd_iterations
== G_MAXULONG
) {
1913 log_write("%s", N_("invalid iteration count"));
1914 usage(argv
[0], EXIT_FAILURE
);
1917 iterations_arg
= TRUE
;
1923 rcfile
= g_strdup(optarg
);
1927 usage(argv
[0], EXIT_FAILURE
);
1931 pth_mutex_init(&cn_mutex
);
1932 pth_mutex_init(&cache_mutex
);
1933 pth_mutex_init(&rcfile_mutex
);
1934 #ifdef WITH_PINENTRY
1935 pth_mutex_init(&pin_mutex
);
1939 rcfile
= g_strdup_printf("%s/.pwmd/config", g_get_home_dir());
1941 if ((keyfileh
= parse_rcfile(rcfile_spec
)) == NULL
)
1944 #ifdef WITH_PINENTRY
1945 if (disable_pinentry
== TRUE
)
1946 g_key_file_set_boolean(keyfileh
, "global", "enable_pinentry", FALSE
);
1949 if (g_key_file_has_key(keyfileh
, "global", "syslog", NULL
) == TRUE
)
1950 log_syslog
= g_key_file_get_boolean(keyfileh
, "global", "syslog", NULL
);
1952 if (log_syslog
== TRUE
)
1953 openlog("pwmd", LOG_NDELAY
|LOG_PID
, LOG_DAEMON
);
1955 if (g_key_file_has_key(keyfileh
, "global", "priority", NULL
)) {
1956 x
= g_key_file_get_integer(keyfileh
, "global", "priority", NULL
);
1959 if (setpriority(PRIO_PROCESS
, 0, x
) == -1) {
1960 log_write("setpriority(): %s", pwmd_strerror(gpg_error_from_syserror()));
1965 #ifdef HAVE_MLOCKALL
1966 if (disable_mlock
== FALSE
&& mlockall(MCL_CURRENT
|MCL_FUTURE
) == -1) {
1967 log_write("mlockall(): %s", pwmd_strerror(gpg_error_from_syserror()));
1974 usage(argv
[0], EXIT_FAILURE
);
1976 opt
= convert_file(convert
, keyfile
, outfile
);
1977 g_key_file_free(keyfileh
);
1979 exit(opt
? EXIT_FAILURE
: EXIT_SUCCESS
);
1984 usage(argv
[0], EXIT_FAILURE
);
1986 if (!iterations_arg
)
1987 cmd_iterations
= (guint64
)get_key_file_double("global", "iterations");
1989 opt
= xml_import(import
, outfile
, keyfile
, cmd_iterations
);
1990 g_key_file_free(keyfileh
);
1992 exit(opt
== FALSE
? EXIT_FAILURE
: EXIT_SUCCESS
);
1995 if ((p
= g_key_file_get_string(keyfileh
, "global", "socket_path", NULL
)) == NULL
)
1996 errx(EXIT_FAILURE
, N_("%s: socket_path not defined"), rcfile
);
1998 socketarg
= expand_homedir(p
);
2001 if ((p
= g_key_file_get_string(keyfileh
, "global", "data_directory", NULL
)) == NULL
)
2002 errx(EXIT_FAILURE
, N_("%s: data_directory not defined"), rcfile
);
2004 datadir
= expand_homedir(p
);
2007 if (secure
== FALSE
&& g_key_file_has_key(keyfileh
, "global", "disable_list_and_dump", NULL
) == TRUE
) {
2008 n
= g_key_file_get_boolean(keyfileh
, "global", "disable_list_and_dump", NULL
);
2009 disable_list_and_dump
= n
;
2012 disable_list_and_dump
= secure
;
2014 if (g_key_file_has_key(keyfileh
, "global", "cache_timeout", NULL
) == TRUE
)
2015 default_timeout
= g_key_file_get_integer(keyfileh
, "global", "cache_timeout", NULL
);
2017 default_timeout
= -1;
2019 setup_logging(keyfileh
);
2021 if (g_key_file_has_key(keyfileh
, "global", "cache_push", NULL
) == TRUE
)
2022 cache_push
= g_key_file_get_string_list(keyfileh
, "global", "cache_push", NULL
, NULL
);
2024 if (argc
!= optind
) {
2025 for (; optind
< argc
; optind
++) {
2026 if (strv_printf(&cache_push
, "%s", argv
[optind
]) == FALSE
)
2027 errx(EXIT_FAILURE
, "%s", pwmd_strerror(GPG_ERR_ENOMEM
));
2031 if (strchr(socketarg
, '/') == NULL
) {
2032 socketdir
= g_get_current_dir();
2033 socketname
= g_strdup(socketarg
);
2034 socketpath
= g_strdup_printf("%s/%s", socketdir
, socketname
);
2037 socketname
= g_strdup(strrchr(socketarg
, '/'));
2039 socketarg
[strlen(socketarg
) - strlen(socketname
) -1] = 0;
2040 socketdir
= g_strdup(socketarg
);
2041 socketpath
= g_strdup_printf("%s/%s", socketdir
, socketname
);
2044 if (chdir(datadir
)) {
2045 log_write("%s: %s", datadir
, pwmd_strerror(gpg_error_from_syserror()));
2050 if (parse_rcfile_keys() == FALSE
)
2053 clear_rcfile_keys();
2056 * Set the cache entry for a file. Prompts for the password.
2059 for (opt
= 0; cache_push
[opt
]; opt
++)
2060 do_cache_push(cache_push
[opt
], NULL
, 0);
2062 g_strfreev(cache_push
);
2063 log_write(background
? N_("Done. Daemonizing...") : N_("Done. Waiting for connections..."));
2067 * bind() doesn't like the full pathname of the socket or any non alphanum
2068 * characters so change to the directory where the socket is wanted then
2069 * create it then change to datadir.
2071 if (chdir(socketdir
)) {
2072 log_write("%s: %s", socketdir
, pwmd_strerror(gpg_error_from_syserror()));
2078 if ((sockfd
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1) {
2079 log_write("socket(): %s", pwmd_strerror(gpg_error_from_syserror()));
2083 addr
.sun_family
= AF_UNIX
;
2084 g_snprintf(addr
.sun_path
, sizeof(addr
.sun_path
), "%s", socketname
);
2086 if (bind(sockfd
, (struct sockaddr
*)&addr
, sizeof(struct sockaddr
)) == -1) {
2087 log_write("bind(): %s", pwmd_strerror(gpg_error_from_syserror()));
2089 if (errno
== EADDRINUSE
)
2090 log_write(N_("Either there is another pwmd running or '%s' is a \n"
2091 "stale socket. Please remove it manually."), socketpath
);
2097 if (g_key_file_has_key(keyfileh
, "global", "socket_perms", NULL
) == TRUE
) {
2098 gchar
*t
= g_key_file_get_string(keyfileh
, "global", "socket_perms", NULL
);
2099 mode_t mode
= strtol(t
, NULL
, 8);
2100 mode_t mask
= umask(0);
2104 if (chmod(socketname
, mode
) == -1) {
2105 log_write("%s: %s", socketname
, pwmd_strerror(gpg_error_from_syserror()));
2115 g_free(--socketname
);
2117 if (chdir(datadir
)) {
2118 log_write("%s: %s", datadir
, pwmd_strerror(gpg_error_from_syserror()));
2126 if (listen(sockfd
, 0) == -1) {
2127 log_write("listen(): %s", pwmd_strerror(gpg_error_from_syserror()));
2132 unsetenv("DISPLAY");
2138 log_write("fork(): %s", pwmd_strerror(gpg_error_from_syserror()));
2151 server_loop(sockfd
, &socketpath
);
2152 estatus
= EXIT_SUCCESS
;
2155 if (socketpath
&& do_unlink
) {
2161 g_key_file_free(keyfileh
);
2164 xmlCleanupGlobals();
2166 if (estatus
== EXIT_SUCCESS
)
2167 log_write(N_("pwmd exiting normally"));
2169 #if defined(DEBUG) && !defined(MEM_DEBUG)