1 /* t-keylist-secret-sig.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, see <https://gnu.org/licenses/>.
19  * SPDX-License-Identifier: LGPL-2.1-or-later
20  */
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
38 {
39   const char *fpr;
40   const char *sec_keyid;
41   struct
42   {
43     const char *name;
44     const char *comment;
45     const char *email;
46     struct
47     {
48       gpgme_pubkey_algo_t algo;
49       const char *keyid;
50       const char *name;
51       const char *comment;
52       const char *email;
53       unsigned int sig_class;
54       int exportable;
55     } sig;
56   } uid[3];
57 }
58 keys[] =
59   {
60     { "A0FF4590BB6122EDEF6E3C542D727CC768697734", "6AE6D7EE46A871F8",
61       { { "Alfa Test", "demo key", "alfa@example.net",
62           { GPGME_PK_DSA, "2D727CC768697734",
63 	    "Alfa Test", "demo key", "alfa@example.net", 19, 1 } },
64 	{ "Alpha Test", "demo key", "alpha@example.net",
65           { GPGME_PK_DSA, "2D727CC768697734",
66 	    "Alfa Test", "demo key", "alfa@example.net", 19, 1 } },
67 	{ "Alice", "demo key", NULL,
68           { GPGME_PK_DSA, "2D727CC768697734",
69 	    "Alfa Test", "demo key", "alfa@example.net", 19, 1 } } } },
70     { NULL }
71   };
72 
73 
74 int
main(void)75 main (void)
76 {
77   gpgme_error_t err;
78   gpgme_ctx_t ctx;
79   gpgme_key_t key;
80   gpgme_keylist_result_t result;
81   int mode;
82   int i = 0;
83 
84   init_gpgme (GPGME_PROTOCOL_OpenPGP);
85 
86   err = gpgme_new (&ctx);
87   fail_if_err (err);
88 
89   mode  = gpgme_get_keylist_mode (ctx);
90   mode |= GPGME_KEYLIST_MODE_SIGS;
91   err = gpgme_set_keylist_mode (ctx, mode);
92   fail_if_err (err);
93 
94   err = gpgme_op_keylist_start (ctx, "Alpha", 1);
95   fail_if_err (err);
96 
97   while (!(err = gpgme_op_keylist_next (ctx, &key)))
98     {
99       if (!keys[i].fpr)
100 	{
101 	  fprintf (stderr, "More keys returned than expected\n");
102 	  exit (1);
103 	}
104 
105       /* Global key flags.  */
106       if (key->revoked)
107 	{
108 	  fprintf (stderr, "Key unexpectedly revoked\n");
109 	  exit (1);
110 	}
111       if (key->expired)
112 	{
113 	  fprintf (stderr, "Key unexpectedly expired\n");
114 	  exit (1);
115 	}
116       if (key->disabled)
117 	{
118 	  fprintf (stderr, "Key unexpectedly disabled\n");
119 	  exit (1);
120 	}
121       if (key->invalid)
122 	{
123 	  fprintf (stderr, "Key unexpectedly invalid\n");
124 	  exit (1);
125 	}
126       if (!key->can_encrypt)
127 	{
128 	  fprintf (stderr, "Key unexpectedly unusable for encryption\n");
129 	  exit (1);
130 	}
131       if (!key->can_sign)
132 	{
133 	  fprintf (stderr, "Key unexpectedly unusable for signing\n");
134 	  exit (1);
135 	}
136       if (!key->can_certify)
137 	{
138 	  fprintf (stderr, "Key unexpectedly unusable for certifications\n");
139 	  exit (1);
140 	}
141       if (!key->secret)
142 	{
143 	  fprintf (stderr, "Key unexpectedly not secret\n");
144 	  exit (1);
145 	}
146       if (key->protocol != GPGME_PROTOCOL_OpenPGP)
147 	{
148 	  fprintf (stderr, "Key has unexpected protocol: %s\n",
149 		   gpgme_get_protocol_name (key->protocol));
150 	  exit (1);
151 	}
152       if (key->issuer_serial)
153 	{
154 	  fprintf (stderr, "Key unexpectedly carries issuer serial: %s\n",
155 		   key->issuer_serial);
156 	  exit (1);
157 	}
158       if (key->issuer_name)
159 	{
160 	  fprintf (stderr, "Key unexpectedly carries issuer name: %s\n",
161 		   key->issuer_name);
162 	  exit (1);
163 	}
164       if (key->chain_id)
165 	{
166 	  fprintf (stderr, "Key unexpectedly carries chain ID: %s\n",
167 		   key->chain_id);
168 	  exit (1);
169 	}
170       if (key->owner_trust != GPGME_VALIDITY_UNKNOWN)
171 	{
172 	  fprintf (stderr, "Key has unexpected owner trust: %i\n",
173 		   key->owner_trust);
174 	  exit (1);
175 	}
176       if (!key->subkeys || !key->subkeys->next || key->subkeys->next->next)
177 	{
178 	  fprintf (stderr, "Key has unexpected number of subkeys\n");
179 	  exit (1);
180 	}
181 
182       /* Primary key.  */
183       if (key->subkeys->revoked)
184 	{
185 	  fprintf (stderr, "Primary key unexpectedly revoked\n");
186 	  exit (1);
187 	}
188       if (key->subkeys->expired)
189 	{
190 	  fprintf (stderr, "Primary key unexpectedly expired\n");
191 	  exit (1);
192 	}
193       if (key->subkeys->disabled)
194 	{
195 	  fprintf (stderr, "Primary key unexpectedly disabled\n");
196 	  exit (1);
197 	}
198       if (key->subkeys->invalid)
199 	{
200 	  fprintf (stderr, "Primary key unexpectedly invalid\n");
201 	  exit (1);
202 	}
203       if (key->subkeys->can_encrypt)
204 	{
205 	  fprintf (stderr, "Primary key unexpectedly usable for encryption\n");
206 	  exit (1);
207 	}
208       if (!key->subkeys->can_sign)
209 	{
210 	  fprintf (stderr, "Primary key unexpectedly unusable for signing\n");
211 	  exit (1);
212 	}
213       if (!key->subkeys->can_certify)
214 	{
215 	  fprintf (stderr, "Primary key unexpectedly unusable for certifications\n");
216 	  exit (1);
217 	}
218       if (!key->subkeys->secret)
219 	{
220 	  fprintf (stderr, "Primary key unexpectedly not secret\n");
221 	  exit (1);
222 	}
223       if (key->subkeys->pubkey_algo != GPGME_PK_DSA)
224 	{
225 	  fprintf (stderr, "Primary key has unexpected public key algo: %s\n",
226 		   gpgme_pubkey_algo_name (key->subkeys->pubkey_algo));
227 	  exit (1);
228 	}
229       if (key->subkeys->length != 1024)
230 	{
231 	  fprintf (stderr, "Primary key has unexpected length: %i\n",
232 		   key->subkeys->length);
233 	  exit (1);
234 	}
235       if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16]))
236 	{
237 	  fprintf (stderr, "Primary key has unexpected key ID: %s\n",
238 		   key->subkeys->keyid);
239 	  exit (1);
240 	}
241       if (strcmp (key->subkeys->fpr, keys[i].fpr))
242 	{
243 	  fprintf (stderr, "Primary key has unexpected fingerprint: %s\n",
244 		   key->subkeys->fpr);
245 	  exit (1);
246 	}
247       if (key->subkeys->expires)
248 	{
249 	  fprintf (stderr, "Primary key unexpectedly expires: %lu\n",
250 		   key->subkeys->expires);
251 	  exit (1);
252 	}
253 
254       /* Secondary key.  */
255       if (key->subkeys->next->revoked)
256 	{
257 	  fprintf (stderr, "Secondary key unexpectedly revoked\n");
258 	  exit (1);
259 	}
260       if (key->subkeys->next->expired)
261 	{
262 	  fprintf (stderr, "Secondary key unexpectedly expired\n");
263 	  exit (1);
264 	}
265       if (key->subkeys->next->disabled)
266 	{
267 	  fprintf (stderr, "Secondary key unexpectedly disabled\n");
268 	  exit (1);
269 	}
270       if (key->subkeys->next->invalid)
271 	{
272 	  fprintf (stderr, "Secondary key unexpectedly invalid\n");
273 	  exit (1);
274 	}
275       if (!key->subkeys->next->can_encrypt)
276 	{
277 	  fprintf (stderr, "Secondary key unexpectedly unusable for encryption\n");
278 	  exit (1);
279 	}
280       if (key->subkeys->next->can_sign)
281 	{
282 	  fprintf (stderr, "Secondary key unexpectedly usable for signing\n");
283 	  exit (1);
284 	}
285       if (key->subkeys->next->can_certify)
286 	{
287 	  fprintf (stderr, "Secondary key unexpectedly usable for certifications\n");
288 	  exit (1);
289 	}
290       if (!key->subkeys->next->secret)
291 	{
292 	  fprintf (stderr, "Secondary key unexpectedly not secret\n");
293 	  exit (1);
294 	}
295       if (key->subkeys->next->pubkey_algo != GPGME_PK_ELG_E)
296 	{
297 	  fprintf (stderr, "Secondary key has unexpected public key algo: %s\n",
298 		   gpgme_pubkey_algo_name (key->subkeys->next->pubkey_algo));
299 	  exit (1);
300 	}
301       if (key->subkeys->next->length != 1024)
302 	{
303 	  fprintf (stderr, "Secondary key has unexpected length: %i\n",
304 		   key->subkeys->next->length);
305 	  exit (1);
306 	}
307       if (strcmp (key->subkeys->next->keyid, keys[i].sec_keyid))
308 	{
309 	  fprintf (stderr, "Secondary key has unexpected key ID: %s\n",
310 		   key->subkeys->next->keyid);
311 	  exit (1);
312 	}
313       if (!key->subkeys->next->fpr)
314 	{
315 	  fprintf (stderr, "Secondary key has unexpectedly no fingerprint\n");
316 	  exit (1);
317 	}
318       if (key->subkeys->next->expires)
319 	{
320 	  fprintf (stderr, "Secondary key unexpectedly expires: %lu\n",
321 		   key->subkeys->next->expires);
322 	  exit (1);
323 	}
324 
325       /* FIXME: The below test will crash if we want to check for a
326 	 name, comment or email that doesn't exist in the key's user
327 	 IDs.  */
328       if (!((!keys[i].uid[0].name && !key->uids)
329 	    || (keys[i].uid[0].name && !keys[i].uid[1].name
330 		&& key->uids && !key->uids->next)
331 	    || (keys[i].uid[0].name && keys[i].uid[1].name
332 		&& !keys[i].uid[2].name
333 		&& key->uids && key->uids->next && !key->uids->next->next)
334 	    || (keys[i].uid[0].name && keys[i].uid[1].name
335 		&& keys[i].uid[2].name
336 		&& key->uids && key->uids->next && key->uids->next->next
337 		&& !key->uids->next->next->next)))
338 	  {
339 	    fprintf (stderr, "Key has unexpected number of user IDs\n");
340 	    exit (1);
341 	  }
342       if (key->uids && key->uids->revoked)
343 	{
344 	  fprintf (stderr, "First user ID unexpectedly revoked\n");
345 	  exit (1);
346 	}
347       if (key->uids && key->uids->invalid)
348 	{
349 	  fprintf (stderr, "First user ID unexpectedly invalid\n");
350 	  exit (1);
351 	}
352       if (key->uids && key->uids->validity != GPGME_VALIDITY_UNKNOWN)
353 	{
354 	  fprintf (stderr, "First user ID has unexpectedly validity: %i\n",
355 		   key->uids->validity);
356 	  exit (1);
357 	}
358       if (keys[i].uid[0].name
359 	  && strcmp (keys[i].uid[0].name, key->uids->name))
360 	{
361 	  fprintf (stderr, "Unexpected name in first user ID: %s\n",
362 		   key->uids->name);
363 	  exit (1);
364 	}
365       if (keys[i].uid[0].comment
366 	  && strcmp (keys[i].uid[0].comment, key->uids->comment))
367 	{
368 	  fprintf (stderr, "Unexpected comment in first user ID: %s\n",
369 		   key->uids->comment);
370 	  exit (1);
371 	}
372       if (keys[i].uid[0].email
373 	  && strcmp (keys[i].uid[0].email, key->uids->email))
374 	{
375 	  fprintf (stderr, "Unexpected email in first user ID: %s\n",
376 		   key->uids->email);
377 	  exit (1);
378 	}
379       if (key->uids && (!key->uids->signatures || key->uids->signatures->next))
380 	{
381 	  fprintf (stderr, "First user ID unexpected number of signatures\n");
382 	  exit (1);
383 	}
384       if (keys[i].uid[0].sig.algo != key->uids->signatures->pubkey_algo)
385 	{
386 	  fprintf (stderr, "Unexpected algorithm in first user ID sig: %s\n",
387 		   gpgme_pubkey_algo_name (key->uids->signatures->pubkey_algo));
388 	  exit (1);
389 	}
390       if (strcmp (keys[i].uid[0].sig.keyid, key->uids->signatures->keyid))
391 	{
392 	  fprintf (stderr, "Unexpected key ID in first user ID sig: %s\n",
393 		   key->uids->signatures->keyid);
394 	  exit (1);
395 	}
396       if (strcmp (keys[i].uid[0].sig.name, key->uids->signatures->name))
397 	{
398 	  fprintf (stderr, "Unexpected name in first user ID sig: %s\n",
399 		   key->uids->signatures->name);
400 	  exit (1);
401 	}
402       if (strcmp (keys[i].uid[0].sig.comment, key->uids->signatures->comment))
403 	{
404 	  fprintf (stderr, "Unexpected comment in first user ID sig: %s\n",
405 		   key->uids->signatures->comment);
406 	  exit (1);
407 	}
408       if (strcmp (keys[i].uid[0].sig.email, key->uids->signatures->email))
409 	{
410 	  fprintf (stderr, "Unexpected email in first user ID sig: %s\n",
411 		   key->uids->signatures->email);
412 	  exit (1);
413 	}
414       if (keys[i].uid[0].sig.sig_class != key->uids->signatures->sig_class)
415 	{
416 	  fprintf (stderr, "Unexpected class in first user ID sig: %i\n",
417 		   key->uids->signatures->sig_class);
418 	  exit (1);
419 	}
420       if (keys[i].uid[0].sig.exportable != key->uids->signatures->exportable)
421 	{
422 	  fprintf (stderr, "Unexpected exportable stat in first user ID sig: %i\n",
423 		   key->uids->signatures->exportable);
424 	  exit (1);
425 	}
426 
427       if (key->uids && key->uids->next && key->uids->next->revoked)
428 	{
429 	  fprintf (stderr, "Second user ID unexpectedly revoked\n");
430 	  exit (1);
431 	}
432       if (key->uids && key->uids->next && key->uids->next->invalid)
433 	{
434 	  fprintf (stderr, "Second user ID unexpectedly invalid\n");
435 	  exit (1);
436 	}
437       if (key->uids && key->uids->next
438 	  && key->uids->next->validity != GPGME_VALIDITY_UNKNOWN)
439 	{
440 	  fprintf (stderr, "Second user ID has unexpectedly validity: %i\n",
441 		   key->uids->next->validity);
442 	  exit (1);
443 	}
444       if (keys[i].uid[1].name
445 	  && strcmp (keys[i].uid[1].name, key->uids->next->name))
446 	{
447 	  fprintf (stderr, "Unexpected name in second user ID: %s\n",
448 		   key->uids->next->name);
449 	  exit (1);
450 	}
451       if (keys[i].uid[1].comment
452 	  && strcmp (keys[i].uid[1].comment, key->uids->next->comment))
453 	{
454 	  fprintf (stderr, "Unexpected comment in second user ID: %s\n",
455 		   key->uids->next->comment);
456 	  exit (1);
457 	}
458       if (keys[i].uid[1].email
459 	  && strcmp (keys[i].uid[1].email, key->uids->next->email))
460 	{
461 	  fprintf (stderr, "Unexpected email in second user ID: %s\n",
462 		   key->uids->next->email);
463 	  exit (1);
464 	}
465       /* Note: There is a bug in gpg 1.3.4 which duplicates a
466          signature after importing the secret key.  Thus we disable
467          the second part of the check. */
468       if (key->uids && (!key->uids->next->signatures /*|| key->uids->next->signatures->next*/))
469 	{
470 	  fprintf (stderr, "Second user ID unexpected number of signatures\n");
471 	  exit (1);
472 	}
473       if (keys[i].uid[1].sig.algo != key->uids->next->signatures->pubkey_algo)
474 	{
475 	  fprintf (stderr, "Unexpected algorithm in second user ID sig: %s\n",
476 		   gpgme_pubkey_algo_name (key->uids->next->signatures->pubkey_algo));
477 	  exit (1);
478 	}
479       if (strcmp (keys[i].uid[1].sig.keyid, key->uids->next->signatures->keyid))
480 	{
481 	  fprintf (stderr, "Unexpected key ID in second user ID sig: %s\n",
482 		   key->uids->next->signatures->keyid);
483 	  exit (1);
484 	}
485       if (strcmp (keys[i].uid[1].sig.name, key->uids->next->signatures->name))
486 	{
487 	  fprintf (stderr, "Unexpected name in second user ID sig: %s\n",
488 		   key->uids->next->signatures->name);
489 	  exit (1);
490 	}
491       if (strcmp (keys[i].uid[1].sig.comment, key->uids->next->signatures->comment))
492 	{
493 	  fprintf (stderr, "Unexpected comment in second user ID sig: %s\n",
494 		   key->uids->next->signatures->comment);
495 	  exit (1);
496 	}
497       if (strcmp (keys[i].uid[1].sig.email, key->uids->next->signatures->email))
498 	{
499 	  fprintf (stderr, "Unexpected email in second user ID sig: %s\n",
500 		   key->uids->next->signatures->email);
501 	  exit (1);
502 	}
503       if (keys[i].uid[1].sig.sig_class != key->uids->next->signatures->sig_class)
504 	{
505 	  fprintf (stderr, "Unexpected class in second user ID sig: %i\n",
506 		   key->uids->next->signatures->sig_class);
507 	  exit (1);
508 	}
509       if (keys[i].uid[1].sig.exportable != key->uids->next->signatures->exportable)
510 	{
511 	  fprintf (stderr, "Unexpected exportable stat in second user ID sig: %i\n",
512 		   key->uids->next->signatures->exportable);
513 	  exit (1);
514 	}
515 
516       if (key->uids && key->uids->next && key->uids->next->next
517 	  && key->uids->next->next->revoked)
518 	{
519 	  fprintf (stderr, "Third user ID unexpectedly revoked\n");
520 	  exit (1);
521 	}
522       if (key->uids && key->uids->next && key->uids->next->next
523 	  && key->uids->next->next->invalid)
524 	{
525 	  fprintf (stderr, "Third user ID unexpectedly invalid\n");
526 	  exit (1);
527 	}
528       if (key->uids && key->uids->next && key->uids->next->next
529 	  && key->uids->next->next->validity != GPGME_VALIDITY_UNKNOWN)
530 	{
531 	  fprintf (stderr, "Third user ID has unexpectedly validity: %i\n",
532 		   key->uids->next->next->validity);
533 	  exit (1);
534 	}
535       if (keys[i].uid[2].name
536 	  && strcmp (keys[i].uid[2].name, key->uids->next->next->name))
537 	{
538 	  fprintf (stderr, "Unexpected name in third user ID: %s\n",
539 		   key->uids->next->next->name);
540 	  exit (1);
541 	}
542       if (keys[i].uid[2].comment
543 	  && strcmp (keys[i].uid[2].comment, key->uids->next->next->comment))
544 	{
545 	  fprintf (stderr, "Unexpected comment in third user ID: %s\n",
546 		   key->uids->next->next->comment);
547 	  exit (1);
548 	}
549       if (keys[i].uid[2].email
550 	  && strcmp (keys[i].uid[2].email, key->uids->next->next->email))
551 	{
552 	  fprintf (stderr, "Unexpected email in third user ID: %s\n",
553 		   key->uids->next->next->email);
554 	  exit (1);
555 	}
556       if (key->uids && (!key->uids->next->next->signatures
557 			|| key->uids->next->next->signatures->next))
558 	{
559 	  fprintf (stderr, "Third user ID unexpected number of signatures\n");
560 	  exit (1);
561 	}
562       if (keys[i].uid[2].sig.algo != key->uids->next->next->signatures->pubkey_algo)
563 	{
564 	  fprintf (stderr, "Unexpected algorithm in third user ID sig: %s\n",
565 		   gpgme_pubkey_algo_name (key->uids->next->next->signatures->pubkey_algo));
566 	  exit (1);
567 	}
568       if (strcmp (keys[i].uid[2].sig.keyid, key->uids->next->next->signatures->keyid))
569 	{
570 	  fprintf (stderr, "Unexpected key ID in third user ID sig: %s\n",
571 		   key->uids->next->next->signatures->keyid);
572 	  exit (1);
573 	}
574       if (strcmp (keys[i].uid[2].sig.name, key->uids->next->next->signatures->name))
575 	{
576 	  fprintf (stderr, "Unexpected name in third user ID sig: %s\n",
577 		   key->uids->next->next->signatures->name);
578 	  exit (1);
579 	}
580       if (strcmp (keys[i].uid[2].sig.comment, key->uids->next->next->signatures->comment))
581 	{
582 	  fprintf (stderr, "Unexpected comment in third user ID sig: %s\n",
583 		   key->uids->next->next->signatures->comment);
584 	  exit (1);
585 	}
586       if (strcmp (keys[i].uid[2].sig.email, key->uids->next->next->signatures->email))
587 	{
588 	  fprintf (stderr, "Unexpected email in third user ID sig: %s\n",
589 		   key->uids->next->next->signatures->email);
590 	  exit (1);
591 	}
592       if (keys[i].uid[2].sig.sig_class != key->uids->next->next->signatures->sig_class)
593 	{
594 	  fprintf (stderr, "Unexpected class in third user ID sig: %i\n",
595 		   key->uids->next->next->signatures->sig_class);
596 	  exit (1);
597 	}
598       if (keys[i].uid[2].sig.exportable != key->uids->next->next->signatures->exportable)
599 	{
600 	  fprintf (stderr, "Unexpected exportable stat in third user ID sig: %i\n",
601 		   key->uids->next->next->signatures->exportable);
602 	  exit (1);
603 	}
604 
605       gpgme_key_unref (key);
606       i++;
607     }
608   if (gpgme_err_code (err) != GPG_ERR_EOF)
609     fail_if_err (err);
610   err = gpgme_op_keylist_end (ctx);
611   fail_if_err (err);
612 
613   result = gpgme_op_keylist_result (ctx);
614   if (result->truncated)
615     {
616       fprintf (stderr, "Key listing unexpectedly truncated\n");
617       exit (1);
618     }
619 
620   if (keys[i].fpr)
621     {
622       fprintf (stderr, "Less keys returned than expected\n");
623       exit (1);
624     }
625 
626   gpgme_release (ctx);
627   return 0;
628 }
629