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 gpg_error_t
41 0 : status_cb (void *opaque, const char *keyword, const char *value)
42 : {
43 : (void)opaque;
44 0 : fprintf (stderr, "status_cb: %s %s\n", nonnull(keyword), nonnull(value));
45 0 : return 0;
46 : }
47 :
48 :
49 : static void
50 0 : progress_cb (void *opaque, const char *what, int type, int current, int total)
51 : {
52 : (void)opaque;
53 : (void)type;
54 :
55 0 : if (total)
56 0 : fprintf (stderr, "progress for '%s' %u%% (%d of %d)\n",
57 : nonnull (what),
58 0 : (unsigned)(((double)current / total) * 100), current, total);
59 : else
60 0 : fprintf (stderr, "progress for '%s' %d\n", nonnull(what), current);
61 0 : fflush (stderr);
62 0 : }
63 :
64 :
65 : static void
66 0 : print_result (gpgme_encrypt_result_t result)
67 : {
68 : gpgme_invalid_key_t invkey;
69 :
70 0 : for (invkey = result->invalid_recipients; invkey; invkey = invkey->next)
71 0 : printf ("Encryption key `%s' not used: %s <%s>\n",
72 0 : nonnull (invkey->fpr),
73 : gpg_strerror (invkey->reason), gpg_strsource (invkey->reason));
74 0 : }
75 :
76 :
77 :
78 : static int
79 0 : show_usage (int ex)
80 : {
81 0 : 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 : " --symmetric encrypt symmetric (OpenPGP only)\n"
92 : , stderr);
93 0 : exit (ex);
94 : }
95 :
96 :
97 : int
98 0 : main (int argc, char **argv)
99 : {
100 0 : int last_argc = -1;
101 : gpgme_error_t err;
102 : gpgme_ctx_t ctx;
103 0 : const char *key_string = NULL;
104 0 : gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
105 : gpgme_data_t in, out;
106 : gpgme_encrypt_result_t result;
107 0 : int print_status = 0;
108 0 : int print_progress = 0;
109 0 : int use_loopback = 0;
110 : char *keyargs[10];
111 : gpgme_key_t keys[10+1];
112 0 : int keycount = 0;
113 : int i;
114 0 : gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST;
115 : gpgme_off_t offset;
116 :
117 0 : if (argc)
118 0 : { argc--; argv++; }
119 :
120 : if (DIM(keys) != DIM(keyargs)+1)
121 : abort ();
122 :
123 0 : while (argc && last_argc != argc )
124 : {
125 0 : last_argc = argc;
126 0 : if (!strcmp (*argv, "--"))
127 : {
128 0 : argc--; argv++;
129 0 : break;
130 : }
131 0 : else if (!strcmp (*argv, "--help"))
132 0 : show_usage (0);
133 0 : else if (!strcmp (*argv, "--verbose"))
134 : {
135 0 : verbose = 1;
136 0 : argc--; argv++;
137 : }
138 0 : else if (!strcmp (*argv, "--status"))
139 : {
140 0 : print_status = 1;
141 0 : argc--; argv++;
142 : }
143 0 : else if (!strcmp (*argv, "--progress"))
144 : {
145 0 : print_progress = 1;
146 0 : argc--; argv++;
147 : }
148 0 : else if (!strcmp (*argv, "--openpgp"))
149 : {
150 0 : protocol = GPGME_PROTOCOL_OpenPGP;
151 0 : argc--; argv++;
152 : }
153 0 : else if (!strcmp (*argv, "--cms"))
154 : {
155 0 : protocol = GPGME_PROTOCOL_CMS;
156 0 : argc--; argv++;
157 : }
158 0 : else if (!strcmp (*argv, "--uiserver"))
159 : {
160 0 : protocol = GPGME_PROTOCOL_UISERVER;
161 0 : argc--; argv++;
162 : }
163 0 : else if (!strcmp (*argv, "--key"))
164 : {
165 0 : argc--; argv++;
166 0 : if (!argc)
167 0 : show_usage (1);
168 0 : if (keycount == DIM (keyargs))
169 0 : show_usage (1);
170 0 : keyargs[keycount++] = *argv;
171 0 : argc--; argv++;
172 : }
173 0 : else if (!strcmp (*argv, "--loopback"))
174 : {
175 0 : use_loopback = 1;
176 0 : argc--; argv++;
177 : }
178 0 : else if (!strcmp (*argv, "--symmetric"))
179 : {
180 0 : flags |= GPGME_ENCRYPT_SYMMETRIC;
181 0 : argc--; argv++;
182 : }
183 0 : else if (!strncmp (*argv, "--", 2))
184 0 : show_usage (1);
185 :
186 : }
187 :
188 0 : if (argc != 1)
189 0 : show_usage (1);
190 :
191 0 : if (key_string && protocol == GPGME_PROTOCOL_UISERVER)
192 : {
193 0 : fprintf (stderr, PGM ": ignoring --key in UI-server mode\n");
194 0 : key_string = NULL;
195 : }
196 :
197 0 : if (!key_string)
198 0 : key_string = "test";
199 :
200 0 : init_gpgme (protocol);
201 :
202 0 : err = gpgme_new (&ctx);
203 0 : fail_if_err (err);
204 0 : gpgme_set_protocol (ctx, protocol);
205 0 : gpgme_set_armor (ctx, 1);
206 0 : if (print_status)
207 : {
208 0 : gpgme_set_status_cb (ctx, status_cb, NULL);
209 0 : gpgme_set_ctx_flag (ctx, "full-status", "1");
210 : }
211 0 : if (print_progress)
212 0 : gpgme_set_progress_cb (ctx, progress_cb, NULL);
213 0 : if (use_loopback)
214 : {
215 0 : gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
216 0 : gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
217 : }
218 :
219 0 : for (i=0; i < keycount; i++)
220 : {
221 0 : err = gpgme_get_key (ctx, keyargs[i], &keys[i], 0);
222 0 : fail_if_err (err);
223 : }
224 0 : keys[i] = NULL;
225 :
226 0 : err = gpgme_data_new_from_file (&in, *argv, 1);
227 0 : if (err)
228 : {
229 0 : fprintf (stderr, PGM ": error reading `%s': %s\n",
230 : *argv, gpg_strerror (err));
231 0 : exit (1);
232 : }
233 0 : offset = gpgme_data_seek (in, 0, SEEK_END);
234 0 : if (offset == (gpgme_off_t)(-1))
235 : {
236 0 : err = gpg_error_from_syserror ();
237 0 : fprintf (stderr, PGM ": error seeking `%s': %s\n",
238 : *argv, gpg_strerror (err));
239 0 : exit (1);
240 : }
241 0 : if (gpgme_data_seek (in, 0, SEEK_SET) == (gpgme_off_t)(-1))
242 : {
243 0 : err = gpg_error_from_syserror ();
244 0 : fprintf (stderr, PGM ": error seeking `%s': %s\n",
245 : *argv, gpg_strerror (err));
246 0 : exit (1);
247 : }
248 : {
249 : char numbuf[50];
250 : char *p;
251 :
252 0 : p = numbuf + sizeof numbuf;
253 0 : *--p = 0;
254 : do
255 : {
256 0 : *--p = '0' + (offset % 10);
257 0 : offset /= 10;
258 : }
259 0 : while (offset);
260 0 : err = gpgme_data_set_flag (in, "size-hint", p);
261 0 : if (err)
262 : {
263 0 : fprintf (stderr, PGM ": error setting size-hint for `%s': %s\n",
264 : *argv, gpg_strerror (err));
265 0 : exit (1);
266 : }
267 : }
268 :
269 0 : err = gpgme_data_new (&out);
270 0 : fail_if_err (err);
271 :
272 0 : err = gpgme_op_encrypt (ctx, keycount ? keys : NULL, flags, in, out);
273 0 : result = gpgme_op_encrypt_result (ctx);
274 0 : if (result)
275 0 : print_result (result);
276 0 : if (err)
277 : {
278 0 : fprintf (stderr, PGM ": encrypting failed: %s\n", gpg_strerror (err));
279 0 : exit (1);
280 : }
281 :
282 0 : fputs ("Begin Output:\n", stdout);
283 0 : print_data (out);
284 0 : fputs ("End Output.\n", stdout);
285 0 : gpgme_data_release (out);
286 :
287 0 : gpgme_data_release (in);
288 :
289 0 : for (i=0; i < keycount; i++)
290 0 : gpgme_key_unref (keys[i]);
291 0 : gpgme_release (ctx);
292 0 : return 0;
293 : }
|