51e2d60f5bd24c92dcc8fdc4acd8dab356eb9581
[gpgme.git] / tests / run-encrypt.c
1 /* run-encrypt.c  - Helper to perform an encrypt operation
2  * Copyright (C) 2016 g10 Code GmbH
3  *
4  * This file is part of GPGME.
5  *
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.
10  *
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.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <https://www.gnu.org/licenses/>.
18  */
19
20 /* We need to include config.h so that we know whether we are building
21    with large file system (LFS) support. */
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <gpgme.h>
31
32 #define PGM "run-encrypt"
33
34 #include "run-support.h"
35
36
37 static int verbose;
38
39
40 static gpg_error_t
41 status_cb (void *opaque, const char *keyword, const char *value)
42 {
43   (void)opaque;
44   fprintf (stderr, "status_cb: %s %s\n", nonnull(keyword), nonnull(value));
45   return 0;
46 }
47
48
49 static void
50 progress_cb (void *opaque, const char *what, int type, int current, int total)
51 {
52   (void)opaque;
53   (void)type;
54
55   if (total)
56     fprintf (stderr, "progress for '%s' %u%% (%d of %d)\n",
57              nonnull (what),
58              (unsigned)(((double)current / total) * 100), current, total);
59   else
60     fprintf (stderr, "progress for '%s' %d\n", nonnull(what), current);
61   fflush (stderr);
62 }
63
64
65 static void
66 print_result (gpgme_encrypt_result_t result)
67 {
68   gpgme_invalid_key_t invkey;
69
70   for (invkey = result->invalid_recipients; invkey; invkey = invkey->next)
71     printf ("Encryption key `%s' not used: %s <%s>\n",
72             nonnull (invkey->fpr),
73             gpg_strerror (invkey->reason), gpg_strsource (invkey->reason));
74 }
75
76
77
78 static int
79 show_usage (int ex)
80 {
81   fputs ("usage: " PGM " [options] FILE\n\n"
82          "Options:\n"
83          "  --verbose          run in verbose mode\n"
84          "  --status           print status lines from the backend\n"
85          "  --progress         print progress info\n"
86          "  --openpgp          use the OpenPGP protocol (default)\n"
87          "  --cms              use the CMS protocol\n"
88          "  --uiserver         use the UI server\n"
89          "  --loopback         use a loopback pinentry\n"
90          "  --key NAME         encrypt to key NAME\n"
91          "  --throw-keyids     use this option\n"
92          "  --no-symkey-cache  disable the use of that cache\n"
93          "  --wrap             assume input is valid OpenPGP message\n"
94          "  --symmetric        encrypt symmetric (OpenPGP only)\n"
95          , stderr);
96   exit (ex);
97 }
98
99
100 int
101 main (int argc, char **argv)
102 {
103   int last_argc = -1;
104   gpgme_error_t err;
105   gpgme_ctx_t ctx;
106   const char *key_string = NULL;
107   gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
108   gpgme_data_t in, out;
109   gpgme_encrypt_result_t result;
110   int print_status = 0;
111   int print_progress = 0;
112   int use_loopback = 0;
113   char *keyargs[10];
114   gpgme_key_t keys[10+1];
115   int keycount = 0;
116   int i;
117   gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST;
118   gpgme_off_t offset;
119   int no_symkey_cache = 0;
120
121   if (argc)
122     { argc--; argv++; }
123
124   if (DIM(keys) != DIM(keyargs)+1)
125     abort ();
126
127   while (argc && last_argc != argc )
128     {
129       last_argc = argc;
130       if (!strcmp (*argv, "--"))
131         {
132           argc--; argv++;
133           break;
134         }
135       else if (!strcmp (*argv, "--help"))
136         show_usage (0);
137       else if (!strcmp (*argv, "--verbose"))
138         {
139           verbose = 1;
140           argc--; argv++;
141         }
142       else if (!strcmp (*argv, "--status"))
143         {
144           print_status = 1;
145           argc--; argv++;
146         }
147       else if (!strcmp (*argv, "--progress"))
148         {
149           print_progress = 1;
150           argc--; argv++;
151         }
152       else if (!strcmp (*argv, "--openpgp"))
153         {
154           protocol = GPGME_PROTOCOL_OpenPGP;
155           argc--; argv++;
156         }
157       else if (!strcmp (*argv, "--cms"))
158         {
159           protocol = GPGME_PROTOCOL_CMS;
160           argc--; argv++;
161         }
162       else if (!strcmp (*argv, "--uiserver"))
163         {
164           protocol = GPGME_PROTOCOL_UISERVER;
165           argc--; argv++;
166         }
167       else if (!strcmp (*argv, "--key"))
168         {
169           argc--; argv++;
170           if (!argc)
171             show_usage (1);
172           if (keycount == DIM (keyargs))
173             show_usage (1);
174           keyargs[keycount++] = *argv;
175           argc--; argv++;
176         }
177       else if (!strcmp (*argv, "--throw-keyids"))
178         {
179           flags |= GPGME_ENCRYPT_THROW_KEYIDS;
180           argc--; argv++;
181         }
182       else if (!strcmp (*argv, "--wrap"))
183         {
184           flags |= GPGME_ENCRYPT_WRAP;
185           argc--; argv++;
186         }
187       else if (!strcmp (*argv, "--loopback"))
188         {
189           use_loopback = 1;
190           argc--; argv++;
191         }
192       else if (!strcmp (*argv, "--symmetric"))
193         {
194           flags |= GPGME_ENCRYPT_SYMMETRIC;
195           argc--; argv++;
196         }
197       else if (!strcmp (*argv, "--no-symkey-cache"))
198         {
199           no_symkey_cache = 1;
200           argc--; argv++;
201         }
202       else if (!strncmp (*argv, "--", 2))
203         show_usage (1);
204
205     }
206
207   if (argc != 1)
208     show_usage (1);
209
210   if (key_string && protocol == GPGME_PROTOCOL_UISERVER)
211     {
212       fprintf (stderr, PGM ": ignoring --key in UI-server mode\n");
213       key_string = NULL;
214     }
215
216   if (!key_string)
217     key_string = "test";
218
219   init_gpgme (protocol);
220
221   err = gpgme_new (&ctx);
222   fail_if_err (err);
223   gpgme_set_protocol (ctx, protocol);
224   gpgme_set_armor (ctx, 1);
225   if (print_status)
226     {
227       gpgme_set_status_cb (ctx, status_cb, NULL);
228       gpgme_set_ctx_flag (ctx, "full-status", "1");
229     }
230   if (print_progress)
231     gpgme_set_progress_cb (ctx, progress_cb, NULL);
232   if (use_loopback)
233     {
234       gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
235       gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
236     }
237   if (no_symkey_cache)
238     {
239       err = gpgme_set_ctx_flag (ctx, "no-symkey-cache", "1");
240       if (err)
241         {
242           fprintf (stderr, PGM ": error setting no-symkey-cache:  %s\n",
243                    gpgme_strerror (err));
244           exit (1);
245         }
246     }
247
248   for (i=0; i < keycount; i++)
249     {
250       err = gpgme_get_key (ctx, keyargs[i], &keys[i], 0);
251       fail_if_err (err);
252     }
253   keys[i] = NULL;
254
255   err = gpgme_data_new_from_file (&in, *argv, 1);
256   if (err)
257     {
258       fprintf (stderr, PGM ": error reading `%s': %s\n",
259                *argv, gpg_strerror (err));
260       exit (1);
261     }
262   offset = gpgme_data_seek (in, 0, SEEK_END);
263   if (offset == (gpgme_off_t)(-1))
264     {
265       err = gpg_error_from_syserror ();
266       fprintf (stderr, PGM ": error seeking `%s': %s\n",
267                *argv, gpg_strerror (err));
268       exit (1);
269     }
270   if (gpgme_data_seek (in, 0, SEEK_SET) == (gpgme_off_t)(-1))
271     {
272       err = gpg_error_from_syserror ();
273       fprintf (stderr, PGM ": error seeking `%s': %s\n",
274                *argv, gpg_strerror (err));
275       exit (1);
276     }
277   {
278     char numbuf[50];
279     char *p;
280
281     p = numbuf + sizeof numbuf;
282     *--p = 0;
283     do
284       {
285         *--p = '0' + (offset % 10);
286         offset /= 10;
287       }
288     while (offset);
289     err = gpgme_data_set_flag (in, "size-hint", p);
290     if (err)
291       {
292         fprintf (stderr, PGM ": error setting size-hint for `%s': %s\n",
293                  *argv, gpg_strerror (err));
294         exit (1);
295       }
296   }
297
298   err = gpgme_data_new (&out);
299   fail_if_err (err);
300
301   err = gpgme_op_encrypt (ctx, keycount ? keys : NULL, flags, in, out);
302   result = gpgme_op_encrypt_result (ctx);
303   if (result)
304     print_result (result);
305   if (err)
306     {
307       fprintf (stderr, PGM ": encrypting failed: %s\n", gpg_strerror (err));
308       exit (1);
309     }
310
311   fputs ("Begin Output:\n", stdout);
312   print_data (out);
313   fputs ("End Output.\n", stdout);
314   gpgme_data_release (out);
315
316   gpgme_data_release (in);
317
318   for (i=0; i < keycount; i++)
319     gpgme_key_unref (keys[i]);
320   gpgme_release (ctx);
321   return 0;
322 }