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