1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2006-2009 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
24 #include <sys/types.h>
44 #include "pwmd_error.h"
53 static void *z_alloc(void *data
, unsigned items
, unsigned size
)
55 return gcry_calloc(items
, size
);
58 static void z_free(void *data
, void *p
)
63 static gpg_error_t
file_modified(struct client_s
*client
)
68 if (client
->state
!= STATE_OPEN
)
71 rc
= lock_file_mutex(client
);
76 if (lstat(client
->filename
, &st
) == 0 && client
->mtime
) {
77 if (client
->mtime
!= st
.st_mtime
)
78 return EPWMD_FILE_MODIFIED
;
84 static gpg_error_t
parse_xml(assuan_context_t ctx
)
86 struct client_s
*client
= assuan_get_pointer(ctx
);
88 client
->doc
= xmlReadMemory(client
->xml
, client
->len
, NULL
, "UTF-8", XML_PARSE_NOBLANKS
);
91 return EPWMD_LIBXML_ERROR
;
96 void unlock_file_mutex(struct client_s
*client
)
98 struct file_mutex_s
*m
;
101 if (client
->has_lock
== FALSE
|| client
->pinentry
->status
!= PINENTRY_NONE
)
103 if (client
->has_lock
== FALSE
)
107 CACHE_LOCK(client
->ctx
);
109 if (cache_get_mutex(client
->md5file
, &m
) == FALSE
) {
115 MUTEX_UNLOCK(&m
->mutex
);
116 client
->has_lock
= client
->is_lock_cmd
= FALSE
;
119 gpg_error_t
lock_file_mutex(struct client_s
*client
)
121 struct file_mutex_s
*m
;
123 if (client
->has_lock
== TRUE
)
126 CACHE_LOCK(client
->ctx
);
128 if (cache_get_mutex(client
->md5file
, &m
) == FALSE
) {
135 if (pthread_mutex_trylock(&m
->mutex
) == EBUSY
) {
138 * If a client disconnects unexpectedly while waiting for a
139 * lock, this lets the thread terminate because send_status()
140 * will return an error.
142 while (pthread_mutex_trylock(&m
->mutex
) == EBUSY
) {
143 gpg_error_t rc
= send_status(client
->ctx
, STATUS_LOCKED
, NULL
);
152 MUTEX_LOCK(&m
->mutex
);
159 client
->has_lock
= TRUE
;
163 void free_client(struct client_s
*client
)
166 xmlFreeDoc(client
->doc
);
169 gcry_free(client
->xml
);
171 if (client
->filename
)
172 g_free(client
->filename
);
175 cleanup_crypto(&client
->crypto
);
178 void cleanup_client(struct client_s
*client
)
180 assuan_context_t ctx
= client
->ctx
;
181 struct client_thread_s
*thd
= client
->thd
;
182 gboolean has_lock
= client
->has_lock
;
184 struct pinentry_s
*pin
= client
->pinentry
;
187 unlock_file_mutex(client
);
188 CACHE_LOCK(client
->ctx
);
189 cache_decr_refcount(client
->md5file
);
192 * This may be a new file so don't use a cache slot. save_command() will
193 * set this to FALSE on success.
195 if (client
->new == TRUE
)
196 cache_clear(client
->md5file
, 1);
199 memset(client
, 0, sizeof(struct client_s
));
200 client
->state
= STATE_CONNECTED
;
203 client
->freed
= TRUE
;
205 client
->pinentry
= pin
;
207 client
->has_lock
= has_lock
;
211 gboolean
do_decompress(assuan_context_t ctx
, gpointer in
, gulong insize
,
212 gpointer
*out
, gulong
*outsize
, gint
*rc
)
222 z
.avail_in
= (uInt
)insize
;
223 z
.avail_out
= zlib_bufsize
;
224 z
.next_out
= pout
= gcry_malloc(zlib_bufsize
);
227 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
232 *rc
= inflateInit2(&z
, 47);
235 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, z
.msg
);
240 memset(&h
, 0, sizeof(gz_header
));
241 h
.comment
= (guchar
*)buf
;
242 h
.comm_max
= sizeof(buf
);
243 *rc
= inflateGetHeader(&z
, &h
);
246 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, z
.msg
);
252 *rc
= inflate(&z
, Z_BLOCK
);
255 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, z
.msg
);
262 insize
= (gulong
)strtol((gchar
*)h
.comment
, NULL
, 10);
267 *rc
= inflate(&z
, Z_FINISH
);
274 p
= gcry_realloc(pout
, z
.total_out
+ zlib_bufsize
);
277 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
283 z
.next_out
= pout
+ z
.total_out
;
284 z
.avail_out
= zlib_bufsize
;
285 *rc
= send_status(ctx
, STATUS_DECOMPRESS
, "%li %li",
286 z
.total_out
, insize
);
297 } while (*rc
!= Z_STREAM_END
);
299 *rc
= send_status(ctx
, STATUS_DECOMPRESS
, "%li %li", z
.total_out
,
306 *outsize
= z
.total_out
;
312 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, z
.msg
);
318 file_header_internal_t
*read_file_header(const gchar
*filename
, gboolean v1
,
323 file_header_internal_t
*fh
= g_malloc0(sizeof(file_header_internal_t
));
329 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
330 *rc
= gpg_error_from_errno(ENOMEM
);
334 fh_size
= v1
? sizeof(fh
->fh1
) : sizeof(fh
->fh2
);
336 if (lstat(filename
, &fh
->st
) == -1) {
337 *rc
= gpg_error_from_syserror();
342 if (!S_ISREG(fh
->st
.st_mode
)) {
343 *rc
= GPG_ERR_ENOANO
;
348 fd
= open(filename
, O_RDONLY
);
351 *rc
= gpg_error_from_errno(errno
);
357 len
= read(fd
, &fh
->fh1
, fh_size
);
359 len
= read(fd
, &fh
->fh2
, fh_size
);
361 if (len
!= fh_size
) {
363 *rc
= GPG_ERR_INV_LENGTH
;
373 static gpg_error_t
open_command_finalize(assuan_context_t ctx
, guchar
*key
,
376 struct client_s
*client
= assuan_get_pointer(ctx
);
381 if (!client
->crypto
->fh
) {
388 rc
= try_xml_decrypt(ctx
, key
, client
->crypto
, NULL
, NULL
);
391 cleanup_client(client
);
392 return send_error(ctx
, rc
);
396 CACHE_LOCK(client
->ctx
);
398 if (cached
== FALSE
) {
399 if (cache_update_key(client
->md5file
, key
) == FALSE
) {
400 cleanup_client(client
);
402 return send_syserror(ctx
, ENOMEM
);
405 timeout
= get_key_file_integer(client
->filename
, "cache_timeout");
406 cache_reset_timeout(client
->md5file
, timeout
);
409 cache_set_timeout(client
->md5file
, -2);
414 if (client
->crypto
->key
!= key
)
415 gcry_free(key
); // This is invokation is a pinentry callback.
420 gcry_free(client
->xml
);
425 if (client
->new == FALSE
)
426 send_status_all(STATUS_CACHE
);
428 client
->state
= STATE_OPEN
;
431 if (!rc
&& client
->new == FALSE
&&
432 client
->crypto
->fh
->fh2
.iter
!= (guint
)get_key_file_integer(client
->filename
, "iterations")) {
433 g_key_file_set_integer(keyfileh
, client
->filename
, "iterations",
434 client
->crypto
->fh
->fh2
.iter
);
435 send_status_all(STATUS_CONFIG
);
439 log_write("OPEN '%s'", client
->filename
);
441 cleanup_crypto(&client
->crypto
);
442 return send_error(ctx
, rc
);
446 static gboolean
validate_access(struct client_s
*cl
, const gchar
*filename
)
448 gchar
*access
= get_key_file_string(filename
, "tcp_access");
454 list
= g_strsplit(access
, ",", -1);
458 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
462 for (p
= list
; *p
; p
++) {
463 gboolean
not = FALSE
;
474 if (strcasecmp(cl
->thd
->tls
->fp
, fp
) == 0) {
489 static int open_command(assuan_context_t ctx
, char *line
)
491 gboolean cached
= FALSE
;
493 struct client_s
*client
= assuan_get_pointer(ctx
);
495 gchar
*filename
= NULL
;
497 if ((req
= split_input_line(line
, " ", 2)) != NULL
)
500 if (!filename
|| !*filename
) {
502 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
505 if (valid_filename(filename
) == FALSE
) {
507 return send_error(ctx
, EPWMD_INVALID_FILENAME
);
510 if (client
->state
== STATE_OPEN
)
511 cleanup_client(client
);
514 if (client
->thd
->remote
== TRUE
) {
515 if (validate_access(client
, filename
) == FALSE
) {
516 log_write(N_("client validation failed for file '%s'"), filename
);
518 return send_error(ctx
, EPWMD_FILE_ACCESS
);
523 gcry_md_hash_buffer(GCRY_MD_MD5
, client
->md5file
, filename
, strlen(filename
));
524 CACHE_LOCK(client
->ctx
);
526 if (cache_has_file(client
->md5file
) == FALSE
) {
527 if (cache_add_file(client
->md5file
, NULL
) == FALSE
) {
530 return send_syserror(ctx
, ENOMEM
);
534 cache_incr_refcount(client
->md5file
);
536 rc
= lock_file_mutex(client
);
540 return send_error(ctx
, rc
);
543 client
->freed
= FALSE
;
544 client
->crypto
= init_client_crypto();
546 if (!client
->crypto
) {
548 cleanup_client(client
);
549 return send_syserror(ctx
, ENOMEM
);
552 client
->crypto
->key
= gcry_malloc(gcrykeysize
);
554 if (!client
->crypto
->key
) {
556 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
,
557 gpg_error_from_errno(ENOMEM
));
558 cleanup_client(client
);
559 return send_syserror(ctx
, ENOMEM
);
562 memset(client
->crypto
->key
, 0, gcrykeysize
);
563 client
->crypto
->fh
= read_file_header(filename
, FALSE
, &rc
);
565 if (!client
->crypto
->fh
) {
566 if (gpg_err_code_to_errno(rc
) != ENOENT
) {
567 log_write("%s: %s", filename
, pwmd_strerror(rc
));
569 cleanup_client(client
);
570 return send_error(ctx
, rc
);
574 * New files don't need a key.
576 if ((client
->xml
= new_document()) == NULL
) {
577 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
579 cleanup_client(client
);
580 return send_syserror(ctx
, ENOMEM
);
583 client
->len
= xmlStrlen(client
->xml
);
585 client
->filename
= g_strdup(filename
);
587 if (!client
->filename
) {
589 cleanup_client(client
);
590 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
591 return send_syserror(ctx
, ENOMEM
);
594 if (req
[1] && *req
[1])
595 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, req
[1],
600 client
->pinentry
->filename
= g_strdup(client
->filename
);
602 if (!client
->pinentry
->filename
) {
603 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
604 cleanup_client(client
);
605 return send_syserror(ctx
, ENOMEM
);
608 return open_command_finalize(ctx
, client
->crypto
->key
, cached
);
611 client
->mtime
= client
->crypto
->fh
->st
.st_mtime
;
613 client
->filename
= g_strdup(filename
);
615 if (!client
->filename
) {
616 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
618 cleanup_client(client
);
619 return send_syserror(ctx
, ENOMEM
);
623 client
->pinentry
->filename
= g_strdup(client
->filename
);
625 if (!client
->pinentry
->filename
) {
626 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
628 cleanup_client(client
);
629 return send_syserror(ctx
, ENOMEM
);
633 if (client
->crypto
->fh
->fh2
.iter
<= 0)
637 if (client
->thd
->remote
== FALSE
||
638 get_key_file_boolean(client
->filename
, "tcp_require_key") == FALSE
)
641 CACHE_LOCK(client
->ctx
);
642 cached
= cache_get_key(client
->md5file
, client
->crypto
->key
);
650 if (cached
== FALSE
) {
651 gchar
*tmp
= get_key_file_string(filename
, "key_file");
655 cleanup_client(client
);
656 return send_error(ctx
, GPG_ERR_WRONG_KEY_USAGE
);
660 * No key specified and no matching filename found in the cache. Use
661 * pinentry to retrieve the key. Cannot return assuan_process_done()
662 * here otherwise the command will be interrupted. The event loop in
663 * client_thread() will poll the file descriptor waiting for it to
664 * become ready to read a pinentry_key_s which will contain the
665 * entered key or rc. It will then call open_command_finalize() to
666 * to finish the command.
668 if (!req
[1] || !*req
[1]) {
670 gboolean b
= get_key_file_boolean(filename
, "enable_pinentry");
672 /* From set_pinentry_defaults(). */
673 if (client
->pinentry
->enable
== FALSE
||
674 (client
->pinentry
->enable
== -1 && b
== FALSE
)) {
675 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
680 rc
= lock_pin_mutex(client
);
683 unlock_pin_mutex(client
->pinentry
);
684 cleanup_client(client
);
685 return send_error(ctx
, rc
);
688 client
->pinentry
->which
= PINENTRY_OPEN
;
689 rc
= pinentry_fork(ctx
);
692 unlock_pin_mutex(client
->pinentry
);
693 cleanup_client(client
);
694 return send_error(ctx
, rc
);
697 client
->pinentry
->cb
= open_command_finalize
;
698 client
->pinentry
->status
= PINENTRY_INIT
;
701 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
706 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, req
[1],
712 return open_command_finalize(ctx
, client
->crypto
->key
, cached
);
715 gboolean
do_compress(assuan_context_t ctx
, gint level
, gpointer data
,
716 gulong size
, gpointer
*out
, gulong
*outsize
, gint
*rc
)
722 gint cmd
= Z_NO_FLUSH
;
726 z
.next_in
= pin
= data
;
727 z
.avail_in
= size
< zlib_bufsize
? (uInt
)size
: (uInt
)zlib_bufsize
;
728 z
.avail_out
= (uInt
)zlib_bufsize
;
729 z
.next_out
= pout
= gcry_malloc(zlib_bufsize
);
732 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
737 *rc
= deflateInit2(&z
, level
, Z_DEFLATED
, 31, 8, Z_DEFAULT_STRATEGY
);
740 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, z
.msg
);
745 /* Rather than store the size of the uncompressed data in the file header,
746 * store it in the comment field of the gzip header. Don't give anyone too
747 * much information. Not sure why really, but it seems the right way. :)
749 memset(&h
, 0, sizeof(gz_header
));
750 g_snprintf(buf
, sizeof(buf
), "%li", size
);
751 h
.comment
= (guchar
*)buf
;
752 *rc
= deflateSetHeader(&z
, &h
);
755 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, z
.msg
);
764 *rc
= deflate(&z
, cmd
);
771 p
= gcry_realloc(pout
, z
.total_out
+ zlib_bufsize
);
774 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
780 z
.next_out
= pout
+ z
.total_out
;
781 z
.avail_out
= zlib_bufsize
;
784 if (!z
.avail_in
&& z
.total_in
< size
) {
785 if (z
.total_in
+ zlib_bufsize
> size
)
786 z
.avail_in
= size
- z
.total_in
;
788 z
.avail_in
= zlib_bufsize
;
790 *rc
= send_status(ctx
, STATUS_COMPRESS
, "%li %li",
797 if (z
.total_in
>= size
)
806 } while (*rc
!= Z_STREAM_END
);
808 *rc
= send_status(ctx
, STATUS_COMPRESS
, "%li %li", z
.total_in
, size
);
814 *outsize
= z
.total_out
;
820 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, z
.msg
);
826 #define CRYPTO_BLOCKSIZE (gcryblocksize * 1024)
828 static gpg_error_t
iterate_crypto_once(struct client_s
*client
,
829 struct client_crypto_s
*crypto
, status_msg_t which
)
832 gsize len
= CRYPTO_BLOCKSIZE
;
833 gpointer p
= gcry_malloc(len
);
838 return gpg_err_code_from_errno(ENOMEM
);
840 if (crypto
->insize
< CRYPTO_BLOCKSIZE
)
841 len
= crypto
->insize
;
844 inbuf
= crypto
->inbuf
+ total
;
847 if (len
+ total
> crypto
->insize
)
850 if (which
== STATUS_ENCRYPT
)
851 rc
= gcry_cipher_encrypt(crypto
->gh
, p
, len
, inbuf
, len
);
853 rc
= gcry_cipher_decrypt(crypto
->gh
, p
, len
, inbuf
, len
);
858 tmp
= crypto
->inbuf
+total
;
859 memmove(tmp
, p
, len
);
862 if (total
>= crypto
->insize
)
865 pthread_testcancel();
873 /* The crypto struct must be setup for iterations and .key. */
874 gpg_error_t
do_xml_encrypt(struct client_s
*client
,
875 struct client_crypto_s
*crypto
, const gchar
*filename
)
877 gsize len
= crypto
->insize
;
881 guint iter_progress
= 0, n_iter
= 0, xiter
= 0;
882 gchar tmp
[FILENAME_MAX
];
886 if (!crypto
->fh
->fh2
.iter
) {
888 * cache_file_count() needs both .used == TRUE and a valid key in
889 * order for it to count as a used cache entry. Fixes CACHE status
892 memset(crypto
->key
, '!', gcrykeysize
);
897 * Resize the existing xml buffer to the block size required by gcrypt
898 * rather than duplicating it and wasting memory.
900 if (crypto
->insize
/ gcryblocksize
) {
901 len
= (crypto
->insize
/ gcryblocksize
) * gcryblocksize
;
903 if (crypto
->insize
% gcryblocksize
)
904 len
+= gcryblocksize
;
907 inbuf
= gcry_realloc(crypto
->inbuf
, len
);
910 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
911 return gpg_error_from_errno(ENOMEM
);
914 crypto
->inbuf
= inbuf
;
915 crypto
->insize
= len
;
916 gcry_create_nonce(crypto
->fh
->fh2
.iv
, sizeof(crypto
->fh
->fh2
.iv
));
917 crypto
->tkey
= gcry_malloc(gcrykeysize
);
920 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
921 return gpg_error_from_errno(ENOMEM
);
924 memcpy(crypto
->tkey
, crypto
->key
, gcrykeysize
);
925 guchar
*tkey
= crypto
->tkey
;
928 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->tkey
, gcrykeysize
))) {
929 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(rc
));
933 iter_progress
= get_key_file_integer(client
? client
->filename
: "global",
934 "iteration_progress");
936 if (iter_progress
&& crypto
->fh
->fh2
.iter
>= iter_progress
) {
937 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
938 "%u %u", 0, crypto
->fh
->fh2
.iter
);
944 while (xiter
< crypto
->fh
->fh2
.iter
-1) {
945 if (iter_progress
> 0 && xiter
>= iter_progress
) {
946 if (!(xiter
% iter_progress
)) {
947 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
948 "%u %u", ++n_iter
* iter_progress
, crypto
->fh
->fh2
.iter
);
955 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->fh
->fh2
.iv
,
956 sizeof(crypto
->fh
->fh2
.iv
)))) {
957 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(rc
));
961 rc
= iterate_crypto_once(client
, crypto
, STATUS_ENCRYPT
);
964 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(rc
));
971 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->fh
->fh2
.iv
,
972 sizeof(crypto
->fh
->fh2
.iv
)))) {
973 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(rc
));
977 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->key
, gcrykeysize
))) {
978 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(rc
));
982 rc
= iterate_crypto_once(client
, crypto
, STATUS_ENCRYPT
);
987 if (iter_progress
&& crypto
->fh
->fh2
.iter
>= iter_progress
) {
988 rc
= send_status(client
? client
->ctx
: NULL
, STATUS_ENCRYPT
,
989 "%u %u", crypto
->fh
->fh2
.iter
, crypto
->fh
->fh2
.iter
);
997 if (!client
&& !strcmp(filename
, "-")) {
998 crypto
->fh
->fd
= STDOUT_FILENO
;
1002 if (lstat(filename
, &st
) == 0) {
1003 mode
= st
.st_mode
& (S_IRWXU
|S_IRWXG
|S_IRWXO
);
1006 * FIXME What if the file has an ACL?
1008 if (!(mode
& S_IWUSR
))
1009 return gpg_error_from_errno(EACCES
);
1012 if (errno
!= ENOENT
)
1013 return gpg_error_from_errno(errno
);
1016 g_snprintf(tmp
, sizeof(tmp
), "%s.XXXXXX", filename
);
1017 crypto
->fh
->fd
= mkstemp(tmp
);
1019 if (crypto
->fh
->fd
== -1) {
1021 p
= strrchr(tmp
, '/');
1023 log_write("%s: %s", p
, strerror(rc
));
1024 return gpg_error_from_errno(rc
);
1029 * xml_import() or convert_file() from command line.
1031 crypto
->fh
->fd
= STDOUT_FILENO
;
1034 crypto
->fh
->fh2
.version
= VERSION_HEX
;
1035 len
= write(crypto
->fh
->fd
, &crypto
->fh
->fh2
, sizeof(crypto
->fh
->fh2
));
1037 if (len
!= sizeof(crypto
->fh
->fh2
)) {
1040 if (filename
&& strcmp(filename
, "-"))
1043 return gpg_error_from_errno(len
);
1046 len
= write(crypto
->fh
->fd
, crypto
->inbuf
, crypto
->insize
);
1048 if (len
!= crypto
->insize
) {
1051 if (filename
&& strcmp(filename
, "-"))
1054 return gpg_error_from_errno(len
);
1057 if (fsync(crypto
->fh
->fd
) == -1) {
1060 if (filename
&& strcmp(filename
, "-"))
1063 return gpg_error_from_errno(len
);
1066 if (filename
&& strcmp(filename
, "-")) {
1067 if (mode
&& get_key_file_boolean(filename
, "backup") == TRUE
) {
1068 gchar tmp2
[FILENAME_MAX
];
1070 g_snprintf(tmp2
, sizeof(tmp2
), "%s.backup", filename
);
1072 if (rename(filename
, tmp2
) == -1) {
1075 return gpg_error_from_errno(len
);
1079 if (rename(tmp
, filename
) == -1) {
1082 return gpg_error_from_errno(len
);
1086 chmod(filename
, mode
);
1089 if (client
&& lstat(filename
, &st
) == 0)
1090 client
->mtime
= st
.st_mtime
;
1095 static gpg_error_t
save_command_finalize(assuan_context_t ctx
, guchar
*key
,
1098 struct client_s
*client
= assuan_get_pointer(ctx
);
1100 gulong len
, outsize
= 0;
1107 if (client
->crypto
->key
&& client
->crypto
->key
!= key
)
1108 gcry_free(client
->crypto
->key
);
1110 client
->crypto
->key
= key
;
1111 xmlDocDumpFormatMemory(client
->doc
, (xmlChar
**)&xmlbuf
, (gint
*)&len
, 0);
1112 iter
= (guint
)get_key_file_integer(client
->filename
, "compression_level");
1117 if (do_compress(ctx
, (gint
)iter
, xmlbuf
, len
, &outbuf
, &outsize
, &zrc
)
1119 if (key
!= client
->crypto
->key
)
1123 cleanup_crypto(&client
->crypto
);
1125 if (zrc
== Z_MEM_ERROR
)
1126 return send_syserror(ctx
, ENOMEM
);
1128 return send_error(ctx
, GPG_ERR_COMPR_ALGO
);
1136 client
->crypto
->fh
= g_malloc0(sizeof(file_header_internal_t
));
1138 if (!client
->crypto
->fh
) {
1139 cleanup_crypto(&client
->crypto
);
1141 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1142 return send_syserror(ctx
, ENOMEM
);
1145 iter
= get_key_file_integer(client
->filename
, "iterations");
1146 client
->crypto
->fh
->fh2
.iter
= iter
< 0 ? 0 : iter
;
1147 client
->crypto
->inbuf
= xmlbuf
;
1148 client
->crypto
->insize
= len
;
1149 rc
= do_xml_encrypt(client
, client
->crypto
, client
->filename
);
1152 cleanup_crypto(&client
->crypto
);
1153 return send_error(ctx
, rc
);
1156 timeout
= get_key_file_integer(client
->filename
, "cache_timeout");
1157 CACHE_LOCK(client
->ctx
);
1160 cache_reset_timeout(client
->md5file
, timeout
);
1163 if (client
->new == TRUE
)
1164 send_status_all(STATUS_CACHE
);
1166 client
->new = FALSE
;
1167 cleanup_crypto(&client
->crypto
);
1168 return send_error(ctx
, 0);
1171 if (cache_update_key(client
->md5file
, client
->crypto
->key
) == FALSE
) {
1173 cleanup_crypto(&client
->crypto
);
1174 return send_syserror(ctx
, ENOMEM
);
1177 client
->new = FALSE
;
1178 cache_reset_timeout(client
->md5file
, timeout
);
1180 send_status_all(STATUS_CACHE
);
1181 cleanup_crypto(&client
->crypto
);
1182 return send_error(ctx
, 0);
1185 static int save_command(assuan_context_t ctx
, char *line
)
1187 gboolean cached
= FALSE
;
1189 struct client_s
*client
= assuan_get_pointer(ctx
);
1192 rc
= lock_file_mutex(client
);
1195 return send_error(ctx
, rc
);
1197 rc
= file_modified(client
);
1200 return send_error(ctx
, rc
);
1202 if (lstat(client
->filename
, &st
) == -1 && errno
!= ENOENT
)
1203 return send_syserror(ctx
, errno
);
1205 if (errno
!= ENOENT
&& !S_ISREG(st
.st_mode
)) {
1206 log_write("%s: %s", client
->filename
, pwmd_strerror(GPG_ERR_ENOANO
));
1207 return send_error(ctx
, GPG_ERR_ENOANO
);
1211 cached
= cache_iscached(client
->md5file
);
1215 * If a cache entry doesn't exist for this file and the file has a
1216 * "key_file" or "key" parameter, then it's an error. The reason is that
1217 * cache expiration would be useless.
1219 if (cached
== FALSE
) {
1220 gchar
*tmp
= get_key_file_string(client
->filename
, "key_file");
1224 return send_error(ctx
, GPG_ERR_WRONG_KEY_USAGE
);
1229 client
->crypto
= init_client_crypto();
1231 if (!client
->crypto
) {
1232 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1233 return send_syserror(ctx
, ENOMEM
);
1236 client
->crypto
->key
= gcry_malloc(gcrykeysize
);
1238 if (!client
->crypto
->key
) {
1239 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1240 cleanup_crypto(&client
->crypto
);
1241 return send_syserror(ctx
, ENOMEM
);
1244 memset(client
->crypto
->key
, '!', gcrykeysize
);
1246 if (get_key_file_integer(client
->filename
, "iterations") <= 0)
1249 if (!line
|| !*line
) {
1250 client
->crypto
->tkey
= gcry_malloc(gcrykeysize
);
1252 if (!client
->crypto
->tkey
) {
1253 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1254 cleanup_crypto(&client
->crypto
);
1255 return send_syserror(ctx
, ENOMEM
);
1258 memset(client
->crypto
->tkey
, '!', gcrykeysize
);
1261 if (cache_get_key(client
->md5file
, client
->crypto
->key
) == FALSE
||
1262 memcmp(client
->crypto
->key
, client
->crypto
->tkey
,
1263 gcrykeysize
) == 0) {
1266 #ifdef WITH_PINENTRY
1267 if (client
->pinentry
->enable
== FALSE
||
1268 get_key_file_boolean(client
->filename
, "enable_pinentry") == FALSE
) {
1269 /* Empty keys are allowed. */
1270 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
1274 lock_pin_mutex(client
);
1275 client
->pinentry
->which
= PINENTRY_SAVE
;
1276 rc
= pinentry_fork(ctx
);
1279 unlock_pin_mutex(client
->pinentry
);
1280 return send_error(ctx
, rc
);
1283 client
->pinentry
->cb
= save_command_finalize
;
1284 client
->pinentry
->status
= PINENTRY_INIT
;
1287 /* Empty keys are allowed. */
1288 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, "", 1);
1298 gcry_md_hash_buffer(GCRY_MD_SHA256
, client
->crypto
->key
, line
,
1300 memset(line
, 0, strlen(line
));
1304 return save_command_finalize(ctx
, client
->crypto
->key
, cached
);
1307 static int delete_command(assuan_context_t ctx
, char *line
)
1309 struct client_s
*client
= assuan_get_pointer(ctx
);
1314 rc
= file_modified(client
);
1317 return send_error(ctx
, rc
);
1319 if (strchr(line
, '\t'))
1320 req
= split_input_line(line
, "\t", -1);
1322 req
= split_input_line(line
, " ", -1);
1325 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
1327 n
= find_account(client
->doc
, &req
, &rc
, NULL
, 0);
1331 return send_error(ctx
, rc
);
1335 * No sub-node defined. Remove the entire node (account).
1344 return send_error(ctx
, 0);
1347 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
1351 return send_error(ctx
, rc
);
1358 return send_error(ctx
, 0);
1362 * Don't return with assuan_process_done() here. This has been called from
1363 * assuan_process_next() and the command should be finished in
1366 static int store_command_finalize(gpointer data
, gint assuan_rc
, guchar
*line
,
1369 assuan_context_t ctx
= data
;
1370 struct client_s
*client
= assuan_get_pointer(ctx
);
1373 gpg_error_t rc
= file_modified(client
);
1375 if (assuan_rc
|| rc
) {
1378 return assuan_rc
? assuan_rc
: rc
;
1381 req
= split_input_line((gchar
*)line
, "\t", 0);
1385 return EPWMD_COMMAND_SYNTAX
;
1387 if (valid_xml_element((xmlChar
*)*req
) == FALSE
) {
1389 return EPWMD_INVALID_ELEMENT
;
1392 if (valid_element_path(req
+1, TRUE
) == FALSE
) {
1394 return EPWMD_INVALID_ELEMENT
;
1398 n
= find_account(client
->doc
, &req
, &rc
, NULL
, 0);
1400 if (rc
&& rc
== EPWMD_ELEMENT_NOT_FOUND
) {
1401 rc
= new_account(client
->doc
, *req
);
1418 create_elements_cb(n
, req
+1, &rc
, NULL
);
1420 find_elements(client
->doc
, n
->children
, req
+1, &rc
,
1421 NULL
, NULL
, create_elements_cb
, FALSE
, 0, NULL
);
1425 client
->inquire_status
= INQUIRE_DONE
;
1429 static int store_command(assuan_context_t ctx
, char *line
)
1431 struct client_s
*client
= assuan_get_pointer(ctx
);
1432 gpg_error_t rc
= file_modified(client
);
1435 return send_error(ctx
, rc
);
1437 rc
= assuan_inquire_ext(ctx
, "STORE", 0, store_command_finalize
, ctx
);
1440 return send_error(ctx
, rc
);
1442 /* Don't return with assuan_process_done() here. This is an INQUIRE. */
1443 client
->inquire_status
= INQUIRE_BUSY
;
1447 static int get_command(assuan_context_t ctx
, char *line
)
1449 struct client_s
*client
= assuan_get_pointer(ctx
);
1454 rc
= file_modified(client
);
1457 return send_error(ctx
, rc
);
1459 req
= split_input_line(line
, "\t", -1);
1461 if (!req
|| !*req
) {
1463 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
1466 n
= find_account(client
->doc
, &req
, &rc
, NULL
, 0);
1470 return send_error(ctx
, rc
);
1474 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
1479 return send_error(ctx
, rc
);
1481 if (!n
|| !n
->children
)
1482 return send_error(ctx
, EPWMD_EMPTY_ELEMENT
);
1484 n
= find_text_node(n
->children
);
1486 if (!n
|| !n
->content
|| !*n
->content
)
1487 return send_error(ctx
, EPWMD_EMPTY_ELEMENT
);
1489 rc
= assuan_send_data(ctx
, n
->content
, xmlStrlen(n
->content
));
1490 return send_error(ctx
, rc
);
1493 static xmlNodePtr
realpath_elements_cb(xmlNodePtr node
, gchar
**target
,
1494 gpg_error_t
*rc
, gchar
**req_orig
, void *data
)
1496 gchar
*path
= *(gchar
**)data
;
1497 gchar
*tmp
= NULL
, *result
;
1501 *(gchar
**)data
= NULL
;
1504 path
= g_strjoinv("\t", target
);
1507 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1508 *rc
= gpg_error_from_errno(ENOMEM
);
1513 tmp
= g_strjoinv("\t", req_orig
);
1517 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1518 *rc
= gpg_error_from_errno(ENOMEM
);
1524 result
= g_strdup_printf("%s\t%s", path
, tmp
);
1526 result
= g_strdup(path
);
1529 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1530 *rc
= gpg_error_from_errno(ENOMEM
);
1538 *(gchar
**)data
= result
;
1542 static int realpath_command(assuan_context_t ctx
, char *line
)
1545 struct client_s
*client
= assuan_get_pointer(ctx
);
1553 rc
= file_modified(client
);
1556 return send_error(ctx
, rc
);
1558 if (strchr(line
, '\t') != NULL
) {
1559 if ((req
= split_input_line(line
, "\t", 0)) == NULL
)
1560 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
1563 if ((req
= split_input_line(line
, " ", 0)) == NULL
)
1564 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
1567 n
= find_account(client
->doc
, &req
, &rc
, NULL
, 0);
1571 return send_error(ctx
, rc
);
1574 rp
= g_strjoinv("\t", req
);
1578 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1579 return send_syserror(ctx
, ENOMEM
);
1583 n
= find_elements(client
->doc
, n
->children
, req
+1, &rc
,
1584 NULL
, realpath_elements_cb
, NULL
, FALSE
, 0, &rp
);
1589 return send_error(ctx
, rc
);
1593 string
= g_string_new(rp
);
1598 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1599 return send_syserror(ctx
, ENOMEM
);
1603 for (i
= 0, t
= string
->str
+ i
; *t
; t
++, i
++) {
1604 if ((!i
&& *t
!= '!') || (*t
== '\t' && *(t
+1) && *(t
+1) != '!')) {
1605 string
= g_string_insert_c(string
, !i
? i
++ : ++i
, '!');
1610 rc
= assuan_send_data(ctx
, string
->str
, string
->len
);
1611 g_string_free(string
, TRUE
);
1612 return send_error(ctx
, rc
);
1615 static int list_command(assuan_context_t ctx
, char *line
)
1617 struct client_s
*client
= assuan_get_pointer(ctx
);
1619 struct element_list_s
*elements
= NULL
;
1622 if (disable_list_and_dump
== TRUE
)
1623 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
1625 rc
= file_modified(client
);
1628 return send_error(ctx
, rc
);
1633 rc
= list_accounts(client
->doc
, &str
);
1636 return send_error(ctx
, rc
);
1638 rc
= assuan_send_data(ctx
, str
->str
, str
->len
);
1639 g_string_free(str
, TRUE
);
1640 return send_error(ctx
, rc
);
1643 elements
= g_malloc0(sizeof(struct element_list_s
));
1646 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1647 rc
= gpg_err_code_from_errno(ENOMEM
);
1651 rc
= create_path_list(client
->doc
, elements
, line
);
1657 gint total
= g_slist_length(elements
->list
);
1662 rc
= EPWMD_EMPTY_ELEMENT
;
1666 str
= g_string_new(NULL
);
1669 rc
= gpg_err_code_from_errno(ENOMEM
);
1670 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1674 for (i
= 0; i
< total
; i
++) {
1675 tmp
= g_slist_nth_data(elements
->list
, i
);
1676 g_string_append_printf(str
, "%s%s", tmp
, i
+1 == total
? "" : "\n");
1679 rc
= assuan_send_data(ctx
, str
->str
, str
->len
);
1680 g_string_free(str
, TRUE
);
1683 rc
= EPWMD_EMPTY_ELEMENT
;
1687 gint total
= g_slist_length(elements
->list
);
1690 for (i
= 0; i
< total
; i
++) {
1691 tmp
= g_slist_nth_data(elements
->list
, i
);
1695 g_slist_free(elements
->list
);
1697 if (elements
->prefix
)
1698 g_free(elements
->prefix
);
1703 return send_error(ctx
, rc
);
1706 static gpg_error_t
add_attribute(xmlNodePtr node
, const gchar
*name
,
1711 if ((a
= xmlHasProp(node
, (xmlChar
*)name
)) == NULL
) {
1712 a
= xmlNewProp(node
, (xmlChar
*)name
, (xmlChar
*)value
);
1715 return EPWMD_LIBXML_ERROR
;
1718 xmlNodeSetContent(a
->children
, (xmlChar
*)value
);
1724 * req[0] - element path
1726 static int attribute_list(assuan_context_t ctx
, gchar
**req
)
1728 struct client_s
*client
= assuan_get_pointer(ctx
);
1729 gchar
**attrlist
= NULL
;
1731 gchar
**path
= NULL
;
1737 if (!req
|| !req
[0])
1738 return EPWMD_COMMAND_SYNTAX
;
1740 if ((path
= split_input_line(req
[0], "\t", 0)) == NULL
) {
1742 * The first argument may be only an account.
1744 if ((path
= split_input_line(req
[0], " ", 0)) == NULL
)
1745 return EPWMD_COMMAND_SYNTAX
;
1748 n
= find_account(client
->doc
, &path
, &rc
, NULL
, 0);
1756 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
1757 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
1767 for (a
= n
->properties
; a
; a
= a
->next
) {
1770 if ((pa
= g_realloc(attrlist
, (i
+ 2) * sizeof(gchar
*))) == NULL
) {
1772 g_strfreev(attrlist
);
1774 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1775 return gpg_error_from_errno(ENOMEM
);
1780 attrlist
[i
] = g_strdup_printf("%s %s", (gchar
*)a
->name
, (gchar
*)an
->content
);
1783 g_strfreev(attrlist
);
1784 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1785 return gpg_error_from_errno(ENOMEM
);
1788 attrlist
[++i
] = NULL
;
1792 return EPWMD_EMPTY_ELEMENT
;
1794 line
= g_strjoinv("\n", attrlist
);
1797 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1798 g_strfreev(attrlist
);
1799 return gpg_error_from_errno(ENOMEM
);
1802 rc
= assuan_send_data(ctx
, line
, strlen(line
));
1804 g_strfreev(attrlist
);
1809 * req[0] - attribute
1810 * req[1] - element path
1812 static int attribute_delete(struct client_s
*client
, gchar
**req
)
1816 gchar
**path
= NULL
;
1819 if (!req
|| !req
[0] || !req
[1])
1820 return EPWMD_COMMAND_SYNTAX
;
1822 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
) {
1824 * The first argument may be only an account.
1826 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
1827 return EPWMD_COMMAND_SYNTAX
;
1831 * Don't remove the "name" attribute for the account element. To remove an
1832 * account use DELETE <account>.
1834 if (!path
[1] && xmlStrEqual((xmlChar
*)req
[0], (xmlChar
*)"name")) {
1835 rc
= EPWMD_ATTR_SYNTAX
;
1839 n
= find_account(client
->doc
, &path
, &rc
, NULL
, 0);
1845 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
1846 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
1854 if ((a
= xmlHasProp(n
, (xmlChar
*)req
[0])) == NULL
)
1855 return EPWMD_ATTR_NOT_FOUND
;
1857 if (xmlRemoveProp(a
) == -1)
1858 return EPWMD_LIBXML_ERROR
;
1867 static xmlNodePtr
create_element_path(struct client_s
*client
, gchar
***path
,
1870 gchar
**src
= *path
;
1871 gchar
**src_orig
= g_strdupv(src
);
1872 xmlNodePtr n
= NULL
;
1877 *rc
= gpg_error_from_errno(ENOMEM
);
1878 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
1883 n
= find_account(client
->doc
, &src
, rc
, NULL
, 0);
1886 if (*rc
== EPWMD_ELEMENT_NOT_FOUND
) {
1887 *rc
= new_account(client
->doc
, src
[0]);
1900 n
= create_target_elements_cb(n
, src
+1, rc
, NULL
);
1902 n
= find_elements(client
->doc
, n
->children
, src
+1, rc
,
1903 NULL
, NULL
, create_target_elements_cb
, FALSE
, 0, NULL
);
1909 * Reset the position of the element tree now that the elements
1910 * have been created.
1915 n
= find_account(client
->doc
, &src
, rc
, NULL
, 0);
1920 n
= find_elements(client
->doc
, n
->children
, src
+1, rc
,
1921 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
1929 g_strfreev(src_orig
);
1936 * Creates a "target" attribute. When other commands encounter an element with
1937 * this attribute, the element path is modified to the target value. If the
1938 * source element path doesn't exist when using 'ATTR SET target', it is
1939 * created, but the destination element path must exist.
1941 * req[0] - source element path
1942 * req[1] - destination element path
1944 static gpg_error_t
target_attribute(struct client_s
*client
, gchar
**req
)
1946 gchar
**src
, **dst
, *line
= NULL
;
1950 if (!req
|| !req
[0] || !req
[1])
1951 return EPWMD_COMMAND_SYNTAX
;
1953 if ((src
= split_input_line(req
[0], "\t", 0)) == NULL
) {
1955 * The first argument may be only an account.
1957 if ((src
= split_input_line(req
[0], " ", 0)) == NULL
)
1958 return EPWMD_COMMAND_SYNTAX
;
1961 if (valid_element_path(src
, FALSE
) == FALSE
) {
1963 return EPWMD_INVALID_ELEMENT
;
1966 if ((dst
= split_input_line(req
[1], "\t", 0)) == NULL
) {
1968 * The first argument may be only an account.
1970 if ((dst
= split_input_line(req
[1], " ", 0)) == NULL
) {
1971 rc
= EPWMD_COMMAND_SYNTAX
;
1976 n
= find_account(client
->doc
, &dst
, &rc
, NULL
, 0);
1979 * Make sure the destination element path exists.
1985 n
= find_elements(client
->doc
, n
->children
, dst
+1, &rc
,
1986 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
1992 n
= create_element_path(client
, &src
, &rc
);
1997 line
= g_strjoinv("\t", dst
);
2000 rc
= gpg_error_from_errno(ENOMEM
);
2001 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2005 rc
= add_attribute(n
, "target", line
);
2015 * req[0] - account name
2018 static gpg_error_t
name_attribute(struct client_s
*client
, gchar
**req
)
2024 tmp
= g_strdupv(req
);
2027 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2028 return gpg_error_from_errno(ENOMEM
);
2031 n
= find_account(client
->doc
, &tmp
, &rc
, NULL
, 0);
2037 if (g_utf8_collate(req
[0], req
[1]) == 0)
2041 * Will not overwrite an existing account.
2043 tmp
= g_strdupv(req
+1);
2046 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2047 return gpg_error_from_errno(ENOMEM
);
2050 n
= find_account(client
->doc
, &tmp
, &rc
, NULL
, 0);
2053 if (rc
&& rc
!= EPWMD_ELEMENT_NOT_FOUND
)
2057 return EPWMD_ACCOUNT_EXISTS
;
2060 * Whitespace not allowed in account names.
2062 if (contains_whitespace(req
[1]) == TRUE
)
2063 return EPWMD_ATTR_SYNTAX
;
2065 tmp
= g_strdupv(req
);
2068 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2069 return gpg_error_from_errno(ENOMEM
);
2072 n
= find_account(client
->doc
, &tmp
, &rc
, NULL
, 0);
2076 return EPWMD_ELEMENT_NOT_FOUND
;
2078 return add_attribute(n
, "name", req
[1]);
2082 * req[0] - attribute
2083 * req[1] - element path
2085 static int attribute_get(assuan_context_t ctx
, gchar
**req
)
2087 struct client_s
*client
= assuan_get_pointer(ctx
);
2093 if (!req
|| !req
[0] || !req
[1])
2094 return EPWMD_COMMAND_SYNTAX
;
2096 if (strchr(req
[1], '\t')) {
2097 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
)
2098 return EPWMD_COMMAND_SYNTAX
;
2101 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
2102 return EPWMD_COMMAND_SYNTAX
;
2105 n
= find_account(client
->doc
, &path
, &rc
, NULL
, 0);
2111 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2112 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
2120 if ((a
= xmlGetProp(n
, (xmlChar
*)req
[0])) == NULL
)
2121 return EPWMD_ATTR_NOT_FOUND
;
2123 rc
= assuan_send_data(ctx
, a
, xmlStrlen(a
));
2133 * req[0] - attribute
2134 * req[1] - element path
2137 static int attribute_set(struct client_s
*client
, gchar
**req
)
2139 gchar
**path
= NULL
;
2143 if (!req
|| !req
[0] || !req
[1] || !req
[2])
2144 return EPWMD_COMMAND_SYNTAX
;
2147 * Reserved attribute names.
2149 if (g_utf8_collate(req
[0], "name") == 0) {
2151 * Only reserved for the account element. Not the rest of the
2154 if (strchr(req
[1], '\t') == NULL
)
2155 return name_attribute(client
, req
+ 1);
2157 else if (g_utf8_collate(req
[0], "target") == 0)
2158 return target_attribute(client
, req
+ 1);
2160 if ((path
= split_input_line(req
[1], "\t", 0)) == NULL
) {
2162 * The first argument may be only an account.
2164 if ((path
= split_input_line(req
[1], " ", 0)) == NULL
)
2165 return EPWMD_COMMAND_SYNTAX
;
2168 n
= find_account(client
->doc
, &path
, &rc
, NULL
, 0);
2174 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
,
2175 NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
2182 return add_attribute(n
, req
[0], req
[2]);
2191 * req[1] - attribute name or element path if command is LIST
2192 * req[2] - element path
2193 * req[2] - element path or value
2195 static int attr_command(assuan_context_t ctx
, char *line
)
2197 struct client_s
*client
= assuan_get_pointer(ctx
);
2201 rc
= file_modified(client
);
2204 return send_error(ctx
, rc
);
2206 req
= split_input_line(line
, " ", 4);
2208 if (!req
|| !req
[0] || !req
[1]) {
2210 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
2213 if (g_ascii_strcasecmp(req
[0], "SET") == 0)
2214 rc
= attribute_set(client
, req
+1);
2215 else if (g_ascii_strcasecmp(req
[0], "GET") == 0)
2216 rc
= attribute_get(ctx
, req
+1);
2217 else if (g_ascii_strcasecmp(req
[0], "DELETE") == 0)
2218 rc
= attribute_delete(client
, req
+1);
2219 else if (g_ascii_strcasecmp(req
[0], "LIST") == 0)
2220 rc
= attribute_list(ctx
, req
+1);
2222 rc
= EPWMD_COMMAND_SYNTAX
;
2225 return send_error(ctx
, rc
);
2228 static int iscached_command(assuan_context_t ctx
, char *line
)
2230 gchar
**req
= split_input_line(line
, " ", 0);
2233 if (!req
|| !*req
) {
2235 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
2238 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2242 if (cache_iscached(md5file
) == FALSE
) {
2244 return send_error(ctx
, EPWMD_CACHE_NOT_FOUND
);
2248 return send_error(ctx
, 0);
2251 static int clearcache_command(assuan_context_t ctx
, char *line
)
2253 struct client_s
*client
= assuan_get_pointer(ctx
);
2254 gchar
**req
= split_input_line(line
, " ", 0);
2259 if (!req
|| !*req
) {
2261 cache_clear(client
->md5file
, 2);
2263 return send_error(ctx
, 0);
2266 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[0], strlen(req
[0]));
2269 if (cache_clear(md5file
, 1) == FALSE
) {
2271 return send_error(ctx
, EPWMD_CACHE_NOT_FOUND
);
2275 return send_error(ctx
, 0);
2278 static int cachetimeout_command(assuan_context_t ctx
, char *line
)
2282 gchar
**req
= split_input_line(line
, " ", 0);
2284 struct client_s
*client
= assuan_get_pointer(ctx
);
2286 if (!req
|| !*req
|| !req
[1]) {
2288 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
2292 timeout
= strtol(req
[0], &p
, 10);
2294 if (errno
!= 0 || *p
!= 0) {
2296 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
2299 gcry_md_hash_buffer(GCRY_MD_MD5
, md5file
, req
[1], strlen(req
[1]));
2301 CACHE_LOCK(client
->ctx
);
2303 if (cache_set_timeout(md5file
, timeout
) == FALSE
) {
2305 return send_error(ctx
, EPWMD_CACHE_NOT_FOUND
);
2309 return send_error(ctx
, 0);
2312 static int dump_command(assuan_context_t ctx
, char *line
)
2316 struct client_s
*client
= assuan_get_pointer(ctx
);
2319 if (disable_list_and_dump
== TRUE
)
2320 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2322 rc
= file_modified(client
);
2325 return send_error(ctx
, rc
);
2327 xmlDocDumpFormatMemory(client
->doc
, &xml
, &len
, 1);
2330 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2331 return send_syserror(ctx
, ENOMEM
);
2334 rc
= assuan_send_data(ctx
, xml
, len
);
2336 return send_error(ctx
, rc
);
2339 static int getconfig_command(assuan_context_t ctx
, gchar
*line
)
2341 struct client_s
*client
= assuan_get_pointer(ctx
);
2343 gchar filename
[255]={0}, param
[747]={0};
2344 gchar
*p
, *tmp
, *fp
= client
->filename
, *paramp
= line
;
2346 if (strchr(line
, ' ')) {
2347 sscanf(line
, " %254[^ ] %746c", filename
, param
);
2352 if (fp
&& !valid_filename(fp
))
2353 return send_error(ctx
, EPWMD_INVALID_FILENAME
);
2355 paramp
= g_ascii_strdown(paramp
, -1);
2358 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2359 return send_syserror(ctx
, ENOMEM
);
2362 p
= get_key_file_string(fp
? fp
: "global", paramp
);
2366 return send_error(ctx
, GPG_ERR_NO_VALUE
);
2368 tmp
= expand_homedir(p
);
2372 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2373 return send_syserror(ctx
, ENOMEM
);
2377 rc
= assuan_send_data(ctx
, p
, strlen(p
));
2379 return send_error(ctx
, rc
);
2382 static int xpath_command(assuan_context_t ctx
, gchar
*line
)
2384 struct client_s
*client
= assuan_get_pointer(ctx
);
2386 xmlXPathContextPtr xp
;
2387 xmlXPathObjectPtr result
;
2388 xmlBufferPtr buf
= NULL
;
2391 if (disable_list_and_dump
== TRUE
)
2392 return send_error(ctx
, GPG_ERR_NOT_IMPLEMENTED
);
2394 rc
= file_modified(client
);
2397 return send_error(ctx
, rc
);
2399 if (!line
|| !*line
)
2400 return send_error(ctx
, EPWMD_COMMAND_SYNTAX
);
2402 if ((req
= split_input_line(line
, "\t", 2)) == NULL
) {
2403 if (strv_printf(&req
, "%s", line
) == FALSE
)
2404 return send_syserror(ctx
, ENOMEM
);
2407 xp
= xmlXPathNewContext(client
->doc
);
2410 return send_error(ctx
, EPWMD_LIBXML_ERROR
);
2412 result
= xmlXPathEvalExpression((xmlChar
*)req
[0], xp
);
2415 xmlXPathFreeContext(xp
);
2416 return send_error(ctx
, EPWMD_LIBXML_ERROR
);
2419 if (xmlXPathNodeSetIsEmpty(result
->nodesetval
)) {
2420 rc
= EPWMD_EMPTY_ELEMENT
;
2424 rc
= recurse_xpath_nodeset(client
->doc
, result
->nodesetval
,
2425 (xmlChar
*)req
[1], &buf
);
2429 else if (!req
[1] && !xmlBufferLength(buf
)) {
2430 rc
= EPWMD_EMPTY_ELEMENT
;
2436 rc
= assuan_send_data(ctx
, xmlBufferContent(buf
), xmlBufferLength(buf
));
2445 xmlXPathFreeObject(result
);
2448 xmlXPathFreeContext(xp
);
2450 return send_error(ctx
, rc
);
2453 static int import_command_finalize(gpointer data
, gint assuan_rc
, guchar
*line
,
2456 struct client_s
*client
= assuan_get_pointer((assuan_context_t
)data
);
2457 gpg_error_t rc
= file_modified(client
);
2458 gchar
**req
, **path
= NULL
, **path_orig
= NULL
, *content
;
2460 xmlNodePtr n
, root
, copy
;
2462 if (assuan_rc
|| rc
) {
2465 return assuan_rc
? assuan_rc
: rc
;
2468 req
= split_input_line((gchar
*)line
, " ", 2);
2472 return EPWMD_COMMAND_SYNTAX
;
2474 if ((path
= split_input_line(req
[0], "\t", 0)) == NULL
) {
2475 if ((path
= split_input_line(req
[0], " ", 0)) == NULL
)
2476 return EPWMD_COMMAND_SYNTAX
;
2481 if (!content
|| !*content
) {
2482 rc
= EPWMD_COMMAND_SYNTAX
;
2486 if (valid_xml_element((xmlChar
*)*path
) == FALSE
) {
2487 rc
= EPWMD_INVALID_ELEMENT
;
2491 if (valid_element_path(path
+1, FALSE
) == FALSE
) {
2492 rc
= EPWMD_INVALID_ELEMENT
;
2496 doc
= xmlReadDoc((xmlChar
*)content
, NULL
, "UTF-8", XML_PARSE_NOBLANKS
);
2499 rc
= EPWMD_LIBXML_ERROR
;
2503 root
= xmlDocGetRootElement(doc
);
2504 path_orig
= g_strdupv(path
);
2508 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2509 rc
= gpg_error_from_errno(ENOMEM
);
2513 if (strv_printf(&path
, "%s", (gchar
*)root
->name
) == FALSE
) {
2514 g_strfreev(path_orig
);
2516 rc
= gpg_error_from_errno(ENOMEM
);
2520 n
= find_account(client
->doc
, &path
, &rc
, NULL
, 0);
2522 if (rc
&& rc
!= EPWMD_ELEMENT_NOT_FOUND
) {
2523 g_strfreev(path_orig
);
2528 n
= find_elements(client
->doc
, n
->children
, path
+1, &rc
, NULL
, NULL
, NULL
, FALSE
, 0, NULL
);
2530 if (rc
&& rc
!= EPWMD_ELEMENT_NOT_FOUND
) {
2531 g_strfreev(path_orig
);
2536 xmlNodePtr parent
= n
->parent
;
2547 if (rc
== EPWMD_ELEMENT_NOT_FOUND
) {
2548 n
= create_element_path(client
, &path
, &rc
);
2556 copy
= xmlCopyNode(root
, 1);
2557 n
= xmlAddChild(n
, copy
);
2561 rc
= EPWMD_LIBXML_ERROR
;
2566 client
->inquire_status
= INQUIRE_DONE
;
2570 static int import_command(assuan_context_t ctx
, gchar
*line
)
2573 struct client_s
*client
= assuan_get_pointer(ctx
);
2575 rc
= file_modified(client
);
2578 return send_error(ctx
, rc
);
2580 rc
= assuan_inquire_ext(ctx
, "IMPORT", 0, import_command_finalize
, ctx
);
2583 return send_error(ctx
, rc
);
2585 /* Don't return with assuan_process_done() here. This is an INQUIRE. */
2586 client
->inquire_status
= INQUIRE_BUSY
;
2590 static int lock_command(assuan_context_t ctx
, gchar
*line
)
2593 struct client_s
*client
= assuan_get_pointer(ctx
);
2595 rc
= file_modified(client
);
2598 return send_error(ctx
, rc
);
2600 rc
= lock_file_mutex(client
);
2603 client
->is_lock_cmd
= TRUE
;
2605 return send_error(ctx
, rc
);
2608 static int unlock_command(assuan_context_t ctx
, gchar
*line
)
2610 struct client_s
*client
= assuan_get_pointer(ctx
);
2611 gpg_error_t rc
= file_modified(client
);
2614 return send_error(ctx
, rc
);
2616 unlock_file_mutex(client
);
2617 return send_error(ctx
, 0);
2620 static int getpid_command(assuan_context_t ctx
, gchar
*line
)
2624 pid_t pid
= getpid();
2626 print_fmt(buf
, sizeof(buf
), "%i", pid
);
2627 rc
= assuan_send_data(ctx
, buf
, strlen(buf
));
2628 return send_error(ctx
, rc
);
2631 static int version_command(assuan_context_t ctx
, gchar
*line
)
2636 print_fmt(buf
, sizeof(buf
), "%s", PACKAGE_VERSION
);
2637 rc
= assuan_send_data(ctx
, buf
, strlen(buf
));
2638 return send_error(ctx
, rc
);
2641 static void bye_notify(assuan_context_t ctx
)
2643 struct client_s
*cl
= assuan_get_pointer(ctx
);
2647 if (!cl
->thd
->remote
)
2651 rc
= gnutls_bye(cl
->thd
->tls
->ses
, GNUTLS_SHUT_RDWR
);
2652 } while (rc
== GNUTLS_E_AGAIN
);
2655 /* This will let assuan_process_next() return. */
2656 fcntl(cl
->thd
->fd
, F_SETFL
, O_NONBLOCK
);
2659 static void reset_notify(assuan_context_t ctx
)
2661 struct client_s
*cl
= assuan_get_pointer(ctx
);
2667 static gpg_error_t
parse_client_option(assuan_context_t ctx
, const gchar
*line
)
2669 gchar name
[32] = {0}, value
[256] = {0};
2671 if (sscanf(line
, " %31[a-zA-Z] = %255c", name
, value
) != 2)
2672 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_SYNTAX
);
2674 if (g_strcasecmp(name
, (gchar
*)"NAME") == 0) {
2675 struct client_s
*cl
= assuan_get_pointer(ctx
);
2678 g_free(cl
->thd
->name
);
2680 cl
->thd
->name
= g_strdup(value
);
2681 log_write("OPTION CLIENT %s", line
);
2684 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_UNKNOWN_OPTION
);
2689 static int option_handler(assuan_context_t ctx
, const gchar
*name
,
2692 struct client_s
*client
= assuan_get_pointer(ctx
);
2694 if (!value
|| !*value
)
2695 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
2697 if (g_strcasecmp(name
, (gchar
*)"client") == 0)
2698 return parse_client_option(ctx
, value
);
2700 if (g_strcasecmp(name
, (gchar
*)"iterations") == 0) {
2705 n
= strtol(value
, &p
, 10);
2707 if (errno
|| (p
&& *p
) || n
< 0)
2708 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
2710 g_key_file_set_integer(keyfileh
, client
->filename
? client
->filename
: "global", "iterations", (guint
)n
);
2711 send_status_all(STATUS_CONFIG
);
2713 #ifdef WITH_PINENTRY
2714 else if (g_strcasecmp(name
, (gchar
*)"ttyname") == 0) {
2715 g_free(client
->pinentry
->ttyname
);
2716 client
->pinentry
->ttyname
= g_strdup(value
);
2718 else if (g_strcasecmp(name
, (gchar
*)"ttytype") == 0) {
2719 g_free(client
->pinentry
->ttytype
);
2720 client
->pinentry
->ttytype
= g_strdup(value
);
2722 else if (g_strcasecmp(name
, (gchar
*)"display") == 0) {
2723 g_free(client
->pinentry
->display
);
2724 client
->pinentry
->display
= g_strdup(value
);
2726 else if (g_strcasecmp(name
, (gchar
*)"path") == 0) {
2727 g_free(client
->pinentry
->path
);
2728 client
->pinentry
->path
= g_strdup(value
);
2730 else if (g_strcasecmp(name
, (gchar
*)"title") == 0) {
2731 g_free(client
->pinentry
->title
);
2732 client
->pinentry
->title
= g_strdup(value
);
2734 else if (g_strcasecmp(name
, (gchar
*)"prompt") == 0) {
2735 g_free(client
->pinentry
->prompt
);
2736 client
->pinentry
->prompt
= g_strdup(value
);
2738 else if (g_strcasecmp(name
, (gchar
*)"desc") == 0) {
2739 g_free(client
->pinentry
->desc
);
2740 client
->pinentry
->desc
= g_strdup(value
);
2743 * Look at client_thread() to see how this works.
2745 else if (g_strcasecmp(name
, (gchar
*)"timeout") == 0) {
2747 gint n
= strtol(value
, &p
, 10);
2750 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
2752 client
->pinentry
->timeout
= n
;
2754 else if (g_strcasecmp(name
, (gchar
*)"pinentry") == 0) {
2756 gint n
= strtol(value
, &p
, 10);
2758 if (*p
|| n
< 0 || n
> 1)
2759 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_INV_VALUE
);
2761 client
->pinentry
->enable
= n
== 0 ? FALSE
: TRUE
;
2765 return gpg_err_make(PWMD_ERR_SOURCE
, GPG_ERR_UNKNOWN_OPTION
);
2767 log_write("OPTION %s=%s", name
, value
);
2771 gpg_error_t
register_commands(assuan_context_t ctx
)
2775 gint (*handler
)(assuan_context_t
, gchar
*line
);
2777 { "OPEN", open_command
},
2778 { "SAVE", save_command
},
2779 { "LIST", list_command
},
2780 { "REALPATH", realpath_command
},
2781 { "STORE", store_command
},
2782 { "DELETE", delete_command
},
2783 { "GET", get_command
},
2784 { "ATTR", attr_command
},
2785 { "ISCACHED", iscached_command
},
2786 { "CLEARCACHE", clearcache_command
},
2787 { "CACHETIMEOUT", cachetimeout_command
},
2788 { "GETCONFIG", getconfig_command
},
2789 { "DUMP", dump_command
},
2790 { "XPATH", xpath_command
},
2791 { "IMPORT", import_command
},
2792 { "LOCK", lock_command
},
2793 { "UNLOCK", unlock_command
},
2794 { "GETPID", getpid_command
},
2795 { "VERSION", version_command
},
2802 for (i
=0; table
[i
].name
; i
++) {
2803 rc
= assuan_register_command (ctx
, table
[i
].name
, table
[i
].handler
);
2809 rc
= assuan_register_bye_notify(ctx
, bye_notify
);
2814 rc
= assuan_register_option_handler(ctx
, option_handler
);
2819 rc
= assuan_register_reset_notify(ctx
, reset_notify
);
2824 return assuan_register_post_cmd_notify(ctx
, command_finalize
);
2827 gpg_error_t
try_xml_decrypt(assuan_context_t ctx
, guchar
*key
,
2828 struct client_crypto_s
*crypto
, gpointer
*dst
, gsize
*dst_len
)
2831 struct client_s
*client
= ctx
? assuan_get_pointer(ctx
) : NULL
;
2832 guint iter
= 0, n_iter
= 0, iter_progress
= 0;
2836 gsize fh_size
= crypto
->fh
->v1
? sizeof(crypto
->fh
->fh1
) : sizeof(crypto
->fh
->fh2
);
2837 glong fh_iter
= crypto
->fh
->v1
? crypto
->fh
->fh1
.iter
: crypto
->fh
->fh2
.iter
;
2839 lseek(crypto
->fh
->fd
, fh_size
, SEEK_SET
);
2840 insize
= crypto
->fh
->st
.st_size
- fh_size
;
2841 crypto
->iv
= gcry_malloc(gcryblocksize
);
2844 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2845 return gpg_error_from_errno(ENOMEM
);
2848 /* No encryption iterations. This is a plain (gzipped) file. */
2849 if ((crypto
->fh
->v1
&& fh_iter
< 0) || (!crypto
->fh
->v1
&& fh_iter
<= 0)) {
2851 * cache_file_count() needs both .used == TRUE and a valid key in
2852 * order for it to count as a used cache entry. Fixes CACHE status
2855 memset(key
, '!', gcrykeysize
);
2859 memcpy(crypto
->iv
, crypto
->fh
->fh1
.iv
, gcryblocksize
);
2861 memcpy(crypto
->iv
, crypto
->fh
->fh2
.iv
, gcryblocksize
);
2863 crypto
->inbuf
= gcry_malloc(insize
);
2865 if (!crypto
->inbuf
) {
2866 log_write("%s(%i): %s", __FILE__
, __LINE__
, strerror(ENOMEM
));
2867 return gpg_error_from_errno(ENOMEM
);
2870 crypto
->insize
= insize
;
2871 len
= read(crypto
->fh
->fd
, crypto
->inbuf
, crypto
->insize
);
2873 if (len
!= crypto
->insize
)
2874 return GPG_ERR_INV_LENGTH
;
2876 if ((crypto
->fh
->v1
&& fh_iter
< 0) || (!crypto
->fh
->v1
&& fh_iter
<= 0))
2879 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->iv
, gcryblocksize
))) {
2880 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(rc
));
2884 if ((rc
= gcry_cipher_setkey(crypto
->gh
, key
, gcrykeysize
))) {
2885 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(rc
));
2889 iter_progress
= (guint
)get_key_file_integer(client
&& client
->filename
?
2890 client
->filename
: "global", "iteration_progress");
2892 if (iter_progress
> 0 && fh_iter
>= iter_progress
) {
2893 rc
= send_status(ctx
, STATUS_DECRYPT
, "%u %u", 0, fh_iter
);
2899 rc
= iterate_crypto_once(client
, crypto
, STATUS_DECRYPT
);
2904 crypto
->tkey
= gcry_malloc(gcrykeysize
);
2906 if (!crypto
->tkey
) {
2907 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, strerror(ENOMEM
));
2908 return gpg_error_from_errno(ENOMEM
);
2911 memcpy(crypto
->tkey
, key
, gcrykeysize
);
2912 guchar
*tkey
= crypto
->tkey
;
2915 if ((rc
= gcry_cipher_setkey(crypto
->gh
, crypto
->tkey
, gcrykeysize
))) {
2916 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(rc
));
2920 while (iter
< (crypto
->fh
->v1
? fh_iter
: fh_iter
-1)) {
2921 if (iter_progress
> 0 && iter
>= iter_progress
) {
2922 if (!(iter
% iter_progress
)) {
2923 rc
= send_status(ctx
, STATUS_DECRYPT
, "%u %u",
2924 ++n_iter
* iter_progress
, fh_iter
);
2931 if ((rc
= gcry_cipher_setiv(crypto
->gh
, crypto
->iv
, gcryblocksize
))) {
2932 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(rc
));
2936 rc
= iterate_crypto_once(client
, crypto
, STATUS_DECRYPT
);
2939 log_write("%s(%i): %s", __FUNCTION__
, __LINE__
, gcry_strerror(rc
));
2946 if (iter_progress
&& fh_iter
>= iter_progress
) {
2947 rc
= send_status(ctx
, STATUS_DECRYPT
, "%u %u", fh_iter
, fh_iter
);
2954 if (do_decompress(ctx
, crypto
->inbuf
, crypto
->insize
,
2955 (gpointer
*)&crypto
->outbuf
, &outsize
, &zrc
) == FALSE
) {
2956 if (zrc
== Z_MEM_ERROR
)
2957 return gpg_error_from_errno(ENOMEM
);
2959 return EPWMD_BADKEY
; // Not a valid gzip header. Must be a bad key.
2962 if (g_strncasecmp(crypto
->outbuf
, "<?xml version=\"1.0\"?>", 21) != 0) {
2963 gcry_free(crypto
->outbuf
);
2964 crypto
->outbuf
= NULL
;
2965 return EPWMD_BADKEY
;
2969 client
->xml
= crypto
->outbuf
;
2970 client
->len
= outsize
;
2971 crypto
->outbuf
= NULL
;
2974 *dst
= crypto
->outbuf
;
2976 crypto
->outbuf
= NULL
;
2979 /* The calling function should free the crypto struct. */
2984 * This is called after every Assuan command.
2986 void command_finalize(assuan_context_t ctx
, gint rc
)
2988 struct client_s
*client
= assuan_get_pointer(ctx
);
2990 if (!client
->is_lock_cmd
)
2991 unlock_file_mutex(client
);