aboutsummaryrefslogtreecommitdiffstats
path: root/g10/key-clean.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2018-07-09 07:49:09 +0000
committerWerner Koch <[email protected]>2018-07-09 07:49:21 +0000
commitc2fd65ec8498a08ee36ca52d99b6b014f6db8d93 (patch)
treeca23db3fe234ed6858c1913e4b463d99c5e27ccd /g10/key-clean.c
parentgpg: Split key cleaning function for clarity. (diff)
downloadgnupg-c2fd65ec8498a08ee36ca52d99b6b014f6db8d93.tar.gz
gnupg-c2fd65ec8498a08ee36ca52d99b6b014f6db8d93.zip
gpg: Let export-clean remove expired subkeys.
* g10/key-clean.h (KEY_CLEAN_NONE, KEY_CLEAN_INVALID) (KEY_CLEAN_ENCR, KEY_CLEAN_AUTHENCR, KEY_CLEAN_ALL): New. * g10/key-clean.c (clean_one_subkey): New. (clean_all_subkeys): Add arg CLEAN_LEVEL. * g10/import.c (import_one): Call clean_all_subkeys with KEY_CLEAN_NONE. * g10/export.c (do_export_stream): Call clean_all_subkeys depedning on the export clean options. -- GnuPG-bug-id: 3622 Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'g10/key-clean.c')
-rw-r--r--g10/key-clean.c102
1 files changed, 98 insertions, 4 deletions
diff --git a/g10/key-clean.c b/g10/key-clean.c
index 10478a46e..097ca17e9 100644
--- a/g10/key-clean.c
+++ b/g10/key-clean.c
@@ -408,24 +408,101 @@ clean_all_uids (ctrl_t ctrl, kbnode_t keyblock, int noisy, int self_only,
}
+/* Helper for clean_all_subkeys. */
+static int
+clean_one_subkey (ctrl_t ctrl, kbnode_t subkeynode, int noisy, int clean_level)
+{
+ kbnode_t node;
+ PKT_public_key *pk = subkeynode->pkt->pkt.public_key;
+ unsigned int use = pk->pubkey_usage;
+ int do_clean = 0;
+
+ (void)ctrl;
+ (void)noisy;
+
+ log_assert (subkeynode->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || subkeynode->pkt->pkttype == PKT_SECRET_SUBKEY);
+
+ if (DBG_LOOKUP)
+ log_debug ("\tchecking subkey %08lX [%c%c%c%c%c]\n",
+ (ulong) keyid_from_pk (pk, NULL),
+ (use & PUBKEY_USAGE_ENC)? 'e':'-',
+ (use & PUBKEY_USAGE_SIG)? 's':'-',
+ (use & PUBKEY_USAGE_CERT)? 'c':'-',
+ (use & PUBKEY_USAGE_AUTH)? 'a':'-',
+ (use & PUBKEY_USAGE_UNKNOWN)? '?':'-');
+
+ if (!pk->flags.valid)
+ {
+ if (DBG_LOOKUP)
+ log_debug ("\tsubkey not valid\n");
+ if (clean_level == KEY_CLEAN_INVALID)
+ do_clean = 1;
+ }
+ if (pk->has_expired)
+ {
+ if (DBG_LOOKUP)
+ log_debug ("\tsubkey has expired\n");
+ if (clean_level == KEY_CLEAN_ALL)
+ do_clean = 1;
+ else if (clean_level == KEY_CLEAN_AUTHENCR
+ && (use & (PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH))
+ && !(use & (PUBKEY_USAGE_SIG | PUBKEY_USAGE_CERT)))
+ do_clean = 1;
+ else if (clean_level == KEY_CLEAN_ENCR
+ && (use & PUBKEY_USAGE_ENC)
+ && !(use & (PUBKEY_USAGE_SIG | PUBKEY_USAGE_CERT
+ | PUBKEY_USAGE_AUTH)))
+ do_clean = 1;
+ }
+ if (pk->flags.revoked)
+ {
+ if (DBG_LOOKUP)
+ log_debug ("\tsubkey has been revoked (keeping)\n");
+ /* Avoid any cleaning because revocations are important. */
+ do_clean = 0;
+ }
+ if (!do_clean)
+ return 0;
+
+ if (DBG_LOOKUP)
+ log_debug ("\t=> removing this subkey\n");
+
+ delete_kbnode (subkeynode);
+ for (node = subkeynode->next;
+ node && !(node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY);
+ node = node->next)
+ delete_kbnode (node);
+
+ return 1;
+}
+
+
/* This function only marks the deleted nodes and the caller is
* responsible to skip or remove them. Needs to be called after a
- * merge_keys_and_selfsig. */
+ * merge_keys_and_selfsig. CLEAN_LEVEL is one of the KEY_CLEAN_*
+ * values. */
void
-clean_all_subkeys (ctrl_t ctrl, kbnode_t keyblock, int noisy,
+clean_all_subkeys (ctrl_t ctrl, kbnode_t keyblock, int noisy, int clean_level,
int *subkeys_cleaned, int *sigs_cleaned)
{
- kbnode_t node;
+ kbnode_t first_subkey, node;
+
+ if (DBG_LOOKUP)
+ log_debug ("clean_all_subkeys: checking key %08lX\n",
+ (ulong) keyid_from_pk (keyblock->pkt->pkt.public_key, NULL));
for (node = keyblock->next; node; node = node->next)
if (!is_deleted_kbnode (node)
&& (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY))
break;
+ first_subkey = node;
/* Remove bogus subkey binding signatures: The only signatures
* allowed are of class 0x18 and 0x28. */
- for (; node; node = node->next)
+ for (node = first_subkey; node; node = node->next)
{
if (is_deleted_kbnode (node))
continue;
@@ -438,4 +515,21 @@ clean_all_subkeys (ctrl_t ctrl, kbnode_t keyblock, int noisy,
++*sigs_cleaned;
}
}
+
+ /* Do the selected cleaning. */
+ if (clean_level > KEY_CLEAN_NONE)
+ {
+ for (node = first_subkey; node; node = node->next)
+ {
+ if (is_deleted_kbnode (node))
+ continue;
+ if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+ if (clean_one_subkey (ctrl, node, noisy, clean_level))
+ {
+ if (subkeys_cleaned)
+ ++*subkeys_cleaned;
+ }
+ }
+ }
}