Coverage Report

Created: 2026-01-09 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/key-check.c
Line
Count
Source
1
/* key-check.c - Detect and fix various problems with keys
2
 * Copyright (C) 1998-2010 Free Software Foundation, Inc.
3
 * Copyright (C) 1998-2017 Werner Koch
4
 * Copyright (C) 2015-2018 g10 Code GmbH
5
 *
6
 * This file is part of GnuPG.
7
 *
8
 * GnuPG is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * GnuPG is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <config.h>
23
24
#include "gpg.h"
25
#include "options.h"
26
#include "packet.h"
27
#include "keydb.h"
28
#include "main.h"
29
#include "../common/ttyio.h"
30
#include "../common/i18n.h"
31
#include "keyedit.h"
32
33
#include "key-check.h"
34
35
36
/* Print PREFIX followed by TEXT.  With mode > 0 use log_info, with
37
 * mode < 0 use ttyio, else print to stdout.  If TEXT is not NULL, it
38
 * may be modified by this function.  */
39
static void
40
print_info (int mode, const char *prefix, char *text)
41
0
{
42
0
  char *p;
43
44
0
  if (!text)
45
0
    text = "";
46
0
  else if ((p = strchr (text,'\n')))
47
0
    *p = 0; /* Strip LF.  */
48
49
0
   if (mode > 0)
50
0
     log_info ("%s %s\n", prefix, text);
51
0
   else
52
0
     tty_fprintf (mode? NULL:es_stdout, "%s %s\n", prefix, text);
53
0
}
54
55
56
/* Order two signatures.  The actual ordering isn't important.  Our
57
 * goal is to ensure that identical signatures occur together.  */
