BULK: Update documentation.
[pwmd.git] / src / commands.c
blobd64d635218051b9d75fa55799a9361fda8ce2e97
1 /*
2 Copyright (C) 2006-2018 Ben Kibbey <bjk@luxsci.net>
4 This file is part of pwmd.
6 Pwmd is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
11 Pwmd is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <err.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <ctype.h>
32 #include <dirent.h>
33 #include <pthread.h>
34 #include <stdint.h>
35 #include <assert.h>
36 #include <signal.h>
38 #include "pwmd-error.h"
39 #include <gcrypt.h>
41 #include "mem.h"
42 #include "xml.h"
43 #include "util-misc.h"
44 #include "common.h"
45 #include "rcfile.h"
46 #include "cache.h"
47 #include "commands.h"
48 #include "mutex.h"
49 #include "crypto.h"
50 #include "acl.h"
52 /* These are command option flags. */
53 #define OPT_INQUIRE 0x0001
54 #define OPT_NO_PASSPHRASE 0x0002
55 #define OPT_ASK 0x0004
56 #define OPT_LIST_RECURSE 0x0008
57 #define OPT_VERBOSE 0x0010
58 #define OPT_LOCK 0x0020
59 #define OPT_LOCK_ON_OPEN 0x0040
60 #define OPT_SIGN 0x0080
61 #define OPT_LIST_ALL 0x0100
62 #define OPT_DATA 0x0200
63 #define OPT_NO_AGENT 0x0400
64 #define OPT_SECRET 0x0800
65 #define OPT_INQUIRE_KEYID 0x1000
66 #define OPT_SYMMETRIC 0x4000
67 #define OPT_NO_SIGNER 0x8000
68 #define OPT_HTML 0x10000
69 #define OPT_CACHE_AGENT 0x20000
70 #define OPT_CACHE_SIGN 0x40000
71 #define OPT_KEYINFO_LEARN 0x80000
73 #define FLOCK_TYPE_NONE 0
74 #define FLOCK_TYPE_SH 0x0001
75 #define FLOCK_TYPE_EX 0x0002
76 #define FLOCK_TYPE_KEEP 0x0004
78 static char env_display[256];
79 static char env_gpg_tty[256];
80 static char env_term[256];
81 static struct command_table_s **command_table;
83 static gpg_error_t do_lock (struct client_s *client, int add);
84 static gpg_error_t validate_checksum (struct client_s *, const char *filename,
85 struct cache_data_s *, unsigned char **,
86 size_t *, int);
87 static gpg_error_t update_checksum (struct client_s *client,
88 unsigned char *from_crc, size_t crclen);
89 static gpg_error_t command_startup (assuan_context_t ctx, const char *name);
90 static void command_finalize (assuan_context_t ctx, gpg_error_t rc);
92 /* When 'status' is true the 'self' field of the status line will be false
93 * because we never send the STATE status message to the same client that
94 * initiated it. */
95 static char *
96 build_client_info_line (struct client_thread_s *thd, int status)
98 char *uid, *username = NULL;
99 char *line;
101 #ifdef WITH_GNUTLS
102 if (thd->remote)
103 uid = str_asprintf("#%s", thd->tls->fp);
104 else
106 uid = str_asprintf("%u", thd->peer->uid);
107 username = get_username (thd->peer->uid);
109 #else
110 uid = str_asprintf("%u", thd->peer->uid);
111 username = get_username (thd->peer->uid);
112 #endif
113 line = str_asprintf ("%p %s %s %s %u %u %u %s %s %u",
114 thd->tid,
115 thd->name ? thd->name : "-",
116 thd->cl && thd->cl->filename
117 && (thd->cl->flags & FLAG_OPEN)
118 ? thd->cl->filename : "/",
119 #ifdef WITH_GNUTLS
120 thd->remote ? thd->peeraddr : "-",
121 #else
122 "-",
123 #endif
124 thd->cl && thd->cl->flags & FLAG_HAS_LOCK ? 1 : 0,
125 !status && pthread_equal (pthread_self (), thd->tid) ? 1 : 0,
126 thd->state, uid,
127 #ifdef WITH_GNUTLS
128 thd->remote ? "-" : username,
129 #else
130 username,
131 #endif
132 thd->conntime
135 xfree (username);
136 xfree (uid);
137 return line;
140 void
141 update_client_state (struct client_s *client, unsigned s)
143 MUTEX_LOCK (&cn_mutex);
144 client->thd->state = s;
145 MUTEX_UNLOCK (&cn_mutex);
147 if (client->thd->state != CLIENT_STATE_UNKNOWN)
149 char *line = build_client_info_line (client->thd, 1);
151 pthread_cleanup_push (xfree, line);
152 if (line)
153 send_status_all_not_self (STATUS_STATE, "%s", line);
154 pthread_cleanup_pop (1);
158 static gpg_error_t
159 unlock_file_mutex (struct client_s *client, int remove)
161 gpg_error_t rc = 0;
163 // OPEN: keep the lock for the same file being reopened.
164 if (client->flags & FLAG_KEEP_LOCK && client->flags & FLAG_HAS_LOCK)
165 return 0;
167 if (!(client->flags & FLAG_HAS_LOCK))
168 return GPG_ERR_NOT_LOCKED;
170 rc = cache_unlock_mutex (client->filename, remove);
171 if (rc)
172 rc = GPG_ERR_INV_STATE;
173 else
174 client->flags &= ~(FLAG_HAS_LOCK | FLAG_LOCK_CMD);
176 return rc;
179 static gpg_error_t
180 lock_file_mutex (struct client_s *client, int add)
182 gpg_error_t rc = 0;
183 long timeout = config_get_long (client->filename, "cache_timeout");
185 if (client->flags & FLAG_HAS_LOCK)
186 return 0;
188 rc = cache_lock_mutex (client->ctx, client->filename,
189 client->lock_timeout, add, timeout);
190 if (!rc)
191 client->flags |= FLAG_HAS_LOCK;
193 return rc;
196 static gpg_error_t
197 file_modified (struct client_s *client, struct command_table_s *cmd)
199 gpg_error_t rc = 0;
200 int type = !cmd->flock_type || (cmd->flock_type & FLOCK_TYPE_SH)
201 ? LOCK_SH : LOCK_EX;
203 if (!(client->flags & FLAG_OPEN))
204 return GPG_ERR_INV_STATE;
206 rc = lock_file_mutex (client, 0);
207 if (rc && rc != GPG_ERR_NO_DATA)
208 return rc;
210 rc = lock_flock (client->ctx, client->filename, type, &client->flock_fd);
211 if (!rc)
213 rc = validate_checksum (client, client->filename, NULL, NULL, NULL, 0);
214 if (gpg_err_code (rc) == GPG_ERR_ENOENT && (client->flags & FLAG_NEW))
215 rc = 0;
216 else if (rc)
217 log_write ("%s: %s", client->filename, pwmd_strerror (rc));
219 else if (gpg_err_code (rc) == GPG_ERR_ENOENT)
220 rc = 0;
222 /* FLAG_HAS_LOCK may have been set by the LOCK command or OPEN --lock. */
223 if ((cmd->unlock && !(client->flags & FLAG_HAS_LOCK)) || rc)
224 unlock_file_mutex (client, 0);
226 if (rc || !(cmd->flock_type & FLOCK_TYPE_KEEP))
227 unlock_flock (&client->flock_fd);
229 return rc;
232 static gpg_error_t
233 parse_xml (assuan_context_t ctx, int new)
235 struct client_s *client = assuan_get_pointer (ctx);
236 int cached = client->doc != NULL;
237 gpg_error_t rc = 0;
239 if (new)
241 client->doc = xml_new_document ();
242 if (client->doc)
244 xmlChar *result;
245 int len;
247 xmlDocDumpFormatMemory (client->doc, &result, &len, 0);
248 client->crypto->plaintext = result;
249 client->crypto->plaintext_size = len;
250 if (!client->crypto->plaintext)
252 xmlFreeDoc (client->doc);
253 client->doc = NULL;
254 rc = GPG_ERR_ENOMEM;
257 else
258 rc = GPG_ERR_ENOMEM;
260 else if (!cached)
261 rc = xml_parse_doc ((char *) client->crypto->plaintext,
262 client->crypto->plaintext_size,
263 (xmlDocPtr *)&client->doc);
265 return rc;
268 static void
269 free_client (struct client_s *client)
271 cache_plaintext_release (&client->doc);
272 xfree (client->crc);
273 xfree (client->filename);
274 xfree (client->last_error);
275 crypto_free (client->crypto);
276 client->crypto = NULL;
279 void
280 reset_client (struct client_s *client)
282 assuan_context_t ctx = client->ctx;
283 struct client_thread_s *thd = client->thd;
284 long lock_timeout = client->lock_timeout;
285 xmlErrorPtr xml_error = client->xml_error;
286 int no_pinentry = (client->flags & FLAG_NO_PINENTRY);
287 int flock_fd = client->flock_fd;
289 unlock_file_mutex (client, client->flags & FLAG_NEW);
290 free_client (client);
291 memset (client, 0, sizeof (struct client_s));
292 client->flock_fd = flock_fd;
293 client->xml_error = xml_error;
294 client->ctx = ctx;
295 client->thd = thd;
296 client->lock_timeout = lock_timeout;
297 client->flags |= no_pinentry ? FLAG_NO_PINENTRY : 0;
300 static void
301 req_free (void *arg)
303 if (!arg)
304 return;
306 strv_free ((char **) arg);
309 static gpg_error_t
310 parse_open_opt_lock (void *data, void *value)
312 struct client_s *client = data;
314 (void)value;
315 client->opts |= OPT_LOCK_ON_OPEN;
316 return 0;
319 static gpg_error_t
320 parse_opt_inquire (void *data, void *value)
322 struct client_s *client = data;
324 (void) value;
325 client->opts |= OPT_INQUIRE;
326 return 0;
329 static gpg_error_t
330 update_checksum (struct client_s *client, unsigned char *from_crc,
331 size_t crclen)
333 unsigned char *crc;
334 size_t len;
335 struct cache_data_s *cdata;
336 gpg_error_t rc;
338 if (!from_crc)
340 rc = get_checksum (client->filename, &crc, &len);
341 if (rc)
342 return rc;
344 else
346 crc = from_crc;
347 len = crclen;
350 xfree (client->crc);
351 client->crc = xmalloc (len);
352 memcpy (client->crc, crc, len);
353 pthread_cleanup_push (xfree, crc);
354 cdata = cache_get_data (client->filename, NULL);
355 pthread_cleanup_pop (0);
356 if (cdata)
358 xfree (cdata->crc);
359 cdata->crc = xmalloc (len);
360 memcpy (cdata->crc, crc, len);
363 if (!from_crc)
364 xfree (crc);
365 return 0;
368 static gpg_error_t
369 validate_checksum (struct client_s *client, const char *filename,
370 struct cache_data_s *cdata, unsigned char **r_crc,
371 size_t *r_crclen, int from_cdata)
373 unsigned char *crc;
374 size_t len;
375 gpg_error_t rc;
376 int n = 0;
378 if (cdata && !cdata->crc)
379 return GPG_ERR_CHECKSUM;
381 rc = get_checksum (filename, &crc, &len);
382 if (rc)
383 return rc;
385 if (client->crc)
386 n = memcmp (client->crc, crc, len);
387 else if ((client->flags & FLAG_NEW) && cache_get_data (filename, NULL))
388 n = 1;
390 if ((!n && cdata) || (from_cdata && cdata && crc))
391 n = memcmp (cdata->crc, crc, len);
393 if (!n && r_crc)
395 *r_crc = crc;
396 *r_crclen = len;
398 else
399 xfree (crc);
401 return n ? GPG_ERR_CHECKSUM : 0;
404 static gpg_error_t
405 open_command (assuan_context_t ctx, char *line)
407 gpg_error_t rc;
408 struct client_s *client = assuan_get_pointer (ctx);
409 int same_file = 0;
410 assuan_peercred_t peer;
411 struct cache_data_s *cdata = NULL;
412 int cached = 0;
413 unsigned char *crc = NULL;
414 size_t crclen = 0;
415 int plaintext = 0;
416 struct argv_s *args[] = {
417 &(struct argv_s) {"lock", OPTION_TYPE_NOARG, parse_open_opt_lock},
418 NULL
421 rc = parse_options (&line, args, client, 1);
422 if (rc)
423 return send_error (ctx, rc);
425 rc = do_validate_peer (ctx, line, &peer);
426 if (rc == GPG_ERR_FORBIDDEN)
428 rc = peer_is_invoker (client);
429 if (rc == GPG_ERR_EACCES)
430 rc = GPG_ERR_FORBIDDEN;
433 if (rc)
434 return send_error (ctx, rc);
436 if (!valid_filename (line))
437 return send_error (ctx, GPG_ERR_INV_VALUE);
439 /* This client may have locked a different file with ISCACHED --lock than
440 * the current filename. This will remove that lock. */
441 same_file = client->filename && !strcmp (line, client->filename);
442 if (client->flags & FLAG_OPEN ||
443 (client->flags & FLAG_HAS_LOCK && !same_file))
445 unsigned opts = client->opts;
446 unsigned flags = client->flags;
448 if (same_file)
449 client->flags |= FLAG_KEEP_LOCK;
451 /* Another client wrote to the same data file as currently opened. */
452 cdata = cache_get_data (client->filename, NULL);
453 if (cdata && cdata->crc)
454 flags &= ~FLAG_NEW;
455 /* Remove cache entry for the new file that hadn't been written. */
456 else if (client->flags & FLAG_NEW)
457 cache_clear (NULL, client->filename, 0, 0);
459 cdata = NULL;
460 reset_client (client);
461 client->opts = opts;
462 client->flags |= flags;
463 client->flags &= ~(FLAG_LOCK_CMD);
464 if (!same_file)
465 client->flags &= ~(FLAG_HAS_LOCK | FLAG_NEW);
468 client->filename = str_dup (line);
469 if (!client->filename)
470 return send_error(ctx, GPG_ERR_ENOMEM);
472 /* Need to lock the mutex here because file_modified() cannot without
473 * knowing the filename. */
474 rc = lock_file_mutex (client, 1);
475 if (rc)
476 client->flags &= ~FLAG_OPEN;
478 if (!rc)
480 rc = lock_flock (ctx, client->filename, LOCK_SH, &client->flock_fd);
481 if (gpg_err_code (rc) == GPG_ERR_ENOENT)
482 rc = 0;
485 if (!rc)
487 char *keyfile = config_get_string (client->filename, "passphrase_file");
489 rc = crypto_init (&client->crypto, client->ctx, client->filename,
490 client->flags & FLAG_NO_PINENTRY, keyfile);
491 if (rc)
492 xfree (keyfile);
493 else
494 rc = open_check_file (client->filename, NULL, NULL, 1);
497 if (!rc || gpg_err_code (rc) == GPG_ERR_ENOENT)
499 int reload = 0;
500 int defer = 0;
502 if (rc) // new file
504 rc = 0;
506 if (config_get_boolean ("global", "strict_open"))
508 rc = peer_is_invoker (client);
509 if (rc == GPG_ERR_EACCES)
510 rc = GPG_ERR_FORBIDDEN;
513 if (!rc)
515 client->flags |= FLAG_NEW;
516 // data file disappeared. clear the cache entry.
517 cache_clear (NULL, client->filename, 1, 1);
518 cdata = NULL;
521 goto done;
524 cdata = cache_get_data (client->filename, &defer);
525 if (cdata && !defer
526 && !cache_plaintext_get (client->filename, &client->doc))
528 rc = validate_checksum (client, client->filename, cdata, &crc,
529 &crclen, 0);
530 if (rc)
532 log_write ("%s: %s", client->filename,
533 pwmd_strerror (rc));
534 cache_plaintext_release (&client->doc);
535 if (rc == GPG_ERR_CHECKSUM)
537 cache_clear (NULL, client->filename, 1, 1);
538 cdata = NULL;
539 goto decrypt;
543 #ifdef WITH_GNUTLS
544 if (!rc && client->thd->remote
545 && config_get_boolean (client->filename, "tcp_require_key")
546 && !(client->flags & FLAG_NEW))
548 rc = crypto_try_decrypt (client,
549 (client->flags & FLAG_NO_PINENTRY));
551 #endif
552 if (!rc)
554 strv_free (client->crypto->pubkey);
555 client->crypto->pubkey = NULL;
556 if (cdata->pubkey)
557 client->crypto->pubkey = strv_dup (cdata->pubkey);
559 xfree (client->crypto->sigkey);
560 client->crypto->sigkey = NULL;
561 if (cdata->sigkey)
562 client->crypto->sigkey = str_dup (cdata->sigkey);
564 cached = 1;
565 plaintext = 1;
568 else if (cdata && cdata->doc) // cached document
570 if (!rc && !(client->flags & FLAG_NEW))
572 rc = validate_checksum (client, client->filename, cdata, &crc,
573 &crclen, 0);
574 if (rc == GPG_ERR_CHECKSUM)
576 rc = 0;
577 reload = 1;
581 if (!rc)
583 rc = cache_iscached (client->filename, &defer, 0, 0);
584 if ((!rc || rc == GPG_ERR_ENOENT) && defer)
586 rc = 0;
587 reload = 2;
591 if (!rc && reload)
593 if (reload == 1)
594 log_write ("%s: %s", client->filename,
595 pwmd_strerror (GPG_ERR_CHECKSUM));
596 cache_clear (NULL, client->filename, 1, 1);
597 cdata = NULL;
598 rc = crypto_decrypt (client, client->crypto);
600 #ifdef WITH_GNUTLS
601 else if (!rc)
603 if (client->thd->remote
604 && config_get_boolean (client->filename, "tcp_require_key")
605 && !(client->flags & FLAG_NEW))
606 rc = crypto_try_decrypt (client,
607 (client->flags & FLAG_NO_PINENTRY));
609 #endif
611 if (!rc && cdata)
613 client->crypto->plaintext = cdata->doc;
614 client->crypto->plaintext_size = cdata->size;
615 rc = cache_decrypt (client->crypto);
616 if (!rc)
618 cdata->doc = NULL;
619 cdata->size = 0;
621 strv_free (client->crypto->pubkey);
622 client->crypto->pubkey = NULL;
623 if (cdata->pubkey)
624 client->crypto->pubkey = strv_dup (cdata->pubkey);
626 xfree (client->crypto->sigkey);
627 client->crypto->sigkey = NULL;
628 if (cdata->sigkey)
629 client->crypto->sigkey = str_dup (cdata->sigkey);
631 cached = 1;
633 else
635 client->crypto->plaintext = NULL;
636 client->crypto->plaintext_size = 0;
640 else // existing file
642 decrypt:
643 cached = cdata != NULL;
644 rc = crypto_decrypt (client, client->crypto);
648 done:
649 if (!rc && !plaintext)
651 rc = parse_xml (ctx, client->flags & FLAG_NEW);
652 if (!rc)
654 rc = cache_encrypt (client->crypto);
655 if (rc)
656 cache_clear (NULL, client->filename, 1, 1);
657 else
659 long timeout = config_get_long (client->filename,
660 "cache_timeout");
662 cache_free_data_once (cdata);
663 cdata = xcalloc (1, sizeof (struct cache_data_s));
664 cdata->doc = client->crypto->plaintext;
665 cdata->size = client->crypto->plaintext_size;
666 cdata->pubkey = strv_dup(client->crypto->pubkey);
667 cdata->sigkey = client->crypto->sigkey ? str_dup(client->crypto->sigkey) : NULL;
668 client->crypto->plaintext = NULL;
669 client->crypto->plaintext_size = 0;
671 if (cached) // wont increment the refcount
673 if (crclen)
675 xfree (client->crc);
676 client->crc = NULL;
677 xfree (cdata->crc);
678 cdata->crc = xmalloc (crclen);
679 memcpy (cdata->crc, crc, crclen);
682 rc = cache_set_data (client->filename, cdata);
683 /* The cache entry may have been removed and cache_set_data()
684 * already sent STATUS_CACHE. */
685 if (!cache_iscached (client->filename, NULL, 0, 0))
686 rc = send_status (ctx, STATUS_CACHE, NULL);
688 else
689 rc = cache_add_file (client->filename, cdata, timeout);
691 if (!rc)
692 cache_plaintext_set (client->filename, client->doc, 0);
696 else if (!rc)
698 xfree (client->crc);
699 client->crc = NULL;
700 if (crc)
702 client->crc = xmalloc (crclen);
703 memcpy (client->crc, crc, crclen);
707 xfree (crc);
709 if (!rc && !(client->flags & FLAG_NEW) && !cached)
710 rc = update_checksum (client, NULL, 0);
712 if (!rc)
714 client->flags |= FLAG_OPEN;
716 if (client->flags & FLAG_NEW)
717 rc = send_status (ctx, STATUS_NEWFILE, NULL);
719 if (!rc && (client->opts & OPT_LOCK_ON_OPEN))
720 rc = do_lock (client, 0);
723 if (rc)
725 log_write ("%s: %s", client->filename, pwmd_strerror (rc));
727 if (client->flags & FLAG_NEW)
728 cache_clear (NULL, client->filename, 1, 1);
730 crypto_free (client->crypto);
731 client->crypto = NULL;
732 client->flags &= ~FLAG_OPEN;
733 cache_plaintext_release (&client->doc);
735 else
736 crypto_free_non_keys (client->crypto);
738 return send_error (ctx, rc);
741 /* If not an invoking_user or is an existing file, check that the list of user
742 * supplied key ID's are in the list of current key ID's obtained when
743 * decrypting the data file.
745 static gpg_error_t
746 permitted_to_save (struct client_s *client, const char **keys,
747 const char **value)
749 gpg_error_t rc = 0;
750 const char **v;
752 if ((client->flags & FLAG_NEW) || (client->opts & OPT_SYMMETRIC))
753 return 0;
755 rc = peer_is_invoker (client);
756 if (!rc)
757 return 0;
758 else if (rc == GPG_ERR_EACCES)
759 rc = GPG_ERR_FORBIDDEN;
760 else if (rc)
761 return rc;
763 /* Empty match. */
764 if ((!value && !keys) || ((value && !*value) && (keys && !*keys)))
765 return 0;
767 for (v = value; v && *v; v++)
769 const char **k, *pv = *v;
770 int match = 0;
772 if (*pv == '0' && *(pv+1) == 'x')
773 pv += 2;
775 for (k = keys; k && *k; k++)
777 const char *pk = *k;
779 if (*pk == '0' && *(pk+1) == 'x')
780 pk += 2;
782 rc = !strcmp (pv, pk) ? 0 : GPG_ERR_FORBIDDEN;
783 if (rc)
784 rc = !strcmp (pv, *k) ? 0 : GPG_ERR_FORBIDDEN;
786 if (!rc)
788 match = 1;
789 break;
793 if (!match)
794 return GPG_ERR_FORBIDDEN;
797 return rc;
800 /* Requires that the keyid be a fingerprint in 16 byte form. */
801 static gpg_error_t
802 parse_save_opt_keyid_common (struct client_s *client, const char **list,
803 const char *value, char ***dst)
805 gpg_error_t rc = 0;
806 char **keys = NULL;
808 if (value && *value)
810 keys = str_split (value, ",", 0);
811 if (!keys)
812 return GPG_ERR_ENOMEM;
815 rc = crypto_keyid_to_16b (keys);
816 if (!rc)
817 rc = permitted_to_save (client, list, (const char **)keys);
819 if (!rc)
820 *dst = keys;
821 else
822 strv_free (keys);
824 return rc;
827 static gpg_error_t
828 parse_save_opt_keyid (void *data, void *value)
830 struct client_s *client = data;
831 const char *str = value;
832 char **dst = NULL;
833 gpg_error_t rc;
835 rc = parse_save_opt_keyid_common (client,
836 (const char **)client->crypto->pubkey,
837 str, &dst);
838 if (rc)
839 return rc;
841 client->crypto->save.pubkey = dst;
842 return 0;
845 static gpg_error_t
846 parse_save_opt_sign_keyid (void *data, void *value)
848 struct client_s *client = data;
849 const char *str = value;
850 char **dst = NULL;
851 gpg_error_t rc;
852 char **tmp = NULL;
854 if (client->crypto->sigkey)
856 if (!strv_printf (&tmp, "%s", client->crypto->sigkey))
857 return GPG_ERR_ENOMEM;
860 rc = parse_save_opt_keyid_common (client, (const char **)tmp, str, &dst);
861 strv_free (tmp);
862 if (rc)
863 return rc;
865 if (!dst)
866 client->opts |= OPT_NO_SIGNER;
867 else
868 client->crypto->save.sigkey = str_dup (*dst);
870 strv_free (dst);
871 return 0;
874 static gpg_error_t
875 parse_save_opt_inquire_keyid (void *data, void *value)
877 struct client_s *client = data;
879 (void)value;
881 if (!(client->flags & FLAG_NEW))
883 gpg_error_t rc = peer_is_invoker (client);
885 if (rc)
886 return rc == GPG_ERR_EACCES ? GPG_ERR_FORBIDDEN : rc;
889 client->opts |= OPT_INQUIRE_KEYID;
890 return 0;
893 static gpg_error_t
894 parse_save_opt_symmetric (void *data, void *value)
896 struct client_s *client = data;
898 (void)value;
899 client->opts |= OPT_SYMMETRIC;
900 return 0;
903 static gpg_error_t
904 parse_genkey_opt_userid (void *data, void *value)
906 struct client_s *client = data;
908 if (!(client->flags & FLAG_NEW))
910 gpg_error_t rc = peer_is_invoker (client);
912 if (rc)
913 return rc == GPG_ERR_EACCES ? GPG_ERR_FORBIDDEN : rc;
916 client->crypto->save.userid = str_dup (value);
917 return client->crypto->save.userid ? 0 : GPG_ERR_ENOMEM;
920 static gpg_error_t
921 parse_genkey_opt_algo (void *data, void *value)
923 struct client_s *client = data;
925 client->crypto->save.algo = str_dup (value);
926 return client->crypto->save.algo ? 0 : GPG_ERR_ENOMEM;
929 static gpg_error_t
930 parse_genkey_opt_no_expire (void *data, void *value)
932 struct client_s *client = data;
934 client->crypto->save.flags |= GPGME_CREATE_NOEXPIRE;
935 return 0;
938 static gpg_error_t
939 parse_genkey_opt_expire (void *data, void *value)
941 struct client_s *client = data;
942 gpg_error_t rc = 0;
943 char *p = NULL;
944 unsigned long t;
946 errno = 0;
947 t = strtoul (value, &p, 10);
949 if (!errno && p && *p)
950 rc = GPG_ERR_INV_VALUE;
951 else if (t == ULONG_MAX)
952 rc = GPG_ERR_INV_VALUE;
953 else if (errno)
954 rc = gpg_error_from_syserror ();
955 else
956 client->crypto->save.expire = t;
958 return rc;
961 static gpg_error_t
962 parse_genkey_opt_no_passphrase (void *data, void *value)
964 struct client_s *client = data;
966 (void)value;
967 client->crypto->save.flags |= GPGME_CREATE_NOPASSWD;
968 return 0;
971 /* Tests that the keys in new_keys are also in old_keys. */
972 static gpg_error_t
973 compare_keys (char **new_keys, char **old_keys)
975 char **o;
977 if (!old_keys || !*old_keys)
978 return 0;
980 crypto_keyid_to_16b (new_keys);
982 for (o = old_keys; *o; o++)
984 char **n;
986 for (n = new_keys; *n; n++)
988 if (!strcmp (*n, *o))
989 break;
992 if (!*n)
993 return GPG_ERR_NOT_FOUND;
996 return 0;
999 static gpg_error_t
1000 inquire_keyid (struct client_s *client)
1002 gpg_error_t rc;
1003 unsigned char *result = NULL;
1004 size_t len;
1005 const char *s = "KEYID";
1006 char ***orig;
1007 char ***save;
1009 orig = &client->crypto->pubkey;
1010 save = &client->crypto->save.pubkey;
1011 rc = assuan_inquire (client->ctx, s, &result, &len, 0);
1012 if (!rc)
1014 char **dst = NULL;
1016 rc = parse_save_opt_keyid_common (client, (const char **)*orig,
1017 (char *)result, &dst);
1018 if (!rc)
1019 *save = dst;
1022 xfree (result);
1023 return rc;
1027 /* When a key lookup in gpg-agent's cache fails, the agent tries the last
1028 * successful key to be unlocked. This prevents pwmd from successfully
1029 * clearing a signing key since the previous key, which more than likely
1030 * belongs to the same keypair as the encryption/decryption key, will have the
1031 * passphrase cached and therefore the signing key also cached. So we need to
1032 * clear both the signing and encryption keys to get the effect of requiring a
1033 * passphrase when generating a new keypair for an existing data file, or when
1034 * the "require_save_key" configuration parameter is set. This parameter is
1035 * mostly a failsafe of the gpg-agent option --ignore-cache-for-signing since
1036 * some/most/all users may fail to set it.
1038 static gpg_error_t
1039 save_command (assuan_context_t ctx, char *line)
1041 struct client_s *client = assuan_get_pointer (ctx);
1042 struct cache_data_s *cdata = NULL;
1043 int sym = 0;
1044 gpg_error_t rc = 0, cache_rc = 0;
1045 int defer = 0;
1046 struct argv_s *args[] = {
1047 &(struct argv_s) {"keyid", OPTION_TYPE_ARG, parse_save_opt_keyid},
1048 &(struct argv_s) {"inquire-keyid", OPTION_TYPE_NOARG,
1049 parse_save_opt_inquire_keyid },
1050 &(struct argv_s) {"sign-keyid", OPTION_TYPE_OPTARG,
1051 parse_save_opt_sign_keyid},
1052 &(struct argv_s) {"symmetric", OPTION_TYPE_NOARG,
1053 parse_save_opt_symmetric },
1054 NULL
1057 crypto_free_save (&client->crypto->save);
1058 client->crypto->save.expire = DEFAULT_EXPIRE;
1060 rc = crypto_is_symmetric (client->filename);
1061 if (!rc || rc == GPG_ERR_BAD_DATA || rc == GPG_ERR_ENOENT)
1063 if (!rc)
1065 client->opts |= OPT_SYMMETRIC;
1066 sym = 1;
1068 else if (rc == GPG_ERR_ENOENT && (client->flags & FLAG_NEW))
1069 rc = 0; // New file
1070 else
1071 rc = 0; // PKI
1074 if (rc)
1075 return send_error (ctx, rc);
1077 rc = parse_options (&line, args, client, 0);
1078 if (rc)
1079 return send_error (ctx, rc);
1081 if (config_get_boolean (client->filename, "require_save_key")
1082 || (client->opts & OPT_SYMMETRIC))
1083 client->opts |= OPT_ASK;
1085 rc = open_check_file (client->filename, NULL, NULL, 1);
1086 if (rc && gpg_err_code (rc) != GPG_ERR_ENOENT)
1088 log_write ("%s: %s", client->filename, pwmd_strerror (rc));
1089 return send_error (ctx, rc);
1092 if (!rc)
1093 cache_rc = rc = cache_iscached (client->filename, &defer, 0, 1);
1095 if (gpg_err_code (rc) == GPG_ERR_ENOENT && (client->flags & FLAG_NEW))
1096 rc = 0;
1097 else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
1098 rc = 0;
1100 if (rc)
1101 return send_error (ctx, rc);
1103 /* Specifying both a recipient and symmetric encryption is an error. */
1104 if ((client->opts & OPT_INQUIRE_KEYID) && (client->opts & OPT_SYMMETRIC))
1105 return send_error (ctx, GPG_ERR_CONFLICT);
1106 /* Existing file with a recipient and wanting symmetric is an error. */
1107 else if ((client->opts & OPT_SYMMETRIC) && client->crypto->save.pubkey)
1108 return send_error (ctx, GPG_ERR_CONFLICT);
1109 else if (client->crypto->save.pubkey && (client->opts & OPT_INQUIRE_KEYID))
1110 return send_error (ctx, GPG_ERR_CONFLICT);
1111 else if (!sym && (client->opts & OPT_SYMMETRIC) && !(client->flags & FLAG_NEW))
1112 return send_error (ctx, GPG_ERR_CONFLICT);
1113 /* New file that is not symmetric without either a recipient or signer. */
1114 else if ((client->flags & FLAG_NEW) && !(client->opts & OPT_SYMMETRIC)
1115 && (!client->crypto->save.pubkey || !client->crypto->save.sigkey))
1116 return send_error (ctx, GPG_ERR_SYNTAX);
1117 else if (client->opts & OPT_INQUIRE_KEYID)
1118 rc = inquire_keyid (client);
1120 if (!rc)
1122 client->crypto->keyfile = config_get_string (client->filename,
1123 "passphrase_file");
1124 rc = crypto_init_ctx (client->crypto, (client->flags & FLAG_NO_PINENTRY),
1125 client->crypto->keyfile);
1128 if (!rc && (client->flags & FLAG_NEW))
1130 /* Require --keyid when --sign-keyid exists to keep KEYINFO
1131 * synchronized. */
1132 if (!client->crypto->save.pubkey && client->crypto->save.sigkey
1133 && !(client->opts & OPT_SYMMETRIC))
1134 rc = GPG_ERR_NO_PUBKEY;
1136 else if (!rc)
1138 cdata = cache_get_data (client->filename, NULL);
1139 if (cdata)
1141 if (client->crypto->save.pubkey)
1142 rc = compare_keys (client->crypto->save.pubkey, cdata->pubkey);
1144 /* Always allow a signer for symmetric data files. */
1145 if (!rc && client->crypto->save.sigkey
1146 && !(client->opts & OPT_SYMMETRIC))
1147 rc = !strcmp (client->crypto->save.sigkey, cdata->sigkey)
1148 ? 0 : GPG_ERR_NOT_FOUND;
1150 /* Prevent saving to a recipient who is not in the original recipient
1151 * list without a passphrase. */
1152 if (rc || (client->crypto->sigkey && (client->opts & OPT_NO_SIGNER)))
1153 client->opts |= OPT_ASK;
1155 if (rc == GPG_ERR_NOT_FOUND)
1157 rc = peer_is_invoker (client);
1158 if (rc == GPG_ERR_EACCES)
1159 rc = GPG_ERR_FORBIDDEN;
1162 if (!client->crypto->save.pubkey
1163 && !(client->opts & OPT_SYMMETRIC))
1164 client->crypto->save.pubkey = strv_dup (cdata->pubkey);
1166 if (!rc && !client->crypto->save.sigkey && cdata->sigkey
1167 && !(client->opts & OPT_NO_SIGNER))
1168 client->crypto->save.sigkey = str_dup (cdata->sigkey);
1169 else if (!rc && !client->crypto->save.sigkey
1170 && (client->opts & OPT_NO_SIGNER)
1171 && !(client->opts & OPT_SYMMETRIC))
1172 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
1174 else
1176 client->crypto->save.pubkey = strv_dup (client->crypto->pubkey);
1177 client->crypto->save.sigkey = str_dup (client->crypto->sigkey);
1181 if (!rc && !(client->flags & FLAG_NEW))
1183 /* Fixes {NEW_,SIGN_}PASSPHRASE inquire keywords. See passphrase_cb(). */
1184 if (client->opts & OPT_SYMMETRIC)
1185 client->crypto->flags |= CRYPTO_FLAG_PASSWD;
1187 if (client->opts & OPT_ASK)
1189 rc = cache_clear_agent_keys (client->filename, 1, 1);
1190 if (!rc)
1191 rc = crypto_try_decrypt (client, client->flags & FLAG_NO_PINENTRY);
1195 if (!rc && client->opts & OPT_SYMMETRIC)
1196 client->crypto->flags |= CRYPTO_FLAG_PASSWD_NEW;
1198 if (!rc)
1199 rc = xml_update_element_mtime (client, xmlDocGetRootElement (client->doc));
1201 if (!rc)
1203 int size;
1205 xmlDocDumpFormatMemory (client->doc, &client->crypto->plaintext, &size,
1207 if (size > 0)
1208 client->crypto->plaintext_size = (size_t) size;
1209 else
1210 rc = GPG_ERR_ENOMEM;
1212 if (!rc)
1214 client->crypto->flags |= (client->opts & OPT_SYMMETRIC) ? CRYPTO_FLAG_SYMMETRIC : 0;
1215 client->crypto->flags |= (client->flags & FLAG_NEW) ? CRYPTO_FLAG_NEWFILE : 0;
1216 client->crypto->flags |= !(client->opts & OPT_SYMMETRIC) ? CRYPTO_FLAG_PASSWD_SIGN : 0;
1217 rc = crypto_encrypt (client, client->crypto);
1218 client->crypto->flags &= ~CRYPTO_FLAG_SYMMETRIC;
1221 if (!rc)
1223 unsigned char *crc = NULL;
1224 size_t crclen = 0;
1226 rc = crypto_write_file (client->crypto, &crc, &crclen);
1227 pthread_cleanup_push ((void *)xfree, crc);
1228 if (!rc)
1230 if (!cache_rc)
1231 cdata = cache_get_data (client->filename, NULL);
1232 else
1233 cdata = xcalloc (1, sizeof (struct cache_data_s));
1236 if (!rc)
1238 rc = cache_encrypt (client->crypto);
1239 if (rc)
1241 cache_clear (NULL, client->filename, 1, 1);
1242 client->flags &= ~(FLAG_NEW);
1244 strv_free (client->crypto->pubkey);
1245 client->crypto->pubkey = NULL;
1246 if (client->crypto->save.pubkey)
1247 client->crypto->pubkey = strv_dup (client->crypto->save.pubkey);
1249 xfree (client->crypto->sigkey);
1250 client->crypto->sigkey = NULL;
1251 if (client->crypto->save.sigkey)
1252 client->crypto->sigkey = str_dup (client->crypto->save.sigkey);
1256 if (!rc)
1258 long timeout = config_get_long (client->filename, "cache_timeout");
1259 xmlDocPtr doc = xmlCopyDoc (client->doc, 1);
1261 if (!doc)
1262 rc = GPG_ERR_ENOMEM;
1264 if (!rc)
1266 cache_plaintext_release (&client->doc);
1267 strv_free (cdata->pubkey);
1268 cdata->pubkey = client->crypto->save.pubkey;
1269 client->crypto->save.pubkey = NULL;
1271 xfree (cdata->sigkey);
1272 cdata->sigkey = client->crypto->save.sigkey;
1273 client->crypto->save.sigkey = NULL;
1275 xfree (cdata->crc);
1276 cdata->crc = NULL;
1278 /* cache_encrypt() does in-place encryption */
1279 xfree (cdata->doc);
1280 cdata->doc = client->crypto->plaintext;
1281 client->crypto->plaintext = NULL;
1282 cdata->size = client->crypto->plaintext_size;
1283 client->crypto->plaintext_size = 0;
1285 client->doc = doc;
1286 cache_plaintext_set (client->filename, client->doc, 0);
1288 /* Update in case the cache entry expires the next SAVE may
1289 * not have any known keys. */
1290 strv_free (client->crypto->pubkey);
1291 client->crypto->pubkey = NULL;
1292 if (cdata->pubkey)
1293 client->crypto->pubkey = strv_dup (cdata->pubkey);
1295 xfree (client->crypto->sigkey);
1296 client->crypto->sigkey = NULL;
1297 if (cdata->sigkey)
1298 client->crypto->sigkey = str_dup (cdata->sigkey);
1300 if (!cache_rc) // wont increment refcount
1301 rc = cache_set_data (client->filename, cdata);
1302 else
1303 rc = cache_add_file (client->filename, cdata, timeout);
1306 if (!rc && (cache_rc || (client->flags & FLAG_NEW)))
1307 send_status_all (STATUS_CACHE, NULL);
1309 if (!rc)
1311 rc = update_checksum (client, crc, crclen);
1312 client->flags &= ~(FLAG_NEW);
1316 pthread_cleanup_pop (1);
1317 if (!rc)
1318 client->did_cow = 0;
1322 crypto_free_non_keys (client->crypto);
1323 return send_error (ctx, rc);
1326 static gpg_error_t
1327 parse_genkey_opt_usage (void *data, void *v)
1329 struct client_s *client = data;
1330 char *value = v;
1332 if (!value || !*value)
1333 return GPG_ERR_INV_VALUE;
1334 else if (!strcmp (value, "sign"))
1335 client->crypto->save.flags |= GPGME_CREATE_SIGN;
1336 else if (!strcmp (value, "encrypt"))
1337 client->crypto->save.flags |= GPGME_CREATE_ENCR;
1338 else if (!strcmp (value, "default"))
1339 client->crypto->save.flags &= ~(GPGME_CREATE_ENCR|GPGME_CREATE_SIGN);
1340 else
1341 return GPG_ERR_INV_VALUE;
1343 return 0;
1346 gpg_error_t
1347 parse_genkey_opt_subkey_of (void *data, void *v)
1349 gpg_error_t rc;
1350 struct client_s *client = data;
1351 char *value = v;
1352 char *tmp[] = { value, NULL };
1353 gpgme_key_t *keys = NULL;
1355 rc = peer_is_invoker (client);
1356 if (rc)
1357 return rc == GPG_ERR_EACCES ? GPG_ERR_FORBIDDEN : rc;
1359 if (!value || !*value)
1360 return GPG_ERR_INV_VALUE;
1362 rc = crypto_list_keys (client->crypto, tmp, 1, &keys);
1363 if (rc)
1364 return rc;
1366 if (!keys || !*keys)
1368 crypto_free_key_list (keys);
1369 return GPG_ERR_NO_SECKEY;
1372 client->crypto->save.mainkey = keys;
1373 return 0;
1376 static gpg_error_t
1377 genkey_command (assuan_context_t ctx, char *line)
1379 struct client_s *client = assuan_get_pointer (ctx);
1380 struct crypto_s *crypto, *orig;
1381 gpg_error_t rc = 0;
1382 struct argv_s *args[] = {
1383 &(struct argv_s) {"userid", OPTION_TYPE_ARG,
1384 parse_genkey_opt_userid},
1385 &(struct argv_s) {"expire", OPTION_TYPE_ARG,
1386 parse_genkey_opt_expire},
1387 &(struct argv_s) {"no-expire", OPTION_TYPE_NOARG,
1388 parse_genkey_opt_no_expire},
1389 &(struct argv_s) {"algo", OPTION_TYPE_ARG,
1390 parse_genkey_opt_algo},
1391 &(struct argv_s) {"no-passphrase", OPTION_TYPE_NOARG,
1392 parse_genkey_opt_no_passphrase},
1393 &(struct argv_s) {"usage", OPTION_TYPE_ARG,
1394 parse_genkey_opt_usage},
1395 &(struct argv_s) {"subkey-of", OPTION_TYPE_ARG,
1396 parse_genkey_opt_subkey_of},
1397 NULL
1400 if (!(client->flags & FLAG_OPEN))
1401 return send_error (ctx, GPG_ERR_INV_STATE);
1403 rc = crypto_init (&crypto, ctx, client->filename,
1404 client->flags & FLAG_NO_PINENTRY, NULL);
1405 if (rc)
1406 return send_error (ctx, rc);
1408 pthread_cleanup_push ((void *)crypto_free, client->crypto);
1409 orig = client->crypto;
1410 client->crypto = crypto;
1411 rc = parse_options (&line, args, client, 0);
1412 if (!rc)
1414 if (!client->crypto->save.userid && !client->crypto->save.mainkey)
1415 rc = GPG_ERR_SYNTAX;
1416 else
1418 client->crypto->flags |= CRYPTO_FLAG_NEWFILE;
1419 rc = crypto_genkey (client, client->crypto);
1423 pthread_cleanup_pop (0);
1424 crypto_free (crypto);
1425 client->crypto = orig;
1426 return send_error (ctx, rc);
1429 static gpg_error_t
1430 do_delete (assuan_context_t ctx, char *line)
1432 struct client_s *client = assuan_get_pointer (ctx);
1433 struct xml_request_s *req;
1434 xmlNodePtr n;
1435 gpg_error_t rc;
1437 if (!line || !*line)
1438 return GPG_ERR_SYNTAX;
1440 rc = xml_new_request (client, line, XML_CMD_DELETE, &req);
1441 if (rc)
1442 return rc;
1444 n = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
1445 xml_free_request (req);
1446 if (rc)
1447 return rc;
1449 rc = xml_is_element_owner (client, n);
1450 if (!rc)
1451 rc = xml_unlink_node (client, n);
1453 return rc;
1456 /* Won't update cdata->plaintext. Other clients are working on the original or
1457 * copy of the same document. The first client to SAVE wins and requires others
1458 * to reopen the data file do to a checksum error. */
1459 static gpg_error_t
1460 copy_on_write (struct client_s *client)
1462 struct cache_data_s *cdata;
1464 if (client->did_cow)
1465 return 0;
1467 cdata = cache_get_data (client->filename, NULL);
1468 if (cdata)
1470 gpg_error_t rc;
1471 xmlDocPtr doc = xmlCopyDoc (client->doc, 1);
1473 if (!doc)
1474 return GPG_ERR_ENOMEM;
1476 rc = cache_plaintext_set (client->filename, doc, 1);
1477 if (rc)
1479 xmlFree (doc);
1480 return rc;
1483 (void)cache_plaintext_release (&client->doc);
1484 client->doc = doc;
1485 client->did_cow = 1;
1486 return 0;
1489 return GPG_ERR_NO_DATA;
1492 static gpg_error_t
1493 delete_command (assuan_context_t ctx, char *line)
1495 struct client_s *client = assuan_get_pointer (ctx);
1496 gpg_error_t rc;
1497 struct argv_s *args[] = {
1498 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1499 NULL
1502 rc = parse_options (&line, args, client, 1);
1503 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
1504 rc = GPG_ERR_SYNTAX;
1505 if (rc)
1506 return send_error (ctx, rc);
1508 rc = copy_on_write (client);
1509 if (rc)
1510 return send_error (ctx, rc);
1512 if (client->opts & OPT_INQUIRE)
1514 unsigned char *result;
1515 size_t len;
1517 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1518 if (rc)
1519 return send_error (ctx, rc);
1521 pthread_cleanup_push ((void *)xfree, result);
1522 rc = do_delete (ctx, (char *)result);
1523 pthread_cleanup_pop (1);
1525 else
1526 rc = do_delete (ctx, line);
1528 return send_error (ctx, rc);
1531 static gpg_error_t
1532 update_element_expirey (struct client_s *client, xmlNodePtr n)
1534 gpg_error_t rc = 0;
1535 xmlChar *expire, *incr;
1536 char *p;
1537 time_t e, e_orig, i;
1538 time_t now = time (NULL);
1540 expire = xml_attribute_value (n, (xmlChar *)"expire");
1541 if (!expire)
1542 return 0;
1544 errno = 0;
1545 e = strtoul ((char *)expire, &p, 10);
1546 if (errno || *p || e == ULONG_MAX || *expire == '-')
1548 xmlFree (expire);
1549 rc = GPG_ERR_ERANGE;
1550 goto fail;
1553 xmlFree (expire);
1554 incr = xml_attribute_value (n, (xmlChar *)"expire_increment");
1555 if (!incr)
1556 return 0;
1558 i = strtoul ((char *)incr, &p, 10);
1559 if (errno || *p || i == ULONG_MAX || *incr == '-')
1561 xmlFree (incr);
1562 rc = GPG_ERR_ERANGE;
1563 goto fail;
1566 xmlFree (incr);
1567 e_orig = e;
1568 e = now + i;
1569 p = str_asprintf ("%lu", e);
1570 if (!p)
1572 rc = GPG_ERR_ENOMEM;
1573 goto fail;
1576 rc = xml_add_attribute (client, n, "expire", p);
1577 xfree (p);
1578 if (!rc)
1579 rc = send_status (client->ctx, STATUS_EXPIRE, "%lu %lu", e_orig, e);
1581 fail:
1582 return rc;
1585 static gpg_error_t
1586 store_command (assuan_context_t ctx, char *line)
1588 struct client_s *client = assuan_get_pointer (ctx);
1589 gpg_error_t rc;
1590 size_t len;
1591 unsigned char *result;
1592 xmlNodePtr n, parent;
1593 int has_content;
1594 char *content = NULL;
1595 struct xml_request_s *req;
1597 if (!client->bulk_p && line && *line)
1598 return send_error (ctx, GPG_ERR_SYNTAX);
1600 rc = copy_on_write (client);
1601 if (rc)
1602 return send_error (ctx, rc);
1604 if (!client->bulk_p)
1606 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1607 if (rc)
1608 return send_error (ctx, rc);
1609 rc = xml_new_request (client, (char *)result, XML_CMD_STORE, &req);
1610 if (!result || !*result)
1612 xfree (result);
1613 return send_error (ctx, GPG_ERR_SYNTAX);
1616 len = strv_length (req->args);
1617 has_content = result[strlen ((char *)result) - 1] != '\t' && len > 1;
1618 xfree (result);
1620 else
1622 rc = xml_new_request (client, line, XML_CMD_STORE, &req);
1623 len = strv_length (req->args);
1624 has_content = line && line[strlen (line) - 1] != '\t' && len > 1;
1627 if (rc)
1628 return send_error (ctx, rc);
1630 /* Prevent passing the element content around to save some memory
1631 * (has_content). */
1632 if (*(req->args+1) && !xml_valid_element_path (req->args, has_content))
1634 xml_free_request (req);
1635 return send_error (ctx, GPG_ERR_INV_VALUE);
1638 if (has_content || !*req->args[len-1])
1640 content = req->args[len-1];
1641 req->args[len-1] = NULL;
1644 if (strv_length (req->args) > 1)
1646 rc = xml_check_recursion (client, req);
1647 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
1648 goto fail;
1651 parent = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
1653 if (!rc && len > 1)
1655 rc = xml_is_element_owner (client, parent);
1656 if (!rc)
1658 n = xml_find_text_node (parent->children);
1659 if (n)
1660 xmlNodeSetContent (n, (xmlChar *) content);
1661 else
1662 xmlNodeAddContent (parent, (xmlChar *) content);
1664 (void)xml_update_element_mtime (client, parent);
1665 (void)update_element_expirey (client, parent);
1669 fail:
1670 xfree (content);
1671 xml_free_request (req);
1672 return send_error (ctx, rc);
1675 static gpg_error_t
1676 xfer_data (assuan_context_t ctx, const char *line, int total)
1678 struct client_s *client = assuan_get_pointer (ctx);
1679 int to_send = total < ASSUAN_LINELENGTH ? total : ASSUAN_LINELENGTH;
1680 int sent = 0;
1681 gpg_error_t rc = 0;
1683 if (!(client->flags & FLAG_LOCK_CMD))
1684 rc = unlock_file_mutex (client, 0);
1685 if (rc && rc != GPG_ERR_NOT_LOCKED)
1686 return rc;
1688 if (client->bulk_p)
1690 client->bulk_p->result = xmalloc (total+1);
1691 if (!client->bulk_p->result)
1692 return GPG_ERR_ENOMEM;
1693 memcpy (client->bulk_p->result, line, total);
1694 client->bulk_p->result[total] = 0;
1695 client->bulk_p->result_len = total;
1696 return 0;
1699 rc = send_status (ctx, STATUS_XFER, "%li %li", sent, total);
1700 if (rc)
1701 return rc;
1705 if (sent + to_send > total)
1706 to_send = total - sent;
1708 rc = assuan_send_data (ctx, (char *) line + sent, to_send);
1709 if (!rc)
1710 sent += to_send;
1712 while (!rc && sent < total);
1714 return rc;
1717 static gpg_error_t
1718 do_get (assuan_context_t ctx, char *line)
1720 struct client_s *client = assuan_get_pointer (ctx);
1721 gpg_error_t rc;
1722 struct xml_request_s *req;
1723 xmlNodePtr n;
1725 if (!line || !*line)
1726 return GPG_ERR_SYNTAX;
1728 rc = xml_new_request (client, line, XML_CMD_NONE, &req);
1729 if (rc)
1730 return rc;
1732 n = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
1733 if (!rc)
1735 if (n && n->children)
1737 xmlNodePtr tmp = n;
1739 n = xml_find_text_node (n->children);
1740 if (!n || !n->content || !*n->content)
1741 rc = GPG_ERR_NO_DATA;
1742 else
1744 rc = xfer_data (ctx, (char *) n->content, xmlStrlen (n->content));
1745 if (!rc)
1747 xmlChar *expire = xml_attribute_value (tmp,
1748 (xmlChar *)"expire");
1749 if (expire)
1751 time_t now = time (NULL);
1752 time_t e;
1753 char *p;
1755 errno = 0;
1756 e = strtoul ((char *)expire, &p, 10);
1757 if (errno || *p || e == ULONG_MAX || *expire == '-')
1758 log_write (_("invalid expire attribute value: %s"),
1759 expire);
1760 else if (now >= e)
1762 pthread_cleanup_push (xmlFree, expire);
1763 rc = send_status (ctx, STATUS_EXPIRE, "%lu 0", e);
1764 pthread_cleanup_pop (0);
1767 xmlFree (expire);
1772 else
1773 rc = GPG_ERR_NO_DATA;
1776 xml_free_request (req);
1777 return rc;
1780 static gpg_error_t
1781 get_command (assuan_context_t ctx, char *line)
1783 struct client_s *client = assuan_get_pointer (ctx);
1784 gpg_error_t rc;
1785 struct argv_s *args[] = {
1786 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1787 NULL
1790 rc = parse_options (&line, args, client, 1);
1791 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
1792 rc = GPG_ERR_SYNTAX;
1793 if (rc)
1794 return send_error (ctx, rc);
1796 if (client->opts & OPT_INQUIRE)
1798 unsigned char *result;
1799 size_t len;
1801 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1802 if (rc)
1803 return send_error (ctx, rc);
1805 pthread_cleanup_push ((void *)xfree, result);
1806 rc = do_get (ctx, (char *)result);
1807 pthread_cleanup_pop (1);
1809 else
1810 rc = do_get (ctx, line);
1812 return send_error (ctx, rc);
1815 static void list_command_free1 (void *arg);
1816 static gpg_error_t
1817 realpath_command (assuan_context_t ctx, char *line)
1819 gpg_error_t rc;
1820 char **realpath = NULL;
1821 struct client_s *client = assuan_get_pointer (ctx);
1822 struct argv_s *args[] = {
1823 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
1824 NULL
1827 rc = parse_options (&line, args, client, 1);
1828 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
1829 rc = GPG_ERR_SYNTAX;
1830 if (rc)
1831 return send_error (ctx, rc);
1833 if (client->opts & OPT_INQUIRE)
1835 unsigned char *result;
1836 size_t len;
1838 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
1839 if (rc)
1840 return send_error (ctx, rc);
1842 pthread_cleanup_push ((void *)xfree, result);
1843 (void)xml_resolve_path (client, client->doc, result, &realpath, &rc);
1844 pthread_cleanup_pop (1);
1846 else
1847 (void)xml_resolve_path (client, client->doc, (unsigned char *)line,
1848 &realpath, &rc);
1850 if (!rc)
1852 char *tmp = strv_join ((char *)"\t", realpath);
1854 strv_free (realpath);
1855 if (!tmp)
1856 return send_error (ctx, GPG_ERR_ENOMEM);
1858 pthread_cleanup_push ((void *)xfree, tmp);
1859 rc = xfer_data (ctx, tmp, strlen (tmp));
1860 pthread_cleanup_pop (1);
1863 return send_error (ctx, rc);
1866 static void
1867 list_command_free1 (void *arg)
1869 if (arg)
1870 string_free ((struct string_s *) arg, 1);
1873 static gpg_error_t
1874 parse_list_opt_recurse (void *data, void *value)
1876 struct client_s *client = data;
1878 (void)value;
1879 client->opts |= OPT_LIST_RECURSE;
1880 return 0;
1883 static gpg_error_t
1884 parse_opt_verbose (void *data, void *value)
1886 struct client_s *client = data;
1888 (void)value;
1889 client->opts |= OPT_VERBOSE;
1890 return 0;
1893 static gpg_error_t
1894 list_path_once (struct client_s *client, char *line,
1895 struct element_list_s *elements, struct string_s *result)
1897 gpg_error_t rc;
1899 rc = xml_create_path_list (client, client->doc, NULL, elements, line, 0);
1900 if (rc == GPG_ERR_ELOOP || rc == GPG_ERR_EACCES)
1901 rc = 0;
1903 if (!rc)
1905 int total = slist_length (elements->list);
1907 if (total)
1909 int i;
1911 for (i = 0; i < total; i++)
1913 char *tmp = slist_nth_data (elements->list, i);
1915 string_append_printf (result, "%s%s", tmp,
1916 i + 1 == total ? "" : "\n");
1919 else
1920 rc = GPG_ERR_NO_DATA;
1923 return rc;
1926 static gpg_error_t
1927 do_list (assuan_context_t ctx, char *line)
1929 struct client_s *client = assuan_get_pointer (ctx);
1930 gpg_error_t rc = GPG_ERR_NO_DATA;
1931 struct element_list_s *elements = NULL;
1933 if (!line || !*line)
1935 struct string_s *str = string_new (NULL);
1936 xmlNodePtr n;
1938 if (!str)
1939 return GPG_ERR_ENOMEM;
1941 pthread_cleanup_push ((void *)list_command_free1, str);
1942 n = xmlDocGetRootElement (client->doc);
1943 for (n = n->children; n; n = n->next)
1945 xmlChar *name;
1947 if (n->type != XML_ELEMENT_NODE)
1948 continue;
1950 name = xmlGetProp (n, (xmlChar *)"_name");
1951 if (!name)
1953 rc = GPG_ERR_ENOMEM;
1954 break;
1957 elements = xcalloc (1, sizeof (struct element_list_s));
1958 if (!elements)
1960 xmlFree (name);
1961 rc = GPG_ERR_ENOMEM;
1962 break;
1965 elements->prefix = string_new (NULL);
1966 if (!elements->prefix)
1968 xmlFree (name);
1969 xml_free_element_list (elements);
1970 rc = GPG_ERR_ENOMEM;
1971 break;
1974 elements->recurse = client->opts & OPT_LIST_RECURSE;
1975 elements->root_only = !elements->recurse;
1976 pthread_cleanup_push ((void *)xml_free_element_list, elements);
1977 rc = list_path_once (client, (char *)name, elements, str);
1978 xmlFree (name);
1979 pthread_cleanup_pop (1);
1980 if (rc)
1981 break;
1983 if (n->next)
1984 string_append (str, "\n");
1987 if (!rc)
1988 rc = xfer_data (ctx, str->str, str->len);
1990 pthread_cleanup_pop (1);
1991 return rc;
1994 elements = xcalloc (1, sizeof (struct element_list_s));
1995 if (!elements)
1996 return GPG_ERR_ENOMEM;
1998 elements->prefix = string_new (NULL);
1999 if (!elements->prefix)
2001 xml_free_element_list (elements);
2002 return GPG_ERR_ENOMEM;
2005 elements->recurse = client->opts & OPT_LIST_RECURSE;
2006 pthread_cleanup_push ((void *)xml_free_element_list, elements);
2007 struct string_s *str = string_new (NULL);
2008 pthread_cleanup_push ((void *)list_command_free1, str);
2009 rc = list_path_once (client, line, elements, str);
2010 if (!rc)
2011 rc = xfer_data (ctx, str->str, str->len);
2013 pthread_cleanup_pop (1);
2014 pthread_cleanup_pop (1);
2015 return rc;
2018 static gpg_error_t
2019 list_command (assuan_context_t ctx, char *line)
2021 struct client_s *client = assuan_get_pointer (ctx);
2022 gpg_error_t rc;
2023 struct argv_s *args[] = {
2024 &(struct argv_s) {"recurse", OPTION_TYPE_NOARG, parse_list_opt_recurse},
2025 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
2026 /* These are deprecated but kept for backward compatibility with older
2027 * clients. */
2028 &(struct argv_s) {"verbose", OPTION_TYPE_NOARG, NULL},
2029 &(struct argv_s) {"with-target", OPTION_TYPE_NOARG, NULL},
2030 &(struct argv_s) {"all", OPTION_TYPE_NOARG, parse_list_opt_recurse},
2031 &(struct argv_s) {"no-recurse", OPTION_TYPE_NOARG, NULL},
2032 NULL
2035 if (disable_list_and_dump == 1)
2036 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
2038 rc = parse_options (&line, args, client, 1);
2039 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
2040 rc = GPG_ERR_SYNTAX;
2041 if (rc)
2042 return send_error (ctx, rc);
2044 if (client->opts & OPT_INQUIRE)
2046 unsigned char *result;
2047 size_t len;
2049 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
2050 if (rc)
2051 return send_error (ctx, rc);
2053 pthread_cleanup_push ((void *)xfree, result);
2054 rc = do_list (ctx, (char *)result);
2055 pthread_cleanup_pop (1);
2057 else
2058 rc = do_list (ctx, line);
2060 return send_error (ctx, rc);
2063 #define RESUMABLE_ERROR(rc) (rc == GPG_ERR_ELOOP || rc == GPG_ERR_EACCES \
2064 || rc == GPG_ERR_ELEMENT_NOT_FOUND || !rc)
2066 * args[0] - element path
2068 static gpg_error_t
2069 attribute_list (assuan_context_t ctx, char **args)
2071 struct client_s *client = assuan_get_pointer (ctx);
2072 char **attrlist = NULL;
2073 int i = 0;
2074 int target = 0;
2075 xmlAttrPtr a;
2076 xmlNodePtr n, an, r;
2077 char *line;
2078 gpg_error_t rc;
2079 struct xml_request_s *req;
2081 if (!args || !args[0] || !*args[0])
2082 return GPG_ERR_SYNTAX;
2084 rc = xml_new_request (client, args[0], XML_CMD_ATTR_LIST, &req);
2085 if (rc)
2086 return rc;
2088 n = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
2089 xml_free_request (req);
2090 if (rc)
2091 return rc;
2093 gpg_error_t acl_rc = 0;
2094 again:
2095 acl_rc = xml_acl_check (client, n);
2096 for (a = n->properties; a; a = a->next)
2098 char **pa;
2099 int reserved = xml_reserved_attribute ((char *)a->name);
2101 if (acl_rc == GPG_ERR_EACCES && !reserved)
2102 continue;
2103 else if (acl_rc && acl_rc != GPG_ERR_EACCES)
2105 rc = acl_rc;
2106 break;
2109 if (reserved && target)
2110 continue;
2112 pa = xrealloc (attrlist, (i + 2) * sizeof (char *));
2113 if (!pa)
2115 log_write ("%s(%i): %s", __FILE__, __LINE__,
2116 pwmd_strerror (GPG_ERR_ENOMEM));
2117 rc = GPG_ERR_ENOMEM;
2118 break;
2121 attrlist = pa;
2122 an = a->children;
2123 attrlist[i] = str_asprintf ("%s %s", (char *) a->name, an && an->content
2124 ? (char *)an->content : "");
2126 if (!attrlist[i])
2128 log_write ("%s(%i): %s", __FILE__, __LINE__,
2129 pwmd_strerror (GPG_ERR_ENOMEM));
2130 rc = GPG_ERR_ENOMEM;
2131 break;
2134 attrlist[++i] = NULL;
2137 if (!rc && !attrlist)
2138 return GPG_ERR_NO_DATA;
2140 if (!rc && !target)
2142 r = xml_resolve_path (client, client->doc, (xmlChar *)args[0], NULL, &rc);
2143 if (RESUMABLE_ERROR (rc))
2145 rc = 0;
2146 if (r && r != n)
2148 target = 1;
2149 n = r;
2150 goto again;
2155 pthread_cleanup_push ((void *)req_free, attrlist);
2157 if (!rc)
2159 line = strv_join ("\n", attrlist);
2160 if (line)
2162 pthread_cleanup_push ((void *)xfree, line);
2163 rc = xfer_data (ctx, line, strlen (line));
2164 pthread_cleanup_pop (1);
2166 else
2168 log_write ("%s(%i): %s", __FILE__, __LINE__,
2169 pwmd_strerror (GPG_ERR_ENOMEM));
2170 rc = GPG_ERR_ENOMEM;
2174 pthread_cleanup_pop (1);
2175 return rc;
2179 * args[0] - attribute
2180 * args[1] - element path
2182 static gpg_error_t
2183 attribute_delete (struct client_s *client, char **args)
2185 gpg_error_t rc;
2186 xmlNodePtr n;
2188 if (!args || !args[0] || !*args[0] || !args[1] || !*args[1])
2189 return GPG_ERR_SYNTAX;
2191 if (!strcmp (args[0], "_name") || !strcmp (args[0], "target"))
2192 return GPG_ERR_INV_ATTR;
2194 rc = copy_on_write (client);
2195 if (rc)
2196 return rc;
2198 if (!xml_reserved_attribute (args[0]))
2199 n = xml_resolve_path (client, client->doc, (xmlChar *)args[1], NULL, &rc);
2200 else
2202 struct xml_request_s *req;
2204 rc = xml_new_request (client, args[1], XML_CMD_ATTR, &req);
2205 if (rc)
2206 return rc;
2208 n = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
2209 xml_free_request (req);
2212 if (!rc)
2213 rc = xml_is_element_owner (client, n);
2215 if (!rc)
2216 rc = xml_delete_attribute (client, n, (xmlChar *) args[0]);
2218 return rc;
2222 * Creates the "target" attribute. When other commands encounter an element
2223 * with this attribute they follow the "target" after appending remaining
2224 * elements from the original element path to the target. The exception is the
2225 * ATTR command that operates on the element itself (for reserved attribute
2226 * names) and not the target.
2228 * If the source element path doesn't exist when using 'ATTR SET target', it is
2229 * created, but the destination element path must exist. This is simliar to the
2230 * ls(1) command: ln -s src dst.
2232 * args[0] - source element path
2233 * args[1] - destination element path
2235 static gpg_error_t
2236 set_target_attribute (struct client_s *client, char **args)
2238 struct xml_request_s *req = NULL;
2239 char **src, **dst;
2240 gpg_error_t rc;
2241 xmlNodePtr n;
2243 if (!args || !args[0] || !args[1])
2244 return GPG_ERR_SYNTAX;
2246 src = str_split (args[0], "\t", 0);
2247 if (!src)
2248 return GPG_ERR_SYNTAX;
2250 if (!xml_valid_element_path (src, 0))
2252 strv_free (src);
2253 return GPG_ERR_INV_VALUE;
2256 dst = str_split (args[1], "\t", 0);
2257 if (!dst)
2259 strv_free (src);
2260 return GPG_ERR_SYNTAX;
2263 rc = copy_on_write (client);
2264 if (rc)
2265 goto fail;
2267 // Be sure the destination element path exists. */
2268 rc = xml_new_request (client, args[1], XML_CMD_NONE, &req);
2269 if (rc)
2270 goto fail;
2272 (void)xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
2273 if (rc && rc != GPG_ERR_EACCES)
2274 goto fail;
2276 xml_free_request (req);
2277 req = NULL;
2279 if (!strcmp (args[0], args[1]))
2281 rc = GPG_ERR_EEXIST;
2282 goto fail;
2285 rc = xml_new_request (client, args[0], XML_CMD_ATTR_TARGET, &req);
2286 if (rc)
2287 goto fail;
2289 n = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
2290 if (rc && rc != GPG_ERR_EACCES)
2291 goto fail;
2293 if (!rc)
2295 rc = xml_add_attribute (client, n, "target", args[1]);
2296 if (!rc)
2298 rc = xml_remove_user_attributes (client, n);
2299 if (!rc)
2300 rc = xml_unlink_node (client, n->children);
2304 fail:
2305 strv_free (src);
2306 strv_free (dst);
2307 xml_free_request (req);
2308 return rc;
2312 * args[0] - attribute
2313 * args[1] - element path
2315 static gpg_error_t
2316 attribute_get (assuan_context_t ctx, char **args)
2318 struct client_s *client = assuan_get_pointer (ctx);
2319 xmlNodePtr n;
2320 xmlChar *a;
2321 gpg_error_t rc;
2322 struct xml_request_s *req;
2324 if (!args || !args[0] || !*args[0] || !args[1] || !*args[1])
2325 return GPG_ERR_SYNTAX;
2327 if (!xml_reserved_attribute (args[0]))
2328 n = xml_resolve_path (client, client->doc, (xmlChar *)args[1], NULL, &rc);
2329 else
2331 rc = xml_new_request (client, args[1], XML_CMD_ATTR, &req);
2332 if (rc)
2333 return rc;
2335 n = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
2336 xml_free_request (req);
2339 if (rc)
2340 return rc;
2342 a = xmlGetProp (n, (xmlChar *) args[0]);
2343 if (!a)
2344 return GPG_ERR_NOT_FOUND;
2346 pthread_cleanup_push ((void *)xmlFree, a);
2348 if (*a)
2349 rc = xfer_data (ctx, (char *) a, xmlStrlen (a));
2350 else
2351 rc = GPG_ERR_NO_DATA;
2353 pthread_cleanup_pop (1);
2354 return rc;
2358 * args[0] - attribute
2359 * args[1] - element path
2360 * args[2] - value
2362 static gpg_error_t
2363 attribute_set (struct client_s *client, char **args)
2365 struct xml_request_s *req;
2366 gpg_error_t rc;
2367 xmlNodePtr n;
2369 if (!args || !args[0] || !args[1])
2370 return GPG_ERR_SYNTAX;
2373 * Reserved attribute names.
2375 if (!strcmp (args[0], "_name")) // Use the RENAME command instead
2376 return GPG_ERR_INV_ATTR;
2377 else if (!strcmp (args[0], "target"))
2378 return set_target_attribute (client, args + 1);
2379 else if (!xml_valid_attribute (args[0]))
2380 return GPG_ERR_INV_VALUE;
2382 if (!xml_valid_attribute_value (args[2]))
2383 return GPG_ERR_INV_VALUE;
2385 rc = copy_on_write (client);
2386 if (rc)
2387 return rc;
2389 if (!xml_reserved_attribute (args[0]))
2391 n = xml_resolve_path (client, client->doc, (xmlChar *)args[1], NULL, &rc);
2392 if (!rc)
2394 rc = xml_new_request (client, args[1], XML_CMD_NONE, &req);
2395 if (!rc)
2397 rc = xml_check_recursion (client, req);
2398 xml_free_request (req);
2402 else
2404 rc = xml_new_request (client, args[1], XML_CMD_ATTR, &req);
2405 if (rc)
2406 return rc;
2408 n = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
2409 xml_free_request (req);
2412 if (!rc)
2413 rc = xml_is_element_owner (client, n);
2415 if (!rc)
2416 rc = xml_add_attribute (client, n, args[0], args[2]);
2418 return rc;
2422 * req[0] - command
2423 * req[1] - attribute name or element path if command is LIST
2424 * req[2] - element path
2425 * req[2] - element path or value
2428 static gpg_error_t
2429 do_attr (assuan_context_t ctx, char *line)
2431 struct client_s *client = assuan_get_pointer (ctx);
2432 gpg_error_t rc = 0;
2433 char **req;
2435 if (!line || !*line)
2436 return GPG_ERR_SYNTAX;
2438 req = str_split (line, " ", 4);
2439 if (!req || !req[0] || !req[1])
2441 strv_free (req);
2442 return GPG_ERR_SYNTAX;
2445 pthread_cleanup_push ((void *)req_free, req);
2447 if (strcasecmp (req[0], "SET") == 0)
2448 rc = attribute_set (client, req + 1);
2449 else if (strcasecmp (req[0], "GET") == 0)
2450 rc = attribute_get (ctx, req + 1);
2451 else if (strcasecmp (req[0], "DELETE") == 0)
2452 rc = attribute_delete (client, req + 1);
2453 else if (strcasecmp (req[0], "LIST") == 0)
2454 rc = attribute_list (ctx, req + 1);
2455 else
2456 rc = GPG_ERR_SYNTAX;
2458 client->flags &= ~(FLAG_ACL_IGNORE|FLAG_ACL_ERROR);
2459 pthread_cleanup_pop (1);
2460 return rc;
2463 static gpg_error_t
2464 attr_command (assuan_context_t ctx, char *line)
2466 struct client_s *client = assuan_get_pointer (ctx);
2467 gpg_error_t rc;
2468 struct argv_s *args[] = {
2469 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
2470 NULL
2473 rc = parse_options (&line, args, client, 1);
2474 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
2475 rc = GPG_ERR_SYNTAX;
2476 if (rc)
2477 return send_error (ctx, rc);
2479 if (client->opts & OPT_INQUIRE)
2481 unsigned char *result;
2482 size_t len;
2484 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
2485 if (rc)
2486 return send_error (ctx, rc);
2488 pthread_cleanup_push ((void *)xfree, result);
2489 rc = do_attr (ctx, (char *)result);
2490 pthread_cleanup_pop (1);
2492 else
2493 rc = do_attr (ctx, line);
2495 return send_error (ctx, rc);
2498 static gpg_error_t
2499 parse_iscached_opt_lock (void *data, void *value)
2501 struct client_s *client = data;
2503 (void) value;
2504 client->opts |= OPT_LOCK;
2505 return 0;
2508 static gpg_error_t
2509 parse_iscached_opt_agent (void *data, void *value)
2511 struct client_s *client = data;
2513 (void) value;
2514 client->opts |= OPT_CACHE_AGENT;
2515 return 0;
2518 static gpg_error_t
2519 parse_iscached_opt_sign (void *data, void *value)
2521 struct client_s *client = data;
2523 (void) value;
2524 client->opts |= OPT_CACHE_SIGN;
2525 return 0;
2528 static gpg_error_t
2529 iscached_command (assuan_context_t ctx, char *line)
2531 struct client_s *client = assuan_get_pointer (ctx);
2532 gpg_error_t rc;
2533 int defer = 0;
2534 struct argv_s *args[] = {
2535 &(struct argv_s) {"lock", OPTION_TYPE_NOARG, parse_iscached_opt_lock},
2536 &(struct argv_s) {"agent", OPTION_TYPE_NOARG, parse_iscached_opt_agent},
2537 &(struct argv_s) {"sign", OPTION_TYPE_NOARG, parse_iscached_opt_sign},
2538 NULL
2541 if (!line || !*line)
2542 return send_error (ctx, GPG_ERR_SYNTAX);
2544 rc = parse_options (&line, args, client, 1);
2545 if (rc)
2546 return send_error (ctx, rc);
2547 else if (!valid_filename (line))
2548 return send_error (ctx, GPG_ERR_INV_VALUE);
2550 if (!(client->flags & FLAG_OPEN)
2551 && ((client->opts & OPT_CACHE_AGENT) || (client->opts & OPT_CACHE_SIGN)))
2552 return send_error (ctx, GPG_ERR_INV_STATE);
2554 rc = cache_iscached (line, &defer, (client->opts & OPT_CACHE_AGENT),
2555 (client->opts & OPT_CACHE_SIGN));
2556 if (!rc && defer)
2557 rc = GPG_ERR_NO_DATA;
2559 if (!rc)
2561 struct cache_data_s *cdata = cache_get_data (line, NULL);
2563 if (cdata)
2565 rc = validate_checksum (client, line, cdata, NULL, NULL, 1);
2566 if (rc == GPG_ERR_CHECKSUM)
2567 rc = GPG_ERR_NO_DATA;
2571 if (client->opts & OPT_LOCK
2572 && (!rc || gpg_err_code (rc) == GPG_ERR_NO_DATA
2573 || gpg_err_code (rc) == GPG_ERR_ENOENT))
2575 gpg_error_t trc = rc;
2577 if (client->filename && strcmp (line, client->filename))
2578 reset_client (client);
2580 xfree (client->filename);
2581 client->filename = str_dup (line);
2582 rc = do_lock (client, 1);
2583 if (!rc)
2584 rc = trc;
2587 return send_error (ctx, rc);
2590 static gpg_error_t
2591 clearcache_command (assuan_context_t ctx, char *line)
2593 struct client_s *client = assuan_get_pointer (ctx);
2594 gpg_error_t rc = 0, all_rc = 0;
2595 int i;
2596 int t;
2597 int all = 0;
2598 struct client_thread_s *once = NULL;
2599 unsigned count;
2601 cache_lock ();
2602 pthread_cleanup_push (cache_release_mutex, NULL);
2603 count = cache_file_count ();
2604 MUTEX_LOCK (&cn_mutex);
2605 pthread_cleanup_push ((void *)release_mutex_cb, &cn_mutex);
2607 if (!line || !*line)
2608 all = 1;
2610 t = slist_length (cn_thread_list);
2612 for (i = 0; i < t; i++)
2614 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
2615 assuan_peercred_t peer;
2617 if (!thd->cl)
2618 continue;
2620 /* Lock each connected clients' file mutex to prevent any other client
2621 * from accessing the cache entry (the file mutex is locked upon
2622 * command startup). The cache for the entry is not cleared if the
2623 * file mutex is locked by another client to prevent this function
2624 * from blocking. Rather, it returns an error.
2626 if (all)
2628 if (thd->cl->filename)
2630 rc = do_validate_peer (ctx, thd->cl->filename, &peer);
2631 /* The current client doesn't have permission to open the other
2632 * filename do to "access" configuration parameter in a filename
2633 * section. Since we are clearning all cache entries the error
2634 * will be returned later during cache_clear(). */
2635 if (rc)
2637 rc = 0;
2638 continue;
2641 else // Idle client without opened file?
2642 continue;
2644 rc = cache_lock_mutex (thd->cl->ctx, thd->cl->filename, -1, 0, -1);
2645 if (gpg_err_code (rc) == GPG_ERR_LOCKED)
2647 /* The current client owns the lock. */
2648 if (pthread_equal (pthread_self (), thd->tid))
2649 rc = 0;
2650 else
2652 if (cache_iscached (thd->cl->filename, NULL, 0, 0)
2653 == GPG_ERR_NO_DATA)
2655 rc = 0;
2656 continue;
2659 /* The cache entry will be cleared when the other client
2660 * disconnects and cache_timer_thread() does its thing. */
2661 cache_defer_clear (thd->cl->filename);
2664 else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
2666 rc = 0;
2667 continue;
2670 if (!rc)
2672 rc = cache_clear (NULL, thd->cl->filename, 1, 0);
2673 cache_unlock_mutex (thd->cl->filename, 0);
2676 if (rc)
2677 all_rc = rc;
2679 rc = 0;
2681 else
2683 /* A single data filename was specified. Lock only this data file
2684 * mutex and free the cache entry. */
2685 rc = do_validate_peer (ctx, line, &peer);
2686 if (rc == GPG_ERR_FORBIDDEN)
2687 rc = peer_is_invoker (client);
2689 if (rc == GPG_ERR_EACCES)
2690 rc = GPG_ERR_FORBIDDEN;
2692 if (!rc && thd->cl->filename && !strcmp (thd->cl->filename , line))
2694 rc = cache_lock_mutex (thd->cl->ctx, thd->cl->filename, -1, 0, -1);
2695 if (gpg_err_code (rc) == GPG_ERR_LOCKED)
2697 /* The current client owns the lock. */
2698 if (pthread_equal (pthread_self (), thd->tid))
2699 rc = 0;
2702 if (!rc)
2704 once = thd;
2705 rc = cache_clear (NULL, thd->cl->filename, 1, 0);
2706 cache_unlock_mutex (thd->cl->filename, 0);
2708 else
2709 cache_defer_clear (thd->cl->filename);
2711 /* Found a client with the opened file. The cache entry has been
2712 * either cleared (self) or defered to be cleared. */
2713 break;
2718 /* Only connected clients' cache entries have been cleared. Now clear any
2719 * remaining cache entries without clients but only if there wasn't an
2720 * error from above since this would defeat the locking check of the
2721 * remaining entries. */
2722 if (all && !all_rc && cache_file_count ())
2724 rc = cache_clear (client, NULL, 1, 0);
2725 if (rc == GPG_ERR_EACCES)
2726 rc = GPG_ERR_FORBIDDEN;
2729 /* No clients are using the specified file. */
2730 else if (!all_rc && !rc && !once)
2731 rc = cache_clear (NULL, line, 1, 0);
2733 /* Release the connection mutex. */
2734 pthread_cleanup_pop (1);
2736 if (!rc || (cache_file_count () && count != cache_file_count ()))
2737 send_status_all (STATUS_CACHE, NULL);
2739 /* Release the cache mutex. */
2740 pthread_cleanup_pop (1);
2742 /* One or more files were locked while clearing all cache entries. */
2743 if (all_rc)
2744 rc = all_rc;
2746 return send_error (ctx, rc);
2749 static gpg_error_t
2750 cachetimeout_command (assuan_context_t ctx, char *line)
2752 struct client_s *client = assuan_get_pointer (ctx);
2753 long timeout;
2754 char **req = str_split (line, " ", 0);
2755 char *p;
2756 gpg_error_t rc = 0;
2758 if (!(client->flags & FLAG_OPEN))
2759 return send_error (ctx, GPG_ERR_INV_STATE);
2761 if (!req || !*req || strv_length (req) > 1)
2763 strv_free (req);
2764 return send_error (ctx, GPG_ERR_SYNTAX);
2767 errno = 0;
2768 timeout = strtol (req[0], &p, 10);
2769 if (errno != 0 || *p || timeout < (long)-1)
2770 rc = GPG_ERR_SYNTAX;
2772 if (!rc)
2774 rc = cache_set_timeout (client->filename, timeout);
2775 if (!rc || gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
2777 rc = 0;
2778 MUTEX_LOCK (&rcfile_mutex);
2779 config_set_long_param (&global_config, client->filename,
2780 "cache_timeout", req[0]);
2781 MUTEX_UNLOCK (&rcfile_mutex);
2785 strv_free (req);
2786 return send_error (ctx, rc);
2789 static gpg_error_t
2790 dump_command (assuan_context_t ctx, char *line)
2792 xmlChar *xml;
2793 int len;
2794 struct client_s *client = assuan_get_pointer (ctx);
2795 gpg_error_t rc;
2797 if (disable_list_and_dump == 1)
2798 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
2800 if (line && *line)
2801 return send_error (ctx, GPG_ERR_SYNTAX);
2803 rc = peer_is_invoker(client);
2804 if (rc)
2805 return send_error (ctx, (rc == GPG_ERR_EACCES ? GPG_ERR_FORBIDDEN : rc));
2807 xmlDocDumpFormatMemory (client->doc, &xml, &len, 1);
2809 if (!xml)
2811 log_write ("%s(%i): %s", __FILE__, __LINE__,
2812 pwmd_strerror (GPG_ERR_ENOMEM));
2813 return send_error (ctx, GPG_ERR_ENOMEM);
2816 pthread_cleanup_push ((void *)xmlFree, xml);
2817 rc = xfer_data (ctx, (char *) xml, len);
2818 pthread_cleanup_pop (1);
2819 return send_error (ctx, rc);
2822 static gpg_error_t
2823 getconfig_command (assuan_context_t ctx, char *line)
2825 struct client_s *client = assuan_get_pointer (ctx);
2826 gpg_error_t rc = 0;
2827 char filename[255] = { 0 }, param[747] = { 0 };
2828 char *p, *tmp = NULL, *fp = client->filename, *paramp = line;
2830 if (!line || !*line)
2831 return send_error (ctx, GPG_ERR_SYNTAX);
2833 if (strchr (line, ' '))
2835 int ret = sscanf (line, " %254[^ ] %746c", filename, param);
2837 if (ret <= 0)
2838 return send_error (ctx, gpg_error_from_syserror());
2839 paramp = param;
2840 fp = filename;
2843 if (fp && !valid_filename (fp))
2844 return send_error (ctx, GPG_ERR_INV_VALUE);
2846 paramp = str_down (paramp);
2847 p = config_get_value (fp ? fp : "global", paramp);
2848 if (!p)
2849 return send_error (ctx, GPG_ERR_UNKNOWN_OPTION);
2851 tmp = expand_homedir (p);
2852 xfree (p);
2853 if (!tmp)
2855 log_write ("%s(%i): %s", __FILE__, __LINE__,
2856 pwmd_strerror (GPG_ERR_ENOMEM));
2857 return send_error (ctx, GPG_ERR_ENOMEM);
2860 p = tmp;
2861 pthread_cleanup_push ((void *)xfree, p);
2862 rc = xfer_data (ctx, p, strlen (p));
2863 pthread_cleanup_pop (1);
2864 return send_error (ctx, rc);
2867 struct xpath_s
2869 xmlXPathContextPtr xp;
2870 xmlXPathObjectPtr result;
2871 xmlBufferPtr buf;
2872 char **req;
2875 static void
2876 xpath_command_free (void *arg)
2878 struct xpath_s *xpath = arg;
2880 if (!xpath)
2881 return;
2883 req_free (xpath->req);
2885 if (xpath->buf)
2886 xmlBufferFree (xpath->buf);
2888 if (xpath->result)
2889 xmlXPathFreeObject (xpath->result);
2891 if (xpath->xp)
2892 xmlXPathFreeContext (xpath->xp);
2895 static gpg_error_t
2896 do_xpath (assuan_context_t ctx, char *line)
2898 gpg_error_t rc;
2899 struct client_s *client = assuan_get_pointer (ctx);
2900 struct xpath_s _x = { 0 };
2901 struct xpath_s *xpath = &_x;
2903 if (!line || !*line)
2904 return GPG_ERR_SYNTAX;
2906 if ((xpath->req = str_split (line, "\t", 2)) == NULL)
2908 if (strv_printf (&xpath->req, "%s", line) == 0)
2909 return GPG_ERR_ENOMEM;
2912 if (xpath->req[1])
2914 rc = copy_on_write (client);
2915 if (rc)
2916 goto fail;
2919 xpath->xp = xmlXPathNewContext (client->doc);
2920 if (!xpath->xp)
2922 rc = GPG_ERR_BAD_DATA;
2923 goto fail;
2926 xpath->result =
2927 xmlXPathEvalExpression ((xmlChar *) xpath->req[0], xpath->xp);
2928 if (!xpath->result)
2930 rc = GPG_ERR_BAD_DATA;
2931 goto fail;
2934 if (xmlXPathNodeSetIsEmpty (xpath->result->nodesetval))
2936 rc = GPG_ERR_ELEMENT_NOT_FOUND;
2937 goto fail;
2940 rc = xml_recurse_xpath_nodeset (client, client->doc,
2941 xpath->result->nodesetval,
2942 (xmlChar *) xpath->req[1], &xpath->buf, 0,
2943 NULL);
2944 if (rc)
2945 goto fail;
2946 else if (!xpath->req[1] && !xmlBufferLength (xpath->buf))
2948 rc = GPG_ERR_NO_DATA;
2949 goto fail;
2951 else if (xpath->req[1])
2953 rc = 0;
2954 goto fail;
2957 pthread_cleanup_push ((void *)xpath_command_free, &xpath);
2958 rc = xfer_data (ctx, (char *) xmlBufferContent (xpath->buf),
2959 xmlBufferLength (xpath->buf));
2960 pthread_cleanup_pop (0);
2961 fail:
2962 xpath_command_free (xpath);
2963 return rc;
2966 static gpg_error_t
2967 xpath_command (assuan_context_t ctx, char *line)
2969 struct client_s *client = assuan_get_pointer (ctx);
2970 gpg_error_t rc;
2971 struct argv_s *args[] = {
2972 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
2973 NULL
2976 if (disable_list_and_dump == 1)
2977 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
2979 rc = peer_is_invoker(client);
2980 if (rc)
2981 return send_error (ctx, (rc == GPG_ERR_EACCES ? GPG_ERR_FORBIDDEN : rc));
2983 rc = parse_options (&line, args, client, 1);
2984 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
2985 rc = GPG_ERR_SYNTAX;
2986 if (rc)
2987 return send_error (ctx, rc);
2989 if (client->opts & OPT_INQUIRE)
2991 unsigned char *result;
2992 size_t len;
2994 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
2995 if (rc)
2996 return send_error (ctx, rc);
2998 pthread_cleanup_push ((void *)xfree, result);
2999 rc = do_xpath (ctx, (char *)result);
3000 pthread_cleanup_pop (1);
3002 else
3003 rc = do_xpath (ctx, line);
3005 return send_error (ctx, rc);
3008 static gpg_error_t
3009 do_xpathattr (assuan_context_t ctx, char *line)
3011 struct client_s *client = assuan_get_pointer (ctx);
3012 gpg_error_t rc;
3013 char **req = NULL;
3014 int cmd = 0; //SET
3015 struct xpath_s _x = { 0 };
3016 struct xpath_s *xpath = &_x;
3018 if (!line || !*line)
3019 return GPG_ERR_SYNTAX;
3021 if ((req = str_split (line, " ", 3)) == NULL)
3022 return GPG_ERR_ENOMEM;
3024 if (!req[0])
3026 rc = GPG_ERR_SYNTAX;
3027 goto fail;
3030 if (!strcasecmp (req[0], "SET"))
3031 cmd = 0;
3032 else if (!strcasecmp (req[0], "DELETE"))
3033 cmd = 1;
3034 else
3036 rc = GPG_ERR_SYNTAX;
3037 goto fail;
3040 if (!req[1] || !req[2])
3042 rc = GPG_ERR_SYNTAX;
3043 goto fail;
3046 if ((xpath->req = str_split (req[2], "\t", 3)) == NULL)
3048 rc = GPG_ERR_ENOMEM;
3049 goto fail;
3052 if (!xpath->req[0] || (!xpath->req[1] && !cmd) || (xpath->req[1] && cmd))
3054 rc = GPG_ERR_SYNTAX;
3055 goto fail;
3058 rc = copy_on_write (client);
3059 if (rc)
3060 goto fail;
3062 xpath->xp = xmlXPathNewContext (client->doc);
3063 if (!xpath->xp)
3065 rc = GPG_ERR_BAD_DATA;
3066 goto fail;
3069 xpath->result = xmlXPathEvalExpression ((xmlChar *) xpath->req[0], xpath->xp);
3070 if (!xpath->result)
3072 rc = GPG_ERR_BAD_DATA;
3073 goto fail;
3076 if (xmlXPathNodeSetIsEmpty (xpath->result->nodesetval))
3078 rc = GPG_ERR_ELEMENT_NOT_FOUND;
3079 goto fail;
3082 rc = xml_recurse_xpath_nodeset (client, client->doc,
3083 xpath->result->nodesetval,
3084 (xmlChar *) xpath->req[1], &xpath->buf, cmd,
3085 (xmlChar *) req[1]);
3087 fail:
3088 xpath_command_free (xpath);
3089 strv_free (req);
3090 return rc;
3093 /* XPATHATTR SET|DELETE <name> <expression>[<TAB>[value]] */
3094 static gpg_error_t
3095 xpathattr_command (assuan_context_t ctx, char *line)
3097 struct client_s *client = assuan_get_pointer (ctx);
3098 gpg_error_t rc;
3099 struct argv_s *args[] = {
3100 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
3101 NULL
3104 if (disable_list_and_dump == 1)
3105 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
3107 rc = peer_is_invoker(client);
3108 if (rc)
3109 return send_error (ctx, (rc == GPG_ERR_EACCES ? GPG_ERR_FORBIDDEN : rc));
3111 rc = parse_options (&line, args, client, 1);
3112 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
3113 rc = GPG_ERR_SYNTAX;
3114 if (rc)
3115 return send_error (ctx, rc);
3117 if (client->opts & OPT_INQUIRE)
3119 unsigned char *result;
3120 size_t len;
3122 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3123 if (rc)
3124 return send_error (ctx, rc);
3126 pthread_cleanup_push ((void *)xfree, result);
3127 rc = do_xpathattr (ctx, (char *)result);
3128 pthread_cleanup_pop (1);
3130 else
3131 rc = do_xpathattr (ctx, line);
3133 return send_error (ctx, rc);
3136 static gpg_error_t
3137 do_import (struct client_s *client, const char *root_element,
3138 unsigned char *content)
3140 xmlDocPtr doc = NULL;
3141 xmlNodePtr n = NULL, root;
3142 gpg_error_t rc = 0;
3143 struct string_s *str = NULL, *tstr = NULL;
3144 struct xml_request_s *req = NULL;
3146 if (!content || !*content)
3147 return GPG_ERR_SYNTAX;
3149 if (root_element)
3151 rc = xml_new_request (client, root_element, XML_CMD_STORE, &req);
3152 if (rc)
3154 xfree (content);
3155 return rc;
3158 if (!xml_valid_element_path (req->args, 0))
3160 xml_free_request (req);
3161 xfree (content);
3162 return GPG_ERR_INV_VALUE;
3166 str = string_new_content ((char *)content);
3167 tstr = string_prepend (str, "<pwmd>");
3168 if (tstr)
3170 str = tstr;
3171 tstr = string_append (str, "</pwmd>");
3172 if (!tstr)
3173 rc = GPG_ERR_ENOMEM;
3174 else
3175 str = tstr;
3177 else
3178 rc = GPG_ERR_ENOMEM;
3180 if (rc)
3181 goto fail;
3183 doc = xmlReadDoc ((xmlChar *) str->str, NULL, "UTF-8", XML_PARSE_NOBLANKS);
3184 string_free (str, 1);
3185 if (!doc)
3187 rc = GPG_ERR_BAD_DATA;
3188 goto fail;
3191 root = xmlDocGetRootElement (doc);
3192 root = root->children;
3193 if (root->type != XML_ELEMENT_NODE)
3195 rc = GPG_ERR_BAD_DATA;
3196 goto fail;
3199 rc = xml_validate_import (client, root);
3200 if (rc)
3201 goto fail;
3203 if (req)
3205 /* Create the new specified root element path, if needed. */
3206 n = xml_find_elements (client, req, xmlDocGetRootElement (req->doc),
3207 &rc);
3208 if (rc)
3209 goto fail;
3211 /* Overwrite the children of the specified root element path. */
3212 (void)xml_unlink_node (client, n->children);
3213 n->children = NULL;
3215 else
3216 n = xmlDocGetRootElement (client->doc);
3218 if (n)
3220 xmlNodePtr copy;
3221 xmlChar *name = xml_attribute_value (root, (xmlChar *)"_name");
3223 if (!name)
3224 rc = GPG_ERR_BAD_DATA;
3225 else if (!req)
3227 /* No --root argument passed. Overwrite the current documents' root
3228 * element matching the root element of the imported data. */
3229 xml_free_request (req);
3230 req = NULL;
3231 rc = xml_new_request (client, (char *)name, XML_CMD_DELETE, &req);
3232 xmlFree (name);
3233 if (!rc)
3235 xmlNodePtr tmp;
3237 tmp = xml_find_elements (client, req,
3238 xmlDocGetRootElement (req->doc), &rc);
3239 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3240 goto fail;
3242 if (!rc)
3243 (void)xml_unlink_node (client, tmp);
3245 rc = 0;
3249 if (!rc)
3251 copy = xmlCopyNodeList (root);
3252 if (!copy)
3253 rc = GPG_ERR_ENOMEM;
3254 else
3256 n = xmlAddChildList (n, copy);
3257 if (!n)
3258 rc = GPG_ERR_ENOMEM;
3263 if (!rc && n && n->parent)
3264 rc = xml_update_element_mtime (client, n->parent);
3266 fail:
3267 xml_free_request (req);
3269 if (doc)
3270 xmlFreeDoc (doc);
3272 return rc;
3275 static gpg_error_t
3276 parse_import_opt_root (void *data, void *value)
3278 struct client_s *client = data;
3280 client->import_root = str_dup (value);
3281 return client->import_root ? 0 : GPG_ERR_ENOMEM;
3284 static gpg_error_t
3285 import_command (assuan_context_t ctx, char *line)
3287 gpg_error_t rc;
3288 struct client_s *client = assuan_get_pointer (ctx);
3289 unsigned char *result;
3290 size_t len;
3291 struct argv_s *args[] = {
3292 &(struct argv_s) {"root", OPTION_TYPE_ARG, parse_import_opt_root},
3293 NULL
3296 xfree (client->import_root);
3297 client->import_root = NULL;
3298 rc = parse_options (&line, args, client, client->bulk_p ? 1 : 0);
3299 if (rc)
3300 return send_error (ctx, rc);
3302 rc = copy_on_write (client);
3303 if (rc)
3304 return send_error (ctx, rc);
3306 if (!client->bulk_p)
3308 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3309 if (rc)
3311 xfree (client->import_root);
3312 client->import_root = NULL;
3313 return send_error (ctx, rc);
3315 rc = do_import (client, client->import_root, result);
3317 else
3319 char *p = str_dup (line);
3321 if (!p)
3322 rc = GPG_ERR_ENOMEM;
3323 else
3324 rc = do_import (client, client->import_root, (unsigned char *)p);
3327 xfree (client->import_root);
3328 client->import_root = NULL;
3329 return send_error (ctx, rc);
3332 static gpg_error_t
3333 do_lock (struct client_s *client, int add)
3335 gpg_error_t rc = lock_file_mutex (client, add);
3337 if (!rc)
3338 client->flags |= FLAG_LOCK_CMD;
3340 return rc;
3343 static gpg_error_t
3344 lock_command (assuan_context_t ctx, char *line)
3346 struct client_s *client = assuan_get_pointer (ctx);
3347 gpg_error_t rc;
3349 if (line && *line)
3350 return send_error (ctx, GPG_ERR_SYNTAX);
3352 rc = do_lock (client, 0);
3353 return send_error (ctx, rc);
3356 static gpg_error_t
3357 unlock_command (assuan_context_t ctx, char *line)
3359 struct client_s *client = assuan_get_pointer (ctx);
3360 gpg_error_t rc;
3362 if (line && *line)
3363 return send_error (ctx, GPG_ERR_SYNTAX);
3365 rc = unlock_file_mutex (client, 0);
3366 return send_error (ctx, rc);
3369 static void
3370 set_env (const char *name, char *buf, size_t size, const char *value)
3372 MUTEX_LOCK (&rcfile_mutex);
3373 if (!value || !*value)
3375 unsetenv (name);
3376 buf[0] = 0;
3378 else if (!buf[0] || strcmp (buf, value))
3380 snprintf (buf, size, "%s=%s", name, value);
3381 putenv (buf);
3384 MUTEX_UNLOCK (&rcfile_mutex);
3387 static gpg_error_t
3388 option_command (assuan_context_t ctx, char *line)
3390 struct client_s *client = assuan_get_pointer (ctx);
3391 gpg_error_t rc = 0;
3392 char namebuf[255] = { 0 };
3393 char *name = namebuf;
3394 char *value = NULL, *p, *tmp = NULL;
3396 p = strchr (line, '=');
3397 if (!p)
3399 strncpy (namebuf, line, sizeof(namebuf));
3400 namebuf[sizeof(namebuf)-1] = 0;
3402 else
3404 tmp = str_dup (line);
3405 if (!tmp)
3406 return send_error (ctx, GPG_ERR_ENOMEM);
3408 tmp[strlen (line) - strlen (p)] = 0;
3409 strncpy (namebuf, tmp, sizeof (namebuf));
3410 namebuf[sizeof(namebuf)-1] = 0;
3411 xfree (tmp);
3412 tmp = NULL;
3413 value = p+1;
3416 log_write2 ("OPTION name='%s' value='%s'", name, value);
3418 if (strcasecmp (name, (char *) "lock-timeout") == 0)
3420 long n = 0;
3422 if (value)
3424 n = strtol (value, &tmp, 10);
3425 if (tmp && *tmp)
3426 return send_error (ctx, GPG_ERR_INV_VALUE);
3429 client->lock_timeout = n;
3431 else if (strcasecmp (name, (char *) "client-state") == 0)
3433 long n = 0;
3435 MUTEX_LOCK (&client->thd->status_mutex);
3436 if (value)
3438 n = strtol (value, &tmp, 10);
3439 if ((tmp && *tmp) || (n < 0 || n > 1))
3441 MUTEX_UNLOCK (&client->thd->status_mutex);
3442 return send_error (ctx, GPG_ERR_INV_VALUE);
3444 client->client_state = n;
3446 else
3447 client->client_state = 0;
3448 MUTEX_UNLOCK (&client->thd->status_mutex);
3450 else if (strcasecmp (name, (char *) "NAME") == 0)
3452 if (value && strchr (value, ' '))
3453 rc = GPG_ERR_INV_VALUE;
3454 else
3456 MUTEX_LOCK (&cn_mutex);
3457 tmp = pthread_getspecific (thread_name_key);
3458 pthread_setspecific (thread_name_key, NULL);
3459 xfree (tmp);
3460 xfree (client->thd->name);
3461 client->thd->name = NULL;
3462 if (value && *value)
3464 pthread_setspecific (thread_name_key, str_dup (value));
3465 client->thd->name = str_dup (value);
3467 MUTEX_UNLOCK (&cn_mutex);
3470 else if (strcasecmp (name, "disable-pinentry") == 0)
3472 int n = 1;
3474 if (value && *value)
3476 n = (int) strtol (value, &tmp, 10);
3477 if (*tmp || n < 0 || n > 1)
3478 return send_error (ctx, GPG_ERR_INV_VALUE);
3481 if (n)
3482 client->flags |= FLAG_NO_PINENTRY;
3483 else
3484 client->flags &= ~FLAG_NO_PINENTRY;
3486 else if (strcasecmp (name, "ttyname") == 0)
3487 set_env ("GPG_TTY", env_gpg_tty, sizeof (env_gpg_tty), value);
3488 else if (strcasecmp (name, "ttytype") == 0)
3489 set_env ("TERM", env_term, sizeof (env_term), value);
3490 else if (strcasecmp (name, "display") == 0)
3491 set_env ("DISPLAY", env_display, sizeof (env_display), value);
3492 else if (strcasecmp (name, "lc_messages") == 0)
3495 else if (strcasecmp (name, "lc_ctype") == 0)
3498 else if (strcasecmp (name, "desc") == 0)
3501 else if (strcasecmp (name, "pinentry-timeout") == 0)
3504 else
3505 rc = GPG_ERR_UNKNOWN_OPTION;
3507 return send_error (ctx, rc);
3510 static gpg_error_t
3511 do_rename (assuan_context_t ctx, char *line)
3513 struct client_s *client = assuan_get_pointer (ctx);
3514 char **args, *p;
3515 xmlNodePtr src, dst;
3516 struct string_s *str = NULL, *tstr;
3517 struct xml_request_s *req;
3518 gpg_error_t rc;
3520 if (!line || !*line)
3521 return GPG_ERR_SYNTAX;
3523 args = str_split (line, " ", 0);
3524 if (!args || strv_length (args) != 2)
3526 strv_free (args);
3527 return GPG_ERR_SYNTAX;
3530 if (!xml_valid_element ((xmlChar *) args[1]))
3532 strv_free (args);
3533 return GPG_ERR_INV_VALUE;
3536 rc = xml_new_request (client, args[0], XML_CMD_RENAME, &req);
3537 if (rc)
3539 strv_free (args);
3540 return rc;
3543 src = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
3544 if (rc)
3545 goto fail;
3547 rc = xml_is_element_owner (client, src);
3548 if (rc)
3549 goto fail;
3551 xmlChar *a = xmlGetProp (src, (xmlChar *) "_name");
3552 if (!a)
3554 rc = GPG_ERR_ENOMEM;
3555 goto fail;
3558 /* To prevent unwanted effects:
3560 * <element _name="a"><element _name="b"/></element>
3562 * RENAME a<TAB>b b
3564 if (xmlStrEqual (a, (xmlChar *) args[1]))
3566 xmlFree (a);
3567 rc = GPG_ERR_EEXIST;
3568 goto fail;
3571 xmlFree (a);
3572 str = string_new (args[0]);
3573 if (!str)
3575 rc = GPG_ERR_ENOMEM;
3576 goto fail;
3579 p = strrchr (str->str, '\t');
3580 if (p)
3581 tstr = string_truncate (str, strlen (str->str)-strlen (p));
3582 else
3583 tstr = string_truncate (str, 0);
3585 if (!tstr)
3587 string_free (str, 1);
3588 rc = GPG_ERR_ENOMEM;
3589 goto fail;
3592 str = tstr;
3593 tstr = string_append_printf (str, "%s%s", str->len ? "\t" : "", args[1]);
3594 if (!tstr)
3596 string_free (str, 1);
3597 rc = GPG_ERR_ENOMEM;
3598 goto fail;
3601 str = tstr;
3602 xml_free_request (req);
3603 rc = xml_new_request (client, str->str, XML_CMD_RENAME, &req);
3604 string_free (str, 1);
3605 if (rc)
3607 req = NULL;
3608 goto fail;
3611 dst = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
3612 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3613 goto fail;
3615 rc = 0;
3617 /* Target may exist:
3619 * <element _name="a"/>
3620 * <element _name="b" target="a"/>
3622 * RENAME b a
3624 if (src == dst)
3626 rc = GPG_ERR_EEXIST;
3627 goto fail;
3630 if (dst)
3632 rc = xml_is_element_owner (client, dst);
3633 if (rc)
3634 goto fail;
3636 rc = xml_add_attribute (client, src, "_name", args[1]);
3637 if (!rc)
3638 xml_unlink_node (client, dst);
3640 else
3641 rc = xml_add_attribute (client, src, "_name", args[1]);
3643 fail:
3644 xml_free_request (req);
3645 strv_free (args);
3646 return rc;
3649 static gpg_error_t
3650 rename_command (assuan_context_t ctx, char *line)
3652 struct client_s *client = assuan_get_pointer (ctx);
3653 gpg_error_t rc;
3654 struct argv_s *args[] = {
3655 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
3656 NULL
3659 rc = parse_options (&line, args, client, 1);
3660 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
3661 rc = GPG_ERR_SYNTAX;
3662 if (rc)
3663 return send_error (ctx, rc);
3665 rc = copy_on_write (client);
3666 if (rc)
3667 return send_error (ctx, rc);
3669 if (client->opts & OPT_INQUIRE)
3671 unsigned char *result;
3672 size_t len;
3674 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3675 if (rc)
3676 return send_error (ctx, rc);
3678 pthread_cleanup_push ((void *)xfree, result);
3679 rc = do_rename (ctx, (char *)result);
3680 pthread_cleanup_pop (1);
3682 else
3683 rc = do_rename (ctx, line);
3685 return send_error (ctx, rc);
3688 static gpg_error_t
3689 do_copy (assuan_context_t ctx, char *line)
3691 struct client_s *client = assuan_get_pointer (ctx);
3692 char **args, **targs;
3693 xmlNodePtr src, dst, tree = NULL;
3694 struct xml_request_s *req;
3695 gpg_error_t rc;
3697 if (!line || !*line)
3698 return GPG_ERR_SYNTAX;
3700 args = str_split (line, " ", 0);
3701 if (!args || strv_length (args) != 2)
3703 strv_free (args);
3704 return GPG_ERR_SYNTAX;
3707 targs = str_split (args[1], "\t", 0);
3708 if (!targs)
3710 strv_free (args);
3711 return GPG_ERR_SYNTAX;
3714 if (!xml_valid_element_path (targs, 0))
3716 strv_free (args);
3717 strv_free (targs);
3718 return GPG_ERR_INV_VALUE;
3720 strv_free (targs);
3722 rc = xml_new_request (client, args[0], XML_CMD_NONE, &req);
3723 if (rc)
3725 strv_free (args);
3726 return rc;
3729 src = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
3730 if (rc)
3731 goto fail;
3733 tree = xmlCopyNodeList (src);
3734 if (!tree)
3736 rc = GPG_ERR_ENOMEM;
3737 goto fail;
3740 xml_free_request (req);
3741 /* Create the destination element path if it does not exist. */
3742 rc = xml_new_request (client, args[1], XML_CMD_STORE, &req);
3743 if (rc)
3745 req = NULL;
3746 goto fail;
3749 dst = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
3750 if (rc)
3751 goto fail;
3753 rc = xml_is_element_owner (client, dst);
3754 if (rc)
3755 goto fail;
3757 rc = xml_validate_target (client, req->doc, args[1], src);
3758 if (rc || src == dst)
3760 rc = rc ? rc : GPG_ERR_EEXIST;
3761 goto fail;
3764 /* Merge any attributes from the src node to the initial dst node. */
3765 for (xmlAttrPtr attr = tree->properties; attr; attr = attr->next)
3767 if (xmlStrEqual (attr->name, (xmlChar *) "_name"))
3768 continue;
3770 xmlAttrPtr a = xmlHasProp (dst, attr->name);
3771 if (a)
3772 xmlRemoveProp (a);
3774 xmlChar *tmp = xmlNodeGetContent (attr->children);
3775 xmlNewProp (dst, attr->name, tmp);
3776 xmlFree (tmp);
3777 /* Create the default attributes. */
3778 rc = xml_add_attribute (client, dst, NULL, NULL);
3781 xmlNodePtr n = dst->children;
3782 (void)xml_unlink_node (client, n);
3783 dst->children = NULL;
3785 if (tree->children)
3787 n = xmlCopyNodeList (tree->children);
3788 if (!n)
3790 rc = GPG_ERR_ENOMEM;
3791 goto fail;
3794 n = xmlAddChildList (dst, n);
3795 if (!n)
3797 rc = GPG_ERR_ENOMEM;
3798 goto fail;
3801 rc = xml_update_element_mtime (client, xmlDocGetRootElement (client->doc)
3802 == dst->parent ? dst : dst->parent);
3805 fail:
3806 if (tree)
3807 (void)xml_unlink_node (client, tree);
3809 xml_free_request (req);
3810 strv_free (args);
3811 return rc;
3814 static gpg_error_t
3815 copy_command (assuan_context_t ctx, char *line)
3817 struct client_s *client = assuan_get_pointer (ctx);
3818 gpg_error_t rc;
3819 struct argv_s *args[] = {
3820 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
3821 NULL
3824 rc = parse_options (&line, args, client, 1);
3825 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
3826 rc = GPG_ERR_SYNTAX;
3827 if (rc)
3828 return send_error (ctx, rc);
3830 rc = copy_on_write (client);
3831 if (rc)
3832 return send_error (ctx, rc);
3834 if (client->opts & OPT_INQUIRE)
3836 unsigned char *result;
3837 size_t len;
3839 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
3840 if (rc)
3841 return send_error (ctx, rc);
3843 pthread_cleanup_push ((void *)xfree, result);
3844 rc = do_copy (ctx, (char *)result);
3845 pthread_cleanup_pop (1);
3847 else
3848 rc = do_copy (ctx, line);
3850 return send_error (ctx, rc);
3853 static gpg_error_t
3854 do_move (assuan_context_t ctx, char *line)
3856 struct client_s *client = assuan_get_pointer (ctx);
3857 char **args;
3858 xmlNodePtr src, dst;
3859 struct xml_request_s *req;
3860 gpg_error_t rc;
3862 if (!line || !*line)
3863 return GPG_ERR_SYNTAX;
3865 args = str_split (line, " ", 0);
3866 if (!args || strv_length (args) != 2)
3868 strv_free (args);
3869 return GPG_ERR_SYNTAX;
3872 if (*args[1])
3874 char **targs = str_split (args[1], "\t", 0);
3875 if (!targs)
3877 strv_free (args);
3878 return GPG_ERR_ENOMEM;
3881 if (!xml_valid_element_path (targs, 0))
3883 strv_free (targs);
3884 strv_free (args);
3885 return GPG_ERR_INV_VALUE;
3888 strv_free (targs);
3891 rc = xml_new_request (client, args[0], XML_CMD_MOVE, &req);
3892 if (rc)
3894 strv_free (args);
3895 return rc;
3898 src = xml_find_elements (client, req, xmlDocGetRootElement (req->doc), &rc);
3899 if (rc)
3900 goto fail;
3902 rc = xml_is_element_owner (client, src);
3903 if (rc)
3904 goto fail;
3906 xml_free_request (req);
3907 req = NULL;
3908 if (*args[1])
3910 rc = xml_new_request (client, args[1], XML_CMD_NONE, &req);
3911 if (rc)
3912 goto fail;
3914 dst = xml_find_elements (client, req, xmlDocGetRootElement (req->doc),
3915 &rc);
3917 else
3918 dst = xmlDocGetRootElement (client->doc);
3920 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3921 goto fail;
3923 rc = 0;
3925 for (xmlNodePtr n = dst; n; n = n->parent)
3927 if (n == src)
3929 rc = GPG_ERR_EEXIST;
3930 goto fail;
3934 if (dst)
3936 xmlChar *a = xml_attribute_value (src, (xmlChar *) "_name");
3937 xmlNodePtr dup = xml_find_element (client, dst->children, (char *) a, &rc);
3939 xmlFree (a);
3940 if (rc && rc != GPG_ERR_ELEMENT_NOT_FOUND)
3941 goto fail;
3943 rc = 0;
3945 if (dup)
3947 if (dup == src)
3949 rc = GPG_ERR_EEXIST;
3950 goto fail;
3953 if (dst == xmlDocGetRootElement (client->doc))
3955 xmlNodePtr n = src;
3956 int match = 0;
3958 while (n->parent && n->parent != dst)
3959 n = n->parent;
3961 a = xml_attribute_value (n, (xmlChar *) "_name");
3962 xmlChar *b = xml_attribute_value (src, (xmlChar *) "_name");
3964 if (xmlStrEqual (a, b))
3966 match = 1;
3967 xmlUnlinkNode (src);
3968 (void)xml_unlink_node (client, n);
3971 xmlFree (a);
3972 xmlFree (b);
3974 if (!match)
3975 (void)xml_unlink_node (client, dup);
3977 else
3978 xmlUnlinkNode (dup);
3982 if (!dst && req && req->args && *req->args)
3984 struct xml_request_s *nreq = NULL;
3985 xmlChar *name = xml_attribute_value (src, (xmlChar *) "_name");
3987 if (src->parent == xmlDocGetRootElement (client->doc)
3988 && !strcmp ((char *) name, *req->args))
3990 xmlFree (name);
3991 rc = GPG_ERR_EEXIST;
3992 goto fail;
3995 xmlFree (name);
3996 rc = xml_new_request (client, args[1], XML_CMD_STORE, &nreq);
3997 if (!rc)
3999 dst = xml_find_elements (client, nreq,
4000 xmlDocGetRootElement (nreq->doc), &rc);
4001 xml_free_request (nreq);
4004 if (rc)
4005 goto fail;
4008 xml_update_element_mtime (client, src->parent);
4009 xmlUnlinkNode (src);
4011 dst = xmlAddChildList (dst, src);
4012 if (!dst)
4013 rc = GPG_ERR_ENOMEM;
4014 else
4015 xml_update_element_mtime (client, dst->parent);
4017 fail:
4018 xml_free_request (req);
4019 strv_free (args);
4020 return rc;
4023 static gpg_error_t
4024 move_command (assuan_context_t ctx, char *line)
4026 struct client_s *client = assuan_get_pointer (ctx);
4027 gpg_error_t rc;
4028 struct argv_s *args[] = {
4029 &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire},
4030 NULL
4033 rc = parse_options (&line, args, client, 1);
4034 if (!rc && (client->opts & OPT_INQUIRE) && line && *line)
4035 rc = GPG_ERR_SYNTAX;
4036 if (rc)
4037 return send_error (ctx, rc);
4039 rc = copy_on_write (client);
4040 if (rc)
4041 return send_error (ctx, rc);
4043 if (client->opts & OPT_INQUIRE)
4045 unsigned char *result;
4046 size_t len;
4048 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
4049 if (rc)
4050 return send_error (ctx, rc);
4052 pthread_cleanup_push ((void *)xfree, result);
4053 rc = do_move (ctx, (char *)result);
4054 pthread_cleanup_pop (1);
4056 else
4057 rc = do_move (ctx, line);
4059 return send_error (ctx, rc);
4062 static int
4063 sort_files (const void *arg1, const void *arg2)
4065 char *const *a = arg1;
4066 char *const *b = arg2;
4068 return strcmp (*a, *b);
4071 static gpg_error_t
4072 ls_command (assuan_context_t ctx, char *line)
4074 struct client_s *client = assuan_get_pointer (ctx);
4075 gpg_error_t rc;
4076 char *tmp;
4077 char *dir;
4078 DIR *d;
4079 char *list = NULL;
4080 char **v = NULL;
4081 #ifdef HAVE_READDIR_R
4082 size_t len;
4083 struct dirent *cur = NULL, *p;
4084 #else
4085 struct dirent *cur = NULL;
4086 #endif
4087 struct argv_s *args[] = {
4088 &(struct argv_s) {"verbose", OPTION_TYPE_NOARG, parse_opt_verbose},
4089 NULL
4092 rc = parse_options (&line, args, client, 0);
4093 if (rc)
4094 return send_error (ctx, rc);
4096 tmp = str_asprintf ("%s/data", homedir);
4097 dir = expand_homedir (tmp);
4098 xfree (tmp);
4099 if (!dir)
4100 return send_error (ctx, GPG_ERR_ENOMEM);
4102 d = opendir (dir);
4103 rc = gpg_error_from_errno (errno);
4105 if (!d)
4107 xfree (dir);
4108 return send_error (ctx, rc);
4111 #ifdef HAVE_READDIR_R
4112 len = offsetof (struct dirent, d_name) + pathconf (dir, _PC_NAME_MAX) + 1;
4113 p = xmalloc (len);
4114 if (!p)
4116 xfree (dir);
4117 closedir (d);
4118 return send_error (ctx, GPG_ERR_ENOMEM);
4120 pthread_cleanup_push (xfree, p);
4121 #endif
4123 pthread_cleanup_push ((void *)closedir, d);
4124 xfree (dir);
4125 rc = 0;
4127 #ifdef HAVE_READDIR_R
4128 while (!readdir_r (d, p, &cur) && cur)
4129 #else
4130 while ((cur = readdir (d)))
4131 #endif
4133 char **vtmp;
4134 struct stat st;
4136 rc = open_check_file (cur->d_name, NULL, &st, 1);
4137 if (rc)
4138 continue;
4140 if (client->opts & OPT_VERBOSE)
4141 tmp = str_asprintf ("%s %lu.%lu %lu.%lu %lu.%lu", cur->d_name,
4142 st.st_atim.tv_sec, st.st_atim.tv_nsec,
4143 st.st_mtim.tv_sec, st.st_mtim.tv_nsec,
4144 st.st_ctim.tv_sec, st.st_ctim.tv_nsec);
4145 else
4146 tmp = str_dup (cur->d_name);
4148 if (!tmp)
4150 rc = GPG_ERR_ENOMEM;
4151 break;
4154 vtmp = strv_cat (v, tmp);
4155 if (!vtmp)
4157 xfree (tmp);
4158 rc = GPG_ERR_ENOMEM;
4159 break;
4162 v = vtmp;
4165 pthread_cleanup_pop (1); // closedir (d)
4166 #ifdef HAVE_READDIR_R
4167 pthread_cleanup_pop (1); // xfree (p)
4168 #endif
4170 if (rc && rc != GPG_ERR_ENODEV)
4172 strv_free (v);
4173 return send_error (ctx, rc);
4176 rc = 0;
4177 if (v && *v)
4179 unsigned n, t = strv_length (v);
4181 qsort (v, t, sizeof (char **), sort_files);
4183 for (n = 0; n < t; n++)
4185 tmp = str_asprintf ("%s%s\n", list ? list : "", v[n]);
4186 if (!tmp)
4188 xfree (list);
4189 rc = GPG_ERR_ENOMEM;
4190 break;
4193 xfree (list);
4194 list = tmp;
4198 strv_free (v);
4199 if (!list)
4200 return send_error (ctx, GPG_ERR_NO_DATA);
4202 list[strlen (list) - 1] = 0;
4203 pthread_cleanup_push (xfree, list);
4204 rc = xfer_data (ctx, list, strlen (list));
4205 pthread_cleanup_pop (1);
4206 return send_error (ctx, rc);
4209 /* Run all commands in the command list 'head'. The return code isn't
4210 * considered at all for a command. It is stored in the list and later sent to
4211 * the client. */
4212 static gpg_error_t
4213 dispatch_bulk_commands (struct client_s *client, struct sexp_s **list)
4215 unsigned i;
4216 gpg_error_t rc = 0;
4218 for (i = 0; list && list[i];)
4220 struct bulk_cmd_s *cur = list[i]->user;
4222 if (!strcmp (list[i]->tag, "command")
4223 || !strcmp (list[i]->tag, "id"))
4225 i++;
4226 continue;
4229 client->bulk_p = cur;
4230 rc = command_startup (client->ctx, cur->cmd->name);
4231 if (rc)
4232 break;
4234 cur->ran = 1;
4235 cur->rc = cur->cmd->handler (client->ctx, list[i]->data);
4236 command_finalize (client->ctx, cur->rc);
4238 do {
4239 if (list[i+1] && !strcmp (list[i+1]->tag, "rc"))
4241 gpg_error_t erc = 0;
4243 if (list[i+1]->data)
4244 erc = strtoul (list[i+1]->data, NULL, 10);
4246 if (erc != cur->rc)
4248 i++;
4249 continue;
4252 rc = dispatch_bulk_commands (client, list[++i]->next);
4254 else
4256 i++;
4257 break;
4259 } while (1);
4262 return rc;
4265 static gpg_error_t
4266 bulk_command (assuan_context_t ctx, char *line)
4268 struct client_s *client = assuan_get_pointer (ctx);
4269 gpg_error_t rc = 0;
4270 unsigned char *result;
4271 size_t len;
4272 struct sexp_s **sexp = NULL;
4274 if (line && *line)
4275 return send_error (ctx, GPG_ERR_SYNTAX);
4277 rc = assuan_inquire (ctx, "DATA", &result, &len, 0);
4278 if (rc)
4279 return send_error (ctx, rc);
4281 if (!len)
4282 return send_error (ctx, GPG_ERR_SYNTAX);
4284 rc = bulk_parse_commands (&sexp, (const char *)result, command_table);
4285 xfree (result);
4286 if (rc)
4287 return send_error (ctx, rc);
4289 pthread_cleanup_push ((void *)bulk_free_list, sexp);
4290 rc = dispatch_bulk_commands (client, sexp);
4291 pthread_cleanup_pop (0);
4292 if (!rc)
4293 rc = bulk_build_result (sexp, (char **)&result);
4295 bulk_free_list (sexp);
4297 if (!rc)
4299 pthread_cleanup_push ((void *)xfree, result);
4300 rc = xfer_data (ctx, (char *)result, strlen ((char *)result));
4301 pthread_cleanup_pop (1);
4304 return send_error (ctx, rc);
4307 static gpg_error_t
4308 nop_command (assuan_context_t ctx, char *line)
4310 return send_error (ctx, 0);
4313 static gpg_error_t
4314 bye_notify (assuan_context_t ctx, char *line)
4316 struct client_s *cl = assuan_get_pointer (ctx);
4317 gpg_error_t ret = 0;
4319 (void)line;
4320 update_client_state (cl, CLIENT_STATE_DISCON);
4322 #ifdef WITH_GNUTLS
4323 cl->disco = 1;
4324 if (cl->thd->remote)
4326 int rc;
4330 struct timeval tv = { 0, 50000 };
4332 rc = gnutls_bye (cl->thd->tls->ses, GNUTLS_SHUT_RDWR);
4333 if (rc == GNUTLS_E_AGAIN)
4334 select (0, NULL, NULL, NULL, &tv);
4336 while (rc == GNUTLS_E_AGAIN);
4338 #endif
4340 /* This will let assuan_process_next() return. */
4341 if (fcntl (cl->thd->fd, F_SETFL, O_NONBLOCK) == -1)
4343 cl->last_rc = gpg_error_from_errno (errno);
4344 ret = cl->last_rc;
4347 cl->last_rc = 0; // BYE command result
4348 return ret;
4351 static gpg_error_t
4352 reset_notify (assuan_context_t ctx, char *line)
4354 struct client_s *client = assuan_get_pointer (ctx);
4356 (void)line;
4357 if (client)
4358 reset_client (client);
4360 return 0;
4364 * This is called before every Assuan command.
4366 static gpg_error_t
4367 command_startup (assuan_context_t ctx, const char *name)
4369 struct client_s *client = assuan_get_pointer (ctx);
4370 gpg_error_t rc;
4371 struct command_table_s *cmd = NULL;
4373 log_write2 ("command='%s'", name);
4374 client->last_rc = client->opts = 0;
4376 for (int i = 0; command_table[i]; i++)
4378 if (!strcasecmp (name, command_table[i]->name))
4380 if (command_table[i]->ignore_startup)
4381 return 0;
4382 cmd = command_table[i];
4383 break;
4387 if (!cmd)
4388 return GPG_ERR_UNKNOWN_COMMAND;
4390 client->last_rc = rc = gpg_error (file_modified (client, cmd));
4391 if (!rc)
4392 update_client_state (client, CLIENT_STATE_COMMAND);
4394 return rc;
4398 * This is called after every Assuan command.
4400 static void
4401 command_finalize (assuan_context_t ctx, gpg_error_t rc)
4403 struct client_s *client = assuan_get_pointer (ctx);
4406 if (!(client->flags & FLAG_LOCK_CMD))
4407 unlock_file_mutex (client, 0);
4409 unlock_flock (&client->flock_fd);
4410 log_write2 (_("command completed: rc=%u"), rc ? rc : client->last_rc);
4411 client->last_rc = gpg_error (GPG_ERR_UNKNOWN_COMMAND);
4412 client->bulk_p = NULL;
4413 #ifdef WITH_GNUTLS
4414 client->thd->buffer_timeout = client->thd->last_buffer_size = 0;
4415 #endif
4416 if (client->thd->state != CLIENT_STATE_DISCON)
4417 update_client_state (client, CLIENT_STATE_IDLE);
4420 static gpg_error_t
4421 parse_help_opt_html (void *data, void *value)
4423 struct client_s *client = data;
4425 (void) value;
4426 client->opts |= OPT_HTML;
4427 return 0;
4430 static gpg_error_t
4431 help_command (assuan_context_t ctx, char *line)
4433 gpg_error_t rc;
4434 int i;
4435 struct client_s *client = assuan_get_pointer (ctx);
4436 struct argv_s *args[] = {
4437 &(struct argv_s) {"html", OPTION_TYPE_NOARG, parse_help_opt_html},
4438 NULL
4441 rc = parse_options (&line, args, client, 1);
4442 if (rc)
4443 return send_error (ctx, rc);
4445 if (!line || !*line)
4447 char *tmp;
4448 char *help = str_dup (_("Usage: HELP [--html] [<COMMAND>]\n"
4449 "For commands that take an element path as an argument, each element is "
4450 "separated with an ASCII @key{TAB} character (ASCII 0x09)."
4451 "@*@*COMMANDS:"));
4453 for (i = 0; command_table[i]; i++)
4455 if (!command_table[i]->help)
4456 continue;
4458 /* @npxref{} won't put a "See " or "see " in front of the command.
4459 * It's not a texinfo command but needed for --html. */
4460 tmp = str_asprintf ("%s %s%s%s", help,
4461 client->opts & OPT_HTML ? "@npxref{" : "",
4462 command_table[i]->name,
4463 client->opts & OPT_HTML ? "}" : "");
4464 xfree (help);
4465 help = tmp;
4468 tmp = strip_texi_and_wrap (help, client->opts & OPT_HTML);
4469 xfree (help);
4470 pthread_cleanup_push ((void *)xfree, tmp);
4471 rc = xfer_data (ctx, tmp, strlen (tmp));
4472 pthread_cleanup_pop (1);
4473 return send_error (ctx, rc);
4476 for (i = 0; command_table[i]; i++)
4478 if (!strcasecmp (line, command_table[i]->name))
4480 char *help, *tmp;
4482 if (!command_table[i]->help)
4483 break;
4485 help = strip_texi_and_wrap (command_table[i]->help,
4486 client->opts & OPT_HTML);
4487 tmp = str_asprintf ("%s%s",
4488 (client->opts & OPT_HTML) ? "" : _("Usage: "),
4489 help);
4490 xfree (help);
4491 pthread_cleanup_push ((void *)xfree, tmp);
4492 rc = xfer_data (ctx, tmp, strlen (tmp));
4493 pthread_cleanup_pop (1);
4494 return send_error (ctx, rc);
4498 return send_error (ctx, GPG_ERR_INV_NAME);
4501 static void
4502 new_command (const char *name, int ignore, int unlock, int flock_type,
4503 gpg_error_t (*handler) (assuan_context_t, char *),
4504 const char *help)
4506 int i = 0;
4507 struct command_table_s **tmp;
4509 if (command_table)
4510 for (i = 0; command_table[i]; i++);
4512 tmp = xrealloc (command_table, (i + 2) * sizeof (struct command_table_s *));
4513 assert (tmp);
4514 command_table = tmp;
4515 command_table[i] = xcalloc (1, sizeof (struct command_table_s));
4516 command_table[i]->name = name;
4517 command_table[i]->handler = handler;
4518 command_table[i]->ignore_startup = ignore;
4519 command_table[i]->unlock = unlock;
4520 command_table[i]->flock_type = flock_type;
4521 command_table[i++]->help = help;
4522 command_table[i] = NULL;
4525 void
4526 deinit_commands ()
4528 int i;
4530 for (i = 0; command_table[i]; i++)
4531 xfree (command_table[i]);
4533 xfree (command_table);
4536 static int
4537 sort_commands (const void *arg1, const void *arg2)
4539 struct command_table_s *const *a = arg1;
4540 struct command_table_s *const *b = arg2;
4542 if (!*a || !*b)
4543 return 0;
4544 else if (*a && !*b)
4545 return 1;
4546 else if (!*a && *b)
4547 return -1;
4549 return strcmp ((*a)->name, (*b)->name);
4552 static gpg_error_t
4553 passwd_command (assuan_context_t ctx, char *line)
4555 struct client_s *client = assuan_get_pointer (ctx);
4556 gpg_error_t rc;
4558 (void)line;
4559 rc = peer_is_invoker (client);
4560 if (rc)
4561 return send_error (ctx, (rc == GPG_ERR_EACCES ? GPG_ERR_FORBIDDEN : rc));
4563 if (client->flags & FLAG_NEW)
4564 return send_error (ctx, GPG_ERR_INV_STATE);
4566 client->crypto->keyfile = config_get_string (client->filename,
4567 "passphrase_file");
4568 rc = crypto_init_ctx (client->crypto, client->flags & FLAG_NO_PINENTRY,
4569 client->crypto->keyfile);
4570 if (!rc)
4571 rc = crypto_passwd (client, client->crypto);
4573 crypto_free_non_keys (client->crypto);
4574 return send_error (ctx, rc);
4577 static gpg_error_t
4578 parse_opt_data (void *data, void *value)
4580 struct client_s *client = data;
4582 (void) value;
4583 client->opts |= OPT_DATA;
4584 return 0;
4587 static gpg_error_t
4588 send_client_list (assuan_context_t ctx)
4590 struct client_s *client = assuan_get_pointer (ctx);
4591 gpg_error_t rc = 0;
4593 if (client->opts & OPT_VERBOSE)
4595 unsigned i, t;
4596 char **list = NULL;
4597 char *line;
4599 MUTEX_LOCK (&cn_mutex);
4600 pthread_cleanup_push ((void *)release_mutex_cb, &cn_mutex);
4601 t = slist_length (cn_thread_list);
4603 for (i = 0; i < t; i++)
4605 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
4606 char *tmp;
4608 if (thd->state == CLIENT_STATE_UNKNOWN)
4609 continue;
4611 tmp = build_client_info_line (thd, 0);
4612 if (tmp)
4614 char **l = strv_cat (list, tmp);
4615 if (!l)
4616 rc = GPG_ERR_ENOMEM;
4617 else
4618 list = l;
4620 else
4621 rc = GPG_ERR_ENOMEM;
4623 if (rc)
4625 strv_free (list);
4626 break;
4630 pthread_cleanup_pop (1);
4631 if (rc)
4632 return rc;
4634 line = strv_join ("\n", list);
4635 strv_free (list);
4636 pthread_cleanup_push ((void *)xfree, line);
4637 rc = xfer_data (ctx, line, strlen (line));
4638 pthread_cleanup_pop (1);
4639 return rc;
4642 if (client->opts & OPT_DATA)
4644 char buf[ASSUAN_LINELENGTH];
4646 MUTEX_LOCK (&cn_mutex);
4647 snprintf (buf, sizeof (buf), "%u", slist_length (cn_thread_list));
4648 MUTEX_UNLOCK (&cn_mutex);
4649 rc = xfer_data (ctx, buf, strlen (buf));
4651 else
4652 rc = send_status (ctx, STATUS_CLIENTS, NULL);
4654 return rc;
4657 static gpg_error_t
4658 getinfo_command (assuan_context_t ctx, char *line)
4660 struct client_s *client = assuan_get_pointer (ctx);
4661 gpg_error_t rc;
4662 char buf[ASSUAN_LINELENGTH];
4663 struct argv_s *args[] = {
4664 &(struct argv_s) {"data", OPTION_TYPE_NOARG, parse_opt_data},
4665 &(struct argv_s) {"verbose", OPTION_TYPE_NOARG, parse_opt_verbose},
4666 NULL
4669 rc = parse_options (&line, args, client, 1);
4670 if (rc)
4671 return send_error (ctx, rc);
4673 if (!line || !*line)
4674 return send_error (ctx, GPG_ERR_SYNTAX);
4676 if (!strcasecmp (line, "clients"))
4678 rc = send_client_list (ctx);
4680 else if (!strcasecmp (line, "cache"))
4682 if (client->opts & OPT_DATA)
4684 snprintf (buf, sizeof (buf), "%u", cache_file_count ());
4685 rc = xfer_data (ctx, buf, strlen (buf));
4687 else
4688 rc = send_status (ctx, STATUS_CACHE, NULL);
4690 else if (!strcasecmp (line, "pid"))
4692 pid_t pid = getpid ();
4694 snprintf (buf, sizeof (buf), "%u", pid);
4695 rc = xfer_data (ctx, buf, strlen (buf));
4697 else if (!strcasecmp (line, "version"))
4699 char *tmp = str_asprintf ("0x%06x %s", VERSION_HEX,
4700 #ifdef WITH_GNUTLS
4701 "GNUTLS "
4702 #endif
4703 #ifdef WITH_LIBACL
4704 "ACL "
4705 #endif
4706 "");
4707 pthread_cleanup_push (xfree, tmp);
4708 rc = xfer_data (ctx, tmp, strlen (tmp));
4709 pthread_cleanup_pop (1);
4711 else if (!strcasecmp (line, "last_error"))
4713 if (client->last_error)
4714 rc = xfer_data (ctx, client->last_error, strlen (client->last_error));
4715 else
4716 rc = GPG_ERR_NO_DATA;
4718 else if (!strcasecmp (line, "user"))
4720 char *user = NULL;
4722 #ifdef WITH_GNUTLS
4723 if (client->thd->remote)
4724 user = str_asprintf ("#%s", client->thd->tls->fp);
4725 else
4726 user = get_username (client->thd->peer->uid);
4727 #else
4728 user = get_username (client->thd->peer->uid);
4729 #endif
4730 if (user)
4732 pthread_cleanup_push ((void *)xfree, user);
4733 rc = xfer_data (ctx, user, strlen (user));
4734 pthread_cleanup_pop (1);
4736 else
4737 rc = GPG_ERR_NO_DATA;
4739 else
4740 rc = gpg_error (GPG_ERR_SYNTAX);
4742 return send_error (ctx, rc);
4745 static gpg_error_t
4746 parse_opt_secret (void *data, void *value)
4748 struct client_s *client = data;
4750 (void) value;
4751 client->opts |= OPT_SECRET;
4752 return 0;
4755 static gpg_error_t
4756 parse_keyinfo_opt_learn (void *data, void *value)
4758 struct client_s *client = data;
4760 (void)value;
4761 client->opts |= OPT_KEYINFO_LEARN;
4762 return 0;
4765 static gpg_error_t
4766 keyinfo_command (assuan_context_t ctx, char *line)
4768 struct client_s *client = assuan_get_pointer (ctx);
4769 gpg_error_t rc = 0;
4770 char **keys = NULL, **p = NULL;
4771 int sym = 0;
4772 struct argv_s *args[] = {
4773 &(struct argv_s) {"learn", OPTION_TYPE_NOARG, parse_keyinfo_opt_learn},
4774 NULL
4777 rc = parse_options (&line, args, client, 0);
4778 if (rc)
4779 return send_error (ctx, rc);
4781 if (line && *line)
4782 return send_error (ctx, GPG_ERR_SYNTAX);
4784 if (!(client->flags & FLAG_OPEN))
4785 return send_error (ctx, GPG_ERR_INV_STATE);
4787 if (client->opts & OPT_KEYINFO_LEARN)
4789 rc = cache_agent_command ("LEARN");
4790 return send_error (ctx, rc);
4793 if (client->flags & FLAG_NEW)
4794 return send_error (ctx, GPG_ERR_NO_DATA);
4796 rc = lock_flock (ctx, client->filename, FLOCK_TYPE_SH, &client->flock_fd);
4797 if (rc)
4798 return send_error (ctx, rc);
4800 rc = crypto_is_symmetric (client->filename);
4801 unlock_flock (&client->flock_fd);
4802 if (!rc)
4803 sym = 1;
4804 else if (rc != GPG_ERR_BAD_DATA)
4805 return send_error (ctx, rc);
4807 rc = 0;
4808 if (!sym)
4810 p = strv_catv (keys, client->crypto->pubkey);
4811 if (!p)
4812 rc = GPG_ERR_ENOMEM;
4813 else
4814 keys = p;
4817 if (!rc && client->crypto->sigkey)
4819 if (!strv_printf (&keys, "S%s", client->crypto->sigkey))
4821 strv_free (keys);
4822 return send_error (ctx, GPG_ERR_ENOMEM);
4826 if (!rc)
4828 if (keys)
4830 line = strv_join ("\n", keys);
4831 strv_free (keys);
4832 pthread_cleanup_push ((void *)xfree, line);
4833 if (line)
4834 rc = xfer_data (ctx, line, strlen (line));
4835 else
4836 rc = GPG_ERR_ENOMEM;
4838 pthread_cleanup_pop (1);
4840 else
4841 rc = GPG_ERR_NO_DATA;
4843 else
4844 strv_free (keys);
4846 return send_error (ctx, rc);
4849 static gpg_error_t
4850 deletekey_command (assuan_context_t ctx, char *line)
4852 gpg_error_t rc;
4853 struct client_s *client = assuan_get_pointer (ctx);
4854 struct crypto_s *crypto = NULL;
4855 char *keys[] = { NULL, NULL };
4856 gpgme_key_t *result;
4857 char **p = NULL;
4859 if (!(client->flags & FLAG_OPEN))
4860 return send_error (ctx, GPG_ERR_INV_STATE);
4862 rc = peer_is_invoker (client);
4863 if (rc)
4864 return send_error (ctx, (rc == GPG_ERR_EACCES ? GPG_ERR_FORBIDDEN : rc));
4866 if (client->flags & FLAG_NO_PINENTRY)
4867 return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED);
4869 if (!*line)
4870 return send_error (ctx, GPG_ERR_SYNTAX);
4872 rc = crypto_keyid_to_16b_once (line);
4873 if (rc)
4874 return send_error (ctx, rc);
4876 for (p = client->crypto->pubkey; p && *p; p++)
4878 if (!strcmp (*p, line))
4879 break;
4882 if (!p)
4884 if (client->crypto->sigkey && strcmp (client->crypto->sigkey, line))
4885 return send_error (ctx, GPG_ERR_FORBIDDEN);
4886 else if (!client->crypto->sigkey)
4887 return send_error (ctx, GPG_ERR_NO_SECKEY);
4890 rc = crypto_init (&crypto, client->ctx, client->filename,
4891 client->flags & FLAG_NO_PINENTRY, NULL);
4892 if (rc)
4893 return send_error (ctx, rc);
4895 pthread_cleanup_push ((void *)crypto_free, crypto);
4896 keys[0] = line;
4897 rc = crypto_list_keys (crypto, keys, 1, &result);
4898 if (!rc)
4900 pthread_cleanup_push ((void *)crypto_free_key_list, result);
4901 rc = crypto_delete_key (client, crypto, *result, 1);
4902 pthread_cleanup_pop (1);
4905 pthread_cleanup_pop (1);
4906 return send_error (ctx, rc);
4909 static gpg_error_t
4910 kill_command (assuan_context_t ctx, char *line)
4912 struct client_s *client = assuan_get_pointer (ctx);
4913 gpg_error_t rc;
4914 unsigned i, t;
4916 if (!line || !*line)
4917 return send_error (ctx, GPG_ERR_SYNTAX);
4919 MUTEX_LOCK (&cn_mutex);
4920 pthread_cleanup_push ((void *)release_mutex_cb, &cn_mutex);
4921 t = slist_length (cn_thread_list);
4922 rc = GPG_ERR_ESRCH;
4924 for (i = 0; i < t; i++)
4926 struct client_thread_s *thd = slist_nth_data (cn_thread_list, i);
4927 char *tmp = str_asprintf ("%p", thd->tid);
4929 if (strcmp (line, tmp))
4931 xfree (tmp);
4932 continue;
4935 xfree (tmp);
4936 rc = peer_is_invoker (client);
4937 if (!rc)
4939 #ifdef HAVE_PTHREAD_CANCEL
4940 pthread_cancel (thd->tid);
4941 #else
4942 pthread_kill (thd->tid, SIGUSR2);
4943 #endif
4944 break;
4946 else if (rc == GPG_ERR_EACCES)
4947 rc = GPG_ERR_FORBIDDEN;
4948 else if (rc)
4949 break;
4951 if (config_get_boolean ("global", "strict_kill"))
4952 break;
4954 #ifdef WITH_GNUTLS
4955 if (client->thd->remote && thd->remote)
4957 if (!thd->tls || !thd->tls->fp)
4959 rc = GPG_ERR_INV_STATE;
4960 break;
4962 if (!strcmp (client->thd->tls->fp, thd->tls->fp))
4964 #ifdef HAVE_PTHREAD_CANCEL
4965 pthread_cancel (thd->tid);
4966 #else
4967 pthread_kill (thd->tid, SIGUSR2);
4968 #endif
4969 rc = 0;
4970 break;
4973 else if (!client->thd->remote && !thd->remote)
4974 #endif
4976 if (client->thd->peer->uid == thd->peer->uid)
4978 #ifdef HAVE_PTHREAD_CANCEL
4979 pthread_cancel (thd->tid);
4980 #else
4981 pthread_kill (thd->tid, SIGUSR2);
4982 #endif
4983 rc = 0;
4986 break;
4989 pthread_cleanup_pop (1);
4990 return send_error (ctx, rc);
4993 static gpg_error_t
4994 listkeys_command (assuan_context_t ctx, char *line)
4996 struct client_s *client = assuan_get_pointer (ctx);
4997 struct crypto_s *crypto = NULL;
4998 char **pattern = NULL;
4999 gpgme_key_t *keys = NULL;
5000 char **result = NULL;
5001 gpg_error_t rc;
5002 struct argv_s *args[] = {
5003 &(struct argv_s) {"secret-only", OPTION_TYPE_NOARG, parse_opt_secret},
5004 NULL
5007 rc = parse_options (&line, args, client, 1);
5008 if (rc)
5009 return send_error (ctx, rc);
5011 rc = crypto_init (&crypto, client->ctx, client->filename,
5012 client->flags & FLAG_NO_PINENTRY, NULL);
5013 if (rc)
5014 return send_error (ctx, rc);
5016 pthread_cleanup_push ((void *)crypto_free, crypto);
5017 pattern = str_split (line, ",", 0);
5018 pthread_cleanup_push ((void *)(void *)strv_free, pattern);
5019 rc = crypto_list_keys (crypto, pattern, client->opts & OPT_SECRET,
5020 &keys);
5021 pthread_cleanup_pop (1);
5022 pthread_cleanup_pop (1);
5023 if (!rc)
5025 int i;
5027 for (i = 0; keys[i]; i++)
5029 char *p = crypto_key_info (keys[i]);
5030 char **r;
5032 if (!p)
5034 rc = GPG_ERR_ENOMEM;
5035 break;
5038 r = strv_cat (result, p);
5039 if (!r)
5041 rc = GPG_ERR_ENOMEM;
5042 break;
5045 result = r;
5048 if (!i)
5049 rc = GPG_ERR_NO_DATA;
5051 crypto_free_key_list (keys);
5054 if (!rc)
5056 line = strv_join ("\n", result);
5057 strv_free (result);
5058 pthread_cleanup_push ((void *)xfree, line);
5059 if (!line)
5060 rc = GPG_ERR_ENOMEM;
5061 else
5062 rc = xfer_data (ctx, line, strlen (line));
5064 pthread_cleanup_pop (1);
5066 else
5067 strv_free (result);
5069 if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
5070 || gpg_err_code (rc) == GPG_ERR_NO_SECKEY)
5071 rc = GPG_ERR_NO_DATA;
5073 return send_error (ctx, rc);
5076 void
5077 init_commands ()
5079 /* !BEGIN-HELP-TEXT!
5081 * This comment is used as a marker to generate the offline documentation
5082 * found in doc/pwmd.info. The indentation needs to be kept for the awk
5083 * script to determine where commands begin and end.
5085 new_command("HELP", 1, 1, 0, help_command, _(
5086 "HELP [--html] [<COMMAND>]\n" /* Showing available commands. */
5087 "Show available commands or command specific help text."
5088 "@*@*"
5089 "The @option{--html} option will output the help text in HTML format."
5092 new_command("DELETEKEY", 1, 1, FLOCK_TYPE_SH|FLOCK_TYPE_KEEP, deletekey_command, _(
5093 "DELETEKEY <keyid>\n" /* Deleting a key from the key ring. */
5094 "Deletes the public and secret key associated with key @var{keyid} from the "
5095 "keyring. The @var{keyid} must be one associated with the currently opened "
5096 "data file. "
5097 "Note that no confirmation occurs. Also note that when the key is deleted, "
5098 "the current or other data files using this key will no longer be able to be "
5099 "opened."
5102 new_command("KILL", 1, 0, 0, kill_command, _(
5103 "KILL <thread_id>\n" /* Terminating another client. */
5104 "Terminates the client identified by @var{thread_id} and releases any file "
5105 "lock or other resources it has held. See @code{GETINFO} (@pxref{GETINFO}) "
5106 "for details about listing connected clients. An @code{invoking_user} "
5107 "(@pxref{Configuration}) may kill any client while others may only kill "
5108 "clients of the same @code{UID} or @abbr{TLS} fingerprint."
5111 new_command("LISTKEYS", 1, 0, 0, listkeys_command, _(
5112 "LISTKEYS [--secret-only] [pattern[,<pattern>]]\n" /* Listing keys in the key ring. */
5113 "Returns a new line separated list of key information matching a comma "
5114 "separated list of @var{pattern}'s. When option @option{--secret-only} is "
5115 "specified, only keys matching @var{pattern} that also have a secret key "
5116 "available will be returned."
5119 new_command("KEYINFO", 1, 0, 0, keyinfo_command, _(
5120 "KEYINFO [--learn]\n" /* Showing keys used for the current data file. */
5121 "Returns a new line separated list of key ID's that the currently opened "
5122 "data file has recipients and signers for. If the key is a signing key it "
5123 "will be prefixed with an @code{S}. If the file is a new one, or has no "
5124 "signers in the case of being symmetrically encrypted, the error code "
5125 "@code{GPG_ERR_NO_DATA} is returned."
5126 "@*@*"
5127 "When the @option{--learn} option is passed, keys on a smartcard will be "
5128 "imported."
5131 new_command("GETINFO", 1, 1, 0, getinfo_command, _(
5132 "GETINFO [--data] [--verbose] CACHE | CLIENTS | PID | USER | LAST_ERROR | VERSION\n" /* Obtaining server and client information. */
5133 "Get server and other information. The information is returned via a status "
5134 "message (@pxref{Status Messages}) unless otherwise noted or @option{--data} "
5135 "is specified."
5136 "@*@*"
5137 "@var{CACHE} returns the number of cached documents."
5138 "@*@*"
5139 "@var{CLIENTS} returns the number of "
5140 "connected clients via a status message or a list of connected clients when "
5141 "the @option{--verbose} parameter is used (implies @option{--data}). A "
5142 "verbose line of a client list contains "
5143 "space delimited "
5144 "fields: the thread ID, client name, opened file (@code{/} if none opened), "
5145 "IP address if remote, file lock status, whether the current client is self "
5146 "or not, client state (see below), "
5147 "user ID or TLS fingerprint of the connected client, username if the "
5148 "client is a local one else @code{-}, and finally the time stamp of when the "
5149 "client connected."
5150 "@*@*"
5151 "Client state @code{0} is an unknown client state, state @code{1} indicates "
5152 "the client has connected but hasn't completed initializing, state @code{2} "
5153 "indicates that the client is idle, state @code{3} means the "
5154 "client is in a command and state @code{4} means the client is disconnecting. "
5155 "@*@*"
5156 "@var{PID} returns the process ID number of the server via a data response."
5157 "@*@*"
5158 "@var{VERSION} returns the server version number and compile-time features "
5159 "via a data response with each being space delimited."
5160 "@*@*"
5161 "@var{LAST_ERROR} returns a detailed description of the last failed command "
5162 "via a data response, when available."
5163 "@*@*"
5164 "@var{USER} returns the username or @abbr{TLS} hash of the connected client "
5165 "via a data response."
5168 new_command("PASSWD", 0, 0, FLOCK_TYPE_EX|FLOCK_TYPE_KEEP, passwd_command, _(
5169 "PASSWD\n" /* Changing the passphrase for a key. */
5170 "Changes the passphrase of the secret key required to open the current "
5171 "data file. If the data file is symmetrically encrypted, the error "
5172 "@code{GPG_ERR_NOT_SUPPORTED} is returned. When symmetrically encrypted, "
5173 "the @code{SAVE} command (@pxref{SAVE}) should be used instead to prevent "
5174 "this command saving any unwanted changes to the @abbr{XML} document."
5175 "@*@*"
5176 "Note that when the current data file has been either encrypted or signed "
5177 "with a key stored on a smartcard this command will return an error. In this "
5178 "case you should instead use @command{gpg --card-edit} to change the "
5179 "pin of the smartcard or @command{gpg --edit-key} to change the passphrase "
5180 "of the key used to sign or encrypt the data file."
5181 "@*@*"
5182 "This command is not available to non-invoking clients "
5183 "(@pxref{Access Control})."
5186 new_command("OPEN", 1, 1, FLOCK_TYPE_SH|FLOCK_TYPE_KEEP, open_command, _(
5187 "OPEN [--lock] <filename>\n" /* Opening a data file. */
5188 "Opens @var{filename}. When the @var{filename} is not found on the "
5189 "file-system then a new in-memory document will be created. If the file is "
5190 "found, it is looked for in the file cache and when found no passphrase will "
5191 "be required to open it. When not cached, @cite{pinentry(1)} will be used to "
5192 "retrieve the passphrase for decryption unless @option{disable-pinentry} "
5193 "(@pxref{OPTION}) was specified in which case @command{pwmd} will "
5194 "@emph{INQUIRE} the client for the passphrase. Note than when configuration "
5195 "option @option{strict_open} is enabled and the client is not an "
5196 "@option{invoking_user}, an error will be returned when the data file does "
5197 "not exist."
5198 "@*@*"
5199 "When the @option{--lock} option is passed then the file mutex will be "
5200 "locked as if the @code{LOCK} command (@pxref{LOCK}) had been sent after the "
5201 "file had been opened."
5204 new_command("GENKEY", 1, 1, 0, genkey_command, _(
5205 "GENKEY --subkey-of=fpr | --userid=\"str\" [--no-expire | --expire=N] [--algo=\"str\"] [--no-passphrase] [--usage=\"default|sign|encrypt\"]\n" /* Generating a new key. */
5206 "Generates a new key based on option arguments. One of "
5207 "@option{--subkey-of} or @option{--userid} is "
5208 "required. The @option{--subkey-of} option will generate a subkey for the key "
5209 "of the specified fingerprint."
5212 new_command("SAVE", 0, 0, FLOCK_TYPE_EX|FLOCK_TYPE_KEEP, save_command, _(
5213 "SAVE [--sign-keyid=[<fpr>]] [--symmetric | --keyid=<fpr>[,..] | --inquire-keyid]\n" /* Saving document changes to disk. */
5214 "Writes the in-memory @abbr{XML} document to disk. The file written to is the "
5215 "file that was opened when using the @code{OPEN} command (@pxref{OPEN})."
5216 "@*@*"
5217 "If the file is a new one, one of @option{--symmetric}, @option{--keyid} or"
5218 "@option{--inquire-keyid} is required. When not @option{--symmetric}, option "
5219 "@option{--sign-keyid} is also required, but optional otherwise."
5220 "@*@*"
5221 "You can encrypt the data file to a recipient other than the one that it "
5222 "was originally encrypted with by passing the @option{--keyid} or "
5223 "@option{--inquire-keyid} option with a comma separated list of "
5224 "public encryption key fingerprints as its argument. Use the "
5225 "@command{LISTKEYS} command (@pxref{LISTKEYS}) to show key information by "
5226 "pattern. The @option{--sign-keyid} option may also be used to sign the data "
5227 "file with an alternate key by specifying the fingerprint of a signing key. "
5228 "Only one signing key is supported unlike the @option{--keyid} option. "
5229 "A passphrase to decrypt the data file "
5230 "will be required when one or more of the original encryption keys or signing "
5231 "key are not found in either of these two options' arguments or when the data "
5232 "file is symmetrically encrypted reguardless of the @code{require_save_key} "
5233 "configuration parameter. The original encryption keys and signing key will be "
5234 "used when neither of these options are specified."
5235 "@*@*"
5236 "The @option{--keyid} and @option{--sign-keyid} options are not available "
5237 "to non-invoking clients "
5238 "(@pxref{Access Control}) when the recipients or signer do not match those "
5239 "that were used when the file was @code{OPEN}'ed."
5240 "@*@*"
5241 "The @option{--symmetric} option specifies that a new data file be "
5242 "conventionally encrypted. These types of data files do not use a recipient "
5243 "public key but may optionally be signed by using the @option{--sign-keyid} "
5244 "option. To remove the signing key from a symmtrically encrypted data file, "
5245 "leave the option value empty."
5246 "@*@*"
5247 "Note that you cannot change encryption schemes once a data file has been "
5248 "saved."
5251 new_command("ISCACHED", 1, 0, 0, iscached_command, _(
5252 "ISCACHED [--lock] [--agent [--sign]] <filename>\n" /* Testing cache status. */
5253 "Determines the file cache status of the specified @var{filename}. "
5254 "The default is to test whether the filename is cached in memory. Passing "
5255 "option @option{--agent} will test the @command{gpg-agent} cache for at most "
5256 "one cached key used for opening the data file (@pxref{OPEN}). To test if "
5257 "a signing key is cached, pass @option{--sign} along with @option{--agent}. "
5258 "Both the @option{--agent} and @option{--sign} options require an opened data "
5259 "file."
5260 "@*@*"
5261 "An @emph{OK} response is returned if the specified @var{filename} is found "
5262 "in the cache. If not found in the cache but exists on the filesystem "
5263 "then @code{GPG_ERR_NO_DATA} is returned. Otherwise a filesystem error is "
5264 "returned."
5265 "@*@*"
5266 "The @option{--lock} option will lock the file mutex of @var{filename} when "
5267 "the file exists; it does not need to be opened nor cached. The lock will be "
5268 "released when the client exits or sends the @code{UNLOCK} command "
5269 "(@pxref{UNLOCK}). When this option is passed the current data file is closed."
5272 new_command("CLEARCACHE", 1, 1, 0, clearcache_command, _(
5273 "CLEARCACHE [<filename>]\n" /* Removing a cache entry. */
5274 "Clears a file cache entry for all or the specified @var{filename}. Note that "
5275 "this will also clear any @command{gpg-agent} cached keys which may cause "
5276 "problems if another data file shares the same keys as @var{filename}."
5277 "@*@*"
5278 "When clearing all cache entries a permissions test is done against the "
5279 "current client based on the @var{allowed} configuration parameter in a "
5280 "@var{filename} section. Both a cache entry may be cleared and an error "
5281 "returned depending on cached data files and client permissions."
5284 new_command("CACHETIMEOUT", 1, 1, 0, cachetimeout_command, _(
5285 "CACHETIMEOUT <seconds>\n" /* Setting the cache timeout. */
5286 "The time in @var{seconds} until the currently opened data file will be "
5287 "removed from the cache. @code{-1} will keep the cache entry forever, "
5288 "@code{0} will require the passphrase for each @code{OPEN} command "
5289 "(@pxref{OPEN}) or @code{SAVE} (@pxref{SAVE}) command. @xref{Configuration}, "
5290 "and the @code{cache_timeout} parameter."
5293 new_command("LIST", 0, 1, 0, list_command, _(
5294 "LIST [--inquire] [--recurse] [element[<TAB>child[..]]]\n" /* Showing document elements. */
5295 "If no element path is given then a newline separated list of root elements "
5296 "is returned with a data response. If given, then children of the specified "
5297 "element path are returned."
5298 "@*@*"
5299 "Each element path "
5300 "returned will have zero or more flags appened to it. These flags are "
5301 "delimited from the element path by a single space character. A flag itself "
5302 "is a single character. Flag @code{P} indicates that access to the element "
5303 "is denied. Flag @code{+} indicates that there are child nodes of "
5304 "the current element path. Flag @code{E} indicates that an element of the "
5305 "element path contained in a @var{target} attribute could not be found. Flag "
5306 "@code{O} indicates that a @var{target} attribute recursion limit was reached "
5307 "(@pxref{Configuration}). Flag @code{T}, followed by a single space character, "
5308 "then an element path, is the element path of the @var{target} attribute "
5309 "contained in the current element."
5310 "@*@*"
5311 "When a specified element path contains an error, beit from the final "
5312 "element in the path or any previous element, the path is still shown but "
5313 "will contain the error flag for the element with the error. Determining "
5314 "the actual element which contains the error is up to the client. This can be "
5315 "done by traversing the final element up to parent elements that contain the "
5316 "same error flag."
5317 "@*@*"
5318 "The option @option{--recurse} may be used to list the entire element tree "
5319 "for a specified element path or the entire tree for all root elements."
5320 "@*@*"
5321 "When the @option{--inquire} option is passed then all remaining non-option "
5322 "arguments are retrieved via a server @emph{INQUIRE}."
5325 new_command("REALPATH", 0, 1, 0, realpath_command, _(
5326 "REALPATH [--inquire] element[<TAB>child[..]]\n" /* Resolving an element. */
5327 "Resolves all @code{target} attributes of the specified element path and "
5328 "returns the result with a data response. @xref{Target Attribute}, for details."
5329 "@*@*"
5330 "When the @option{--inquire} option is passed then all remaining non-option "
5331 "arguments are retrieved via a server @emph{INQUIRE}."
5334 new_command("STORE", 0, 1, 0, store_command, _(
5335 "STORE element[<TAB>child[..]]<TAB>[content]\n" /* Modifying the content of an element. */
5336 "This command uses a server @emph{INQUIRE} to retrieve data from the client."
5337 "@*@*"
5338 "Creates a new element path or modifies the @var{content} of an existing "
5339 "element. If only a single element is specified then a new root element is "
5340 "created. Otherwise, elements are @key{TAB} delimited and the content will be "
5341 "set to the final @key{TAB} delimited element. If no @var{content} is "
5342 "specified after the final @key{TAB}, then the content of the existing "
5343 "element will be removed; or will be empty if creating a new element."
5344 "@*@*"
5345 "The only restriction of an element name is that it not contain whitespace "
5346 "characters. There is no other whitespace between the @key{TAB} delimited "
5347 "elements. It is recommended that the content of an element be base64 encoded "
5348 "when it contains control or @key{TAB} characters to prevent @abbr{XML} "
5349 "parsing and @command{pwmd} syntax errors."
5352 new_command("RENAME", 0, 1, 0, rename_command, _(
5353 "RENAME [--inquire] element[<TAB>child[..]] <value>\n" /* Renaming an element. */
5354 "Renames the specified @var{element} to the new @var{value}. If an element of "
5355 "the same name as the @var{value} already exists it will be overwritten."
5356 "@*@*"
5357 "When the @option{--inquire} option is passed then all remaining non-option "
5358 "arguments are retrieved via a server @emph{INQUIRE}."
5361 new_command("COPY", 0, 1, 0, copy_command, _(
5362 "COPY [--inquire] source[<TAB>child[..]] dest[<TAB>child[..]]\n" /* Copying an element. */
5363 "Copies the entire element tree starting from the child node of the source "
5364 "element, to the destination element path. If the destination element path "
5365 "does not exist then it will be created; otherwise it is overwritten."
5366 "@*@*"
5367 "Note that attributes from the source element are merged into the "
5368 "destination element when the destination element path exists. When an "
5369 "attribute of the same name exists in both the source and destination "
5370 "elements then the destination attribute will be updated to the source "
5371 "attribute value."
5372 "@*@*"
5373 "When the @option{--inquire} option is passed then all remaining non-option "
5374 "arguments are retrieved via a server @emph{INQUIRE}."
5377 new_command("MOVE", 0, 1, 0, move_command, _(
5378 "MOVE [--inquire] source[<TAB>child[..]] [dest[<TAB>child[..]]]\n" /* Moving an element. */
5379 "Moves the source element path to the destination element path. If the "
5380 "destination is not specified then it will be moved to the root node of the "
5381 "document. If the destination is specified and exists then it will be "
5382 "overwritten; otherwise non-existing elements of the destination element "
5383 "path will be created."
5384 "@*@*"
5385 "When the @option{--inquire} option is passed then all remaining non-option "
5386 "arguments are retrieved via a server @emph{INQUIRE}."
5389 new_command("DELETE", 0, 1, 0, delete_command, _(
5390 "DELETE [--inquire] element[<TAB>child[..]]\n" /* Deleting an element. */
5391 "Removes the specified element path and all of its children. This may break "
5392 "an element with a @code{target} attribute (@pxref{Target Attribute}) that "
5393 "refers to this element or any of its children."
5394 "@*@*"
5395 "When the @option{--inquire} option is passed then all remaining non-option "
5396 "arguments are retrieved via a server @emph{INQUIRE}."
5399 new_command("GET", 0, 1, 0, get_command, _(
5400 "GET [--inquire] element[<TAB>child[..]]\n" /* Getting the content of an element. */
5401 "Retrieves the content of the specified element. The content is returned "
5402 "with a data response."
5403 "@*@*"
5404 "When the @option{--inquire} option is passed then all remaining non-option "
5405 "arguments are retrieved via a server @emph{INQUIRE}."
5408 new_command("ATTR", 0, 1, 0, attr_command, _(
5409 "ATTR [--inquire] SET|GET|DELETE|LIST [<attribute>] element[<TAB>child[..]] ..\n" /* Modifying element attributes. */
5410 "@table @asis\n"
5411 "@item ATTR SET attribute element[<TAB>child[..]] [value]\n"
5412 " Stores or updates an @var{attribute} name and optional @var{value} of an "
5413 "element. When no @var{value} is specified any existing value will be removed."
5414 "@*@*"
5415 "@item ATTR DELETE attribute element[<TAB>child[..]]\n"
5416 " Removes an attribute from an element. If @var{attribute} is @code{_name} "
5417 "or @code{target} an error is returned. Use the @command{DELETE} command "
5418 "(@pxref{DELETE}) instead."
5419 "@*@*"
5420 "@item ATTR LIST element[<TAB>child[..]]\n"
5421 " Retrieves a newline separated list of attributes names and values "
5422 "from the specified element. Each attribute name and value is space delimited."
5423 "@*@*"
5424 "@item ATTR GET attribute element[<TAB>child[..]]\n"
5425 " Retrieves the value of an @var{attribute} from an element."
5426 "@end table\n"
5427 "@*@*"
5428 "When the @option{--inquire} option is passed then all remaining non-option "
5429 "arguments are retrieved via a server @emph{INQUIRE}."
5430 "@*@*"
5431 "@xref{Target Attribute}, for details about this special attribute and also "
5432 "@pxref{Other Attributes} for other attributes that are handled specially "
5433 "by @command{pwmd}."
5436 new_command("XPATH", 0, 1, 0, xpath_command, _(
5437 "XPATH [--inquire] <expression>[<TAB>[value]]\n" /* Modifying more than one element. */
5438 "Evaluates an XPath @var{expression}. If no @var{value} argument is "
5439 "specified it is assumed the expression is a request to return a result. "
5440 "Otherwise, the result is set to the @var{value} argument and the document is "
5441 "updated. If there is no @var{value} after the @key{TAB} character, the value "
5442 "is assumed to be empty and the document is updated. For example:"
5443 "@sp 1\n"
5444 "@example\n"
5445 "XPATH //element[@@_name='password']@key{TAB}\n"
5446 "@end example\n"
5447 "@sp 1\n"
5448 "would clear the content of all @var{password} elements in the data file "
5449 "while leaving off the trailing @key{TAB} would return all @var{password} "
5450 "elements in @abbr{XML} format."
5451 "@*@*"
5452 "When the @option{--inquire} option is passed then all remaining non-option "
5453 "arguments are retrieved via a server @emph{INQUIRE}."
5454 "@*@*"
5455 "See @url{http://www.w3schools.com/xpath/xpath_syntax.asp} for @abbr{XPATH} "
5456 "expression syntax."
5459 new_command("XPATHATTR", 0, 1, 0, xpathattr_command, _(
5460 "XPATHATTR [--inquire] SET|DELETE <name> <expression>[<TAB>[<value>]]\n" /* Modifying more than one element's attributes. */
5461 "Like the @code{XPATH} command (@pxref{XPATH}) but operates on element "
5462 "attributes and does not return a result. For the @var{SET} operation the "
5463 "@var{value} is optional but the field is required. If not specified then "
5464 "the attribute value will be empty. For example:"
5465 "@sp 1\n"
5466 "@example\n"
5467 "XPATHATTR SET password //element[@@_name='password']@key{TAB}\n"
5468 "@end example\n"
5469 "@sp 1\n"
5470 "would create a @var{password} attribute for each @var{password} element "
5471 "found in the document. The attribute value will be empty but still exist."
5472 "@*@*"
5473 "When the @option{--inquire} option is passed then all remaining non-option "
5474 "arguments are retrieved via a server @emph{INQUIRE}."
5475 "@*@*"
5476 "See @url{http://www.w3schools.com/xpath/xpath_syntax.asp} for @abbr{XPATH} "
5477 "expression syntax."
5480 new_command("IMPORT", 0, 1, 0, import_command, _(
5481 "IMPORT [--root=element[<TAB>child[..]]]\n" /* Creating elements from XML. */
5482 "This command uses a server @emph{INQUIRE} to retrieve data from the client."
5483 "@*@*"
5484 "Like the @code{STORE} command (@pxref{STORE}), but the @var{content} "
5485 "argument is raw @abbr{XML} data. The content is created as a child of "
5486 "the element path specified with the @option{--root} option or at the "
5487 "document root when not specified. Existing elements of the same name will "
5488 "be overwritten."
5489 "@*@*"
5490 "The content must begin with an @abbr{XML} element node. @xref{Introduction}, "
5491 "for details."
5494 new_command("DUMP", 1, 1, 0, dump_command, _(
5495 "DUMP\n" /* Showing the XML document. */
5496 "Shows the in memory @abbr{XML} document with indenting. @xref{XPATH}, for "
5497 "dumping a specific node."
5500 new_command("LOCK", 0, 0, 0, lock_command, _(
5501 "LOCK\n" /* Locking the current data file. */
5502 "Locks the mutex associated with the opened file. This prevents other clients "
5503 "from sending commands to the same opened file until the client "
5504 "that sent this command either disconnects or sends the @code{UNLOCK} "
5505 "command. @xref{UNLOCK}."
5508 new_command("UNLOCK", 1, 0, 0, unlock_command, _(
5509 "UNLOCK\n" /* Removing a data file lock. */
5510 "Unlocks the file mutex which was locked with the @code{LOCK} command or "
5511 "a commands' @option{--lock} option (@pxref{LOCK}, @pxref{OPEN}, "
5512 "@pxref{ISCACHED})."
5515 new_command("GETCONFIG", 1, 1, 0, getconfig_command, _(
5516 "GETCONFIG [filename] <parameter>\n" /* Obtaining a configuration value. */
5517 "Returns the value of a @command{pwmd} configuration @var{parameter} with a "
5518 "data response. If no file has been opened then the value for @var{filename} "
5519 "or the default from the @var{global} section will be returned. If a file "
5520 "has been opened and no @var{filename} is specified, the value previously "
5521 "set with the @code{OPTION} command (@pxref{OPTION}) will be returned."
5524 new_command("OPTION", 1, 1, 0, option_command, _(
5525 "OPTION <NAME>=[<VALUE>]\n" /* Setting various client parameters. */
5526 "Sets a client option @var{name} to @var{value}. The value for an option is "
5527 "kept for the duration of the connection with the exception of the "
5528 "@command{pinentry} options which are defaults for all future connections "
5529 "(@pxref{Pinentry}). When @var{value} is empty the option is unset."
5530 "@*@*"
5531 "@table @asis\n"
5532 "@item DISABLE-PINENTRY\n"
5533 "Disable use of @command{pinentry} for passphrase retrieval. When @code{1}, a "
5534 "server inquire is sent to the client to obtain the passphrase. This option "
5535 "may be set as needed before the @code{OPEN} (@pxref{OPEN}), @code{PASSWD} "
5536 "(@pxref{PASSWD}) and @code{SAVE} (@pxref{SAVE}) commands. Set to @code{0} "
5537 "to use a @command{pinentry}."
5538 "@*@*"
5539 "@item DISPLAY\n"
5540 "Set or unset the X11 display to use when prompting for a passphrase."
5541 "@*@*"
5542 "@item TTYNAME\n"
5543 "Set the terminal device path to use when prompting for a passphrase."
5544 "@*@*"
5545 "@item TTYTYPE\n"
5546 "Set the terminal type for use with @option{TTYNAME}."
5547 "@*@*"
5548 "@item NAME\n"
5549 "Associates the thread ID of the connection with the specified textual "
5550 "representation. Useful for debugging log messages. May not contain whitespace."
5551 "@*@*"
5552 "@item LOCK-TIMEOUT\n"
5553 "When not @code{0}, the duration in tenths of a second to wait for the file "
5554 "mutex which has been locked by another thread to be released before returning "
5555 "an error. When @code{-1} the error will be returned immediately."
5556 "@*@*"
5557 "@item CLIENT-STATE\n"
5558 "When set to @code{1} then client state status messages for other clients are "
5559 "sent to the current client. The default is @code{0}."
5560 "@end table\n"
5563 new_command("LS", 1, 1, 0, ls_command, _(
5564 "LS [--verbose]\n" /* Showing available data files. */
5565 "Returns a newline separated list of data files stored in the data directory "
5566 "@file{HOMEDIR/data} (@pxref{Invoking}) with a data response. When the "
5567 "@var{--verbose} option is passed, the space-separated filesystem inode "
5568 "access, modification and change times are appended to the line."
5571 new_command("BULK", 1, 1, 0, bulk_command, _(
5572 "BULK\n" /* Run a series of commands in sequence. */
5573 "Inquire a semi-canonical s-expression representing a series of protocol "
5574 "commands to be run in seqeunce (@pxref{Bulk Commands}). Returns a canonical "
5575 "s-expression containing each commands id, return value and result data "
5576 "(if any)."
5579 new_command("RESET", 1, 1, 0, NULL, _(
5580 "RESET\n" /* Resetting the client state. */
5581 "Closes the currently opened file but keeps any previously set client options "
5582 "(@pxref{OPTION})."
5585 new_command("NOP", 1, 1, 0, nop_command, _(
5586 "NOP\n" /* Testing the connection. */
5587 "This command does nothing. It is useful for testing the connection for a "
5588 "timeout condition."
5591 /* !END-HELP-TEXT! */
5592 new_command ("CANCEL", 1, 1, 0, NULL, NULL);
5593 new_command ("END", 1, 1, 0, NULL, NULL);
5594 new_command ("BYE", 1, 1, 0, NULL, NULL);
5596 int i;
5597 for (i = 0; command_table[i]; i++);
5598 qsort (command_table, i - 1, sizeof (struct command_table_s *),
5599 sort_commands);
5602 gpg_error_t
5603 register_commands (assuan_context_t ctx)
5605 int i = 0, rc;
5607 for (; command_table[i]; i++)
5609 if (!command_table[i]->handler)
5610 continue;
5612 rc = assuan_register_command (ctx, command_table[i]->name,
5613 command_table[i]->handler,
5614 command_table[i]->help);
5615 if (rc)
5616 return rc;
5619 rc = assuan_register_bye_notify (ctx, bye_notify);
5620 if (rc)
5621 return rc;
5623 rc = assuan_register_reset_notify (ctx, reset_notify);
5624 if (rc)
5625 return rc;
5627 rc = assuan_register_pre_cmd_notify (ctx, command_startup);
5628 if (rc)
5629 return rc;
5631 return assuan_register_post_cmd_notify (ctx, command_finalize);