Coverage Report

Created: 2026-01-09 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/key-clean.c
Line
Count
Source
1
/* key-clean.c - Functions to clean a keyblock
2
 * Copyright (C) 1998-2008, 2010-2011 Free Software Foundation, Inc.
3
 * Copyright (C) 2014, 2016-2018  Werner Koch
4
 *
5
 * This file is part of GnuPG.
6
 *
7
 * GnuPG is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * GnuPG is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19
 * SPDX-License-Identifier: GPL-3.0-or-later
20
 */
21
22
#include <config.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include "gpg.h"
28
#include "keydb.h"
29
#include "../common/util.h"
30
#include "../common/host2net.h"
31
#include "../common/i18n.h"
32
#include "options.h"
33
#include "packet.h"
34
#include "main.h"
35
#include "key-clean.h"
36
37
38
0
#define NF_USABLE     8  /* Usable signature and not a revocation.    */
39
0
#define NF_CONSIDER   9  /* Internal use.  */
40
0
#define NF_PROCESSED 10  /* Internal use.  */
41
0
#define NF_REVOC     11  /* Usable revocation.   */
42
0
#define NF_NOKEY     12  /* Key not available.   */
43
44
/*
45
 * Mark the signature of the given UID which are used to certify it.
46
 * To do this, we first remove all signatures which are not valid and
47
 * from the remaining we look for the latest one.  If this is not a
48
 * certification revocation signature we mark the signature by setting
49
 * node flag bit NF_USABLE.  Revocations are marked with NF_REVOC, and
50
 * sigs from unavailable keys are marked with NF_NOKEY.
51
 */
52
void
53
mark_usable_uid_certs (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
54
                       u32 *main_kid, struct key_item *klist,
55
                       u32 curtime, u32 *next_expire)
56
0
{
57
0
  kbnode_t node;
58
0
  PKT_signature *sig;
59
60
  /* First check all signatures.  */
61
0
  for (node=uidnode->next; node; node = node->next)
62
0
    {
63
0
      int rc;
64
65
0
      node->flag &= ~(1<<NF_USABLE | 1<<NF_CONSIDER
66
0
                      | 1<<NF_PROCESSED | 1<<NF_REVOC | 1<<NF_NOKEY);
67
0
      if (node->pkt->pkttype == PKT_USER_ID
68
0
          || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
69
0
          || node->pkt->pkttype == PKT_SECRET_SUBKEY)
70
0
        break; /* ready */
71
0
      if (node->pkt->pkttype != PKT_SIGNATURE)
72
0
        continue;
73
0
      sig = node->pkt->pkt.signature;
74
0
      if (main_kid
75
0
    && sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1])
76
0
        continue; /* ignore self-signatures if we pass in a main_kid */
77
0
      if (!IS_UID_SIG(sig) && !IS_UID_REV(sig))
78
0
        continue; /* we only look at these signature classes */
79
0
      if(sig->sig_class>=0x11 && sig->sig_class<=0x13 &&
80
0
   sig->sig_class-0x10<opt.min_cert_level)
81
0
  continue; /* treat anything under our min_cert_level as an
82
         invalid signature */
83
0
      if (klist && !is_in_klist (klist, sig))
84
0
        continue;  /* no need to check it then */
85
0
      if ((rc=check_key_signature (ctrl, keyblock, node, NULL)))
86
0
  {
87
    /* we ignore anything that won't verify, but tag the
88
       no_pubkey case */
89
0
    if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY)
90
0
            node->flag |= 1<<NF_NOKEY;
91
0
          continue;
92
0
        }
93
0
      node->flag |= 1<<NF_CONSIDER;
94
95
0
    }
96
  /* Reset the remaining flags. */
97
0
  for (; node; node = node->next)
98
0
    node->flag &= ~(1<<NF_USABLE | 1<<NF_CONSIDER
99
0
                    | 1<<NF_PROCESSED | 1<<NF_REVOC | 1<<NF_NOKEY);
