1 /* gpgme-tool.c - Assuan server exposing GnuPG Made Easy operations.
2 Copyright (C) 2009, 2010, 2012 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);
648 fprintf (log_stream, ": %s <%s>", gpg_strerror (errnum),
649 gpg_strsource (errnum));
650 fprintf (log_stream, "\n");
656 /* Note that it is sufficient to allocate the target string D as long
657 as the source string S, i.e.: strlen(s)+1;. D == S is allowed. */
659 strcpy_escaped_plus (char *d, const char *s)
663 if (*s == '%' && s[1] && s[2])
678 /* Check whether the option NAME appears in LINE. */
680 has_option (const char *line, const char *name)
683 int n = strlen (name);
685 s = strstr (line, name);
686 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
689 /* Skip over options. It is assumed that leading spaces have been
690 removed (this is the case for lines passed to a handler from
691 assuan). Blanks after the options are also removed. */
693 skip_options (char *line)
695 while ( *line == '-' && line[1] == '-' )
697 while (*line && !spacep (line))
699 while (spacep (line))
708 typedef gpg_error_t (*result_xml_write_cb_t) (void *hook, const void *buf,
711 static char xml_preamble1[] = "<?xml version=\"1.0\" "
712 "encoding=\"UTF-8\" standalone=\"yes\"?>\n";
713 static const char xml_preamble2[] = "<gpgme>\n";
714 static const char xml_end[] = "</gpgme>\n";
717 struct result_xml_state
720 result_xml_write_cb_t cb;
726 int had_data[MAX_TAGS];
731 result_init (struct result_xml_state *state, int indent,
732 result_xml_write_cb_t cb, void *hook)
734 memset (state, '\0', sizeof (*state));
735 state->indent = indent;
742 result_xml_indent (struct result_xml_state *state)
744 char spaces[state->indent + 1];
746 for (i = 0; i < state->indent; i++)
749 return (*state->cb) (state->hook, spaces, i);
754 result_xml_tag_start (struct result_xml_state *state, char *name, ...)
756 result_xml_write_cb_t cb = state->cb;
757 void *hook = state->hook;
764 if (state->next_tag > 0)
766 if (! state->had_data[state->next_tag - 1])
768 (*cb) (hook, ">\n", 2);
769 (*cb) (hook, NULL, 0);
771 state->had_data[state->next_tag - 1] = 1;
774 result_xml_indent (state);
775 (*cb) (hook, "<", 1);
776 (*cb) (hook, name, strlen (name));
778 state->tag[state->next_tag] = name;
779 state->had_data[state->next_tag] = 0;
785 attr = va_arg (ap, char *);
789 attr_val = va_arg (ap, char *);
790 if (attr_val == NULL)
793 (*cb) (hook, " ", 1);
794 (*cb) (hook, attr, strlen (attr));
795 (*cb) (hook, "=\"", 2);
796 (*cb) (hook, attr_val, strlen (attr_val));
797 (*cb) (hook, "\"", 1);
803 /* Return a constant string with an XML entity for C. */
805 result_xml_escape_replacement(char c)
820 /* Escape DATA by replacing certain characters with their XML
821 entities. The result is stored in a newly allocated buffer which
822 address will be stored at BUF. Returns 0 on success. */
824 result_xml_escape (const char *data, char **buf)
830 init_membuf (&mb, 128);
831 data_len = strlen (data);
832 for (i = 0; i < data_len; i++)
834 r = result_xml_escape_replacement (data[i]);
836 put_membuf (&mb, r, strlen (r));
838 put_membuf (&mb, data+i, 1);
840 put_membuf (&mb, "", 1);
841 *buf = get_membuf (&mb, NULL);
842 return *buf? 0 : gpg_error_from_syserror ();
847 result_xml_tag_data (struct result_xml_state *state, const char *data)
850 result_xml_write_cb_t cb = state->cb;
851 void *hook = state->hook;
854 if (state->had_data[state->next_tag - 1])
856 (*cb) (hook, "\n", 2);
857 (*cb) (hook, NULL, 0);
858 result_xml_indent (state);
861 (*cb) (hook, ">", 1);
862 state->had_data[state->next_tag - 1] = 2;
864 err = result_xml_escape (data, &buf);
868 (*cb) (hook, buf, strlen (buf));
877 result_xml_tag_end (struct result_xml_state *state)
879 result_xml_write_cb_t cb = state->cb;
880 void *hook = state->hook;
885 if (state->had_data[state->next_tag])
887 if (state->had_data[state->next_tag] == 1)
888 result_xml_indent (state);
889 (*cb) (hook, "</", 2);
890 (*cb) (hook, state->tag[state->next_tag],
891 strlen (state->tag[state->next_tag]));
892 (*cb) (hook, ">\n", 2);
893 (*cb) (hook, NULL, 0);
897 (*cb) (hook, " />\n", 4);
898 (*cb) (hook, NULL, 0);
905 result_add_error (struct result_xml_state *state, char *name, gpg_error_t err)
909 snprintf (code, sizeof (code) - 1, "0x%x", err);
910 snprintf (msg, sizeof (msg) - 1, "%s <%s>",
911 gpg_strerror (err), gpg_strsource (err));
912 result_xml_tag_start (state, name, "value", code, NULL);
913 result_xml_tag_data (state, msg);
914 result_xml_tag_end (state);
920 result_add_pubkey_algo (struct result_xml_state *state,
921 char *name, gpgme_pubkey_algo_t algo)
925 snprintf (code, sizeof (code) - 1, "0x%x", algo);
926 snprintf (msg, sizeof (msg) - 1, "%s",
927 gpgme_pubkey_algo_name (algo));
928 result_xml_tag_start (state, name, "value", code, NULL);
929 result_xml_tag_data (state, msg);
930 result_xml_tag_end (state);
936 result_add_hash_algo (struct result_xml_state *state,
937 char *name, gpgme_hash_algo_t algo)
941 snprintf (code, sizeof (code) - 1, "0x%x", algo);
942 snprintf (msg, sizeof (msg) - 1, "%s",
943 gpgme_hash_algo_name (algo));
944 result_xml_tag_start (state, name, "value", code, NULL);
945 result_xml_tag_data (state, msg);
946 result_xml_tag_end (state);
952 result_add_keyid (struct result_xml_state *state, char *name, char *keyid)
954 result_xml_tag_start (state, name, NULL);
955 result_xml_tag_data (state, keyid);
956 result_xml_tag_end (state);
962 result_add_fpr (struct result_xml_state *state, char *name, char *fpr)
964 result_xml_tag_start (state, name, NULL);
965 result_xml_tag_data (state, fpr);
966 result_xml_tag_end (state);
972 result_add_timestamp (struct result_xml_state *state, char *name,
973 unsigned int timestamp)
977 snprintf (code, sizeof (code) - 1, "%ui", timestamp);
978 result_xml_tag_start (state, name, "unix", code, NULL);
979 result_xml_tag_end (state);
985 result_add_sig_mode (struct result_xml_state *state, char *name,
986 gpgme_sig_mode_t sig_mode)
991 snprintf (code, sizeof (code) - 1, "%i", sig_mode);
994 case GPGME_SIG_MODE_NORMAL:
997 case GPGME_SIG_MODE_DETACH:
1000 case GPGME_SIG_MODE_CLEAR:
1007 result_xml_tag_start (state, name, "type", mode, "value", code, NULL);
1008 result_xml_tag_data (state, mode);
1009 result_xml_tag_end (state);
1015 result_add_protocol (struct result_xml_state *state, char *name,
1016 gpgme_protocol_t protocol)
1021 snprintf (code, sizeof (code) - 1, "%i", protocol);
1022 str = gpgme_get_protocol_name(protocol);
1025 result_xml_tag_start (state, name, "value", code, NULL);
1026 result_xml_tag_data (state, str);
1027 result_xml_tag_end (state);
1033 result_add_validity (struct result_xml_state *state, char *name,
1034 gpgme_validity_t validity)
1039 snprintf (code, sizeof (code) - 1, "%i", validity);
1042 case GPGME_VALIDITY_UNDEFINED:
1045 case GPGME_VALIDITY_NEVER:
1048 case GPGME_VALIDITY_MARGINAL:
1051 case GPGME_VALIDITY_FULL:
1054 case GPGME_VALIDITY_ULTIMATE:
1061 result_xml_tag_start (state, name, "value", code, NULL);
1062 result_xml_tag_data (state, str);
1063 result_xml_tag_end (state);
1069 result_add_value (struct result_xml_state *state,
1070 char *name, unsigned int val)
1074 snprintf (code, sizeof (code) - 1, "0x%x", val);
1075 result_xml_tag_start (state, name, "value", code, NULL);
1076 result_xml_tag_end (state);
1082 result_add_string (struct result_xml_state *state,
1083 char *name, char *str)
1087 result_xml_tag_start (state, name, NULL);
1088 result_xml_tag_data (state, str);
1089 result_xml_tag_end (state);
1095 result_encrypt_to_xml (gpgme_ctx_t ctx, int indent,
1096 result_xml_write_cb_t cb, void *hook)
1098 struct result_xml_state state;
1099 gpgme_encrypt_result_t res = gpgme_op_encrypt_result (ctx);
1100 gpgme_invalid_key_t inv_recp;
1105 result_init (&state, indent, cb, hook);
1106 result_xml_tag_start (&state, "encrypt-result", NULL);
1108 inv_recp = res->invalid_recipients;
1111 result_xml_tag_start (&state, "invalid-recipients", NULL);
1115 result_xml_tag_start (&state, "invalid-key", NULL);
1117 result_add_fpr (&state, "fpr", inv_recp->fpr);
1118 result_add_error (&state, "reason", inv_recp->reason);
1119 result_xml_tag_end (&state);
1120 inv_recp = inv_recp->next;
1122 result_xml_tag_end (&state);
1124 result_xml_tag_end (&state);
1131 result_decrypt_to_xml (gpgme_ctx_t ctx, int indent,
1132 result_xml_write_cb_t cb, void *hook)
1134 struct result_xml_state state;
1135 gpgme_decrypt_result_t res = gpgme_op_decrypt_result (ctx);
1136 gpgme_recipient_t recp;
1141 result_init (&state, indent, cb, hook);
1142 result_xml_tag_start (&state, "decrypt-result", NULL);
1146 result_xml_tag_start (&state, "file-name", NULL);
1147 result_xml_tag_data (&state, res->file_name);
1148 result_xml_tag_end (&state);
1150 if (res->unsupported_algorithm)
1152 result_xml_tag_start (&state, "unsupported-alogorithm", NULL);
1153 result_xml_tag_data (&state, res->unsupported_algorithm);
1154 result_xml_tag_end (&state);
1156 if (res->wrong_key_usage)
1158 result_xml_tag_start (&state, "wrong-key-usage", NULL);
1159 result_xml_tag_end (&state);
1162 recp = res->recipients;
1165 result_xml_tag_start (&state, "recipients", NULL);
1168 result_xml_tag_start (&state, "recipient", NULL);
1169 result_add_keyid (&state, "keyid", recp->keyid);
1170 result_add_pubkey_algo (&state, "pubkey-algo", recp->pubkey_algo);
1171 result_add_error (&state, "status", recp->status);
1172 result_xml_tag_end (&state);
1175 result_xml_tag_end (&state);
1177 result_xml_tag_end (&state);
1184 result_sign_to_xml (gpgme_ctx_t ctx, int indent,
1185 result_xml_write_cb_t cb, void *hook)
1187 struct result_xml_state state;
1188 gpgme_sign_result_t res = gpgme_op_sign_result (ctx);
1189 gpgme_invalid_key_t inv_key;
1190 gpgme_new_signature_t new_sig;
1195 result_init (&state, indent, cb, hook);
1196 result_xml_tag_start (&state, "sign-result", NULL);
1198 inv_key = res->invalid_signers;
1201 result_xml_tag_start (&state, "invalid-signers", NULL);
1205 result_xml_tag_start (&state, "invalid-key", NULL);
1207 result_add_fpr (&state, "fpr", inv_key->fpr);
1208 result_add_error (&state, "reason", inv_key->reason);
1209 result_xml_tag_end (&state);
1210 inv_key = inv_key->next;
1212 result_xml_tag_end (&state);
1215 new_sig = res->signatures;
1218 result_xml_tag_start (&state, "signatures", NULL);
1222 result_xml_tag_start (&state, "new-signature", NULL);
1223 result_add_sig_mode (&state, "type", new_sig->type);
1224 result_add_pubkey_algo (&state, "pubkey-algo", new_sig->pubkey_algo);
1225 result_add_hash_algo (&state, "hash-algo", new_sig->hash_algo);
1226 result_add_timestamp (&state, "timestamp", new_sig->timestamp);
1228 result_add_fpr (&state, "fpr", new_sig->fpr);
1229 result_add_value (&state, "sig-class", new_sig->sig_class);
1231 result_xml_tag_end (&state);
1232 new_sig = new_sig->next;
1234 result_xml_tag_end (&state);
1237 result_xml_tag_end (&state);
1244 result_verify_to_xml (gpgme_ctx_t ctx, int indent,
1245 result_xml_write_cb_t cb, void *hook)
1247 struct result_xml_state state;
1248 gpgme_verify_result_t res = gpgme_op_verify_result (ctx);
1249 gpgme_signature_t sig;
1254 result_init (&state, indent, cb, hook);
1255 result_xml_tag_start (&state, "verify-result", NULL);
1259 result_xml_tag_start (&state, "file-name", NULL);
1260 result_xml_tag_data (&state, res->file_name);
1261 result_xml_tag_end (&state);
1264 sig = res->signatures;
1267 result_xml_tag_start (&state, "signatures", NULL);
1271 result_xml_tag_start (&state, "signature", NULL);
1273 /* FIXME: Could be done better. */
1274 result_add_value (&state, "summary", sig->summary);
1276 result_add_fpr (&state, "fpr", sig->fpr);
1277 result_add_error (&state, "status", sig->status);
1278 /* FIXME: notations */
1279 result_add_timestamp (&state, "timestamp", sig->timestamp);
1280 result_add_timestamp (&state, "exp-timestamp", sig->exp_timestamp);
1281 result_add_value (&state, "wrong-key-usage", sig->wrong_key_usage);
1282 result_add_value (&state, "pka-trust", sig->pka_trust);
1283 result_add_value (&state, "chain-model", sig->chain_model);
1284 result_add_value (&state, "validity", sig->validity);
1285 result_add_error (&state, "validity-reason", sig->validity_reason);
1286 result_add_pubkey_algo (&state, "pubkey-algo", sig->pubkey_algo);
1287 result_add_hash_algo (&state, "hash-algo", sig->hash_algo);
1288 if (sig->pka_address)
1289 result_add_string (&state, "pka_address", sig->pka_address);
1291 result_xml_tag_end (&state);
1294 result_xml_tag_end (&state);
1297 result_xml_tag_end (&state);
1304 result_import_to_xml (gpgme_ctx_t ctx, int indent,
1305 result_xml_write_cb_t cb, void *hook)
1307 struct result_xml_state state;
1308 gpgme_import_result_t res = gpgme_op_import_result (ctx);
1309 gpgme_import_status_t stat;
1314 result_init (&state, indent, cb, hook);
1315 result_xml_tag_start (&state, "import-result", NULL);
1317 result_add_value (&state, "considered", res->considered);
1318 result_add_value (&state, "no-user-id", res->no_user_id);
1319 result_add_value (&state, "imported", res->imported);
1320 result_add_value (&state, "imported-rsa", res->imported_rsa);
1321 result_add_value (&state, "unchanged", res->unchanged);
1322 result_add_value (&state, "new-user-ids", res->new_user_ids);
1323 result_add_value (&state, "new-sub-keys", res->new_sub_keys);
1324 result_add_value (&state, "new-signatures", res->new_signatures);
1325 result_add_value (&state, "new-revocations", res->new_revocations);
1326 result_add_value (&state, "secret-read", res->secret_read);
1327 result_add_value (&state, "secret-imported", res->secret_imported);
1328 result_add_value (&state, "secret-unchanged", res->secret_unchanged);
1329 result_add_value (&state, "skipped-new-keys", res->skipped_new_keys);
1330 result_add_value (&state, "not-imported", res->not_imported);
1332 stat = res->imports;
1335 result_xml_tag_start (&state, "imports", NULL);
1339 result_xml_tag_start (&state, "import-status", NULL);
1342 result_add_fpr (&state, "fpr", stat->fpr);
1343 result_add_error (&state, "result", stat->result);
1344 /* FIXME: Could be done better. */
1345 result_add_value (&state, "status", stat->status);
1347 result_xml_tag_end (&state);
1350 result_xml_tag_end (&state);
1353 result_xml_tag_end (&state);
1360 result_genkey_to_xml (gpgme_ctx_t ctx, int indent,
1361 result_xml_write_cb_t cb, void *hook)
1363 struct result_xml_state state;
1364 gpgme_genkey_result_t res = gpgme_op_genkey_result (ctx);
1369 result_init (&state, indent, cb, hook);
1370 result_xml_tag_start (&state, "genkey-result", NULL);
1372 result_add_value (&state, "primary", res->primary);
1373 result_add_value (&state, "sub", res->sub);
1375 result_add_fpr (&state, "fpr", res->fpr);
1377 result_xml_tag_end (&state);
1384 result_keylist_to_xml (gpgme_ctx_t ctx, int indent,
1385 result_xml_write_cb_t cb, void *hook)
1387 struct result_xml_state state;
1388 gpgme_keylist_result_t res = gpgme_op_keylist_result (ctx);
1393 result_init (&state, indent, cb, hook);
1394 result_xml_tag_start (&state, "keylist-result", NULL);
1396 result_add_value (&state, "truncated", res->truncated);
1398 result_xml_tag_end (&state);
1405 result_vfs_mount_to_xml (gpgme_ctx_t ctx, int indent,
1406 result_xml_write_cb_t cb, void *hook)
1408 struct result_xml_state state;
1409 gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (ctx);
1414 result_init (&state, indent, cb, hook);
1415 result_xml_tag_start (&state, "vfs-mount-result", NULL);
1417 result_add_string (&state, "mount-dir", res->mount_dir);
1419 result_xml_tag_end (&state);
1432 STATUS_INCLUDE_CERTS,
1433 STATUS_KEYLIST_MODE,
1435 STATUS_ENCRYPT_RESULT
1438 const char *status_string[] =
1454 #define MAX_RECIPIENTS 10
1455 gpgme_key_t recipients[MAX_RECIPIENTS + 1];
1458 gpg_error_t (*write_status) (void *hook, const char *status, const char *msg);
1459 void *write_status_hook;
1460 gpg_error_t (*write_data) (void *hook, const void *buf, size_t len);
1461 void *write_data_hook;
1463 typedef struct gpgme_tool *gpgme_tool_t;
1466 /* Forward declaration. */
1467 void gt_write_status (gpgme_tool_t gt,
1468 status_t status, ...) GT_GCC_A_SENTINEL(0);
1471 _gt_progress_cb (void *opaque, const char *what,
1472 int type, int current, int total)
1474 gpgme_tool_t gt = opaque;
1477 snprintf (buf, sizeof (buf), "0x%02x %i %i", type, current, total);
1478 gt_write_status (gt, STATUS_PROGRESS, what, buf, NULL);
1483 _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
1487 err = gpgme_new (ctx);
1490 gpgme_set_progress_cb (*ctx, _gt_progress_cb, gt);
1496 gt_init (gpgme_tool_t gt)
1498 memset (gt, '\0', sizeof (*gt));
1501 err = _gt_gpgme_new (gt, >->ctx);
1503 log_error (1, err, "can't create gpgme context");
1508 gt_signers_add (gpgme_tool_t gt, const char *fpr)
1513 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1517 return gpgme_signers_add (gt->ctx, key);
1522 gt_signers_clear (gpgme_tool_t gt)
1524 gpgme_signers_clear (gt->ctx);
1530 gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key)
1533 gpgme_ctx_t listctx;
1537 if (!gt || !r_key || !pattern)
1538 return gpg_error (GPG_ERR_INV_VALUE);
1542 err = gpgme_new (&listctx);
1547 gpgme_protocol_t proto;
1548 gpgme_engine_info_t info;
1550 /* Clone the relevant state. */
1551 proto = gpgme_get_protocol (ctx);
1552 /* The g13 protocol does not allow keylisting, we need to choose
1554 if (proto == GPGME_PROTOCOL_G13)
1555 proto = GPGME_PROTOCOL_OpenPGP;
1557 gpgme_set_protocol (listctx, proto);
1558 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1559 info = gpgme_ctx_get_engine_info (ctx);
1560 while (info && info->protocol != proto)
1563 gpgme_ctx_set_engine_info (listctx, proto,
1564 info->file_name, info->home_dir);
1567 err = gpgme_op_keylist_start (listctx, pattern, 0);
1569 err = gpgme_op_keylist_next (listctx, r_key);
1573 err = gpgme_op_keylist_next (listctx, &key);
1574 if (gpgme_err_code (err) == GPG_ERR_EOF)
1579 && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1580 && key && key->subkeys && key->subkeys->fpr
1581 && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1583 /* The fingerprint is identical. We assume that this is
1584 the same key and don't mark it as an ambiguous. This
1585 problem may occur with corrupted keyrings and has
1586 been noticed often with gpgsm. In fact gpgsm uses a
1587 similar hack to sort out such duplicates but it can't
1588 do that while listing keys. */
1589 gpgme_key_unref (key);
1594 gpgme_key_unref (key);
1595 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1597 gpgme_key_unref (*r_key);
1600 gpgme_release (listctx);
1603 gt_write_status (gt, STATUS_RECIPIENT,
1604 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1605 (*r_key)->subkeys->fpr : "invalid", NULL);
1611 gt_recipients_add (gpgme_tool_t gt, const char *pattern)
1616 if (gt->recipients_nr >= MAX_RECIPIENTS)
1617 return gpg_error_from_errno (ENOMEM);
1619 if (gpgme_get_protocol (gt->ctx) == GPGME_PROTOCOL_UISERVER)
1620 err = gpgme_key_from_uid (&key, pattern);
1622 err = gt_get_key (gt, pattern, &key);
1626 gt->recipients[gt->recipients_nr++] = key;
1632 gt_recipients_clear (gpgme_tool_t gt)
1636 for (idx = 0; idx < gt->recipients_nr; idx++)
1637 gpgme_key_unref (gt->recipients[idx]);
1638 memset (gt->recipients, '\0', gt->recipients_nr * sizeof (gpgme_key_t));
1639 gt->recipients_nr = 0;
1644 gt_reset (gpgme_tool_t gt)
1649 err = _gt_gpgme_new (gt, &ctx);
1653 gpgme_release (gt->ctx);
1655 gt_recipients_clear (gt);
1661 gt_write_status (gpgme_tool_t gt, status_t status, ...)
1670 va_start (ap, status);
1673 while ((text = va_arg (ap, const char *)))
1680 while (*text && n < sizeof (buf) - 2)
1689 err = gt->write_status (gt->write_status_hook, status_string[status], buf);
1691 log_error (1, err, "can't write status line");
1696 gt_write_data (gpgme_tool_t gt, const void *buf, size_t len)
1698 return gt->write_data (gt->write_data_hook, buf, len);
1703 gt_get_engine_info (gpgme_tool_t gt, gpgme_protocol_t proto)
1705 gpgme_engine_info_t info;
1706 info = gpgme_ctx_get_engine_info (gt->ctx);
1709 if (proto == GPGME_PROTOCOL_UNKNOWN || proto == info->protocol)
1710 gt_write_status (gt, STATUS_ENGINE,
1711 gpgme_get_protocol_name (info->protocol),
1712 info->file_name, info->version,
1713 info->req_version, info->home_dir, NULL);
1721 gt_protocol_from_name (const char *name)
1723 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_OpenPGP)))
1724 return GPGME_PROTOCOL_OpenPGP;
1725 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_CMS)))
1726 return GPGME_PROTOCOL_CMS;
1727 if (! strcasecmp (name,gpgme_get_protocol_name (GPGME_PROTOCOL_GPGCONF)))
1728 return GPGME_PROTOCOL_GPGCONF;
1729 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_ASSUAN)))
1730 return GPGME_PROTOCOL_ASSUAN;
1731 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_G13)))
1732 return GPGME_PROTOCOL_G13;
1733 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_UISERVER)))
1734 return GPGME_PROTOCOL_UISERVER;
1735 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_DEFAULT)))
1736 return GPGME_PROTOCOL_DEFAULT;
1737 return GPGME_PROTOCOL_UNKNOWN;
1742 gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1744 return gpgme_set_protocol (gt->ctx, proto);
1749 gt_get_protocol (gpgme_tool_t gt)
1751 gpgme_protocol_t proto = gpgme_get_protocol (gt->ctx);
1753 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1761 gt_set_sub_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1763 return gpgme_set_sub_protocol (gt->ctx, proto);
1768 gt_get_sub_protocol (gpgme_tool_t gt)
1770 gpgme_protocol_t proto = gpgme_get_sub_protocol (gt->ctx);
1772 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1780 gt_set_armor (gpgme_tool_t gt, int armor)
1782 gpgme_set_armor (gt->ctx, armor);
1788 gt_get_armor (gpgme_tool_t gt)
1790 gt_write_status (gt, STATUS_ARMOR,
1791 gpgme_get_armor (gt->ctx) ? "true" : "false", NULL);
1798 gt_set_textmode (gpgme_tool_t gt, int textmode)
1800 gpgme_set_textmode (gt->ctx, textmode);
1806 gt_get_textmode (gpgme_tool_t gt)
1808 gt_write_status (gt, STATUS_TEXTMODE,
1809 gpgme_get_textmode (gt->ctx) ? "true" : "false", NULL);
1816 gt_set_keylist_mode (gpgme_tool_t gt, gpgme_keylist_mode_t keylist_mode)
1818 gpgme_set_keylist_mode (gt->ctx, keylist_mode);
1824 gt_get_keylist_mode (gpgme_tool_t gt)
1826 #define NR_KEYLIST_MODES 6
1827 const char *modes[NR_KEYLIST_MODES + 1];
1829 gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx);
1831 if (mode & GPGME_KEYLIST_MODE_LOCAL)
1832 modes[idx++] = "local";
1833 if (mode & GPGME_KEYLIST_MODE_EXTERN)
1834 modes[idx++] = "extern";
1835 if (mode & GPGME_KEYLIST_MODE_SIGS)
1836 modes[idx++] = "sigs";
1837 if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
1838 modes[idx++] = "sig_notations";
1839 if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
1840 modes[idx++] = "ephemeral";
1841 if (mode & GPGME_KEYLIST_MODE_VALIDATE)
1842 modes[idx++] = "validate";
1843 modes[idx++] = NULL;
1845 gt_write_status (gt, STATUS_KEYLIST_MODE, modes[0], modes[1], modes[2],
1846 modes[3], modes[4], modes[5], modes[6], NULL);
1853 gt_set_include_certs (gpgme_tool_t gt, int include_certs)
1855 gpgme_set_include_certs (gt->ctx, include_certs);
1861 gt_get_include_certs (gpgme_tool_t gt)
1863 int include_certs = gpgme_get_include_certs (gt->ctx);
1866 if (include_certs == GPGME_INCLUDE_CERTS_DEFAULT)
1867 strcpy (buf, "default");
1869 snprintf (buf, sizeof (buf), "%i", include_certs);
1871 gt_write_status (gt, STATUS_INCLUDE_CERTS, buf, NULL);
1878 gt_decrypt_verify (gpgme_tool_t gt, gpgme_data_t cipher, gpgme_data_t plain,
1882 return gpgme_op_decrypt_verify (gt->ctx, cipher, plain);
1884 return gpgme_op_decrypt (gt->ctx, cipher, plain);
1889 gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
1890 gpgme_data_t plain, gpgme_data_t cipher, int sign)
1895 err = gpgme_op_encrypt_sign (gt->ctx, gt->recipients, flags, plain, cipher);
1897 err = gpgme_op_encrypt (gt->ctx, gt->recipients, flags, plain, cipher);
1899 gt_recipients_clear (gt);
1906 gt_sign (gpgme_tool_t gt, gpgme_data_t plain, gpgme_data_t sig,
1907 gpgme_sig_mode_t mode)
1909 return gpgme_op_sign (gt->ctx, plain, sig, mode);
1914 gt_verify (gpgme_tool_t gt, gpgme_data_t sig, gpgme_data_t sig_text,
1917 return gpgme_op_verify (gt->ctx, sig, sig_text, plain);
1922 gt_import (gpgme_tool_t gt, gpgme_data_t data)
1924 return gpgme_op_import (gt->ctx, data);
1929 gt_export (gpgme_tool_t gt, const char *pattern[], gpgme_export_mode_t mode,
1932 return gpgme_op_export_ext (gt->ctx, pattern, mode, data);
1937 gt_genkey (gpgme_tool_t gt, const char *parms, gpgme_data_t public,
1938 gpgme_data_t secret)
1940 return gpgme_op_genkey (gt->ctx, parms, public, secret);
1945 gt_import_keys (gpgme_tool_t gt, char *fpr[])
1947 gpg_error_t err = 0;
1957 return gpg_error (GPG_ERR_INV_VALUE);
1959 keys = malloc ((cnt + 1) * sizeof (gpgme_key_t));
1961 return gpg_error_from_syserror ();
1963 for (idx = 0; idx < cnt; idx++)
1965 err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0);
1972 err = gpgme_op_import_keys (gt->ctx, keys);
1977 gpgme_key_unref (keys[idx]);
1985 gt_delete (gpgme_tool_t gt, char *fpr, int allow_secret)
1990 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1994 err = gpgme_op_delete (gt->ctx, key, allow_secret);
1995 gpgme_key_unref (key);
2001 gt_keylist_start (gpgme_tool_t gt, const char *pattern[], int secret_only)
2003 return gpgme_op_keylist_ext_start (gt->ctx, pattern, secret_only, 0);
2008 gt_keylist_next (gpgme_tool_t gt, gpgme_key_t *key)
2010 return gpgme_op_keylist_next (gt->ctx, key);
2015 gt_getauditlog (gpgme_tool_t gt, gpgme_data_t output, unsigned int flags)
2017 return gpgme_op_getauditlog (gt->ctx, output, flags);
2022 gt_vfs_mount (gpgme_tool_t gt, const char *container_file,
2023 const char *mount_dir, int flags)
2027 err = gpgme_op_vfs_mount (gt->ctx, container_file, mount_dir, flags, &op_err);
2028 return err ? err : op_err;
2033 gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
2037 err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file,
2039 gt_recipients_clear (gt);
2040 return err ? err : op_err;
2044 static const char hlp_passwd[] =
2045 "PASSWD <user-id>\n"
2047 "Ask the backend to change the passphrase for the key\n"
2048 "specified by USER-ID.";
2050 gt_passwd (gpgme_tool_t gt, char *fpr)
2055 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
2057 return gpg_err_code (err) == GPG_ERR_EOF? gpg_error (GPG_ERR_NO_PUBKEY):err;
2059 err = gpgme_op_passwd (gt->ctx, key, 0);
2060 gpgme_key_unref (key);
2065 #define GT_RESULT_ENCRYPT 0x1
2066 #define GT_RESULT_DECRYPT 0x2
2067 #define GT_RESULT_SIGN 0x4
2068 #define GT_RESULT_VERIFY 0x8
2069 #define GT_RESULT_IMPORT 0x10
2070 #define GT_RESULT_GENKEY 0x20
2071 #define GT_RESULT_KEYLIST 0x40
2072 #define GT_RESULT_VFS_MOUNT 0x80
2073 #define GT_RESULT_ALL (~0U)
2076 gt_result (gpgme_tool_t gt, unsigned int flags)
2080 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
2081 gt_write_data (gt, NULL, 0);
2082 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
2083 gt_write_data (gt, NULL, 0);
2084 if (flags & GT_RESULT_ENCRYPT)
2085 result_encrypt_to_xml (gt->ctx, indent,
2086 (result_xml_write_cb_t) gt_write_data, gt);
2087 if (flags & GT_RESULT_DECRYPT)
2088 result_decrypt_to_xml (gt->ctx, indent,
2089 (result_xml_write_cb_t) gt_write_data, gt);
2090 if (flags & GT_RESULT_SIGN)
2091 result_sign_to_xml (gt->ctx, indent,
2092 (result_xml_write_cb_t) gt_write_data, gt);
2093 if (flags & GT_RESULT_VERIFY)
2094 result_verify_to_xml (gt->ctx, indent,
2095 (result_xml_write_cb_t) gt_write_data, gt);
2096 if (flags & GT_RESULT_IMPORT)
2097 result_import_to_xml (gt->ctx, indent,
2098 (result_xml_write_cb_t) gt_write_data, gt);
2099 if (flags & GT_RESULT_GENKEY)
2100 result_genkey_to_xml (gt->ctx, indent,
2101 (result_xml_write_cb_t) gt_write_data, gt);
2102 if (flags & GT_RESULT_KEYLIST)
2103 result_keylist_to_xml (gt->ctx, indent,
2104 (result_xml_write_cb_t) gt_write_data, gt);
2105 if (flags & GT_RESULT_VFS_MOUNT)
2106 result_vfs_mount_to_xml (gt->ctx, indent,
2107 (result_xml_write_cb_t) gt_write_data, gt);
2108 gt_write_data (gt, xml_end, sizeof (xml_end));
2121 assuan_context_t assuan_ctx;
2123 gpgme_data_encoding_t input_enc;
2124 gpgme_data_encoding_t output_enc;
2125 assuan_fd_t input_fd;
2126 char *input_filename;
2128 assuan_fd_t output_fd;
2129 char *output_filename;
2130 FILE *output_stream;
2131 assuan_fd_t message_fd;
2132 char *message_filename;
2133 FILE *message_stream;
2134 gpgme_data_encoding_t message_enc;
2139 server_write_status (void *hook, const char *status, const char *msg)
2141 struct server *server = hook;
2142 return assuan_write_status (server->assuan_ctx, status, msg);
2147 server_write_data (void *hook, const void *buf, size_t len)
2149 struct server *server = hook;
2150 return assuan_send_data (server->assuan_ctx, buf, len);
2154 /* Wrapper around assuan_command_parse_fd to also handle a
2155 "file=FILENAME" argument. On success either a filename is returned
2156 at FILENAME or a file descriptor at RFD; the other one is set to
2157 NULL respective ASSUAN_INVALID_FD. */
2159 server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd,
2162 *rfd = ASSUAN_INVALID_FD;
2165 if (! strncasecmp (line, "file=", 5))
2168 *filename = strdup (line + 5);
2170 return gpg_error_from_syserror();
2171 term = strchr (*filename, ' ');
2177 return assuan_command_parse_fd (ctx, line, rfd);
2181 static gpgme_data_encoding_t
2182 server_data_encoding (const char *line)
2184 if (strstr (line, "--binary"))
2185 return GPGME_DATA_ENCODING_BINARY;
2186 if (strstr (line, "--base64"))
2187 return GPGME_DATA_ENCODING_BASE64;
2188 if (strstr (line, "--armor"))
2189 return GPGME_DATA_ENCODING_ARMOR;
2190 if (strstr (line, "--url"))
2191 return GPGME_DATA_ENCODING_URL;
2192 if (strstr (line, "--urlesc"))
2193 return GPGME_DATA_ENCODING_URLESC;
2194 if (strstr (line, "--url0"))
2195 return GPGME_DATA_ENCODING_URL0;
2196 return GPGME_DATA_ENCODING_NONE;
2200 static gpgme_error_t
2201 server_data_obj (assuan_fd_t fd, char *fn, int out,
2202 gpgme_data_encoding_t encoding,
2203 gpgme_data_t *data, FILE **fs)
2210 *fs = fopen (fn, out ? "wb" : "rb");
2212 return gpg_error_from_syserror ();
2214 err = gpgme_data_new_from_stream (data, *fs);
2217 err = gpgme_data_new_from_fd (data, (int) fd);
2221 return gpgme_data_set_encoding (*data, encoding);
2226 server_reset_fds (struct server *server)
2228 /* assuan closes the input and output FDs for us when doing a RESET,
2229 but we use this same function after commands, so repeat it
2231 if (server->input_fd != ASSUAN_INVALID_FD)
2234 CloseHandle (server->input_fd);
2236 close (server->input_fd);
2238 server->input_fd = ASSUAN_INVALID_FD;
2240 if (server->output_fd != ASSUAN_INVALID_FD)
2243 CloseHandle (server->output_fd);
2245 close (server->output_fd);
2247 server->output_fd = ASSUAN_INVALID_FD;
2249 if (server->message_fd != ASSUAN_INVALID_FD)
2251 /* FIXME: Assuan should provide a close function. */
2253 CloseHandle (server->message_fd);
2255 close (server->message_fd);
2257 server->message_fd = ASSUAN_INVALID_FD;
2259 if (server->input_filename)
2261 free (server->input_filename);
2262 server->input_filename = NULL;
2264 if (server->output_filename)
2266 free (server->output_filename);
2267 server->output_filename = NULL;
2269 if (server->message_filename)
2271 free (server->message_filename);
2272 server->message_filename = NULL;
2274 if (server->input_stream)
2276 fclose (server->input_stream);
2277 server->input_stream = NULL;
2279 if (server->output_stream)
2281 fclose (server->output_stream);
2282 server->output_stream = NULL;
2284 if (server->message_stream)
2286 fclose (server->message_stream);
2287 server->message_stream = NULL;
2290 server->input_enc = GPGME_DATA_ENCODING_NONE;
2291 server->output_enc = GPGME_DATA_ENCODING_NONE;
2292 server->message_enc = GPGME_DATA_ENCODING_NONE;
2297 reset_notify (assuan_context_t ctx, char *line)
2299 struct server *server = assuan_get_pointer (ctx);
2300 server_reset_fds (server);
2301 gt_reset (server->gt);
2306 static const char hlp_version[] =
2307 "VERSION [<string>]\n"
2309 "Call the function gpgme_check_version.";
2311 cmd_version (assuan_context_t ctx, char *line)
2315 const char *version = gpgme_check_version (line);
2316 return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
2320 const char *version = gpgme_check_version (NULL);
2321 return assuan_send_data (ctx, version, strlen (version));
2326 static const char hlp_engine[] =
2327 "ENGINE [<string>]\n"
2329 "Get information about a GPGME engine (a.k.a. protocol).";
2331 cmd_engine (assuan_context_t ctx, char *line)
2333 struct server *server = assuan_get_pointer (ctx);
2334 return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
2338 static const char hlp_protocol[] =
2339 "PROTOCOL [<name>]\n"
2341 "With NAME, set the protocol. Without, return the current\n"
2344 cmd_protocol (assuan_context_t ctx, char *line)
2346 struct server *server = assuan_get_pointer (ctx);
2348 return gt_set_protocol (server->gt, gt_protocol_from_name (line));
2350 return gt_get_protocol (server->gt);
2354 static const char hlp_sub_protocol[] =
2355 "SUB_PROTOCOL [<name>]\n"
2357 "With NAME, set the sub-protocol. Without, return the\n"
2358 "current sub-protocol.";
2360 cmd_sub_protocol (assuan_context_t ctx, char *line)
2362 struct server *server = assuan_get_pointer (ctx);
2364 return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
2366 return gt_get_sub_protocol (server->gt);
2370 static const char hlp_armor[] =
2371 "ARMOR [true|false]\n"
2373 "With 'true' or 'false', turn output ASCII armoring on or\n"
2374 "off. Without, return the current armoring status.";
2376 cmd_armor (assuan_context_t ctx, char *line)
2378 struct server *server = assuan_get_pointer (ctx);
2383 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2387 return gt_set_armor (server->gt, flag);
2390 return gt_get_armor (server->gt);
2394 static const char hlp_textmode[] =
2395 "TEXTMODE [true|false]\n"
2397 "With 'true' or 'false', turn text mode on or off.\n"
2398 "Without, return the current text mode status.";
2400 cmd_textmode (assuan_context_t ctx, char *line)
2402 struct server *server = assuan_get_pointer (ctx);
2407 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2411 return gt_set_textmode (server->gt, flag);
2414 return gt_get_textmode (server->gt);
2418 static const char hlp_include_certs[] =
2419 "INCLUDE_CERTS [default|<n>]\n"
2421 "With DEFAULT or N, set how many certificates should be\n"
2422 "included in the next S/MIME signed message. See the\n"
2423 "GPGME documentation for details on the meaning of"
2424 "various N. Without either, return the current setting.";
2426 cmd_include_certs (assuan_context_t ctx, char *line)
2428 struct server *server = assuan_get_pointer (ctx);
2432 int include_certs = 0;
2434 if (! strcasecmp (line, "default"))
2435 include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
2437 include_certs = atoi (line);
2439 return gt_set_include_certs (server->gt, include_certs);
2442 return gt_get_include_certs (server->gt);
2446 static const char hlp_keylist_mode[] =
2447 "KEYLIST_MODE [local] [extern] [sigs] [sig_notations]\n"
2448 " [ephemeral] [validate]\n"
2450 "Set the mode for the next KEYLIST command.";
2452 cmd_keylist_mode (assuan_context_t ctx, char *line)
2454 struct server *server = assuan_get_pointer (ctx);
2458 gpgme_keylist_mode_t mode = 0;
2460 if (strstr (line, "local"))
2461 mode |= GPGME_KEYLIST_MODE_LOCAL;
2462 if (strstr (line, "extern"))
2463 mode |= GPGME_KEYLIST_MODE_EXTERN;
2464 if (strstr (line, "sigs"))
2465 mode |= GPGME_KEYLIST_MODE_SIGS;
2466 if (strstr (line, "sig_notations"))
2467 mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
2468 if (strstr (line, "ephemeral"))
2469 mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
2470 if (strstr (line, "validate"))
2471 mode |= GPGME_KEYLIST_MODE_VALIDATE;
2473 return gt_set_keylist_mode (server->gt, mode);
2476 return gt_get_keylist_mode (server->gt);
2480 static const char hlp_input[] =
2481 "INPUT [<fd>|FILE=<path>]\n"
2483 "Set the input for the next command. Use either the\n"
2484 "Assuan file descriptor FD or a filesystem PATH.";
2486 cmd_input (assuan_context_t ctx, char *line)
2488 struct server *server = assuan_get_pointer (ctx);
2493 err = server_parse_fd (ctx, line, &sysfd, &filename);
2496 server->input_fd = sysfd;
2497 server->input_filename = filename;
2498 server->input_enc = server_data_encoding (line);
2503 static const char hlp_output[] =
2504 "OUTPUT [<fd>|FILE=<path>]\n"
2506 "Set the output for the next command. Use either the\n"
2507 "Assuan file descriptor FD or a filesystem PATH.";
2509 cmd_output (assuan_context_t ctx, char *line)
2511 struct server *server = assuan_get_pointer (ctx);
2516 err = server_parse_fd (ctx, line, &sysfd, &filename);
2519 server->output_fd = sysfd;
2520 server->output_filename = filename;
2521 server->output_enc = server_data_encoding (line);
2526 static const char hlp_message[] =
2527 "MESSAGE [<fd>|FILE=<path>]\n"
2529 "Set the plaintext message for the next VERIFY command\n"
2530 "with a detached signature. Use either the Assuan file\n"
2531 "descriptor FD or a filesystem PATH.";
2533 cmd_message (assuan_context_t ctx, char *line)
2535 struct server *server = assuan_get_pointer (ctx);
2540 err = server_parse_fd (ctx, line, &sysfd, &filename);
2543 server->message_fd = sysfd;
2544 server->message_filename = filename;
2545 server->message_enc = server_data_encoding (line);
2550 static const char hlp_recipient[] =
2551 "RECIPIENT <pattern>\n"
2553 "Add the key matching PATTERN to the list of recipients\n"
2554 "for the next encryption command.";
2556 cmd_recipient (assuan_context_t ctx, char *line)
2558 struct server *server = assuan_get_pointer (ctx);
2560 return gt_recipients_add (server->gt, line);
2564 static const char hlp_signer[] =
2565 "SIGNER <fingerprint>\n"
2567 "Add the key with FINGERPRINT to the list of signers to\n"
2568 "be used for the next signing command.";
2570 cmd_signer (assuan_context_t ctx, char *line)
2572 struct server *server = assuan_get_pointer (ctx);
2574 return gt_signers_add (server->gt, line);
2578 static const char hlp_signers_clear[] =
2581 "Clear the list of signers specified by previous SIGNER\n"
2584 cmd_signers_clear (assuan_context_t ctx, char *line)
2586 struct server *server = assuan_get_pointer (ctx);
2588 return gt_signers_clear (server->gt);
2593 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
2595 struct server *server = assuan_get_pointer (ctx);
2601 gpgme_data_t inp_data;
2602 gpgme_data_t out_data;
2604 inp_fd = server->input_fd;
2605 inp_fn = server->input_filename;
2606 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2607 return GPG_ERR_ASS_NO_INPUT;
2608 out_fd = server->output_fd;
2609 out_fn = server->output_filename;
2610 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2611 return GPG_ERR_ASS_NO_OUTPUT;
2613 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2614 &server->input_stream);
2617 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2618 &server->output_stream);
2621 gpgme_data_release (inp_data);
2625 err = gt_decrypt_verify (server->gt, inp_data, out_data, verify);
2627 gpgme_data_release (inp_data);
2628 gpgme_data_release (out_data);
2630 server_reset_fds (server);
2636 static const char hlp_decrypt[] =
2639 "Decrypt the object set by the last INPUT command and\n"
2640 "write the decrypted message to the object set by the\n"
2641 "last OUTPUT command.";
2643 cmd_decrypt (assuan_context_t ctx, char *line)
2645 return _cmd_decrypt_verify (ctx, line, 0);
2649 static const char hlp_decrypt_verify[] =
2652 "Decrypt the object set by the last INPUT command and\n"
2653 "verify any embedded signatures. Write the decrypted\n"
2654 "message to the object set by the last OUTPUT command.";
2656 cmd_decrypt_verify (assuan_context_t ctx, char *line)
2658 return _cmd_decrypt_verify (ctx, line, 1);
2663 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
2665 struct server *server = assuan_get_pointer (ctx);
2671 gpgme_data_t inp_data = NULL;
2672 gpgme_data_t out_data = NULL;
2673 gpgme_encrypt_flags_t flags = 0;
2675 if (strstr (line, "--always-trust"))
2676 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
2677 if (strstr (line, "--no-encrypt-to"))
2678 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
2679 if (strstr (line, "--prepare"))
2680 flags |= GPGME_ENCRYPT_PREPARE;
2681 if (strstr (line, "--expect-sign"))
2682 flags |= GPGME_ENCRYPT_EXPECT_SIGN;
2684 inp_fd = server->input_fd;
2685 inp_fn = server->input_filename;
2686 out_fd = server->output_fd;
2687 out_fn = server->output_filename;
2688 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
2690 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2691 &server->input_stream);
2695 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2697 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2698 &server->output_stream);
2701 gpgme_data_release (inp_data);
2706 err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign);
2708 gpgme_data_release (inp_data);
2709 gpgme_data_release (out_data);
2711 server_reset_fds (server);
2717 static const char hlp_encrypt[] =
2718 "ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2719 " [--prepare] [--expect-sign]\n"
2721 "Encrypt the object set by the last INPUT command to\n"
2722 "the keys specified by previous RECIPIENT commands. \n"
2723 "Write the signed and encrypted message to the object\n"
2724 "set by the last OUTPUT command.";
2726 cmd_encrypt (assuan_context_t ctx, char *line)
2728 return _cmd_sign_encrypt (ctx, line, 0);
2732 static const char hlp_sign_encrypt[] =
2733 "SIGN_ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2734 " [--prepare] [--expect-sign]\n"
2736 "Sign the object set by the last INPUT command with the\n"
2737 "keys specified by previous SIGNER commands and encrypt\n"
2738 "it to the keys specified by previous RECIPIENT\n"
2739 "commands. Write the signed and encrypted message to\n"
2740 "the object set by the last OUTPUT command.";
2742 cmd_sign_encrypt (assuan_context_t ctx, char *line)
2744 return _cmd_sign_encrypt (ctx, line, 1);
2748 static const char hlp_sign[] =
2749 "SIGN [--clear|--detach]\n"
2751 "Sign the object set by the last INPUT command with the\n"
2752 "keys specified by previous SIGNER commands. Write the\n"
2753 "signed message to the object set by the last OUTPUT\n"
2754 "command. With `--clear`, generate a clear text\n"
2755 "signature. With `--detach`, generate a detached\n"
2758 cmd_sign (assuan_context_t ctx, char *line)
2760 struct server *server = assuan_get_pointer (ctx);
2766 gpgme_data_t inp_data;
2767 gpgme_data_t out_data;
2768 gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
2770 if (strstr (line, "--clear"))
2771 mode = GPGME_SIG_MODE_CLEAR;
2772 if (strstr (line, "--detach"))
2773 mode = GPGME_SIG_MODE_DETACH;
2775 inp_fd = server->input_fd;
2776 inp_fn = server->input_filename;
2777 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2778 return GPG_ERR_ASS_NO_INPUT;
2779 out_fd = server->output_fd;
2780 out_fn = server->output_filename;
2781 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2782 return GPG_ERR_ASS_NO_OUTPUT;
2784 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2785 &server->input_stream);
2788 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2789 &server->output_stream);
2792 gpgme_data_release (inp_data);
2796 err = gt_sign (server->gt, inp_data, out_data, mode);
2798 gpgme_data_release (inp_data);
2799 gpgme_data_release (out_data);
2800 server_reset_fds (server);
2806 static const char hlp_verify[] =
2809 "Verify signatures on the object set by the last INPUT\n"
2810 "and MESSAGE commands. If the message was encrypted,\n"
2811 "write the plaintext to the object set by the last\n"
2814 cmd_verify (assuan_context_t ctx, char *line)
2816 struct server *server = assuan_get_pointer (ctx);
2824 gpgme_data_t inp_data;
2825 gpgme_data_t msg_data = NULL;
2826 gpgme_data_t out_data = NULL;
2828 inp_fd = server->input_fd;
2829 inp_fn = server->input_filename;
2830 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2831 return GPG_ERR_ASS_NO_INPUT;
2832 msg_fd = server->message_fd;
2833 msg_fn = server->message_filename;
2834 out_fd = server->output_fd;
2835 out_fn = server->output_filename;
2837 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2838 &server->input_stream);
2841 if (msg_fd != ASSUAN_INVALID_FD || msg_fn)
2843 err = server_data_obj (msg_fd, msg_fn, 0, server->message_enc, &msg_data,
2844 &server->message_stream);
2847 gpgme_data_release (inp_data);
2851 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2853 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2854 &server->output_stream);
2857 gpgme_data_release (inp_data);
2858 gpgme_data_release (msg_data);
2863 err = gt_verify (server->gt, inp_data, msg_data, out_data);
2865 gpgme_data_release (inp_data);
2867 gpgme_data_release (msg_data);
2869 gpgme_data_release (out_data);
2871 server_reset_fds (server);
2877 static const char hlp_import[] =
2878 "IMPORT [<pattern>]\n"
2880 "With PATTERN, import the keys described by PATTERN.\n"
2881 "Without, read a key (or keys) from the object set by the\n"
2882 "last INPUT command.";
2884 cmd_import (assuan_context_t ctx, char *line)
2886 struct server *server = assuan_get_pointer (ctx);
2890 char *fprs[2] = { line, NULL };
2892 return gt_import_keys (server->gt, fprs);
2899 gpgme_data_t inp_data;
2901 inp_fd = server->input_fd;
2902 inp_fn = server->input_filename;
2903 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2904 return GPG_ERR_ASS_NO_INPUT;
2906 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2907 &server->input_stream);
2911 err = gt_import (server->gt, inp_data);
2913 gpgme_data_release (inp_data);
2914 server_reset_fds (server);
2921 static const char hlp_export[] =
2922 "EXPORT [--extern] [--minimal] [<pattern>]\n"
2924 "Export the keys described by PATTERN. Write the\n"
2925 "the output to the object set by the last OUTPUT command.";
2927 cmd_export (assuan_context_t ctx, char *line)
2929 struct server *server = assuan_get_pointer (ctx);
2933 gpgme_data_t out_data;
2934 gpgme_export_mode_t mode = 0;
2935 const char *pattern[2];
2937 out_fd = server->output_fd;
2938 out_fn = server->output_filename;
2939 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2940 return GPG_ERR_ASS_NO_OUTPUT;
2941 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2942 &server->output_stream);
2946 if (has_option (line, "--extern"))
2947 mode |= GPGME_EXPORT_MODE_EXTERN;
2948 if (has_option (line, "--minimal"))
2949 mode |= GPGME_EXPORT_MODE_MINIMAL;
2951 line = skip_options (line);
2956 err = gt_export (server->gt, pattern, mode, out_data);
2958 gpgme_data_release (out_data);
2959 server_reset_fds (server);
2966 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
2970 ssize_t writen = gpgme_data_write (data, buf, size);
2971 if (writen < 0 && errno != EAGAIN)
2972 return gpg_error_from_syserror ();
2973 else if (writen > 0)
2975 buf = (void *) (((char *) buf) + writen);
2984 cmd_genkey (assuan_context_t ctx, char *line)
2986 struct server *server = assuan_get_pointer (ctx);
2992 gpgme_data_t inp_data;
2993 gpgme_data_t out_data = NULL;
2994 gpgme_data_t parms_data = NULL;
2997 inp_fd = server->input_fd;
2998 inp_fn = server->input_filename;
2999 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
3000 return GPG_ERR_ASS_NO_INPUT;
3001 out_fd = server->output_fd;
3002 out_fn = server->output_filename;
3004 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
3005 &server->input_stream);
3008 if (out_fd != ASSUAN_INVALID_FD || out_fn)
3010 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
3011 &server->output_stream);
3014 gpgme_data_release (inp_data);
3019 /* Convert input data. */
3020 err = gpgme_data_new (&parms_data);
3026 ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
3029 err = gpg_error_from_syserror ();
3032 else if (readn == 0)
3035 err = _cmd_genkey_write (parms_data, buf, readn);
3040 err = _cmd_genkey_write (parms_data, "", 1);
3043 parms = gpgme_data_release_and_get_mem (parms_data, NULL);
3047 err = gpg_error (GPG_ERR_GENERAL);
3051 err = gt_genkey (server->gt, parms, out_data, NULL);
3053 server_reset_fds (server);
3056 gpgme_data_release (inp_data);
3058 gpgme_data_release (out_data);
3060 gpgme_data_release (parms_data);
3067 cmd_delete (assuan_context_t ctx, char *line)
3069 struct server *server = assuan_get_pointer (ctx);
3070 int allow_secret = 0;
3071 const char optstr[] = "--allow-secret";
3073 if (!strncasecmp (line, optstr, strlen (optstr)))
3076 line += strlen (optstr);
3077 while (*line && !spacep (line))
3080 return gt_delete (server->gt, line, allow_secret);
3084 static const char hlp_keylist[] =
3085 "KEYLIST [--secret-only] [<patterns>]\n"
3087 "List all certificates or only those specified by PATTERNS. Each\n"
3088 "pattern shall be a percent-plus escaped certificate specification.";
3090 cmd_keylist (assuan_context_t ctx, char *line)
3092 #define MAX_CMD_KEYLIST_PATTERN 20
3093 struct server *server = assuan_get_pointer (ctx);
3094 gpgme_tool_t gt = server->gt;
3095 struct result_xml_state state;
3097 int secret_only = 0;
3099 const char *pattern[MAX_CMD_KEYLIST_PATTERN+1];
3100 const char optstr[] = "--secret-only";
3103 if (!strncasecmp (line, optstr, strlen (optstr)))
3106 line += strlen (optstr);
3107 while (*line && !spacep (line))
3112 for (p=line; *p; line = p)
3114 while (*p && *p != ' ')
3120 if (idx+1 == DIM (pattern))
3121 return gpg_error (GPG_ERR_TOO_MANY);
3122 strcpy_escaped_plus (line, line);
3123 pattern[idx++] = line;
3126 pattern[idx] = NULL;
3128 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
3129 gt_write_data (gt, NULL, 0);
3130 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
3131 gt_write_data (gt, NULL, 0);
3132 result_init (&state, indent, (result_xml_write_cb_t) gt_write_data, gt);
3133 result_xml_tag_start (&state, "keylist", NULL);
3135 err = gt_keylist_start (server->gt, pattern, secret_only);
3139 gpgme_subkey_t subkey;
3140 gpgme_user_id_t uid;
3142 err = gt_keylist_next (server->gt, &key);
3143 if (gpg_err_code (err) == GPG_ERR_EOF)
3150 result_xml_tag_start (&state, "key", NULL);
3151 result_add_value (&state, "revoked", key->revoked);
3152 result_add_value (&state, "expired", key->expired);
3153 result_add_value (&state, "disabled", key->disabled);
3154 result_add_value (&state, "invalid", key->invalid);
3155 result_add_value (&state, "can-encrypt", key->can_encrypt);
3156 result_add_value (&state, "can-sign", key->can_sign);
3157 result_add_value (&state, "can-certify", key->can_certify);
3158 result_add_value (&state, "can-authenticate", key->can_authenticate);
3159 result_add_value (&state, "is-qualified", key->is_qualified);
3160 result_add_value (&state, "secret", key->secret);
3161 result_add_protocol (&state, "protocol", key->protocol);
3162 result_xml_tag_start (&state, "issuer", NULL);
3163 result_add_string (&state, "serial", key->issuer_serial);
3164 result_add_string (&state, "name", key->issuer_name);
3165 result_xml_tag_end (&state); /* issuer */
3166 result_add_string (&state, "chain-id", key->chain_id);
3167 result_add_validity (&state, "owner-trust", key->owner_trust);
3168 result_xml_tag_start (&state, "subkeys", NULL);
3169 subkey = key->subkeys;
3171 result_xml_tag_start (&state, "subkey", NULL);
3172 /* FIXME: more data */
3173 result_add_fpr (&state, "fpr", subkey->fpr);
3174 result_xml_tag_end (&state); /* subkey */
3175 subkey = subkey->next;
3177 result_xml_tag_end (&state); /* subkeys */
3178 result_xml_tag_start (&state, "uids", NULL);
3181 result_xml_tag_start (&state, "uid", NULL);
3182 /* FIXME: more data */
3183 result_add_string (&state, "uid", uid->uid);
3184 result_add_string (&state, "name", uid->name);
3185 result_add_string (&state, "email", uid->email);
3186 result_add_string (&state, "comment", uid->comment);
3187 result_xml_tag_end (&state); /* uid */
3190 result_xml_tag_end (&state); /* uids */
3191 result_xml_tag_end (&state); /* key */
3192 gpgme_key_unref (key);
3196 result_xml_tag_end (&state); /* keylist */
3197 gt_write_data (gt, xml_end, sizeof (xml_end));
3199 server_reset_fds (server);
3205 static const char hlp_getauditlog[] =
3206 "GETAUDITLOG [--html] [--with-help]\n"
3208 "Call the function gpgme_op_getauditlog with the given flags. Write\n"
3209 "the output to the object set by the last OUTPUT command.";
3211 cmd_getauditlog (assuan_context_t ctx, char *line)
3213 struct server *server = assuan_get_pointer (ctx);
3217 gpgme_data_t out_data;
3218 unsigned int flags = 0;
3220 out_fd = server->output_fd;
3221 out_fn = server->output_filename;
3222 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
3223 return GPG_ERR_ASS_NO_OUTPUT;
3224 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
3225 &server->output_stream);
3229 if (strstr (line, "--html"))
3230 flags |= GPGME_AUDITLOG_HTML;
3231 if (strstr (line, "--with-help"))
3232 flags |= GPGME_AUDITLOG_WITH_HELP;
3234 err = gt_getauditlog (server->gt, out_data, flags);
3236 gpgme_data_release (out_data);
3237 server_reset_fds (server);
3244 cmd_vfs_mount (assuan_context_t ctx, char *line)
3246 struct server *server = assuan_get_pointer (ctx);
3250 mount_dir = strchr (line, ' ');
3253 *(mount_dir++) = '\0';
3254 while (*mount_dir == ' ')
3258 err = gt_vfs_mount (server->gt, line, mount_dir, 0);
3265 cmd_vfs_create (assuan_context_t ctx, char *line)
3267 struct server *server = assuan_get_pointer (ctx);
3271 end = strchr (line, ' ');
3279 err = gt_vfs_create (server->gt, line, 0);
3286 cmd_passwd (assuan_context_t ctx, char *line)
3288 struct server *server = assuan_get_pointer (ctx);
3290 return gt_passwd (server->gt, line);
3296 cmd_result (assuan_context_t ctx, char *line)
3298 struct server *server = assuan_get_pointer (ctx);
3299 return gt_result (server->gt, GT_RESULT_ALL);
3303 /* STRERROR <err> */
3305 cmd_strerror (assuan_context_t ctx, char *line)
3311 snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
3312 gpgme_strsource (err));
3313 return assuan_send_data (ctx, buf, strlen (buf));
3318 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
3320 gpgme_pubkey_algo_t algo;
3324 snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
3325 return assuan_send_data (ctx, buf, strlen (buf));
3330 cmd_hash_algo_name (assuan_context_t ctx, char *line)
3332 gpgme_hash_algo_t algo;
3336 snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
3337 return assuan_send_data (ctx, buf, strlen (buf));
3341 /* Tell the assuan library about our commands. */
3343 register_commands (assuan_context_t ctx)
3348 assuan_handler_t handler;
3349 const char * const help;
3351 /* RESET, BYE are implicit. */
3352 { "VERSION", cmd_version, hlp_version },
3353 /* TODO: Set engine info. */
3354 { "ENGINE", cmd_engine, hlp_engine },
3355 { "PROTOCOL", cmd_protocol, hlp_protocol },
3356 { "SUB_PROTOCOL", cmd_sub_protocol, hlp_sub_protocol },
3357 { "ARMOR", cmd_armor, hlp_armor },
3358 { "TEXTMODE", cmd_textmode, hlp_textmode },
3359 { "INCLUDE_CERTS", cmd_include_certs, hlp_include_certs },
3360 { "KEYLIST_MODE", cmd_keylist_mode, hlp_keylist_mode },
3361 { "INPUT", cmd_input, hlp_input },
3362 { "OUTPUT", cmd_output, hlp_output },
3363 { "MESSAGE", cmd_message, hlp_message },
3364 { "RECIPIENT", cmd_recipient, hlp_recipient },
3365 { "SIGNER", cmd_signer, hlp_signer },
3366 { "SIGNERS_CLEAR", cmd_signers_clear, hlp_signers_clear },
3367 /* TODO: SIGNOTATION missing. */
3368 /* TODO: Could add wait interface if we allow more than one context */
3369 /* and add _START variants. */
3370 /* TODO: Could add data interfaces if we allow multiple data objects. */
3371 { "DECRYPT", cmd_decrypt, hlp_decrypt },
3372 { "DECRYPT_VERIFY", cmd_decrypt_verify, hlp_decrypt_verify },
3373 { "ENCRYPT", cmd_encrypt, hlp_encrypt },
3374 { "ENCRYPT_SIGN", cmd_sign_encrypt, hlp_sign_encrypt },
3375 { "SIGN_ENCRYPT", cmd_sign_encrypt, hlp_sign_encrypt },
3376 { "SIGN", cmd_sign, hlp_sign },
3377 { "VERIFY", cmd_verify, hlp_verify },
3378 { "IMPORT", cmd_import, hlp_import },
3379 { "EXPORT", cmd_export, hlp_export },
3380 { "GENKEY", cmd_genkey },
3381 { "DELETE", cmd_delete },
3382 /* TODO: EDIT, CARD_EDIT (with INQUIRE) */
3383 { "KEYLIST", cmd_keylist, hlp_keylist },
3384 { "LISTKEYS", cmd_keylist, hlp_keylist },
3385 /* TODO: TRUSTLIST, TRUSTLIST_EXT */
3386 { "GETAUDITLOG", cmd_getauditlog, hlp_getauditlog },
3388 { "VFS_MOUNT", cmd_vfs_mount },
3389 { "MOUNT", cmd_vfs_mount },
3390 { "VFS_CREATE", cmd_vfs_create },
3391 { "CREATE", cmd_vfs_create },
3393 { "RESULT", cmd_result },
3394 { "STRERROR", cmd_strerror },
3395 { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
3396 { "HASH_ALGO_NAME", cmd_hash_algo_name },
3397 { "PASSWD", cmd_passwd, hlp_passwd },
3402 for (idx = 0; table[idx].name; idx++)
3404 err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
3413 /* TODO: password callback can do INQUIRE. */
3415 gpgme_server (gpgme_tool_t gt)
3418 assuan_fd_t filedes[2];
3419 struct server server;
3420 static const char hello[] = ("GPGME-Tool " VERSION " ready");
3422 memset (&server, 0, sizeof (server));
3423 server.input_fd = ASSUAN_INVALID_FD;
3424 server.output_fd = ASSUAN_INVALID_FD;
3425 server.message_fd = ASSUAN_INVALID_FD;
3426 server.input_enc = GPGME_DATA_ENCODING_NONE;
3427 server.output_enc = GPGME_DATA_ENCODING_NONE;
3428 server.message_enc = GPGME_DATA_ENCODING_NONE;
3431 gt->write_status = server_write_status;
3432 gt->write_status_hook = &server;
3433 gt->write_data = server_write_data;
3434 gt->write_data_hook = &server;
3436 /* We use a pipe based server so that we can work from scripts.
3437 assuan_init_pipe_server will automagically detect when we are
3438 called with a socketpair and ignore FIELDES in this case. */
3439 #ifdef HAVE_W32CE_SYSTEM
3440 filedes[0] = ASSUAN_STDIN;
3441 filedes[1] = ASSUAN_STDOUT;
3443 filedes[0] = assuan_fdopen (0);
3444 filedes[1] = assuan_fdopen (1);
3446 err = assuan_new (&server.assuan_ctx);
3448 log_error (1, err, "can't create assuan context");
3450 assuan_set_pointer (server.assuan_ctx, &server);
3452 err = assuan_init_pipe_server (server.assuan_ctx, filedes);
3454 log_error (1, err, "can't initialize assuan server");
3455 err = register_commands (server.assuan_ctx);
3457 log_error (1, err, "can't register assuan commands");
3458 assuan_set_hello_line (server.assuan_ctx, hello);
3460 assuan_register_reset_notify (server.assuan_ctx, reset_notify);
3462 #define DBG_ASSUAN 0
3464 assuan_set_log_stream (server.assuan_ctx, log_stream);
3468 err = assuan_accept (server.assuan_ctx);
3473 log_error (0, err, "assuan accept problem");
3477 err = assuan_process (server.assuan_ctx);
3479 log_error (0, err, "assuan processing failed");
3482 assuan_release (server.assuan_ctx);
3487 /* MAIN PROGRAM STARTS HERE. */
3489 const char *argp_program_version = VERSION;
3490 const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
3491 error_t argp_err_exit_status = 1;
3493 static char doc[] = "GPGME Tool -- Assuan server exposing GPGME operations";
3494 static char args_doc[] = "COMMAND [OPTIONS...]";
3496 static struct argp_option options[] = {
3497 { "server", 's', 0, 0, "Server mode" },
3501 static error_t parse_options (int key, char *arg, struct argp_state *state);
3502 static struct argp argp = { options, parse_options, args_doc, doc };
3506 enum { CMD_DEFAULT, CMD_SERVER } cmd;
3510 args_init (struct args *args)
3512 memset (args, '\0', sizeof (*args));
3513 args->cmd = CMD_DEFAULT;
3518 parse_options (int key, char *arg, struct argp_state *state)
3520 struct args *args = state->input;
3525 args->cmd = CMD_SERVER;
3529 if (state->arg_num >= 2)
3531 printf ("Arg[%i] = %s\n", state->arg_num, arg);
3534 if (state->arg_num < 2)
3540 return ARGP_ERR_UNKNOWN;
3547 main (int argc, char *argv[])
3550 struct gpgme_tool gt;
3552 #ifdef HAVE_SETLOCALE
3553 setlocale (LC_ALL, "");
3555 gpgme_check_version (NULL);
3557 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
3560 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
3565 argp_parse (&argp, argc, argv, 0, 0, &args);
3578 gpgme_release (gt.ctx);
3580 #ifdef HAVE_W32CE_SYSTEM
3581 /* Give the buggy ssh server time to flush the output buffers. */