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]\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 : " --local use GPGME_KEYLIST_MODE_LOCAL\n"
51 : " --extern use GPGME_KEYLIST_MODE_EXTERN\n"
52 : " --sigs use GPGME_KEYLIST_MODE_SIGS\n"
53 : " --tofu use GPGME_KEYLIST_MODE_TOFU\n"
54 : " --sig-notations use GPGME_KEYLIST_MODE_SIG_NOTATIONS\n"
55 : " --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n"
56 : " --validate use GPGME_KEYLIST_MODE_VALIDATE\n"
57 : " --import import all keys\n"
58 : " --offline use offline mode\n"
59 : " --require-gnupg required at least the given GnuPG version\n"
60 : , stderr);
61 0 : exit (ex);
62 : }
63 :
64 :
65 : static const char *
66 0 : isotimestr (unsigned long value)
67 : {
68 : time_t t;
69 : static char buffer[25+5];
70 : struct tm *tp;
71 :
72 0 : if (!value)
73 0 : return "none";
74 0 : t = value;
75 :
76 0 : tp = gmtime (&t);
77 0 : snprintf (buffer, sizeof buffer, "%04d-%02d-%02d %02d:%02d:%02d",
78 0 : 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
79 : tp->tm_hour, tp->tm_min, tp->tm_sec);
80 0 : return buffer;
81 : }
82 :
83 :
84 :
85 : int
86 0 : main (int argc, char **argv)
87 : {
88 0 : int last_argc = -1;
89 : gpgme_error_t err;
90 : gpgme_ctx_t ctx;
91 0 : gpgme_keylist_mode_t mode = 0;
92 : gpgme_key_t key;
93 : gpgme_subkey_t subkey;
94 : gpgme_keylist_result_t result;
95 0 : int import = 0;
96 : gpgme_key_t keyarray[100];
97 0 : int keyidx = 0;
98 0 : gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
99 0 : int only_secret = 0;
100 0 : int offline = 0;
101 :
102 0 : if (argc)
103 0 : { argc--; argv++; }
104 :
105 0 : while (argc && last_argc != argc )
106 : {
107 0 : last_argc = argc;
108 0 : if (!strcmp (*argv, "--"))
109 : {
110 0 : argc--; argv++;
111 0 : break;
112 : }
113 0 : else if (!strcmp (*argv, "--help"))
114 0 : show_usage (0);
115 0 : else if (!strcmp (*argv, "--verbose"))
116 : {
117 0 : verbose = 1;
118 0 : argc--; argv++;
119 : }
120 0 : else if (!strcmp (*argv, "--openpgp"))
121 : {
122 0 : protocol = GPGME_PROTOCOL_OpenPGP;
123 0 : argc--; argv++;
124 : }
125 0 : else if (!strcmp (*argv, "--cms"))
126 : {
127 0 : protocol = GPGME_PROTOCOL_CMS;
128 0 : argc--; argv++;
129 : }
130 0 : else if (!strcmp (*argv, "--secret"))
131 : {
132 0 : only_secret = 1;
133 0 : argc--; argv++;
134 : }
135 0 : else if (!strcmp (*argv, "--local"))
136 : {
137 0 : mode |= GPGME_KEYLIST_MODE_LOCAL;
138 0 : argc--; argv++;
139 : }
140 0 : else if (!strcmp (*argv, "--extern"))
141 : {
142 0 : mode |= GPGME_KEYLIST_MODE_EXTERN;
143 0 : argc--; argv++;
144 : }
145 0 : else if (!strcmp (*argv, "--tofu"))
146 : {
147 0 : mode |= GPGME_KEYLIST_MODE_WITH_TOFU;
148 0 : argc--; argv++;
149 : }
150 0 : else if (!strcmp (*argv, "--sigs"))
151 : {
152 0 : mode |= GPGME_KEYLIST_MODE_SIGS;
153 0 : argc--; argv++;
154 : }
155 0 : else if (!strcmp (*argv, "--sig-notations"))
156 : {
157 0 : mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
158 0 : argc--; argv++;
159 : }
160 0 : else if (!strcmp (*argv, "--ephemeral"))
161 : {
162 0 : mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
163 0 : argc--; argv++;
164 : }
165 0 : else if (!strcmp (*argv, "--validate"))
166 : {
167 0 : mode |= GPGME_KEYLIST_MODE_VALIDATE;
168 0 : argc--; argv++;
169 : }
170 0 : else if (!strcmp (*argv, "--import"))
171 : {
172 0 : import = 1;
173 0 : argc--; argv++;
174 : }
175 0 : else if (!strcmp (*argv, "--offline"))
176 : {
177 0 : offline = 1;
178 0 : argc--; argv++;
179 : }
180 0 : else if (!strcmp (*argv, "--require-gnupg"))
181 : {
182 0 : argc--; argv++;
183 0 : if (!argc)
184 0 : show_usage (1);
185 0 : gpgme_set_global_flag ("require-gnupg", *argv);
186 0 : argc--; argv++;
187 : }
188 0 : else if (!strncmp (*argv, "--", 2))
189 0 : show_usage (1);
190 : }
191 :
192 0 : if (argc > 1)
193 0 : show_usage (1);
194 :
195 0 : init_gpgme (protocol);
196 :
197 0 : err = gpgme_new (&ctx);
198 0 : fail_if_err (err);
199 0 : gpgme_set_protocol (ctx, protocol);
200 :
201 0 : gpgme_set_keylist_mode (ctx, mode);
202 :
203 0 : gpgme_set_offline (ctx, offline);
204 :
205 0 : err = gpgme_op_keylist_start (ctx, argc? argv[0]:NULL, only_secret);
206 0 : fail_if_err (err);
207 :
208 0 : while (!(err = gpgme_op_keylist_next (ctx, &key)))
209 : {
210 : gpgme_user_id_t uid;
211 : gpgme_tofu_info_t ti;
212 : int nuids;
213 : int nsub;
214 :
215 0 : printf ("keyid : %s\n", key->subkeys?nonnull (key->subkeys->keyid):"?");
216 0 : printf ("fpr : %s\n", key->subkeys?nonnull (key->subkeys->fpr):"?");
217 0 : if (key->subkeys && key->subkeys->keygrip)
218 0 : printf ("grip : %s\n", key->subkeys->keygrip);
219 0 : if (key->subkeys && key->subkeys->curve)
220 0 : printf ("curve : %s\n", key->subkeys->curve);
221 0 : printf ("caps : %s%s%s%s\n",
222 0 : key->can_encrypt? "e":"",
223 0 : key->can_sign? "s":"",
224 0 : key->can_certify? "c":"",
225 0 : key->can_authenticate? "a":"");
226 0 : printf ("flags :%s%s%s%s%s%s%s\n",
227 0 : key->secret? " secret":"",
228 0 : key->revoked? " revoked":"",
229 0 : key->expired? " expired":"",
230 0 : key->disabled? " disabled":"",
231 0 : key->invalid? " invalid":"",
232 0 : key->is_qualified? " qualifid":"",
233 0 : key->subkeys && key->subkeys->is_cardkey? " cardkey":"");
234 :
235 0 : subkey = key->subkeys;
236 0 : if (subkey)
237 0 : subkey = subkey->next;
238 0 : for (nsub=1; subkey; subkey = subkey->next, nsub++)
239 : {
240 0 : printf ("fpr %2d: %s\n", nsub, nonnull (subkey->fpr));
241 0 : if (subkey->keygrip)
242 0 : printf ("grip %2d: %s\n", nsub, subkey->keygrip);
243 0 : if (subkey->curve)
244 0 : printf ("curve %2d: %s\n", nsub, subkey->curve);
245 0 : printf ("caps %2d: %s%s%s%s\n",
246 : nsub,
247 0 : subkey->can_encrypt? "e":"",
248 0 : subkey->can_sign? "s":"",
249 0 : subkey->can_certify? "c":"",
250 0 : subkey->can_authenticate? "a":"");
251 0 : printf ("flags %2d:%s%s%s%s%s%s%s\n",
252 : nsub,
253 0 : subkey->secret? " secret":"",
254 0 : subkey->revoked? " revoked":"",
255 0 : subkey->expired? " expired":"",
256 0 : subkey->disabled? " disabled":"",
257 0 : subkey->invalid? " invalid":"",
258 0 : subkey->is_qualified? " qualifid":"",
259 0 : subkey->is_cardkey? " cardkey":"");
260 : }
261 0 : for (nuids=0, uid=key->uids; uid; uid = uid->next, nuids++)
262 : {
263 0 : printf ("userid %d: %s\n", nuids, nonnull(uid->uid));
264 0 : printf (" mbox: %s\n", nonnull(uid->address));
265 0 : if (uid->email && uid->email != uid->address)
266 0 : printf (" email: %s\n", uid->email);
267 0 : if (uid->name)
268 0 : printf (" name: %s\n", uid->name);
269 0 : if (uid->comment)
270 0 : printf (" cmmnt: %s\n", uid->comment);
271 0 : printf (" valid: %s\n",
272 0 : uid->validity == GPGME_VALIDITY_UNKNOWN? "unknown":
273 0 : uid->validity == GPGME_VALIDITY_UNDEFINED? "undefined":
274 0 : uid->validity == GPGME_VALIDITY_NEVER? "never":
275 0 : uid->validity == GPGME_VALIDITY_MARGINAL? "marginal":
276 0 : uid->validity == GPGME_VALIDITY_FULL? "full":
277 0 : uid->validity == GPGME_VALIDITY_ULTIMATE? "ultimate": "[?]");
278 0 : if ((ti = uid->tofu))
279 : {
280 0 : printf (" tofu: %u (%s)\n", ti->validity,
281 0 : ti->validity == 0? "conflict" :
282 0 : ti->validity == 1? "no history" :
283 0 : ti->validity == 2? "little history" :
284 0 : ti->validity == 3? "enough history" :
285 0 : ti->validity == 4? "lot of history" : "?");
286 0 : printf (" policy: %u (%s)\n", ti->policy,
287 0 : ti->policy == GPGME_TOFU_POLICY_NONE? "none" :
288 0 : ti->policy == GPGME_TOFU_POLICY_AUTO? "auto" :
289 0 : ti->policy == GPGME_TOFU_POLICY_GOOD? "good" :
290 0 : ti->policy == GPGME_TOFU_POLICY_UNKNOWN? "unknown" :
291 0 : ti->policy == GPGME_TOFU_POLICY_BAD? "bad" :
292 0 : ti->policy == GPGME_TOFU_POLICY_ASK? "ask" : "?");
293 0 : printf (" nsigs: %hu\n", ti->signcount);
294 0 : printf (" first: %s\n", isotimestr (ti->signfirst));
295 0 : printf (" last: %s\n", isotimestr (ti->signlast));
296 0 : printf (" nencr: %hu\n", ti->encrcount);
297 0 : printf (" first: %s\n", isotimestr (ti->encrfirst));
298 0 : printf (" last: %s\n", isotimestr (ti->encrlast));
299 : }
300 : }
301 :
302 0 : putchar ('\n');
303 :
304 0 : if (import)
305 : {
306 0 : if (keyidx < DIM (keyarray)-1)
307 0 : keyarray[keyidx++] = key;
308 : else
309 : {
310 0 : fprintf (stderr, PGM": too many keys in import mode"
311 : "- skipping this key\n");
312 0 : gpgme_key_unref (key);
313 : }
314 : }
315 : else
316 0 : gpgme_key_unref (key);
317 : }
318 0 : if (gpgme_err_code (err) != GPG_ERR_EOF)
319 0 : fail_if_err (err);
320 0 : err = gpgme_op_keylist_end (ctx);
321 0 : fail_if_err (err);
322 0 : keyarray[keyidx] = NULL;
323 :
324 0 : result = gpgme_op_keylist_result (ctx);
325 0 : if (result->truncated)
326 : {
327 0 : fprintf (stderr, PGM ": key listing unexpectedly truncated\n");
328 0 : exit (1);
329 : }
330 :
331 0 : if (import)
332 : {
333 : gpgme_import_result_t impres;
334 :
335 0 : err = gpgme_op_import_keys (ctx, keyarray);
336 0 : fail_if_err (err);
337 0 : impres = gpgme_op_import_result (ctx);
338 0 : if (!impres)
339 : {
340 0 : fprintf (stderr, PGM ": no import result returned\n");
341 0 : exit (1);
342 : }
343 0 : print_import_result (impres);
344 : }
345 :
346 0 : for (keyidx=0; keyarray[keyidx]; keyidx++)
347 0 : gpgme_key_unref (keyarray[keyidx]);
348 :
349 0 : gpgme_release (ctx);
350 0 : return 0;
351 : }
|