100
101
  /* kbnode flag usage: bit NF_CONSIDER is here set for signatures to consider,
102
   * bit NF_PROCESSED will be set by the loop to keep track of keyIDs already
103
   * processed, bit NF_USABLE will be set for the usable signatures, and bit
104
   * NF_REVOC will be set for usable revocations. */
105
106
  /* For each cert figure out the latest valid one.  */
107
0
  for (node=uidnode->next; node; node = node->next)
108
0
    {
109
0
      KBNODE n, signode;
110
0
      u32 kid[2];
111
0
      u32 sigdate;
112
113
0
      if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
114
0
          || node->pkt->pkttype == PKT_SECRET_SUBKEY)
115
0
        break;
116
0
      if ( !(node->flag & (1<<NF_CONSIDER)) )
117
0
        continue; /* not a node to look at */
118
0
      if ( (node->flag & (1<<NF_PROCESSED)) )
119
0
        continue; /* signature with a keyID already processed */
120
0
      node->flag |= (1<<NF_PROCESSED); /* mark this node as processed */
121
0
      sig = node->pkt->pkt.signature;
122
0
      signode = node;
123
0
      sigdate = sig->timestamp;
124
0
      kid[0] = sig->keyid[0]; kid[1] = sig->keyid[1];
125
126
      /* Now find the latest and greatest signature */
127
0
      for (n=uidnode->next; n; n = n->next)
128
0
        {
129
0
          if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY
130
0
              || n->pkt->pkttype == PKT_SECRET_SUBKEY)
131
0
            break;
132
0
          if ( !(n->flag & (1<<NF_CONSIDER)) )
133
0
            continue;
134
0
          if ( (n->flag & (1<<NF_PROCESSED)) )
135
0
            continue; /* shortcut already processed signatures */
136
0
          sig = n->pkt->pkt.signature;
137
0
          if (kid[0] != sig->keyid[0] || kid[1] != sig->keyid[1])
138
0
            continue;
139
0
          n->flag |= (1<<NF_PROCESSED); /* mark this node as processed */
140
141
    /* If signode is nonrevocable and unexpired and n isn't,
142
             then take signode (skip).  It doesn't matter which is
143
             older: if signode was older then we don't want to take n
144
             as signode is nonrevocable.  If n was older then we're
145
             automatically fine. */
146
147
0
    if(((IS_UID_SIG(signode->pkt->pkt.signature) &&
148
0
         !signode->pkt->pkt.signature->flags.revocable &&
149
0
         (signode->pkt->pkt.signature->expiredate==0 ||
150
0
    signode->pkt->pkt.signature->expiredate>curtime))) &&
151
0
       (!(IS_UID_SIG(n->pkt->pkt.signature) &&
152
0
    !n->pkt->pkt.signature->flags.revocable &&
153
0
    (n->pkt->pkt.signature->expiredate==0 ||
154
0
     n->pkt->pkt.signature->expiredate>curtime))))
155
0
      continue;
156
157
    /* If n is nonrevocable and unexpired and signode isn't,
158
             then take n.  Again, it doesn't matter which is older: if
159
             n was older then we don't want to take signode as n is
160
             nonrevocable.  If signode was older then we're
161
             automatically fine. */
162
163
0
    if((!(IS_UID_SIG(signode->pkt->pkt.signature) &&
164
0
    !signode->pkt->pkt.signature->flags.revocable &&
165
0
    (signode->pkt->pkt.signature->expiredate==0 ||
166
0
     signode->pkt->pkt.signature->expiredate>curtime))) &&
167
0
       ((IS_UID_SIG(n->pkt->pkt.signature) &&
168
0
         !n->pkt->pkt.signature->flags.revocable &&
169
0
         (n->pkt->pkt.signature->expiredate==0 ||
170
0
    n->pkt->pkt.signature->expiredate>curtime))))
171
0
            {
172
0
              signode = n;
173
0
              sigdate = sig->timestamp;
174
0
        continue;
175
0
            }
176
177
    /* At this point, if it's newer, it goes in as the only
178
             remaining possibilities are signode and n are both either
179
             revocable or expired or both nonrevocable and unexpired.
180
             If the timestamps are equal take the later ordered
181
             packet, presuming that the key packets are hopefully in
182
             their original order. */
