1 /* gpgme-tool.c - Assuan server exposing GnuPG Made Easy operations.
2 Copyright (C) 2009, 2010, 2012, 2013 g10 Code GmbH
3 Copyright (C) 2001, 2003, 2009, 2011 Free Software Foundation, Inc.
5 This file is part of GPGME.
7 GPGME is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 GPGME is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this program; if not, see <https://www.gnu.org/licenses/>.
43 # define GT_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a)))
45 # define GT_GCC_A_SENTINEL(a)
48 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
49 # define GT_GCC_A_PRINTF(f, a) __attribute__ ((format (printf,f,a)))
51 # define GT_GCC_A_PRINTF(f, a)
54 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
55 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
56 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
57 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
63 /* A simple implementation of a dynamic buffer. Use init_membuf() to
64 create a buffer, put_membuf to append bytes and get_membuf to
65 release and return the buffer. Allocation errors are detected but
66 only returned at the final get_membuf(), this helps not to clutter
67 the code with out-of-core checks. */
69 /* The definition of the structure is private, we only need it here,
70 so it can be allocated on the stack. */
71 struct private_membuf_s
79 typedef struct private_membuf_s membuf_t;
81 /* Return the current length of the membuf. */
82 #define get_membuf_len(a) ((a)->len)
83 #define is_membuf_ready(a) ((a)->buf || (a)->out_of_core)
84 #define MEMBUF_ZERO { 0, 0, NULL, 0}
88 init_membuf (membuf_t *mb, int initiallen)
91 mb->size = initiallen;
93 mb->buf = malloc (initiallen);
95 mb->out_of_core = errno;
99 /* Shift the the content of the membuf MB by AMOUNT bytes. The next
100 operation will then behave as if AMOUNT bytes had not been put into
101 the buffer. If AMOUNT is greater than the actual accumulated
102 bytes, the membuf is basically reset to its initial state. */
103 #if 0 /* Not yet used. */
105 clear_membuf (membuf_t *mb, size_t amount)
107 /* No need to clear if we are already out of core. */
110 if (amount >= mb->len)
115 memmove (mb->buf, mb->buf+amount, mb->len);
121 put_membuf (membuf_t *mb, const void *buf, size_t len)
123 if (mb->out_of_core || !len)
126 if (mb->len + len >= mb->size)
130 mb->size += len + 1024;
131 p = realloc (mb->buf, mb->size);
134 mb->out_of_core = errno ? errno : ENOMEM;
139 memcpy (mb->buf + mb->len, buf, len);
144 #if 0 /* Not yet used. */
146 put_membuf_str (membuf_t *mb, const char *string)
148 put_membuf (mb, string, strlen (string));
154 get_membuf (membuf_t *mb, size_t *len)
165 gpg_err_set_errno (mb->out_of_core);
173 mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
178 /* Peek at the membuf MB. On success a pointer to the buffer is
179 returned which is valid until the next operation on MB. If LEN is
180 not NULL the current LEN of the buffer is stored there. On error
181 NULL is returned and ERRNO is set. */
182 #if 0 /* Not yet used. */
184 peek_membuf (membuf_t *mb, size_t *len)
190 gpg_err_set_errno (mb->out_of_core);
205 char program_name[] = "gpgme-tool";
207 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
210 void log_error (int status, gpg_error_t errnum,
211 const char *fmt, ...) GT_GCC_A_PRINTF(3,4);
222 log_error (int status, gpg_error_t errnum, const char *fmt, ...)
226 fprintf (log_stream, "%s: ", program_name);
228 vfprintf (log_stream, fmt, ap);
232 fprintf (log_stream, ": %s", gpg_strerror (errnum));
233 if (gpg_err_source (errnum) != GPG_ERR_SOURCE_GPGME)
234 fprintf (log_stream, " <%s>", gpg_strsource (errnum));
236 fprintf (log_stream, "\n");
242 /* Note that it is sufficient to allocate the target string D as long
243 as the source string S, i.e.: strlen(s)+1;. D == S is allowed. */
245 strcpy_escaped_plus (char *d, const char *s)
249 if (*s == '%' && s[1] && s[2])
264 /* Check whether the option NAME appears in LINE. */
266 has_option (const char *line, const char *name)
269 int n = strlen (name);
271 s = strstr (line, name);
272 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
275 /* Skip over options. It is assumed that leading spaces have been
276 removed (this is the case for lines passed to a handler from
277 assuan). Blanks after the options are also removed. */
279 skip_options (char *line)
281 while ( *line == '-' && line[1] == '-' )
283 while (*line && !spacep (line))
285 while (spacep (line))
294 typedef gpg_error_t (*result_xml_write_cb_t) (void *hook, const void *buf,
297 static char xml_preamble1[] = "<?xml version=\"1.0\" "
298 "encoding=\"UTF-8\" standalone=\"yes\"?>\n";
299 static const char xml_preamble2[] = "<gpgme>\n";
300 static const char xml_end[] = "</gpgme>\n";
303 struct result_xml_state
306 result_xml_write_cb_t cb;
311 const char *tag[MAX_TAGS];
312 int had_data[MAX_TAGS];
317 result_init (struct result_xml_state *state, int indent,
318 result_xml_write_cb_t cb, void *hook)
320 memset (state, '\0', sizeof (*state));
321 state->indent = indent;
328 result_xml_indent (struct result_xml_state *state)
330 char spaces[state->indent + 1];
332 for (i = 0; i < state->indent; i++)
335 return (*state->cb) (state->hook, spaces, i);
340 result_xml_tag_start (struct result_xml_state *state, const char *name, ...)
342 result_xml_write_cb_t cb = state->cb;
343 void *hook = state->hook;
347 char string_null[] = "(null)";
351 if (state->next_tag > 0)
353 if (! state->had_data[state->next_tag - 1])
355 (*cb) (hook, ">\n", 2);
356 (*cb) (hook, NULL, 0);
358 state->had_data[state->next_tag - 1] = 1;
361 result_xml_indent (state);
362 (*cb) (hook, "<", 1);
363 (*cb) (hook, name, strlen (name));
365 state->tag[state->next_tag] = name;
366 state->had_data[state->next_tag] = 0;
372 attr = va_arg (ap, char *);
376 attr_val = va_arg (ap, char *);
377 if (attr_val == NULL)
378 attr_val = string_null;
380 (*cb) (hook, " ", 1);
381 (*cb) (hook, attr, strlen (attr));
382 (*cb) (hook, "=\"", 2);
383 (*cb) (hook, attr_val, strlen (attr_val));
384 (*cb) (hook, "\"", 1);
390 /* Return a constant string with an XML entity for C. */
392 result_xml_escape_replacement(char c)
407 /* Escape DATA by replacing certain characters with their XML
408 entities. The result is stored in a newly allocated buffer which
409 address will be stored at BUF. Returns 0 on success. */
411 result_xml_escape (const char *data, char **buf)
417 init_membuf (&mb, 128);
420 data_len = strlen (data);
421 for (i = 0; i < data_len; i++)
423 r = result_xml_escape_replacement (data[i]);
425 put_membuf (&mb, r, strlen (r));
427 put_membuf (&mb, data+i, 1);
430 put_membuf (&mb, "", 1);
431 *buf = get_membuf (&mb, NULL);
432 return *buf? 0 : gpg_error_from_syserror ();
437 result_xml_tag_data (struct result_xml_state *state, const char *data)
440 result_xml_write_cb_t cb = state->cb;
441 void *hook = state->hook;
444 if (state->had_data[state->next_tag - 1])
446 (*cb) (hook, "\n", 2);
447 (*cb) (hook, NULL, 0);
448 result_xml_indent (state);
451 (*cb) (hook, ">", 1);
452 state->had_data[state->next_tag - 1] = 2;
454 err = result_xml_escape (data, &buf);
458 (*cb) (hook, buf, strlen (buf));
467 result_xml_tag_end (struct result_xml_state *state)
469 result_xml_write_cb_t cb = state->cb;
470 void *hook = state->hook;
475 if (state->had_data[state->next_tag])
477 if (state->had_data[state->next_tag] == 1)
478 result_xml_indent (state);
479 (*cb) (hook, "</", 2);
480 (*cb) (hook, state->tag[state->next_tag],
481 strlen (state->tag[state->next_tag]));
482 (*cb) (hook, ">\n", 2);
483 (*cb) (hook, NULL, 0);
487 (*cb) (hook, " />\n", 4);
488 (*cb) (hook, NULL, 0);
495 result_add_error (struct result_xml_state *state,
496 const char *name, gpg_error_t err)
500 snprintf (code, sizeof (code) - 1, "0x%x", err);
501 snprintf (msg, sizeof (msg) - 1, "%s <%s>",
502 gpg_strerror (err), gpg_strsource (err));
503 result_xml_tag_start (state, name, "value", code, NULL);
504 result_xml_tag_data (state, msg);
505 result_xml_tag_end (state);
511 result_add_pubkey_algo (struct result_xml_state *state,
512 const char *name, gpgme_pubkey_algo_t algo)
516 snprintf (code, sizeof (code) - 1, "0x%x", algo);
517 snprintf (msg, sizeof (msg) - 1, "%s",
518 gpgme_pubkey_algo_name (algo));
519 result_xml_tag_start (state, name, "value", code, NULL);
520 result_xml_tag_data (state, msg);
521 result_xml_tag_end (state);
527 result_add_hash_algo (struct result_xml_state *state,
528 const char *name, gpgme_hash_algo_t algo)
533 snprintf (code, sizeof (code) - 1, "0x%x", algo);
534 snprintf (msg, sizeof (msg) - 1, "%s",
535 gpgme_hash_algo_name (algo));
536 result_xml_tag_start (state, name, "value", code, NULL);
537 result_xml_tag_data (state, msg);
538 result_xml_tag_end (state);
544 result_add_keyid (struct result_xml_state *state,
545 const char *name, const char *keyid)
547 result_xml_tag_start (state, name, NULL);
548 result_xml_tag_data (state, keyid);
549 result_xml_tag_end (state);
555 result_add_fpr (struct result_xml_state *state,
556 const char *name, const char *fpr)
558 result_xml_tag_start (state, name, NULL);
559 result_xml_tag_data (state, fpr);
560 result_xml_tag_end (state);
566 result_add_timestamp (struct result_xml_state *state, const char *name,
567 unsigned int timestamp)
571 snprintf (code, sizeof (code) - 1, "%ui", timestamp);
572 result_xml_tag_start (state, name, "unix", code, NULL);
573 result_xml_tag_end (state);
579 result_add_sig_mode (struct result_xml_state *state, const char *name,
580 gpgme_sig_mode_t sig_mode)
585 snprintf (code, sizeof (code) - 1, "%i", sig_mode);
588 case GPGME_SIG_MODE_NORMAL:
591 case GPGME_SIG_MODE_DETACH:
594 case GPGME_SIG_MODE_CLEAR:
601 result_xml_tag_start (state, name, "type", mode, "value", code, NULL);
602 result_xml_tag_data (state, mode);
603 result_xml_tag_end (state);
609 result_add_protocol (struct result_xml_state *state, const char *name,
610 gpgme_protocol_t protocol)
615 snprintf (code, sizeof (code) - 1, "%i", protocol);
616 str = gpgme_get_protocol_name(protocol);
619 result_xml_tag_start (state, name, "value", code, NULL);
620 result_xml_tag_data (state, str);
621 result_xml_tag_end (state);
627 result_add_validity (struct result_xml_state *state, const char *name,
628 gpgme_validity_t validity)
633 snprintf (code, sizeof (code) - 1, "%i", validity);
636 case GPGME_VALIDITY_UNDEFINED:
639 case GPGME_VALIDITY_NEVER:
642 case GPGME_VALIDITY_MARGINAL:
645 case GPGME_VALIDITY_FULL:
648 case GPGME_VALIDITY_ULTIMATE:
655 result_xml_tag_start (state, name, "value", code, NULL);
656 result_xml_tag_data (state, str);
657 result_xml_tag_end (state);
663 result_add_value (struct result_xml_state *state,
664 const char *name, unsigned int val)
668 snprintf (code, sizeof (code) - 1, "0x%x", val);
669 result_xml_tag_start (state, name, "value", code, NULL);
670 result_xml_tag_end (state);
676 result_add_string (struct result_xml_state *state,
677 const char *name, const char *str)
681 result_xml_tag_start (state, name, NULL);
682 result_xml_tag_data (state, str);
683 result_xml_tag_end (state);
689 result_encrypt_to_xml (gpgme_ctx_t ctx, int indent,
690 result_xml_write_cb_t cb, void *hook)
692 struct result_xml_state state;
693 gpgme_encrypt_result_t res = gpgme_op_encrypt_result (ctx);
694 gpgme_invalid_key_t inv_recp;
699 result_init (&state, indent, cb, hook);
700 result_xml_tag_start (&state, "encrypt-result", NULL);
702 inv_recp = res->invalid_recipients;
705 result_xml_tag_start (&state, "invalid-recipients", NULL);
709 result_xml_tag_start (&state, "invalid-key", NULL);
711 result_add_fpr (&state, "fpr", inv_recp->fpr);
712 result_add_error (&state, "reason", inv_recp->reason);
713 result_xml_tag_end (&state);
714 inv_recp = inv_recp->next;
716 result_xml_tag_end (&state);
718 result_xml_tag_end (&state);
725 result_decrypt_to_xml (gpgme_ctx_t ctx, int indent,
726 result_xml_write_cb_t cb, void *hook)
728 struct result_xml_state state;
729 gpgme_decrypt_result_t res = gpgme_op_decrypt_result (ctx);
730 gpgme_recipient_t recp;
735 result_init (&state, indent, cb, hook);
736 result_xml_tag_start (&state, "decrypt-result", NULL);
740 result_xml_tag_start (&state, "file-name", NULL);
741 result_xml_tag_data (&state, res->file_name);
742 result_xml_tag_end (&state);
744 if (res->unsupported_algorithm)
746 result_xml_tag_start (&state, "unsupported-alogorithm", NULL);
747 result_xml_tag_data (&state, res->unsupported_algorithm);
748 result_xml_tag_end (&state);
750 if (res->wrong_key_usage)
752 result_xml_tag_start (&state, "wrong-key-usage", NULL);
753 result_xml_tag_end (&state);
756 recp = res->recipients;
759 result_xml_tag_start (&state, "recipients", NULL);
762 result_xml_tag_start (&state, "recipient", NULL);
763 result_add_keyid (&state, "keyid", recp->keyid);
764 result_add_pubkey_algo (&state, "pubkey-algo", recp->pubkey_algo);
765 result_add_error (&state, "status", recp->status);
766 result_xml_tag_end (&state);
769 result_xml_tag_end (&state);
771 result_xml_tag_end (&state);
778 result_sign_to_xml (gpgme_ctx_t ctx, int indent,
779 result_xml_write_cb_t cb, void *hook)
781 struct result_xml_state state;
782 gpgme_sign_result_t res = gpgme_op_sign_result (ctx);
783 gpgme_invalid_key_t inv_key;
784 gpgme_new_signature_t new_sig;
789 result_init (&state, indent, cb, hook);
790 result_xml_tag_start (&state, "sign-result", NULL);
792 inv_key = res->invalid_signers;
795 result_xml_tag_start (&state, "invalid-signers", NULL);
799 result_xml_tag_start (&state, "invalid-key", NULL);
801 result_add_fpr (&state, "fpr", inv_key->fpr);
802 result_add_error (&state, "reason", inv_key->reason);
803 result_xml_tag_end (&state);
804 inv_key = inv_key->next;
806 result_xml_tag_end (&state);
809 new_sig = res->signatures;
812 result_xml_tag_start (&state, "signatures", NULL);
816 result_xml_tag_start (&state, "new-signature", NULL);
817 result_add_sig_mode (&state, "type", new_sig->type);
818 result_add_pubkey_algo (&state, "pubkey-algo", new_sig->pubkey_algo);
819 result_add_hash_algo (&state, "hash-algo", new_sig->hash_algo);
820 result_add_timestamp (&state, "timestamp", new_sig->timestamp);
822 result_add_fpr (&state, "fpr", new_sig->fpr);
823 result_add_value (&state, "sig-class", new_sig->sig_class);
825 result_xml_tag_end (&state);
826 new_sig = new_sig->next;
828 result_xml_tag_end (&state);
831 result_xml_tag_end (&state);
838 result_verify_to_xml (gpgme_ctx_t ctx, int indent,
839 result_xml_write_cb_t cb, void *hook)
841 struct result_xml_state state;
842 gpgme_verify_result_t res = gpgme_op_verify_result (ctx);
843 gpgme_signature_t sig;
848 result_init (&state, indent, cb, hook);
849 result_xml_tag_start (&state, "verify-result", NULL);
853 result_xml_tag_start (&state, "file-name", NULL);
854 result_xml_tag_data (&state, res->file_name);
855 result_xml_tag_end (&state);
858 sig = res->signatures;
861 result_xml_tag_start (&state, "signatures", NULL);
865 result_xml_tag_start (&state, "signature", NULL);
867 /* FIXME: Could be done better. */
868 result_add_value (&state, "summary", sig->summary);
870 result_add_fpr (&state, "fpr", sig->fpr);
871 result_add_error (&state, "status", sig->status);
872 /* FIXME: notations */
873 result_add_timestamp (&state, "timestamp", sig->timestamp);
874 result_add_timestamp (&state, "exp-timestamp", sig->exp_timestamp);
875 result_add_value (&state, "wrong-key-usage", sig->wrong_key_usage);
876 result_add_value (&state, "pka-trust", sig->pka_trust);
877 result_add_value (&state, "chain-model", sig->chain_model);
878 result_add_value (&state, "validity", sig->validity);
879 result_add_error (&state, "validity-reason", sig->validity_reason);
880 result_add_pubkey_algo (&state, "pubkey-algo", sig->pubkey_algo);
881 result_add_hash_algo (&state, "hash-algo", sig->hash_algo);
882 if (sig->pka_address)
883 result_add_string (&state, "pka_address", sig->pka_address);
885 result_xml_tag_end (&state);
888 result_xml_tag_end (&state);
891 result_xml_tag_end (&state);
898 result_import_to_xml (gpgme_ctx_t ctx, int indent,
899 result_xml_write_cb_t cb, void *hook)
901 struct result_xml_state state;
902 gpgme_import_result_t res = gpgme_op_import_result (ctx);
903 gpgme_import_status_t stat;
908 result_init (&state, indent, cb, hook);
909 result_xml_tag_start (&state, "import-result", NULL);
911 result_add_value (&state, "considered", res->considered);
912 result_add_value (&state, "no-user-id", res->no_user_id);
913 result_add_value (&state, "imported", res->imported);
914 result_add_value (&state, "imported-rsa", res->imported_rsa);
915 result_add_value (&state, "unchanged", res->unchanged);
916 result_add_value (&state, "new-user-ids", res->new_user_ids);
917 result_add_value (&state, "new-sub-keys", res->new_sub_keys);
918 result_add_value (&state, "new-signatures", res->new_signatures);
919 result_add_value (&state, "new-revocations", res->new_revocations);
920 result_add_value (&state, "secret-read", res->secret_read);
921 result_add_value (&state, "secret-imported", res->secret_imported);
922 result_add_value (&state, "secret-unchanged", res->secret_unchanged);
923 result_add_value (&state, "skipped-new-keys", res->skipped_new_keys);
924 result_add_value (&state, "not-imported", res->not_imported);
929 result_xml_tag_start (&state, "imports", NULL);
933 result_xml_tag_start (&state, "import-status", NULL);
936 result_add_fpr (&state, "fpr", stat->fpr);
937 result_add_error (&state, "result", stat->result);
938 /* FIXME: Could be done better. */
939 result_add_value (&state, "status", stat->status);
941 result_xml_tag_end (&state);
944 result_xml_tag_end (&state);
947 result_xml_tag_end (&state);
954 result_genkey_to_xml (gpgme_ctx_t ctx, int indent,
955 result_xml_write_cb_t cb, void *hook)
957 struct result_xml_state state;
958 gpgme_genkey_result_t res = gpgme_op_genkey_result (ctx);
963 result_init (&state, indent, cb, hook);
964 result_xml_tag_start (&state, "genkey-result", NULL);
966 result_add_value (&state, "primary", res->primary);
967 result_add_value (&state, "sub", res->sub);
969 result_add_fpr (&state, "fpr", res->fpr);
971 result_xml_tag_end (&state);
978 result_keylist_to_xml (gpgme_ctx_t ctx, int indent,
979 result_xml_write_cb_t cb, void *hook)
981 struct result_xml_state state;
982 gpgme_keylist_result_t res = gpgme_op_keylist_result (ctx);
987 result_init (&state, indent, cb, hook);
988 result_xml_tag_start (&state, "keylist-result", NULL);
990 result_add_value (&state, "truncated", res->truncated);
992 result_xml_tag_end (&state);
999 result_vfs_mount_to_xml (gpgme_ctx_t ctx, int indent,
1000 result_xml_write_cb_t cb, void *hook)
1002 struct result_xml_state state;
1003 gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (ctx);
1008 result_init (&state, indent, cb, hook);
1009 result_xml_tag_start (&state, "vfs-mount-result", NULL);
1011 result_add_string (&state, "mount-dir", res->mount_dir);
1013 result_xml_tag_end (&state);
1026 STATUS_INCLUDE_CERTS,
1027 STATUS_KEYLIST_MODE,
1029 STATUS_ENCRYPT_RESULT,
1030 STATUS_IDENTIFY_RESULT
1033 const char *status_string[] =
1050 #define MAX_RECIPIENTS 10
1051 gpgme_key_t recipients[MAX_RECIPIENTS + 1];
1054 gpg_error_t (*write_status) (void *hook, const char *status, const char *msg);
1055 void *write_status_hook;
1056 gpg_error_t (*write_data) (void *hook, const void *buf, size_t len);
1057 void *write_data_hook;
1059 typedef struct gpgme_tool *gpgme_tool_t;
1062 /* Forward declaration. */
1063 void gt_write_status (gpgme_tool_t gt,
1064 status_t status, ...) GT_GCC_A_SENTINEL(0);
1066 server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
1067 int was_bad, int fd);
1071 _gt_progress_cb (void *opaque, const char *what,
1072 int type, int current, int total)
1074 gpgme_tool_t gt = opaque;
1077 snprintf (buf, sizeof (buf), "0x%02x %i %i", type, current, total);
1078 gt_write_status (gt, STATUS_PROGRESS, what, buf, NULL);
1083 _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
1087 err = gpgme_new (ctx);
1090 gpgme_set_progress_cb (*ctx, _gt_progress_cb, gt);
1096 gt_init (gpgme_tool_t gt)
1100 memset (gt, '\0', sizeof (*gt));
1102 err = _gt_gpgme_new (gt, >->ctx);
1104 log_error (1, err, "can't create gpgme context");
1109 gt_signers_add (gpgme_tool_t gt, const char *fpr)
1114 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1118 return gpgme_signers_add (gt->ctx, key);
1123 gt_signers_clear (gpgme_tool_t gt)
1125 gpgme_signers_clear (gt->ctx);
1131 gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key)
1134 gpgme_ctx_t listctx;
1138 if (!gt || !r_key || !pattern)
1139 return gpg_error (GPG_ERR_INV_VALUE);
1143 err = gpgme_new (&listctx);
1148 gpgme_protocol_t proto;
1149 gpgme_engine_info_t info;
1151 /* Clone the relevant state. */
1152 proto = gpgme_get_protocol (ctx);
1153 /* The g13 protocol does not allow keylisting, we need to choose
1155 if (proto == GPGME_PROTOCOL_G13)
1156 proto = GPGME_PROTOCOL_OpenPGP;
1158 gpgme_set_protocol (listctx, proto);
1159 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1160 info = gpgme_ctx_get_engine_info (ctx);
1161 while (info && info->protocol != proto)
1164 gpgme_ctx_set_engine_info (listctx, proto,
1165 info->file_name, info->home_dir);
1168 err = gpgme_op_keylist_start (listctx, pattern, 0);
1170 err = gpgme_op_keylist_next (listctx, r_key);
1174 err = gpgme_op_keylist_next (listctx, &key);
1175 if (gpgme_err_code (err) == GPG_ERR_EOF)
1180 && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1181 && key && key->subkeys && key->subkeys->fpr
1182 && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1184 /* The fingerprint is identical. We assume that this is
1185 the same key and don't mark it as an ambiguous. This
1186 problem may occur with corrupted keyrings and has
1187 been noticed often with gpgsm. In fact gpgsm uses a
1188 similar hack to sort out such duplicates but it can't
1189 do that while listing keys. */
1190 gpgme_key_unref (key);
1195 gpgme_key_unref (key);
1196 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1198 gpgme_key_unref (*r_key);
1201 gpgme_release (listctx);
1204 gt_write_status (gt, STATUS_RECIPIENT,
1205 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1206 (*r_key)->subkeys->fpr : "invalid", NULL);
1212 gt_recipients_add (gpgme_tool_t gt, const char *pattern)
1217 if (gt->recipients_nr >= MAX_RECIPIENTS)
1218 return gpg_error (GPG_ERR_ENOMEM);
1220 if (gpgme_get_protocol (gt->ctx) == GPGME_PROTOCOL_UISERVER)
1221 err = gpgme_key_from_uid (&key, pattern);
1223 err = gt_get_key (gt, pattern, &key);
1227 gt->recipients[gt->recipients_nr++] = key;
1233 gt_recipients_clear (gpgme_tool_t gt)
1237 for (idx = 0; idx < gt->recipients_nr; idx++)
1238 gpgme_key_unref (gt->recipients[idx]);
1239 memset (gt->recipients, '\0', gt->recipients_nr * sizeof (gpgme_key_t));
1240 gt->recipients_nr = 0;
1245 gt_reset (gpgme_tool_t gt)
1250 err = _gt_gpgme_new (gt, &ctx);
1254 gpgme_release (gt->ctx);
1256 gt_recipients_clear (gt);
1262 gt_write_status (gpgme_tool_t gt, status_t status, ...)
1271 va_start (ap, status);
1274 while ((text = va_arg (ap, const char *)))
1281 while (*text && n < sizeof (buf) - 2)
1290 err = gt->write_status (gt->write_status_hook, status_string[status], buf);
1292 log_error (1, err, "can't write status line");
1297 gt_write_data (gpgme_tool_t gt, const void *buf, size_t len)
1299 return gt->write_data (gt->write_data_hook, buf, len);
1304 gt_get_engine_info (gpgme_tool_t gt, gpgme_protocol_t proto)
1306 gpgme_engine_info_t info;
1307 info = gpgme_ctx_get_engine_info (gt->ctx);
1310 if (proto == GPGME_PROTOCOL_UNKNOWN || proto == info->protocol)
1311 gt_write_status (gt, STATUS_ENGINE,
1312 gpgme_get_protocol_name (info->protocol),
1313 info->file_name, info->version,
1314 info->req_version, info->home_dir, NULL);
1322 gt_protocol_from_name (const char *name)
1324 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_OpenPGP)))
1325 return GPGME_PROTOCOL_OpenPGP;
1326 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_CMS)))
1327 return GPGME_PROTOCOL_CMS;
1328 if (! strcasecmp (name,gpgme_get_protocol_name (GPGME_PROTOCOL_GPGCONF)))
1329 return GPGME_PROTOCOL_GPGCONF;
1330 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_ASSUAN)))
1331 return GPGME_PROTOCOL_ASSUAN;
1332 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_G13)))
1333 return GPGME_PROTOCOL_G13;
1334 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_UISERVER)))
1335 return GPGME_PROTOCOL_UISERVER;
1336 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_SPAWN)))
1337 return GPGME_PROTOCOL_SPAWN;
1338 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_DEFAULT)))
1339 return GPGME_PROTOCOL_DEFAULT;
1340 return GPGME_PROTOCOL_UNKNOWN;
1345 gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1347 return gpgme_set_protocol (gt->ctx, proto);
1352 gt_get_protocol (gpgme_tool_t gt)
1354 gpgme_protocol_t proto = gpgme_get_protocol (gt->ctx);
1356 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1364 gt_set_sub_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1366 return gpgme_set_sub_protocol (gt->ctx, proto);
1371 gt_get_sub_protocol (gpgme_tool_t gt)
1373 gpgme_protocol_t proto = gpgme_get_sub_protocol (gt->ctx);
1375 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1383 gt_set_pinentry_mode (gpgme_tool_t gt, gpgme_pinentry_mode_t mode, void *opaque)
1387 gpgme_set_passphrase_cb (gt->ctx, NULL, NULL);
1388 err = gpgme_set_pinentry_mode (gt->ctx, mode);
1389 if (!err && mode == GPGME_PINENTRY_MODE_LOOPBACK)
1390 gpgme_set_passphrase_cb (gt->ctx, server_passphrase_cb, opaque);
1396 gt_set_armor (gpgme_tool_t gt, int armor)
1398 gpgme_set_armor (gt->ctx, armor);
1404 gt_get_armor (gpgme_tool_t gt)
1406 gt_write_status (gt, STATUS_ARMOR,
1407 gpgme_get_armor (gt->ctx) ? "true" : "false", NULL);
1414 gt_set_textmode (gpgme_tool_t gt, int textmode)
1416 gpgme_set_textmode (gt->ctx, textmode);
1422 gt_get_textmode (gpgme_tool_t gt)
1424 gt_write_status (gt, STATUS_TEXTMODE,
1425 gpgme_get_textmode (gt->ctx) ? "true" : "false", NULL);
1432 gt_set_keylist_mode (gpgme_tool_t gt, gpgme_keylist_mode_t keylist_mode)
1434 gpgme_set_keylist_mode (gt->ctx, keylist_mode);
1440 gt_get_keylist_mode (gpgme_tool_t gt)
1442 #define NR_KEYLIST_MODES 6
1443 const char *modes[NR_KEYLIST_MODES + 1];
1445 gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx);
1447 if (mode & GPGME_KEYLIST_MODE_LOCAL)
1448 modes[idx++] = "local";
1449 if (mode & GPGME_KEYLIST_MODE_EXTERN)
1450 modes[idx++] = "extern";
1451 if (mode & GPGME_KEYLIST_MODE_SIGS)
1452 modes[idx++] = "sigs";
1453 if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
1454 modes[idx++] = "sig_notations";
1455 if (mode & GPGME_KEYLIST_MODE_WITH_SECRET)
1456 modes[idx++] = "with_secret";
1457 if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
1458 modes[idx++] = "ephemeral";
1459 if (mode & GPGME_KEYLIST_MODE_VALIDATE)
1460 modes[idx++] = "validate";
1461 modes[idx++] = NULL;
1463 gt_write_status (gt, STATUS_KEYLIST_MODE, modes[0], modes[1], modes[2],
1464 modes[3], modes[4], modes[5], modes[6], NULL);
1471 gt_set_include_certs (gpgme_tool_t gt, int include_certs)
1473 gpgme_set_include_certs (gt->ctx, include_certs);
1479 gt_get_include_certs (gpgme_tool_t gt)
1481 int include_certs = gpgme_get_include_certs (gt->ctx);
1484 if (include_certs == GPGME_INCLUDE_CERTS_DEFAULT)
1485 strcpy (buf, "default");
1487 snprintf (buf, sizeof (buf), "%i", include_certs);
1489 gt_write_status (gt, STATUS_INCLUDE_CERTS, buf, NULL);
1496 gt_decrypt_verify (gpgme_tool_t gt, gpgme_data_t cipher, gpgme_data_t plain,
1500 return gpgme_op_decrypt_verify (gt->ctx, cipher, plain);
1502 return gpgme_op_decrypt (gt->ctx, cipher, plain);
1507 gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
1508 gpgme_data_t plain, gpgme_data_t cipher, int sign)
1513 recp = gt->recipients_nr? gt->recipients : NULL;
1516 err = gpgme_op_encrypt_sign (gt->ctx, recp, flags, plain, cipher);
1518 err = gpgme_op_encrypt (gt->ctx, recp, flags, plain, cipher);
1520 gt_recipients_clear (gt);
1527 gt_sign (gpgme_tool_t gt, gpgme_data_t plain, gpgme_data_t sig,
1528 gpgme_sig_mode_t mode)
1530 return gpgme_op_sign (gt->ctx, plain, sig, mode);
1535 gt_verify (gpgme_tool_t gt, gpgme_data_t sig, gpgme_data_t sig_text,
1538 return gpgme_op_verify (gt->ctx, sig, sig_text, plain);
1543 gt_import (gpgme_tool_t gt, gpgme_data_t data)
1545 return gpgme_op_import (gt->ctx, data);
1550 gt_export (gpgme_tool_t gt, const char *pattern[], gpgme_export_mode_t mode,
1553 return gpgme_op_export_ext (gt->ctx, pattern, mode, data);
1558 gt_genkey (gpgme_tool_t gt, const char *parms, gpgme_data_t public,
1559 gpgme_data_t secret)
1561 return gpgme_op_genkey (gt->ctx, parms, public, secret);
1566 gt_import_keys (gpgme_tool_t gt, char *fpr[])
1568 gpg_error_t err = 0;
1578 return gpg_error (GPG_ERR_INV_VALUE);
1580 keys = malloc ((cnt + 1) * sizeof (gpgme_key_t));
1582 return gpg_error_from_syserror ();
1584 for (idx = 0; idx < cnt; idx++)
1586 err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0);
1593 err = gpgme_op_import_keys (gt->ctx, keys);
1598 gpgme_key_unref (keys[idx]);
1606 gt_delete (gpgme_tool_t gt, char *fpr, int allow_secret)
1611 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1615 err = gpgme_op_delete (gt->ctx, key, allow_secret);
1616 gpgme_key_unref (key);
1622 gt_keylist_start (gpgme_tool_t gt, const char *pattern[], int secret_only)
1624 return gpgme_op_keylist_ext_start (gt->ctx, pattern, secret_only, 0);
1629 gt_keylist_next (gpgme_tool_t gt, gpgme_key_t *key)
1631 return gpgme_op_keylist_next (gt->ctx, key);
1636 gt_getauditlog (gpgme_tool_t gt, gpgme_data_t output, unsigned int flags)
1638 return gpgme_op_getauditlog (gt->ctx, output, flags);
1643 gt_vfs_mount (gpgme_tool_t gt, const char *container_file,
1644 const char *mount_dir, int flags)
1648 err = gpgme_op_vfs_mount (gt->ctx, container_file, mount_dir, flags, &op_err);
1649 return err ? err : op_err;
1654 gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
1658 err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file,
1660 gt_recipients_clear (gt);
1661 return err ? err : op_err;
1666 gt_passwd (gpgme_tool_t gt, char *fpr)
1671 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1673 return gpg_err_code (err) == GPG_ERR_EOF? gpg_error (GPG_ERR_NO_PUBKEY):err;
1675 err = gpgme_op_passwd (gt->ctx, key, 0);
1676 gpgme_key_unref (key);
1682 gt_identify (gpgme_tool_t gt, gpgme_data_t data)
1684 const char *s = "?";
1686 switch (gpgme_data_identify (data, 0))
1688 case GPGME_DATA_TYPE_INVALID: return gpg_error (GPG_ERR_GENERAL);
1689 case GPGME_DATA_TYPE_UNKNOWN : s = "unknown"; break;
1690 case GPGME_DATA_TYPE_PGP_SIGNED : s = "PGP-signed"; break;
1691 case GPGME_DATA_TYPE_PGP_SIGNATURE: s = "PGP-signature"; break;
1692 case GPGME_DATA_TYPE_PGP_ENCRYPTED: s = "PGP-encrypted"; break;
1693 case GPGME_DATA_TYPE_PGP_OTHER : s = "PGP"; break;
1694 case GPGME_DATA_TYPE_PGP_KEY : s = "PGP-key"; break;
1695 case GPGME_DATA_TYPE_CMS_SIGNED : s = "CMS-signed"; break;
1696 case GPGME_DATA_TYPE_CMS_ENCRYPTED: s = "CMS-encrypted"; break;
1697 case GPGME_DATA_TYPE_CMS_OTHER : s = "CMS"; break;
1698 case GPGME_DATA_TYPE_X509_CERT : s = "X.509"; break;
1699 case GPGME_DATA_TYPE_PKCS12 : s = "PKCS12"; break;
1701 gt_write_status (gt, STATUS_IDENTIFY_RESULT, s, NULL);
1707 gt_spawn (gpgme_tool_t gt, const char *pgm,
1708 gpgme_data_t inp, gpgme_data_t outp)
1712 err = gpgme_op_spawn (gt->ctx, pgm, NULL, inp, outp, outp, 0);
1718 #define GT_RESULT_ENCRYPT 0x1
1719 #define GT_RESULT_DECRYPT 0x2
1720 #define GT_RESULT_SIGN 0x4
1721 #define GT_RESULT_VERIFY 0x8
1722 #define GT_RESULT_IMPORT 0x10
1723 #define GT_RESULT_GENKEY 0x20
1724 #define GT_RESULT_KEYLIST 0x40
1725 #define GT_RESULT_VFS_MOUNT 0x80
1726 #define GT_RESULT_ALL (~0U)
1729 gt_result (gpgme_tool_t gt, unsigned int flags)
1733 gt_write_data (gt, xml_preamble1, strlen (xml_preamble1));
1734 gt_write_data (gt, NULL, 0);
1735 gt_write_data (gt, xml_preamble2, strlen (xml_preamble2));
1736 gt_write_data (gt, NULL, 0);
1737 if (flags & GT_RESULT_ENCRYPT)
1738 result_encrypt_to_xml (gt->ctx, indent,
1739 (result_xml_write_cb_t) gt_write_data, gt);
1740 if (flags & GT_RESULT_DECRYPT)
1741 result_decrypt_to_xml (gt->ctx, indent,
1742 (result_xml_write_cb_t) gt_write_data, gt);
1743 if (flags & GT_RESULT_SIGN)
1744 result_sign_to_xml (gt->ctx, indent,
1745 (result_xml_write_cb_t) gt_write_data, gt);
1746 if (flags & GT_RESULT_VERIFY)
1747 result_verify_to_xml (gt->ctx, indent,
1748 (result_xml_write_cb_t) gt_write_data, gt);
1749 if (flags & GT_RESULT_IMPORT)
1750 result_import_to_xml (gt->ctx, indent,
1751 (result_xml_write_cb_t) gt_write_data, gt);
1752 if (flags & GT_RESULT_GENKEY)
1753 result_genkey_to_xml (gt->ctx, indent,
1754 (result_xml_write_cb_t) gt_write_data, gt);
1755 if (flags & GT_RESULT_KEYLIST)
1756 result_keylist_to_xml (gt->ctx, indent,
1757 (result_xml_write_cb_t) gt_write_data, gt);
1758 if (flags & GT_RESULT_VFS_MOUNT)
1759 result_vfs_mount_to_xml (gt->ctx, indent,
1760 (result_xml_write_cb_t) gt_write_data, gt);
1761 gt_write_data (gt, xml_end, strlen (xml_end));
1774 assuan_context_t assuan_ctx;
1776 gpgme_data_encoding_t input_enc;
1777 gpgme_data_encoding_t output_enc;
1778 assuan_fd_t input_fd;
1779 char *input_filename;
1781 assuan_fd_t output_fd;
1782 char *output_filename;
1783 FILE *output_stream;
1784 assuan_fd_t message_fd;
1785 char *message_filename;
1786 FILE *message_stream;
1787 gpgme_data_encoding_t message_enc;
1792 server_write_status (void *hook, const char *status, const char *msg)
1794 struct server *server = hook;
1795 return assuan_write_status (server->assuan_ctx, status, msg);
1800 server_write_data (void *hook, const void *buf, size_t len)
1802 struct server *server = hook;
1803 return assuan_send_data (server->assuan_ctx, buf, len);
1808 server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
1809 int was_bad, int fd)
1811 struct server *server = opaque;
1813 unsigned char *buf = NULL;
1818 if (server && server->assuan_ctx)
1821 assuan_write_status (server->assuan_ctx, "USERID_HINT", uid_hint);
1823 assuan_write_status (server->assuan_ctx, "NEED_PASSPHRASE", info);
1825 err = assuan_inquire (server->assuan_ctx, "PASSPHRASE",
1826 &buf, &buflen, 100);
1829 err = gpg_error (GPG_ERR_NO_PASSPHRASE);
1833 /* We take care to always send a LF. */
1834 if (gpgme_io_writen (fd, buf, buflen))
1835 err = gpg_error_from_syserror ();
1836 else if (!memchr (buf, '\n', buflen) && gpgme_io_writen (fd, "\n", 1))
1837 err = gpg_error_from_syserror ();
1844 /* Wrapper around assuan_command_parse_fd to also handle a
1845 "file=FILENAME" argument. On success either a filename is returned
1846 at FILENAME or a file descriptor at RFD; the other one is set to
1847 NULL respective ASSUAN_INVALID_FD. */
1849 server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd,
1852 *rfd = ASSUAN_INVALID_FD;
1855 if (! strncasecmp (line, "file=", 5))
1858 *filename = strdup (line + 5);
1860 return gpg_error_from_syserror();
1861 term = strchr (*filename, ' ');
1867 return assuan_command_parse_fd (ctx, line, rfd);
1871 static gpgme_data_encoding_t
1872 server_data_encoding (const char *line)
1874 if (strstr (line, "--binary"))
1875 return GPGME_DATA_ENCODING_BINARY;
1876 if (strstr (line, "--base64"))
1877 return GPGME_DATA_ENCODING_BASE64;
1878 if (strstr (line, "--armor"))
1879 return GPGME_DATA_ENCODING_ARMOR;
1880 if (strstr (line, "--url"))
1881 return GPGME_DATA_ENCODING_URL;
1882 if (strstr (line, "--urlesc"))
1883 return GPGME_DATA_ENCODING_URLESC;
1884 if (strstr (line, "--url0"))
1885 return GPGME_DATA_ENCODING_URL0;
1886 if (strstr (line, "--mime"))
1887 return GPGME_DATA_ENCODING_MIME;
1888 return GPGME_DATA_ENCODING_NONE;
1892 static gpgme_error_t
1893 server_data_obj (assuan_fd_t fd, char *fn, int out,
1894 gpgme_data_encoding_t encoding,
1895 gpgme_data_t *data, FILE **fs)
1902 *fs = fopen (fn, out ? "wb" : "rb");
1904 return gpg_error_from_syserror ();
1906 err = gpgme_data_new_from_stream (data, *fs);
1909 err = gpgme_data_new_from_fd (data, (int) fd);
1913 return gpgme_data_set_encoding (*data, encoding);
1918 server_reset_fds (struct server *server)
1920 /* assuan closes the input and output FDs for us when doing a RESET,
1921 but we use this same function after commands, so repeat it
1923 if (server->input_fd != ASSUAN_INVALID_FD)
1926 CloseHandle (server->input_fd);
1928 close (server->input_fd);
1930 server->input_fd = ASSUAN_INVALID_FD;
1932 if (server->output_fd != ASSUAN_INVALID_FD)
1935 CloseHandle (server->output_fd);
1937 close (server->output_fd);
1939 server->output_fd = ASSUAN_INVALID_FD;
1941 if (server->message_fd != ASSUAN_INVALID_FD)
1943 /* FIXME: Assuan should provide a close function. */
1945 CloseHandle (server->message_fd);
1947 close (server->message_fd);
1949 server->message_fd = ASSUAN_INVALID_FD;
1951 if (server->input_filename)
1953 free (server->input_filename);
1954 server->input_filename = NULL;
1956 if (server->output_filename)
1958 free (server->output_filename);
1959 server->output_filename = NULL;
1961 if (server->message_filename)
1963 free (server->message_filename);
1964 server->message_filename = NULL;
1966 if (server->input_stream)
1968 fclose (server->input_stream);
1969 server->input_stream = NULL;
1971 if (server->output_stream)
1973 fclose (server->output_stream);
1974 server->output_stream = NULL;
1976 if (server->message_stream)
1978 fclose (server->message_stream);
1979 server->message_stream = NULL;
1982 server->input_enc = GPGME_DATA_ENCODING_NONE;
1983 server->output_enc = GPGME_DATA_ENCODING_NONE;
1984 server->message_enc = GPGME_DATA_ENCODING_NONE;
1989 reset_notify (assuan_context_t ctx, char *line)
1991 struct server *server = assuan_get_pointer (ctx);
1995 server_reset_fds (server);
1996 gt_reset (server->gt);
2001 static const char hlp_version[] =
2002 "VERSION [<string>]\n"
2004 "Call the function gpgme_check_version.";
2006 cmd_version (assuan_context_t ctx, char *line)
2010 const char *version = gpgme_check_version (line);
2011 return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
2015 const char *version = gpgme_check_version (NULL);
2016 return assuan_send_data (ctx, version, strlen (version));
2021 static const char hlp_engine[] =
2022 "ENGINE [<string>]\n"
2024 "Get information about a GPGME engine (a.k.a. protocol).";
2026 cmd_engine (assuan_context_t ctx, char *line)
2028 struct server *server = assuan_get_pointer (ctx);
2029 return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
2033 static const char hlp_protocol[] =
2034 "PROTOCOL [<name>]\n"
2036 "With NAME, set the protocol. Without, return the current\n"
2039 cmd_protocol (assuan_context_t ctx, char *line)
2041 struct server *server = assuan_get_pointer (ctx);
2043 return gt_set_protocol (server->gt, gt_protocol_from_name (line));
2045 return gt_get_protocol (server->gt);
2049 static const char hlp_sub_protocol[] =
2050 "SUB_PROTOCOL [<name>]\n"
2052 "With NAME, set the sub-protocol. Without, return the\n"
2053 "current sub-protocol.";
2055 cmd_sub_protocol (assuan_context_t ctx, char *line)
2057 struct server *server = assuan_get_pointer (ctx);
2059 return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
2061 return gt_get_sub_protocol (server->gt);
2065 static const char hlp_pinentry_mode[] =
2066 "PINENTRY_MODE <name>\n"
2068 "Set the pinentry mode to NAME. Allowedvalues for NAME are:\n"
2069 " default - reset to the default of the engine,\n"
2070 " ask - force the use of the pinentry,\n"
2071 " cancel - emulate use of pinentry's cancel button,\n"
2072 " error - return a pinentry error,\n"
2073 " loopback - redirect pinentry queries to the caller.\n"
2074 "Note that only recent versions of GPG support changing the pinentry mode.";
2076 cmd_pinentry_mode (assuan_context_t ctx, char *line)
2078 struct server *server = assuan_get_pointer (ctx);
2079 gpgme_pinentry_mode_t mode;
2081 if (!line || !*line || !strcmp (line, "default"))
2082 mode = GPGME_PINENTRY_MODE_DEFAULT;
2083 else if (!strcmp (line, "ask"))
2084 mode = GPGME_PINENTRY_MODE_ASK;
2085 else if (!strcmp (line, "cancel"))
2086 mode = GPGME_PINENTRY_MODE_CANCEL;
2087 else if (!strcmp (line, "error"))
2088 mode = GPGME_PINENTRY_MODE_ERROR;
2089 else if (!strcmp (line, "loopback"))
2090 mode = GPGME_PINENTRY_MODE_LOOPBACK;
2092 return gpg_error (GPG_ERR_INV_VALUE);
2094 return gt_set_pinentry_mode (server->gt, mode, server);
2098 static const char hlp_armor[] =
2099 "ARMOR [true|false]\n"
2101 "With 'true' or 'false', turn output ASCII armoring on or\n"
2102 "off. Without, return the current armoring status.";
2104 cmd_armor (assuan_context_t ctx, char *line)
2106 struct server *server = assuan_get_pointer (ctx);
2111 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2115 return gt_set_armor (server->gt, flag);
2118 return gt_get_armor (server->gt);
2122 static const char hlp_textmode[] =
2123 "TEXTMODE [true|false]\n"
2125 "With 'true' or 'false', turn text mode on or off.\n"
2126 "Without, return the current text mode status.";
2128 cmd_textmode (assuan_context_t ctx, char *line)
2130 struct server *server = assuan_get_pointer (ctx);
2135 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2139 return gt_set_textmode (server->gt, flag);
2142 return gt_get_textmode (server->gt);
2146 static const char hlp_include_certs[] =
2147 "INCLUDE_CERTS [default|<n>]\n"
2149 "With DEFAULT or N, set how many certificates should be\n"
2150 "included in the next S/MIME signed message. See the\n"
2151 "GPGME documentation for details on the meaning of"
2152 "various N. Without either, return the current setting.";
2154 cmd_include_certs (assuan_context_t ctx, char *line)
2156 struct server *server = assuan_get_pointer (ctx);
2160 int include_certs = 0;
2162 if (! strcasecmp (line, "default"))
2163 include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
2165 include_certs = atoi (line);
2167 return gt_set_include_certs (server->gt, include_certs);
2170 return gt_get_include_certs (server->gt);
2174 static const char hlp_keylist_mode[] =
2175 "KEYLIST_MODE [local] [extern] [sigs] [sig_notations]\n"
2176 " [ephemeral] [validate]\n"
2178 "Set the mode for the next KEYLIST command.";
2180 cmd_keylist_mode (assuan_context_t ctx, char *line)
2182 struct server *server = assuan_get_pointer (ctx);
2186 gpgme_keylist_mode_t mode = 0;
2188 if (strstr (line, "local"))
2189 mode |= GPGME_KEYLIST_MODE_LOCAL;
2190 if (strstr (line, "extern"))
2191 mode |= GPGME_KEYLIST_MODE_EXTERN;
2192 if (strstr (line, "sigs"))
2193 mode |= GPGME_KEYLIST_MODE_SIGS;
2194 if (strstr (line, "sig_notations"))
2195 mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
2196 if (strstr (line, "with_secret"))
2197 mode |= GPGME_KEYLIST_MODE_WITH_SECRET;
2198 if (strstr (line, "ephemeral"))
2199 mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
2200 if (strstr (line, "validate"))
2201 mode |= GPGME_KEYLIST_MODE_VALIDATE;
2203 return gt_set_keylist_mode (server->gt, mode);
2206 return gt_get_keylist_mode (server->gt);
2210 static const char hlp_input[] =
2211 "INPUT [<fd>|FILE=<path>]\n"
2213 "Set the input for the next command. Use either the\n"
2214 "Assuan file descriptor FD or a filesystem PATH.";
2216 cmd_input (assuan_context_t ctx, char *line)
2218 struct server *server = assuan_get_pointer (ctx);
2223 err = server_parse_fd (ctx, line, &sysfd, &filename);
2226 server->input_fd = sysfd;
2227 server->input_filename = filename;
2228 server->input_enc = server_data_encoding (line);
2233 static const char hlp_output[] =
2234 "OUTPUT [<fd>|FILE=<path>]\n"
2236 "Set the output for the next command. Use either the\n"
2237 "Assuan file descriptor FD or a filesystem PATH.";
2239 cmd_output (assuan_context_t ctx, char *line)
2241 struct server *server = assuan_get_pointer (ctx);
2246 err = server_parse_fd (ctx, line, &sysfd, &filename);
2249 server->output_fd = sysfd;
2250 server->output_filename = filename;
2251 server->output_enc = server_data_encoding (line);
2256 static const char hlp_message[] =
2257 "MESSAGE [<fd>|FILE=<path>]\n"
2259 "Set the plaintext message for the next VERIFY command\n"
2260 "with a detached signature. Use either the Assuan file\n"
2261 "descriptor FD or a filesystem PATH.";
2263 cmd_message (assuan_context_t ctx, char *line)
2265 struct server *server = assuan_get_pointer (ctx);
2270 err = server_parse_fd (ctx, line, &sysfd, &filename);
2273 server->message_fd = sysfd;
2274 server->message_filename = filename;
2275 server->message_enc = server_data_encoding (line);
2280 static const char hlp_recipient[] =
2281 "RECIPIENT <pattern>\n"
2283 "Add the key matching PATTERN to the list of recipients\n"
2284 "for the next encryption command.";
2286 cmd_recipient (assuan_context_t ctx, char *line)
2288 struct server *server = assuan_get_pointer (ctx);
2290 return gt_recipients_add (server->gt, line);
2294 static const char hlp_signer[] =
2295 "SIGNER <fingerprint>\n"
2297 "Add the key with FINGERPRINT to the list of signers to\n"
2298 "be used for the next signing command.";
2300 cmd_signer (assuan_context_t ctx, char *line)
2302 struct server *server = assuan_get_pointer (ctx);
2304 return gt_signers_add (server->gt, line);
2308 static const char hlp_signers_clear[] =
2311 "Clear the list of signers specified by previous SIGNER\n"
2314 cmd_signers_clear (assuan_context_t ctx, char *line)
2316 struct server *server = assuan_get_pointer (ctx);
2320 return gt_signers_clear (server->gt);
2325 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
2327 struct server *server = assuan_get_pointer (ctx);
2333 gpgme_data_t inp_data;
2334 gpgme_data_t out_data;
2338 inp_fd = server->input_fd;
2339 inp_fn = server->input_filename;
2340 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2341 return GPG_ERR_ASS_NO_INPUT;
2342 out_fd = server->output_fd;
2343 out_fn = server->output_filename;
2344 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2345 return GPG_ERR_ASS_NO_OUTPUT;
2347 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2348 &server->input_stream);
2351 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2352 &server->output_stream);
2355 gpgme_data_release (inp_data);
2359 err = gt_decrypt_verify (server->gt, inp_data, out_data, verify);
2361 gpgme_data_release (inp_data);
2362 gpgme_data_release (out_data);
2364 server_reset_fds (server);
2370 static const char hlp_decrypt[] =
2373 "Decrypt the object set by the last INPUT command and\n"
2374 "write the decrypted message to the object set by the\n"
2375 "last OUTPUT command.";
2377 cmd_decrypt (assuan_context_t ctx, char *line)
2379 return _cmd_decrypt_verify (ctx, line, 0);
2383 static const char hlp_decrypt_verify[] =
2386 "Decrypt the object set by the last INPUT command and\n"
2387 "verify any embedded signatures. Write the decrypted\n"
2388 "message to the object set by the last OUTPUT command.";
2390 cmd_decrypt_verify (assuan_context_t ctx, char *line)
2392 return _cmd_decrypt_verify (ctx, line, 1);
2397 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
2399 struct server *server = assuan_get_pointer (ctx);
2405 gpgme_data_t inp_data = NULL;
2406 gpgme_data_t out_data = NULL;
2407 gpgme_encrypt_flags_t flags = 0;
2409 if (strstr (line, "--always-trust"))
2410 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
2411 if (strstr (line, "--no-encrypt-to"))
2412 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
2413 if (strstr (line, "--prepare"))
2414 flags |= GPGME_ENCRYPT_PREPARE;
2415 if (strstr (line, "--expect-sign"))
2416 flags |= GPGME_ENCRYPT_EXPECT_SIGN;
2417 if (strstr (line, "--no-compress"))
2418 flags |= GPGME_ENCRYPT_NO_COMPRESS;
2420 inp_fd = server->input_fd;
2421 inp_fn = server->input_filename;
2422 out_fd = server->output_fd;
2423 out_fn = server->output_filename;
2424 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
2426 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2427 &server->input_stream);
2431 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2433 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2434 &server->output_stream);
2437 gpgme_data_release (inp_data);
2442 err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign);
2444 gpgme_data_release (inp_data);
2445 gpgme_data_release (out_data);
2447 server_reset_fds (server);
2453 static const char hlp_encrypt[] =
2454 "ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2455 " [--no-compress] [--prepare] [--expect-sign]\n"
2457 "Encrypt the object set by the last INPUT command to\n"
2458 "the keys specified by previous RECIPIENT commands. \n"
2459 "Write the signed and encrypted message to the object\n"
2460 "set by the last OUTPUT command.";
2462 cmd_encrypt (assuan_context_t ctx, char *line)
2464 return _cmd_sign_encrypt (ctx, line, 0);
2468 static const char hlp_sign_encrypt[] =
2469 "SIGN_ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2470 " [--no-compress] [--prepare] [--expect-sign]\n"
2472 "Sign the object set by the last INPUT command with the\n"
2473 "keys specified by previous SIGNER commands and encrypt\n"
2474 "it to the keys specified by previous RECIPIENT\n"
2475 "commands. Write the signed and encrypted message to\n"
2476 "the object set by the last OUTPUT command.";
2478 cmd_sign_encrypt (assuan_context_t ctx, char *line)
2480 return _cmd_sign_encrypt (ctx, line, 1);
2484 static const char hlp_sign[] =
2485 "SIGN [--clear|--detach]\n"
2487 "Sign the object set by the last INPUT command with the\n"
2488 "keys specified by previous SIGNER commands. Write the\n"
2489 "signed message to the object set by the last OUTPUT\n"
2490 "command. With `--clear`, generate a clear text\n"
2491 "signature. With `--detach`, generate a detached\n"
2494 cmd_sign (assuan_context_t ctx, char *line)
2496 struct server *server = assuan_get_pointer (ctx);
2502 gpgme_data_t inp_data;
2503 gpgme_data_t out_data;
2504 gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
2506 if (strstr (line, "--clear"))
2507 mode = GPGME_SIG_MODE_CLEAR;
2508 if (strstr (line, "--detach"))
2509 mode = GPGME_SIG_MODE_DETACH;
2511 inp_fd = server->input_fd;
2512 inp_fn = server->input_filename;
2513 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2514 return GPG_ERR_ASS_NO_INPUT;
2515 out_fd = server->output_fd;
2516 out_fn = server->output_filename;
2517 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2518 return GPG_ERR_ASS_NO_OUTPUT;
2520 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2521 &server->input_stream);
2524 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2525 &server->output_stream);
2528 gpgme_data_release (inp_data);
2532 err = gt_sign (server->gt, inp_data, out_data, mode);
2534 gpgme_data_release (inp_data);
2535 gpgme_data_release (out_data);
2536 server_reset_fds (server);
2542 static const char hlp_verify[] =
2545 "Verify signatures on the object set by the last INPUT\n"
2546 "and MESSAGE commands. If the message was encrypted,\n"
2547 "write the plaintext to the object set by the last\n"
2550 cmd_verify (assuan_context_t ctx, char *line)
2552 struct server *server = assuan_get_pointer (ctx);
2560 gpgme_data_t inp_data;
2561 gpgme_data_t msg_data = NULL;
2562 gpgme_data_t out_data = NULL;
2566 inp_fd = server->input_fd;
2567 inp_fn = server->input_filename;
2568 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2569 return GPG_ERR_ASS_NO_INPUT;
2570 msg_fd = server->message_fd;
2571 msg_fn = server->message_filename;
2572 out_fd = server->output_fd;
2573 out_fn = server->output_filename;
2575 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2576 &server->input_stream);
2579 if (msg_fd != ASSUAN_INVALID_FD || msg_fn)
2581 err = server_data_obj (msg_fd, msg_fn, 0, server->message_enc, &msg_data,
2582 &server->message_stream);
2585 gpgme_data_release (inp_data);
2589 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2591 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2592 &server->output_stream);
2595 gpgme_data_release (inp_data);
2596 gpgme_data_release (msg_data);
2601 err = gt_verify (server->gt, inp_data, msg_data, out_data);
2603 gpgme_data_release (inp_data);
2605 gpgme_data_release (msg_data);
2607 gpgme_data_release (out_data);
2609 server_reset_fds (server);
2615 static const char hlp_import[] =
2616 "IMPORT [<pattern>]\n"
2618 "With PATTERN, import the keys described by PATTERN.\n"
2619 "Without, read a key (or keys) from the object set by the\n"
2620 "last INPUT command.";
2622 cmd_import (assuan_context_t ctx, char *line)
2624 struct server *server = assuan_get_pointer (ctx);
2628 char *fprs[2] = { line, NULL };
2630 return gt_import_keys (server->gt, fprs);
2637 gpgme_data_t inp_data;
2639 inp_fd = server->input_fd;
2640 inp_fn = server->input_filename;
2641 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2642 return GPG_ERR_ASS_NO_INPUT;
2644 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2645 &server->input_stream);
2649 err = gt_import (server->gt, inp_data);
2651 gpgme_data_release (inp_data);
2652 server_reset_fds (server);
2659 static const char hlp_export[] =
2660 "EXPORT [--extern] [--minimal] [--secret [--pkcs12] [--raw]] [<pattern>]\n"
2662 "Export the keys described by PATTERN. Write the\n"
2663 "the output to the object set by the last OUTPUT command.";
2665 cmd_export (assuan_context_t ctx, char *line)
2667 struct server *server = assuan_get_pointer (ctx);
2671 gpgme_data_t out_data;
2672 gpgme_export_mode_t mode = 0;
2673 const char *pattern[2];
2675 out_fd = server->output_fd;
2676 out_fn = server->output_filename;
2677 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2678 return GPG_ERR_ASS_NO_OUTPUT;
2679 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2680 &server->output_stream);
2684 if (has_option (line, "--extern"))
2685 mode |= GPGME_EXPORT_MODE_EXTERN;
2686 if (has_option (line, "--minimal"))
2687 mode |= GPGME_EXPORT_MODE_MINIMAL;
2688 if (has_option (line, "--secret"))
2689 mode |= GPGME_EXPORT_MODE_SECRET;
2690 if (has_option (line, "--raw"))
2691 mode |= GPGME_EXPORT_MODE_RAW;
2692 if (has_option (line, "--pkcs12"))
2693 mode |= GPGME_EXPORT_MODE_PKCS12;
2695 line = skip_options (line);
2700 err = gt_export (server->gt, pattern, mode, out_data);
2702 gpgme_data_release (out_data);
2703 server_reset_fds (server);
2710 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
2714 gpgme_ssize_t writen = gpgme_data_write (data, buf, size);
2715 if (writen < 0 && errno != EAGAIN)
2716 return gpg_error_from_syserror ();
2717 else if (writen > 0)
2719 buf = (void *) (((char *) buf) + writen);
2728 cmd_genkey (assuan_context_t ctx, char *line)
2730 struct server *server = assuan_get_pointer (ctx);
2736 gpgme_data_t inp_data;
2737 gpgme_data_t out_data = NULL;
2738 gpgme_data_t parms_data = NULL;
2743 inp_fd = server->input_fd;
2744 inp_fn = server->input_filename;
2745 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2746 return GPG_ERR_ASS_NO_INPUT;
2747 out_fd = server->output_fd;
2748 out_fn = server->output_filename;
2750 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2751 &server->input_stream);
2754 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2756 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2757 &server->output_stream);
2760 gpgme_data_release (inp_data);
2765 /* Convert input data. */
2766 err = gpgme_data_new (&parms_data);
2772 gpgme_ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
2775 err = gpg_error_from_syserror ();
2778 else if (readn == 0)
2781 err = _cmd_genkey_write (parms_data, buf, readn);
2786 err = _cmd_genkey_write (parms_data, "", 1);
2789 parms = gpgme_data_release_and_get_mem (parms_data, NULL);
2793 err = gpg_error (GPG_ERR_GENERAL);
2797 err = gt_genkey (server->gt, parms, out_data, NULL);
2799 server_reset_fds (server);
2802 gpgme_data_release (inp_data);
2804 gpgme_data_release (out_data);
2806 gpgme_data_release (parms_data);
2813 cmd_delete (assuan_context_t ctx, char *line)
2815 struct server *server = assuan_get_pointer (ctx);
2816 int allow_secret = 0;
2817 const char optstr[] = "--allow-secret";
2819 if (!strncasecmp (line, optstr, strlen (optstr)))
2822 line += strlen (optstr);
2823 while (*line && !spacep (line))
2826 return gt_delete (server->gt, line, allow_secret);
2830 static const char hlp_keylist[] =
2831 "KEYLIST [--secret-only] [<patterns>]\n"
2833 "List all certificates or only those specified by PATTERNS. Each\n"
2834 "pattern shall be a percent-plus escaped certificate specification.";
2836 cmd_keylist (assuan_context_t ctx, char *line)
2838 #define MAX_CMD_KEYLIST_PATTERN 20
2839 struct server *server = assuan_get_pointer (ctx);
2840 gpgme_tool_t gt = server->gt;
2841 struct result_xml_state state;
2843 int secret_only = 0;
2845 const char *pattern[MAX_CMD_KEYLIST_PATTERN+1];
2846 const char optstr[] = "--secret-only";
2849 if (!strncasecmp (line, optstr, strlen (optstr)))
2852 line += strlen (optstr);
2853 while (*line && !spacep (line))
2858 for (p=line; *p; line = p)
2860 while (*p && *p != ' ')
2866 if (idx+1 == DIM (pattern))
2867 return gpg_error (GPG_ERR_TOO_MANY);
2868 strcpy_escaped_plus (line, line);
2869 pattern[idx++] = line;
2872 pattern[idx] = NULL;
2874 gt_write_data (gt, xml_preamble1, strlen (xml_preamble1));
2875 gt_write_data (gt, NULL, 0);
2876 gt_write_data (gt, xml_preamble2, strlen (xml_preamble2));
2877 gt_write_data (gt, NULL, 0);
2878 result_init (&state, indent, (result_xml_write_cb_t) gt_write_data, gt);
2879 result_xml_tag_start (&state, "keylist", NULL);
2881 err = gt_keylist_start (server->gt, pattern, secret_only);
2885 gpgme_subkey_t subkey;
2886 gpgme_user_id_t uid;
2888 err = gt_keylist_next (server->gt, &key);
2889 if (gpg_err_code (err) == GPG_ERR_EOF)
2896 result_xml_tag_start (&state, "key", NULL);
2897 result_add_value (&state, "revoked", key->revoked);
2898 result_add_value (&state, "expired", key->expired);
2899 result_add_value (&state, "disabled", key->disabled);
2900 result_add_value (&state, "invalid", key->invalid);
2901 result_add_value (&state, "can-encrypt", key->can_encrypt);
2902 result_add_value (&state, "can-sign", key->can_sign);
2903 result_add_value (&state, "can-certify", key->can_certify);
2904 result_add_value (&state, "can-authenticate", key->can_authenticate);
2905 result_add_value (&state, "is-qualified", key->is_qualified);
2906 result_add_value (&state, "secret", key->secret);
2907 result_add_protocol (&state, "protocol", key->protocol);
2908 result_xml_tag_start (&state, "issuer", NULL);
2909 result_add_string (&state, "serial", key->issuer_serial);
2910 result_add_string (&state, "name", key->issuer_name);
2911 result_xml_tag_end (&state); /* issuer */
2912 result_add_string (&state, "chain-id", key->chain_id);
2913 result_add_validity (&state, "owner-trust", key->owner_trust);
2914 result_xml_tag_start (&state, "subkeys", NULL);
2915 subkey = key->subkeys;
2917 result_xml_tag_start (&state, "subkey", NULL);
2918 /* FIXME: more data */
2919 result_add_keyid (&state, "keyid", subkey->keyid);
2921 result_add_fpr (&state, "fpr", subkey->fpr);
2922 result_add_value (&state, "secret", subkey->secret);
2923 result_add_value (&state, "is_cardkey", subkey->is_cardkey);
2924 if (subkey->card_number)
2925 result_add_string (&state, "card_number", subkey->card_number);
2927 result_add_string (&state, "curve", subkey->curve);
2928 result_xml_tag_end (&state); /* subkey */
2929 subkey = subkey->next;
2931 result_xml_tag_end (&state); /* subkeys */
2932 result_xml_tag_start (&state, "uids", NULL);
2935 result_xml_tag_start (&state, "uid", NULL);
2936 /* FIXME: more data */
2937 result_add_string (&state, "uid", uid->uid);
2938 result_add_string (&state, "name", uid->name);
2939 result_add_string (&state, "email", uid->email);
2940 result_add_string (&state, "comment", uid->comment);
2941 result_xml_tag_end (&state); /* uid */
2944 result_xml_tag_end (&state); /* uids */
2945 result_xml_tag_end (&state); /* key */
2946 gpgme_key_unref (key);
2950 result_xml_tag_end (&state); /* keylist */
2951 gt_write_data (gt, xml_end, strlen (xml_end));
2953 server_reset_fds (server);
2959 static const char hlp_getauditlog[] =
2960 "GETAUDITLOG [--html] [--with-help]\n"
2962 "Call the function gpgme_op_getauditlog with the given flags. Write\n"
2963 "the output to the object set by the last OUTPUT command.";
2965 cmd_getauditlog (assuan_context_t ctx, char *line)
2967 struct server *server = assuan_get_pointer (ctx);
2971 gpgme_data_t out_data;
2972 unsigned int flags = 0;
2974 out_fd = server->output_fd;
2975 out_fn = server->output_filename;
2976 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2977 return GPG_ERR_ASS_NO_OUTPUT;
2978 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2979 &server->output_stream);
2983 if (strstr (line, "--html"))
2984 flags |= GPGME_AUDITLOG_HTML;
2985 if (strstr (line, "--with-help"))
2986 flags |= GPGME_AUDITLOG_WITH_HELP;
2988 err = gt_getauditlog (server->gt, out_data, flags);
2990 gpgme_data_release (out_data);
2991 server_reset_fds (server);
2998 cmd_vfs_mount (assuan_context_t ctx, char *line)
3000 struct server *server = assuan_get_pointer (ctx);
3004 mount_dir = strchr (line, ' ');
3007 *(mount_dir++) = '\0';
3008 while (*mount_dir == ' ')
3012 err = gt_vfs_mount (server->gt, line, mount_dir, 0);
3019 cmd_vfs_create (assuan_context_t ctx, char *line)
3021 struct server *server = assuan_get_pointer (ctx);
3025 end = strchr (line, ' ');
3033 err = gt_vfs_create (server->gt, line, 0);
3039 static const char hlp_passwd[] =
3040 "PASSWD <user-id>\n"
3042 "Ask the backend to change the passphrase for the key\n"
3043 "specified by USER-ID.";
3045 cmd_passwd (assuan_context_t ctx, char *line)
3047 struct server *server = assuan_get_pointer (ctx);
3049 return gt_passwd (server->gt, line);
3055 cmd_result (assuan_context_t ctx, char *line)
3057 struct server *server = assuan_get_pointer (ctx);
3061 return gt_result (server->gt, GT_RESULT_ALL);
3065 /* STRERROR <err> */
3067 cmd_strerror (assuan_context_t ctx, char *line)
3073 snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
3074 gpgme_strsource (err));
3075 return assuan_send_data (ctx, buf, strlen (buf));
3080 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
3082 gpgme_pubkey_algo_t algo;
3086 snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
3087 return assuan_send_data (ctx, buf, strlen (buf));
3092 cmd_hash_algo_name (assuan_context_t ctx, char *line)
3094 gpgme_hash_algo_t algo;
3098 snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
3099 return assuan_send_data (ctx, buf, strlen (buf));
3103 static const char hlp_identify[] =
3106 "Identify the type of data set with the INPUT command.";
3108 cmd_identify (assuan_context_t ctx, char *line)
3110 struct server *server = assuan_get_pointer (ctx);
3114 gpgme_data_t inp_data;
3118 inp_fd = server->input_fd;
3119 inp_fn = server->input_filename;
3120 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
3121 return GPG_ERR_ASS_NO_INPUT;
3123 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
3124 &server->input_stream);
3128 err = gt_identify (server->gt, inp_data);
3130 gpgme_data_release (inp_data);
3131 server_reset_fds (server);
3137 static const char hlp_spawn[] =
3138 "SPAWN PGM [args]\n"
3140 "Run program PGM with stdin connected to the INPUT source;\n"
3141 "stdout and stderr to the OUTPUT source.";
3143 cmd_spawn (assuan_context_t ctx, char *line)
3145 struct server *server = assuan_get_pointer (ctx);
3151 gpgme_data_t inp_data = NULL;
3152 gpgme_data_t out_data = NULL;
3154 inp_fd = server->input_fd;
3155 inp_fn = server->input_filename;
3156 out_fd = server->output_fd;
3157 out_fn = server->output_filename;
3158 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
3160 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
3161 &server->input_stream);
3165 if (out_fd != ASSUAN_INVALID_FD || out_fn)
3167 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
3168 &server->output_stream);
3171 gpgme_data_release (inp_data);
3176 err = gt_spawn (server->gt, line, inp_data, out_data);
3178 gpgme_data_release (inp_data);
3179 gpgme_data_release (out_data);
3181 server_reset_fds (server);
3187 /* Tell the assuan library about our commands. */
3189 register_commands (assuan_context_t ctx)
3194 assuan_handler_t handler;
3195 const char * const help;
3197 /* RESET, BYE are implicit. */
3198 { "VERSION", cmd_version, hlp_version },
3199 /* TODO: Set engine info. */
3200 { "ENGINE", cmd_engine, hlp_engine },
3201 { "PROTOCOL", cmd_protocol, hlp_protocol },
3202 { "SUB_PROTOCOL", cmd_sub_protocol, hlp_sub_protocol },
3203 { "PINENTRY_MODE", cmd_pinentry_mode, hlp_pinentry_mode },
3204 { "ARMOR", cmd_armor, hlp_armor },
3205 { "TEXTMODE", cmd_textmode, hlp_textmode },
3206 { "INCLUDE_CERTS", cmd_include_certs, hlp_include_certs },
3207 { "KEYLIST_MODE", cmd_keylist_mode, hlp_keylist_mode },
3208 { "INPUT", cmd_input, hlp_input },
3209 { "OUTPUT", cmd_output, hlp_output },
3210 { "MESSAGE", cmd_message, hlp_message },
3211 { "RECIPIENT", cmd_recipient, hlp_recipient },
3212 { "SIGNER", cmd_signer, hlp_signer },
3213 { "SIGNERS_CLEAR", cmd_signers_clear, hlp_signers_clear },
3214 /* TODO: SIGNOTATION missing. */
3215 /* TODO: Could add wait interface if we allow more than one context */
3216 /* and add _START variants. */
3217 /* TODO: Could add data interfaces if we allow multiple data objects. */
3218 { "DECRYPT", cmd_decrypt, hlp_decrypt },
3219 { "DECRYPT_VERIFY", cmd_decrypt_verify, hlp_decrypt_verify },
3220 { "ENCRYPT", cmd_encrypt, hlp_encrypt },
3221 { "ENCRYPT_SIGN", cmd_sign_encrypt, hlp_sign_encrypt },
3222 { "SIGN_ENCRYPT", cmd_sign_encrypt, hlp_sign_encrypt },
3223 { "SIGN", cmd_sign, hlp_sign },
3224 { "VERIFY", cmd_verify, hlp_verify },
3225 { "IMPORT", cmd_import, hlp_import },
3226 { "EXPORT", cmd_export, hlp_export },
3227 { "GENKEY", cmd_genkey },
3228 { "DELETE", cmd_delete },
3229 /* TODO: EDIT, CARD_EDIT (with INQUIRE) */
3230 { "KEYLIST", cmd_keylist, hlp_keylist },
3231 { "LISTKEYS", cmd_keylist, hlp_keylist },
3232 /* TODO: TRUSTLIST, TRUSTLIST_EXT */
3233 { "GETAUDITLOG", cmd_getauditlog, hlp_getauditlog },
3235 { "VFS_MOUNT", cmd_vfs_mount },
3236 { "MOUNT", cmd_vfs_mount },
3237 { "VFS_CREATE", cmd_vfs_create },
3238 { "CREATE", cmd_vfs_create },
3240 { "RESULT", cmd_result },
3241 { "STRERROR", cmd_strerror },
3242 { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
3243 { "HASH_ALGO_NAME", cmd_hash_algo_name },
3244 { "PASSWD", cmd_passwd, hlp_passwd },
3245 { "IDENTIFY", cmd_identify, hlp_identify },
3246 { "SPAWN", cmd_spawn, hlp_spawn },
3251 for (idx = 0; table[idx].name; idx++)
3253 err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
3263 gpgme_server (gpgme_tool_t gt)
3266 assuan_fd_t filedes[2];
3267 struct server server;
3268 static const char hello[] = ("GPGME-Tool " VERSION " ready");
3270 memset (&server, 0, sizeof (server));
3271 server.input_fd = ASSUAN_INVALID_FD;
3272 server.output_fd = ASSUAN_INVALID_FD;
3273 server.message_fd = ASSUAN_INVALID_FD;
3274 server.input_enc = GPGME_DATA_ENCODING_NONE;
3275 server.output_enc = GPGME_DATA_ENCODING_NONE;
3276 server.message_enc = GPGME_DATA_ENCODING_NONE;
3279 gt->write_status = server_write_status;
3280 gt->write_status_hook = &server;
3281 gt->write_data = server_write_data;
3282 gt->write_data_hook = &server;
3284 /* We use a pipe based server so that we can work from scripts.
3285 * assuan_init_pipe_server will automagically detect when we are
3286 * called with a socketpair and ignore FILEDES in this case. */
3287 filedes[0] = assuan_fdopen (0);
3288 filedes[1] = assuan_fdopen (1);
3290 err = assuan_new (&server.assuan_ctx);
3292 log_error (1, err, "can't create assuan context");
3294 assuan_set_pointer (server.assuan_ctx, &server);
3296 err = assuan_init_pipe_server (server.assuan_ctx, filedes);
3298 log_error (1, err, "can't initialize assuan server");
3299 err = register_commands (server.assuan_ctx);
3301 log_error (1, err, "can't register assuan commands");
3302 assuan_set_hello_line (server.assuan_ctx, hello);
3304 assuan_register_reset_notify (server.assuan_ctx, reset_notify);
3306 #define DBG_ASSUAN 0
3308 assuan_set_log_stream (server.assuan_ctx, log_stream);
3312 err = assuan_accept (server.assuan_ctx);
3317 log_error (0, err, "assuan accept problem");
3321 err = assuan_process (server.assuan_ctx);
3323 log_error (0, err, "assuan processing failed");
3326 assuan_release (server.assuan_ctx);
3332 my_strusage( int level )
3338 case 11: p = "gpgme-tool"; break;
3339 case 13: p = PACKAGE_VERSION; break;
3340 case 14: p = "Copyright (C) 2015 g10 Code GmbH"; break;
3341 case 19: p = "Please report bugs to <" PACKAGE_BUGREPORT ">.\n"; break;
3344 p = "Usage: gpgme-tool [OPTIONS] [COMMANDS]";
3347 p = "GPGME Tool -- Assuan server exposing GPGME operations\n";
3350 p = "1"; /* Flag print 40 as part of 41. */
3352 default: p = NULL; break;
3359 main (int argc, char *argv[])
3361 static ARGPARSE_OPTS opts[] = {
3362 ARGPARSE_c ('s', "server", "Server mode"),
3363 ARGPARSE_s_s(501, "gpg-binary", "|FILE|Use FILE for the GPG backend"),
3364 ARGPARSE_c (502, "lib-version", "Show library version"),
3367 ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
3368 enum { CMD_DEFAULT, CMD_SERVER, CMD_LIBVERSION } cmd = CMD_DEFAULT;
3369 const char *gpg_binary = NULL;
3370 struct gpgme_tool gt;
3374 set_strusage (my_strusage);
3376 #ifdef HAVE_SETLOCALE
3377 setlocale (LC_ALL, "");
3379 gpgme_check_version (NULL);
3381 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
3384 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
3389 while (arg_parse (&pargs, opts))
3391 switch (pargs.r_opt)
3393 case 's': cmd = CMD_SERVER; break;
3394 case 501: gpg_binary = pargs.r.ret_str; break;
3395 case 502: cmd = CMD_LIBVERSION; break;
3397 pargs.err = ARGPARSE_PRINT_WARNING;
3402 if (cmd == CMD_LIBVERSION)
3405 if (needgt && gpg_binary)
3407 if (access (gpg_binary, X_OK))
3408 err = gpg_error_from_syserror ();
3410 err = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP,
3413 log_error (1, err, "error witching OpenPGP engine to '%s'",
3427 case CMD_LIBVERSION:
3428 printf ("Version from header: %s (0x%06x)\n",
3429 GPGME_VERSION, GPGME_VERSION_NUMBER);
3430 printf ("Version from binary: %s\n", gpgme_check_version (NULL));
3431 printf ("Copyright blurb ...:%s\n", gpgme_check_version ("\x01\x01"));
3436 gpgme_release (gt.ctx);