Line data Source code
1 : /* run-keylist.c - Helper to show a key listing.
2 : Copyright (C) 2008, 2009 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 <time.h>
30 :
31 : #include <gpgme.h>
32 :
33 : #define PGM "run-keylist"
34 :
35 : #include "run-support.h"
36 :
37 :
38 : static int verbose;
39 :
40 :
41 : static int
42 0 : show_usage (int ex)
43 : {
44 0 : fputs ("usage: " PGM " [options] [USERID_or_FILE]\n\n"
45 : "Options:\n"
46 : " --verbose run in verbose mode\n"
47 : " --openpgp use the OpenPGP protocol (default)\n"
48 : " --cms use the CMS protocol\n"
49 : " --secret list only secret keys\n"
50 : " --with-secret list pubkeys with secret info filled\n"
51 : " --local use GPGME_KEYLIST_MODE_LOCAL\n"
52 : " --extern use GPGME_KEYLIST_MODE_EXTERN\n"
53 : " --sigs use GPGME_KEYLIST_MODE_SIGS\n"
54 : " --tofu use GPGME_KEYLIST_MODE_TOFU\n"
55 : " --sig-notations use GPGME_KEYLIST_MODE_SIG_NOTATIONS\n"
56 : " --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n"
57 : " --validate use GPGME_KEYLIST_MODE_VALIDATE\n"
58 : " --import import all keys\n"
59 : " --offline use offline mode\n"
60 : " --from-file list all keys in the given file\n"
61 : " --from-wkd list key from a web key directory\n"
62 : " --require-gnupg required at least the given GnuPG version\n"
63 : " --trust-model use the specified trust-model\n"
64 : , stderr);
65 0 : exit (ex);
66 : }
67 :
68 :
69 : static const char *
70 0 : isotimestr (unsigned long value)
71 : {
72 : time_t t;
73 : static char buffer[25+5];
74 : struct tm *tp;
75 :
76 0 : if (!value)
77 0 : return "none";
78 0 : t = value;
79 :
80 0 : tp = gmtime (&t);
81 0 : snprintf (buffer, sizeof buffer, "%04d-%02d-%02d %02d:%02d:%02d",
82 0 : 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
83 : tp->tm_hour, tp->tm_min, tp->tm_sec);
84 0 : return buffer;
85 : }
86 :
87 :
88 :
89 : int
90 0 : main (int argc, char **argv)
91 : {
92 0 : int last_argc = -1;
93 : gpgme_error_t err;
94 : gpgme_ctx_t ctx;
95 0 : gpgme_keylist_mode_t mode = 0;
96 : gpgme_key_t key;
97 : gpgme_subkey_t subkey;
98 : gpgme_keylist_result_t result;
99 0 : int import = 0;
100 : gpgme_key_t keyarray[100];
101 0 : int keyidx = 0;
102 0 : gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
103 0 : int only_secret = 0;
104 0 : int offline = 0;
105 0 : int from_file = 0;
106 0 : int from_wkd = 0;
107 0 : gpgme_data_t data = NULL;
108 0 : char *trust_model = NULL;
109 :
110 :
111 0 : if (argc)
112 0 : { argc--; argv++; }
113 :
114 0 : while (argc && last_argc != argc )
115 : {
116 0 : last_argc = argc;
117 0 : if (!strcmp (*argv, "--"))
118 : {
119 0 : argc--; argv++;
120 0 : break;
121 : }
122 0 : else if (!strcmp (*argv, "--help"))
123 0 : show_usage (0);
124 0 : else if (!strcmp (*argv, "--verbose"))
125 : {
126 0 : verbose = 1;
127 0 : argc--; argv++;
128 : }
129 0 : else if (!strcmp (*argv, "--openpgp"))
130 : {
131 0 : protocol = GPGME_PROTOCOL_OpenPGP;
132 0 : argc--; argv++;
133 : }
134 0 : else if (!strcmp (*argv, "--cms"))
135 : {
136 0 : protocol = GPGME_PROTOCOL_CMS;
137 0 : argc--; argv++;
138 : }
139 0 : else if (!strcmp (*argv, "--secret"))
140 : {
141 0 : only_secret = 1;
142 0 : argc--; argv++;
143 : }
144 0 : else if (!strcmp (*argv, "--local"))
145 : {
146 0 : mode |= GPGME_KEYLIST_MODE_LOCAL;
147 0 : argc--; argv++;
148 : }
149 0 : else if (!strcmp (*argv, "--extern"))
150 : {
151 0 : mode |= GPGME_KEYLIST_MODE_EXTERN;
152 0 : argc--; argv++;
153 : }
154 0 : else if (!strcmp (*argv, "--tofu"))
155 : {
156 0 : mode |= GPGME_KEYLIST_MODE_WITH_TOFU;
157 0 : argc--; argv++;
158 : }
159 0 : else if (!strcmp (*argv, "--sigs"))
160 : {
161 0 : mode |= GPGME_KEYLIST_MODE_SIGS;
162 0 : argc--; argv++;
163 : }
164 0 : else if (!strcmp (*argv, "--sig-notations"))
165 : {
166 0 : mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
167 0 : argc--; argv++;
168 : }
169 0 : else if (!strcmp (*argv, "--ephemeral"))
170 : {
171 0 : mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
172 0 : argc--; argv++;
173 : }
174 0 : else if (!strcmp (*argv, "--validate"))
175 : {
176 0 : mode |= GPGME_KEYLIST_MODE_VALIDATE;
177 0 : argc--; argv++;
178 : }
179 0 : else if (!strcmp (*argv, "--with-secret"))
180 : {
181 0 : mode |= GPGME_KEYLIST_MODE_WITH_SECRET;
182 0 : argc--; argv++;
183 : }
184 0 : else if (!strcmp (*argv, "--import"))
185 : {
186 0 : import = 1;
187 0 : argc--; argv++;
188 : }
189 0 : else if (!strcmp (*argv, "--offline"))
190 : {
191 0 : offline = 1;
192 0 : argc--; argv++;
193 : }
194 0 : else if (!strcmp (*argv, "--from-file"))
195 : {
196 0 : from_file = 1;
197 0 : argc--; argv++;
198 : }
199 0 : else if (!strcmp (*argv, "--require-gnupg"))
200 : {
201 0 : argc--; argv++;
202 0 : if (!argc)
203 0 : show_usage (1);
204 0 : gpgme_set_global_flag ("require-gnupg", *argv);
205 0 : argc--; argv++;
206 : }
207 0 : else if (!strcmp (*argv, "--from-wkd"))
208 : {
209 0 : argc--; argv++;
210 0 : mode |= GPGME_KEYLIST_MODE_LOCATE;
211 0 : from_wkd = 1;
212 : }
213 0 : else if (!strcmp (*argv, "--trust-model"))
214 : {
215 0 : argc--; argv++;
216 0 : if (!argc)
217 0 : show_usage (1);
218 0 : trust_model = strdup (*argv);
219 0 : argc--; argv++;
220 : }
221 0 : else if (!strncmp (*argv, "--", 2))
222 0 : show_usage (1);
223 : }
224 :
225 0 : if (argc > 1)
226 0 : show_usage (1);
227 0 : else if (from_file && !argc)
228 0 : show_usage (1);
229 :
230 0 : init_gpgme (protocol);
231 :
232 0 : err = gpgme_new (&ctx);
233 0 : fail_if_err (err);
234 0 : gpgme_set_protocol (ctx, protocol);
235 :
236 0 : gpgme_set_keylist_mode (ctx, mode);
237 :
238 0 : gpgme_set_offline (ctx, offline);
239 :
240 0 : if (trust_model)
241 : {
242 0 : err = gpgme_set_ctx_flag (ctx, "trust-model", trust_model);
243 0 : fail_if_err (err);
244 : }
245 :
246 0 : if (from_wkd)
247 : {
248 0 : err = gpgme_set_ctx_flag (ctx, "auto-key-locate",
249 : "clear,nodefault,wkd");
250 0 : fail_if_err (err);
251 : }
252 :
253 0 : if (from_file)
254 : {
255 0 : err = gpgme_data_new_from_file (&data, *argv, 1);
256 0 : fail_if_err (err);
257 :
258 0 : err = gpgme_op_keylist_from_data_start (ctx, data, 0);
259 : }
260 : else
261 0 : err = gpgme_op_keylist_start (ctx, argc? argv[0]:NULL, only_secret);
262 0 : fail_if_err (err);
263 :
264 0 : while (!(err = gpgme_op_keylist_next (ctx, &key)))
265 : {
266 : gpgme_user_id_t uid;
267 : gpgme_tofu_info_t ti;
268 : gpgme_key_sig_t ks;
269 : int nuids;
270 : int nsub;
271 : int nsigs;
272 :
273 0 : printf ("keyid : %s\n", key->subkeys?nonnull (key->subkeys->keyid):"?");
274 0 : printf ("fpr : %s\n", key->subkeys?nonnull (key->subkeys->fpr):"?");
275 0 : if (key->subkeys && key->subkeys->keygrip)
276 0 : printf ("grip : %s\n", key->subkeys->keygrip);
277 0 : if (key->subkeys && key->subkeys->curve)
278 0 : printf ("curve : %s\n", key->subkeys->curve);
279 0 : printf ("caps : %s%s%s%s\n",
280 0 : key->can_encrypt? "e":"",
281 0 : key->can_sign? "s":"",
282 0 : key->can_certify? "c":"",
283 0 : key->can_authenticate? "a":"");
284 0 : printf ("flags :%s%s%s%s%s%s%s%s\n",
285 0 : key->secret? " secret":"",
286 0 : key->revoked? " revoked":"",
287 0 : key->expired? " expired":"",
288 0 : key->disabled? " disabled":"",
289 0 : key->invalid? " invalid":"",
290 0 : key->is_qualified? " qualified":"",
291 0 : key->subkeys && key->subkeys->is_de_vs? " de-vs":"",
292 0 : key->subkeys && key->subkeys->is_cardkey? " cardkey":"");
293 0 : printf ("upd : %lu (%u)\n", key->last_update, key->origin);
294 :
295 0 : subkey = key->subkeys;
296 0 : if (subkey)
297 0 : subkey = subkey->next;
298 0 : for (nsub=1; subkey; subkey = subkey->next, nsub++)
299 : {
300 0 : printf ("fpr %2d: %s\n", nsub, nonnull (subkey->fpr));
301 0 : if (subkey->keygrip)
302 0 : printf ("grip %2d: %s\n", nsub, subkey->keygrip);
303 0 : if (subkey->curve)
304 0 : printf ("curve %2d: %s\n", nsub, subkey->curve);
305 0 : printf ("caps %2d: %s%s%s%s\n",
306 : nsub,
307 0 : subkey->can_encrypt? "e":"",
308 0 : subkey->can_sign? "s":"",
309 0 : subkey->can_certify? "c":"",
310 0 : subkey->can_authenticate? "a":"");
311 0 : printf ("flags %2d:%s%s%s%s%s%s%s%s\n",
312 : nsub,
313 0 : subkey->secret? " secret":"",
314 0 : subkey->revoked? " revoked":"",
315 0 : subkey->expired? " expired":"",
316 0 : subkey->disabled? " disabled":"",
317 0 : subkey->invalid? " invalid":"",
318 0 : subkey->is_qualified? " qualified":"",
319 0 : subkey->is_de_vs? " de-vs":"",
320 0 : subkey->is_cardkey? " cardkey":"");
321 : }
322 0 : for (nuids=0, uid=key->uids; uid; uid = uid->next, nuids++)
323 : {
324 0 : printf ("userid %d: %s\n", nuids, nonnull(uid->uid));
325 0 : printf (" mbox: %s\n", nonnull(uid->address));
326 0 : if (uid->email && uid->email != uid->address)
327 0 : printf (" email: %s\n", uid->email);
328 0 : if (uid->name)
329 0 : printf (" name: %s\n", uid->name);
330 0 : if (uid->comment)
331 0 : printf (" cmmnt: %s\n", uid->comment);
332 0 : printf (" upd: %lu (%u)\n", uid->last_update, uid->origin);
333 0 : printf (" valid: %s\n",
334 0 : uid->validity == GPGME_VALIDITY_UNKNOWN? "unknown":
335 0 : uid->validity == GPGME_VALIDITY_UNDEFINED? "undefined":
336 0 : uid->validity == GPGME_VALIDITY_NEVER? "never":
337 0 : uid->validity == GPGME_VALIDITY_MARGINAL? "marginal":
338 0 : uid->validity == GPGME_VALIDITY_FULL? "full":
339 0 : uid->validity == GPGME_VALIDITY_ULTIMATE? "ultimate": "[?]");
340 0 : if ((ti = uid->tofu))
341 : {
342 0 : printf (" tofu: %u (%s)\n", ti->validity,
343 0 : ti->validity == 0? "conflict" :
344 0 : ti->validity == 1? "no history" :
345 0 : ti->validity == 2? "little history" :
346 0 : ti->validity == 3? "enough history" :
347 0 : ti->validity == 4? "lot of history" : "?");
348 0 : printf (" policy: %u (%s)\n", ti->policy,
349 0 : ti->policy == GPGME_TOFU_POLICY_NONE? "none" :
350 0 : ti->policy == GPGME_TOFU_POLICY_AUTO? "auto" :
351 0 : ti->policy == GPGME_TOFU_POLICY_GOOD? "good" :
352 0 : ti->policy == GPGME_TOFU_POLICY_UNKNOWN? "unknown" :
353 0 : ti->policy == GPGME_TOFU_POLICY_BAD? "bad" :
354 0 : ti->policy == GPGME_TOFU_POLICY_ASK? "ask" : "?");
355 0 : printf (" nsigs: %hu\n", ti->signcount);
356 0 : printf (" first: %s\n", isotimestr (ti->signfirst));
357 0 : printf (" last: %s\n", isotimestr (ti->signlast));
358 0 : printf (" nencr: %hu\n", ti->encrcount);
359 0 : printf (" first: %s\n", isotimestr (ti->encrfirst));
360 0 : printf (" last: %s\n", isotimestr (ti->encrlast));
361 : }
362 0 : for (nsigs=0, ks=uid->signatures; ks; ks = ks->next, nsigs++)
363 : {
364 0 : printf ("signature %d: %s\n", nsigs, nonnull (ks->uid));
365 0 : printf (" keyid: %s\n", nonnull (ks->keyid));
366 0 : printf (" created: %s\n", isotimestr(ks->timestamp));
367 0 : printf (" expires: %s\n", isotimestr(ks->expires));
368 0 : printf (" class: %x\n", ks->sig_class);
369 : }
370 : }
371 :
372 0 : putchar ('\n');
373 :
374 0 : if (import)
375 : {
376 0 : if (keyidx < DIM (keyarray)-1)
377 0 : keyarray[keyidx++] = key;
378 : else
379 : {
380 0 : fprintf (stderr, PGM": too many keys in import mode"
381 : "- skipping this key\n");
382 0 : gpgme_key_unref (key);
383 : }
384 : }
385 : else
386 0 : gpgme_key_unref (key);
387 : }
388 0 : if (gpgme_err_code (err) != GPG_ERR_EOF)
389 0 : fail_if_err (err);
390 0 : err = gpgme_op_keylist_end (ctx);
391 0 : fail_if_err (err);
392 0 : keyarray[keyidx] = NULL;
393 0 : gpgme_data_release (data);
394 :
395 0 : result = gpgme_op_keylist_result (ctx);
396 0 : if (result->truncated)
397 : {
398 0 : fprintf (stderr, PGM ": key listing unexpectedly truncated\n");
399 0 : exit (1);
400 : }
401 :
402 0 : if (import)
403 : {
404 : gpgme_import_result_t impres;
405 :
406 0 : err = gpgme_op_import_keys (ctx, keyarray);
407 0 : fail_if_err (err);
408 0 : impres = gpgme_op_import_result (ctx);
409 0 : if (!impres)
410 : {
411 0 : fprintf (stderr, PGM ": no import result returned\n");
412 0 : exit (1);
413 : }
414 0 : print_import_result (impres);
415 : }
416 :
417 0 : for (keyidx=0; keyarray[keyidx]; keyidx++)
418 0 : gpgme_key_unref (keyarray[keyidx]);
419 :
420 0 : free (trust_model);
421 :
422 0 : gpgme_release (ctx);
423 0 : return 0;
424 : }
|