183
184
0
          if (sig->timestamp >= sigdate)
185
0
            {
186
0
              signode = n;
187
0
              sigdate = sig->timestamp;
188
0
            }
189
0
        }
190
191
0
      sig = signode->pkt->pkt.signature;
192
0
      if (IS_UID_SIG (sig))
193
0
        { /* this seems to be a usable one which is not revoked.
194
           * Just need to check whether there is an expiration time,
195
           * We do the expired certification after finding a suitable
196
           * certification, the assumption is that a signator does not
197
           * want that after the expiration of his certificate the
198
           * system falls back to an older certification which has a
199
           * different expiration time */
200
0
          const byte *p;
201
0
          u32 expire;
202
203
0
          p = parse_sig_subpkt (sig, 1, SIGSUBPKT_SIG_EXPIRE, NULL );
204
0
          expire = p? sig->timestamp + buf32_to_u32(p) : 0;
205
206
0
          if (expire==0 || expire > curtime )
207
0
            {
208
0
              signode->flag |= (1<<NF_USABLE); /* yeah, found a good cert */
209
0
              if (next_expire && expire && expire < *next_expire)
210
0
                *next_expire = expire;
211
0
            }
212
0
        }
213
0
      else
214
0
  signode->flag |= (1<<NF_REVOC);
215
0
    }
216
0
}
217
218
219
/* Return true if the signature at NODE has is from a key specified by
220
 * the --trusted-key option and is exportable.  */
221
static int
222
is_trusted_key_sig (kbnode_t node)
223
0
{
224
0
  if (!node->pkt->pkt.signature->flags.exportable)
225
0
    return 0;
226
  /* Not yet implemented.  */
227
0
  return 0;
228
0
}
229
230
231
/* Note: OPTIONS are from the EXPORT_* set. */
232
static int
233
clean_sigs_from_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
234
                     int noisy, unsigned int options)
235
0
{
236
0
  int deleted = 0;
237
0
  kbnode_t node;
238
0
  u32 keyid[2];
239
240
0
  log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
241
0
              || keyblock->pkt->pkttype == PKT_SECRET_KEY);
242
243
0
  keyid_from_pk (keyblock->pkt->pkt.public_key, keyid);
244
245
  /* Passing in a 0 for current time here means that we'll never weed
246
     out an expired sig.  This is correct behavior since we want to
247
     keep the most recent expired sig in a series. */
248
0
  mark_usable_uid_certs (ctrl, keyblock, uidnode, NULL, NULL, 0, NULL);
249
250
  /* What we want to do here is remove signatures that are not
251
     considered as part of the trust calculations.  Thus, all invalid
252
     signatures are out, as are any signatures that aren't the last of
253
     a series of uid sigs or revocations It breaks down like this:
254
     coming out of mark_usable_uid_certs, if a sig is unflagged, it is
255
     not even a candidate.  If a sig has flag NF_CONSIDER or
256
     NF_PROCESSED, that means it was selected as a candidate and
257
     vetted.  If a sig has flag NF_USABLE it is a usable signature.
258
     If a sig has flag NF_REVOC it is a usable revocation.  If a sig
259
     has flag NF_NOKEY it was issued by an unavailable key.  "Usable"
260
     here means the most recent valid signature/revocation in a series
261
     from a particular signer.
262
263
     Delete everything that isn't a usable uid sig (which might be
264
     expired), a usable revocation, or a sig from an unavailable
265
     key. */
266
267
0
  for (node=uidnode->next;
268
0
       node && node->pkt->pkttype==PKT_SIGNATURE;
269
0
       node=node->next)
