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
24 #include <sys/types.h>
49 #include "pwmd_error.h"
62 static gpg_error_t
do_lock_command(struct client_s
*client
);
64 static void *z_alloc(void *data
, unsigned items
, unsigned size
)
66 return gcry_calloc(items
, size
);
69 static void z_free(void *data
, void *p
)
74 static gpg_error_t
file_modified(struct client_s
*client
)
79 if (client
->state
!= STATE_OPEN
)
82 rc
= lock_file_mutex(client
);
87 if (lstat(client
->filename
, &st
) == 0 && client
->mtime
) {
88 if (client
->mtime
!= st
.st_mtime
)
89 return EPWMD_FILE_MODIFIED
;
96 static gpg_error_t
parse_xml(assuan_context_t ctx
)
98 struct client_s
*client
= assuan_get_pointer(ctx
);
100 client
->doc
= xmlReadMemory(client
->xml
, client
->len
, NULL
, "UTF-8", XML_PARSE_NOBLANKS
);
103 return EPWMD_LIBXML_ERROR
;
105 if (!client
->crypto
->fh
|| client
->crypto
->fh
->ver
.fh2
.version
>= 0x212)
108 return convert_elements(client
->doc
);
111 void unlock_file_mutex(struct client_s
*client
)
116 if (client
->has_lock
== FALSE
|| client
->pinentry
->status
!= PINENTRY_NONE
)
118 if (client
->has_lock
== FALSE
)
122 CACHE_LOCK(client
->ctx
);
124 if (cache_get_mutex(client
->md5file
, &m
) == FALSE
) {
131 client
->has_lock
= client
->is_lock_cmd
= FALSE
;
134 gpg_error_t
lock_file_mutex(struct client_s
*client
)
139 if (client
->has_lock
== TRUE
)
142 CACHE_LOCK(client
->ctx
);
144 if (cache_get_mutex(client
->md5file
, &m
) == FALSE
) {
151 if (client
->rc_on_locked
) {
152 if (!pth_mutex_acquire(m
, TRUE
, NULL
))
153 return GPG_ERR_LOCKED
;
159 MUTEX_TRYLOCK(client
, m
, rc
);
162 client
->has_lock
= TRUE
;
167 void free_client(struct client_s
*client
)
170 xmlFreeDoc(client
->doc
);
173 gcry_free(client
->xml
);
175 if (client
->filename
)
176 g_free(client
->filename
);
179 cleanup_crypto(&client
->crypto
);
181 if (client
->xml_error
)
182 xmlResetError(client
->xml_error
);
185 void cleanup_client(struct client_s
*client
)
187 assuan_context_t ctx
= client
->ctx
;
188 struct client_thread_s
*thd
= client
->thd
;
189 gboolean rc_on_locked
= client
->rc_on_locked
;
190 gboolean lock_on_open
= client
->lock_on_open
;
192 struct pinentry_s
*pin
= client
->pinentry
;
195 unlock_file_mutex(client
);
196 CACHE_LOCK(client
->ctx
);
197 cache_decr_refcount(client
->md5file
);
200 * This may be a new file so don't use a cache slot. save_command() will
201 * set this to FALSE on success.
203 if (client
->new == TRUE
)
204 cache_clear(client
->md5file
, 1);
208 memset(client
, 0, sizeof(struct client_s
));
209 client
->state
= STATE_CONNECTED
;
212 client
->freed
= TRUE
;
214 client
->pinentry
= pin
;
216 client
->rc_on_locked
= rc_on_locked
;
217 client
->lock_on_open
= lock_on_open
;
220 static void gz_cleanup(void *arg
)
222 struct gz_s
**gz
= (struct gz_s
**)arg
;
227 if (!(*gz
)->done
&& (*gz
)->out
)
228 gcry_free((*gz
)->out
);
230 if ((*gz
)->which
== STATUS_COMPRESS
) {
232 deflateEnd(&(*gz
)->z
);
236 inflateEnd(&(*gz
)->z
);
243 gboolean
do_decompress(assuan_context_t ctx
, gpointer in
, gulong insize
,
244 gpointer
*out
, gulong
*outsize
, gint
*rc
)
250 gz
= g_malloc0(sizeof(struct gz_s
));
253 *rc
= gpg_error_from_errno(ENOMEM
);
257 pth_cleanup_push(gz_cleanup
, &gz
);
258 gz
->which
= STATUS_DECOMPRESS
;
259 gz
->z
.zalloc
= z_alloc
;
260 gz
->z
.zfree
= z_free
;
262 gz
->z
.avail_in
= (uInt
)insize
;
263 gz
->z
.avail_out
= zlib_bufsize
;
264 gz
->z
.next_out
= gz
->out
= gcry_malloc(zlib_bufsize
);
267 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
273 *rc
= inflateInit2(&gz
->z
, 47);
276 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
281 memset(&h
, 0, sizeof(gz_header
));
282 h
.comment
= (guchar
*)buf
;
283 h
.comm_max
= sizeof(buf
);
284 *rc
= inflateGetHeader(&gz
->z
, &h
);
287 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
292 *rc
= inflate(&gz
->z
, Z_BLOCK
);
295 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
301 insize
= (gulong
)strtol((gchar
*)h
.comment
, NULL
, 10);
306 *rc
= inflate(&gz
->z
, Z_FINISH
);
312 if (!gz
->z
.avail_out
) {
313 p
= gcry_realloc(gz
->out
, gz
->z
.total_out
+ zlib_bufsize
);
316 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
322 gz
->z
.next_out
= (guchar
*)gz
->out
+ gz
->z
.total_out
;
323 gz
->z
.avail_out
= zlib_bufsize
;
324 *rc
= send_status(ctx
, STATUS_DECOMPRESS
, "%li %li",
325 gz
->z
.total_out
, insize
);
337 } while (*rc
!= Z_STREAM_END
);
339 *rc
= send_status(ctx
, STATUS_DECOMPRESS
, "%li %li", gz
->z
.total_out
,
346 *outsize
= gz
->z
.total_out
;
353 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
358 file_header_internal_t
*read_file_header(const gchar
*filename
, gboolean v1
,
363 file_header_internal_t
*fh
= g_malloc0(sizeof(file_header_internal_t
));
370 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
371 *rc
= gpg_error_from_errno(ENOMEM
);
375 pth_cleanup_push(g_free
, fh
);
376 fh_size
= v1
? sizeof(fh
->ver
.fh1
) : sizeof(fh
->ver
.fh2
);
378 if (lstat(filename
, &fh
->st
) == -1) {
379 *rc
= gpg_error_from_syserror();
384 if (!S_ISREG(fh
->st
.st_mode
)) {
385 *rc
= GPG_ERR_ENOANO
;
390 fd
= open(filename
, O_RDONLY
);
393 *rc
= gpg_error_from_errno(errno
);
398 pth_cleanup_push(cleanup_fd_cb
, &fd
);
399 p
= v1
? (void *)&fh
->ver
.fh1
: (void *)&fh
->ver
.fh2
;
400 len
= pth_read(fd
, p
, fh_size
);
402 if (len
!= fh_size
) {
406 *rc
= gpg_error_from_errno(n
);
417 static gpg_error_t
open_command_finalize(assuan_context_t ctx
, guchar
*unused
,
420 struct client_s
*client
= assuan_get_pointer(ctx
);
423 guchar
*key
= client
->crypto
->key
;
426 if (!client
->crypto
->fh
) {
433 rc
= init_client_crypto2(client
->filename
, client
->crypto
);
436 cleanup_client(client
);
437 return send_error(ctx
, rc
);
440 rc
= try_xml_decrypt(ctx
, client
->crypto
, NULL
, NULL
);
443 cleanup_client(client
);
444 return send_error(ctx
, rc
);
448 CACHE_LOCK(client
->ctx
);
450 if (cached
== FALSE
) {
451 if (cache_update_key(client
->md5file
, key
) == FALSE
) {
452 cleanup_client(client
);
454 return send_syserror(ctx
, ENOMEM
);
457 timeout
= get_key_file_integer(client
->filename
, "cache_timeout");
458 cache_reset_timeout(client
->md5file
, timeout
);
461 cache_set_timeout(client
->md5file
, -2);
469 gcry_free(client
->xml
);
474 if (client
->new == FALSE
)
475 send_status_all(STATUS_CACHE
);
477 client
->state
= STATE_OPEN
;
480 if (!rc
&& client
->new == FALSE
&&
481 client
->crypto
->fh
->ver
.fh2
.iter
!= (guint64
)get_key_file_double(client
->filename
, "iterations")) {
482 MUTEX_LOCK(&rcfile_mutex
);
483 g_key_file_set_double(keyfileh
, client
->filename
, "iterations",
484 client
->crypto
->fh
->ver
.fh2
.iter
);
485 MUTEX_UNLOCK(&rcfile_mutex
);
486 send_status_all(STATUS_CONFIG
);
489 cleanup_crypto(&client
->crypto
);
491 if (!rc
&& client
->lock_on_open
)
492 return do_lock_command(client
);
494 return send_error(ctx
, rc
);
497 static void req_cleanup(void *arg
)
502 g_strfreev((gchar
**)arg
);
505 static gpg_error_t
parse_open_opt_lock(gpointer data
, gpointer value
)
507 struct client_s
*client
= data
;
508 const gchar
*p
= value
;
511 long l
= strtol(p
, NULL
, 10);
514 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
516 client
->lock_on_open
= l
? TRUE
: FALSE
;
518 else if ((!p
|| !*p
) && (client
->opts
& OPT_LOCK
))
519 client
->lock_on_open
= FALSE
;
521 client
->lock_on_open
= TRUE
;
526 static gpg_error_t
parse_opt_pinentry(gpointer data
, gpointer value
)
529 struct client_s
*client
= data
;
535 client
->pinentry
->enable
= -1;
536 client
->opts
&= ~(OPT_PINENTRY
);
540 n
= strtol(str
, &p
, 10);
542 if (*p
|| n
< 0 || n
> 1)
543 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
545 client
->pinentry
->enable
= n
? TRUE
: FALSE
;
546 client
->opts
|= OPT_PINENTRY
;
547 log_write1("enable_pinentry=%i", n
);
552 static gint
open_command(assuan_context_t ctx
, gchar
*line
)
554 gboolean cached
= FALSE
;
556 struct client_s
*client
= assuan_get_pointer(ctx
);
558 gchar
*filename
= NULL
;
559 gsize hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
560 struct argv_s
*args
[] = {
561 &(struct argv_s
) { "lock", OPT_NOARG
, parse_open_opt_lock
},
562 &(struct argv_s
) { "pinentry", OPT_OPTARG
, parse_opt_pinentry
},
566 if (client
->state
== STATE_OPEN
)
567 cleanup_client(client
);
569 if (!(client
->opts
& OPT_LOCK
))
570 client
->lock_on_open
= FALSE
;
572 rc
= parse_options(&line
, args
, client
);
575 return send_error(ctx
, rc
);
577 if ((req
= split_input_line(line
, " ", 2)) != NULL
)
580 pth_cleanup_push(req_cleanup
, req
);
582 if (!filename
|| !*filename
) {
584 return send_error(ctx
, GPG_ERR_SYNTAX
);
587 log_write2("ARGS=\"%s\" %s", filename
, req
[1] ? "<passphrase>" : "");
589 if (valid_filename(filename
) == FALSE
) {
591 return send_error(ctx
, GPG_ERR_INV_VALUE
);
594 gcry_md_hash_buffer(GCRY_MD_MD5
, client
->md5file
, filename
, strlen(filename
));
595 CACHE_LOCK(client
->ctx
);
597 if (cache_has_file(client
->md5file
) == FALSE
) {
598 if (cache_add_file(client
->md5file
, NULL
) == FALSE
) {
601 return send_syserror(ctx
, ENOMEM
);
605 cache_incr_refcount(client
->md5file
);
607 rc
= lock_file_mutex(client
);
611 return send_error(ctx
, rc
);
614 client
->freed
= FALSE
;
615 client
->crypto
= init_client_crypto();
617 if (!client
->crypto
) {
619 cleanup_client(client
);
620 return send_syserror(ctx
, ENOMEM
);
623 client
->crypto
->key
= gcry_malloc(hashlen
);
625 if (!client
->crypto
->key
) {
627 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
,
628 gpg_error_from_errno(ENOMEM
));
629 cleanup_client(client
);
630 return send_syserror(ctx
, ENOMEM
);
633 memset(client
->crypto
->key
, 0, hashlen
);
634 client
->crypto
->fh
= read_file_header(filename
, FALSE
, &rc
);
636 if (!client
->crypto
->fh
) {
637 if (gpg_err_code_to_errno(rc
) != ENOENT
) {
638 log_write("%s: %s", filename
, pwmd_strerror(rc
));
640 cleanup_client(client
);
641 return send_error(ctx
, rc
);
645 * New files don't need a key.
647 if ((client
->xml
= new_document()) == NULL
) {
648 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
650 cleanup_client(client
);
651 return send_syserror(ctx
, ENOMEM
);
654 client
->len
= xmlStrlen(client
->xml
);
656 client
->filename
= g_strdup(filename
);
658 if (!client
->filename
) {
660 cleanup_client(client
);
661 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
662 return send_syserror(ctx
, ENOMEM
);
665 if (req
[1] && *req
[1])
666 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, req
[1],
671 client
->pinentry
->filename
= g_strdup(client
->filename
);
673 if (!client
->pinentry
->filename
) {
674 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
675 cleanup_client(client
);
676 return send_syserror(ctx
, ENOMEM
);
679 return open_command_finalize(ctx
, NULL
, cached
);
682 if (!(client
->opts
& OPT_CIPHER
))
683 g_key_file_set_string(keyfileh
, filename
, "cipher",
684 pwmd_cipher_to_str(client
->crypto
->fh
->ver
.fh2
.flags
));
686 client
->mtime
= client
->crypto
->fh
->st
.st_mtime
;
689 client
->filename
= g_strdup(filename
);
691 if (!client
->filename
) {
692 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
694 cleanup_client(client
);
695 return send_syserror(ctx
, ENOMEM
);
699 if (client
->pinentry
->filename
)
700 g_free(client
->pinentry
->filename
);
702 client
->pinentry
->filename
= g_strdup(client
->filename
);
704 if (!client
->pinentry
->filename
) {
705 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
707 cleanup_client(client
);
708 return send_syserror(ctx
, ENOMEM
);
712 if (client
->crypto
->fh
->ver
.fh2
.iter
<= 0ULL)
715 CACHE_LOCK(client
->ctx
);
716 cached
= cache_get_key(client
->md5file
, client
->crypto
->key
);
719 if (cached
== FALSE
) {
720 gchar
*tmp
= get_key_file_string(filename
, "key_file");
725 cleanup_client(client
);
726 return send_error(ctx
, GPG_ERR_WRONG_KEY_USAGE
);
730 * No key specified and no matching filename found in the cache. Use
731 * pinentry to retrieve the key. Cannot return assuan_process_done()
732 * here otherwise the command will be interrupted. The event loop in
733 * client_thread() will poll the file descriptor waiting for it to
734 * become ready to read a pinentry_key_s which will contain the
735 * entered key or an error code. It will then call
736 * open_command_finalize() to to finish the command.
738 if (!req
[1] || !*req
[1]) {
740 gboolean b
= get_key_file_boolean(filename
, "enable_pinentry");
742 /* From set_pinentry_defaults(). */
743 if (client
->pinentry
->enable
== FALSE
||
744 (client
->pinentry
->enable
== -1 && b
== FALSE
)) {
745 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
750 rc
= lock_pin_mutex(client
);
753 unlock_pin_mutex(client
->pinentry
);
754 cleanup_client(client
);
755 return send_error(ctx
, rc
);
758 client
->pinentry
->which
= PINENTRY_OPEN
;
759 rc
= pinentry_fork(ctx
);
762 unlock_pin_mutex(client
->pinentry
);
763 cleanup_client(client
);
764 return send_error(ctx
, rc
);
767 // Called from pinentry iterate.
768 client
->pinentry
->cb
= open_command_finalize
;
769 client
->pinentry
->status
= PINENTRY_INIT
;
772 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
777 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, req
[1],
780 else if (req
&& req
[1] && *req
[1]) {
781 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, req
[1],
782 strlen(req
[1]) ? strlen(req
[1]) : 1);
787 return open_command_finalize(ctx
, NULL
, cached
);
790 gboolean
do_compress(assuan_context_t ctx
, gint level
, gpointer data
,
791 guint size
, gpointer
*out
, gulong
*outsize
, gint
*rc
)
796 gint cmd
= Z_NO_FLUSH
;
798 gz
= g_malloc0(sizeof(struct gz_s
));
801 *rc
= gpg_error_from_errno(ENOMEM
);
805 pth_cleanup_push(gz_cleanup
, &gz
);
806 gz
->which
= STATUS_COMPRESS
;
807 gz
->z
.zalloc
= z_alloc
;
808 gz
->z
.zfree
= z_free
;
809 gz
->z
.next_in
= data
;
810 gz
->z
.avail_in
= size
< zlib_bufsize
? (uInt
)size
: (uInt
)zlib_bufsize
;
811 gz
->z
.avail_out
= (uInt
)zlib_bufsize
;
812 gz
->z
.next_out
= gz
->out
= gcry_malloc(zlib_bufsize
);
815 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
821 *rc
= deflateInit2(&gz
->z
, level
, Z_DEFLATED
, 31, 8, Z_DEFAULT_STRATEGY
);
824 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
829 /* Rather than store the size of the uncompressed data in the file header,
830 * store it in the comment field of the gzip header. Don't give anyone too
831 * much information. Not sure why really, but it seems the right way. :)
833 memset(&h
, 0, sizeof(gz_header
));
834 g_snprintf(buf
, sizeof(buf
), "%u", size
);
835 h
.comment
= (guchar
*)buf
;
836 *rc
= deflateSetHeader(&gz
->z
, &h
);
839 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
847 *rc
= deflate(&gz
->z
, cmd
);
853 if (!gz
->z
.avail_out
) {
854 p
= gcry_realloc(gz
->out
, gz
->z
.total_out
+ zlib_bufsize
);
857 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
863 gz
->z
.next_out
= (guchar
*)gz
->out
+ gz
->z
.total_out
;
864 gz
->z
.avail_out
= zlib_bufsize
;
867 if (!gz
->z
.avail_in
&& gz
->z
.total_in
< size
) {
868 if (gz
->z
.total_in
+ zlib_bufsize
> size
)
869 gz
->z
.avail_in
= size
- gz
->z
.total_in
;
871 gz
->z
.avail_in
= zlib_bufsize
;
873 *rc
= send_status(ctx
, STATUS_COMPRESS
, "%li %u",
874 gz
->z
.total_in
, size
);
880 if (gz
->z
.total_in
>= size
)
889 } while (*rc
!= Z_STREAM_END
);
891 *rc
= send_status(ctx
, STATUS_COMPRESS
, "%li %u", gz
->z
.total_in
, size
);
897 *outsize
= gz
->z
.total_out
;
904 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
909 #define CRYPTO_BLOCKSIZE(c) (c->blocksize * 1024)
912 * Useful for a large amount of data. Rather than doing all of the data in one
913 * iteration do it in chunks. This lets the command be cancelable rather than
914 * waiting for it to complete.
916 static gpg_error_t
iterate_crypto_once(struct client_s
*client
,
917 struct crypto_s
*crypto
, status_msg_t which
)
920 goffset len
= CRYPTO_BLOCKSIZE(crypto
);
921 gpointer p
= gcry_malloc(len
);
926 return gpg_err_code_from_errno(ENOMEM
);
928 if (crypto
->insize
< CRYPTO_BLOCKSIZE(crypto
))
929 len
= crypto
->insize
;
931 pth_cleanup_push(gcry_free
, p
);
934 inbuf
= (guchar
*)crypto
->inbuf
+ total
;
937 if (len
+ total
> crypto
->insize
)
938 len
= crypto
->blocksize
;
940 if (which
== STATUS_ENCRYPT
)
941 rc
= gcry_cipher_encrypt(crypto
->gh
, p
, len
, inbuf
, len
);
943 rc
= gcry_cipher_decrypt(crypto
->gh
, p
, len
, inbuf
, len
);
948 tmp
= (guchar
*)crypto
->inbuf
+ total
;
949 memmove(tmp
, p
, len
);
952 if (total
>= crypto
->insize
)
963 /* The crypto struct must be setup for iterations and .key. */
964 gpg_error_t
do_xml_encrypt(struct client_s
*client
,
965 struct crypto_s
*crypto
, const gchar
*filename
)
967 goffset len
= crypto
->insize
;
971 guint64 iter_progress
= 0ULL, n_iter
= 0ULL, xiter
= 0ULL;
972 gchar tmp
[FILENAME_MAX
];
975 gsize hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
977 if (!crypto
->fh
->ver
.fh2
.iter
) {
979 * cache_file_count() needs both .used == TRUE and a valid key in
980 * order for it to count as a used cache entry. Fixes CACHE status
983 memset(crypto
->key
, '!', hashlen
);
988 * Resize the existing xml buffer to the block size required by gcrypt
989 * rather than duplicating it and wasting memory.
991 len
= (crypto
->insize
/ crypto
->blocksize
) * crypto
->blocksize
;
993 if (crypto
->insize
% crypto
->blocksize
)
994 len
+= crypto
->blocksize
;
996 inbuf
= gcry_realloc(crypto
->inbuf
, len
);
999 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1000 return gpg_error_from_errno(ENOMEM
);
1003 crypto
->inbuf
= inbuf
;
1004 crypto
->insize
= len
;
1005 gcry_create_nonce(crypto
->fh
->ver
.fh2
.iv
, crypto
->blocksize
);
1008 gcry_free(crypto
->tkey
);
1010 crypto
->tkey
= gcry_malloc(hashlen
);
1012 if (!crypto
->tkey
) {
1013 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1014 return gpg_error_from_errno(ENOMEM
);
1017 memcpy(crypto
->tkey
, crypto
->key
, hashlen
);
1018 guchar
*tkey
= crypto
->tkey
;
1021 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->tkey
, crypto
->keysize
))) {
1022 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
1026 iter_progress
= (guint64
)get_key_file_double(
1027 client
? client
->filename
: "global", "iteration_progress");
1029 if (iter_progress
&& crypto
->fh
->ver
.fh2
.iter
>= iter_progress
) {
1030 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
1031 "0 %llu", crypto
->fh
->ver
.fh2
.iter
);
1037 while (xiter
< crypto
->fh
->ver
.fh2
.iter
-1) {
1038 if (iter_progress
> 0ULL && xiter
>= iter_progress
) {
1039 if (!(xiter
% iter_progress
)) {
1040 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
1041 "%llu %llu", ++n_iter
* iter_progress
,
1042 crypto
->fh
->ver
.fh2
.iter
);
1049 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->fh
->ver
.fh2
.iv
,
1050 crypto
->blocksize
))) {
1051 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
1055 rc
= iterate_crypto_once(client
, crypto
, STATUS_ENCRYPT
);
1058 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
1065 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->fh
->ver
.fh2
.iv
,
1066 crypto
->blocksize
))) {
1067 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
1071 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->key
, crypto
->keysize
))) {
1072 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
1076 rc
= iterate_crypto_once(client
, crypto
, STATUS_ENCRYPT
);
1081 if (iter_progress
&& crypto
->fh
->ver
.fh2
.iter
>= iter_progress
) {
1082 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
1083 "%llu %llu", crypto
->fh
->ver
.fh2
.iter
, crypto
->fh
->ver
.fh2
.iter
);
1093 if (!client
&& !g_ascii_strcasecmp(filename
, "-")) {
1094 crypto
->fh
->fd
= STDOUT_FILENO
;
1098 if (lstat(filename
, &st
) == 0) {
1099 mode
= st
.st_mode
& (S_IRWXU
|S_IRWXG
|S_IRWXO
);
1101 if (!(mode
& S_IWUSR
))
1102 return gpg_error_from_errno(EACCES
);
1104 else if (errno
!= ENOENT
)
1105 return gpg_error_from_errno(errno
);
1107 g_snprintf(tmp
, sizeof(tmp
), "%s.XXXXXX", filename
);
1108 crypto
->fh
->fd
= mkstemp(tmp
);
1110 if (crypto
->fh
->fd
== -1) {
1112 p
= strrchr(tmp
, '/');
1114 log_write("%s: %s", p
, strerror(rc
));
1115 return gpg_error_from_errno(rc
);
1118 pth_cleanup_push(cleanup_unlink_cb
, tmp
);
1122 * xml_import() or convert_file() from command line.
1124 crypto
->fh
->fd
= STDOUT_FILENO
;
1127 crypto
->fh
->ver
.fh2
.magic
[0] = '\177';
1128 crypto
->fh
->ver
.fh2
.magic
[1] = 'P';
1129 crypto
->fh
->ver
.fh2
.magic
[2] = 'W';
1130 crypto
->fh
->ver
.fh2
.magic
[3] = 'M';
1131 crypto
->fh
->ver
.fh2
.magic
[4] = 'D';
1132 crypto
->fh
->ver
.fh2
.version
= VERSION_HEX
;
1133 len
= pth_write(crypto
->fh
->fd
, &crypto
->fh
->ver
.fh2
, sizeof(crypto
->fh
->ver
.fh2
));
1135 if (len
!= sizeof(crypto
->fh
->ver
.fh2
)) {
1141 return gpg_error_from_errno(len
);
1144 len
= pth_write(crypto
->fh
->fd
, crypto
->inbuf
, crypto
->insize
);
1146 if (len
!= crypto
->insize
) {
1152 return gpg_error_from_errno(len
);
1155 if (fsync(crypto
->fh
->fd
) == -1) {
1161 return gpg_error_from_errno(len
);
1168 if (mode
&& get_key_file_boolean(filename
, "backup") == TRUE
) {
1169 gchar tmp2
[FILENAME_MAX
];
1171 g_snprintf(tmp2
, sizeof(tmp2
), "%s.backup", filename
);
1173 acl
= acl_get_file(filename
, ACL_TYPE_ACCESS
);
1176 log_write("ACL: %s: %s", filename
, strerror(errno
));
1179 if (rename(filename
, tmp2
) == -1) {
1186 return gpg_error_from_errno(len
);
1191 acl
= acl_get_file(".", ACL_TYPE_DEFAULT
);
1194 log_write("ACL: %s: %s", filename
, strerror(errno
));
1198 if (rename(tmp
, filename
) == -1) {
1205 return gpg_error_from_errno(len
);
1211 chmod(filename
, mode
);
1214 if (acl
&& acl_set_file(filename
, ACL_TYPE_ACCESS
, acl
))
1215 log_write("ACL: %s: %s", filename
, strerror(errno
));
1222 if (client
&& lstat(filename
, &st
) == 0)
1223 client
->mtime
= st
.st_mtime
;
1228 gpg_error_t
update_save_flags(const gchar
*filename
,
1229 struct crypto_s
*crypto
)
1236 crypto
->fh
= g_malloc0(sizeof(file_header_internal_t
));
1239 return GPG_ERR_ENOMEM
;
1242 rc
= init_client_crypto2(filename
, crypto
);
1247 if (filename
&& !crypto
->fh
->v1
) {
1248 iter
= (guint64
)get_key_file_double(filename
, "iterations");
1249 crypto
->fh
->ver
.fh2
.iter
= iter
< 0L ? 0UL : iter
;
1255 static gpg_error_t
save_command_finalize(assuan_context_t ctx
, guchar
*key
,
1258 struct client_s
*client
= assuan_get_pointer(ctx
);
1268 if (client
->crypto
->key
&& client
->crypto
->key
!= key
)
1269 gcry_free(client
->crypto
->key
);
1271 client
->crypto
->key
= key
;
1272 rc
= update_element_mtime(xmlDocGetRootElement(client
->doc
));
1275 return send_error(ctx
, rc
);
1277 xmlDocDumpFormatMemory(client
->doc
, (xmlChar
**)&xmlbuf
, (gint
*)&len
, 0);
1278 pth_cleanup_push(xmlFree
, xmlbuf
);
1279 clevel
= get_key_file_integer(client
->filename
, "compression_level");
1284 if (do_compress(ctx
, clevel
, xmlbuf
, len
, &outbuf
, &outsize
, &zrc
) == FALSE
) {
1286 cleanup_crypto(&client
->crypto
);
1288 if (zrc
== Z_MEM_ERROR
)
1289 return send_syserror(ctx
, ENOMEM
);
1291 return send_error(ctx
, GPG_ERR_COMPR_ALGO
);
1299 client
->crypto
->inbuf
= xmlbuf
;
1300 client
->crypto
->insize
= len
;
1301 rc
= update_save_flags(client
->filename
, client
->crypto
);
1304 cleanup_crypto(&client
->crypto
);
1305 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(rc
));
1306 return send_error(ctx
, rc
);
1309 rc
= do_xml_encrypt(client
, client
->crypto
, client
->filename
);
1312 cleanup_crypto(&client
->crypto
);
1313 return send_error(ctx
, rc
);
1316 timeout
= get_key_file_integer(client
->filename
, "cache_timeout");
1317 CACHE_LOCK(client
->ctx
);
1320 cache_reset_timeout(client
->md5file
, timeout
);
1323 if (client
->new == TRUE
)
1324 send_status_all(STATUS_CACHE
);
1326 client
->new = FALSE
;
1327 cleanup_crypto(&client
->crypto
);
1328 return send_error(ctx
, 0);
1331 if (cache_update_key(client
->md5file
, client
->crypto
->key
) == FALSE
) {
1333 cleanup_crypto(&client
->crypto
);
1334 return send_syserror(ctx
, ENOMEM
);
1337 client
->new = FALSE
;
1338 cache_reset_timeout(client
->md5file
, timeout
);
1340 send_status_all(STATUS_CACHE
);
1341 cleanup_crypto(&client
->crypto
);
1342 return send_error(ctx
, 0);
1345 static gpg_error_t
parse_save_opt_iterations(gpointer data
, gpointer v
)
1347 struct client_s
*client
= data
;
1352 if (!client
->filename
)
1353 return EPWMD_NO_FILE
;
1355 if (!value
|| !*value
)
1359 n
= strtoul(value
, &p
, 10);
1361 if (errno
|| (p
&& *p
) || n
== G_MAXULONG
)
1362 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
1364 MUTEX_LOCK(&rcfile_mutex
);
1365 g_key_file_set_double(keyfileh
,
1366 client
->filename
? client
->filename
: "global", "iterations", n
);
1367 MUTEX_UNLOCK(&rcfile_mutex
);
1369 if (client
->filename
)
1370 client
->opts
|= OPT_ITERATIONS
;
1372 log_write1("iterations=%lu", n
);
1376 static gpg_error_t
parse_save_opt_cipher(gpointer data
, gpointer value
)
1378 struct client_s
*client
= data
;
1379 const gchar
*p
= value
;
1382 if (!client
->filename
)
1383 return EPWMD_NO_FILE
;
1388 flags
= pwmd_cipher_str_to_cipher(p
);
1391 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
1393 MUTEX_LOCK(&rcfile_mutex
);
1394 g_key_file_set_string(keyfileh
, client
->filename
, "cipher", p
);
1395 MUTEX_UNLOCK(&rcfile_mutex
);
1396 log_write1("cipher=%s", p
);
1404 static gpg_error_t
parse_save_opt_reset(gpointer data
, gpointer value
)
1406 struct client_s
*client
= data
;
1408 CACHE_LOCK(client
->ctx
);
1409 cache_clear(client
->md5file
, 1);
1414 static gint
save_command(assuan_context_t ctx
, gchar
*line
)
1416 gboolean cached
= FALSE
;
1418 struct client_s
*client
= assuan_get_pointer(ctx
);
1419 guint hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
1421 struct argv_s
*args
[] = {
1422 &(struct argv_s
) { "iterations", OPT_OPTARG
, parse_save_opt_iterations
},
1423 &(struct argv_s
) { "cipher", OPT_OPTARG
, parse_save_opt_cipher
},
1424 &(struct argv_s
) { "pinentry", OPT_OPTARG
, parse_opt_pinentry
},
1425 &(struct argv_s
) { "reset", OPT_NOARG
, parse_save_opt_reset
},
1429 rc
= parse_options(&line
, args
, client
);
1432 return send_error(ctx
, rc
);
1435 log_write2("ARGS=%s", "<passphrase>");
1437 if (lstat(client
->filename
, &st
) == -1 && errno
!= ENOENT
)
1438 return send_syserror(ctx
, errno
);
1440 if (errno
!= ENOENT
&& !S_ISREG(st
.st_mode
)) {
1441 log_write("%s: %s", client
->filename
, pwmd_strerror(GPG_ERR_ENOANO
));
1442 return send_error(ctx
, GPG_ERR_ENOANO
);
1446 cached
= cache_iscached(client
->md5file
);
1450 * If a cache entry doesn't exist for this file and the file has a
1451 * "key_file" or "key" parameter, then it's an error. The reason is that
1452 * cache expiration would be useless.
1454 if (cached
== FALSE
) {
1455 gchar
*tmp
= get_key_file_string(client
->filename
, "key_file");
1459 return send_error(ctx
, GPG_ERR_WRONG_KEY_USAGE
);
1466 if (!client
->crypto
) {
1467 client
->crypto
= init_client_crypto();
1469 if (!client
->crypto
) {
1470 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1471 return send_syserror(ctx
, ENOMEM
);
1475 client
->crypto
->key
= gcry_malloc(hashlen
);
1477 if (!client
->crypto
->key
) {
1478 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1479 cleanup_crypto(&client
->crypto
);
1480 return send_syserror(ctx
, ENOMEM
);
1483 memset(client
->crypto
->key
, '!', hashlen
);
1485 if (get_key_file_double(client
->filename
, "iterations") <= 0L &&
1489 if (!line
|| !*line
) {
1490 client
->crypto
->tkey
= gcry_malloc(hashlen
);
1492 if (!client
->crypto
->tkey
) {
1493 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1494 cleanup_crypto(&client
->crypto
);
1495 return send_syserror(ctx
, ENOMEM
);
1498 memset(client
->crypto
->tkey
, '!', hashlen
);
1501 if (cache_get_key(client
->md5file
, client
->crypto
->key
) == FALSE
||
1502 !memcmp(client
->crypto
->key
, client
->crypto
->tkey
, hashlen
)) {
1505 #ifdef WITH_PINENTRY
1508 if (client
->pinentry
->enable
== FALSE
||
1509 get_key_file_boolean(client
->filename
, "enable_pinentry") == FALSE
) {
1510 /* Empty keys are allowed. */
1511 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
1515 lock_pin_mutex(client
);
1516 client
->pinentry
->which
= PINENTRY_SAVE
;
1517 rc
= pinentry_fork(ctx
);
1520 unlock_pin_mutex(client
->pinentry
);
1521 cleanup_crypto(&client
->crypto
);
1522 return send_error(ctx
, rc
);
1525 client
->pinentry
->cb
= save_command_finalize
;
1526 client
->pinentry
->status
= PINENTRY_INIT
;
1529 /* Empty keys are allowed. */
1530 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
1540 if (get_key_file_double(client
->filename
, "iterations") <= 0L) {
1541 guint64 iter
= (guint64
)get_key_file_double(NULL
, "iterations");
1546 MUTEX_LOCK(&rcfile_mutex
);
1547 g_key_file_set_double(keyfileh
, client
->filename
, "iterations", iter
);
1548 MUTEX_UNLOCK(&rcfile_mutex
);
1549 client
->opts
|= OPT_ITERATIONS
;
1550 gpg_error_t rc
= send_status(ctx
, STATUS_CONFIG
, NULL
);
1553 return send_error(ctx
, rc
);
1556 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, line
,
1561 return save_command_finalize(ctx
, client
->crypto
->key
, cached
);
1564 static gint
delete_command(assuan_context_t ctx
, gchar
*line
)
1566 struct client_s
*client
= assuan_get_pointer(ctx
);
1571 log_write2("ARGS=\"%s\"", line
);
1573 if (strchr(line
, '\t'))
1574 req
= split_input_line(line
, "\t", -1);
1576 req
= split_input_line(line
, " ", -1);
1579 return send_error(ctx
, GPG_ERR_SYNTAX
);
1581 n
= find_root_element(client
->doc
, &req
, &rc
, NULL
, 0, FALSE
);
1585 return send_error(ctx
, rc
);
1589 * No sub-node defined. Remove the entire node (root element).
1593 rc
= unlink_node(n
);
1598 return send_error(ctx
, rc
);
1601 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
1605 return send_error(ctx
, rc
);
1608 rc
= unlink_node(n
);
1612 return send_error(ctx
, rc
);
1616 * Don't return with assuan_process_done() here. This has been called from
1617 * assuan_process_next() and the command should be finished in
1620 static gint
store_command_finalize(gpointer data
, gint assuan_rc
, guchar
*line
,
1623 assuan_context_t ctx
= data
;
1624 struct client_s
*client
= assuan_get_pointer(ctx
);
1627 gpg_error_t rc
= file_modified(client
);
1629 if (assuan_rc
|| rc
) {
1632 return assuan_rc
? assuan_rc
: rc
;
1635 req
= split_input_line((gchar
*)line
, "\t", 0);
1639 return GPG_ERR_SYNTAX
;
1642 n
= find_root_element(client
->doc
, &req
, &rc
, NULL
, 0, FALSE
);
1644 if (rc
&& rc
== GPG_ERR_ELEMENT_NOT_FOUND
) {
1645 rc
= new_root_element(client
->doc
, *req
);
1662 n
= create_elements_cb(n
, req
+1, &rc
, NULL
);
1664 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
,
1665 NULL
, NULL
, create_elements_cb
, FALSE
, 0, NULL
, FALSE
);
1669 client
->inquire_status
= INQUIRE_DONE
;
1672 rc
= update_element_mtime(n
);
1677 static gint
store_command(assuan_context_t ctx
, gchar
*line
)
1679 struct client_s
*client
= assuan_get_pointer(ctx
);
1682 rc
= assuan_inquire_ext(ctx
, "STORE", 0, store_command_finalize
, ctx
);
1685 return send_error(ctx
, rc
);
1687 /* Don't return with assuan_process_done() here. This is an INQUIRE. */
1688 client
->inquire_status
= INQUIRE_BUSY
;
1692 static void *send_data_cb(void *arg
)
1694 struct assuan_cmd_s
*data
= arg
;
1698 pth_cancel_state(PTH_CANCEL_ENABLE
|PTH_CANCEL_ASYNCHRONOUS
, &old
);
1699 rc
= g_malloc(sizeof(gpg_error_t
));
1700 *rc
= assuan_send_data(data
->ctx
, data
->line
, data
->line_len
);
1701 pth_cancel_state(old
, NULL
);
1706 /* For every assuan command that needs to be sent to the client, a timeout is
1707 * needed to determine if the client lost the connection. The timeout is the
1708 * same as the "keepalive" configuration parameter or a default if unset.
1710 gpg_error_t
do_assuan_command(assuan_context_t ctx
,
1711 void *(*cb
)(void *data
), void *data
)
1713 pth_attr_t attr
= pth_attr_new();
1716 gint to
= get_key_file_integer("global", "keepalive");
1717 pth_event_t ev
, tev
;
1722 pth_attr_init(attr
);
1723 pth_attr_set(attr
, PTH_ATTR_JOINABLE
, TRUE
);
1724 tid
= pth_spawn(attr
, cb
, data
);
1726 pth_attr_destroy(attr
);
1729 log_write("%s(%i): pth_spawn(): %s", __FILE__
, __LINE__
,
1730 _gpg_strerror(gpg_error_from_errno(n
)));
1731 return gpg_error_from_errno(n
);
1734 pth_cleanup_push(cleanup_cancel_cb
, tid
);
1735 to
= to
<= 0 ? DEFAULT_KEEPALIVE_TO
: to
;
1736 ev
= pth_event(PTH_EVENT_TID
|PTH_UNTIL_TID_DEAD
, tid
);
1737 tev
= to
? pth_event(PTH_EVENT_TIME
, pth_timeout(to
, 0)) : NULL
;
1738 ev
= pth_event_concat(ev
, tev
, NULL
);
1739 pth_cleanup_push(cleanup_ev_cb
, ev
);
1744 st
= pth_event_status(tev
);
1746 if (st
== PTH_STATUS_OCCURRED
) {
1749 return GPG_ERR_TIMEOUT
;
1753 st
= pth_event_status(ev
);
1755 if (st
== PTH_STATUS_FAILED
) {
1759 rc
= GPG_ERR_ASS_WRITE_ERROR
;
1761 else if (st
== PTH_STATUS_OCCURRED
) {
1763 rc
= *(gpg_error_t
*)p
;
1772 static gpg_error_t
xfer_data(assuan_context_t ctx
, const gchar
*line
,
1778 struct assuan_cmd_s data
;
1779 gint progress
= get_key_file_integer("global", "xfer_progress");
1782 progress
= progress
>0 ? (progress
/ASSUAN_LINELENGTH
)*ASSUAN_LINELENGTH
: 0;
1783 to_send
= total
< ASSUAN_LINELENGTH
? total
: ASSUAN_LINELENGTH
;
1785 rc
= send_status(ctx
, STATUS_XFER
, "%li %li", sent
, total
);
1792 if (sent
+ to_send
> total
)
1793 to_send
= total
- sent
;
1795 data
.line
= flush
? NULL
: (gchar
*)line
+sent
;
1796 data
.line_len
= flush
? 0 : to_send
;
1797 rc
= do_assuan_command(ctx
, send_data_cb
, &data
);
1800 sent
+= flush
? 0 : to_send
;
1802 if ((progress
&& !(sent
% progress
) && sent
!= total
) ||
1803 (sent
== total
&& flush
))
1804 rc
= send_status(ctx
, STATUS_XFER
, "%li %li", sent
, total
);
1806 if (!flush
&& !rc
&& sent
== total
) {
1811 } while (!rc
&& sent
< total
);
1816 static gint
get_command(assuan_context_t ctx
, gchar
*line
)
1818 struct client_s
*client
= assuan_get_pointer(ctx
);
1823 log_write2("ARGS=\"%s\"", line
);
1824 req
= split_input_line(line
, "\t", -1);
1826 if (!req
|| !*req
) {
1828 return send_error(ctx
, GPG_ERR_SYNTAX
);
1831 n
= find_root_element(client
->doc
, &req
, &rc
, NULL
, 0, FALSE
);
1835 return send_error(ctx
, rc
);
1839 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
1844 return send_error(ctx
, rc
);
1846 if (!n
|| !n
->children
)
1847 return send_error(ctx
, GPG_ERR_NO_VALUE
);
1849 n
= find_text_node(n
->children
);
1851 if (!n
|| !n
->content
|| !*n
->content
)
1852 return send_error(ctx
, GPG_ERR_NO_VALUE
);
1854 rc
= xfer_data(ctx
, (gchar
*)n
->content
, xmlStrlen(n
->content
));
1855 return send_error(ctx
, rc
);
1858 static xmlNodePtr
realpath_elements_cb(xmlNodePtr node
, gchar
**target
,
1859 gpg_error_t
*rc
, gchar
**req_orig
, void *data
)
1861 gchar
*path
= *(gchar
**)data
;
1862 gchar
*tmp
= NULL
, *result
;
1866 *(gchar
**)data
= NULL
;
1869 path
= g_strjoinv("\t", target
);
1872 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1873 *rc
= gpg_error_from_errno(ENOMEM
);
1878 tmp
= g_strjoinv("\t", req_orig
);
1882 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1883 *rc
= gpg_error_from_errno(ENOMEM
);
1889 result
= g_strdup_printf("%s\t%s", path
, tmp
);
1891 result
= g_strdup(path
);
1894 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1895 *rc
= gpg_error_from_errno(ENOMEM
);
1903 *(gchar
**)data
= result
;
1907 static void list_command_cleanup1(void *arg
);
1908 static gint
realpath_command(assuan_context_t ctx
, gchar
*line
)
1911 struct client_s
*client
= assuan_get_pointer(ctx
);
1919 log_write2("ARGS=\"%s\"", line
);
1921 if (strchr(line
, '\t') != NULL
) {
1922 if ((req
= split_input_line(line
, "\t", 0)) == NULL
)
1923 return send_error(ctx
, GPG_ERR_SYNTAX
);
1926 if ((req
= split_input_line(line
, " ", 0)) == NULL
)
1927 return send_error(ctx
, GPG_ERR_SYNTAX
);
1930 n
= find_root_element(client
->doc
, &req
, &rc
, NULL
, 0, FALSE
);
1934 return send_error(ctx
, rc
);
1937 rp
= g_strjoinv("\t", req
);
1941 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1942 return send_syserror(ctx
, ENOMEM
);
1946 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
,
1947 NULL
, realpath_elements_cb
, NULL
, FALSE
, 0, &rp
, FALSE
);
1952 return send_error(ctx
, rc
);
1956 string
= g_string_new(rp
);
1961 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1962 return send_syserror(ctx
, ENOMEM
);
1966 for (i
= 0, t
= string
->str
+ i
; *t
; t
++, i
++) {
1967 if ((!i
&& *t
!= '!') || (*t
== '\t' && *(t
+1) && *(t
+1) != '!')) {
1968 string
= g_string_insert_c(string
, !i
? i
++ : ++i
, '!');
1973 pth_cleanup_push(list_command_cleanup1
, string
);
1974 rc
= xfer_data(ctx
, string
->str
, string
->len
);
1976 return send_error(ctx
, rc
);
1979 static void list_command_cleanup1(void *arg
)
1981 g_string_free((GString
*)arg
, TRUE
);
1984 static void list_command_cleanup2(void *arg
)
1986 struct element_list_s
*elements
= arg
;
1989 if (elements
->list
) {
1990 gint total
= g_slist_length(elements
->list
);
1993 for (i
= 0; i
< total
; i
++) {
1994 gchar
*tmp
= g_slist_nth_data(elements
->list
, i
);
1998 g_slist_free(elements
->list
);
2001 if (elements
->prefix
)
2002 g_free(elements
->prefix
);
2005 g_strfreev(elements
->req
);
2011 static gpg_error_t
parse_list_opt_norecurse(gpointer data
, gpointer value
)
2013 struct element_list_s
*elements
= data
;
2015 elements
->recurse
= FALSE
;
2019 static gpg_error_t
parse_list_opt_verbose(gpointer data
, gpointer value
)
2021 struct element_list_s
*elements
= data
;
2023 elements
->verbose
= TRUE
;
2027 static gint
list_command(assuan_context_t ctx
, gchar
*line
)
2029 struct client_s
*client
= assuan_get_pointer(ctx
);
2031 struct element_list_s
*elements
= NULL
;
2033 struct argv_s
*args
[] = {
2034 &(struct argv_s
) { "no-recurse", OPT_NOARG
, parse_list_opt_norecurse
},
2035 &(struct argv_s
) { "verbose", OPT_NOARG
, parse_list_opt_verbose
},
2039 if (disable_list_and_dump
== TRUE
)
2040 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2042 elements
= g_malloc0(sizeof(struct element_list_s
));
2045 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2046 return gpg_err_code_from_errno(ENOMEM
);
2049 elements
->recurse
= TRUE
; // default
2050 pth_cleanup_push(list_command_cleanup2
, elements
);
2051 rc
= parse_options(&line
, args
, elements
);
2059 rc
= list_root_elements(client
->doc
, &str
, elements
->verbose
);
2063 return send_error(ctx
, rc
);
2066 pth_cleanup_push(list_command_cleanup1
, str
);
2067 rc
= xfer_data(ctx
, str
->str
, str
->len
);
2070 return send_error(ctx
, rc
);
2073 elements
->req
= split_input_line(line
, " ", 0);
2076 strv_printf(&elements
->req
, "%s", line
);
2078 rc
= create_path_list(client
->doc
, elements
, *elements
->req
);
2084 gint total
= g_slist_length(elements
->list
);
2089 rc
= GPG_ERR_NO_VALUE
;
2093 str
= g_string_new(NULL
);
2096 rc
= gpg_err_code_from_errno(ENOMEM
);
2097 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2101 for (i
= 0; i
< total
; i
++) {
2102 tmp
= g_slist_nth_data(elements
->list
, i
);
2103 g_string_append_printf(str
, "%s%s", tmp
, i
+1 == total
? "" : "\n");
2106 pth_cleanup_push(list_command_cleanup1
, str
);
2107 rc
= xfer_data(ctx
, str
->str
, str
->len
);
2111 rc
= GPG_ERR_NO_VALUE
;
2115 return send_error(ctx
, rc
);
2119 * req[0] - element path
2121 static gpg_error_t
attribute_list(assuan_context_t ctx
, gchar
**req
)
2123 struct client_s
*client
= assuan_get_pointer(ctx
);
2124 gchar
**attrlist
= NULL
;
2126 gchar
**path
= NULL
;
2132 if (!req
|| !req
[0])
2133 return GPG_ERR_SYNTAX
;
2135 if ((path
= split_input_line(req
[0], "\t", 0)) == NULL
) {
2137 * The first argument may be only a root element.
2139 if ((path
= split_input_line(req
[0], " ", 0)) == NULL
)
2140 return GPG_ERR_SYNTAX
;
2143 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, FALSE
);
2151 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2152 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2162 for (a
= n
->properties
; a
; a
= a
->next
) {
2165 if ((pa
= g_realloc(attrlist
, (i
+ 2) * sizeof(gchar
*))) == NULL
) {
2167 g_strfreev(attrlist
);
2169 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2170 return gpg_error_from_errno(ENOMEM
);
2175 attrlist
[i
] = g_strdup_printf("%s %s", (gchar
*)a
->name
,
2176 an
&& an
->content
? (gchar
*)an
->content
: "");
2179 g_strfreev(attrlist
);
2180 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2181 return gpg_error_from_errno(ENOMEM
);
2184 attrlist
[++i
] = NULL
;
2188 return GPG_ERR_NO_VALUE
;
2190 line
= g_strjoinv("\n", attrlist
);
2193 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2194 g_strfreev(attrlist
);
2195 return gpg_error_from_errno(ENOMEM
);
2198 pth_cleanup_push(g_free
, line
);
2199 pth_cleanup_push(req_cleanup
, attrlist
);
2200 rc
= xfer_data(ctx
, line
, strlen(line
));
2207 * req[0] - attribute
2208 * req[1] - element path
2210 static gpg_error_t
attribute_delete(struct client_s
*client
, gchar
**req
)
2213 gchar
**path
= NULL
;
2216 if (!req
|| !req
[0] || !req
[1])
2217 return GPG_ERR_SYNTAX
;
2219 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
) {
2221 * The first argument may be only a root element.
2223 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
2224 return GPG_ERR_SYNTAX
;
2228 * Don't remove the "_name" attribute for the root element. To remove an
2229 * root element use DELETE <name>.
2231 if (!path
[1] && xmlStrEqual((xmlChar
*)req
[0], (xmlChar
*)"_name")) {
2232 rc
= GPG_ERR_SYNTAX
;
2236 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, FALSE
);
2242 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2243 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2249 rc
= delete_attribute(n
, (xmlChar
*)req
[0]);
2256 static xmlNodePtr
create_element_path(struct client_s
*client
, gchar
***path
,
2259 gchar
**src
= *path
;
2260 gchar
**src_orig
= g_strdupv(src
);
2261 xmlNodePtr n
= NULL
;
2266 *rc
= gpg_error_from_errno(ENOMEM
);
2267 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2272 n
= find_root_element(client
->doc
, &src
, rc
, NULL
, 0, FALSE
);
2275 if (*rc
== GPG_ERR_ELEMENT_NOT_FOUND
) {
2276 *rc
= new_root_element(client
->doc
, src
[0]);
2289 n
= create_target_elements_cb(n
, src
+1, rc
, NULL
);
2291 n
= find_elements(client
->doc
, n
->children
, src
+1, rc
,
2292 NULL
, NULL
, create_target_elements_cb
, FALSE
, 0, NULL
, FALSE
);
2298 * Reset the position of the element tree now that the elements
2299 * have been created.
2304 n
= find_root_element(client
->doc
, &src
, rc
, NULL
, 0, FALSE
);
2309 n
= find_elements(client
->doc
, n
->children
, src
+1, rc
,
2310 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2318 g_strfreev(src_orig
);
2325 * Creates a "target" attribute. When other commands encounter an element with
2326 * this attribute, the element path is modified to the target value. If the
2327 * source element path doesn't exist when using 'ATTR SET target', it is
2328 * created, but the destination element path must exist.
2330 * req[0] - source element path
2331 * req[1] - destination element path
2333 static gpg_error_t
target_attribute(struct client_s
*client
, gchar
**req
)
2335 gchar
**src
, **dst
, *line
= NULL
, **odst
= NULL
;
2339 if (!req
|| !req
[0] || !req
[1])
2340 return GPG_ERR_SYNTAX
;
2342 if ((src
= split_input_line(req
[0], "\t", 0)) == NULL
) {
2344 * The first argument may be only a root element.
2346 if ((src
= split_input_line(req
[0], " ", 0)) == NULL
)
2347 return GPG_ERR_SYNTAX
;
2350 if ((dst
= split_input_line(req
[1], "\t", 0)) == NULL
) {
2352 * The first argument may be only a root element.
2354 if ((dst
= split_input_line(req
[1], " ", 0)) == NULL
) {
2355 rc
= GPG_ERR_SYNTAX
;
2360 odst
= g_strdupv(dst
);
2363 rc
= gpg_error_from_errno(ENOMEM
);
2367 n
= find_root_element(client
->doc
, &dst
, &rc
, NULL
, 0, FALSE
);
2370 * Make sure the destination element path exists.
2376 n
= find_elements(client
->doc
, n
->children
, dst
+1, &rc
,
2377 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2383 n
= create_element_path(client
, &src
, &rc
);
2388 line
= g_strjoinv("\t", odst
);
2391 rc
= gpg_error_from_errno(ENOMEM
);
2392 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2396 rc
= add_attribute(n
, "target", line
);
2410 static gpg_error_t
name_attribute(struct client_s
*client
, gchar
**req
)
2416 tmp
= g_strdupv(req
);
2419 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2420 return gpg_error_from_errno(ENOMEM
);
2423 n
= find_root_element(client
->doc
, &tmp
, &rc
, NULL
, 0, FALSE
);
2429 if (g_utf8_collate(req
[0], req
[1]) == 0)
2433 * Will not overwrite an existing root.
2435 tmp
= g_strdupv(req
+1);
2438 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2439 return gpg_error_from_errno(ENOMEM
);
2442 n
= find_root_element(client
->doc
, &tmp
, &rc
, NULL
, 0, FALSE
);
2445 if (rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
)
2449 return GPG_ERR_AMBIGUOUS_NAME
;
2452 * Whitespace not allowed in root names.
2454 if (contains_whitespace(req
[1]) == TRUE
)
2455 return GPG_ERR_SYNTAX
;
2457 tmp
= g_strdupv(req
);
2460 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2461 return gpg_error_from_errno(ENOMEM
);
2464 n
= find_root_element(client
->doc
, &tmp
, &rc
, NULL
, 0, FALSE
);
2468 return GPG_ERR_ELEMENT_NOT_FOUND
;
2470 return add_attribute(n
, "_name", req
[1]);
2474 * req[0] - attribute
2475 * req[1] - element path
2477 static gpg_error_t
attribute_get(assuan_context_t ctx
, gchar
**req
)
2479 struct client_s
*client
= assuan_get_pointer(ctx
);
2485 if (!req
|| !req
[0] || !req
[1])
2486 return GPG_ERR_SYNTAX
;
2488 if (strchr(req
[1], '\t')) {
2489 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
)
2490 return GPG_ERR_SYNTAX
;
2493 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
2494 return GPG_ERR_SYNTAX
;
2497 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, FALSE
);
2503 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2504 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2512 if ((a
= xmlGetProp(n
, (xmlChar
*)req
[0])) == NULL
)
2513 return GPG_ERR_NOT_FOUND
;
2515 pth_cleanup_push(xmlFree
, a
);
2518 rc
= xfer_data(ctx
, (gchar
*)a
, xmlStrlen(a
));
2520 rc
= GPG_ERR_NO_VALUE
;
2531 * req[0] - attribute
2532 * req[1] - element path
2535 static gpg_error_t
attribute_set(struct client_s
*client
, gchar
**req
)
2537 gchar
**path
= NULL
;
2541 if (!req
|| !req
[0] || !req
[1])
2542 return GPG_ERR_SYNTAX
;
2545 * Reserved attribute names.
2547 if (!strcmp(req
[0], "_name")) {
2549 * Only reserved for the root element. Not the rest of the
2552 if (strchr(req
[1], '\t') == NULL
)
2553 return name_attribute(client
, req
+ 1);
2555 else if (!strcmp(req
[0], "target"))
2556 return target_attribute(client
, req
+ 1);
2558 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
) {
2560 * The first argument may be only a root element.
2562 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
2563 return GPG_ERR_SYNTAX
;
2566 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, FALSE
);
2572 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2573 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2579 rc
= add_attribute(n
, req
[0], req
[2]);
2588 * req[1] - attribute name or element path if command is LIST
2589 * req[2] - element path
2590 * req[2] - element path or value
2592 static gint
attr_command(assuan_context_t ctx
, gchar
*line
)
2594 struct client_s
*client
= assuan_get_pointer(ctx
);
2598 log_write2("ARGS=\"%s\"", line
);
2599 req
= split_input_line(line
, " ", 4);
2601 if (!req
|| !req
[0] || !req
[1]) {
2603 return send_error(ctx
, GPG_ERR_SYNTAX
);
2606 pth_cleanup_push(req_cleanup
, req
);
2608 if (g_ascii_strcasecmp(req
[0], "SET") == 0)
2609 rc
= attribute_set(client
, req
+1);
2610 else if (g_ascii_strcasecmp(req
[0], "GET") == 0)
2611 rc
= attribute_get(ctx
, req
+1);
2612 else if (g_ascii_strcasecmp(req
[0], "DELETE") == 0)
2613 rc
= attribute_delete(client
, req
+1);
2614 else if (g_ascii_strcasecmp(req
[0], "LIST") == 0)
2615 rc
= attribute_list(ctx
, req
+1);
2617 rc
= GPG_ERR_SYNTAX
;
2620 return send_error(ctx
, rc
);
2623 static gint
iscached_command(assuan_context_t ctx
, gchar
*line
)
2625 gchar
**req
= split_input_line(line
, " ", 0);
2629 if (!req
|| !*req
) {
2631 return send_error(ctx
, GPG_ERR_SYNTAX
);
2634 log_write2("ARGS=\"%s\"", line
);
2636 if (!valid_filename(req
[0])) {
2638 return GPG_ERR_INV_VALUE
;
2641 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2644 if (cache_iscached(md5file
)) {
2647 return send_error(ctx
, 0);
2651 tmp
= get_key_file_string("global", "data_directory");
2655 return gpg_error_from_errno(ENOMEM
);
2658 path
= expand_homedir(tmp
);
2663 return gpg_error_from_errno(ENOMEM
);
2668 path
= g_strdup_printf("%s/%s", tmp
, req
[0]);
2673 return gpg_error_from_errno(ENOMEM
);
2676 if (access(path
, R_OK
) == -1) {
2677 gpg_error_t rc
= gpg_error_from_syserror();
2681 return send_error(ctx
, rc
);
2685 return send_error(ctx
, GPG_ERR_NOT_FOUND
);
2688 static gint
clearcache_command(assuan_context_t ctx
, gchar
*line
)
2690 struct client_s
*client
= assuan_get_pointer(ctx
);
2691 gchar
**req
= split_input_line(line
, " ", 0);
2694 log_write2("ARGS=\"%s\"", line
);
2697 if (!req
|| !*req
) {
2699 cache_clear(client
->md5file
, 2);
2701 return send_error(ctx
, 0);
2704 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2707 if (cache_clear(md5file
, 1) == FALSE
) {
2709 return send_error(ctx
, GPG_ERR_NOT_FOUND
);
2713 return send_error(ctx
, 0);
2716 static gint
cachetimeout_command(assuan_context_t ctx
, gchar
*line
)
2720 gchar
**req
= split_input_line(line
, " ", 0);
2723 if (!req
|| !*req
|| !req
[1]) {
2725 return send_error(ctx
, GPG_ERR_SYNTAX
);
2729 timeout
= strtol(req
[1], &p
, 10);
2731 if (errno
!= 0 || *p
!= 0 || timeout
< -1) {
2733 return send_error(ctx
, GPG_ERR_SYNTAX
);
2736 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2737 CACHE_LOCK(client
->ctx
);
2739 if (cache_set_timeout(md5file
, timeout
) == FALSE
) {
2741 return send_error(ctx
, GPG_ERR_NOT_FOUND
);
2745 return send_error(ctx
, 0);
2748 static gint
dump_command(assuan_context_t ctx
, gchar
*line
)
2752 struct client_s
*client
= assuan_get_pointer(ctx
);
2755 if (disable_list_and_dump
== TRUE
)
2756 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2758 xmlDocDumpFormatMemory(client
->doc
, &xml
, &len
, 1);
2761 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2762 return send_syserror(ctx
, ENOMEM
);
2765 pth_cleanup_push(xmlFree
, xml
);
2766 rc
= xfer_data(ctx
, (gchar
*)xml
, len
);
2768 return send_error(ctx
, rc
);
2771 static gint
getconfig_command(assuan_context_t ctx
, gchar
*line
)
2773 struct client_s
*client
= assuan_get_pointer(ctx
);
2775 gchar filename
[255]={0}, param
[747]={0};
2776 gchar
*p
, *tmp
, *fp
= client
->filename
, *paramp
= line
;
2778 log_write2("ARGS=\"%s\"", line
);
2780 if (strchr(line
, ' ')) {
2781 sscanf(line
, " %254[^ ] %746c", filename
, param
);
2786 if (fp
&& !valid_filename(fp
))
2787 return send_error(ctx
, GPG_ERR_INV_VALUE
);
2789 paramp
= g_ascii_strdown(paramp
, -1);
2792 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2793 return send_syserror(ctx
, ENOMEM
);
2796 if (fp
&& !g_ascii_strcasecmp(paramp
, "iterations")) {
2797 if (!(client
->opts
& OPT_ITERATIONS
) || fp
!= client
->filename
) {
2798 file_header_internal_t
*fh
= read_file_header(fp
, FALSE
, &rc
);
2800 if (!fh
&& rc
!= GPG_ERR_ENOENT
)
2801 return send_error(ctx
, rc
);
2805 p
= g_strdup_printf("%lu", (unsigned long)fh
->ver
.fh2
.iter
);
2806 close_file_header(fh
);
2809 log_write("%s(%i): %s", __FILE__
, __LINE__
,
2811 return send_syserror(ctx
, ENOMEM
);
2818 else if (!g_ascii_strcasecmp(paramp
, "enable_pinentry")) {
2819 #ifdef WITH_PINENTRY
2822 if (fp
== client
->filename
&& (client
->opts
& OPT_PINENTRY
))
2823 n
= client
->pinentry
->enable
;
2825 n
= get_key_file_boolean(fp
, "enable_pinentry");
2827 p
= g_strdup_printf("%s", n
? "true" : "false");
2830 log_write("%s(%i): %s", __FILE__
, __LINE__
,
2832 return send_syserror(ctx
, ENOMEM
);
2837 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2840 else if (!g_ascii_strcasecmp(paramp
, "pinentry_timeout")) {
2841 #ifdef WITH_PINENTRY
2842 p
= g_strdup_printf("%i", get_key_file_integer(fp
, "pinentry_timeout"));
2845 log_write("%s(%i): %s", __FILE__
, __LINE__
,
2847 return send_syserror(ctx
, ENOMEM
);
2852 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2856 p
= get_key_file_string(fp
? fp
: "global", paramp
);
2860 return send_error(ctx
, GPG_ERR_NO_VALUE
);
2862 tmp
= expand_homedir(p
);
2866 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2867 return send_syserror(ctx
, ENOMEM
);
2872 pth_cleanup_push(g_free
, p
);
2873 rc
= xfer_data(ctx
, p
, strlen(p
));
2875 return send_error(ctx
, rc
);
2879 xmlXPathContextPtr xp
;
2880 xmlXPathObjectPtr result
;
2885 static void xpath_command_cleanup(void *arg
)
2887 struct xpath_s
*xpath
= arg
;
2889 req_cleanup(xpath
->req
);
2892 xmlBufferFree(xpath
->buf
);
2895 xmlXPathFreeObject(xpath
->result
);
2898 xmlXPathFreeContext(xpath
->xp
);
2901 static gint
xpath_command(assuan_context_t ctx
, gchar
*line
)
2903 struct client_s
*client
= assuan_get_pointer(ctx
);
2905 struct xpath_s xpath
;
2907 log_write2("ARGS=\"%s\"", line
);
2909 if (disable_list_and_dump
== TRUE
)
2910 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2912 if (!line
|| !*line
)
2913 return send_error(ctx
, GPG_ERR_SYNTAX
);
2915 memset(&xpath
, 0, sizeof(struct xpath_s
));
2917 if ((xpath
.req
= split_input_line(line
, "\t", 2)) == NULL
) {
2918 if (strv_printf(&xpath
.req
, "%s", line
) == FALSE
)
2919 return send_syserror(ctx
, ENOMEM
);
2922 xpath
.xp
= xmlXPathNewContext(client
->doc
);
2925 xpath_command_cleanup(&xpath
);
2926 return send_error(ctx
, EPWMD_LIBXML_ERROR
);
2929 xpath
.result
= xmlXPathEvalExpression((xmlChar
*)xpath
.req
[0], xpath
.xp
);
2931 if (!xpath
.result
) {
2932 xpath_command_cleanup(&xpath
);
2933 return send_error(ctx
, EPWMD_LIBXML_ERROR
);
2936 if (xmlXPathNodeSetIsEmpty(xpath
.result
->nodesetval
)) {
2937 rc
= GPG_ERR_ELEMENT_NOT_FOUND
;
2941 rc
= recurse_xpath_nodeset(client
->doc
, xpath
.result
->nodesetval
,
2942 (xmlChar
*)xpath
.req
[1], &xpath
.buf
, 0, NULL
);
2946 else if (!xpath
.req
[1] && !xmlBufferLength(xpath
.buf
)) {
2947 rc
= GPG_ERR_NO_VALUE
;
2950 else if (xpath
.req
[1])
2953 pth_cleanup_push(xpath_command_cleanup
, &xpath
);
2954 rc
= xfer_data(ctx
, (gchar
*)xmlBufferContent(xpath
.buf
),
2955 xmlBufferLength(xpath
.buf
));
2959 xpath_command_cleanup(&xpath
);
2960 return send_error(ctx
, rc
);
2963 /* XPATHATTR SET|DELETE <name> <expression>[<TAB>[value]] */
2964 static gint
xpathattr_command(assuan_context_t ctx
, gchar
*line
)
2966 struct client_s
*client
= assuan_get_pointer(ctx
);
2968 struct xpath_s xpath
;
2970 gboolean cmd
= FALSE
; //SET
2972 log_write2("ARGS=\"%s\"", line
);
2974 if (disable_list_and_dump
== TRUE
)
2975 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2977 if (!line
|| !*line
)
2978 return send_error(ctx
, GPG_ERR_SYNTAX
);
2980 memset(&xpath
, 0, sizeof(struct xpath_s
));
2982 if ((req
= split_input_line(line
, " ", 3)) == NULL
)
2983 return send_syserror(ctx
, ENOMEM
);
2986 rc
= GPG_ERR_SYNTAX
;
2990 if (!g_ascii_strcasecmp(req
[0], "SET"))
2992 else if (!g_ascii_strcasecmp(req
[0], "DELETE"))
2995 rc
= GPG_ERR_SYNTAX
;
2999 if (!req
[1] || !req
[2]) {
3000 rc
= GPG_ERR_SYNTAX
;
3004 if ((xpath
.req
= split_input_line(req
[2], "\t", 3)) == NULL
) {
3005 rc
= gpg_err_code_from_errno(ENOMEM
);
3009 if (!xpath
.req
[0] || (!xpath
.req
[1] && !cmd
) || (xpath
.req
[1] && cmd
)) {
3010 rc
= GPG_ERR_SYNTAX
;
3014 xpath
.xp
= xmlXPathNewContext(client
->doc
);
3017 rc
= EPWMD_LIBXML_ERROR
;
3021 xpath
.result
= xmlXPathEvalExpression((xmlChar
*)xpath
.req
[0], xpath
.xp
);
3023 if (!xpath
.result
) {
3024 rc
= EPWMD_LIBXML_ERROR
;
3028 if (xmlXPathNodeSetIsEmpty(xpath
.result
->nodesetval
)) {
3029 rc
= GPG_ERR_ELEMENT_NOT_FOUND
;
3033 rc
= recurse_xpath_nodeset(client
->doc
, xpath
.result
->nodesetval
,
3034 (xmlChar
*)xpath
.req
[1], &xpath
.buf
, cmd
, (xmlChar
*)req
[1]);
3038 xpath_command_cleanup(&xpath
);
3039 return send_error(ctx
, rc
);
3042 static gint
import_command_finalize(gpointer data
, gint assuan_rc
, guchar
*line
,
3045 struct client_s
*client
= assuan_get_pointer((assuan_context_t
)data
);
3046 gpg_error_t rc
= file_modified(client
);
3047 gchar
**req
, **path
= NULL
, **path_orig
= NULL
, *content
;
3048 xmlDocPtr doc
= NULL
;
3049 xmlNodePtr n
, root
, copy
;
3051 if (assuan_rc
|| rc
) {
3054 return assuan_rc
? assuan_rc
: rc
;
3057 req
= split_input_line((gchar
*)line
, "\t", 2);
3061 return GPG_ERR_SYNTAX
;
3064 path
= split_input_line(req
[1], "\t", 0);
3066 if (!content
|| !*content
) {
3067 rc
= GPG_ERR_SYNTAX
;
3071 doc
= xmlReadDoc((xmlChar
*)content
, NULL
, "UTF-8", XML_PARSE_NOBLANKS
);
3074 rc
= EPWMD_LIBXML_ERROR
;
3078 root
= xmlDocGetRootElement(doc
);
3079 rc
= validate_import(root
);
3085 path_orig
= g_strdupv(path
);
3088 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
3089 rc
= gpg_error_from_errno(ENOMEM
);
3093 xmlChar
*a
= xmlGetProp(root
, (xmlChar
*)"_name");
3096 g_strfreev(path_orig
);
3097 rc
= gpg_error_from_errno(ENOMEM
);
3101 if (strv_printf(&path
, "%s", (gchar
*)a
) == FALSE
) {
3103 g_strfreev(path_orig
);
3104 rc
= gpg_error_from_errno(ENOMEM
);
3109 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, FALSE
);
3111 if (rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
) {
3112 g_strfreev(path_orig
);
3117 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, TRUE
);
3119 if (rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
) {
3120 g_strfreev(path_orig
);
3124 xmlNodePtr parent
= n
->parent
;
3135 if (rc
== GPG_ERR_ELEMENT_NOT_FOUND
) {
3136 n
= create_element_path(client
, &path
, &rc
);
3142 copy
= xmlCopyNodeList(root
);
3143 n
= xmlAddChildList(n
, copy
);
3146 rc
= EPWMD_LIBXML_ERROR
;
3149 /* Check if the content root element can create a DTD root element. */
3150 if (!xmlStrEqual((xmlChar
*)"element", root
->name
)) {
3151 rc
= GPG_ERR_SYNTAX
;
3157 if ((a
= xmlGetProp(root
, (xmlChar
*)"_name")) == NULL
) {
3158 rc
= GPG_ERR_SYNTAX
;
3162 gchar
*tmp
= g_strdup((gchar
*)a
);
3164 gboolean literal
= is_literal_element(&tmp
);
3166 if (!valid_xml_element((xmlChar
*)tmp
) || literal
) {
3168 rc
= GPG_ERR_INV_VALUE
;
3172 if (strv_printf(&path
, "%s", tmp
) == FALSE
) {
3174 rc
= gpg_error_from_errno(ENOMEM
);
3179 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, TRUE
);
3181 if (rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
) {
3182 rc
= EPWMD_LIBXML_ERROR
;
3186 /* Overwriting the existing tree. */
3193 xmlSetProp(root
, (xmlChar
*)"_name", (xmlChar
*)path
[0]);
3194 n
= xmlCopyNode(root
, 1);
3195 n
= xmlAddChildList(xmlDocGetRootElement(client
->doc
), n
);
3199 rc
= update_element_mtime(n
->parent
);
3209 client
->inquire_status
= INQUIRE_DONE
;
3213 static gint
import_command(assuan_context_t ctx
, gchar
*line
)
3216 struct client_s
*client
= assuan_get_pointer(ctx
);
3218 rc
= assuan_inquire_ext(ctx
, "IMPORT", 0, import_command_finalize
, ctx
);
3221 return send_error(ctx
, rc
);
3223 /* Don't return with assuan_process_done() here. This is an INQUIRE. */
3224 client
->inquire_status
= INQUIRE_BUSY
;
3228 static gpg_error_t
do_lock_command(struct client_s
*client
)
3230 gpg_error_t rc
= lock_file_mutex(client
);
3233 client
->is_lock_cmd
= TRUE
;
3235 return send_error(client
->ctx
, rc
);
3238 static gint
lock_command(assuan_context_t ctx
, gchar
*line
)
3240 struct client_s
*client
= assuan_get_pointer(ctx
);
3242 return do_lock_command(client
);
3245 static gint
unlock_command(assuan_context_t ctx
, gchar
*line
)
3247 struct client_s
*client
= assuan_get_pointer(ctx
);
3249 unlock_file_mutex(client
);
3250 return send_error(ctx
, 0);
3253 static gint
getpid_command(assuan_context_t ctx
, gchar
*line
)
3257 pid_t pid
= getpid();
3259 print_fmt(buf
, sizeof(buf
), "%i", pid
);
3260 rc
= xfer_data(ctx
, buf
, strlen(buf
));
3261 return send_error(ctx
, rc
);
3264 static gint
version_command(assuan_context_t ctx
, gchar
*line
)
3269 print_fmt(buf
, sizeof(buf
), "0x%X", VERSION_HEX
);
3270 rc
= xfer_data(ctx
, buf
, strlen(buf
));
3271 return send_error(ctx
, rc
);
3274 #ifdef WITH_PINENTRY
3275 static void set_option_value(gchar
**opt
, const gchar
*value
)
3283 *opt
= g_strdup(value
);
3287 static gint
set_unset_common(assuan_context_t ctx
, const gchar
*name
,
3290 struct client_s
*client
= assuan_get_pointer(ctx
);
3293 if (g_ascii_strcasecmp(name
, (gchar
*)"log_level") == 0) {
3297 l
= strtol(value
, NULL
, 10);
3300 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
3303 log_write1("log_level=%li", l
);
3304 MUTEX_LOCK(&rcfile_mutex
);
3305 g_key_file_set_integer(keyfileh
, "global", "log_level", (gint
)l
);
3306 MUTEX_UNLOCK(&rcfile_mutex
);
3309 else if (g_ascii_strcasecmp(name
, (gchar
*)"rc_on_locked") == 0) {
3313 l
= strtol(value
, NULL
, 10);
3316 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
3319 log_write1("rc_on_locked=%li", l
);
3320 client
->rc_on_locked
= l
? TRUE
: FALSE
;
3323 else if (g_ascii_strcasecmp(name
, (gchar
*)"lock_on_open") == 0) {
3324 rc
= parse_open_opt_lock(client
, (gpointer
)value
);
3329 client
->opts
|= OPT_LOCK
;
3331 else if (g_ascii_strcasecmp(name
, (gchar
*)"cipher") == 0) {
3333 client
->opts
&= ~(OPT_CIPHER
);
3337 rc
= parse_save_opt_cipher(client
, (gpointer
)value
);
3342 client
->opts
|= OPT_CIPHER
;
3345 else if (g_ascii_strcasecmp(name
, (gchar
*)"iterations") == 0) {
3346 rc
= parse_save_opt_iterations(client
, (gpointer
)value
);
3353 else if (g_ascii_strcasecmp(name
, (gchar
*)"NAME") == 0) {
3354 pth_attr_t attr
= pth_attr_of(pth_self());
3358 pth_attr_destroy(attr
);
3362 print_fmt(buf
, sizeof(buf
), "%s", value
);
3363 pth_attr_set(attr
, PTH_ATTR_NAME
, buf
);
3364 pth_attr_destroy(attr
);
3365 log_write1("name=%s", buf
);
3366 #ifdef WITH_PINENTRY
3367 if (client
->pinentry
->name
)
3368 g_free(client
->pinentry
->name
);
3370 client
->pinentry
->name
= g_strdup(buf
);
3372 if (!client
->pinentry
->name
)
3373 return gpg_error_from_errno(ENOMEM
);
3378 #ifdef WITH_PINENTRY
3379 else if (g_ascii_strcasecmp(name
, (gchar
*)"lc_messages") == 0)
3380 set_option_value(&client
->pinentry
->lcmessages
, value
);
3381 else if (g_ascii_strcasecmp(name
, (gchar
*)"lc_ctype") == 0)
3382 set_option_value(&client
->pinentry
->lcctype
, value
);
3383 else if (g_ascii_strcasecmp(name
, (gchar
*)"ttyname") == 0)
3384 set_option_value(&client
->pinentry
->ttyname
, value
);
3385 else if (g_ascii_strcasecmp(name
, (gchar
*)"ttytype") == 0)
3386 set_option_value(&client
->pinentry
->ttytype
, value
);
3387 else if (g_ascii_strcasecmp(name
, (gchar
*)"display") == 0)
3388 set_option_value(&client
->pinentry
->display
, value
);
3389 else if (g_ascii_strcasecmp(name
, (gchar
*)"pinentry_path") == 0)
3390 set_option_value(&client
->pinentry
->path
, value
);
3391 else if (g_ascii_strcasecmp(name
, (gchar
*)"title") == 0)
3392 set_option_value(&client
->pinentry
->title
, value
);
3393 else if (g_ascii_strcasecmp(name
, (gchar
*)"prompt") == 0)
3394 set_option_value(&client
->pinentry
->prompt
, value
);
3395 else if (g_ascii_strcasecmp(name
, (gchar
*)"desc") == 0)
3396 set_option_value(&client
->pinentry
->desc
, value
);
3397 else if (g_ascii_strcasecmp(name
, "pinentry_timeout") == 0) {
3404 n
= strtol(value
, &p
, 10);
3407 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
3409 MUTEX_LOCK(&rcfile_mutex
);
3410 g_key_file_set_integer(keyfileh
, client
->filename
? client
->filename
:
3411 "global", "pinentry_timeout", n
);
3412 MUTEX_UNLOCK(&rcfile_mutex
);
3413 log_write1("pinentry_timeout=%i", n
);
3416 else if (g_ascii_strcasecmp(name
, "enable_pinentry") == 0) {
3417 rc
= parse_opt_pinentry(client
, (gpointer
)value
);
3426 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_UNKNOWN_OPTION
);
3428 log_write1("%s=%s", name
, value
? value
: "");
3434 static gint
unset_command(assuan_context_t ctx
, gchar
*line
)
3436 log_write2("ARGS=\"%s\"", line
);
3437 return send_error(ctx
, set_unset_common(ctx
, line
, NULL
));
3440 static gint
set_command(assuan_context_t ctx
, gchar
*line
)
3442 gchar name
[64] = {0}, value
[256] = {0};
3444 log_write2("ARGS=\"%s\"", line
);
3446 if (sscanf(line
, " %63[_a-zA-Z] = %255c", name
, value
) != 2)
3447 return send_error(ctx
, gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_SYNTAX
));
3449 return send_error(ctx
, set_unset_common(ctx
, name
, value
));
3452 static gint
rename_command(assuan_context_t ctx
, gchar
*line
)
3454 struct client_s
*client
= assuan_get_pointer(ctx
);
3456 gchar
**req
, **src
, *dst
;
3459 log_write2("ARGS=\"%s\"", line
);
3460 req
= split_input_line(line
, " ", -1);
3462 if (!req
|| !req
[0] || !req
[1]) {
3464 return send_error(ctx
, GPG_ERR_SYNTAX
);
3468 is_literal_element(&dst
);
3470 if (!valid_xml_element((xmlChar
*)dst
)) {
3472 return GPG_ERR_INV_VALUE
;
3475 if (strchr(req
[0], '\t'))
3476 src
= split_input_line(req
[0], "\t", -1);
3478 src
= split_input_line(req
[0], " ", -1);
3480 if (!src
|| !*src
) {
3481 rc
= GPG_ERR_SYNTAX
;
3485 n
= find_root_element(client
->doc
, &src
, &rc
, NULL
, 0, FALSE
);
3488 n
= find_elements(client
->doc
, n
->children
, src
+1, &rc
, NULL
, NULL
,
3489 NULL
, FALSE
, 0, NULL
, FALSE
);
3495 xmlChar
*a
= xmlGetProp(n
, (xmlChar
*)"_name");
3498 rc
= gpg_error_from_errno(ENOMEM
);
3502 /* To prevent unwanted effects:
3504 * <root name="a"><b/></root>
3508 if (xmlStrEqual(a
, (xmlChar
*)dst
)) {
3510 rc
= GPG_ERR_AMBIGUOUS_NAME
;
3520 for (p
= src
; *p
; p
++) {
3524 strv_printf(&tmp
, "%s", *p
);
3528 strv_printf(&tmp
, "!%s", dst
);
3529 ndst
= find_root_element(client
->doc
, &tmp
, &rc
, NULL
, 0, FALSE
);
3531 if (!ndst
&& rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
) {
3537 ndst
= find_elements(client
->doc
, ndst
->children
, tmp
+1, &rc
, NULL
,
3538 NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
3542 if (!ndst
&& rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
)
3547 /* Target may exist:
3550 * <root name="b" target="a"/>
3558 rc
= GPG_ERR_AMBIGUOUS_NAME
;
3564 xmlFreeNodeList(ndst
);
3567 rc
= add_attribute(n
, "_name", dst
);
3572 return send_error(ctx
, rc
);
3575 static gint
copy_command(assuan_context_t ctx
, gchar
*line
)
3577 struct client_s
*client
= assuan_get_pointer(ctx
);
3579 gchar
**req
, **src
= NULL
, **dst
= NULL
;
3580 xmlNodePtr nsrc
, ndst
, new;
3582 log_write2("ARGS=\"%s\"", line
);
3583 req
= split_input_line(line
, " ", -1);
3585 if (!req
|| !req
[0] || !req
[1]) {
3587 return send_error(ctx
, GPG_ERR_SYNTAX
);
3590 if (strchr(req
[0], '\t'))
3591 src
= split_input_line(req
[0], "\t", -1);
3593 src
= split_input_line(req
[0], " ", -1);
3595 if (!src
|| !*src
) {
3596 rc
= GPG_ERR_SYNTAX
;
3600 if (strchr(req
[1], '\t'))
3601 dst
= split_input_line(req
[1], "\t", -1);
3603 dst
= split_input_line(req
[1], " ", -1);
3605 if (!dst
|| !*dst
) {
3606 rc
= GPG_ERR_SYNTAX
;
3610 nsrc
= find_root_element(client
->doc
, &src
, &rc
, NULL
, 0, FALSE
);
3613 nsrc
= find_elements(client
->doc
, nsrc
->children
, src
+1, &rc
, NULL
,
3614 NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
3619 ndst
= find_root_element(client
->doc
, &dst
, &rc
, NULL
, 0, FALSE
);
3622 ndst
= find_elements(client
->doc
, ndst
->children
, dst
+1, &rc
, NULL
,
3623 NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
3625 if (!ndst
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
)
3628 new = xmlCopyNodeList(nsrc
);
3631 rc
= GPG_ERR_ENOMEM
;
3636 ndst
= create_element_path(client
, &dst
, &rc
);
3640 xmlFreeNodeList(new);
3644 /* Merge any attributes from the src node to the initial dst node. */
3645 for (xmlAttrPtr attr
= new->properties
; attr
; attr
= attr
->next
) {
3646 if (xmlStrEqual(attr
->name
, (xmlChar
*)"_name"))
3649 xmlAttrPtr a
= xmlHasProp(ndst
, attr
->name
);
3654 xmlChar
*tmp
= xmlNodeGetContent(attr
->children
);
3655 xmlNewProp(ndst
, attr
->name
, tmp
);
3657 rc
= add_attribute(ndst
, NULL
, NULL
);
3660 xmlNodePtr n
= ndst
->children
;
3663 ndst
->children
= NULL
;
3665 if (!new->children
) {
3667 xmlFreeNodeList(new);
3671 n
= xmlCopyNodeList(new->children
);
3674 rc
= GPG_ERR_ENOMEM
;
3679 xmlFreeNodeList(new);
3680 n
= xmlAddChildList(ndst
, n
);
3683 rc
= GPG_ERR_ENOMEM
;
3687 rc
= update_element_mtime(xmlDocGetRootElement(client
->doc
) == ndst
->parent
? ndst
: ndst
->parent
);
3699 return send_error(ctx
, rc
);
3702 static gint
move_command(assuan_context_t ctx
, gchar
*line
)
3704 struct client_s
*client
= assuan_get_pointer(ctx
);
3706 gchar
**req
, **src
= NULL
, **dst
= NULL
;
3707 xmlNodePtr nsrc
, ndst
= NULL
;
3709 log_write2("ARGS=\"%s\"", line
);
3710 req
= split_input_line(line
, " ", -1);
3712 if (!req
|| !req
[0] || !req
[1]) {
3714 return send_error(ctx
, GPG_ERR_SYNTAX
);
3717 if (strchr(req
[0], '\t'))
3718 src
= split_input_line(req
[0], "\t", -1);
3720 src
= split_input_line(req
[0], " ", -1);
3722 if (!src
|| !*src
) {
3723 rc
= GPG_ERR_SYNTAX
;
3727 if (strchr(req
[1], '\t'))
3728 dst
= split_input_line(req
[1], "\t", -1);
3730 dst
= split_input_line(req
[1], " ", -1);
3732 nsrc
= find_root_element(client
->doc
, &src
, &rc
, NULL
, 0, FALSE
);
3735 nsrc
= find_elements(client
->doc
, nsrc
->children
, src
+1, &rc
, NULL
,
3736 NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
3742 ndst
= find_root_element(client
->doc
, &dst
, &rc
, NULL
, 0, FALSE
);
3745 ndst
= find_elements(client
->doc
, ndst
->children
, dst
+1, &rc
, NULL
,
3746 NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
3749 ndst
= xmlDocGetRootElement(client
->doc
);
3751 for (xmlNodePtr n
= ndst
; n
; n
= n
->parent
) {
3753 rc
= GPG_ERR_CONFLICT
;
3758 if (rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
)
3764 xmlChar
*a
= node_has_attribute(nsrc
, (xmlChar
*)"_name");
3765 xmlNodePtr dup
= find_element(ndst
->children
, (gchar
*)a
, NULL
);
3773 if (ndst
== xmlDocGetRootElement(client
->doc
)) {
3774 xmlNodePtr n
= nsrc
;
3775 gboolean match
= FALSE
;
3777 while (n
->parent
&& n
->parent
!= ndst
)
3780 xmlChar
*a
= node_has_attribute(n
, (xmlChar
*)"_name");
3781 xmlChar
*b
= node_has_attribute(nsrc
, (xmlChar
*)"_name");
3783 if (xmlStrEqual(a
, b
)) {
3785 xmlUnlinkNode(nsrc
);
3795 xmlFreeNodeList(dup
);
3804 ndst
= create_element_path(client
, &dst
, &rc
);
3809 update_element_mtime(nsrc
->parent
);
3810 xmlUnlinkNode(nsrc
);
3811 ndst
= xmlAddChildList(ndst
, nsrc
);
3814 rc
= GPG_ERR_ENOMEM
;
3816 update_element_mtime(ndst
->parent
);
3828 return send_error(ctx
, rc
);
3831 static int ls_command(assuan_context_t ctx
, gchar
*line
)
3833 log_write2("ARGS=\"%s\"", line
);
3835 gchar
*tmp
= g_key_file_get_string(keyfileh
, "global", "data_directory", NULL
);
3836 gchar
*dir
= expand_homedir(tmp
);
3837 DIR *d
= opendir(dir
);
3844 return send_syserror(ctx
, n
);
3847 size_t len
= offsetof(struct dirent
, d_name
)+pathconf(dir
, _PC_NAME_MAX
)+1;
3848 struct dirent
*p
= g_malloc(len
), *cur
= NULL
;
3854 while (!readdir_r(d
, p
, &cur
) && cur
) {
3855 if (cur
->d_name
[0] == '.' && cur
->d_name
[1] == '\0')
3857 else if (cur
->d_name
[0] == '.' && cur
->d_name
[1] == '.' && cur
->d_name
[2] == '\0')
3860 tmp
= g_strdup_printf("%s%s\n", list
? list
: "", cur
->d_name
);
3866 rc
= GPG_ERR_ENOMEM
;
3878 return send_error(ctx
, rc
);
3881 return send_error(ctx
, GPG_ERR_NO_VALUE
);
3883 list
[strlen(list
)-1] = 0;
3884 rc
= xfer_data(ctx
, list
, strlen(list
));
3886 return send_error(ctx
, rc
);
3889 static void bye_notify(assuan_context_t ctx
)
3891 struct client_s
*cl
= assuan_get_pointer(ctx
);
3893 /* This will let assuan_process_next() return. */
3894 fcntl(cl
->thd
->fd
, F_SETFL
, O_NONBLOCK
);
3897 static void reset_notify(assuan_context_t ctx
)
3899 struct client_s
*cl
= assuan_get_pointer(ctx
);
3906 * This is called before every Assuan command.
3908 gint
command_startup(assuan_context_t ctx
, const gchar
*name
)
3910 struct client_s
*cl
= assuan_get_pointer(ctx
);
3913 log_write1("%s", name
);
3915 if (!g_ascii_strcasecmp(name
, "ISCACHED") ||
3916 !g_ascii_strcasecmp(name
, "CLEARCACHE") ||
3917 !g_ascii_strcasecmp(name
, "CACHETIMEOUT") ||
3918 !g_ascii_strcasecmp(name
, "GETCONFIG") ||
3919 !g_ascii_strcasecmp(name
, "GETPID") ||
3920 !g_ascii_strcasecmp(name
, "VERSION") ||
3921 !g_ascii_strcasecmp(name
, "SET") ||
3922 !g_ascii_strcasecmp(name
, "BYE") ||
3923 !g_ascii_strcasecmp(name
, "NOP") ||
3924 !g_ascii_strcasecmp(name
, "CANCEL") ||
3925 !g_ascii_strcasecmp(name
, "RESET") ||
3926 !g_ascii_strcasecmp(name
, "END") ||
3927 !g_ascii_strcasecmp(name
, "HELP") ||
3928 !g_ascii_strcasecmp(name
, "OPTION") ||
3929 !g_ascii_strcasecmp(name
, "INPUT") ||
3930 !g_ascii_strcasecmp(name
, "OUTPUT") ||
3931 !g_ascii_strcasecmp(name
, "LS") ||
3932 !g_ascii_strcasecmp(name
, "UNSET"))
3935 #ifdef WITH_PINENTRY
3936 if (!(cl
->opts
& OPT_PINENTRY
))
3937 reset_pin_defaults(cl
->pinentry
);
3940 cl
->last_rc
= rc
= file_modified(cl
);
3943 if ((rc
== EPWMD_NO_FILE
|| rc
== EPWMD_FILE_MODIFIED
) &&
3944 !g_ascii_strcasecmp(name
, "OPEN"))
3952 * This is called after every Assuan command.
3954 void command_finalize(assuan_context_t ctx
, gint rc
)
3956 struct client_s
*client
= assuan_get_pointer(ctx
);
3958 if (!client
->is_lock_cmd
)
3959 unlock_file_mutex(client
);
3961 log_write1(N_("command completed (rc=%u)"), client
->last_rc
);
3964 gpg_error_t
register_commands(assuan_context_t ctx
)
3968 gint (*handler
)(assuan_context_t
, gchar
*line
);
3970 { "OPEN", open_command
},
3971 { "SAVE", save_command
},
3972 { "LIST", list_command
},
3973 { "REALPATH", realpath_command
},
3974 { "STORE", store_command
},
3975 { "DELETE", delete_command
},
3976 { "GET", get_command
},
3977 { "ATTR", attr_command
},
3978 { "ISCACHED", iscached_command
},
3979 { "CLEARCACHE", clearcache_command
},
3980 { "CACHETIMEOUT", cachetimeout_command
},
3981 { "GETCONFIG", getconfig_command
},
3982 { "DUMP", dump_command
},
3983 { "XPATH", xpath_command
},
3984 { "XPATHATTR", xpathattr_command
},
3985 { "IMPORT", import_command
},
3986 { "LOCK", lock_command
},
3987 { "UNLOCK", unlock_command
},
3988 { "GETPID", getpid_command
},
3989 { "VERSION", version_command
},
3990 { "SET", set_command
},
3991 { "UNSET", unset_command
},
3992 { "RENAME", rename_command
},
3993 { "COPY", copy_command
},
3994 { "LS", ls_command
},
3995 { "MOVE", move_command
},
4002 for (i
=0; table
[i
].name
; i
++) {
4003 rc
= assuan_register_command (ctx
, table
[i
].name
, table
[i
].handler
);
4009 rc
= assuan_register_bye_notify(ctx
, bye_notify
);
4014 rc
= assuan_register_reset_notify(ctx
, reset_notify
);
4019 rc
= assuan_register_pre_cmd_notify(ctx
, command_startup
);
4024 return assuan_register_post_cmd_notify(ctx
, command_finalize
);
4027 gpg_error_t
try_xml_decrypt(assuan_context_t ctx
,
4028 struct crypto_s
*crypto
, gpointer
*dst
, goffset
*dst_len
)
4030 goffset insize
, len
;
4031 struct client_s
*client
= ctx
? assuan_get_pointer(ctx
) : NULL
;
4032 guint64 iter
= 0ULL, n_iter
= 0ULL, iter_progress
= 0ULL;
4036 gsize fh_size
= crypto
->fh
->v1
? sizeof(crypto
->fh
->ver
.fh1
) : sizeof(crypto
->fh
->ver
.fh2
);
4037 guint64 fh_iter
= crypto
->fh
->v1
? crypto
->fh
->ver
.fh1
.iter
: crypto
->fh
->ver
.fh2
.iter
;
4038 gsize hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
4040 lseek(crypto
->fh
->fd
, fh_size
, SEEK_SET
);
4041 insize
= crypto
->fh
->st
.st_size
- fh_size
;
4042 crypto
->iv
= gcry_malloc(crypto
->blocksize
);
4045 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
4046 return gpg_error_from_errno(ENOMEM
);
4050 memcpy(crypto
->iv
, crypto
->fh
->ver
.fh1
.iv
, crypto
->blocksize
);
4052 memcpy(crypto
->iv
, crypto
->fh
->ver
.fh2
.iv
, crypto
->blocksize
);
4054 crypto
->inbuf
= gcry_malloc(insize
);
4056 if (!crypto
->inbuf
) {
4057 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
4058 return gpg_error_from_errno(ENOMEM
);
4061 crypto
->insize
= insize
;
4062 len
= pth_read(crypto
->fh
->fd
, crypto
->inbuf
, crypto
->insize
);
4064 if (len
!= crypto
->insize
)
4065 return GPG_ERR_INV_LENGTH
;
4067 /* No encryption iterations. This is a plain (gzipped) file. */
4068 if ((crypto
->fh
->v1
&& (long)fh_iter
< 0L) ||
4069 (!crypto
->fh
->v1
&& fh_iter
<= 0L)) {
4071 * cache_file_count() needs both .used == TRUE and a valid key in
4072 * order for it to count as a used cache entry. Fixes CACHE status
4075 memset(crypto
->key
, '!', hashlen
);
4079 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->iv
, crypto
->blocksize
))) {
4080 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
4084 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->key
, crypto
->keysize
))) {
4085 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
4089 iter_progress
= (guint64
)get_key_file_double(client
&& client
->filename
?
4090 client
->filename
: "global", "iteration_progress");
4092 if (iter_progress
> 0ULL && fh_iter
>= iter_progress
) {
4093 rc
= send_status(ctx
, STATUS_DECRYPT
, "0 %llu", fh_iter
);
4099 rc
= iterate_crypto_once(client
, crypto
, STATUS_DECRYPT
);
4104 crypto
->tkey
= gcry_malloc(hashlen
);
4106 if (!crypto
->tkey
) {
4107 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
4108 return gpg_error_from_errno(ENOMEM
);
4111 memcpy(crypto
->tkey
, crypto
->key
, hashlen
);
4112 guchar
*tkey
= crypto
->tkey
;
4115 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->tkey
, crypto
->keysize
))) {
4116 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
4120 while (iter
< (crypto
->fh
->v1
? fh_iter
: fh_iter
-1)) {
4121 if (iter_progress
> 0ULL && iter
>= iter_progress
) {
4122 if (!(iter
% iter_progress
)) {
4123 rc
= send_status(ctx
, STATUS_DECRYPT
, "%llu %llu",
4124 ++n_iter
* iter_progress
, fh_iter
);
4131 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->iv
, crypto
->blocksize
))) {
4132 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
4136 rc
= iterate_crypto_once(client
, crypto
, STATUS_DECRYPT
);
4139 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
4146 if (iter_progress
&& fh_iter
>= iter_progress
) {
4147 rc
= send_status(ctx
, STATUS_DECRYPT
, "%llu %llu", fh_iter
, fh_iter
);
4154 if (do_decompress(ctx
, crypto
->inbuf
, crypto
->insize
,
4155 (gpointer
*)&crypto
->outbuf
, &outsize
, &zrc
) == FALSE
) {
4156 if (zrc
== Z_MEM_ERROR
)
4157 return gpg_error_from_errno(ENOMEM
);
4159 return GPG_ERR_INV_PASSPHRASE
; // Not a valid gzip header. Must be a bad key.
4162 if (g_strncasecmp(crypto
->outbuf
, "<?xml ", 6) != 0) {
4163 gcry_free(crypto
->outbuf
);
4164 crypto
->outbuf
= NULL
;
4165 return GPG_ERR_INV_PASSPHRASE
;
4169 client
->xml
= crypto
->outbuf
;
4170 client
->len
= outsize
;
4171 crypto
->outbuf
= NULL
;
4174 *dst
= crypto
->outbuf
;
4176 crypto
->outbuf
= NULL
;
4179 /* The calling function should free the crypto struct. */