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);
1903 /* Wrapper around assuan_command_parse_fd to also handle a
1904 "file=FILENAME" argument. On success either a filename is returned
1905 at FILENAME or a file descriptor at RFD; the other one is set to
1906 NULL respective ASSUAN_INVALID_FD. */
1908 server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd,
1911 *rfd = ASSUAN_INVALID_FD;
1914 if (! strncasecmp (line, "file=", 5))
1917 *filename = strdup (line + 5);
1919 return gpg_error_from_syserror();
1920 term = strchr (*filename, ' ');
1926 return assuan_command_parse_fd (ctx, line, rfd);
1930 static gpgme_data_encoding_t
1931 server_data_encoding (const char *line)
1933 if (strstr (line, "--binary"))
1934 return GPGME_DATA_ENCODING_BINARY;
1935 if (strstr (line, "--base64"))
1936 return GPGME_DATA_ENCODING_BASE64;
1937 if (strstr (line, "--armor"))
1938 return GPGME_DATA_ENCODING_ARMOR;
1939 if (strstr (line, "--url"))
1940 return GPGME_DATA_ENCODING_URL;
1941 if (strstr (line, "--urlesc"))
1942 return GPGME_DATA_ENCODING_URLESC;
1943 if (strstr (line, "--url0"))
1944 return GPGME_DATA_ENCODING_URL0;
1945 return GPGME_DATA_ENCODING_NONE;
1949 static gpgme_error_t
1950 server_data_obj (assuan_fd_t fd, char *fn, int out,
1951 gpgme_data_encoding_t encoding,
1952 gpgme_data_t *data, FILE **fs)
1959 *fs = fopen (fn, out ? "wb" : "rb");
1961 return gpg_error_from_syserror ();
1963 err = gpgme_data_new_from_stream (data, *fs);
1966 err = gpgme_data_new_from_fd (data, (int) fd);
1970 return gpgme_data_set_encoding (*data, encoding);
1975 server_reset_fds (struct server *server)
1977 /* assuan closes the input and output FDs for us when doing a RESET,
1978 but we use this same function after commands, so repeat it
1980 if (server->input_fd != ASSUAN_INVALID_FD)
1983 CloseHandle (server->input_fd);
1985 close (server->input_fd);
1987 server->input_fd = ASSUAN_INVALID_FD;
1989 if (server->output_fd != ASSUAN_INVALID_FD)
1992 CloseHandle (server->output_fd);
1994 close (server->output_fd);
1996 server->output_fd = ASSUAN_INVALID_FD;
1998 if (server->message_fd != ASSUAN_INVALID_FD)
2000 /* FIXME: Assuan should provide a close function. */
2002 CloseHandle (server->message_fd);
2004 close (server->message_fd);
2006 server->message_fd = ASSUAN_INVALID_FD;
2008 if (server->input_filename)
2010 free (server->input_filename);
2011 server->input_filename = NULL;
2013 if (server->output_filename)
2015 free (server->output_filename);
2016 server->output_filename = NULL;
2018 if (server->message_filename)
2020 free (server->message_filename);
2021 server->message_filename = NULL;
2023 if (server->input_stream)
2025 fclose (server->input_stream);
2026 server->input_stream = NULL;
2028 if (server->output_stream)
2030 fclose (server->output_stream);
2031 server->output_stream = NULL;
2033 if (server->message_stream)
2035 fclose (server->message_stream);
2036 server->message_stream = NULL;
2039 server->input_enc = GPGME_DATA_ENCODING_NONE;
2040 server->output_enc = GPGME_DATA_ENCODING_NONE;
2041 server->message_enc = GPGME_DATA_ENCODING_NONE;
2046 reset_notify (assuan_context_t ctx, char *line)
2048 struct server *server = assuan_get_pointer (ctx);
2049 server_reset_fds (server);
2050 gt_reset (server->gt);
2055 static const char hlp_version[] =
2056 "VERSION [<string>]\n"
2058 "Call the function gpgme_check_version.";
2060 cmd_version (assuan_context_t ctx, char *line)
2064 const char *version = gpgme_check_version (line);
2065 return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
2069 const char *version = gpgme_check_version (NULL);
2070 return assuan_send_data (ctx, version, strlen (version));
2075 static const char hlp_engine[] =
2076 "ENGINE [<string>]\n"
2078 "Get information about a GPGME engine (a.k.a. protocol).";
2080 cmd_engine (assuan_context_t ctx, char *line)
2082 struct server *server = assuan_get_pointer (ctx);
2083 return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
2087 static const char hlp_protocol[] =
2088 "PROTOCOL [<name>]\n"
2090 "With NAME, set the protocol. Without, return the current\n"
2093 cmd_protocol (assuan_context_t ctx, char *line)
2095 struct server *server = assuan_get_pointer (ctx);
2097 return gt_set_protocol (server->gt, gt_protocol_from_name (line));
2099 return gt_get_protocol (server->gt);
2103 static const char hlp_sub_protocol[] =
2104 "SUB_PROTOCOL [<name>]\n"
2106 "With NAME, set the sub-protocol. Without, return the\n"
2107 "current sub-protocol.";
2109 cmd_sub_protocol (assuan_context_t ctx, char *line)
2111 struct server *server = assuan_get_pointer (ctx);
2113 return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
2115 return gt_get_sub_protocol (server->gt);
2119 static const char hlp_armor[] =
2120 "ARMOR [true|false]\n"
2122 "With 'true' or 'false', turn output ASCII armoring on or\n"
2123 "off. Without, return the current armoring status.";
2125 cmd_armor (assuan_context_t ctx, char *line)
2127 struct server *server = assuan_get_pointer (ctx);
2132 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2136 return gt_set_armor (server->gt, flag);
2139 return gt_get_armor (server->gt);
2143 static const char hlp_textmode[] =
2144 "TEXTMODE [true|false]\n"
2146 "With 'true' or 'false', turn text mode on or off.\n"
2147 "Without, return the current text mode status.";
2149 cmd_textmode (assuan_context_t ctx, char *line)
2151 struct server *server = assuan_get_pointer (ctx);
2156 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2160 return gt_set_textmode (server->gt, flag);
2163 return gt_get_textmode (server->gt);
2167 static const char hlp_include_certs[] =
2168 "INCLUDE_CERTS [default|<n>]\n"
2170 "With DEFAULT or N, set how many certificates should be\n"
2171 "included in the next S/MIME signed message. See the\n"
2172 "GPGME documentation for details on the meaning of"
2173 "various N. Without either, return the current setting.";
2175 cmd_include_certs (assuan_context_t ctx, char *line)
2177 struct server *server = assuan_get_pointer (ctx);
2181 int include_certs = 0;
2183 if (! strcasecmp (line, "default"))
2184 include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
2186 include_certs = atoi (line);
2188 return gt_set_include_certs (server->gt, include_certs);
2191 return gt_get_include_certs (server->gt);
2195 static const char hlp_keylist_mode[] =
2196 "KEYLIST_MODE [local] [extern] [sigs] [sig_notations]\n"
2197 " [ephemeral] [validate]\n"
2199 "Set the mode for the next KEYLIST command.";
2201 cmd_keylist_mode (assuan_context_t ctx, char *line)
2203 struct server *server = assuan_get_pointer (ctx);
2207 gpgme_keylist_mode_t mode = 0;
2209 if (strstr (line, "local"))
2210 mode |= GPGME_KEYLIST_MODE_LOCAL;
2211 if (strstr (line, "extern"))
2212 mode |= GPGME_KEYLIST_MODE_EXTERN;
2213 if (strstr (line, "sigs"))
2214 mode |= GPGME_KEYLIST_MODE_SIGS;
2215 if (strstr (line, "sig_notations"))
2216 mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
2217 if (strstr (line, "ephemeral"))
2218 mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
2219 if (strstr (line, "validate"))
2220 mode |= GPGME_KEYLIST_MODE_VALIDATE;
2222 return gt_set_keylist_mode (server->gt, mode);
2225 return gt_get_keylist_mode (server->gt);
2229 static const char hlp_input[] =
2230 "INPUT [<fd>|FILE=<path>]\n"
2232 "Set the input for the next command. Use either the\n"
2233 "Assuan file descriptor FD or a filesystem PATH.";
2235 cmd_input (assuan_context_t ctx, char *line)
2237 struct server *server = assuan_get_pointer (ctx);
2242 err = server_parse_fd (ctx, line, &sysfd, &filename);
2245 server->input_fd = sysfd;
2246 server->input_filename = filename;
2247 server->input_enc = server_data_encoding (line);
2252 static const char hlp_output[] =
2253 "OUTPUT [<fd>|FILE=<path>]\n"
2255 "Set the output for the next command. Use either the\n"
2256 "Assuan file descriptor FD or a filesystem PATH.";
2258 cmd_output (assuan_context_t ctx, char *line)
2260 struct server *server = assuan_get_pointer (ctx);
2265 err = server_parse_fd (ctx, line, &sysfd, &filename);
2268 server->output_fd = sysfd;
2269 server->output_filename = filename;
2270 server->output_enc = server_data_encoding (line);
2275 static const char hlp_message[] =
2276 "MESSAGE [<fd>|FILE=<path>]\n"
2278 "Set the plaintext message for the next VERIFY command\n"
2279 "with a detached signature. Use either the Assuan file\n"
2280 "descriptor FD or a filesystem PATH.";
2282 cmd_message (assuan_context_t ctx, char *line)
2284 struct server *server = assuan_get_pointer (ctx);
2289 err = server_parse_fd (ctx, line, &sysfd, &filename);
2292 server->message_fd = sysfd;
2293 server->message_filename = filename;
2294 server->message_enc = server_data_encoding (line);
2299 static const char hlp_recipient[] =
2300 "RECIPIENT <pattern>\n"
2302 "Add the key matching PATTERN to the list of recipients\n"
2303 "for the next encryption command.";
2305 cmd_recipient (assuan_context_t ctx, char *line)
2307 struct server *server = assuan_get_pointer (ctx);
2309 return gt_recipients_add (server->gt, line);
2313 static const char hlp_signer[] =
2314 "SIGNER <fingerprint>\n"
2316 "Add the key with FINGERPRINT to the list of signers to\n"
2317 "be used for the next signing command.";
2319 cmd_signer (assuan_context_t ctx, char *line)
2321 struct server *server = assuan_get_pointer (ctx);
2323 return gt_signers_add (server->gt, line);
2327 static const char hlp_signers_clear[] =
2330 "Clear the list of signers specified by previous SIGNER\n"
2333 cmd_signers_clear (assuan_context_t ctx, char *line)
2335 struct server *server = assuan_get_pointer (ctx);
2337 return gt_signers_clear (server->gt);
2342 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
2344 struct server *server = assuan_get_pointer (ctx);
2350 gpgme_data_t inp_data;
2351 gpgme_data_t out_data;
2353 inp_fd = server->input_fd;
2354 inp_fn = server->input_filename;
2355 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2356 return GPG_ERR_ASS_NO_INPUT;
2357 out_fd = server->output_fd;
2358 out_fn = server->output_filename;
2359 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2360 return GPG_ERR_ASS_NO_OUTPUT;
2362 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2363 &server->input_stream);
2366 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2367 &server->output_stream);
2370 gpgme_data_release (inp_data);
2374 err = gt_decrypt_verify (server->gt, inp_data, out_data, verify);
2376 gpgme_data_release (inp_data);
2377 gpgme_data_release (out_data);
2379 server_reset_fds (server);
2385 static const char hlp_decrypt[] =
2388 "Decrypt the object set by the last INPUT command and\n"
2389 "write the decrypted message to the object set by the\n"
2390 "last OUTPUT command.";
2392 cmd_decrypt (assuan_context_t ctx, char *line)
2394 return _cmd_decrypt_verify (ctx, line, 0);
2398 static const char hlp_decrypt_verify[] =
2401 "Decrypt the object set by the last INPUT command and\n"
2402 "verify any embedded signatures. Write the decrypted\n"
2403 "message to the object set by the last OUTPUT command.";
2405 cmd_decrypt_verify (assuan_context_t ctx, char *line)
2407 return _cmd_decrypt_verify (ctx, line, 1);
2412 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
2414 struct server *server = assuan_get_pointer (ctx);
2420 gpgme_data_t inp_data = NULL;
2421 gpgme_data_t out_data = NULL;
2422 gpgme_encrypt_flags_t flags = 0;
2424 if (strstr (line, "--always-trust"))
2425 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
2426 if (strstr (line, "--no-encrypt-to"))
2427 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
2428 if (strstr (line, "--prepare"))
2429 flags |= GPGME_ENCRYPT_PREPARE;
2430 if (strstr (line, "--expect-sign"))
2431 flags |= GPGME_ENCRYPT_EXPECT_SIGN;
2433 inp_fd = server->input_fd;
2434 inp_fn = server->input_filename;
2435 out_fd = server->output_fd;
2436 out_fn = server->output_filename;
2437 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
2439 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2440 &server->input_stream);
2444 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2446 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2447 &server->output_stream);
2450 gpgme_data_release (inp_data);
2455 err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign);
2457 gpgme_data_release (inp_data);
2458 gpgme_data_release (out_data);
2460 server_reset_fds (server);
2466 static const char hlp_encrypt[] =
2467 "ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2468 " [--prepare] [--expect-sign]\n"
2470 "Encrypt the object set by the last INPUT command to\n"
2471 "the keys specified by previous RECIPIENT commands. \n"
2472 "Write the signed and encrypted message to the object\n"
2473 "set by the last OUTPUT command.";
2475 cmd_encrypt (assuan_context_t ctx, char *line)
2477 return _cmd_sign_encrypt (ctx, line, 0);
2481 static const char hlp_sign_encrypt[] =
2482 "SIGN_ENCRYPT [--always-trust] [--no-encrypt-to]\n"
2483 " [--prepare] [--expect-sign]\n"
2485 "Sign the object set by the last INPUT command with the\n"
2486 "keys specified by previous SIGNER commands and encrypt\n"
2487 "it to the keys specified by previous RECIPIENT\n"
2488 "commands. Write the signed and encrypted message to\n"
2489 "the object set by the last OUTPUT command.";
2491 cmd_sign_encrypt (assuan_context_t ctx, char *line)
2493 return _cmd_sign_encrypt (ctx, line, 1);
2497 static const char hlp_sign[] =
2498 "SIGN [--clear|--detach]\n"
2500 "Sign the object set by the last INPUT command with the\n"
2501 "keys specified by previous SIGNER commands. Write the\n"
2502 "signed message to the object set by the last OUTPUT\n"
2503 "command. With `--clear`, generate a clear text\n"
2504 "signature. With `--detach`, generate a detached\n"
2507 cmd_sign (assuan_context_t ctx, char *line)
2509 struct server *server = assuan_get_pointer (ctx);
2515 gpgme_data_t inp_data;
2516 gpgme_data_t out_data;
2517 gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
2519 if (strstr (line, "--clear"))
2520 mode = GPGME_SIG_MODE_CLEAR;
2521 if (strstr (line, "--detach"))
2522 mode = GPGME_SIG_MODE_DETACH;
2524 inp_fd = server->input_fd;
2525 inp_fn = server->input_filename;
2526 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2527 return GPG_ERR_ASS_NO_INPUT;
2528 out_fd = server->output_fd;
2529 out_fn = server->output_filename;
2530 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2531 return GPG_ERR_ASS_NO_OUTPUT;
2533 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2534 &server->input_stream);
2537 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2538 &server->output_stream);
2541 gpgme_data_release (inp_data);
2545 err = gt_sign (server->gt, inp_data, out_data, mode);
2547 gpgme_data_release (inp_data);
2548 gpgme_data_release (out_data);
2549 server_reset_fds (server);
2555 static const char hlp_verify[] =
2558 "Verify signatures on the object set by the last INPUT\n"
2559 "and MESSAGE commands. If the message was encrypted,\n"
2560 "write the plaintext to the object set by the last\n"
2563 cmd_verify (assuan_context_t ctx, char *line)
2565 struct server *server = assuan_get_pointer (ctx);
2573 gpgme_data_t inp_data;
2574 gpgme_data_t msg_data = NULL;
2575 gpgme_data_t out_data = NULL;
2577 inp_fd = server->input_fd;
2578 inp_fn = server->input_filename;
2579 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2580 return GPG_ERR_ASS_NO_INPUT;
2581 msg_fd = server->message_fd;
2582 msg_fn = server->message_filename;
2583 out_fd = server->output_fd;
2584 out_fn = server->output_filename;
2586 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2587 &server->input_stream);
2590 if (msg_fd != ASSUAN_INVALID_FD || msg_fn)
2592 err = server_data_obj (msg_fd, msg_fn, 0, server->message_enc, &msg_data,
2593 &server->message_stream);
2596 gpgme_data_release (inp_data);
2600 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2602 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2603 &server->output_stream);
2606 gpgme_data_release (inp_data);
2607 gpgme_data_release (msg_data);
2612 err = gt_verify (server->gt, inp_data, msg_data, out_data);
2614 gpgme_data_release (inp_data);
2616 gpgme_data_release (msg_data);
2618 gpgme_data_release (out_data);
2620 server_reset_fds (server);
2626 static const char hlp_import[] =
2627 "IMPORT [<pattern>]\n"
2629 "With PATTERN, import the keys described by PATTERN.\n"
2630 "Without, read a key (or keys) from the object set by the\n"
2631 "last INPUT command.";
2633 cmd_import (assuan_context_t ctx, char *line)
2635 struct server *server = assuan_get_pointer (ctx);
2639 char *fprs[2] = { line, NULL };
2641 return gt_import_keys (server->gt, fprs);
2648 gpgme_data_t inp_data;
2650 inp_fd = server->input_fd;
2651 inp_fn = server->input_filename;
2652 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2653 return GPG_ERR_ASS_NO_INPUT;
2655 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2656 &server->input_stream);
2660 err = gt_import (server->gt, inp_data);
2662 gpgme_data_release (inp_data);
2663 server_reset_fds (server);
2670 static const char hlp_export[] =
2671 "EXPORT [--extern] [--minimal] [<pattern>]\n"
2673 "Export the keys described by PATTERN. Write the\n"
2674 "the output to the object set by the last OUTPUT command.";
2676 cmd_export (assuan_context_t ctx, char *line)
2678 struct server *server = assuan_get_pointer (ctx);
2682 gpgme_data_t out_data;
2683 gpgme_export_mode_t mode = 0;
2684 const char *pattern[2];
2686 out_fd = server->output_fd;
2687 out_fn = server->output_filename;
2688 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2689 return GPG_ERR_ASS_NO_OUTPUT;
2690 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2691 &server->output_stream);
2695 if (has_option (line, "--extern"))
2696 mode |= GPGME_EXPORT_MODE_EXTERN;
2697 if (has_option (line, "--minimal"))
2698 mode |= GPGME_EXPORT_MODE_MINIMAL;
2700 line = skip_options (line);
2705 err = gt_export (server->gt, pattern, mode, out_data);
2707 gpgme_data_release (out_data);
2708 server_reset_fds (server);
2715 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
2719 ssize_t writen = gpgme_data_write (data, buf, size);
2720 if (writen < 0 && errno != EAGAIN)
2721 return gpg_error_from_syserror ();
2722 else if (writen > 0)
2724 buf = (void *) (((char *) buf) + writen);
2733 cmd_genkey (assuan_context_t ctx, char *line)
2735 struct server *server = assuan_get_pointer (ctx);
2741 gpgme_data_t inp_data;
2742 gpgme_data_t out_data = NULL;
2743 gpgme_data_t parms_data = NULL;
2746 inp_fd = server->input_fd;
2747 inp_fn = server->input_filename;
2748 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2749 return GPG_ERR_ASS_NO_INPUT;
2750 out_fd = server->output_fd;
2751 out_fn = server->output_filename;
2753 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2754 &server->input_stream);
2757 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2759 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2760 &server->output_stream);
2763 gpgme_data_release (inp_data);
2768 /* Convert input data. */
2769 err = gpgme_data_new (&parms_data);
2775 ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
2778 err = gpg_error_from_syserror ();
2781 else if (readn == 0)
2784 err = _cmd_genkey_write (parms_data, buf, readn);
2789 err = _cmd_genkey_write (parms_data, "", 1);
2792 parms = gpgme_data_release_and_get_mem (parms_data, NULL);
2796 err = gpg_error (GPG_ERR_GENERAL);
2800 err = gt_genkey (server->gt, parms, out_data, NULL);
2802 server_reset_fds (server);
2805 gpgme_data_release (inp_data);
2807 gpgme_data_release (out_data);
2809 gpgme_data_release (parms_data);
2816 cmd_delete (assuan_context_t ctx, char *line)
2818 struct server *server = assuan_get_pointer (ctx);
2819 int allow_secret = 0;
2820 const char optstr[] = "--allow-secret";
2822 if (!strncasecmp (line, optstr, strlen (optstr)))
2825 line += strlen (optstr);
2826 while (*line && !spacep (line))
2829 return gt_delete (server->gt, line, allow_secret);
2833 static const char hlp_keylist[] =
2834 "KEYLIST [--secret-only] [<patterns>]\n"
2836 "List all certificates or only those specified by PATTERNS. Each\n"
2837 "pattern shall be a percent-plus escaped certificate specification.";
2839 cmd_keylist (assuan_context_t ctx, char *line)
2841 #define MAX_CMD_KEYLIST_PATTERN 20
2842 struct server *server = assuan_get_pointer (ctx);
2844 int secret_only = 0;
2846 const char *pattern[MAX_CMD_KEYLIST_PATTERN+1];
2847 const char optstr[] = "--secret-only";
2850 if (!strncasecmp (line, optstr, strlen (optstr)))
2853 line += strlen (optstr);
2854 while (*line && !spacep (line))
2859 for (p=line; *p; line = p)
2861 while (*p && *p != ' ')
2867 if (idx+1 == DIM (pattern))
2868 return gpg_error (GPG_ERR_TOO_MANY);
2869 strcpy_escaped_plus (line, line);
2870 pattern[idx++] = line;
2873 pattern[idx] = NULL;
2875 err = gt_keylist_start (server->gt, pattern, secret_only);
2880 err = gt_keylist_next (server->gt, &key);
2881 if (gpg_err_code (err) == GPG_ERR_EOF)
2889 /* FIXME: More data. */
2890 snprintf (buf, sizeof (buf), "key:%s\n", key->subkeys->fpr);
2891 /* Write data and flush so that we see one D line for each
2892 key. This does not change the semantics but is easier to
2893 read by organic eyes. */
2894 if (!assuan_send_data (ctx, buf, strlen (buf)))
2895 assuan_send_data (ctx, NULL, 0);
2896 gpgme_key_unref (key);
2900 server_reset_fds (server);
2906 static const char hlp_getauditlog[] =
2907 "GETAUDITLOG [--html] [--with-help]\n"
2909 "Call the function gpgme_op_getauditlog with the given flags. Write\n"
2910 "the output to the object set by the last OUTPUT command.";
2912 cmd_getauditlog (assuan_context_t ctx, char *line)
2914 struct server *server = assuan_get_pointer (ctx);
2918 gpgme_data_t out_data;
2919 unsigned int flags = 0;
2921 out_fd = server->output_fd;
2922 out_fn = server->output_filename;
2923 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2924 return GPG_ERR_ASS_NO_OUTPUT;
2925 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2926 &server->output_stream);
2930 if (strstr (line, "--html"))
2931 flags |= GPGME_AUDITLOG_HTML;
2932 if (strstr (line, "--with-help"))
2933 flags |= GPGME_AUDITLOG_WITH_HELP;
2935 err = gt_getauditlog (server->gt, out_data, flags);
2937 gpgme_data_release (out_data);
2938 server_reset_fds (server);
2945 cmd_vfs_mount (assuan_context_t ctx, char *line)
2947 struct server *server = assuan_get_pointer (ctx);
2951 mount_dir = strchr (line, ' ');
2954 *(mount_dir++) = '\0';
2955 while (*mount_dir == ' ')
2959 err = gt_vfs_mount (server->gt, line, mount_dir, 0);
2966 cmd_vfs_create (assuan_context_t ctx, char *line)
2968 struct server *server = assuan_get_pointer (ctx);
2972 end = strchr (line, ' ');
2980 err = gt_vfs_create (server->gt, line, 0);
2987 cmd_passwd (assuan_context_t ctx, char *line)
2989 struct server *server = assuan_get_pointer (ctx);
2991 return gt_passwd (server->gt, line);
2997 cmd_result (assuan_context_t ctx, char *line)
2999 struct server *server = assuan_get_pointer (ctx);
3000 return gt_result (server->gt, GT_RESULT_ALL);
3004 /* STRERROR <err> */
3006 cmd_strerror (assuan_context_t ctx, char *line)
3012 snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
3013 gpgme_strsource (err));
3014 return assuan_send_data (ctx, buf, strlen (buf));
3019 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
3021 gpgme_pubkey_algo_t algo;
3025 snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
3026 return assuan_send_data (ctx, buf, strlen (buf));
3031 cmd_hash_algo_name (assuan_context_t ctx, char *line)
3033 gpgme_hash_algo_t algo;
3037 snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
3038 return assuan_send_data (ctx, buf, strlen (buf));
3042 /* Tell the assuan library about our commands. */
3044 register_commands (assuan_context_t ctx)
3049 assuan_handler_t handler;
3050 const char * const help;
3052 /* RESET, BYE are implicit. */
3053 { "VERSION", cmd_version, hlp_version },
3054 /* TODO: Set engine info. */
3055 { "ENGINE", cmd_engine, hlp_engine },
3056 { "PROTOCOL", cmd_protocol, hlp_protocol },
3057 { "SUB_PROTOCOL", cmd_sub_protocol, hlp_sub_protocol },
3058 { "ARMOR", cmd_armor, hlp_armor },
3059 { "TEXTMODE", cmd_textmode, hlp_textmode },
3060 { "INCLUDE_CERTS", cmd_include_certs, hlp_include_certs },
3061 { "KEYLIST_MODE", cmd_keylist_mode, hlp_keylist_mode },
3062 { "INPUT", cmd_input, hlp_input },
3063 { "OUTPUT", cmd_output, hlp_output },
3064 { "MESSAGE", cmd_message, hlp_message },
3065 { "RECIPIENT", cmd_recipient, hlp_recipient },
3066 { "SIGNER", cmd_signer, hlp_signer },
3067 { "SIGNERS_CLEAR", cmd_signers_clear, hlp_signers_clear },
3068 /* TODO: SIGNOTATION missing. */
3069 /* TODO: Could add wait interface if we allow more than one context */
3070 /* and add _START variants. */
3071 /* TODO: Could add data interfaces if we allow multiple data objects. */
3072 { "DECRYPT", cmd_decrypt, hlp_decrypt },
3073 { "DECRYPT_VERIFY", cmd_decrypt_verify, hlp_decrypt_verify },
3074 { "ENCRYPT", cmd_encrypt, hlp_encrypt },
3075 { "ENCRYPT_SIGN", cmd_sign_encrypt, hlp_sign_encrypt },
3076 { "SIGN_ENCRYPT", cmd_sign_encrypt, hlp_sign_encrypt },
3077 { "SIGN", cmd_sign, hlp_sign },
3078 { "VERIFY", cmd_verify, hlp_verify },
3079 { "IMPORT", cmd_import, hlp_import },
3080 { "EXPORT", cmd_export, hlp_export },
3081 { "GENKEY", cmd_genkey },
3082 { "DELETE", cmd_delete },
3083 /* TODO: EDIT, CARD_EDIT (with INQUIRE) */
3084 { "KEYLIST", cmd_keylist, hlp_keylist },
3085 { "LISTKEYS", cmd_keylist, hlp_keylist },
3086 /* TODO: TRUSTLIST, TRUSTLIST_EXT */
3087 { "GETAUDITLOG", cmd_getauditlog, hlp_getauditlog },
3089 { "VFS_MOUNT", cmd_vfs_mount },
3090 { "MOUNT", cmd_vfs_mount },
3091 { "VFS_CREATE", cmd_vfs_create },
3092 { "CREATE", cmd_vfs_create },
3094 { "RESULT", cmd_result },
3095 { "STRERROR", cmd_strerror },
3096 { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
3097 { "HASH_ALGO_NAME", cmd_hash_algo_name },
3098 { "PASSWD", cmd_passwd, hlp_passwd },
3103 for (idx = 0; table[idx].name; idx++)
3105 err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
3114 /* TODO: password callback can do INQUIRE. */
3116 gpgme_server (gpgme_tool_t gt)
3119 assuan_fd_t filedes[2];
3120 struct server server;
3121 static const char hello[] = ("GPGME-Tool " VERSION " ready");
3123 memset (&server, 0, sizeof (server));
3124 server.message_fd = ASSUAN_INVALID_FD;
3125 server.input_enc = GPGME_DATA_ENCODING_NONE;
3126 server.output_enc = GPGME_DATA_ENCODING_NONE;
3127 server.message_enc = GPGME_DATA_ENCODING_NONE;
3130 gt->write_status = server_write_status;
3131 gt->write_status_hook = &server;
3132 gt->write_data = server_write_data;
3133 gt->write_data_hook = &server;
3135 /* We use a pipe based server so that we can work from scripts.
3136 assuan_init_pipe_server will automagically detect when we are
3137 called with a socketpair and ignore FIELDES in this case. */
3138 #ifdef HAVE_W32CE_SYSTEM
3139 filedes[0] = ASSUAN_STDIN;
3140 filedes[1] = ASSUAN_STDOUT;
3142 filedes[0] = assuan_fdopen (0);
3143 filedes[1] = assuan_fdopen (1);
3145 err = assuan_new (&server.assuan_ctx);
3147 log_error (1, err, "can't create assuan context");
3149 assuan_set_pointer (server.assuan_ctx, &server);
3151 err = assuan_init_pipe_server (server.assuan_ctx, filedes);
3153 log_error (1, err, "can't initialize assuan server");
3154 err = register_commands (server.assuan_ctx);
3156 log_error (1, err, "can't register assuan commands");
3157 assuan_set_hello_line (server.assuan_ctx, hello);
3159 assuan_register_reset_notify (server.assuan_ctx, reset_notify);
3161 #define DBG_ASSUAN 0
3163 assuan_set_log_stream (server.assuan_ctx, log_stream);
3167 err = assuan_accept (server.assuan_ctx);
3172 log_error (0, err, "assuan accept problem");
3176 err = assuan_process (server.assuan_ctx);
3178 log_error (0, err, "assuan processing failed");
3181 assuan_release (server.assuan_ctx);
3186 /* MAIN PROGRAM STARTS HERE. */
3188 const char *argp_program_version = VERSION;
3189 const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
3190 error_t argp_err_exit_status = 1;
3192 static char doc[] = "GPGME Tool -- Assuan server exposing GPGME operations";
3193 static char args_doc[] = "COMMAND [OPTIONS...]";
3195 static struct argp_option options[] = {
3196 { "server", 's', 0, 0, "Server mode" },
3200 static error_t parse_options (int key, char *arg, struct argp_state *state);
3201 static struct argp argp = { options, parse_options, args_doc, doc };
3205 enum { CMD_DEFAULT, CMD_SERVER } cmd;
3209 args_init (struct args *args)
3211 memset (args, '\0', sizeof (*args));
3212 args->cmd = CMD_DEFAULT;
3217 parse_options (int key, char *arg, struct argp_state *state)
3219 struct args *args = state->input;
3224 args->cmd = CMD_SERVER;
3228 if (state->arg_num >= 2)
3230 printf ("Arg[%i] = %s\n", state->arg_num, arg);
3233 if (state->arg_num < 2)
3239 return ARGP_ERR_UNKNOWN;
3246 main (int argc, char *argv[])
3249 struct gpgme_tool gt;
3251 #ifdef HAVE_SETLOCALE
3252 setlocale (LC_ALL, "");
3254 gpgme_check_version (NULL);
3256 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
3259 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
3264 argp_parse (&argp, argc, argv, 0, 0, &args);
3277 gpgme_release (gt.ctx);
3279 #ifdef HAVE_W32CE_SYSTEM
3280 /* Give the buggy ssh server time to flush the output buffers. */