270
0
    {
271
0
      int keep;
272
273
0
      if ((options & EXPORT_REALCLEAN))
274
0
        keep = ((node->pkt->pkt.signature->keyid[0] == keyid[0]
275
0
                 && node->pkt->pkt.signature->keyid[1] == keyid[1])
276
0
                || is_trusted_key_sig (node));
277
0
      else if ((options & EXPORT_MINIMAL))
278
0
        keep = (node->pkt->pkt.signature->keyid[0] == keyid[0]
279
0
                && node->pkt->pkt.signature->keyid[1] == keyid[1]);
280
0
      else
281
0
        keep = 1;
282
283
      /* Keep usable uid sigs ... */
284
0
      if ((node->flag & (1<<NF_USABLE)) && keep)
285
0
  continue;
286
287
      /* ... and usable revocations... */
288
0
      if ((node->flag & (1<<NF_REVOC)) && keep)
289
0
  continue;
290
291
      /* ... and sigs from unavailable keys. */
292
      /* disabled for now since more people seem to want sigs from
293
   unavailable keys removed altogether.  */
294
      /*
295
  if(node->flag & (1<<NF_NOKEY))
296
  continue;
297
      */
298
299
      /* Everything else we delete */
300
301
      /* At this point, if NF_NOKEY is set, the signing key was
302
       * unavailable.  If NF_CONSIDER or NF_PROCESSED is set, it's
303
       * superseded.  Otherwise, it's invalid.  */
304
305
0
      if (noisy)
306
0
  log_info ("removing signature from key %s on user ID \"%s\": %s\n",
307
0
                  keystr (node->pkt->pkt.signature->keyid),
308
0
                  uidnode->pkt->pkt.user_id->name,
309
0
                  node->flag&(1<<NF_NOKEY)?    "key unavailable":
310
0
                  node->flag&(1<<NF_CONSIDER)? "signature superseded"
311
0
                  /* */                      : "invalid signature"  );
312
313
0
      delete_kbnode (node);
314
0
      deleted++;
315
0
    }
316
317
0
  return deleted;
318
0
}
319
320
321
/* This is substantially easier than clean_sigs_from_uid since we just
322
   have to establish if the uid has a valid self-sig, is not revoked,
323
   and is not expired.  Note that this does not take into account
324
   whether the uid has a trust path to it - just whether the keyholder
325
   themselves has certified the uid.  Returns true if the uid was
326
   compacted.  To "compact" a user ID, we simply remove ALL signatures
327
   except the self-sig that caused the user ID to be remove-worthy.
328
   We don't actually remove the user ID packet itself since it might
329
   be resurrected in a later merge.  Note that this function requires
330
   that the caller has already done a merge_keys_and_selfsig().
331
332
   TODO: change the import code to allow importing a uid with only a
333
   revocation if the uid already exists on the keyring. */
334
335
static int
336
clean_uid_from_key (kbnode_t keyblock, kbnode_t uidnode, int noisy)
337
0
{
338
0
  kbnode_t node;
339
0
  PKT_user_id *uid = uidnode->pkt->pkt.user_id;
340
0
  int deleted = 0;
341
342
0
  log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
343
0
              || keyblock->pkt->pkttype == PKT_SECRET_KEY);
344
0
  log_assert (uidnode->pkt->pkttype==PKT_USER_ID);
345
346
  /* Skip valid user IDs, compacted user IDs, and non-self-signed user
347
     IDs if --allow-non-selfsigned-uid is set. */
348
0
  if (uid->created
349
0
      || uid->flags.compacted
350
0
      || (!uid->flags.expired && !uid->flags.revoked && opt.allow_non_selfsigned_uid))
351
0
    return 0;
352
353
0
  for (node=uidnode->next;
354
0
       node && node->pkt->pkttype == PKT_SIGNATURE;
355
0
      node=node->next)
356
0
    {
357
0
      if (!node->pkt->pkt.signature->flags.chosen_selfsig)
358
0
        {
359
0
          delete_kbnode (node);
360
0
          deleted = 1;
361
0
          uidnode->pkt->pkt.user_id->flags.compacted = 1;
362
0
        }
363
0
    }
364
365
0
  if (noisy)
