core,w32: Fix minor potential memleak
[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://gnu.org/licenses/>.
20  * SPDX-License-Identifier: LGPL-2.1-or-later
21  */
22
23 /* We need to include config.h so that we know whether we are building
24    with large file system (LFS) support. */
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include <gpgme.h>
34
35 #define PGM "run-decrypt"
36
37 #include "run-support.h"
38
39
40 static int verbose;
41
42 static gpg_error_t
43 status_cb (void *opaque, const char *keyword, const char *value)
44 {
45   (void)opaque;
46   fprintf (stderr, "status_cb: %s %s\n", keyword, value);
47   return 0;
48 }
49
50
51 static void
52 print_result (gpgme_decrypt_result_t result)
53 {
54   gpgme_recipient_t recp;
55   int count = 0;
56
57   printf ("Original file name .: %s\n", nonnull(result->file_name));
58   printf ("Wrong key usage ....: %s\n", result->wrong_key_usage? "yes":"no");
59   printf ("Legacy w/o MDC ... .: %s\n", result->legacy_cipher_nomdc?"yes":"no");
60   printf ("Compliance de-vs ...: %s\n", result->is_de_vs? "yes":"no");
61   printf ("MIME flag ..........: %s\n", result->is_mime? "yes":"no");
62   printf ("Unsupported algo ...: %s\n", nonnull(result->unsupported_algorithm));
63   printf ("Session key ........: %s\n", nonnull (result->session_key));
64   printf ("Symmetric algorithm : %s\n", result->symkey_algo);
65
66   for (recp = result->recipients; recp && recp->next; recp = recp->next)
67     {
68       printf ("Recipient ...: %d\n", count++);
69       printf ("  status ....: %s\n", gpgme_strerror (recp->status));
70       printf ("  keyid .....: %s\n", nonnull (recp->keyid));
71       printf ("  algo ......: %s\n",
72               gpgme_pubkey_algo_name (recp->pubkey_algo));
73     }
74 }
75
76
77 static int
78 show_usage (int ex)
79 {
80   fputs ("usage: " PGM " [options] FILE\n\n"
81          "Options:\n"
82          "  --verbose        run in verbose mode\n"
83          "  --status         print status lines from the backend\n"
84          "  --openpgp        use the OpenPGP protocol (default)\n"
85          "  --cms            use the CMS protocol\n"
86          "  --export-session-key            show the session key\n"
87          "  --override-session-key STRING   use STRING as session key\n"
88          "  --request-origin STRING         use STRING as request origin\n"
89          "  --no-symkey-cache               disable the use of that cache\n"
90          "  --ignore-mdc-error              allow decryption of legacy data\n"
91          "  --unwrap         remove only the encryption layer\n"
92          "  --diagnostics    print diagnostics\n"
93          , stderr);
94   exit (ex);
95 }
96
97
98 int
99 main (int argc, char **argv)
100 {
101   int last_argc = -1;
102   gpgme_error_t err;
103   gpgme_ctx_t ctx;
104   gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
105   gpgme_decrypt_flags_t flags = 0;
106   FILE *fp_in = NULL;
107   gpgme_data_t in = NULL;
108   gpgme_data_t out = NULL;
109   gpgme_decrypt_result_t result;
110   int print_status = 0;
111   int export_session_key = 0;
112   const char *override_session_key = NULL;
113   const char *request_origin = NULL;
114   int no_symkey_cache = 0;
115   int ignore_mdc_error = 0;
116   int raw_output = 0;
117   int diagnostics = 0;
118
119   if (argc)
120     { argc--; argv++; }
121
122   while (argc && last_argc != argc )
123     {
124       last_argc = argc;
125       if (!strcmp (*argv, "--"))
126         {
127           argc--; argv++;
128           break;
129         }
130       else if (!strcmp (*argv, "--help"))
131         show_usage (0);
132       else if (!strcmp (*argv, "--verbose"))
133         {
134           verbose = 1;
135           argc--; argv++;
136         }
137       else if (!strcmp (*argv, "--status"))
138         {
139           print_status = 1;
140           argc--; argv++;
141         }
142       else if (!strcmp (*argv, "--openpgp"))
143         {
144           protocol = GPGME_PROTOCOL_OpenPGP;
145           argc--; argv++;
146         }
147       else if (!strcmp (*argv, "--cms"))
148         {
149           protocol = GPGME_PROTOCOL_CMS;
150           argc--; argv++;
151         }
152       else if (!strcmp (*argv, "--export-session-key"))
153         {
154           export_session_key = 1;
155           argc--; argv++;
156         }
157       else if (!strcmp (*argv, "--override-session-key"))
158         {
159           argc--; argv++;
160           if (!argc)
161             show_usage (1);
162           override_session_key = *argv;
163           argc--; argv++;
164         }
165       else if (!strcmp (*argv, "--request-origin"))
166         {
167           argc--; argv++;
168           if (!argc)
169             show_usage (1);
170           request_origin = *argv;
171           argc--; argv++;
172         }
173       else if (!strcmp (*argv, "--no-symkey-cache"))
174         {
175           no_symkey_cache = 1;
176           argc--; argv++;
177         }
178       else if (!strcmp (*argv, "--ignore-mdc-error"))
179         {
180           ignore_mdc_error = 1;
181           argc--; argv++;
182         }
183       else if (!strcmp (*argv, "--diagnostics"))
184         {
185           diagnostics = 1;
186           argc--; argv++;
187         }
188       else if (!strcmp (*argv, "--unwrap"))
189         {
190           flags |= GPGME_DECRYPT_UNWRAP;
191           raw_output = 1;
192           argc--; argv++;
193         }
194       else if (!strncmp (*argv, "--", 2))
195         show_usage (1);
196
197     }
198
199   if (argc < 1 || argc > 2)
200     show_usage (1);
201
202   fp_in = fopen (argv[0], "rb");
203   if (!fp_in)
204     {
205       err = gpgme_error_from_syserror ();
206       fprintf (stderr, PGM ": can't open `%s': %s\n",
207                argv[0], gpgme_strerror (err));
208       exit (1);
209     }
210
211   init_gpgme (protocol);
212
213   err = gpgme_new (&ctx);
214   fail_if_err (err);
215   gpgme_set_protocol (ctx, protocol);
216   if (print_status)
217     {
218       gpgme_set_status_cb (ctx, status_cb, NULL);
219       gpgme_set_ctx_flag (ctx, "full-status", "1");
220     }
221   if (export_session_key)
222     {
223       err = gpgme_set_ctx_flag (ctx, "export-session-key", "1");
224       if (err)
225         {
226           fprintf (stderr, PGM ": error requesting exported session key: %s\n",
227                    gpgme_strerror (err));
228           exit (1);
229         }
230     }
231   if (override_session_key)
232     {
233       err = gpgme_set_ctx_flag (ctx, "override-session-key",
234                                 override_session_key);
235       if (err)
236         {
237           fprintf (stderr, PGM ": error setting overriding session key: %s\n",
238                    gpgme_strerror (err));
239           exit (1);
240         }
241     }
242
243   if (request_origin)
244     {
245       err = gpgme_set_ctx_flag (ctx, "request-origin", request_origin);
246       if (err)
247         {
248           fprintf (stderr, PGM ": error setting request_origin: %s\n",
249                    gpgme_strerror (err));
250           exit (1);
251         }
252     }
253
254   if (no_symkey_cache)
255     {
256       err = gpgme_set_ctx_flag (ctx, "no-symkey-cache", "1");
257       if (err)
258         {
259           fprintf (stderr, PGM ": error setting no-symkey-cache: %s\n",
260                    gpgme_strerror (err));
261           exit (1);
262         }
263     }
264
265   if (ignore_mdc_error)
266     {
267       err = gpgme_set_ctx_flag (ctx, "ignore-mdc-error", "1");
268       if (err)
269         {
270           fprintf (stderr, PGM ": error setting ignore-mdc-error: %s\n",
271                    gpgme_strerror (err));
272           exit (1);
273         }
274     }
275
276   err = gpgme_data_new_from_stream (&in, fp_in);
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_data_new (&out);
285   if (err)
286     {
287       fprintf (stderr, PGM ": error allocating data object: %s\n",
288                gpgme_strerror (err));
289       exit (1);
290     }
291
292   err = gpgme_op_decrypt_ext (ctx, flags, in, out);
293   result = gpgme_op_decrypt_result (ctx);
294
295   if (diagnostics)
296     {
297       gpgme_data_t diag;
298       gpgme_error_t diag_err;
299
300       gpgme_data_new (&diag);
301       diag_err = gpgme_op_getauditlog (ctx, diag, GPGME_AUDITLOG_DIAG);
302       if (diag_err)
303         {
304           fprintf (stderr, PGM ": getting diagnostics failed: %s\n",
305                    gpgme_strerror (diag_err));
306         }
307       else
308         {
309           fputs ("Begin Diagnostics:\n", stdout);
310           print_data (diag);
311           fputs ("End Diagnostics.\n", stdout);
312         }
313       gpgme_data_release (diag);
314     }
315
316   if (err)
317     {
318       fprintf (stderr, PGM ": decrypt failed: %s\n", gpgme_strerror (err));
319       if (result)
320         print_result (result);
321       exit (1);
322     }
323   if (result)
324     {
325       if (!raw_output)
326         print_result (result);
327       if (!raw_output)
328         fputs ("Begin Output:\n", stdout);
329       print_data (out);
330       if (!raw_output)
331         fputs ("End Output.\n", stdout);
332     }
333
334   gpgme_data_release (out);
335   gpgme_data_release (in);
336
337   gpgme_release (ctx);
338   return 0;
339 }