Fix PASSWD and SAVE for symmetric encrypted files.
[pwmd.git] / src / commands.c
blob9331a6a4e8cb552614ea684c7582e37dbcd30a44
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <err.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <ctype.h>
33 #include <dirent.h>
34 #include <pthread.h>
35 #include <stdint.h>
37 #ifdef WITH_LIBACL
38 #include <sys/acl.h>
39 #endif
41 #include "pwmd-error.h"
42 #include <gcrypt.h>
44 #include "mem.h"
45 #include "xml.h"
46 #include "common.h"
47 #include "rcfile.h"
48 #include "cache.h"
49 #include "util-misc.h"
50 #include "commands.h"
51 #include "mutex.h"
52 #include "pinentry.h"
54 /* Flags needed to be retained for a client across commands. */
55 #define FLAG_NEW 0x0001
56 #define FLAG_HAS_LOCK 0x0002
57 #define FLAG_LOCK_CMD 0x0004
58 #define FLAG_NO_PINENTRY 0x0008
59 #define FLAG_OPEN 0x0010
60 #define FLAG_KEEP_LOCK 0x0020
62 /* These are command option flags. */
63 #define OPT_INQUIRE 0x0001
64 #define OPT_NO_PASSPHRASE 0x0002
65 #define OPT_RESET 0x0004
66 #define OPT_LIST_RECURSE 0x0008
67 #define OPT_LIST_VERBOSE 0x0010
68 #define OPT_LOCK 0x0020
69 #define OPT_LOCK_ON_OPEN 0x0040
70 #define OPT_SIGN 0x0080
71 #define OPT_LIST_ALL 0x0100
72 #define OPT_LIST_WITH_TARGET 0x0200
73 #define OPT_DATA 0x0400
74 #define OPT_NO_AGENT 0x0800
76 struct command_table_s
78 const char *name;
79 gpg_error_t (*handler) (assuan_context_t, char *line);
80 const char *help;
81 int ignore_startup;
82 int unlock; // unlock the file mutex after validating the checksum
85 static struct command_table_s **command_table;
87 static gpg_error_t do_lock (struct client_s *client, int add);
88 static gpg_error_t validate_checksum (struct client_s *,
89 struct cache_data_s *);
90 static gpg_error_t update_checksum (struct client_s *client);
92 static gpg_error_t
93 unlock_file_mutex (struct client_s *client, int remove)
95 gpg_error_t rc = 0;
97 // OPEN: keep the lock for the same file being reopened.
98 if (client->flags & FLAG_KEEP_LOCK && client->flags & FLAG_HAS_LOCK)
99 return 0;
101 if (!(client->flags & FLAG_HAS_LOCK))
102 return GPG_ERR_NOT_LOCKED;
104 rc = cache_unlock_mutex (client->md5file, remove);
105 if (rc)
106 rc = GPG_ERR_INV_STATE;
107 else
108 client->flags &= ~(FLAG_HAS_LOCK | FLAG_LOCK_CMD);
110 return rc;
113 static gpg_error_t
114 lock_file_mutex (struct client_s *client, int add)
116 gpg_error_t rc = 0;
117 int timeout = config_get_integer (client->filename, "cache_timeout");
119 if (client->flags & FLAG_HAS_LOCK)
120 return 0;
122 rc = cache_lock_mutex (client->ctx, client->md5file,
123 client->lock_timeout, add, timeout);
124 if (!rc)
125 client->flags |= FLAG_HAS_LOCK;
127 return rc;
130 static gpg_error_t
131 file_modified (struct client_s *client, struct command_table_s *cmd)
133 gpg_error_t rc = 0;
135 if (!(client->flags & FLAG_OPEN))
136 return GPG_ERR_INV_STATE;
138 rc = lock_file_mutex (client, 0);
139 if (!rc || rc == GPG_ERR_NO_DATA)
141 rc = validate_checksum (client, NULL);
142 if (gpg_err_code (rc) == GPG_ERR_ENOENT)
143 rc = 0;
146 if ((cmd->unlock && !(client->flags & FLAG_HAS_LOCK)) || rc)
147 unlock_file_mutex (client, 0);
149 return rc;
152 static gpg_error_t
153 parse_xml (assuan_context_t ctx, int new)
155 struct client_s *client = assuan_get_pointer (ctx);
156 int cached = client->doc != NULL;
158 if (new)
160 client->doc = new_document ();
161 if (client->doc)
163 xmlDocDumpFormatMemory (client->doc,
164 (xmlChar **) & client->crypto->plaintext,
165 (int *) &client->crypto->plaintext_len, 0);
166 if (!client->crypto->plaintext)
168 xmlFreeDoc (client->doc);
169 client->doc = NULL;
173 else if (!cached)
174 client->doc = parse_doc ((char *) client->crypto->plaintext,
175 client->crypto->plaintext_len);
177 return !client->doc ? GPG_ERR_ENOMEM : 0;
180 static void
181 free_client (struct client_s *client)
183 if (client->doc)
184 xmlFreeDoc (client->doc);
186 xfree (client->crc);
187 xfree (client->filename);
188 xfree (client->last_error);
190 if (client->crypto)
192 cleanup_crypto_stage2 (client->crypto);
193 if (client->crypto->pkey_sexp)
194 gcry_sexp_release (client->crypto->pkey_sexp);
196 client->crypto->pkey_sexp = NULL;
197 memset (client->crypto->sign_grip, 0,
198 sizeof (client->crypto->sign_grip));
201 if (client->xml_error)
202 xmlResetError (client->xml_error);
205 void
206 cleanup_client (struct client_s *client)
208 assuan_context_t ctx = client->ctx;
209 struct client_thread_s *thd = client->thd;
210 struct crypto_s *crypto = client->crypto;
211 long lock_timeout = client->lock_timeout;
213 unlock_file_mutex (client, client->flags & FLAG_NEW);
214 free_client (client);
215 memset (client, 0, sizeof (struct client_s));
216 client->crypto = crypto;
217 client->ctx = ctx;
218 client->thd = thd;
219 client->lock_timeout = lock_timeout;
222 static gpg_error_t
223 open_finalize (assuan_context_t ctx, char *key, size_t keylen)
225 struct client_s *client = assuan_get_pointer (ctx);
226 gpg_error_t rc = 0;
227 struct cache_data_s *cdata = cache_get_data (client->md5file);
228 int cached = 0, keyarg = key ? 1 : 0;
229 size_t keysize;
230 unsigned char *salted_key = NULL;
231 struct pinentry_s *pin;
232 int algo;
234 client->crypto->filename = str_dup (client->filename);
235 if (cdata || client->flags & FLAG_NEW)
237 if (!(client->flags & FLAG_NEW))
239 rc = decrypt_xml (client->crypto, cdata->doc, cdata->doclen);
240 if (rc)
241 return rc;
244 cached = cdata != NULL;
245 goto done;
248 if (!key && !IS_PKCS (client->crypto))
250 if (client->flags & FLAG_NO_PINENTRY)
252 assuan_begin_confidential (ctx);
253 /* Note: 'key' is freed with gcry_free() and not
254 * xfree(). Although both call xfree(). */
255 rc = assuan_inquire (ctx, "PASSPHRASE", (unsigned char **)&key,
256 &keylen, 0);
257 assuan_end_confidential (ctx);
259 else
261 pin = pinentry_init (client->filename);
262 if (!pin)
263 return GPG_ERR_ENOMEM;
265 rc = pinentry_getpin (pin, &key, PINENTRY_OPEN);
266 pinentry_deinit (pin);
267 if (rc)
268 return rc;
271 /* Empty keys are allowed. */
272 keylen = strlen (key);
273 if (!keylen)
274 keylen++;
277 if (!IS_PKCS (client->crypto))
279 algo = cipher_to_gcrypt (client->crypto->hdr.flags);
280 rc = gcry_cipher_algo_info (algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
281 if (!rc)
283 salted_key = gcry_malloc (keysize);
284 if (salted_key)
285 rc = gcry_kdf_derive(key, keylen, GCRY_KDF_ITERSALTED_S2K,
286 GCRY_MD_SHA1, client->crypto->hdr.salt, 8,
287 DEFAULT_KDFS2K_ITERATIONS, keysize,
288 salted_key);
289 else
290 rc = GPG_ERR_ENOMEM;
293 if (!keyarg)
294 gcry_free (key);
296 if (!rc)
297 rc = decrypt_data (client->ctx, client->crypto, salted_key, keysize);
299 if (rc)
300 return rc;
302 cdata = xcalloc (1, sizeof (struct cache_data_s));
303 if (!cdata)
304 return GPG_ERR_ENOMEM;
306 cdata->key = salted_key;
307 cdata->keylen = keysize;
309 else
310 rc = decrypt_data (client->ctx, client->crypto, NULL, 0);
312 done:
313 if (!rc)
315 rc = parse_xml (ctx, client->flags & FLAG_NEW);
316 if (!rc)
318 int timeout = config_get_integer (client->filename,
319 "cache_timeout");
321 if (!cached)
323 if (!cdata)
324 cdata = xcalloc (1, sizeof (struct cache_data_s));
326 rc = encrypt_xml (NULL, cache_key, cache_keysize,
327 GCRY_CIPHER_AES, client->crypto->plaintext,
328 client->crypto->plaintext_len, &cdata->doc,
329 &cdata->doclen, &cache_iv, &cache_blocksize,
331 if (!rc && !(client->flags & FLAG_NEW) && IS_PKCS (client->crypto))
333 rc = gcry_sexp_build ((gcry_sexp_t *) & cdata->pubkey, NULL,
334 "%S", client->crypto->pkey_sexp);
338 if (cdata->sigkey)
339 gcry_sexp_release (cdata->sigkey);
341 cdata->sigkey = NULL;
343 if (!rc && IS_PKCS (client->crypto))
344 rc = gcry_sexp_build ((gcry_sexp_t *) &cdata->sigkey, NULL,
345 "%S", client->crypto->sigpkey_sexp);
347 if (!rc
348 && !cache_add_file (client->md5file, (client->flags & FLAG_NEW)
349 ? NULL : client->crypto->grip, cdata, timeout))
351 if (!cached)
353 free_cache_data_once (cdata);
354 xmlFreeDoc (client->doc);
355 client->doc = NULL;
357 rc = GPG_ERR_ENOMEM;
360 if (!rc)
361 client->flags |= FLAG_OPEN;
365 if (!rc)
366 update_checksum (client);
368 if (!rc && (client->opts & OPT_LOCK_ON_OPEN))
369 rc = do_lock (client, 0);
371 return rc;
374 static void
375 req_cleanup (void *arg)
377 if (!arg)
378 return;
380 strv_free ((char **) arg);
383 static gpg_error_t
384 parse_open_opt_lock (void *data, void *value)
386 struct client_s *client = data;
388 client->opts |= OPT_LOCK_ON_OPEN;
389 return 0;
392 static gpg_error_t
393 parse_opt_pinentry (void *data, void *value)
395 struct client_s *client = data;
397 client->flags |= FLAG_NO_PINENTRY;
398 return 0;
401 static gpg_error_t
402 parse_opt_inquire (void *data, void *value)
404 struct client_s *client = data;
406 (void) value;
407 client->opts |= OPT_INQUIRE;
408 return 0;
411 static gpg_error_t
412 update_checksum (struct client_s *client)
414 unsigned char *crc;
415 size_t len;
416 struct cache_data_s *cdata;
417 gpg_error_t rc = get_checksum (client->filename, &crc, &len);
419 if (rc)
420 return rc;
422 xfree (client->crc);
423 client->crc = crc;
424 cdata = cache_get_data (client->md5file);
425 if (cdata)
427 xfree (cdata->crc);
428 cdata->crc = xmalloc (len);
429 memcpy (cdata->crc, crc, len);
432 return 0;
435 static gpg_error_t
436 validate_checksum (struct client_s *client, struct cache_data_s *cdata)
438 unsigned char *crc;
439 size_t len;
440 gpg_error_t rc;
441 int n = 0;
443 if (cdata && !cdata->crc)
444 return GPG_ERR_CHECKSUM;
446 rc = get_checksum (client->filename, &crc, &len);
447 if (rc)
448 return rc;
450 if (cdata)
451 n = memcmp (cdata->crc, crc, len);
452 else if (client->crc)
453 n = memcmp (client->crc, crc, len);
455 xfree (crc);
456 return n ? GPG_ERR_CHECKSUM : 0;
459 static gpg_error_t
460 do_open (assuan_context_t ctx, const char *filename, const char *password)
462 struct client_s *client = assuan_get_pointer (ctx);
463 struct cache_data_s *cdata;
464 gpg_error_t rc = 0;
465 int done = 0;
467 if (!valid_filename (filename))
468 return GPG_ERR_INV_VALUE;
470 gcry_md_hash_buffer (GCRY_MD_MD5, client->md5file, filename,
471 strlen (filename));
472 client->filename = str_dup (filename);
473 if (!client->filename)
474 return GPG_ERR_ENOMEM;
476 // Cached document?
477 cdata = cache_get_data (client->md5file);
478 if (cdata && cdata->doc)
480 int defer;
482 rc = validate_checksum (client, cdata);
483 /* This will check that the key is cached in the agent which needs to
484 * be determined for files that share a keygrip. */
485 if (!rc)
487 rc = cache_iscached (client->filename, &defer);
488 if (!rc && defer)
489 rc = GPG_ERR_KEY_EXPIRED;
492 #ifdef WITH_GNUTLS
493 if (!rc && client->thd->remote &&
494 config_get_boolean (NULL, "tcp_require_key"))
495 rc = GPG_ERR_KEY_EXPIRED;
496 #endif
498 if (!rc && !password)
500 rc = read_data_header (client->filename, &client->crypto->hdr,
501 NULL, NULL);
502 if (!rc)
504 if (IS_PKCS (client->crypto))
506 gcry_sexp_build (&client->crypto->pkey_sexp, NULL, "%S",
507 cdata->pubkey);
508 gcry_pk_get_keygrip (client->crypto->pkey_sexp,
509 client->crypto->grip);
510 gcry_sexp_build (&client->crypto->sigpkey_sexp, NULL, "%S",
511 cdata->sigkey);
512 gcry_pk_get_keygrip (client->crypto->sigpkey_sexp,
513 client->crypto->sign_grip);
516 if (!rc)
518 rc = open_finalize (ctx, NULL, 0);
519 done = 1;
524 /* There was an error accessing the file so clear the cache entry. The
525 * real error will be returned from read_data_file() since the file
526 * may have only disappeared. */
527 if (!done)
529 log_write ("%s: %s", filename, pwmd_strerror (rc));
530 rc = cache_clear (client->md5file);
531 send_status_all (STATUS_CACHE, NULL);
535 if (done || rc)
536 return rc;
538 rc = read_data_file (client->filename, client->crypto);
539 if (rc)
541 if (gpg_err_source (rc) != GPG_ERR_SOURCE_DEFAULT ||
542 gpg_err_code (rc) != GPG_ERR_ENOENT)
544 log_write ("%s: %s", client->filename, pwmd_strerror (rc));
545 return rc;
548 client->flags |= FLAG_NEW;
549 memset (client->crypto->grip, 0, sizeof (client->crypto->grip));
550 memset (client->crypto->sign_grip, 0,
551 sizeof (client->crypto->sign_grip));
552 rc = open_finalize (ctx, NULL, 0);
553 return rc;
556 if (password && IS_PKCS (client->crypto))
558 #ifdef WITH_AGENT
559 rc = set_agent_passphrase (client->crypto, password, strlen (password));
560 if (rc)
561 return rc;
562 #endif
565 rc = open_finalize (ctx, (char *)password, password ? strlen (password) : 0);
566 return rc;
569 static gpg_error_t
570 open_command (assuan_context_t ctx, char *line)
572 gpg_error_t rc;
573 struct client_s *client = assuan_get_pointer (ctx);
574 char **req, *password = NULL, *filename;
575 unsigned char md5file[16];
576 int same_file = 0;
577 struct argv_s *args[] = {
578 &(struct argv_s) {"lock", OPTION_TYPE_NOARG, parse_open_opt_lock},
579 &(struct argv_s) {"no-pinentry", OPTION_TYPE_NOARG,
580 parse_opt_pinentry},
581 NULL
584 client->flags &= ~(FLAG_NO_PINENTRY);
585 rc = parse_options (&line, args, client);
586 if (rc)
587 return send_error (ctx, rc);
589 req = str_split (line, " ", 2);
590 if (!req)
591 return send_error (ctx, GPG_ERR_SYNTAX);
593 #ifdef WITH_GNUTLS
594 if (client->thd->remote)
596 rc = tls_validate_access (client, req[0]);
597 if (rc)
599 if (rc == GPG_ERR_INV_USER_ID)
600 log_write (_("client validation failed for file '%s'"), req[0]);
601 strv_free (req);
602 return send_error (ctx, rc);
605 /* Remote pinentries are not supported. */
606 client->flags |= FLAG_NO_PINENTRY;
608 #endif
610 pthread_cleanup_push (req_cleanup, req);
611 filename = req[0];
612 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, filename, strlen (filename));
613 /* This client may have locked a different file with ISCACHED --lock than
614 * the current filename. This will remove that lock. */
615 same_file = !memcmp (md5file, client->md5file, 16) ? 1 : 0;
616 if (client->flags & FLAG_OPEN ||
617 (client->flags & FLAG_HAS_LOCK && !same_file))
619 typeof (client->opts) opts = client->opts;
620 typeof (client->flags) flags = client->flags;
622 if (same_file)
623 client->flags |= FLAG_KEEP_LOCK;
625 cleanup_client (client);
626 client->opts = opts;
627 client->flags |= flags;
628 client->flags &= ~(FLAG_LOCK_CMD | FLAG_NEW);
629 if (!same_file)
630 client->flags &= ~(FLAG_HAS_LOCK);
633 /* Need to lock the mutex here because file_modified() cannot without
634 * knowing the filename. */
635 memcpy (client->md5file, md5file, 16);
636 rc = lock_file_mutex (client, 1);
637 if (!rc)
639 password = req[1] && *req[1] ? req[1] : NULL;
640 #ifdef WITH_AGENT
641 if (IS_PKCS (client->crypto))
642 rc = set_pinentry_mode (client->crypto->agent,
643 (client->flags & FLAG_NO_PINENTRY) ? "loopback"
644 : "ask");
645 #endif
646 if (!rc)
648 rc = do_open (ctx, filename, password);
649 if (rc)
650 cleanup_client (client);
652 cleanup_crypto_stage1 (client->crypto);
656 pthread_cleanup_pop (1);
658 if (!rc && client->flags & FLAG_NEW)
659 rc = send_status (ctx, STATUS_NEWFILE, NULL);
661 #ifdef WITH_AGENT
662 (void) kill_scd (client->crypto->agent);
663 #endif
664 return send_error (ctx, rc);
667 static gpg_error_t
668 parse_save_opt_no_passphrase (void *data, void *value)
670 struct client_s *client = data;
672 (void) value;
673 client->opts |= OPT_NO_PASSPHRASE;
674 return 0;
677 static gpg_error_t
678 parse_save_opt_no_agent (void *data, void *value)
680 struct client_s *client = data;
682 client->opts |= OPT_NO_AGENT;
683 return 0;
686 static gpg_error_t
687 parse_save_opt_cipher (void *data, void *value)
689 struct client_s *client = data;
690 int algo = cipher_string_to_gcrypt ((char *) value);
691 file_header_t *hdr = &client->crypto->save.hdr;
693 if (algo == -1)
694 return GPG_ERR_INV_VALUE;
696 hdr->flags = set_cipher_flag (hdr->flags, algo);
697 return 0;
700 static gpg_error_t
701 parse_save_opt_keygrip (void *data, void *value)
703 struct client_s *client = data;
705 if (!IS_PKCS (client->crypto))
706 return GPG_ERR_INV_ARG;
708 #ifdef WITH_AGENT
709 if (client->crypto->save.pkey)
710 gcry_sexp_release (client->crypto->save.pkey);
712 client->crypto->save.pkey = NULL;
713 return get_pubkey (client->crypto, value, &client->crypto->save.pkey);
714 #else
715 return GPG_ERR_INV_ARG;
716 #endif
719 static gpg_error_t
720 parse_save_opt_sign_keygrip (void *data, void *value)
722 struct client_s *client = data;
724 if (!IS_PKCS (client->crypto))
725 return GPG_ERR_INV_ARG;
727 #ifdef WITH_AGENT
728 if (client->crypto->save.sigpkey)
729 gcry_sexp_release (client->crypto->save.sigpkey);
731 client->crypto->save.sigpkey = NULL;
732 return get_pubkey (client->crypto, value, &client->crypto->save.sigpkey);
733 #else
734 return GPG_ERR_INV_ARG;
735 #endif
738 static gpg_error_t
739 parse_opt_s2k_count (void *data, void *value)
741 struct client_s *client = data;
742 char *v = value;
744 if (!v || !*v)
745 return GPG_ERR_INV_VALUE;
747 client->crypto->save.s2k_count = strtoul (v, NULL, 10);
748 return 0;
751 static gpg_error_t
752 parse_save_opt_iterations (void *data, void *value)
754 struct client_s *client = data;
755 char *v = value, *p;
756 uint64_t n;
758 if (!v || !*v)
759 return GPG_ERR_INV_VALUE;
761 errno = 0;
762 n = strtoull (v, &p, 10);
763 if (n == UINT64_MAX && errno)
764 return gpg_error_from_syserror ();
765 else if (p && *p)
766 return GPG_ERR_INV_VALUE;
768 client->crypto->save.hdr.iterations = n;
769 return 0;
772 static gpg_error_t
773 save_finalize (assuan_context_t ctx)
775 struct client_s *client = assuan_get_pointer (ctx);
776 gpg_error_t rc = 0;
777 xmlChar *xmlbuf = NULL;
778 int xmlbuflen;
779 void *key = NULL;
780 size_t keylen = 0;
782 xmlDocDumpFormatMemory (client->doc, &xmlbuf, &xmlbuflen, 0);
783 if (!xmlbuf)
784 return GPG_ERR_ENOMEM;
786 pthread_cleanup_push (xmlFree, xmlbuf);
788 if (!use_agent || ((client->flags & FLAG_NEW)
789 && (client->opts & OPT_NO_AGENT))
790 || !(client->crypto->hdr.flags & PWMD_FLAG_PKCS))
792 rc = export_common (ctx, client->crypto, 0, xmlbuf, xmlbuflen,
793 client->filename, NULL, &key, &keylen, 1, 1);
795 #ifdef WITH_AGENT
796 else
798 gcry_sexp_t pubkey = client->crypto->save.pkey;
799 gcry_sexp_t sigkey = client->crypto->save.sigpkey;
801 if (!pubkey)
802 pubkey = client->crypto->pkey_sexp;
804 if (!sigkey)
806 sigkey = client->crypto->sigpkey_sexp;
807 if (!sigkey)
809 gcry_sexp_build (&client->crypto->save.sigpkey, 0, "%S", pubkey);
810 sigkey = client->crypto->save.sigpkey;
814 rc = encrypt_data_file (client->ctx, client->crypto, pubkey, sigkey,
815 client->filename, xmlbuf, xmlbuflen);
816 if (pubkey == client->crypto->save.pkey)
818 if (!rc)
820 gcry_sexp_release (client->crypto->pkey_sexp);
821 client->crypto->pkey_sexp = client->crypto->save.pkey;
822 gcry_pk_get_keygrip (client->crypto->pkey_sexp,
823 client->crypto->grip);
825 else
826 gcry_sexp_release (pubkey);
828 client->crypto->save.pkey = NULL;
831 if (!rc)
832 gcry_pk_get_keygrip (sigkey, client->crypto->sign_grip);
834 if (sigkey == client->crypto->save.sigpkey)
836 if (!rc)
838 if (client->crypto->sigpkey_sexp)
839 gcry_sexp_release (client->crypto->sigpkey_sexp);
841 client->crypto->sigpkey_sexp = client->crypto->save.sigpkey;
842 gcry_pk_get_keygrip (client->crypto->sigpkey_sexp,
843 client->crypto->sign_grip);
845 else
846 gcry_sexp_release (sigkey);
848 client->crypto->save.sigpkey = NULL;
851 #endif
853 if (!rc)
855 int cached;
857 rc = save_common (client->filename, client->crypto, xmlbuf, xmlbuflen,
858 key, keylen, &cached, client->opts & OPT_NO_AGENT);
859 if (rc)
860 gcry_free (key);
862 if (!rc && (!cached || (client->flags & FLAG_NEW)))
863 send_status_all (STATUS_CACHE, NULL);
865 if (!rc)
867 update_checksum (client);
868 client->flags &= ~(FLAG_NEW);
870 else
871 rc = GPG_ERR_ENOMEM;
874 pthread_cleanup_pop (1); // xmlFree
875 return rc;
878 static gpg_error_t
879 parse_opt_reset (void *data, void *value)
881 struct client_s *client = data;
883 (void) value;
884 client->opts |= OPT_RESET;
885 return 0;
888 static gpg_error_t
889 save_command (assuan_context_t ctx, char *line)
891 struct client_s *client = assuan_get_pointer (ctx);
892 gpg_error_t rc;
893 struct stat st;
894 struct argv_s *args[] = {
895 &(struct argv_s) {"no-passphrase", OPTION_TYPE_NOARG,
896 parse_save_opt_no_passphrase},
897 &(struct argv_s) {"cipher", OPTION_TYPE_ARG, parse_save_opt_cipher},
898 &(struct argv_s) {"inquire-keyparam", OPTION_TYPE_NOARG,
899 parse_opt_inquire},
900 &(struct argv_s) {"keygrip", OPTION_TYPE_ARG, parse_save_opt_keygrip},
901 &(struct argv_s) {"sign-keygrip", OPTION_TYPE_ARG,
902 parse_save_opt_sign_keygrip},
903 &(struct argv_s) {"s2k-count", OPTION_TYPE_ARG, parse_opt_s2k_count},
904 &(struct argv_s) {"reset", OPTION_TYPE_NOARG, parse_opt_reset},
905 &(struct argv_s) {"cipher-iterations", OPTION_TYPE_ARG,
906 parse_save_opt_iterations},
907 &(struct argv_s) {"no-agent", OPTION_TYPE_NOARG,
908 parse_save_opt_no_agent},
909 NULL
912 cleanup_save (&client->crypto->save);
913 memcpy (&client->crypto->save.hdr, &client->crypto->hdr,
914 sizeof (file_header_t));
915 client->crypto->save.s2k_count =
916 config_get_ulong (client->filename, "s2k_count");
918 if (client->flags & FLAG_NEW)
919 client->crypto->save.hdr.iterations =
920 config_get_ulonglong (client->filename, "cipher_iterations");
922 rc = parse_options (&line, args, client);
923 if (rc)
924 return send_error (ctx, rc);
926 if (!(client->flags & FLAG_NEW))
927 client->opts &= ~OPT_NO_AGENT;
928 else if (client->opts & OPT_NO_AGENT)
930 client->crypto->save.hdr.flags &= ~PWMD_FLAG_PKCS;
931 client->crypto->hdr.flags &= ~PWMD_FLAG_PKCS;
934 if ((client->opts & OPT_NO_PASSPHRASE) && !(client->flags & FLAG_NEW)
935 && !(client->opts & OPT_INQUIRE))
936 return send_error (ctx, GPG_ERR_WRONG_KEY_USAGE);
938 if (lstat (client->filename, &st) == -1 && errno != ENOENT)
939 return send_error (ctx, gpg_error_from_syserror ());
941 if (errno != ENOENT && !S_ISREG (st.st_mode))
943 log_write ("%s: %s", client->filename, pwmd_strerror (GPG_ERR_ENOANO));
944 return send_error (ctx, GPG_ERR_ENOANO);
947 int defer;
948 rc = cache_iscached (client->filename, &defer);
949 if (!rc && defer)
951 log_write ("%s: %s", client->filename,
952 pwmd_strerror (GPG_ERR_KEY_EXPIRED));
953 client->opts |= OPT_RESET;
956 if (client->opts & OPT_RESET)
958 rc = cache_clear (client->md5file);
959 if (rc)
960 return send_error (ctx, rc);
962 send_status_all (STATUS_CACHE, NULL);
965 rc = update_element_mtime (xmlDocGetRootElement (client->doc));
966 if (rc)
967 return send_error (ctx, rc);
969 #ifdef WITH_AGENT
970 if (!rc && use_agent && !client->crypto->save.pkey &&
971 (client->flags & FLAG_NEW || client->opts & OPT_INQUIRE)
972 && !(client->opts & OPT_NO_AGENT))
974 rc = send_status (client->ctx, STATUS_GENKEY, NULL);
975 if (!rc)
977 struct inquire_data_s idata = { 0 };
978 char *params = client->opts & OPT_INQUIRE ? NULL
979 : default_key_params (client->crypto);
981 pthread_cleanup_push (xfree, params);
982 idata.crypto = client->crypto;
984 if (params)
986 idata.line = params;
987 idata.len = strlen (params);
989 else
990 idata.preset = 1;
992 client->crypto->agent->inquire_data = &idata;
993 client->crypto->agent->inquire_cb = NULL;
994 rc = generate_key (client->crypto, params,
995 (client->opts & OPT_NO_PASSPHRASE), 1);
996 pthread_cleanup_pop (1);
999 #endif
1001 if (!rc)
1002 rc = save_finalize (ctx);
1004 cleanup_crypto_stage1 (client->crypto);
1005 #ifdef WITH_AGENT
1006 (void) kill_scd (client->crypto->agent);
1007 #endif
1008 return send_error (ctx, rc);
1011 static gpg_error_t
1012 do_delete (assuan_context_t ctx, char *line)
1014 struct client_s *client = assuan_get_pointer (ctx);
1015 gpg_error_t rc;
1016 char **req;
1017 xmlNodePtr n;
1019 if (strchr (line, '\t'))
1020 req = str_split (line, "\t", 0);
1021 else
1022 req = str_split (line, " ", 0);
1024 if (!req || !*req)
1025 return GPG_ERR_SYNTAX;
1027 n = find_root_element (client->doc, &req, &rc, NULL, 0, 0);
1028 if (!n)
1030 strv_free (req);
1031 return rc;
1035 * No sub-node defined. Remove the entire node (root element).
1037 if (!req[1])
1039 if (n)
1041 rc = unlink_node (n);
1042 xmlFreeNode (n);
1045 strv_free (req);
1046 return rc;
1050 find_elements (client->doc, n->children, req + 1, &rc, NULL, NULL, NULL,
1051 0, 0, NULL, 0);
1052 strv_free (req);
1053 if (!n)
1054 return rc;
1056 if (n)
1058 rc = unlink_node (n);
1059 xmlFreeNode (n);
1062 return rc;
1065 static gpg_error_t
1066 delete_command (assuan_context_t ctx, char *line)
1068 struct client_s *client = assuan_get_pointer (ctx);
1069 gpg_error_t rc;
1070 struct argv_s *args[] = {
1071 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1072 NULL
1075 rc = parse_options (&line, args, client);
1076 if (rc)
1077 return send_error (ctx, rc);
1079 if (client->opts & OPT_INQUIRE)
1081 unsigned char *result;
1082 size_t len;
1084 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1085 if (rc)
1086 return send_error (ctx, rc);
1088 line = (char *) result;
1091 rc = do_delete (ctx, line);
1093 if (client->opts & OPT_INQUIRE)
1094 xfree (line);
1096 return send_error (ctx, rc);
1099 static gpg_error_t
1100 store_command (assuan_context_t ctx, char *line)
1102 struct client_s *client = assuan_get_pointer (ctx);
1103 gpg_error_t rc;
1104 size_t len;
1105 unsigned char *result;
1106 char **req;
1107 xmlNodePtr n, parent;
1108 int has_content;
1109 char *content = NULL;
1111 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1112 if (rc)
1113 return send_error (ctx, rc);
1115 req = str_split ((char *) result, "\t", 0);
1116 xfree (result);
1118 if (!req || !*req)
1119 return send_error (ctx, GPG_ERR_SYNTAX);
1121 len = strv_length (req);
1122 has_content = line[strlen (line) - 1] != '\t' && len > 1;
1123 if (*(req + 1) && !valid_element_path (req, has_content))
1125 strv_free (req);
1126 return send_error (ctx, GPG_ERR_INV_VALUE);
1129 if (has_content || !*req[len - 1])
1131 has_content = 1;
1132 content = req[len - 1];
1133 req[len - 1] = NULL;
1136 again:
1137 n = find_root_element (client->doc, &req, &rc, NULL, 0, 0);
1138 if (rc && rc == GPG_ERR_ELEMENT_NOT_FOUND)
1140 rc = new_root_element (client->doc, *req);
1141 if (rc)
1143 strv_free (req);
1144 return send_error (ctx, GPG_ERR_SYNTAX);
1147 goto again;
1150 if (!n)
1152 strv_free (req);
1153 return send_error (ctx, rc);
1156 parent = n;
1158 if (req[1] && *req[1])
1160 if (!n->children)
1161 parent = create_elements_cb (n, req + 1, &rc, NULL);
1162 else
1163 parent = find_elements (client->doc, n->children, req + 1, &rc,
1164 NULL, NULL, create_elements_cb, 0, 0, NULL,
1168 if (!rc && len > 1)
1170 n = find_text_node (parent->children);
1171 if (n)
1172 xmlNodeSetContent (n, (xmlChar *) content);
1173 else
1174 xmlNodeAddContent (parent, (xmlChar *) content);
1176 update_element_mtime (parent);
1179 xfree (content);
1180 strv_free (req);
1181 return send_error (ctx, rc);
1184 static gpg_error_t
1185 xfer_data (assuan_context_t ctx, const char *line, int total)
1187 int to_send;
1188 int sent = 0;
1189 gpg_error_t rc;
1190 int progress = config_get_integer ("global", "xfer_progress");
1191 int flush = 0;
1193 progress =
1194 progress > 0 ? (progress / ASSUAN_LINELENGTH) * ASSUAN_LINELENGTH : 0;
1195 to_send = total < ASSUAN_LINELENGTH ? total : ASSUAN_LINELENGTH;
1196 rc = send_status (ctx, STATUS_XFER, "%li %li", sent, total);
1198 if (rc)
1199 return rc;
1201 again:
1204 if (sent + to_send > total)
1205 to_send = total - sent;
1207 rc = assuan_send_data (ctx, flush ? NULL : (char *) line + sent,
1208 flush ? 0 : to_send);
1209 if (!rc)
1211 sent += flush ? 0 : to_send;
1213 if ((progress && !(sent % progress) && sent != total) ||
1214 (sent == total && flush))
1215 rc = send_status (ctx, STATUS_XFER, "%li %li", sent, total);
1217 if (!flush && !rc && sent == total)
1219 flush = 1;
1220 goto again;
1224 while (!rc && sent < total);
1226 return rc;
1229 static gpg_error_t
1230 do_get (assuan_context_t ctx, char *line)
1232 struct client_s *client = assuan_get_pointer (ctx);
1233 gpg_error_t rc;
1234 char **req;
1235 xmlNodePtr n;
1237 req = str_split (line, "\t", 0);
1239 if (!req || !*req)
1241 strv_free (req);
1242 return GPG_ERR_SYNTAX;
1245 n = find_root_element (client->doc, &req, &rc, NULL, 0, 0);
1246 if (!n)
1248 strv_free (req);
1249 return rc;
1252 if (req[1])
1254 find_elements (client->doc, n->children, req + 1, &rc, NULL, NULL, NULL,
1255 0, 0, NULL, 0);
1257 strv_free (req);
1258 if (rc)
1259 return rc;
1261 if (!n || !n->children)
1262 return GPG_ERR_NO_DATA;
1264 n = find_text_node (n->children);
1265 if (!n || !n->content || !*n->content)
1266 return GPG_ERR_NO_DATA;
1268 rc = xfer_data (ctx, (char *) n->content, xmlStrlen (n->content));
1269 return rc;
1272 static gpg_error_t
1273 get_command (assuan_context_t ctx, char *line)
1275 struct client_s *client = assuan_get_pointer (ctx);
1276 gpg_error_t rc;
1277 struct argv_s *args[] = {
1278 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1279 NULL
1282 rc = parse_options (&line, args, client);
1283 if (rc)
1284 return send_error (ctx, rc);
1286 if (client->opts & OPT_INQUIRE)
1288 unsigned char *result;
1289 size_t len;
1291 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1292 if (rc)
1293 return send_error (ctx, rc);
1295 line = (char *) result;
1298 rc = do_get (ctx, line);
1300 if (client->opts & OPT_INQUIRE)
1301 xfree (line);
1303 return send_error (ctx, rc);
1306 static void list_command_cleanup1 (void *arg);
1307 static gpg_error_t
1308 realpath_command (assuan_context_t ctx, char *line)
1310 struct string_s *string = NULL;
1311 gpg_error_t rc;
1312 struct client_s *client = assuan_get_pointer (ctx);
1313 struct argv_s *args[] = {
1314 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1315 NULL
1318 rc = parse_options (&line, args, client);
1319 if (rc)
1320 return send_error (ctx, rc);
1322 if (client->opts & OPT_INQUIRE)
1324 unsigned char *result;
1325 size_t len;
1327 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1328 if (rc)
1329 return send_error (ctx, rc);
1331 line = (char *) result;
1334 rc = build_realpath (client->doc, line, &string);
1335 if (!rc)
1337 pthread_cleanup_push (list_command_cleanup1, string);
1338 rc = xfer_data (ctx, string->str, string->len);
1339 pthread_cleanup_pop (1);
1342 if (client->opts & OPT_INQUIRE)
1343 xfree (line);
1345 return send_error (ctx, rc);
1348 static void
1349 list_command_cleanup1 (void *arg)
1351 if (arg)
1352 string_free ((struct string_s *) arg, 1);
1355 static void
1356 list_command_cleanup2 (void *arg)
1358 struct element_list_s *elements = arg;
1360 if (elements)
1362 if (elements->list)
1364 int total = slist_length (elements->list);
1365 int i;
1367 for (i = 0; i < total; i++)
1369 char *tmp = slist_nth_data (elements->list, i);
1370 xfree (tmp);
1373 slist_free (elements->list);
1376 if (elements->prefix)
1377 xfree (elements->prefix);
1379 if (elements->req)
1380 strv_free (elements->req);
1382 xfree (elements);
1386 static gpg_error_t
1387 parse_list_opt_norecurse (void *data, void *value)
1389 struct client_s *client = data;
1391 client->opts &= ~(OPT_LIST_RECURSE);
1392 return 0;
1395 static gpg_error_t
1396 parse_list_opt_verbose (void *data, void *value)
1398 struct client_s *client = data;
1400 client->opts |= OPT_LIST_VERBOSE;
1401 return 0;
1404 static gpg_error_t
1405 parse_list_opt_target (void *data, void *value)
1407 struct client_s *client = data;
1409 client->opts |= OPT_LIST_WITH_TARGET;
1410 return 0;
1413 static gpg_error_t
1414 parse_list_opt_all (void *data, void *value)
1416 struct client_s *client = data;
1418 client->opts |= OPT_LIST_ALL;
1419 return 0;
1422 static gpg_error_t
1423 list_path_once (struct client_s *client, char *line,
1424 struct element_list_s *elements, struct string_s *result)
1426 gpg_error_t rc;
1428 elements->req = str_split (line, " ", 0);
1429 if (!elements->req)
1430 strv_printf (&elements->req, "%s", line);
1432 rc = create_path_list (client->doc, elements, *elements->req);
1433 if (rc == GPG_ERR_ELOOP && elements->verbose)
1434 rc = 0;
1436 if (!rc)
1438 if (elements)
1440 int total = slist_length (elements->list);
1441 int i;
1443 if (!total)
1444 rc = GPG_ERR_NO_DATA;
1446 if (!rc)
1448 if (!rc)
1450 for (i = 0; i < total; i++)
1452 char *tmp = slist_nth_data (elements->list, i);
1454 string_append_printf (result, "%s%s", tmp,
1455 i + 1 == total ? "" : "\n");
1460 else
1461 rc = GPG_ERR_NO_DATA;
1464 return rc;
1467 static int
1468 has_list_flag (char *path, char *flags)
1470 char *p = path;
1472 while (*p && *++p != ' ');
1474 if (!*p)
1475 return 0;
1477 for (; *p; p++)
1479 char *f;
1481 for (f = flags; *f && *f != ' '; f++)
1483 if (*p == *f)
1484 return 1;
1488 return 0;
1491 static gpg_error_t
1492 do_list (assuan_context_t ctx, char *line)
1494 struct client_s *client = assuan_get_pointer (ctx);
1495 gpg_error_t rc;
1496 struct element_list_s *elements = NULL;
1498 elements = xcalloc (1, sizeof (struct element_list_s));
1499 if (!elements)
1500 return GPG_ERR_ENOMEM;
1502 elements->recurse = client->opts & OPT_LIST_RECURSE;
1503 elements->verbose =
1504 (client->opts & OPT_LIST_VERBOSE) | (client->opts & OPT_LIST_WITH_TARGET);
1505 elements->with_target = client->opts & OPT_LIST_WITH_TARGET;
1507 if (!line || !*line)
1509 struct string_s *str = NULL;
1511 pthread_cleanup_push (list_command_cleanup2, elements);
1512 rc = list_root_elements (client->doc, &str, elements->verbose,
1513 elements->with_target);
1514 pthread_cleanup_pop (1);
1515 pthread_cleanup_push (list_command_cleanup1, str);
1517 if (!rc)
1519 if (client->opts & OPT_LIST_ALL)
1521 char **roots = str_split (str->str, "\n", 0);
1522 char **p;
1524 pthread_cleanup_push (req_cleanup, roots);
1525 string_truncate (str, 0);
1527 for (p = roots; *p; p++)
1529 if (strchr (*p, ' '))
1531 if (has_list_flag (*p, "EO"))
1533 string_append_printf (str, "%s%s", *p,
1534 *(p + 1) ? "\n" : "");
1535 continue;
1539 elements = xcalloc (1, sizeof (struct element_list_s));
1540 if (!elements)
1542 rc = GPG_ERR_ENOMEM;
1543 break;
1546 elements->recurse = client->opts & OPT_LIST_RECURSE;
1547 elements->verbose =
1548 (client->opts & OPT_LIST_VERBOSE) | (client->opts &
1549 OPT_LIST_WITH_TARGET);
1550 elements->with_target = client->opts & OPT_LIST_WITH_TARGET;
1551 pthread_cleanup_push (list_command_cleanup2, elements);
1552 rc = list_path_once (client, *p, elements, str);
1553 pthread_cleanup_pop (1);
1554 if (rc)
1555 break;
1557 if (*(p + 1))
1558 string_append (str, "\n");
1561 pthread_cleanup_pop (1);
1564 if (!rc)
1565 rc = xfer_data (ctx, str->str, str->len);
1568 pthread_cleanup_pop (1);
1569 return rc;
1572 pthread_cleanup_push (list_command_cleanup2, elements);
1573 struct string_s *str = string_new (NULL);
1574 pthread_cleanup_push (list_command_cleanup1, str);
1575 rc = list_path_once (client, line, elements, str);
1576 if (!rc)
1577 rc = xfer_data (ctx, str->str, str->len);
1579 pthread_cleanup_pop (1);
1580 pthread_cleanup_pop (1);
1581 return rc;
1584 static gpg_error_t
1585 list_command (assuan_context_t ctx, char *line)
1587 struct client_s *client = assuan_get_pointer (ctx);
1588 gpg_error_t rc;
1589 struct argv_s *args[] = {
1590 &(struct argv_s) {"no-recurse", OPTION_TYPE_NOARG,
1591 parse_list_opt_norecurse},
1592 &(struct argv_s) {"verbose", OPTION_TYPE_NOARG, parse_list_opt_verbose},
1593 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1594 &(struct argv_s) {"with-target", OPTION_TYPE_NOARG,
1595 parse_list_opt_target},
1596 &(struct argv_s) {"all", OPTION_TYPE_NOARG, parse_list_opt_all},
1597 NULL
1600 if (disable_list_and_dump == 1)
1601 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
1603 client->opts |= OPT_LIST_RECURSE;
1604 rc = parse_options (&line, args, client);
1605 if (rc)
1606 return send_error (ctx, rc);
1608 if (client->opts & OPT_LIST_ALL)
1609 client->opts |= OPT_LIST_RECURSE | OPT_LIST_VERBOSE;
1611 if (client->opts & OPT_INQUIRE)
1613 unsigned char *result;
1614 size_t len;
1616 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1617 if (rc)
1618 return send_error (ctx, rc);
1620 line = (char *) result;
1623 rc = do_list (ctx, line);
1625 if (client->opts & OPT_INQUIRE)
1626 xfree (line);
1628 return send_error (ctx, rc);
1632 * req[0] - element path
1634 static gpg_error_t
1635 attribute_list (assuan_context_t ctx, char **req)
1637 struct client_s *client = assuan_get_pointer (ctx);
1638 char **attrlist = NULL;
1639 int i = 0;
1640 char **path = NULL;
1641 xmlAttrPtr a;
1642 xmlNodePtr n, an;
1643 char *line;
1644 gpg_error_t rc;
1646 if (!req || !req[0])
1647 return GPG_ERR_SYNTAX;
1649 if ((path = str_split (req[0], "\t", 0)) == NULL)
1652 * The first argument may be only a root element.
1654 if ((path = str_split (req[0], " ", 0)) == NULL)
1655 return GPG_ERR_SYNTAX;
1658 n = find_root_element (client->doc, &path, &rc, NULL, 0, 0);
1660 if (!n)
1662 strv_free (path);
1663 return rc;
1666 if (path[1])
1668 n = find_elements (client->doc, n->children, path + 1, &rc,
1669 NULL, NULL, NULL, 0, 0, NULL, 0);
1671 if (!n)
1673 strv_free (path);
1674 return rc;
1678 strv_free (path);
1680 for (a = n->properties; a; a = a->next)
1682 char **pa;
1684 if ((pa = xrealloc (attrlist, (i + 2) * sizeof (char *))) == NULL)
1686 if (attrlist)
1687 strv_free (attrlist);
1689 log_write ("%s(%i): %s", __FILE__, __LINE__,
1690 pwmd_strerror (GPG_ERR_ENOMEM));
1691 return GPG_ERR_ENOMEM;
1694 attrlist = pa;
1695 an = a->children;
1696 attrlist[i] = str_asprintf ("%s %s", (char *) a->name,
1698 && an->content ? (char *) an->content : "");
1700 if (!attrlist[i])
1702 strv_free (attrlist);
1703 log_write ("%s(%i): %s", __FILE__, __LINE__,
1704 pwmd_strerror (GPG_ERR_ENOMEM));
1705 return GPG_ERR_ENOMEM;
1708 attrlist[++i] = NULL;
1711 if (!attrlist)
1712 return GPG_ERR_NO_DATA;
1714 line = strv_join ("\n", attrlist);
1716 if (!line)
1718 log_write ("%s(%i): %s", __FILE__, __LINE__,
1719 pwmd_strerror (GPG_ERR_ENOMEM));
1720 strv_free (attrlist);
1721 return GPG_ERR_ENOMEM;
1724 pthread_cleanup_push (xfree, line);
1725 pthread_cleanup_push (req_cleanup, attrlist);
1726 rc = xfer_data (ctx, line, strlen (line));
1727 pthread_cleanup_pop (1);
1728 pthread_cleanup_pop (1);
1729 return rc;
1733 * req[0] - attribute
1734 * req[1] - element path
1736 static gpg_error_t
1737 attribute_delete (struct client_s *client, char **req)
1739 xmlNodePtr n;
1740 char **path = NULL;
1741 gpg_error_t rc;
1743 if (!req || !req[0] || !req[1])
1744 return GPG_ERR_SYNTAX;
1746 if (!strcmp (req[0], "_name"))
1747 return GPG_ERR_INV_ATTR;
1749 if ((path = str_split (req[1], "\t", 0)) == NULL)
1752 * The first argument may be only a root element.
1754 if ((path = str_split (req[1], " ", 0)) == NULL)
1755 return GPG_ERR_SYNTAX;
1758 n = find_root_element (client->doc, &path, &rc, NULL, 0, 0);
1759 if (!n)
1760 goto fail;
1762 if (path[1])
1764 n = find_elements (client->doc, n->children, path + 1, &rc,
1765 NULL, NULL, NULL, 0, 0, NULL, 0);
1766 if (!n)
1767 goto fail;
1770 rc = delete_attribute (n, (xmlChar *) req[0]);
1772 fail:
1773 strv_free (path);
1774 return rc;
1777 static xmlNodePtr
1778 create_element_path (struct client_s *client,
1779 char ***elements, gpg_error_t * rc, xmlNodePtr parent)
1781 char **req = *elements;
1782 char **req_orig = strv_dup (req);
1783 xmlNodePtr n = NULL;
1785 *rc = 0;
1787 if (!req_orig)
1789 *rc = GPG_ERR_ENOMEM;
1790 log_write ("%s(%i): %s", __FILE__, __LINE__,
1791 pwmd_strerror (GPG_ERR_ENOMEM));
1792 goto fail;
1795 again:
1796 n = find_root_element (client->doc, &req, rc, NULL, 0, 0);
1797 if (!n)
1799 if (*rc != GPG_ERR_ELEMENT_NOT_FOUND)
1800 goto fail;
1802 *rc = new_root_element (client->doc, req[0]);
1803 if (*rc)
1804 goto fail;
1806 goto again;
1808 else if (n == parent)
1810 *rc = GPG_ERR_CONFLICT;
1811 goto fail;
1814 if (req[1])
1816 if (!n->children)
1817 n = create_target_elements_cb (n, req + 1, rc, NULL);
1818 else
1819 n = find_elements (client->doc, n->children, req + 1, rc, NULL, NULL,
1820 create_target_elements_cb, 0, 0, parent, 0);
1822 if (!n)
1823 goto fail;
1826 * Reset the position of the element tree now that the elements
1827 * have been created.
1829 strv_free (req);
1830 req = req_orig;
1831 req_orig = NULL;
1832 n = find_root_element (client->doc, &req, rc, NULL, 0, 0);
1833 if (!n)
1834 goto fail;
1836 n = find_elements (client->doc, n->children, req + 1, rc,
1837 NULL, NULL, NULL, 0, 0, NULL, 0);
1838 if (!n)
1839 goto fail;
1842 fail:
1843 if (req_orig)
1844 strv_free (req_orig);
1846 *elements = req;
1847 return n;
1851 * Creates a "target" attribute. When other commands encounter an element with
1852 * this attribute, the element path is modified to the target value. If the
1853 * source element path doesn't exist when using 'ATTR SET target', it is
1854 * created, but the destination element path must exist.
1856 * req[0] - source element path
1857 * req[1] - destination element path
1859 static gpg_error_t
1860 target_attribute (struct client_s *client, char **req)
1862 char **src, **dst, *line = NULL, **odst = NULL;
1863 gpg_error_t rc;
1864 xmlNodePtr n;
1866 if (!req || !req[0] || !req[1])
1867 return GPG_ERR_SYNTAX;
1869 if ((src = str_split (req[0], "\t", 0)) == NULL)
1872 * The first argument may be only a root element.
1874 if ((src = str_split (req[0], " ", 0)) == NULL)
1875 return GPG_ERR_SYNTAX;
1878 if (!valid_element_path (src, 0))
1879 return GPG_ERR_INV_VALUE;
1881 if ((dst = str_split (req[1], "\t", 0)) == NULL)
1884 * The first argument may be only a root element.
1886 if ((dst = str_split (req[1], " ", 0)) == NULL)
1888 rc = GPG_ERR_SYNTAX;
1889 goto fail;
1893 odst = strv_dup (dst);
1894 if (!odst)
1896 rc = GPG_ERR_ENOMEM;
1897 goto fail;
1900 n = find_root_element (client->doc, &dst, &rc, NULL, 0, 0);
1902 * Make sure the destination element path exists.
1904 if (!n)
1905 goto fail;
1907 if (dst[1])
1909 n = find_elements (client->doc, n->children, dst + 1, &rc,
1910 NULL, NULL, NULL, 0, 0, NULL, 0);
1911 if (!n)
1912 goto fail;
1915 rc = validate_target_attribute (client->doc, req[0], n);
1916 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
1917 goto fail;
1919 n = create_element_path (client, &src, &rc, NULL);
1920 if (rc)
1921 goto fail;
1923 line = strv_join ("\t", odst);
1924 if (!line)
1926 rc = GPG_ERR_ENOMEM;
1927 goto fail;
1930 rc = add_attribute (n, "target", line);
1932 fail:
1933 xfree (line);
1934 strv_free (src);
1935 strv_free (dst);
1936 strv_free (odst);
1937 return rc;
1941 * req[0] - attribute
1942 * req[1] - element path
1944 static gpg_error_t
1945 attribute_get (assuan_context_t ctx, char **req)
1947 struct client_s *client = assuan_get_pointer (ctx);
1948 xmlNodePtr n;
1949 xmlChar *a;
1950 char **path = NULL;
1951 gpg_error_t rc;
1953 if (!req || !req[0] || !req[1])
1954 return GPG_ERR_SYNTAX;
1956 if (strchr (req[1], '\t'))
1958 if ((path = str_split (req[1], "\t", 0)) == NULL)
1959 return GPG_ERR_SYNTAX;
1961 else
1963 if ((path = str_split (req[1], " ", 0)) == NULL)
1964 return GPG_ERR_SYNTAX;
1967 n = find_root_element (client->doc, &path, &rc, NULL, 0, 0);
1969 if (!n)
1970 goto fail;
1972 if (path[1])
1974 n = find_elements (client->doc, n->children, path + 1, &rc,
1975 NULL, NULL, NULL, 0, 0, NULL, 0);
1977 if (!n)
1978 goto fail;
1981 strv_free (path);
1983 if ((a = xmlGetProp (n, (xmlChar *) req[0])) == NULL)
1984 return GPG_ERR_NOT_FOUND;
1986 pthread_cleanup_push (xmlFree, a);
1988 if (*a)
1989 rc = xfer_data (ctx, (char *) a, xmlStrlen (a));
1990 else
1991 rc = GPG_ERR_NO_DATA;
1993 pthread_cleanup_pop (1);
1994 return rc;
1996 fail:
1997 strv_free (path);
1998 return rc;
2002 * req[0] - attribute
2003 * req[1] - element path
2004 * req[2] - value
2006 static gpg_error_t
2007 attribute_set (struct client_s *client, char **req)
2009 char **path = NULL;
2010 gpg_error_t rc;
2011 xmlNodePtr n;
2013 if (!req || !req[0] || !req[1])
2014 return GPG_ERR_SYNTAX;
2017 * Reserved attribute names.
2019 if (!strcmp (req[0], "_name"))
2020 return GPG_ERR_INV_ATTR;
2021 else if (!strcmp (req[0], "target"))
2022 return target_attribute (client, req + 1);
2024 if ((path = str_split (req[1], "\t", 0)) == NULL)
2027 * The first argument may be only a root element.
2029 if ((path = str_split (req[1], " ", 0)) == NULL)
2030 return GPG_ERR_SYNTAX;
2033 n = find_root_element (client->doc, &path, &rc, NULL, 0, 0);
2035 if (!n)
2036 goto fail;
2038 if (path[1])
2040 n = find_elements (client->doc, n->children, path + 1, &rc,
2041 NULL, NULL, NULL, 0, 0, NULL, 0);
2043 if (!n)
2044 goto fail;
2047 rc = add_attribute (n, req[0], req[2]);
2049 fail:
2050 strv_free (path);
2051 return rc;
2055 * req[0] - command
2056 * req[1] - attribute name or element path if command is LIST
2057 * req[2] - element path
2058 * req[2] - element path or value
2061 static gpg_error_t
2062 do_attr (assuan_context_t ctx, char *line)
2064 struct client_s *client = assuan_get_pointer (ctx);
2065 gpg_error_t rc = 0;
2066 char **req;
2068 req = str_split (line, " ", 4);
2069 if (!req || !req[0] || !req[1])
2071 strv_free (req);
2072 return GPG_ERR_SYNTAX;
2075 pthread_cleanup_push (req_cleanup, req);
2077 if (strcasecmp (req[0], "SET") == 0)
2078 rc = attribute_set (client, req + 1);
2079 else if (strcasecmp (req[0], "GET") == 0)
2080 rc = attribute_get (ctx, req + 1);
2081 else if (strcasecmp (req[0], "DELETE") == 0)
2082 rc = attribute_delete (client, req + 1);
2083 else if (strcasecmp (req[0], "LIST") == 0)
2084 rc = attribute_list (ctx, req + 1);
2085 else
2086 rc = GPG_ERR_SYNTAX;
2088 pthread_cleanup_pop (1);
2089 return rc;
2092 static gpg_error_t
2093 attr_command (assuan_context_t ctx, char *line)
2095 struct client_s *client = assuan_get_pointer (ctx);
2096 gpg_error_t rc;
2097 struct argv_s *args[] = {
2098 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
2099 NULL
2102 rc = parse_options (&line, args, client);
2103 if (rc)
2104 return send_error (ctx, rc);
2106 if (client->opts & OPT_INQUIRE)
2108 unsigned char *result;
2109 size_t len;
2111 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
2112 if (rc)
2113 return send_error (ctx, rc);
2115 line = (char *) result;
2118 rc = do_attr (ctx, line);
2120 if (client->opts & OPT_INQUIRE)
2121 xfree (line);
2123 return send_error (ctx, rc);
2126 static gpg_error_t
2127 parse_iscached_opt_lock (void *data, void *value)
2129 struct client_s *client = data;
2131 (void) value;
2132 client->opts |= OPT_LOCK;
2133 return 0;
2136 static gpg_error_t
2137 iscached_command (assuan_context_t ctx, char *line)
2139 struct client_s *client = assuan_get_pointer (ctx);
2140 gpg_error_t rc;
2141 unsigned char md5file[16];
2142 struct argv_s *args[] = {
2143 &(struct argv_s) {"lock", OPTION_TYPE_NOARG, parse_iscached_opt_lock},
2144 NULL
2147 if (!line || !*line)
2148 return send_error (ctx, GPG_ERR_SYNTAX);
2150 rc = parse_options (&line, args, client);
2151 if (rc)
2152 return send_error (ctx, rc);
2153 else if (!valid_filename (line))
2154 return send_error (ctx, GPG_ERR_INV_VALUE);
2156 rc = cache_iscached (line, NULL);
2157 if (client->opts & OPT_LOCK
2158 && (!rc || gpg_err_code (rc) == GPG_ERR_NO_DATA))
2160 gpg_error_t trc = rc;
2161 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, line, strlen (line));
2162 if (memcmp (md5file, client->md5file, 16))
2163 cleanup_client (client);
2165 memcpy (client->md5file, md5file, 16);
2166 rc = do_lock (client, 1);
2167 if (!rc)
2168 rc = trc;
2171 return send_error (ctx, rc);
2174 static gpg_error_t
2175 clearcache_command (assuan_context_t ctx, char *line)
2177 gpg_error_t rc = 0, all_rc = 0;
2178 unsigned char md5file[16];
2179 int i;
2180 int t;
2181 int all = 0;
2182 struct client_thread_s *once = NULL;
2184 cache_lock ();
2185 MUTEX_LOCK (&cn_mutex);
2186 pthread_cleanup_push (cleanup_mutex_cb, &cn_mutex);
2188 if (!line || !*line)
2189 all = 1;
2191 t = slist_length (cn_thread_list);
2193 for (i = 0; i < t; i++)
2195 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
2197 if (!thd->cl)
2198 continue;
2200 /* Lock each connected clients' file mutex to prevent any other client
2201 * from accessing the cache entry (the file mutex is locked upon
2202 * command startup). The cache for the entry is not cleared if the
2203 * file mutex is locked by another client to prevent this function
2204 * from blocking.
2206 if (all)
2208 rc = cache_lock_mutex (thd->cl->ctx, thd->cl->md5file, -1, 0, -1);
2209 if (gpg_err_code (rc) == GPG_ERR_LOCKED)
2211 if (pthread_equal (pthread_self (), thd->tid))
2212 rc = 0;
2213 else
2215 if (!thd->cl->filename ||
2216 cache_iscached (thd->cl->filename,
2217 NULL) == GPG_ERR_NO_DATA)
2219 rc = 0;
2220 continue;
2223 cache_defer_clear (thd->cl->md5file);
2226 else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
2228 rc = 0;
2229 continue;
2232 if (!rc)
2234 rc = cache_clear (thd->cl->md5file);
2235 if (rc)
2236 all_rc = rc;
2238 cache_unlock_mutex (thd->cl->md5file, 0);
2240 else
2241 all_rc = rc;
2243 rc = 0;
2245 /* A single data filename was specified. Lock only this data file
2246 * mutex and free the cache entry. */
2247 else
2249 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, line, strlen (line));
2251 if (!memcmp (thd->cl->md5file, md5file, sizeof (md5file)))
2253 rc =
2254 cache_lock_mutex (thd->cl->ctx, thd->cl->md5file, -1, 0, -1);
2255 if (gpg_err_code (rc) == GPG_ERR_LOCKED)
2257 if (pthread_equal (pthread_self (), thd->tid))
2258 rc = 0;
2261 if (!rc)
2263 once = thd;
2264 rc = cache_clear (thd->cl->md5file);
2265 cache_unlock_mutex (thd->cl->md5file, 0);
2267 else
2268 cache_defer_clear (thd->cl->md5file);
2270 break;
2275 /* Only connected clients' cache entries have been cleared. Now clear any
2276 * remaining cache entries without clients but only if there wasn't an
2277 * error from above since this would defeat the locking check of the
2278 * remaining entries. */
2279 if (!all_rc && all)
2280 cache_clear (NULL);
2281 /* No clients are using the specified file. */
2282 else if (!all_rc && !rc && !once)
2284 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, line, strlen (line));
2285 rc = cache_clear (md5file);
2288 /* Release the connection mutex. */
2289 pthread_cleanup_pop (1);
2290 cache_unlock ();
2292 if (!rc)
2293 send_status_all (STATUS_CACHE, NULL);
2295 /* One or more files were locked while clearing all cache entries. */
2296 if (all_rc)
2297 rc = all_rc;
2299 return send_error (ctx, rc);
2302 static gpg_error_t
2303 cachetimeout_command (assuan_context_t ctx, char *line)
2305 unsigned char md5file[16];
2306 int timeout;
2307 char **req = str_split (line, " ", 0);
2308 char *p;
2309 gpg_error_t rc = 0;
2311 if (!req || !*req || !req[1])
2313 strv_free (req);
2314 return send_error (ctx, GPG_ERR_SYNTAX);
2317 errno = 0;
2318 timeout = (int) strtol (req[1], &p, 10);
2319 if (errno != 0 || *p || timeout < -1)
2321 strv_free (req);
2322 return send_error (ctx, GPG_ERR_SYNTAX);
2325 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, req[0], strlen (req[0]));
2326 rc = cache_set_timeout (md5file, timeout);
2327 if (!rc)
2329 MUTEX_LOCK (&rcfile_mutex);
2330 config_set_int_param (&global_config, req[0], "cache_timeout", req[1]);
2331 MUTEX_UNLOCK (&rcfile_mutex);
2334 strv_free (req);
2335 return send_error (ctx, rc);
2338 static gpg_error_t
2339 dump_command (assuan_context_t ctx, char *line)
2341 xmlChar *xml;
2342 int len;
2343 struct client_s *client = assuan_get_pointer (ctx);
2344 gpg_error_t rc;
2346 if (disable_list_and_dump == 1)
2347 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
2349 xmlDocDumpFormatMemory (client->doc, &xml, &len, 1);
2351 if (!xml)
2353 log_write ("%s(%i): %s", __FILE__, __LINE__,
2354 pwmd_strerror (GPG_ERR_ENOMEM));
2355 return send_error (ctx, GPG_ERR_ENOMEM);
2358 pthread_cleanup_push (xmlFree, xml);
2359 rc = xfer_data (ctx, (char *) xml, len);
2360 pthread_cleanup_pop (1);
2361 return send_error (ctx, rc);
2364 static gpg_error_t
2365 getconfig_command (assuan_context_t ctx, char *line)
2367 struct client_s *client = assuan_get_pointer (ctx);
2368 gpg_error_t rc = 0;
2369 char filename[255] = { 0 }, param[747] =
2372 char *p, *tmp = NULL, *fp = client->filename, *paramp = line;
2374 if (!line || !*line)
2375 return send_error (ctx, GPG_ERR_SYNTAX);
2377 if (strchr (line, ' '))
2379 sscanf (line, " %254[^ ] %746c", filename, param);
2380 paramp = param;
2381 fp = filename;
2384 if (fp && !valid_filename (fp))
2385 return send_error (ctx, GPG_ERR_INV_VALUE);
2387 paramp = str_down (paramp);
2388 if (!strcmp (paramp, "cipher") && fp)
2390 struct crypto_s *crypto;
2392 rc = init_client_crypto (&crypto);
2393 if (!rc)
2395 rc = read_data_header (fp, &crypto->hdr, NULL, NULL);
2396 if (!rc)
2398 const char *t =
2399 gcry_cipher_algo_name (cipher_to_gcrypt (crypto->hdr.flags));
2400 if (t)
2402 tmp = str_dup (t);
2403 if (tmp)
2404 str_down (tmp);
2409 cleanup_crypto (&crypto);
2410 if (rc && gpg_err_code (rc) != GPG_ERR_ENOENT)
2411 return send_error (ctx, rc);
2413 if (!rc && tmp)
2414 goto done;
2416 else if (!strcmp (paramp, "cipher_iterations") && fp)
2418 struct crypto_s *crypto;
2420 rc = init_client_crypto (&crypto);
2421 if (!rc)
2423 rc = read_data_header (fp, &crypto->hdr, NULL, NULL);
2424 if (!rc)
2426 tmp = str_asprintf ("%llu",
2427 (unsigned long long) crypto->hdr.
2428 iterations);
2429 if (!tmp)
2430 rc = GPG_ERR_ENOMEM;
2434 cleanup_crypto (&crypto);
2435 if (rc && gpg_err_code (rc) != GPG_ERR_ENOENT)
2436 return send_error (ctx, rc);
2438 if (!rc && tmp)
2439 goto done;
2441 else if (!strcmp (paramp, "passphrase"))
2442 return send_error (ctx, GPG_ERR_UNKNOWN_OPTION);
2444 p = config_get_value (fp ? fp : "global", paramp);
2445 if (!p)
2446 return send_error (ctx, GPG_ERR_UNKNOWN_OPTION);
2448 tmp = expand_homedir (p);
2449 xfree (p);
2450 if (!tmp)
2452 log_write ("%s(%i): %s", __FILE__, __LINE__,
2453 pwmd_strerror (GPG_ERR_ENOMEM));
2454 return send_error (ctx, GPG_ERR_ENOMEM);
2457 done:
2458 p = tmp;
2459 pthread_cleanup_push (xfree, p);
2460 rc = xfer_data (ctx, p, strlen (p));
2461 pthread_cleanup_pop (1);
2462 return send_error (ctx, rc);
2465 struct xpath_s
2467 xmlXPathContextPtr xp;
2468 xmlXPathObjectPtr result;
2469 xmlBufferPtr buf;
2470 char **req;
2473 static void
2474 xpath_command_cleanup (void *arg)
2476 struct xpath_s *xpath = arg;
2478 if (!xpath)
2479 return;
2481 req_cleanup (xpath->req);
2483 if (xpath->buf)
2484 xmlBufferFree (xpath->buf);
2486 if (xpath->result)
2487 xmlXPathFreeObject (xpath->result);
2489 if (xpath->xp)
2490 xmlXPathFreeContext (xpath->xp);
2493 static gpg_error_t
2494 do_xpath (assuan_context_t ctx, char *line)
2496 gpg_error_t rc;
2497 struct client_s *client = assuan_get_pointer (ctx);
2498 struct xpath_s _x = { 0 };
2499 struct xpath_s *xpath = &_x;
2501 if ((xpath->req = str_split (line, "\t", 2)) == NULL)
2503 if (strv_printf (&xpath->req, "%s", line) == 0)
2504 return GPG_ERR_ENOMEM;
2507 xpath->xp = xmlXPathNewContext (client->doc);
2508 if (!xpath->xp)
2510 rc = GPG_ERR_BAD_DATA;
2511 goto fail;
2514 xpath->result =
2515 xmlXPathEvalExpression ((xmlChar *) xpath->req[0], xpath->xp);
2516 if (!xpath->result)
2518 rc = GPG_ERR_BAD_DATA;
2519 goto fail;
2522 if (xmlXPathNodeSetIsEmpty (xpath->result->nodesetval))
2524 rc = GPG_ERR_ELEMENT_NOT_FOUND;
2525 goto fail;
2528 rc = recurse_xpath_nodeset (client->doc, xpath->result->nodesetval,
2529 (xmlChar *) xpath->req[1], &xpath->buf, 0,
2530 NULL);
2531 if (rc)
2532 goto fail;
2533 else if (!xpath->req[1] && !xmlBufferLength (xpath->buf))
2535 rc = GPG_ERR_NO_DATA;
2536 goto fail;
2538 else if (xpath->req[1])
2540 rc = 0;
2541 goto fail;
2544 pthread_cleanup_push (xpath_command_cleanup, &xpath);
2545 rc = xfer_data (ctx, (char *) xmlBufferContent (xpath->buf),
2546 xmlBufferLength (xpath->buf));
2547 pthread_cleanup_pop (0);
2548 fail:
2549 xpath_command_cleanup (xpath);
2550 return rc;
2553 static gpg_error_t
2554 xpath_command (assuan_context_t ctx, char *line)
2556 struct client_s *client = assuan_get_pointer (ctx);
2557 gpg_error_t rc;
2558 struct argv_s *args[] = {
2559 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
2560 NULL
2563 if (disable_list_and_dump == 1)
2564 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
2566 rc = parse_options (&line, args, client);
2567 if (rc)
2568 return send_error (ctx, rc);
2570 if (client->opts & OPT_INQUIRE)
2572 unsigned char *result;
2573 size_t len;
2575 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
2576 if (rc)
2577 return send_error (ctx, rc);
2579 line = (char *) result;
2582 if (!line || !*line)
2583 rc = GPG_ERR_SYNTAX;
2585 if (!rc)
2586 rc = do_xpath (ctx, line);
2588 if (client->opts & OPT_INQUIRE)
2589 xfree (line);
2591 return send_error (ctx, rc);
2594 static gpg_error_t
2595 do_xpathattr (assuan_context_t ctx, char *line)
2597 struct client_s *client = assuan_get_pointer (ctx);
2598 gpg_error_t rc;
2599 char **req = NULL;
2600 int cmd = 0; //SET
2601 struct xpath_s _x = { 0 };
2602 struct xpath_s *xpath = &_x;
2604 if ((req = str_split (line, " ", 3)) == NULL)
2605 return GPG_ERR_ENOMEM;
2607 if (!req[0])
2609 rc = GPG_ERR_SYNTAX;
2610 goto fail;
2613 if (!strcasecmp (req[0], "SET"))
2614 cmd = 0;
2615 else if (!strcasecmp (req[0], "DELETE"))
2616 cmd = 1;
2617 else
2619 rc = GPG_ERR_SYNTAX;
2620 goto fail;
2623 if (!req[1] || !req[2])
2625 rc = GPG_ERR_SYNTAX;
2626 goto fail;
2629 if ((xpath->req = str_split (req[2], "\t", 3)) == NULL)
2631 rc = GPG_ERR_ENOMEM;
2632 goto fail;
2635 if (!xpath->req[0] || (!xpath->req[1] && !cmd) || (xpath->req[1] && cmd))
2637 rc = GPG_ERR_SYNTAX;
2638 goto fail;
2641 xpath->xp = xmlXPathNewContext (client->doc);
2642 if (!xpath->xp)
2644 rc = GPG_ERR_BAD_DATA;
2645 goto fail;
2648 xpath->result =
2649 xmlXPathEvalExpression ((xmlChar *) xpath->req[0], xpath->xp);
2650 if (!xpath->result)
2652 rc = GPG_ERR_BAD_DATA;
2653 goto fail;
2656 if (xmlXPathNodeSetIsEmpty (xpath->result->nodesetval))
2658 rc = GPG_ERR_ELEMENT_NOT_FOUND;
2659 goto fail;
2662 rc = recurse_xpath_nodeset (client->doc, xpath->result->nodesetval,
2663 (xmlChar *) xpath->req[1], &xpath->buf, cmd,
2664 (xmlChar *) req[1]);
2666 fail:
2667 xpath_command_cleanup (xpath);
2668 strv_free (req);
2669 return rc;
2672 /* XPATHATTR SET|DELETE <name> <expression>[<TAB>[value]] */
2673 static gpg_error_t
2674 xpathattr_command (assuan_context_t ctx, char *line)
2676 struct client_s *client = assuan_get_pointer (ctx);
2677 gpg_error_t rc;
2678 struct argv_s *args[] = {
2679 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
2680 NULL
2683 if (disable_list_and_dump == 1)
2684 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
2686 rc = parse_options (&line, args, client);
2687 if (rc)
2688 return send_error (ctx, rc);
2690 if (client->opts & OPT_INQUIRE)
2692 unsigned char *result;
2693 size_t len;
2695 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
2696 if (rc)
2697 return send_error (ctx, rc);
2699 line = (char *) result;
2702 if (!line || !*line)
2703 rc = GPG_ERR_SYNTAX;
2705 if (!rc)
2706 rc = do_xpathattr (ctx, line);
2708 if (client->opts & OPT_INQUIRE)
2709 xfree (line);
2711 return send_error (ctx, rc);
2714 static gpg_error_t
2715 do_import (struct client_s *client, unsigned char *line)
2717 char **req, **path = NULL, **path_orig = NULL, *content;
2718 xmlDocPtr doc = NULL;
2719 xmlNodePtr n, root, copy;
2720 gpg_error_t rc;
2722 req = str_split ((char *) line, "\t", 2);
2723 xfree (line);
2724 if (!req || !*req)
2725 return GPG_ERR_SYNTAX;
2727 content = req[0];
2728 path = str_split (req[1], "\t", 0);
2729 if (!content || !*content)
2731 rc = GPG_ERR_SYNTAX;
2732 goto fail;
2735 if (path && !valid_element_path (path, 0))
2737 rc = GPG_ERR_INV_VALUE;
2738 goto fail;
2741 doc = xmlReadDoc ((xmlChar *) content, NULL, "UTF-8", XML_PARSE_NOBLANKS);
2742 if (!doc)
2744 rc = GPG_ERR_BAD_DATA;
2745 goto fail;
2748 root = xmlDocGetRootElement (doc);
2749 rc = validate_import (root);
2750 if (rc)
2751 goto fail;
2753 if (path)
2755 path_orig = strv_dup (path);
2756 if (!path_orig)
2758 log_write ("%s(%i): %s", __FILE__, __LINE__,
2759 pwmd_strerror (GPG_ERR_ENOMEM));
2760 rc = GPG_ERR_ENOMEM;
2761 goto fail;
2764 xmlChar *a = xmlGetProp (root, (xmlChar *) "_name");
2765 if (!a)
2767 strv_free (path_orig);
2768 rc = GPG_ERR_ENOMEM;
2769 goto fail;
2772 if (strv_printf (&path, "%s", (char *) a) == 0)
2774 xmlFree (a);
2775 strv_free (path_orig);
2776 rc = GPG_ERR_ENOMEM;
2777 goto fail;
2780 xmlFree (a);
2781 n = find_root_element (client->doc, &path, &rc, NULL, 0, 0);
2783 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
2785 strv_free (path_orig);
2786 goto fail;
2789 if (!rc)
2792 find_elements (client->doc, n->children, path + 1, &rc, NULL,
2793 NULL, NULL, 0, 0, NULL, 1);
2795 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
2797 strv_free (path_orig);
2798 goto fail;
2800 else if (!rc)
2802 xmlNodePtr parent = n->parent;
2804 xmlUnlinkNode (n);
2805 xmlFreeNode (n);
2806 n = parent;
2810 strv_free (path);
2811 path = path_orig;
2813 if (rc == GPG_ERR_ELEMENT_NOT_FOUND)
2815 n = create_element_path (client, &path, &rc, NULL);
2817 if (rc)
2818 goto fail;
2821 copy = xmlCopyNodeList (root);
2822 n = xmlAddChildList (n, copy);
2823 if (!n)
2824 rc = GPG_ERR_BAD_DATA;
2826 else
2828 /* Check if the content root element can create a DTD root element. */
2829 if (!xmlStrEqual ((xmlChar *) "element", root->name))
2831 rc = GPG_ERR_SYNTAX;
2832 goto fail;
2835 xmlChar *a;
2837 if ((a = xmlGetProp (root, (xmlChar *) "_name")) == NULL)
2839 rc = GPG_ERR_SYNTAX;
2840 goto fail;
2843 char *tmp = str_dup ((char *) a);
2844 xmlFree (a);
2845 int literal = is_literal_element (&tmp);
2847 if (!valid_xml_element ((xmlChar *) tmp) || literal)
2849 xfree (tmp);
2850 rc = GPG_ERR_INV_VALUE;
2851 goto fail;
2854 if (strv_printf (&path, "%s", tmp) == 0)
2856 xfree (tmp);
2857 rc = GPG_ERR_ENOMEM;
2858 goto fail;
2861 xfree (tmp);
2862 n = find_root_element (client->doc, &path, &rc, NULL, 0, 1);
2864 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
2866 rc = GPG_ERR_BAD_DATA;
2867 goto fail;
2870 /* Overwriting the existing tree. */
2871 if (!rc)
2873 xmlUnlinkNode (n);
2874 xmlFreeNodeList (n);
2877 rc = 0;
2878 xmlSetProp (root, (xmlChar *) "_name", (xmlChar *) path[0]);
2879 n = xmlCopyNode (root, 1);
2880 n = xmlAddChildList (xmlDocGetRootElement (client->doc), n);
2883 if (n && !rc)
2884 rc = update_element_mtime (n->parent);
2886 fail:
2887 if (doc)
2888 xmlFreeDoc (doc);
2890 if (path)
2891 strv_free (path);
2893 strv_free (req);
2894 return rc;
2897 static gpg_error_t
2898 import_command (assuan_context_t ctx, char *line)
2900 gpg_error_t rc;
2901 struct client_s *client = assuan_get_pointer (ctx);
2902 unsigned char *result;
2903 size_t len;
2905 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
2906 if (rc)
2907 return send_error (ctx, rc);
2909 rc = do_import (client, result);
2910 return send_error (ctx, rc);
2913 static gpg_error_t
2914 do_lock (struct client_s *client, int add)
2916 gpg_error_t rc = lock_file_mutex (client, add);
2918 if (!rc)
2919 client->flags |= FLAG_LOCK_CMD;
2921 return rc;
2924 static gpg_error_t
2925 lock_command (assuan_context_t ctx, char *line)
2927 struct client_s *client = assuan_get_pointer (ctx);
2928 gpg_error_t rc = do_lock (client, 0);
2930 return send_error (ctx, rc);
2933 static gpg_error_t
2934 unlock_command (assuan_context_t ctx, char *line)
2936 struct client_s *client = assuan_get_pointer (ctx);
2937 gpg_error_t rc;
2939 rc = unlock_file_mutex (client, 0);
2940 return send_error (ctx, rc);
2943 static gpg_error_t
2944 option_command (assuan_context_t ctx, const char *name, const char *value)
2946 struct client_s *client = assuan_get_pointer (ctx);
2947 gpg_error_t rc = 0;
2948 #ifdef WITH_AGENT
2949 struct agent_s *agent = client->crypto->agent;
2950 #endif
2952 log_write1 ("OPTION name='%s' value='%s'", name, value);
2954 if (strcasecmp (name, (char *) "log_level") == 0)
2956 long l = 0;
2958 if (value)
2960 l = strtol (value, NULL, 10);
2962 if (l < 0 || l > 2)
2963 return gpg_error (GPG_ERR_INV_VALUE);
2966 MUTEX_LOCK (&rcfile_mutex);
2967 config_set_int_param (&global_config, "global", "log_level", value);
2968 MUTEX_UNLOCK (&rcfile_mutex);
2969 goto done;
2971 else if (strcasecmp (name, (char *) "lock-timeout") == 0)
2973 long n = 0;
2974 char *p = NULL;
2976 if (value)
2978 n = strtol (value, &p, 10);
2979 if (p && *p)
2980 return gpg_error (GPG_ERR_INV_VALUE);
2983 client->lock_timeout = n;
2984 goto done;
2986 else if (strcasecmp (name, (char *) "NAME") == 0)
2988 char *tmp = pthread_getspecific (thread_name_key);
2990 if (tmp)
2991 xfree (tmp);
2993 if (!value || !*value)
2995 pthread_setspecific (thread_name_key, str_dup (""));
2996 goto done;
2999 pthread_setspecific (thread_name_key, str_dup (value));
3000 goto done;
3002 else if (strcasecmp (name, (char *) "lc-messages") == 0)
3004 #ifdef WITH_AGENT
3005 if (use_agent)
3007 rc = set_agent_option (client->crypto->agent, "lc-messages", value);
3008 if (!rc)
3010 xfree (agent->lc_messages);
3011 agent->lc_messages = str_dup (value);
3014 #endif
3016 else if (strcasecmp (name, (char *) "lc-ctype") == 0)
3018 #ifdef WITH_AGENT
3019 rc = set_agent_option (client->crypto->agent, "lc-ctype", value);
3020 if (!rc)
3022 xfree (agent->lc_ctype);
3023 agent->lc_ctype = str_dup (value);
3025 #endif
3027 else if (strcasecmp (name, (char *) "ttyname") == 0)
3029 #ifdef WITH_AGENT
3030 if (use_agent)
3032 rc = set_agent_option (client->crypto->agent, "ttyname", value);
3033 if (!rc)
3035 xfree (agent->ttyname);
3036 agent->ttyname = str_dup (value);
3039 #endif
3041 else if (strcasecmp (name, (char *) "ttytype") == 0)
3043 #ifdef WITH_AGENT
3044 if (use_agent)
3046 rc = set_agent_option (client->crypto->agent, "ttytype", value);
3047 if (!rc)
3049 xfree (agent->ttytype);
3050 agent->ttytype = str_dup (value);
3053 #endif
3055 else if (strcasecmp (name, (char *) "display") == 0)
3057 #ifdef WITH_AGENT
3058 if (use_agent)
3060 rc = set_agent_option (client->crypto->agent, "display", value);
3061 if (!rc)
3063 xfree (agent->display);
3064 agent->display = str_dup (value);
3067 #endif
3069 else if (strcasecmp (name, (char *) "desc") == 0)
3071 #ifdef WITH_AGENT
3072 if (client->crypto->agent->desc)
3073 xfree (client->crypto->agent->desc);
3075 client->crypto->agent->desc = str_dup (value);
3076 if (!client->crypto->agent->desc)
3077 rc = GPG_ERR_ENOMEM;
3078 #endif
3080 #if 0
3081 else if (strcasecmp (name, "pinentry_timeout") == 0)
3083 char *p = NULL;
3084 int n;
3086 if (!value)
3087 goto done;
3089 n = (int) strtol (value, &p, 10);
3091 if (*p || n < 0)
3092 return gpg_error (GPG_ERR_INV_VALUE);
3094 MUTEX_LOCK (&rcfile_mutex);
3095 config_set_int_param (global_config,
3096 client->filename ? client->filename : "global",
3097 "pinentry_timeout", value);
3098 MUTEX_UNLOCK (&rcfile_mutex);
3099 goto done;
3101 #endif
3102 else
3103 return gpg_error (GPG_ERR_UNKNOWN_OPTION);
3105 done:
3106 return rc;
3109 static gpg_error_t
3110 do_rename (assuan_context_t ctx, char *line)
3112 struct client_s *client = assuan_get_pointer (ctx);
3113 gpg_error_t rc;
3114 char **req, **src, *dst;
3115 xmlNodePtr n, ndst;
3117 req = str_split (line, " ", 0);
3119 if (!req || !req[0] || !req[1])
3121 strv_free (req);
3122 return GPG_ERR_SYNTAX;
3125 dst = req[1];
3126 is_literal_element (&dst);
3128 if (!valid_xml_element ((xmlChar *) dst))
3130 strv_free (req);
3131 return GPG_ERR_INV_VALUE;
3134 if (strchr (req[0], '\t'))
3135 src = str_split (req[0], "\t", 0);
3136 else
3137 src = str_split (req[0], " ", 0);
3139 if (!src || !*src)
3141 rc = GPG_ERR_SYNTAX;
3142 goto fail;
3145 n = find_root_element (client->doc, &src, &rc, NULL, 0, 0);
3146 if (src[1] && n)
3147 n = find_elements (client->doc, n->children, src + 1, &rc, NULL, NULL,
3148 NULL, 0, 0, NULL, 0);
3150 if (!n)
3151 goto fail;
3153 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
3154 if (!a)
3156 rc = GPG_ERR_ENOMEM;
3157 goto fail;
3160 /* To prevent unwanted effects:
3162 * <root name="a"><b/></root>
3164 * RENAME a<TAB>b b
3166 if (xmlStrEqual (a, (xmlChar *) dst))
3168 xmlFree (a);
3169 rc = GPG_ERR_AMBIGUOUS_NAME;
3170 goto fail;
3173 xmlFree (a);
3174 char **tmp = NULL;
3175 if (src[1])
3177 char **p;
3179 for (p = src; *p; p++)
3181 if (!*(p + 1))
3182 break;
3183 strv_printf (&tmp, "%s", *p);
3187 strv_printf (&tmp, "!%s", dst);
3188 ndst = find_root_element (client->doc, &tmp, &rc, NULL, 0, 0);
3189 if (!ndst && rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3191 strv_free (tmp);
3192 goto fail;
3195 if (tmp[1] && ndst)
3196 ndst = find_elements (client->doc, ndst->children, tmp + 1, &rc, NULL,
3197 NULL, NULL, 0, 0, NULL, 0);
3199 strv_free (tmp);
3200 if (!ndst && rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3201 goto fail;
3203 rc = 0;
3205 /* Target may exist:
3207 * <root name="a"/>
3208 * <root name="b" target="a"/>
3210 * RENAME b a
3212 * Would need to do:
3213 * RENAME !b a
3215 if (ndst == n)
3217 rc = GPG_ERR_AMBIGUOUS_NAME;
3218 goto fail;
3221 if (ndst)
3223 unlink_node (ndst);
3224 xmlFreeNodeList (ndst);
3227 rc = add_attribute (n, "_name", dst);
3229 fail:
3230 strv_free (req);
3231 strv_free (src);
3232 return rc;
3235 static gpg_error_t
3236 rename_command (assuan_context_t ctx, char *line)
3238 struct client_s *client = assuan_get_pointer (ctx);
3239 gpg_error_t rc;
3240 struct argv_s *args[] = {
3241 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
3242 NULL
3245 rc = parse_options (&line, args, client);
3246 if (rc)
3247 return send_error (ctx, rc);
3249 if (client->opts & OPT_INQUIRE)
3251 unsigned char *result;
3252 size_t len;
3254 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3255 if (rc)
3256 return send_error (ctx, rc);
3258 line = (char *) result;
3261 rc = do_rename (ctx, line);
3263 if (client->opts & OPT_INQUIRE)
3264 xfree (line);
3266 return send_error (ctx, rc);
3269 static gpg_error_t
3270 do_copy (assuan_context_t ctx, char *line)
3272 struct client_s *client = assuan_get_pointer (ctx);
3273 gpg_error_t rc;
3274 char **req, **src = NULL, **dst = NULL;
3275 xmlNodePtr nsrc, ndst, new = NULL;
3277 req = str_split (line, " ", 0);
3278 if (!req || !req[0] || !req[1])
3280 strv_free (req);
3281 return GPG_ERR_SYNTAX;
3284 if (strchr (req[0], '\t'))
3285 src = str_split (req[0], "\t", 0);
3286 else
3287 src = str_split (req[0], " ", 0);
3289 if (!src || !*src)
3291 rc = GPG_ERR_SYNTAX;
3292 goto fail;
3295 if (strchr (req[1], '\t'))
3296 dst = str_split (req[1], "\t", 0);
3297 else
3298 dst = str_split (req[1], " ", 0);
3300 if (!dst || !*dst)
3302 rc = GPG_ERR_SYNTAX;
3303 goto fail;
3306 if (!valid_element_path (dst, 0))
3308 rc = GPG_ERR_INV_VALUE;
3309 goto fail;
3312 nsrc = find_root_element (client->doc, &src, &rc, NULL, 0, 0);
3313 if (nsrc && src[1])
3314 nsrc = find_elements (client->doc, nsrc->children, src + 1, &rc, NULL,
3315 NULL, NULL, 0, 0, NULL, 0);
3317 if (!nsrc)
3318 goto fail;
3320 new = xmlCopyNodeList (nsrc);
3321 if (!new)
3323 rc = GPG_ERR_ENOMEM;
3324 goto fail;
3327 int create = 0;
3328 ndst = find_root_element (client->doc, &dst, &rc, NULL, 0, 0);
3329 if (ndst && dst[1])
3331 if (ndst->children)
3332 ndst = find_elements (client->doc, ndst->children, dst + 1, &rc, NULL,
3333 NULL, create_target_elements_cb, 0, 0, NULL, 0);
3334 else
3335 create = 1;
3337 else
3338 create = 1;
3340 if (!ndst && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3341 goto fail;
3342 else if (create)
3344 ndst = create_element_path (client, &dst, &rc, NULL);
3345 if (!ndst)
3346 goto fail;
3349 /* Merge any attributes from the src node to the initial dst node. */
3350 for (xmlAttrPtr attr = new->properties; attr; attr = attr->next)
3352 if (xmlStrEqual (attr->name, (xmlChar *) "_name"))
3353 continue;
3355 xmlAttrPtr a = xmlHasProp (ndst, attr->name);
3356 if (a)
3357 xmlRemoveProp (a);
3359 xmlChar *tmp = xmlNodeGetContent (attr->children);
3360 xmlNewProp (ndst, attr->name, tmp);
3361 xmlFree (tmp);
3362 rc = add_attribute (ndst, NULL, NULL);
3365 xmlNodePtr n = ndst->children;
3366 xmlUnlinkNode (n);
3367 xmlFreeNodeList (n);
3368 ndst->children = NULL;
3370 if (new->children)
3372 n = xmlCopyNodeList (new->children);
3373 if (!n)
3375 rc = GPG_ERR_ENOMEM;
3376 goto fail;
3379 n = xmlAddChildList (ndst, n);
3380 if (!n)
3382 rc = GPG_ERR_ENOMEM;
3383 goto fail;
3386 rc = update_element_mtime (xmlDocGetRootElement (client->doc) ==
3387 ndst->parent ? ndst : ndst->parent);
3390 fail:
3391 if (new)
3393 xmlUnlinkNode (new);
3394 xmlFreeNodeList (new);
3397 if (req)
3398 strv_free (req);
3400 if (src)
3401 strv_free (src);
3403 if (dst)
3404 strv_free (dst);
3406 return rc;
3409 static gpg_error_t
3410 copy_command (assuan_context_t ctx, char *line)
3412 struct client_s *client = assuan_get_pointer (ctx);
3413 gpg_error_t rc;
3414 struct argv_s *args[] = {
3415 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
3416 NULL
3419 rc = parse_options (&line, args, client);
3420 if (rc)
3421 return send_error (ctx, rc);
3423 if (client->opts & OPT_INQUIRE)
3425 unsigned char *result;
3426 size_t len;
3428 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3429 if (rc)
3430 return send_error (ctx, rc);
3432 line = (char *) result;
3435 rc = do_copy (ctx, line);
3437 if (client->opts & OPT_INQUIRE)
3438 xfree (line);
3440 return send_error (ctx, rc);
3443 static gpg_error_t
3444 do_move (assuan_context_t ctx, char *line)
3446 struct client_s *client = assuan_get_pointer (ctx);
3447 gpg_error_t rc;
3448 char **req, **src = NULL, **dst = NULL;
3449 xmlNodePtr nsrc, ndst = NULL;
3451 req = str_split (line, " ", 0);
3453 if (!req || !req[0] || !req[1])
3455 strv_free (req);
3456 return GPG_ERR_SYNTAX;
3459 if (strchr (req[0], '\t'))
3460 src = str_split (req[0], "\t", 0);
3461 else
3462 src = str_split (req[0], " ", 0);
3464 if (!src || !*src)
3466 rc = GPG_ERR_SYNTAX;
3467 goto fail;
3470 if (strchr (req[1], '\t'))
3471 dst = str_split (req[1], "\t", 0);
3472 else
3473 dst = str_split (req[1], " ", 0);
3475 nsrc = find_root_element (client->doc, &src, &rc, NULL, 0, 0);
3476 if (nsrc && src[1])
3477 nsrc = find_elements (client->doc, nsrc->children, src + 1, &rc, NULL,
3478 NULL, NULL, 0, 0, NULL, 0);
3480 if (!nsrc)
3481 goto fail;
3483 if (dst)
3485 if (!valid_element_path (dst, 0))
3487 rc = GPG_ERR_INV_VALUE;
3488 goto fail;
3491 ndst = find_root_element (client->doc, &dst, &rc, NULL, 0, 0);
3492 if (ndst && dst[1])
3493 ndst = find_elements (client->doc, ndst->children, dst + 1, &rc, NULL,
3494 NULL, NULL, 0, 0, NULL, 0);
3496 else
3497 ndst = xmlDocGetRootElement (client->doc);
3499 for (xmlNodePtr n = ndst; n; n = n->parent)
3501 if (n == nsrc)
3503 rc = GPG_ERR_CONFLICT;
3504 goto fail;
3508 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3509 goto fail;
3511 rc = 0;
3513 if (ndst)
3515 xmlChar *a = node_has_attribute (nsrc, (xmlChar *) "_name");
3516 xmlNodePtr dup = find_element (ndst->children, (char *) a, NULL);
3518 xmlFree (a);
3519 if (dup)
3521 if (dup == nsrc)
3522 goto fail;
3524 if (ndst == xmlDocGetRootElement (client->doc))
3526 xmlNodePtr n = nsrc;
3527 int match = 0;
3529 while (n->parent && n->parent != ndst)
3530 n = n->parent;
3532 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
3533 xmlChar *b = node_has_attribute (nsrc, (xmlChar *) "_name");
3535 if (xmlStrEqual (a, b))
3537 match = 1;
3538 xmlUnlinkNode (nsrc);
3539 xmlUnlinkNode (n);
3540 xmlFreeNodeList (n);
3543 xmlFree (a);
3544 xmlFree (b);
3546 if (!match)
3548 xmlUnlinkNode (dup);
3549 xmlFreeNodeList (dup);
3552 else
3553 xmlUnlinkNode (dup);
3557 if (!ndst && dst)
3559 xmlChar *name = node_has_attribute (nsrc, (xmlChar *) "_name");
3561 if (nsrc->parent == xmlDocGetRootElement (client->doc)
3562 && !strcmp ((char *) name, *dst))
3564 xmlFree (name);
3565 rc = GPG_ERR_CONFLICT;
3566 goto fail;
3569 xmlFree (name);
3570 ndst = create_element_path (client, &dst, &rc, nsrc);
3573 if (!ndst)
3574 goto fail;
3576 update_element_mtime (nsrc->parent);
3577 xmlUnlinkNode (nsrc);
3578 ndst = xmlAddChildList (ndst, nsrc);
3580 if (!ndst)
3581 rc = GPG_ERR_ENOMEM;
3583 update_element_mtime (ndst->parent);
3585 fail:
3586 if (req)
3587 strv_free (req);
3589 if (src)
3590 strv_free (src);
3592 if (dst)
3593 strv_free (dst);
3595 return rc;
3598 static gpg_error_t
3599 move_command (assuan_context_t ctx, char *line)
3601 struct client_s *client = assuan_get_pointer (ctx);
3602 gpg_error_t rc;
3603 struct argv_s *args[] = {
3604 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
3605 NULL
3608 rc = parse_options (&line, args, client);
3609 if (rc)
3610 return send_error (ctx, rc);
3612 if (client->opts & OPT_INQUIRE)
3614 unsigned char *result;
3615 size_t len;
3617 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3618 if (rc)
3619 return send_error (ctx, rc);
3621 line = (char *) result;
3624 rc = do_move (ctx, line);
3626 if (client->opts & OPT_INQUIRE)
3627 xfree (line);
3629 return send_error (ctx, rc);
3632 static gpg_error_t
3633 ls_command (assuan_context_t ctx, char *line)
3635 gpg_error_t rc;
3636 char *tmp = str_asprintf ("%s/data", homedir);
3637 char *dir = expand_homedir (tmp);
3638 DIR *d = opendir (dir);
3640 rc = gpg_error_from_syserror ();
3641 xfree (tmp);
3643 if (!d)
3645 xfree (dir);
3646 return send_error (ctx, rc);
3649 size_t len =
3650 offsetof (struct dirent, d_name) +pathconf (dir, _PC_NAME_MAX) + 1;
3651 struct dirent *p = xmalloc (len), *cur = NULL;
3652 char *list = NULL;
3654 xfree (dir);
3655 rc = 0;
3657 while (!readdir_r (d, p, &cur) && cur)
3659 if (cur->d_name[0] == '.' && cur->d_name[1] == '\0')
3660 continue;
3661 else if (cur->d_name[0] == '.' && cur->d_name[1] == '.'
3662 && cur->d_name[2] == '\0')
3663 continue;
3665 tmp = str_asprintf ("%s%s\n", list ? list : "", cur->d_name);
3667 if (!tmp)
3669 if (list)
3670 xfree (list);
3672 rc = GPG_ERR_ENOMEM;
3673 break;
3676 xfree (list);
3677 list = tmp;
3680 closedir (d);
3681 xfree (p);
3683 if (rc)
3684 return send_error (ctx, rc);
3686 if (!list)
3687 return send_error (ctx, GPG_ERR_NO_DATA);
3689 list[strlen (list) - 1] = 0;
3690 rc = xfer_data (ctx, list, strlen (list));
3691 xfree (list);
3692 return send_error (ctx, rc);
3695 static gpg_error_t
3696 bye_notify (assuan_context_t ctx, char *line)
3698 struct client_s *cl = assuan_get_pointer (ctx);
3700 #ifdef WITH_GNUTLS
3701 if (cl->thd->remote)
3703 int rc;
3707 struct timeval tv = { 0, 50000 };
3709 rc = gnutls_bye (cl->thd->tls->ses, GNUTLS_SHUT_RDWR);
3710 if (rc == GNUTLS_E_AGAIN)
3711 select (0, NULL, NULL, NULL, &tv);
3713 while (rc == GNUTLS_E_AGAIN);
3715 #endif
3717 /* This will let assuan_process_next() return. */
3718 fcntl (cl->thd->fd, F_SETFL, O_NONBLOCK);
3719 cl->last_rc = 0; // BYE command result
3720 return 0;
3723 static gpg_error_t
3724 reset_notify (assuan_context_t ctx, char *line)
3726 struct client_s *client = assuan_get_pointer (ctx);
3728 if (client)
3729 cleanup_client (client);
3731 return 0;
3735 * This is called before every Assuan command.
3737 static gpg_error_t
3738 command_startup (assuan_context_t ctx, const char *name)
3740 struct client_s *client = assuan_get_pointer (ctx);
3741 gpg_error_t rc;
3742 struct command_table_s *cmd = NULL;
3744 log_write1 ("command='%s'", name);
3745 client->last_rc = client->opts = 0;
3747 for (int i = 0; command_table[i]; i++)
3749 if (!strcasecmp (name, command_table[i]->name))
3751 if (command_table[i]->ignore_startup)
3752 return 0;
3753 cmd = command_table[i];
3754 break;
3758 client->last_rc = rc = gpg_error (file_modified (client, cmd));
3759 return rc;
3763 * This is called after every Assuan command.
3765 static void
3766 command_finalize (assuan_context_t ctx, gpg_error_t rc)
3768 struct client_s *client = assuan_get_pointer (ctx);
3770 if (!(client->flags & FLAG_LOCK_CMD))
3771 unlock_file_mutex (client, 0);
3773 log_write1 (_("command completed: rc=%u"), client->last_rc);
3774 client->last_rc = gpg_error (GPG_ERR_UNKNOWN_COMMAND);
3777 static gpg_error_t
3778 help_command (assuan_context_t ctx, char *line)
3780 gpg_error_t rc;
3781 int i;
3783 if (!line || !*line)
3785 char *tmp;
3786 char *help = str_dup (_("Usage: HELP [<COMMAND>]\n"
3787 "For commands that take an element path as an argument, each element is "
3788 "separated with an ASCII @key{TAB} character (ASCII 0x09)."
3789 "\n" "COMMANDS:"));
3791 for (i = 0; command_table[i]; i++)
3793 if (!command_table[i]->help)
3794 continue;
3796 tmp = str_asprintf ("%s %s", help, command_table[i]->name);
3797 xfree (help);
3798 help = tmp;
3801 tmp = strip_texi_and_wrap (help);
3802 xfree (help);
3803 rc = xfer_data (ctx, tmp, strlen (tmp));
3804 xfree (tmp);
3805 return send_error (ctx, rc);
3808 for (i = 0; command_table[i]; i++)
3810 if (!strcasecmp (line, command_table[i]->name))
3812 char *help, *tmp;
3814 if (!command_table[i]->help)
3815 break;
3817 help = strip_texi_and_wrap (command_table[i]->help);
3818 tmp = str_asprintf (_("Usage: %s"), help);
3819 xfree (help);
3820 rc = xfer_data (ctx, tmp, strlen (tmp));
3821 xfree (tmp);
3822 return send_error (ctx, rc);
3826 return send_error (ctx, GPG_ERR_INV_NAME);
3829 static void
3830 new_command (const char *name, int ignore, int unlock,
3831 gpg_error_t (*handler) (assuan_context_t, char *),
3832 const char *help)
3834 int i = 0;
3836 if (command_table)
3837 for (i = 0; command_table[i]; i++);
3839 command_table =
3840 xrealloc (command_table, (i + 2) * sizeof (struct command_table_s *));
3841 command_table[i] = xcalloc (1, sizeof (struct command_table_s));
3842 command_table[i]->name = name;
3843 command_table[i]->handler = handler;
3844 command_table[i]->ignore_startup = ignore;
3845 command_table[i]->unlock = unlock;
3846 command_table[i++]->help = help;
3847 command_table[i] = NULL;
3850 void
3851 deinit_commands ()
3853 int i;
3855 for (i = 0; command_table[i]; i++)
3856 xfree (command_table[i]);
3858 xfree (command_table);
3861 static int
3862 sort_commands (const void *arg1, const void *arg2)
3864 struct command_table_s *const *a = arg1;
3865 struct command_table_s *const *b = arg2;
3867 if (!*a || !*b)
3868 return 0;
3869 else if (*a && !*b)
3870 return 1;
3871 else if (!*a && *b)
3872 return -1;
3874 return strcmp ((*a)->name, (*b)->name);
3877 static gpg_error_t
3878 passwd_command (assuan_context_t ctx, char *line)
3880 struct client_s *client = assuan_get_pointer (ctx);
3881 gpg_error_t rc;
3882 struct argv_s *args[] = {
3883 &(struct argv_s) {"reset", OPTION_TYPE_NOARG, parse_opt_reset},
3884 &(struct argv_s) {"s2k-count", OPTION_TYPE_ARG, parse_opt_s2k_count},
3885 NULL
3888 if (client->flags & FLAG_NEW)
3889 return send_error (ctx, GPG_ERR_INV_STATE);
3891 client->crypto->save.s2k_count =
3892 config_get_ulong (client->filename, "s2k_count");
3893 rc = parse_options (&line, args, client);
3894 if (rc)
3895 return send_error (ctx, rc);
3897 if (!rc && client->opts & OPT_RESET)
3899 rc = cache_clear (client->md5file);
3900 if (!rc)
3901 send_status_all (STATUS_CACHE, NULL);
3904 if (!rc)
3906 if (!IS_PKCS (client->crypto))
3908 struct crypto_s *crypto;
3910 xfree (client->crypto->filename);
3911 client->crypto->filename = str_dup (client->filename);
3912 rc = change_passwd (client->filename, &crypto);
3913 if (!rc)
3915 cleanup_crypto (&client->crypto);
3916 client->crypto = crypto;
3917 update_checksum (client);
3918 cleanup_crypto_stage1 (client->crypto);
3921 #ifdef WITH_AGENT
3922 else
3924 if (client->crypto->save.s2k_count)
3925 rc = send_to_agent (client->crypto->agent, NULL, NULL,
3926 "OPTION s2k-count=%lu",
3927 client->crypto->save.s2k_count);
3929 if (!rc)
3930 rc = agent_passwd (client->crypto);
3932 #endif
3935 return send_error (ctx, rc);
3938 static gpg_error_t
3939 parse_keygrip_opt_sign (void *data, void *value)
3941 struct client_s *client = data;
3943 (void) value;
3944 client->opts |= OPT_SIGN;
3945 return 0;
3948 static gpg_error_t
3949 keygrip_command (assuan_context_t ctx, char *line)
3951 struct client_s *client = assuan_get_pointer (ctx);
3952 gpg_error_t rc;
3953 struct crypto_s *crypto;
3954 struct argv_s *args[] = {
3955 &(struct argv_s) {"sign", OPTION_TYPE_NOARG, parse_keygrip_opt_sign},
3956 NULL
3959 if (!line || !*line)
3960 return send_error (ctx, GPG_ERR_SYNTAX);
3962 rc = parse_options (&line, args, client);
3963 if (rc)
3964 return send_error (ctx, rc);
3966 if (!valid_filename (line))
3967 return send_error (ctx, GPG_ERR_INV_VALUE);
3969 rc = init_client_crypto (&crypto);
3970 if (rc)
3971 return send_error (ctx, rc);
3973 rc = read_data_file (line, crypto);
3974 if (!rc)
3976 char *hexgrip = NULL;
3978 if (client->opts & OPT_SIGN)
3980 if (valid_keygrip (crypto->sign_grip, sizeof (crypto->sign_grip)))
3981 hexgrip = bin2hex (crypto->sign_grip, sizeof (crypto->sign_grip));
3984 if (!hexgrip)
3985 hexgrip = bin2hex (crypto->grip, sizeof (crypto->grip));
3987 if (!hexgrip)
3988 rc = GPG_ERR_ENOMEM;
3989 else
3990 rc = xfer_data (ctx, hexgrip, strlen (hexgrip));
3992 xfree (hexgrip);
3995 cleanup_crypto (&crypto);
3996 return send_error (ctx, rc);
3999 static gpg_error_t
4000 parse_opt_data (void *data, void *value)
4002 struct client_s *client = data;
4004 (void) value;
4005 client->opts |= OPT_DATA;
4006 return 0;
4009 static gpg_error_t
4010 getinfo_command (assuan_context_t ctx, char *line)
4012 struct client_s *client = assuan_get_pointer (ctx);
4013 gpg_error_t rc;
4014 char buf[ASSUAN_LINELENGTH];
4015 struct argv_s *args[] = {
4016 &(struct argv_s) {"data", OPTION_TYPE_NOARG, parse_opt_data},
4017 NULL
4020 rc = parse_options (&line, args, client);
4021 if (rc)
4022 return send_error (ctx, rc);
4024 if (!strcasecmp (line, "clients"))
4026 if (client->opts & OPT_DATA)
4028 MUTEX_LOCK (&cn_mutex);
4029 snprintf (buf, sizeof (buf), "%i", slist_length (cn_thread_list));
4030 MUTEX_UNLOCK (&cn_mutex);
4031 rc = xfer_data (ctx, buf, strlen (buf));
4033 else
4034 rc = send_status (ctx, STATUS_CLIENTS, NULL);
4036 else if (!strcasecmp (line, "cache"))
4038 if (client->opts & OPT_DATA)
4040 snprintf (buf, sizeof (buf), "%u", cache_file_count ());
4041 rc = xfer_data (ctx, buf, strlen (buf));
4043 else
4044 rc = send_status (ctx, STATUS_CACHE, NULL);
4046 else if (!strcasecmp (line, "pid"))
4048 char buf[32];
4049 pid_t pid = getpid ();
4051 snprintf (buf, sizeof (buf), "%i", pid);
4052 rc = xfer_data (ctx, buf, strlen (buf));
4054 else if (!strcasecmp (line, "version"))
4056 char *buf = str_asprintf ("0x%06x %s", VERSION_HEX,
4057 #ifdef WITH_LIBACL
4058 "ACL "
4059 #endif
4060 #ifdef WITH_GNUTLS
4061 "GNUTLS "
4062 #endif
4063 #ifdef WITH_AGENT
4064 "AGENT "
4065 #endif
4066 "");
4067 rc = xfer_data (ctx, buf, strlen (buf));
4068 xfree (buf);
4070 else if (!strcasecmp (line, "last_error"))
4072 if (client->last_error)
4073 rc = xfer_data (ctx, client->last_error, strlen (client->last_error));
4074 else
4075 rc = GPG_ERR_NO_DATA;
4077 else
4078 rc = gpg_error (GPG_ERR_SYNTAX);
4080 return send_error (ctx, rc);
4083 #ifdef WITH_AGENT
4084 static gpg_error_t
4085 send_data_cb (void *user, const void *buf, size_t len)
4087 assuan_context_t ctx = user;
4089 return assuan_send_data (ctx, buf, len);
4092 static gpg_error_t
4093 send_status_cb (void *user, const char *line)
4095 assuan_context_t ctx = user;
4096 char keyword[200], *k;
4097 const char *p;
4099 for (p = line, k = keyword; *p; p++)
4101 if (isspace (*p))
4102 break;
4104 *k++ = *p;
4107 *k = 0;
4108 if (*p == '#')
4109 p++;
4111 while (isspace (*p))
4112 p++;
4114 return assuan_write_status (ctx, keyword, *p ? p : NULL);
4116 #endif
4118 static gpg_error_t
4119 agent_command (assuan_context_t ctx, char *line)
4121 gpg_error_t rc = 0;
4123 if (!use_agent)
4124 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
4126 #ifdef WITH_AGENT
4127 struct client_s *client = assuan_get_pointer (ctx);
4129 if (!line || !*line)
4130 return send_error (ctx, GPG_ERR_SYNTAX);
4132 assuan_set_flag (client->crypto->agent->ctx, ASSUAN_CONVEY_COMMENTS, 1);
4133 rc = assuan_transact (client->crypto->agent->ctx, line, send_data_cb,
4134 client->ctx, agent_loopback_cb, client->crypto,
4135 send_status_cb, client->ctx);
4136 if (gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
4138 char *line;
4139 size_t len;
4141 rc = assuan_write_line (client->crypto->agent->ctx, "CAN");
4142 if (!rc)
4144 rc = assuan_read_line (client->crypto->agent->ctx, &line, &len);
4145 if (!rc)
4146 rc = gpg_error (GPG_ERR_ASS_CANCELED);
4150 assuan_set_flag (client->crypto->agent->ctx, ASSUAN_CONVEY_COMMENTS, 0);
4151 #endif
4152 return send_error (ctx, rc);
4155 void
4156 init_commands ()
4158 /* !BEGIN-HELP-TEXT!
4160 * This comment is used as a marker to generate the offline documentation
4161 * found in doc/pwmd.info. The indentation needs to be kept for the awk
4162 * script to determine where commands begin and end.
4164 new_command("HELP", 1, 1, help_command, _(
4165 "HELP [<COMMAND>]\n"
4166 "Show available commands or command specific help text."
4169 new_command("AGENT", 1, 1, agent_command, _(
4170 "AGENT <command>\n"
4171 "Send a @command{gpg-agent} protocol @var{command} directly to the "
4172 "@command{gpg-agent}."
4175 new_command("GETINFO", 1, 1, getinfo_command, _(
4176 "GETINFO [--data] CACHE | CLIENTS | PID | LAST_ERROR | VERSION\n"
4177 "Get server and other information: @var{cache} returns the number of cached "
4178 "documents via a status message. @var{clients} returns the number of "
4179 "connected clients via a status message. @var{pid} returns the process ID "
4180 "number of the server via a data response. @var{VERSION} returns the server "
4181 "version number and compile-time features with a data response with each "
4182 "being space delimited. @var{LAST_ERROR} returns a detailed description of "
4183 "the last failed command when available. @xref{Status Messages}. "
4184 "\n"
4185 "When the @option{--data} option is specified then the result will be send "
4186 "via a data response rather than a status message."
4189 new_command("PASSWD", 0, 0, passwd_command, _(
4190 "PASSWD [--reset] [--s2k-count=N]\n"
4191 "Changes the passphrase of the secret key required to open the current "
4192 "file. When the @option{--reset} option is passed then the cache entry for "
4193 "the current file will be reset and the passphrase, if any, will be required "
4194 "during the next @code{OPEN}. @xref{OPEN}."
4195 "\n"
4196 "The @option{--s2k-count} option sets number of hash iterations for a "
4197 "passphrase and must be either @code{0} to use the calibrated count of the "
4198 "machine (the default), or a value greater than or equal to @code{65536}. "
4199 "@xref{SAVE}."
4202 new_command("KEYGRIP", 1, 1, keygrip_command, _(
4203 "KEYGRIP [--sign] <filename>\n"
4204 "Returns the hex encoded keygrip of the specified @var{filename} with a "
4205 "data response."
4206 "\n"
4207 "When the @option{--sign} option is specified then the key used for signing "
4208 "of the specified @var{filename} will be returned."
4211 new_command("OPEN", 1, 1, open_command, _(
4212 "OPEN [--lock] [--no-pinentry] <filename> [<passphrase>]\n"
4213 "Opens @var{filename} using @var{passphrase}. When the filename is not "
4214 "found on the file-system then a new document will be created. If the file "
4215 "is found, it is looked for in the file cache. If cached and no "
4216 "@var{passphrase} was specified then the cached document is opened. When not "
4217 "cached, @cite{pinentry(1)} will be used to retrieve the passphrase to use "
4218 "for decryption unless @option{--no-pinentry} was specified (see below)."
4219 "\n"
4220 "When the @option{--lock} option is passed then the file mutex will be "
4221 "locked as if the @code{LOCK} command (@pxref{LOCK}) had been sent after the "
4222 "file has been opened."
4223 "\n"
4224 "By default, a pinentry is used to retrieve a passphrase when required. "
4225 "Passing @option{--no-pinentry} will disable pinentry use for the rest of "
4226 "the session. When pinentry use is disabled but required for some operation "
4227 "then a server @emph{INQUIRE} will be send to the client to retrieve the "
4228 "passphrase. See the @code{OPTION} command (@pxref{OPTION}), for pinentry "
4229 "specific options."
4232 new_command("SAVE", 0, 0, save_command, _(
4233 "SAVE [--no-passphrase] [--reset] [--no-agent] [--s2k-count=N] [--cipher=<algo>] [--cipher-iterations=N] [--inquire-keyparam] [--keygrip=hexstring [--sign-keygrip=hexstring]]\n"
4234 "Writes the @abbr{XML} document to disk. The file written to is the file that "
4235 "was opened using the @code{OPEN} command (@pxref{OPEN}). If the file is a "
4236 "new one or the option @option{--inquire-keyparam} was passed, then a new "
4237 "keypair will be generated and a pinentry will be used to prompt for the "
4238 "passphrase to encrypt with unless the @option{--no-passphrase} option was "
4239 "passed, in which case the data file will not be passphrase protected."
4240 "\n"
4241 "The @option{--no-agent} option disables use of @command{gpg-agent} for "
4242 "passphrase retrieval and caching for new files and behaves as if the "
4243 "@option{--no-agent} commmand line option to @command{pwmd} was specified."
4244 "\n"
4245 "The @option{--reset} option will clear the cache entry for the current file "
4246 "before saving."
4247 "\n"
4248 "The @option{--cipher} option can be used to encrypt the @abbr{XML} data to "
4249 "an alternate cipher. The default is @code{aes256}. See the Configuration "
4250 "(@pxref{Configuration}) for available ciphers."
4251 "\n"
4252 "The @option{--cipher-iterations} option specifies the number of times to "
4253 "encrypt the XML data. The default is 0 although 1 iteration is still done."
4254 "\n"
4255 "The @option{--inquire-keyparam} option will send a server @emph{INQUIRE} to "
4256 "the client to obtain the key paramaters to use when generating a new "
4257 "keypair. The inquired data is expected to be an S-expression. If not "
4258 "specified then an @samp{RSA} key of @samp{2048} bits will be generated "
4259 "unless otherwise set in the configuration file (@pxref{Configuration}). Note "
4260 "that when this option is specified a new keypair will be generated "
4261 "reguardless if the file is a new one or not."
4262 "\n"
4263 "You can encrypt the data file to a public key other than the one that it "
4264 "was originally encrypted with by passing the @option{--keygrip} option with "
4265 "the hex encoded keygrip of the public key as its argument. The keygrip may "
4266 "be of any key that @command{gpg-agent} knows about. The "
4267 "@option{--sign-keygrip} option may also be used to sign with an alternate "
4268 "secret key. This option may be needed when using a smartcard."
4269 "\n"
4270 "The @option{--s2k-count} option sets number of hash iterations for a "
4271 "passphrase. A value less-than @code{65536} will use the machine calibrated "
4272 "value which is the default. This setting only affects new files. To change "
4273 "the setting, use the @code{PASSWD} command (@pxref{PASSWD})."
4276 new_command("ISCACHED", 1, 0, iscached_command, _(
4277 "ISCACHED [--lock] <filename>\n"
4278 "An @emph{OK} response is returned if the specified @var{filename} is found "
4279 "in the file cache. If not found in the cache but exists on the filesystem "
4280 "then @var{GPG_ERR_NO_DATA} is returned. Otherwise a filesystem error is "
4281 "returned."
4282 "\n"
4283 "The @option{lock} option will lock the file mutex of @var{filename} when the "
4284 "file exists; it does not need to be opened nor cached."
4287 new_command("CLEARCACHE", 1, 1, clearcache_command, _(
4288 "CLEARCACHE [<filename>]\n"
4289 "Clears a file cache entry for all or the specified @var{filename}."
4292 new_command("CACHETIMEOUT", 1, 1, cachetimeout_command, _(
4293 "CACHETIMEOUT <filename> <seconds>\n"
4294 "The time in @var{seconds} until @var{filename} will be removed from the "
4295 "cache. @code{-1} will keep the cache entry forever, @code{0} will require "
4296 "the passphrase for each @code{OPEN} command (@pxref{OPEN}). "
4297 "@xref{Configuration}, and the @code{cache_timeout} parameter."
4300 new_command("LIST", 0, 1, list_command, _(
4301 "LIST [--inquire] [--no-recurse] [--verbose] [--with-target] [--all] [[!]element[<TAB>[!]child[..]]]\n"
4302 "If no element path is given then a newline separated list of root elements "
4303 "is returned with a data response. If given, then all reachable elements "
4304 "of the specified element path are returned unless the @option{--no-recurse} "
4305 "option is specified. If specified, only the child elements of the element "
4306 "path are returned without recursing into grandchildren. Each resulting "
4307 "element is prefixed with the literal @code{!} character when the element "
4308 "contains no @code{target} attribute. @xref{Target Attribute}, for details."
4309 "\n"
4310 "When the @option{--verbose} option is passed then each element path "
4311 "returned will have zero or more flags appened to it. These flags are "
4312 "delimited from the element path by a single space character. A flag itself "
4313 "is a single character. Flag @code{+} indicates that there are child nodes of "
4314 "the current element path. Flag @code{E} indicates that an element of an "
4315 "element path contained in a @var{target} attribute could not be found. Flag "
4316 "@code{O} indicates that a @var{target} attribute recursion limit was reached "
4317 "(@pxref{Configuration}). Flag @code{T} will append the resolved element path "
4318 "of a @var{target} attribute (see below)."
4319 "\n"
4320 "The @option{--with-target} option implies @option{--verbose} and will append "
4321 "an additional flag @code{T} followed by a single space then an element path. "
4322 "The appended element path is the resolved path (@pxref{REALPATH}) of the "
4323 "current element when it contains a @var{target} attribute. When no "
4324 "@var{target} attribute is found then no flag will be appended."
4325 "\n"
4326 "The @option{--no-recurse} option limits the amount of data returned to only "
4327 "the listing of children of the specified element path and not any "
4328 "grandchildren."
4329 "\n"
4330 "The @option{--all} option lists the entire element tree for each root "
4331 "element. This option also implies option @option{--verbose}."
4332 "\n"
4333 "When the @option{--inquire} option is passed then all remaining non-option "
4334 "arguments are retrieved via a server @emph{INQUIRE}."
4337 new_command("REALPATH", 0, 1, realpath_command, _(
4338 "REALPATH [--inquire] [!]element[<TAB>[!]child[..]]\n"
4339 "Resolves all @code{target} attributes of the specified element path and "
4340 "returns the result with a data response. @xref{Target Attribute}, for details."
4341 "\n"
4342 "When the @option{--inquire} option is passed then all remaining non-option "
4343 "arguments are retrieved via a server @emph{INQUIRE}."
4346 new_command("STORE", 0, 1, store_command, _(
4347 "STORE [!]element[<TAB>[!]child[..]]<TAB>[content]\n"
4348 "This command uses a server @emph{INQUIRE} to retrieve data from the client."
4349 "\n"
4350 "Creates a new element path or modifies the @var{content} of an existing "
4351 "element. If only a single element is specified then a new root element is "
4352 "created. Otherwise, elements are @key{TAB} delimited and the content will be "
4353 "set to the final @key{TAB} delimited element. If no @var{content} is "
4354 "specified after the final @key{TAB}, then the content of the element will "
4355 "be removed, or empty when creating a new element."
4356 "\n"
4357 "The only restriction of an element name is that it not contain whitespace "
4358 "or begin with the literal element character @code{!} unless specifying a "
4359 "literal element (@pxref{Target Attribute}). There is no whitespace between "
4360 "the @key{TAB} delimited elements. It is recommended that the content of an "
4361 "element be base64 encoded when it contains control or @key{TAB} characters "
4362 "to prevent @abbr{XML} and @command{pwmd} parsing errors."
4365 new_command("RENAME", 0, 1, rename_command, _(
4366 "RENAME [--inquire] [!]element[<TAB>[!]child[..]] <value>\n"
4367 "Renames the specified @var{element} to the new @var{value}. If an element of "
4368 "the same name as the @var{value} already exists it will be overwritten."
4369 "\n"
4370 "When the @option{--inquire} option is passed then all remaining non-option "
4371 "arguments are retrieved via a server @emph{INQUIRE}."
4374 new_command("COPY", 0, 1, copy_command, _(
4375 "COPY [--inquire] [!]source[<TAB>[!]child[..]] [!]dest[<TAB>[!]child[..]]\n"
4376 "Copies the entire element tree starting from the child node of the source "
4377 "element, to the destination element path. If the destination element path "
4378 "does not exist then it will be created; otherwise it is overwritten."
4379 "\n"
4380 "Note that attributes from the source element are merged into the "
4381 "destination element when the destination element path exists. When an "
4382 "attribute of the same name exists in both the source and destination "
4383 "elements then the destination attribute will be updated to the source "
4384 "attribute value."
4385 "\n"
4386 "When the @option{--inquire} option is passed then all remaining non-option "
4387 "arguments are retrieved via a server @emph{INQUIRE}."
4390 new_command("MOVE", 0, 1, move_command, _(
4391 "MOVE [--inquire] [!]source[<TAB>[!]child[..]] [[!]dest[<TAB>[!]child[..]]]\n"
4392 "Moves the source element path to the destination element path. If the "
4393 "destination is not specified then it will be moved to the root node of the "
4394 "document. If the destination is specified and exists then it will be "
4395 "overwritten; otherwise it will be created."
4396 "\n"
4397 "When the @option{--inquire} option is passed then all remaining non-option "
4398 "arguments are retrieved via a server @emph{INQUIRE}."
4401 new_command("DELETE", 0, 1, delete_command, _(
4402 "DELETE [--inquire] [!]element[<TAB>[!]child[..]]\n"
4403 "Removes the specified element path and all of its children. This may break "
4404 "an element with a @code{target} attribute (@pxref{Target Attribute}) that "
4405 "refers to this element or any of its children."
4406 "\n"
4407 "When the @option{--inquire} option is passed then all remaining non-option "
4408 "arguments are retrieved via a server @emph{INQUIRE}."
4411 new_command("GET", 0, 1, get_command, _(
4412 "GET [--inquire] [!]element[<TAB>[!]child[..]]\n"
4413 "Retrieves the content of the specified element. The content is returned "
4414 "with a data response."
4415 "\n"
4416 "When the @option{--inquire} option is passed then all remaining non-option "
4417 "arguments are retrieved via a server @emph{INQUIRE}."
4420 new_command("ATTR", 0, 1, attr_command, _(
4421 "ATTR [--inquire] SET|GET|DELETE|LIST [<attribute>] [!]element[<TAB>[!]child[..]] ..\n"
4422 "@table @asis\n"
4423 "@item ATTR SET attribute [!]element[<TAB>[!]child[..]] [value]\n"
4424 "\n"
4425 " Stores or updates an @var{attribute} name and optional @var{value} of an "
4426 "element. When no @var{value} is specified any existing value will be removed."
4427 "\n"
4428 "@item ATTR DELETE attribute [!]element[<TAB>[!]child[..]]\n"
4429 "\n"
4430 " Removes an @var{attribute} from an element."
4431 "\n"
4432 "@item ATTR LIST [!]element[<TAB>[!]child[..]]\n"
4433 "\n"
4434 " Retrieves a newline separated list of attributes names and values "
4435 "from the specified element. Each attribute name and value is space delimited."
4436 "\n"
4437 "@item ATTR GET attribute [!]element[<TAB>[!]child[..]]\n"
4438 "\n"
4439 " Retrieves the value of an @var{attribute} from an element."
4440 "@end table\n"
4441 "\n"
4442 "The @code{_name} attribute (case sensitive) cannot be removed nor modified. "
4443 "Use the @code{DELETE} (@pxref{DELETE}) or @code{RENAME} (@pxref{RENAME}) "
4444 "commands instead."
4445 "\n"
4446 "The @code{_mtime} attribute is updated each time an element is modified by "
4447 "either storing content, editing attributes or by deleting a child element. "
4448 "The @code{_ctime} attribute is created for each new element in an element "
4449 "path."
4450 "\n"
4451 "When the @option{--inquire} option is passed then all remaining non-option "
4452 "arguments are retrieved via a server @emph{INQUIRE}."
4453 "\n"
4454 "@xref{Target Attribute}, for details about this special attribute."
4457 new_command("XPATH", 0, 1, xpath_command, _(
4458 "XPATH [--inquire] <expression>[<TAB>[value]]\n"
4459 "Evaluates an XPath @var{expression}. If no @var{value} argument is "
4460 "specified, it is assumed the expression is a request to return a result. "
4461 "Otherwise, the result is set to the @var{value} argument and the document is "
4462 "updated. If there is no @var{value} after the @key{TAB} character, the value "
4463 "is assumed to be empty and the document is updated. For example:"
4464 "@sp 1\n"
4465 "@example\n"
4466 "XPATH //element[@@_name='password']@key{TAB}\n"
4467 "@end example\n"
4468 "@sp 1"
4469 "would clear the content of all @code{password} elements in the data file "
4470 "while leaving off the trailing @key{TAB} would return all @code{password} "
4471 "elements in @abbr{XML} format."
4472 "\n"
4473 "When the @option{--inquire} option is passed then all remaining non-option "
4474 "arguments are retrieved via a server @emph{INQUIRE}."
4475 "\n"
4476 "See @url{http://www.w3schools.com/xpath/xpath_syntax.asp} for @abbr{XPATH} "
4477 "expression syntax."
4480 new_command("XPATHATTR", 0, 1, xpathattr_command, _(
4481 "XPATHATTR [--inquire] SET|DELETE <name> <expression>[<TAB>[<value>]]\n"
4482 "Like the @code{XPATH} command (@pxref{XPATH}) but operates on element "
4483 "attributes and does not return a result. For the @var{SET} operation the "
4484 "@var{value} is optional but the field is required. If not specified then "
4485 "the attribute value will be empty. For example:"
4486 "@sp 1"
4487 "@example\n"
4488 "XPATHATTR SET password //element[@@_name='password']@key{TAB}\n"
4489 "@end example\n"
4490 "@sp 1"
4491 "would create an @code{password} attribute for each @code{password} element "
4492 "found in the document. The attribute value will be empty but still exist."
4493 "\n"
4494 "When the @option{--inquire} option is passed then all remaining non-option "
4495 "arguments are retrieved via a server @emph{INQUIRE}."
4496 "\n"
4497 "See @url{http://www.w3schools.com/xpath/xpath_syntax.asp} for @abbr{XPATH} "
4498 "expression syntax."
4501 new_command("IMPORT", 0, 1, import_command, _(
4502 "IMPORT <content>[<TAB>[!]element[<TAB>[!]child[..]]]\n"
4503 "This command uses a server @emph{INQUIRE} to retrieve data from the client."
4504 "\n"
4505 "Like the @code{STORE} command (@pxref{STORE}), but the @var{content} "
4506 "argument is raw @abbr{XML} data. The content is created as a child of the "
4507 "specified element path and will overwrite an existing element of the same "
4508 "name. If an element of the element path does not exist then it will be "
4509 "created."
4510 "\n"
4511 "The content must begin with an @abbr{XML} element node. @xref{Introduction}, "
4512 "for details."
4515 new_command("DUMP", 0, 1, dump_command, _(
4516 "DUMP\n"
4517 "Shows the in memory @abbr{XML} document with indenting. @xref{XPATH}, for "
4518 "dumping a specific node."
4521 new_command("LOCK", 0, 0, lock_command, _(
4522 "LOCK\n"
4523 "Locks the mutex associated with the opened file. This prevents other clients "
4524 "from sending commands to the same opened file until the client "
4525 "that sent this command either disconnects or sends the @code{UNLOCK} "
4526 "command. @xref{UNLOCK}."
4529 new_command("UNLOCK", 1, 0, unlock_command, _(
4530 "UNLOCK\n"
4531 "Unlocks the file mutex which was locked with the @code{LOCK} command or "
4532 "a commands' @option{lock} option. @xref{LOCK}."
4535 new_command("GETCONFIG", 1, 1, getconfig_command, _(
4536 "GETCONFIG [filename] <parameter>\n"
4537 "Returns the value of a @command{pwmd} configuration @var{parameter} with a "
4538 "data response. If no file has been opened then the value for @var{filename} "
4539 "or the default from the @samp{global} section will be returned. If a file "
4540 "has been opened and no @var{filename} is specified, a value previously "
4541 "set with the @code{OPTION} command (@pxref{OPTION}) will be returned."
4544 new_command("OPTION", 1, 1, NULL, _(
4545 "OPTION <NAME>=<VALUE>\n"
4546 "Sets a client option @var{name} to @var{value}. The value for an option is "
4547 "kept for the duration of the connection."
4548 "\n"
4549 "@table @asis\n"
4550 "@item TTYNAME\n"
4551 " Passed to the @command{gpg-agent} and used for the @command{pinentry} dialog."
4552 "\n"
4553 "@item TTYTYPE\n"
4554 " Passed to the @command{gpg-agent} and used for the @command{pinentry} dialog."
4555 "\n"
4556 "@item DISPLAY\n"
4557 " Passed to the @command{gpg-agent} and used for the @command{pinentry} dialog."
4558 "\n"
4559 "@item DESC\n"
4560 " Sets the description string of the @command{gpg-agent} and @command{pinentry} dialog."
4561 "\n"
4562 "@item LC-CTYPE\n"
4563 " Passed to the @command{gpg-agent} and used for the @command{pinentry} dialog."
4564 "\n"
4565 "@item LC-MESSAGES\n"
4566 " Passed to the @command{gpg-agent} and used for the @command{pinentry} dialog."
4567 "\n"
4568 "@item NAME\n"
4569 " Associates the thread ID of the connection with the specified textual "
4570 "representation. Useful for debugging log messages."
4571 "\n"
4572 "@item LOCK-TIMEOUT\n"
4573 " When not @code{0}, the duration in tenths of a second to wait for the file "
4574 "mutex which has been locked by another thread to be released before returning "
4575 "an error. When @code{-1}, then an error will be returned immediately."
4576 "@end table\n"
4579 new_command("LS", 1, 1, ls_command, _(
4580 "LS\n"
4581 "Lists the available data files stored in the data directory "
4582 "(@file{~/.pwmd/data}). The result is a newline separated list of filenames."
4585 new_command("RESET", 1, 1, NULL, _(
4586 "RESET\n"
4587 "Closes the currently opened file but keeps any previously set client options."
4590 new_command("NOP", 1, 1, NULL, _(
4591 "NOP\n"
4592 "Does nothing. Always returns successfully."
4595 /* !END-HELP-TEXT! */
4596 new_command ("CANCEL", 1, 1, NULL, NULL);
4597 new_command ("END", 1, 1, NULL, NULL);
4598 new_command ("BYE", 1, 1, NULL, NULL);
4600 int i;
4601 for (i = 0; command_table[i]; i++);
4602 qsort (command_table, i - 1, sizeof (struct command_table_s *),
4603 sort_commands);
4606 gpg_error_t
4607 register_commands (assuan_context_t ctx)
4609 int i = 0, rc;
4611 for (; command_table[i]; i++)
4613 if (!command_table[i]->handler)
4614 continue;
4616 rc = assuan_register_command (ctx, command_table[i]->name,
4617 command_table[i]->handler,
4618 command_table[i]->help);
4619 if (rc)
4620 return rc;
4623 rc = assuan_register_option_handler (ctx, option_command);
4624 if (rc)
4625 return rc;
4627 rc = assuan_register_bye_notify (ctx, bye_notify);
4628 if (rc)
4629 return rc;
4631 rc = assuan_register_reset_notify (ctx, reset_notify);
4632 if (rc)
4633 return rc;
4635 rc = assuan_register_pre_cmd_notify (ctx, command_startup);
4636 if (rc)
4637 return rc;
4639 return assuan_register_post_cmd_notify (ctx, command_finalize);