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