core: New context flag "ignore-mdc-error".
[gpgme.git] / tests / run-decrypt.c
1 /* run-decrypt.c  - Helper to perform a verify operation
2    Copyright (C) 2009 g10 Code GmbH
3                  2016 by Bundesamt für Sicherheit in der Informationstechnik
4                  Software engineering by Intevation GmbH
5
6    This file is part of GPGME.
7
8    GPGME is free software; you can redistribute it and/or modify it
9    under the terms of the GNU Lesser General Public License as
10    published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    GPGME is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with this program; if not, see <https://www.gnu.org/licenses/>.
20 */
21
22 /* We need to include config.h so that we know whether we are building
23    with large file system (LFS) support. */
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include <gpgme.h>
33
34 #define PGM "run-decrypt"
35
36 #include "run-support.h"
37
38
39 static int verbose;
40
41 static gpg_error_t
42 status_cb (void *opaque, const char *keyword, const char *value)
43 {
44   (void)opaque;
45   fprintf (stderr, "status_cb: %s %s\n", keyword, value);
46   return 0;
47 }
48
49
50 static void
51 print_result (gpgme_decrypt_result_t result)
52 {
53   gpgme_recipient_t recp;
54   int count = 0;
55
56   printf ("Original file name .: %s\n", nonnull(result->file_name));
57   printf ("Wrong key usage ....: %s\n", result->wrong_key_usage? "yes":"no");
58   printf ("Legacy w/o MDC ... .: %s\n", result->legacy_cipher_nomdc?"yes":"no");
59   printf ("Compliance de-vs ...: %s\n", result->is_de_vs? "yes":"no");
60   printf ("MIME flag ..........: %s\n", result->is_mime? "yes":"no");
61   printf ("Unsupported algo ...: %s\n", nonnull(result->unsupported_algorithm));
62   printf ("Session key ........: %s\n", nonnull (result->session_key));
63   printf ("Symmetric algorithm : %s\n", result->symkey_algo);
64
65   for (recp = result->recipients; recp && recp->next; recp = recp->next)
66     {
67       printf ("Recipient ...: %d\n", count++);
68       printf ("  status ....: %s\n", gpgme_strerror (recp->status));
69       printf ("  keyid .....: %s\n", nonnull (recp->keyid));
70       printf ("  algo ......: %s\n",
71               gpgme_pubkey_algo_name (recp->pubkey_algo));
72     }
73 }
74
75
76 static int
77 show_usage (int ex)
78 {
79   fputs ("usage: " PGM " [options] FILE\n\n"
80          "Options:\n"
81          "  --verbose        run in verbose mode\n"
82          "  --status         print status lines from the backend\n"
83          "  --openpgp        use the OpenPGP protocol (default)\n"
84          "  --cms            use the CMS protocol\n"
85          "  --export-session-key            show the session key\n"
86          "  --override-session-key STRING   use STRING as session key\n"
87          "  --request-origin STRING         use STRING as request origin\n"
88          "  --no-symkey-cache               disable the use of that cache\n"
89          "  --ignore-mdc-error              allow decryption of legacy data\n"
90          "  --unwrap         remove only the encryption layer\n"
91          , stderr);
92   exit (ex);
93 }
94
95
96 int
97 main (int argc, char **argv)
98 {
99   int last_argc = -1;
100   gpgme_error_t err;
101   gpgme_ctx_t ctx;
102   gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
103   gpgme_decrypt_flags_t flags = 0;
104   FILE *fp_in = NULL;
105   gpgme_data_t in = NULL;
106   gpgme_data_t out = NULL;
107   gpgme_decrypt_result_t result;
108   int print_status = 0;
109   int export_session_key = 0;
110   const char *override_session_key = NULL;
111   const char *request_origin = NULL;
112   int no_symkey_cache = 0;
113   int ignore_mdc_error = 0;
114   int raw_output = 0;
115
116   if (argc)
117     { argc--; argv++; }
118
119   while (argc && last_argc != argc )
120     {
121       last_argc = argc;
122       if (!strcmp (*argv, "--"))
123         {
124           argc--; argv++;
125           break;
126         }
127       else if (!strcmp (*argv, "--help"))
128         show_usage (0);
129       else if (!strcmp (*argv, "--verbose"))
130         {
131           verbose = 1;
132           argc--; argv++;
133         }
134       else if (!strcmp (*argv, "--status"))
135         {
136           print_status = 1;
137           argc--; argv++;
138         }
139       else if (!strcmp (*argv, "--openpgp"))
140         {
141           protocol = GPGME_PROTOCOL_OpenPGP;
142           argc--; argv++;
143         }
144       else if (!strcmp (*argv, "--cms"))
145         {
146           protocol = GPGME_PROTOCOL_CMS;
147           argc--; argv++;
148         }
149       else if (!strcmp (*argv, "--export-session-key"))
150         {
151           export_session_key = 1;
152           argc--; argv++;
153         }
154       else if (!strcmp (*argv, "--override-session-key"))
155         {
156           argc--; argv++;
157           if (!argc)
158             show_usage (1);
159           override_session_key = *argv;
160           argc--; argv++;
161         }
162       else if (!strcmp (*argv, "--request-origin"))
163         {
164           argc--; argv++;
165           if (!argc)
166             show_usage (1);
167           request_origin = *argv;
168           argc--; argv++;
169         }
170       else if (!strcmp (*argv, "--no-symkey-cache"))
171         {
172           no_symkey_cache = 1;
173           argc--; argv++;
174         }
175       else if (!strcmp (*argv, "--ignore-mdc-error"))
176         {
177           ignore_mdc_error = 1;
178           argc--; argv++;
179         }
180       else if (!strcmp (*argv, "--unwrap"))
181         {
182           flags |= GPGME_DECRYPT_UNWRAP;
183           raw_output = 1;
184           argc--; argv++;
185         }
186       else if (!strncmp (*argv, "--", 2))
187         show_usage (1);
188
189     }
190
191   if (argc < 1 || argc > 2)
192     show_usage (1);
193
194   fp_in = fopen (argv[0], "rb");
195   if (!fp_in)
196     {
197       err = gpgme_error_from_syserror ();
198       fprintf (stderr, PGM ": can't open `%s': %s\n",
199                argv[0], gpgme_strerror (err));
200       exit (1);
201     }
202
203   init_gpgme (protocol);
204
205   err = gpgme_new (&ctx);
206   fail_if_err (err);
207   gpgme_set_protocol (ctx, protocol);
208   if (print_status)
209     {
210       gpgme_set_status_cb (ctx, status_cb, NULL);
211       gpgme_set_ctx_flag (ctx, "full-status", "1");
212     }
213   if (export_session_key)
214     {
215       err = gpgme_set_ctx_flag (ctx, "export-session-key", "1");
216       if (err)
217         {
218           fprintf (stderr, PGM ": error requesting exported session key: %s\n",
219                    gpgme_strerror (err));
220           exit (1);
221         }
222     }
223   if (override_session_key)
224     {
225       err = gpgme_set_ctx_flag (ctx, "override-session-key",
226                                 override_session_key);
227       if (err)
228         {
229           fprintf (stderr, PGM ": error setting overriding session key: %s\n",
230                    gpgme_strerror (err));
231           exit (1);
232         }
233     }
234
235   if (request_origin)
236     {
237       err = gpgme_set_ctx_flag (ctx, "request-origin", request_origin);
238       if (err)
239         {
240           fprintf (stderr, PGM ": error setting request_origin: %s\n",
241                    gpgme_strerror (err));
242           exit (1);
243         }
244     }
245
246   if (no_symkey_cache)
247     {
248       err = gpgme_set_ctx_flag (ctx, "no-symkey-cache", "1");
249       if (err)
250         {
251           fprintf (stderr, PGM ": error setting no-symkey-cache: %s\n",
252                    gpgme_strerror (err));
253           exit (1);
254         }
255     }
256
257   if (ignore_mdc_error)
258     {
259       err = gpgme_set_ctx_flag (ctx, "ignore-mdc-error", "1");
260       if (err)
261         {
262           fprintf (stderr, PGM ": error setting ignore-mdc-error: %s\n",
263                    gpgme_strerror (err));
264           exit (1);
265         }
266     }
267
268   err = gpgme_data_new_from_stream (&in, fp_in);
269   if (err)
270     {
271       fprintf (stderr, PGM ": error allocating data object: %s\n",
272                gpgme_strerror (err));
273       exit (1);
274     }
275
276   err = gpgme_data_new (&out);
277   if (err)
278     {
279       fprintf (stderr, PGM ": error allocating data object: %s\n",
280                gpgme_strerror (err));
281       exit (1);
282     }
283
284   err = gpgme_op_decrypt_ext (ctx, flags, in, out);
285   result = gpgme_op_decrypt_result (ctx);
286   if (err)
287     {
288       fprintf (stderr, PGM ": decrypt failed: %s\n", gpgme_strerror (err));
289       if (result)
290         print_result (result);
291       exit (1);
292     }
293   if (result)
294     {
295       if (!raw_output)
296         print_result (result);
297       if (!raw_output)
298         fputs ("Begin Output:\n", stdout);
299       print_data (out);
300       if (!raw_output)
301         fputs ("End Output.\n", stdout);
302     }
303
304   gpgme_data_release (out);
305   gpgme_data_release (in);
306
307   gpgme_release (ctx);
308   return 0;
309 }