366
0
    {
367
0
      const char *reason;
368
0
      char *user = utf8_to_native (uid->name, uid->len, 0);
369
370
0
      if (uid->flags.revoked)
371
0
  reason = _("revoked");
372
0
      else if (uid->flags.expired)
373
0
  reason = _("expired");
374
0
      else
375
0
  reason = _("invalid");
376
377
0
      log_info ("compacting user ID \"%s\" on key %s: %s\n",
378
0
                user, keystr_from_pk (keyblock->pkt->pkt.public_key),
379
0
                reason);
380
381
0
      xfree (user);
382
0
    }
383
384
0
  return deleted;
385
0
}
386
387
388
/* Needs to be called after a merge_keys_and_selfsig().
389
 * Note: OPTIONS are from the EXPORT_* set.  */
390
void
391
clean_one_uid (ctrl_t ctrl, kbnode_t keyblock, kbnode_t uidnode,
392
               int noisy, unsigned int options,
393
               int *uids_cleaned, int *sigs_cleaned)
394
0
{
395
0
  int dummy = 0;
396
397
0
  log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
398
0
              || keyblock->pkt->pkttype == PKT_SECRET_KEY);
399
0
  log_assert (uidnode->pkt->pkttype==PKT_USER_ID);
400
401
0
  if (!uids_cleaned)
402
0
    uids_cleaned = &dummy;
403
404
0
  if (!sigs_cleaned)
405
0
    sigs_cleaned = &dummy;
406
407
  /* Do clean_uid_from_key first since if it fires off, we don't have
408
     to bother with the other.  */
409
0
  *uids_cleaned += clean_uid_from_key (keyblock, uidnode, noisy);
410
0
  if (!uidnode->pkt->pkt.user_id->flags.compacted)
411
0
    *sigs_cleaned += clean_sigs_from_uid (ctrl, keyblock, uidnode,
412
0
                                          noisy, options);
413
0
}
414
415
416
/* NB: This function marks the deleted nodes only and the caller is
417
 * responsible to skip or remove them.  Needs to be called after a
418
 * merge_keys_and_selfsig.  Note: OPTIONS are from the EXPORT_* set. */
419
void
420
clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, unsigned int options,
421
                int *uids_cleaned, int *sigs_cleaned)