58
static int
59
sig_comparison (const void *av, const void *bv)
60
0
{
61
0
  const KBNODE an = *(const KBNODE *) av;
62
0
  const KBNODE bn = *(const KBNODE *) bv;
63
0
  const PKT_signature *a;
64
0
  const PKT_signature *b;
65
0
  int ndataa;
66
0
  int ndatab;
67
0
  int i;
68
69
0
  log_assert (an->pkt->pkttype == PKT_SIGNATURE);
70
0
  log_assert (bn->pkt->pkttype == PKT_SIGNATURE);
71
72
0
  a = an->pkt->pkt.signature;
73
0
  b = bn->pkt->pkt.signature;
74
75
  /* Signatures with a different help counter are not identical for
76
   * our purpose.  */
77
0
  if (a->help_counter < b->help_counter)
78
0
    return -1;
79
0
  if (a->help_counter > b->help_counter)
80
0
    return 1;
81
82
0
  if (a->digest_algo < b->digest_algo)
83
0
    return -1;
84
0
  if (a->digest_algo > b->digest_algo)
85
0
    return 1;
86
87
0
  ndataa = pubkey_get_nsig (a->pubkey_algo);
88
0
  ndatab = pubkey_get_nsig (b->pubkey_algo);
89
0
  if (ndataa != ndatab)
90
0
    return (ndataa < ndatab)? -1 : 1;
91
92
0
  for (i = 0; i < ndataa; i ++)
93
0
    {
94
0
      int c = gcry_mpi_cmp (a->data[i], b->data[i]);
95
0
      if (c != 0)
96
0
        return c;
97
0
    }
98
99
  /* Okay, they are equal.  */
100
0
  return 0;
101
0
}
102
103
104
static gpg_error_t
105
remove_duplicate_sigs (kbnode_t kb, int *dups, int *modified)
106
0
{
107
0
  gpg_error_t err;
108
0
  kbnode_t n;
109
0
  int nsigs;
110
0
  kbnode_t *sigs;  /* Allocated array with the signature packet.  */
111
0
  int i;
112
0
  int last_i;
113
0
  int block;
114
0
  PKT_signature *sig;
115
116
  /* Count the sigs.  */
117
0
  for (nsigs = 0, n = kb; n; n = n->next)
118
0
    {
119
0
      if (is_deleted_kbnode (n))
120
0
        continue;
121
0
      else if (n->pkt->pkttype == PKT_SIGNATURE)
122
0
        nsigs ++;
123
0
    }
124
125
0
  if (!nsigs)
126
0
    return 0; /* No signatures at all.  */
127
128
  /* Add them all to the SIGS array.  */
129
0
  sigs = xtrycalloc (nsigs, sizeof *sigs);
130
0
  if (!sigs)
131
0
    {
132
0
      err = gpg_error_from_syserror ();
133
0
      log_error (_("error allocating memory: %s\n"), gpg_strerror (err));
134
0
      return err;
135
0
    }
136
137
0
  block = 0;
138
0
  i = 0;
139
0
  for (n = kb; n; n = n->next)
140
0
    {
141
0
      if (is_deleted_kbnode (n))
142
0
        continue;
143
144
0
      if (n->pkt->pkttype != PKT_SIGNATURE)
145
0
        {
146
0
          switch (n->pkt->pkttype)
147
0
            {
148
0
            case PKT_PUBLIC_SUBKEY:
149
0
            case PKT_SECRET_SUBKEY:
150
0
            case PKT_USER_ID:
151
0
            case PKT_ATTRIBUTE:
152
              /* Bump the block number so that we only consider
153
               * signatures below the same object as duplicates.  */
154
0
              block++;
155
0
              break;
156
0
            default:
157
0
              break;
158
0
            }
159
0
          continue;
160
0
        }
161
0
      sig = n->pkt->pkt.signature;
162
0
      sig->help_counter = block;
163
0
      sigs[i++] = n;
164
0
    }
165
0
  log_assert (i == nsigs);
166
167
0
  qsort (sigs, nsigs, sizeof (sigs[0]), sig_comparison);
168
169
0
  last_i = 0;
170
0
  for (i = 1; i < nsigs; i ++)
171
0
    {
172
0
      log_assert (sigs[last_i]);
173
0
      log_assert (sigs[last_i]->pkt->pkttype == PKT_SIGNATURE);
174
0
      log_assert (sigs[i]);
175
0
      log_assert (sigs[i]->pkt->pkttype == PKT_SIGNATURE);
176
177
0
      if (sig_comparison (&sigs[last_i], &sigs[i]) == 0)
178
0
        {
179
          /* They are the same.  Kill the latter.  */
180
0
          if (DBG_PACKET)
181
0
            {
182
0
              sig = sigs[i]->pkt->pkt.signature;
183
184
0
              log_debug ("Signature appears multiple times, "
185
0
                         "deleting duplicate:\n");
186
0
              log_debug ("  sig: class 0x%x, issuer: %s,"
187
0
                         " timestamp: %s (%lld), digest: %02x %02x\n",
188
0
                         sig->sig_class, keystr (sig->keyid),
189
0
                         isotimestamp (sig->timestamp),
190
0
                         (long long) sig->timestamp,
191
0
                         sig->digest_start[0], sig->digest_start[1]);
192
0
            }
193
194
          /* Remove sigs[i] from the keyblock.  */
195
0
          {
196
0
            kbnode_t z, *prevp;
197
0
            int to_kill = last_i;
198
0
            last_i = i;
199
200
0
            for (prevp = &kb, z = kb; z; prevp = &z->next, z = z->next)
201
0
              if (z == sigs[to_kill])
202
0
                break;
203
204
0
            *prevp = sigs[to_kill]->next;
205
206
0
            sigs[to_kill]->next = NULL;
207
0
            release_kbnode (sigs[to_kill]);
208
0
            sigs[to_kill] = NULL;
209
210
0
            ++*dups;
211
0
            *modified = 1;
212
0
          }
213
0
        }
214
0
      else
215
0
        last_i = i;
216
0
    }
217
218
0
  xfree (sigs);
219
0
  return 0;
220
0
}
221
222
223
/* Perform a few sanity checks on a keyblock is okay and possibly
224
 * repair some damage.  Concretely:
225
 *
226
 *   - Detect duplicate signatures and remove them.
227
 *
228
 *   - Detect out of order signatures and relocate them (e.g., a sig
229
 *     over user id X located under subkey Y).
230
 *
231
 * Note: this function does not remove signatures that don't belong or
232
 * components that are not signed!  (Although it would be trivial to
233
 * do so.)
234
 *
235
 * If ONLY_SELFSIGS is true, then this function only reorders self
236
 * signatures (it still checks all signatures for duplicates,
237
 * however).
238
 *
239
 * Allowed values for MODE are:
240
 *  -1 - print to the TTY
241
 *   0 - print to stdout
242
 *   1 - use log_info.
243
 *
244
 * Returns true if the keyblock was modified.  */
