1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2006-2009 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
24 #include <sys/types.h>
48 #include "pwmd_error.h"
61 static void *z_alloc(void *data
, unsigned items
, unsigned size
)
63 return gcry_calloc(items
, size
);
66 static void z_free(void *data
, void *p
)
71 static gpg_error_t
file_modified(struct client_s
*client
)
76 if (client
->state
!= STATE_OPEN
)
79 rc
= lock_file_mutex(client
);
84 if (lstat(client
->filename
, &st
) == 0 && client
->mtime
) {
85 if (client
->mtime
!= st
.st_mtime
)
86 return EPWMD_FILE_MODIFIED
;
93 static gpg_error_t
parse_xml(assuan_context_t ctx
)
95 struct client_s
*client
= assuan_get_pointer(ctx
);
97 client
->doc
= xmlReadMemory(client
->xml
, client
->len
, NULL
, "UTF-8", XML_PARSE_NOBLANKS
);
100 return EPWMD_LIBXML_ERROR
;
105 void unlock_file_mutex(struct client_s
*client
)
110 if (client
->has_lock
== FALSE
|| client
->pinentry
->status
!= PINENTRY_NONE
)
112 if (client
->has_lock
== FALSE
)
116 CACHE_LOCK(client
->ctx
);
118 if (cache_get_mutex(client
->md5file
, &m
) == FALSE
) {
125 client
->has_lock
= client
->is_lock_cmd
= FALSE
;
128 gpg_error_t
lock_file_mutex(struct client_s
*client
)
133 if (client
->has_lock
== TRUE
)
136 CACHE_LOCK(client
->ctx
);
138 if (cache_get_mutex(client
->md5file
, &m
) == FALSE
) {
144 MUTEX_TRYLOCK(client
->ctx
, m
, rc
);
147 client
->has_lock
= TRUE
;
152 void free_client(struct client_s
*client
)
155 xmlFreeDoc(client
->doc
);
158 gcry_free(client
->xml
);
160 if (client
->filename
)
161 g_free(client
->filename
);
164 cleanup_crypto(&client
->crypto
);
166 if (client
->xml_error
)
167 xmlResetError(client
->xml_error
);
170 void cleanup_client(struct client_s
*client
)
172 assuan_context_t ctx
= client
->ctx
;
173 struct client_thread_s
*thd
= client
->thd
;
174 gboolean has_lock
= client
->has_lock
;
176 struct pinentry_s
*pin
= client
->pinentry
;
179 unlock_file_mutex(client
);
180 CACHE_LOCK(client
->ctx
);
181 cache_decr_refcount(client
->md5file
);
184 * This may be a new file so don't use a cache slot. save_command() will
185 * set this to FALSE on success.
187 if (client
->new == TRUE
)
188 cache_clear(client
->md5file
, 1);
192 memset(client
, 0, sizeof(struct client_s
));
193 client
->state
= STATE_CONNECTED
;
196 client
->freed
= TRUE
;
198 client
->pinentry
= pin
;
200 client
->has_lock
= has_lock
;
203 static void gz_cleanup(void *arg
)
205 struct gz_s
**gz
= (struct gz_s
**)arg
;
210 if (!(*gz
)->done
&& (*gz
)->out
)
211 gcry_free((*gz
)->out
);
213 if ((*gz
)->which
== STATUS_COMPRESS
) {
215 deflateEnd(&(*gz
)->z
);
219 inflateEnd(&(*gz
)->z
);
226 gboolean
do_decompress(assuan_context_t ctx
, gpointer in
, gulong insize
,
227 gpointer
*out
, gulong
*outsize
, gint
*rc
)
233 gz
= g_malloc0(sizeof(struct gz_s
));
236 *rc
= gpg_error_from_errno(ENOMEM
);
240 pth_cleanup_push(gz_cleanup
, &gz
);
241 gz
->which
= STATUS_DECOMPRESS
;
242 gz
->z
.zalloc
= z_alloc
;
243 gz
->z
.zfree
= z_free
;
245 gz
->z
.avail_in
= (uInt
)insize
;
246 gz
->z
.avail_out
= zlib_bufsize
;
247 gz
->z
.next_out
= gz
->out
= gcry_malloc(zlib_bufsize
);
250 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
256 *rc
= inflateInit2(&gz
->z
, 47);
259 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
264 memset(&h
, 0, sizeof(gz_header
));
265 h
.comment
= (guchar
*)buf
;
266 h
.comm_max
= sizeof(buf
);
267 *rc
= inflateGetHeader(&gz
->z
, &h
);
270 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
275 *rc
= inflate(&gz
->z
, Z_BLOCK
);
278 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
284 insize
= (gulong
)strtol((gchar
*)h
.comment
, NULL
, 10);
289 *rc
= inflate(&gz
->z
, Z_FINISH
);
295 if (!gz
->z
.avail_out
) {
296 p
= gcry_realloc(gz
->out
, gz
->z
.total_out
+ zlib_bufsize
);
299 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
305 gz
->z
.next_out
= (guchar
*)gz
->out
+ gz
->z
.total_out
;
306 gz
->z
.avail_out
= zlib_bufsize
;
307 *rc
= send_status(ctx
, STATUS_DECOMPRESS
, "%li %li",
308 gz
->z
.total_out
, insize
);
320 } while (*rc
!= Z_STREAM_END
);
322 *rc
= send_status(ctx
, STATUS_DECOMPRESS
, "%li %li", gz
->z
.total_out
,
329 *outsize
= gz
->z
.total_out
;
336 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
341 file_header_internal_t
*read_file_header(const gchar
*filename
, gboolean v1
,
346 file_header_internal_t
*fh
= g_malloc0(sizeof(file_header_internal_t
));
353 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
354 *rc
= gpg_error_from_errno(ENOMEM
);
358 pth_cleanup_push(g_free
, fh
);
359 fh_size
= v1
? sizeof(fh
->ver
.fh1
) : sizeof(fh
->ver
.fh2
);
361 if (lstat(filename
, &fh
->st
) == -1) {
362 *rc
= gpg_error_from_syserror();
367 if (!S_ISREG(fh
->st
.st_mode
)) {
368 *rc
= GPG_ERR_ENOANO
;
373 fd
= open(filename
, O_RDONLY
);
376 *rc
= gpg_error_from_errno(errno
);
381 pth_cleanup_push(cleanup_fd_cb
, &fd
);
382 p
= v1
? (void *)&fh
->ver
.fh1
: (void *)&fh
->ver
.fh2
;
383 len
= pth_read(fd
, p
, fh_size
);
385 if (len
!= fh_size
) {
389 *rc
= gpg_error_from_errno(n
);
400 static gpg_error_t
open_command_finalize(assuan_context_t ctx
, guchar
*key
,
403 struct client_s
*client
= assuan_get_pointer(ctx
);
408 if (!client
->crypto
->fh
) {
415 rc
= try_xml_decrypt(ctx
, key
, client
->crypto
, NULL
, NULL
);
418 cleanup_client(client
);
419 return send_error(ctx
, rc
);
423 CACHE_LOCK(client
->ctx
);
425 if (cached
== FALSE
) {
426 if (cache_update_key(client
->md5file
, key
) == FALSE
) {
427 cleanup_client(client
);
429 return send_syserror(ctx
, ENOMEM
);
432 timeout
= get_key_file_integer(client
->filename
, "cache_timeout");
433 cache_reset_timeout(client
->md5file
, timeout
);
436 cache_set_timeout(client
->md5file
, -2);
444 gcry_free(client
->xml
);
449 if (client
->new == FALSE
)
450 send_status_all(STATUS_CACHE
);
452 client
->state
= STATE_OPEN
;
455 if (!rc
&& client
->new == FALSE
&&
456 client
->crypto
->fh
->ver
.fh2
.iter
!= (guint64
)get_key_file_integer(client
->filename
, "iterations")) {
457 MUTEX_LOCK(&rcfile_mutex
);
458 g_key_file_set_integer(keyfileh
, client
->filename
, "iterations",
459 client
->crypto
->fh
->ver
.fh2
.iter
);
460 MUTEX_UNLOCK(&rcfile_mutex
);
461 send_status_all(STATUS_CONFIG
);
465 log_write("OPEN '%s'", client
->filename
);
467 cleanup_crypto(&client
->crypto
);
468 return send_error(ctx
, rc
);
471 static void req_cleanup(void *arg
)
476 g_strfreev((gchar
**)arg
);
479 static int open_command(assuan_context_t ctx
, char *line
)
481 gboolean cached
= FALSE
;
483 struct client_s
*client
= assuan_get_pointer(ctx
);
485 gchar
*filename
= NULL
;
487 if ((req
= split_input_line(line
, " ", 2)) != NULL
)
490 pth_cleanup_push(req_cleanup
, req
);
492 if (!filename
|| !*filename
) {
494 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
497 if (valid_filename(filename
) == FALSE
) {
499 return send_error(ctx
, EPWMD_INVALID_FILENAME
);
502 if (client
->state
== STATE_OPEN
)
503 cleanup_client(client
);
505 gcry_md_hash_buffer(GCRY_MD_MD5
, client
->md5file
, filename
, strlen(filename
));
506 CACHE_LOCK(client
->ctx
);
508 if (cache_has_file(client
->md5file
) == FALSE
) {
509 if (cache_add_file(client
->md5file
, NULL
) == FALSE
) {
512 return send_syserror(ctx
, ENOMEM
);
516 cache_incr_refcount(client
->md5file
);
518 rc
= lock_file_mutex(client
);
522 return send_error(ctx
, rc
);
525 client
->freed
= FALSE
;
526 client
->crypto
= init_client_crypto();
528 if (!client
->crypto
) {
530 cleanup_client(client
);
531 return send_syserror(ctx
, ENOMEM
);
534 client
->crypto
->key
= gcry_malloc(gcrykeysize
);
536 if (!client
->crypto
->key
) {
538 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
,
539 gpg_error_from_errno(ENOMEM
));
540 cleanup_client(client
);
541 return send_syserror(ctx
, ENOMEM
);
544 memset(client
->crypto
->key
, 0, gcrykeysize
);
545 client
->crypto
->fh
= read_file_header(filename
, FALSE
, &rc
);
547 if (!client
->crypto
->fh
) {
548 if (gpg_err_code_to_errno(rc
) != ENOENT
) {
549 log_write("%s: %s", filename
, pwmd_strerror(rc
));
551 cleanup_client(client
);
552 return send_error(ctx
, rc
);
556 * New files don't need a key.
558 if ((client
->xml
= new_document()) == NULL
) {
559 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
561 cleanup_client(client
);
562 return send_syserror(ctx
, ENOMEM
);
565 client
->len
= xmlStrlen(client
->xml
);
567 client
->filename
= g_strdup(filename
);
569 if (!client
->filename
) {
571 cleanup_client(client
);
572 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
573 return send_syserror(ctx
, ENOMEM
);
576 if (req
[1] && *req
[1])
577 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, req
[1],
582 client
->pinentry
->filename
= g_strdup(client
->filename
);
584 if (!client
->pinentry
->filename
) {
585 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
586 cleanup_client(client
);
587 return send_syserror(ctx
, ENOMEM
);
590 return open_command_finalize(ctx
, client
->crypto
->key
, cached
);
593 client
->mtime
= client
->crypto
->fh
->st
.st_mtime
;
595 client
->filename
= g_strdup(filename
);
597 if (!client
->filename
) {
598 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
600 cleanup_client(client
);
601 return send_syserror(ctx
, ENOMEM
);
605 client
->pinentry
->filename
= g_strdup(client
->filename
);
607 if (!client
->pinentry
->filename
) {
608 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
610 cleanup_client(client
);
611 return send_syserror(ctx
, ENOMEM
);
615 if (client
->crypto
->fh
->ver
.fh2
.iter
<= 0)
618 CACHE_LOCK(client
->ctx
);
619 cached
= cache_get_key(client
->md5file
, client
->crypto
->key
);
622 if (cached
== FALSE
) {
623 gchar
*tmp
= get_key_file_string(filename
, "key_file");
628 cleanup_client(client
);
629 return send_error(ctx
, GPG_ERR_WRONG_KEY_USAGE
);
633 * No key specified and no matching filename found in the cache. Use
634 * pinentry to retrieve the key. Cannot return assuan_process_done()
635 * here otherwise the command will be interrupted. The event loop in
636 * client_thread() will poll the file descriptor waiting for it to
637 * become ready to read a pinentry_key_s which will contain the
638 * entered key or an error code. It will then call
639 * open_command_finalize() to to finish the command.
641 if (!req
[1] || !*req
[1]) {
643 gboolean b
= get_key_file_boolean(filename
, "enable_pinentry");
645 /* From set_pinentry_defaults(). */
646 if (client
->pinentry
->enable
== FALSE
||
647 (client
->pinentry
->enable
== -1 && b
== FALSE
)) {
648 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
653 rc
= lock_pin_mutex(client
);
656 unlock_pin_mutex(client
->pinentry
);
657 cleanup_client(client
);
658 return send_error(ctx
, rc
);
661 client
->pinentry
->which
= PINENTRY_OPEN
;
662 rc
= pinentry_fork(ctx
);
665 unlock_pin_mutex(client
->pinentry
);
666 cleanup_client(client
);
667 return send_error(ctx
, rc
);
670 // Called from pinentry iterate.
671 client
->pinentry
->cb
= open_command_finalize
;
672 client
->pinentry
->status
= PINENTRY_INIT
;
675 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
680 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, req
[1],
686 return open_command_finalize(ctx
, client
->crypto
->key
, cached
);
689 gboolean
do_compress(assuan_context_t ctx
, gint level
, gpointer data
,
690 gulong size
, gpointer
*out
, gulong
*outsize
, gint
*rc
)
695 gint cmd
= Z_NO_FLUSH
;
697 gz
= g_malloc0(sizeof(struct gz_s
));
700 *rc
= gpg_error_from_errno(ENOMEM
);
704 pth_cleanup_push(gz_cleanup
, &gz
);
705 gz
->which
= STATUS_COMPRESS
;
706 gz
->z
.zalloc
= z_alloc
;
707 gz
->z
.zfree
= z_free
;
708 gz
->z
.next_in
= data
;
709 gz
->z
.avail_in
= size
< zlib_bufsize
? (uInt
)size
: (uInt
)zlib_bufsize
;
710 gz
->z
.avail_out
= (uInt
)zlib_bufsize
;
711 gz
->z
.next_out
= gz
->out
= gcry_malloc(zlib_bufsize
);
714 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
720 *rc
= deflateInit2(&gz
->z
, level
, Z_DEFLATED
, 31, 8, Z_DEFAULT_STRATEGY
);
723 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
728 /* Rather than store the size of the uncompressed data in the file header,
729 * store it in the comment field of the gzip header. Don't give anyone too
730 * much information. Not sure why really, but it seems the right way. :)
732 memset(&h
, 0, sizeof(gz_header
));
733 g_snprintf(buf
, sizeof(buf
), "%li", size
);
734 h
.comment
= (guchar
*)buf
;
735 *rc
= deflateSetHeader(&gz
->z
, &h
);
738 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
746 *rc
= deflate(&gz
->z
, cmd
);
752 if (!gz
->z
.avail_out
) {
753 p
= gcry_realloc(gz
->out
, gz
->z
.total_out
+ zlib_bufsize
);
756 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
762 gz
->z
.next_out
= (guchar
*)gz
->out
+ gz
->z
.total_out
;
763 gz
->z
.avail_out
= zlib_bufsize
;
766 if (!gz
->z
.avail_in
&& gz
->z
.total_in
< size
) {
767 if (gz
->z
.total_in
+ zlib_bufsize
> size
)
768 gz
->z
.avail_in
= size
- gz
->z
.total_in
;
770 gz
->z
.avail_in
= zlib_bufsize
;
772 *rc
= send_status(ctx
, STATUS_COMPRESS
, "%li %li",
773 gz
->z
.total_in
, size
);
779 if (gz
->z
.total_in
>= size
)
788 } while (*rc
!= Z_STREAM_END
);
790 *rc
= send_status(ctx
, STATUS_COMPRESS
, "%li %li", gz
->z
.total_in
, size
);
796 *outsize
= gz
->z
.total_out
;
803 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
808 #define CRYPTO_BLOCKSIZE (gcryblocksize * 1024)
810 static gpg_error_t
iterate_crypto_once(struct client_s
*client
,
811 struct client_crypto_s
*crypto
, status_msg_t which
)
814 goffset len
= CRYPTO_BLOCKSIZE
;
815 gpointer p
= gcry_malloc(len
);
820 return gpg_err_code_from_errno(ENOMEM
);
822 if (crypto
->insize
< CRYPTO_BLOCKSIZE
)
823 len
= crypto
->insize
;
825 pth_cleanup_push(gcry_free
, p
);
828 inbuf
= (guchar
*)crypto
->inbuf
+ total
;
831 if (len
+ total
> crypto
->insize
)
834 if (which
== STATUS_ENCRYPT
)
835 rc
= gcry_cipher_encrypt(crypto
->gh
, p
, len
, inbuf
, len
);
837 rc
= gcry_cipher_decrypt(crypto
->gh
, p
, len
, inbuf
, len
);
842 tmp
= (guchar
*)crypto
->inbuf
+ total
;
843 memmove(tmp
, p
, len
);
846 if (total
>= crypto
->insize
)
857 /* The crypto struct must be setup for iterations and .key. */
858 gpg_error_t
do_xml_encrypt(struct client_s
*client
,
859 struct client_crypto_s
*crypto
, const gchar
*filename
)
861 goffset len
= crypto
->insize
;
865 guint64 iter_progress
= 0, n_iter
= 0, xiter
= 0;
866 gchar tmp
[FILENAME_MAX
];
870 if (!crypto
->fh
->ver
.fh2
.iter
) {
872 * cache_file_count() needs both .used == TRUE and a valid key in
873 * order for it to count as a used cache entry. Fixes CACHE status
876 memset(crypto
->key
, '!', gcrykeysize
);
881 * Resize the existing xml buffer to the block size required by gcrypt
882 * rather than duplicating it and wasting memory.
884 if (crypto
->insize
/ gcryblocksize
) {
885 len
= (crypto
->insize
/ gcryblocksize
) * gcryblocksize
;
887 if (crypto
->insize
% gcryblocksize
)
888 len
+= gcryblocksize
;
891 inbuf
= gcry_realloc(crypto
->inbuf
, len
);
894 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
895 return gpg_error_from_errno(ENOMEM
);
898 crypto
->inbuf
= inbuf
;
899 crypto
->insize
= len
;
900 gcry_create_nonce(crypto
->fh
->ver
.fh2
.iv
, sizeof(crypto
->fh
->ver
.fh2
.iv
));
901 crypto
->tkey
= gcry_malloc(gcrykeysize
);
904 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
905 return gpg_error_from_errno(ENOMEM
);
908 memcpy(crypto
->tkey
, crypto
->key
, gcrykeysize
);
909 guchar
*tkey
= crypto
->tkey
;
912 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->tkey
, gcrykeysize
))) {
913 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
917 iter_progress
= (guint64
)get_key_file_integer(
918 client
? client
->filename
: "global", "iteration_progress");
920 if (iter_progress
&& crypto
->fh
->ver
.fh2
.iter
>= iter_progress
) {
921 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
922 "0 %llu", crypto
->fh
->ver
.fh2
.iter
);
928 while (xiter
< crypto
->fh
->ver
.fh2
.iter
-1) {
929 if (iter_progress
> 0 && xiter
>= iter_progress
) {
930 if (!(xiter
% iter_progress
)) {
931 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
932 "%llu %llu", ++n_iter
* iter_progress
,
933 crypto
->fh
->ver
.fh2
.iter
);
940 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->fh
->ver
.fh2
.iv
,
941 sizeof(crypto
->fh
->ver
.fh2
.iv
)))) {
942 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
946 rc
= iterate_crypto_once(client
, crypto
, STATUS_ENCRYPT
);
949 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
956 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->fh
->ver
.fh2
.iv
,
957 sizeof(crypto
->fh
->ver
.fh2
.iv
)))) {
958 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
962 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->key
, gcrykeysize
))) {
963 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
967 rc
= iterate_crypto_once(client
, crypto
, STATUS_ENCRYPT
);
972 if (iter_progress
&& crypto
->fh
->ver
.fh2
.iter
>= iter_progress
) {
973 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
974 "%llu %llu", crypto
->fh
->ver
.fh2
.iter
, crypto
->fh
->ver
.fh2
.iter
);
984 if (!client
&& !g_strcmp0(filename
, "-")) {
985 crypto
->fh
->fd
= STDOUT_FILENO
;
989 if (lstat(filename
, &st
) == 0) {
990 mode
= st
.st_mode
& (S_IRWXU
|S_IRWXG
|S_IRWXO
);
992 if (!(mode
& S_IWUSR
))
993 return gpg_error_from_errno(EACCES
);
995 else if (errno
!= ENOENT
)
996 return gpg_error_from_errno(errno
);
998 g_snprintf(tmp
, sizeof(tmp
), "%s.XXXXXX", filename
);
999 crypto
->fh
->fd
= mkstemp(tmp
);
1001 if (crypto
->fh
->fd
== -1) {
1003 p
= strrchr(tmp
, '/');
1005 log_write("%s: %s", p
, strerror(rc
));
1006 return gpg_error_from_errno(rc
);
1009 pth_cleanup_push(cleanup_unlink_cb
, tmp
);
1013 * xml_import() or convert_file() from command line.
1015 crypto
->fh
->fd
= STDOUT_FILENO
;
1018 crypto
->fh
->ver
.fh2
.magic
[0] = '\177';
1019 crypto
->fh
->ver
.fh2
.magic
[1] = 'P';
1020 crypto
->fh
->ver
.fh2
.magic
[2] = 'W';
1021 crypto
->fh
->ver
.fh2
.magic
[3] = 'M';
1022 crypto
->fh
->ver
.fh2
.magic
[4] = 'D';
1023 crypto
->fh
->ver
.fh2
.version
= VERSION_HEX
;
1024 len
= pth_write(crypto
->fh
->fd
, &crypto
->fh
->ver
.fh2
, sizeof(crypto
->fh
->ver
.fh2
));
1026 if (len
!= sizeof(crypto
->fh
->ver
.fh2
)) {
1032 return gpg_error_from_errno(len
);
1035 len
= pth_write(crypto
->fh
->fd
, crypto
->inbuf
, crypto
->insize
);
1037 if (len
!= crypto
->insize
) {
1043 return gpg_error_from_errno(len
);
1046 if (fsync(crypto
->fh
->fd
) == -1) {
1052 return gpg_error_from_errno(len
);
1059 if (mode
&& get_key_file_boolean(filename
, "backup") == TRUE
) {
1060 gchar tmp2
[FILENAME_MAX
];
1062 g_snprintf(tmp2
, sizeof(tmp2
), "%s.backup", filename
);
1064 acl
= acl_get_file(filename
, ACL_TYPE_ACCESS
);
1067 log_write("ACL: %s: %s", filename
, strerror(errno
));
1070 if (rename(filename
, tmp2
) == -1) {
1077 return gpg_error_from_errno(len
);
1082 acl
= acl_get_file(".", ACL_TYPE_DEFAULT
);
1085 log_write("ACL: %s: %s", filename
, strerror(errno
));
1089 if (rename(tmp
, filename
) == -1) {
1096 return gpg_error_from_errno(len
);
1102 chmod(filename
, mode
);
1105 if (acl
&& acl_set_file(filename
, ACL_TYPE_ACCESS
, acl
))
1106 log_write("ACL: %s: %s", filename
, strerror(errno
));
1113 if (client
&& lstat(filename
, &st
) == 0)
1114 client
->mtime
= st
.st_mtime
;
1119 static gpg_error_t
save_command_finalize(assuan_context_t ctx
, guchar
*key
,
1122 struct client_s
*client
= assuan_get_pointer(ctx
);
1124 gulong len
, outsize
= 0;
1131 if (client
->crypto
->key
&& client
->crypto
->key
!= key
)
1132 gcry_free(client
->crypto
->key
);
1134 client
->crypto
->key
= key
;
1135 xmlDocDumpFormatMemory(client
->doc
, (xmlChar
**)&xmlbuf
, (gint
*)&len
, 0);
1136 pth_cleanup_push(xmlFree
, xmlbuf
);
1137 iter
= (guint
)get_key_file_integer(client
->filename
, "compression_level");
1142 if (do_compress(ctx
, (gint
)iter
, xmlbuf
, len
, &outbuf
, &outsize
, &zrc
)
1145 cleanup_crypto(&client
->crypto
);
1147 if (zrc
== Z_MEM_ERROR
)
1148 return send_syserror(ctx
, ENOMEM
);
1150 return send_error(ctx
, GPG_ERR_COMPR_ALGO
);
1158 client
->crypto
->fh
= g_malloc0(sizeof(file_header_internal_t
));
1160 if (!client
->crypto
->fh
) {
1161 cleanup_crypto(&client
->crypto
);
1163 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1164 return send_syserror(ctx
, ENOMEM
);
1167 iter
= get_key_file_integer(client
->filename
, "iterations");
1168 client
->crypto
->fh
->ver
.fh2
.iter
= iter
< 0 ? 0 : iter
;
1169 client
->crypto
->inbuf
= xmlbuf
;
1170 client
->crypto
->insize
= len
;
1171 rc
= do_xml_encrypt(client
, client
->crypto
, client
->filename
);
1174 cleanup_crypto(&client
->crypto
);
1175 return send_error(ctx
, rc
);
1178 timeout
= get_key_file_integer(client
->filename
, "cache_timeout");
1179 CACHE_LOCK(client
->ctx
);
1182 cache_reset_timeout(client
->md5file
, timeout
);
1185 if (client
->new == TRUE
)
1186 send_status_all(STATUS_CACHE
);
1188 client
->new = FALSE
;
1189 cleanup_crypto(&client
->crypto
);
1190 return send_error(ctx
, 0);
1193 if (cache_update_key(client
->md5file
, client
->crypto
->key
) == FALSE
) {
1195 cleanup_crypto(&client
->crypto
);
1196 return send_syserror(ctx
, ENOMEM
);
1199 client
->new = FALSE
;
1200 cache_reset_timeout(client
->md5file
, timeout
);
1202 send_status_all(STATUS_CACHE
);
1203 cleanup_crypto(&client
->crypto
);
1204 return send_error(ctx
, 0);
1207 static int save_command(assuan_context_t ctx
, char *line
)
1209 gboolean cached
= FALSE
;
1211 struct client_s
*client
= assuan_get_pointer(ctx
);
1213 if (lstat(client
->filename
, &st
) == -1 && errno
!= ENOENT
)
1214 return send_syserror(ctx
, errno
);
1216 if (errno
!= ENOENT
&& !S_ISREG(st
.st_mode
)) {
1217 log_write("%s: %s", client
->filename
, pwmd_strerror(GPG_ERR_ENOANO
));
1218 return send_error(ctx
, GPG_ERR_ENOANO
);
1222 cached
= cache_iscached(client
->md5file
);
1226 * If a cache entry doesn't exist for this file and the file has a
1227 * "key_file" or "key" parameter, then it's an error. The reason is that
1228 * cache expiration would be useless.
1230 if (cached
== FALSE
) {
1231 gchar
*tmp
= get_key_file_string(client
->filename
, "key_file");
1235 return send_error(ctx
, GPG_ERR_WRONG_KEY_USAGE
);
1240 client
->crypto
= init_client_crypto();
1242 if (!client
->crypto
) {
1243 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1244 return send_syserror(ctx
, ENOMEM
);
1247 client
->crypto
->key
= gcry_malloc(gcrykeysize
);
1249 if (!client
->crypto
->key
) {
1250 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1251 cleanup_crypto(&client
->crypto
);
1252 return send_syserror(ctx
, ENOMEM
);
1255 memset(client
->crypto
->key
, '!', gcrykeysize
);
1257 if (get_key_file_integer(client
->filename
, "iterations") <= 0)
1260 if (!line
|| !*line
) {
1261 client
->crypto
->tkey
= gcry_malloc(gcrykeysize
);
1263 if (!client
->crypto
->tkey
) {
1264 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1265 cleanup_crypto(&client
->crypto
);
1266 return send_syserror(ctx
, ENOMEM
);
1269 memset(client
->crypto
->tkey
, '!', gcrykeysize
);
1272 if (cache_get_key(client
->md5file
, client
->crypto
->key
) == FALSE
||
1273 memcmp(client
->crypto
->key
, client
->crypto
->tkey
,
1274 gcrykeysize
) == 0) {
1277 #ifdef WITH_PINENTRY
1280 if (client
->pinentry
->enable
== FALSE
||
1281 get_key_file_boolean(client
->filename
, "enable_pinentry") == FALSE
) {
1282 /* Empty keys are allowed. */
1283 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
1287 lock_pin_mutex(client
);
1288 client
->pinentry
->which
= PINENTRY_SAVE
;
1289 rc
= pinentry_fork(ctx
);
1292 unlock_pin_mutex(client
->pinentry
);
1293 return send_error(ctx
, rc
);
1296 client
->pinentry
->cb
= save_command_finalize
;
1297 client
->pinentry
->status
= PINENTRY_INIT
;
1300 /* Empty keys are allowed. */
1301 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
1311 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, line
,
1315 return save_command_finalize(ctx
, client
->crypto
->key
, cached
);
1318 static int delete_command(assuan_context_t ctx
, char *line
)
1320 struct client_s
*client
= assuan_get_pointer(ctx
);
1325 if (strchr(line
, '\t'))
1326 req
= split_input_line(line
, "\t", -1);
1328 req
= split_input_line(line
, " ", -1);
1331 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
1333 n
= find_account(client
->doc
, &req
, &rc
, NULL
, 0);
1337 return send_error(ctx
, rc
);
1341 * No sub-node defined. Remove the entire node (account).
1350 return send_error(ctx
, 0);
1353 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
1357 return send_error(ctx
, rc
);
1364 return send_error(ctx
, 0);
1368 * Don't return with assuan_process_done() here. This has been called from
1369 * assuan_process_next() and the command should be finished in
1372 static int store_command_finalize(gpointer data
, gint assuan_rc
, guchar
*line
,
1375 assuan_context_t ctx
= data
;
1376 struct client_s
*client
= assuan_get_pointer(ctx
);
1379 gpg_error_t rc
= file_modified(client
);
1381 if (assuan_rc
|| rc
) {
1384 return assuan_rc
? assuan_rc
: rc
;
1387 req
= split_input_line((gchar
*)line
, "\t", 0);
1391 return EPWMD_COMMAND_SYNTAX
;
1393 if (valid_xml_element((xmlChar
*)*req
) == FALSE
) {
1395 return EPWMD_INVALID_ELEMENT
;
1398 if (valid_element_path(req
+1, TRUE
) == FALSE
) {
1400 return EPWMD_INVALID_ELEMENT
;
1404 n
= find_account(client
->doc
, &req
, &rc
, NULL
, 0);
1406 if (rc
&& rc
== EPWMD_ELEMENT_NOT_FOUND
) {
1407 rc
= new_account(client
->doc
, *req
);
1424 create_elements_cb(n
, req
+1, &rc
, NULL
);
1426 find_elements(client
->doc
, n
->children
, req
+1, &rc
,
1427 NULL
, NULL
, create_elements_cb
, FALSE
, 0, NULL
);
1431 client
->inquire_status
= INQUIRE_DONE
;
1435 static int store_command(assuan_context_t ctx
, char *line
)
1437 struct client_s
*client
= assuan_get_pointer(ctx
);
1440 rc
= assuan_inquire_ext(ctx
, "STORE", 0, store_command_finalize
, ctx
);
1443 return send_error(ctx
, rc
);
1445 /* Don't return with assuan_process_done() here. This is an INQUIRE. */
1446 client
->inquire_status
= INQUIRE_BUSY
;
1450 static void *send_data_cb(void *arg
)
1452 struct assuan_cmd_s
*data
= arg
;
1456 pth_cancel_state(PTH_CANCEL_ENABLE
|PTH_CANCEL_ASYNCHRONOUS
, &old
);
1457 rc
= assuan_send_data(data
->ctx
, data
->line
, data
->line_len
);
1458 pth_cancel_state(old
, NULL
);
1459 pth_exit((void *)rc
);
1463 /* For every assuan command that needs to be sent to the client, a timeout is
1464 * needed to determine if the client lost the connection. The timeout is the
1465 * same as the "keepalive" configuration parameter or a default if unset.
1467 gpg_error_t
do_assuan_command(assuan_context_t ctx
,
1468 void *(*cb
)(void *data
), void *data
)
1470 pth_attr_t attr
= pth_attr_new();
1473 gint to
= get_key_file_integer("global", "keepalive");
1474 pth_event_t ev
, tev
;
1478 pth_attr_init(attr
);
1479 pth_attr_set(attr
, PTH_ATTR_JOINABLE
, TRUE
);
1480 pth_cleanup_push(cleanup_attr_cb
, attr
);
1481 tid
= pth_spawn(attr
, cb
, data
);
1486 log_write("%s(%i): pth_spawn(): %s", __FILE__
, __LINE__
,
1487 _gpg_strerror(gpg_error_from_errno(n
)));
1488 return gpg_error_from_errno(n
);
1491 pth_cleanup_push(cleanup_cancel_cb
, tid
);
1492 to
= to
<= 0 ? DEFAULT_KEEPALIVE_TO
: to
;
1493 ev
= pth_event(PTH_EVENT_TID
|PTH_UNTIL_TID_DEAD
, tid
);
1494 tev
= pth_event(PTH_EVENT_TIME
, pth_timeout(to
, 0));
1495 ev
= pth_event_concat(ev
, tev
, NULL
);
1496 pth_cleanup_push(cleanup_ev_cb
, ev
);
1499 st
= pth_event_status(ev
);
1501 if (st
== PTH_STATUS_FAILED
) {
1503 rc
= GPG_ERR_ASS_WRITE_ERROR
;
1505 else if (st
== PTH_STATUS_OCCURRED
)
1506 pth_join(tid
, (void **)&rc
);
1508 st
= pth_event_status(tev
);
1510 if (st
== PTH_STATUS_OCCURRED
) {
1512 rc
= GPG_ERR_ASS_WRITE_ERROR
;
1521 static gpg_error_t
xfer_data(assuan_context_t ctx
, const gchar
*line
,
1527 struct assuan_cmd_s data
;
1528 int progress
= get_key_file_integer("global", "xfer_progress");
1531 progress
= progress
>0 ? (progress
/ASSUAN_LINELENGTH
)*ASSUAN_LINELENGTH
: 0;
1532 to_send
= total
< ASSUAN_LINELENGTH
? total
: ASSUAN_LINELENGTH
;
1534 rc
= send_status(ctx
, STATUS_XFER
, "%li %li", sent
, total
);
1541 if (sent
+ to_send
> total
)
1542 to_send
= total
- sent
;
1544 data
.line
= flush
? NULL
: (gchar
*)line
+sent
;
1545 data
.line_len
= flush
? 0 : to_send
;
1546 rc
= do_assuan_command(ctx
, send_data_cb
, &data
);
1549 sent
+= flush
? 0 : to_send
;
1551 if ((progress
&& !(sent
% progress
) && sent
!= total
) ||
1552 (sent
== total
&& flush
))
1553 rc
= send_status(ctx
, STATUS_XFER
, "%li %li", sent
, total
);
1555 if (!flush
&& !rc
&& sent
== total
) {
1560 } while (!rc
&& sent
< total
);
1565 static int get_command(assuan_context_t ctx
, char *line
)
1567 struct client_s
*client
= assuan_get_pointer(ctx
);
1572 req
= split_input_line(line
, "\t", -1);
1574 if (!req
|| !*req
) {
1576 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
1579 n
= find_account(client
->doc
, &req
, &rc
, NULL
, 0);
1583 return send_error(ctx
, rc
);
1587 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
1592 return send_error(ctx
, rc
);
1594 if (!n
|| !n
->children
)
1595 return send_error(ctx
, EPWMD_EMPTY_ELEMENT
);
1597 n
= find_text_node(n
->children
);
1599 if (!n
|| !n
->content
|| !*n
->content
)
1600 return send_error(ctx
, EPWMD_EMPTY_ELEMENT
);
1602 rc
= xfer_data(ctx
, (gchar
*)n
->content
, xmlStrlen(n
->content
));
1603 return send_error(ctx
, rc
);
1606 static xmlNodePtr
realpath_elements_cb(xmlNodePtr node
, gchar
**target
,
1607 gpg_error_t
*rc
, gchar
**req_orig
, void *data
)
1609 gchar
*path
= *(gchar
**)data
;
1610 gchar
*tmp
= NULL
, *result
;
1614 *(gchar
**)data
= NULL
;
1617 path
= g_strjoinv("\t", target
);
1620 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1621 *rc
= gpg_error_from_errno(ENOMEM
);
1626 tmp
= g_strjoinv("\t", req_orig
);
1630 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1631 *rc
= gpg_error_from_errno(ENOMEM
);
1637 result
= g_strdup_printf("%s\t%s", path
, tmp
);
1639 result
= g_strdup(path
);
1642 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1643 *rc
= gpg_error_from_errno(ENOMEM
);
1651 *(gchar
**)data
= result
;
1655 static void list_command_cleanup1(void *arg
);
1656 static int realpath_command(assuan_context_t ctx
, char *line
)
1659 struct client_s
*client
= assuan_get_pointer(ctx
);
1667 if (strchr(line
, '\t') != NULL
) {
1668 if ((req
= split_input_line(line
, "\t", 0)) == NULL
)
1669 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
1672 if ((req
= split_input_line(line
, " ", 0)) == NULL
)
1673 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
1676 n
= find_account(client
->doc
, &req
, &rc
, NULL
, 0);
1680 return send_error(ctx
, rc
);
1683 rp
= g_strjoinv("\t", req
);
1687 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1688 return send_syserror(ctx
, ENOMEM
);
1692 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
,
1693 NULL
, realpath_elements_cb
, NULL
, FALSE
, 0, &rp
);
1698 return send_error(ctx
, rc
);
1702 string
= g_string_new(rp
);
1707 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1708 return send_syserror(ctx
, ENOMEM
);
1712 for (i
= 0, t
= string
->str
+ i
; *t
; t
++, i
++) {
1713 if ((!i
&& *t
!= '!') || (*t
== '\t' && *(t
+1) && *(t
+1) != '!')) {
1714 string
= g_string_insert_c(string
, !i
? i
++ : ++i
, '!');
1719 pth_cleanup_push(list_command_cleanup1
, string
);
1720 rc
= xfer_data(ctx
, string
->str
, string
->len
);
1722 return send_error(ctx
, rc
);
1725 static void list_command_cleanup1(void *arg
)
1727 g_string_free((GString
*)arg
, TRUE
);
1730 static void list_command_cleanup2(void *arg
)
1732 struct element_list_s
*elements
= arg
;
1735 gint total
= g_slist_length(elements
->list
);
1738 for (i
= 0; i
< total
; i
++) {
1739 gchar
*tmp
= g_slist_nth_data(elements
->list
, i
);
1743 g_slist_free(elements
->list
);
1745 if (elements
->prefix
)
1746 g_free(elements
->prefix
);
1752 static int list_command(assuan_context_t ctx
, char *line
)
1754 struct client_s
*client
= assuan_get_pointer(ctx
);
1756 struct element_list_s
*elements
= NULL
;
1759 if (disable_list_and_dump
== TRUE
)
1760 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
1765 rc
= list_accounts(client
->doc
, &str
);
1768 return send_error(ctx
, rc
);
1770 pth_cleanup_push(list_command_cleanup1
, str
);
1771 rc
= xfer_data(ctx
, str
->str
, str
->len
);
1773 return send_error(ctx
, rc
);
1776 elements
= g_malloc0(sizeof(struct element_list_s
));
1779 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1780 rc
= gpg_err_code_from_errno(ENOMEM
);
1784 pth_cleanup_push(list_command_cleanup2
, elements
);
1785 rc
= create_path_list(client
->doc
, elements
, line
);
1791 gint total
= g_slist_length(elements
->list
);
1796 rc
= EPWMD_EMPTY_ELEMENT
;
1800 str
= g_string_new(NULL
);
1803 rc
= gpg_err_code_from_errno(ENOMEM
);
1804 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1808 for (i
= 0; i
< total
; i
++) {
1809 tmp
= g_slist_nth_data(elements
->list
, i
);
1810 g_string_append_printf(str
, "%s%s", tmp
, i
+1 == total
? "" : "\n");
1813 pth_cleanup_push(list_command_cleanup1
, str
);
1814 rc
= xfer_data(ctx
, str
->str
, str
->len
);
1818 rc
= EPWMD_EMPTY_ELEMENT
;
1822 return send_error(ctx
, rc
);
1825 static gpg_error_t
add_attribute(xmlNodePtr node
, const gchar
*name
,
1830 if ((a
= xmlHasProp(node
, (xmlChar
*)name
)) == NULL
) {
1831 a
= xmlNewProp(node
, (xmlChar
*)name
, (xmlChar
*)value
);
1834 return EPWMD_LIBXML_ERROR
;
1837 xmlNodeSetContent(a
->children
, (xmlChar
*)value
);
1843 * req[0] - element path
1845 static int attribute_list(assuan_context_t ctx
, gchar
**req
)
1847 struct client_s
*client
= assuan_get_pointer(ctx
);
1848 gchar
**attrlist
= NULL
;
1850 gchar
**path
= NULL
;
1856 if (!req
|| !req
[0])
1857 return EPWMD_COMMAND_SYNTAX
;
1859 if ((path
= split_input_line(req
[0], "\t", 0)) == NULL
) {
1861 * The first argument may be only an account.
1863 if ((path
= split_input_line(req
[0], " ", 0)) == NULL
)
1864 return EPWMD_COMMAND_SYNTAX
;
1867 n
= find_account(client
->doc
, &path
, &rc
, NULL
, 0);
1875 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
1876 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
1886 for (a
= n
->properties
; a
; a
= a
->next
) {
1889 if ((pa
= g_realloc(attrlist
, (i
+ 2) * sizeof(gchar
*))) == NULL
) {
1891 g_strfreev(attrlist
);
1893 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1894 return gpg_error_from_errno(ENOMEM
);
1899 attrlist
[i
] = g_strdup_printf("%s %s", (gchar
*)a
->name
, (gchar
*)an
->content
);
1902 g_strfreev(attrlist
);
1903 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1904 return gpg_error_from_errno(ENOMEM
);
1907 attrlist
[++i
] = NULL
;
1911 return EPWMD_EMPTY_ELEMENT
;
1913 line
= g_strjoinv("\n", attrlist
);
1916 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1917 g_strfreev(attrlist
);
1918 return gpg_error_from_errno(ENOMEM
);
1921 pth_cleanup_push(g_free
, line
);
1922 pth_cleanup_push(req_cleanup
, attrlist
);
1923 rc
= xfer_data(ctx
, line
, strlen(line
));
1930 * req[0] - attribute
1931 * req[1] - element path
1933 static int attribute_delete(struct client_s
*client
, gchar
**req
)
1937 gchar
**path
= NULL
;
1940 if (!req
|| !req
[0] || !req
[1])
1941 return EPWMD_COMMAND_SYNTAX
;
1943 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
) {
1945 * The first argument may be only an account.
1947 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
1948 return EPWMD_COMMAND_SYNTAX
;
1952 * Don't remove the "name" attribute for the account element. To remove an
1953 * account use DELETE <account>.
1955 if (!path
[1] && xmlStrEqual((xmlChar
*)req
[0], (xmlChar
*)"name")) {
1956 rc
= EPWMD_ATTR_SYNTAX
;
1960 n
= find_account(client
->doc
, &path
, &rc
, NULL
, 0);
1966 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
1967 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
1975 if ((a
= xmlHasProp(n
, (xmlChar
*)req
[0])) == NULL
)
1976 return EPWMD_ATTR_NOT_FOUND
;
1978 if (xmlRemoveProp(a
) == -1)
1979 return EPWMD_LIBXML_ERROR
;
1988 static xmlNodePtr
create_element_path(struct client_s
*client
, gchar
***path
,
1991 gchar
**src
= *path
;
1992 gchar
**src_orig
= g_strdupv(src
);
1993 xmlNodePtr n
= NULL
;
1998 *rc
= gpg_error_from_errno(ENOMEM
);
1999 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2004 n
= find_account(client
->doc
, &src
, rc
, NULL
, 0);
2007 if (*rc
== EPWMD_ELEMENT_NOT_FOUND
) {
2008 *rc
= new_account(client
->doc
, src
[0]);
2021 n
= create_target_elements_cb(n
, src
+1, rc
, NULL
);
2023 n
= find_elements(client
->doc
, n
->children
, src
+1, rc
,
2024 NULL
, NULL
, create_target_elements_cb
, FALSE
, 0, NULL
);
2030 * Reset the position of the element tree now that the elements
2031 * have been created.
2036 n
= find_account(client
->doc
, &src
, rc
, NULL
, 0);
2041 n
= find_elements(client
->doc
, n
->children
, src
+1, rc
,
2042 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
2050 g_strfreev(src_orig
);
2057 * Creates a "target" attribute. When other commands encounter an element with
2058 * this attribute, the element path is modified to the target value. If the
2059 * source element path doesn't exist when using 'ATTR SET target', it is
2060 * created, but the destination element path must exist.
2062 * req[0] - source element path
2063 * req[1] - destination element path
2065 static gpg_error_t
target_attribute(struct client_s
*client
, gchar
**req
)
2067 gchar
**src
, **dst
, *line
= NULL
;
2071 if (!req
|| !req
[0] || !req
[1])
2072 return EPWMD_COMMAND_SYNTAX
;
2074 if ((src
= split_input_line(req
[0], "\t", 0)) == NULL
) {
2076 * The first argument may be only an account.
2078 if ((src
= split_input_line(req
[0], " ", 0)) == NULL
)
2079 return EPWMD_COMMAND_SYNTAX
;
2082 if (valid_element_path(src
, FALSE
) == FALSE
) {
2084 return EPWMD_INVALID_ELEMENT
;
2087 if ((dst
= split_input_line(req
[1], "\t", 0)) == NULL
) {
2089 * The first argument may be only an account.
2091 if ((dst
= split_input_line(req
[1], " ", 0)) == NULL
) {
2092 rc
= EPWMD_COMMAND_SYNTAX
;
2097 n
= find_account(client
->doc
, &dst
, &rc
, NULL
, 0);
2100 * Make sure the destination element path exists.
2106 n
= find_elements(client
->doc
, n
->children
, dst
+1, &rc
,
2107 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
2113 n
= create_element_path(client
, &src
, &rc
);
2118 line
= g_strjoinv("\t", dst
);
2121 rc
= gpg_error_from_errno(ENOMEM
);
2122 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2126 rc
= add_attribute(n
, "target", line
);
2136 * req[0] - account name
2139 static gpg_error_t
name_attribute(struct client_s
*client
, gchar
**req
)
2145 tmp
= g_strdupv(req
);
2148 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2149 return gpg_error_from_errno(ENOMEM
);
2152 n
= find_account(client
->doc
, &tmp
, &rc
, NULL
, 0);
2158 if (g_utf8_collate(req
[0], req
[1]) == 0)
2162 * Will not overwrite an existing account.
2164 tmp
= g_strdupv(req
+1);
2167 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2168 return gpg_error_from_errno(ENOMEM
);
2171 n
= find_account(client
->doc
, &tmp
, &rc
, NULL
, 0);
2174 if (rc
&& rc
!= EPWMD_ELEMENT_NOT_FOUND
)
2178 return EPWMD_ACCOUNT_EXISTS
;
2181 * Whitespace not allowed in account names.
2183 if (contains_whitespace(req
[1]) == TRUE
)
2184 return EPWMD_ATTR_SYNTAX
;
2186 tmp
= g_strdupv(req
);
2189 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2190 return gpg_error_from_errno(ENOMEM
);
2193 n
= find_account(client
->doc
, &tmp
, &rc
, NULL
, 0);
2197 return EPWMD_ELEMENT_NOT_FOUND
;
2199 return add_attribute(n
, "name", req
[1]);
2203 * req[0] - attribute
2204 * req[1] - element path
2206 static int attribute_get(assuan_context_t ctx
, gchar
**req
)
2208 struct client_s
*client
= assuan_get_pointer(ctx
);
2214 if (!req
|| !req
[0] || !req
[1])
2215 return EPWMD_COMMAND_SYNTAX
;
2217 if (strchr(req
[1], '\t')) {
2218 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
)
2219 return EPWMD_COMMAND_SYNTAX
;
2222 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
2223 return EPWMD_COMMAND_SYNTAX
;
2226 n
= find_account(client
->doc
, &path
, &rc
, NULL
, 0);
2232 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2233 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
2241 if ((a
= xmlGetProp(n
, (xmlChar
*)req
[0])) == NULL
)
2242 return EPWMD_ATTR_NOT_FOUND
;
2244 pth_cleanup_push(xmlFree
, a
);
2245 rc
= xfer_data(ctx
, (gchar
*)a
, xmlStrlen(a
));
2255 * req[0] - attribute
2256 * req[1] - element path
2259 static int attribute_set(struct client_s
*client
, gchar
**req
)
2261 gchar
**path
= NULL
;
2265 if (!req
|| !req
[0] || !req
[1] || !req
[2])
2266 return EPWMD_COMMAND_SYNTAX
;
2269 * Reserved attribute names.
2271 if (g_utf8_collate(req
[0], "name") == 0) {
2273 * Only reserved for the account element. Not the rest of the
2276 if (strchr(req
[1], '\t') == NULL
)
2277 return name_attribute(client
, req
+ 1);
2279 else if (g_utf8_collate(req
[0], "target") == 0)
2280 return target_attribute(client
, req
+ 1);
2282 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
) {
2284 * The first argument may be only an account.
2286 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
2287 return EPWMD_COMMAND_SYNTAX
;
2290 n
= find_account(client
->doc
, &path
, &rc
, NULL
, 0);
2296 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2297 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
2304 return add_attribute(n
, req
[0], req
[2]);
2313 * req[1] - attribute name or element path if command is LIST
2314 * req[2] - element path
2315 * req[2] - element path or value
2317 static int attr_command(assuan_context_t ctx
, char *line
)
2319 struct client_s
*client
= assuan_get_pointer(ctx
);
2323 req
= split_input_line(line
, " ", 4);
2325 if (!req
|| !req
[0] || !req
[1]) {
2327 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
2330 pth_cleanup_push(req_cleanup
, req
);
2332 if (g_ascii_strcasecmp(req
[0], "SET") == 0)
2333 rc
= attribute_set(client
, req
+1);
2334 else if (g_ascii_strcasecmp(req
[0], "GET") == 0)
2335 rc
= attribute_get(ctx
, req
+1);
2336 else if (g_ascii_strcasecmp(req
[0], "DELETE") == 0)
2337 rc
= attribute_delete(client
, req
+1);
2338 else if (g_ascii_strcasecmp(req
[0], "LIST") == 0)
2339 rc
= attribute_list(ctx
, req
+1);
2341 rc
= EPWMD_COMMAND_SYNTAX
;
2344 return send_error(ctx
, rc
);
2347 static int iscached_command(assuan_context_t ctx
, char *line
)
2349 gchar
**req
= split_input_line(line
, " ", 0);
2353 if (!req
|| !*req
) {
2355 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
2358 if (!valid_filename(req
[0])) {
2360 return EPWMD_INVALID_FILENAME
;
2363 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2366 if (cache_iscached(md5file
)) {
2369 return send_error(ctx
, 0);
2372 tmp
= get_key_file_string("global", "data_directory");
2376 return gpg_error_from_errno(ENOMEM
);
2379 path
= expand_homedir(tmp
);
2384 return gpg_error_from_errno(ENOMEM
);
2389 path
= g_strdup_printf("%s/%s", tmp
, req
[0]);
2394 return gpg_error_from_errno(ENOMEM
);
2397 if (access(path
, R_OK
) == -1) {
2398 gpg_error_t rc
= gpg_error_from_syserror();
2402 return send_error(ctx
, rc
);
2406 return send_error(ctx
, EPWMD_CACHE_NOT_FOUND
);
2409 static int clearcache_command(assuan_context_t ctx
, char *line
)
2411 struct client_s
*client
= assuan_get_pointer(ctx
);
2412 gchar
**req
= split_input_line(line
, " ", 0);
2417 if (!req
|| !*req
) {
2419 cache_clear(client
->md5file
, 2);
2421 return send_error(ctx
, 0);
2424 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2427 if (cache_clear(md5file
, 1) == FALSE
) {
2429 return send_error(ctx
, EPWMD_CACHE_NOT_FOUND
);
2433 return send_error(ctx
, 0);
2436 static int cachetimeout_command(assuan_context_t ctx
, char *line
)
2440 gchar
**req
= split_input_line(line
, " ", 0);
2443 if (!req
|| !*req
|| !req
[1]) {
2445 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
2449 timeout
= strtol(req
[1], &p
, 10);
2451 if (errno
!= 0 || *p
!= 0 || timeout
< -1) {
2453 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
2456 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2457 CACHE_LOCK(client
->ctx
);
2459 if (cache_set_timeout(md5file
, timeout
) == FALSE
) {
2461 return send_error(ctx
, EPWMD_CACHE_NOT_FOUND
);
2465 return send_error(ctx
, 0);
2468 static int dump_command(assuan_context_t ctx
, char *line
)
2472 struct client_s
*client
= assuan_get_pointer(ctx
);
2475 if (disable_list_and_dump
== TRUE
)
2476 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2478 xmlDocDumpFormatMemory(client
->doc
, &xml
, &len
, 1);
2481 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2482 return send_syserror(ctx
, ENOMEM
);
2485 pth_cleanup_push(xmlFree
, xml
);
2486 rc
= xfer_data(ctx
, (gchar
*)xml
, len
);
2488 return send_error(ctx
, rc
);
2491 static int getconfig_command(assuan_context_t ctx
, gchar
*line
)
2493 struct client_s
*client
= assuan_get_pointer(ctx
);
2495 gchar filename
[255]={0}, param
[747]={0};
2496 gchar
*p
, *tmp
, *fp
= client
->filename
, *paramp
= line
;
2498 if (strchr(line
, ' ')) {
2499 sscanf(line
, " %254[^ ] %746c", filename
, param
);
2504 if (fp
&& !valid_filename(fp
))
2505 return send_error(ctx
, EPWMD_INVALID_FILENAME
);
2507 paramp
= g_ascii_strdown(paramp
, -1);
2510 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2511 return send_syserror(ctx
, ENOMEM
);
2514 if (fp
&& !g_ascii_strcasecmp(paramp
, "iterations")) {
2515 if (!(client
->opts
& OPT_ITERATIONS
) || fp
!= client
->filename
) {
2516 file_header_internal_t
*fh
= read_file_header(fp
, FALSE
, &rc
);
2518 if (!fh
&& rc
!= GPG_ERR_ENOENT
)
2519 return send_error(ctx
, rc
);
2523 p
= g_strdup_printf("%llu", fh
->ver
.fh2
.iter
);
2524 close_file_header(fh
);
2527 log_write("%s(%i): %s", __FILE__
, __LINE__
,
2529 return send_syserror(ctx
, ENOMEM
);
2536 else if (!g_ascii_strcasecmp(paramp
, "enable_pinentry")) {
2537 #ifdef WITH_PINENTRY
2540 if (fp
== client
->filename
&& (client
->opts
& OPT_PINENTRY
))
2541 n
= client
->pinentry
->enable
;
2543 n
= get_key_file_boolean(fp
, "enable_pinentry");
2545 p
= g_strdup_printf("%s", n
? "true" : "false");
2548 log_write("%s(%i): %s", __FILE__
, __LINE__
,
2550 return send_syserror(ctx
, ENOMEM
);
2555 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2558 else if (!g_ascii_strcasecmp(paramp
, "pinentry_timeout")) {
2559 #ifdef WITH_PINENTRY
2560 if (fp
== client
->filename
&& (client
->opts
& OPT_PINENTRY_TO
))
2561 p
= g_strdup_printf("%i", client
->pinentry
->timeout
);
2563 p
= g_strdup_printf("%i",
2564 get_key_file_integer(fp
, "pinentry_timeout"));
2567 log_write("%s(%i): %s", __FILE__
, __LINE__
,
2569 return send_syserror(ctx
, ENOMEM
);
2574 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2578 p
= get_key_file_string(fp
? fp
: "global", paramp
);
2582 return send_error(ctx
, GPG_ERR_NO_VALUE
);
2584 tmp
= expand_homedir(p
);
2588 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2589 return send_syserror(ctx
, ENOMEM
);
2594 pth_cleanup_push(g_free
, p
);
2595 rc
= xfer_data(ctx
, p
, strlen(p
));
2597 return send_error(ctx
, rc
);
2601 xmlXPathContextPtr xp
;
2602 xmlXPathObjectPtr result
;
2607 static void xpath_command_cleanup(void *arg
)
2609 struct xpath_s
*xpath
= arg
;
2611 req_cleanup(xpath
->req
);
2614 xmlBufferFree(xpath
->buf
);
2617 xmlXPathFreeObject(xpath
->result
);
2620 xmlXPathFreeContext(xpath
->xp
);
2623 static int xpath_command(assuan_context_t ctx
, gchar
*line
)
2625 struct client_s
*client
= assuan_get_pointer(ctx
);
2627 struct xpath_s xpath
;
2629 if (disable_list_and_dump
== TRUE
)
2630 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2632 if (!line
|| !*line
)
2633 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
2635 memset(&xpath
, 0, sizeof(struct xpath_s
));
2637 if ((xpath
.req
= split_input_line(line
, "\t", 2)) == NULL
) {
2638 if (strv_printf(&xpath
.req
, "%s", line
) == FALSE
)
2639 return send_syserror(ctx
, ENOMEM
);
2642 xpath
.xp
= xmlXPathNewContext(client
->doc
);
2645 xpath_command_cleanup(&xpath
);
2646 return send_error(ctx
, EPWMD_LIBXML_ERROR
);
2649 xpath
.result
= xmlXPathEvalExpression((xmlChar
*)xpath
.req
[0], xpath
.xp
);
2651 if (!xpath
.result
) {
2652 xpath_command_cleanup(&xpath
);
2653 return send_error(ctx
, EPWMD_LIBXML_ERROR
);
2656 if (xmlXPathNodeSetIsEmpty(xpath
.result
->nodesetval
)) {
2657 rc
= EPWMD_EMPTY_ELEMENT
;
2661 rc
= recurse_xpath_nodeset(client
->doc
, xpath
.result
->nodesetval
,
2662 (xmlChar
*)xpath
.req
[1], &xpath
.buf
);
2666 else if (!xpath
.req
[1] && !xmlBufferLength(xpath
.buf
)) {
2667 rc
= EPWMD_EMPTY_ELEMENT
;
2670 else if (xpath
.req
[1])
2673 pth_cleanup_push(xpath_command_cleanup
, &xpath
);
2674 rc
= xfer_data(ctx
, (gchar
*)xmlBufferContent(xpath
.buf
),
2675 xmlBufferLength(xpath
.buf
));
2679 xpath_command_cleanup(&xpath
);
2680 return send_error(ctx
, rc
);
2683 static int import_command_finalize(gpointer data
, gint assuan_rc
, guchar
*line
,
2686 struct client_s
*client
= assuan_get_pointer((assuan_context_t
)data
);
2687 gpg_error_t rc
= file_modified(client
);
2688 gchar
**req
, **path
= NULL
, **path_orig
= NULL
, *content
;
2690 xmlNodePtr n
, root
, copy
;
2692 if (assuan_rc
|| rc
) {
2695 return assuan_rc
? assuan_rc
: rc
;
2698 req
= split_input_line((gchar
*)line
, " ", 2);
2702 return EPWMD_COMMAND_SYNTAX
;
2704 if ((path
= split_input_line(req
[0], "\t", 0)) == NULL
) {
2705 if ((path
= split_input_line(req
[0], " ", 0)) == NULL
)
2706 return EPWMD_COMMAND_SYNTAX
;
2711 if (!content
|| !*content
) {
2712 rc
= EPWMD_COMMAND_SYNTAX
;
2716 if (valid_xml_element((xmlChar
*)*path
) == FALSE
) {
2717 rc
= EPWMD_INVALID_ELEMENT
;
2721 if (valid_element_path(path
+1, FALSE
) == FALSE
) {
2722 rc
= EPWMD_INVALID_ELEMENT
;
2726 doc
= xmlReadDoc((xmlChar
*)content
, NULL
, "UTF-8", XML_PARSE_NOBLANKS
);
2729 rc
= EPWMD_LIBXML_ERROR
;
2733 root
= xmlDocGetRootElement(doc
);
2734 path_orig
= g_strdupv(path
);
2738 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2739 rc
= gpg_error_from_errno(ENOMEM
);
2743 if (strv_printf(&path
, "%s", (gchar
*)root
->name
) == FALSE
) {
2744 g_strfreev(path_orig
);
2746 rc
= gpg_error_from_errno(ENOMEM
);
2750 n
= find_account(client
->doc
, &path
, &rc
, NULL
, 0);
2752 if (rc
&& rc
!= EPWMD_ELEMENT_NOT_FOUND
) {
2753 g_strfreev(path_orig
);
2758 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
2760 if (rc
&& rc
!= EPWMD_ELEMENT_NOT_FOUND
) {
2761 g_strfreev(path_orig
);
2766 xmlNodePtr parent
= n
->parent
;
2777 if (rc
== EPWMD_ELEMENT_NOT_FOUND
) {
2778 n
= create_element_path(client
, &path
, &rc
);
2786 copy
= xmlCopyNode(root
, 1);
2787 n
= xmlAddChild(n
, copy
);
2791 rc
= EPWMD_LIBXML_ERROR
;
2796 client
->inquire_status
= INQUIRE_DONE
;
2800 static int import_command(assuan_context_t ctx
, gchar
*line
)
2803 struct client_s
*client
= assuan_get_pointer(ctx
);
2805 rc
= assuan_inquire_ext(ctx
, "IMPORT", 0, import_command_finalize
, ctx
);
2808 return send_error(ctx
, rc
);
2810 /* Don't return with assuan_process_done() here. This is an INQUIRE. */
2811 client
->inquire_status
= INQUIRE_BUSY
;
2815 static int lock_command(assuan_context_t ctx
, gchar
*line
)
2818 struct client_s
*client
= assuan_get_pointer(ctx
);
2820 rc
= lock_file_mutex(client
);
2823 client
->is_lock_cmd
= TRUE
;
2825 return send_error(ctx
, rc
);
2828 static int unlock_command(assuan_context_t ctx
, gchar
*line
)
2830 struct client_s
*client
= assuan_get_pointer(ctx
);
2832 unlock_file_mutex(client
);
2833 return send_error(ctx
, 0);
2836 static int getpid_command(assuan_context_t ctx
, gchar
*line
)
2840 pid_t pid
= getpid();
2842 print_fmt(buf
, sizeof(buf
), "%i", pid
);
2843 rc
= xfer_data(ctx
, buf
, strlen(buf
));
2844 return send_error(ctx
, rc
);
2847 static int version_command(assuan_context_t ctx
, gchar
*line
)
2852 print_fmt(buf
, sizeof(buf
), "0x%X", VERSION_HEX
);
2853 rc
= xfer_data(ctx
, buf
, strlen(buf
));
2854 return send_error(ctx
, rc
);
2857 #ifdef WITH_PINENTRY
2858 static void set_option_value(gchar
**opt
, const gchar
*value
)
2866 *opt
= g_strdup(value
);
2870 static int set_unset_common(assuan_context_t ctx
, const gchar
*name
,
2873 struct client_s
*client
= assuan_get_pointer(ctx
);
2875 if (g_ascii_strcasecmp(name
, (gchar
*)"iterations") == 0) {
2879 if (!client
->filename
)
2880 return EPWMD_NO_FILE
;
2883 MUTEX_LOCK(&rcfile_mutex
);
2884 g_key_file_set_integer(keyfileh
, client
->filename
, "iterations",
2885 get_key_file_integer("global", "iterations"));
2886 MUTEX_UNLOCK(&rcfile_mutex
);
2891 n
= strtol(value
, &p
, 10);
2893 if (errno
|| (p
&& *p
) || n
< 0)
2894 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
2896 MUTEX_LOCK(&rcfile_mutex
);
2897 g_key_file_set_integer(keyfileh
,
2898 client
->filename
? client
->filename
: "global", "iterations",
2900 MUTEX_UNLOCK(&rcfile_mutex
);
2902 if (client
->filename
)
2903 client
->opts
|= OPT_ITERATIONS
;
2905 else if (g_ascii_strcasecmp(name
, (gchar
*)"NAME") == 0) {
2906 pth_attr_t attr
= pth_attr_of(pth_self());
2910 pth_attr_destroy(attr
);
2914 print_fmt(buf
, sizeof(buf
), "%s", value
);
2915 pth_attr_set(attr
, PTH_ATTR_NAME
, buf
);
2916 pth_attr_destroy(attr
);
2917 #ifdef WITH_PINENTRY
2918 if (client
->pinentry
->name
)
2919 g_free(client
->pinentry
->name
);
2921 client
->pinentry
->name
= g_strdup(buf
);
2923 if (!client
->pinentry
->name
)
2924 return gpg_error_from_errno(ENOMEM
);
2927 #ifdef WITH_PINENTRY
2928 else if (g_ascii_strcasecmp(name
, (gchar
*)"lc_messages") == 0)
2929 set_option_value(&client
->pinentry
->lcmessages
, value
);
2930 else if (g_ascii_strcasecmp(name
, (gchar
*)"lc_ctype") == 0)
2931 set_option_value(&client
->pinentry
->lcctype
, value
);
2932 else if (g_ascii_strcasecmp(name
, (gchar
*)"ttyname") == 0)
2933 set_option_value(&client
->pinentry
->ttyname
, value
);
2934 else if (g_ascii_strcasecmp(name
, (gchar
*)"ttytype") == 0)
2935 set_option_value(&client
->pinentry
->ttytype
, value
);
2936 else if (g_ascii_strcasecmp(name
, (gchar
*)"display") == 0)
2937 set_option_value(&client
->pinentry
->display
, value
);
2938 else if (g_ascii_strcasecmp(name
, (gchar
*)"pinentry_path") == 0)
2939 set_option_value(&client
->pinentry
->path
, value
);
2940 else if (g_ascii_strcasecmp(name
, (gchar
*)"title") == 0)
2941 set_option_value(&client
->pinentry
->title
, value
);
2942 else if (g_ascii_strcasecmp(name
, (gchar
*)"prompt") == 0)
2943 set_option_value(&client
->pinentry
->prompt
, value
);
2944 else if (g_ascii_strcasecmp(name
, (gchar
*)"desc") == 0)
2945 set_option_value(&client
->pinentry
->desc
, value
);
2946 else if (g_ascii_strcasecmp(name
, "pinentry_timeout") == 0) {
2951 client
->pinentry
->timeout
=
2952 get_key_file_integer(client
->filename
, "pinentry_timeout");
2953 client
->opts
&= ~(OPT_PINENTRY_TO
);
2957 n
= strtol(value
, &p
, 10);
2960 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
2962 client
->pinentry
->timeout
= n
;
2963 client
->opts
|= OPT_PINENTRY_TO
;
2965 else if (g_ascii_strcasecmp(name
, "enable_pinentry") == 0) {
2970 client
->pinentry
->enable
= -1;
2971 client
->opts
&= ~(OPT_PINENTRY
);
2975 n
= strtol(value
, &p
, 10);
2977 if (*p
|| n
< 0 || n
> 1)
2978 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
2980 client
->pinentry
->enable
= n
== 0 ? FALSE
: TRUE
;
2981 client
->opts
|= OPT_PINENTRY
;
2985 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_UNKNOWN_OPTION
);
2988 log_write("%s %s%s%s", value
? "SET" : "UNSET", name
,
2989 value
? "=" : "", value
? value
: "");
2993 static int unset_command(assuan_context_t ctx
, gchar
*line
)
2995 return send_error(ctx
, set_unset_common(ctx
, line
, NULL
));
2998 static int set_command(assuan_context_t ctx
, gchar
*line
)
3000 gchar name
[64] = {0}, value
[256] = {0};
3002 if (sscanf(line
, " %63[_a-zA-Z] = %255c", name
, value
) != 2)
3003 return send_error(ctx
, gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_SYNTAX
));
3005 return send_error(ctx
, set_unset_common(ctx
, name
, value
));
3008 static void bye_notify(assuan_context_t ctx
)
3010 struct client_s
*cl
= assuan_get_pointer(ctx
);
3012 /* This will let assuan_process_next() return. */
3013 fcntl(cl
->thd
->fd
, F_SETFL
, O_NONBLOCK
);
3016 static void reset_notify(assuan_context_t ctx
)
3018 struct client_s
*cl
= assuan_get_pointer(ctx
);
3025 * This is called before every Assuan command.
3027 int command_startup(assuan_context_t ctx
, const char *name
)
3029 struct client_s
*cl
= assuan_get_pointer(ctx
);
3032 if (!g_strcmp0(name
, "ISCACHED") ||
3033 !g_strcmp0(name
, "CLEARCACHE") ||
3034 !g_strcmp0(name
, "CACHETIMEOUT") ||
3035 !g_strcmp0(name
, "GETCONFIG") ||
3036 !g_strcmp0(name
, "GETPID") ||
3037 !g_strcmp0(name
, "VERSION") ||
3038 !g_strcmp0(name
, "SET") ||
3039 !g_strcmp0(name
, "BYE") ||
3040 !g_strcmp0(name
, "NOP") ||
3041 !g_strcmp0(name
, "CANCEL") ||
3042 !g_strcmp0(name
, "RESET") ||
3043 !g_strcmp0(name
, "END") ||
3044 !g_strcmp0(name
, "HELP") ||
3045 !g_strcmp0(name
, "OPTION") ||
3046 !g_strcmp0(name
, "INPUT") ||
3047 !g_strcmp0(name
, "OUTPUT") ||
3048 !g_strcmp0(name
, "UNSET"))
3051 rc
= file_modified(cl
);
3054 if ((rc
== EPWMD_NO_FILE
|| rc
== EPWMD_FILE_MODIFIED
) &&
3055 !g_strcmp0(name
, "OPEN"))
3063 * This is called after every Assuan command.
3065 void command_finalize(assuan_context_t ctx
, gint rc
)
3067 struct client_s
*client
= assuan_get_pointer(ctx
);
3069 if (!client
->is_lock_cmd
)
3070 unlock_file_mutex(client
);
3073 gpg_error_t
register_commands(assuan_context_t ctx
)
3077 gint (*handler
)(assuan_context_t
, gchar
*line
);
3079 { "OPEN", open_command
},
3080 { "SAVE", save_command
},
3081 { "LIST", list_command
},
3082 { "REALPATH", realpath_command
},
3083 { "STORE", store_command
},
3084 { "DELETE", delete_command
},
3085 { "GET", get_command
},
3086 { "ATTR", attr_command
},
3087 { "ISCACHED", iscached_command
},
3088 { "CLEARCACHE", clearcache_command
},
3089 { "CACHETIMEOUT", cachetimeout_command
},
3090 { "GETCONFIG", getconfig_command
},
3091 { "DUMP", dump_command
},
3092 { "XPATH", xpath_command
},
3093 { "IMPORT", import_command
},
3094 { "LOCK", lock_command
},
3095 { "UNLOCK", unlock_command
},
3096 { "GETPID", getpid_command
},
3097 { "VERSION", version_command
},
3098 { "SET", set_command
},
3099 { "UNSET", unset_command
},
3106 for (i
=0; table
[i
].name
; i
++) {
3107 rc
= assuan_register_command (ctx
, table
[i
].name
, table
[i
].handler
);
3113 rc
= assuan_register_bye_notify(ctx
, bye_notify
);
3118 rc
= assuan_register_reset_notify(ctx
, reset_notify
);
3123 rc
= assuan_register_pre_cmd_notify(ctx
, command_startup
);
3128 return assuan_register_post_cmd_notify(ctx
, command_finalize
);
3131 gpg_error_t
try_xml_decrypt(assuan_context_t ctx
, guchar
*key
,
3132 struct client_crypto_s
*crypto
, gpointer
*dst
, goffset
*dst_len
)
3134 goffset insize
, len
;
3135 struct client_s
*client
= ctx
? assuan_get_pointer(ctx
) : NULL
;
3136 guint64 iter
= 0, n_iter
= 0, iter_progress
= 0;
3140 gsize fh_size
= crypto
->fh
->v1
? sizeof(crypto
->fh
->ver
.fh1
) : sizeof(crypto
->fh
->ver
.fh2
);
3141 guint64 fh_iter
= crypto
->fh
->v1
? crypto
->fh
->ver
.fh1
.iter
: crypto
->fh
->ver
.fh2
.iter
;
3143 lseek(crypto
->fh
->fd
, fh_size
, SEEK_SET
);
3144 insize
= crypto
->fh
->st
.st_size
- fh_size
;
3145 crypto
->iv
= gcry_malloc(gcryblocksize
);
3148 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
3149 return gpg_error_from_errno(ENOMEM
);
3152 /* No encryption iterations. This is a plain (gzipped) file. */
3153 if ((crypto
->fh
->v1
&& fh_iter
< 0) || (!crypto
->fh
->v1
&& fh_iter
<= 0)) {
3155 * cache_file_count() needs both .used == TRUE and a valid key in
3156 * order for it to count as a used cache entry. Fixes CACHE status
3159 memset(key
, '!', gcrykeysize
);
3163 memcpy(crypto
->iv
, crypto
->fh
->ver
.fh1
.iv
, gcryblocksize
);
3165 memcpy(crypto
->iv
, crypto
->fh
->ver
.fh2
.iv
, gcryblocksize
);
3167 crypto
->inbuf
= gcry_malloc(insize
);
3169 if (!crypto
->inbuf
) {
3170 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
3171 return gpg_error_from_errno(ENOMEM
);
3174 crypto
->insize
= insize
;
3175 len
= pth_read(crypto
->fh
->fd
, crypto
->inbuf
, crypto
->insize
);
3177 if (len
!= crypto
->insize
)
3178 return GPG_ERR_INV_LENGTH
;
3180 if ((crypto
->fh
->v1
&& fh_iter
< 0) || (!crypto
->fh
->v1
&& fh_iter
<= 0))
3183 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->iv
, gcryblocksize
))) {
3184 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
3188 if ((rc
= gcry_cipher_setkey(crypto
->gh
, key
, gcrykeysize
))) {
3189 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
3193 iter_progress
= (guint64
)get_key_file_integer(client
&& client
->filename
?
3194 client
->filename
: "global", "iteration_progress");
3196 if (iter_progress
> 0 && fh_iter
>= iter_progress
) {
3197 rc
= send_status(ctx
, STATUS_DECRYPT
, "0 %llu", fh_iter
);
3203 rc
= iterate_crypto_once(client
, crypto
, STATUS_DECRYPT
);
3208 crypto
->tkey
= gcry_malloc(gcrykeysize
);
3210 if (!crypto
->tkey
) {
3211 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
3212 return gpg_error_from_errno(ENOMEM
);
3215 memcpy(crypto
->tkey
, key
, gcrykeysize
);
3216 guchar
*tkey
= crypto
->tkey
;
3219 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->tkey
, gcrykeysize
))) {
3220 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
3224 while (iter
< (crypto
->fh
->v1
? fh_iter
: fh_iter
-1)) {
3225 if (iter_progress
> 0 && iter
>= iter_progress
) {
3226 if (!(iter
% iter_progress
)) {
3227 rc
= send_status(ctx
, STATUS_DECRYPT
, "%llu %llu",
3228 ++n_iter
* iter_progress
, fh_iter
);
3235 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->iv
, gcryblocksize
))) {
3236 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
3240 rc
= iterate_crypto_once(client
, crypto
, STATUS_DECRYPT
);
3243 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
3250 if (iter_progress
&& fh_iter
>= iter_progress
) {
3251 rc
= send_status(ctx
, STATUS_DECRYPT
, "%llu %llu", fh_iter
, fh_iter
);
3258 if (do_decompress(ctx
, crypto
->inbuf
, crypto
->insize
,
3259 (gpointer
*)&crypto
->outbuf
, &outsize
, &zrc
) == FALSE
) {
3260 if (zrc
== Z_MEM_ERROR
)
3261 return gpg_error_from_errno(ENOMEM
);
3263 return EPWMD_BADKEY
; // Not a valid gzip header. Must be a bad key.
3266 if (g_strncasecmp(crypto
->outbuf
, "<?xml version=", 14) != 0) {
3267 gcry_free(crypto
->outbuf
);
3268 crypto
->outbuf
= NULL
;
3269 return EPWMD_BADKEY
;
3273 client
->xml
= crypto
->outbuf
;
3274 client
->len
= outsize
;
3275 crypto
->outbuf
= NULL
;
3278 *dst
= crypto
->outbuf
;
3280 crypto
->outbuf
= NULL
;
3283 /* The calling function should free the crypto struct. */