Update doc/yat2m.c.
[pwmd.git] / src / commands.c
blob3c536742c13ac0bec9f4b4b16387bc5024dcd037
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
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 "util-misc.h"
47 #include "common.h"
48 #include "rcfile.h"
49 #include "cache.h"
50 #include "commands.h"
51 #include "mutex.h"
52 #include "crypto.h"
53 #include "pinentry.h"
55 /* These are command option flags. */
56 #define OPT_INQUIRE 0x0001
57 #define OPT_NO_PASSPHRASE 0x0002
58 #define OPT_RESET 0x0004
59 #define OPT_LIST_RECURSE 0x0008
60 #define OPT_VERBOSE 0x0010
61 #define OPT_LOCK 0x0020
62 #define OPT_LOCK_ON_OPEN 0x0040
63 #define OPT_SIGN 0x0080
64 #define OPT_LIST_ALL 0x0100
65 #define OPT_LIST_WITH_TARGET 0x0200
66 #define OPT_DATA 0x0400
67 #define OPT_NO_AGENT 0x0800
68 #define OPT_ASK 0x1000
70 #ifdef WITH_AGENT
71 /* The GETCONFIG command, for example, may fail because pwmd lost the
72 * gpg-agent connection. Update the recovered agent ctx. */
73 #define UPDATE_AGENT_CTX(client, crypto) do { \
74 if (crypto && crypto->agent && crypto->agent->did_restart \
75 && client->crypto && client->crypto->agent \
76 && client->crypto->agent->ctx && \
77 crypto->agent->ctx != client->crypto->agent->ctx) \
78 { \
79 client->crypto->agent->ctx = crypto->agent->ctx; \
80 crypto->agent->ctx = NULL; \
81 } \
82 } while (0)
83 #else
84 #define UPDATE_AGENT_CTX(client, crypto)
85 #endif
87 #define FLOCK_TYPE_NONE 0
88 #define FLOCK_TYPE_SH 0x0001
89 #define FLOCK_TYPE_EX 0x0002
90 #define FLOCK_TYPE_KEEP 0x0004
92 struct command_table_s
94 const char *name;
95 gpg_error_t (*handler) (assuan_context_t, char *line);
96 const char *help;
97 int ignore_startup;
98 int unlock; // unlock the file mutex after validating the checksum
99 uint32_t flock_type;
102 static struct command_table_s **command_table;
104 static gpg_error_t do_lock (struct client_s *client, int add);
105 static gpg_error_t validate_checksum (struct client_s *,
106 struct cache_data_s *);
107 static gpg_error_t update_checksum (struct client_s *client);
109 /* When 'status' is true the 'self' field of the status line will be false
110 * because we never send the STATE status message to the same client that
111 * initiated it. */
112 static char *
113 build_client_info_line (struct client_thread_s *thd, int status)
115 MUTEX_LOCK (&cn_mutex);
116 int with_state = config_get_boolean ("global", "send_state");
117 char *uid, *username = NULL;
118 char *line;
120 #ifdef WITH_GNUTLS
121 if (thd->remote)
122 uid = str_asprintf("#%s", thd->tls->fp);
123 else
125 uid = str_asprintf("%u", thd->peer->uid);
126 username = get_username (thd->peer->uid);
128 #else
129 uid = str_asprintf("%u", thd->peer->uid);
130 username = get_username (thd->peer->uid);
131 #endif
132 line = str_asprintf ("%p %s %s %s %u %u %u %s %s",
133 thd->tid,
134 thd->name ? thd->name : "-",
135 thd->cl && thd->cl->filename
136 && (thd->cl->flags & FLAG_OPEN)
137 ? thd->cl->filename : "/",
138 #ifdef WITH_GNUTLS
139 thd->remote ? thd->peeraddr : "-",
140 #else
141 "-",
142 #endif
143 thd->cl && thd->cl->flags & FLAG_HAS_LOCK ? 1 : 0,
144 !status && pthread_equal (pthread_self (), thd->tid) ? 1 : 0,
145 with_state ? thd->state : CLIENT_STATE_UNKNOWN, uid,
146 #ifdef WITH_GNUTLS
147 thd->remote ? "" : username
148 #else
149 username
150 #endif
153 xfree (username);
154 xfree (uid);
155 MUTEX_UNLOCK (&cn_mutex);
156 return line;
159 void
160 update_client_state (struct client_s *client, unsigned s)
162 client->thd->state = s;
163 int n = config_get_boolean ("global", "send_state");
165 if (n && client->thd->state != CLIENT_STATE_UNKNOWN)
167 char *line = build_client_info_line (client->thd, 1);
169 if (line)
170 send_status_all_not_self (n == 2, STATUS_STATE, "%s", line);
174 static gpg_error_t
175 unlock_file_mutex (struct client_s *client, int remove)
177 gpg_error_t rc = 0;
179 // OPEN: keep the lock for the same file being reopened.
180 if (client->flags & FLAG_KEEP_LOCK && client->flags & FLAG_HAS_LOCK)
181 return 0;
183 if (!(client->flags & FLAG_HAS_LOCK))
184 return GPG_ERR_NOT_LOCKED;
186 rc = cache_unlock_mutex (client->md5file, remove);
187 if (rc)
188 rc = GPG_ERR_INV_STATE;
189 else
190 client->flags &= ~(FLAG_HAS_LOCK | FLAG_LOCK_CMD);
192 return rc;
195 static gpg_error_t
196 lock_file_mutex (struct client_s *client, int add)
198 gpg_error_t rc = 0;
199 int timeout = config_get_integer (client->filename, "cache_timeout");
201 if (client->flags & FLAG_HAS_LOCK)
202 return 0;
204 rc = cache_lock_mutex (client->ctx, client->md5file,
205 client->lock_timeout, add, timeout);
206 if (!rc)
207 client->flags |= FLAG_HAS_LOCK;
209 return rc;
212 static gpg_error_t
213 file_modified (struct client_s *client, struct command_table_s *cmd)
215 gpg_error_t rc = 0;
216 int type = !cmd->flock_type || (cmd->flock_type & FLOCK_TYPE_SH)
217 ? LOCK_SH : LOCK_EX;
219 if (!(client->flags & FLAG_OPEN))
220 return GPG_ERR_INV_STATE;
222 rc = lock_file_mutex (client, 0);
223 if (rc && rc != GPG_ERR_NO_DATA)
224 return rc;
226 rc = lock_flock (client->ctx, client->filename, type, &client->flock_fd);
227 if (!rc)
229 rc = validate_checksum (client, NULL);
230 if (gpg_err_code (rc) == GPG_ERR_ENOENT && (client->flags & FLAG_NEW))
231 rc = 0;
232 else if (rc)
233 log_write ("%s: %s", client->filename, pwmd_strerror (rc));
235 else if (gpg_err_code(rc) == GPG_ERR_ENOENT)
236 rc = 0;
238 if ((cmd->unlock && !(client->flags & FLAG_HAS_LOCK)) || rc)
239 unlock_file_mutex (client, 0);
241 if (rc || !(cmd->flock_type & FLOCK_TYPE_KEEP))
242 unlock_flock (&client->flock_fd);
244 return rc;
247 static gpg_error_t
248 parse_xml (assuan_context_t ctx, int new)
250 struct client_s *client = assuan_get_pointer (ctx);
251 int cached = client->doc != NULL;
252 gpg_error_t rc = 0;
254 if (new)
256 client->doc = new_document ();
257 if (client->doc)
259 xmlChar *result;
260 int len;
262 xmlDocDumpFormatMemory (client->doc, &result, &len, 0);
263 client->crypto->plaintext = result;
264 client->crypto->plaintext_len = len;
265 if (!client->crypto->plaintext)
267 xmlFreeDoc (client->doc);
268 client->doc = NULL;
269 rc = GPG_ERR_ENOMEM;
272 else
273 rc = GPG_ERR_ENOMEM;
275 else if (!cached)
276 rc = parse_doc ((char *) client->crypto->plaintext,
277 client->crypto->plaintext_len, (xmlDocPtr *)&client->doc);
279 return rc;
282 static void
283 free_client (struct client_s *client)
285 if (client->doc)
286 xmlFreeDoc (client->doc);
288 xfree (client->crc);
289 xfree (client->filename);
290 xfree (client->last_error);
292 if (client->crypto)
294 cleanup_crypto_stage2 (client->crypto);
295 if (client->crypto->pkey_sexp)
296 gcry_sexp_release (client->crypto->pkey_sexp);
298 if (client->crypto->sigpkey_sexp)
299 gcry_sexp_release (client->crypto->sigpkey_sexp);
301 client->crypto->pkey_sexp = NULL;
302 client->crypto->sigpkey_sexp = NULL;
303 memset (client->crypto->sign_grip, 0,
304 sizeof (client->crypto->sign_grip));
305 memset (client->crypto->grip, 0, sizeof(client->crypto->grip));
309 void
310 cleanup_client (struct client_s *client)
312 assuan_context_t ctx = client->ctx;
313 struct client_thread_s *thd = client->thd;
314 struct crypto_s *crypto = client->crypto;
315 long lock_timeout = client->lock_timeout;
316 int no_pinentry = (client->flags & FLAG_NO_PINENTRY);
317 struct pinentry_option_s pin_opts;
318 xmlErrorPtr xml_error = client->xml_error;
319 int flock_fd = client->flock_fd;
320 #ifdef WITH_AGENT
321 struct pinentry_option_s agent_pin_opts;
323 if (crypto && crypto->agent)
324 memcpy (&agent_pin_opts, &crypto->agent->pinentry_opts,
325 sizeof(struct pinentry_option_s));
326 #endif
328 memcpy (&pin_opts, &client->pinentry_opts, sizeof(struct pinentry_option_s));
329 unlock_file_mutex (client, client->flags & FLAG_NEW);
330 free_client (client);
331 memset (client, 0, sizeof (struct client_s));
332 client->flock_fd = flock_fd;
333 client->xml_error = xml_error;
334 client->crypto = crypto;
335 client->ctx = ctx;
336 client->thd = thd;
337 client->lock_timeout = lock_timeout;
338 memcpy (&client->pinentry_opts, &pin_opts, sizeof(struct pinentry_option_s));
339 client->flags |= no_pinentry ? FLAG_NO_PINENTRY : 0;
340 #ifdef WITH_AGENT
341 if (crypto && crypto->agent)
342 memcpy (&crypto->agent->pinentry_opts, &agent_pin_opts,
343 sizeof(struct pinentry_option_s));
344 #endif
347 static gpg_error_t
348 open_finalize (assuan_context_t ctx, char *key, size_t keylen)
350 struct client_s *client = assuan_get_pointer (ctx);
351 gpg_error_t rc = 0;
352 struct cache_data_s *cdata = cache_get_data (client->md5file);
353 int cached = 0, keyarg = key ? 1 : 0;
354 size_t keysize;
355 unsigned char *salted_key = NULL;
356 int algo;
357 int pin_try = 1;
358 int pin_tries = 3;
359 char *pin_title = client->pinentry_opts.title;
361 client->crypto->filename = str_dup (client->filename);
362 if (cdata || client->flags & FLAG_NEW)
364 if (cdata && !(client->flags & FLAG_NEW))
366 rc = decrypt_cache (client->crypto, cdata->doc, cdata->doclen);
367 if (rc)
368 return rc;
371 cached = cdata != NULL;
372 goto done;
375 if (!key && !IS_PKI (client->crypto)
376 && !(client->crypto->hdr.flags & PWMD_FLAG_NO_PASSPHRASE))
378 if (client->flags & FLAG_NO_PINENTRY)
380 rc = inquire_passphrase (ctx, "PASSPHRASE", (unsigned char **)&key,
381 &keylen);
382 if (rc)
383 return rc;
385 else
387 client->pinentry_opts.timeout = config_get_integer (client->filename,
388 "pinentry_timeout");
389 pin_again:
390 rc = getpin_common (client->ctx, client->filename, PINENTRY_OPEN,
391 &key, &keylen);
392 if (rc)
393 return rc;
397 if (!IS_PKI (client->crypto))
399 if (client->crypto->hdr.flags & PWMD_FLAG_NO_PASSPHRASE)
401 keylen = 1;
402 key = gcry_malloc (keylen);
403 memset (key, 0, keylen);
406 algo = cipher_to_gcrypt (client->crypto->hdr.flags);
407 rc = hash_key (algo, client->crypto->hdr.salt,
408 sizeof(client->crypto->hdr.salt), key, keylen,
409 (void **)&salted_key, &keysize,
410 client->crypto->hdr.version <= 0x03000e ? COMPAT_KDFS2K_ITERATIONS : client->crypto->hdr.s2k_count);
411 if (!keyarg)
412 gcry_free (key);
414 if (!rc)
416 rc = decrypt_data (client->ctx, client->crypto, salted_key, keysize);
417 if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
418 && ++pin_try <= pin_tries && !(client->flags & FLAG_NO_PINENTRY))
420 gcry_free (salted_key);
421 salted_key = NULL;
422 key = NULL;
423 keylen = 0;
424 client->pinentry_opts.title = str_asprintf (_ ("Bad passphrase (try %i of %i)"), pin_try, pin_tries);
425 goto pin_again;
429 if (client->pinentry_opts.title != pin_title)
430 xfree (client->pinentry_opts.title);
432 client->pinentry_opts.title = pin_title;
433 if (rc)
435 gcry_free (salted_key);
436 return rc;
439 cdata = xcalloc (1, sizeof (struct cache_data_s));
440 if (!cdata)
442 gcry_free (salted_key);
443 return GPG_ERR_ENOMEM;
446 cdata->key = salted_key;
447 cdata->keylen = keysize;
449 else
450 #ifdef WITH_AGENT
451 rc = decrypt_data (client->ctx, client->crypto, NULL, 0);
452 #else
453 rc = GPG_ERR_NOT_IMPLEMENTED;
454 #endif
456 done:
457 if (!rc)
459 rc = parse_xml (ctx, client->flags & FLAG_NEW);
460 if (rc && !cached)
461 free_cache_data_once (cdata);
463 if (!rc)
465 int timeout = config_get_integer (client->filename,
466 "cache_timeout");
468 if (!cached)
470 if (!cdata)
471 cdata = xcalloc (1, sizeof (struct cache_data_s));
473 rc = encrypt_xml (NULL, cache_key, cache_keysize,
474 GCRY_CIPHER_AES, client->crypto->plaintext,
475 client->crypto->plaintext_len, &cdata->doc,
476 &cdata->doclen, &cache_iv, &cache_blocksize);
477 if (!rc && !(client->flags & FLAG_NEW) && IS_PKI (client->crypto))
479 rc = gcry_sexp_build ((gcry_sexp_t *) & cdata->pubkey, NULL,
480 "%S", client->crypto->pkey_sexp);
484 if (cdata->sigkey)
485 gcry_sexp_release (cdata->sigkey);
487 cdata->sigkey = NULL;
488 if (!rc && IS_PKI (client->crypto))
489 rc = gcry_sexp_build ((gcry_sexp_t *) &cdata->sigkey, NULL,
490 "%S", client->crypto->sigpkey_sexp);
492 if (!rc)
494 rc = cache_add_file (client->md5file,
495 (client->flags & FLAG_NEW) ? NULL
496 : client->crypto->grip, cdata, timeout);
497 if (rc)
499 if (!cached)
501 free_cache_data_once (cdata);
502 xmlFreeDoc (client->doc);
503 client->doc = NULL;
508 if (!rc)
509 client->flags |= FLAG_OPEN;
513 if (!rc)
515 rc = update_checksum (client);
516 if (gpg_err_code (rc) == GPG_ERR_ENOENT)
517 rc = 0;
520 if (!rc && (client->opts & OPT_LOCK_ON_OPEN))
521 rc = do_lock (client, 0);
523 return rc;
526 static void
527 req_cleanup (void *arg)
529 if (!arg)
530 return;
532 strv_free ((char **) arg);
535 static gpg_error_t
536 parse_open_opt_lock (void *data, void *value)
538 struct client_s *client = data;
540 client->opts |= OPT_LOCK_ON_OPEN;
541 return 0;
544 static gpg_error_t
545 parse_save_opt_inquire (void *data, void *value)
547 struct client_s *client = data;
548 gpg_error_t rc;
550 if (!(client->flags & FLAG_NEW))
552 rc = peer_is_invoker (client);
553 if (rc == GPG_ERR_EACCES)
554 return rc;
557 (void) value;
558 client->opts |= OPT_INQUIRE;
559 return 0;
562 static gpg_error_t
563 parse_opt_inquire (void *data, void *value)
565 struct client_s *client = data;
567 (void) value;
568 client->opts |= OPT_INQUIRE;
569 return 0;
572 static gpg_error_t
573 update_checksum (struct client_s *client)
575 unsigned char *crc;
576 size_t len;
577 struct cache_data_s *cdata;
578 gpg_error_t rc = get_checksum (client->filename, &crc, &len);
580 if (rc)
581 return rc;
583 xfree (client->crc);
584 client->crc = crc;
585 cdata = cache_get_data (client->md5file);
586 if (cdata)
588 xfree (cdata->crc);
589 cdata->crc = xmalloc (len);
590 memcpy (cdata->crc, crc, len);
593 return 0;
596 static gpg_error_t
597 validate_checksum (struct client_s *client, struct cache_data_s *cdata)
599 unsigned char *crc;
600 size_t len;
601 gpg_error_t rc;
602 int n = 0;
604 if (cdata && !cdata->crc)
605 return GPG_ERR_CHECKSUM;
607 rc = get_checksum (client->filename, &crc, &len);
608 if (rc)
609 return rc;
611 if (cdata)
612 n = memcmp (cdata->crc, crc, len);
613 else if (client->crc)
614 n = memcmp (client->crc, crc, len);
616 xfree (crc);
617 return n ? GPG_ERR_CHECKSUM : 0;
620 static gpg_error_t
621 do_open (assuan_context_t ctx, const char *password)
623 struct client_s *client = assuan_get_pointer (ctx);
624 struct cache_data_s *cdata;
625 gpg_error_t rc = 0;
626 int done = 0;
628 // Cached document?
629 cdata = cache_get_data (client->md5file);
630 if (cdata && cdata->doc)
632 int defer = 0;
634 /* This will check that the key is cached in the agent which needs to
635 * be determined for files that share a keygrip. */
636 if (!rc)
638 rc = cache_iscached (client->filename, &defer);
639 if ((!rc || rc == GPG_ERR_ENOENT) && defer)
640 rc = GPG_ERR_KEY_EXPIRED;
643 if (!rc && !(client->flags & FLAG_NEW))
644 rc = validate_checksum (client, cdata);
646 #ifdef WITH_GNUTLS
647 if (!rc && client->thd->remote
648 && config_get_boolean (client->filename, "tcp_require_key"))
649 rc = GPG_ERR_KEY_EXPIRED;
650 #endif
652 if (!rc && !password)
654 rc = read_data_header (client->filename, &client->crypto->hdr,
655 NULL, NULL);
656 if (!rc)
658 if (IS_PKI (client->crypto))
660 gcry_sexp_build (&client->crypto->pkey_sexp, NULL, "%S",
661 cdata->pubkey);
662 gcry_pk_get_keygrip (client->crypto->pkey_sexp,
663 client->crypto->grip);
664 gcry_sexp_build (&client->crypto->sigpkey_sexp, NULL, "%S",
665 cdata->sigkey);
666 gcry_pk_get_keygrip (client->crypto->sigpkey_sexp,
667 client->crypto->sign_grip);
670 if (!rc)
672 rc = open_finalize (ctx, NULL, 0);
673 done = 1;
678 /* There was an error accessing the file so clear the cache entry. The
679 * real error will be returned from read_data_file() since the file
680 * may have only disappeared. */
681 if (!done)
683 log_write ("%s: %s", client->filename, pwmd_strerror (rc));
684 rc = cache_clear (client->md5file);
685 send_status_all (STATUS_CACHE, NULL);
689 if (done || rc)
690 return rc;
692 rc = read_data_file (client->filename, client->crypto);
693 if (rc)
695 if (gpg_err_source (rc) != GPG_ERR_SOURCE_DEFAULT ||
696 gpg_err_code (rc) != GPG_ERR_ENOENT)
698 log_write ("%s: %s", client->filename, pwmd_strerror (rc));
699 return rc;
702 client->flags |= FLAG_NEW;
703 memset (client->crypto->grip, 0, sizeof (client->crypto->grip));
704 memset (client->crypto->sign_grip, 0,
705 sizeof (client->crypto->sign_grip));
706 rc = open_finalize (ctx, NULL, 0);
707 return rc;
710 if (password && IS_PKI (client->crypto))
712 #ifdef WITH_AGENT
713 rc = set_agent_passphrase (client->crypto, password, strlen (password));
714 if (rc)
715 return rc;
716 #endif
719 rc = open_finalize (ctx, (char *)password, password ? strlen (password) : 0);
720 return rc;
723 static gpg_error_t
724 open_command (assuan_context_t ctx, char *line)
726 gpg_error_t rc;
727 struct client_s *client = assuan_get_pointer (ctx);
728 char **req, *filename;
729 unsigned char md5file[16];
730 int same_file = 0;
731 assuan_peercred_t peer;
732 struct argv_s *args[] = {
733 &(struct argv_s) {"lock", OPTION_TYPE_NOARG, parse_open_opt_lock},
734 NULL
737 rc = parse_options (&line, args, client, 1);
738 if (rc)
739 return send_error (ctx, rc);
741 req = str_split (line, " ", 2);
742 if (!req)
743 return send_error (ctx, GPG_ERR_SYNTAX);
745 rc = do_validate_peer (ctx, req[0], &peer);
746 if (rc)
748 strv_free (req);
749 return send_error (ctx, rc);
752 filename = req[0];
753 if (!valid_filename (filename))
755 strv_free (req);
756 return send_error (ctx, GPG_ERR_INV_VALUE);
759 pthread_cleanup_push (req_cleanup, req);
760 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, filename, strlen (filename));
761 /* This client may have locked a different file with ISCACHED --lock than
762 * the current filename. This will remove that lock. */
763 same_file = !memcmp (md5file, client->md5file, 16) ? 1 : 0;
764 if (client->flags & FLAG_OPEN ||
765 (client->flags & FLAG_HAS_LOCK && !same_file))
767 uint32_t opts = client->opts;
768 uint32_t flags = client->flags;
770 if (same_file)
771 client->flags |= FLAG_KEEP_LOCK;
772 else if (client->flags & FLAG_NEW)
773 cache_clear (client->md5file);
775 cleanup_client (client);
776 client->opts = opts;
777 client->flags |= flags;
778 client->flags &= ~(FLAG_LOCK_CMD);
779 if (!same_file)
780 client->flags &= ~(FLAG_HAS_LOCK | FLAG_NEW);
783 memcpy (client->md5file, md5file, 16);
784 client->filename = str_dup (filename);
785 if (!client->filename)
786 rc = GPG_ERR_ENOMEM;
788 /* Need to lock the mutex here because file_modified() cannot without
789 * knowing the filename. */
790 if (!rc)
792 rc = lock_file_mutex (client, 1);
793 if (rc)
794 client->flags &= ~FLAG_OPEN;
797 if (!rc)
799 rc = lock_flock (ctx, filename, LOCK_SH, &client->flock_fd);
800 if (!rc || gpg_err_code (rc) == GPG_ERR_ENOENT)
801 rc = 0;
804 if (!rc)
806 struct stat st;
808 if (stat (filename, &st) == -1 && errno != ENOENT)
809 rc = gpg_error_from_syserror ();
810 else if (!errno)
812 if (!rc && !S_ISREG (st.st_mode)) // to match LS output
813 rc = gpg_error_from_errno (ENOANO);
817 if (!rc)
819 char *password = req[1] && *req[1] ? req[1] : NULL;
821 #ifdef WITH_AGENT
822 if (IS_PKI (client->crypto))
823 rc = set_pinentry_mode (client->crypto->agent,
824 (client->flags & FLAG_NO_PINENTRY) ? "loopback"
825 : "ask");
826 #endif
827 if (!rc)
829 rc = do_open (ctx, password);
830 if (rc)
831 cleanup_client (client);
833 cleanup_crypto_stage1 (client->crypto);
837 pthread_cleanup_pop (1);
839 if (!rc && client->flags & FLAG_NEW)
840 rc = send_status (ctx, STATUS_NEWFILE, NULL);
842 #ifdef WITH_AGENT
843 (void) kill_scd (client->crypto->agent);
844 #endif
846 return send_error (ctx, rc);
849 static gpg_error_t
850 parse_opt_no_passphrase (void *data, void *value)
852 struct client_s *client = data;
854 (void) value;
855 client->opts |= OPT_NO_PASSPHRASE;
856 return 0;
859 static gpg_error_t
860 parse_save_opt_no_agent (void *data, void *value)
862 struct client_s *client = data;
864 client->opts |= OPT_NO_AGENT;
865 return 0;
868 static gpg_error_t
869 parse_save_opt_cipher (void *data, void *value)
871 struct client_s *client = data;
872 int algo = cipher_string_to_gcrypt ((char *) value);
873 file_header_t *hdr = &client->crypto->save.hdr;
874 gpg_error_t rc = 0;
876 if (algo == -1)
877 return GPG_ERR_INV_VALUE;
879 if (!(client->flags & FLAG_NEW))
881 rc = peer_is_invoker (client);
882 if (rc == GPG_ERR_EACCES)
884 uint64_t flags = 0;
886 flags &= ((uint16_t) ((uint32_t) (flags & 0xFFFFFFFF)));
887 if (!(client->crypto->hdr.flags & gcrypt_to_cipher (algo)))
888 return rc;
890 rc = 0;
892 else if (rc)
893 return rc;
896 if (!rc)
897 hdr->flags = set_cipher_flag (hdr->flags, algo);
899 return rc;
902 #ifdef WITH_AGENT
903 static gpg_error_t
904 permitted_to_save (struct client_s *client, const unsigned char *grip,
905 size_t size, const char *value)
907 char *hexgrip;
908 gpg_error_t rc = 0;
910 if (!(client->flags & FLAG_NEW))
912 hexgrip = bin2hex (grip, size);
913 rc = !strcmp (hexgrip, (char *)value) ? 0 : GPG_ERR_EACCES;
914 xfree (hexgrip);
915 if (rc)
916 rc = peer_is_invoker (client);
919 return rc;
921 #endif
923 static gpg_error_t
924 parse_save_opt_keygrip (void *data, void *value)
926 #ifdef WITH_AGENT
927 struct client_s *client = data;
928 gpg_error_t rc = permitted_to_save (client, client->crypto->grip,
929 sizeof (client->crypto->grip),
930 value);
932 if (!IS_PKI (client->crypto))
933 return GPG_ERR_INV_ARG;
935 if (rc)
936 return rc;
938 if (client->crypto->save.pkey)
939 gcry_sexp_release (client->crypto->save.pkey);
941 client->crypto->save.pkey = NULL;
942 return get_pubkey (client->crypto, value, &client->crypto->save.pkey);
943 #else
944 return GPG_ERR_INV_ARG;
945 #endif
948 static gpg_error_t
949 parse_save_opt_sign_keygrip (void *data, void *value)
951 #ifdef WITH_AGENT
952 struct client_s *client = data;
953 gpg_error_t rc = permitted_to_save (client, client->crypto->sign_grip,
954 sizeof (client->crypto->sign_grip),
955 value);
957 if (!IS_PKI (client->crypto))
958 return GPG_ERR_INV_ARG;
960 if (rc)
961 return rc;
963 if (client->crypto->save.sigpkey)
964 gcry_sexp_release (client->crypto->save.sigpkey);
966 client->crypto->save.sigpkey = NULL;
967 return get_pubkey (client->crypto, value, &client->crypto->save.sigpkey);
968 #else
969 return GPG_ERR_INV_ARG;
970 #endif
973 static gpg_error_t
974 parse_opt_s2k_count (void *data, void *value)
976 struct client_s *client = data;
977 char *v = value, *p;
978 uint64_t n;
980 if (!v || !*v)
981 return GPG_ERR_INV_VALUE;
983 errno = 0;
984 n = strtoull (v, &p, 10);
985 if (n == UINT64_MAX && errno)
986 return gpg_error_from_errno (errno);
987 else if (p && *p)
988 return GPG_ERR_INV_VALUE;
990 if (!(client->flags & FLAG_NEW))
992 gpg_error_t rc = peer_is_invoker (client);
994 if (rc == GPG_ERR_EACCES)
996 if (n && client->crypto->hdr.s2k_count != n)
997 return rc;
999 rc = 0;
1001 else if (rc)
1002 return rc;
1005 // Keep compatibility with libpwmd passing --s2k-count=0. If somehow
1006 // s2k_count == 0 it will be set to DEFAULT_KDFS2K_ITERATIONS in
1007 // save_command().
1008 if (n)
1009 client->crypto->save.hdr.s2k_count = n;
1011 return 0;
1014 static gpg_error_t
1015 save_finalize (assuan_context_t ctx)
1017 struct client_s *client = assuan_get_pointer (ctx);
1018 gpg_error_t rc = 0;
1019 xmlChar *xmlbuf = NULL;
1020 int xmlbuflen;
1021 void *key = NULL;
1022 size_t keylen = 0;
1024 xmlDocDumpFormatMemory (client->doc, &xmlbuf, &xmlbuflen, 0);
1025 if (!xmlbuf)
1026 return GPG_ERR_ENOMEM;
1028 pthread_cleanup_push (xmlFree, xmlbuf);
1030 if (!use_agent || ((client->flags & FLAG_NEW)
1031 && (client->opts & OPT_NO_AGENT))
1032 || !(client->crypto->hdr.flags & PWMD_FLAG_PKI))
1034 rc = export_common (ctx, client->flags & FLAG_NO_PINENTRY,
1035 client->crypto, xmlbuf, xmlbuflen, client->filename,
1036 NULL, &key, &keylen, 1, 1,
1037 (client->opts & OPT_NO_PASSPHRASE));
1039 #ifdef WITH_AGENT
1040 else
1042 gcry_sexp_t pubkey = client->crypto->save.pkey;
1043 gcry_sexp_t sigkey = client->crypto->save.sigpkey;
1045 if (!pubkey)
1046 pubkey = client->crypto->pkey_sexp;
1048 if (!sigkey)
1050 sigkey = client->crypto->sigpkey_sexp;
1051 if (!sigkey)
1053 gcry_sexp_build (&client->crypto->save.sigpkey, 0, "%S", pubkey);
1054 sigkey = client->crypto->save.sigpkey;
1058 rc = encrypt_data_file (client->ctx, client->crypto, pubkey, sigkey,
1059 client->filename, xmlbuf, xmlbuflen);
1060 if (pubkey == client->crypto->save.pkey)
1062 if (!rc)
1064 gcry_sexp_release (client->crypto->pkey_sexp);
1065 client->crypto->pkey_sexp = client->crypto->save.pkey;
1066 gcry_pk_get_keygrip (client->crypto->pkey_sexp,
1067 client->crypto->grip);
1069 else
1070 gcry_sexp_release (pubkey);
1072 client->crypto->save.pkey = NULL;
1075 if (!rc)
1076 gcry_pk_get_keygrip (sigkey, client->crypto->sign_grip);
1078 if (sigkey == client->crypto->save.sigpkey)
1080 if (!rc)
1082 if (client->crypto->sigpkey_sexp)
1083 gcry_sexp_release (client->crypto->sigpkey_sexp);
1085 client->crypto->sigpkey_sexp = client->crypto->save.sigpkey;
1086 gcry_pk_get_keygrip (client->crypto->sigpkey_sexp,
1087 client->crypto->sign_grip);
1089 else
1090 gcry_sexp_release (sigkey);
1092 client->crypto->save.sigpkey = NULL;
1095 #endif
1097 if (!rc)
1099 int cached;
1101 rc = save_common (client->filename, client->crypto, xmlbuf, xmlbuflen,
1102 key, keylen, &cached, client->opts & OPT_NO_AGENT);
1103 gcry_free (key);
1105 if (!rc && (!cached || (client->flags & FLAG_NEW)))
1106 send_status_all (STATUS_CACHE, NULL);
1108 if (!rc)
1110 rc = update_checksum (client);
1111 client->flags &= ~(FLAG_NEW);
1115 pthread_cleanup_pop (1); // xmlFree
1116 return rc;
1119 static gpg_error_t
1120 parse_opt_reset (void *data, void *value)
1122 struct client_s *client = data;
1124 (void) value;
1125 client->opts |= OPT_RESET;
1126 return 0;
1129 static gpg_error_t
1130 parse_opt_ask (void *data, void *value)
1132 struct client_s *client = data;
1134 (void) value;
1135 client->opts |= OPT_ASK;
1136 return 0;
1139 static gpg_error_t
1140 save_command (assuan_context_t ctx, char *line)
1142 struct client_s *client = assuan_get_pointer (ctx);
1143 gpg_error_t rc;
1144 struct stat st;
1145 struct argv_s *args[] = {
1146 &(struct argv_s) {"no-passphrase", OPTION_TYPE_NOARG,
1147 parse_opt_no_passphrase},
1148 &(struct argv_s) {"cipher", OPTION_TYPE_ARG, parse_save_opt_cipher},
1149 &(struct argv_s) {"inquire-keyparam", OPTION_TYPE_NOARG,
1150 parse_save_opt_inquire},
1151 &(struct argv_s) {"keygrip", OPTION_TYPE_ARG, parse_save_opt_keygrip},
1152 &(struct argv_s) {"sign-keygrip", OPTION_TYPE_ARG,
1153 parse_save_opt_sign_keygrip},
1154 &(struct argv_s) {"s2k-count", OPTION_TYPE_ARG, parse_opt_s2k_count},
1155 &(struct argv_s) {"reset", OPTION_TYPE_NOARG, parse_opt_reset},
1156 &(struct argv_s) {"cipher-iterations", OPTION_TYPE_ARG,
1157 parse_opt_s2k_count},
1158 &(struct argv_s) {"no-agent", OPTION_TYPE_NOARG,
1159 parse_save_opt_no_agent},
1160 &(struct argv_s) {"ask", OPTION_TYPE_NOARG,
1161 parse_opt_ask},
1162 NULL
1165 cleanup_save (&client->crypto->save);
1166 memcpy (&client->crypto->save.hdr, &client->crypto->hdr,
1167 sizeof (file_header_t));
1169 rc = parse_options (&line, args, client, 0);
1170 if (rc)
1171 return send_error (ctx, rc);
1173 if (!(client->flags & FLAG_NEW))
1174 client->opts &= ~OPT_NO_AGENT;
1175 else if (client->opts & OPT_NO_AGENT)
1177 client->crypto->save.hdr.flags &= ~PWMD_FLAG_PKI;
1178 client->crypto->hdr.flags &= ~PWMD_FLAG_PKI;
1181 /* Update to the default hash iteration count for data file
1182 * versions <= 3.0.14. */
1183 #ifdef WITH_AGENT
1184 if ((!IS_PKI (client->crypto) && client->crypto->hdr.version <= 0x03000e
1185 && client->crypto->save.hdr.s2k_count < DEFAULT_KDFS2K_ITERATIONS)
1186 || (!IS_PKI (client->crypto) && !client->crypto->save.hdr.s2k_count))
1187 #else
1188 if ((client->crypto->hdr.version <= 0x03000e
1189 && client->crypto->save.hdr.s2k_count < DEFAULT_KDFS2K_ITERATIONS)
1190 || !client->crypto->save.hdr.s2k_count)
1191 #endif
1193 client->crypto->save.hdr.s2k_count =
1194 config_get_ulonglong (client->filename, "s2k_count");
1195 if (!client->crypto->save.hdr.s2k_count)
1196 client->crypto->save.hdr.s2k_count = DEFAULT_KDFS2K_ITERATIONS;
1199 /* Deal with the hashed vs non-hashed cached key mess by clearing the cached
1200 * key entry. */
1201 if (client->crypto->hdr.version <= 0x03000e && !IS_PKI (client->crypto))
1202 client->opts |= OPT_RESET;
1203 else if (!IS_PKI (client->crypto) && !(client->flags & FLAG_NEW)
1204 && client->crypto->hdr.s2k_count !=
1205 client->crypto->save.hdr.s2k_count)
1206 client->opts |= OPT_RESET;
1208 if ((client->opts & OPT_NO_PASSPHRASE) && !(client->flags & FLAG_NEW)
1209 && !(client->opts & OPT_INQUIRE))
1210 return send_error (ctx, GPG_ERR_WRONG_KEY_USAGE);
1212 if (lstat (client->filename, &st) == -1 && errno != ENOENT)
1213 return send_error (ctx, gpg_error_from_errno (errno));
1215 if (errno != ENOENT && !S_ISREG (st.st_mode))
1217 log_write ("%s: %s", client->filename, pwmd_strerror (GPG_ERR_ENOANO));
1218 return send_error (ctx, GPG_ERR_ENOANO);
1221 int defer = 0;
1222 rc = cache_iscached (client->filename, &defer);
1223 if (gpg_err_code (rc) == GPG_ERR_ENOENT && client->flags & FLAG_NEW)
1224 rc = 0;
1225 else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
1226 rc = 0;
1228 if ((!rc && defer))
1229 client->opts |= OPT_RESET;
1230 else if (config_get_boolean ("global", "require_save_key"))
1231 client->opts |= OPT_ASK;
1233 if (!rc && (client->opts & OPT_RESET))
1235 rc = cache_clear (client->md5file);
1236 if (rc)
1237 return send_error (ctx, rc);
1239 log_write ("%s: %s", client->filename,
1240 pwmd_strerror (GPG_ERR_KEY_EXPIRED));
1241 send_status_all (STATUS_CACHE, NULL);
1244 if (!rc && client->opts & OPT_ASK)
1245 rc = crypto_try_decrypt (ctx, client->flags & FLAG_NO_PINENTRY,
1246 client->filename, NULL, NULL, NULL);
1248 if (!rc)
1249 rc = update_element_mtime (client, xmlDocGetRootElement (client->doc));
1251 if (rc)
1252 return send_error (ctx, rc);
1254 #ifdef WITH_AGENT
1255 if (!rc && use_agent && !client->crypto->save.pkey &&
1256 (client->flags & FLAG_NEW || client->opts & OPT_INQUIRE)
1257 && !(client->opts & OPT_NO_AGENT))
1259 rc = set_pinentry_mode (client->crypto->agent,
1260 (client->flags & FLAG_NO_PINENTRY) ? "loopback"
1261 : "ask");
1263 if (!(client->flags & FLAG_NEW))
1265 struct crypto_s *crypto;
1266 void *key = NULL;
1267 size_t keylen = 0;
1269 /* Wanting to generate a new key. Require the key to open the
1270 current file before proceeding reguardless of the
1271 require_save_key configuration parameter. */
1272 rc = cache_clear (client->md5file);
1273 if (!rc)
1275 rc = init_client_crypto (&crypto);
1276 if (!rc)
1277 crypto->client_ctx = client->ctx;
1280 if (!rc)
1281 rc = decrypt_common (client->ctx, client->opts&OPT_INQUIRE, crypto,
1282 client->filename, &key, &keylen, NULL, NULL);
1284 xfree (key);
1285 cleanup_crypto (&crypto);
1288 if (!rc)
1289 rc = send_status (client->ctx, STATUS_GENKEY, NULL);
1291 if (!rc)
1293 struct inquire_data_s idata = { 0 };
1294 char *params = client->opts & OPT_INQUIRE
1295 ? NULL : default_key_params (client->crypto);
1297 pthread_cleanup_push (xfree, params);
1298 idata.crypto = client->crypto;
1300 if (params)
1302 idata.line = params;
1303 idata.len = strlen (params);
1305 else
1306 idata.preset = 1;
1308 client->crypto->agent->inquire_data = &idata;
1309 client->crypto->agent->inquire_cb = NULL;
1310 rc = generate_key (client->crypto, params,
1311 (client->opts & OPT_NO_PASSPHRASE), 1);
1312 pthread_cleanup_pop (1);
1315 #endif
1317 if (!rc)
1318 rc = save_finalize (ctx);
1320 cleanup_crypto_stage1 (client->crypto);
1321 #ifdef WITH_AGENT
1322 (void) kill_scd (client->crypto->agent);
1323 #endif
1324 return send_error (ctx, rc);
1327 static gpg_error_t
1328 do_delete (assuan_context_t ctx, char *line)
1330 struct client_s *client = assuan_get_pointer (ctx);
1331 gpg_error_t rc;
1332 char **req;
1333 xmlNodePtr n;
1335 if (strchr (line, '\t'))
1336 req = str_split (line, "\t", 0);
1337 else
1338 req = str_split (line, " ", 0);
1340 if (!req || !*req)
1341 return GPG_ERR_SYNTAX;
1343 n = find_root_element (client, client->doc, &req, &rc, NULL, 0, 0);
1344 if (!n || rc)
1346 strv_free (req);
1347 return rc;
1351 * No sub-node defined. Remove the entire node (root element).
1353 if (!req[1])
1355 if (n)
1357 rc = is_element_owner (client, n);
1358 if (!rc)
1360 rc = unlink_node (client, n);
1361 xmlFreeNode (n);
1365 strv_free (req);
1366 return rc;
1369 n = find_elements (client, client->doc, n->children, req + 1, &rc, NULL,
1370 NULL, NULL, 0, 0, NULL, 0);
1371 strv_free (req);
1372 if (!n || rc)
1373 return rc;
1375 rc = is_element_owner (client, n);
1376 if (!rc)
1378 rc = unlink_node (client, n);
1379 xmlFreeNode (n);
1382 return rc;
1385 static gpg_error_t
1386 delete_command (assuan_context_t ctx, char *line)
1388 struct client_s *client = assuan_get_pointer (ctx);
1389 gpg_error_t rc;
1390 struct argv_s *args[] = {
1391 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1392 NULL
1395 rc = parse_options (&line, args, client, 1);
1396 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
1397 rc = GPG_ERR_SYNTAX;
1398 if (rc)
1399 return send_error (ctx, rc);
1401 if (client->opts & OPT_INQUIRE)
1403 unsigned char *result;
1404 size_t len;
1406 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1407 if (rc)
1408 return send_error (ctx, rc);
1410 pthread_cleanup_push (xfree, result);
1411 rc = do_delete (ctx, (char *)result);
1412 pthread_cleanup_pop (1);
1414 else
1415 rc = do_delete (ctx, line);
1417 return send_error (ctx, rc);
1420 static gpg_error_t
1421 store_command (assuan_context_t ctx, char *line)
1423 struct client_s *client = assuan_get_pointer (ctx);
1424 gpg_error_t rc;
1425 size_t len;
1426 unsigned char *result;
1427 char **req;
1428 xmlNodePtr n, parent;
1429 int has_content;
1430 char *content = NULL;
1432 if (line && *line)
1433 return send_error (ctx, GPG_ERR_SYNTAX);
1435 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1436 if (rc)
1437 return send_error (ctx, rc);
1439 req = str_split ((char *) result, "\t", 0);
1440 xfree (result);
1442 if (!req || !*req)
1443 return send_error (ctx, GPG_ERR_SYNTAX);
1445 len = strv_length (req);
1446 has_content = line[strlen (line) - 1] != '\t' && len > 1;
1447 if (*(req + 1) && !valid_element_path (req, has_content))
1449 strv_free (req);
1450 return send_error (ctx, GPG_ERR_INV_VALUE);
1453 if (has_content || !*req[len - 1])
1455 has_content = 1;
1456 content = req[len - 1];
1457 req[len - 1] = NULL;
1460 again:
1461 n = find_root_element (client, client->doc, &req, &rc, NULL, 0, 0);
1462 if (rc && rc == GPG_ERR_ELEMENT_NOT_FOUND)
1464 rc = new_root_element (client, client->doc, *req);
1465 if (rc)
1467 strv_free (req);
1468 return send_error (ctx, rc);
1471 goto again;
1474 if (!n || rc)
1476 strv_free (req);
1477 return send_error (ctx, rc);
1480 parent = n;
1482 if (req[1] && *req[1])
1484 if (!n->children)
1485 parent = create_elements_cb (client, 1, n, req + 1, &rc, NULL);
1486 else
1487 parent = find_elements (client, client->doc, n->children, req + 1, &rc,
1488 NULL, NULL, create_elements_cb, 0, 0, NULL,
1492 if (!rc && len > 1)
1494 rc = is_element_owner (client, parent);
1495 if (!rc)
1497 n = find_text_node (parent->children);
1498 if (n)
1499 xmlNodeSetContent (n, (xmlChar *) content);
1500 else
1501 xmlNodeAddContent (parent, (xmlChar *) content);
1503 update_element_mtime (client, parent);
1507 xfree (content);
1508 strv_free (req);
1509 return send_error (ctx, rc);
1512 static gpg_error_t
1513 xfer_data (assuan_context_t ctx, const char *line, int total)
1515 struct client_s *client = assuan_get_pointer (ctx);
1516 int to_send;
1517 int sent = 0;
1518 gpg_error_t rc = 0;
1519 int progress = config_get_integer ("global", "xfer_progress");
1520 int flush = 0;
1522 if (!(client->flags & FLAG_LOCK_CMD))
1523 rc = unlock_file_mutex (client, 0);
1524 if (rc && rc != GPG_ERR_NOT_LOCKED)
1525 return rc;
1527 progress =
1528 progress > 0 ? (progress / ASSUAN_LINELENGTH) * ASSUAN_LINELENGTH : 0;
1529 to_send = total < ASSUAN_LINELENGTH ? total : ASSUAN_LINELENGTH;
1530 rc = send_status (ctx, STATUS_XFER, "%li %li", sent, total);
1532 if (rc)
1533 return rc;
1535 again:
1538 if (sent + to_send > total)
1539 to_send = total - sent;
1541 rc = assuan_send_data (ctx, flush ? NULL : (char *) line + sent,
1542 flush ? 0 : to_send);
1543 if (!rc)
1545 sent += flush ? 0 : to_send;
1547 if ((progress && !(sent % progress) && sent != total) ||
1548 (sent == total && flush))
1549 rc = send_status (ctx, STATUS_XFER, "%li %li", sent, total);
1551 if (!flush && !rc && sent == total)
1553 flush = 1;
1554 goto again;
1558 while (!rc && sent < total);
1560 return rc;
1563 static gpg_error_t
1564 do_get (assuan_context_t ctx, char *line)
1566 struct client_s *client = assuan_get_pointer (ctx);
1567 gpg_error_t rc;
1568 char **req;
1569 xmlNodePtr n;
1571 req = str_split (line, "\t", 0);
1573 if (!req || !*req)
1575 strv_free (req);
1576 return GPG_ERR_SYNTAX;
1579 n = find_root_element (client, client->doc, &req, &rc, NULL, 0, 0);
1580 if (!n || rc)
1582 strv_free (req);
1583 return rc;
1586 if (req[1])
1587 n = find_elements (client, client->doc, n->children, req + 1, &rc,
1588 NULL, NULL, NULL, 0, 0, NULL, 0);
1590 strv_free (req);
1591 if (rc)
1592 return rc;
1594 if (!n || !n->children)
1595 return GPG_ERR_NO_DATA;
1597 n = find_text_node (n->children);
1598 if (!n || !n->content || !*n->content)
1599 return GPG_ERR_NO_DATA;
1601 rc = xfer_data (ctx, (char *) n->content, xmlStrlen (n->content));
1602 return rc;
1605 static gpg_error_t
1606 get_command (assuan_context_t ctx, char *line)
1608 struct client_s *client = assuan_get_pointer (ctx);
1609 gpg_error_t rc;
1610 struct argv_s *args[] = {
1611 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1612 NULL
1615 rc = parse_options (&line, args, client, 1);
1616 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
1617 rc = GPG_ERR_SYNTAX;
1618 if (rc)
1619 return send_error (ctx, rc);
1621 if (client->opts & OPT_INQUIRE)
1623 unsigned char *result;
1624 size_t len;
1626 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1627 if (rc)
1628 return send_error (ctx, rc);
1630 pthread_cleanup_push (xfree, result);
1631 rc = do_get (ctx, (char *)result);
1632 pthread_cleanup_pop (1);
1634 else
1635 rc = do_get (ctx, line);
1637 return send_error (ctx, rc);
1640 static void list_command_cleanup1 (void *arg);
1641 static gpg_error_t
1642 realpath_command (assuan_context_t ctx, char *line)
1644 struct string_s *string = NULL;
1645 gpg_error_t rc;
1646 struct client_s *client = assuan_get_pointer (ctx);
1647 struct argv_s *args[] = {
1648 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1649 NULL
1652 rc = parse_options (&line, args, client, 1);
1653 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
1654 rc = GPG_ERR_SYNTAX;
1655 if (rc)
1656 return send_error (ctx, rc);
1658 if (client->opts & OPT_INQUIRE)
1660 unsigned char *result;
1661 size_t len;
1663 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1664 if (rc)
1665 return send_error (ctx, rc);
1667 pthread_cleanup_push (xfree, result);
1668 rc = build_realpath (client, client->doc, (char *)result, &string);
1669 pthread_cleanup_pop (1);
1671 else
1672 rc = build_realpath (client, client->doc, line, &string);
1674 if (!rc)
1676 pthread_cleanup_push (list_command_cleanup1, string);
1677 rc = xfer_data (ctx, string->str, string->len);
1678 pthread_cleanup_pop (1);
1681 return send_error (ctx, rc);
1684 static void
1685 list_command_cleanup1 (void *arg)
1687 if (arg)
1688 string_free ((struct string_s *) arg, 1);
1691 static void
1692 list_command_cleanup2 (void *arg)
1694 struct element_list_s *elements = arg;
1696 if (elements)
1698 if (elements->list)
1700 int total = slist_length (elements->list);
1701 int i;
1703 for (i = 0; i < total; i++)
1705 char *tmp = slist_nth_data (elements->list, i);
1706 xfree (tmp);
1709 slist_free (elements->list);
1712 if (elements->prefix)
1713 xfree (elements->prefix);
1715 if (elements->req)
1716 strv_free (elements->req);
1718 xfree (elements);
1722 static gpg_error_t
1723 parse_list_opt_norecurse (void *data, void *value)
1725 struct client_s *client = data;
1727 client->opts &= ~(OPT_LIST_RECURSE);
1728 return 0;
1731 static gpg_error_t
1732 parse_opt_verbose (void *data, void *value)
1734 struct client_s *client = data;
1736 client->opts |= OPT_VERBOSE;
1737 return 0;
1740 static gpg_error_t
1741 parse_list_opt_target (void *data, void *value)
1743 struct client_s *client = data;
1745 client->opts |= OPT_LIST_WITH_TARGET;
1746 return 0;
1749 static gpg_error_t
1750 parse_list_opt_all (void *data, void *value)
1752 struct client_s *client = data;
1754 client->opts |= OPT_LIST_ALL;
1755 return 0;
1758 static gpg_error_t
1759 list_path_once (struct client_s *client, char *line,
1760 struct element_list_s *elements, struct string_s *result)
1762 gpg_error_t rc;
1764 elements->req = str_split (line, " ", 0);
1765 if (!elements->req)
1766 strv_printf (&elements->req, "%s", line);
1768 rc = create_path_list (client, client->doc, elements, *elements->req);
1769 if ((rc == GPG_ERR_ELOOP || rc == GPG_ERR_EACCES) && elements->verbose)
1770 rc = 0;
1772 if (!rc)
1774 int total = slist_length (elements->list);
1776 if (total)
1778 int i;
1780 for (i = 0; i < total; i++)
1782 char *tmp = slist_nth_data (elements->list, i);
1784 string_append_printf (result, "%s%s", tmp,
1785 i + 1 == total ? "" : "\n");
1788 else
1789 rc = GPG_ERR_NO_DATA;
1792 return rc;
1795 static int
1796 has_list_flag (char *path, char *flags)
1798 char *p = path;
1800 while (*p && *++p != ' ');
1802 if (!*p)
1803 return 0;
1805 for (; *p; p++)
1807 char *f;
1809 for (f = flags; *f && *f != ' '; f++)
1811 if (*p == *f)
1812 return 1;
1816 return 0;
1819 static gpg_error_t
1820 do_list (assuan_context_t ctx, char *line)
1822 struct client_s *client = assuan_get_pointer (ctx);
1823 gpg_error_t rc;
1824 struct element_list_s *elements = NULL;
1826 elements = xcalloc (1, sizeof (struct element_list_s));
1827 if (!elements)
1828 return GPG_ERR_ENOMEM;
1830 elements->recurse = client->opts & OPT_LIST_RECURSE;
1831 elements->verbose =
1832 (client->opts & OPT_VERBOSE) | (client->opts & OPT_LIST_WITH_TARGET);
1833 elements->with_target = client->opts & OPT_LIST_WITH_TARGET;
1835 if (!line || !*line)
1837 struct string_s *str = NULL;
1839 pthread_cleanup_push (list_command_cleanup2, elements);
1840 rc = list_root_elements (client, client->doc, &str, elements->verbose,
1841 elements->with_target);
1842 pthread_cleanup_pop (1);
1843 pthread_cleanup_push (list_command_cleanup1, str);
1845 if (!rc)
1847 if (client->opts & OPT_LIST_ALL)
1849 char **roots = str_split (str->str, "\n", 0);
1850 char **p;
1852 pthread_cleanup_push (req_cleanup, roots);
1853 string_truncate (str, 0);
1855 for (p = roots; *p; p++)
1857 if (strchr (*p, ' '))
1859 if (has_list_flag (*p, "EOP"))
1861 string_append_printf (str, "%s%s", *p,
1862 *(p + 1) ? "\n" : "");
1863 continue;
1867 elements = xcalloc (1, sizeof (struct element_list_s));
1868 if (!elements)
1870 rc = GPG_ERR_ENOMEM;
1871 break;
1874 elements->recurse = client->opts & OPT_LIST_RECURSE;
1875 elements->verbose =
1876 (client->opts & OPT_VERBOSE) | (client->opts &
1877 OPT_LIST_WITH_TARGET);
1878 elements->with_target = client->opts & OPT_LIST_WITH_TARGET;
1879 pthread_cleanup_push (list_command_cleanup2, elements);
1880 rc = list_path_once (client, *p, elements, str);
1881 pthread_cleanup_pop (1);
1882 if (rc)
1883 break;
1885 if (*(p + 1))
1886 string_append (str, "\n");
1889 pthread_cleanup_pop (1);
1892 if (!rc)
1893 rc = xfer_data (ctx, str->str, str->len);
1896 pthread_cleanup_pop (1);
1897 return rc;
1900 pthread_cleanup_push (list_command_cleanup2, elements);
1901 struct string_s *str = string_new (NULL);
1902 pthread_cleanup_push (list_command_cleanup1, str);
1903 rc = list_path_once (client, line, elements, str);
1904 if (!rc)
1905 rc = xfer_data (ctx, str->str, str->len);
1907 pthread_cleanup_pop (1);
1908 pthread_cleanup_pop (1);
1909 return rc;
1912 static gpg_error_t
1913 list_command (assuan_context_t ctx, char *line)
1915 struct client_s *client = assuan_get_pointer (ctx);
1916 gpg_error_t rc;
1917 struct argv_s *args[] = {
1918 &(struct argv_s) {"no-recurse", OPTION_TYPE_NOARG,
1919 parse_list_opt_norecurse},
1920 &(struct argv_s) {"verbose", OPTION_TYPE_NOARG, parse_opt_verbose},
1921 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1922 &(struct argv_s) {"with-target", OPTION_TYPE_NOARG,
1923 parse_list_opt_target},
1924 &(struct argv_s) {"all", OPTION_TYPE_NOARG, parse_list_opt_all},
1925 NULL
1928 if (disable_list_and_dump == 1)
1929 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
1931 client->opts |= OPT_LIST_RECURSE;
1932 rc = parse_options (&line, args, client, 1);
1933 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
1934 rc = GPG_ERR_SYNTAX;
1935 if (rc)
1936 return send_error (ctx, rc);
1938 if (client->opts & OPT_LIST_ALL)
1939 client->opts |= OPT_LIST_RECURSE | OPT_VERBOSE;
1941 if (client->opts & OPT_INQUIRE)
1943 unsigned char *result;
1944 size_t len;
1946 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1947 if (rc)
1948 return send_error (ctx, rc);
1950 pthread_cleanup_push (xfree, result);
1951 rc = do_list (ctx, (char *)result);
1952 pthread_cleanup_pop (1);
1954 else
1955 rc = do_list (ctx, line);
1957 return send_error (ctx, rc);
1961 * req[0] - element path
1963 static gpg_error_t
1964 attribute_list (assuan_context_t ctx, char **req)
1966 struct client_s *client = assuan_get_pointer (ctx);
1967 char **attrlist = NULL;
1968 int i = 0;
1969 char **path = NULL;
1970 xmlAttrPtr a;
1971 xmlNodePtr n, an;
1972 char *line;
1973 gpg_error_t rc;
1975 if (!req || !req[0])
1976 return GPG_ERR_SYNTAX;
1978 client->flags |= FLAG_ACL_IGNORE;
1980 if ((path = str_split (req[0], "\t", 0)) == NULL)
1983 * The first argument may be only a root element.
1985 if ((path = str_split (req[0], " ", 0)) == NULL)
1986 return GPG_ERR_SYNTAX;
1989 n = find_root_element (client, client->doc, &path, &rc, NULL, 0, 0);
1990 if (!n || rc)
1992 strv_free (path);
1993 return rc;
1996 if (client->flags & FLAG_ACL_ERROR)
1998 client->flags &= ~FLAG_ACL_IGNORE;
1999 if (path[1])
2001 strv_free (path);
2002 return GPG_ERR_EACCES;
2005 client->flags &= ~FLAG_ACL_ERROR;
2008 if (path[1])
2010 n = find_elements (client, client->doc, n->children, path + 1, &rc,
2011 NULL, NULL, NULL, 0, 0, NULL, 0);
2012 if (!n || rc)
2014 strv_free (path);
2015 return rc;
2019 strv_free (path);
2021 for (a = n->properties; a; a = a->next)
2023 char **pa;
2025 if ((pa = xrealloc (attrlist, (i + 2) * sizeof (char *))) == NULL)
2027 if (attrlist)
2028 strv_free (attrlist);
2030 log_write ("%s(%i): %s", __FILE__, __LINE__,
2031 pwmd_strerror (GPG_ERR_ENOMEM));
2032 return GPG_ERR_ENOMEM;
2035 attrlist = pa;
2036 an = a->children;
2037 attrlist[i] = str_asprintf ("%s %s", (char *) a->name,
2039 && an->content ? (char *) an->content : "");
2041 if (!attrlist[i])
2043 strv_free (attrlist);
2044 log_write ("%s(%i): %s", __FILE__, __LINE__,
2045 pwmd_strerror (GPG_ERR_ENOMEM));
2046 return GPG_ERR_ENOMEM;
2049 attrlist[++i] = NULL;
2052 if (!attrlist)
2053 return GPG_ERR_NO_DATA;
2055 line = strv_join ("\n", attrlist);
2057 if (!line)
2059 log_write ("%s(%i): %s", __FILE__, __LINE__,
2060 pwmd_strerror (GPG_ERR_ENOMEM));
2061 strv_free (attrlist);
2062 return GPG_ERR_ENOMEM;
2065 pthread_cleanup_push (xfree, line);
2066 pthread_cleanup_push (req_cleanup, attrlist);
2067 rc = xfer_data (ctx, line, strlen (line));
2068 pthread_cleanup_pop (1);
2069 pthread_cleanup_pop (1);
2070 return rc;
2074 * req[0] - attribute
2075 * req[1] - element path
2077 static gpg_error_t
2078 attribute_delete (struct client_s *client, char **req)
2080 xmlNodePtr n;
2081 char **path = NULL;
2082 gpg_error_t rc;
2084 if (!req || !req[0] || !req[1])
2085 return GPG_ERR_SYNTAX;
2087 if (!strcmp (req[0], "_name"))
2088 return GPG_ERR_INV_ATTR;
2090 if ((path = str_split (req[1], "\t", 0)) == NULL)
2093 * The first argument may be only a root element.
2095 if ((path = str_split (req[1], " ", 0)) == NULL)
2096 return GPG_ERR_SYNTAX;
2099 n = find_root_element (client, client->doc, &path, &rc, NULL, 0, 0);
2100 if (!n || rc)
2101 goto fail;
2103 if (path[1])
2105 n = find_elements (client, client->doc, n->children, path + 1, &rc,
2106 NULL, NULL, NULL, 0, 0, NULL, 0);
2107 if (!n || rc)
2108 goto fail;
2111 if (!strcmp (req[0], (char *) "_acl"))
2113 rc = is_element_owner (client, n);
2114 if (rc)
2115 goto fail;
2118 rc = delete_attribute (client, n, (xmlChar *) req[0]);
2120 fail:
2121 strv_free (path);
2122 return rc;
2125 static xmlNodePtr
2126 create_element_path (struct client_s *client,
2127 char ***elements, gpg_error_t * rc, xmlNodePtr parent)
2129 char **req = *elements;
2130 char **req_orig = strv_dup (req);
2131 xmlNodePtr n = NULL;
2133 *rc = 0;
2135 if (!req_orig)
2137 *rc = GPG_ERR_ENOMEM;
2138 log_write ("%s(%i): %s", __FILE__, __LINE__,
2139 pwmd_strerror (GPG_ERR_ENOMEM));
2140 goto fail;
2143 again:
2144 n = find_root_element (client, client->doc, &req, rc, NULL, 0, 0);
2145 if (!n)
2147 if (*rc != GPG_ERR_ELEMENT_NOT_FOUND)
2148 goto fail;
2150 *rc = new_root_element (client, client->doc, req[0]);
2151 if (*rc)
2152 goto fail;
2154 goto again;
2156 else if (n == parent)
2158 *rc = GPG_ERR_CONFLICT;
2159 goto fail;
2162 if (req[1])
2164 if (!n->children)
2165 n = create_target_elements_cb (client, 1, n, req + 1, rc, NULL);
2166 else
2167 n = find_elements (client, client->doc, n->children, req + 1, rc,
2168 NULL, NULL, create_target_elements_cb, 0, 0,
2169 parent, 0);
2171 if (!n)
2172 goto fail;
2175 * Reset the position of the element tree now that the elements
2176 * have been created.
2178 strv_free (req);
2179 req = req_orig;
2180 req_orig = NULL;
2181 n = find_root_element (client, client->doc, &req, rc, NULL, 0, 0);
2182 if (!n)
2183 goto fail;
2185 n = find_elements (client, client->doc, n->children, req + 1, rc,
2186 NULL, NULL, NULL, 0, 0, NULL, 0);
2187 if (!n)
2188 goto fail;
2191 fail:
2192 if (req_orig)
2193 strv_free (req_orig);
2195 *elements = req;
2196 return n;
2200 * Creates a "target" attribute. When other commands encounter an element with
2201 * this attribute, the element path is modified to the target value. If the
2202 * source element path doesn't exist when using 'ATTR SET target', it is
2203 * created, but the destination element path must exist.
2205 * req[0] - source element path
2206 * req[1] - destination element path
2208 static gpg_error_t
2209 target_attribute (struct client_s *client, char **req)
2211 char **src, **dst, *line = NULL, **odst = NULL;
2212 gpg_error_t rc;
2213 xmlNodePtr n;
2215 if (!req || !req[0] || !req[1])
2216 return GPG_ERR_SYNTAX;
2218 if ((src = str_split (req[0], "\t", 0)) == NULL)
2221 * The first argument may be only a root element.
2223 if ((src = str_split (req[0], " ", 0)) == NULL)
2224 return GPG_ERR_SYNTAX;
2227 if (!valid_element_path (src, 0))
2228 return GPG_ERR_INV_VALUE;
2230 if ((dst = str_split (req[1], "\t", 0)) == NULL)
2233 * The first argument may be only a root element.
2235 if ((dst = str_split (req[1], " ", 0)) == NULL)
2237 rc = GPG_ERR_SYNTAX;
2238 goto fail;
2242 odst = strv_dup (dst);
2243 if (!odst)
2245 rc = GPG_ERR_ENOMEM;
2246 goto fail;
2249 n = find_root_element (client, client->doc, &dst, &rc, NULL, 0, 0);
2251 * Make sure the destination element path exists.
2253 if (rc && rc != GPG_ERR_EACCES)
2254 goto fail;
2256 rc = 0;
2257 if (dst[1])
2259 n = find_elements (client, client->doc, n->children, dst + 1, &rc,
2260 NULL, NULL, NULL, 0, 0, NULL, 0);
2261 if (rc && rc != GPG_ERR_EACCES)
2262 goto fail;
2265 rc = validate_target_attribute (client, client->doc, req[0], n);
2266 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
2267 goto fail;
2269 n = create_element_path (client, &src, &rc, NULL);
2270 if (rc)
2271 goto fail;
2273 line = strv_join ("\t", odst);
2274 if (!line)
2276 rc = GPG_ERR_ENOMEM;
2277 goto fail;
2280 rc = add_attribute (client, n, "target", line);
2282 fail:
2283 xfree (line);
2284 strv_free (src);
2285 strv_free (dst);
2286 strv_free (odst);
2287 return rc;
2291 * req[0] - attribute
2292 * req[1] - element path
2294 static gpg_error_t
2295 attribute_get (assuan_context_t ctx, char **req)
2297 struct client_s *client = assuan_get_pointer (ctx);
2298 xmlNodePtr n;
2299 xmlChar *a;
2300 char **path = NULL;
2301 gpg_error_t rc;
2303 if (!req || !req[0] || !req[1])
2304 return GPG_ERR_SYNTAX;
2306 if (strchr (req[1], '\t'))
2308 if ((path = str_split (req[1], "\t", 0)) == NULL)
2309 return GPG_ERR_SYNTAX;
2311 else
2313 if ((path = str_split (req[1], " ", 0)) == NULL)
2314 return GPG_ERR_SYNTAX;
2317 n = find_root_element (client, client->doc, &path, &rc, NULL, 0, 0);
2318 if (!n || rc)
2319 goto fail;
2321 if (path[1])
2323 n = find_elements (client, client->doc, n->children, path + 1, &rc,
2324 NULL, NULL, NULL, 0, 0, NULL, 0);
2325 if (!n || rc)
2326 goto fail;
2329 strv_free (path);
2331 if ((a = xmlGetProp (n, (xmlChar *) req[0])) == NULL)
2332 return GPG_ERR_NOT_FOUND;
2334 pthread_cleanup_push (xmlFree, a);
2336 if (*a)
2337 rc = xfer_data (ctx, (char *) a, xmlStrlen (a));
2338 else
2339 rc = GPG_ERR_NO_DATA;
2341 pthread_cleanup_pop (1);
2342 return rc;
2344 fail:
2345 strv_free (path);
2346 return rc;
2350 * req[0] - attribute
2351 * req[1] - element path
2352 * req[2] - value
2354 static gpg_error_t
2355 attribute_set (struct client_s *client, char **req)
2357 char **path = NULL;
2358 gpg_error_t rc;
2359 xmlNodePtr n;
2361 if (!req || !req[0] || !req[1])
2362 return GPG_ERR_SYNTAX;
2365 * Reserved attribute names.
2367 if (!strcmp (req[0], "_name"))
2368 return GPG_ERR_INV_ATTR;
2369 else if (!strcmp (req[0], "target"))
2370 return target_attribute (client, req + 1);
2371 else if (!valid_xml_attribute (req[0]))
2372 return GPG_ERR_INV_VALUE;
2374 if (!valid_xml_attribute_value (req[2]))
2375 return GPG_ERR_INV_VALUE;
2377 if ((path = str_split (req[1], "\t", 0)) == NULL)
2380 * The first argument may be only a root element.
2382 if ((path = str_split (req[1], " ", 0)) == NULL)
2383 return GPG_ERR_SYNTAX;
2386 n = find_root_element (client, client->doc, &path, &rc, NULL, 0, 0);
2387 if (!n || rc)
2388 goto fail;
2390 if (path[1])
2392 n = find_elements (client, client->doc, n->children, path + 1, &rc,
2393 NULL, NULL, NULL, 0, 0, NULL, 0);
2394 if (!n || rc)
2395 goto fail;
2398 if (!strcmp (req[0], (char *) "_acl"))
2400 rc = is_element_owner (client, n);
2401 if (rc)
2402 goto fail;
2405 rc = add_attribute (client, n, req[0], req[2]);
2407 fail:
2408 strv_free (path);
2409 return rc;
2413 * req[0] - command
2414 * req[1] - attribute name or element path if command is LIST
2415 * req[2] - element path
2416 * req[2] - element path or value
2419 static gpg_error_t
2420 do_attr (assuan_context_t ctx, char *line)
2422 struct client_s *client = assuan_get_pointer (ctx);
2423 gpg_error_t rc = 0;
2424 char **req;
2426 req = str_split (line, " ", 4);
2427 if (!req || !req[0] || !req[1])
2429 strv_free (req);
2430 return GPG_ERR_SYNTAX;
2433 pthread_cleanup_push (req_cleanup, req);
2435 if (strcasecmp (req[0], "SET") == 0)
2436 rc = attribute_set (client, req + 1);
2437 else if (strcasecmp (req[0], "GET") == 0)
2438 rc = attribute_get (ctx, req + 1);
2439 else if (strcasecmp (req[0], "DELETE") == 0)
2440 rc = attribute_delete (client, req + 1);
2441 else if (strcasecmp (req[0], "LIST") == 0)
2442 rc = attribute_list (ctx, req + 1);
2443 else
2444 rc = GPG_ERR_SYNTAX;
2446 client->flags &= ~(FLAG_ACL_IGNORE|FLAG_ACL_ERROR);
2447 pthread_cleanup_pop (1);
2448 return rc;
2451 static gpg_error_t
2452 attr_command (assuan_context_t ctx, char *line)
2454 struct client_s *client = assuan_get_pointer (ctx);
2455 gpg_error_t rc;
2456 struct argv_s *args[] = {
2457 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
2458 NULL
2461 rc = parse_options (&line, args, client, 1);
2462 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
2463 rc = GPG_ERR_SYNTAX;
2464 if (rc)
2465 return send_error (ctx, rc);
2467 if (client->opts & OPT_INQUIRE)
2469 unsigned char *result;
2470 size_t len;
2472 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
2473 if (rc)
2474 return send_error (ctx, rc);
2476 pthread_cleanup_push (xfree, result);
2477 rc = do_attr (ctx, (char *)result);
2478 pthread_cleanup_pop (1);
2480 else
2481 rc = do_attr (ctx, line);
2483 return send_error (ctx, rc);
2486 static gpg_error_t
2487 parse_iscached_opt_lock (void *data, void *value)
2489 struct client_s *client = data;
2491 (void) value;
2492 client->opts |= OPT_LOCK;
2493 return 0;
2496 static gpg_error_t
2497 iscached_command (assuan_context_t ctx, char *line)
2499 struct client_s *client = assuan_get_pointer (ctx);
2500 gpg_error_t rc;
2501 struct argv_s *args[] = {
2502 &(struct argv_s) {"lock", OPTION_TYPE_NOARG, parse_iscached_opt_lock},
2503 NULL
2506 if (!line || !*line)
2507 return send_error (ctx, GPG_ERR_SYNTAX);
2509 rc = parse_options (&line, args, client, 1);
2510 if (rc)
2511 return send_error (ctx, rc);
2512 else if (!valid_filename (line))
2513 return send_error (ctx, GPG_ERR_INV_VALUE);
2515 rc = cache_iscached (line, NULL);
2516 if (client->opts & OPT_LOCK
2517 && (!rc || gpg_err_code (rc) == GPG_ERR_NO_DATA))
2519 unsigned char md5file[16];
2520 gpg_error_t trc = rc;
2522 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, line, strlen (line));
2523 if (memcmp (md5file, client->md5file, 16))
2524 cleanup_client (client);
2526 memcpy (client->md5file, md5file, 16);
2527 rc = do_lock (client, 1);
2528 if (!rc)
2529 rc = trc;
2532 return send_error (ctx, rc);
2535 static gpg_error_t
2536 clearcache_command (assuan_context_t ctx, char *line)
2538 gpg_error_t rc = 0, all_rc = 0;
2539 unsigned char md5file[16];
2540 int i;
2541 int t;
2542 int all = 0;
2543 struct client_thread_s *once = NULL;
2545 cache_lock ();
2546 MUTEX_LOCK (&cn_mutex);
2547 pthread_cleanup_push (cleanup_mutex_cb, &cn_mutex);
2549 if (!line || !*line)
2550 all = 1;
2552 t = slist_length (cn_thread_list);
2554 for (i = 0; i < t; i++)
2556 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
2557 assuan_peercred_t peer;
2559 if (!thd->cl)
2560 continue;
2562 /* Lock each connected clients' file mutex to prevent any other client
2563 * from accessing the cache entry (the file mutex is locked upon
2564 * command startup). The cache for the entry is not cleared if the
2565 * file mutex is locked by another client to prevent this function
2566 * from blocking.
2568 if (all)
2570 if (thd->cl->filename)
2572 rc = do_validate_peer (ctx, thd->cl->filename, &peer);
2573 all_rc = !all_rc ? rc : all_rc;
2574 if (rc)
2576 rc = 0;
2577 continue;
2581 rc = cache_lock_mutex (thd->cl->ctx, thd->cl->md5file, -1, 0, -1);
2582 if (gpg_err_code (rc) == GPG_ERR_LOCKED)
2584 if (pthread_equal (pthread_self (), thd->tid))
2585 rc = 0;
2586 else
2588 if (!thd->cl->filename ||
2589 cache_iscached (thd->cl->filename,
2590 NULL) == GPG_ERR_NO_DATA)
2592 rc = 0;
2593 continue;
2596 cache_defer_clear (thd->cl->md5file);
2599 else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
2601 rc = 0;
2602 continue;
2605 if (!rc)
2607 rc = cache_clear (thd->cl->md5file);
2608 cache_unlock_mutex (thd->cl->md5file, 0);
2611 if (rc)
2612 all_rc = rc;
2614 rc = 0;
2616 /* A single data filename was specified. Lock only this data file
2617 * mutex and free the cache entry. */
2618 else
2620 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, line, strlen (line));
2621 rc = do_validate_peer (ctx, line, &peer);
2623 if (!rc && !memcmp (thd->cl->md5file, md5file, sizeof (md5file)))
2625 rc = cache_lock_mutex (thd->cl->ctx, thd->cl->md5file, -1, 0,
2626 -1);
2627 if (gpg_err_code (rc) == GPG_ERR_LOCKED)
2629 if (pthread_equal (pthread_self (), thd->tid))
2630 rc = 0;
2633 if (!rc)
2635 once = thd;
2636 rc = cache_clear (thd->cl->md5file);
2637 cache_unlock_mutex (thd->cl->md5file, 0);
2639 else
2641 cache_defer_clear (thd->cl->md5file);
2644 break;
2649 /* Only connected clients' cache entries have been cleared. Now clear any
2650 * remaining cache entries without clients but only if there wasn't an
2651 * error from above since this would defeat the locking check of the
2652 * remaining entries. */
2653 if (!all_rc && all)
2655 cache_clear (NULL);
2658 /* No clients are using the specified file. */
2659 else if (!all_rc && !rc && !once)
2661 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, line, strlen (line));
2662 rc = cache_clear (md5file);
2665 /* Release the connection mutex. */
2666 pthread_cleanup_pop (1);
2667 cache_unlock ();
2669 if (!rc)
2670 send_status_all (STATUS_CACHE, NULL);
2672 /* One or more files were locked while clearing all cache entries. */
2673 if (all_rc)
2674 rc = all_rc;
2676 return send_error (ctx, rc);
2679 static gpg_error_t
2680 cachetimeout_command (assuan_context_t ctx, char *line)
2682 int timeout;
2683 char **req = str_split (line, " ", 0);
2684 char *p;
2685 gpg_error_t rc = 0;
2686 assuan_peercred_t peer;
2688 if (!req || !*req || !req[1])
2690 strv_free (req);
2691 return send_error (ctx, GPG_ERR_SYNTAX);
2694 errno = 0;
2695 timeout = (int) strtol (req[1], &p, 10);
2696 if (errno != 0 || *p || timeout < -1)
2698 strv_free (req);
2699 return send_error (ctx, GPG_ERR_SYNTAX);
2702 rc = do_validate_peer (ctx, req[0], &peer);
2703 if (!rc)
2705 unsigned char md5file[16];
2707 gcry_md_hash_buffer (GCRY_MD_MD5, md5file, req[0], strlen (req[0]));
2708 rc = cache_set_timeout (md5file, timeout);
2709 if (!rc || gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
2711 rc = 0;
2712 MUTEX_LOCK (&rcfile_mutex);
2713 config_set_int_param (&global_config, req[0], "cache_timeout",
2714 req[1]);
2715 MUTEX_UNLOCK (&rcfile_mutex);
2719 strv_free (req);
2720 return send_error (ctx, rc);
2723 static gpg_error_t
2724 dump_command (assuan_context_t ctx, char *line)
2726 xmlChar *xml;
2727 int len;
2728 struct client_s *client = assuan_get_pointer (ctx);
2729 gpg_error_t rc;
2731 if (disable_list_and_dump == 1)
2732 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
2734 if (line && *line)
2735 return send_error (ctx, GPG_ERR_SYNTAX);
2737 rc = peer_is_invoker(client);
2738 if (rc)
2739 return send_error (ctx, rc);
2741 xmlDocDumpFormatMemory (client->doc, &xml, &len, 1);
2743 if (!xml)
2745 log_write ("%s(%i): %s", __FILE__, __LINE__,
2746 pwmd_strerror (GPG_ERR_ENOMEM));
2747 return send_error (ctx, GPG_ERR_ENOMEM);
2750 pthread_cleanup_push (xmlFree, xml);
2751 rc = xfer_data (ctx, (char *) xml, len);
2752 pthread_cleanup_pop (1);
2753 return send_error (ctx, rc);
2756 static gpg_error_t
2757 getconfig_command (assuan_context_t ctx, char *line)
2759 struct client_s *client = assuan_get_pointer (ctx);
2760 gpg_error_t rc = 0;
2761 char filename[255] = { 0 }, param[747] = { 0 };
2762 char *p, *tmp = NULL, *fp = client->filename, *paramp = line;
2764 if (!line || !*line)
2765 return send_error (ctx, GPG_ERR_SYNTAX);
2767 if (strchr (line, ' '))
2769 sscanf (line, " %254[^ ] %746c", filename, param);
2770 paramp = param;
2771 fp = filename;
2774 if (fp && !valid_filename (fp))
2775 return send_error (ctx, GPG_ERR_INV_VALUE);
2777 paramp = str_down (paramp);
2778 if (!strcmp (paramp, "cipher") && fp)
2780 struct crypto_s *crypto = NULL;
2782 rc = init_client_crypto (&crypto);
2783 if (!rc)
2785 rc = read_data_header (fp, &crypto->hdr, NULL, NULL);
2786 if (!rc)
2788 const char *t =
2789 gcry_cipher_algo_name (cipher_to_gcrypt (crypto->hdr.flags));
2790 if (t)
2792 tmp = str_dup (t);
2793 if (tmp)
2794 str_down (tmp);
2799 UPDATE_AGENT_CTX (client, crypto);
2800 cleanup_crypto (&crypto);
2801 if (rc && gpg_err_code (rc) != GPG_ERR_ENOENT)
2802 return send_error (ctx, rc);
2804 if (!rc && tmp)
2805 goto done;
2807 else if (!strcmp (paramp, "cipher_iterations") && fp)
2809 struct crypto_s *crypto = NULL;
2811 rc = init_client_crypto (&crypto);
2812 if (!rc)
2814 rc = read_data_header (fp, &crypto->hdr, NULL, NULL);
2815 if (!rc)
2817 tmp = str_asprintf ("%llu",
2818 (unsigned long long) crypto->hdr.s2k_count);
2819 if (!tmp)
2820 rc = GPG_ERR_ENOMEM;
2824 UPDATE_AGENT_CTX (client, crypto);
2825 cleanup_crypto (&crypto);
2826 if (rc && gpg_err_code (rc) != GPG_ERR_ENOENT)
2827 return send_error (ctx, rc);
2829 if (!rc && tmp)
2830 goto done;
2832 else if (!strcmp (paramp, "passphrase"))
2833 return send_error (ctx, GPG_ERR_UNKNOWN_OPTION);
2835 p = config_get_value (fp ? fp : "global", paramp);
2836 if (!p)
2837 return send_error (ctx, GPG_ERR_UNKNOWN_OPTION);
2839 tmp = expand_homedir (p);
2840 xfree (p);
2841 if (!tmp)
2843 log_write ("%s(%i): %s", __FILE__, __LINE__,
2844 pwmd_strerror (GPG_ERR_ENOMEM));
2845 return send_error (ctx, GPG_ERR_ENOMEM);
2848 done:
2849 p = tmp;
2850 pthread_cleanup_push (xfree, p);
2851 rc = xfer_data (ctx, p, strlen (p));
2852 pthread_cleanup_pop (1);
2853 return send_error (ctx, rc);
2856 struct xpath_s
2858 xmlXPathContextPtr xp;
2859 xmlXPathObjectPtr result;
2860 xmlBufferPtr buf;
2861 char **req;
2864 static void
2865 xpath_command_cleanup (void *arg)
2867 struct xpath_s *xpath = arg;
2869 if (!xpath)
2870 return;
2872 req_cleanup (xpath->req);
2874 if (xpath->buf)
2875 xmlBufferFree (xpath->buf);
2877 if (xpath->result)
2878 xmlXPathFreeObject (xpath->result);
2880 if (xpath->xp)
2881 xmlXPathFreeContext (xpath->xp);
2884 static gpg_error_t
2885 do_xpath (assuan_context_t ctx, char *line)
2887 gpg_error_t rc;
2888 struct client_s *client = assuan_get_pointer (ctx);
2889 struct xpath_s _x = { 0 };
2890 struct xpath_s *xpath = &_x;
2892 if (!line || !*line)
2893 return GPG_ERR_SYNTAX;
2895 if ((xpath->req = str_split (line, "\t", 2)) == NULL)
2897 if (strv_printf (&xpath->req, "%s", line) == 0)
2898 return GPG_ERR_ENOMEM;
2901 xpath->xp = xmlXPathNewContext (client->doc);
2902 if (!xpath->xp)
2904 rc = GPG_ERR_BAD_DATA;
2905 goto fail;
2908 xpath->result =
2909 xmlXPathEvalExpression ((xmlChar *) xpath->req[0], xpath->xp);
2910 if (!xpath->result)
2912 rc = GPG_ERR_BAD_DATA;
2913 goto fail;
2916 if (xmlXPathNodeSetIsEmpty (xpath->result->nodesetval))
2918 rc = GPG_ERR_ELEMENT_NOT_FOUND;
2919 goto fail;
2922 rc = recurse_xpath_nodeset (client, client->doc, xpath->result->nodesetval,
2923 (xmlChar *) xpath->req[1], &xpath->buf, 0,
2924 NULL);
2925 if (rc)
2926 goto fail;
2927 else if (!xpath->req[1] && !xmlBufferLength (xpath->buf))
2929 rc = GPG_ERR_NO_DATA;
2930 goto fail;
2932 else if (xpath->req[1])
2934 rc = 0;
2935 goto fail;
2938 pthread_cleanup_push (xpath_command_cleanup, &xpath);
2939 rc = xfer_data (ctx, (char *) xmlBufferContent (xpath->buf),
2940 xmlBufferLength (xpath->buf));
2941 pthread_cleanup_pop (0);
2942 fail:
2943 xpath_command_cleanup (xpath);
2944 return rc;
2947 static gpg_error_t
2948 xpath_command (assuan_context_t ctx, char *line)
2950 struct client_s *client = assuan_get_pointer (ctx);
2951 gpg_error_t rc;
2952 struct argv_s *args[] = {
2953 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
2954 NULL
2957 if (disable_list_and_dump == 1)
2958 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
2960 rc = peer_is_invoker(client);
2961 if (rc)
2962 return send_error (ctx, rc);
2964 rc = parse_options (&line, args, client, 1);
2965 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
2966 rc = GPG_ERR_SYNTAX;
2967 if (rc)
2968 return send_error (ctx, rc);
2970 if (client->opts & OPT_INQUIRE)
2972 unsigned char *result;
2973 size_t len;
2975 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
2976 if (rc)
2977 return send_error (ctx, rc);
2979 pthread_cleanup_push (xfree, result);
2980 rc = do_xpath (ctx, (char *)result);
2981 pthread_cleanup_pop (1);
2983 else
2984 rc = do_xpath (ctx, line);
2986 return send_error (ctx, rc);
2989 static gpg_error_t
2990 do_xpathattr (assuan_context_t ctx, char *line)
2992 struct client_s *client = assuan_get_pointer (ctx);
2993 gpg_error_t rc;
2994 char **req = NULL;
2995 int cmd = 0; //SET
2996 struct xpath_s _x = { 0 };
2997 struct xpath_s *xpath = &_x;
2999 if (!line || !*line)
3000 return GPG_ERR_SYNTAX;
3002 if ((req = str_split (line, " ", 3)) == NULL)
3003 return GPG_ERR_ENOMEM;
3005 if (!req[0])
3007 rc = GPG_ERR_SYNTAX;
3008 goto fail;
3011 if (!strcasecmp (req[0], "SET"))
3012 cmd = 0;
3013 else if (!strcasecmp (req[0], "DELETE"))
3014 cmd = 1;
3015 else
3017 rc = GPG_ERR_SYNTAX;
3018 goto fail;
3021 if (!req[1] || !req[2])
3023 rc = GPG_ERR_SYNTAX;
3024 goto fail;
3027 if ((xpath->req = str_split (req[2], "\t", 3)) == NULL)
3029 rc = GPG_ERR_ENOMEM;
3030 goto fail;
3033 if (!xpath->req[0] || (!xpath->req[1] && !cmd) || (xpath->req[1] && cmd))
3035 rc = GPG_ERR_SYNTAX;
3036 goto fail;
3039 xpath->xp = xmlXPathNewContext (client->doc);
3040 if (!xpath->xp)
3042 rc = GPG_ERR_BAD_DATA;
3043 goto fail;
3046 xpath->result = xmlXPathEvalExpression ((xmlChar *) xpath->req[0], xpath->xp);
3047 if (!xpath->result)
3049 rc = GPG_ERR_BAD_DATA;
3050 goto fail;
3053 if (xmlXPathNodeSetIsEmpty (xpath->result->nodesetval))
3055 rc = GPG_ERR_ELEMENT_NOT_FOUND;
3056 goto fail;
3059 rc = recurse_xpath_nodeset (client, client->doc, xpath->result->nodesetval,
3060 (xmlChar *) xpath->req[1], &xpath->buf, cmd,
3061 (xmlChar *) req[1]);
3063 fail:
3064 xpath_command_cleanup (xpath);
3065 strv_free (req);
3066 return rc;
3069 /* XPATHATTR SET|DELETE <name> <expression>[<TAB>[value]] */
3070 static gpg_error_t
3071 xpathattr_command (assuan_context_t ctx, char *line)
3073 struct client_s *client = assuan_get_pointer (ctx);
3074 gpg_error_t rc;
3075 struct argv_s *args[] = {
3076 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
3077 NULL
3080 if (disable_list_and_dump == 1)
3081 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
3083 rc = peer_is_invoker(client);
3084 if (rc)
3085 return send_error (ctx, rc);
3087 rc = parse_options (&line, args, client, 1);
3088 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
3089 rc = GPG_ERR_SYNTAX;
3090 if (rc)
3091 return send_error (ctx, rc);
3093 if (client->opts & OPT_INQUIRE)
3095 unsigned char *result;
3096 size_t len;
3098 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3099 if (rc)
3100 return send_error (ctx, rc);
3102 pthread_cleanup_push (xfree, result);
3103 rc = do_xpathattr (ctx, (char *)result);
3104 pthread_cleanup_pop (1);
3106 else
3107 rc = do_xpathattr (ctx, line);
3109 return send_error (ctx, rc);
3112 static gpg_error_t
3113 do_import (struct client_s *client, const char *root_element,
3114 unsigned char *content)
3116 char **dst_path = NULL;
3117 xmlDocPtr doc = NULL;
3118 xmlNodePtr n, root, copy;
3119 gpg_error_t rc;
3121 if (!content || !*content)
3123 xfree (content);
3124 return GPG_ERR_SYNTAX;
3127 if (root_element)
3128 dst_path = str_split (root_element, "\t", 0);
3130 if (dst_path && !valid_element_path (dst_path, 0))
3132 if (dst_path)
3133 strv_free (dst_path);
3135 return GPG_ERR_INV_VALUE;
3138 struct string_s *str = string_new_content ((char *)content);
3139 str = string_prepend (str, "<pwmd>");
3140 str = string_append (str, "</pwmd>");
3141 doc = xmlReadDoc ((xmlChar *) str->str, NULL, "UTF-8", XML_PARSE_NOBLANKS);
3142 string_free (str, 1);
3143 if (!doc)
3145 rc = GPG_ERR_BAD_DATA;
3146 goto fail;
3149 root = xmlDocGetRootElement (doc);
3150 xmlNodePtr root_orig = root->children;
3151 root = root->children;
3152 rc = validate_import (client, root);
3153 if (rc)
3154 goto fail;
3158 again:
3159 if (dst_path)
3161 char **path = strv_dup (dst_path);
3162 if (!path)
3164 log_write ("%s(%i): %s", __FILE__, __LINE__,
3165 pwmd_strerror (GPG_ERR_ENOMEM));
3166 rc = GPG_ERR_ENOMEM;
3167 goto fail;
3170 xmlChar *a = xmlGetProp (root, (xmlChar *) "_name");
3171 if (!a)
3173 strv_free (path);
3174 rc = GPG_ERR_INV_VALUE;
3175 goto fail;
3178 if (strv_printf (&path, "%s", (char *) a) == 0)
3180 xmlFree (a);
3181 rc = GPG_ERR_ENOMEM;
3182 goto fail;
3185 xmlFree (a);
3186 n = find_root_element (client, client->doc, &path, &rc, NULL, 0, 0);
3187 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3189 strv_free (path);
3190 goto fail;
3193 if (!rc)
3195 n = find_elements (client, client->doc, n->children, path + 1, &rc,
3196 NULL, NULL, NULL, 0, 0, NULL, 1);
3197 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3199 strv_free (path);
3200 goto fail;
3202 else if (!rc)
3204 xmlUnlinkNode (n);
3205 xmlFreeNode (n);
3206 strv_free (path);
3207 path = NULL;
3208 goto again;
3212 if (rc == GPG_ERR_ELEMENT_NOT_FOUND)
3214 n = create_element_path (client, &path, &rc, NULL);
3215 if (rc)
3216 goto fail;
3219 if (root->children)
3221 copy = xmlCopyNodeList (root->children);
3222 n = xmlAddChildList (n, copy);
3223 if (!n)
3224 rc = GPG_ERR_ENOMEM;
3227 strv_free (path);
3229 else
3231 char **path = NULL;
3233 /* Check if the content root element can create a DTD root element. */
3234 if (!xmlStrEqual ((xmlChar *) "element", root->name))
3236 rc = GPG_ERR_SYNTAX;
3237 goto fail;
3240 xmlChar *a;
3242 if ((a = xmlGetProp (root, (xmlChar *) "_name")) == NULL)
3244 rc = GPG_ERR_SYNTAX;
3245 goto fail;
3248 char *tmp = str_dup ((char *) a);
3249 xmlFree (a);
3250 int literal = is_literal_element (&tmp);
3252 if (!valid_xml_element ((xmlChar *) tmp) || literal)
3254 xfree (tmp);
3255 rc = GPG_ERR_INV_VALUE;
3256 goto fail;
3259 if (strv_printf (&path, "%s", tmp) == 0)
3261 xfree (tmp);
3262 rc = GPG_ERR_ENOMEM;
3263 goto fail;
3266 xfree (tmp);
3267 n = find_root_element (client, client->doc, &path, &rc, NULL, 0, 1);
3268 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3270 rc = GPG_ERR_BAD_DATA;
3271 goto fail;
3274 /* Overwriting the existing tree. */
3275 if (!rc)
3277 xmlUnlinkNode (n);
3278 xmlFreeNodeList (n);
3281 rc = 0;
3282 xmlSetProp (root, (xmlChar *) "_name", (xmlChar *) path[0]);
3283 n = xmlCopyNode (root, 1);
3284 n = xmlAddChildList (xmlDocGetRootElement (client->doc), n);
3285 strv_free (path);
3288 if (n && !rc)
3289 rc = update_element_mtime (client, n->parent);
3291 for (root = root_orig->next; root; root = root->next)
3293 if (root->type == XML_ELEMENT_NODE)
3294 break;
3297 root_orig = root;
3299 while (root);
3301 fail:
3302 if (doc)
3303 xmlFreeDoc (doc);
3305 if (dst_path)
3306 strv_free (dst_path);
3308 return rc;
3311 static gpg_error_t
3312 parse_import_opt_root (void *data, void *value)
3314 struct client_s *client = data;
3316 client->import_root = str_dup (value);
3317 return client->import_root ? 0 : GPG_ERR_ENOMEM;
3320 static gpg_error_t
3321 import_command (assuan_context_t ctx, char *line)
3323 gpg_error_t rc;
3324 struct client_s *client = assuan_get_pointer (ctx);
3325 unsigned char *result;
3326 size_t len;
3327 struct argv_s *args[] = {
3328 &(struct argv_s) {"root", OPTION_TYPE_ARG, parse_import_opt_root},
3329 NULL
3332 xfree (client->import_root);
3333 client->import_root = NULL;
3334 rc = parse_options (&line, args, client, 0);
3335 if (rc)
3336 return send_error (ctx, rc);
3338 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3339 if (rc)
3341 xfree (client->import_root);
3342 client->import_root = NULL;
3343 return send_error (ctx, rc);
3346 rc = do_import (client, client->import_root, result);
3347 xfree (client->import_root);
3348 client->import_root = NULL;
3349 return send_error (ctx, rc);
3352 static gpg_error_t
3353 do_lock (struct client_s *client, int add)
3355 gpg_error_t rc = lock_file_mutex (client, add);
3357 if (!rc)
3358 client->flags |= FLAG_LOCK_CMD;
3360 return rc;
3363 static gpg_error_t
3364 lock_command (assuan_context_t ctx, char *line)
3366 struct client_s *client = assuan_get_pointer (ctx);
3367 gpg_error_t rc;
3369 if (line && *line)
3370 return send_error (ctx, GPG_ERR_SYNTAX);
3372 rc = do_lock (client, 0);
3373 return send_error (ctx, rc);
3376 static gpg_error_t
3377 unlock_command (assuan_context_t ctx, char *line)
3379 struct client_s *client = assuan_get_pointer (ctx);
3380 gpg_error_t rc;
3382 if (line && *line)
3383 return send_error (ctx, GPG_ERR_SYNTAX);
3385 rc = unlock_file_mutex (client, 0);
3386 return send_error (ctx, rc);
3389 static gpg_error_t
3390 option_command (assuan_context_t ctx, char *line)
3392 struct client_s *client = assuan_get_pointer (ctx);
3393 gpg_error_t rc = 0;
3394 struct pinentry_option_s *pin_opts = &client->pinentry_opts;
3395 #ifdef WITH_AGENT
3396 struct agent_s *agent = client->crypto->agent;
3397 #endif
3398 char namebuf[255] = { 0 };
3399 char *name = namebuf;
3400 char *value = NULL, *p, *tmp = NULL;
3402 p = strchr (line, '=');
3403 if (!p)
3405 strncpy (namebuf, line, sizeof(namebuf));
3406 namebuf[sizeof(namebuf)-1] = 0;
3408 else
3410 strncpy (namebuf, line, strlen (line)-strlen (p));
3411 namebuf[sizeof(namebuf)-1] = 0;
3412 value = p+1;
3415 log_write1 ("OPTION name='%s' value='%s'", name, value);
3417 if (strcasecmp (name, (char *) "lock-timeout") == 0)
3419 long n = 0;
3421 if (value)
3423 n = strtol (value, &tmp, 10);
3424 if (tmp && *tmp)
3425 return send_error (ctx, GPG_ERR_INV_VALUE);
3428 client->lock_timeout = n;
3429 goto done;
3431 else if (strcasecmp (name, (char *) "NAME") == 0)
3433 if (value && strchr (value, ' '))
3434 rc = GPG_ERR_INV_VALUE;
3435 else
3437 tmp = pthread_getspecific (thread_name_key);
3438 xfree (tmp);
3439 MUTEX_LOCK (&cn_mutex);
3440 xfree (client->thd->name);
3441 client->thd->name = NULL;
3443 if (!value || !*value)
3444 pthread_setspecific (thread_name_key, str_dup (""));
3445 else
3447 client->thd->name = str_dup (value);
3448 pthread_setspecific (thread_name_key, str_dup (value));
3451 MUTEX_UNLOCK (&cn_mutex);
3453 goto done;
3455 else if (strcasecmp (name, (char *) "lc-messages") == 0)
3457 xfree (pin_opts->lc_messages);
3458 pin_opts->lc_messages = NULL;
3459 if (value && *value)
3460 pin_opts->lc_messages = str_dup (value);
3461 #ifdef WITH_AGENT
3462 if (use_agent)
3463 rc = set_agent_option (client->crypto->agent, "lc-messages", value);
3464 #endif
3466 else if (strcasecmp (name, (char *) "lc-ctype") == 0)
3468 xfree (pin_opts->lc_ctype);
3469 pin_opts->lc_ctype = NULL;
3470 if (value && *value)
3471 pin_opts->lc_ctype = str_dup (value);
3472 #ifdef WITH_AGENT
3473 if (use_agent)
3474 rc = set_agent_option (client->crypto->agent, "lc-ctype", value);
3475 #endif
3477 else if (strcasecmp (name, (char *) "ttyname") == 0)
3479 xfree (pin_opts->ttyname);
3480 pin_opts->ttyname = NULL;
3481 if (value && *value)
3482 pin_opts->ttyname = str_dup (value);
3483 #ifdef WITH_AGENT
3484 if (use_agent)
3485 rc = set_agent_option (client->crypto->agent, "ttyname", value);
3486 #endif
3488 else if (strcasecmp (name, (char *) "ttytype") == 0)
3490 xfree (pin_opts->ttytype);
3491 pin_opts->ttytype = NULL;
3492 if (value && *value)
3493 pin_opts->ttytype = str_dup (value);
3494 #ifdef WITH_AGENT
3495 if (use_agent)
3496 rc = set_agent_option (client->crypto->agent, "ttytype", value);
3497 #endif
3499 else if (strcasecmp (name, (char *) "display") == 0)
3501 xfree (pin_opts->display);
3502 pin_opts->display = NULL;
3503 if (value && *value)
3504 pin_opts->display = str_dup (value);
3505 #ifdef WITH_AGENT
3506 if (use_agent)
3507 rc = set_agent_option (client->crypto->agent, "display", value);
3508 #endif
3510 else if (strcasecmp (name, (char *) "pinentry-desc") == 0)
3512 xfree (pin_opts->desc);
3513 pin_opts->desc = NULL;
3514 if (value && *value)
3515 pin_opts->desc = str_dup (value);
3517 else if (strcasecmp (name, (char *) "pinentry-title") == 0)
3519 xfree (pin_opts->title);
3520 pin_opts->title = NULL;
3521 if (value && *value)
3522 pin_opts->title = str_dup (value);
3524 else if (strcasecmp (name, (char *) "pinentry-prompt") == 0)
3526 xfree (pin_opts->prompt);
3527 pin_opts->prompt = NULL;
3528 if (value && *value)
3529 pin_opts->prompt = str_dup (value);
3532 else if (strcasecmp (name, "pinentry-timeout") == 0)
3534 char *p = NULL;
3535 int n;
3537 if (!value)
3538 goto done;
3540 n = (int) strtol (value, &p, 10);
3542 if (*p || n < 0)
3543 return send_error (ctx, GPG_ERR_INV_VALUE);
3545 pin_opts->timeout = n;
3546 MUTEX_LOCK (&rcfile_mutex);
3547 config_set_int_param (&global_config,
3548 client->filename ? client->filename : "global",
3549 "pinentry_timeout", value);
3550 MUTEX_UNLOCK (&rcfile_mutex);
3551 goto done;
3553 else if (strcasecmp (name, "disable-pinentry") == 0)
3555 int n = 1;
3557 if (value && *value)
3559 n = (int) strtol (value, &tmp, 10);
3560 if (*tmp || n < 0 || n > 1)
3561 return send_error (ctx, GPG_ERR_INV_VALUE);
3564 if (n)
3565 client->flags |= FLAG_NO_PINENTRY;
3566 else
3567 client->flags &= ~FLAG_NO_PINENTRY;
3569 #ifdef WITH_AGENT
3570 if (use_agent)
3572 if (client->flags & FLAG_NO_PINENTRY)
3573 rc = set_agent_option (client->crypto->agent, "pinentry-mode",
3574 "loopback");
3575 else
3576 rc = set_agent_option (client->crypto->agent, "pinentry-mode",
3577 "ask");
3579 if (rc)
3580 return send_error (ctx, rc);
3582 #endif
3584 else
3585 return send_error (ctx, GPG_ERR_UNKNOWN_OPTION);
3587 done:
3588 #ifdef WITH_AGENT
3589 if (!rc && use_agent && agent)
3591 rc = pinentry_merge_options (&client->crypto->agent->pinentry_opts,
3592 pin_opts);
3594 #endif
3596 return send_error (ctx, rc);
3599 static gpg_error_t
3600 do_rename (assuan_context_t ctx, char *line)
3602 struct client_s *client = assuan_get_pointer (ctx);
3603 gpg_error_t rc;
3604 char **req, **src, *dst;
3605 xmlNodePtr n, ndst;
3607 req = str_split (line, " ", 0);
3609 if (!req || !req[0] || !req[1])
3611 strv_free (req);
3612 return GPG_ERR_SYNTAX;
3615 dst = req[1];
3616 is_literal_element (&dst);
3618 if (!valid_xml_element ((xmlChar *) dst))
3620 strv_free (req);
3621 return GPG_ERR_INV_VALUE;
3624 if (strchr (req[0], '\t'))
3625 src = str_split (req[0], "\t", 0);
3626 else
3627 src = str_split (req[0], " ", 0);
3629 if (!src || !*src)
3631 rc = GPG_ERR_SYNTAX;
3632 goto fail;
3635 n = find_root_element (client, client->doc, &src, &rc, NULL, 0, 0);
3636 if (rc)
3637 goto fail;
3639 if (src[1] && n)
3640 n = find_elements (client, client->doc, n->children, src + 1, &rc, NULL, NULL,
3641 NULL, 0, 0, NULL, 0);
3643 if (!n || rc)
3644 goto fail;
3646 rc = is_element_owner (client, n);
3647 if (rc)
3648 goto fail;
3650 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
3651 if (!a)
3653 rc = GPG_ERR_ENOMEM;
3654 goto fail;
3657 /* To prevent unwanted effects:
3659 * <root name="a"><b/></root>
3661 * RENAME a<TAB>b b
3663 if (xmlStrEqual (a, (xmlChar *) dst))
3665 xmlFree (a);
3666 rc = GPG_ERR_AMBIGUOUS_NAME;
3667 goto fail;
3670 xmlFree (a);
3671 char **tmp = NULL;
3672 if (src[1])
3674 char **p;
3676 for (p = src; *p; p++)
3678 if (!*(p + 1))
3679 break;
3680 strv_printf (&tmp, "%s", *p);
3684 strv_printf (&tmp, "!%s", dst);
3685 ndst = find_root_element (client, client->doc, &tmp, &rc, NULL, 0, 0);
3686 if (!ndst && rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3688 strv_free (tmp);
3689 goto fail;
3692 if (tmp[1] && ndst)
3693 ndst = find_elements (client, client->doc, ndst->children, tmp + 1, &rc, NULL,
3694 NULL, NULL, 0, 0, NULL, 0);
3696 strv_free (tmp);
3697 if (!ndst && rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3698 goto fail;
3700 rc = 0;
3702 /* Target may exist:
3704 * <root name="a"/>
3705 * <root name="b" target="a"/>
3707 * RENAME b a
3709 * Would need to do:
3710 * RENAME !b a
3712 if (ndst == n)
3714 rc = GPG_ERR_AMBIGUOUS_NAME;
3715 goto fail;
3718 if (ndst)
3720 rc = is_element_owner (client, ndst);
3721 if (rc)
3722 goto fail;
3724 unlink_node (client, ndst);
3725 xmlFreeNodeList (ndst);
3728 rc = add_attribute (client, n, "_name", dst);
3730 fail:
3731 strv_free (req);
3732 strv_free (src);
3733 return rc;
3736 static gpg_error_t
3737 rename_command (assuan_context_t ctx, char *line)
3739 struct client_s *client = assuan_get_pointer (ctx);
3740 gpg_error_t rc;
3741 struct argv_s *args[] = {
3742 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
3743 NULL
3746 rc = parse_options (&line, args, client, 1);
3747 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
3748 rc = GPG_ERR_SYNTAX;
3749 if (rc)
3750 return send_error (ctx, rc);
3752 if (client->opts & OPT_INQUIRE)
3754 unsigned char *result;
3755 size_t len;
3757 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3758 if (rc)
3759 return send_error (ctx, rc);
3761 pthread_cleanup_push (xfree, result);
3762 rc = do_rename (ctx, (char *)result);
3763 pthread_cleanup_pop (1);
3765 else
3766 rc = do_rename (ctx, line);
3768 return send_error (ctx, rc);
3771 static gpg_error_t
3772 do_copy (assuan_context_t ctx, char *line)
3774 struct client_s *client = assuan_get_pointer (ctx);
3775 gpg_error_t rc;
3776 char **req, **src = NULL, **dst = NULL;
3777 xmlNodePtr nsrc, ndst, new = NULL;
3779 req = str_split (line, " ", 0);
3780 if (!req || !req[0] || !req[1])
3782 strv_free (req);
3783 return GPG_ERR_SYNTAX;
3786 if (strchr (req[0], '\t'))
3787 src = str_split (req[0], "\t", 0);
3788 else
3789 src = str_split (req[0], " ", 0);
3791 if (!src || !*src)
3793 rc = GPG_ERR_SYNTAX;
3794 goto fail;
3797 if (strchr (req[1], '\t'))
3798 dst = str_split (req[1], "\t", 0);
3799 else
3800 dst = str_split (req[1], " ", 0);
3802 if (!dst || !*dst)
3804 rc = GPG_ERR_SYNTAX;
3805 goto fail;
3808 if (!valid_element_path (dst, 0))
3810 rc = GPG_ERR_INV_VALUE;
3811 goto fail;
3814 nsrc = find_root_element (client, client->doc, &src, &rc, NULL, 0, 0);
3815 if (rc)
3816 goto fail;
3818 if (nsrc && src[1])
3819 nsrc = find_elements (client, client->doc, nsrc->children, src + 1, &rc, NULL,
3820 NULL, NULL, 0, 0, NULL, 0);
3822 if (!nsrc || rc)
3823 goto fail;
3825 new = xmlCopyNodeList (nsrc);
3826 if (!new)
3828 rc = GPG_ERR_ENOMEM;
3829 goto fail;
3832 int create = 0;
3833 ndst = find_root_element (client, client->doc, &dst, &rc, NULL, 0, 0);
3834 if (rc == GPG_ERR_EACCES)
3835 goto fail;
3837 if (ndst && dst[1])
3839 if (ndst->children)
3840 ndst = find_elements (client, client->doc, ndst->children, dst + 1, &rc, NULL,
3841 NULL, create_target_elements_cb, 0, 0, NULL, 0);
3842 else
3843 create = 1;
3845 else
3846 create = 1;
3848 if (!ndst && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3849 goto fail;
3850 else if (!ndst || create)
3852 ndst = create_element_path (client, &dst, &rc, NULL);
3853 if (!ndst || rc)
3854 goto fail;
3857 rc = is_element_owner (client, ndst);
3858 if (rc)
3859 goto fail;
3861 /* Merge any attributes from the src node to the initial dst node. */
3862 for (xmlAttrPtr attr = new->properties; attr; attr = attr->next)
3864 if (xmlStrEqual (attr->name, (xmlChar *) "_name"))
3865 continue;
3867 xmlAttrPtr a = xmlHasProp (ndst, attr->name);
3868 if (a)
3869 xmlRemoveProp (a);
3871 xmlChar *tmp = xmlNodeGetContent (attr->children);
3872 xmlNewProp (ndst, attr->name, tmp);
3873 xmlFree (tmp);
3874 rc = add_attribute (client, ndst, NULL, NULL);
3877 xmlNodePtr n = ndst->children;
3878 xmlUnlinkNode (n);
3879 xmlFreeNodeList (n);
3880 ndst->children = NULL;
3882 if (new->children)
3884 n = xmlCopyNodeList (new->children);
3885 if (!n)
3887 rc = GPG_ERR_ENOMEM;
3888 goto fail;
3891 n = xmlAddChildList (ndst, n);
3892 if (!n)
3894 rc = GPG_ERR_ENOMEM;
3895 goto fail;
3898 rc = update_element_mtime (client, xmlDocGetRootElement (client->doc) ==
3899 ndst->parent ? ndst : ndst->parent);
3902 fail:
3903 if (new)
3905 xmlUnlinkNode (new);
3906 xmlFreeNodeList (new);
3909 if (req)
3910 strv_free (req);
3912 if (src)
3913 strv_free (src);
3915 if (dst)
3916 strv_free (dst);
3918 return rc;
3921 static gpg_error_t
3922 copy_command (assuan_context_t ctx, char *line)
3924 struct client_s *client = assuan_get_pointer (ctx);
3925 gpg_error_t rc;
3926 struct argv_s *args[] = {
3927 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
3928 NULL
3931 rc = parse_options (&line, args, client, 1);
3932 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
3933 rc = GPG_ERR_SYNTAX;
3934 if (rc)
3935 return send_error (ctx, rc);
3937 if (client->opts & OPT_INQUIRE)
3939 unsigned char *result;
3940 size_t len;
3942 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3943 if (rc)
3944 return send_error (ctx, rc);
3946 pthread_cleanup_push (xfree, result);
3947 rc = do_copy (ctx, (char *)result);
3948 pthread_cleanup_pop (1);
3950 else
3951 rc = do_copy (ctx, line);
3953 return send_error (ctx, rc);
3956 static gpg_error_t
3957 do_move (assuan_context_t ctx, char *line)
3959 struct client_s *client = assuan_get_pointer (ctx);
3960 gpg_error_t rc;
3961 char **req, **src = NULL, **dst = NULL;
3962 xmlNodePtr nsrc, ndst = NULL;
3964 req = str_split (line, " ", 0);
3966 if (!req || !req[0] || !req[1])
3968 strv_free (req);
3969 return GPG_ERR_SYNTAX;
3972 if (strchr (req[0], '\t'))
3973 src = str_split (req[0], "\t", 0);
3974 else
3975 src = str_split (req[0], " ", 0);
3977 if (!src || !*src)
3979 rc = GPG_ERR_SYNTAX;
3980 goto fail;
3983 if (strchr (req[1], '\t'))
3984 dst = str_split (req[1], "\t", 0);
3985 else
3986 dst = str_split (req[1], " ", 0);
3988 nsrc = find_root_element (client, client->doc, &src, &rc, NULL, 0, 0);
3989 if (rc)
3990 goto fail;
3992 if (nsrc && src[1])
3993 nsrc = find_elements (client, client->doc, nsrc->children, src + 1, &rc,
3994 NULL, NULL, NULL, 0, 0, NULL, 0);
3996 if (!nsrc)
3997 goto fail;
3999 rc = is_element_owner (client, nsrc);
4000 if (rc)
4001 goto fail;
4003 if (dst)
4005 if (!valid_element_path (dst, 0))
4007 rc = GPG_ERR_INV_VALUE;
4008 goto fail;
4011 ndst = find_root_element (client, client->doc, &dst, &rc, NULL, 0, 0);
4012 if (rc)
4013 goto fail;
4015 if (ndst && dst[1])
4016 ndst = find_elements (client, client->doc, ndst->children, dst + 1,
4017 &rc, NULL, NULL, NULL, 0, 0, NULL, 0);
4019 else
4020 ndst = xmlDocGetRootElement (client->doc);
4022 for (xmlNodePtr n = ndst; n; n = n->parent)
4024 if (n == nsrc)
4026 rc = GPG_ERR_CONFLICT;
4027 goto fail;
4031 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
4032 goto fail;
4034 rc = 0;
4036 if (ndst)
4038 xmlChar *a = node_has_attribute (nsrc, (xmlChar *) "_name");
4040 xmlNodePtr dup = find_element (client, ndst->children, (char *) a,
4041 NULL, &rc);
4042 xmlFree (a);
4044 if (rc)
4045 goto fail;
4047 if (dup)
4049 if (dup == nsrc)
4050 goto fail;
4052 if (ndst == xmlDocGetRootElement (client->doc))
4054 xmlNodePtr n = nsrc;
4055 int match = 0;
4057 while (n->parent && n->parent != ndst)
4058 n = n->parent;
4060 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
4061 xmlChar *b = node_has_attribute (nsrc, (xmlChar *) "_name");
4063 if (xmlStrEqual (a, b))
4065 match = 1;
4066 xmlUnlinkNode (nsrc);
4067 xmlUnlinkNode (n);
4068 xmlFreeNodeList (n);
4071 xmlFree (a);
4072 xmlFree (b);
4074 if (!match)
4076 xmlUnlinkNode (dup);
4077 xmlFreeNodeList (dup);
4080 else
4081 xmlUnlinkNode (dup);
4085 if (!ndst && dst)
4087 xmlChar *name = node_has_attribute (nsrc, (xmlChar *) "_name");
4089 if (nsrc->parent == xmlDocGetRootElement (client->doc)
4090 && !strcmp ((char *) name, *dst))
4092 xmlFree (name);
4093 rc = GPG_ERR_CONFLICT;
4094 goto fail;
4097 xmlFree (name);
4098 ndst = create_element_path (client, &dst, &rc, nsrc);
4099 if (rc)
4100 goto fail;
4103 if (!ndst)
4104 goto fail;
4106 update_element_mtime (client, nsrc->parent);
4107 xmlUnlinkNode (nsrc);
4108 ndst = xmlAddChildList (ndst, nsrc);
4110 if (!ndst)
4111 rc = GPG_ERR_ENOMEM;
4112 else
4113 update_element_mtime (client, ndst->parent);
4115 fail:
4116 if (req)
4117 strv_free (req);
4119 if (src)
4120 strv_free (src);
4122 if (dst)
4123 strv_free (dst);
4125 return rc;
4128 static gpg_error_t
4129 move_command (assuan_context_t ctx, char *line)
4131 struct client_s *client = assuan_get_pointer (ctx);
4132 gpg_error_t rc;
4133 struct argv_s *args[] = {
4134 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
4135 NULL
4138 rc = parse_options (&line, args, client, 1);
4139 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
4140 rc = GPG_ERR_SYNTAX;
4141 if (rc)
4142 return send_error (ctx, rc);
4144 if (client->opts & OPT_INQUIRE)
4146 unsigned char *result;
4147 size_t len;
4149 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
4150 if (rc)
4151 return send_error (ctx, rc);
4153 pthread_cleanup_push (xfree, result);
4154 rc = do_move (ctx, (char *)result);
4155 pthread_cleanup_pop (1);
4157 else
4158 rc = do_move (ctx, line);
4160 return send_error (ctx, rc);
4163 static gpg_error_t
4164 ls_command (assuan_context_t ctx, char *line)
4166 gpg_error_t rc;
4167 char *tmp;
4168 char *dir;
4169 DIR *d;
4171 if (line && *line)
4172 return send_error (ctx, GPG_ERR_SYNTAX);
4174 tmp = str_asprintf ("%s/data", homedir);
4175 dir = expand_homedir (tmp);
4176 xfree (tmp);
4177 d = opendir (dir);
4178 rc = gpg_error_from_errno (errno);
4180 if (!d)
4182 xfree (dir);
4183 return send_error (ctx, rc);
4186 size_t len =
4187 offsetof (struct dirent, d_name) +pathconf (dir, _PC_NAME_MAX) + 1;
4188 struct dirent *p = xmalloc (len), *cur = NULL;
4189 char *list = NULL;
4191 xfree (dir);
4192 pthread_cleanup_push (xfree, p);
4193 pthread_cleanup_push ((void *)(void *)closedir, d);
4194 rc = 0;
4196 while (!readdir_r (d, p, &cur) && cur)
4198 struct stat st;
4200 if (stat (cur->d_name, &st) == -1 || !S_ISREG (st.st_mode))
4201 continue;
4203 tmp = str_asprintf ("%s%s\n", list ? list : "", cur->d_name);
4205 if (!tmp)
4207 if (list)
4208 xfree (list);
4210 rc = GPG_ERR_ENOMEM;
4211 break;
4214 xfree (list);
4215 list = tmp;
4218 pthread_cleanup_pop (1); // closedir (d)
4219 pthread_cleanup_pop (1); // xfree (p)
4221 if (rc)
4222 return send_error (ctx, rc);
4224 if (!list)
4225 return send_error (ctx, GPG_ERR_NO_DATA);
4227 list[strlen (list) - 1] = 0;
4228 pthread_cleanup_push (xfree, list);
4229 rc = xfer_data (ctx, list, strlen (list));
4230 pthread_cleanup_pop (1);
4231 return send_error (ctx, rc);
4234 static gpg_error_t
4235 bye_notify (assuan_context_t ctx, char *line)
4237 struct client_s *cl = assuan_get_pointer (ctx);
4239 cl->thd->state = CLIENT_STATE_DISCON;
4241 #ifdef WITH_GNUTLS
4242 if (cl->thd->remote)
4244 int rc;
4248 struct timeval tv = { 0, 50000 };
4250 rc = gnutls_bye (cl->thd->tls->ses, GNUTLS_SHUT_RDWR);
4251 if (rc == GNUTLS_E_AGAIN)
4252 select (0, NULL, NULL, NULL, &tv);
4254 while (rc == GNUTLS_E_AGAIN);
4256 #endif
4258 /* This will let assuan_process_next() return. */
4259 if (fcntl (cl->thd->fd, F_SETFL, O_NONBLOCK) == -1)
4261 cl->last_rc = gpg_error_from_errno (errno);
4262 return cl->last_rc;
4265 cl->last_rc = 0; // BYE command result
4266 return 0;
4269 static gpg_error_t
4270 reset_notify (assuan_context_t ctx, char *line)
4272 struct client_s *client = assuan_get_pointer (ctx);
4274 if (client)
4275 cleanup_client (client);
4277 return 0;
4281 * This is called before every Assuan command.
4283 static gpg_error_t
4284 command_startup (assuan_context_t ctx, const char *name)
4286 struct client_s *client = assuan_get_pointer (ctx);
4287 gpg_error_t rc;
4288 struct command_table_s *cmd = NULL;
4290 log_write1 ("command='%s'", name);
4291 client->last_rc = client->opts = 0;
4293 for (int i = 0; command_table[i]; i++)
4295 if (!strcasecmp (name, command_table[i]->name))
4297 if (command_table[i]->ignore_startup)
4298 return 0;
4299 cmd = command_table[i];
4300 break;
4304 if (!cmd)
4305 return GPG_ERR_UNKNOWN_COMMAND;
4307 client->last_rc = rc = gpg_error (file_modified (client, cmd));
4308 if (!rc)
4309 update_client_state (client, CLIENT_STATE_COMMAND);
4311 return rc;
4315 * This is called after every Assuan command.
4317 static void
4318 command_finalize (assuan_context_t ctx, gpg_error_t rc)
4320 struct client_s *client = assuan_get_pointer (ctx);
4322 if (!(client->flags & FLAG_LOCK_CMD))
4323 unlock_file_mutex (client, 0);
4325 unlock_flock (&client->flock_fd);
4326 log_write1 (_("command completed: rc=%u"), rc ? rc : client->last_rc);
4327 client->last_rc = gpg_error (GPG_ERR_UNKNOWN_COMMAND);
4328 #ifdef WITH_GNUTLS
4329 client->thd->buffer_timeout = client->thd->last_buffer_size = 0;
4330 #endif
4331 update_client_state (client, CLIENT_STATE_IDLE);
4334 static gpg_error_t
4335 help_command (assuan_context_t ctx, char *line)
4337 gpg_error_t rc;
4338 int i;
4340 if (!line || !*line)
4342 char *tmp;
4343 char *help = str_dup (_("Usage: HELP [<COMMAND>]\n"
4344 "For commands that take an element path as an argument, each element is "
4345 "separated with an ASCII @key{TAB} character (ASCII 0x09)."
4346 "\n" "COMMANDS:"));
4348 for (i = 0; command_table[i]; i++)
4350 if (!command_table[i]->help)
4351 continue;
4353 tmp = str_asprintf ("%s %s", help, command_table[i]->name);
4354 xfree (help);
4355 help = tmp;
4358 tmp = strip_texi_and_wrap (help);
4359 xfree (help);
4360 pthread_cleanup_push (xfree, tmp);
4361 rc = xfer_data (ctx, tmp, strlen (tmp));
4362 pthread_cleanup_pop (1);
4363 return send_error (ctx, rc);
4366 for (i = 0; command_table[i]; i++)
4368 if (!strcasecmp (line, command_table[i]->name))
4370 char *help, *tmp;
4372 if (!command_table[i]->help)
4373 break;
4375 help = strip_texi_and_wrap (command_table[i]->help);
4376 tmp = str_asprintf (_("Usage: %s"), help);
4377 xfree (help);
4378 pthread_cleanup_push (xfree, tmp);
4379 rc = xfer_data (ctx, tmp, strlen (tmp));
4380 pthread_cleanup_pop (1);
4381 return send_error (ctx, rc);
4385 return send_error (ctx, GPG_ERR_INV_NAME);
4388 static void
4389 new_command (const char *name, int ignore, int unlock, int flock_type,
4390 gpg_error_t (*handler) (assuan_context_t, char *),
4391 const char *help)
4393 int i = 0;
4395 if (command_table)
4396 for (i = 0; command_table[i]; i++);
4398 command_table =
4399 xrealloc (command_table, (i + 2) * sizeof (struct command_table_s *));
4400 command_table[i] = xcalloc (1, sizeof (struct command_table_s));
4401 command_table[i]->name = name;
4402 command_table[i]->handler = handler;
4403 command_table[i]->ignore_startup = ignore;
4404 command_table[i]->unlock = unlock;
4405 command_table[i]->flock_type = flock_type;
4406 command_table[i++]->help = help;
4407 command_table[i] = NULL;
4410 void
4411 deinit_commands ()
4413 int i;
4415 for (i = 0; command_table[i]; i++)
4416 xfree (command_table[i]);
4418 xfree (command_table);
4421 static int
4422 sort_commands (const void *arg1, const void *arg2)
4424 struct command_table_s *const *a = arg1;
4425 struct command_table_s *const *b = arg2;
4427 if (!*a || !*b)
4428 return 0;
4429 else if (*a && !*b)
4430 return 1;
4431 else if (!*a && *b)
4432 return -1;
4434 return strcmp ((*a)->name, (*b)->name);
4437 static gpg_error_t
4438 passwd_command (assuan_context_t ctx, char *line)
4440 struct client_s *client = assuan_get_pointer (ctx);
4441 gpg_error_t rc;
4442 struct argv_s *args[] = {
4443 &(struct argv_s) {"reset", OPTION_TYPE_NOARG, parse_opt_reset},
4444 &(struct argv_s) {"s2k-count", OPTION_TYPE_ARG, parse_opt_s2k_count},
4445 &(struct argv_s) {"no-passphrase", OPTION_TYPE_NOARG, parse_opt_no_passphrase},
4446 NULL
4449 rc = peer_is_invoker (client);
4450 if (rc == GPG_ERR_EACCES)
4451 return send_error (ctx, rc);
4453 if (client->flags & FLAG_NEW)
4454 return send_error (ctx, GPG_ERR_INV_STATE);
4456 client->crypto->save.hdr.s2k_count =
4457 config_get_ulonglong (client->filename, "s2k_count");
4458 rc = parse_options (&line, args, client, 0);
4459 if (rc)
4460 return send_error (ctx, rc);
4462 if (!rc && client->opts & OPT_RESET)
4464 rc = cache_clear (client->md5file);
4465 if (!rc)
4466 send_status_all (STATUS_CACHE, NULL);
4469 if (!rc)
4471 if (!IS_PKI (client->crypto))
4473 struct crypto_s *crypto;
4475 xfree (client->crypto->filename);
4476 client->crypto->filename = str_dup (client->filename);
4477 rc = change_passwd (ctx, client->filename,
4478 client->flags & FLAG_NO_PINENTRY, &crypto,
4479 (client->opts & OPT_NO_PASSPHRASE));
4480 if (!rc)
4482 cleanup_crypto (&client->crypto);
4483 client->crypto = crypto;
4484 update_checksum (client);
4485 cleanup_crypto_stage1 (client->crypto);
4488 #ifdef WITH_AGENT
4489 else
4491 if (client->crypto->save.hdr.s2k_count)
4492 rc = send_to_agent (client->crypto->agent, NULL, NULL,
4493 "OPTION s2k-count=%lu",
4494 client->crypto->save.hdr.s2k_count);
4496 if (!rc)
4497 rc = agent_passwd (client->crypto);
4499 (void) kill_scd (client->crypto->agent);
4501 #endif
4504 return send_error (ctx, rc);
4507 static gpg_error_t
4508 parse_keygrip_opt_sign (void *data, void *value)
4510 struct client_s *client = data;
4512 (void) value;
4513 client->opts |= OPT_SIGN;
4514 return 0;
4517 static gpg_error_t
4518 keygrip_command (assuan_context_t ctx, char *line)
4520 struct client_s *client = assuan_get_pointer (ctx);
4521 gpg_error_t rc;
4522 struct crypto_s *crypto = NULL;
4523 struct argv_s *args[] = {
4524 &(struct argv_s) {"sign", OPTION_TYPE_NOARG, parse_keygrip_opt_sign},
4525 NULL
4528 if (!line || !*line)
4529 return send_error (ctx, GPG_ERR_SYNTAX);
4531 rc = parse_options (&line, args, client, 1);
4532 if (rc)
4533 return send_error (ctx, rc);
4535 if (!valid_filename (line))
4536 return send_error (ctx, GPG_ERR_INV_VALUE);
4538 rc = init_client_crypto (&crypto);
4539 if (rc)
4540 return send_error (ctx, rc);
4542 rc = read_data_file (line, crypto);
4543 if (!rc)
4545 char *hexgrip = NULL;
4547 if (!IS_PKI (crypto))
4549 cleanup_crypto (&crypto);
4550 return send_error (ctx, GPG_ERR_NOT_SUPPORTED);
4553 if (client->opts & OPT_SIGN)
4555 if (valid_keygrip (crypto->sign_grip, sizeof (crypto->sign_grip)))
4556 hexgrip = bin2hex (crypto->sign_grip, sizeof (crypto->sign_grip));
4559 if (!hexgrip)
4560 hexgrip = bin2hex (crypto->grip, sizeof (crypto->grip));
4562 if (!hexgrip)
4563 rc = GPG_ERR_ENOMEM;
4564 else
4565 rc = xfer_data (ctx, hexgrip, strlen (hexgrip));
4567 xfree (hexgrip);
4570 UPDATE_AGENT_CTX (client, crypto);
4571 cleanup_crypto (&crypto);
4572 return send_error (ctx, rc);
4575 static gpg_error_t
4576 parse_opt_data (void *data, void *value)
4578 struct client_s *client = data;
4580 (void) value;
4581 client->opts |= OPT_DATA;
4582 return 0;
4585 static gpg_error_t
4586 send_client_list (assuan_context_t ctx)
4588 struct client_s *client = assuan_get_pointer (ctx);
4589 gpg_error_t rc = 0;
4590 char buf[ASSUAN_LINELENGTH];
4592 if (client->opts & OPT_VERBOSE)
4594 unsigned i, t;
4595 char **list = NULL;
4596 char *line;
4598 MUTEX_LOCK (&cn_mutex);
4599 pthread_cleanup_push (cleanup_mutex_cb, &cn_mutex);
4600 t = slist_length (cn_thread_list);
4602 for (i = 0; i < t; i++)
4604 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
4605 char *tmp;
4607 if (thd->state == CLIENT_STATE_UNKNOWN)
4608 continue;
4610 tmp = build_client_info_line (thd, 0);
4611 if (tmp)
4613 char **l = strv_cat (list, tmp);
4614 if (!l)
4615 rc = GPG_ERR_ENOMEM;
4616 else
4617 list = l;
4619 else
4620 rc = GPG_ERR_ENOMEM;
4622 if (rc)
4624 strv_free (list);
4625 break;
4629 pthread_cleanup_pop (1);
4630 if (rc)
4631 return rc;
4633 line = strv_join ("\n", list);
4634 strv_free (list);
4635 pthread_cleanup_push (xfree, line);
4636 rc = xfer_data (ctx, line, strlen (line));
4637 pthread_cleanup_pop (1);
4638 return rc;
4641 if (client->opts & OPT_DATA)
4643 MUTEX_LOCK (&cn_mutex);
4644 pthread_cleanup_push (cleanup_mutex_cb, &cn_mutex);
4645 snprintf (buf, sizeof (buf), "%i", slist_length (cn_thread_list));
4646 pthread_cleanup_pop (1);
4647 rc = xfer_data (ctx, buf, strlen (buf));
4649 else
4650 rc = send_status (ctx, STATUS_CLIENTS, NULL);
4652 return rc;
4655 static gpg_error_t
4656 getinfo_command (assuan_context_t ctx, char *line)
4658 struct client_s *client = assuan_get_pointer (ctx);
4659 gpg_error_t rc;
4660 char buf[ASSUAN_LINELENGTH];
4661 struct argv_s *args[] = {
4662 &(struct argv_s) {"data", OPTION_TYPE_NOARG, parse_opt_data},
4663 &(struct argv_s) {"verbose", OPTION_TYPE_NOARG, parse_opt_verbose},
4664 NULL
4667 rc = parse_options (&line, args, client, 1);
4668 if (rc)
4669 return send_error (ctx, rc);
4671 if (!strcasecmp (line, "clients"))
4673 rc = send_client_list (ctx);
4675 else if (!strcasecmp (line, "cache"))
4677 if (client->opts & OPT_DATA)
4679 snprintf (buf, sizeof (buf), "%u", cache_file_count ());
4680 rc = xfer_data (ctx, buf, strlen (buf));
4682 else
4683 rc = send_status (ctx, STATUS_CACHE, NULL);
4685 else if (!strcasecmp (line, "pid"))
4687 char buf[32];
4688 pid_t pid = getpid ();
4690 snprintf (buf, sizeof (buf), "%i", pid);
4691 rc = xfer_data (ctx, buf, strlen (buf));
4693 else if (!strcasecmp (line, "version"))
4695 char *buf = str_asprintf ("0x%06x %s%s", VERSION_HEX,
4696 #ifdef WITH_LIBACL
4697 "ACL "
4698 #endif
4699 #ifdef WITH_GNUTLS
4700 "GNUTLS "
4701 #endif
4702 #ifdef WITH_QUALITY
4703 "QUALITY "
4704 #endif
4705 "", use_agent ? "AGENT" : "");
4706 rc = xfer_data (ctx, buf, strlen (buf));
4707 xfree (buf);
4709 else if (!strcasecmp (line, "last_error"))
4711 if (client->last_error)
4712 rc = xfer_data (ctx, client->last_error, strlen (client->last_error));
4713 else
4714 rc = GPG_ERR_NO_DATA;
4716 else if (!strcasecmp (line, "user"))
4718 char *user = NULL;
4720 #ifdef WITH_GNUTLS
4721 if (client->thd->remote)
4722 user = str_asprintf ("#%s", client->thd->tls->fp);
4723 else
4724 user = get_username (client->thd->peer->uid);
4725 #else
4726 user = get_username (client->thd->peer->uid);
4727 #endif
4728 if (user)
4730 pthread_cleanup_push (xfree, user);
4731 rc = xfer_data (ctx, user, strlen (user));
4732 pthread_cleanup_pop (1);
4734 else
4735 rc = GPG_ERR_NO_DATA;
4737 else
4738 rc = gpg_error (GPG_ERR_SYNTAX);
4740 return send_error (ctx, rc);
4743 #ifdef WITH_AGENT
4744 static gpg_error_t
4745 send_data_cb (void *user, const void *buf, size_t len)
4747 assuan_context_t ctx = user;
4749 return assuan_send_data (ctx, buf, len);
4752 static gpg_error_t
4753 send_status_cb (void *user, const char *line)
4755 assuan_context_t ctx = user;
4756 char keyword[200], *k;
4757 const char *p;
4759 for (p = line, k = keyword; *p; p++)
4761 if (isspace (*p))
4762 break;
4764 *k++ = *p;
4767 *k = 0;
4768 if (*p == '#')
4769 p++;
4771 while (isspace (*p))
4772 p++;
4774 return assuan_write_status (ctx, keyword, *p ? p : NULL);
4776 #endif
4778 static gpg_error_t
4779 kill_command (assuan_context_t ctx, char *line)
4781 struct client_s *client = assuan_get_pointer (ctx);
4782 gpg_error_t rc;
4783 unsigned i, t;
4785 if (!line || !*line)
4786 return send_error (ctx, GPG_ERR_SYNTAX);
4788 MUTEX_LOCK (&cn_mutex);
4789 pthread_cleanup_push (cleanup_mutex_cb, &cn_mutex);
4790 t = slist_length (cn_thread_list);
4791 rc = GPG_ERR_ESRCH;
4793 for (i = 0; i < t; i++)
4795 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
4796 char *tmp = str_asprintf ("%p", thd->tid);
4798 if (strcmp (line, tmp))
4800 xfree (tmp);
4801 continue;
4804 xfree (tmp);
4805 rc = peer_is_invoker (client);
4806 if (!rc)
4808 #ifdef HAVE_PTHREAD_CANCEL
4809 rc = pthread_cancel (thd->tid);
4810 #else
4811 close (thd->fd);
4812 thd->fd = -1;
4813 #endif
4814 break;
4817 rc = GPG_ERR_EACCES;
4818 if (config_get_boolean ("global", "strict_kill"))
4819 break;
4821 #ifdef WITH_GNUTLS
4822 if (client->thd->remote && thd->remote)
4824 if (!strcmp (client->thd->tls->fp, thd->tls->fp))
4826 #ifdef HAVE_PTHREAD_CANCEL
4827 rc = pthread_cancel (thd->tid);
4828 #else
4829 close (thd->fd);
4830 thd->fd = -1;
4831 #endif
4832 break;
4835 else if (!client->thd->remote && !thd->remote)
4836 #endif
4838 if (client->thd->peer->uid == thd->peer->uid)
4840 #ifdef HAVE_PTHREAD_CANCEL
4841 rc = pthread_cancel (thd->tid);
4842 #else
4843 close (thd->fd);
4844 thd->fd = -1;
4845 #endif
4848 break;
4851 pthread_cleanup_pop (1);
4852 return send_error (ctx, rc);
4855 static gpg_error_t
4856 agent_command (assuan_context_t ctx, char *line)
4858 gpg_error_t rc = 0;
4860 if (!use_agent)
4861 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
4863 #ifdef WITH_AGENT
4864 struct client_s *client = assuan_get_pointer (ctx);
4866 if (!line || !*line)
4867 return send_error (ctx, GPG_ERR_SYNTAX);
4869 assuan_set_flag (client->crypto->agent->ctx, ASSUAN_CONVEY_COMMENTS, 1);
4870 rc = assuan_transact (client->crypto->agent->ctx, line, send_data_cb,
4871 client->ctx, agent_loopback_cb, client->crypto,
4872 send_status_cb, client->ctx);
4873 if (gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
4875 char *line;
4876 size_t len;
4878 rc = assuan_write_line (client->crypto->agent->ctx, "CAN");
4879 if (!rc)
4881 rc = assuan_read_line (client->crypto->agent->ctx, &line, &len);
4882 if (!rc)
4883 rc = gpg_error (GPG_ERR_ASS_CANCELED);
4887 assuan_set_flag (client->crypto->agent->ctx, ASSUAN_CONVEY_COMMENTS, 0);
4888 #endif
4889 return send_error (ctx, rc);
4892 void
4893 init_commands ()
4895 /* !BEGIN-HELP-TEXT!
4897 * This comment is used as a marker to generate the offline documentation
4898 * found in doc/pwmd.info. The indentation needs to be kept for the awk
4899 * script to determine where commands begin and end.
4901 new_command("HELP", 1, 1, 0, help_command, _(
4902 "HELP [<COMMAND>]\n"
4903 "Show available commands or command specific help text."
4906 new_command("AGENT", 1, 1, 0, agent_command, _(
4907 "AGENT <command>\n"
4908 "Send a @command{gpg-agent} protocol @var{command} directly to the "
4909 "@command{gpg-agent}."
4912 new_command("KILL", 1, 0, 0, kill_command, _(
4913 "KILL <thread_id>\n"
4914 "Terminates the client identified by @var{thread_id} and releases any file "
4915 "lock or other resources it has held. See @code{GETINFO} (@pxref{GETINFO}) "
4916 "for details about listing connected clients. The @code{invoking_user} "
4917 "(@pxref{Configuration}) may kill any client while others may only kill "
4918 "clients of the same @code{UID} or @abbr{TLS} fingerprint.\n"
4921 new_command("GETINFO", 1, 1, 0, getinfo_command, _(
4922 "GETINFO [--data] [--verbose] CACHE | CLIENTS | PID | USER | LAST_ERROR | VERSION\n"
4923 "Get server and other information: @var{CACHE} returns the number of cached "
4924 "documents via a status message. @var{CLIENTS} returns the number of "
4925 "connected clients via a status message or a list of connected clients when "
4926 "the @option{--verbose} parameter is used. The list contains space delimited "
4927 "fields: the thread ID, client name, opened file (@code{/} if none opened), "
4928 "file lock status, whether the current client is self, client state, "
4929 "user ID or TLS fingerprint of the connected client and username if the "
4930 "client is a local one. "
4931 "Client state @code{0} is an unknown client state, @code{1} indicates the "
4932 "client has connected but hasn't completed initializing, @code{2} indicates "
4933 "that the client is idle, @code{3} means the "
4934 "client is in a command and @code{4} means the client is disconnecting. This "
4935 "line is always returned with a data response. @var{PID} returns the process "
4936 "ID number of the server via a data response. @var{VERSION} returns the server "
4937 "version number and compile-time features with a data response with each "
4938 "being space delimited. @var{LAST_ERROR} returns a detailed description of "
4939 "the last failed command when available. @var{USER} returns the username or "
4940 "@abbr{TLS} hash of the connected client. @xref{Status Messages}. "
4941 "\n"
4942 "When the @option{--data} option is specified then the result will be sent "
4943 "via a data response rather than a status message."
4946 new_command("PASSWD", 0, 0, FLOCK_TYPE_EX|FLOCK_TYPE_KEEP, passwd_command, _(
4947 "PASSWD [--reset] [--s2k-count=N] [--no-passphrase]\n"
4948 "Changes the passphrase of the secret key required to open the current "
4949 "file or the passphrase of a symmetrically encrypted data file. When the "
4950 "@option{--reset} option is passed then the cache entry for the current "
4951 "file will be reset and the passphrase, if any, will be required during the "
4952 "next @code{OPEN} (@pxref{OPEN})."
4953 "\n"
4954 "The @option{--s2k-count} option sets or changes (@pxref{SAVE}) the number "
4955 "of hash iterations for a passphrase and must be either @code{0} to use "
4956 "the calibrated count of the machine (the default), or a value greater than "
4957 "or equal to @code{65536}. This option has no effect for symmetrically "
4958 "encrypted data files."
4959 "\n"
4960 "The @option{--no-passphrase} option will prevent requiring a passphrase for "
4961 "the data file, although a passphrase may be required when changing it."
4962 "\n"
4963 "This command is not available for non-invoking clients "
4964 "(@pxref{Access Control})."
4967 new_command("KEYGRIP", 1, 1, FLOCK_TYPE_SH|FLOCK_TYPE_KEEP, keygrip_command, _(
4968 "KEYGRIP [--sign] <filename>\n"
4969 "Returns the hex encoded keygrip of the specified @var{filename} with a "
4970 "data response."
4971 "\n"
4972 "When the @option{--sign} option is specified then the key used for signing "
4973 "of the specified @var{filename} will be returned."
4974 "\n"
4975 "For symmetrically encrypted data files this command returns the error "
4976 "GPG_ERR_NOT_SUPPORTED."
4979 new_command("OPEN", 1, 1, FLOCK_TYPE_SH|FLOCK_TYPE_KEEP, open_command, _(
4980 "OPEN [--lock] <filename> [<passphrase>]\n"
4981 "Opens @var{filename} using @var{passphrase}. When the filename is not "
4982 "found on the file-system then a new document will be created. If the file "
4983 "is found, it is looked for in the file cache. If cached and no "
4984 "@var{passphrase} was specified then the cached document is opened. When not "
4985 "cached, @cite{pinentry(1)} will be used to retrieve the passphrase to use "
4986 "for decryption unless @option{disable-pinentry} (@pxref{OPTION}) was "
4987 "specified."
4988 "\n"
4989 "When the @option{--lock} option is passed then the file mutex will be "
4990 "locked as if the @code{LOCK} command (@pxref{LOCK}) had been sent after the "
4991 "file has been opened."
4994 new_command("SAVE", 0, 0, FLOCK_TYPE_EX|FLOCK_TYPE_KEEP, save_command, _(
4995 "SAVE [--no-passphrase] [--reset] [--ask] [--no-agent] [--s2k-count=N] [--cipher=<algo>] [--cipher-iterations=N] [--inquire-keyparam] [--keygrip=hexstring] [--sign-keygrip=hexstring]\n"
4996 "Writes the @abbr{XML} document to disk. The file written to is the file that "
4997 "was opened using the @code{OPEN} command (@pxref{OPEN}). If the file is a "
4998 "new one or the option @option{--inquire-keyparam} was passed, then a new "
4999 "keypair will be generated and a pinentry will be used to prompt for the "
5000 "passphrase to encrypt with unless the @option{--no-passphrase} option was "
5001 "passed in which case the data file will not be passphrase protected. "
5002 "\n"
5003 "The @option{--no-agent} option disables use of @command{gpg-agent} for "
5004 "passphrase retrieval and caching of new files when @command{gpg-agent} "
5005 "use is enabled. The datafile will be symmetrically encrypted and will not "
5006 "use or generate any keypair."
5007 "\n"
5008 "The @option{--reset} option will clear the cache entry for the current file "
5009 "and require a passphrase, if needed, before saving."
5010 "\n"
5011 "The @option{--ask} option will prompt for the passphrase of the current file, "
5012 "if needed, before saving. This differs from the @option{--reset} option by "
5013 "keeping the cache entry in case of an invalid passphrase or some other failure "
5014 "which may otherwise cause a denial of service for other clients."
5015 "\n"
5016 "The @option{--cipher} option can be used to encrypt the @abbr{XML} data to "
5017 "an alternate cipher. The default is @code{aes256}. See the Configuration "
5018 "(@pxref{Configuration}) for available ciphers."
5019 "\n"
5020 "The @option{--cipher-iterations} option specifies the number of times to "
5021 "hash the passphrase before encrypting the XML data. The default is "
5022 "@code{5000000}. This option is an alias for @option{--s2k-count} since "
5023 "version @var{3.0.15} of @command{pwmd}."
5024 "\n"
5025 "The @option{--inquire-keyparam} option will send a server @emph{INQUIRE} to "
5026 "the client to obtain the key paramaters to use when generating a new "
5027 "keypair. The inquired data is expected to be an S-expression. If not "
5028 "specified then an @samp{RSA} key of @samp{2048} bits will be generated "
5029 "unless otherwise set in the configuration file (@pxref{Configuration}). Note "
5030 "that when this option is specified a new keypair will be generated "
5031 "reguardless if the file is a new one and that if the data file is protected "
5032 "the passphrase to open it will be required before generating the new "
5033 "keypair. This option is not available for non-invoking clients "
5034 "(@pxref{Access Control})."
5035 "\n"
5036 "You can encrypt the data file to a public key other than the one that it "
5037 "was originally encrypted with by passing the @option{--keygrip} option with "
5038 "the hex encoded keygrip of the public key as its argument. The keygrip may "
5039 "be of any key that @command{gpg-agent} knows about. The "
5040 "@option{--sign-keygrip} option may also be used to sign with an alternate "
5041 "secret key. Use the @code{KEYGRIP} (@pxref{KEYGRIP}) command to obtain the "
5042 "keygrip of an existing data file. This option may be needed when using a "
5043 "smartcard. This option has no effect with symmetrically encrypted data "
5044 "files. These options are not available for non-invoking clients "
5045 "(@pxref{Access Control})."
5046 "\n"
5047 "The @option{--s2k-count} option sets number of hash iterations for a "
5048 "passphrase. A value less-than @code{65536} will use the machine calibrated "
5049 "value and is the default when using @command{gpg-agent}. This setting only "
5050 "affects new files when using @command{gpg-agent}. To change the setting use "
5051 "the @code{PASSWD} command (@pxref{PASSWD}). This option is an alias for "
5052 "option @option{--cipher-iterations} when not using @command{gpg-agent}."
5055 new_command("ISCACHED", 1, 0, 0, iscached_command, _(
5056 "ISCACHED [--lock] <filename>\n"
5057 "An @emph{OK} response is returned if the specified @var{filename} is found "
5058 "in the file cache. If not found in the cache but exists on the filesystem "
5059 "then @var{GPG_ERR_NO_DATA} is returned. Otherwise a filesystem error is "
5060 "returned."
5061 "\n"
5062 "The @option{lock} option will lock the file mutex of @var{filename} when the "
5063 "file exists; it does not need to be opened nor cached. The lock will be "
5064 "released when the client exits or sends the @code{UNLOCK} (@pxref{UNLOCK}) "
5065 "command."
5068 new_command("CLEARCACHE", 1, 1, 0, clearcache_command, _(
5069 "CLEARCACHE [<filename>]\n"
5070 "Clears a file cache entry for all or the specified @var{filename}."
5073 new_command("CACHETIMEOUT", 1, 1, 0, cachetimeout_command, _(
5074 "CACHETIMEOUT <filename> <seconds>\n"
5075 "The time in @var{seconds} until @var{filename} will be removed from the "
5076 "cache. @code{-1} will keep the cache entry forever, @code{0} will require "
5077 "the passphrase for each @code{OPEN} or @code{SAVE} command (@pxref{OPEN}, "
5078 "@pxref{SAVE}). @xref{Configuration}, and the @code{cache_timeout} "
5079 "parameter."
5082 new_command("LIST", 0, 1, 0, list_command, _(
5083 "LIST [--inquire] [--no-recurse] [--verbose] [--with-target] [--all] [[!]element[<TAB>[!]child[..]]]\n"
5084 "If no element path is given then a newline separated list of root elements "
5085 "is returned with a data response. If given, then all reachable elements "
5086 "of the specified element path are returned unless the @option{--no-recurse} "
5087 "option is specified. If specified, only the child elements of the element "
5088 "path are returned without recursing into grandchildren. Each resulting "
5089 "element is prefixed with the literal @code{!} character when the element "
5090 "contains no @code{target} attribute. @xref{Target Attribute}, for details."
5091 "\n"
5092 "When the @option{--verbose} option is passed then each element path "
5093 "returned will have zero or more flags appened to it. These flags are "
5094 "delimited from the element path by a single space character. A flag itself "
5095 "is a single character. Flag @code{P} indicates that access to the element "
5096 "is denied. Flag @code{+} indicates that there are child nodes of "
5097 "the current element path. Flag @code{E} indicates that an element of an "
5098 "element path contained in a @var{target} attribute could not be found. Flag "
5099 "@code{O} indicates that a @var{target} attribute recursion limit was reached "
5100 "(@pxref{Configuration}). Flag @code{T} will append the resolved element path "
5101 "of the @var{target} attribute contained in the current element (see below)."
5102 "\n"
5103 "The @option{--with-target} option implies @option{--verbose} and will append "
5104 "an additional flag @code{T} followed by a single space then an element path. "
5105 "The appended element path is the resolved path (@pxref{REALPATH}) of the "
5106 "current element when it contains a @var{target} attribute. When no "
5107 "@var{target} attribute is found then no flag will be appended."
5108 "\n"
5109 "The @option{--no-recurse} option limits the amount of data returned to only "
5110 "the listing of children of the specified element path and not any "
5111 "grandchildren."
5112 "\n"
5113 "The @option{--all} option lists the entire element tree for each root "
5114 "element. This option also implies option @option{--verbose}."
5115 "\n"
5116 "When the @option{--inquire} option is passed then all remaining non-option "
5117 "arguments are retrieved via a server @emph{INQUIRE}."
5120 new_command("REALPATH", 0, 1, 0, realpath_command, _(
5121 "REALPATH [--inquire] [!]element[<TAB>[!]child[..]]\n"
5122 "Resolves all @code{target} attributes of the specified element path and "
5123 "returns the result with a data response. @xref{Target Attribute}, for details."
5124 "\n"
5125 "When the @option{--inquire} option is passed then all remaining non-option "
5126 "arguments are retrieved via a server @emph{INQUIRE}."
5129 new_command("STORE", 0, 1, 0, store_command, _(
5130 "STORE [!]element[<TAB>[!]child[..]]<TAB>[content]\n"
5131 "This command uses a server @emph{INQUIRE} to retrieve data from the client."
5132 "\n"
5133 "Creates a new element path or modifies the @var{content} of an existing "
5134 "element. If only a single element is specified then a new root element is "
5135 "created. Otherwise, elements are @key{TAB} delimited and the content will be "
5136 "set to the final @key{TAB} delimited element. If no @var{content} is "
5137 "specified after the final @key{TAB}, then the content of an existing "
5138 "element will be removed; or empty when creating a new element."
5139 "\n"
5140 "The only restriction of an element name is that it not contain whitespace "
5141 "or begin with the literal element character @code{!} unless specifying a "
5142 "literal element (@pxref{Target Attribute}). There is no whitespace between "
5143 "the @key{TAB} delimited elements. It is recommended that the content of an "
5144 "element be base64 encoded when it contains control or @key{TAB} characters "
5145 "to prevent @abbr{XML} parsing and @command{pwmd} syntax errors."
5148 new_command("RENAME", 0, 1, 0, rename_command, _(
5149 "RENAME [--inquire] [!]element[<TAB>[!]child[..]] <value>\n"
5150 "Renames the specified @var{element} to the new @var{value}. If an element of "
5151 "the same name as the @var{value} already exists it will be overwritten."
5152 "\n"
5153 "When the @option{--inquire} option is passed then all remaining non-option "
5154 "arguments are retrieved via a server @emph{INQUIRE}."
5157 new_command("COPY", 0, 1, 0, copy_command, _(
5158 "COPY [--inquire] [!]source[<TAB>[!]child[..]] [!]dest[<TAB>[!]child[..]]\n"
5159 "Copies the entire element tree starting from the child node of the source "
5160 "element, to the destination element path. If the destination element path "
5161 "does not exist then it will be created; otherwise it is overwritten."
5162 "\n"
5163 "Note that attributes from the source element are merged into the "
5164 "destination element when the destination element path exists. When an "
5165 "attribute of the same name exists in both the source and destination "
5166 "elements then the destination attribute will be updated to the source "
5167 "attribute value."
5168 "\n"
5169 "When the @option{--inquire} option is passed then all remaining non-option "
5170 "arguments are retrieved via a server @emph{INQUIRE}."
5173 new_command("MOVE", 0, 1, 0, move_command, _(
5174 "MOVE [--inquire] [!]source[<TAB>[!]child[..]] [[!]dest[<TAB>[!]child[..]]]\n"
5175 "Moves the source element path to the destination element path. If the "
5176 "destination is not specified then it will be moved to the root node of the "
5177 "document. If the destination is specified and exists then it will be "
5178 "overwritten; otherwise non-existing elements of the destination element "
5179 "path will be created."
5180 "\n"
5181 "When the @option{--inquire} option is passed then all remaining non-option "
5182 "arguments are retrieved via a server @emph{INQUIRE}."
5185 new_command("DELETE", 0, 1, 0, delete_command, _(
5186 "DELETE [--inquire] [!]element[<TAB>[!]child[..]]\n"
5187 "Removes the specified element path and all of its children. This may break "
5188 "an element with a @code{target} attribute (@pxref{Target Attribute}) that "
5189 "refers to this element or any of its children."
5190 "\n"
5191 "When the @option{--inquire} option is passed then all remaining non-option "
5192 "arguments are retrieved via a server @emph{INQUIRE}."
5195 new_command("GET", 0, 1, 0, get_command, _(
5196 "GET [--inquire] [!]element[<TAB>[!]child[..]]\n"
5197 "Retrieves the content of the specified element. The content is returned "
5198 "with a data response."
5199 "\n"
5200 "When the @option{--inquire} option is passed then all remaining non-option "
5201 "arguments are retrieved via a server @emph{INQUIRE}."
5204 new_command("ATTR", 0, 1, 0, attr_command, _(
5205 "ATTR [--inquire] SET|GET|DELETE|LIST [<attribute>] [!]element[<TAB>[!]child[..]] ..\n"
5206 "@table @asis\n"
5207 "@item ATTR SET attribute [!]element[<TAB>[!]child[..]] [value]\n"
5208 "\n"
5209 " Stores or updates an @var{attribute} name and optional @var{value} of an "
5210 "element. When no @var{value} is specified any existing value will be removed."
5211 "\n"
5212 "@item ATTR DELETE attribute [!]element[<TAB>[!]child[..]]\n"
5213 "\n"
5214 " Removes an @var{attribute} from an element."
5215 "\n"
5216 "@item ATTR LIST [!]element[<TAB>[!]child[..]]\n"
5217 "\n"
5218 " Retrieves a newline separated list of attributes names and values "
5219 "from the specified element. Each attribute name and value is space delimited."
5220 "\n"
5221 "@item ATTR GET attribute [!]element[<TAB>[!]child[..]]\n"
5222 "\n"
5223 " Retrieves the value of an @var{attribute} from an element."
5224 "@end table\n"
5225 "\n"
5226 "The @code{_name} attribute (case sensitive) cannot be removed nor modified. "
5227 "Use the @code{DELETE} (@pxref{DELETE}) or @code{RENAME} (@pxref{RENAME}) "
5228 "commands instead."
5229 "\n"
5230 "The @code{_mtime} attribute is updated each time an element is modified by "
5231 "either storing content, editing attributes or by deleting a child element. "
5232 "The @code{_ctime} attribute is created for each new element in an element "
5233 "path."
5234 "\n"
5235 "When the @option{--inquire} option is passed then all remaining non-option "
5236 "arguments are retrieved via a server @emph{INQUIRE}."
5237 "\n"
5238 "@xref{Target Attribute}, for details about this special attribute."
5241 new_command("XPATH", 0, 1, 0, xpath_command, _(
5242 "XPATH [--inquire] <expression>[<TAB>[value]]\n"
5243 "Evaluates an XPath @var{expression}. If no @var{value} argument is "
5244 "specified it is assumed the expression is a request to return a result. "
5245 "Otherwise, the result is set to the @var{value} argument and the document is "
5246 "updated. If there is no @var{value} after the @key{TAB} character, the value "
5247 "is assumed to be empty and the document is updated. For example:"
5248 "@sp 1\n"
5249 "@example\n"
5250 "XPATH //element[@@_name='password']@key{TAB}\n"
5251 "@end example\n"
5252 "@sp 1"
5253 "would clear the content of all @code{password} elements in the data file "
5254 "while leaving off the trailing @key{TAB} would return all @code{password} "
5255 "elements in @abbr{XML} format."
5256 "\n"
5257 "When the @option{--inquire} option is passed then all remaining non-option "
5258 "arguments are retrieved via a server @emph{INQUIRE}."
5259 "\n"
5260 "See @url{http://www.w3schools.com/xpath/xpath_syntax.asp} for @abbr{XPATH} "
5261 "expression syntax."
5264 new_command("XPATHATTR", 0, 1, 0, xpathattr_command, _(
5265 "XPATHATTR [--inquire] SET|DELETE <name> <expression>[<TAB>[<value>]]\n"
5266 "Like the @code{XPATH} command (@pxref{XPATH}) but operates on element "
5267 "attributes and does not return a result. For the @var{SET} operation the "
5268 "@var{value} is optional but the field is required. If not specified then "
5269 "the attribute value will be empty. For example:"
5270 "@sp 1"
5271 "@example\n"
5272 "XPATHATTR SET password //element[@@_name='password']@key{TAB}\n"
5273 "@end example\n"
5274 "@sp 1"
5275 "would create an @code{password} attribute for each @code{password} element "
5276 "found in the document. The attribute value will be empty but still exist."
5277 "\n"
5278 "When the @option{--inquire} option is passed then all remaining non-option "
5279 "arguments are retrieved via a server @emph{INQUIRE}."
5280 "\n"
5281 "See @url{http://www.w3schools.com/xpath/xpath_syntax.asp} for @abbr{XPATH} "
5282 "expression syntax."
5285 new_command("IMPORT", 0, 1, 0, import_command, _(
5286 "IMPORT [--root=[!]element[<TAB>[!]child[..]]] <content>\n"
5287 "This command uses a server @emph{INQUIRE} to retrieve data from the client."
5288 "\n"
5289 "Like the @code{STORE} command (@pxref{STORE}), but the @var{content} "
5290 "argument is raw @abbr{XML} data. The content is created as a child of "
5291 "the element path specified with the @option{--root} option or at the "
5292 "document root when not specified. Existing elements of the same name will "
5293 "be overwritten."
5294 "\n"
5295 "The content must begin with an @abbr{XML} element node. @xref{Introduction}, "
5296 "for details."
5299 new_command("DUMP", 0, 1, 0, dump_command, _(
5300 "DUMP\n"
5301 "Shows the in memory @abbr{XML} document with indenting. @xref{XPATH}, for "
5302 "dumping a specific node."
5305 new_command("LOCK", 0, 0, 0, lock_command, _(
5306 "LOCK\n"
5307 "Locks the mutex associated with the opened file. This prevents other clients "
5308 "from sending commands to the same opened file until the client "
5309 "that sent this command either disconnects or sends the @code{UNLOCK} "
5310 "command. @xref{UNLOCK}."
5313 new_command("UNLOCK", 1, 0, 0, unlock_command, _(
5314 "UNLOCK\n"
5315 "Unlocks the file mutex which was locked with the @code{LOCK} command or "
5316 "a commands' @option{--lock} option (@pxref{LOCK}, @pxref{OPEN}, "
5317 "@pxref{ISCACHED})."
5320 new_command("GETCONFIG", 1, 1, FLOCK_TYPE_SH|FLOCK_TYPE_KEEP, getconfig_command, _(
5321 "GETCONFIG [filename] <parameter>\n"
5322 "Returns the value of a @command{pwmd} configuration @var{parameter} with a "
5323 "data response. If no file has been opened then the value for @var{filename} "
5324 "or the default from the @samp{global} section will be returned. If a file "
5325 "has been opened and no @var{filename} is specified, a value previously "
5326 "set with the @code{OPTION} command (@pxref{OPTION}) will be returned."
5329 new_command("OPTION", 1, 1, 0, option_command, _(
5330 "OPTION <NAME>=<VALUE>\n"
5331 "Sets a client option @var{name} to @var{value}. The value for an option is "
5332 "kept for the duration of the connection."
5333 "\n"
5334 "@table @asis\n"
5335 "@item DISABLE-PINENTRY\n"
5336 "Disable use of @command{pinentry} for passphrase retrieval. When set, a "
5337 "server inquire is sent to the client to obtain the passphrase. This option "
5338 "may be set as needed before the @code{OPEN} (@pxref{OPEN}), @code{PASSWD} "
5339 "(@pxref{PASSWD}) and @code{SAVE} (@pxref{SAVE}) commands."
5340 "\n"
5341 "@item PINENTRY-TIMEOUT\n"
5342 "Sets the number of seconds before a pinentry prompt will return an error "
5343 "while waiting for user input."
5344 "\n"
5345 "@item TTYNAME\n"
5346 "Passed to the @command{gpg-agent} and used for the @command{pinentry} dialog."
5347 "\n"
5348 "@item TTYTYPE\n"
5349 "Passed to the @command{gpg-agent} and used for the @command{pinentry} dialog."
5350 "\n"
5351 "@item DISPLAY\n"
5352 "Passed to the @command{gpg-agent} and used for the @command{pinentry} dialog."
5353 "\n"
5354 "@item PINENTRY-DESC\n"
5355 "Sets the description string of the @command{gpg-agent} and @command{pinentry} dialog."
5356 "\n"
5357 "@item PINENTRY-TITLE\n"
5358 "Sets the title string of the @command{gpg-agent} and @command{pinentry} dialog."
5359 "\n"
5360 "@item PINENTRY-PROMPT\n"
5361 "Sets the prompt string of the @command{gpg-agent} and @command{pinentry} dialog."
5362 "\n"
5363 "@item LC-CTYPE\n"
5364 "Passed to the @command{gpg-agent} and used for the @command{pinentry} dialog."
5365 "\n"
5366 "@item LC-MESSAGES\n"
5367 "Passed to the @command{gpg-agent} and used for the @command{pinentry} dialog."
5368 "\n"
5369 "@item NAME\n"
5370 "Associates the thread ID of the connection with the specified textual "
5371 "representation. Useful for debugging log messages. May not contain whitespace."
5372 "\n"
5373 "@item LOCK-TIMEOUT\n"
5374 "When not @code{0}, the duration in tenths of a second to wait for the file "
5375 "mutex which has been locked by another thread to be released before returning "
5376 "an error. When @code{-1}, then an error will be returned immediately."
5377 "@end table\n"
5380 new_command("LS", 1, 1, 0, ls_command, _(
5381 "LS\n"
5382 "Lists the available data files stored in the data directory "
5383 "(@file{~/.pwmd/data}). The result is a newline separated list of filenames."
5386 new_command("RESET", 1, 1, 0, NULL, _(
5387 "RESET\n"
5388 "Closes the currently opened file but keeps any previously set client options."
5391 new_command("NOP", 1, 1, 0, NULL, _(
5392 "NOP\n"
5393 "Does nothing. Always returns successfully."
5396 /* !END-HELP-TEXT! */
5397 new_command ("CANCEL", 1, 1, 0, NULL, NULL);
5398 new_command ("END", 1, 1, 0, NULL, NULL);
5399 new_command ("BYE", 1, 1, 0, NULL, NULL);
5401 int i;
5402 for (i = 0; command_table[i]; i++);
5403 qsort (command_table, i - 1, sizeof (struct command_table_s *),
5404 sort_commands);
5407 gpg_error_t
5408 register_commands (assuan_context_t ctx)
5410 int i = 0, rc;
5412 for (; command_table[i]; i++)
5414 if (!command_table[i]->handler)
5415 continue;
5417 rc = assuan_register_command (ctx, command_table[i]->name,
5418 command_table[i]->handler,
5419 command_table[i]->help);
5420 if (rc)
5421 return rc;
5424 rc = assuan_register_bye_notify (ctx, bye_notify);
5425 if (rc)
5426 return rc;
5428 rc = assuan_register_reset_notify (ctx, reset_notify);
5429 if (rc)
5430 return rc;
5432 rc = assuan_register_pre_cmd_notify (ctx, command_startup);
5433 if (rc)
5434 return rc;
5436 return assuan_register_post_cmd_notify (ctx, command_finalize);