Line data Source code
1 : /* run-keysign.c - Test tool to sign a key
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 : #include <assert.h>
30 :
31 : #include <gpgme.h>
32 :
33 : #define PGM "run-keysign"
34 :
35 : #include "run-support.h"
36 :
37 :
38 : static int verbose;
39 :
40 :
41 : static gpg_error_t
42 0 : status_cb (void *opaque, const char *keyword, const char *value)
43 : {
44 : (void)opaque;
45 0 : fprintf (stderr, "status_cb: %s %s\n", nonnull(keyword), nonnull(value));
46 0 : return 0;
47 : }
48 :
49 :
50 : static unsigned long
51 0 : parse_expire_string (const char *string)
52 : {
53 : unsigned long seconds;
54 :
55 0 : if (!string || !*string || !strcmp (string, "none")
56 0 : || !strcmp (string, "never") || !strcmp (string, "-"))
57 0 : seconds = 0;
58 0 : else if (strspn (string, "01234567890") == strlen (string))
59 0 : seconds = strtoul (string, NULL, 10);
60 : else
61 : {
62 0 : fprintf (stderr, PGM ": invalid value '%s'\n", string);
63 0 : exit (1);
64 : }
65 :
66 0 : return seconds;
67 : }
68 :
69 :
70 :
71 : static int
72 0 : show_usage (int ex)
73 : {
74 0 : fputs ("usage: " PGM " [options] FPR USERIDS\n\n"
75 : "Options:\n"
76 : " --verbose run in verbose mode\n"
77 : " --status print status lines from the backend\n"
78 : " --loopback use a loopback pinentry\n"
79 : " --signer NAME use key NAME for signing\n"
80 : " --local create a local signature\n"
81 : " --noexpire force no expiration\n"
82 : " --expire EPOCH expire the signature at EPOCH\n"
83 : , stderr);
84 0 : exit (ex);
85 : }
86 :
87 :
88 : int
89 0 : main (int argc, char **argv)
90 : {
91 0 : int last_argc = -1;
92 : gpgme_error_t err;
93 : gpgme_ctx_t ctx;
94 0 : gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
95 0 : const char *signer_string = NULL;
96 0 : int print_status = 0;
97 0 : int use_loopback = 0;
98 : const char *userid;
99 0 : unsigned int flags = 0;
100 0 : unsigned long expire = 0;
101 : gpgme_key_t thekey;
102 : int i;
103 : size_t n;
104 0 : char *userid_buffer = NULL;
105 :
106 0 : if (argc)
107 0 : { argc--; argv++; }
108 :
109 0 : while (argc && last_argc != argc )
110 : {
111 0 : last_argc = argc;
112 0 : if (!strcmp (*argv, "--"))
113 : {
114 0 : argc--; argv++;
115 0 : break;
116 : }
117 0 : else if (!strcmp (*argv, "--help"))
118 0 : show_usage (0);
119 0 : else if (!strcmp (*argv, "--verbose"))
120 : {
121 0 : verbose = 1;
122 0 : argc--; argv++;
123 : }
124 0 : else if (!strcmp (*argv, "--status"))
125 : {
126 0 : print_status = 1;
127 0 : argc--; argv++;
128 : }
129 0 : else if (!strcmp (*argv, "--signer"))
130 : {
131 0 : argc--; argv++;
132 0 : if (!argc)
133 0 : show_usage (1);
134 0 : signer_string = *argv;
135 0 : argc--; argv++;
136 : }
137 0 : else if (!strcmp (*argv, "--loopback"))
138 : {
139 0 : use_loopback = 1;
140 0 : argc--; argv++;
141 : }
142 0 : else if (!strcmp (*argv, "--local"))
143 : {
144 0 : flags |= GPGME_KEYSIGN_LOCAL;
145 0 : argc--; argv++;
146 : }
147 0 : else if (!strcmp (*argv, "--noexpire"))
148 : {
149 0 : flags |= GPGME_KEYSIGN_NOEXPIRE;
150 0 : argc--; argv++;
151 : }
152 0 : else if (!strcmp (*argv, "--expire"))
153 : {
154 0 : argc--; argv++;
155 0 : if (!argc)
156 0 : show_usage (1);
157 0 : expire = parse_expire_string (*argv);
158 0 : argc--; argv++;
159 : }
160 0 : else if (!strncmp (*argv, "--", 2))
161 0 : show_usage (1);
162 : }
163 :
164 0 : if (!argc)
165 0 : show_usage (1);
166 0 : userid = argv[0];
167 0 : argc--; argv++;
168 :
169 0 : init_gpgme (protocol);
170 :
171 0 : err = gpgme_new (&ctx);
172 0 : fail_if_err (err);
173 0 : gpgme_set_protocol (ctx, protocol);
174 0 : gpgme_set_armor (ctx, 1);
175 0 : if (print_status)
176 : {
177 0 : gpgme_set_status_cb (ctx, status_cb, NULL);
178 0 : gpgme_set_ctx_flag (ctx, "full-status", "1");
179 : }
180 0 : if (use_loopback)
181 : {
182 0 : gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
183 0 : gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
184 : }
185 :
186 0 : if (signer_string)
187 : {
188 : gpgme_key_t akey;
189 :
190 0 : err = gpgme_get_key (ctx, signer_string, &akey, 1);
191 0 : if (err)
192 : {
193 0 : fprintf (stderr, PGM ": error getting signer key '%s': %s\n",
194 : signer_string, gpg_strerror (err));
195 0 : exit (1);
196 : }
197 0 : err = gpgme_signers_add (ctx, akey);
198 0 : if (err)
199 : {
200 0 : fprintf (stderr, PGM ": error adding signer key: %s\n",
201 : gpg_strerror (err));
202 0 : exit (1);
203 : }
204 0 : gpgme_key_unref (akey);
205 : }
206 :
207 :
208 0 : err = gpgme_get_key (ctx, userid, &thekey, 0);
209 0 : if (err)
210 : {
211 0 : fprintf (stderr, PGM ": error getting key for '%s': %s\n",
212 : userid, gpg_strerror (err));
213 0 : exit (1);
214 : }
215 :
216 0 : if (argc > 1)
217 : {
218 : /* Several user ids given */
219 0 : for (i=0, n = 0; i < argc; i++)
220 0 : n += strlen (argv[1]) + 1;
221 0 : n++;
222 0 : userid_buffer = malloc (n);
223 0 : if (!userid_buffer)
224 : {
225 0 : fprintf (stderr, PGM ": malloc failed: %s\n",
226 : gpg_strerror (gpg_error_from_syserror ()));
227 0 : exit (1);
228 : }
229 0 : *userid_buffer = 0;
230 0 : for (i=0; i < argc; i++)
231 : {
232 0 : strcat (userid_buffer, argv[i]);
233 0 : strcat (userid_buffer, "\n");
234 : }
235 0 : userid = userid_buffer;
236 0 : flags |= GPGME_KEYSIGN_LFSEP;
237 : }
238 0 : else if (argc)
239 : {
240 : /* One user id given */
241 0 : userid = *argv;
242 : }
243 : else
244 : {
245 : /* No user id given. */
246 0 : userid = NULL;
247 : }
248 :
249 0 : err = gpgme_op_keysign (ctx, thekey, userid, expire, flags);
250 0 : if (err)
251 : {
252 0 : fprintf (stderr, PGM ": gpgme_op_adduid failed: %s\n",
253 : gpg_strerror (err));
254 0 : exit (1);
255 : }
256 :
257 0 : free (userid_buffer);
258 0 : gpgme_key_unref (thekey);
259 0 : gpgme_release (ctx);
260 0 : return 0;
261 : }
|