245
int
246
key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb,
247
                       int only_selected, int only_selfsigs)
248
0
{
249
0
  gpg_error_t err;
250
0
  PKT_public_key *pk;
251
0
  KBNODE n, n_next, *n_prevp, n2;
252
0
  char *pending_desc = NULL;
253
0
  PKT_public_key *issuer;
254
0
  KBNODE last_printed_component;
255
0
  KBNODE current_component = NULL;
256
0
  int dups = 0;
257
0
  int missing_issuer = 0;
258
0
  int reordered = 0;
259
0
  int bad_signature = 0;
260
0
  int missing_selfsig = 0;
261
0
  int modified = 0;
262
0
  PKT_signature *sig;
263
264
0
  (void)missing_selfsig;
265
0
  log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
266
0
  pk = kb->pkt->pkt.public_key;
267
268
  /* First we look for duplicates.  */
269
0
  if (remove_duplicate_sigs (kb, &dups, &modified))
270
0
    goto leave;  /* Error */
271
272
  /* Now make sure the sigs occur after the component (aka block)
273
   * (public key, subkey, user id) that they sign.  */
274
0
  issuer = NULL;
275
0
  last_printed_component = NULL;
276
0
  for (n_prevp = &kb, n = kb;
277
0
       n;
278
       /* If we moved n, then n_prevp is need valid.  */
279
0
       n_prevp = (n->next == n_next ? &n->next : n_prevp), n = n_next)
280
0
    {
281
0
      PACKET *p;
282
0
      int processed_current_component;
283
0
      int rc;
284
0
      int dump_sig_params = 0;
285
286
0
      n_next = n->next;
287
288
0
      if (is_deleted_kbnode (n))
289
0
        continue;
290
291
0
      p = n->pkt;
292
293
0
      if (issuer && issuer != pk)
294
0
        {
295
0
          free_public_key (issuer);
296
0
          issuer = NULL;
297
0
        }
298
299
0
      xfree (pending_desc);
300
0
      pending_desc = NULL;
301
302
0
      switch (p->pkttype)
303
0
        {
304
0
        case PKT_PUBLIC_KEY:
305
0
          log_assert (p->pkt.public_key == pk);
306
0
          if (only_selected && ! (n->flag & NODFLG_SELKEY))
307
0
            {
308
0
              current_component = NULL;
309
0
              break;
310
0
            }
311
312
0
          if (DBG_PACKET)
313
0
            log_debug ("public key %s: timestamp: %s (%lld)\n",
314
0
                       pk_keyid_str (pk),
315
0
                       isotimestamp (pk->timestamp),
316
0
                       (long long) pk->timestamp);
317
0
          current_component = n;
318
0
          break;
319
0
        case PKT_PUBLIC_SUBKEY:
320
0
          if (only_selected && ! (n->flag & NODFLG_SELKEY))
321
0
            {
322
0
              current_component = NULL;
323
0
              break;
324
0
            }
325
326
0
          if (DBG_PACKET)
327
0
            log_debug ("subkey %s: timestamp: %s (%lld)\n",
328
0
                       pk_keyid_str (p->pkt.public_key),
329
0
                       isotimestamp (p->pkt.public_key->timestamp),
330
0
                       (long long) p->pkt.public_key->timestamp);
331
0
          current_component = n;
332
0
          break;
333
0
        case PKT_USER_ID:
334
0
          if (only_selected && ! (n->flag & NODFLG_SELUID))
335
0
            {
336
0
              current_component = NULL;
337
0
              break;
338
0
            }
339
340
0
          if (DBG_PACKET)
341
0
            log_debug ("user id: %s\n",
342
0
                       p->pkt.user_id->attrib_data
343
0
                       ? "[ photo id ]"
344
0
                       : p->pkt.user_id->name);
345
0
          current_component = n;
346
0
          break;
347
0
        case PKT_SIGNATURE:
348
0
          if (! current_component)
349
            /* The current component is not selected, don't check the
350
               sigs under it.  */
351
0
            break;
352
353
0
          sig = n->pkt->pkt.signature;
354
355
0
          pending_desc = xasprintf ("  sig: class: 0x%x, issuer: %s,"
356
0
                                    " timestamp: %s (%lld), digest: %02x %02x",
357
0
                                    sig->sig_class,
358
0
                                    keystr (sig->keyid),
359
0
                                    isotimestamp (sig->timestamp),
360
0
                                    (long long) sig->timestamp,
361
0
                                    sig->digest_start[0], sig->digest_start[1]);
362
363
364
0
          if (keyid_cmp (pk_keyid (pk), sig->keyid) == 0)
365
0
            issuer = pk;
366
0
          else /* Issuer is a different key.  */
367
0
            {
368
0
              if (only_selfsigs)
369
0
                continue;
370
371
0
              issuer = xtrycalloc (1, sizeof *issuer);
372
0
              if (!issuer)
373
0
                err = gpg_error_from_syserror ();
374
0
              else
375
0
                err = get_pubkey (ctrl, issuer, sig->keyid);
376
0
              if (err)
377
0
                {
378
0
                  xfree (issuer);
379
0
                  issuer = NULL;
380
0
                  if (DBG_PACKET)
381
0
                    {
382
0
                      if (pending_desc)
383
0
                        log_debug ("%s", pending_desc);
384
0
                      log_debug ("    Can't check signature allegedly"
385
0
                                 " issued by %s: %s\n",
386
0
                                 keystr (sig->keyid), gpg_strerror (err));
387
0
                    }
388
0
                  missing_issuer ++;
389
0
                  break;
390
0
                }
391
0
            }
392
393
0
          if ((err = openpgp_pk_test_algo (sig->pubkey_algo)))
394
0
            {
395
0
              if (DBG_PACKET && pending_desc)
396
0
                log_debug ("%s", pending_desc);
397
0
              log_info (_("can't check signature with unsupported"
398
0
                          " public-key algorithm (%d): %s.\n"),
399
0
                          sig->pubkey_algo, gpg_strerror (err));
400
0
              break;
401
0
            }
402
0
          if ((err = openpgp_md_test_algo (sig->digest_algo)))
403
0
            {
404
0
              if (DBG_PACKET && pending_desc)
405
0
                log_debug ("%s", pending_desc);
406
0
              log_info (_("can't check signature with unsupported"
407
0
                          " message-digest algorithm %d: %s.\n"),
408
0
                          sig->digest_algo, gpg_strerror (err));
409
0
              break;
410
0
            }
411
412
          /* We iterate over the keyblock.  Most likely, the matching
413
             component is the current component so always try that
414
             first.  */
415
0
          processed_current_component = 0;
416
0
          for (n2 = current_component;
417
0
               n2;
418
0
               n2 = (processed_current_component ? n2->next : kb),
419
0
                 processed_current_component = 1)
420
0
            if (is_deleted_kbnode (n2))
421
0
              continue;
422
0
            else if (processed_current_component && n2 == current_component)
423
              /* Don't process it twice.  */
424
0
              continue;
425
0
            else
426
0
              {
427
0
                err = check_signature_over_key_or_uid (ctrl,
428
0
                                                       issuer, sig, kb, n2->pkt,
429
0
                                                       NULL, NULL);
430
0
                if (! err)
431
0
                  break;
432
0
              }
433
434
          /* n/sig is a signature and n2 is the component (public key,
435
             subkey or user id) that it signs, if any.
436
             current_component is that component that it appears to
437
             apply to (according to the ordering).  */
438
439
0
          if (current_component == n2)
440
0
            {
441
0
              if (DBG_PACKET)
442
0
                {
443
0
                  log_debug ("%s", pending_desc);
444
0
                  log_debug ("    Good signature over last key or uid!\n");
445
0
                }
446
447
0
              rc = 0;
448
0
            }
449
0
          else if (n2)
450
0
            {
451
0
              log_assert (n2->pkt->pkttype == PKT_USER_ID
452
0
                          || n2->pkt->pkttype == PKT_PUBLIC_KEY
453
0
                          || n2->pkt->pkttype == PKT_PUBLIC_SUBKEY);
454
455
0
              if (DBG_PACKET)
456
0
                {
457
0
                  log_debug ("%s", pending_desc);
458
0
                  log_debug ("    Good signature out of order!"
459
0
                             "  (Over %s (%d) '%s')\n",
460
0
                             n2->pkt->pkttype == PKT_USER_ID
461
0
                             ? "user id"
462
0
                             : n2->pkt->pkttype == PKT_PUBLIC_SUBKEY
463
0
                             ? "subkey"
464
0
                             : "primary key",
465
0
                             n2->pkt->pkttype,
466
0
                             n2->pkt->pkttype == PKT_USER_ID
467
0
                             ? n2->pkt->pkt.user_id->name
468
0
                             : pk_keyid_str (n2->pkt->pkt.public_key));
469
0
                }
470
471
              /* Reorder the packets: move the signature n to be just
472
                 after n2.  */
473
474
              /* Unlink the signature.  */
475
0
              log_assert (n_prevp);
476
0
              *n_prevp = n->next;
477
478
              /* Insert the sig immediately after the component.  */
479
0
              n->next = n2->next;
480
0
              n2->next = n;
481
482
0
              reordered ++;
483
0
              modified = 1;
484
485
0
              rc = 0;
486
0
            }
487
0
          else
488
0
            {
489
0
              if (DBG_PACKET)
490
0
                {
491
0
                  log_debug ("%s", pending_desc);
492
0
                  log_debug ("    Bad signature.\n");
493
0
                }
494
495
0
              if (DBG_PACKET)
496
0
                dump_sig_params = 1;
497
498
0
              bad_signature ++;
499
500
0
              rc = GPG_ERR_BAD_SIGNATURE;
501
0
            }
502
503
          /* We don't cache the result here, because we haven't
504
             completely checked that the signature is legitimate.  For
505
             instance, if we have a revocation certificate on Alice's
506
             key signed by Bob, the signature may be good, but we
507
             haven't checked that Bob is a designated revoker.  */
508
          /* cache_sig_result (sig, rc); */
509
510
0
          {
511
0
            int has_selfsig = 0;
512
0
            if (! rc && issuer == pk)
513
0
              {
514
0
                if (n2->pkt->pkttype == PKT_PUBLIC_KEY
515
0
                    && (/* Direct key signature.  */
516
0
                        sig->sig_class == 0x1f
517
                        /* Key revocation signature.  */
518
0
                        || sig->sig_class == 0x20))
519
0
                  has_selfsig = 1;
520
0
                if (n2->pkt->pkttype == PKT_PUBLIC_SUBKEY
521
0
                    && (/* Subkey binding sig.  */
522
0
                        sig->sig_class == 0x18
523
                        /* Subkey revocation sig.  */
524
0
                        || sig->sig_class == 0x28))
525
0
                  has_selfsig = 1;
526
0
                if (n2->pkt->pkttype == PKT_USER_ID
527
0
                    && (/* Certification sigs.  */
528
0
                        sig->sig_class == 0x10
529
0
                        || sig->sig_class == 0x11
530
0
                        || sig->sig_class == 0x12
531
0
                        || sig->sig_class == 0x13
532
                        /* Certification revocation sig.  */
533
0
                        || sig->sig_class == 0x30))
534
0
                  has_selfsig = 1;
535
0
              }
536
537
0
            if (DBG_PACKET
538
0
                && ((n2 && n2 != last_printed_component)
539
0
                    || (! n2 && last_printed_component != current_component)))
540
0
              {
541
0
                int is_reordered = n2 && n2 != current_component;
542
0
                if (n2)
543
0
                  last_printed_component = n2;
544
0
                else
545
0
                  last_printed_component = current_component;
546
547
0
                if (!modified)
548
0
                  ;
549
0
                else if (last_printed_component->pkt->pkttype == PKT_USER_ID)
550
0
                  {
551
0
                    log_debug ("uid  ");
552
0
                    print_utf8_buffer (log_get_stream (),
553
0
                                       last_printed_component
554
0
                                       ->pkt->pkt.user_id->name,
555
0
                                       last_printed_component
556
0
                                       ->pkt->pkt.user_id->len);
557
0
                    log_flush ();
558
0
                  }
559
0
                else if (last_printed_component->pkt->pkttype
560
0
                         == PKT_PUBLIC_KEY)
561
0
                  log_debug ("pub  %s\n",
562
0
                             pk_keyid_str (last_printed_component
563
0
                                             ->pkt->pkt.public_key));
564
0
                else
565
0
                  log_debug ("sub  %s\n",
566
0
                             pk_keyid_str (last_printed_component
567
0
                                           ->pkt->pkt.public_key));
568
569
0
                if (modified)
570
0
                  {
571
0
                    if (is_reordered)
572
0
                      log_debug ("%s\n", _(" (reordered signatures follow)"));
573
0
                  }
574
0
              }
575
576
0
            if (DBG_PACKET && modified)
577
0
              keyedit_print_one_sig (ctrl, log_get_stream (),
578
0
                                     rc, kb, n, NULL, NULL, NULL,
579
0
             has_selfsig, 0, only_selfsigs);
580
0
          }
581
582
0
          if (dump_sig_params)
583
0
            {
584
0
              int i;
585
586
0
              for (i = 0; i < pubkey_get_nsig (sig->pubkey_algo); i ++)
587
0
                {
588
0
                  char buffer[1024];
589
0
                  size_t len;
590
0
                  char *printable;
591
0
                  if (gcry_mpi_get_flag (sig->data[i], GCRYMPI_FLAG_OPAQUE))
592
0
                    {
593
0
                      const byte *sigdata;
594
0
                      unsigned int nbits;
595
596
0
                      sigdata = gcry_mpi_get_opaque (sig->data[i], &nbits);
597
0
                      len = (nbits+7)/8;
598
0
                      memcpy (buffer, sigdata, len);
599
0
                    }
600
0
                  else
601
0
                    gcry_mpi_print (GCRYMPI_FMT_USG,
602
0
                                    buffer, sizeof (buffer), &len,
603
0
                                    sig->data[i]);
604
0
                  printable = bin2hex (buffer, len, NULL);
605
0
                  log_debug ("        %d: %s\n", i, printable);
606
0
                  xfree (printable);
607
0
                }
608
0
            }
609
0
          break;
610
0
        default:
611
0
          if (DBG_PACKET)
612
0
            log_debug ("unhandled packet: %d\n", p->pkttype);
613
0
          break;
614
0
        }
615
0
    }
616
617
0
  xfree (pending_desc);
618
0
  pending_desc = NULL;
619
620
0
  if (issuer != pk)
621
0
    free_public_key (issuer);
622
0
  issuer = NULL;
623
624
  /* If we reordered signatures we need to de-duplicate again because
625
   * a signature can now be a duplicate in another block.  */
626
0
  if (reordered)
627
0
    {
628
0
      if (remove_duplicate_sigs (kb, &dups, &modified))
629
0
        goto leave;
630
0
    }
631
632
  /* Identify keys / uids that don't have a self-sig.  */
633
0
  {
634
0
    int has_selfsig = 0;
635
0
    PACKET *p;
636
637
0
    current_component = NULL;
638
0
    for (n = kb; n; n = n->next)
639
0
      {
640
0
        if (is_deleted_kbnode (n))
641
0
          continue;
642
643
0
        p = n->pkt;
644
645
0
        switch (p->pkttype)
646
0
          {
647
0
          case PKT_PUBLIC_KEY:
648
0
          case PKT_PUBLIC_SUBKEY:
649
0
          case PKT_USER_ID:
650
0
            if (current_component && ! has_selfsig)
651
0
              missing_selfsig ++;
652
0
            current_component = n;
653
0
            has_selfsig = 0;
654
0
            break;
655
656
0
          case PKT_SIGNATURE:
657
0
            if (! current_component || has_selfsig)
658
0
              break;
659
660
0
            sig = n->pkt->pkt.signature;
661
662
0
            if (! (sig->flags.checked && sig->flags.valid))
663
0
              break;
664
665
0
            if (keyid_cmp (pk_keyid (pk), sig->keyid) != 0)
666
              /* Different issuer, couldn't be a self-sig.  */
667
0
              break;
668
669
0
            if (current_component->pkt->pkttype == PKT_PUBLIC_KEY
670
0
                && (/* Direct key signature.  */
671
0
                    sig->sig_class == 0x1f
672
                    /* Key revocation signature.  */
673
0
                    || sig->sig_class == 0x20))
674
0
              has_selfsig = 1;
675
0
            if (current_component->pkt->pkttype == PKT_PUBLIC_SUBKEY
676
0
                && (/* Subkey binding sig.  */
677
0
                    sig->sig_class == 0x18
678
                    /* Subkey revocation sig.  */
679
0
                    || sig->sig_class == 0x28))
680
0
              has_selfsig = 1;
681
0
            if (current_component->pkt->pkttype == PKT_USER_ID
682
0
                && (/* Certification sigs.  */
683
0
                    sig->sig_class == 0x10
684
0
                    || sig->sig_class == 0x11
685
0
                    || sig->sig_class == 0x12
686
0
                    || sig->sig_class == 0x13
687
                    /* Certification revocation sig.  */
688
0
                    || sig->sig_class == 0x30))
689
0
              has_selfsig = 1;
690
691
0
            break;
692
693
0
          default:
694
0
            if (current_component && ! has_selfsig)
695
0
              missing_selfsig ++;
696
0
            current_component = NULL;
697
0
          }
698
0
      }
699
0
  }
700
701
702
0
 leave:
703
0
  if (!opt.quiet)
704
0
    {
705
0
      char prefix[100];
706
0
      char *p;
707
708
      /* To avoid string changes in 2.2 we strip the LF here. */
709
0
      snprintf (prefix, sizeof prefix, _("key %s:\n"), pk_keyid_str (pk));
710
0
      p = strrchr (prefix, '\n');
711
0
      if (p)
712
0
        *p = 0;
713
714
0
      if (dups)
715
0
        {
716
0
          p = xtryasprintf
717
0
            (ngettext ("%d duplicate signature removed\n",
718
0
                       "%d duplicate signatures removed\n", dups), dups);
719
0
          print_info (mode, prefix, p);
720
0
          xfree (p);
721
0
        }
722
723
0
      if (missing_issuer)
724
0
        {
725
0
          p = xtryasprintf
726
0
            (ngettext ("%d signature not checked due to a missing key\n",
727
0
                       "%d signatures not checked due to missing keys\n",
728
0
                       missing_issuer), missing_issuer);
729
0
          print_info (mode, prefix, p);
730
0
          xfree (p);
731
0
        }
732
0
      if (bad_signature)
733
0
        {
734
0
          p = xtryasprintf (ngettext ("%d bad signature\n",
735
0
                                      "%d bad signatures\n",
736
0
                                      bad_signature), bad_signature);
737
0
          print_info (mode, prefix, p);
738
0
          xfree (p);
739
0
        }
740
741
0
      if (reordered)
742
0
        {
743
0
          p = xtryasprintf (ngettext ("%d signature reordered\n",
744
0
                                      "%d signatures reordered\n",
745
0
                                      reordered), reordered);
746
0
          print_info (mode, prefix, p);
747
0
          xfree (p);
748
0
        }
749
750
0
      if (only_selfsigs && (bad_signature || reordered))
751
0
        {
752
0
          p = xtryasprintf
753
0
            (_("Warning: errors found and only checked self-signatures,"
754
0
               " run '%s' to check all signatures.\n"), "check");
755
0
          print_info (mode, prefix, p);
756
0
          xfree (p);
757
0
        }
758
0
    }
759
760
0
  return modified;
761
0
}