1 /* gpgme-tool.c - GnuPG Made Easy.
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/>.
42 # define GT_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a)))
44 # define GT_GCC_A_SENTINEL(a)
47 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
48 # define GT_GCC_A_PRINTF(f, a) __attribute__ ((format (printf,f,a)))
50 # define GT_GCC_A_PRINTF(f, a)
57 /* Minimal argp implementation. */
59 /* Differences to ARGP:
60 argp_program_version: Required.
61 argp_program_bug_address: Required.
62 argp_program_version_hook: Not supported.
63 argp_err_exit_status: Required.
64 struct argp: Children and help_filter not supported.
65 argp_domain: Not supported.
66 struct argp_option: Group not supported. Options are printed in
67 order given. Flags OPTION_ALIAS, OPTION_DOC and OPTION_NO_USAGE
69 argp_parse: No flags are supported (ARGP_PARSE_ARGV0, ARGP_NO_ERRS,
70 ARGP_NO_ARGS, ARGP_IN_ORDER, ARGP_NO_HELP, ARGP_NO_EXIT,
71 ARGP_LONG_ONLY, ARGP_SILENT). ARGP must not be NULL.
72 argp_help: Flag ARGP_HELP_LONG_ONLY not supported.
73 argp_state: argc, argv, next may not be modified and should not be used. */
75 extern const char *argp_program_version;
76 extern const char *argp_program_bug_address;
77 extern error_t argp_err_exit_status;
84 #define OPTION_ARG_OPTIONAL 0x1
85 #define OPTION_HIDDEN 0x2
94 const struct argp *const root_argp;
110 #define ARGP_ERR_UNKNOWN E2BIG
111 #define ARGP_KEY_ARG 0
112 #define ARGP_KEY_ARGS 0x1000006
113 #define ARGP_KEY_END 0x1000001
114 #define ARGP_KEY_NO_ARGS 0x1000002
115 #define ARGP_KEY_INIT 0x1000003
116 #define ARGP_KEY_FINI 0x1000007
117 #define ARGP_KEY_SUCCESS 0x1000004
118 #define ARGP_KEY_ERROR 0x1000005
119 typedef error_t (*argp_parser_t) (int key, char *arg, struct argp_state *state);
123 const struct argp_option *options;
124 argp_parser_t parser;
125 const char *args_doc;
128 const struct argp_child *children;
129 char *(*help_filter) (int key, const char *text, void *input);
130 const char *argp_domain;
133 #define ARGP_HELP_USAGE ARGP_HELP_SHORT_USAGE
134 #define ARGP_HELP_SHORT_USAGE 0x02
135 #define ARGP_HELP_SEE 0x04
136 #define ARGP_HELP_LONG 0x08
137 #define ARGP_HELP_PRE_DOC 0x10
138 #define ARGP_HELP_POST_DOC 0x20
139 #define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
140 #define ARGP_HELP_BUG_ADDR 0x40
141 #define ARGP_HELP_EXIT_ERR 0x100
142 #define ARGP_HELP_EXIT_OK 0x200
143 #define ARGP_HELP_STD_ERR (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
144 #define ARGP_HELP_STD_USAGE \
145 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
146 #define ARGP_HELP_STD_HELP \
147 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
148 | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
151 void argp_error (const struct argp_state *state,
152 const char *fmt, ...) GT_GCC_A_PRINTF(2, 3);
157 _argp_pname (char *name)
160 char *bname = strrchr (pname, '/');
162 bname = strrchr (pname, '\\');
170 _argp_state_help (const struct argp *argp, const struct argp_state *state,
171 FILE *stream, unsigned flags, char *name)
176 if (flags & ARGP_HELP_SHORT_USAGE)
177 fprintf (stream, "Usage: %s [OPTIONS...] %s\n", name, argp->args_doc);
178 if (flags & ARGP_HELP_SEE)
179 fprintf (stream, "Try `%s --help' or `%s --usage' for more information.\n",
181 if (flags & ARGP_HELP_PRE_DOC)
185 strncpy (buf, argp->doc, sizeof (buf));
186 buf[sizeof (buf) - 1] = '\0';
187 end = strchr (buf, '\v');
190 fprintf (stream, "%s\n%s", buf, buf[0] ? "\n" : "");
192 if (flags & ARGP_HELP_LONG)
194 const struct argp_option *opt = argp->options;
198 char spaces[NSPACES + 1] = " ";
200 fprintf (stream, " ");
202 if (isascii (opt->key))
204 fprintf (stream, "-%c", opt->key);
208 fprintf (stream, ", ");
214 fprintf (stream, "--%s", opt->name);
215 len += 2 + strlen (opt->name);
217 if (opt->arg && (opt->flags & OPTION_ARG_OPTIONAL))
219 fprintf (stream, "[=%s]", opt->arg);
220 len += 3 + strlen (opt->arg);
224 fprintf (stream, "=%s", opt->arg);
225 len += 1 + strlen (opt->arg);
229 spaces[NSPACES - len] = '\0';
230 fprintf (stream, "%s%s\n", spaces, opt->doc);
233 fprintf (stream, " -?, --help Give this help list\n");
234 fprintf (stream, " --usage Give a short usage "
237 if (flags & ARGP_HELP_POST_DOC)
241 strncpy (buf, argp->doc, sizeof (buf));
242 buf[sizeof (buf) - 1] = '\0';
243 end = strchr (buf, '\v');
248 fprintf (stream, "\n%s\n", end);
250 fprintf (stream, "\nMandatory or optional arguments to long options are also mandatory or optional\n");
251 fprintf (stream, "for any corresponding short options.\n");
253 if (flags & ARGP_HELP_BUG_ADDR)
254 fprintf (stream, "\nReport bugs to %s.\n", argp_program_bug_address);
256 if (flags & ARGP_HELP_EXIT_ERR)
257 exit (argp_err_exit_status);
258 if (flags & ARGP_HELP_EXIT_OK)
264 argp_usage (const struct argp_state *state)
266 _argp_state_help (state->root_argp, state, state->err_stream,
267 ARGP_HELP_STD_USAGE, state->name);
272 argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
274 _argp_state_help (state->root_argp, state, stream, flags, state->name);
279 argp_error (const struct argp_state *state, const char *fmt, ...)
283 fprintf (state->err_stream, "%s: ", state->name);
285 vfprintf (state->err_stream, fmt, ap);
287 fprintf (state->err_stream, "\n");
288 argp_state_help (state, state->err_stream, ARGP_HELP_STD_ERR);
289 exit (argp_err_exit_status);
294 argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name)
296 _argp_state_help (argp, NULL, stream, flags, name);
301 argp_parse (const struct argp *argp, int argc,
302 char **argv, unsigned flags, int *arg_index, void *input)
305 struct argp_state state = { argp, argc, argv, 1, flags, 0, 0, input,
306 NULL, NULL, _argp_pname (argv[0]),
307 stderr, stdout, NULL };
308 /* All non-option arguments are collected at the beginning of
309 &argv[1] during processing. This is a counter for their number. */
310 int non_opt_args = 0;
312 rc = argp->parser (ARGP_KEY_INIT, NULL, &state);
313 if (rc && rc != ARGP_ERR_UNKNOWN)
316 while (state.next < state.argc - non_opt_args)
318 int idx = state.next;
321 if (! strcasecmp (state.argv[idx], "--"))
327 if (state.quoted || state.argv[idx][0] != '-')
329 char *arg_saved = state.argv[idx];
331 memmove (&state.argv[idx], &state.argv[idx + 1],
332 (state.argc - 1 - idx) * sizeof (char *));
333 state.argv[argc - 1] = arg_saved;
336 else if (! strcasecmp (state.argv[idx], "--help")
337 || !strcmp (state.argv[idx], "-?"))
339 argp_state_help (&state, state.out_stream, ARGP_HELP_STD_HELP);
341 else if (! strcasecmp (state.argv[idx], "--usage"))
343 argp_state_help (&state, state.out_stream,
344 ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
346 else if (! strcasecmp (state.argv[idx], "--version")
347 || !strcmp (state.argv[idx], "-V"))
349 fprintf (state.out_stream, "%s\n", argp_program_version);
354 /* Search for option and call parser with its KEY. */
355 int key = ARGP_KEY_ARG; /* Just some dummy value. */
356 const struct argp_option *opt = argp->options;
360 /* Check for --opt=value syntax. */
361 arg = strchr (state.argv[idx], '=');
368 if (state.argv[idx][1] != '-')
369 key = state.argv[idx][1];
371 while (! found && opt->key)
374 || (key == ARGP_KEY_ARG
375 && ! strcasecmp (&state.argv[idx][2], opt->name)))
377 if (arg && !opt->arg)
378 argp_error (&state, "Option %s does not take an argument",
380 if (opt->arg && state.next < state.argc
381 && state.argv[idx + 1][0] != '-')
383 arg = state.argv[idx + 1];
386 if (opt->arg && !(opt->flags & OPTION_ARG_OPTIONAL))
387 argp_error (&state, "Option %s requires an argument",
390 rc = argp->parser (opt->key, arg, &state);
391 if (rc == ARGP_ERR_UNKNOWN)
400 argp_error (&state, "Unknown option %s", state.argv[idx]);
404 while (state.next < state.argc)
406 /* Call parser for all non-option args. */
407 int idx = state.next;
409 rc = argp->parser (ARGP_KEY_ARG, state.argv[idx], &state);
410 if (rc && rc != ARGP_ERR_UNKNOWN)
412 if (rc == ARGP_ERR_UNKNOWN)
414 int old_next = state.next;
415 rc = argp->parser (ARGP_KEY_ARGS, NULL, &state);
416 if (rc == ARGP_ERR_UNKNOWN)
418 argp_error (&state, "Too many arguments");
421 if (! rc && state.next == old_next)
423 state.arg_num += state.argc - state.next;
424 state.next = state.argc;
431 if (state.arg_num == 0)
433 rc = argp->parser (ARGP_KEY_NO_ARGS, NULL, &state);
434 if (rc && rc != ARGP_ERR_UNKNOWN)
437 if (state.next == state.argc)
439 rc = argp->parser (ARGP_KEY_END, NULL, &state);
440 if (rc && rc != ARGP_ERR_UNKNOWN)
443 rc = argp->parser (ARGP_KEY_FINI, NULL, &state);
444 if (rc && rc != ARGP_ERR_UNKNOWN)
448 argp->parser (ARGP_KEY_SUCCESS, NULL, &state);
453 argp_error (&state, "unexpected error: %s", strerror (rc));
454 argp->parser (ARGP_KEY_ERROR, NULL, &state);
457 argp->parser (ARGP_KEY_FINI, NULL, &state);
460 *arg_index = state.next - 1;
469 char *program_name = "gpgme-tool";
471 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
474 void log_error (int status, gpg_error_t errnum,
475 const char *fmt, ...) GT_GCC_A_PRINTF(3,4);
486 log_error (int status, gpg_error_t errnum, const char *fmt, ...)
490 fprintf (log_stream, "%s: ", program_name);
492 vfprintf (log_stream, fmt, ap);
495 fprintf (log_stream, ": %s <%s>", gpg_strerror (errnum),
496 gpg_strsource (errnum));
497 fprintf (log_stream, "\n");
503 /* Check whether the option NAME appears in LINE. */
505 has_option (const char *line, const char *name)
508 int n = strlen (name);
510 s = strstr (line, name);
511 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
514 /* Skip over options. It is assumed that leading spaces have been
515 removed (this is the case for lines passed to a handler from
516 assuan). Blanks after the options are also removed. */
518 skip_options (char *line)
520 while ( *line == '-' && line[1] == '-' )
522 while (*line && !spacep (line))
524 while (spacep (line))
533 typedef gpg_error_t (*result_xml_write_cb_t) (void *hook, const void *buf,
536 struct result_xml_state
539 result_xml_write_cb_t cb;
545 int had_data[MAX_TAGS];
550 result_init (struct result_xml_state *state, int indent,
551 result_xml_write_cb_t cb, void *hook)
553 memset (state, '\0', sizeof (*state));
554 state->indent = indent;
561 result_xml_indent (struct result_xml_state *state)
563 char spaces[state->indent + 1];
565 for (i = 0; i < state->indent; i++)
568 return (*state->cb) (state->hook, spaces, i);
573 result_xml_tag_start (struct result_xml_state *state, char *name, ...)
575 result_xml_write_cb_t cb = state->cb;
576 void *hook = state->hook;
583 if (state->next_tag > 0)
585 if (! state->had_data[state->next_tag - 1])
587 (*cb) (hook, ">\n", 2);
588 (*cb) (hook, NULL, 0);
590 state->had_data[state->next_tag - 1] = 1;
593 result_xml_indent (state);
594 (*cb) (hook, "<", 1);
595 (*cb) (hook, name, strlen (name));
597 state->tag[state->next_tag] = name;
598 state->had_data[state->next_tag] = 0;
604 attr = va_arg (ap, char *);
608 attr_val = va_arg (ap, char *);
609 if (attr_val == NULL)
612 (*cb) (hook, " ", 1);
613 (*cb) (hook, attr, strlen (attr));
614 (*cb) (hook, "=\"", 2);
615 (*cb) (hook, attr_val, strlen (attr_val));
616 (*cb) (hook, "\"", 1);
624 result_xml_tag_data (struct result_xml_state *state, char *data)
626 result_xml_write_cb_t cb = state->cb;
627 void *hook = state->hook;
629 if (state->had_data[state->next_tag - 1])
631 (*cb) (hook, "\n", 2);
632 (*cb) (hook, NULL, 0);
633 result_xml_indent (state);
636 (*cb) (hook, ">", 1);
637 state->had_data[state->next_tag - 1] = 2;
639 (*cb) (hook, data, strlen (data));
646 result_xml_tag_end (struct result_xml_state *state)
648 result_xml_write_cb_t cb = state->cb;
649 void *hook = state->hook;
654 if (state->had_data[state->next_tag])
656 if (state->had_data[state->next_tag] == 1)
657 result_xml_indent (state);
658 (*cb) (hook, "</", 2);
659 (*cb) (hook, state->tag[state->next_tag],
660 strlen (state->tag[state->next_tag]));
661 (*cb) (hook, ">\n", 2);
662 (*cb) (hook, NULL, 0);
666 (*cb) (hook, " />\n", 4);
667 (*cb) (hook, NULL, 0);
674 result_add_error (struct result_xml_state *state, char *name, gpg_error_t err)
678 snprintf (code, sizeof (code) - 1, "0x%x", err);
679 snprintf (msg, sizeof (msg) - 1, "%s <%s>",
680 gpg_strerror (err), gpg_strsource (err));
681 result_xml_tag_start (state, name, "value", code, NULL);
682 result_xml_tag_data (state, msg);
683 result_xml_tag_end (state);
689 result_add_pubkey_algo (struct result_xml_state *state,
690 char *name, gpgme_pubkey_algo_t algo)
694 snprintf (code, sizeof (code) - 1, "0x%x", algo);
695 snprintf (msg, sizeof (msg) - 1, "%s",
696 gpgme_pubkey_algo_name (algo));
697 result_xml_tag_start (state, name, "value", code, NULL);
698 result_xml_tag_data (state, msg);
699 result_xml_tag_end (state);
705 result_add_hash_algo (struct result_xml_state *state,
706 char *name, gpgme_hash_algo_t algo)
710 snprintf (code, sizeof (code) - 1, "0x%x", algo);
711 snprintf (msg, sizeof (msg) - 1, "%s",
712 gpgme_hash_algo_name (algo));
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_keyid (struct result_xml_state *state, char *name, char *keyid)
723 result_xml_tag_start (state, name, NULL);
724 result_xml_tag_data (state, keyid);
725 result_xml_tag_end (state);
731 result_add_fpr (struct result_xml_state *state, char *name, char *fpr)
733 result_xml_tag_start (state, name, NULL);
734 result_xml_tag_data (state, fpr);
735 result_xml_tag_end (state);
741 result_add_timestamp (struct result_xml_state *state, char *name,
742 unsigned int timestamp)
746 snprintf (code, sizeof (code) - 1, "%ui", timestamp);
747 result_xml_tag_start (state, name, "unix", code);
748 result_xml_tag_end (state);
754 result_add_sig_mode (struct result_xml_state *state, char *name,
755 gpgme_sig_mode_t sig_mode)
760 snprintf (code, sizeof (code) - 1, "%i", sig_mode);
763 case GPGME_SIG_MODE_NORMAL:
766 case GPGME_SIG_MODE_DETACH:
769 case GPGME_SIG_MODE_CLEAR:
776 result_xml_tag_start (state, name, "type", mode, "value", code, NULL);
777 result_xml_tag_data (state, mode);
778 result_xml_tag_end (state);
784 result_add_value (struct result_xml_state *state,
785 char *name, unsigned int val)
789 snprintf (code, sizeof (code) - 1, "0x%x", val);
790 result_xml_tag_start (state, name, "value", code, NULL);
791 result_xml_tag_end (state);
797 result_add_string (struct result_xml_state *state,
798 char *name, char *str)
800 result_xml_tag_start (state, name, NULL);
801 result_xml_tag_data (state, str);
802 result_xml_tag_end (state);
808 result_encrypt_to_xml (gpgme_ctx_t ctx, int indent,
809 result_xml_write_cb_t cb, void *hook)
811 struct result_xml_state state;
812 gpgme_encrypt_result_t res = gpgme_op_encrypt_result (ctx);
813 gpgme_invalid_key_t inv_recp;
818 result_init (&state, indent, cb, hook);
819 result_xml_tag_start (&state, "encrypt-result", NULL);
821 inv_recp = res->invalid_recipients;
824 result_xml_tag_start (&state, "invalid-recipients", NULL);
828 result_xml_tag_start (&state, "invalid-key", NULL);
829 result_add_fpr (&state, "fpr", inv_recp->fpr);
830 result_add_error (&state, "reason", inv_recp->reason);
831 result_xml_tag_end (&state);
832 inv_recp = inv_recp->next;
834 result_xml_tag_end (&state);
836 result_xml_tag_end (&state);
843 result_decrypt_to_xml (gpgme_ctx_t ctx, int indent,
844 result_xml_write_cb_t cb, void *hook)
846 struct result_xml_state state;
847 gpgme_decrypt_result_t res = gpgme_op_decrypt_result (ctx);
848 gpgme_recipient_t recp;
853 result_init (&state, indent, cb, hook);
854 result_xml_tag_start (&state, "decrypt-result", NULL);
858 result_xml_tag_start (&state, "file-name", NULL);
859 result_xml_tag_data (&state, res->file_name);
860 result_xml_tag_end (&state);
862 if (res->unsupported_algorithm)
864 result_xml_tag_start (&state, "unsupported-alogorithm", NULL);
865 result_xml_tag_data (&state, res->unsupported_algorithm);
866 result_xml_tag_end (&state);
868 if (res->wrong_key_usage)
870 result_xml_tag_start (&state, "wrong-key-usage", NULL);
871 result_xml_tag_end (&state);
874 recp = res->recipients;
877 result_xml_tag_start (&state, "recipients", NULL);
880 result_xml_tag_start (&state, "recipient", NULL);
881 result_add_keyid (&state, "keyid", recp->keyid);
882 result_add_pubkey_algo (&state, "pubkey-algo", recp->pubkey_algo);
883 result_add_error (&state, "status", recp->status);
884 result_xml_tag_end (&state);
887 result_xml_tag_end (&state);
889 result_xml_tag_end (&state);
896 result_sign_to_xml (gpgme_ctx_t ctx, int indent,
897 result_xml_write_cb_t cb, void *hook)
899 struct result_xml_state state;
900 gpgme_sign_result_t res = gpgme_op_sign_result (ctx);
901 gpgme_invalid_key_t inv_key;
902 gpgme_new_signature_t new_sig;
907 result_init (&state, indent, cb, hook);
908 result_xml_tag_start (&state, "sign-result", NULL);
910 inv_key = res->invalid_signers;
913 result_xml_tag_start (&state, "invalid-signers", NULL);
917 result_xml_tag_start (&state, "invalid-key", NULL);
918 result_add_fpr (&state, "fpr", inv_key->fpr);
919 result_add_error (&state, "reason", inv_key->reason);
920 result_xml_tag_end (&state);
921 inv_key = inv_key->next;
923 result_xml_tag_end (&state);
926 new_sig = res->signatures;
929 result_xml_tag_start (&state, "signatures", NULL);
933 result_xml_tag_start (&state, "new-signature", NULL);
934 result_add_sig_mode (&state, "type", new_sig->type);
935 result_add_pubkey_algo (&state, "pubkey-algo", new_sig->pubkey_algo);
936 result_add_hash_algo (&state, "hash-algo", new_sig->hash_algo);
937 result_add_timestamp (&state, "timestamp", new_sig->timestamp);
938 result_add_fpr (&state, "fpr", new_sig->fpr);
939 result_add_value (&state, "sig-class", new_sig->sig_class);
941 result_xml_tag_end (&state);
942 new_sig = new_sig->next;
944 result_xml_tag_end (&state);
947 result_xml_tag_end (&state);
954 result_verify_to_xml (gpgme_ctx_t ctx, int indent,
955 result_xml_write_cb_t cb, void *hook)
957 struct result_xml_state state;
958 gpgme_verify_result_t res = gpgme_op_verify_result (ctx);
959 gpgme_signature_t sig;
964 result_init (&state, indent, cb, hook);
965 result_xml_tag_start (&state, "verify-result", NULL);
969 result_xml_tag_start (&state, "file-name", NULL);
970 result_xml_tag_data (&state, res->file_name);
971 result_xml_tag_end (&state);
974 sig = res->signatures;
977 result_xml_tag_start (&state, "signatures", NULL);
981 result_xml_tag_start (&state, "signature", NULL);
983 /* FIXME: Could be done better. */
984 result_add_value (&state, "summary", sig->summary);
985 result_add_fpr (&state, "fpr", sig->fpr);
986 result_add_error (&state, "status", sig->status);
987 /* FIXME: notations */
988 result_add_timestamp (&state, "timestamp", sig->timestamp);
989 result_add_timestamp (&state, "exp-timestamp", sig->exp_timestamp);
990 result_add_value (&state, "wrong-key-usage", sig->wrong_key_usage);
991 result_add_value (&state, "pka-trust", sig->pka_trust);
992 result_add_value (&state, "chain-model", sig->chain_model);
993 result_add_value (&state, "validity", sig->validity);
994 result_add_error (&state, "validity-reason", sig->validity_reason);
995 result_add_pubkey_algo (&state, "pubkey-algo", sig->pubkey_algo);
996 result_add_hash_algo (&state, "hash-algo", sig->hash_algo);
997 if (sig->pka_address)
998 result_add_string (&state, "pka_address", sig->pka_address);
1000 result_xml_tag_end (&state);
1003 result_xml_tag_end (&state);
1006 result_xml_tag_end (&state);
1013 result_import_to_xml (gpgme_ctx_t ctx, int indent,
1014 result_xml_write_cb_t cb, void *hook)
1016 struct result_xml_state state;
1017 gpgme_import_result_t res = gpgme_op_import_result (ctx);
1018 gpgme_import_status_t stat;
1023 result_init (&state, indent, cb, hook);
1024 result_xml_tag_start (&state, "import-result", NULL);
1026 result_add_value (&state, "considered", res->considered);
1027 result_add_value (&state, "no-user-id", res->no_user_id);
1028 result_add_value (&state, "imported", res->imported);
1029 result_add_value (&state, "imported-rsa", res->imported_rsa);
1030 result_add_value (&state, "unchanged", res->unchanged);
1031 result_add_value (&state, "new-user-ids", res->new_user_ids);
1032 result_add_value (&state, "new-sub-keys", res->new_sub_keys);
1033 result_add_value (&state, "new-signatures", res->new_signatures);
1034 result_add_value (&state, "new-revocations", res->new_revocations);
1035 result_add_value (&state, "secret-read", res->secret_read);
1036 result_add_value (&state, "secret-imported", res->secret_imported);
1037 result_add_value (&state, "secret-unchanged", res->secret_unchanged);
1038 result_add_value (&state, "skipped-new-keys", res->skipped_new_keys);
1039 result_add_value (&state, "not-imported", res->not_imported);
1041 stat = res->imports;
1044 result_xml_tag_start (&state, "imports", NULL);
1048 result_xml_tag_start (&state, "import-status", NULL);
1050 result_add_fpr (&state, "fpr", stat->fpr);
1051 result_add_error (&state, "result", stat->result);
1052 /* FIXME: Could be done better. */
1053 result_add_value (&state, "status", stat->status);
1055 result_xml_tag_end (&state);
1058 result_xml_tag_end (&state);
1061 result_xml_tag_end (&state);
1068 result_genkey_to_xml (gpgme_ctx_t ctx, int indent,
1069 result_xml_write_cb_t cb, void *hook)
1071 struct result_xml_state state;
1072 gpgme_genkey_result_t res = gpgme_op_genkey_result (ctx);
1077 result_init (&state, indent, cb, hook);
1078 result_xml_tag_start (&state, "genkey-result", NULL);
1080 result_add_value (&state, "primary", res->primary);
1081 result_add_value (&state, "sub", res->sub);
1082 result_add_fpr (&state, "fpr", res->fpr);
1084 result_xml_tag_end (&state);
1091 result_keylist_to_xml (gpgme_ctx_t ctx, int indent,
1092 result_xml_write_cb_t cb, void *hook)
1094 struct result_xml_state state;
1095 gpgme_keylist_result_t res = gpgme_op_keylist_result (ctx);
1100 result_init (&state, indent, cb, hook);
1101 result_xml_tag_start (&state, "keylist-result", NULL);
1103 result_add_value (&state, "truncated", res->truncated);
1105 result_xml_tag_end (&state);
1112 result_vfs_mount_to_xml (gpgme_ctx_t ctx, int indent,
1113 result_xml_write_cb_t cb, void *hook)
1115 struct result_xml_state state;
1116 gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (ctx);
1121 result_init (&state, indent, cb, hook);
1122 result_xml_tag_start (&state, "vfs-mount-result", NULL);
1124 result_add_string (&state, "mount-dir", res->mount_dir);
1126 result_xml_tag_end (&state);
1139 STATUS_INCLUDE_CERTS,
1140 STATUS_KEYLIST_MODE,
1142 STATUS_ENCRYPT_RESULT
1145 const char *status_string[] =
1161 #define MAX_RECIPIENTS 10
1162 gpgme_key_t recipients[MAX_RECIPIENTS + 1];
1165 gpg_error_t (*write_status) (void *hook, const char *status, const char *msg);
1166 void *write_status_hook;
1167 gpg_error_t (*write_data) (void *hook, const void *buf, size_t len);
1168 void *write_data_hook;
1170 typedef struct gpgme_tool *gpgme_tool_t;
1173 /* Forward declaration. */
1174 void gt_write_status (gpgme_tool_t gt,
1175 status_t status, ...) GT_GCC_A_SENTINEL(0);
1178 _gt_progress_cb (void *opaque, const char *what,
1179 int type, int current, int total)
1181 gpgme_tool_t gt = opaque;
1184 snprintf (buf, sizeof (buf), "0x%02x %i %i", type, current, total);
1185 gt_write_status (gt, STATUS_PROGRESS, what, buf, NULL);
1190 _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
1194 err = gpgme_new (ctx);
1197 gpgme_set_progress_cb (*ctx, _gt_progress_cb, gt);
1203 gt_init (gpgme_tool_t gt)
1205 memset (gt, '\0', sizeof (*gt));
1208 err = _gt_gpgme_new (gt, >->ctx);
1210 log_error (1, err, "can't create gpgme context");
1215 gt_signers_add (gpgme_tool_t gt, const char *fpr)
1220 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1224 return gpgme_signers_add (gt->ctx, key);
1229 gt_signers_clear (gpgme_tool_t gt)
1231 gpgme_signers_clear (gt->ctx);
1237 gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key)
1240 gpgme_ctx_t listctx;
1244 if (!gt || !r_key || !pattern)
1245 return gpg_error (GPG_ERR_INV_VALUE);
1249 err = gpgme_new (&listctx);
1254 gpgme_protocol_t proto;
1255 gpgme_engine_info_t info;
1257 /* Clone the relevant state. */
1258 proto = gpgme_get_protocol (ctx);
1259 /* The g13 protocol does not allow keylisting, we need to choose
1261 if (proto == GPGME_PROTOCOL_G13)
1262 proto = GPGME_PROTOCOL_OpenPGP;
1264 gpgme_set_protocol (listctx, proto);
1265 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1266 info = gpgme_ctx_get_engine_info (ctx);
1267 while (info && info->protocol != proto)
1270 gpgme_ctx_set_engine_info (listctx, proto,
1271 info->file_name, info->home_dir);
1274 err = gpgme_op_keylist_start (listctx, pattern, 0);
1276 err = gpgme_op_keylist_next (listctx, r_key);
1280 err = gpgme_op_keylist_next (listctx, &key);
1281 if (gpgme_err_code (err) == GPG_ERR_EOF)
1286 && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1287 && key && key->subkeys && key->subkeys->fpr
1288 && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1290 /* The fingerprint is identical. We assume that this is
1291 the same key and don't mark it as an ambiguous. This
1292 problem may occur with corrupted keyrings and has
1293 been noticed often with gpgsm. In fact gpgsm uses a
1294 similar hack to sort out such duplicates but it can't
1295 do that while listing keys. */
1296 gpgme_key_unref (key);
1301 gpgme_key_unref (key);
1302 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1304 gpgme_key_unref (*r_key);
1307 gpgme_release (listctx);
1310 gt_write_status (gt, STATUS_RECIPIENT,
1311 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1312 (*r_key)->subkeys->fpr : "invalid", NULL);
1318 gt_recipients_add (gpgme_tool_t gt, const char *pattern)
1323 if (gt->recipients_nr >= MAX_RECIPIENTS)
1324 return gpg_error_from_errno (ENOMEM);
1326 if (gpgme_get_protocol (gt->ctx) == GPGME_PROTOCOL_UISERVER)
1327 err = gpgme_key_from_uid (&key, pattern);
1329 err = gt_get_key (gt, pattern, &key);
1333 gt->recipients[gt->recipients_nr++] = key;
1339 gt_recipients_clear (gpgme_tool_t gt)
1343 for (idx = 0; idx < gt->recipients_nr; idx++)
1344 gpgme_key_unref (gt->recipients[idx]);
1345 memset (gt->recipients, '\0', gt->recipients_nr * sizeof (gpgme_key_t));
1346 gt->recipients_nr = 0;
1351 gt_reset (gpgme_tool_t gt)
1356 err = _gt_gpgme_new (gt, &ctx);
1360 gpgme_release (gt->ctx);
1362 gt_recipients_clear (gt);
1368 gt_write_status (gpgme_tool_t gt, status_t status, ...)
1377 va_start (ap, status);
1380 while ((text = va_arg (ap, const char *)))
1387 while (*text && n < sizeof (buf) - 2)
1396 err = gt->write_status (gt->write_status_hook, status_string[status], buf);
1398 log_error (1, err, "can't write status line");
1403 gt_write_data (gpgme_tool_t gt, const void *buf, size_t len)
1405 return gt->write_data (gt->write_data_hook, buf, len);
1410 gt_get_engine_info (gpgme_tool_t gt, gpgme_protocol_t proto)
1412 gpgme_engine_info_t info;
1413 info = gpgme_ctx_get_engine_info (gt->ctx);
1416 if (proto == GPGME_PROTOCOL_UNKNOWN || proto == info->protocol)
1417 gt_write_status (gt, STATUS_ENGINE,
1418 gpgme_get_protocol_name (info->protocol),
1419 info->file_name, info->version,
1420 info->req_version, info->home_dir, NULL);
1428 gt_protocol_from_name (const char *name)
1430 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_OpenPGP)))
1431 return GPGME_PROTOCOL_OpenPGP;
1432 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_CMS)))
1433 return GPGME_PROTOCOL_CMS;
1434 if (! strcasecmp (name,gpgme_get_protocol_name (GPGME_PROTOCOL_GPGCONF)))
1435 return GPGME_PROTOCOL_GPGCONF;
1436 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_ASSUAN)))
1437 return GPGME_PROTOCOL_ASSUAN;
1438 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_G13)))
1439 return GPGME_PROTOCOL_G13;
1440 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_UISERVER)))
1441 return GPGME_PROTOCOL_UISERVER;
1442 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_DEFAULT)))
1443 return GPGME_PROTOCOL_DEFAULT;
1444 return GPGME_PROTOCOL_UNKNOWN;
1449 gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1451 return gpgme_set_protocol (gt->ctx, proto);
1456 gt_get_protocol (gpgme_tool_t gt)
1458 gpgme_protocol_t proto = gpgme_get_protocol (gt->ctx);
1460 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1468 gt_set_sub_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1470 return gpgme_set_sub_protocol (gt->ctx, proto);
1475 gt_get_sub_protocol (gpgme_tool_t gt)
1477 gpgme_protocol_t proto = gpgme_get_sub_protocol (gt->ctx);
1479 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1487 gt_set_armor (gpgme_tool_t gt, int armor)
1489 gpgme_set_armor (gt->ctx, armor);
1495 gt_get_armor (gpgme_tool_t gt)
1497 gt_write_status (gt, STATUS_ARMOR,
1498 gpgme_get_armor (gt->ctx) ? "true" : "false", NULL);
1505 gt_set_textmode (gpgme_tool_t gt, int textmode)
1507 gpgme_set_textmode (gt->ctx, textmode);
1513 gt_get_textmode (gpgme_tool_t gt)
1515 gt_write_status (gt, STATUS_TEXTMODE,
1516 gpgme_get_textmode (gt->ctx) ? "true" : "false", NULL);
1523 gt_set_keylist_mode (gpgme_tool_t gt, gpgme_keylist_mode_t keylist_mode)
1525 gpgme_set_keylist_mode (gt->ctx, keylist_mode);
1531 gt_get_keylist_mode (gpgme_tool_t gt)
1533 #define NR_KEYLIST_MODES 6
1534 const char *modes[NR_KEYLIST_MODES + 1];
1536 gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx);
1538 if (mode & GPGME_KEYLIST_MODE_LOCAL)
1539 modes[idx++] = "local";
1540 if (mode & GPGME_KEYLIST_MODE_EXTERN)
1541 modes[idx++] = "extern";
1542 if (mode & GPGME_KEYLIST_MODE_SIGS)
1543 modes[idx++] = "sigs";
1544 if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
1545 modes[idx++] = "sig_notations";
1546 if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
1547 modes[idx++] = "ephemeral";
1548 if (mode & GPGME_KEYLIST_MODE_VALIDATE)
1549 modes[idx++] = "validate";
1550 modes[idx++] = NULL;
1552 gt_write_status (gt, STATUS_KEYLIST_MODE, modes[0], modes[1], modes[2],
1553 modes[3], modes[4], modes[5], modes[6], NULL);
1560 gt_set_include_certs (gpgme_tool_t gt, int include_certs)
1562 gpgme_set_include_certs (gt->ctx, include_certs);
1568 gt_get_include_certs (gpgme_tool_t gt)
1570 int include_certs = gpgme_get_include_certs (gt->ctx);
1573 if (include_certs == GPGME_INCLUDE_CERTS_DEFAULT)
1574 strcpy (buf, "default");
1576 snprintf (buf, sizeof (buf), "%i", include_certs);
1578 gt_write_status (gt, STATUS_INCLUDE_CERTS, buf, NULL);
1585 gt_decrypt_verify (gpgme_tool_t gt, gpgme_data_t cipher, gpgme_data_t plain,
1589 return gpgme_op_decrypt_verify (gt->ctx, cipher, plain);
1591 return gpgme_op_decrypt (gt->ctx, cipher, plain);
1596 gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
1597 gpgme_data_t plain, gpgme_data_t cipher, int sign)
1602 err = gpgme_op_encrypt_sign (gt->ctx, gt->recipients, flags, plain, cipher);
1604 err = gpgme_op_encrypt (gt->ctx, gt->recipients, flags, plain, cipher);
1606 gt_recipients_clear (gt);
1613 gt_sign (gpgme_tool_t gt, gpgme_data_t plain, gpgme_data_t sig,
1614 gpgme_sig_mode_t mode)
1616 return gpgme_op_sign (gt->ctx, plain, sig, mode);
1621 gt_verify (gpgme_tool_t gt, gpgme_data_t sig, gpgme_data_t sig_text,
1624 return gpgme_op_verify (gt->ctx, sig, sig_text, plain);
1629 gt_import (gpgme_tool_t gt, gpgme_data_t data)
1631 return gpgme_op_import (gt->ctx, data);
1636 gt_export (gpgme_tool_t gt, const char *pattern[], gpgme_export_mode_t mode,
1639 return gpgme_op_export_ext (gt->ctx, pattern, mode, data);
1644 gt_genkey (gpgme_tool_t gt, const char *parms, gpgme_data_t public,
1645 gpgme_data_t secret)
1647 return gpgme_op_genkey (gt->ctx, parms, public, secret);
1652 gt_import_keys (gpgme_tool_t gt, char *fpr[])
1664 return gpg_error (GPG_ERR_INV_VALUE);
1666 keys = malloc ((cnt + 1) * sizeof (gpgme_key_t));
1668 return gpg_error_from_syserror ();
1670 for (idx = 0; idx < cnt; idx++)
1672 err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0);
1679 err = gpgme_op_import_keys (gt->ctx, keys);
1684 gpgme_key_unref (keys[idx]);
1692 gt_delete (gpgme_tool_t gt, char *fpr, int allow_secret)
1697 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1701 err = gpgme_op_delete (gt->ctx, key, allow_secret);
1702 gpgme_key_unref (key);
1708 gt_keylist_start (gpgme_tool_t gt, const char *pattern[], int secret_only)
1710 return gpgme_op_keylist_ext_start (gt->ctx, pattern, secret_only, 0);
1715 gt_keylist_next (gpgme_tool_t gt, gpgme_key_t *key)
1717 return gpgme_op_keylist_next (gt->ctx, key);
1722 gt_getauditlog (gpgme_tool_t gt, gpgme_data_t output, unsigned int flags)
1724 return gpgme_op_getauditlog (gt->ctx, output, flags);
1729 gt_vfs_mount (gpgme_tool_t gt, const char *container_file,
1730 const char *mount_dir, int flags)
1734 err = gpgme_op_vfs_mount (gt->ctx, container_file, mount_dir, flags, &op_err);
1735 return err ? err : op_err;
1740 gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
1744 err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file,
1746 gt_recipients_clear (gt);
1747 return err ? err : op_err;
1751 static const char hlp_passwd[] =
1752 "PASSWD <user-id>\n"
1754 "Ask the backend to change the passphrase for the key\n"
1755 "specified by USER-ID.";
1757 gt_passwd (gpgme_tool_t gt, char *fpr)
1762 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1764 return gpg_err_code (err) == GPG_ERR_EOF? gpg_error (GPG_ERR_NO_PUBKEY):err;
1766 err = gpgme_op_passwd (gt->ctx, key, 0);
1767 gpgme_key_unref (key);
1772 #define GT_RESULT_ENCRYPT 0x1
1773 #define GT_RESULT_DECRYPT 0x2
1774 #define GT_RESULT_SIGN 0x4
1775 #define GT_RESULT_VERIFY 0x8
1776 #define GT_RESULT_IMPORT 0x10
1777 #define GT_RESULT_GENKEY 0x20
1778 #define GT_RESULT_KEYLIST 0x40
1779 #define GT_RESULT_VFS_MOUNT 0x80
1780 #define GT_RESULT_ALL (~0U)
1783 gt_result (gpgme_tool_t gt, unsigned int flags)
1785 static const char xml_preamble1[] = "<?xml version=\"1.0\" "
1786 "encoding=\"UTF-8\" standalone=\"yes\"?>\n";
1787 static const char xml_preamble2[] = "<gpgme>\n";
1788 static const char xml_end[] = "</gpgme>\n";
1791 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
1792 gt_write_data (gt, NULL, 0);
1793 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
1794 gt_write_data (gt, NULL, 0);
1795 if (flags & GT_RESULT_ENCRYPT)
1796 result_encrypt_to_xml (gt->ctx, indent,
1797 (result_xml_write_cb_t) gt_write_data, gt);
1798 if (flags & GT_RESULT_DECRYPT)
1799 result_decrypt_to_xml (gt->ctx, indent,
1800 (result_xml_write_cb_t) gt_write_data, gt);
1801 if (flags & GT_RESULT_SIGN)
1802 result_sign_to_xml (gt->ctx, indent,
1803 (result_xml_write_cb_t) gt_write_data, gt);
1804 if (flags & GT_RESULT_VERIFY)
1805 result_verify_to_xml (gt->ctx, indent,
1806 (result_xml_write_cb_t) gt_write_data, gt);
1807 if (flags & GT_RESULT_IMPORT)
1808 result_import_to_xml (gt->ctx, indent,
1809 (result_xml_write_cb_t) gt_write_data, gt);
1810 if (flags & GT_RESULT_GENKEY)
1811 result_genkey_to_xml (gt->ctx, indent,
1812 (result_xml_write_cb_t) gt_write_data, gt);
1813 if (flags & GT_RESULT_KEYLIST)
1814 result_keylist_to_xml (gt->ctx, indent,
1815 (result_xml_write_cb_t) gt_write_data, gt);
1816 if (flags & GT_RESULT_VFS_MOUNT)
1817 result_vfs_mount_to_xml (gt->ctx, indent,
1818 (result_xml_write_cb_t) gt_write_data, gt);
1819 gt_write_data (gt, xml_end, sizeof (xml_end));
1832 assuan_context_t assuan_ctx;
1834 gpgme_data_encoding_t input_enc;
1835 gpgme_data_encoding_t output_enc;
1836 assuan_fd_t message_fd;
1837 gpgme_data_encoding_t message_enc;
1842 server_write_status (void *hook, const char *status, const char *msg)
1844 struct server *server = hook;
1845 return assuan_write_status (server->assuan_ctx, status, msg);
1850 server_write_data (void *hook, const void *buf, size_t len)
1852 struct server *server = hook;
1853 return assuan_send_data (server->assuan_ctx, buf, len);
1857 static gpgme_data_encoding_t
1858 server_data_encoding (const char *line)
1860 if (strstr (line, "--binary"))
1861 return GPGME_DATA_ENCODING_BINARY;
1862 if (strstr (line, "--base64"))
1863 return GPGME_DATA_ENCODING_BASE64;
1864 if (strstr (line, "--armor"))
1865 return GPGME_DATA_ENCODING_ARMOR;
1866 if (strstr (line, "--url"))
1867 return GPGME_DATA_ENCODING_URL;
1868 if (strstr (line, "--urlesc"))
1869 return GPGME_DATA_ENCODING_URLESC;
1870 if (strstr (line, "--url0"))
1871 return GPGME_DATA_ENCODING_URL0;
1872 return GPGME_DATA_ENCODING_NONE;
1876 static gpgme_error_t
1877 server_data_obj (assuan_fd_t fd, gpgme_data_encoding_t encoding,
1882 err = gpgme_data_new_from_fd (data, fd);
1885 return gpgme_data_set_encoding (*data, encoding);
1890 server_reset_fds (struct server *server)
1892 /* assuan closes the input and output FDs for us when doing a RESET,
1893 but we use this same function after commands, so repeat it
1895 assuan_close_input_fd (server->assuan_ctx);
1896 assuan_close_output_fd (server->assuan_ctx);
1897 if (server->message_fd != -1)
1899 /* FIXME: Assuan should provide a close function. */
1900 close (server->message_fd);
1901 server->message_fd = -1;
1903 server->input_enc = GPGME_DATA_ENCODING_NONE;
1904 server->output_enc = GPGME_DATA_ENCODING_NONE;
1905 server->message_enc = GPGME_DATA_ENCODING_NONE;
1910 reset_notify (assuan_context_t ctx, char *line)
1912 struct server *server = assuan_get_pointer (ctx);
1913 server_reset_fds (server);
1914 gt_reset (server->gt);
1918 static const char hlp_version[] =
1919 "VERSION [<string>]\n"
1921 "Call the function gpgme_check_version.";
1923 cmd_version (assuan_context_t ctx, char *line)
1927 const char *version = gpgme_check_version (line);
1928 return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
1932 const char *version = gpgme_check_version (NULL);
1933 return assuan_send_data (ctx, version, strlen (version));
1939 cmd_engine (assuan_context_t ctx, char *line)
1941 struct server *server = assuan_get_pointer (ctx);
1942 return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
1946 static const char hlp_protocol[] =
1947 "PROTOCOL [<name>]\n"
1949 "With NAME, set the protocol. Without return the current protocol.";
1951 cmd_protocol (assuan_context_t ctx, char *line)
1953 struct server *server = assuan_get_pointer (ctx);
1955 return gt_set_protocol (server->gt, gt_protocol_from_name (line));
1957 return gt_get_protocol (server->gt);
1962 cmd_sub_protocol (assuan_context_t ctx, char *line)
1964 struct server *server = assuan_get_pointer (ctx);
1966 return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
1968 return gt_get_sub_protocol (server->gt);
1973 cmd_armor (assuan_context_t ctx, char *line)
1975 struct server *server = assuan_get_pointer (ctx);
1980 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
1984 return gt_set_armor (server->gt, flag);
1987 return gt_get_armor (server->gt);
1992 cmd_textmode (assuan_context_t ctx, char *line)
1994 struct server *server = assuan_get_pointer (ctx);
1999 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2003 return gt_set_textmode (server->gt, flag);
2006 return gt_get_textmode (server->gt);
2011 cmd_include_certs (assuan_context_t ctx, char *line)
2013 struct server *server = assuan_get_pointer (ctx);
2017 int include_certs = 0;
2019 if (! strcasecmp (line, "default"))
2020 include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
2022 include_certs = atoi (line);
2024 return gt_set_include_certs (server->gt, include_certs);
2027 return gt_get_include_certs (server->gt);
2032 cmd_keylist_mode (assuan_context_t ctx, char *line)
2034 struct server *server = assuan_get_pointer (ctx);
2038 gpgme_keylist_mode_t mode = 0;
2040 if (strstr (line, "local"))
2041 mode |= GPGME_KEYLIST_MODE_LOCAL;
2042 if (strstr (line, "extern"))
2043 mode |= GPGME_KEYLIST_MODE_EXTERN;
2044 if (strstr (line, "sigs"))
2045 mode |= GPGME_KEYLIST_MODE_SIGS;
2046 if (strstr (line, "sig_notations"))
2047 mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
2048 if (strstr (line, "ephemeral"))
2049 mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
2050 if (strstr (line, "validate"))
2051 mode |= GPGME_KEYLIST_MODE_VALIDATE;
2053 return gt_set_keylist_mode (server->gt, mode);
2056 return gt_get_keylist_mode (server->gt);
2061 input_notify (assuan_context_t ctx, char *line)
2063 struct server *server = assuan_get_pointer (ctx);
2064 server->input_enc = server_data_encoding (line);
2070 output_notify (assuan_context_t ctx, char *line)
2072 struct server *server = assuan_get_pointer (ctx);
2073 server->output_enc = server_data_encoding (line);
2079 cmd_message (assuan_context_t ctx, char *line)
2081 struct server *server = assuan_get_pointer (ctx);
2085 err = assuan_command_parse_fd (ctx, line, &sysfd);
2088 server->message_fd = sysfd;
2089 server->message_enc = server_data_encoding (line);
2095 cmd_recipient (assuan_context_t ctx, char *line)
2097 struct server *server = assuan_get_pointer (ctx);
2099 return gt_recipients_add (server->gt, line);
2104 cmd_signer (assuan_context_t ctx, char *line)
2106 struct server *server = assuan_get_pointer (ctx);
2108 return gt_signers_add (server->gt, line);
2113 cmd_signers_clear (assuan_context_t ctx, char *line)
2115 struct server *server = assuan_get_pointer (ctx);
2117 return gt_signers_clear (server->gt);
2122 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
2124 struct server *server = assuan_get_pointer (ctx);
2128 gpgme_data_t inp_data;
2129 gpgme_data_t out_data;
2131 inp_fd = assuan_get_input_fd (ctx);
2132 if (inp_fd == ASSUAN_INVALID_FD)
2133 return GPG_ERR_ASS_NO_INPUT;
2134 out_fd = assuan_get_output_fd (ctx);
2135 if (out_fd == ASSUAN_INVALID_FD)
2136 return GPG_ERR_ASS_NO_OUTPUT;
2138 err = server_data_obj (inp_fd, server->input_enc, &inp_data);
2141 err = server_data_obj (out_fd, server->output_enc, &out_data);
2144 gpgme_data_release (inp_data);
2148 err = gt_decrypt_verify (server->gt, inp_data, out_data, verify);
2150 gpgme_data_release (inp_data);
2151 gpgme_data_release (out_data);
2153 server_reset_fds (server);
2160 cmd_decrypt (assuan_context_t ctx, char *line)
2162 return _cmd_decrypt_verify (ctx, line, 0);
2167 cmd_decrypt_verify (assuan_context_t ctx, char *line)
2169 return _cmd_decrypt_verify (ctx, line, 1);
2174 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
2176 struct server *server = assuan_get_pointer (ctx);
2180 gpgme_data_t inp_data = NULL;
2181 gpgme_data_t out_data = NULL;
2182 gpgme_encrypt_flags_t flags = 0;
2184 if (strstr (line, "--always-trust"))
2185 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
2186 if (strstr (line, "--no-encrypt-to"))
2187 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
2188 if (strstr (line, "--prepare"))
2189 flags |= GPGME_ENCRYPT_PREPARE;
2190 if (strstr (line, "--expect-sign"))
2191 flags |= GPGME_ENCRYPT_EXPECT_SIGN;
2193 inp_fd = assuan_get_input_fd (ctx);
2194 out_fd = assuan_get_output_fd (ctx);
2195 if (inp_fd != ASSUAN_INVALID_FD)
2197 err = server_data_obj (inp_fd, server->input_enc, &inp_data);
2201 if (out_fd != ASSUAN_INVALID_FD)
2203 err = server_data_obj (out_fd, server->output_enc, &out_data);
2206 gpgme_data_release (inp_data);
2211 err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign);
2213 gpgme_data_release (inp_data);
2214 gpgme_data_release (out_data);
2216 server_reset_fds (server);
2223 cmd_encrypt (assuan_context_t ctx, char *line)
2225 return _cmd_sign_encrypt (ctx, line, 0);
2230 cmd_sign_encrypt (assuan_context_t ctx, char *line)
2232 return _cmd_sign_encrypt (ctx, line, 1);
2237 cmd_sign (assuan_context_t ctx, char *line)
2239 struct server *server = assuan_get_pointer (ctx);
2243 gpgme_data_t inp_data;
2244 gpgme_data_t out_data;
2245 gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
2247 if (strstr (line, "--clear"))
2248 mode = GPGME_SIG_MODE_CLEAR;
2249 if (strstr (line, "--detach"))
2250 mode = GPGME_SIG_MODE_DETACH;
2252 inp_fd = assuan_get_input_fd (ctx);
2253 if (inp_fd == ASSUAN_INVALID_FD)
2254 return GPG_ERR_ASS_NO_INPUT;
2255 out_fd = assuan_get_output_fd (ctx);
2256 if (out_fd == ASSUAN_INVALID_FD)
2257 return GPG_ERR_ASS_NO_OUTPUT;
2259 err = server_data_obj (inp_fd, server->input_enc, &inp_data);
2262 err = server_data_obj (out_fd, server->output_enc, &out_data);
2265 gpgme_data_release (inp_data);
2269 err = gt_sign (server->gt, inp_data, out_data, mode);
2271 gpgme_data_release (inp_data);
2272 gpgme_data_release (out_data);
2273 server_reset_fds (server);
2280 cmd_verify (assuan_context_t ctx, char *line)
2282 struct server *server = assuan_get_pointer (ctx);
2287 gpgme_data_t inp_data;
2288 gpgme_data_t msg_data = NULL;
2289 gpgme_data_t out_data = NULL;
2291 inp_fd = assuan_get_input_fd (ctx);
2292 if (inp_fd == ASSUAN_INVALID_FD)
2293 return GPG_ERR_ASS_NO_INPUT;
2294 msg_fd = server->message_fd;
2295 out_fd = assuan_get_output_fd (ctx);
2297 err = server_data_obj (inp_fd, server->input_enc, &inp_data);
2300 if (msg_fd != ASSUAN_INVALID_FD)
2302 err = server_data_obj (msg_fd, server->message_enc, &msg_data);
2305 gpgme_data_release (inp_data);
2309 if (out_fd != ASSUAN_INVALID_FD)
2311 err = server_data_obj (out_fd, server->output_enc, &out_data);
2314 gpgme_data_release (inp_data);
2315 gpgme_data_release (msg_data);
2320 err = gt_verify (server->gt, inp_data, msg_data, out_data);
2322 gpgme_data_release (inp_data);
2324 gpgme_data_release (msg_data);
2326 gpgme_data_release (out_data);
2328 server_reset_fds (server);
2335 cmd_import (assuan_context_t ctx, char *line)
2337 struct server *server = assuan_get_pointer (ctx);
2341 char *fprs[2] = { line, NULL };
2343 return gt_import_keys (server->gt, fprs);
2349 gpgme_data_t inp_data;
2351 inp_fd = assuan_get_input_fd (ctx);
2352 if (inp_fd == ASSUAN_INVALID_FD)
2353 return GPG_ERR_ASS_NO_INPUT;
2355 err = server_data_obj (inp_fd, server->input_enc, &inp_data);
2359 err = gt_import (server->gt, inp_data);
2361 gpgme_data_release (inp_data);
2362 server_reset_fds (server);
2369 static const char hlp_export[] =
2370 "EXPORT [--extern] [--minimal] [<pattern>]\n"
2372 "Export the keys described by PATTERN. Write the\n"
2373 "the output to the object set by the last OUTPUT command.";
2375 cmd_export (assuan_context_t ctx, char *line)
2377 struct server *server = assuan_get_pointer (ctx);
2380 gpgme_data_t out_data;
2381 gpgme_export_mode_t mode = 0;
2382 const char *pattern[2];
2384 out_fd = assuan_get_output_fd (ctx);
2385 if (out_fd == ASSUAN_INVALID_FD)
2386 return GPG_ERR_ASS_NO_OUTPUT;
2387 err = server_data_obj (out_fd, server->output_enc, &out_data);
2391 if (has_option (line, "--extern"))
2392 mode |= GPGME_EXPORT_MODE_EXTERN;
2393 if (has_option (line, "--minimal"))
2394 mode |= GPGME_EXPORT_MODE_MINIMAL;
2396 line = skip_options (line);
2401 err = gt_export (server->gt, pattern, mode, out_data);
2403 gpgme_data_release (out_data);
2404 server_reset_fds (server);
2411 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
2415 ssize_t writen = gpgme_data_write (data, buf, size);
2416 if (writen < 0 && errno != EAGAIN)
2417 return gpg_error_from_syserror ();
2418 else if (writen > 0)
2420 buf = (void *) (((char *) buf) + writen);
2429 cmd_genkey (assuan_context_t ctx, char *line)
2431 struct server *server = assuan_get_pointer (ctx);
2435 gpgme_data_t inp_data;
2436 gpgme_data_t out_data = NULL;
2437 gpgme_data_t parms_data = NULL;
2440 inp_fd = assuan_get_input_fd (ctx);
2441 if (inp_fd == ASSUAN_INVALID_FD)
2442 return GPG_ERR_ASS_NO_INPUT;
2443 out_fd = assuan_get_output_fd (ctx);
2445 err = server_data_obj (inp_fd, server->input_enc, &inp_data);
2448 if (out_fd != ASSUAN_INVALID_FD)
2450 err = server_data_obj (out_fd, server->output_enc, &out_data);
2453 gpgme_data_release (inp_data);
2458 /* Convert input data. */
2459 err = gpgme_data_new (&parms_data);
2465 ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
2468 err = gpg_error_from_syserror ();
2471 else if (readn == 0)
2474 err = _cmd_genkey_write (parms_data, buf, readn);
2479 err = _cmd_genkey_write (parms_data, "", 1);
2482 parms = gpgme_data_release_and_get_mem (parms_data, NULL);
2486 err = gpg_error (GPG_ERR_GENERAL);
2490 err = gt_genkey (server->gt, parms, out_data, NULL);
2492 server_reset_fds (server);
2495 gpgme_data_release (inp_data);
2497 gpgme_data_release (out_data);
2499 gpgme_data_release (parms_data);
2506 cmd_delete (assuan_context_t ctx, char *line)
2508 struct server *server = assuan_get_pointer (ctx);
2509 int allow_secret = 0;
2510 const char optstr[] = "--allow-secret ";
2512 if (strncasecmp (line, optstr, strlen (optstr)))
2515 line += strlen (optstr);
2517 return gt_delete (server->gt, line, allow_secret);
2522 cmd_keylist (assuan_context_t ctx, char *line)
2524 struct server *server = assuan_get_pointer (ctx);
2526 int secret_only = 0;
2527 const char *pattern[2];
2528 const char optstr[] = "--secret-only ";
2530 if (strncasecmp (line, optstr, strlen (optstr)))
2533 line += strlen (optstr);
2538 err = gt_keylist_start (server->gt, pattern, secret_only);
2543 err = gt_keylist_next (server->gt, &key);
2544 if (gpg_err_code (err) == GPG_ERR_EOF)
2552 /* FIXME: More data. */
2553 snprintf (buf, sizeof (buf), "key:%s\n", key->subkeys->fpr);
2554 assuan_send_data (ctx, buf, strlen (buf));
2555 gpgme_key_unref (key);
2559 server_reset_fds (server);
2565 static const char hlp_getauditlog[] =
2566 "GETAUDITLOG [--html] [--with-help]\n"
2568 "Call the function gpgme_op_getauditlog with the given flags. Write\n"
2569 "the output to the object set by the last OUTPUT command.";
2571 cmd_getauditlog (assuan_context_t ctx, char *line)
2573 struct server *server = assuan_get_pointer (ctx);
2576 gpgme_data_t out_data;
2577 unsigned int flags = 0;
2579 out_fd = assuan_get_output_fd (ctx);
2580 if (out_fd == ASSUAN_INVALID_FD)
2581 return GPG_ERR_ASS_NO_OUTPUT;
2582 err = server_data_obj (out_fd, server->output_enc, &out_data);
2586 if (strstr (line, "--html"))
2587 flags |= GPGME_AUDITLOG_HTML;
2588 if (strstr (line, "--with-help"))
2589 flags |= GPGME_AUDITLOG_WITH_HELP;
2591 err = gt_getauditlog (server->gt, out_data, flags);
2593 gpgme_data_release (out_data);
2594 server_reset_fds (server);
2601 cmd_vfs_mount (assuan_context_t ctx, char *line)
2603 struct server *server = assuan_get_pointer (ctx);
2607 mount_dir = strchr (line, ' ');
2610 *(mount_dir++) = '\0';
2611 while (*mount_dir == ' ')
2615 err = gt_vfs_mount (server->gt, line, mount_dir, 0);
2622 cmd_vfs_create (assuan_context_t ctx, char *line)
2624 struct server *server = assuan_get_pointer (ctx);
2628 end = strchr (line, ' ');
2636 err = gt_vfs_create (server->gt, line, 0);
2643 cmd_passwd (assuan_context_t ctx, char *line)
2645 struct server *server = assuan_get_pointer (ctx);
2647 return gt_passwd (server->gt, line);
2653 cmd_result (assuan_context_t ctx, char *line)
2655 struct server *server = assuan_get_pointer (ctx);
2656 return gt_result (server->gt, GT_RESULT_ALL);
2660 /* STRERROR <err> */
2662 cmd_strerror (assuan_context_t ctx, char *line)
2668 snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
2669 gpgme_strsource (err));
2670 return assuan_send_data (ctx, buf, strlen (buf));
2675 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
2677 gpgme_pubkey_algo_t algo;
2681 snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
2682 return assuan_send_data (ctx, buf, strlen (buf));
2687 cmd_hash_algo_name (assuan_context_t ctx, char *line)
2689 gpgme_hash_algo_t algo;
2693 snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
2694 return assuan_send_data (ctx, buf, strlen (buf));
2698 /* Tell the assuan library about our commands. */
2700 register_commands (assuan_context_t ctx)
2705 assuan_handler_t handler;
2706 const char * const help;
2708 /* RESET, BYE are implicit. */
2709 { "VERSION", cmd_version, hlp_version },
2710 /* TODO: Set engine info. */
2711 { "ENGINE", cmd_engine },
2712 { "PROTOCOL", cmd_protocol, hlp_protocol },
2713 { "SUB_PROTOCOL", cmd_sub_protocol },
2714 { "ARMOR", cmd_armor },
2715 { "TEXTMODE", cmd_textmode },
2716 { "INCLUDE_CERTS", cmd_include_certs },
2717 { "KEYLIST_MODE", cmd_keylist_mode },
2720 { "MESSAGE", cmd_message },
2721 { "RECIPIENT", cmd_recipient },
2722 { "SIGNER", cmd_signer },
2723 { "SIGNERS_CLEAR", cmd_signers_clear },
2724 /* TODO: SIGNOTATION missing. */
2725 /* TODO: Could add wait interface if we allow more than one context */
2726 /* and add _START variants. */
2727 /* TODO: Could add data interfaces if we allow multiple data objects. */
2728 { "DECRYPT", cmd_decrypt },
2729 { "DECRYPT_VERIFY", cmd_decrypt_verify },
2730 { "ENCRYPT", cmd_encrypt },
2731 { "ENCRYPT_SIGN", cmd_sign_encrypt },
2732 { "SIGN_ENCRYPT", cmd_sign_encrypt },
2733 { "SIGN", cmd_sign },
2734 { "VERIFY", cmd_verify },
2735 { "IMPORT", cmd_import },
2736 { "EXPORT", cmd_export, hlp_export },
2737 { "GENKEY", cmd_genkey },
2738 { "DELETE", cmd_delete },
2739 /* TODO: EDIT, CARD_EDIT (with INQUIRE) */
2740 { "KEYLIST", cmd_keylist },
2741 { "LISTKEYS", cmd_keylist },
2742 /* TODO: TRUSTLIST, TRUSTLIST_EXT */
2743 { "GETAUDITLOG", cmd_getauditlog, hlp_getauditlog },
2745 { "VFS_MOUNT", cmd_vfs_mount },
2746 { "MOUNT", cmd_vfs_mount },
2747 { "VFS_CREATE", cmd_vfs_create },
2748 { "CREATE", cmd_vfs_create },
2750 { "RESULT", cmd_result },
2751 { "STRERROR", cmd_strerror },
2752 { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
2753 { "HASH_ALGO_NAME", cmd_hash_algo_name },
2754 { "PASSWD", cmd_passwd, hlp_passwd },
2759 for (idx = 0; table[idx].name; idx++)
2761 err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
2770 /* TODO: password callback can do INQUIRE. */
2772 gpgme_server (gpgme_tool_t gt)
2775 assuan_fd_t filedes[2];
2776 struct server server;
2777 static const char hello[] = ("GPGME-Tool " VERSION " ready");
2779 memset (&server, 0, sizeof (server));
2780 server.message_fd = -1;
2781 server.input_enc = GPGME_DATA_ENCODING_NONE;
2782 server.output_enc = GPGME_DATA_ENCODING_NONE;
2783 server.message_enc = GPGME_DATA_ENCODING_NONE;
2786 gt->write_status = server_write_status;
2787 gt->write_status_hook = &server;
2788 gt->write_data = server_write_data;
2789 gt->write_data_hook = &server;
2791 /* We use a pipe based server so that we can work from scripts.
2792 assuan_init_pipe_server will automagically detect when we are
2793 called with a socketpair and ignore FIELDES in this case. */
2794 filedes[0] = assuan_fdopen (0);
2795 filedes[1] = assuan_fdopen (1);
2796 err = assuan_new (&server.assuan_ctx);
2798 log_error (1, err, "can't create assuan context");
2800 assuan_set_pointer (server.assuan_ctx, &server);
2802 err = assuan_init_pipe_server (server.assuan_ctx, filedes);
2804 log_error (1, err, "can't initialize assuan server");
2805 err = register_commands (server.assuan_ctx);
2807 log_error (1, err, "can't register assuan commands");
2808 assuan_set_hello_line (server.assuan_ctx, hello);
2810 assuan_register_reset_notify (server.assuan_ctx, reset_notify);
2811 assuan_register_input_notify (server.assuan_ctx, input_notify);
2812 assuan_register_output_notify (server.assuan_ctx, output_notify);
2814 #define DBG_ASSUAN 0
2816 assuan_set_log_stream (server.assuan_ctx, log_stream);
2820 err = assuan_accept (server.assuan_ctx);
2825 log_error (0, err, "assuan accept problem");
2829 err = assuan_process (server.assuan_ctx);
2831 log_error (0, err, "assuan processing failed");
2834 assuan_release (server.assuan_ctx);
2839 /* MAIN PROGRAM STARTS HERE. */
2841 const char *argp_program_version = VERSION;
2842 const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
2843 error_t argp_err_exit_status = 1;
2845 static char doc[] = "GPGME Tool -- invoke GPGME operations";
2846 static char args_doc[] = "COMMAND [OPTIONS...]";
2848 static struct argp_option options[] = {
2849 { "server", 's', 0, 0, "Server mode" },
2853 static error_t parse_options (int key, char *arg, struct argp_state *state);
2854 static struct argp argp = { options, parse_options, args_doc, doc };
2858 enum { CMD_DEFAULT, CMD_SERVER } cmd;
2862 args_init (struct args *args)
2864 memset (args, '\0', sizeof (*args));
2865 args->cmd = CMD_DEFAULT;
2870 parse_options (int key, char *arg, struct argp_state *state)
2872 struct args *args = state->input;
2877 args->cmd = CMD_SERVER;
2881 if (state->arg_num >= 2)
2883 printf ("Arg[%i] = %s\n", state->arg_num, arg);
2886 if (state->arg_num < 2)
2892 return ARGP_ERR_UNKNOWN;
2899 main (int argc, char *argv[])
2902 struct gpgme_tool gt;
2904 setlocale (LC_ALL, "");
2905 gpgme_check_version (NULL);
2906 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
2908 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
2912 argp_parse (&argp, argc, argv, 0, 0, &args);
2925 gpgme_release (gt.ctx);