Use gpgme interface for error handling to avoid linking with gpg-error.
[gpgme.git] / tests / gpg / t-keylist.c
1 /* t-keylist.c  - regression test
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2003, 2004 g10 Code GmbH
4
5    This file is part of GPGME.
6  
7    GPGME is free software; you can redistribute it and/or modify it
8    under the terms of the GNU Lesser General Public License as
9    published by the Free Software Foundation; either version 2.1 of
10    the License, or (at your option) any later version.
11    
12    GPGME is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16    
17    You should have received a copy of the GNU Lesser General Public
18    License along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21
22 /* We need to include config.h so that we know whether we are building
23    with large file system (LFS) support. */
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include <gpgme.h>
33
34 #include "t-support.h"
35
36
37 struct key_info_s
38 {
39   char *fpr;
40   char *sec_keyid;
41   struct
42   {
43     char *name;
44     char *comment;
45     char *email;
46   } uid[3];
47   int n_subkeys;
48   void (*misc_check)(struct key_info_s *keyinfo, gpgme_key_t key);
49 };
50
51
52 static void check_whisky (struct key_info_s *keyinfo, gpgme_key_t key);
53
54
55 \f
56 struct key_info_s keys[] =
57   {
58     { "A0FF4590BB6122EDEF6E3C542D727CC768697734", "6AE6D7EE46A871F8",
59       { { "Alfa Test", "demo key", "alfa@example.net" },
60         { "Alpha Test", "demo key", "alpha@example.net" },
61         { "Alice", "demo key", NULL } }, 1 },
62     { "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", "5381EA4EE29BA37F",
63       { { "Bob", "demo key", NULL },
64         { "Bravo Test", "demo key", "bravo@example.net" } }, 1 },
65     { "61EE841A2A27EB983B3B3C26413F4AF31AFDAB6C", "E71E72ACBC43DA60",
66       { { "Charlie Test", "demo key", "charlie@example.net" } }, 1 },
67     { "6560C59C43D031C54D7C588EEBA9F240EB9DC9E6", "06F22880B0C45424",
68       { { "Delta Test", "demo key", "delta@example.net" } }, 1 },
69     { "3531152DE293E26A07F504BC318C1FAEFAEF6D1B", "B5C79E1A7272144D",
70       { { "Echelon", "demo key", NULL },
71         { "Echo Test", "demo key", "echo@example.net" },
72         { "Eve", "demo key", NULL } }, 1 },
73     { "56D33268F7FE693FBB594762D4BF57F37372E243", "0A32EE79EE45198E",
74       { { "Foxtrot Test", "demo key", "foxtrot@example.net" } }, 1 },
75     { "C9C07DCC6621B9FB8D071B1D168410A48FC282E6", "247491CC9DCAD354",
76       { { "Golf Test", "demo key", "golf@example.net" } }, 1 },
77     { "9E91CBB11E4D4135583EF90513DB965534C6E3F1", "76E26537D622AD0A",
78       { { "Hotel Test", "demo key", "hotel@example.net" } }, 1 },
79     { "CD538D6CC9FB3D745ECDA5201FE8FC6F04259677", "C1C8EFDE61F76C73",
80       { { "India Test", "demo key", "india@example.net" } }, 1 },
81     { "F8F1EDC73995AB739AD54B380C820C71D2699313", "BD0B108735F8F136",
82       { { "Juliet Test", "demo key", "juliet@example.net" } }, 1 },
83     { "3FD11083779196C2ECDD9594AD1B0FAD43C2D0C7", "86CBB34A9AF64D02",
84       { { "Kilo Test", "demo key", "kilo@example.net" } }, 1 },
85     { "1DDD28CEF714F5B03B8C246937CAB51FB79103F8", "0363B449FE56350C",
86       { { "Lima Test", "demo key", "lima@example.net" } }, 1 },
87     { "2686AA191A278013992C72EBBE794852BE5CF886", "5F600A834F31EAE8",
88       { { "Mallory", "demo key", NULL },
89         { "Mike Test", "demo key", "mike@example.net" } }, 1 },
90     { "5AB9D6D7BAA1C95B3BAA3D9425B00FD430CEC684", "4C1D63308B70E472",
91       { { "November Test", "demo key", "november@example.net" } }, 1 },
92     { "43929E89F8F79381678CAE515F6356BA6D9732AC", "FF0785712681619F",
93       { { "Oscar Test", "demo key", "oscar@example.net" } }, 1 },
94     { "6FAA9C201E5E26DCBAEC39FD5D15E01D3FF13206", "2764E18263330D9C",
95       { { "Papa test", "demo key", "papa@example.net" } }, 1 },
96     { "A7969DA1C3297AA96D49843F1C67EC133C661C84", "6CDCFC44A029ACF4",
97       { { "Quebec Test", "demo key", "quebec@example.net" } }, 1 },
98     { "38FBE1E4BF6A5E1242C8F6A13BDBEDB1777FBED3", "9FAB805A11D102EA",
99       { { "Romeo Test", "demo key", "romeo@example.net" } }, 1 },
100     { "045B2334ADD69FC221076841A5E67F7FA3AE3EA1", "93B88B0F0F1B50B4",
101       { { "Sierra Test", "demo key", "sierra@example.net" } }, 1 },
102     { "ECAC774F4EEEB0620767044A58CB9A4C85A81F38", "97B60E01101C0402",
103       { { "Tango Test", "demo key", "tango@example.net" } }, 1 },
104     { "0DBCAD3F08843B9557C6C4D4A94C0F75653244D6", "93079B915522BDB9",
105       { { "Uniform Test", "demo key", "uniform@example.net" } }, 1 },
106     { "E8143C489C8D41124DC40D0B47AF4B6961F04784", "04071FB807287134",
107       { { "Victor Test", "demo key", "victor@example.org" } }, 1 },
108     { "E8D6C90B683B0982BD557A99DEF0F7B8EC67DBDE", "D7FBB421FD6E27F6",
109       { { "Whisky Test", "demo key", "whisky@example.net" } }, 3,
110           check_whisky },
111     { "04C1DF62EFA0EBB00519B06A8979A6C5567FB34A", "5CC6F87F41E408BE",
112       { { "XRay Test", "demo key", "xray@example.net" } }, 1 },
113     { "ED9B316F78644A58D042655A9EEF34CD4B11B25F", "5ADFD255F7B080AD",
114       { { "Yankee Test", "demo key", "yankee@example.net" } }, 1 },
115     { "23FD347A419429BACCD5E72D6BC4778054ACD246", "EF9DC276A172C881",
116       { { "Zulu Test", "demo key", "zulu@example.net" } }, 1 },
117     { "ADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", "087DD7E0381701C4",
118       { { "Joe Random Hacker", "test key with passphrase \"abc\"",
119           "joe@example.com" } }, 1 },
120     { NULL }
121   };
122
123
124 int 
125 main (int argc, char **argv)
126 {
127   gpgme_error_t err;
128   gpgme_ctx_t ctx;
129   gpgme_key_t key;
130   gpgme_keylist_result_t result;
131   int i = 0;
132   int n;
133   gpgme_subkey_t subkey;
134
135   init_gpgme (GPGME_PROTOCOL_OpenPGP);
136
137   err = gpgme_new (&ctx);
138   fail_if_err (err);
139
140   err = gpgme_op_keylist_start (ctx, NULL, 0);
141   fail_if_err (err);
142     
143   while (!(err = gpgme_op_keylist_next (ctx, &key)))
144     {
145       if (!keys[i].fpr)
146         {
147           fprintf (stderr, "More keys returned than expected\n");
148           exit (1);
149         }
150
151       /* Global key flags.  */
152       if (key->revoked)
153         {
154           fprintf (stderr, "Key unexpectedly revoked\n");
155           exit (1);
156         }
157       if (key->expired)
158         {
159           fprintf (stderr, "Key unexpectedly expired\n");
160           exit (1);
161         }
162       if (key->disabled)
163         {
164           fprintf (stderr, "Key unexpectedly disabled\n");
165           exit (1);
166         }
167       if (key->invalid)
168         {
169           fprintf (stderr, "Key unexpectedly invalid\n");
170           exit (1);
171         }
172 #if 0
173       /* GnuPG 2.1+ have a different subkey for encryption.  */
174       if (!key->can_encrypt)
175         {
176           fprintf (stderr, "Key unexpectedly unusable for encryption\n");
177           exit (1);
178         }
179 #endif
180       if (!key->can_sign)
181         {
182           fprintf (stderr, "Key unexpectedly unusable for signing\n");
183           exit (1);
184         }
185       if (!key->can_certify)
186         {
187           fprintf (stderr, "Key unexpectedly unusable for certifications\n");
188           exit (1);
189         }
190       if (key->secret)
191         {
192           fprintf (stderr, "Key unexpectedly secret\n");
193           exit (1);
194         }
195       if (key->protocol != GPGME_PROTOCOL_OpenPGP)
196         {
197           fprintf (stderr, "Key has unexpected protocol: %s\n",
198                    gpgme_get_protocol_name (key->protocol));
199           exit (1);
200         }
201       if (key->issuer_serial)
202         {
203           fprintf (stderr, "Key unexpectedly carries issuer serial: %s\n",
204                    key->issuer_serial);
205           exit (1);
206         }
207       if (key->issuer_name)
208         {
209           fprintf (stderr, "Key unexpectedly carries issuer name: %s\n",
210                    key->issuer_name);
211           exit (1);
212         }
213       if (key->chain_id)
214         {
215           fprintf (stderr, "Key unexpectedly carries chain ID: %s\n",
216                    key->chain_id);
217           exit (1);
218         }
219       if (key->owner_trust != GPGME_VALIDITY_UNKNOWN)
220         {
221           fprintf (stderr, "Key has unexpected owner trust: %i\n",
222                    key->owner_trust);
223           exit (1);
224         }
225
226       for (n=0, subkey = key->subkeys; subkey; subkey = subkey->next) 
227         n++;
228       if (!n || n-1 != keys[i].n_subkeys)
229         {
230           fprintf (stderr, "Key `%s' has unexpected number of subkeys\n",
231                    keys[i].uid[0].name);
232           exit (1);
233         }
234
235       /* Primary key.  */
236       if (key->subkeys->revoked)
237         {
238           fprintf (stderr, "Primary key unexpectedly revoked\n");
239           exit (1);
240         }
241       if (key->subkeys->expired)
242         {
243           fprintf (stderr, "Primary key unexpectedly expired\n");
244           exit (1);
245         }
246       if (key->subkeys->disabled)
247         {
248           fprintf (stderr, "Primary key unexpectedly disabled\n");
249           exit (1);
250         }
251       if (key->subkeys->invalid)
252         {
253           fprintf (stderr, "Primary key unexpectedly invalid\n");
254           exit (1);
255         }
256       if (key->subkeys->can_encrypt)
257         {
258           fprintf (stderr, "Primary key unexpectedly usable for encryption\n");
259           exit (1);
260         }
261       if (!key->subkeys->can_sign)
262         {
263           fprintf (stderr, "Primary key unexpectedly unusable for signing\n");
264           exit (1);
265         }
266       if (!key->subkeys->can_certify)
267         {
268           fprintf (stderr, "Primary key unexpectedly unusable for certifications\n");
269           exit (1);
270         }
271       if (key->subkeys->secret)
272         {
273           fprintf (stderr, "Primary key unexpectedly secret\n");
274           exit (1);
275         }
276       if (key->subkeys->is_cardkey)
277         {
278           fprintf (stderr, "Public key marked as card key\n");
279           exit (1);
280         }
281       if (key->subkeys->card_number)
282         {
283           fprintf (stderr, "Public key with card number set\n");
284           exit (1);
285         }
286       if (key->subkeys->pubkey_algo != GPGME_PK_DSA)
287         {
288           fprintf (stderr, "Primary key has unexpected public key algo: %s\n",
289                    gpgme_pubkey_algo_name (key->subkeys->pubkey_algo));
290           exit (1);
291         }
292       if (key->subkeys->length != 1024)
293         {
294           fprintf (stderr, "Primary key has unexpected length: %i\n",
295                    key->subkeys->length);
296           exit (1);
297         }
298       if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16]))
299         {
300           fprintf (stderr, "Primary key `%s' has unexpected key ID: %s\n",
301                    keys[i].uid[0].name, key->subkeys->keyid);
302           exit (1);
303         }
304       if (strcmp (key->subkeys->fpr, keys[i].fpr))
305         {
306           fprintf (stderr, "Primary key has unexpected fingerprint: %s\n",
307                    key->subkeys->fpr);
308           exit (1);
309         }
310       if (key->subkeys->expires)
311         {
312           fprintf (stderr, "Primary key `%s' unexpectedly expires: %lu\n",
313                    keys[i].uid[0].name, key->subkeys->expires);
314           exit (1);
315         }
316
317       /* Secondary key.  */
318       if (key->subkeys->next->revoked)
319         {
320           fprintf (stderr, "Secondary key unexpectedly revoked\n");
321           exit (1);
322         }
323       if (key->subkeys->next->expired)
324         {
325           fprintf (stderr, "Secondary key unexpectedly expired\n");
326           exit (1);
327         }
328       if (key->subkeys->next->disabled)
329         {
330           fprintf (stderr, "Secondary key unexpectedly disabled\n");
331           exit (1);
332         }
333       if (key->subkeys->next->invalid)
334         {
335           fprintf (stderr, "Secondary key unexpectedly invalid\n");
336           exit (1);
337         }
338       if (!key->subkeys->next->can_encrypt)
339         {
340           fprintf (stderr, "Secondary key unexpectedly unusable for encryption\n");
341           exit (1);
342         }
343       if (key->subkeys->next->can_sign)
344         {
345           fprintf (stderr, "Secondary key unexpectedly usable for signing\n");
346           exit (1);
347         }
348       if (key->subkeys->next->can_certify)
349         {
350           fprintf (stderr, "Secondary key unexpectedly usable for certifications\n");
351           exit (1);
352         }
353       if (key->subkeys->next->secret)
354         {
355           fprintf (stderr, "Secondary key unexpectedly secret\n");
356           exit (1);
357         }
358       if (key->subkeys->next->is_cardkey)
359         {
360           fprintf (stderr, "Secondary public key marked as card key\n");
361           exit (1);
362         }
363       if (key->subkeys->next->card_number)
364         {
365           fprintf (stderr, "Secondary public key with card number set\n");
366           exit (1);
367         }
368       if (key->subkeys->next->pubkey_algo != GPGME_PK_ELG_E)
369         {
370           fprintf (stderr, "Secondary key has unexpected public key algo: %s\n",
371                    gpgme_pubkey_algo_name (key->subkeys->next->pubkey_algo));
372           exit (1);
373         }
374       if (key->subkeys->next->length != 1024)
375         {
376           fprintf (stderr, "Secondary key has unexpected length: %i\n",
377                    key->subkeys->next->length);
378           exit (1);
379         }
380       if (strcmp (key->subkeys->next->keyid, keys[i].sec_keyid))
381         {
382           fprintf (stderr, "Secondary key `%s' has unexpected key ID: %s/%s\n",
383                    keys[i].uid[0].name,
384                    key->subkeys->next->keyid, keys[i].sec_keyid );
385           exit (1);
386         }
387       if (!key->subkeys->next->fpr)
388         {
389           fprintf (stderr, "Secondary key has unexpectedly no fingerprint\n");
390           exit (1);
391         }
392       if (key->subkeys->next->expires)
393         {
394           fprintf (stderr, "Secondary key unexpectedly expires: %lu\n",
395                    key->subkeys->next->expires);
396           exit (1);
397         }
398
399       /* FIXME: The below test will crash if we want to check for a
400          name, comment or email that doesn't exist in the key's user
401          IDs.  */
402       if (!((!keys[i].uid[0].name && !key->uids)
403             || (keys[i].uid[0].name && !keys[i].uid[1].name
404                 && key->uids && !key->uids->next)
405             || (keys[i].uid[0].name && keys[i].uid[1].name
406                 && !keys[i].uid[2].name
407                 && key->uids && key->uids->next && !key->uids->next->next)
408             || (keys[i].uid[0].name && keys[i].uid[1].name
409                 && keys[i].uid[2].name
410                 && key->uids && key->uids->next && key->uids->next->next
411                 && !key->uids->next->next->next)))
412           {
413             fprintf (stderr, "Key has unexpected number of user IDs\n");
414             exit (1);
415           }
416       if (key->uids && key->uids->revoked)
417         {
418           fprintf (stderr, "First user ID unexpectedly revoked\n");
419           exit (1);
420         }
421       if (key->uids && key->uids->invalid)
422         {
423           fprintf (stderr, "First user ID unexpectedly invalid\n");
424           exit (1);
425         }
426       if (key->uids && key->uids->validity != GPGME_VALIDITY_UNKNOWN)
427         {
428           fprintf (stderr, "First user ID has unexpectedly validity: %i\n",
429                    key->uids->validity);
430           exit (1);
431         }
432       if (key->uids && key->uids->signatures)
433         {
434           fprintf (stderr, "First user ID unexpectedly signed\n");
435           exit (1);
436         }
437       if (keys[i].uid[0].name
438           && strcmp (keys[i].uid[0].name, key->uids->name))
439         {
440           fprintf (stderr, "Unexpected name in first user ID: %s\n",
441                    key->uids->name);
442           exit (1);
443         }
444       if (keys[i].uid[0].comment
445           && strcmp (keys[i].uid[0].comment, key->uids->comment))
446         {
447           fprintf (stderr, "Unexpected comment in first user ID: %s\n",
448                    key->uids->comment);
449           exit (1);
450         }
451       if (keys[i].uid[0].email
452           && strcmp (keys[i].uid[0].email, key->uids->email))
453         {
454           fprintf (stderr, "Unexpected email in first user ID: %s\n",
455                    key->uids->email);
456           exit (1);
457         }
458       if (key->uids && key->uids->next && key->uids->next->revoked)
459         {
460           fprintf (stderr, "Second user ID unexpectedly revoked\n");
461           exit (1);
462         }
463       if (key->uids && key->uids->next && key->uids->next->invalid)
464         {
465           fprintf (stderr, "Second user ID unexpectedly invalid\n");
466           exit (1);
467         }
468       if (key->uids && key->uids->next
469           && key->uids->next->validity != GPGME_VALIDITY_UNKNOWN)
470         {
471           fprintf (stderr, "Second user ID has unexpectedly validity: %i\n",
472                    key->uids->next->validity);
473           exit (1);
474         }
475       if (key->uids && key->uids->next && key->uids->next->signatures)
476         {
477           fprintf (stderr, "Second user ID unexpectedly signed\n");
478           exit (1);
479         }
480       if (keys[i].uid[1].name
481           && strcmp (keys[i].uid[1].name, key->uids->next->name))
482         {
483           fprintf (stderr, "Unexpected name in second user ID: %s\n",
484                    key->uids->next->name);
485           exit (1);
486         }
487       if (keys[i].uid[1].comment
488           && strcmp (keys[i].uid[1].comment, key->uids->next->comment))
489         {
490           fprintf (stderr, "Unexpected comment in second user ID: %s\n",
491                    key->uids->next->comment);
492           exit (1);
493         }
494       if (keys[i].uid[1].email
495           && strcmp (keys[i].uid[1].email, key->uids->next->email))
496         {
497           fprintf (stderr, "Unexpected email in second user ID: %s\n",
498                    key->uids->next->email);
499           exit (1);
500         }
501       if (key->uids && key->uids->next && key->uids->next->next
502           && key->uids->next->next->revoked)
503         {
504           fprintf (stderr, "Third user ID unexpectedly revoked\n");
505           exit (1);
506         }
507       if (key->uids && key->uids->next && key->uids->next->next
508           && key->uids->next->next->invalid)
509         {
510           fprintf (stderr, "Third user ID unexpectedly invalid\n");
511           exit (1);
512         }
513       if (key->uids && key->uids->next && key->uids->next->next
514           && key->uids->next->next->validity != GPGME_VALIDITY_UNKNOWN)
515         {
516           fprintf (stderr, "Third user ID has unexpectedly validity: %i\n",
517                    key->uids->next->next->validity);
518           exit (1);
519         }
520       if (key->uids && key->uids->next && key->uids->next->next
521           && key->uids->next->next->signatures)
522         {
523           fprintf (stderr, "Third user ID unexpectedly signed\n");
524           exit (1);
525         }
526       if (keys[i].uid[2].name
527           && strcmp (keys[i].uid[2].name, key->uids->next->next->name))
528         {
529           fprintf (stderr, "Unexpected name in third user ID: %s\n",
530                    key->uids->next->next->name);
531           exit (1);
532         }
533       if (keys[i].uid[2].comment
534           && strcmp (keys[i].uid[2].comment, key->uids->next->next->comment))
535         {
536           fprintf (stderr, "Unexpected comment in third user ID: %s\n",
537                    key->uids->next->next->comment);
538           exit (1);
539         }
540       if (keys[i].uid[2].email
541           && strcmp (keys[i].uid[2].email, key->uids->next->next->email))
542         {
543           fprintf (stderr, "Unexpected email in third user ID: %s\n",
544                    key->uids->next->next->email);
545           exit (1);
546         }
547
548       if (keys[i].misc_check)
549         keys[i].misc_check (keys+i, key);
550
551       gpgme_key_unref (key);
552       i++;
553     }
554   if (gpgme_err_code (err) != GPG_ERR_EOF)
555     fail_if_err (err);
556   err = gpgme_op_keylist_end (ctx);
557   fail_if_err (err);
558
559   result = gpgme_op_keylist_result (ctx);
560   if (result->truncated)
561     {
562       fprintf (stderr, "Key listing unexpectedly truncated\n");
563       exit (1);
564     }
565
566   if (keys[i].fpr)
567     {
568       fprintf (stderr, "Less keys returned than expected\n");
569       exit (1);
570     }
571
572   gpgme_release (ctx);
573   return 0;
574 }
575
576
577
578 /* Check expration of keys.  This test assumes three subkeys of which
579    2 are expired; it is used with the "Whisky" test key.  It has
580    already been checked that these 3 subkeys are available. */
581 static void
582 check_whisky (struct key_info_s *keyinfo, gpgme_key_t key)
583 {
584   const char *name = keyinfo->uid[0].name;
585   gpgme_subkey_t sub1, sub2;
586   
587   sub1 = key->subkeys->next->next;
588   sub2 = sub1->next;
589
590   if (!sub1->expired || !sub2->expired)
591     {
592       fprintf (stderr, "Subkey of `%s' not flagged as expired\n", name);
593       exit (1);
594     }
595   if (sub1->expires != 1129636886 || sub2->expires != 1129636939)
596     {
597       fprintf (stderr, "Subkey of `%s' has wrong expiration date\n", name);
598       exit (1);
599     }
600
601 }
602