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
->ctx
, 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 lock_on_open
= client
->lockonopen
;
190 gboolean rc_on_locked
= client
->rc_on_locked
;
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
->lockonopen
= 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
->lockonopen
)
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 gint
open_command(assuan_context_t ctx
, gchar
*line
)
507 gboolean cached
= FALSE
;
509 struct client_s
*client
= assuan_get_pointer(ctx
);
511 gchar
*filename
= NULL
;
512 gsize hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
514 if ((req
= split_input_line(line
, " ", 2)) != NULL
)
517 pth_cleanup_push(req_cleanup
, req
);
519 if (!filename
|| !*filename
) {
521 return send_error(ctx
, GPG_ERR_SYNTAX
);
524 log_write2("ARGS=\"%s\" %s", filename
, req
[1] ? "<passphrase>" : "");
526 if (valid_filename(filename
) == FALSE
) {
528 return send_error(ctx
, GPG_ERR_INV_VALUE
);
531 if (client
->state
== STATE_OPEN
)
532 cleanup_client(client
);
534 gcry_md_hash_buffer(GCRY_MD_MD5
, client
->md5file
, filename
, strlen(filename
));
535 CACHE_LOCK(client
->ctx
);
537 if (cache_has_file(client
->md5file
) == FALSE
) {
538 if (cache_add_file(client
->md5file
, NULL
) == FALSE
) {
541 return send_syserror(ctx
, ENOMEM
);
545 cache_incr_refcount(client
->md5file
);
547 rc
= lock_file_mutex(client
);
551 return send_error(ctx
, rc
);
554 client
->freed
= FALSE
;
555 client
->crypto
= init_client_crypto();
557 if (!client
->crypto
) {
559 cleanup_client(client
);
560 return send_syserror(ctx
, ENOMEM
);
563 client
->crypto
->key
= gcry_malloc(hashlen
);
565 if (!client
->crypto
->key
) {
567 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
,
568 gpg_error_from_errno(ENOMEM
));
569 cleanup_client(client
);
570 return send_syserror(ctx
, ENOMEM
);
573 memset(client
->crypto
->key
, 0, hashlen
);
574 client
->crypto
->fh
= read_file_header(filename
, FALSE
, &rc
);
576 if (!client
->crypto
->fh
) {
577 if (gpg_err_code_to_errno(rc
) != ENOENT
) {
578 log_write("%s: %s", filename
, pwmd_strerror(rc
));
580 cleanup_client(client
);
581 return send_error(ctx
, rc
);
585 * New files don't need a key.
587 if ((client
->xml
= new_document()) == NULL
) {
588 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
590 cleanup_client(client
);
591 return send_syserror(ctx
, ENOMEM
);
594 client
->len
= xmlStrlen(client
->xml
);
596 client
->filename
= g_strdup(filename
);
598 if (!client
->filename
) {
600 cleanup_client(client
);
601 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
602 return send_syserror(ctx
, ENOMEM
);
605 if (req
[1] && *req
[1])
606 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, req
[1],
611 client
->pinentry
->filename
= g_strdup(client
->filename
);
613 if (!client
->pinentry
->filename
) {
614 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
615 cleanup_client(client
);
616 return send_syserror(ctx
, ENOMEM
);
619 return open_command_finalize(ctx
, NULL
, cached
);
622 client
->mtime
= client
->crypto
->fh
->st
.st_mtime
;
624 client
->filename
= g_strdup(filename
);
626 if (!client
->filename
) {
627 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
629 cleanup_client(client
);
630 return send_syserror(ctx
, ENOMEM
);
634 if (client
->pinentry
->filename
)
635 g_free(client
->pinentry
->filename
);
637 client
->pinentry
->filename
= g_strdup(client
->filename
);
639 if (!client
->pinentry
->filename
) {
640 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
642 cleanup_client(client
);
643 return send_syserror(ctx
, ENOMEM
);
647 if (client
->crypto
->fh
->ver
.fh2
.iter
<= 0ULL)
650 CACHE_LOCK(client
->ctx
);
651 cached
= cache_get_key(client
->md5file
, client
->crypto
->key
);
654 if (cached
== FALSE
) {
655 gchar
*tmp
= get_key_file_string(filename
, "key_file");
660 cleanup_client(client
);
661 return send_error(ctx
, GPG_ERR_WRONG_KEY_USAGE
);
665 * No key specified and no matching filename found in the cache. Use
666 * pinentry to retrieve the key. Cannot return assuan_process_done()
667 * here otherwise the command will be interrupted. The event loop in
668 * client_thread() will poll the file descriptor waiting for it to
669 * become ready to read a pinentry_key_s which will contain the
670 * entered key or an error code. It will then call
671 * open_command_finalize() to to finish the command.
673 if (!req
[1] || !*req
[1]) {
675 gboolean b
= get_key_file_boolean(filename
, "enable_pinentry");
677 /* From set_pinentry_defaults(). */
678 if (client
->pinentry
->enable
== FALSE
||
679 (client
->pinentry
->enable
== -1 && b
== FALSE
)) {
680 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
685 rc
= lock_pin_mutex(client
);
688 unlock_pin_mutex(client
->pinentry
);
689 cleanup_client(client
);
690 return send_error(ctx
, rc
);
693 client
->pinentry
->which
= PINENTRY_OPEN
;
694 rc
= pinentry_fork(ctx
);
697 unlock_pin_mutex(client
->pinentry
);
698 cleanup_client(client
);
699 return send_error(ctx
, rc
);
702 // Called from pinentry iterate.
703 client
->pinentry
->cb
= open_command_finalize
;
704 client
->pinentry
->status
= PINENTRY_INIT
;
707 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
712 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, req
[1],
715 else if (req
&& req
[1] && *req
[1]) {
716 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, req
[1],
717 strlen(req
[1]) ? strlen(req
[1]) : 1);
722 return open_command_finalize(ctx
, NULL
, cached
);
725 gboolean
do_compress(assuan_context_t ctx
, gint level
, gpointer data
,
726 guint size
, gpointer
*out
, gulong
*outsize
, gint
*rc
)
731 gint cmd
= Z_NO_FLUSH
;
733 gz
= g_malloc0(sizeof(struct gz_s
));
736 *rc
= gpg_error_from_errno(ENOMEM
);
740 pth_cleanup_push(gz_cleanup
, &gz
);
741 gz
->which
= STATUS_COMPRESS
;
742 gz
->z
.zalloc
= z_alloc
;
743 gz
->z
.zfree
= z_free
;
744 gz
->z
.next_in
= data
;
745 gz
->z
.avail_in
= size
< zlib_bufsize
? (uInt
)size
: (uInt
)zlib_bufsize
;
746 gz
->z
.avail_out
= (uInt
)zlib_bufsize
;
747 gz
->z
.next_out
= gz
->out
= gcry_malloc(zlib_bufsize
);
750 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
756 *rc
= deflateInit2(&gz
->z
, level
, Z_DEFLATED
, 31, 8, Z_DEFAULT_STRATEGY
);
759 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
764 /* Rather than store the size of the uncompressed data in the file header,
765 * store it in the comment field of the gzip header. Don't give anyone too
766 * much information. Not sure why really, but it seems the right way. :)
768 memset(&h
, 0, sizeof(gz_header
));
769 g_snprintf(buf
, sizeof(buf
), "%u", size
);
770 h
.comment
= (guchar
*)buf
;
771 *rc
= deflateSetHeader(&gz
->z
, &h
);
774 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
782 *rc
= deflate(&gz
->z
, cmd
);
788 if (!gz
->z
.avail_out
) {
789 p
= gcry_realloc(gz
->out
, gz
->z
.total_out
+ zlib_bufsize
);
792 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
798 gz
->z
.next_out
= (guchar
*)gz
->out
+ gz
->z
.total_out
;
799 gz
->z
.avail_out
= zlib_bufsize
;
802 if (!gz
->z
.avail_in
&& gz
->z
.total_in
< size
) {
803 if (gz
->z
.total_in
+ zlib_bufsize
> size
)
804 gz
->z
.avail_in
= size
- gz
->z
.total_in
;
806 gz
->z
.avail_in
= zlib_bufsize
;
808 *rc
= send_status(ctx
, STATUS_COMPRESS
, "%li %u",
809 gz
->z
.total_in
, size
);
815 if (gz
->z
.total_in
>= size
)
824 } while (*rc
!= Z_STREAM_END
);
826 *rc
= send_status(ctx
, STATUS_COMPRESS
, "%li %u", gz
->z
.total_in
, size
);
832 *outsize
= gz
->z
.total_out
;
839 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gz
->z
.msg
);
844 #define CRYPTO_BLOCKSIZE(c) (c->blocksize * 1024)
847 * Useful for a large amount of data. Rather than doing all of the data in one
848 * iteration do it in chunks. This lets the command be cancelable rather than
849 * waiting for it to complete.
851 static gpg_error_t
iterate_crypto_once(struct client_s
*client
,
852 struct crypto_s
*crypto
, status_msg_t which
)
855 goffset len
= CRYPTO_BLOCKSIZE(crypto
);
856 gpointer p
= gcry_malloc(len
);
861 return gpg_err_code_from_errno(ENOMEM
);
863 if (crypto
->insize
< CRYPTO_BLOCKSIZE(crypto
))
864 len
= crypto
->insize
;
866 pth_cleanup_push(gcry_free
, p
);
869 inbuf
= (guchar
*)crypto
->inbuf
+ total
;
872 if (len
+ total
> crypto
->insize
)
873 len
= crypto
->blocksize
;
875 if (which
== STATUS_ENCRYPT
)
876 rc
= gcry_cipher_encrypt(crypto
->gh
, p
, len
, inbuf
, len
);
878 rc
= gcry_cipher_decrypt(crypto
->gh
, p
, len
, inbuf
, len
);
883 tmp
= (guchar
*)crypto
->inbuf
+ total
;
884 memmove(tmp
, p
, len
);
887 if (total
>= crypto
->insize
)
898 /* The crypto struct must be setup for iterations and .key. */
899 gpg_error_t
do_xml_encrypt(struct client_s
*client
,
900 struct crypto_s
*crypto
, const gchar
*filename
)
902 goffset len
= crypto
->insize
;
906 guint64 iter_progress
= 0ULL, n_iter
= 0ULL, xiter
= 0ULL;
907 gchar tmp
[FILENAME_MAX
];
910 gsize hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
912 if (!crypto
->fh
->ver
.fh2
.iter
) {
914 * cache_file_count() needs both .used == TRUE and a valid key in
915 * order for it to count as a used cache entry. Fixes CACHE status
918 memset(crypto
->key
, '!', hashlen
);
923 * Resize the existing xml buffer to the block size required by gcrypt
924 * rather than duplicating it and wasting memory.
926 len
= (crypto
->insize
/ crypto
->blocksize
) * crypto
->blocksize
;
928 if (crypto
->insize
% crypto
->blocksize
)
929 len
+= crypto
->blocksize
;
931 inbuf
= gcry_realloc(crypto
->inbuf
, len
);
934 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
935 return gpg_error_from_errno(ENOMEM
);
938 crypto
->inbuf
= inbuf
;
939 crypto
->insize
= len
;
940 gcry_create_nonce(crypto
->fh
->ver
.fh2
.iv
, crypto
->blocksize
);
943 gcry_free(crypto
->tkey
);
945 crypto
->tkey
= gcry_malloc(hashlen
);
948 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
949 return gpg_error_from_errno(ENOMEM
);
952 memcpy(crypto
->tkey
, crypto
->key
, hashlen
);
953 guchar
*tkey
= crypto
->tkey
;
956 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->tkey
, crypto
->keysize
))) {
957 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
961 iter_progress
= (guint64
)get_key_file_double(
962 client
? client
->filename
: "global", "iteration_progress");
964 if (iter_progress
&& crypto
->fh
->ver
.fh2
.iter
>= iter_progress
) {
965 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
966 "0 %llu", crypto
->fh
->ver
.fh2
.iter
);
972 while (xiter
< crypto
->fh
->ver
.fh2
.iter
-1) {
973 if (iter_progress
> 0ULL && xiter
>= iter_progress
) {
974 if (!(xiter
% iter_progress
)) {
975 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
976 "%llu %llu", ++n_iter
* iter_progress
,
977 crypto
->fh
->ver
.fh2
.iter
);
984 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->fh
->ver
.fh2
.iv
,
985 crypto
->blocksize
))) {
986 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
990 rc
= iterate_crypto_once(client
, crypto
, STATUS_ENCRYPT
);
993 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
1000 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->fh
->ver
.fh2
.iv
,
1001 crypto
->blocksize
))) {
1002 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
1006 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->key
, crypto
->keysize
))) {
1007 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
1011 rc
= iterate_crypto_once(client
, crypto
, STATUS_ENCRYPT
);
1016 if (iter_progress
&& crypto
->fh
->ver
.fh2
.iter
>= iter_progress
) {
1017 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
1018 "%llu %llu", crypto
->fh
->ver
.fh2
.iter
, crypto
->fh
->ver
.fh2
.iter
);
1028 if (!client
&& !g_ascii_strcasecmp(filename
, "-")) {
1029 crypto
->fh
->fd
= STDOUT_FILENO
;
1033 if (lstat(filename
, &st
) == 0) {
1034 mode
= st
.st_mode
& (S_IRWXU
|S_IRWXG
|S_IRWXO
);
1036 if (!(mode
& S_IWUSR
))
1037 return gpg_error_from_errno(EACCES
);
1039 else if (errno
!= ENOENT
)
1040 return gpg_error_from_errno(errno
);
1042 g_snprintf(tmp
, sizeof(tmp
), "%s.XXXXXX", filename
);
1043 crypto
->fh
->fd
= mkstemp(tmp
);
1045 if (crypto
->fh
->fd
== -1) {
1047 p
= strrchr(tmp
, '/');
1049 log_write("%s: %s", p
, strerror(rc
));
1050 return gpg_error_from_errno(rc
);
1053 pth_cleanup_push(cleanup_unlink_cb
, tmp
);
1057 * xml_import() or convert_file() from command line.
1059 crypto
->fh
->fd
= STDOUT_FILENO
;
1062 crypto
->fh
->ver
.fh2
.magic
[0] = '\177';
1063 crypto
->fh
->ver
.fh2
.magic
[1] = 'P';
1064 crypto
->fh
->ver
.fh2
.magic
[2] = 'W';
1065 crypto
->fh
->ver
.fh2
.magic
[3] = 'M';
1066 crypto
->fh
->ver
.fh2
.magic
[4] = 'D';
1067 crypto
->fh
->ver
.fh2
.version
= VERSION_HEX
;
1068 len
= pth_write(crypto
->fh
->fd
, &crypto
->fh
->ver
.fh2
, sizeof(crypto
->fh
->ver
.fh2
));
1070 if (len
!= sizeof(crypto
->fh
->ver
.fh2
)) {
1076 return gpg_error_from_errno(len
);
1079 len
= pth_write(crypto
->fh
->fd
, crypto
->inbuf
, crypto
->insize
);
1081 if (len
!= crypto
->insize
) {
1087 return gpg_error_from_errno(len
);
1090 if (fsync(crypto
->fh
->fd
) == -1) {
1096 return gpg_error_from_errno(len
);
1103 if (mode
&& get_key_file_boolean(filename
, "backup") == TRUE
) {
1104 gchar tmp2
[FILENAME_MAX
];
1106 g_snprintf(tmp2
, sizeof(tmp2
), "%s.backup", filename
);
1108 acl
= acl_get_file(filename
, ACL_TYPE_ACCESS
);
1111 log_write("ACL: %s: %s", filename
, strerror(errno
));
1114 if (rename(filename
, tmp2
) == -1) {
1121 return gpg_error_from_errno(len
);
1126 acl
= acl_get_file(".", ACL_TYPE_DEFAULT
);
1129 log_write("ACL: %s: %s", filename
, strerror(errno
));
1133 if (rename(tmp
, filename
) == -1) {
1140 return gpg_error_from_errno(len
);
1146 chmod(filename
, mode
);
1149 if (acl
&& acl_set_file(filename
, ACL_TYPE_ACCESS
, acl
))
1150 log_write("ACL: %s: %s", filename
, strerror(errno
));
1157 if (client
&& lstat(filename
, &st
) == 0)
1158 client
->mtime
= st
.st_mtime
;
1163 gpg_error_t
update_save_flags(const gchar
*filename
,
1164 struct crypto_s
*crypto
)
1171 crypto
->fh
= g_malloc0(sizeof(file_header_internal_t
));
1174 return GPG_ERR_ENOMEM
;
1177 rc
= init_client_crypto2(filename
, crypto
);
1182 if (filename
&& !crypto
->fh
->v1
) {
1183 iter
= (guint64
)get_key_file_double(filename
, "iterations");
1184 crypto
->fh
->ver
.fh2
.iter
= iter
< 0L ? 0UL : iter
;
1190 static gpg_error_t
save_command_finalize(assuan_context_t ctx
, guchar
*key
,
1193 struct client_s
*client
= assuan_get_pointer(ctx
);
1203 if (client
->crypto
->key
&& client
->crypto
->key
!= key
)
1204 gcry_free(client
->crypto
->key
);
1206 client
->crypto
->key
= key
;
1207 rc
= update_timestamp(client
->doc
);
1210 return send_error(ctx
, rc
);
1212 xmlDocDumpFormatMemory(client
->doc
, (xmlChar
**)&xmlbuf
, (gint
*)&len
, 0);
1213 pth_cleanup_push(xmlFree
, xmlbuf
);
1214 clevel
= get_key_file_integer(client
->filename
, "compression_level");
1219 if (do_compress(ctx
, clevel
, xmlbuf
, len
, &outbuf
, &outsize
, &zrc
) == FALSE
) {
1221 cleanup_crypto(&client
->crypto
);
1223 if (zrc
== Z_MEM_ERROR
)
1224 return send_syserror(ctx
, ENOMEM
);
1226 return send_error(ctx
, GPG_ERR_COMPR_ALGO
);
1234 client
->crypto
->inbuf
= xmlbuf
;
1235 client
->crypto
->insize
= len
;
1236 rc
= update_save_flags(client
->filename
, client
->crypto
);
1239 cleanup_crypto(&client
->crypto
);
1240 log_write("%s(%i): %s", __FILE__
, __LINE__
, pwmd_strerror(rc
));
1241 return send_error(ctx
, rc
);
1244 rc
= do_xml_encrypt(client
, client
->crypto
, client
->filename
);
1247 cleanup_crypto(&client
->crypto
);
1248 return send_error(ctx
, rc
);
1251 timeout
= get_key_file_integer(client
->filename
, "cache_timeout");
1252 CACHE_LOCK(client
->ctx
);
1255 cache_reset_timeout(client
->md5file
, timeout
);
1258 if (client
->new == TRUE
)
1259 send_status_all(STATUS_CACHE
);
1261 client
->new = FALSE
;
1262 cleanup_crypto(&client
->crypto
);
1263 return send_error(ctx
, 0);
1266 if (cache_update_key(client
->md5file
, client
->crypto
->key
) == FALSE
) {
1268 cleanup_crypto(&client
->crypto
);
1269 return send_syserror(ctx
, ENOMEM
);
1272 client
->new = FALSE
;
1273 cache_reset_timeout(client
->md5file
, timeout
);
1275 send_status_all(STATUS_CACHE
);
1276 cleanup_crypto(&client
->crypto
);
1277 return send_error(ctx
, 0);
1280 static gint
save_command(assuan_context_t ctx
, gchar
*line
)
1282 gboolean cached
= FALSE
;
1284 struct client_s
*client
= assuan_get_pointer(ctx
);
1285 guint hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
1288 log_write2("ARGS=%s", "<passphrase>");
1290 if (lstat(client
->filename
, &st
) == -1 && errno
!= ENOENT
)
1291 return send_syserror(ctx
, errno
);
1293 if (errno
!= ENOENT
&& !S_ISREG(st
.st_mode
)) {
1294 log_write("%s: %s", client
->filename
, pwmd_strerror(GPG_ERR_ENOANO
));
1295 return send_error(ctx
, GPG_ERR_ENOANO
);
1299 cached
= cache_iscached(client
->md5file
);
1303 * If a cache entry doesn't exist for this file and the file has a
1304 * "key_file" or "key" parameter, then it's an error. The reason is that
1305 * cache expiration would be useless.
1307 if (cached
== FALSE
) {
1308 gchar
*tmp
= get_key_file_string(client
->filename
, "key_file");
1312 return send_error(ctx
, GPG_ERR_WRONG_KEY_USAGE
);
1319 if (!client
->crypto
) {
1320 client
->crypto
= init_client_crypto();
1322 if (!client
->crypto
) {
1323 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1324 return send_syserror(ctx
, ENOMEM
);
1328 client
->crypto
->key
= gcry_malloc(hashlen
);
1330 if (!client
->crypto
->key
) {
1331 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1332 cleanup_crypto(&client
->crypto
);
1333 return send_syserror(ctx
, ENOMEM
);
1336 memset(client
->crypto
->key
, '!', hashlen
);
1338 if (get_key_file_double(client
->filename
, "iterations") <= 0L &&
1342 if (!line
|| !*line
) {
1343 client
->crypto
->tkey
= gcry_malloc(hashlen
);
1345 if (!client
->crypto
->tkey
) {
1346 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1347 cleanup_crypto(&client
->crypto
);
1348 return send_syserror(ctx
, ENOMEM
);
1351 memset(client
->crypto
->tkey
, '!', hashlen
);
1354 if (cache_get_key(client
->md5file
, client
->crypto
->key
) == FALSE
||
1355 !memcmp(client
->crypto
->key
, client
->crypto
->tkey
, hashlen
)) {
1358 #ifdef WITH_PINENTRY
1361 if (client
->pinentry
->enable
== FALSE
||
1362 get_key_file_boolean(client
->filename
, "enable_pinentry") == FALSE
) {
1363 /* Empty keys are allowed. */
1364 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
1368 lock_pin_mutex(client
);
1369 client
->pinentry
->which
= PINENTRY_SAVE
;
1370 rc
= pinentry_fork(ctx
);
1373 unlock_pin_mutex(client
->pinentry
);
1374 cleanup_crypto(&client
->crypto
);
1375 return send_error(ctx
, rc
);
1378 client
->pinentry
->cb
= save_command_finalize
;
1379 client
->pinentry
->status
= PINENTRY_INIT
;
1382 /* Empty keys are allowed. */
1383 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
1393 if (get_key_file_double(client
->filename
, "iterations") <= 0L) {
1394 guint64 iter
= (guint64
)get_key_file_double(NULL
, "iterations");
1399 MUTEX_LOCK(&rcfile_mutex
);
1400 g_key_file_set_double(keyfileh
, client
->filename
, "iterations", iter
);
1401 MUTEX_UNLOCK(&rcfile_mutex
);
1402 client
->opts
|= OPT_ITERATIONS
;
1403 gpg_error_t rc
= send_status(ctx
, STATUS_CONFIG
, NULL
);
1406 return send_error(ctx
, rc
);
1409 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, line
,
1414 return save_command_finalize(ctx
, client
->crypto
->key
, cached
);
1417 static gint
delete_command(assuan_context_t ctx
, gchar
*line
)
1419 struct client_s
*client
= assuan_get_pointer(ctx
);
1424 log_write2("ARGS=\"%s\"", line
);
1426 if (strchr(line
, '\t'))
1427 req
= split_input_line(line
, "\t", -1);
1429 req
= split_input_line(line
, " ", -1);
1432 return send_error(ctx
, GPG_ERR_SYNTAX
);
1434 n
= find_root_element(client
->doc
, &req
, &rc
, NULL
, 0, FALSE
);
1438 return send_error(ctx
, rc
);
1442 * No sub-node defined. Remove the entire node (root element).
1451 return send_error(ctx
, 0);
1454 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
1458 return send_error(ctx
, rc
);
1465 return send_error(ctx
, 0);
1469 * Don't return with assuan_process_done() here. This has been called from
1470 * assuan_process_next() and the command should be finished in
1473 static gint
store_command_finalize(gpointer data
, gint assuan_rc
, guchar
*line
,
1476 assuan_context_t ctx
= data
;
1477 struct client_s
*client
= assuan_get_pointer(ctx
);
1480 gpg_error_t rc
= file_modified(client
);
1482 if (assuan_rc
|| rc
) {
1485 return assuan_rc
? assuan_rc
: rc
;
1488 req
= split_input_line((gchar
*)line
, "\t", 0);
1492 return GPG_ERR_SYNTAX
;
1495 n
= find_root_element(client
->doc
, &req
, &rc
, NULL
, 0, FALSE
);
1497 if (rc
&& rc
== GPG_ERR_ELEMENT_NOT_FOUND
) {
1498 rc
= new_root_element(client
->doc
, *req
);
1515 create_elements_cb(n
, req
+1, &rc
, NULL
);
1517 find_elements(client
->doc
, n
->children
, req
+1, &rc
,
1518 NULL
, NULL
, create_elements_cb
, FALSE
, 0, NULL
, FALSE
);
1522 client
->inquire_status
= INQUIRE_DONE
;
1526 static gint
store_command(assuan_context_t ctx
, gchar
*line
)
1528 struct client_s
*client
= assuan_get_pointer(ctx
);
1531 rc
= assuan_inquire_ext(ctx
, "STORE", 0, store_command_finalize
, ctx
);
1534 return send_error(ctx
, rc
);
1536 /* Don't return with assuan_process_done() here. This is an INQUIRE. */
1537 client
->inquire_status
= INQUIRE_BUSY
;
1541 static void *send_data_cb(void *arg
)
1543 struct assuan_cmd_s
*data
= arg
;
1547 pth_cancel_state(PTH_CANCEL_ENABLE
|PTH_CANCEL_ASYNCHRONOUS
, &old
);
1548 rc
= g_malloc(sizeof(gpg_error_t
));
1549 *rc
= assuan_send_data(data
->ctx
, data
->line
, data
->line_len
);
1550 pth_cancel_state(old
, NULL
);
1555 /* For every assuan command that needs to be sent to the client, a timeout is
1556 * needed to determine if the client lost the connection. The timeout is the
1557 * same as the "keepalive" configuration parameter or a default if unset.
1559 gpg_error_t
do_assuan_command(assuan_context_t ctx
,
1560 void *(*cb
)(void *data
), void *data
)
1562 pth_attr_t attr
= pth_attr_new();
1565 gint to
= get_key_file_integer("global", "keepalive");
1566 pth_event_t ev
, tev
;
1571 pth_attr_init(attr
);
1572 pth_attr_set(attr
, PTH_ATTR_JOINABLE
, TRUE
);
1573 tid
= pth_spawn(attr
, cb
, data
);
1575 pth_attr_destroy(attr
);
1578 log_write("%s(%i): pth_spawn(): %s", __FILE__
, __LINE__
,
1579 _gpg_strerror(gpg_error_from_errno(n
)));
1580 return gpg_error_from_errno(n
);
1583 pth_cleanup_push(cleanup_cancel_cb
, tid
);
1584 to
= to
<= 0 ? DEFAULT_KEEPALIVE_TO
: to
;
1585 ev
= pth_event(PTH_EVENT_TID
|PTH_UNTIL_TID_DEAD
, tid
);
1586 tev
= to
? pth_event(PTH_EVENT_TIME
, pth_timeout(to
, 0)) : NULL
;
1587 ev
= pth_event_concat(ev
, tev
, NULL
);
1588 pth_cleanup_push(cleanup_ev_cb
, ev
);
1593 st
= pth_event_status(tev
);
1595 if (st
== PTH_STATUS_OCCURRED
) {
1598 return GPG_ERR_TIMEOUT
;
1602 st
= pth_event_status(ev
);
1604 if (st
== PTH_STATUS_FAILED
) {
1608 rc
= GPG_ERR_ASS_WRITE_ERROR
;
1610 else if (st
== PTH_STATUS_OCCURRED
) {
1612 rc
= *(gpg_error_t
*)p
;
1621 static gpg_error_t
xfer_data(assuan_context_t ctx
, const gchar
*line
,
1627 struct assuan_cmd_s data
;
1628 gint progress
= get_key_file_integer("global", "xfer_progress");
1631 progress
= progress
>0 ? (progress
/ASSUAN_LINELENGTH
)*ASSUAN_LINELENGTH
: 0;
1632 to_send
= total
< ASSUAN_LINELENGTH
? total
: ASSUAN_LINELENGTH
;
1634 rc
= send_status(ctx
, STATUS_XFER
, "%li %li", sent
, total
);
1641 if (sent
+ to_send
> total
)
1642 to_send
= total
- sent
;
1644 data
.line
= flush
? NULL
: (gchar
*)line
+sent
;
1645 data
.line_len
= flush
? 0 : to_send
;
1646 rc
= do_assuan_command(ctx
, send_data_cb
, &data
);
1649 sent
+= flush
? 0 : to_send
;
1651 if ((progress
&& !(sent
% progress
) && sent
!= total
) ||
1652 (sent
== total
&& flush
))
1653 rc
= send_status(ctx
, STATUS_XFER
, "%li %li", sent
, total
);
1655 if (!flush
&& !rc
&& sent
== total
) {
1660 } while (!rc
&& sent
< total
);
1665 static gint
get_command(assuan_context_t ctx
, gchar
*line
)
1667 struct client_s
*client
= assuan_get_pointer(ctx
);
1672 log_write2("ARGS=\"%s\"", line
);
1673 req
= split_input_line(line
, "\t", -1);
1675 if (!req
|| !*req
) {
1677 return send_error(ctx
, GPG_ERR_SYNTAX
);
1680 n
= find_root_element(client
->doc
, &req
, &rc
, NULL
, 0, FALSE
);
1684 return send_error(ctx
, rc
);
1688 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
1693 return send_error(ctx
, rc
);
1695 if (!n
|| !n
->children
)
1696 return send_error(ctx
, GPG_ERR_NO_VALUE
);
1698 n
= find_text_node(n
->children
);
1700 if (!n
|| !n
->content
|| !*n
->content
)
1701 return send_error(ctx
, GPG_ERR_NO_VALUE
);
1703 rc
= xfer_data(ctx
, (gchar
*)n
->content
, xmlStrlen(n
->content
));
1704 return send_error(ctx
, rc
);
1707 static xmlNodePtr
realpath_elements_cb(xmlNodePtr node
, gchar
**target
,
1708 gpg_error_t
*rc
, gchar
**req_orig
, void *data
)
1710 gchar
*path
= *(gchar
**)data
;
1711 gchar
*tmp
= NULL
, *result
;
1715 *(gchar
**)data
= NULL
;
1718 path
= g_strjoinv("\t", target
);
1721 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1722 *rc
= gpg_error_from_errno(ENOMEM
);
1727 tmp
= g_strjoinv("\t", req_orig
);
1731 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1732 *rc
= gpg_error_from_errno(ENOMEM
);
1738 result
= g_strdup_printf("%s\t%s", path
, tmp
);
1740 result
= g_strdup(path
);
1743 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1744 *rc
= gpg_error_from_errno(ENOMEM
);
1752 *(gchar
**)data
= result
;
1756 static void list_command_cleanup1(void *arg
);
1757 static gint
realpath_command(assuan_context_t ctx
, gchar
*line
)
1760 struct client_s
*client
= assuan_get_pointer(ctx
);
1768 log_write2("ARGS=\"%s\"", line
);
1770 if (strchr(line
, '\t') != NULL
) {
1771 if ((req
= split_input_line(line
, "\t", 0)) == NULL
)
1772 return send_error(ctx
, GPG_ERR_SYNTAX
);
1775 if ((req
= split_input_line(line
, " ", 0)) == NULL
)
1776 return send_error(ctx
, GPG_ERR_SYNTAX
);
1779 n
= find_root_element(client
->doc
, &req
, &rc
, NULL
, 0, FALSE
);
1783 return send_error(ctx
, rc
);
1786 rp
= g_strjoinv("\t", req
);
1790 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1791 return send_syserror(ctx
, ENOMEM
);
1795 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
,
1796 NULL
, realpath_elements_cb
, NULL
, FALSE
, 0, &rp
, FALSE
);
1801 return send_error(ctx
, rc
);
1805 string
= g_string_new(rp
);
1810 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1811 return send_syserror(ctx
, ENOMEM
);
1815 for (i
= 0, t
= string
->str
+ i
; *t
; t
++, i
++) {
1816 if ((!i
&& *t
!= '!') || (*t
== '\t' && *(t
+1) && *(t
+1) != '!')) {
1817 string
= g_string_insert_c(string
, !i
? i
++ : ++i
, '!');
1822 pth_cleanup_push(list_command_cleanup1
, string
);
1823 rc
= xfer_data(ctx
, string
->str
, string
->len
);
1825 return send_error(ctx
, rc
);
1828 static void list_command_cleanup1(void *arg
)
1830 g_string_free((GString
*)arg
, TRUE
);
1833 static void list_command_cleanup2(void *arg
)
1835 struct element_list_s
*elements
= arg
;
1838 gint total
= g_slist_length(elements
->list
);
1841 for (i
= 0; i
< total
; i
++) {
1842 gchar
*tmp
= g_slist_nth_data(elements
->list
, i
);
1846 g_slist_free(elements
->list
);
1848 if (elements
->prefix
)
1849 g_free(elements
->prefix
);
1855 static gint
list_command(assuan_context_t ctx
, gchar
*line
)
1857 struct client_s
*client
= assuan_get_pointer(ctx
);
1859 struct element_list_s
*elements
= NULL
;
1862 if (disable_list_and_dump
== TRUE
)
1863 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
1865 log_write2("ARGS=\"%s\"", line
);
1870 rc
= list_root_elements(client
->doc
, &str
);
1873 return send_error(ctx
, rc
);
1875 pth_cleanup_push(list_command_cleanup1
, str
);
1876 rc
= xfer_data(ctx
, str
->str
, str
->len
);
1878 return send_error(ctx
, rc
);
1881 elements
= g_malloc0(sizeof(struct element_list_s
));
1884 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1885 rc
= gpg_err_code_from_errno(ENOMEM
);
1889 pth_cleanup_push(list_command_cleanup2
, elements
);
1890 rc
= create_path_list(client
->doc
, elements
, line
);
1896 gint total
= g_slist_length(elements
->list
);
1901 rc
= GPG_ERR_NO_VALUE
;
1905 str
= g_string_new(NULL
);
1908 rc
= gpg_err_code_from_errno(ENOMEM
);
1909 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1913 for (i
= 0; i
< total
; i
++) {
1914 tmp
= g_slist_nth_data(elements
->list
, i
);
1915 g_string_append_printf(str
, "%s%s", tmp
, i
+1 == total
? "" : "\n");
1918 pth_cleanup_push(list_command_cleanup1
, str
);
1919 rc
= xfer_data(ctx
, str
->str
, str
->len
);
1923 rc
= GPG_ERR_NO_VALUE
;
1927 return send_error(ctx
, rc
);
1931 * req[0] - element path
1933 static gint
attribute_list(assuan_context_t ctx
, gchar
**req
)
1935 struct client_s
*client
= assuan_get_pointer(ctx
);
1936 gchar
**attrlist
= NULL
;
1938 gchar
**path
= NULL
;
1944 if (!req
|| !req
[0])
1945 return GPG_ERR_SYNTAX
;
1947 if ((path
= split_input_line(req
[0], "\t", 0)) == NULL
) {
1949 * The first argument may be only a root element.
1951 if ((path
= split_input_line(req
[0], " ", 0)) == NULL
)
1952 return GPG_ERR_SYNTAX
;
1955 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, FALSE
);
1963 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
1964 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
1974 for (a
= n
->properties
; a
; a
= a
->next
) {
1977 if ((pa
= g_realloc(attrlist
, (i
+ 2) * sizeof(gchar
*))) == NULL
) {
1979 g_strfreev(attrlist
);
1981 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1982 return gpg_error_from_errno(ENOMEM
);
1987 attrlist
[i
] = g_strdup_printf("%s %s", (gchar
*)a
->name
,
1988 an
&& an
->content
? (gchar
*)an
->content
: "");
1991 g_strfreev(attrlist
);
1992 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1993 return gpg_error_from_errno(ENOMEM
);
1996 attrlist
[++i
] = NULL
;
2000 return GPG_ERR_NO_VALUE
;
2002 line
= g_strjoinv("\n", attrlist
);
2005 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2006 g_strfreev(attrlist
);
2007 return gpg_error_from_errno(ENOMEM
);
2010 pth_cleanup_push(g_free
, line
);
2011 pth_cleanup_push(req_cleanup
, attrlist
);
2012 rc
= xfer_data(ctx
, line
, strlen(line
));
2019 * req[0] - attribute
2020 * req[1] - element path
2022 static gint
attribute_delete(struct client_s
*client
, gchar
**req
)
2025 gchar
**path
= NULL
;
2028 if (!req
|| !req
[0] || !req
[1])
2029 return GPG_ERR_SYNTAX
;
2031 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
) {
2033 * The first argument may be only a root element.
2035 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
2036 return GPG_ERR_SYNTAX
;
2040 * Don't remove the "_name" attribute for the root element. To remove an
2041 * root element use DELETE <name>.
2043 if (!path
[1] && xmlStrEqual((xmlChar
*)req
[0], (xmlChar
*)"_name")) {
2044 rc
= GPG_ERR_SYNTAX
;
2048 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, FALSE
);
2054 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2055 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2062 return delete_attribute(n
, (xmlChar
*)req
[0]);
2069 static xmlNodePtr
create_element_path(struct client_s
*client
, gchar
***path
,
2072 gchar
**src
= *path
;
2073 gchar
**src_orig
= g_strdupv(src
);
2074 xmlNodePtr n
= NULL
;
2079 *rc
= gpg_error_from_errno(ENOMEM
);
2080 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2085 n
= find_root_element(client
->doc
, &src
, rc
, NULL
, 0, FALSE
);
2088 if (*rc
== GPG_ERR_ELEMENT_NOT_FOUND
) {
2089 *rc
= new_root_element(client
->doc
, src
[0]);
2102 n
= create_target_elements_cb(n
, src
+1, rc
, NULL
);
2104 n
= find_elements(client
->doc
, n
->children
, src
+1, rc
,
2105 NULL
, NULL
, create_target_elements_cb
, FALSE
, 0, NULL
, FALSE
);
2111 * Reset the position of the element tree now that the elements
2112 * have been created.
2117 n
= find_root_element(client
->doc
, &src
, rc
, NULL
, 0, FALSE
);
2122 n
= find_elements(client
->doc
, n
->children
, src
+1, rc
,
2123 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2131 g_strfreev(src_orig
);
2138 * Creates a "target" attribute. When other commands encounter an element with
2139 * this attribute, the element path is modified to the target value. If the
2140 * source element path doesn't exist when using 'ATTR SET target', it is
2141 * created, but the destination element path must exist.
2143 * req[0] - source element path
2144 * req[1] - destination element path
2146 static gpg_error_t
target_attribute(struct client_s
*client
, gchar
**req
)
2148 gchar
**src
, **dst
, *line
= NULL
, **odst
= NULL
;
2152 if (!req
|| !req
[0] || !req
[1])
2153 return GPG_ERR_SYNTAX
;
2155 if ((src
= split_input_line(req
[0], "\t", 0)) == NULL
) {
2157 * The first argument may be only a root element.
2159 if ((src
= split_input_line(req
[0], " ", 0)) == NULL
)
2160 return GPG_ERR_SYNTAX
;
2163 if ((dst
= split_input_line(req
[1], "\t", 0)) == NULL
) {
2165 * The first argument may be only a root element.
2167 if ((dst
= split_input_line(req
[1], " ", 0)) == NULL
) {
2168 rc
= GPG_ERR_SYNTAX
;
2173 odst
= g_strdupv(dst
);
2176 rc
= gpg_error_from_errno(ENOMEM
);
2180 n
= find_root_element(client
->doc
, &dst
, &rc
, NULL
, 0, FALSE
);
2183 * Make sure the destination element path exists.
2189 n
= find_elements(client
->doc
, n
->children
, dst
+1, &rc
,
2190 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2196 n
= create_element_path(client
, &src
, &rc
);
2201 line
= g_strjoinv("\t", odst
);
2204 rc
= gpg_error_from_errno(ENOMEM
);
2205 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2209 rc
= add_attribute(n
, "target", line
);
2223 static gpg_error_t
name_attribute(struct client_s
*client
, gchar
**req
)
2229 tmp
= g_strdupv(req
);
2232 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2233 return gpg_error_from_errno(ENOMEM
);
2236 n
= find_root_element(client
->doc
, &tmp
, &rc
, NULL
, 0, FALSE
);
2242 if (g_utf8_collate(req
[0], req
[1]) == 0)
2246 * Will not overwrite an existing root.
2248 tmp
= g_strdupv(req
+1);
2251 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2252 return gpg_error_from_errno(ENOMEM
);
2255 n
= find_root_element(client
->doc
, &tmp
, &rc
, NULL
, 0, FALSE
);
2258 if (rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
)
2262 return GPG_ERR_AMBIGUOUS_NAME
;
2265 * Whitespace not allowed in root names.
2267 if (contains_whitespace(req
[1]) == TRUE
)
2268 return GPG_ERR_SYNTAX
;
2270 tmp
= g_strdupv(req
);
2273 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2274 return gpg_error_from_errno(ENOMEM
);
2277 n
= find_root_element(client
->doc
, &tmp
, &rc
, NULL
, 0, FALSE
);
2281 return GPG_ERR_ELEMENT_NOT_FOUND
;
2283 return add_attribute(n
, "_name", req
[1]);
2287 * req[0] - attribute
2288 * req[1] - element path
2290 static gint
attribute_get(assuan_context_t ctx
, gchar
**req
)
2292 struct client_s
*client
= assuan_get_pointer(ctx
);
2298 if (!req
|| !req
[0] || !req
[1])
2299 return GPG_ERR_SYNTAX
;
2301 if (strchr(req
[1], '\t')) {
2302 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
)
2303 return GPG_ERR_SYNTAX
;
2306 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
2307 return GPG_ERR_SYNTAX
;
2310 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, FALSE
);
2316 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2317 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2325 if ((a
= xmlGetProp(n
, (xmlChar
*)req
[0])) == NULL
)
2326 return GPG_ERR_NOT_FOUND
;
2328 pth_cleanup_push(xmlFree
, a
);
2331 rc
= xfer_data(ctx
, (gchar
*)a
, xmlStrlen(a
));
2333 rc
= GPG_ERR_NO_VALUE
;
2344 * req[0] - attribute
2345 * req[1] - element path
2348 static gint
attribute_set(struct client_s
*client
, gchar
**req
)
2350 gchar
**path
= NULL
;
2354 if (!req
|| !req
[0] || !req
[1])
2355 return GPG_ERR_SYNTAX
;
2358 * Reserved attribute names.
2360 if (!strcmp(req
[0], "_name")) {
2362 * Only reserved for the root element. Not the rest of the
2365 if (strchr(req
[1], '\t') == NULL
)
2366 return name_attribute(client
, req
+ 1);
2368 else if (!strcmp(req
[0], "target"))
2369 return target_attribute(client
, req
+ 1);
2371 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
) {
2373 * The first argument may be only a root element.
2375 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
2376 return GPG_ERR_SYNTAX
;
2379 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, FALSE
);
2385 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2386 NULL
, NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
2393 return add_attribute(n
, req
[0], req
[2]);
2402 * req[1] - attribute name or element path if command is LIST
2403 * req[2] - element path
2404 * req[2] - element path or value
2406 static gint
attr_command(assuan_context_t ctx
, gchar
*line
)
2408 struct client_s
*client
= assuan_get_pointer(ctx
);
2412 log_write2("ARGS=\"%s\"", line
);
2413 req
= split_input_line(line
, " ", 4);
2415 if (!req
|| !req
[0] || !req
[1]) {
2417 return send_error(ctx
, GPG_ERR_SYNTAX
);
2420 pth_cleanup_push(req_cleanup
, req
);
2422 if (g_ascii_strcasecmp(req
[0], "SET") == 0)
2423 rc
= attribute_set(client
, req
+1);
2424 else if (g_ascii_strcasecmp(req
[0], "GET") == 0)
2425 rc
= attribute_get(ctx
, req
+1);
2426 else if (g_ascii_strcasecmp(req
[0], "DELETE") == 0)
2427 rc
= attribute_delete(client
, req
+1);
2428 else if (g_ascii_strcasecmp(req
[0], "LIST") == 0)
2429 rc
= attribute_list(ctx
, req
+1);
2431 rc
= GPG_ERR_SYNTAX
;
2434 return send_error(ctx
, rc
);
2437 static gint
iscached_command(assuan_context_t ctx
, gchar
*line
)
2439 gchar
**req
= split_input_line(line
, " ", 0);
2443 if (!req
|| !*req
) {
2445 return send_error(ctx
, GPG_ERR_SYNTAX
);
2448 log_write2("ARGS=\"%s\"", line
);
2450 if (!valid_filename(req
[0])) {
2452 return GPG_ERR_INV_VALUE
;
2455 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2458 if (cache_iscached(md5file
)) {
2461 return send_error(ctx
, 0);
2465 tmp
= get_key_file_string("global", "data_directory");
2469 return gpg_error_from_errno(ENOMEM
);
2472 path
= expand_homedir(tmp
);
2477 return gpg_error_from_errno(ENOMEM
);
2482 path
= g_strdup_printf("%s/%s", tmp
, req
[0]);
2487 return gpg_error_from_errno(ENOMEM
);
2490 if (access(path
, R_OK
) == -1) {
2491 gpg_error_t rc
= gpg_error_from_syserror();
2495 return send_error(ctx
, rc
);
2499 return send_error(ctx
, GPG_ERR_NOT_FOUND
);
2502 static gint
clearcache_command(assuan_context_t ctx
, gchar
*line
)
2504 struct client_s
*client
= assuan_get_pointer(ctx
);
2505 gchar
**req
= split_input_line(line
, " ", 0);
2508 log_write2("ARGS=\"%s\"", line
);
2511 if (!req
|| !*req
) {
2513 cache_clear(client
->md5file
, 2);
2515 return send_error(ctx
, 0);
2518 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2521 if (cache_clear(md5file
, 1) == FALSE
) {
2523 return send_error(ctx
, GPG_ERR_NOT_FOUND
);
2527 return send_error(ctx
, 0);
2530 static gint
cachetimeout_command(assuan_context_t ctx
, gchar
*line
)
2534 gchar
**req
= split_input_line(line
, " ", 0);
2537 if (!req
|| !*req
|| !req
[1]) {
2539 return send_error(ctx
, GPG_ERR_SYNTAX
);
2543 timeout
= strtol(req
[1], &p
, 10);
2545 if (errno
!= 0 || *p
!= 0 || timeout
< -1) {
2547 return send_error(ctx
, GPG_ERR_SYNTAX
);
2550 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2551 CACHE_LOCK(client
->ctx
);
2553 if (cache_set_timeout(md5file
, timeout
) == FALSE
) {
2555 return send_error(ctx
, GPG_ERR_NOT_FOUND
);
2559 return send_error(ctx
, 0);
2562 static gint
dump_command(assuan_context_t ctx
, gchar
*line
)
2566 struct client_s
*client
= assuan_get_pointer(ctx
);
2569 if (disable_list_and_dump
== TRUE
)
2570 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2572 xmlDocDumpFormatMemory(client
->doc
, &xml
, &len
, 1);
2575 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2576 return send_syserror(ctx
, ENOMEM
);
2579 pth_cleanup_push(xmlFree
, xml
);
2580 rc
= xfer_data(ctx
, (gchar
*)xml
, len
);
2582 return send_error(ctx
, rc
);
2585 static gint
getconfig_command(assuan_context_t ctx
, gchar
*line
)
2587 struct client_s
*client
= assuan_get_pointer(ctx
);
2589 gchar filename
[255]={0}, param
[747]={0};
2590 gchar
*p
, *tmp
, *fp
= client
->filename
, *paramp
= line
;
2592 log_write2("ARGS=\"%s\"", line
);
2594 if (strchr(line
, ' ')) {
2595 sscanf(line
, " %254[^ ] %746c", filename
, param
);
2600 if (fp
&& !valid_filename(fp
))
2601 return send_error(ctx
, GPG_ERR_INV_VALUE
);
2603 paramp
= g_ascii_strdown(paramp
, -1);
2606 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2607 return send_syserror(ctx
, ENOMEM
);
2610 if (fp
&& !g_ascii_strcasecmp(paramp
, "iterations")) {
2611 if (!(client
->opts
& OPT_ITERATIONS
) || fp
!= client
->filename
) {
2612 file_header_internal_t
*fh
= read_file_header(fp
, FALSE
, &rc
);
2614 if (!fh
&& rc
!= GPG_ERR_ENOENT
)
2615 return send_error(ctx
, rc
);
2619 p
= g_strdup_printf("%lu", (unsigned long)fh
->ver
.fh2
.iter
);
2620 close_file_header(fh
);
2623 log_write("%s(%i): %s", __FILE__
, __LINE__
,
2625 return send_syserror(ctx
, ENOMEM
);
2632 else if (!g_ascii_strcasecmp(paramp
, "enable_pinentry")) {
2633 #ifdef WITH_PINENTRY
2636 if (fp
== client
->filename
&& (client
->opts
& OPT_PINENTRY
))
2637 n
= client
->pinentry
->enable
;
2639 n
= get_key_file_boolean(fp
, "enable_pinentry");
2641 p
= g_strdup_printf("%s", n
? "true" : "false");
2644 log_write("%s(%i): %s", __FILE__
, __LINE__
,
2646 return send_syserror(ctx
, ENOMEM
);
2651 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2654 else if (!g_ascii_strcasecmp(paramp
, "pinentry_timeout")) {
2655 #ifdef WITH_PINENTRY
2656 if (fp
== client
->filename
&& (client
->opts
& OPT_PINENTRY_TO
))
2657 p
= g_strdup_printf("%i", client
->pinentry
->timeout
);
2659 p
= g_strdup_printf("%i",
2660 get_key_file_integer(fp
, "pinentry_timeout"));
2663 log_write("%s(%i): %s", __FILE__
, __LINE__
,
2665 return send_syserror(ctx
, ENOMEM
);
2670 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2674 p
= get_key_file_string(fp
? fp
: "global", paramp
);
2678 return send_error(ctx
, GPG_ERR_NO_VALUE
);
2680 tmp
= expand_homedir(p
);
2684 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2685 return send_syserror(ctx
, ENOMEM
);
2690 pth_cleanup_push(g_free
, p
);
2691 rc
= xfer_data(ctx
, p
, strlen(p
));
2693 return send_error(ctx
, rc
);
2697 xmlXPathContextPtr xp
;
2698 xmlXPathObjectPtr result
;
2703 static void xpath_command_cleanup(void *arg
)
2705 struct xpath_s
*xpath
= arg
;
2707 req_cleanup(xpath
->req
);
2710 xmlBufferFree(xpath
->buf
);
2713 xmlXPathFreeObject(xpath
->result
);
2716 xmlXPathFreeContext(xpath
->xp
);
2719 static gint
xpath_command(assuan_context_t ctx
, gchar
*line
)
2721 struct client_s
*client
= assuan_get_pointer(ctx
);
2723 struct xpath_s xpath
;
2725 log_write2("ARGS=\"%s\"", line
);
2727 if (disable_list_and_dump
== TRUE
)
2728 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2730 if (!line
|| !*line
)
2731 return send_error(ctx
, GPG_ERR_SYNTAX
);
2733 memset(&xpath
, 0, sizeof(struct xpath_s
));
2735 if ((xpath
.req
= split_input_line(line
, "\t", 2)) == NULL
) {
2736 if (strv_printf(&xpath
.req
, "%s", line
) == FALSE
)
2737 return send_syserror(ctx
, ENOMEM
);
2740 xpath
.xp
= xmlXPathNewContext(client
->doc
);
2743 xpath_command_cleanup(&xpath
);
2744 return send_error(ctx
, EPWMD_LIBXML_ERROR
);
2747 xpath
.result
= xmlXPathEvalExpression((xmlChar
*)xpath
.req
[0], xpath
.xp
);
2749 if (!xpath
.result
) {
2750 xpath_command_cleanup(&xpath
);
2751 return send_error(ctx
, EPWMD_LIBXML_ERROR
);
2754 if (xmlXPathNodeSetIsEmpty(xpath
.result
->nodesetval
)) {
2755 rc
= GPG_ERR_ELEMENT_NOT_FOUND
;
2759 rc
= recurse_xpath_nodeset(client
->doc
, xpath
.result
->nodesetval
,
2760 (xmlChar
*)xpath
.req
[1], &xpath
.buf
, 0, NULL
);
2764 else if (!xpath
.req
[1] && !xmlBufferLength(xpath
.buf
)) {
2765 rc
= GPG_ERR_NO_VALUE
;
2768 else if (xpath
.req
[1])
2771 pth_cleanup_push(xpath_command_cleanup
, &xpath
);
2772 rc
= xfer_data(ctx
, (gchar
*)xmlBufferContent(xpath
.buf
),
2773 xmlBufferLength(xpath
.buf
));
2777 xpath_command_cleanup(&xpath
);
2778 return send_error(ctx
, rc
);
2781 /* XPATHATTR SET|DELETE <name> <expression>[<TAB>[value]] */
2782 static gint
xpathattr_command(assuan_context_t ctx
, gchar
*line
)
2784 struct client_s
*client
= assuan_get_pointer(ctx
);
2786 struct xpath_s xpath
;
2788 gboolean cmd
= FALSE
; //SET
2790 log_write2("ARGS=\"%s\"", line
);
2792 if (disable_list_and_dump
== TRUE
)
2793 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2795 if (!line
|| !*line
)
2796 return send_error(ctx
, GPG_ERR_SYNTAX
);
2798 memset(&xpath
, 0, sizeof(struct xpath_s
));
2800 if ((req
= split_input_line(line
, " ", 3)) == NULL
)
2801 return send_syserror(ctx
, ENOMEM
);
2804 rc
= GPG_ERR_SYNTAX
;
2808 if (!g_ascii_strcasecmp(req
[0], "SET"))
2810 else if (!g_ascii_strcasecmp(req
[0], "DELETE"))
2813 rc
= GPG_ERR_SYNTAX
;
2817 if (!req
[1] || !req
[2]) {
2818 rc
= GPG_ERR_SYNTAX
;
2822 if ((xpath
.req
= split_input_line(req
[2], "\t", 3)) == NULL
) {
2823 rc
= gpg_err_code_from_errno(ENOMEM
);
2827 if (!xpath
.req
[0] || (!xpath
.req
[1] && !cmd
) || (xpath
.req
[1] && cmd
)) {
2828 rc
= GPG_ERR_SYNTAX
;
2832 xpath
.xp
= xmlXPathNewContext(client
->doc
);
2835 rc
= EPWMD_LIBXML_ERROR
;
2839 xpath
.result
= xmlXPathEvalExpression((xmlChar
*)xpath
.req
[0], xpath
.xp
);
2841 if (!xpath
.result
) {
2842 rc
= EPWMD_LIBXML_ERROR
;
2846 if (xmlXPathNodeSetIsEmpty(xpath
.result
->nodesetval
)) {
2847 rc
= GPG_ERR_ELEMENT_NOT_FOUND
;
2851 rc
= recurse_xpath_nodeset(client
->doc
, xpath
.result
->nodesetval
,
2852 (xmlChar
*)xpath
.req
[1], &xpath
.buf
, cmd
, (xmlChar
*)req
[1]);
2856 xpath_command_cleanup(&xpath
);
2857 return send_error(ctx
, rc
);
2860 static gint
import_command_finalize(gpointer data
, gint assuan_rc
, guchar
*line
,
2863 struct client_s
*client
= assuan_get_pointer((assuan_context_t
)data
);
2864 gpg_error_t rc
= file_modified(client
);
2865 gchar
**req
, **path
= NULL
, **path_orig
= NULL
, *content
;
2866 xmlDocPtr doc
= NULL
;
2867 xmlNodePtr n
, root
, copy
;
2869 if (assuan_rc
|| rc
) {
2872 return assuan_rc
? assuan_rc
: rc
;
2875 req
= split_input_line((gchar
*)line
, "\t", 2);
2879 return GPG_ERR_SYNTAX
;
2882 path
= split_input_line(req
[1], "\t", 0);
2884 if (!content
|| !*content
) {
2885 rc
= GPG_ERR_SYNTAX
;
2889 doc
= xmlReadDoc((xmlChar
*)content
, NULL
, "UTF-8", XML_PARSE_NOBLANKS
);
2892 rc
= EPWMD_LIBXML_ERROR
;
2896 root
= xmlDocGetRootElement(doc
);
2897 rc
= validate_import(root
);
2903 path_orig
= g_strdupv(path
);
2906 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2907 rc
= gpg_error_from_errno(ENOMEM
);
2911 xmlChar
*a
= xmlGetProp(root
, (xmlChar
*)"_name");
2914 g_strfreev(path_orig
);
2915 rc
= gpg_error_from_errno(ENOMEM
);
2919 if (strv_printf(&path
, "%s", (gchar
*)a
) == FALSE
) {
2921 g_strfreev(path_orig
);
2922 rc
= gpg_error_from_errno(ENOMEM
);
2927 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, FALSE
);
2929 if (rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
) {
2930 g_strfreev(path_orig
);
2935 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
, TRUE
);
2937 if (rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
) {
2938 g_strfreev(path_orig
);
2942 xmlNodePtr parent
= n
->parent
;
2953 if (rc
== GPG_ERR_ELEMENT_NOT_FOUND
) {
2954 n
= create_element_path(client
, &path
, &rc
);
2960 copy
= xmlCopyNodeList(root
);
2961 n
= xmlAddChildList(n
, copy
);
2964 rc
= EPWMD_LIBXML_ERROR
;
2967 /* Check if the content root element can create a DTD root element. */
2968 if (!xmlStrEqual((xmlChar
*)"element", root
->name
)) {
2969 rc
= GPG_ERR_SYNTAX
;
2975 if ((a
= xmlGetProp(root
, (xmlChar
*)"_name")) == NULL
) {
2976 rc
= GPG_ERR_SYNTAX
;
2980 gchar
*tmp
= g_strdup((gchar
*)a
);
2982 gboolean literal
= is_literal_element(&tmp
);
2984 if (!valid_xml_element((xmlChar
*)tmp
) || literal
) {
2986 rc
= GPG_ERR_INV_VALUE
;
2990 if (strv_printf(&path
, "%s", tmp
) == FALSE
) {
2992 rc
= gpg_error_from_errno(ENOMEM
);
2997 n
= find_root_element(client
->doc
, &path
, &rc
, NULL
, 0, TRUE
);
2999 if (rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
) {
3000 rc
= EPWMD_LIBXML_ERROR
;
3004 /* Overwriting the existing tree. */
3011 xmlSetProp(root
, (xmlChar
*)"_name", (xmlChar
*)path
[0]);
3012 n
= xmlCopyNode(root
, 1);
3013 n
= xmlAddChildList(xmlDocGetRootElement(client
->doc
), n
);
3024 client
->inquire_status
= INQUIRE_DONE
;
3028 static gint
import_command(assuan_context_t ctx
, gchar
*line
)
3031 struct client_s
*client
= assuan_get_pointer(ctx
);
3033 rc
= assuan_inquire_ext(ctx
, "IMPORT", 0, import_command_finalize
, ctx
);
3036 return send_error(ctx
, rc
);
3038 /* Don't return with assuan_process_done() here. This is an INQUIRE. */
3039 client
->inquire_status
= INQUIRE_BUSY
;
3043 static gpg_error_t
do_lock_command(struct client_s
*client
)
3045 gpg_error_t rc
= lock_file_mutex(client
);
3048 client
->is_lock_cmd
= TRUE
;
3050 return send_error(client
->ctx
, rc
);
3053 static gint
lock_command(assuan_context_t ctx
, gchar
*line
)
3055 struct client_s
*client
= assuan_get_pointer(ctx
);
3057 return do_lock_command(client
);
3060 static gint
unlock_command(assuan_context_t ctx
, gchar
*line
)
3062 struct client_s
*client
= assuan_get_pointer(ctx
);
3064 unlock_file_mutex(client
);
3065 return send_error(ctx
, 0);
3068 static gint
getpid_command(assuan_context_t ctx
, gchar
*line
)
3072 pid_t pid
= getpid();
3074 print_fmt(buf
, sizeof(buf
), "%i", pid
);
3075 rc
= xfer_data(ctx
, buf
, strlen(buf
));
3076 return send_error(ctx
, rc
);
3079 static gint
version_command(assuan_context_t ctx
, gchar
*line
)
3084 print_fmt(buf
, sizeof(buf
), "0x%X", VERSION_HEX
);
3085 rc
= xfer_data(ctx
, buf
, strlen(buf
));
3086 return send_error(ctx
, rc
);
3089 #ifdef WITH_PINENTRY
3090 static void set_option_value(gchar
**opt
, const gchar
*value
)
3098 *opt
= g_strdup(value
);
3102 static gint
set_unset_common(assuan_context_t ctx
, const gchar
*name
,
3105 struct client_s
*client
= assuan_get_pointer(ctx
);
3107 if (g_ascii_strcasecmp(name
, (gchar
*)"log_level") == 0) {
3111 l
= strtol(value
, NULL
, 10);
3114 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
3117 log_write1("log_level=%li", l
);
3118 MUTEX_LOCK(&rcfile_mutex
);
3119 g_key_file_set_integer(keyfileh
, "global", "log_level", (gint
)l
);
3120 MUTEX_UNLOCK(&rcfile_mutex
);
3123 else if (g_ascii_strcasecmp(name
, (gchar
*)"rc_on_locked") == 0) {
3127 l
= strtol(value
, NULL
, 10);
3130 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
3133 log_write1("rc_on_locked=%li", l
);
3134 client
->rc_on_locked
= l
? TRUE
: FALSE
;
3137 else if (g_ascii_strcasecmp(name
, (gchar
*)"lock_on_open") == 0) {
3141 l
= strtol(value
, NULL
, 10);
3144 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
3147 log_write1("lock_on_open=%li", l
);
3148 client
->lockonopen
= l
? TRUE
: FALSE
;
3151 else if (g_ascii_strcasecmp(name
, (gchar
*)"cipher") == 0) {
3153 const gchar
*p
= value
;
3155 if (!client
->filename
)
3156 return EPWMD_NO_FILE
;
3159 flags
= pwmd_cipher_str_to_cipher(value
);
3162 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
3165 p
= get_key_file_string("global", "cipher");
3167 MUTEX_LOCK(&rcfile_mutex
);
3168 g_key_file_set_string(keyfileh
, client
->filename
, "cipher", p
);
3169 MUTEX_UNLOCK(&rcfile_mutex
);
3170 log_write1("cipher=%s", p
);
3177 else if (g_ascii_strcasecmp(name
, (gchar
*)"iterations") == 0) {
3181 if (!client
->filename
)
3182 return EPWMD_NO_FILE
;
3185 MUTEX_LOCK(&rcfile_mutex
);
3186 g_key_file_set_double(keyfileh
, client
->filename
, "iterations",
3187 get_key_file_double("global", "iterations"));
3188 MUTEX_UNLOCK(&rcfile_mutex
);
3189 log_write1("iterations=%lu",
3190 (guint64
)get_key_file_double(client
->filename
, "iterations"));
3195 n
= strtoul(value
, &p
, 10);
3197 if (errno
|| (p
&& *p
) || n
== G_MAXULONG
)
3198 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
3200 MUTEX_LOCK(&rcfile_mutex
);
3201 g_key_file_set_double(keyfileh
,
3202 client
->filename
? client
->filename
: "global", "iterations", n
);
3203 MUTEX_UNLOCK(&rcfile_mutex
);
3205 if (client
->filename
)
3206 client
->opts
|= OPT_ITERATIONS
;
3208 log_write1("iterations=%lu", n
);
3211 else if (g_ascii_strcasecmp(name
, (gchar
*)"NAME") == 0) {
3212 pth_attr_t attr
= pth_attr_of(pth_self());
3216 pth_attr_destroy(attr
);
3220 print_fmt(buf
, sizeof(buf
), "%s", value
);
3221 pth_attr_set(attr
, PTH_ATTR_NAME
, buf
);
3222 pth_attr_destroy(attr
);
3223 log_write1("name=%s", buf
);
3224 #ifdef WITH_PINENTRY
3225 if (client
->pinentry
->name
)
3226 g_free(client
->pinentry
->name
);
3228 client
->pinentry
->name
= g_strdup(buf
);
3230 if (!client
->pinentry
->name
)
3231 return gpg_error_from_errno(ENOMEM
);
3236 #ifdef WITH_PINENTRY
3237 else if (g_ascii_strcasecmp(name
, (gchar
*)"lc_messages") == 0)
3238 set_option_value(&client
->pinentry
->lcmessages
, value
);
3239 else if (g_ascii_strcasecmp(name
, (gchar
*)"lc_ctype") == 0)
3240 set_option_value(&client
->pinentry
->lcctype
, value
);
3241 else if (g_ascii_strcasecmp(name
, (gchar
*)"ttyname") == 0)
3242 set_option_value(&client
->pinentry
->ttyname
, value
);
3243 else if (g_ascii_strcasecmp(name
, (gchar
*)"ttytype") == 0)
3244 set_option_value(&client
->pinentry
->ttytype
, value
);
3245 else if (g_ascii_strcasecmp(name
, (gchar
*)"display") == 0)
3246 set_option_value(&client
->pinentry
->display
, value
);
3247 else if (g_ascii_strcasecmp(name
, (gchar
*)"pinentry_path") == 0)
3248 set_option_value(&client
->pinentry
->path
, value
);
3249 else if (g_ascii_strcasecmp(name
, (gchar
*)"title") == 0)
3250 set_option_value(&client
->pinentry
->title
, value
);
3251 else if (g_ascii_strcasecmp(name
, (gchar
*)"prompt") == 0)
3252 set_option_value(&client
->pinentry
->prompt
, value
);
3253 else if (g_ascii_strcasecmp(name
, (gchar
*)"desc") == 0)
3254 set_option_value(&client
->pinentry
->desc
, value
);
3255 else if (g_ascii_strcasecmp(name
, "pinentry_timeout") == 0) {
3260 client
->pinentry
->timeout
=
3261 get_key_file_integer(client
->filename
, "pinentry_timeout");
3262 client
->opts
&= ~(OPT_PINENTRY_TO
);
3263 log_write1("pinentry_timeout=%i",
3264 get_key_file_integer(client
->filename
, "pinentry_timeout"));
3268 n
= strtol(value
, &p
, 10);
3271 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
3273 client
->pinentry
->timeout
= n
;
3274 client
->opts
|= OPT_PINENTRY_TO
;
3275 log_write1("pinentry_timeout=%i", n
);
3278 else if (g_ascii_strcasecmp(name
, "enable_pinentry") == 0) {
3283 client
->pinentry
->enable
= -1;
3284 client
->opts
&= ~(OPT_PINENTRY
);
3288 n
= strtol(value
, &p
, 10);
3290 if (*p
|| n
< 0 || n
> 1)
3291 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
3293 client
->pinentry
->enable
= n
== 0 ? FALSE
: TRUE
;
3294 client
->opts
|= OPT_PINENTRY
;
3295 log_write1("enable_pinentry=%i", n
);
3300 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_UNKNOWN_OPTION
);
3302 log_write1("%s=%s", name
, value
? value
: "");
3308 static gint
unset_command(assuan_context_t ctx
, gchar
*line
)
3310 log_write2("ARGS=\"%s\"", line
);
3311 return send_error(ctx
, set_unset_common(ctx
, line
, NULL
));
3314 static gint
set_command(assuan_context_t ctx
, gchar
*line
)
3316 gchar name
[64] = {0}, value
[256] = {0};
3318 log_write2("ARGS=\"%s\"", line
);
3320 if (sscanf(line
, " %63[_a-zA-Z] = %255c", name
, value
) != 2)
3321 return send_error(ctx
, gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_SYNTAX
));
3323 return send_error(ctx
, set_unset_common(ctx
, name
, value
));
3326 static gint
rename_command(assuan_context_t ctx
, gchar
*line
)
3328 struct client_s
*client
= assuan_get_pointer(ctx
);
3330 gchar
**req
, **src
, *dst
;
3333 log_write2("ARGS=\"%s\"", line
);
3334 req
= split_input_line(line
, " ", -1);
3336 if (!req
|| !req
[0] || !req
[1]) {
3338 return send_error(ctx
, GPG_ERR_SYNTAX
);
3342 is_literal_element(&dst
);
3344 if (!valid_xml_element((xmlChar
*)dst
)) {
3346 return GPG_ERR_INV_VALUE
;
3349 if (strchr(req
[0], '\t'))
3350 src
= split_input_line(req
[0], "\t", -1);
3352 src
= split_input_line(req
[0], " ", -1);
3354 if (!src
|| !*src
) {
3355 rc
= GPG_ERR_SYNTAX
;
3359 n
= find_root_element(client
->doc
, &src
, &rc
, NULL
, 0, FALSE
);
3362 n
= find_elements(client
->doc
, n
->children
, src
+1, &rc
, NULL
, NULL
,
3363 NULL
, FALSE
, 0, NULL
, FALSE
);
3369 xmlChar
*a
= xmlGetProp(n
, (xmlChar
*)"_name");
3372 rc
= gpg_error_from_errno(ENOMEM
);
3376 /* To prevent unwanted effects:
3378 * <root name="a"><b/></root>
3382 if (xmlStrEqual(a
, (xmlChar
*)dst
)) {
3384 rc
= GPG_ERR_AMBIGUOUS_NAME
;
3394 for (p
= src
; *p
; p
++) {
3398 strv_printf(&tmp
, "%s", *p
);
3402 strv_printf(&tmp
, "!%s", dst
);
3403 ndst
= find_root_element(client
->doc
, &tmp
, &rc
, NULL
, 0, FALSE
);
3405 if (!ndst
&& rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
) {
3411 ndst
= find_elements(client
->doc
, ndst
->children
, tmp
+1, &rc
, NULL
,
3412 NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
3416 if (!ndst
&& rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
)
3421 /* Target may exist:
3424 * <root name="b" target="a"/>
3432 rc
= GPG_ERR_AMBIGUOUS_NAME
;
3437 xmlUnlinkNode(ndst
);
3438 xmlFreeNodeList(ndst
);
3441 rc
= add_attribute(n
, "_name", dst
);
3446 return send_error(ctx
, rc
);
3449 static gint
copy_command(assuan_context_t ctx
, gchar
*line
)
3451 struct client_s
*client
= assuan_get_pointer(ctx
);
3453 gchar
**req
, **src
= NULL
, **dst
= NULL
;
3454 xmlNodePtr nsrc
, ndst
, new;
3456 log_write2("ARGS=\"%s\"", line
);
3457 req
= split_input_line(line
, " ", -1);
3459 if (!req
|| !req
[0] || !req
[1]) {
3461 return send_error(ctx
, GPG_ERR_SYNTAX
);
3464 if (strchr(req
[0], '\t'))
3465 src
= split_input_line(req
[0], "\t", -1);
3467 src
= split_input_line(req
[0], " ", -1);
3469 if (!src
|| !*src
) {
3470 rc
= GPG_ERR_SYNTAX
;
3474 if (strchr(req
[1], '\t'))
3475 dst
= split_input_line(req
[1], "\t", -1);
3477 dst
= split_input_line(req
[1], " ", -1);
3479 if (!dst
|| !*dst
) {
3480 rc
= GPG_ERR_SYNTAX
;
3484 nsrc
= find_root_element(client
->doc
, &src
, &rc
, NULL
, 0, FALSE
);
3487 nsrc
= find_elements(client
->doc
, nsrc
->children
, src
+1, &rc
, NULL
,
3488 NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
3493 ndst
= find_root_element(client
->doc
, &dst
, &rc
, NULL
, 0, FALSE
);
3496 ndst
= find_elements(client
->doc
, ndst
->children
, dst
+1, &rc
, NULL
,
3497 NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
3499 if (!ndst
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
)
3502 new = xmlCopyNodeList(nsrc
);
3505 rc
= GPG_ERR_ENOMEM
;
3510 ndst
= create_element_path(client
, &dst
, &rc
);
3514 xmlFreeNodeList(new);
3518 /* Merge any attributes from the src node to the initial dst node. */
3519 for (xmlAttrPtr attr
= new->properties
; attr
; attr
= attr
->next
) {
3520 if ((!src
[1] || !dst
[1]) && xmlStrEqual(attr
->name
, (xmlChar
*)"_name"))
3523 xmlAttrPtr a
= xmlHasProp(ndst
, attr
->name
);
3528 xmlNewProp(ndst
, attr
->name
, attr
->children
->content
);
3531 xmlNodePtr n
= ndst
->children
;
3534 ndst
->children
= NULL
;
3536 if (!new->children
) {
3538 xmlFreeNodeList(new);
3542 n
= xmlCopyNodeList(new->children
);
3545 rc
= GPG_ERR_ENOMEM
;
3550 xmlFreeNodeList(new);
3551 n
= xmlAddChildList(ndst
, n
);
3554 rc
= GPG_ERR_ENOMEM
;
3568 return send_error(ctx
, rc
);
3571 static gint
move_command(assuan_context_t ctx
, gchar
*line
)
3573 struct client_s
*client
= assuan_get_pointer(ctx
);
3575 gchar
**req
, **src
= NULL
, **dst
= NULL
;
3576 xmlNodePtr nsrc
, ndst
= NULL
;
3578 log_write2("ARGS=\"%s\"", line
);
3579 req
= split_input_line(line
, " ", -1);
3581 if (!req
|| !req
[0] || !req
[1]) {
3583 return send_error(ctx
, GPG_ERR_SYNTAX
);
3586 if (strchr(req
[0], '\t'))
3587 src
= split_input_line(req
[0], "\t", -1);
3589 src
= split_input_line(req
[0], " ", -1);
3591 if (!src
|| !*src
) {
3592 rc
= GPG_ERR_SYNTAX
;
3596 if (strchr(req
[1], '\t'))
3597 dst
= split_input_line(req
[1], "\t", -1);
3599 dst
= split_input_line(req
[1], " ", -1);
3601 nsrc
= find_root_element(client
->doc
, &src
, &rc
, NULL
, 0, FALSE
);
3604 nsrc
= find_elements(client
->doc
, nsrc
->children
, src
+1, &rc
, NULL
,
3605 NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
3611 ndst
= find_root_element(client
->doc
, &dst
, &rc
, NULL
, 0, FALSE
);
3614 ndst
= find_elements(client
->doc
, ndst
->children
, dst
+1, &rc
, NULL
,
3615 NULL
, NULL
, FALSE
, 0, NULL
, FALSE
);
3618 ndst
= xmlDocGetRootElement(client
->doc
);
3620 for (xmlNodePtr n
= ndst
; n
; n
= n
->parent
) {
3622 rc
= GPG_ERR_CONFLICT
;
3627 if (rc
&& rc
!= GPG_ERR_ELEMENT_NOT_FOUND
)
3633 xmlChar
*a
= node_has_attribute(nsrc
, (xmlChar
*)"_name");
3634 xmlNodePtr dup
= find_element(ndst
->children
, (gchar
*)a
, NULL
);
3642 if (ndst
== xmlDocGetRootElement(client
->doc
)) {
3643 xmlNodePtr n
= nsrc
;
3644 gboolean match
= FALSE
;
3646 while (n
->parent
&& n
->parent
!= ndst
)
3649 xmlChar
*a
= node_has_attribute(n
, (xmlChar
*)"_name");
3650 xmlChar
*b
= node_has_attribute(nsrc
, (xmlChar
*)"_name");
3652 if (xmlStrEqual(a
, b
)) {
3654 xmlUnlinkNode(nsrc
);
3664 xmlFreeNodeList(dup
);
3673 ndst
= create_element_path(client
, &dst
, &rc
);
3678 xmlUnlinkNode(nsrc
);
3679 ndst
= xmlAddChildList(ndst
, nsrc
);
3682 rc
= GPG_ERR_ENOMEM
;
3694 return send_error(ctx
, rc
);
3697 static int ls_command(assuan_context_t ctx
, gchar
*line
)
3699 log_write2("ARGS=\"%s\"", line
);
3701 gchar
*tmp
= g_key_file_get_string(keyfileh
, "global", "data_directory", NULL
);
3702 gchar
*dir
= expand_homedir(tmp
);
3703 DIR *d
= opendir(dir
);
3710 return send_syserror(ctx
, n
);
3713 size_t len
= offsetof(struct dirent
, d_name
)+pathconf(dir
, _PC_NAME_MAX
)+1;
3714 struct dirent
*p
= g_malloc(len
), *cur
= NULL
;
3720 while (!readdir_r(d
, p
, &cur
) && cur
) {
3721 if (cur
->d_name
[0] == '.' && cur
->d_name
[1] == '\0')
3723 else if (cur
->d_name
[0] == '.' && cur
->d_name
[1] == '.' && cur
->d_name
[2] == '\0')
3726 tmp
= g_strdup_printf("%s%s\n", list
? list
: "", cur
->d_name
);
3732 rc
= GPG_ERR_ENOMEM
;
3744 return send_error(ctx
, rc
);
3747 return send_error(ctx
, GPG_ERR_NO_VALUE
);
3749 list
[strlen(list
)-1] = 0;
3750 rc
= xfer_data(ctx
, list
, strlen(list
));
3752 return send_error(ctx
, rc
);
3755 static void bye_notify(assuan_context_t ctx
)
3757 struct client_s
*cl
= assuan_get_pointer(ctx
);
3759 /* This will let assuan_process_next() return. */
3760 fcntl(cl
->thd
->fd
, F_SETFL
, O_NONBLOCK
);
3763 static void reset_notify(assuan_context_t ctx
)
3765 struct client_s
*cl
= assuan_get_pointer(ctx
);
3772 * This is called before every Assuan command.
3774 gint
command_startup(assuan_context_t ctx
, const gchar
*name
)
3776 struct client_s
*cl
= assuan_get_pointer(ctx
);
3779 log_write1("%s", name
);
3781 if (!g_ascii_strcasecmp(name
, "ISCACHED") ||
3782 !g_ascii_strcasecmp(name
, "CLEARCACHE") ||
3783 !g_ascii_strcasecmp(name
, "CACHETIMEOUT") ||
3784 !g_ascii_strcasecmp(name
, "GETCONFIG") ||
3785 !g_ascii_strcasecmp(name
, "GETPID") ||
3786 !g_ascii_strcasecmp(name
, "VERSION") ||
3787 !g_ascii_strcasecmp(name
, "SET") ||
3788 !g_ascii_strcasecmp(name
, "BYE") ||
3789 !g_ascii_strcasecmp(name
, "NOP") ||
3790 !g_ascii_strcasecmp(name
, "CANCEL") ||
3791 !g_ascii_strcasecmp(name
, "RESET") ||
3792 !g_ascii_strcasecmp(name
, "END") ||
3793 !g_ascii_strcasecmp(name
, "HELP") ||
3794 !g_ascii_strcasecmp(name
, "OPTION") ||
3795 !g_ascii_strcasecmp(name
, "INPUT") ||
3796 !g_ascii_strcasecmp(name
, "OUTPUT") ||
3797 !g_ascii_strcasecmp(name
, "LS") ||
3798 !g_ascii_strcasecmp(name
, "UNSET"))
3801 cl
->last_rc
= rc
= file_modified(cl
);
3804 if ((rc
== EPWMD_NO_FILE
|| rc
== EPWMD_FILE_MODIFIED
) &&
3805 !g_ascii_strcasecmp(name
, "OPEN"))
3813 * This is called after every Assuan command.
3815 void command_finalize(assuan_context_t ctx
, gint rc
)
3817 struct client_s
*client
= assuan_get_pointer(ctx
);
3819 if (!client
->is_lock_cmd
)
3820 unlock_file_mutex(client
);
3822 log_write1(N_("command completed (rc=%u)"), client
->last_rc
);
3825 gpg_error_t
register_commands(assuan_context_t ctx
)
3829 gint (*handler
)(assuan_context_t
, gchar
*line
);
3831 { "OPEN", open_command
},
3832 { "SAVE", save_command
},
3833 { "LIST", list_command
},
3834 { "REALPATH", realpath_command
},
3835 { "STORE", store_command
},
3836 { "DELETE", delete_command
},
3837 { "GET", get_command
},
3838 { "ATTR", attr_command
},
3839 { "ISCACHED", iscached_command
},
3840 { "CLEARCACHE", clearcache_command
},
3841 { "CACHETIMEOUT", cachetimeout_command
},
3842 { "GETCONFIG", getconfig_command
},
3843 { "DUMP", dump_command
},
3844 { "XPATH", xpath_command
},
3845 { "XPATHATTR", xpathattr_command
},
3846 { "IMPORT", import_command
},
3847 { "LOCK", lock_command
},
3848 { "UNLOCK", unlock_command
},
3849 { "GETPID", getpid_command
},
3850 { "VERSION", version_command
},
3851 { "SET", set_command
},
3852 { "UNSET", unset_command
},
3853 { "RENAME", rename_command
},
3854 { "COPY", copy_command
},
3855 { "LS", ls_command
},
3856 { "MOVE", move_command
},
3863 for (i
=0; table
[i
].name
; i
++) {
3864 rc
= assuan_register_command (ctx
, table
[i
].name
, table
[i
].handler
);
3870 rc
= assuan_register_bye_notify(ctx
, bye_notify
);
3875 rc
= assuan_register_reset_notify(ctx
, reset_notify
);
3880 rc
= assuan_register_pre_cmd_notify(ctx
, command_startup
);
3885 return assuan_register_post_cmd_notify(ctx
, command_finalize
);
3888 gpg_error_t
try_xml_decrypt(assuan_context_t ctx
,
3889 struct crypto_s
*crypto
, gpointer
*dst
, goffset
*dst_len
)
3891 goffset insize
, len
;
3892 struct client_s
*client
= ctx
? assuan_get_pointer(ctx
) : NULL
;
3893 guint64 iter
= 0ULL, n_iter
= 0ULL, iter_progress
= 0ULL;
3897 gsize fh_size
= crypto
->fh
->v1
? sizeof(crypto
->fh
->ver
.fh1
) : sizeof(crypto
->fh
->ver
.fh2
);
3898 guint64 fh_iter
= crypto
->fh
->v1
? crypto
->fh
->ver
.fh1
.iter
: crypto
->fh
->ver
.fh2
.iter
;
3899 gsize hashlen
= gcry_md_get_algo_dlen(GCRY_MD_SHA256
);
3901 lseek(crypto
->fh
->fd
, fh_size
, SEEK_SET
);
3902 insize
= crypto
->fh
->st
.st_size
- fh_size
;
3903 crypto
->iv
= gcry_malloc(crypto
->blocksize
);
3906 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
3907 return gpg_error_from_errno(ENOMEM
);
3911 memcpy(crypto
->iv
, crypto
->fh
->ver
.fh1
.iv
, crypto
->blocksize
);
3913 memcpy(crypto
->iv
, crypto
->fh
->ver
.fh2
.iv
, crypto
->blocksize
);
3915 crypto
->inbuf
= gcry_malloc(insize
);
3917 if (!crypto
->inbuf
) {
3918 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
3919 return gpg_error_from_errno(ENOMEM
);
3922 crypto
->insize
= insize
;
3923 len
= pth_read(crypto
->fh
->fd
, crypto
->inbuf
, crypto
->insize
);
3925 if (len
!= crypto
->insize
)
3926 return GPG_ERR_INV_LENGTH
;
3928 /* No encryption iterations. This is a plain (gzipped) file. */
3929 if ((crypto
->fh
->v1
&& (long)fh_iter
< 0L) ||
3930 (!crypto
->fh
->v1
&& fh_iter
<= 0L)) {
3932 * cache_file_count() needs both .used == TRUE and a valid key in
3933 * order for it to count as a used cache entry. Fixes CACHE status
3936 memset(crypto
->key
, '!', hashlen
);
3940 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->iv
, crypto
->blocksize
))) {
3941 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
3945 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->key
, crypto
->keysize
))) {
3946 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
3950 iter_progress
= (guint64
)get_key_file_double(client
&& client
->filename
?
3951 client
->filename
: "global", "iteration_progress");
3953 if (iter_progress
> 0ULL && fh_iter
>= iter_progress
) {
3954 rc
= send_status(ctx
, STATUS_DECRYPT
, "0 %llu", fh_iter
);
3960 rc
= iterate_crypto_once(client
, crypto
, STATUS_DECRYPT
);
3965 crypto
->tkey
= gcry_malloc(hashlen
);
3967 if (!crypto
->tkey
) {
3968 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
3969 return gpg_error_from_errno(ENOMEM
);
3972 memcpy(crypto
->tkey
, crypto
->key
, hashlen
);
3973 guchar
*tkey
= crypto
->tkey
;
3976 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->tkey
, crypto
->keysize
))) {
3977 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
3981 while (iter
< (crypto
->fh
->v1
? fh_iter
: fh_iter
-1)) {
3982 if (iter_progress
> 0ULL && iter
>= iter_progress
) {
3983 if (!(iter
% iter_progress
)) {
3984 rc
= send_status(ctx
, STATUS_DECRYPT
, "%llu %llu",
3985 ++n_iter
* iter_progress
, fh_iter
);
3992 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->iv
, crypto
->blocksize
))) {
3993 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
3997 rc
= iterate_crypto_once(client
, crypto
, STATUS_DECRYPT
);
4000 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, _gpg_strerror(rc
));
4007 if (iter_progress
&& fh_iter
>= iter_progress
) {
4008 rc
= send_status(ctx
, STATUS_DECRYPT
, "%llu %llu", fh_iter
, fh_iter
);
4015 if (do_decompress(ctx
, crypto
->inbuf
, crypto
->insize
,
4016 (gpointer
*)&crypto
->outbuf
, &outsize
, &zrc
) == FALSE
) {
4017 if (zrc
== Z_MEM_ERROR
)
4018 return gpg_error_from_errno(ENOMEM
);
4020 return GPG_ERR_INV_PASSPHRASE
; // Not a valid gzip header. Must be a bad key.
4023 if (g_strncasecmp(crypto
->outbuf
, "<?xml ", 6) != 0) {
4024 gcry_free(crypto
->outbuf
);
4025 crypto
->outbuf
= NULL
;
4026 return GPG_ERR_INV_PASSPHRASE
;
4030 client
->xml
= crypto
->outbuf
;
4031 client
->len
= outsize
;
4032 crypto
->outbuf
= NULL
;
4035 *dst
= crypto
->outbuf
;
4037 crypto
->outbuf
= NULL
;
4040 /* The calling function should free the crypto struct. */