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,
1439 STATUS_IDENTIFY_RESULT
1442 const char *status_string[] =
1459 #define MAX_RECIPIENTS 10
1460 gpgme_key_t recipients[MAX_RECIPIENTS + 1];
1463 gpg_error_t (*write_status) (void *hook, const char *status, const char *msg);
1464 void *write_status_hook;
1465 gpg_error_t (*write_data) (void *hook, const void *buf, size_t len);
1466 void *write_data_hook;
1468 typedef struct gpgme_tool *gpgme_tool_t;
1471 /* Forward declaration. */
1472 void gt_write_status (gpgme_tool_t gt,
1473 status_t status, ...) GT_GCC_A_SENTINEL(0);
1475 server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
1476 int was_bad, int fd);
1480 _gt_progress_cb (void *opaque, const char *what,
1481 int type, int current, int total)
1483 gpgme_tool_t gt = opaque;
1486 snprintf (buf, sizeof (buf), "0x%02x %i %i", type, current, total);
1487 gt_write_status (gt, STATUS_PROGRESS, what, buf, NULL);
1492 _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
1496 err = gpgme_new (ctx);
1499 gpgme_set_progress_cb (*ctx, _gt_progress_cb, gt);
1505 gt_init (gpgme_tool_t gt)
1509 memset (gt, '\0', sizeof (*gt));
1511 err = _gt_gpgme_new (gt, >->ctx);
1513 log_error (1, err, "can't create gpgme context");
1518 gt_signers_add (gpgme_tool_t gt, const char *fpr)
1523 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1527 return gpgme_signers_add (gt->ctx, key);
1532 gt_signers_clear (gpgme_tool_t gt)
1534 gpgme_signers_clear (gt->ctx);
1540 gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key)
1543 gpgme_ctx_t listctx;
1547 if (!gt || !r_key || !pattern)
1548 return gpg_error (GPG_ERR_INV_VALUE);
1552 err = gpgme_new (&listctx);
1557 gpgme_protocol_t proto;
1558 gpgme_engine_info_t info;
1560 /* Clone the relevant state. */
1561 proto = gpgme_get_protocol (ctx);
1562 /* The g13 protocol does not allow keylisting, we need to choose
1564 if (proto == GPGME_PROTOCOL_G13)
1565 proto = GPGME_PROTOCOL_OpenPGP;
1567 gpgme_set_protocol (listctx, proto);
1568 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1569 info = gpgme_ctx_get_engine_info (ctx);
1570 while (info && info->protocol != proto)
1573 gpgme_ctx_set_engine_info (listctx, proto,
1574 info->file_name, info->home_dir);
1577 err = gpgme_op_keylist_start (listctx, pattern, 0);
1579 err = gpgme_op_keylist_next (listctx, r_key);
1583 err = gpgme_op_keylist_next (listctx, &key);
1584 if (gpgme_err_code (err) == GPG_ERR_EOF)
1589 && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1590 && key && key->subkeys && key->subkeys->fpr
1591 && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1593 /* The fingerprint is identical. We assume that this is
1594 the same key and don't mark it as an ambiguous. This
1595 problem may occur with corrupted keyrings and has
1596 been noticed often with gpgsm. In fact gpgsm uses a
1597 similar hack to sort out such duplicates but it can't
1598 do that while listing keys. */
1599 gpgme_key_unref (key);
1604 gpgme_key_unref (key);
1605 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1607 gpgme_key_unref (*r_key);
1610 gpgme_release (listctx);
1613 gt_write_status (gt, STATUS_RECIPIENT,
1614 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1615 (*r_key)->subkeys->fpr : "invalid", NULL);
1621 gt_recipients_add (gpgme_tool_t gt, const char *pattern)
1626 if (gt->recipients_nr >= MAX_RECIPIENTS)
1627 return gpg_error (GPG_ERR_ENOMEM);
1629 if (gpgme_get_protocol (gt->ctx) == GPGME_PROTOCOL_UISERVER)
1630 err = gpgme_key_from_uid (&key, pattern);
1632 err = gt_get_key (gt, pattern, &key);
1636 gt->recipients[gt->recipients_nr++] = key;
1642 gt_recipients_clear (gpgme_tool_t gt)
1646 for (idx = 0; idx < gt->recipients_nr; idx++)
1647 gpgme_key_unref (gt->recipients[idx]);
1648 memset (gt->recipients, '\0', gt->recipients_nr * sizeof (gpgme_key_t));
1649 gt->recipients_nr = 0;
1654 gt_reset (gpgme_tool_t gt)
1659 err = _gt_gpgme_new (gt, &ctx);
1663 gpgme_release (gt->ctx);
1665 gt_recipients_clear (gt);
1671 gt_write_status (gpgme_tool_t gt, status_t status, ...)
1680 va_start (ap, status);
1683 while ((text = va_arg (ap, const char *)))
1690 while (*text && n < sizeof (buf) - 2)
1699 err = gt->write_status (gt->write_status_hook, status_string[status], buf);
1701 log_error (1, err, "can't write status line");
1706 gt_write_data (gpgme_tool_t gt, const void *buf, size_t len)
1708 return gt->write_data (gt->write_data_hook, buf, len);
1713 gt_get_engine_info (gpgme_tool_t gt, gpgme_protocol_t proto)
1715 gpgme_engine_info_t info;
1716 info = gpgme_ctx_get_engine_info (gt->ctx);
1719 if (proto == GPGME_PROTOCOL_UNKNOWN || proto == info->protocol)
1720 gt_write_status (gt, STATUS_ENGINE,
1721 gpgme_get_protocol_name (info->protocol),
1722 info->file_name, info->version,
1723 info->req_version, info->home_dir, NULL);
1731 gt_protocol_from_name (const char *name)
1733 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_OpenPGP)))
1734 return GPGME_PROTOCOL_OpenPGP;
1735 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_CMS)))
1736 return GPGME_PROTOCOL_CMS;
1737 if (! strcasecmp (name,gpgme_get_protocol_name (GPGME_PROTOCOL_GPGCONF)))
1738 return GPGME_PROTOCOL_GPGCONF;
1739 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_ASSUAN)))
1740 return GPGME_PROTOCOL_ASSUAN;
1741 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_G13)))
1742 return GPGME_PROTOCOL_G13;
1743 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_UISERVER)))
1744 return GPGME_PROTOCOL_UISERVER;
1745 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_SPAWN)))
1746 return GPGME_PROTOCOL_SPAWN;
1747 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_DEFAULT)))
1748 return GPGME_PROTOCOL_DEFAULT;
1749 return GPGME_PROTOCOL_UNKNOWN;
1754 gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1756 return gpgme_set_protocol (gt->ctx, proto);
1761 gt_get_protocol (gpgme_tool_t gt)
1763 gpgme_protocol_t proto = gpgme_get_protocol (gt->ctx);
1765 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1773 gt_set_sub_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1775 return gpgme_set_sub_protocol (gt->ctx, proto);
1780 gt_get_sub_protocol (gpgme_tool_t gt)
1782 gpgme_protocol_t proto = gpgme_get_sub_protocol (gt->ctx);
1784 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1792 gt_set_pinentry_mode (gpgme_tool_t gt, gpgme_pinentry_mode_t mode, void *opaque)
1796 gpgme_set_passphrase_cb (gt->ctx, NULL, NULL);
1797 err = gpgme_set_pinentry_mode (gt->ctx, mode);
1798 if (!err && mode == GPGME_PINENTRY_MODE_LOOPBACK)
1799 gpgme_set_passphrase_cb (gt->ctx, server_passphrase_cb, opaque);
1805 gt_set_armor (gpgme_tool_t gt, int armor)
1807 gpgme_set_armor (gt->ctx, armor);
1813 gt_get_armor (gpgme_tool_t gt)
1815 gt_write_status (gt, STATUS_ARMOR,
1816 gpgme_get_armor (gt->ctx) ? "true" : "false", NULL);
1823 gt_set_textmode (gpgme_tool_t gt, int textmode)
1825 gpgme_set_textmode (gt->ctx, textmode);
1831 gt_get_textmode (gpgme_tool_t gt)
1833 gt_write_status (gt, STATUS_TEXTMODE,
1834 gpgme_get_textmode (gt->ctx) ? "true" : "false", NULL);
1841 gt_set_keylist_mode (gpgme_tool_t gt, gpgme_keylist_mode_t keylist_mode)
1843 gpgme_set_keylist_mode (gt->ctx, keylist_mode);
1849 gt_get_keylist_mode (gpgme_tool_t gt)
1851 #define NR_KEYLIST_MODES 6
1852 const char *modes[NR_KEYLIST_MODES + 1];
1854 gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx);
1856 if (mode & GPGME_KEYLIST_MODE_LOCAL)
1857 modes[idx++] = "local";
1858 if (mode & GPGME_KEYLIST_MODE_EXTERN)
1859 modes[idx++] = "extern";
1860 if (mode & GPGME_KEYLIST_MODE_SIGS)
1861 modes[idx++] = "sigs";
1862 if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
1863 modes[idx++] = "sig_notations";
1864 if (mode & GPGME_KEYLIST_MODE_WITH_SECRET)
1865 modes[idx++] = "with_secret";
1866 if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
1867 modes[idx++] = "ephemeral";
1868 if (mode & GPGME_KEYLIST_MODE_VALIDATE)
1869 modes[idx++] = "validate";
1870 modes[idx++] = NULL;
1872 gt_write_status (gt, STATUS_KEYLIST_MODE, modes[0], modes[1], modes[2],
1873 modes[3], modes[4], modes[5], modes[6], NULL);
1880 gt_set_include_certs (gpgme_tool_t gt, int include_certs)
1882 gpgme_set_include_certs (gt->ctx, include_certs);
1888 gt_get_include_certs (gpgme_tool_t gt)
1890 int include_certs = gpgme_get_include_certs (gt->ctx);
1893 if (include_certs == GPGME_INCLUDE_CERTS_DEFAULT)
1894 strcpy (buf, "default");
1896 snprintf (buf, sizeof (buf), "%i", include_certs);
1898 gt_write_status (gt, STATUS_INCLUDE_CERTS, buf, NULL);
1905 gt_decrypt_verify (gpgme_tool_t gt, gpgme_data_t cipher, gpgme_data_t plain,
1909 return gpgme_op_decrypt_verify (gt->ctx, cipher, plain);
1911 return gpgme_op_decrypt (gt->ctx, cipher, plain);
1916 gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
1917 gpgme_data_t plain, gpgme_data_t cipher, int sign)
1922 recp = gt->recipients_nr? gt->recipients : NULL;
1925 err = gpgme_op_encrypt_sign (gt->ctx, recp, flags, plain, cipher);
1927 err = gpgme_op_encrypt (gt->ctx, recp, flags, plain, cipher);
1929 gt_recipients_clear (gt);
1936 gt_sign (gpgme_tool_t gt, gpgme_data_t plain, gpgme_data_t sig,
1937 gpgme_sig_mode_t mode)
1939 return gpgme_op_sign (gt->ctx, plain, sig, mode);
1944 gt_verify (gpgme_tool_t gt, gpgme_data_t sig, gpgme_data_t sig_text,
1947 return gpgme_op_verify (gt->ctx, sig, sig_text, plain);
1952 gt_import (gpgme_tool_t gt, gpgme_data_t data)
1954 return gpgme_op_import (gt->ctx, data);
1959 gt_export (gpgme_tool_t gt, const char *pattern[], gpgme_export_mode_t mode,
1962 return gpgme_op_export_ext (gt->ctx, pattern, mode, data);
1967 gt_genkey (gpgme_tool_t gt, const char *parms, gpgme_data_t public,
1968 gpgme_data_t secret)
1970 return gpgme_op_genkey (gt->ctx, parms, public, secret);
1975 gt_import_keys (gpgme_tool_t gt, char *fpr[])
1977 gpg_error_t err = 0;
1987 return gpg_error (GPG_ERR_INV_VALUE);
1989 keys = malloc ((cnt + 1) * sizeof (gpgme_key_t));
1991 return gpg_error_from_syserror ();
1993 for (idx = 0; idx < cnt; idx++)
1995 err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0);
2002 err = gpgme_op_import_keys (gt->ctx, keys);
2007 gpgme_key_unref (keys[idx]);
2015 gt_delete (gpgme_tool_t gt, char *fpr, int allow_secret)
2020 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
2024 err = gpgme_op_delete (gt->ctx, key, allow_secret);
2025 gpgme_key_unref (key);
2031 gt_keylist_start (gpgme_tool_t gt, const char *pattern[], int secret_only)
2033 return gpgme_op_keylist_ext_start (gt->ctx, pattern, secret_only, 0);
2038 gt_keylist_next (gpgme_tool_t gt, gpgme_key_t *key)
2040 return gpgme_op_keylist_next (gt->ctx, key);
2045 gt_getauditlog (gpgme_tool_t gt, gpgme_data_t output, unsigned int flags)
2047 return gpgme_op_getauditlog (gt->ctx, output, flags);
2052 gt_vfs_mount (gpgme_tool_t gt, const char *container_file,
2053 const char *mount_dir, int flags)
2057 err = gpgme_op_vfs_mount (gt->ctx, container_file, mount_dir, flags, &op_err);
2058 return err ? err : op_err;
2063 gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
2067 err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file,
2069 gt_recipients_clear (gt);
2070 return err ? err : op_err;
2075 gt_passwd (gpgme_tool_t gt, char *fpr)
2080 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
2082 return gpg_err_code (err) == GPG_ERR_EOF? gpg_error (GPG_ERR_NO_PUBKEY):err;
2084 err = gpgme_op_passwd (gt->ctx, key, 0);
2085 gpgme_key_unref (key);
2091 gt_identify (gpgme_tool_t gt, gpgme_data_t data)
2093 const char *s = "?";
2095 switch (gpgme_data_identify (data, 0))
2097 case GPGME_DATA_TYPE_INVALID: return gpg_error (GPG_ERR_GENERAL);
2098 case GPGME_DATA_TYPE_UNKNOWN : s = "unknown"; break;
2099 case GPGME_DATA_TYPE_PGP_SIGNED : s = "PGP-signed"; break;
2100 case GPGME_DATA_TYPE_PGP_OTHER : s = "PGP"; break;
2101 case GPGME_DATA_TYPE_PGP_KEY : s = "PGP-key"; break;
2102 case GPGME_DATA_TYPE_CMS_SIGNED : s = "CMS-signed"; break;
2103 case GPGME_DATA_TYPE_CMS_ENCRYPTED: s = "CMS-encrypted"; break;
2104 case GPGME_DATA_TYPE_CMS_OTHER : s = "CMS"; break;
2105 case GPGME_DATA_TYPE_X509_CERT : s = "X.509"; break;
2106 case GPGME_DATA_TYPE_PKCS12 : s = "PKCS12"; break;
2108 gt_write_status (gt, STATUS_IDENTIFY_RESULT, s, NULL);
2114 gt_spawn (gpgme_tool_t gt, const char *pgm,
2115 gpgme_data_t inp, gpgme_data_t outp)
2119 err = gpgme_op_spawn (gt->ctx, pgm, NULL, inp, outp, outp, 0);
2125 #define GT_RESULT_ENCRYPT 0x1
2126 #define GT_RESULT_DECRYPT 0x2
2127 #define GT_RESULT_SIGN 0x4
2128 #define GT_RESULT_VERIFY 0x8
2129 #define GT_RESULT_IMPORT 0x10
2130 #define GT_RESULT_GENKEY 0x20
2131 #define GT_RESULT_KEYLIST 0x40
2132 #define GT_RESULT_VFS_MOUNT 0x80
2133 #define GT_RESULT_ALL (~0U)
2136 gt_result (gpgme_tool_t gt, unsigned int flags)
2140 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
2141 gt_write_data (gt, NULL, 0);
2142 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
2143 gt_write_data (gt, NULL, 0);
2144 if (flags & GT_RESULT_ENCRYPT)
2145 result_encrypt_to_xml (gt->ctx, indent,
2146 (result_xml_write_cb_t) gt_write_data, gt);
2147 if (flags & GT_RESULT_DECRYPT)
2148 result_decrypt_to_xml (gt->ctx, indent,
2149 (result_xml_write_cb_t) gt_write_data, gt);
2150 if (flags & GT_RESULT_SIGN)
2151 result_sign_to_xml (gt->ctx, indent,
2152 (result_xml_write_cb_t) gt_write_data, gt);
2153 if (flags & GT_RESULT_VERIFY)
2154 result_verify_to_xml (gt->ctx, indent,
2155 (result_xml_write_cb_t) gt_write_data, gt);
2156 if (flags & GT_RESULT_IMPORT)
2157 result_import_to_xml (gt->ctx, indent,
2158 (result_xml_write_cb_t) gt_write_data, gt);
2159 if (flags & GT_RESULT_GENKEY)
2160 result_genkey_to_xml (gt->ctx, indent,
2161 (result_xml_write_cb_t) gt_write_data, gt);
2162 if (flags & GT_RESULT_KEYLIST)
2163 result_keylist_to_xml (gt->ctx, indent,
2164 (result_xml_write_cb_t) gt_write_data, gt);
2165 if (flags & GT_RESULT_VFS_MOUNT)
2166 result_vfs_mount_to_xml (gt->ctx, indent,
2167 (result_xml_write_cb_t) gt_write_data, gt);
2168 gt_write_data (gt, xml_end, sizeof (xml_end));
2181 assuan_context_t assuan_ctx;
2183 gpgme_data_encoding_t input_enc;
2184 gpgme_data_encoding_t output_enc;
2185 assuan_fd_t input_fd;
2186 char *input_filename;
2188 assuan_fd_t output_fd;
2189 char *output_filename;
2190 FILE *output_stream;
2191 assuan_fd_t message_fd;
2192 char *message_filename;
2193 FILE *message_stream;
2194 gpgme_data_encoding_t message_enc;
2199 server_write_status (void *hook, const char *status, const char *msg)
2201 struct server *server = hook;
2202 return assuan_write_status (server->assuan_ctx, status, msg);
2207 server_write_data (void *hook, const void *buf, size_t len)
2209 struct server *server = hook;
2210 return assuan_send_data (server->assuan_ctx, buf, len);
2215 server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
2216 int was_bad, int fd)
2218 struct server *server = opaque;
2220 unsigned char *buf = NULL;
2223 if (server && server->assuan_ctx)
2226 assuan_write_status (server->assuan_ctx, "USERID_HINT", uid_hint);
2228 assuan_write_status (server->assuan_ctx, "NEED_PASSPHRASE", info);
2230 err = assuan_inquire (server->assuan_ctx, "PASSPHRASE",
2231 &buf, &buflen, 100);
2234 err = gpg_error (GPG_ERR_NO_PASSPHRASE);
2238 /* We take care to always send a LF. */
2239 if (gpgme_io_writen (fd, buf, buflen))
2240 err = gpg_error_from_syserror ();
2241 else if (!memchr (buf, '\n', buflen) && gpgme_io_writen (fd, "\n", 1))
2242 err = gpg_error_from_syserror ();
2249 /* Wrapper around assuan_command_parse_fd to also handle a
2250 "file=FILENAME" argument. On success either a filename is returned
2251 at FILENAME or a file descriptor at RFD; the other one is set to
2252 NULL respective ASSUAN_INVALID_FD. */
2254 server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd,
2257 *rfd = ASSUAN_INVALID_FD;
2260 if (! strncasecmp (line, "file=", 5))
2263 *filename = strdup (line + 5);
2265 return gpg_error_from_syserror();
2266 term = strchr (*filename, ' ');
2272 return assuan_command_parse_fd (ctx, line, rfd);
2276 static gpgme_data_encoding_t
2277 server_data_encoding (const char *line)
2279 if (strstr (line, "--binary"))
2280 return GPGME_DATA_ENCODING_BINARY;
2281 if (strstr (line, "--base64"))
2282 return GPGME_DATA_ENCODING_BASE64;
2283 if (strstr (line, "--armor"))
2284 return GPGME_DATA_ENCODING_ARMOR;
2285 if (strstr (line, "--url"))
2286 return GPGME_DATA_ENCODING_URL;
2287 if (strstr (line, "--urlesc"))
2288 return GPGME_DATA_ENCODING_URLESC;
2289 if (strstr (line, "--url0"))
2290 return GPGME_DATA_ENCODING_URL0;
2291 return GPGME_DATA_ENCODING_NONE;
2295 static gpgme_error_t
2296 server_data_obj (assuan_fd_t fd, char *fn, int out,
2297 gpgme_data_encoding_t encoding,
2298 gpgme_data_t *data, FILE **fs)
2305 *fs = fopen (fn, out ? "wb" : "rb");
2307 return gpg_error_from_syserror ();
2309 err = gpgme_data_new_from_stream (data, *fs);
2312 err = gpgme_data_new_from_fd (data, (int) fd);
2316 return gpgme_data_set_encoding (*data, encoding);
2321 server_reset_fds (struct server *server)
2323 /* assuan closes the input and output FDs for us when doing a RESET,
2324 but we use this same function after commands, so repeat it
2326 if (server->input_fd != ASSUAN_INVALID_FD)
2329 CloseHandle (server->input_fd);
2331 close (server->input_fd);
2333 server->input_fd = ASSUAN_INVALID_FD;
2335 if (server->output_fd != ASSUAN_INVALID_FD)
2338 CloseHandle (server->output_fd);
2340 close (server->output_fd);
2342 server->output_fd = ASSUAN_INVALID_FD;
2344 if (server->message_fd != ASSUAN_INVALID_FD)
2346 /* FIXME: Assuan should provide a close function. */
2348 CloseHandle (server->message_fd);
2350 close (server->message_fd);
2352 server->message_fd = ASSUAN_INVALID_FD;
2354 if (server->input_filename)
2356 free (server->input_filename);
2357 server->input_filename = NULL;
2359 if (server->output_filename)
2361 free (server->output_filename);
2362 server->output_filename = NULL;
2364 if (server->message_filename)
2366 free (server->message_filename);
2367 server->message_filename = NULL;
2369 if (server->input_stream)
2371 fclose (server->input_stream);
2372 server->input_stream = NULL;
2374 if (server->output_stream)
2376 fclose (server->output_stream);
2377 server->output_stream = NULL;
2379 if (server->message_stream)
2381 fclose (server->message_stream);
2382 server->message_stream = NULL;
2385 server->input_enc = GPGME_DATA_ENCODING_NONE;
2386 server->output_enc = GPGME_DATA_ENCODING_NONE;
2387 server->message_enc = GPGME_DATA_ENCODING_NONE;
2392 reset_notify (assuan_context_t ctx, char *line)
2394 struct server *server = assuan_get_pointer (ctx);
2395 server_reset_fds (server);
2396 gt_reset (server->gt);
2401 static const char hlp_version[] =
2402 "VERSION [<string>]\n"
2404 "Call the function gpgme_check_version.";
2406 cmd_version (assuan_context_t ctx, char *line)
2410 const char *version = gpgme_check_version (line);
2411 return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
2415 const char *version = gpgme_check_version (NULL);
2416 return assuan_send_data (ctx, version, strlen (version));
2421 static const char hlp_engine[] =
2422 "ENGINE [<string>]\n"
2424 "Get information about a GPGME engine (a.k.a. protocol).";
2426 cmd_engine (assuan_context_t ctx, char *line)
2428 struct server *server = assuan_get_pointer (ctx);
2429 return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
2433 static const char hlp_protocol[] =
2434 "PROTOCOL [<name>]\n"
2436 "With NAME, set the protocol. Without, return the current\n"
2439 cmd_protocol (assuan_context_t ctx, char *line)
2441 struct server *server = assuan_get_pointer (ctx);
2443 return gt_set_protocol (server->gt, gt_protocol_from_name (line));
2445 return gt_get_protocol (server->gt);
2449 static const char hlp_sub_protocol[] =
2450 "SUB_PROTOCOL [<name>]\n"
2452 "With NAME, set the sub-protocol. Without, return the\n"
2453 "current sub-protocol.";
2455 cmd_sub_protocol (assuan_context_t ctx, char *line)
2457 struct server *server = assuan_get_pointer (ctx);
2459 return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
2461 return gt_get_sub_protocol (server->gt);
2465 static const char hlp_pinentry_mode[] =
2466 "PINENTRY_MODE <name>\n"
2468 "Set the pinentry mode to NAME. Allowedvalues for NAME are:\n"
2469 " default - reset to the default of the engine,\n"
2470 " ask - force the use of the pinentry,\n"
2471 " cancel - emulate use of pinentry's cancel button,\n"
2472 " error - return a pinentry error,\n"
2473 " loopback - redirect pinentry queries to the caller.\n"
2474 "Note that only recent versions of GPG support changing the pinentry mode.";
2476 cmd_pinentry_mode (assuan_context_t ctx, char *line)
2478 struct server *server = assuan_get_pointer (ctx);
2479 gpgme_pinentry_mode_t mode;
2481 if (!line || !*line || !strcmp (line, "default"))
2482 mode = GPGME_PINENTRY_MODE_DEFAULT;
2483 else if (!strcmp (line, "ask"))
2484 mode = GPGME_PINENTRY_MODE_ASK;
2485 else if (!strcmp (line, "cancel"))
2486 mode = GPGME_PINENTRY_MODE_CANCEL;
2487 else if (!strcmp (line, "error"))
2488 mode = GPGME_PINENTRY_MODE_ERROR;
2489 else if (!strcmp (line, "loopback"))
2490 mode = GPGME_PINENTRY_MODE_LOOPBACK;
2492 return gpg_error (GPG_ERR_INV_VALUE);
2494 return gt_set_pinentry_mode (server->gt, mode, server);
2498 static const char hlp_armor[] =
2499 "ARMOR [true|false]\n"
2501 "With 'true' or 'false', turn output ASCII armoring on or\n"
2502 "off. Without, return the current armoring status.";
2504 cmd_armor (assuan_context_t ctx, char *line)
2506 struct server *server = assuan_get_pointer (ctx);
2511 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2515 return gt_set_armor (server->gt, flag);
2518 return gt_get_armor (server->gt);
2522 static const char hlp_textmode[] =
2523 "TEXTMODE [true|false]\n"
2525 "With 'true' or 'false', turn text mode on or off.\n"
2526 "Without, return the current text mode status.";
2528 cmd_textmode (assuan_context_t ctx, char *line)
2530 struct server *server = assuan_get_pointer (ctx);
2535 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2539 return gt_set_textmode (server->gt, flag);
2542 return gt_get_textmode (server->gt);
2546 static const char hlp_include_certs[] =
2547 "INCLUDE_CERTS [default|<n>]\n"
2549 "With DEFAULT or N, set how many certificates should be\n"
2550 "included in the next S/MIME signed message. See the\n"
2551 "GPGME documentation for details on the meaning of"
2552 "various N. Without either, return the current setting.";
2554 cmd_include_certs (assuan_context_t ctx, char *line)
2556 struct server *server = assuan_get_pointer (ctx);
2560 int include_certs = 0;
2562 if (! strcasecmp (line, "default"))
2563 include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
2565 include_certs = atoi (line);
2567 return gt_set_include_certs (server->gt, include_certs);
2570 return gt_get_include_certs (server->gt);
2574 static const char hlp_keylist_mode[] =
2575 "KEYLIST_MODE [local] [extern] [sigs] [sig_notations]\n"
2576 " [ephemeral] [validate]\n"
2578 "Set the mode for the next KEYLIST command.";
2580 cmd_keylist_mode (assuan_context_t ctx, char *line)
2582 struct server *server = assuan_get_pointer (ctx);
2586 gpgme_keylist_mode_t mode = 0;
2588 if (strstr (line, "local"))
2589 mode |= GPGME_KEYLIST_MODE_LOCAL;
2590 if (strstr (line, "extern"))
2591 mode |= GPGME_KEYLIST_MODE_EXTERN;
2592 if (strstr (line, "sigs"))
2593 mode |= GPGME_KEYLIST_MODE_SIGS;
2594 if (strstr (line, "sig_notations"))
2595 mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
2596 if (strstr (line, "with_secret"))
2597 mode |= GPGME_KEYLIST_MODE_WITH_SECRET;
2598 if (strstr (line, "ephemeral"))
2599 mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
2600 if (strstr (line, "validate"))
2601 mode |= GPGME_KEYLIST_MODE_VALIDATE;
2603 return gt_set_keylist_mode (server->gt, mode);
2606 return gt_get_keylist_mode (server->gt);
2610 static const char hlp_input[] =
2611 "INPUT [<fd>|FILE=<path>]\n"
2613 "Set the input for the next command. Use either the\n"
2614 "Assuan file descriptor FD or a filesystem PATH.";
2616 cmd_input (assuan_context_t ctx, char *line)
2618 struct server *server = assuan_get_pointer (ctx);
2623 err = server_parse_fd (ctx, line, &sysfd, &filename);
2626 server->input_fd = sysfd;
2627 server->input_filename = filename;
2628 server->input_enc = server_data_encoding (line);
2633 static const char hlp_output[] =
2634 "OUTPUT [<fd>|FILE=<path>]\n"
2636 "Set the output for the next command. Use either the\n"
2637 "Assuan file descriptor FD or a filesystem PATH.";
2639 cmd_output (assuan_context_t ctx, char *line)
2641 struct server *server = assuan_get_pointer (ctx);
2646 err = server_parse_fd (ctx, line, &sysfd, &filename);
2649 server->output_fd = sysfd;
2650 server->output_filename = filename;
2651 server->output_enc = server_data_encoding (line);
2656 static const char hlp_message[] =
2657 "MESSAGE [<fd>|FILE=<path>]\n"
2659 "Set the plaintext message for the next VERIFY command\n"
2660 "with a detached signature. Use either the Assuan file\n"
2661 "descriptor FD or a filesystem PATH.";
2663 cmd_message (assuan_context_t ctx, char *line)
2665 struct server *server = assuan_get_pointer (ctx);
2670 err = server_parse_fd (ctx, line, &sysfd, &filename);
2673 server->message_fd = sysfd;
2674 server->message_filename = filename;
2675 server->message_enc = server_data_encoding (line);
2680 static const char hlp_recipient[] =
2681 "RECIPIENT <pattern>\n"
2683 "Add the key matching PATTERN to the list of recipients\n"
2684 "for the next encryption command.";
2686 cmd_recipient (assuan_context_t ctx, char *line)
2688 struct server *server = assuan_get_pointer (ctx);
2690 return gt_recipients_add (server->gt, line);
2694 static const char hlp_signer[] =
2695 "SIGNER <fingerprint>\n"
2697 "Add the key with FINGERPRINT to the list of signers to\n"
2698 "be used for the next signing command.";
2700 cmd_signer (assuan_context_t ctx, char *line)
2702 struct server *server = assuan_get_pointer (ctx);
2704 return gt_signers_add (server->gt, line);
2708 static const char hlp_signers_clear[] =
2711 "Clear the list of signers specified by previous SIGNER\n"
2714 cmd_signers_clear (assuan_context_t ctx, char *line)
2716 struct server *server = assuan_get_pointer (ctx);
2718 return gt_signers_clear (server->gt);
2723 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
2725 struct server *server = assuan_get_pointer (ctx);
2731 gpgme_data_t inp_data;
2732 gpgme_data_t out_data;
2734 inp_fd = server->input_fd;
2735 inp_fn = server->input_filename;
2736 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2737 return GPG_ERR_ASS_NO_INPUT;
2738 out_fd = server->output_fd;
2739 out_fn = server->output_filename;
2740 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2741 return GPG_ERR_ASS_NO_OUTPUT;
2743 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2744 &server->input_stream);
2747 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2748 &server->output_stream);
2751 gpgme_data_release (inp_data);
2755 err = gt_decrypt_verify (server->gt, inp_data, out_data, verify);
2757 gpgme_data_release (inp_data);
2758 gpgme_data_release (out_data);
2760 server_reset_fds (server);
2766 static const char hlp_decrypt[] =
2769 "Decrypt the object set by the last INPUT command and\n"
2770 "write the decrypted message to the object set by the\n"
2771 "last OUTPUT command.";
2773 cmd_decrypt (assuan_context_t ctx, char *line)
2775 return _cmd_decrypt_verify (ctx, line, 0);
2779 static const char hlp_decrypt_verify[] =
2782 "Decrypt the object set by the last INPUT command and\n"
2783 "verify any embedded signatures. Write the decrypted\n"
2784 "message to the object set by the last OUTPUT command.";
2786 cmd_decrypt_verify (assuan_context_t ctx, char *line)
2788 return _cmd_decrypt_verify (ctx, line, 1);
2793 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
2795 struct server *server = assuan_get_pointer (ctx);
2801 gpgme_data_t inp_data = NULL;
2802 gpgme_data_t out_data = NULL;
2803 gpgme_encrypt_flags_t flags = 0;
2805 if (strstr (line, "--always-trust"))
2806 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
2807 if (strstr (line, "--no-encrypt-to"))
2808 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
2809 if (strstr (line, "--prepare"))
2810 flags |= GPGME_ENCRYPT_PREPARE;
2811 if (strstr (line, "--expect-sign"))
2812 flags |= GPGME_ENCRYPT_EXPECT_SIGN;
2813 if (strstr (line, "--no-compress"))
2814 flags |= GPGME_ENCRYPT_NO_COMPRESS;
2816 inp_fd = server->input_fd;
2817 inp_fn = server->input_filename;
2818 out_fd = server->output_fd;
2819 out_fn = server->output_filename;
2820 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
2822 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2823 &server->input_stream);
2827 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2829 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2830 &server->output_stream);
2833 gpgme_data_release (inp_data);
2838 err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign);
2840 gpgme_data_release (inp_data);
2841 gpgme_data_release (out_data);
2843 server_reset_fds (server);
2849 static const char hlp_encrypt[] =
2850 "ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2851 " [--no-compress] [--prepare] [--expect-sign]\n"
2853 "Encrypt the object set by the last INPUT command to\n"
2854 "the keys specified by previous RECIPIENT commands. \n"
2855 "Write the signed and encrypted message to the object\n"
2856 "set by the last OUTPUT command.";
2858 cmd_encrypt (assuan_context_t ctx, char *line)
2860 return _cmd_sign_encrypt (ctx, line, 0);
2864 static const char hlp_sign_encrypt[] =
2865 "SIGN_ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2866 " [--no-compress] [--prepare] [--expect-sign]\n"
2868 "Sign the object set by the last INPUT command with the\n"
2869 "keys specified by previous SIGNER commands and encrypt\n"
2870 "it to the keys specified by previous RECIPIENT\n"
2871 "commands. Write the signed and encrypted message to\n"
2872 "the object set by the last OUTPUT command.";
2874 cmd_sign_encrypt (assuan_context_t ctx, char *line)
2876 return _cmd_sign_encrypt (ctx, line, 1);
2880 static const char hlp_sign[] =
2881 "SIGN [--clear|--detach]\n"
2883 "Sign the object set by the last INPUT command with the\n"
2884 "keys specified by previous SIGNER commands. Write the\n"
2885 "signed message to the object set by the last OUTPUT\n"
2886 "command. With `--clear`, generate a clear text\n"
2887 "signature. With `--detach`, generate a detached\n"
2890 cmd_sign (assuan_context_t ctx, char *line)
2892 struct server *server = assuan_get_pointer (ctx);
2898 gpgme_data_t inp_data;
2899 gpgme_data_t out_data;
2900 gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
2902 if (strstr (line, "--clear"))
2903 mode = GPGME_SIG_MODE_CLEAR;
2904 if (strstr (line, "--detach"))
2905 mode = GPGME_SIG_MODE_DETACH;
2907 inp_fd = server->input_fd;
2908 inp_fn = server->input_filename;
2909 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2910 return GPG_ERR_ASS_NO_INPUT;
2911 out_fd = server->output_fd;
2912 out_fn = server->output_filename;
2913 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2914 return GPG_ERR_ASS_NO_OUTPUT;
2916 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2917 &server->input_stream);
2920 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2921 &server->output_stream);
2924 gpgme_data_release (inp_data);
2928 err = gt_sign (server->gt, inp_data, out_data, mode);
2930 gpgme_data_release (inp_data);
2931 gpgme_data_release (out_data);
2932 server_reset_fds (server);
2938 static const char hlp_verify[] =
2941 "Verify signatures on the object set by the last INPUT\n"
2942 "and MESSAGE commands. If the message was encrypted,\n"
2943 "write the plaintext to the object set by the last\n"
2946 cmd_verify (assuan_context_t ctx, char *line)
2948 struct server *server = assuan_get_pointer (ctx);
2956 gpgme_data_t inp_data;
2957 gpgme_data_t msg_data = NULL;
2958 gpgme_data_t out_data = NULL;
2960 inp_fd = server->input_fd;
2961 inp_fn = server->input_filename;
2962 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2963 return GPG_ERR_ASS_NO_INPUT;
2964 msg_fd = server->message_fd;
2965 msg_fn = server->message_filename;
2966 out_fd = server->output_fd;
2967 out_fn = server->output_filename;
2969 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2970 &server->input_stream);
2973 if (msg_fd != ASSUAN_INVALID_FD || msg_fn)
2975 err = server_data_obj (msg_fd, msg_fn, 0, server->message_enc, &msg_data,
2976 &server->message_stream);
2979 gpgme_data_release (inp_data);
2983 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2985 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2986 &server->output_stream);
2989 gpgme_data_release (inp_data);
2990 gpgme_data_release (msg_data);
2995 err = gt_verify (server->gt, inp_data, msg_data, out_data);
2997 gpgme_data_release (inp_data);
2999 gpgme_data_release (msg_data);
3001 gpgme_data_release (out_data);
3003 server_reset_fds (server);
3009 static const char hlp_import[] =
3010 "IMPORT [<pattern>]\n"
3012 "With PATTERN, import the keys described by PATTERN.\n"
3013 "Without, read a key (or keys) from the object set by the\n"
3014 "last INPUT command.";
3016 cmd_import (assuan_context_t ctx, char *line)
3018 struct server *server = assuan_get_pointer (ctx);
3022 char *fprs[2] = { line, NULL };
3024 return gt_import_keys (server->gt, fprs);
3031 gpgme_data_t inp_data;
3033 inp_fd = server->input_fd;
3034 inp_fn = server->input_filename;
3035 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
3036 return GPG_ERR_ASS_NO_INPUT;
3038 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
3039 &server->input_stream);
3043 err = gt_import (server->gt, inp_data);
3045 gpgme_data_release (inp_data);
3046 server_reset_fds (server);
3053 static const char hlp_export[] =
3054 "EXPORT [--extern] [--minimal] [<pattern>]\n"
3056 "Export the keys described by PATTERN. Write the\n"
3057 "the output to the object set by the last OUTPUT command.";
3059 cmd_export (assuan_context_t ctx, char *line)
3061 struct server *server = assuan_get_pointer (ctx);
3065 gpgme_data_t out_data;
3066 gpgme_export_mode_t mode = 0;
3067 const char *pattern[2];
3069 out_fd = server->output_fd;
3070 out_fn = server->output_filename;
3071 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
3072 return GPG_ERR_ASS_NO_OUTPUT;
3073 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
3074 &server->output_stream);
3078 if (has_option (line, "--extern"))
3079 mode |= GPGME_EXPORT_MODE_EXTERN;
3080 if (has_option (line, "--minimal"))
3081 mode |= GPGME_EXPORT_MODE_MINIMAL;
3083 line = skip_options (line);
3088 err = gt_export (server->gt, pattern, mode, out_data);
3090 gpgme_data_release (out_data);
3091 server_reset_fds (server);
3098 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
3102 gpgme_ssize_t writen = gpgme_data_write (data, buf, size);
3103 if (writen < 0 && errno != EAGAIN)
3104 return gpg_error_from_syserror ();
3105 else if (writen > 0)
3107 buf = (void *) (((char *) buf) + writen);
3116 cmd_genkey (assuan_context_t ctx, char *line)
3118 struct server *server = assuan_get_pointer (ctx);
3124 gpgme_data_t inp_data;
3125 gpgme_data_t out_data = NULL;
3126 gpgme_data_t parms_data = NULL;
3129 inp_fd = server->input_fd;
3130 inp_fn = server->input_filename;
3131 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
3132 return GPG_ERR_ASS_NO_INPUT;
3133 out_fd = server->output_fd;
3134 out_fn = server->output_filename;
3136 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
3137 &server->input_stream);
3140 if (out_fd != ASSUAN_INVALID_FD || out_fn)
3142 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
3143 &server->output_stream);
3146 gpgme_data_release (inp_data);
3151 /* Convert input data. */
3152 err = gpgme_data_new (&parms_data);
3158 gpgme_ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
3161 err = gpg_error_from_syserror ();
3164 else if (readn == 0)
3167 err = _cmd_genkey_write (parms_data, buf, readn);
3172 err = _cmd_genkey_write (parms_data, "", 1);
3175 parms = gpgme_data_release_and_get_mem (parms_data, NULL);
3179 err = gpg_error (GPG_ERR_GENERAL);
3183 err = gt_genkey (server->gt, parms, out_data, NULL);
3185 server_reset_fds (server);
3188 gpgme_data_release (inp_data);
3190 gpgme_data_release (out_data);
3192 gpgme_data_release (parms_data);
3199 cmd_delete (assuan_context_t ctx, char *line)
3201 struct server *server = assuan_get_pointer (ctx);
3202 int allow_secret = 0;
3203 const char optstr[] = "--allow-secret";
3205 if (!strncasecmp (line, optstr, strlen (optstr)))
3208 line += strlen (optstr);
3209 while (*line && !spacep (line))
3212 return gt_delete (server->gt, line, allow_secret);
3216 static const char hlp_keylist[] =
3217 "KEYLIST [--secret-only] [<patterns>]\n"
3219 "List all certificates or only those specified by PATTERNS. Each\n"
3220 "pattern shall be a percent-plus escaped certificate specification.";
3222 cmd_keylist (assuan_context_t ctx, char *line)
3224 #define MAX_CMD_KEYLIST_PATTERN 20
3225 struct server *server = assuan_get_pointer (ctx);
3226 gpgme_tool_t gt = server->gt;
3227 struct result_xml_state state;
3229 int secret_only = 0;
3231 const char *pattern[MAX_CMD_KEYLIST_PATTERN+1];
3232 const char optstr[] = "--secret-only";
3235 if (!strncasecmp (line, optstr, strlen (optstr)))
3238 line += strlen (optstr);
3239 while (*line && !spacep (line))
3244 for (p=line; *p; line = p)
3246 while (*p && *p != ' ')
3252 if (idx+1 == DIM (pattern))
3253 return gpg_error (GPG_ERR_TOO_MANY);
3254 strcpy_escaped_plus (line, line);
3255 pattern[idx++] = line;
3258 pattern[idx] = NULL;
3260 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
3261 gt_write_data (gt, NULL, 0);
3262 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
3263 gt_write_data (gt, NULL, 0);
3264 result_init (&state, indent, (result_xml_write_cb_t) gt_write_data, gt);
3265 result_xml_tag_start (&state, "keylist", NULL);
3267 err = gt_keylist_start (server->gt, pattern, secret_only);
3271 gpgme_subkey_t subkey;
3272 gpgme_user_id_t uid;
3274 err = gt_keylist_next (server->gt, &key);
3275 if (gpg_err_code (err) == GPG_ERR_EOF)
3282 result_xml_tag_start (&state, "key", NULL);
3283 result_add_value (&state, "revoked", key->revoked);
3284 result_add_value (&state, "expired", key->expired);
3285 result_add_value (&state, "disabled", key->disabled);
3286 result_add_value (&state, "invalid", key->invalid);
3287 result_add_value (&state, "can-encrypt", key->can_encrypt);
3288 result_add_value (&state, "can-sign", key->can_sign);
3289 result_add_value (&state, "can-certify", key->can_certify);
3290 result_add_value (&state, "can-authenticate", key->can_authenticate);
3291 result_add_value (&state, "is-qualified", key->is_qualified);
3292 result_add_value (&state, "secret", key->secret);
3293 result_add_protocol (&state, "protocol", key->protocol);
3294 result_xml_tag_start (&state, "issuer", NULL);
3295 result_add_string (&state, "serial", key->issuer_serial);
3296 result_add_string (&state, "name", key->issuer_name);
3297 result_xml_tag_end (&state); /* issuer */
3298 result_add_string (&state, "chain-id", key->chain_id);
3299 result_add_validity (&state, "owner-trust", key->owner_trust);
3300 result_xml_tag_start (&state, "subkeys", NULL);
3301 subkey = key->subkeys;
3303 result_xml_tag_start (&state, "subkey", NULL);
3304 /* FIXME: more data */
3305 result_add_fpr (&state, "fpr", subkey->fpr);
3306 result_add_value (&state, "secret", subkey->secret);
3307 result_add_value (&state, "is_cardkey", subkey->is_cardkey);
3308 if (subkey->card_number)
3309 result_add_string (&state, "card_number", subkey->card_number);
3311 result_add_string (&state, "curve", subkey->curve);
3312 result_xml_tag_end (&state); /* subkey */
3313 subkey = subkey->next;
3315 result_xml_tag_end (&state); /* subkeys */
3316 result_xml_tag_start (&state, "uids", NULL);
3319 result_xml_tag_start (&state, "uid", NULL);
3320 /* FIXME: more data */
3321 result_add_string (&state, "uid", uid->uid);
3322 result_add_string (&state, "name", uid->name);
3323 result_add_string (&state, "email", uid->email);
3324 result_add_string (&state, "comment", uid->comment);
3325 result_xml_tag_end (&state); /* uid */
3328 result_xml_tag_end (&state); /* uids */
3329 result_xml_tag_end (&state); /* key */
3330 gpgme_key_unref (key);
3334 result_xml_tag_end (&state); /* keylist */
3335 gt_write_data (gt, xml_end, sizeof (xml_end));
3337 server_reset_fds (server);
3343 static const char hlp_getauditlog[] =
3344 "GETAUDITLOG [--html] [--with-help]\n"
3346 "Call the function gpgme_op_getauditlog with the given flags. Write\n"
3347 "the output to the object set by the last OUTPUT command.";
3349 cmd_getauditlog (assuan_context_t ctx, char *line)
3351 struct server *server = assuan_get_pointer (ctx);
3355 gpgme_data_t out_data;
3356 unsigned int flags = 0;
3358 out_fd = server->output_fd;
3359 out_fn = server->output_filename;
3360 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
3361 return GPG_ERR_ASS_NO_OUTPUT;
3362 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
3363 &server->output_stream);
3367 if (strstr (line, "--html"))
3368 flags |= GPGME_AUDITLOG_HTML;
3369 if (strstr (line, "--with-help"))
3370 flags |= GPGME_AUDITLOG_WITH_HELP;
3372 err = gt_getauditlog (server->gt, out_data, flags);
3374 gpgme_data_release (out_data);
3375 server_reset_fds (server);
3382 cmd_vfs_mount (assuan_context_t ctx, char *line)
3384 struct server *server = assuan_get_pointer (ctx);
3388 mount_dir = strchr (line, ' ');
3391 *(mount_dir++) = '\0';
3392 while (*mount_dir == ' ')
3396 err = gt_vfs_mount (server->gt, line, mount_dir, 0);
3403 cmd_vfs_create (assuan_context_t ctx, char *line)
3405 struct server *server = assuan_get_pointer (ctx);
3409 end = strchr (line, ' ');
3417 err = gt_vfs_create (server->gt, line, 0);
3423 static const char hlp_passwd[] =
3424 "PASSWD <user-id>\n"
3426 "Ask the backend to change the passphrase for the key\n"
3427 "specified by USER-ID.";
3429 cmd_passwd (assuan_context_t ctx, char *line)
3431 struct server *server = assuan_get_pointer (ctx);
3433 return gt_passwd (server->gt, line);
3439 cmd_result (assuan_context_t ctx, char *line)
3441 struct server *server = assuan_get_pointer (ctx);
3442 return gt_result (server->gt, GT_RESULT_ALL);
3446 /* STRERROR <err> */
3448 cmd_strerror (assuan_context_t ctx, char *line)
3454 snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
3455 gpgme_strsource (err));
3456 return assuan_send_data (ctx, buf, strlen (buf));
3461 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
3463 gpgme_pubkey_algo_t algo;
3467 snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
3468 return assuan_send_data (ctx, buf, strlen (buf));
3473 cmd_hash_algo_name (assuan_context_t ctx, char *line)
3475 gpgme_hash_algo_t algo;
3479 snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
3480 return assuan_send_data (ctx, buf, strlen (buf));
3484 static const char hlp_identify[] =
3487 "Identify the type of data set with the INPUT command.";
3489 cmd_identify (assuan_context_t ctx, char *line)
3491 struct server *server = assuan_get_pointer (ctx);
3495 gpgme_data_t inp_data;
3497 inp_fd = server->input_fd;
3498 inp_fn = server->input_filename;
3499 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
3500 return GPG_ERR_ASS_NO_INPUT;
3502 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
3503 &server->input_stream);
3507 err = gt_identify (server->gt, inp_data);
3509 gpgme_data_release (inp_data);
3510 server_reset_fds (server);
3516 static const char hlp_spawn[] =
3517 "SPAWN PGM [args]\n"
3519 "Run program PGM with stdin connected to the INPUT source;\n"
3520 "stdout and stderr to the OUTPUT source.";
3522 cmd_spawn (assuan_context_t ctx, char *line)
3524 struct server *server = assuan_get_pointer (ctx);
3530 gpgme_data_t inp_data = NULL;
3531 gpgme_data_t out_data = NULL;
3533 inp_fd = server->input_fd;
3534 inp_fn = server->input_filename;
3535 out_fd = server->output_fd;
3536 out_fn = server->output_filename;
3537 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
3539 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
3540 &server->input_stream);
3544 if (out_fd != ASSUAN_INVALID_FD || out_fn)
3546 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
3547 &server->output_stream);
3550 gpgme_data_release (inp_data);
3555 err = gt_spawn (server->gt, line, inp_data, out_data);
3557 gpgme_data_release (inp_data);
3558 gpgme_data_release (out_data);
3560 server_reset_fds (server);
3566 /* Tell the assuan library about our commands. */
3568 register_commands (assuan_context_t ctx)
3573 assuan_handler_t handler;
3574 const char * const help;
3576 /* RESET, BYE are implicit. */
3577 { "VERSION", cmd_version, hlp_version },
3578 /* TODO: Set engine info. */
3579 { "ENGINE", cmd_engine, hlp_engine },
3580 { "PROTOCOL", cmd_protocol, hlp_protocol },
3581 { "SUB_PROTOCOL", cmd_sub_protocol, hlp_sub_protocol },
3582 { "PINENTRY_MODE", cmd_pinentry_mode, hlp_pinentry_mode },
3583 { "ARMOR", cmd_armor, hlp_armor },
3584 { "TEXTMODE", cmd_textmode, hlp_textmode },
3585 { "INCLUDE_CERTS", cmd_include_certs, hlp_include_certs },
3586 { "KEYLIST_MODE", cmd_keylist_mode, hlp_keylist_mode },
3587 { "INPUT", cmd_input, hlp_input },
3588 { "OUTPUT", cmd_output, hlp_output },
3589 { "MESSAGE", cmd_message, hlp_message },
3590 { "RECIPIENT", cmd_recipient, hlp_recipient },
3591 { "SIGNER", cmd_signer, hlp_signer },
3592 { "SIGNERS_CLEAR", cmd_signers_clear, hlp_signers_clear },
3593 /* TODO: SIGNOTATION missing. */
3594 /* TODO: Could add wait interface if we allow more than one context */
3595 /* and add _START variants. */
3596 /* TODO: Could add data interfaces if we allow multiple data objects. */
3597 { "DECRYPT", cmd_decrypt, hlp_decrypt },
3598 { "DECRYPT_VERIFY", cmd_decrypt_verify, hlp_decrypt_verify },
3599 { "ENCRYPT", cmd_encrypt, hlp_encrypt },
3600 { "ENCRYPT_SIGN", cmd_sign_encrypt, hlp_sign_encrypt },
3601 { "SIGN_ENCRYPT", cmd_sign_encrypt, hlp_sign_encrypt },
3602 { "SIGN", cmd_sign, hlp_sign },
3603 { "VERIFY", cmd_verify, hlp_verify },
3604 { "IMPORT", cmd_import, hlp_import },
3605 { "EXPORT", cmd_export, hlp_export },
3606 { "GENKEY", cmd_genkey },
3607 { "DELETE", cmd_delete },
3608 /* TODO: EDIT, CARD_EDIT (with INQUIRE) */
3609 { "KEYLIST", cmd_keylist, hlp_keylist },
3610 { "LISTKEYS", cmd_keylist, hlp_keylist },
3611 /* TODO: TRUSTLIST, TRUSTLIST_EXT */
3612 { "GETAUDITLOG", cmd_getauditlog, hlp_getauditlog },
3614 { "VFS_MOUNT", cmd_vfs_mount },
3615 { "MOUNT", cmd_vfs_mount },
3616 { "VFS_CREATE", cmd_vfs_create },
3617 { "CREATE", cmd_vfs_create },
3619 { "RESULT", cmd_result },
3620 { "STRERROR", cmd_strerror },
3621 { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
3622 { "HASH_ALGO_NAME", cmd_hash_algo_name },
3623 { "PASSWD", cmd_passwd, hlp_passwd },
3624 { "IDENTIFY", cmd_identify, hlp_identify },
3625 { "SPAWN", cmd_spawn, hlp_spawn },
3630 for (idx = 0; table[idx].name; idx++)
3632 err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
3642 gpgme_server (gpgme_tool_t gt)
3645 assuan_fd_t filedes[2];
3646 struct server server;
3647 static const char hello[] = ("GPGME-Tool " VERSION " ready");
3649 memset (&server, 0, sizeof (server));
3650 server.input_fd = ASSUAN_INVALID_FD;
3651 server.output_fd = ASSUAN_INVALID_FD;
3652 server.message_fd = ASSUAN_INVALID_FD;
3653 server.input_enc = GPGME_DATA_ENCODING_NONE;
3654 server.output_enc = GPGME_DATA_ENCODING_NONE;
3655 server.message_enc = GPGME_DATA_ENCODING_NONE;
3658 gt->write_status = server_write_status;
3659 gt->write_status_hook = &server;
3660 gt->write_data = server_write_data;
3661 gt->write_data_hook = &server;
3663 /* We use a pipe based server so that we can work from scripts.
3664 assuan_init_pipe_server will automagically detect when we are
3665 called with a socketpair and ignore FIELDES in this case. */
3666 #ifdef HAVE_W32CE_SYSTEM
3667 filedes[0] = ASSUAN_STDIN;
3668 filedes[1] = ASSUAN_STDOUT;
3670 filedes[0] = assuan_fdopen (0);
3671 filedes[1] = assuan_fdopen (1);
3673 err = assuan_new (&server.assuan_ctx);
3675 log_error (1, err, "can't create assuan context");
3677 assuan_set_pointer (server.assuan_ctx, &server);
3679 err = assuan_init_pipe_server (server.assuan_ctx, filedes);
3681 log_error (1, err, "can't initialize assuan server");
3682 err = register_commands (server.assuan_ctx);
3684 log_error (1, err, "can't register assuan commands");
3685 assuan_set_hello_line (server.assuan_ctx, hello);
3687 assuan_register_reset_notify (server.assuan_ctx, reset_notify);
3689 #define DBG_ASSUAN 0
3691 assuan_set_log_stream (server.assuan_ctx, log_stream);
3695 err = assuan_accept (server.assuan_ctx);
3700 log_error (0, err, "assuan accept problem");
3704 err = assuan_process (server.assuan_ctx);
3706 log_error (0, err, "assuan processing failed");
3709 assuan_release (server.assuan_ctx);
3714 /* MAIN PROGRAM STARTS HERE. */
3716 const char *argp_program_version = VERSION;
3717 const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
3718 error_t argp_err_exit_status = 1;
3720 static char doc[] = "GPGME Tool -- Assuan server exposing GPGME operations";
3721 static char args_doc[] = "COMMAND [OPTIONS...]";
3723 static struct argp_option options[] = {
3724 { "server", 's', 0, 0, "Server mode" },
3725 { "gpg-binary", 501, "FILE", 0, "Use FILE for the GPG backend" },
3729 static error_t parse_options (int key, char *arg, struct argp_state *state);
3730 static struct argp argp = { options, parse_options, args_doc, doc };
3734 enum { CMD_DEFAULT, CMD_SERVER } cmd;
3735 const char *gpg_binary;
3739 args_init (struct args *args)
3741 memset (args, '\0', sizeof (*args));
3742 args->cmd = CMD_DEFAULT;
3747 parse_options (int key, char *arg, struct argp_state *state)
3749 struct args *args = state->input;
3754 args->cmd = CMD_SERVER;
3758 args->gpg_binary = arg;
3762 if (state->arg_num >= 2)
3764 printf ("Arg[%i] = %s\n", state->arg_num, arg);
3767 if (state->arg_num < 2)
3773 return ARGP_ERR_UNKNOWN;
3780 main (int argc, char *argv[])
3783 struct gpgme_tool gt;
3786 #ifdef HAVE_SETLOCALE
3787 setlocale (LC_ALL, "");
3789 gpgme_check_version (NULL);
3791 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
3794 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
3799 argp_parse (&argp, argc, argv, 0, 0, &args);
3802 if (args.gpg_binary)
3804 if (access (args.gpg_binary, X_OK))
3805 err = gpg_error_from_syserror ();
3807 err = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP,
3808 args.gpg_binary, NULL);
3810 log_error (1, err, "error witching OpenPGP engine to '%s'",
3824 gpgme_release (gt.ctx);
3826 #ifdef HAVE_W32CE_SYSTEM
3827 /* Give the buggy ssh server time to flush the output buffers. */