1 /* gpgme-tool.c - Assuan server exposing GnuPG Made Easy operations.
2 Copyright (C) 2009, 2010 g10 Code GmbH
4 This file is part of GPGME.
6 GPGME is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of
9 the License, or (at your option) any later version.
11 GPGME is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this program; if not, see <http://www.gnu.org/licenses/>.
44 # define GT_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a)))
46 # define GT_GCC_A_SENTINEL(a)
49 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
50 # define GT_GCC_A_PRINTF(f, a) __attribute__ ((format (printf,f,a)))
52 # define GT_GCC_A_PRINTF(f, a)
55 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
56 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
57 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
58 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
63 /* Minimal argp implementation. */
65 /* Differences to ARGP:
66 argp_program_version: Required.
67 argp_program_bug_address: Required.
68 argp_program_version_hook: Not supported.
69 argp_err_exit_status: Required.
70 struct argp: Children and help_filter not supported.
71 argp_domain: Not supported.
72 struct argp_option: Group not supported. Options are printed in
73 order given. Flags OPTION_ALIAS, OPTION_DOC and OPTION_NO_USAGE
75 argp_parse: No flags are supported (ARGP_PARSE_ARGV0, ARGP_NO_ERRS,
76 ARGP_NO_ARGS, ARGP_IN_ORDER, ARGP_NO_HELP, ARGP_NO_EXIT,
77 ARGP_LONG_ONLY, ARGP_SILENT). ARGP must not be NULL.
78 argp_help: Flag ARGP_HELP_LONG_ONLY not supported.
79 argp_state: argc, argv, next may not be modified and should not be used. */
81 extern const char *argp_program_version;
82 extern const char *argp_program_bug_address;
83 extern error_t argp_err_exit_status;
90 #define OPTION_ARG_OPTIONAL 0x1
91 #define OPTION_HIDDEN 0x2
100 const struct argp *const root_argp;
117 # define ARGP_ERR_UNKNOWN EDEADLK /* POSIX */
119 # define ARGP_ERR_UNKNOWN EDEADLOCK /* *GNU/kFreebsd does not define this) */
121 #define ARGP_KEY_ARG 0
122 #define ARGP_KEY_ARGS 0x1000006
123 #define ARGP_KEY_END 0x1000001
124 #define ARGP_KEY_NO_ARGS 0x1000002
125 #define ARGP_KEY_INIT 0x1000003
126 #define ARGP_KEY_FINI 0x1000007
127 #define ARGP_KEY_SUCCESS 0x1000004
128 #define ARGP_KEY_ERROR 0x1000005
129 typedef error_t (*argp_parser_t) (int key, char *arg, struct argp_state *state);
133 const struct argp_option *options;
134 argp_parser_t parser;
135 const char *args_doc;
138 const struct argp_child *children;
139 char *(*help_filter) (int key, const char *text, void *input);
140 const char *argp_domain;
143 #define ARGP_HELP_USAGE ARGP_HELP_SHORT_USAGE
144 #define ARGP_HELP_SHORT_USAGE 0x02
145 #define ARGP_HELP_SEE 0x04
146 #define ARGP_HELP_LONG 0x08
147 #define ARGP_HELP_PRE_DOC 0x10
148 #define ARGP_HELP_POST_DOC 0x20
149 #define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
150 #define ARGP_HELP_BUG_ADDR 0x40
151 #define ARGP_HELP_EXIT_ERR 0x100
152 #define ARGP_HELP_EXIT_OK 0x200
153 #define ARGP_HELP_STD_ERR (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
154 #define ARGP_HELP_STD_USAGE \
155 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
156 #define ARGP_HELP_STD_HELP \
157 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
158 | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
161 void argp_error (const struct argp_state *state,
162 const char *fmt, ...) GT_GCC_A_PRINTF(2, 3);
167 _argp_pname (char *name)
170 char *bname = strrchr (pname, '/');
172 bname = strrchr (pname, '\\');
180 _argp_state_help (const struct argp *argp, const struct argp_state *state,
181 FILE *stream, unsigned flags, char *name)
186 if (flags & ARGP_HELP_SHORT_USAGE)
187 fprintf (stream, "Usage: %s [OPTIONS...] %s\n", name, argp->args_doc);
188 if (flags & ARGP_HELP_SEE)
189 fprintf (stream, "Try `%s --help' or `%s --usage' for more information.\n",
191 if (flags & ARGP_HELP_PRE_DOC)
195 strncpy (buf, argp->doc, sizeof (buf));
196 buf[sizeof (buf) - 1] = '\0';
197 end = strchr (buf, '\v');
200 fprintf (stream, "%s\n%s", buf, buf[0] ? "\n" : "");
202 if (flags & ARGP_HELP_LONG)
204 const struct argp_option *opt = argp->options;
208 char spaces[NSPACES + 1] = " ";
210 fprintf (stream, " ");
212 if (isascii (opt->key))
214 fprintf (stream, "-%c", opt->key);
218 fprintf (stream, ", ");
224 fprintf (stream, "--%s", opt->name);
225 len += 2 + strlen (opt->name);
227 if (opt->arg && (opt->flags & OPTION_ARG_OPTIONAL))
229 fprintf (stream, "[=%s]", opt->arg);
230 len += 3 + strlen (opt->arg);
234 fprintf (stream, "=%s", opt->arg);
235 len += 1 + strlen (opt->arg);
239 spaces[NSPACES - len] = '\0';
240 fprintf (stream, "%s%s\n", spaces, opt->doc);
243 fprintf (stream, " -?, --help Give this help list\n");
244 fprintf (stream, " --usage Give a short usage "
247 if (flags & ARGP_HELP_POST_DOC)
251 strncpy (buf, argp->doc, sizeof (buf));
252 buf[sizeof (buf) - 1] = '\0';
253 end = strchr (buf, '\v');
258 fprintf (stream, "\n%s\n", end);
260 fprintf (stream, "\nMandatory or optional arguments to long options are also mandatory or optional\n");
261 fprintf (stream, "for any corresponding short options.\n");
263 if (flags & ARGP_HELP_BUG_ADDR)
264 fprintf (stream, "\nReport bugs to %s.\n", argp_program_bug_address);
266 if (flags & ARGP_HELP_EXIT_ERR)
267 exit (argp_err_exit_status);
268 if (flags & ARGP_HELP_EXIT_OK)
274 argp_usage (const struct argp_state *state)
276 _argp_state_help (state->root_argp, state, state->err_stream,
277 ARGP_HELP_STD_USAGE, state->name);
282 argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
284 _argp_state_help (state->root_argp, state, stream, flags, state->name);
289 argp_error (const struct argp_state *state, const char *fmt, ...)
293 fprintf (state->err_stream, "%s: ", state->name);
295 vfprintf (state->err_stream, fmt, ap);
297 fprintf (state->err_stream, "\n");
298 argp_state_help (state, state->err_stream, ARGP_HELP_STD_ERR);
299 exit (argp_err_exit_status);
304 argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name)
306 _argp_state_help (argp, NULL, stream, flags, name);
311 argp_parse (const struct argp *argp, int argc,
312 char **argv, unsigned flags, int *arg_index, void *input)
315 struct argp_state state = { argp, argc, argv, 1, flags, 0, 0, input,
316 NULL, NULL, _argp_pname (argv[0]),
317 stderr, stdout, NULL };
318 /* All non-option arguments are collected at the beginning of
319 &argv[1] during processing. This is a counter for their number. */
320 int non_opt_args = 0;
322 rc = argp->parser (ARGP_KEY_INIT, NULL, &state);
323 if (rc && rc != ARGP_ERR_UNKNOWN)
326 while (state.next < state.argc - non_opt_args)
328 int idx = state.next;
331 if (! strcasecmp (state.argv[idx], "--"))
337 if (state.quoted || state.argv[idx][0] != '-')
339 char *arg_saved = state.argv[idx];
341 memmove (&state.argv[idx], &state.argv[idx + 1],
342 (state.argc - 1 - idx) * sizeof (char *));
343 state.argv[argc - 1] = arg_saved;
346 else if (! strcasecmp (state.argv[idx], "--help")
347 || !strcmp (state.argv[idx], "-?"))
349 argp_state_help (&state, state.out_stream, ARGP_HELP_STD_HELP);
351 else if (! strcasecmp (state.argv[idx], "--usage"))
353 argp_state_help (&state, state.out_stream,
354 ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
356 else if (! strcasecmp (state.argv[idx], "--version")
357 || !strcmp (state.argv[idx], "-V"))
359 fprintf (state.out_stream, "%s\n", argp_program_version);
364 /* Search for option and call parser with its KEY. */
365 int key = ARGP_KEY_ARG; /* Just some dummy value. */
366 const struct argp_option *opt = argp->options;
370 /* Check for --opt=value syntax. */
371 arg = strchr (state.argv[idx], '=');
378 if (state.argv[idx][1] != '-')
379 key = state.argv[idx][1];
381 while (! found && opt->key)
384 || (key == ARGP_KEY_ARG
385 && ! strcasecmp (&state.argv[idx][2], opt->name)))
387 if (arg && !opt->arg)
388 argp_error (&state, "Option %s does not take an argument",
390 if (opt->arg && state.next < state.argc
391 && state.argv[idx + 1][0] != '-')
393 arg = state.argv[idx + 1];
396 if (opt->arg && !(opt->flags & OPTION_ARG_OPTIONAL))
397 argp_error (&state, "Option %s requires an argument",
400 rc = argp->parser (opt->key, arg, &state);
401 if (rc == ARGP_ERR_UNKNOWN)
410 argp_error (&state, "Unknown option %s", state.argv[idx]);
414 while (state.next < state.argc)
416 /* Call parser for all non-option args. */
417 int idx = state.next;
419 rc = argp->parser (ARGP_KEY_ARG, state.argv[idx], &state);
420 if (rc && rc != ARGP_ERR_UNKNOWN)
422 if (rc == ARGP_ERR_UNKNOWN)
424 int old_next = state.next;
425 rc = argp->parser (ARGP_KEY_ARGS, NULL, &state);
426 if (rc == ARGP_ERR_UNKNOWN)
428 argp_error (&state, "Too many arguments");
431 if (! rc && state.next == old_next)
433 state.arg_num += state.argc - state.next;
434 state.next = state.argc;
441 if (state.arg_num == 0)
443 rc = argp->parser (ARGP_KEY_NO_ARGS, NULL, &state);
444 if (rc && rc != ARGP_ERR_UNKNOWN)
447 if (state.next == state.argc)
449 rc = argp->parser (ARGP_KEY_END, NULL, &state);
450 if (rc && rc != ARGP_ERR_UNKNOWN)
453 rc = argp->parser (ARGP_KEY_FINI, NULL, &state);
454 if (rc && rc != ARGP_ERR_UNKNOWN)
458 argp->parser (ARGP_KEY_SUCCESS, NULL, &state);
463 argp_error (&state, "unexpected error: %s", strerror (rc));
464 argp->parser (ARGP_KEY_ERROR, NULL, &state);
467 argp->parser (ARGP_KEY_FINI, NULL, &state);
470 *arg_index = state.next - 1;
479 char *program_name = "gpgme-tool";
481 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
484 void log_error (int status, gpg_error_t errnum,
485 const char *fmt, ...) GT_GCC_A_PRINTF(3,4);
496 log_error (int status, gpg_error_t errnum, const char *fmt, ...)
500 fprintf (log_stream, "%s: ", program_name);
502 vfprintf (log_stream, fmt, ap);
505 fprintf (log_stream, ": %s <%s>", gpg_strerror (errnum),
506 gpg_strsource (errnum));
507 fprintf (log_stream, "\n");
513 /* Note that it is sufficient to allocate the target string D as long
514 as the source string S, i.e.: strlen(s)+1;. D == S is allowed. */
516 strcpy_escaped_plus (char *d, const char *s)
520 if (*s == '%' && s[1] && s[2])
535 /* Check whether the option NAME appears in LINE. */
537 has_option (const char *line, const char *name)
540 int n = strlen (name);
542 s = strstr (line, name);
543 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
546 /* Skip over options. It is assumed that leading spaces have been
547 removed (this is the case for lines passed to a handler from
548 assuan). Blanks after the options are also removed. */
550 skip_options (char *line)
552 while ( *line == '-' && line[1] == '-' )
554 while (*line && !spacep (line))
556 while (spacep (line))
565 typedef gpg_error_t (*result_xml_write_cb_t) (void *hook, const void *buf,
568 struct result_xml_state
571 result_xml_write_cb_t cb;
577 int had_data[MAX_TAGS];
582 result_init (struct result_xml_state *state, int indent,
583 result_xml_write_cb_t cb, void *hook)
585 memset (state, '\0', sizeof (*state));
586 state->indent = indent;
593 result_xml_indent (struct result_xml_state *state)
595 char spaces[state->indent + 1];
597 for (i = 0; i < state->indent; i++)
600 return (*state->cb) (state->hook, spaces, i);
605 result_xml_tag_start (struct result_xml_state *state, char *name, ...)
607 result_xml_write_cb_t cb = state->cb;
608 void *hook = state->hook;
615 if (state->next_tag > 0)
617 if (! state->had_data[state->next_tag - 1])
619 (*cb) (hook, ">\n", 2);
620 (*cb) (hook, NULL, 0);
622 state->had_data[state->next_tag - 1] = 1;
625 result_xml_indent (state);
626 (*cb) (hook, "<", 1);
627 (*cb) (hook, name, strlen (name));
629 state->tag[state->next_tag] = name;
630 state->had_data[state->next_tag] = 0;
636 attr = va_arg (ap, char *);
640 attr_val = va_arg (ap, char *);
641 if (attr_val == NULL)
644 (*cb) (hook, " ", 1);
645 (*cb) (hook, attr, strlen (attr));
646 (*cb) (hook, "=\"", 2);
647 (*cb) (hook, attr_val, strlen (attr_val));
648 (*cb) (hook, "\"", 1);
656 result_xml_tag_data (struct result_xml_state *state, char *data)
658 result_xml_write_cb_t cb = state->cb;
659 void *hook = state->hook;
661 if (state->had_data[state->next_tag - 1])
663 (*cb) (hook, "\n", 2);
664 (*cb) (hook, NULL, 0);
665 result_xml_indent (state);
668 (*cb) (hook, ">", 1);
669 state->had_data[state->next_tag - 1] = 2;
671 (*cb) (hook, data, strlen (data));
678 result_xml_tag_end (struct result_xml_state *state)
680 result_xml_write_cb_t cb = state->cb;
681 void *hook = state->hook;
686 if (state->had_data[state->next_tag])
688 if (state->had_data[state->next_tag] == 1)
689 result_xml_indent (state);
690 (*cb) (hook, "</", 2);
691 (*cb) (hook, state->tag[state->next_tag],
692 strlen (state->tag[state->next_tag]));
693 (*cb) (hook, ">\n", 2);
694 (*cb) (hook, NULL, 0);
698 (*cb) (hook, " />\n", 4);
699 (*cb) (hook, NULL, 0);
706 result_add_error (struct result_xml_state *state, char *name, gpg_error_t err)
710 snprintf (code, sizeof (code) - 1, "0x%x", err);
711 snprintf (msg, sizeof (msg) - 1, "%s <%s>",
712 gpg_strerror (err), gpg_strsource (err));
713 result_xml_tag_start (state, name, "value", code, NULL);
714 result_xml_tag_data (state, msg);
715 result_xml_tag_end (state);
721 result_add_pubkey_algo (struct result_xml_state *state,
722 char *name, gpgme_pubkey_algo_t algo)
726 snprintf (code, sizeof (code) - 1, "0x%x", algo);
727 snprintf (msg, sizeof (msg) - 1, "%s",
728 gpgme_pubkey_algo_name (algo));
729 result_xml_tag_start (state, name, "value", code, NULL);
730 result_xml_tag_data (state, msg);
731 result_xml_tag_end (state);
737 result_add_hash_algo (struct result_xml_state *state,
738 char *name, gpgme_hash_algo_t algo)
742 snprintf (code, sizeof (code) - 1, "0x%x", algo);
743 snprintf (msg, sizeof (msg) - 1, "%s",
744 gpgme_hash_algo_name (algo));
745 result_xml_tag_start (state, name, "value", code, NULL);
746 result_xml_tag_data (state, msg);
747 result_xml_tag_end (state);
753 result_add_keyid (struct result_xml_state *state, char *name, char *keyid)
755 result_xml_tag_start (state, name, NULL);
756 result_xml_tag_data (state, keyid);
757 result_xml_tag_end (state);
763 result_add_fpr (struct result_xml_state *state, char *name, char *fpr)
765 result_xml_tag_start (state, name, NULL);
766 result_xml_tag_data (state, fpr);
767 result_xml_tag_end (state);
773 result_add_timestamp (struct result_xml_state *state, char *name,
774 unsigned int timestamp)
778 snprintf (code, sizeof (code) - 1, "%ui", timestamp);
779 result_xml_tag_start (state, name, "unix", code, NULL);
780 result_xml_tag_end (state);
786 result_add_sig_mode (struct result_xml_state *state, char *name,
787 gpgme_sig_mode_t sig_mode)
792 snprintf (code, sizeof (code) - 1, "%i", sig_mode);
795 case GPGME_SIG_MODE_NORMAL:
798 case GPGME_SIG_MODE_DETACH:
801 case GPGME_SIG_MODE_CLEAR:
808 result_xml_tag_start (state, name, "type", mode, "value", code, NULL);
809 result_xml_tag_data (state, mode);
810 result_xml_tag_end (state);
816 result_add_value (struct result_xml_state *state,
817 char *name, unsigned int val)
821 snprintf (code, sizeof (code) - 1, "0x%x", val);
822 result_xml_tag_start (state, name, "value", code, NULL);
823 result_xml_tag_end (state);
829 result_add_string (struct result_xml_state *state,
830 char *name, char *str)
832 result_xml_tag_start (state, name, NULL);
833 result_xml_tag_data (state, str);
834 result_xml_tag_end (state);
840 result_encrypt_to_xml (gpgme_ctx_t ctx, int indent,
841 result_xml_write_cb_t cb, void *hook)
843 struct result_xml_state state;
844 gpgme_encrypt_result_t res = gpgme_op_encrypt_result (ctx);
845 gpgme_invalid_key_t inv_recp;
850 result_init (&state, indent, cb, hook);
851 result_xml_tag_start (&state, "encrypt-result", NULL);
853 inv_recp = res->invalid_recipients;
856 result_xml_tag_start (&state, "invalid-recipients", NULL);
860 result_xml_tag_start (&state, "invalid-key", NULL);
862 result_add_fpr (&state, "fpr", inv_recp->fpr);
863 result_add_error (&state, "reason", inv_recp->reason);
864 result_xml_tag_end (&state);
865 inv_recp = inv_recp->next;
867 result_xml_tag_end (&state);
869 result_xml_tag_end (&state);
876 result_decrypt_to_xml (gpgme_ctx_t ctx, int indent,
877 result_xml_write_cb_t cb, void *hook)
879 struct result_xml_state state;
880 gpgme_decrypt_result_t res = gpgme_op_decrypt_result (ctx);
881 gpgme_recipient_t recp;
886 result_init (&state, indent, cb, hook);
887 result_xml_tag_start (&state, "decrypt-result", NULL);
891 result_xml_tag_start (&state, "file-name", NULL);
892 result_xml_tag_data (&state, res->file_name);
893 result_xml_tag_end (&state);
895 if (res->unsupported_algorithm)
897 result_xml_tag_start (&state, "unsupported-alogorithm", NULL);
898 result_xml_tag_data (&state, res->unsupported_algorithm);
899 result_xml_tag_end (&state);
901 if (res->wrong_key_usage)
903 result_xml_tag_start (&state, "wrong-key-usage", NULL);
904 result_xml_tag_end (&state);
907 recp = res->recipients;
910 result_xml_tag_start (&state, "recipients", NULL);
913 result_xml_tag_start (&state, "recipient", NULL);
914 result_add_keyid (&state, "keyid", recp->keyid);
915 result_add_pubkey_algo (&state, "pubkey-algo", recp->pubkey_algo);
916 result_add_error (&state, "status", recp->status);
917 result_xml_tag_end (&state);
920 result_xml_tag_end (&state);
922 result_xml_tag_end (&state);
929 result_sign_to_xml (gpgme_ctx_t ctx, int indent,
930 result_xml_write_cb_t cb, void *hook)
932 struct result_xml_state state;
933 gpgme_sign_result_t res = gpgme_op_sign_result (ctx);
934 gpgme_invalid_key_t inv_key;
935 gpgme_new_signature_t new_sig;
940 result_init (&state, indent, cb, hook);
941 result_xml_tag_start (&state, "sign-result", NULL);
943 inv_key = res->invalid_signers;
946 result_xml_tag_start (&state, "invalid-signers", NULL);
950 result_xml_tag_start (&state, "invalid-key", NULL);
952 result_add_fpr (&state, "fpr", inv_key->fpr);
953 result_add_error (&state, "reason", inv_key->reason);
954 result_xml_tag_end (&state);
955 inv_key = inv_key->next;
957 result_xml_tag_end (&state);
960 new_sig = res->signatures;
963 result_xml_tag_start (&state, "signatures", NULL);
967 result_xml_tag_start (&state, "new-signature", NULL);
968 result_add_sig_mode (&state, "type", new_sig->type);
969 result_add_pubkey_algo (&state, "pubkey-algo", new_sig->pubkey_algo);
970 result_add_hash_algo (&state, "hash-algo", new_sig->hash_algo);
971 result_add_timestamp (&state, "timestamp", new_sig->timestamp);
973 result_add_fpr (&state, "fpr", new_sig->fpr);
974 result_add_value (&state, "sig-class", new_sig->sig_class);
976 result_xml_tag_end (&state);
977 new_sig = new_sig->next;
979 result_xml_tag_end (&state);
982 result_xml_tag_end (&state);
989 result_verify_to_xml (gpgme_ctx_t ctx, int indent,
990 result_xml_write_cb_t cb, void *hook)
992 struct result_xml_state state;
993 gpgme_verify_result_t res = gpgme_op_verify_result (ctx);
994 gpgme_signature_t sig;
999 result_init (&state, indent, cb, hook);
1000 result_xml_tag_start (&state, "verify-result", NULL);
1004 result_xml_tag_start (&state, "file-name", NULL);
1005 result_xml_tag_data (&state, res->file_name);
1006 result_xml_tag_end (&state);
1009 sig = res->signatures;
1012 result_xml_tag_start (&state, "signatures", NULL);
1016 result_xml_tag_start (&state, "signature", NULL);
1018 /* FIXME: Could be done better. */
1019 result_add_value (&state, "summary", sig->summary);
1021 result_add_fpr (&state, "fpr", sig->fpr);
1022 result_add_error (&state, "status", sig->status);
1023 /* FIXME: notations */
1024 result_add_timestamp (&state, "timestamp", sig->timestamp);
1025 result_add_timestamp (&state, "exp-timestamp", sig->exp_timestamp);
1026 result_add_value (&state, "wrong-key-usage", sig->wrong_key_usage);
1027 result_add_value (&state, "pka-trust", sig->pka_trust);
1028 result_add_value (&state, "chain-model", sig->chain_model);
1029 result_add_value (&state, "validity", sig->validity);
1030 result_add_error (&state, "validity-reason", sig->validity_reason);
1031 result_add_pubkey_algo (&state, "pubkey-algo", sig->pubkey_algo);
1032 result_add_hash_algo (&state, "hash-algo", sig->hash_algo);
1033 if (sig->pka_address)
1034 result_add_string (&state, "pka_address", sig->pka_address);
1036 result_xml_tag_end (&state);
1039 result_xml_tag_end (&state);
1042 result_xml_tag_end (&state);
1049 result_import_to_xml (gpgme_ctx_t ctx, int indent,
1050 result_xml_write_cb_t cb, void *hook)
1052 struct result_xml_state state;
1053 gpgme_import_result_t res = gpgme_op_import_result (ctx);
1054 gpgme_import_status_t stat;
1059 result_init (&state, indent, cb, hook);
1060 result_xml_tag_start (&state, "import-result", NULL);
1062 result_add_value (&state, "considered", res->considered);
1063 result_add_value (&state, "no-user-id", res->no_user_id);
1064 result_add_value (&state, "imported", res->imported);
1065 result_add_value (&state, "imported-rsa", res->imported_rsa);
1066 result_add_value (&state, "unchanged", res->unchanged);
1067 result_add_value (&state, "new-user-ids", res->new_user_ids);
1068 result_add_value (&state, "new-sub-keys", res->new_sub_keys);
1069 result_add_value (&state, "new-signatures", res->new_signatures);
1070 result_add_value (&state, "new-revocations", res->new_revocations);
1071 result_add_value (&state, "secret-read", res->secret_read);
1072 result_add_value (&state, "secret-imported", res->secret_imported);
1073 result_add_value (&state, "secret-unchanged", res->secret_unchanged);
1074 result_add_value (&state, "skipped-new-keys", res->skipped_new_keys);
1075 result_add_value (&state, "not-imported", res->not_imported);
1077 stat = res->imports;
1080 result_xml_tag_start (&state, "imports", NULL);
1084 result_xml_tag_start (&state, "import-status", NULL);
1087 result_add_fpr (&state, "fpr", stat->fpr);
1088 result_add_error (&state, "result", stat->result);
1089 /* FIXME: Could be done better. */
1090 result_add_value (&state, "status", stat->status);
1092 result_xml_tag_end (&state);
1095 result_xml_tag_end (&state);
1098 result_xml_tag_end (&state);
1105 result_genkey_to_xml (gpgme_ctx_t ctx, int indent,
1106 result_xml_write_cb_t cb, void *hook)
1108 struct result_xml_state state;
1109 gpgme_genkey_result_t res = gpgme_op_genkey_result (ctx);
1114 result_init (&state, indent, cb, hook);
1115 result_xml_tag_start (&state, "genkey-result", NULL);
1117 result_add_value (&state, "primary", res->primary);
1118 result_add_value (&state, "sub", res->sub);
1120 result_add_fpr (&state, "fpr", res->fpr);
1122 result_xml_tag_end (&state);
1129 result_keylist_to_xml (gpgme_ctx_t ctx, int indent,
1130 result_xml_write_cb_t cb, void *hook)
1132 struct result_xml_state state;
1133 gpgme_keylist_result_t res = gpgme_op_keylist_result (ctx);
1138 result_init (&state, indent, cb, hook);
1139 result_xml_tag_start (&state, "keylist-result", NULL);
1141 result_add_value (&state, "truncated", res->truncated);
1143 result_xml_tag_end (&state);
1150 result_vfs_mount_to_xml (gpgme_ctx_t ctx, int indent,
1151 result_xml_write_cb_t cb, void *hook)
1153 struct result_xml_state state;
1154 gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (ctx);
1159 result_init (&state, indent, cb, hook);
1160 result_xml_tag_start (&state, "vfs-mount-result", NULL);
1162 result_add_string (&state, "mount-dir", res->mount_dir);
1164 result_xml_tag_end (&state);
1177 STATUS_INCLUDE_CERTS,
1178 STATUS_KEYLIST_MODE,
1180 STATUS_ENCRYPT_RESULT
1183 const char *status_string[] =
1199 #define MAX_RECIPIENTS 10
1200 gpgme_key_t recipients[MAX_RECIPIENTS + 1];
1203 gpg_error_t (*write_status) (void *hook, const char *status, const char *msg);
1204 void *write_status_hook;
1205 gpg_error_t (*write_data) (void *hook, const void *buf, size_t len);
1206 void *write_data_hook;
1208 typedef struct gpgme_tool *gpgme_tool_t;
1211 /* Forward declaration. */
1212 void gt_write_status (gpgme_tool_t gt,
1213 status_t status, ...) GT_GCC_A_SENTINEL(0);
1216 _gt_progress_cb (void *opaque, const char *what,
1217 int type, int current, int total)
1219 gpgme_tool_t gt = opaque;
1222 snprintf (buf, sizeof (buf), "0x%02x %i %i", type, current, total);
1223 gt_write_status (gt, STATUS_PROGRESS, what, buf, NULL);
1228 _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
1232 err = gpgme_new (ctx);
1235 gpgme_set_progress_cb (*ctx, _gt_progress_cb, gt);
1241 gt_init (gpgme_tool_t gt)
1243 memset (gt, '\0', sizeof (*gt));
1246 err = _gt_gpgme_new (gt, >->ctx);
1248 log_error (1, err, "can't create gpgme context");
1253 gt_signers_add (gpgme_tool_t gt, const char *fpr)
1258 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1262 return gpgme_signers_add (gt->ctx, key);
1267 gt_signers_clear (gpgme_tool_t gt)
1269 gpgme_signers_clear (gt->ctx);
1275 gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key)
1278 gpgme_ctx_t listctx;
1282 if (!gt || !r_key || !pattern)
1283 return gpg_error (GPG_ERR_INV_VALUE);
1287 err = gpgme_new (&listctx);
1292 gpgme_protocol_t proto;
1293 gpgme_engine_info_t info;
1295 /* Clone the relevant state. */
1296 proto = gpgme_get_protocol (ctx);
1297 /* The g13 protocol does not allow keylisting, we need to choose
1299 if (proto == GPGME_PROTOCOL_G13)
1300 proto = GPGME_PROTOCOL_OpenPGP;
1302 gpgme_set_protocol (listctx, proto);
1303 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1304 info = gpgme_ctx_get_engine_info (ctx);
1305 while (info && info->protocol != proto)
1308 gpgme_ctx_set_engine_info (listctx, proto,
1309 info->file_name, info->home_dir);
1312 err = gpgme_op_keylist_start (listctx, pattern, 0);
1314 err = gpgme_op_keylist_next (listctx, r_key);
1318 err = gpgme_op_keylist_next (listctx, &key);
1319 if (gpgme_err_code (err) == GPG_ERR_EOF)
1324 && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1325 && key && key->subkeys && key->subkeys->fpr
1326 && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1328 /* The fingerprint is identical. We assume that this is
1329 the same key and don't mark it as an ambiguous. This
1330 problem may occur with corrupted keyrings and has
1331 been noticed often with gpgsm. In fact gpgsm uses a
1332 similar hack to sort out such duplicates but it can't
1333 do that while listing keys. */
1334 gpgme_key_unref (key);
1339 gpgme_key_unref (key);
1340 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1342 gpgme_key_unref (*r_key);
1345 gpgme_release (listctx);
1348 gt_write_status (gt, STATUS_RECIPIENT,
1349 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1350 (*r_key)->subkeys->fpr : "invalid", NULL);
1356 gt_recipients_add (gpgme_tool_t gt, const char *pattern)
1361 if (gt->recipients_nr >= MAX_RECIPIENTS)
1362 return gpg_error_from_errno (ENOMEM);
1364 if (gpgme_get_protocol (gt->ctx) == GPGME_PROTOCOL_UISERVER)
1365 err = gpgme_key_from_uid (&key, pattern);
1367 err = gt_get_key (gt, pattern, &key);
1371 gt->recipients[gt->recipients_nr++] = key;
1377 gt_recipients_clear (gpgme_tool_t gt)
1381 for (idx = 0; idx < gt->recipients_nr; idx++)
1382 gpgme_key_unref (gt->recipients[idx]);
1383 memset (gt->recipients, '\0', gt->recipients_nr * sizeof (gpgme_key_t));
1384 gt->recipients_nr = 0;
1389 gt_reset (gpgme_tool_t gt)
1394 err = _gt_gpgme_new (gt, &ctx);
1398 gpgme_release (gt->ctx);
1400 gt_recipients_clear (gt);
1406 gt_write_status (gpgme_tool_t gt, status_t status, ...)
1415 va_start (ap, status);
1418 while ((text = va_arg (ap, const char *)))
1425 while (*text && n < sizeof (buf) - 2)
1434 err = gt->write_status (gt->write_status_hook, status_string[status], buf);
1436 log_error (1, err, "can't write status line");
1441 gt_write_data (gpgme_tool_t gt, const void *buf, size_t len)
1443 return gt->write_data (gt->write_data_hook, buf, len);
1448 gt_get_engine_info (gpgme_tool_t gt, gpgme_protocol_t proto)
1450 gpgme_engine_info_t info;
1451 info = gpgme_ctx_get_engine_info (gt->ctx);
1454 if (proto == GPGME_PROTOCOL_UNKNOWN || proto == info->protocol)
1455 gt_write_status (gt, STATUS_ENGINE,
1456 gpgme_get_protocol_name (info->protocol),
1457 info->file_name, info->version,
1458 info->req_version, info->home_dir, NULL);
1466 gt_protocol_from_name (const char *name)
1468 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_OpenPGP)))
1469 return GPGME_PROTOCOL_OpenPGP;
1470 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_CMS)))
1471 return GPGME_PROTOCOL_CMS;
1472 if (! strcasecmp (name,gpgme_get_protocol_name (GPGME_PROTOCOL_GPGCONF)))
1473 return GPGME_PROTOCOL_GPGCONF;
1474 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_ASSUAN)))
1475 return GPGME_PROTOCOL_ASSUAN;
1476 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_G13)))
1477 return GPGME_PROTOCOL_G13;
1478 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_UISERVER)))
1479 return GPGME_PROTOCOL_UISERVER;
1480 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_DEFAULT)))
1481 return GPGME_PROTOCOL_DEFAULT;
1482 return GPGME_PROTOCOL_UNKNOWN;
1487 gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1489 return gpgme_set_protocol (gt->ctx, proto);
1494 gt_get_protocol (gpgme_tool_t gt)
1496 gpgme_protocol_t proto = gpgme_get_protocol (gt->ctx);
1498 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1506 gt_set_sub_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1508 return gpgme_set_sub_protocol (gt->ctx, proto);
1513 gt_get_sub_protocol (gpgme_tool_t gt)
1515 gpgme_protocol_t proto = gpgme_get_sub_protocol (gt->ctx);
1517 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1525 gt_set_armor (gpgme_tool_t gt, int armor)
1527 gpgme_set_armor (gt->ctx, armor);
1533 gt_get_armor (gpgme_tool_t gt)
1535 gt_write_status (gt, STATUS_ARMOR,
1536 gpgme_get_armor (gt->ctx) ? "true" : "false", NULL);
1543 gt_set_textmode (gpgme_tool_t gt, int textmode)
1545 gpgme_set_textmode (gt->ctx, textmode);
1551 gt_get_textmode (gpgme_tool_t gt)
1553 gt_write_status (gt, STATUS_TEXTMODE,
1554 gpgme_get_textmode (gt->ctx) ? "true" : "false", NULL);
1561 gt_set_keylist_mode (gpgme_tool_t gt, gpgme_keylist_mode_t keylist_mode)
1563 gpgme_set_keylist_mode (gt->ctx, keylist_mode);
1569 gt_get_keylist_mode (gpgme_tool_t gt)
1571 #define NR_KEYLIST_MODES 6
1572 const char *modes[NR_KEYLIST_MODES + 1];
1574 gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx);
1576 if (mode & GPGME_KEYLIST_MODE_LOCAL)
1577 modes[idx++] = "local";
1578 if (mode & GPGME_KEYLIST_MODE_EXTERN)
1579 modes[idx++] = "extern";
1580 if (mode & GPGME_KEYLIST_MODE_SIGS)
1581 modes[idx++] = "sigs";
1582 if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
1583 modes[idx++] = "sig_notations";
1584 if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
1585 modes[idx++] = "ephemeral";
1586 if (mode & GPGME_KEYLIST_MODE_VALIDATE)
1587 modes[idx++] = "validate";
1588 modes[idx++] = NULL;
1590 gt_write_status (gt, STATUS_KEYLIST_MODE, modes[0], modes[1], modes[2],
1591 modes[3], modes[4], modes[5], modes[6], NULL);
1598 gt_set_include_certs (gpgme_tool_t gt, int include_certs)
1600 gpgme_set_include_certs (gt->ctx, include_certs);
1606 gt_get_include_certs (gpgme_tool_t gt)
1608 int include_certs = gpgme_get_include_certs (gt->ctx);
1611 if (include_certs == GPGME_INCLUDE_CERTS_DEFAULT)
1612 strcpy (buf, "default");
1614 snprintf (buf, sizeof (buf), "%i", include_certs);
1616 gt_write_status (gt, STATUS_INCLUDE_CERTS, buf, NULL);
1623 gt_decrypt_verify (gpgme_tool_t gt, gpgme_data_t cipher, gpgme_data_t plain,
1627 return gpgme_op_decrypt_verify (gt->ctx, cipher, plain);
1629 return gpgme_op_decrypt (gt->ctx, cipher, plain);
1634 gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
1635 gpgme_data_t plain, gpgme_data_t cipher, int sign)
1640 err = gpgme_op_encrypt_sign (gt->ctx, gt->recipients, flags, plain, cipher);
1642 err = gpgme_op_encrypt (gt->ctx, gt->recipients, flags, plain, cipher);
1644 gt_recipients_clear (gt);
1651 gt_sign (gpgme_tool_t gt, gpgme_data_t plain, gpgme_data_t sig,
1652 gpgme_sig_mode_t mode)
1654 return gpgme_op_sign (gt->ctx, plain, sig, mode);
1659 gt_verify (gpgme_tool_t gt, gpgme_data_t sig, gpgme_data_t sig_text,
1662 return gpgme_op_verify (gt->ctx, sig, sig_text, plain);
1667 gt_import (gpgme_tool_t gt, gpgme_data_t data)
1669 return gpgme_op_import (gt->ctx, data);
1674 gt_export (gpgme_tool_t gt, const char *pattern[], gpgme_export_mode_t mode,
1677 return gpgme_op_export_ext (gt->ctx, pattern, mode, data);
1682 gt_genkey (gpgme_tool_t gt, const char *parms, gpgme_data_t public,
1683 gpgme_data_t secret)
1685 return gpgme_op_genkey (gt->ctx, parms, public, secret);
1690 gt_import_keys (gpgme_tool_t gt, char *fpr[])
1692 gpg_error_t err = 0;
1702 return gpg_error (GPG_ERR_INV_VALUE);
1704 keys = malloc ((cnt + 1) * sizeof (gpgme_key_t));
1706 return gpg_error_from_syserror ();
1708 for (idx = 0; idx < cnt; idx++)
1710 err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0);
1717 err = gpgme_op_import_keys (gt->ctx, keys);
1722 gpgme_key_unref (keys[idx]);
1730 gt_delete (gpgme_tool_t gt, char *fpr, int allow_secret)
1735 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1739 err = gpgme_op_delete (gt->ctx, key, allow_secret);
1740 gpgme_key_unref (key);
1746 gt_keylist_start (gpgme_tool_t gt, const char *pattern[], int secret_only)
1748 return gpgme_op_keylist_ext_start (gt->ctx, pattern, secret_only, 0);
1753 gt_keylist_next (gpgme_tool_t gt, gpgme_key_t *key)
1755 return gpgme_op_keylist_next (gt->ctx, key);
1760 gt_getauditlog (gpgme_tool_t gt, gpgme_data_t output, unsigned int flags)
1762 return gpgme_op_getauditlog (gt->ctx, output, flags);
1767 gt_vfs_mount (gpgme_tool_t gt, const char *container_file,
1768 const char *mount_dir, int flags)
1772 err = gpgme_op_vfs_mount (gt->ctx, container_file, mount_dir, flags, &op_err);
1773 return err ? err : op_err;
1778 gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
1782 err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file,
1784 gt_recipients_clear (gt);
1785 return err ? err : op_err;
1789 static const char hlp_passwd[] =
1790 "PASSWD <user-id>\n"
1792 "Ask the backend to change the passphrase for the key\n"
1793 "specified by USER-ID.";
1795 gt_passwd (gpgme_tool_t gt, char *fpr)
1800 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1802 return gpg_err_code (err) == GPG_ERR_EOF? gpg_error (GPG_ERR_NO_PUBKEY):err;
1804 err = gpgme_op_passwd (gt->ctx, key, 0);
1805 gpgme_key_unref (key);
1810 #define GT_RESULT_ENCRYPT 0x1
1811 #define GT_RESULT_DECRYPT 0x2
1812 #define GT_RESULT_SIGN 0x4
1813 #define GT_RESULT_VERIFY 0x8
1814 #define GT_RESULT_IMPORT 0x10
1815 #define GT_RESULT_GENKEY 0x20
1816 #define GT_RESULT_KEYLIST 0x40
1817 #define GT_RESULT_VFS_MOUNT 0x80
1818 #define GT_RESULT_ALL (~0U)
1821 gt_result (gpgme_tool_t gt, unsigned int flags)
1823 static const char xml_preamble1[] = "<?xml version=\"1.0\" "
1824 "encoding=\"UTF-8\" standalone=\"yes\"?>\n";
1825 static const char xml_preamble2[] = "<gpgme>\n";
1826 static const char xml_end[] = "</gpgme>\n";
1829 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
1830 gt_write_data (gt, NULL, 0);
1831 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
1832 gt_write_data (gt, NULL, 0);
1833 if (flags & GT_RESULT_ENCRYPT)
1834 result_encrypt_to_xml (gt->ctx, indent,
1835 (result_xml_write_cb_t) gt_write_data, gt);
1836 if (flags & GT_RESULT_DECRYPT)
1837 result_decrypt_to_xml (gt->ctx, indent,
1838 (result_xml_write_cb_t) gt_write_data, gt);
1839 if (flags & GT_RESULT_SIGN)
1840 result_sign_to_xml (gt->ctx, indent,
1841 (result_xml_write_cb_t) gt_write_data, gt);
1842 if (flags & GT_RESULT_VERIFY)
1843 result_verify_to_xml (gt->ctx, indent,
1844 (result_xml_write_cb_t) gt_write_data, gt);
1845 if (flags & GT_RESULT_IMPORT)
1846 result_import_to_xml (gt->ctx, indent,
1847 (result_xml_write_cb_t) gt_write_data, gt);
1848 if (flags & GT_RESULT_GENKEY)
1849 result_genkey_to_xml (gt->ctx, indent,
1850 (result_xml_write_cb_t) gt_write_data, gt);
1851 if (flags & GT_RESULT_KEYLIST)
1852 result_keylist_to_xml (gt->ctx, indent,
1853 (result_xml_write_cb_t) gt_write_data, gt);
1854 if (flags & GT_RESULT_VFS_MOUNT)
1855 result_vfs_mount_to_xml (gt->ctx, indent,
1856 (result_xml_write_cb_t) gt_write_data, gt);
1857 gt_write_data (gt, xml_end, sizeof (xml_end));
1870 assuan_context_t assuan_ctx;
1872 gpgme_data_encoding_t input_enc;
1873 gpgme_data_encoding_t output_enc;
1874 assuan_fd_t input_fd;
1875 char *input_filename;
1877 assuan_fd_t output_fd;
1878 char *output_filename;
1879 FILE *output_stream;
1880 assuan_fd_t message_fd;
1881 char *message_filename;
1882 FILE *message_stream;
1883 gpgme_data_encoding_t message_enc;
1888 server_write_status (void *hook, const char *status, const char *msg)
1890 struct server *server = hook;
1891 return assuan_write_status (server->assuan_ctx, status, msg);
1896 server_write_data (void *hook, const void *buf, size_t len)
1898 struct server *server = hook;
1899 return assuan_send_data (server->assuan_ctx, buf, len);
1905 server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd,
1908 *rfd = ASSUAN_INVALID_FD;
1911 if (! strncasecmp (line, "file=", 5))
1914 *filename = strdup (line + 5);
1916 return gpg_error_from_syserror();
1917 term = strchr (*filename, ' ');
1923 return assuan_command_parse_fd (ctx, line, rfd);
1927 static gpgme_data_encoding_t
1928 server_data_encoding (const char *line)
1930 if (strstr (line, "--binary"))
1931 return GPGME_DATA_ENCODING_BINARY;
1932 if (strstr (line, "--base64"))
1933 return GPGME_DATA_ENCODING_BASE64;
1934 if (strstr (line, "--armor"))
1935 return GPGME_DATA_ENCODING_ARMOR;
1936 if (strstr (line, "--url"))
1937 return GPGME_DATA_ENCODING_URL;
1938 if (strstr (line, "--urlesc"))
1939 return GPGME_DATA_ENCODING_URLESC;
1940 if (strstr (line, "--url0"))
1941 return GPGME_DATA_ENCODING_URL0;
1942 return GPGME_DATA_ENCODING_NONE;
1946 static gpgme_error_t
1947 server_data_obj (assuan_fd_t fd, char *fn, int out,
1948 gpgme_data_encoding_t encoding,
1949 gpgme_data_t *data, FILE **fs)
1956 *fs = fopen (fn, out ? "wb" : "rb");
1958 return gpg_error_from_syserror ();
1960 err = gpgme_data_new_from_stream (data, *fs);
1963 err = gpgme_data_new_from_fd (data, (int) fd);
1967 return gpgme_data_set_encoding (*data, encoding);
1972 server_reset_fds (struct server *server)
1974 /* assuan closes the input and output FDs for us when doing a RESET,
1975 but we use this same function after commands, so repeat it
1977 assuan_close_input_fd (server->assuan_ctx);
1978 assuan_close_output_fd (server->assuan_ctx);
1979 if (server->message_fd != ASSUAN_INVALID_FD)
1981 /* FIXME: Assuan should provide a close function. */
1983 CloseHandle (server->message_fd);
1985 close (server->message_fd);
1987 server->message_fd = ASSUAN_INVALID_FD;
1989 if (server->input_filename)
1991 free (server->input_filename);
1992 server->input_filename = NULL;
1994 if (server->output_filename)
1996 free (server->output_filename);
1997 server->output_filename = NULL;
1999 if (server->message_filename)
2001 free (server->message_filename);
2002 server->message_filename = NULL;
2004 if (server->input_stream)
2006 fclose (server->input_stream);
2007 server->input_stream = NULL;
2009 if (server->output_stream)
2011 fclose (server->output_stream);
2012 server->output_stream = NULL;
2014 if (server->message_stream)
2016 fclose (server->message_stream);
2017 server->message_stream = NULL;
2020 server->input_enc = GPGME_DATA_ENCODING_NONE;
2021 server->output_enc = GPGME_DATA_ENCODING_NONE;
2022 server->message_enc = GPGME_DATA_ENCODING_NONE;
2027 reset_notify (assuan_context_t ctx, char *line)
2029 struct server *server = assuan_get_pointer (ctx);
2030 server_reset_fds (server);
2031 gt_reset (server->gt);
2036 static const char hlp_version[] =
2037 "VERSION [<string>]\n"
2039 "Call the function gpgme_check_version.";
2041 cmd_version (assuan_context_t ctx, char *line)
2045 const char *version = gpgme_check_version (line);
2046 return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
2050 const char *version = gpgme_check_version (NULL);
2051 return assuan_send_data (ctx, version, strlen (version));
2056 static const char hlp_engine[] =
2057 "ENGINE [<string>]\n"
2059 "Get information about a GPGME engine (a.k.a. protocol).";
2061 cmd_engine (assuan_context_t ctx, char *line)
2063 struct server *server = assuan_get_pointer (ctx);
2064 return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
2068 static const char hlp_protocol[] =
2069 "PROTOCOL [<name>]\n"
2071 "With NAME, set the protocol. Without, return the current\n"
2074 cmd_protocol (assuan_context_t ctx, char *line)
2076 struct server *server = assuan_get_pointer (ctx);
2078 return gt_set_protocol (server->gt, gt_protocol_from_name (line));
2080 return gt_get_protocol (server->gt);
2084 static const char hlp_sub_protocol[] =
2085 "SUB_PROTOCOL [<name>]\n"
2087 "With NAME, set the sub-protocol. Without, return the\n"
2088 "current sub-protocol.";
2090 cmd_sub_protocol (assuan_context_t ctx, char *line)
2092 struct server *server = assuan_get_pointer (ctx);
2094 return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
2096 return gt_get_sub_protocol (server->gt);
2100 static const char hlp_armor[] =
2101 "ARMOR [true|false]\n"
2103 "With 'true' or 'false', turn output ASCII armoring on or\n"
2104 "off. Without, return the current armoring status.";
2106 cmd_armor (assuan_context_t ctx, char *line)
2108 struct server *server = assuan_get_pointer (ctx);
2113 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2117 return gt_set_armor (server->gt, flag);
2120 return gt_get_armor (server->gt);
2124 static const char hlp_textmode[] =
2125 "TEXTMODE [true|false]\n"
2127 "With 'true' or 'false', turn text mode on or off.\n"
2128 "Without, return the current text mode status.";
2130 cmd_textmode (assuan_context_t ctx, char *line)
2132 struct server *server = assuan_get_pointer (ctx);
2137 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2141 return gt_set_textmode (server->gt, flag);
2144 return gt_get_textmode (server->gt);
2148 static const char hlp_include_certs[] =
2149 "INCLUDE_CERTS [default|<n>]\n"
2151 "With DEFAULT or N, set how many certificates should be\n"
2152 "included in the next S/MIME signed message. See the\n"
2153 "GPGME documentation for details on the meaning of"
2154 "various N. Without either, return the current setting.";
2156 cmd_include_certs (assuan_context_t ctx, char *line)
2158 struct server *server = assuan_get_pointer (ctx);
2162 int include_certs = 0;
2164 if (! strcasecmp (line, "default"))
2165 include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
2167 include_certs = atoi (line);
2169 return gt_set_include_certs (server->gt, include_certs);
2172 return gt_get_include_certs (server->gt);
2176 static const char hlp_keylist_mode[] =
2177 "KEYLIST_MODE [local] [extern] [sigs] [sig_notations]\n"
2178 " [ephemeral] [validate]\n"
2180 "Set the mode for the next KEYLIST command.";
2182 cmd_keylist_mode (assuan_context_t ctx, char *line)
2184 struct server *server = assuan_get_pointer (ctx);
2188 gpgme_keylist_mode_t mode = 0;
2190 if (strstr (line, "local"))
2191 mode |= GPGME_KEYLIST_MODE_LOCAL;
2192 if (strstr (line, "extern"))
2193 mode |= GPGME_KEYLIST_MODE_EXTERN;
2194 if (strstr (line, "sigs"))
2195 mode |= GPGME_KEYLIST_MODE_SIGS;
2196 if (strstr (line, "sig_notations"))
2197 mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
2198 if (strstr (line, "ephemeral"))
2199 mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
2200 if (strstr (line, "validate"))
2201 mode |= GPGME_KEYLIST_MODE_VALIDATE;
2203 return gt_set_keylist_mode (server->gt, mode);
2206 return gt_get_keylist_mode (server->gt);
2210 static const char hlp_input[] =
2211 "INPUT [<fd>|FILE=<path>]\n"
2213 "Set the input for the next command. Use either the\n"
2214 "Assuan file descriptor FD or a filesystem PATH.";
2216 cmd_input (assuan_context_t ctx, char *line)
2218 struct server *server = assuan_get_pointer (ctx);
2223 err = server_parse_fd (ctx, line, &sysfd, &filename);
2226 server->input_fd = sysfd;
2227 server->input_filename = filename;
2228 server->input_enc = server_data_encoding (line);
2233 static const char hlp_output[] =
2234 "OUTPUT [<fd>|FILE=<path>]\n"
2236 "Set the output for the next command. Use either the\n"
2237 "Assuan file descriptor FD or a filesystem PATH.";
2239 cmd_output (assuan_context_t ctx, char *line)
2241 struct server *server = assuan_get_pointer (ctx);
2246 err = server_parse_fd (ctx, line, &sysfd, &filename);
2249 server->output_fd = sysfd;
2250 server->output_filename = filename;
2251 server->output_enc = server_data_encoding (line);
2256 static const char hlp_message[] =
2257 "MESSAGE [<fd>|FILE=<path>]\n"
2259 "Set the plaintext message for the next VERIFY command\n"
2260 "with a detached signature. Use either the Assuan file\n"
2261 "descriptor FD or a filesystem PATH.";
2263 cmd_message (assuan_context_t ctx, char *line)
2265 struct server *server = assuan_get_pointer (ctx);
2270 err = server_parse_fd (ctx, line, &sysfd, &filename);
2273 server->message_fd = sysfd;
2274 server->message_filename = filename;
2275 server->message_enc = server_data_encoding (line);
2280 static const char hlp_recipient[] =
2281 "RECIPIENT <pattern>\n"
2283 "Add the key matching PATTERN to the list of recipients\n"
2284 "for the next encryption command.";
2286 cmd_recipient (assuan_context_t ctx, char *line)
2288 struct server *server = assuan_get_pointer (ctx);
2290 return gt_recipients_add (server->gt, line);
2294 static const char hlp_signer[] =
2295 "SIGNER <fingerprint>\n"
2297 "Add the key with FINGERPRINT to the list of signers to\n"
2298 "be used for the next signing command.";
2300 cmd_signer (assuan_context_t ctx, char *line)
2302 struct server *server = assuan_get_pointer (ctx);
2304 return gt_signers_add (server->gt, line);
2308 static const char hlp_signers_clear[] =
2311 "Clear the list of signers specified by previous SIGNER\n"
2314 cmd_signers_clear (assuan_context_t ctx, char *line)
2316 struct server *server = assuan_get_pointer (ctx);
2318 return gt_signers_clear (server->gt);
2323 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
2325 struct server *server = assuan_get_pointer (ctx);
2331 gpgme_data_t inp_data;
2332 gpgme_data_t out_data;
2334 inp_fd = assuan_get_input_fd (ctx);
2335 inp_fn = server->input_filename;
2336 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2337 return GPG_ERR_ASS_NO_INPUT;
2338 out_fd = assuan_get_output_fd (ctx);
2339 out_fn = server->output_filename;
2340 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2341 return GPG_ERR_ASS_NO_OUTPUT;
2343 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2344 &server->input_stream);
2347 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2348 &server->output_stream);
2351 gpgme_data_release (inp_data);
2355 err = gt_decrypt_verify (server->gt, inp_data, out_data, verify);
2357 gpgme_data_release (inp_data);
2358 gpgme_data_release (out_data);
2360 server_reset_fds (server);
2366 static const char hlp_decrypt[] =
2369 "Decrypt the object set by the last INPUT command and\n"
2370 "write the decrypted message to the object set by the\n"
2371 "last OUTPUT command.";
2373 cmd_decrypt (assuan_context_t ctx, char *line)
2375 return _cmd_decrypt_verify (ctx, line, 0);
2379 static const char hlp_decrypt_verify[] =
2382 "Decrypt the object set by the last INPUT command and\n"
2383 "verify any embedded signatures. Write the decrypted\n"
2384 "message to the object set by the last OUTPUT command.";
2386 cmd_decrypt_verify (assuan_context_t ctx, char *line)
2388 return _cmd_decrypt_verify (ctx, line, 1);
2393 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
2395 struct server *server = assuan_get_pointer (ctx);
2401 gpgme_data_t inp_data = NULL;
2402 gpgme_data_t out_data = NULL;
2403 gpgme_encrypt_flags_t flags = 0;
2405 if (strstr (line, "--always-trust"))
2406 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
2407 if (strstr (line, "--no-encrypt-to"))
2408 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
2409 if (strstr (line, "--prepare"))
2410 flags |= GPGME_ENCRYPT_PREPARE;
2411 if (strstr (line, "--expect-sign"))
2412 flags |= GPGME_ENCRYPT_EXPECT_SIGN;
2414 inp_fd = assuan_get_input_fd (ctx);
2415 inp_fn = server->input_filename;
2416 out_fd = assuan_get_output_fd (ctx);
2417 out_fn = server->output_filename;
2418 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
2420 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2421 &server->input_stream);
2425 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2427 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2428 &server->output_stream);
2431 gpgme_data_release (inp_data);
2436 err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign);
2438 gpgme_data_release (inp_data);
2439 gpgme_data_release (out_data);
2441 server_reset_fds (server);
2447 static const char hlp_encrypt[] =
2448 "ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2449 " [--prepare] [--expect-sign]\n"
2451 "Encrypt the object set by the last INPUT command to\n"
2452 "the keys specified by previous RECIPIENT commands. \n"
2453 "Write the signed and encrypted message to the object\n"
2454 "set by the last OUTPUT command.";
2456 cmd_encrypt (assuan_context_t ctx, char *line)
2458 return _cmd_sign_encrypt (ctx, line, 0);
2462 static const char hlp_sign_encrypt[] =
2463 "SIGN_ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2464 " [--prepare] [--expect-sign]\n"
2466 "Sign the object set by the last INPUT command with the\n"
2467 "keys specified by previous SIGNER commands and encrypt\n"
2468 "it to the keys specified by previous RECIPIENT\n"
2469 "commands. Write the signed and encrypted message to\n"
2470 "the object set by the last OUTPUT command.";
2472 cmd_sign_encrypt (assuan_context_t ctx, char *line)
2474 return _cmd_sign_encrypt (ctx, line, 1);
2478 static const char hlp_sign[] =
2479 "SIGN [--clear|--detach]\n"
2481 "Sign the object set by the last INPUT command with the\n"
2482 "keys specified by previous SIGNER commands. Write the\n"
2483 "signed message to the object set by the last OUTPUT\n"
2484 "command. With `--clear`, generate a clear text\n"
2485 "signature. With `--detach`, generate a detached\n"
2488 cmd_sign (assuan_context_t ctx, char *line)
2490 struct server *server = assuan_get_pointer (ctx);
2496 gpgme_data_t inp_data;
2497 gpgme_data_t out_data;
2498 gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
2500 if (strstr (line, "--clear"))
2501 mode = GPGME_SIG_MODE_CLEAR;
2502 if (strstr (line, "--detach"))
2503 mode = GPGME_SIG_MODE_DETACH;
2505 inp_fd = assuan_get_input_fd (ctx);
2506 inp_fn = server->input_filename;
2507 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2508 return GPG_ERR_ASS_NO_INPUT;
2509 out_fd = assuan_get_output_fd (ctx);
2510 out_fn = server->output_filename;
2511 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2512 return GPG_ERR_ASS_NO_OUTPUT;
2514 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2515 &server->input_stream);
2518 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2519 &server->output_stream);
2522 gpgme_data_release (inp_data);
2526 err = gt_sign (server->gt, inp_data, out_data, mode);
2528 gpgme_data_release (inp_data);
2529 gpgme_data_release (out_data);
2530 server_reset_fds (server);
2536 static const char hlp_verify[] =
2539 "Verify signatures on the object set by the last INPUT\n"
2540 "and MESSAGE commands. If the message was encrypted,\n"
2541 "write the plaintext to the object set by the last\n"
2544 cmd_verify (assuan_context_t ctx, char *line)
2546 struct server *server = assuan_get_pointer (ctx);
2554 gpgme_data_t inp_data;
2555 gpgme_data_t msg_data = NULL;
2556 gpgme_data_t out_data = NULL;
2558 inp_fd = assuan_get_input_fd (ctx);
2559 inp_fn = server->input_filename;
2560 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2561 return GPG_ERR_ASS_NO_INPUT;
2562 msg_fd = server->message_fd;
2563 msg_fn = server->message_filename;
2564 out_fd = assuan_get_output_fd (ctx);
2565 out_fn = server->output_filename;
2567 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2568 &server->input_stream);
2571 if (msg_fd != ASSUAN_INVALID_FD || msg_fn)
2573 err = server_data_obj (msg_fd, msg_fn, 0, server->message_enc, &msg_data,
2574 &server->message_stream);
2577 gpgme_data_release (inp_data);
2581 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2583 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2584 &server->output_stream);
2587 gpgme_data_release (inp_data);
2588 gpgme_data_release (msg_data);
2593 err = gt_verify (server->gt, inp_data, msg_data, out_data);
2595 gpgme_data_release (inp_data);
2597 gpgme_data_release (msg_data);
2599 gpgme_data_release (out_data);
2601 server_reset_fds (server);
2607 static const char hlp_import[] =
2608 "IMPORT [<pattern>]\n"
2610 "With PATTERN, import the keys described by PATTERN.\n"
2611 "Without, read a key (or keys) from the object set by the\n"
2612 "last INPUT command.";
2614 cmd_import (assuan_context_t ctx, char *line)
2616 struct server *server = assuan_get_pointer (ctx);
2620 char *fprs[2] = { line, NULL };
2622 return gt_import_keys (server->gt, fprs);
2629 gpgme_data_t inp_data;
2631 inp_fd = assuan_get_input_fd (ctx);
2632 inp_fn = server->input_filename;
2633 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2634 return GPG_ERR_ASS_NO_INPUT;
2636 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2637 &server->input_stream);
2641 err = gt_import (server->gt, inp_data);
2643 gpgme_data_release (inp_data);
2644 server_reset_fds (server);
2651 static const char hlp_export[] =
2652 "EXPORT [--extern] [--minimal] [<pattern>]\n"
2654 "Export the keys described by PATTERN. Write the\n"
2655 "the output to the object set by the last OUTPUT command.";
2657 cmd_export (assuan_context_t ctx, char *line)
2659 struct server *server = assuan_get_pointer (ctx);
2663 gpgme_data_t out_data;
2664 gpgme_export_mode_t mode = 0;
2665 const char *pattern[2];
2667 out_fd = assuan_get_output_fd (ctx);
2668 out_fn = server->output_filename;
2669 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2670 return GPG_ERR_ASS_NO_OUTPUT;
2671 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2672 &server->output_stream);
2676 if (has_option (line, "--extern"))
2677 mode |= GPGME_EXPORT_MODE_EXTERN;
2678 if (has_option (line, "--minimal"))
2679 mode |= GPGME_EXPORT_MODE_MINIMAL;
2681 line = skip_options (line);
2686 err = gt_export (server->gt, pattern, mode, out_data);
2688 gpgme_data_release (out_data);
2689 server_reset_fds (server);
2696 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
2700 ssize_t writen = gpgme_data_write (data, buf, size);
2701 if (writen < 0 && errno != EAGAIN)
2702 return gpg_error_from_syserror ();
2703 else if (writen > 0)
2705 buf = (void *) (((char *) buf) + writen);
2714 cmd_genkey (assuan_context_t ctx, char *line)
2716 struct server *server = assuan_get_pointer (ctx);
2722 gpgme_data_t inp_data;
2723 gpgme_data_t out_data = NULL;
2724 gpgme_data_t parms_data = NULL;
2727 inp_fd = assuan_get_input_fd (ctx);
2728 inp_fn = server->input_filename;
2729 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2730 return GPG_ERR_ASS_NO_INPUT;
2731 out_fd = assuan_get_output_fd (ctx);
2732 out_fn = server->output_filename;
2734 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2735 &server->input_stream);
2738 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2740 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2741 &server->output_stream);
2744 gpgme_data_release (inp_data);
2749 /* Convert input data. */
2750 err = gpgme_data_new (&parms_data);
2756 ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
2759 err = gpg_error_from_syserror ();
2762 else if (readn == 0)
2765 err = _cmd_genkey_write (parms_data, buf, readn);
2770 err = _cmd_genkey_write (parms_data, "", 1);
2773 parms = gpgme_data_release_and_get_mem (parms_data, NULL);
2777 err = gpg_error (GPG_ERR_GENERAL);
2781 err = gt_genkey (server->gt, parms, out_data, NULL);
2783 server_reset_fds (server);
2786 gpgme_data_release (inp_data);
2788 gpgme_data_release (out_data);
2790 gpgme_data_release (parms_data);
2797 cmd_delete (assuan_context_t ctx, char *line)
2799 struct server *server = assuan_get_pointer (ctx);
2800 int allow_secret = 0;
2801 const char optstr[] = "--allow-secret";
2803 if (!strncasecmp (line, optstr, strlen (optstr)))
2806 line += strlen (optstr);
2807 while (*line && !spacep (line))
2810 return gt_delete (server->gt, line, allow_secret);
2814 static const char hlp_keylist[] =
2815 "KEYLIST [--secret-only] [<patterns>]\n"
2817 "List all certificates or only those specified by PATTERNS. Each\n"
2818 "pattern shall be a percent-plus escaped certificate specification.";
2820 cmd_keylist (assuan_context_t ctx, char *line)
2822 #define MAX_CMD_KEYLIST_PATTERN 20
2823 struct server *server = assuan_get_pointer (ctx);
2825 int secret_only = 0;
2827 const char *pattern[MAX_CMD_KEYLIST_PATTERN+1];
2828 const char optstr[] = "--secret-only";
2831 if (!strncasecmp (line, optstr, strlen (optstr)))
2834 line += strlen (optstr);
2835 while (*line && !spacep (line))
2840 for (p=line; *p; line = p)
2842 while (*p && *p != ' ')
2848 if (idx+1 == DIM (pattern))
2849 return gpg_error (GPG_ERR_TOO_MANY);
2850 strcpy_escaped_plus (line, line);
2851 pattern[idx++] = line;
2854 pattern[idx] = NULL;
2856 err = gt_keylist_start (server->gt, pattern, secret_only);
2861 err = gt_keylist_next (server->gt, &key);
2862 if (gpg_err_code (err) == GPG_ERR_EOF)
2870 /* FIXME: More data. */
2871 snprintf (buf, sizeof (buf), "key:%s\n", key->subkeys->fpr);
2872 /* Write data and flush so that we see one D line for each
2873 key. This does not change the semantics but is easier to
2874 read by organic eyes. */
2875 if (!assuan_send_data (ctx, buf, strlen (buf)))
2876 assuan_send_data (ctx, NULL, 0);
2877 gpgme_key_unref (key);
2881 server_reset_fds (server);
2887 static const char hlp_getauditlog[] =
2888 "GETAUDITLOG [--html] [--with-help]\n"
2890 "Call the function gpgme_op_getauditlog with the given flags. Write\n"
2891 "the output to the object set by the last OUTPUT command.";
2893 cmd_getauditlog (assuan_context_t ctx, char *line)
2895 struct server *server = assuan_get_pointer (ctx);
2899 gpgme_data_t out_data;
2900 unsigned int flags = 0;
2902 out_fd = assuan_get_output_fd (ctx);
2903 out_fn = server->output_filename;
2904 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2905 return GPG_ERR_ASS_NO_OUTPUT;
2906 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2907 &server->output_stream);
2911 if (strstr (line, "--html"))
2912 flags |= GPGME_AUDITLOG_HTML;
2913 if (strstr (line, "--with-help"))
2914 flags |= GPGME_AUDITLOG_WITH_HELP;
2916 err = gt_getauditlog (server->gt, out_data, flags);
2918 gpgme_data_release (out_data);
2919 server_reset_fds (server);
2926 cmd_vfs_mount (assuan_context_t ctx, char *line)
2928 struct server *server = assuan_get_pointer (ctx);
2932 mount_dir = strchr (line, ' ');
2935 *(mount_dir++) = '\0';
2936 while (*mount_dir == ' ')
2940 err = gt_vfs_mount (server->gt, line, mount_dir, 0);
2947 cmd_vfs_create (assuan_context_t ctx, char *line)
2949 struct server *server = assuan_get_pointer (ctx);
2953 end = strchr (line, ' ');
2961 err = gt_vfs_create (server->gt, line, 0);
2968 cmd_passwd (assuan_context_t ctx, char *line)
2970 struct server *server = assuan_get_pointer (ctx);
2972 return gt_passwd (server->gt, line);
2978 cmd_result (assuan_context_t ctx, char *line)
2980 struct server *server = assuan_get_pointer (ctx);
2981 return gt_result (server->gt, GT_RESULT_ALL);
2985 /* STRERROR <err> */
2987 cmd_strerror (assuan_context_t ctx, char *line)
2993 snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
2994 gpgme_strsource (err));
2995 return assuan_send_data (ctx, buf, strlen (buf));
3000 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
3002 gpgme_pubkey_algo_t algo;
3006 snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
3007 return assuan_send_data (ctx, buf, strlen (buf));
3012 cmd_hash_algo_name (assuan_context_t ctx, char *line)
3014 gpgme_hash_algo_t algo;
3018 snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
3019 return assuan_send_data (ctx, buf, strlen (buf));
3023 /* Tell the assuan library about our commands. */
3025 register_commands (assuan_context_t ctx)
3030 assuan_handler_t handler;
3031 const char * const help;
3033 /* RESET, BYE are implicit. */
3034 { "VERSION", cmd_version, hlp_version },
3035 /* TODO: Set engine info. */
3036 { "ENGINE", cmd_engine, hlp_engine },
3037 { "PROTOCOL", cmd_protocol, hlp_protocol },
3038 { "SUB_PROTOCOL", cmd_sub_protocol, hlp_sub_protocol },
3039 { "ARMOR", cmd_armor, hlp_armor },
3040 { "TEXTMODE", cmd_textmode, hlp_textmode },
3041 { "INCLUDE_CERTS", cmd_include_certs, hlp_include_certs },
3042 { "KEYLIST_MODE", cmd_keylist_mode, hlp_keylist_mode },
3043 { "INPUT", cmd_input, hlp_input },
3044 { "OUTPUT", cmd_output, hlp_output },
3045 { "MESSAGE", cmd_message, hlp_message },
3046 { "RECIPIENT", cmd_recipient, hlp_recipient },
3047 { "SIGNER", cmd_signer, hlp_signer },
3048 { "SIGNERS_CLEAR", cmd_signers_clear, hlp_signers_clear },
3049 /* TODO: SIGNOTATION missing. */
3050 /* TODO: Could add wait interface if we allow more than one context */
3051 /* and add _START variants. */
3052 /* TODO: Could add data interfaces if we allow multiple data objects. */
3053 { "DECRYPT", cmd_decrypt, hlp_decrypt },
3054 { "DECRYPT_VERIFY", cmd_decrypt_verify, hlp_decrypt_verify },
3055 { "ENCRYPT", cmd_encrypt, hlp_encrypt },
3056 { "ENCRYPT_SIGN", cmd_sign_encrypt, hlp_sign_encrypt },
3057 { "SIGN_ENCRYPT", cmd_sign_encrypt, hlp_sign_encrypt },
3058 { "SIGN", cmd_sign, hlp_sign },
3059 { "VERIFY", cmd_verify, hlp_verify },
3060 { "IMPORT", cmd_import, hlp_import },
3061 { "EXPORT", cmd_export, hlp_export },
3062 { "GENKEY", cmd_genkey },
3063 { "DELETE", cmd_delete },
3064 /* TODO: EDIT, CARD_EDIT (with INQUIRE) */
3065 { "KEYLIST", cmd_keylist, hlp_keylist },
3066 { "LISTKEYS", cmd_keylist, hlp_keylist },
3067 /* TODO: TRUSTLIST, TRUSTLIST_EXT */
3068 { "GETAUDITLOG", cmd_getauditlog, hlp_getauditlog },
3070 { "VFS_MOUNT", cmd_vfs_mount },
3071 { "MOUNT", cmd_vfs_mount },
3072 { "VFS_CREATE", cmd_vfs_create },
3073 { "CREATE", cmd_vfs_create },
3075 { "RESULT", cmd_result },
3076 { "STRERROR", cmd_strerror },
3077 { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
3078 { "HASH_ALGO_NAME", cmd_hash_algo_name },
3079 { "PASSWD", cmd_passwd, hlp_passwd },
3084 for (idx = 0; table[idx].name; idx++)
3086 err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
3095 /* TODO: password callback can do INQUIRE. */
3097 gpgme_server (gpgme_tool_t gt)
3100 assuan_fd_t filedes[2];
3101 struct server server;
3102 static const char hello[] = ("GPGME-Tool " VERSION " ready");
3104 memset (&server, 0, sizeof (server));
3105 server.message_fd = ASSUAN_INVALID_FD;
3106 server.input_enc = GPGME_DATA_ENCODING_NONE;
3107 server.output_enc = GPGME_DATA_ENCODING_NONE;
3108 server.message_enc = GPGME_DATA_ENCODING_NONE;
3111 gt->write_status = server_write_status;
3112 gt->write_status_hook = &server;
3113 gt->write_data = server_write_data;
3114 gt->write_data_hook = &server;
3116 /* We use a pipe based server so that we can work from scripts.
3117 assuan_init_pipe_server will automagically detect when we are
3118 called with a socketpair and ignore FIELDES in this case. */
3119 #ifdef HAVE_W32CE_SYSTEM
3120 filedes[0] = ASSUAN_STDIN;
3121 filedes[1] = ASSUAN_STDOUT;
3123 filedes[0] = assuan_fdopen (0);
3124 filedes[1] = assuan_fdopen (1);
3126 err = assuan_new (&server.assuan_ctx);
3128 log_error (1, err, "can't create assuan context");
3130 assuan_set_pointer (server.assuan_ctx, &server);
3132 err = assuan_init_pipe_server (server.assuan_ctx, filedes);
3134 log_error (1, err, "can't initialize assuan server");
3135 err = register_commands (server.assuan_ctx);
3137 log_error (1, err, "can't register assuan commands");
3138 assuan_set_hello_line (server.assuan_ctx, hello);
3140 assuan_register_reset_notify (server.assuan_ctx, reset_notify);
3142 #define DBG_ASSUAN 0
3144 assuan_set_log_stream (server.assuan_ctx, log_stream);
3148 err = assuan_accept (server.assuan_ctx);
3153 log_error (0, err, "assuan accept problem");
3157 err = assuan_process (server.assuan_ctx);
3159 log_error (0, err, "assuan processing failed");
3162 assuan_release (server.assuan_ctx);
3167 /* MAIN PROGRAM STARTS HERE. */
3169 const char *argp_program_version = VERSION;
3170 const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
3171 error_t argp_err_exit_status = 1;
3173 static char doc[] = "GPGME Tool -- Assuan server exposing GPGME operations";
3174 static char args_doc[] = "COMMAND [OPTIONS...]";
3176 static struct argp_option options[] = {
3177 { "server", 's', 0, 0, "Server mode" },
3181 static error_t parse_options (int key, char *arg, struct argp_state *state);
3182 static struct argp argp = { options, parse_options, args_doc, doc };
3186 enum { CMD_DEFAULT, CMD_SERVER } cmd;
3190 args_init (struct args *args)
3192 memset (args, '\0', sizeof (*args));
3193 args->cmd = CMD_DEFAULT;
3198 parse_options (int key, char *arg, struct argp_state *state)
3200 struct args *args = state->input;
3205 args->cmd = CMD_SERVER;
3209 if (state->arg_num >= 2)
3211 printf ("Arg[%i] = %s\n", state->arg_num, arg);
3214 if (state->arg_num < 2)
3220 return ARGP_ERR_UNKNOWN;
3227 main (int argc, char *argv[])
3230 struct gpgme_tool gt;
3232 #ifdef HAVE_SETLOCALE
3233 setlocale (LC_ALL, "");
3235 gpgme_check_version (NULL);
3237 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
3240 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
3245 argp_parse (&argp, argc, argv, 0, 0, &args);
3258 gpgme_release (gt.ctx);
3260 #ifdef HAVE_W32CE_SYSTEM
3261 /* Give the buggy ssh server time to flush the output buffers. */