422
0
{
423
0
  kbnode_t node;
424
425
0
  for (node = keyblock->next;
426
0
       node && !(node->pkt->pkttype == PKT_PUBLIC_SUBKEY
427
0
                    || node->pkt->pkttype == PKT_SECRET_SUBKEY);
428
0
       node = node->next)
429
0
    {
430
0
      if (node->pkt->pkttype == PKT_USER_ID)
431
0
        clean_one_uid (ctrl, keyblock, node, noisy, options,
432
0
                       uids_cleaned, sigs_cleaned);
433
0
    }
434
435
  /* Remove bogus subkey binding signatures: The only signatures
436
   * allowed are of class 0x18 and 0x28.  */
437
0
  log_assert (!node || (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
438
0
                        || node->pkt->pkttype == PKT_SECRET_SUBKEY));
439
0
}
440
441
442
/* Helper for clean_all_subkeys.  */
443
static int
444
clean_one_subkey (ctrl_t ctrl, kbnode_t subkeynode, int noisy, int clean_level)
445
0
{
446
0
  kbnode_t node;
447
0
  PKT_public_key *pk = subkeynode->pkt->pkt.public_key;
448
0
  unsigned int use = pk->pubkey_usage;
449
0
  int do_clean = 0;
450
451
0
  (void)ctrl;
452
0
  (void)noisy;
453
454
0
  log_assert (subkeynode->pkt->pkttype == PKT_PUBLIC_SUBKEY
455
0
              || subkeynode->pkt->pkttype == PKT_SECRET_SUBKEY);
456
457
0
  if (DBG_LOOKUP)
458
0
    log_debug ("\tchecking subkey %08lX [%c%c%c%c%c]\n",
459
0
               (ulong) keyid_from_pk (pk, NULL),
460
0
               (use & PUBKEY_USAGE_ENC)? 'e':'-',
461
0
               (use & PUBKEY_USAGE_SIG)? 's':'-',
462
0
               (use & PUBKEY_USAGE_CERT)? 'c':'-',
463
0
               (use & PUBKEY_USAGE_AUTH)? 'a':'-',
464
0
               (use & PUBKEY_USAGE_UNKNOWN)? '?':'-');
465
466
0
  if (!pk->flags.valid)
467
0
    {
468
0
      if (DBG_LOOKUP)
469
0
        log_debug ("\tsubkey not valid\n");
470
0
      if (clean_level == KEY_CLEAN_INVALID)
471
0
        do_clean = 1;
472
0
    }
473
0
  if (pk->has_expired)
474
0
    {
475
0
      if (DBG_LOOKUP)
476
0
        log_debug ("\tsubkey has expired\n");
477
0
      if (clean_level == KEY_CLEAN_ALL)
478
0
        do_clean = 1;
479
0
      else if (clean_level == KEY_CLEAN_AUTHENCR
480
0
               && (use & (PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH))
481
0
               && !(use & (PUBKEY_USAGE_SIG | PUBKEY_USAGE_CERT)))
482
0
        do_clean = 1;
483
0
      else if (clean_level == KEY_CLEAN_ENCR
484
0
               && (use & PUBKEY_USAGE_ENC)
485
0
               && !(use & (PUBKEY_USAGE_SIG | PUBKEY_USAGE_CERT
486
0
                           | PUBKEY_USAGE_AUTH)))
487
0
        do_clean = 1;
488
0
    }
489
0
  if (pk->flags.revoked)
490
0
    {
491
0
      if (DBG_LOOKUP)
492
0
        log_debug ("\tsubkey has been revoked (keeping)\n");
493
      /* Avoid any cleaning because revocations are important.  */
494
0
      do_clean = 0;
495
0
    }
496
0
  if (!do_clean)
497
0
    return 0;
498
499
0
  if (DBG_LOOKUP)
500
0
    log_debug ("\t=> removing this subkey\n");
501
502
0
  delete_kbnode (subkeynode);
503
0
  for (node = subkeynode->next;
504
0
       node && !(node->pkt->pkttype == PKT_PUBLIC_SUBKEY
505
0
                 || node->pkt->pkttype == PKT_SECRET_SUBKEY);
506
0
       node = node->next)
507
0
    delete_kbnode (node);
508
509
0
  return 1;
510
0
}
511
512
513
/* Helper for clean_all_subkeys.  Here duplicate signatures from a
514
 * subkey are removed.  This should in general not happen because
515
 * import takes care of that.  However, sometimes other tools are used
516
 * to manage a keyring or key has been imported a long time ago.  */
517
static int
518
clean_one_subkey_dupsigs (ctrl_t ctrl, kbnode_t subkeynode)
519
0
{
520
0
  kbnode_t node;
521
0
  PKT_public_key *pk = subkeynode->pkt->pkt.public_key;
522
0
  int any_choosen = 0;
523
0
  int count = 0;
524
525
0
  (void)ctrl;
526
527
0
  log_assert (subkeynode->pkt->pkttype == PKT_PUBLIC_SUBKEY
528
0
              || subkeynode->pkt->pkttype == PKT_SECRET_SUBKEY);
529
530
0
  if (DBG_LOOKUP)
531
0
    log_debug ("\tchecking subkey %08lX for dupsigs\n",
532
0
               (ulong) keyid_from_pk (pk, NULL));
533
534
  /* First check that the chosen flag has been set.  Note that we
535
   * only look at plain signatures so to keep all revocation
536
   * signatures which may carry important information.  */
537
0
  for (node = subkeynode->next;
538
0
       node && !(node->pkt->pkttype == PKT_PUBLIC_SUBKEY
539
0
                 || node->pkt->pkttype == PKT_SECRET_SUBKEY);
540
0
       node = node->next)
541
0
    {
542
0
      if (!is_deleted_kbnode (node)
543
0
          && node->pkt->pkttype == PKT_SIGNATURE
544
0
          && IS_SUBKEY_SIG (node->pkt->pkt.signature)
545
0
          && node->pkt->pkt.signature->flags.chosen_selfsig)
546
0
        {
547
0
          any_choosen = 1;
548
0
          break;
549
0
        }
550
0
    }
551
552
0
  if (!any_choosen)
553
0
    return 0; /* Ooops no chosen flag set - we can't decide.  */
554
555
0
  for (node = subkeynode->next;
556
0
       node && !(node->pkt->pkttype == PKT_PUBLIC_SUBKEY
557
0
                 || node->pkt->pkttype == PKT_SECRET_SUBKEY);
558
0
       node = node->next)
559
0
    {
560
0
      if (!is_deleted_kbnode (node)
561
0
          && node->pkt->pkttype == PKT_SIGNATURE
562
0
          && IS_SUBKEY_SIG (node->pkt->pkt.signature)
563
0
          && !node->pkt->pkt.signature->flags.chosen_selfsig)
564
0
        {
565
0
          delete_kbnode (node);
566
0
          count++;
567
0
        }
568
0
    }
569
570
0
  return count;
571
0
}
572
573
574
/* This function only marks the deleted nodes and the caller is
575
 * responsible to skip or remove them.  Needs to be called after a
576
 * merge_keys_and_selfsig.  CLEAN_LEVEL is one of the KEY_CLEAN_*
577
 * values.   */
