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 <http://www.gnu.org/licenses/>.
45 # define GT_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a)))
47 # define GT_GCC_A_SENTINEL(a)
50 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
51 # define GT_GCC_A_PRINTF(f, a) __attribute__ ((format (printf,f,a)))
53 # define GT_GCC_A_PRINTF(f, a)
56 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
57 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
58 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
59 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
64 /* Minimal argp implementation. */
66 /* Differences to ARGP:
67 argp_program_version: Required.
68 argp_program_bug_address: Required.
69 argp_program_version_hook: Not supported.
70 argp_err_exit_status: Required.
71 struct argp: Children and help_filter not supported.
72 argp_domain: Not supported.
73 struct argp_option: Group not supported. Options are printed in
74 order given. Flags OPTION_ALIAS, OPTION_DOC and OPTION_NO_USAGE
76 argp_parse: No flags are supported (ARGP_PARSE_ARGV0, ARGP_NO_ERRS,
77 ARGP_NO_ARGS, ARGP_IN_ORDER, ARGP_NO_HELP, ARGP_NO_EXIT,
78 ARGP_LONG_ONLY, ARGP_SILENT). ARGP must not be NULL.
79 argp_help: Flag ARGP_HELP_LONG_ONLY not supported.
80 argp_state: argc, argv, next may not be modified and should not be used. */
82 extern const char *argp_program_version;
83 extern const char *argp_program_bug_address;
84 extern error_t argp_err_exit_status;
91 #define OPTION_ARG_OPTIONAL 0x1
92 #define OPTION_HIDDEN 0x2
101 const struct argp *const root_argp;
118 # define ARGP_ERR_UNKNOWN EDEADLK /* POSIX */
120 # define ARGP_ERR_UNKNOWN EDEADLOCK /* *GNU/kFreebsd does not define this) */
122 #define ARGP_KEY_ARG 0
123 #define ARGP_KEY_ARGS 0x1000006
124 #define ARGP_KEY_END 0x1000001
125 #define ARGP_KEY_NO_ARGS 0x1000002
126 #define ARGP_KEY_INIT 0x1000003
127 #define ARGP_KEY_FINI 0x1000007
128 #define ARGP_KEY_SUCCESS 0x1000004
129 #define ARGP_KEY_ERROR 0x1000005
130 typedef error_t (*argp_parser_t) (int key, char *arg, struct argp_state *state);
134 const struct argp_option *options;
135 argp_parser_t parser;
136 const char *args_doc;
139 const struct argp_child *children;
140 char *(*help_filter) (int key, const char *text, void *input);
141 const char *argp_domain;
144 #define ARGP_HELP_USAGE ARGP_HELP_SHORT_USAGE
145 #define ARGP_HELP_SHORT_USAGE 0x02
146 #define ARGP_HELP_SEE 0x04
147 #define ARGP_HELP_LONG 0x08
148 #define ARGP_HELP_PRE_DOC 0x10
149 #define ARGP_HELP_POST_DOC 0x20
150 #define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
151 #define ARGP_HELP_BUG_ADDR 0x40
152 #define ARGP_HELP_EXIT_ERR 0x100
153 #define ARGP_HELP_EXIT_OK 0x200
154 #define ARGP_HELP_STD_ERR (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
155 #define ARGP_HELP_STD_USAGE \
156 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
157 #define ARGP_HELP_STD_HELP \
158 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
159 | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
162 void argp_error (const struct argp_state *state,
163 const char *fmt, ...) GT_GCC_A_PRINTF(2, 3);
168 _argp_pname (char *name)
171 char *bname = strrchr (pname, '/');
173 bname = strrchr (pname, '\\');
181 _argp_state_help (const struct argp *argp, const struct argp_state *state,
182 FILE *stream, unsigned flags, char *name)
187 if (flags & ARGP_HELP_SHORT_USAGE)
188 fprintf (stream, "Usage: %s [OPTIONS...] %s\n", name, argp->args_doc);
189 if (flags & ARGP_HELP_SEE)
190 fprintf (stream, "Try `%s --help' or `%s --usage' for more information.\n",
192 if (flags & ARGP_HELP_PRE_DOC)
196 strncpy (buf, argp->doc, sizeof (buf));
197 buf[sizeof (buf) - 1] = '\0';
198 end = strchr (buf, '\v');
201 fprintf (stream, "%s\n%s", buf, buf[0] ? "\n" : "");
203 if (flags & ARGP_HELP_LONG)
205 const struct argp_option *opt = argp->options;
209 char spaces[NSPACES + 1] = " ";
211 fprintf (stream, " ");
213 if (isascii (opt->key))
215 fprintf (stream, "-%c", opt->key);
219 fprintf (stream, ", ");
225 fprintf (stream, "--%s", opt->name);
226 len += 2 + strlen (opt->name);
228 if (opt->arg && (opt->flags & OPTION_ARG_OPTIONAL))
230 fprintf (stream, "[=%s]", opt->arg);
231 len += 3 + strlen (opt->arg);
235 fprintf (stream, "=%s", opt->arg);
236 len += 1 + strlen (opt->arg);
240 spaces[NSPACES - len] = '\0';
241 fprintf (stream, "%s%s\n", spaces, opt->doc);
244 fprintf (stream, " -?, --help Give this help list\n");
245 fprintf (stream, " --usage Give a short usage "
248 if (flags & ARGP_HELP_POST_DOC)
252 strncpy (buf, argp->doc, sizeof (buf));
253 buf[sizeof (buf) - 1] = '\0';
254 end = strchr (buf, '\v');
259 fprintf (stream, "\n%s\n", end);
261 fprintf (stream, "\nMandatory or optional arguments to long options are also mandatory or optional\n");
262 fprintf (stream, "for any corresponding short options.\n");
264 if (flags & ARGP_HELP_BUG_ADDR)
265 fprintf (stream, "\nReport bugs to %s.\n", argp_program_bug_address);
267 if (flags & ARGP_HELP_EXIT_ERR)
268 exit (argp_err_exit_status);
269 if (flags & ARGP_HELP_EXIT_OK)
275 argp_usage (const struct argp_state *state)
277 _argp_state_help (state->root_argp, state, state->err_stream,
278 ARGP_HELP_STD_USAGE, state->name);
283 argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
285 _argp_state_help (state->root_argp, state, stream, flags, state->name);
290 argp_error (const struct argp_state *state, const char *fmt, ...)
294 fprintf (state->err_stream, "%s: ", state->name);
296 vfprintf (state->err_stream, fmt, ap);
298 fprintf (state->err_stream, "\n");
299 argp_state_help (state, state->err_stream, ARGP_HELP_STD_ERR);
300 exit (argp_err_exit_status);
305 argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name)
307 _argp_state_help (argp, NULL, stream, flags, name);
312 argp_parse (const struct argp *argp, int argc,
313 char **argv, unsigned flags, int *arg_index, void *input)
316 struct argp_state state = { argp, argc, argv, 1, flags, 0, 0, input,
317 NULL, NULL, _argp_pname (argv[0]),
318 stderr, stdout, NULL };
319 /* All non-option arguments are collected at the beginning of
320 &argv[1] during processing. This is a counter for their number. */
321 int non_opt_args = 0;
323 rc = argp->parser (ARGP_KEY_INIT, NULL, &state);
324 if (rc && rc != ARGP_ERR_UNKNOWN)
327 while (state.next < state.argc - non_opt_args)
329 int idx = state.next;
332 if (! strcasecmp (state.argv[idx], "--"))
338 if (state.quoted || state.argv[idx][0] != '-')
340 char *arg_saved = state.argv[idx];
342 memmove (&state.argv[idx], &state.argv[idx + 1],
343 (state.argc - 1 - idx) * sizeof (char *));
344 state.argv[argc - 1] = arg_saved;
347 else if (! strcasecmp (state.argv[idx], "--help")
348 || !strcmp (state.argv[idx], "-?"))
350 argp_state_help (&state, state.out_stream, ARGP_HELP_STD_HELP);
352 else if (! strcasecmp (state.argv[idx], "--usage"))
354 argp_state_help (&state, state.out_stream,
355 ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
357 else if (! strcasecmp (state.argv[idx], "--version")
358 || !strcmp (state.argv[idx], "-V"))
360 fprintf (state.out_stream, "%s\n", argp_program_version);
365 /* Search for option and call parser with its KEY. */
366 int key = ARGP_KEY_ARG; /* Just some dummy value. */
367 const struct argp_option *opt = argp->options;
371 /* Check for --opt=value syntax. */
372 arg = strchr (state.argv[idx], '=');
379 if (state.argv[idx][1] != '-')
380 key = state.argv[idx][1];
382 while (! found && opt->key)
385 || (key == ARGP_KEY_ARG
386 && ! strcasecmp (&state.argv[idx][2], opt->name)))
388 if (arg && !opt->arg)
389 argp_error (&state, "Option %s does not take an argument",
391 if (opt->arg && state.next < state.argc
392 && state.argv[idx + 1][0] != '-')
394 arg = state.argv[idx + 1];
397 if (opt->arg && !(opt->flags & OPTION_ARG_OPTIONAL))
398 argp_error (&state, "Option %s requires an argument",
401 rc = argp->parser (opt->key, arg, &state);
402 if (rc == ARGP_ERR_UNKNOWN)
411 argp_error (&state, "Unknown option %s", state.argv[idx]);
415 while (state.next < state.argc)
417 /* Call parser for all non-option args. */
418 int idx = state.next;
420 rc = argp->parser (ARGP_KEY_ARG, state.argv[idx], &state);
421 if (rc && rc != ARGP_ERR_UNKNOWN)
423 if (rc == ARGP_ERR_UNKNOWN)
425 int old_next = state.next;
426 rc = argp->parser (ARGP_KEY_ARGS, NULL, &state);
427 if (rc == ARGP_ERR_UNKNOWN)
429 argp_error (&state, "Too many arguments");
432 if (! rc && state.next == old_next)
434 state.arg_num += state.argc - state.next;
435 state.next = state.argc;
442 if (state.arg_num == 0)
444 rc = argp->parser (ARGP_KEY_NO_ARGS, NULL, &state);
445 if (rc && rc != ARGP_ERR_UNKNOWN)
448 if (state.next == state.argc)
450 rc = argp->parser (ARGP_KEY_END, NULL, &state);
451 if (rc && rc != ARGP_ERR_UNKNOWN)
454 rc = argp->parser (ARGP_KEY_FINI, NULL, &state);
455 if (rc && rc != ARGP_ERR_UNKNOWN)
459 argp->parser (ARGP_KEY_SUCCESS, NULL, &state);
464 argp_error (&state, "unexpected error: %s", strerror (rc));
465 argp->parser (ARGP_KEY_ERROR, NULL, &state);
468 argp->parser (ARGP_KEY_FINI, NULL, &state);
471 *arg_index = state.next - 1;
480 /* A simple implementation of a dynamic buffer. Use init_membuf() to
481 create a buffer, put_membuf to append bytes and get_membuf to
482 release and return the buffer. Allocation errors are detected but
483 only returned at the final get_membuf(), this helps not to clutter
484 the code with out-of-core checks. */
486 /* The definition of the structure is private, we only need it here,
487 so it can be allocated on the stack. */
488 struct private_membuf_s
496 typedef struct private_membuf_s membuf_t;
498 /* Return the current length of the membuf. */
499 #define get_membuf_len(a) ((a)->len)
500 #define is_membuf_ready(a) ((a)->buf || (a)->out_of_core)
501 #define MEMBUF_ZERO { 0, 0, NULL, 0}
505 init_membuf (membuf_t *mb, int initiallen)
508 mb->size = initiallen;
510 mb->buf = malloc (initiallen);
512 mb->out_of_core = errno;
516 /* Shift the the content of the membuf MB by AMOUNT bytes. The next
517 operation will then behave as if AMOUNT bytes had not been put into
518 the buffer. If AMOUNT is greater than the actual accumulated
519 bytes, the membuf is basically reset to its initial state. */
520 #if 0 /* Not yet used. */
522 clear_membuf (membuf_t *mb, size_t amount)
524 /* No need to clear if we are already out of core. */
527 if (amount >= mb->len)
532 memmove (mb->buf, mb->buf+amount, mb->len);
538 put_membuf (membuf_t *mb, const void *buf, size_t len)
540 if (mb->out_of_core || !len)
543 if (mb->len + len >= mb->size)
547 mb->size += len + 1024;
548 p = realloc (mb->buf, mb->size);
551 mb->out_of_core = errno ? errno : ENOMEM;
556 memcpy (mb->buf + mb->len, buf, len);
561 #if 0 /* Not yet used. */
563 put_membuf_str (membuf_t *mb, const char *string)
565 put_membuf (mb, string, strlen (string));
571 get_membuf (membuf_t *mb, size_t *len)
582 gpg_err_set_errno (mb->out_of_core);
590 mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
595 /* Peek at the membuf MB. On success a pointer to the buffer is
596 returned which is valid until the next operation on MB. If LEN is
597 not NULL the current LEN of the buffer is stored there. On error
598 NULL is returned and ERRNO is set. */
599 #if 0 /* Not yet used. */
601 peek_membuf (membuf_t *mb, size_t *len)
607 gpg_err_set_errno (mb->out_of_core);
622 char *program_name = "gpgme-tool";
624 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
627 void log_error (int status, gpg_error_t errnum,
628 const char *fmt, ...) GT_GCC_A_PRINTF(3,4);
639 log_error (int status, gpg_error_t errnum, const char *fmt, ...)
643 fprintf (log_stream, "%s: ", program_name);
645 vfprintf (log_stream, fmt, ap);
649 fprintf (log_stream, ": %s", gpg_strerror (errnum));
650 if (gpg_err_source (errnum) != GPG_ERR_SOURCE_GPGME)
651 fprintf (log_stream, " <%s>", gpg_strsource (errnum));
653 fprintf (log_stream, "\n");
659 /* Note that it is sufficient to allocate the target string D as long
660 as the source string S, i.e.: strlen(s)+1;. D == S is allowed. */
662 strcpy_escaped_plus (char *d, const char *s)
666 if (*s == '%' && s[1] && s[2])
681 /* Check whether the option NAME appears in LINE. */
683 has_option (const char *line, const char *name)
686 int n = strlen (name);
688 s = strstr (line, name);
689 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
692 /* Skip over options. It is assumed that leading spaces have been
693 removed (this is the case for lines passed to a handler from
694 assuan). Blanks after the options are also removed. */
696 skip_options (char *line)
698 while ( *line == '-' && line[1] == '-' )
700 while (*line && !spacep (line))
702 while (spacep (line))
711 typedef gpg_error_t (*result_xml_write_cb_t) (void *hook, const void *buf,
714 static char xml_preamble1[] = "<?xml version=\"1.0\" "
715 "encoding=\"UTF-8\" standalone=\"yes\"?>\n";
716 static const char xml_preamble2[] = "<gpgme>\n";
717 static const char xml_end[] = "</gpgme>\n";
720 struct result_xml_state
723 result_xml_write_cb_t cb;
729 int had_data[MAX_TAGS];
734 result_init (struct result_xml_state *state, int indent,
735 result_xml_write_cb_t cb, void *hook)
737 memset (state, '\0', sizeof (*state));
738 state->indent = indent;
745 result_xml_indent (struct result_xml_state *state)
747 char spaces[state->indent + 1];
749 for (i = 0; i < state->indent; i++)
752 return (*state->cb) (state->hook, spaces, i);
757 result_xml_tag_start (struct result_xml_state *state, char *name, ...)
759 result_xml_write_cb_t cb = state->cb;
760 void *hook = state->hook;
767 if (state->next_tag > 0)
769 if (! state->had_data[state->next_tag - 1])
771 (*cb) (hook, ">\n", 2);
772 (*cb) (hook, NULL, 0);
774 state->had_data[state->next_tag - 1] = 1;
777 result_xml_indent (state);
778 (*cb) (hook, "<", 1);
779 (*cb) (hook, name, strlen (name));
781 state->tag[state->next_tag] = name;
782 state->had_data[state->next_tag] = 0;
788 attr = va_arg (ap, char *);
792 attr_val = va_arg (ap, char *);
793 if (attr_val == NULL)
796 (*cb) (hook, " ", 1);
797 (*cb) (hook, attr, strlen (attr));
798 (*cb) (hook, "=\"", 2);
799 (*cb) (hook, attr_val, strlen (attr_val));
800 (*cb) (hook, "\"", 1);
806 /* Return a constant string with an XML entity for C. */
808 result_xml_escape_replacement(char c)
823 /* Escape DATA by replacing certain characters with their XML
824 entities. The result is stored in a newly allocated buffer which
825 address will be stored at BUF. Returns 0 on success. */
827 result_xml_escape (const char *data, char **buf)
833 init_membuf (&mb, 128);
834 data_len = strlen (data);
835 for (i = 0; i < data_len; i++)
837 r = result_xml_escape_replacement (data[i]);
839 put_membuf (&mb, r, strlen (r));
841 put_membuf (&mb, data+i, 1);
843 put_membuf (&mb, "", 1);
844 *buf = get_membuf (&mb, NULL);
845 return *buf? 0 : gpg_error_from_syserror ();
850 result_xml_tag_data (struct result_xml_state *state, const char *data)
853 result_xml_write_cb_t cb = state->cb;
854 void *hook = state->hook;
857 if (state->had_data[state->next_tag - 1])
859 (*cb) (hook, "\n", 2);
860 (*cb) (hook, NULL, 0);
861 result_xml_indent (state);
864 (*cb) (hook, ">", 1);
865 state->had_data[state->next_tag - 1] = 2;
867 err = result_xml_escape (data, &buf);
871 (*cb) (hook, buf, strlen (buf));
880 result_xml_tag_end (struct result_xml_state *state)
882 result_xml_write_cb_t cb = state->cb;
883 void *hook = state->hook;
888 if (state->had_data[state->next_tag])
890 if (state->had_data[state->next_tag] == 1)
891 result_xml_indent (state);
892 (*cb) (hook, "</", 2);
893 (*cb) (hook, state->tag[state->next_tag],
894 strlen (state->tag[state->next_tag]));
895 (*cb) (hook, ">\n", 2);
896 (*cb) (hook, NULL, 0);
900 (*cb) (hook, " />\n", 4);
901 (*cb) (hook, NULL, 0);
908 result_add_error (struct result_xml_state *state, char *name, gpg_error_t err)
912 snprintf (code, sizeof (code) - 1, "0x%x", err);
913 snprintf (msg, sizeof (msg) - 1, "%s <%s>",
914 gpg_strerror (err), gpg_strsource (err));
915 result_xml_tag_start (state, name, "value", code, NULL);
916 result_xml_tag_data (state, msg);
917 result_xml_tag_end (state);
923 result_add_pubkey_algo (struct result_xml_state *state,
924 char *name, gpgme_pubkey_algo_t algo)
928 snprintf (code, sizeof (code) - 1, "0x%x", algo);
929 snprintf (msg, sizeof (msg) - 1, "%s",
930 gpgme_pubkey_algo_name (algo));
931 result_xml_tag_start (state, name, "value", code, NULL);
932 result_xml_tag_data (state, msg);
933 result_xml_tag_end (state);
939 result_add_hash_algo (struct result_xml_state *state,
940 char *name, gpgme_hash_algo_t algo)
944 snprintf (code, sizeof (code) - 1, "0x%x", algo);
945 snprintf (msg, sizeof (msg) - 1, "%s",
946 gpgme_hash_algo_name (algo));
947 result_xml_tag_start (state, name, "value", code, NULL);
948 result_xml_tag_data (state, msg);
949 result_xml_tag_end (state);
955 result_add_keyid (struct result_xml_state *state, char *name, char *keyid)
957 result_xml_tag_start (state, name, NULL);
958 result_xml_tag_data (state, keyid);
959 result_xml_tag_end (state);
965 result_add_fpr (struct result_xml_state *state, char *name, char *fpr)
967 result_xml_tag_start (state, name, NULL);
968 result_xml_tag_data (state, fpr);
969 result_xml_tag_end (state);
975 result_add_timestamp (struct result_xml_state *state, char *name,
976 unsigned int timestamp)
980 snprintf (code, sizeof (code) - 1, "%ui", timestamp);
981 result_xml_tag_start (state, name, "unix", code, NULL);
982 result_xml_tag_end (state);
988 result_add_sig_mode (struct result_xml_state *state, char *name,
989 gpgme_sig_mode_t sig_mode)
994 snprintf (code, sizeof (code) - 1, "%i", sig_mode);
997 case GPGME_SIG_MODE_NORMAL:
1000 case GPGME_SIG_MODE_DETACH:
1003 case GPGME_SIG_MODE_CLEAR:
1010 result_xml_tag_start (state, name, "type", mode, "value", code, NULL);
1011 result_xml_tag_data (state, mode);
1012 result_xml_tag_end (state);
1018 result_add_protocol (struct result_xml_state *state, char *name,
1019 gpgme_protocol_t protocol)
1024 snprintf (code, sizeof (code) - 1, "%i", protocol);
1025 str = gpgme_get_protocol_name(protocol);
1028 result_xml_tag_start (state, name, "value", code, NULL);
1029 result_xml_tag_data (state, str);
1030 result_xml_tag_end (state);
1036 result_add_validity (struct result_xml_state *state, char *name,
1037 gpgme_validity_t validity)
1042 snprintf (code, sizeof (code) - 1, "%i", validity);
1045 case GPGME_VALIDITY_UNDEFINED:
1048 case GPGME_VALIDITY_NEVER:
1051 case GPGME_VALIDITY_MARGINAL:
1054 case GPGME_VALIDITY_FULL:
1057 case GPGME_VALIDITY_ULTIMATE:
1064 result_xml_tag_start (state, name, "value", code, NULL);
1065 result_xml_tag_data (state, str);
1066 result_xml_tag_end (state);
1072 result_add_value (struct result_xml_state *state,
1073 char *name, unsigned int val)
1077 snprintf (code, sizeof (code) - 1, "0x%x", val);
1078 result_xml_tag_start (state, name, "value", code, NULL);
1079 result_xml_tag_end (state);
1085 result_add_string (struct result_xml_state *state,
1086 char *name, char *str)
1090 result_xml_tag_start (state, name, NULL);
1091 result_xml_tag_data (state, str);
1092 result_xml_tag_end (state);
1098 result_encrypt_to_xml (gpgme_ctx_t ctx, int indent,
1099 result_xml_write_cb_t cb, void *hook)
1101 struct result_xml_state state;
1102 gpgme_encrypt_result_t res = gpgme_op_encrypt_result (ctx);
1103 gpgme_invalid_key_t inv_recp;
1108 result_init (&state, indent, cb, hook);
1109 result_xml_tag_start (&state, "encrypt-result", NULL);
1111 inv_recp = res->invalid_recipients;
1114 result_xml_tag_start (&state, "invalid-recipients", NULL);
1118 result_xml_tag_start (&state, "invalid-key", NULL);
1120 result_add_fpr (&state, "fpr", inv_recp->fpr);
1121 result_add_error (&state, "reason", inv_recp->reason);
1122 result_xml_tag_end (&state);
1123 inv_recp = inv_recp->next;
1125 result_xml_tag_end (&state);
1127 result_xml_tag_end (&state);
1134 result_decrypt_to_xml (gpgme_ctx_t ctx, int indent,
1135 result_xml_write_cb_t cb, void *hook)
1137 struct result_xml_state state;
1138 gpgme_decrypt_result_t res = gpgme_op_decrypt_result (ctx);
1139 gpgme_recipient_t recp;
1144 result_init (&state, indent, cb, hook);
1145 result_xml_tag_start (&state, "decrypt-result", NULL);
1149 result_xml_tag_start (&state, "file-name", NULL);
1150 result_xml_tag_data (&state, res->file_name);
1151 result_xml_tag_end (&state);
1153 if (res->unsupported_algorithm)
1155 result_xml_tag_start (&state, "unsupported-alogorithm", NULL);
1156 result_xml_tag_data (&state, res->unsupported_algorithm);
1157 result_xml_tag_end (&state);
1159 if (res->wrong_key_usage)
1161 result_xml_tag_start (&state, "wrong-key-usage", NULL);
1162 result_xml_tag_end (&state);
1165 recp = res->recipients;
1168 result_xml_tag_start (&state, "recipients", NULL);
1171 result_xml_tag_start (&state, "recipient", NULL);
1172 result_add_keyid (&state, "keyid", recp->keyid);
1173 result_add_pubkey_algo (&state, "pubkey-algo", recp->pubkey_algo);
1174 result_add_error (&state, "status", recp->status);
1175 result_xml_tag_end (&state);
1178 result_xml_tag_end (&state);
1180 result_xml_tag_end (&state);
1187 result_sign_to_xml (gpgme_ctx_t ctx, int indent,
1188 result_xml_write_cb_t cb, void *hook)
1190 struct result_xml_state state;
1191 gpgme_sign_result_t res = gpgme_op_sign_result (ctx);
1192 gpgme_invalid_key_t inv_key;
1193 gpgme_new_signature_t new_sig;
1198 result_init (&state, indent, cb, hook);
1199 result_xml_tag_start (&state, "sign-result", NULL);
1201 inv_key = res->invalid_signers;
1204 result_xml_tag_start (&state, "invalid-signers", NULL);
1208 result_xml_tag_start (&state, "invalid-key", NULL);
1210 result_add_fpr (&state, "fpr", inv_key->fpr);
1211 result_add_error (&state, "reason", inv_key->reason);
1212 result_xml_tag_end (&state);
1213 inv_key = inv_key->next;
1215 result_xml_tag_end (&state);
1218 new_sig = res->signatures;
1221 result_xml_tag_start (&state, "signatures", NULL);
1225 result_xml_tag_start (&state, "new-signature", NULL);
1226 result_add_sig_mode (&state, "type", new_sig->type);
1227 result_add_pubkey_algo (&state, "pubkey-algo", new_sig->pubkey_algo);
1228 result_add_hash_algo (&state, "hash-algo", new_sig->hash_algo);
1229 result_add_timestamp (&state, "timestamp", new_sig->timestamp);
1231 result_add_fpr (&state, "fpr", new_sig->fpr);
1232 result_add_value (&state, "sig-class", new_sig->sig_class);
1234 result_xml_tag_end (&state);
1235 new_sig = new_sig->next;
1237 result_xml_tag_end (&state);
1240 result_xml_tag_end (&state);
1247 result_verify_to_xml (gpgme_ctx_t ctx, int indent,
1248 result_xml_write_cb_t cb, void *hook)
1250 struct result_xml_state state;
1251 gpgme_verify_result_t res = gpgme_op_verify_result (ctx);
1252 gpgme_signature_t sig;
1257 result_init (&state, indent, cb, hook);
1258 result_xml_tag_start (&state, "verify-result", NULL);
1262 result_xml_tag_start (&state, "file-name", NULL);
1263 result_xml_tag_data (&state, res->file_name);
1264 result_xml_tag_end (&state);
1267 sig = res->signatures;
1270 result_xml_tag_start (&state, "signatures", NULL);
1274 result_xml_tag_start (&state, "signature", NULL);
1276 /* FIXME: Could be done better. */
1277 result_add_value (&state, "summary", sig->summary);
1279 result_add_fpr (&state, "fpr", sig->fpr);
1280 result_add_error (&state, "status", sig->status);
1281 /* FIXME: notations */
1282 result_add_timestamp (&state, "timestamp", sig->timestamp);
1283 result_add_timestamp (&state, "exp-timestamp", sig->exp_timestamp);
1284 result_add_value (&state, "wrong-key-usage", sig->wrong_key_usage);
1285 result_add_value (&state, "pka-trust", sig->pka_trust);
1286 result_add_value (&state, "chain-model", sig->chain_model);
1287 result_add_value (&state, "validity", sig->validity);
1288 result_add_error (&state, "validity-reason", sig->validity_reason);
1289 result_add_pubkey_algo (&state, "pubkey-algo", sig->pubkey_algo);
1290 result_add_hash_algo (&state, "hash-algo", sig->hash_algo);
1291 if (sig->pka_address)
1292 result_add_string (&state, "pka_address", sig->pka_address);
1294 result_xml_tag_end (&state);
1297 result_xml_tag_end (&state);
1300 result_xml_tag_end (&state);
1307 result_import_to_xml (gpgme_ctx_t ctx, int indent,
1308 result_xml_write_cb_t cb, void *hook)
1310 struct result_xml_state state;
1311 gpgme_import_result_t res = gpgme_op_import_result (ctx);
1312 gpgme_import_status_t stat;
1317 result_init (&state, indent, cb, hook);
1318 result_xml_tag_start (&state, "import-result", NULL);
1320 result_add_value (&state, "considered", res->considered);
1321 result_add_value (&state, "no-user-id", res->no_user_id);
1322 result_add_value (&state, "imported", res->imported);
1323 result_add_value (&state, "imported-rsa", res->imported_rsa);
1324 result_add_value (&state, "unchanged", res->unchanged);
1325 result_add_value (&state, "new-user-ids", res->new_user_ids);
1326 result_add_value (&state, "new-sub-keys", res->new_sub_keys);
1327 result_add_value (&state, "new-signatures", res->new_signatures);
1328 result_add_value (&state, "new-revocations", res->new_revocations);
1329 result_add_value (&state, "secret-read", res->secret_read);
1330 result_add_value (&state, "secret-imported", res->secret_imported);
1331 result_add_value (&state, "secret-unchanged", res->secret_unchanged);
1332 result_add_value (&state, "skipped-new-keys", res->skipped_new_keys);
1333 result_add_value (&state, "not-imported", res->not_imported);
1335 stat = res->imports;
1338 result_xml_tag_start (&state, "imports", NULL);
1342 result_xml_tag_start (&state, "import-status", NULL);
1345 result_add_fpr (&state, "fpr", stat->fpr);
1346 result_add_error (&state, "result", stat->result);
1347 /* FIXME: Could be done better. */
1348 result_add_value (&state, "status", stat->status);
1350 result_xml_tag_end (&state);
1353 result_xml_tag_end (&state);
1356 result_xml_tag_end (&state);
1363 result_genkey_to_xml (gpgme_ctx_t ctx, int indent,
1364 result_xml_write_cb_t cb, void *hook)
1366 struct result_xml_state state;
1367 gpgme_genkey_result_t res = gpgme_op_genkey_result (ctx);
1372 result_init (&state, indent, cb, hook);
1373 result_xml_tag_start (&state, "genkey-result", NULL);
1375 result_add_value (&state, "primary", res->primary);
1376 result_add_value (&state, "sub", res->sub);
1378 result_add_fpr (&state, "fpr", res->fpr);
1380 result_xml_tag_end (&state);
1387 result_keylist_to_xml (gpgme_ctx_t ctx, int indent,
1388 result_xml_write_cb_t cb, void *hook)
1390 struct result_xml_state state;
1391 gpgme_keylist_result_t res = gpgme_op_keylist_result (ctx);
1396 result_init (&state, indent, cb, hook);
1397 result_xml_tag_start (&state, "keylist-result", NULL);
1399 result_add_value (&state, "truncated", res->truncated);
1401 result_xml_tag_end (&state);
1408 result_vfs_mount_to_xml (gpgme_ctx_t ctx, int indent,
1409 result_xml_write_cb_t cb, void *hook)
1411 struct result_xml_state state;
1412 gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (ctx);
1417 result_init (&state, indent, cb, hook);
1418 result_xml_tag_start (&state, "vfs-mount-result", NULL);
1420 result_add_string (&state, "mount-dir", res->mount_dir);
1422 result_xml_tag_end (&state);
1435 STATUS_INCLUDE_CERTS,
1436 STATUS_KEYLIST_MODE,
1438 STATUS_ENCRYPT_RESULT
1441 const char *status_string[] =
1457 #define MAX_RECIPIENTS 10
1458 gpgme_key_t recipients[MAX_RECIPIENTS + 1];
1461 gpg_error_t (*write_status) (void *hook, const char *status, const char *msg);
1462 void *write_status_hook;
1463 gpg_error_t (*write_data) (void *hook, const void *buf, size_t len);
1464 void *write_data_hook;
1466 typedef struct gpgme_tool *gpgme_tool_t;
1469 /* Forward declaration. */
1470 void gt_write_status (gpgme_tool_t gt,
1471 status_t status, ...) GT_GCC_A_SENTINEL(0);
1473 server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
1474 int was_bad, int fd);
1478 _gt_progress_cb (void *opaque, const char *what,
1479 int type, int current, int total)
1481 gpgme_tool_t gt = opaque;
1484 snprintf (buf, sizeof (buf), "0x%02x %i %i", type, current, total);
1485 gt_write_status (gt, STATUS_PROGRESS, what, buf, NULL);
1490 _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
1494 err = gpgme_new (ctx);
1497 gpgme_set_progress_cb (*ctx, _gt_progress_cb, gt);
1503 gt_init (gpgme_tool_t gt)
1507 memset (gt, '\0', sizeof (*gt));
1509 err = _gt_gpgme_new (gt, >->ctx);
1511 log_error (1, err, "can't create gpgme context");
1516 gt_signers_add (gpgme_tool_t gt, const char *fpr)
1521 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1525 return gpgme_signers_add (gt->ctx, key);
1530 gt_signers_clear (gpgme_tool_t gt)
1532 gpgme_signers_clear (gt->ctx);
1538 gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key)
1541 gpgme_ctx_t listctx;
1545 if (!gt || !r_key || !pattern)
1546 return gpg_error (GPG_ERR_INV_VALUE);
1550 err = gpgme_new (&listctx);
1555 gpgme_protocol_t proto;
1556 gpgme_engine_info_t info;
1558 /* Clone the relevant state. */
1559 proto = gpgme_get_protocol (ctx);
1560 /* The g13 protocol does not allow keylisting, we need to choose
1562 if (proto == GPGME_PROTOCOL_G13)
1563 proto = GPGME_PROTOCOL_OpenPGP;
1565 gpgme_set_protocol (listctx, proto);
1566 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1567 info = gpgme_ctx_get_engine_info (ctx);
1568 while (info && info->protocol != proto)
1571 gpgme_ctx_set_engine_info (listctx, proto,
1572 info->file_name, info->home_dir);
1575 err = gpgme_op_keylist_start (listctx, pattern, 0);
1577 err = gpgme_op_keylist_next (listctx, r_key);
1581 err = gpgme_op_keylist_next (listctx, &key);
1582 if (gpgme_err_code (err) == GPG_ERR_EOF)
1587 && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1588 && key && key->subkeys && key->subkeys->fpr
1589 && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1591 /* The fingerprint is identical. We assume that this is
1592 the same key and don't mark it as an ambiguous. This
1593 problem may occur with corrupted keyrings and has
1594 been noticed often with gpgsm. In fact gpgsm uses a
1595 similar hack to sort out such duplicates but it can't
1596 do that while listing keys. */
1597 gpgme_key_unref (key);
1602 gpgme_key_unref (key);
1603 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1605 gpgme_key_unref (*r_key);
1608 gpgme_release (listctx);
1611 gt_write_status (gt, STATUS_RECIPIENT,
1612 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1613 (*r_key)->subkeys->fpr : "invalid", NULL);
1619 gt_recipients_add (gpgme_tool_t gt, const char *pattern)
1624 if (gt->recipients_nr >= MAX_RECIPIENTS)
1625 return gpg_error (GPG_ERR_ENOMEM);
1627 if (gpgme_get_protocol (gt->ctx) == GPGME_PROTOCOL_UISERVER)
1628 err = gpgme_key_from_uid (&key, pattern);
1630 err = gt_get_key (gt, pattern, &key);
1634 gt->recipients[gt->recipients_nr++] = key;
1640 gt_recipients_clear (gpgme_tool_t gt)
1644 for (idx = 0; idx < gt->recipients_nr; idx++)
1645 gpgme_key_unref (gt->recipients[idx]);
1646 memset (gt->recipients, '\0', gt->recipients_nr * sizeof (gpgme_key_t));
1647 gt->recipients_nr = 0;
1652 gt_reset (gpgme_tool_t gt)
1657 err = _gt_gpgme_new (gt, &ctx);
1661 gpgme_release (gt->ctx);
1663 gt_recipients_clear (gt);
1669 gt_write_status (gpgme_tool_t gt, status_t status, ...)
1678 va_start (ap, status);
1681 while ((text = va_arg (ap, const char *)))
1688 while (*text && n < sizeof (buf) - 2)
1697 err = gt->write_status (gt->write_status_hook, status_string[status], buf);
1699 log_error (1, err, "can't write status line");
1704 gt_write_data (gpgme_tool_t gt, const void *buf, size_t len)
1706 return gt->write_data (gt->write_data_hook, buf, len);
1711 gt_get_engine_info (gpgme_tool_t gt, gpgme_protocol_t proto)
1713 gpgme_engine_info_t info;
1714 info = gpgme_ctx_get_engine_info (gt->ctx);
1717 if (proto == GPGME_PROTOCOL_UNKNOWN || proto == info->protocol)
1718 gt_write_status (gt, STATUS_ENGINE,
1719 gpgme_get_protocol_name (info->protocol),
1720 info->file_name, info->version,
1721 info->req_version, info->home_dir, NULL);
1729 gt_protocol_from_name (const char *name)
1731 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_OpenPGP)))
1732 return GPGME_PROTOCOL_OpenPGP;
1733 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_CMS)))
1734 return GPGME_PROTOCOL_CMS;
1735 if (! strcasecmp (name,gpgme_get_protocol_name (GPGME_PROTOCOL_GPGCONF)))
1736 return GPGME_PROTOCOL_GPGCONF;
1737 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_ASSUAN)))
1738 return GPGME_PROTOCOL_ASSUAN;
1739 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_G13)))
1740 return GPGME_PROTOCOL_G13;
1741 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_UISERVER)))
1742 return GPGME_PROTOCOL_UISERVER;
1743 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_DEFAULT)))
1744 return GPGME_PROTOCOL_DEFAULT;
1745 return GPGME_PROTOCOL_UNKNOWN;
1750 gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1752 return gpgme_set_protocol (gt->ctx, proto);
1757 gt_get_protocol (gpgme_tool_t gt)
1759 gpgme_protocol_t proto = gpgme_get_protocol (gt->ctx);
1761 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1769 gt_set_sub_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1771 return gpgme_set_sub_protocol (gt->ctx, proto);
1776 gt_get_sub_protocol (gpgme_tool_t gt)
1778 gpgme_protocol_t proto = gpgme_get_sub_protocol (gt->ctx);
1780 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1788 gt_set_pinentry_mode (gpgme_tool_t gt, gpgme_pinentry_mode_t mode, void *opaque)
1792 gpgme_set_passphrase_cb (gt->ctx, NULL, NULL);
1793 err = gpgme_set_pinentry_mode (gt->ctx, mode);
1794 if (!err && mode == GPGME_PINENTRY_MODE_LOOPBACK)
1795 gpgme_set_passphrase_cb (gt->ctx, server_passphrase_cb, opaque);
1801 gt_set_armor (gpgme_tool_t gt, int armor)
1803 gpgme_set_armor (gt->ctx, armor);
1809 gt_get_armor (gpgme_tool_t gt)
1811 gt_write_status (gt, STATUS_ARMOR,
1812 gpgme_get_armor (gt->ctx) ? "true" : "false", NULL);
1819 gt_set_textmode (gpgme_tool_t gt, int textmode)
1821 gpgme_set_textmode (gt->ctx, textmode);
1827 gt_get_textmode (gpgme_tool_t gt)
1829 gt_write_status (gt, STATUS_TEXTMODE,
1830 gpgme_get_textmode (gt->ctx) ? "true" : "false", NULL);
1837 gt_set_keylist_mode (gpgme_tool_t gt, gpgme_keylist_mode_t keylist_mode)
1839 gpgme_set_keylist_mode (gt->ctx, keylist_mode);
1845 gt_get_keylist_mode (gpgme_tool_t gt)
1847 #define NR_KEYLIST_MODES 6
1848 const char *modes[NR_KEYLIST_MODES + 1];
1850 gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx);
1852 if (mode & GPGME_KEYLIST_MODE_LOCAL)
1853 modes[idx++] = "local";
1854 if (mode & GPGME_KEYLIST_MODE_EXTERN)
1855 modes[idx++] = "extern";
1856 if (mode & GPGME_KEYLIST_MODE_SIGS)
1857 modes[idx++] = "sigs";
1858 if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
1859 modes[idx++] = "sig_notations";
1860 if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
1861 modes[idx++] = "ephemeral";
1862 if (mode & GPGME_KEYLIST_MODE_VALIDATE)
1863 modes[idx++] = "validate";
1864 modes[idx++] = NULL;
1866 gt_write_status (gt, STATUS_KEYLIST_MODE, modes[0], modes[1], modes[2],
1867 modes[3], modes[4], modes[5], modes[6], NULL);
1874 gt_set_include_certs (gpgme_tool_t gt, int include_certs)
1876 gpgme_set_include_certs (gt->ctx, include_certs);
1882 gt_get_include_certs (gpgme_tool_t gt)
1884 int include_certs = gpgme_get_include_certs (gt->ctx);
1887 if (include_certs == GPGME_INCLUDE_CERTS_DEFAULT)
1888 strcpy (buf, "default");
1890 snprintf (buf, sizeof (buf), "%i", include_certs);
1892 gt_write_status (gt, STATUS_INCLUDE_CERTS, buf, NULL);
1899 gt_decrypt_verify (gpgme_tool_t gt, gpgme_data_t cipher, gpgme_data_t plain,
1903 return gpgme_op_decrypt_verify (gt->ctx, cipher, plain);
1905 return gpgme_op_decrypt (gt->ctx, cipher, plain);
1910 gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
1911 gpgme_data_t plain, gpgme_data_t cipher, int sign)
1916 recp = gt->recipients_nr? gt->recipients : NULL;
1919 err = gpgme_op_encrypt_sign (gt->ctx, recp, flags, plain, cipher);
1921 err = gpgme_op_encrypt (gt->ctx, recp, flags, plain, cipher);
1923 gt_recipients_clear (gt);
1930 gt_sign (gpgme_tool_t gt, gpgme_data_t plain, gpgme_data_t sig,
1931 gpgme_sig_mode_t mode)
1933 return gpgme_op_sign (gt->ctx, plain, sig, mode);
1938 gt_verify (gpgme_tool_t gt, gpgme_data_t sig, gpgme_data_t sig_text,
1941 return gpgme_op_verify (gt->ctx, sig, sig_text, plain);
1946 gt_import (gpgme_tool_t gt, gpgme_data_t data)
1948 return gpgme_op_import (gt->ctx, data);
1953 gt_export (gpgme_tool_t gt, const char *pattern[], gpgme_export_mode_t mode,
1956 return gpgme_op_export_ext (gt->ctx, pattern, mode, data);
1961 gt_genkey (gpgme_tool_t gt, const char *parms, gpgme_data_t public,
1962 gpgme_data_t secret)
1964 return gpgme_op_genkey (gt->ctx, parms, public, secret);
1969 gt_import_keys (gpgme_tool_t gt, char *fpr[])
1971 gpg_error_t err = 0;
1981 return gpg_error (GPG_ERR_INV_VALUE);
1983 keys = malloc ((cnt + 1) * sizeof (gpgme_key_t));
1985 return gpg_error_from_syserror ();
1987 for (idx = 0; idx < cnt; idx++)
1989 err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0);
1996 err = gpgme_op_import_keys (gt->ctx, keys);
2001 gpgme_key_unref (keys[idx]);
2009 gt_delete (gpgme_tool_t gt, char *fpr, int allow_secret)
2014 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
2018 err = gpgme_op_delete (gt->ctx, key, allow_secret);
2019 gpgme_key_unref (key);
2025 gt_keylist_start (gpgme_tool_t gt, const char *pattern[], int secret_only)
2027 return gpgme_op_keylist_ext_start (gt->ctx, pattern, secret_only, 0);
2032 gt_keylist_next (gpgme_tool_t gt, gpgme_key_t *key)
2034 return gpgme_op_keylist_next (gt->ctx, key);
2039 gt_getauditlog (gpgme_tool_t gt, gpgme_data_t output, unsigned int flags)
2041 return gpgme_op_getauditlog (gt->ctx, output, flags);
2046 gt_vfs_mount (gpgme_tool_t gt, const char *container_file,
2047 const char *mount_dir, int flags)
2051 err = gpgme_op_vfs_mount (gt->ctx, container_file, mount_dir, flags, &op_err);
2052 return err ? err : op_err;
2057 gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
2061 err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file,
2063 gt_recipients_clear (gt);
2064 return err ? err : op_err;
2068 static const char hlp_passwd[] =
2069 "PASSWD <user-id>\n"
2071 "Ask the backend to change the passphrase for the key\n"
2072 "specified by USER-ID.";
2074 gt_passwd (gpgme_tool_t gt, char *fpr)
2079 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
2081 return gpg_err_code (err) == GPG_ERR_EOF? gpg_error (GPG_ERR_NO_PUBKEY):err;
2083 err = gpgme_op_passwd (gt->ctx, key, 0);
2084 gpgme_key_unref (key);
2089 #define GT_RESULT_ENCRYPT 0x1
2090 #define GT_RESULT_DECRYPT 0x2
2091 #define GT_RESULT_SIGN 0x4
2092 #define GT_RESULT_VERIFY 0x8
2093 #define GT_RESULT_IMPORT 0x10
2094 #define GT_RESULT_GENKEY 0x20
2095 #define GT_RESULT_KEYLIST 0x40
2096 #define GT_RESULT_VFS_MOUNT 0x80
2097 #define GT_RESULT_ALL (~0U)
2100 gt_result (gpgme_tool_t gt, unsigned int flags)
2104 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
2105 gt_write_data (gt, NULL, 0);
2106 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
2107 gt_write_data (gt, NULL, 0);
2108 if (flags & GT_RESULT_ENCRYPT)
2109 result_encrypt_to_xml (gt->ctx, indent,
2110 (result_xml_write_cb_t) gt_write_data, gt);
2111 if (flags & GT_RESULT_DECRYPT)
2112 result_decrypt_to_xml (gt->ctx, indent,
2113 (result_xml_write_cb_t) gt_write_data, gt);
2114 if (flags & GT_RESULT_SIGN)
2115 result_sign_to_xml (gt->ctx, indent,
2116 (result_xml_write_cb_t) gt_write_data, gt);
2117 if (flags & GT_RESULT_VERIFY)
2118 result_verify_to_xml (gt->ctx, indent,
2119 (result_xml_write_cb_t) gt_write_data, gt);
2120 if (flags & GT_RESULT_IMPORT)
2121 result_import_to_xml (gt->ctx, indent,
2122 (result_xml_write_cb_t) gt_write_data, gt);
2123 if (flags & GT_RESULT_GENKEY)
2124 result_genkey_to_xml (gt->ctx, indent,
2125 (result_xml_write_cb_t) gt_write_data, gt);
2126 if (flags & GT_RESULT_KEYLIST)
2127 result_keylist_to_xml (gt->ctx, indent,
2128 (result_xml_write_cb_t) gt_write_data, gt);
2129 if (flags & GT_RESULT_VFS_MOUNT)
2130 result_vfs_mount_to_xml (gt->ctx, indent,
2131 (result_xml_write_cb_t) gt_write_data, gt);
2132 gt_write_data (gt, xml_end, sizeof (xml_end));
2145 assuan_context_t assuan_ctx;
2147 gpgme_data_encoding_t input_enc;
2148 gpgme_data_encoding_t output_enc;
2149 assuan_fd_t input_fd;
2150 char *input_filename;
2152 assuan_fd_t output_fd;
2153 char *output_filename;
2154 FILE *output_stream;
2155 assuan_fd_t message_fd;
2156 char *message_filename;
2157 FILE *message_stream;
2158 gpgme_data_encoding_t message_enc;
2163 server_write_status (void *hook, const char *status, const char *msg)
2165 struct server *server = hook;
2166 return assuan_write_status (server->assuan_ctx, status, msg);
2171 server_write_data (void *hook, const void *buf, size_t len)
2173 struct server *server = hook;
2174 return assuan_send_data (server->assuan_ctx, buf, len);
2179 server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
2180 int was_bad, int fd)
2182 struct server *server = opaque;
2184 unsigned char *buf = NULL;
2187 if (server && server->assuan_ctx)
2190 assuan_write_status (server->assuan_ctx, "USERID_HINT", uid_hint);
2192 assuan_write_status (server->assuan_ctx, "NEED_PASSPHRASE", info);
2194 err = assuan_inquire (server->assuan_ctx, "PASSPHRASE",
2195 &buf, &buflen, 100);
2198 err = gpg_error (GPG_ERR_NO_PASSPHRASE);
2202 /* We take care to always send a LF. */
2203 if (gpgme_io_writen (fd, buf, buflen))
2204 err = gpg_error_from_syserror ();
2205 else if (!memchr (buf, '\n', buflen) && gpgme_io_writen (fd, "\n", 1))
2206 err = gpg_error_from_syserror ();
2213 /* Wrapper around assuan_command_parse_fd to also handle a
2214 "file=FILENAME" argument. On success either a filename is returned
2215 at FILENAME or a file descriptor at RFD; the other one is set to
2216 NULL respective ASSUAN_INVALID_FD. */
2218 server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd,
2221 *rfd = ASSUAN_INVALID_FD;
2224 if (! strncasecmp (line, "file=", 5))
2227 *filename = strdup (line + 5);
2229 return gpg_error_from_syserror();
2230 term = strchr (*filename, ' ');
2236 return assuan_command_parse_fd (ctx, line, rfd);
2240 static gpgme_data_encoding_t
2241 server_data_encoding (const char *line)
2243 if (strstr (line, "--binary"))
2244 return GPGME_DATA_ENCODING_BINARY;
2245 if (strstr (line, "--base64"))
2246 return GPGME_DATA_ENCODING_BASE64;
2247 if (strstr (line, "--armor"))
2248 return GPGME_DATA_ENCODING_ARMOR;
2249 if (strstr (line, "--url"))
2250 return GPGME_DATA_ENCODING_URL;
2251 if (strstr (line, "--urlesc"))
2252 return GPGME_DATA_ENCODING_URLESC;
2253 if (strstr (line, "--url0"))
2254 return GPGME_DATA_ENCODING_URL0;
2255 return GPGME_DATA_ENCODING_NONE;
2259 static gpgme_error_t
2260 server_data_obj (assuan_fd_t fd, char *fn, int out,
2261 gpgme_data_encoding_t encoding,
2262 gpgme_data_t *data, FILE **fs)
2269 *fs = fopen (fn, out ? "wb" : "rb");
2271 return gpg_error_from_syserror ();
2273 err = gpgme_data_new_from_stream (data, *fs);
2276 err = gpgme_data_new_from_fd (data, (int) fd);
2280 return gpgme_data_set_encoding (*data, encoding);
2285 server_reset_fds (struct server *server)
2287 /* assuan closes the input and output FDs for us when doing a RESET,
2288 but we use this same function after commands, so repeat it
2290 if (server->input_fd != ASSUAN_INVALID_FD)
2293 CloseHandle (server->input_fd);
2295 close (server->input_fd);
2297 server->input_fd = ASSUAN_INVALID_FD;
2299 if (server->output_fd != ASSUAN_INVALID_FD)
2302 CloseHandle (server->output_fd);
2304 close (server->output_fd);
2306 server->output_fd = ASSUAN_INVALID_FD;
2308 if (server->message_fd != ASSUAN_INVALID_FD)
2310 /* FIXME: Assuan should provide a close function. */
2312 CloseHandle (server->message_fd);
2314 close (server->message_fd);
2316 server->message_fd = ASSUAN_INVALID_FD;
2318 if (server->input_filename)
2320 free (server->input_filename);
2321 server->input_filename = NULL;
2323 if (server->output_filename)
2325 free (server->output_filename);
2326 server->output_filename = NULL;
2328 if (server->message_filename)
2330 free (server->message_filename);
2331 server->message_filename = NULL;
2333 if (server->input_stream)
2335 fclose (server->input_stream);
2336 server->input_stream = NULL;
2338 if (server->output_stream)
2340 fclose (server->output_stream);
2341 server->output_stream = NULL;
2343 if (server->message_stream)
2345 fclose (server->message_stream);
2346 server->message_stream = NULL;
2349 server->input_enc = GPGME_DATA_ENCODING_NONE;
2350 server->output_enc = GPGME_DATA_ENCODING_NONE;
2351 server->message_enc = GPGME_DATA_ENCODING_NONE;
2356 reset_notify (assuan_context_t ctx, char *line)
2358 struct server *server = assuan_get_pointer (ctx);
2359 server_reset_fds (server);
2360 gt_reset (server->gt);
2365 static const char hlp_version[] =
2366 "VERSION [<string>]\n"
2368 "Call the function gpgme_check_version.";
2370 cmd_version (assuan_context_t ctx, char *line)
2374 const char *version = gpgme_check_version (line);
2375 return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
2379 const char *version = gpgme_check_version (NULL);
2380 return assuan_send_data (ctx, version, strlen (version));
2385 static const char hlp_engine[] =
2386 "ENGINE [<string>]\n"
2388 "Get information about a GPGME engine (a.k.a. protocol).";
2390 cmd_engine (assuan_context_t ctx, char *line)
2392 struct server *server = assuan_get_pointer (ctx);
2393 return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
2397 static const char hlp_protocol[] =
2398 "PROTOCOL [<name>]\n"
2400 "With NAME, set the protocol. Without, return the current\n"
2403 cmd_protocol (assuan_context_t ctx, char *line)
2405 struct server *server = assuan_get_pointer (ctx);
2407 return gt_set_protocol (server->gt, gt_protocol_from_name (line));
2409 return gt_get_protocol (server->gt);
2413 static const char hlp_sub_protocol[] =
2414 "SUB_PROTOCOL [<name>]\n"
2416 "With NAME, set the sub-protocol. Without, return the\n"
2417 "current sub-protocol.";
2419 cmd_sub_protocol (assuan_context_t ctx, char *line)
2421 struct server *server = assuan_get_pointer (ctx);
2423 return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
2425 return gt_get_sub_protocol (server->gt);
2429 static const char hlp_pinentry_mode[] =
2430 "PINENTRY_MODE <name>\n"
2432 "Set the pinentry mode to NAME. Allowedvalues for NAME are:\n"
2433 " default - reset to the default of the engine,\n"
2434 " ask - force the use of the pinentry,\n"
2435 " cancel - emulate use of pinentry's cancel button,\n"
2436 " error - return a pinentry error,\n"
2437 " loopback - redirect pinentry queries to the caller.\n"
2438 "Note that only recent versions of GPG support changing the pinentry mode.";
2440 cmd_pinentry_mode (assuan_context_t ctx, char *line)
2442 struct server *server = assuan_get_pointer (ctx);
2443 gpgme_pinentry_mode_t mode;
2445 if (!line || !*line || !strcmp (line, "default"))
2446 mode = GPGME_PINENTRY_MODE_DEFAULT;
2447 else if (!strcmp (line, "ask"))
2448 mode = GPGME_PINENTRY_MODE_ASK;
2449 else if (!strcmp (line, "cancel"))
2450 mode = GPGME_PINENTRY_MODE_CANCEL;
2451 else if (!strcmp (line, "error"))
2452 mode = GPGME_PINENTRY_MODE_ERROR;
2453 else if (!strcmp (line, "loopback"))
2454 mode = GPGME_PINENTRY_MODE_LOOPBACK;
2456 return gpg_error (GPG_ERR_INV_VALUE);
2458 return gt_set_pinentry_mode (server->gt, mode, server);
2462 static const char hlp_armor[] =
2463 "ARMOR [true|false]\n"
2465 "With 'true' or 'false', turn output ASCII armoring on or\n"
2466 "off. Without, return the current armoring status.";
2468 cmd_armor (assuan_context_t ctx, char *line)
2470 struct server *server = assuan_get_pointer (ctx);
2475 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2479 return gt_set_armor (server->gt, flag);
2482 return gt_get_armor (server->gt);
2486 static const char hlp_textmode[] =
2487 "TEXTMODE [true|false]\n"
2489 "With 'true' or 'false', turn text mode on or off.\n"
2490 "Without, return the current text mode status.";
2492 cmd_textmode (assuan_context_t ctx, char *line)
2494 struct server *server = assuan_get_pointer (ctx);
2499 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2503 return gt_set_textmode (server->gt, flag);
2506 return gt_get_textmode (server->gt);
2510 static const char hlp_include_certs[] =
2511 "INCLUDE_CERTS [default|<n>]\n"
2513 "With DEFAULT or N, set how many certificates should be\n"
2514 "included in the next S/MIME signed message. See the\n"
2515 "GPGME documentation for details on the meaning of"
2516 "various N. Without either, return the current setting.";
2518 cmd_include_certs (assuan_context_t ctx, char *line)
2520 struct server *server = assuan_get_pointer (ctx);
2524 int include_certs = 0;
2526 if (! strcasecmp (line, "default"))
2527 include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
2529 include_certs = atoi (line);
2531 return gt_set_include_certs (server->gt, include_certs);
2534 return gt_get_include_certs (server->gt);
2538 static const char hlp_keylist_mode[] =
2539 "KEYLIST_MODE [local] [extern] [sigs] [sig_notations]\n"
2540 " [ephemeral] [validate]\n"
2542 "Set the mode for the next KEYLIST command.";
2544 cmd_keylist_mode (assuan_context_t ctx, char *line)
2546 struct server *server = assuan_get_pointer (ctx);
2550 gpgme_keylist_mode_t mode = 0;
2552 if (strstr (line, "local"))
2553 mode |= GPGME_KEYLIST_MODE_LOCAL;
2554 if (strstr (line, "extern"))
2555 mode |= GPGME_KEYLIST_MODE_EXTERN;
2556 if (strstr (line, "sigs"))
2557 mode |= GPGME_KEYLIST_MODE_SIGS;
2558 if (strstr (line, "sig_notations"))
2559 mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
2560 if (strstr (line, "ephemeral"))
2561 mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
2562 if (strstr (line, "validate"))
2563 mode |= GPGME_KEYLIST_MODE_VALIDATE;
2565 return gt_set_keylist_mode (server->gt, mode);
2568 return gt_get_keylist_mode (server->gt);
2572 static const char hlp_input[] =
2573 "INPUT [<fd>|FILE=<path>]\n"
2575 "Set the input for the next command. Use either the\n"
2576 "Assuan file descriptor FD or a filesystem PATH.";
2578 cmd_input (assuan_context_t ctx, char *line)
2580 struct server *server = assuan_get_pointer (ctx);
2585 err = server_parse_fd (ctx, line, &sysfd, &filename);
2588 server->input_fd = sysfd;
2589 server->input_filename = filename;
2590 server->input_enc = server_data_encoding (line);
2595 static const char hlp_output[] =
2596 "OUTPUT [<fd>|FILE=<path>]\n"
2598 "Set the output for the next command. Use either the\n"
2599 "Assuan file descriptor FD or a filesystem PATH.";
2601 cmd_output (assuan_context_t ctx, char *line)
2603 struct server *server = assuan_get_pointer (ctx);
2608 err = server_parse_fd (ctx, line, &sysfd, &filename);
2611 server->output_fd = sysfd;
2612 server->output_filename = filename;
2613 server->output_enc = server_data_encoding (line);
2618 static const char hlp_message[] =
2619 "MESSAGE [<fd>|FILE=<path>]\n"
2621 "Set the plaintext message for the next VERIFY command\n"
2622 "with a detached signature. Use either the Assuan file\n"
2623 "descriptor FD or a filesystem PATH.";
2625 cmd_message (assuan_context_t ctx, char *line)
2627 struct server *server = assuan_get_pointer (ctx);
2632 err = server_parse_fd (ctx, line, &sysfd, &filename);
2635 server->message_fd = sysfd;
2636 server->message_filename = filename;
2637 server->message_enc = server_data_encoding (line);
2642 static const char hlp_recipient[] =
2643 "RECIPIENT <pattern>\n"
2645 "Add the key matching PATTERN to the list of recipients\n"
2646 "for the next encryption command.";
2648 cmd_recipient (assuan_context_t ctx, char *line)
2650 struct server *server = assuan_get_pointer (ctx);
2652 return gt_recipients_add (server->gt, line);
2656 static const char hlp_signer[] =
2657 "SIGNER <fingerprint>\n"
2659 "Add the key with FINGERPRINT to the list of signers to\n"
2660 "be used for the next signing command.";
2662 cmd_signer (assuan_context_t ctx, char *line)
2664 struct server *server = assuan_get_pointer (ctx);
2666 return gt_signers_add (server->gt, line);
2670 static const char hlp_signers_clear[] =
2673 "Clear the list of signers specified by previous SIGNER\n"
2676 cmd_signers_clear (assuan_context_t ctx, char *line)
2678 struct server *server = assuan_get_pointer (ctx);
2680 return gt_signers_clear (server->gt);
2685 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
2687 struct server *server = assuan_get_pointer (ctx);
2693 gpgme_data_t inp_data;
2694 gpgme_data_t out_data;
2696 inp_fd = server->input_fd;
2697 inp_fn = server->input_filename;
2698 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2699 return GPG_ERR_ASS_NO_INPUT;
2700 out_fd = server->output_fd;
2701 out_fn = server->output_filename;
2702 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2703 return GPG_ERR_ASS_NO_OUTPUT;
2705 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2706 &server->input_stream);
2709 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2710 &server->output_stream);
2713 gpgme_data_release (inp_data);
2717 err = gt_decrypt_verify (server->gt, inp_data, out_data, verify);
2719 gpgme_data_release (inp_data);
2720 gpgme_data_release (out_data);
2722 server_reset_fds (server);
2728 static const char hlp_decrypt[] =
2731 "Decrypt the object set by the last INPUT command and\n"
2732 "write the decrypted message to the object set by the\n"
2733 "last OUTPUT command.";
2735 cmd_decrypt (assuan_context_t ctx, char *line)
2737 return _cmd_decrypt_verify (ctx, line, 0);
2741 static const char hlp_decrypt_verify[] =
2744 "Decrypt the object set by the last INPUT command and\n"
2745 "verify any embedded signatures. Write the decrypted\n"
2746 "message to the object set by the last OUTPUT command.";
2748 cmd_decrypt_verify (assuan_context_t ctx, char *line)
2750 return _cmd_decrypt_verify (ctx, line, 1);
2755 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
2757 struct server *server = assuan_get_pointer (ctx);
2763 gpgme_data_t inp_data = NULL;
2764 gpgme_data_t out_data = NULL;
2765 gpgme_encrypt_flags_t flags = 0;
2767 if (strstr (line, "--always-trust"))
2768 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
2769 if (strstr (line, "--no-encrypt-to"))
2770 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
2771 if (strstr (line, "--prepare"))
2772 flags |= GPGME_ENCRYPT_PREPARE;
2773 if (strstr (line, "--expect-sign"))
2774 flags |= GPGME_ENCRYPT_EXPECT_SIGN;
2776 inp_fd = server->input_fd;
2777 inp_fn = server->input_filename;
2778 out_fd = server->output_fd;
2779 out_fn = server->output_filename;
2780 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
2782 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2783 &server->input_stream);
2787 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2789 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2790 &server->output_stream);
2793 gpgme_data_release (inp_data);
2798 err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign);
2800 gpgme_data_release (inp_data);
2801 gpgme_data_release (out_data);
2803 server_reset_fds (server);
2809 static const char hlp_encrypt[] =
2810 "ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2811 " [--prepare] [--expect-sign]\n"
2813 "Encrypt the object set by the last INPUT command to\n"
2814 "the keys specified by previous RECIPIENT commands. \n"
2815 "Write the signed and encrypted message to the object\n"
2816 "set by the last OUTPUT command.";
2818 cmd_encrypt (assuan_context_t ctx, char *line)
2820 return _cmd_sign_encrypt (ctx, line, 0);
2824 static const char hlp_sign_encrypt[] =
2825 "SIGN_ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2826 " [--prepare] [--expect-sign]\n"
2828 "Sign the object set by the last INPUT command with the\n"
2829 "keys specified by previous SIGNER commands and encrypt\n"
2830 "it to the keys specified by previous RECIPIENT\n"
2831 "commands. Write the signed and encrypted message to\n"
2832 "the object set by the last OUTPUT command.";
2834 cmd_sign_encrypt (assuan_context_t ctx, char *line)
2836 return _cmd_sign_encrypt (ctx, line, 1);
2840 static const char hlp_sign[] =
2841 "SIGN [--clear|--detach]\n"
2843 "Sign the object set by the last INPUT command with the\n"
2844 "keys specified by previous SIGNER commands. Write the\n"
2845 "signed message to the object set by the last OUTPUT\n"
2846 "command. With `--clear`, generate a clear text\n"
2847 "signature. With `--detach`, generate a detached\n"
2850 cmd_sign (assuan_context_t ctx, char *line)
2852 struct server *server = assuan_get_pointer (ctx);
2858 gpgme_data_t inp_data;
2859 gpgme_data_t out_data;
2860 gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
2862 if (strstr (line, "--clear"))
2863 mode = GPGME_SIG_MODE_CLEAR;
2864 if (strstr (line, "--detach"))
2865 mode = GPGME_SIG_MODE_DETACH;
2867 inp_fd = server->input_fd;
2868 inp_fn = server->input_filename;
2869 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2870 return GPG_ERR_ASS_NO_INPUT;
2871 out_fd = server->output_fd;
2872 out_fn = server->output_filename;
2873 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2874 return GPG_ERR_ASS_NO_OUTPUT;
2876 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2877 &server->input_stream);
2880 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2881 &server->output_stream);
2884 gpgme_data_release (inp_data);
2888 err = gt_sign (server->gt, inp_data, out_data, mode);
2890 gpgme_data_release (inp_data);
2891 gpgme_data_release (out_data);
2892 server_reset_fds (server);
2898 static const char hlp_verify[] =
2901 "Verify signatures on the object set by the last INPUT\n"
2902 "and MESSAGE commands. If the message was encrypted,\n"
2903 "write the plaintext to the object set by the last\n"
2906 cmd_verify (assuan_context_t ctx, char *line)
2908 struct server *server = assuan_get_pointer (ctx);
2916 gpgme_data_t inp_data;
2917 gpgme_data_t msg_data = NULL;
2918 gpgme_data_t out_data = NULL;
2920 inp_fd = server->input_fd;
2921 inp_fn = server->input_filename;
2922 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2923 return GPG_ERR_ASS_NO_INPUT;
2924 msg_fd = server->message_fd;
2925 msg_fn = server->message_filename;
2926 out_fd = server->output_fd;
2927 out_fn = server->output_filename;
2929 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2930 &server->input_stream);
2933 if (msg_fd != ASSUAN_INVALID_FD || msg_fn)
2935 err = server_data_obj (msg_fd, msg_fn, 0, server->message_enc, &msg_data,
2936 &server->message_stream);
2939 gpgme_data_release (inp_data);
2943 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2945 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2946 &server->output_stream);
2949 gpgme_data_release (inp_data);
2950 gpgme_data_release (msg_data);
2955 err = gt_verify (server->gt, inp_data, msg_data, out_data);
2957 gpgme_data_release (inp_data);
2959 gpgme_data_release (msg_data);
2961 gpgme_data_release (out_data);
2963 server_reset_fds (server);
2969 static const char hlp_import[] =
2970 "IMPORT [<pattern>]\n"
2972 "With PATTERN, import the keys described by PATTERN.\n"
2973 "Without, read a key (or keys) from the object set by the\n"
2974 "last INPUT command.";
2976 cmd_import (assuan_context_t ctx, char *line)
2978 struct server *server = assuan_get_pointer (ctx);
2982 char *fprs[2] = { line, NULL };
2984 return gt_import_keys (server->gt, fprs);
2991 gpgme_data_t inp_data;
2993 inp_fd = server->input_fd;
2994 inp_fn = server->input_filename;
2995 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2996 return GPG_ERR_ASS_NO_INPUT;
2998 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2999 &server->input_stream);
3003 err = gt_import (server->gt, inp_data);
3005 gpgme_data_release (inp_data);
3006 server_reset_fds (server);
3013 static const char hlp_export[] =
3014 "EXPORT [--extern] [--minimal] [<pattern>]\n"
3016 "Export the keys described by PATTERN. Write the\n"
3017 "the output to the object set by the last OUTPUT command.";
3019 cmd_export (assuan_context_t ctx, char *line)
3021 struct server *server = assuan_get_pointer (ctx);
3025 gpgme_data_t out_data;
3026 gpgme_export_mode_t mode = 0;
3027 const char *pattern[2];
3029 out_fd = server->output_fd;
3030 out_fn = server->output_filename;
3031 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
3032 return GPG_ERR_ASS_NO_OUTPUT;
3033 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
3034 &server->output_stream);
3038 if (has_option (line, "--extern"))
3039 mode |= GPGME_EXPORT_MODE_EXTERN;
3040 if (has_option (line, "--minimal"))
3041 mode |= GPGME_EXPORT_MODE_MINIMAL;
3043 line = skip_options (line);
3048 err = gt_export (server->gt, pattern, mode, out_data);
3050 gpgme_data_release (out_data);
3051 server_reset_fds (server);
3058 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
3062 gpgme_ssize_t writen = gpgme_data_write (data, buf, size);
3063 if (writen < 0 && errno != EAGAIN)
3064 return gpg_error_from_syserror ();
3065 else if (writen > 0)
3067 buf = (void *) (((char *) buf) + writen);
3076 cmd_genkey (assuan_context_t ctx, char *line)
3078 struct server *server = assuan_get_pointer (ctx);
3084 gpgme_data_t inp_data;
3085 gpgme_data_t out_data = NULL;
3086 gpgme_data_t parms_data = NULL;
3089 inp_fd = server->input_fd;
3090 inp_fn = server->input_filename;
3091 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
3092 return GPG_ERR_ASS_NO_INPUT;
3093 out_fd = server->output_fd;
3094 out_fn = server->output_filename;
3096 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
3097 &server->input_stream);
3100 if (out_fd != ASSUAN_INVALID_FD || out_fn)
3102 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
3103 &server->output_stream);
3106 gpgme_data_release (inp_data);
3111 /* Convert input data. */
3112 err = gpgme_data_new (&parms_data);
3118 gpgme_ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
3121 err = gpg_error_from_syserror ();
3124 else if (readn == 0)
3127 err = _cmd_genkey_write (parms_data, buf, readn);
3132 err = _cmd_genkey_write (parms_data, "", 1);
3135 parms = gpgme_data_release_and_get_mem (parms_data, NULL);
3139 err = gpg_error (GPG_ERR_GENERAL);
3143 err = gt_genkey (server->gt, parms, out_data, NULL);
3145 server_reset_fds (server);
3148 gpgme_data_release (inp_data);
3150 gpgme_data_release (out_data);
3152 gpgme_data_release (parms_data);
3159 cmd_delete (assuan_context_t ctx, char *line)
3161 struct server *server = assuan_get_pointer (ctx);
3162 int allow_secret = 0;
3163 const char optstr[] = "--allow-secret";
3165 if (!strncasecmp (line, optstr, strlen (optstr)))
3168 line += strlen (optstr);
3169 while (*line && !spacep (line))
3172 return gt_delete (server->gt, line, allow_secret);
3176 static const char hlp_keylist[] =
3177 "KEYLIST [--secret-only] [<patterns>]\n"
3179 "List all certificates or only those specified by PATTERNS. Each\n"
3180 "pattern shall be a percent-plus escaped certificate specification.";
3182 cmd_keylist (assuan_context_t ctx, char *line)
3184 #define MAX_CMD_KEYLIST_PATTERN 20
3185 struct server *server = assuan_get_pointer (ctx);
3186 gpgme_tool_t gt = server->gt;
3187 struct result_xml_state state;
3189 int secret_only = 0;
3191 const char *pattern[MAX_CMD_KEYLIST_PATTERN+1];
3192 const char optstr[] = "--secret-only";
3195 if (!strncasecmp (line, optstr, strlen (optstr)))
3198 line += strlen (optstr);
3199 while (*line && !spacep (line))
3204 for (p=line; *p; line = p)
3206 while (*p && *p != ' ')
3212 if (idx+1 == DIM (pattern))
3213 return gpg_error (GPG_ERR_TOO_MANY);
3214 strcpy_escaped_plus (line, line);
3215 pattern[idx++] = line;
3218 pattern[idx] = NULL;
3220 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
3221 gt_write_data (gt, NULL, 0);
3222 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
3223 gt_write_data (gt, NULL, 0);
3224 result_init (&state, indent, (result_xml_write_cb_t) gt_write_data, gt);
3225 result_xml_tag_start (&state, "keylist", NULL);
3227 err = gt_keylist_start (server->gt, pattern, secret_only);
3231 gpgme_subkey_t subkey;
3232 gpgme_user_id_t uid;
3234 err = gt_keylist_next (server->gt, &key);
3235 if (gpg_err_code (err) == GPG_ERR_EOF)
3242 result_xml_tag_start (&state, "key", NULL);
3243 result_add_value (&state, "revoked", key->revoked);
3244 result_add_value (&state, "expired", key->expired);
3245 result_add_value (&state, "disabled", key->disabled);
3246 result_add_value (&state, "invalid", key->invalid);
3247 result_add_value (&state, "can-encrypt", key->can_encrypt);
3248 result_add_value (&state, "can-sign", key->can_sign);
3249 result_add_value (&state, "can-certify", key->can_certify);
3250 result_add_value (&state, "can-authenticate", key->can_authenticate);
3251 result_add_value (&state, "is-qualified", key->is_qualified);
3252 result_add_value (&state, "secret", key->secret);
3253 result_add_protocol (&state, "protocol", key->protocol);
3254 result_xml_tag_start (&state, "issuer", NULL);
3255 result_add_string (&state, "serial", key->issuer_serial);
3256 result_add_string (&state, "name", key->issuer_name);
3257 result_xml_tag_end (&state); /* issuer */
3258 result_add_string (&state, "chain-id", key->chain_id);
3259 result_add_validity (&state, "owner-trust", key->owner_trust);
3260 result_xml_tag_start (&state, "subkeys", NULL);
3261 subkey = key->subkeys;
3263 result_xml_tag_start (&state, "subkey", NULL);
3264 /* FIXME: more data */
3265 result_add_fpr (&state, "fpr", subkey->fpr);
3266 result_xml_tag_end (&state); /* subkey */
3267 subkey = subkey->next;
3269 result_xml_tag_end (&state); /* subkeys */
3270 result_xml_tag_start (&state, "uids", NULL);
3273 result_xml_tag_start (&state, "uid", NULL);
3274 /* FIXME: more data */
3275 result_add_string (&state, "uid", uid->uid);
3276 result_add_string (&state, "name", uid->name);
3277 result_add_string (&state, "email", uid->email);
3278 result_add_string (&state, "comment", uid->comment);
3279 result_xml_tag_end (&state); /* uid */
3282 result_xml_tag_end (&state); /* uids */
3283 result_xml_tag_end (&state); /* key */
3284 gpgme_key_unref (key);
3288 result_xml_tag_end (&state); /* keylist */
3289 gt_write_data (gt, xml_end, sizeof (xml_end));
3291 server_reset_fds (server);
3297 static const char hlp_getauditlog[] =
3298 "GETAUDITLOG [--html] [--with-help]\n"
3300 "Call the function gpgme_op_getauditlog with the given flags. Write\n"
3301 "the output to the object set by the last OUTPUT command.";
3303 cmd_getauditlog (assuan_context_t ctx, char *line)
3305 struct server *server = assuan_get_pointer (ctx);
3309 gpgme_data_t out_data;
3310 unsigned int flags = 0;
3312 out_fd = server->output_fd;
3313 out_fn = server->output_filename;
3314 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
3315 return GPG_ERR_ASS_NO_OUTPUT;
3316 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
3317 &server->output_stream);
3321 if (strstr (line, "--html"))
3322 flags |= GPGME_AUDITLOG_HTML;
3323 if (strstr (line, "--with-help"))
3324 flags |= GPGME_AUDITLOG_WITH_HELP;
3326 err = gt_getauditlog (server->gt, out_data, flags);
3328 gpgme_data_release (out_data);
3329 server_reset_fds (server);
3336 cmd_vfs_mount (assuan_context_t ctx, char *line)
3338 struct server *server = assuan_get_pointer (ctx);
3342 mount_dir = strchr (line, ' ');
3345 *(mount_dir++) = '\0';
3346 while (*mount_dir == ' ')
3350 err = gt_vfs_mount (server->gt, line, mount_dir, 0);
3357 cmd_vfs_create (assuan_context_t ctx, char *line)
3359 struct server *server = assuan_get_pointer (ctx);
3363 end = strchr (line, ' ');
3371 err = gt_vfs_create (server->gt, line, 0);
3378 cmd_passwd (assuan_context_t ctx, char *line)
3380 struct server *server = assuan_get_pointer (ctx);
3382 return gt_passwd (server->gt, line);
3388 cmd_result (assuan_context_t ctx, char *line)
3390 struct server *server = assuan_get_pointer (ctx);
3391 return gt_result (server->gt, GT_RESULT_ALL);
3395 /* STRERROR <err> */
3397 cmd_strerror (assuan_context_t ctx, char *line)
3403 snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
3404 gpgme_strsource (err));
3405 return assuan_send_data (ctx, buf, strlen (buf));
3410 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
3412 gpgme_pubkey_algo_t algo;
3416 snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
3417 return assuan_send_data (ctx, buf, strlen (buf));
3422 cmd_hash_algo_name (assuan_context_t ctx, char *line)
3424 gpgme_hash_algo_t algo;
3428 snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
3429 return assuan_send_data (ctx, buf, strlen (buf));
3433 /* Tell the assuan library about our commands. */
3435 register_commands (assuan_context_t ctx)
3440 assuan_handler_t handler;
3441 const char * const help;
3443 /* RESET, BYE are implicit. */
3444 { "VERSION", cmd_version, hlp_version },
3445 /* TODO: Set engine info. */
3446 { "ENGINE", cmd_engine, hlp_engine },
3447 { "PROTOCOL", cmd_protocol, hlp_protocol },
3448 { "SUB_PROTOCOL", cmd_sub_protocol, hlp_sub_protocol },
3449 { "PINENTRY_MODE", cmd_pinentry_mode, hlp_pinentry_mode },
3450 { "ARMOR", cmd_armor, hlp_armor },
3451 { "TEXTMODE", cmd_textmode, hlp_textmode },
3452 { "INCLUDE_CERTS", cmd_include_certs, hlp_include_certs },
3453 { "KEYLIST_MODE", cmd_keylist_mode, hlp_keylist_mode },
3454 { "INPUT", cmd_input, hlp_input },
3455 { "OUTPUT", cmd_output, hlp_output },
3456 { "MESSAGE", cmd_message, hlp_message },
3457 { "RECIPIENT", cmd_recipient, hlp_recipient },
3458 { "SIGNER", cmd_signer, hlp_signer },
3459 { "SIGNERS_CLEAR", cmd_signers_clear, hlp_signers_clear },
3460 /* TODO: SIGNOTATION missing. */
3461 /* TODO: Could add wait interface if we allow more than one context */
3462 /* and add _START variants. */
3463 /* TODO: Could add data interfaces if we allow multiple data objects. */
3464 { "DECRYPT", cmd_decrypt, hlp_decrypt },
3465 { "DECRYPT_VERIFY", cmd_decrypt_verify, hlp_decrypt_verify },
3466 { "ENCRYPT", cmd_encrypt, hlp_encrypt },
3467 { "ENCRYPT_SIGN", cmd_sign_encrypt, hlp_sign_encrypt },
3468 { "SIGN_ENCRYPT", cmd_sign_encrypt, hlp_sign_encrypt },
3469 { "SIGN", cmd_sign, hlp_sign },
3470 { "VERIFY", cmd_verify, hlp_verify },
3471 { "IMPORT", cmd_import, hlp_import },
3472 { "EXPORT", cmd_export, hlp_export },
3473 { "GENKEY", cmd_genkey },
3474 { "DELETE", cmd_delete },
3475 /* TODO: EDIT, CARD_EDIT (with INQUIRE) */
3476 { "KEYLIST", cmd_keylist, hlp_keylist },
3477 { "LISTKEYS", cmd_keylist, hlp_keylist },
3478 /* TODO: TRUSTLIST, TRUSTLIST_EXT */
3479 { "GETAUDITLOG", cmd_getauditlog, hlp_getauditlog },
3481 { "VFS_MOUNT", cmd_vfs_mount },
3482 { "MOUNT", cmd_vfs_mount },
3483 { "VFS_CREATE", cmd_vfs_create },
3484 { "CREATE", cmd_vfs_create },
3486 { "RESULT", cmd_result },
3487 { "STRERROR", cmd_strerror },
3488 { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
3489 { "HASH_ALGO_NAME", cmd_hash_algo_name },
3490 { "PASSWD", cmd_passwd, hlp_passwd },
3495 for (idx = 0; table[idx].name; idx++)
3497 err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
3507 gpgme_server (gpgme_tool_t gt)
3510 assuan_fd_t filedes[2];
3511 struct server server;
3512 static const char hello[] = ("GPGME-Tool " VERSION " ready");
3514 memset (&server, 0, sizeof (server));
3515 server.input_fd = ASSUAN_INVALID_FD;
3516 server.output_fd = ASSUAN_INVALID_FD;
3517 server.message_fd = ASSUAN_INVALID_FD;
3518 server.input_enc = GPGME_DATA_ENCODING_NONE;
3519 server.output_enc = GPGME_DATA_ENCODING_NONE;
3520 server.message_enc = GPGME_DATA_ENCODING_NONE;
3523 gt->write_status = server_write_status;
3524 gt->write_status_hook = &server;
3525 gt->write_data = server_write_data;
3526 gt->write_data_hook = &server;
3528 /* We use a pipe based server so that we can work from scripts.
3529 assuan_init_pipe_server will automagically detect when we are
3530 called with a socketpair and ignore FIELDES in this case. */
3531 #ifdef HAVE_W32CE_SYSTEM
3532 filedes[0] = ASSUAN_STDIN;
3533 filedes[1] = ASSUAN_STDOUT;
3535 filedes[0] = assuan_fdopen (0);
3536 filedes[1] = assuan_fdopen (1);
3538 err = assuan_new (&server.assuan_ctx);
3540 log_error (1, err, "can't create assuan context");
3542 assuan_set_pointer (server.assuan_ctx, &server);
3544 err = assuan_init_pipe_server (server.assuan_ctx, filedes);
3546 log_error (1, err, "can't initialize assuan server");
3547 err = register_commands (server.assuan_ctx);
3549 log_error (1, err, "can't register assuan commands");
3550 assuan_set_hello_line (server.assuan_ctx, hello);
3552 assuan_register_reset_notify (server.assuan_ctx, reset_notify);
3554 #define DBG_ASSUAN 0
3556 assuan_set_log_stream (server.assuan_ctx, log_stream);
3560 err = assuan_accept (server.assuan_ctx);
3565 log_error (0, err, "assuan accept problem");
3569 err = assuan_process (server.assuan_ctx);
3571 log_error (0, err, "assuan processing failed");
3574 assuan_release (server.assuan_ctx);
3579 /* MAIN PROGRAM STARTS HERE. */
3581 const char *argp_program_version = VERSION;
3582 const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
3583 error_t argp_err_exit_status = 1;
3585 static char doc[] = "GPGME Tool -- Assuan server exposing GPGME operations";
3586 static char args_doc[] = "COMMAND [OPTIONS...]";
3588 static struct argp_option options[] = {
3589 { "server", 's', 0, 0, "Server mode" },
3590 { "gpg-binary", 501, "FILE", 0, "Use FILE for the GPG backend" },
3594 static error_t parse_options (int key, char *arg, struct argp_state *state);
3595 static struct argp argp = { options, parse_options, args_doc, doc };
3599 enum { CMD_DEFAULT, CMD_SERVER } cmd;
3600 const char *gpg_binary;
3604 args_init (struct args *args)
3606 memset (args, '\0', sizeof (*args));
3607 args->cmd = CMD_DEFAULT;
3612 parse_options (int key, char *arg, struct argp_state *state)
3614 struct args *args = state->input;
3619 args->cmd = CMD_SERVER;
3623 args->gpg_binary = arg;
3627 if (state->arg_num >= 2)
3629 printf ("Arg[%i] = %s\n", state->arg_num, arg);
3632 if (state->arg_num < 2)
3638 return ARGP_ERR_UNKNOWN;
3645 main (int argc, char *argv[])
3648 struct gpgme_tool gt;
3651 #ifdef HAVE_SETLOCALE
3652 setlocale (LC_ALL, "");
3654 gpgme_check_version (NULL);
3656 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
3659 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
3664 argp_parse (&argp, argc, argv, 0, 0, &args);
3667 if (args.gpg_binary)
3669 if (access (args.gpg_binary, X_OK))
3670 err = gpg_error_from_syserror ();
3672 err = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP,
3673 args.gpg_binary, NULL);
3675 log_error (1, err, "error witching OpenPGP engine to '%s'",
3689 gpgme_release (gt.ctx);
3691 #ifdef HAVE_W32CE_SYSTEM
3692 /* Give the buggy ssh server time to flush the output buffers. */