diff --git a/g10/delkey.c b/g10/delkey.c --- a/g10/delkey.c +++ b/g10/delkey.c @@ -40,6 +40,54 @@ #include "../common/i18n.h" #include "call-agent.h" +/* Determines whether to skip the deletion of the key at PK. + Returns true if the search description at DESC is an exact key specification + that doesn't match the key at PK. */ +static int +should_skip (KEYDB_SEARCH_DESC *desc, PKT_public_key *pk) +{ + u32 kid[2]; + byte fpr[MAX_FINGERPRINT_LEN]; + size_t fprlen; + + if (!desc->exact) + return 0; + + switch(desc->mode) + { + case KEYDB_SEARCH_MODE_SHORT_KID: + case KEYDB_SEARCH_MODE_LONG_KID: + keyid_from_pk (pk, kid); + break; + + case KEYDB_SEARCH_MODE_FPR: + fingerprint_from_pk (pk, fpr, &fprlen); + if (fprlen == desc->fprlen && !memcmp (desc->u.fpr, fpr, desc->fprlen)) + return 0; + break; + + default: + break; + } + + switch(desc->mode) + { + case KEYDB_SEARCH_MODE_SHORT_KID: + if (desc->u.kid[1] == kid[1]) + return 0; + break; + + case KEYDB_SEARCH_MODE_LONG_KID: + if (desc->u.kid[0] == kid[0] && desc->u.kid[1] == kid[1]) + return 0; + break; + + default: + break; + } + + return 1; +} /**************** * Delete a public or secret key from a keyring. @@ -176,6 +224,9 @@ || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)) continue; + if (should_skip (&desc, node->pkt->pkt.public_key)) + continue; + if (agent_probe_secret_key (NULL, node->pkt->pkt.public_key)) continue; /* No secret key for that public (sub)key. */