578
void
579
clean_all_subkeys (ctrl_t ctrl, kbnode_t keyblock, int noisy, int clean_level,
580
                   int *subkeys_cleaned, int *sigs_cleaned)
581
0
{
582
0
  kbnode_t first_subkey, node;
583
0
  int n;
584
585
0
  if (DBG_LOOKUP)
586
0
    log_debug ("clean_all_subkeys: checking key %08lX\n",
587
0
         (ulong) keyid_from_pk (keyblock->pkt->pkt.public_key, NULL));
588
589
0
  for (node = keyblock->next; node; node = node->next)
590
0
    if (!is_deleted_kbnode (node)
591
0
        && (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
592
0
            || node->pkt->pkttype == PKT_SECRET_SUBKEY))
593
0
      break;
594
0
  first_subkey = node;
595
596
  /* Remove bogus subkey binding signatures: The only signatures
597
   * allowed are of class 0x18 and 0x28.  */
598
0
  for (node = first_subkey; node; node = node->next)
599
0
    {
600
0
      if (is_deleted_kbnode (node))
601
0
        continue;
602
0
      if (node->pkt->pkttype == PKT_SIGNATURE
603
0
          && !(IS_SUBKEY_SIG (node->pkt->pkt.signature)
604
0
                || IS_SUBKEY_REV (node->pkt->pkt.signature)))
605
0
        {
606
0
          delete_kbnode (node);
607
0
          if (sigs_cleaned)
608
0
            ++*sigs_cleaned;
609
0
        }
610
0
    }
611
612
  /* Do the selected cleaning.  */
613
0
  if (clean_level > KEY_CLEAN_NONE)
614
0
    {
615
      /* Clean entire subkeys.  */
616
0
      for (node = first_subkey; node; node = node->next)
617
0
        {
618
0
          if (is_deleted_kbnode (node))
619
0
            continue;
620
0
          if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
621
0
              || node->pkt->pkttype == PKT_SECRET_SUBKEY)
622
0
            {
623
0
              if (clean_one_subkey (ctrl, node, noisy, clean_level))
624
0
                {
625
0
                  if (subkeys_cleaned)
626
0
                    ++*subkeys_cleaned;
627
0
                }
628
0
            }
629
0
        }
630
631
      /* Clean duplicate signatures from a subkey.  */
632
0
      for (node = first_subkey; node; node = node->next)
633
0
        {
634
0
          if (is_deleted_kbnode (node))
635
0
            continue;
636
0
          if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
637
0
              || node->pkt->pkttype == PKT_SECRET_SUBKEY)
638
0
            {
639
0
              n = clean_one_subkey_dupsigs (ctrl, node);
640
0
              if (sigs_cleaned)
641
0
                *sigs_cleaned += n;
642
0
            }
643
0
        }
644
0
    }
645
0
}