diff --git a/g10/delkey.c b/g10/delkey.c --- a/g10/delkey.c +++ b/g10/delkey.c @@ -44,12 +44,23 @@ 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) +should_skip (KEYDB_SEARCH_DESC *desc, PACKET *pkt, int subkeys_only) { u32 kid[2]; byte fpr[MAX_FINGERPRINT_LEN]; size_t fprlen; + if (subkeys_only) + { + if (pkt->pkttype != PKT_PUBLIC_SUBKEY) + return 1; + } + else + { + if (!(pkt->pkttype == PKT_PUBLIC_KEY || pkt->pkttype == PKT_PUBLIC_SUBKEY)) + return 1; + } + if (!desc->exact) return 0; @@ -57,11 +68,11 @@ { case KEYDB_SEARCH_MODE_SHORT_KID: case KEYDB_SEARCH_MODE_LONG_KID: - keyid_from_pk (pk, kid); + keyid_from_pk (pkt->pkt.public_key, kid); break; case KEYDB_SEARCH_MODE_FPR: - fingerprint_from_pk (pk, fpr, &fprlen); + fingerprint_from_pk (pkt->pkt.public_key, fpr, &fprlen); if (fprlen == desc->fprlen && !memcmp (desc->u.fpr, fpr, desc->fprlen)) return 0; break; @@ -163,7 +174,8 @@ * key can't be deleted for that reason. */ static gpg_error_t -do_delete_key (ctrl_t ctrl, const char *username, int secret, int force, +do_delete_key (ctrl_t ctrl, const char *username, + int secret, int force, int subkeys_only, int *r_sec_avail) { gpg_error_t err; @@ -256,11 +268,7 @@ setup_main_keyids (keyblock); for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); ) { - if (!(node->pkt->pkttype == PKT_PUBLIC_KEY - || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)) - continue; - - if (should_skip (&desc, node->pkt->pkt.public_key)) + if (should_skip (&desc, node->pkt, subkeys_only)) continue; if (confirm_deletion (ctrl, node->pkt, secret, exactmatch)) @@ -331,7 +339,7 @@ * Delete a public or secret key from a keyring. */ gpg_error_t -delete_keys (ctrl_t ctrl, strlist_t names, int secret, int allow_both) +delete_keys (ctrl_t ctrl, strlist_t names, int secret, int allow_both, int subkeys_only) { gpg_error_t err; int avail; @@ -342,14 +350,14 @@ for ( ;names ; names=names->next ) { - err = do_delete_key (ctrl, names->d, secret, force, &avail); + err = do_delete_key (ctrl, names->d, secret, force, subkeys_only, &avail); if (err && avail) { if (allow_both) { - err = do_delete_key (ctrl, names->d, 1, 0, &avail); + err = do_delete_key (ctrl, names->d, 1, 0, subkeys_only, &avail); if (!err) - err = do_delete_key (ctrl, names->d, 0, 0, &avail); + err = do_delete_key (ctrl, names->d, 0, 0, subkeys_only, &avail); } else { diff --git a/g10/gpg.c b/g10/gpg.c --- a/g10/gpg.c +++ b/g10/gpg.c @@ -140,6 +140,7 @@ aEditKey, aDeleteKeys, aDeleteSecretKeys, + aDeleteSecretSubkeys, aDeleteSecretAndPublicKeys, aImport, aFastImport, @@ -482,6 +483,8 @@ N_("remove keys from the public keyring")), ARGPARSE_c (aDeleteSecretKeys, "delete-secret-keys", N_("remove keys from the secret keyring")), + ARGPARSE_c (aDeleteSecretSubkeys, "delete-secret-subkeys", + N_("remove subkeys from the secret keyring")), ARGPARSE_c (aQuickSignKey, "quick-sign-key" , N_("quickly sign a key")), ARGPARSE_c (aQuickLSignKey, "quick-lsign-key", @@ -2653,6 +2656,7 @@ case aFullKeygen: case aEditKey: case aDeleteSecretKeys: + case aDeleteSecretSubkeys: case aDeleteSecretAndPublicKeys: case aDeleteKeys: case aPasswd: @@ -4205,6 +4209,7 @@ case aEditKey: case aPasswd: case aDeleteSecretKeys: + case aDeleteSecretSubkeys: case aDeleteSecretAndPublicKeys: case aQuickKeygen: case aQuickAddUid: @@ -4492,6 +4497,7 @@ case aDeleteKeys: case aDeleteSecretKeys: + case aDeleteSecretSubkeys: case aDeleteSecretAndPublicKeys: sl = NULL; /* I'm adding these in reverse order as add_to_strlist2 @@ -4500,7 +4506,9 @@ for( ; argc; argc-- ) add_to_strlist2( &sl, argv[argc-1], utf8_strings ); delete_keys (ctrl, sl, - cmd==aDeleteSecretKeys, cmd==aDeleteSecretAndPublicKeys); + cmd == aDeleteSecretKeys || cmd == aDeleteSecretSubkeys, + cmd == aDeleteSecretAndPublicKeys, + cmd == aDeleteSecretSubkeys); free_strlist(sl); break; diff --git a/g10/main.h b/g10/main.h --- a/g10/main.h +++ b/g10/main.h @@ -304,7 +304,7 @@ /*-- delkey.c --*/ gpg_error_t delete_keys (ctrl_t ctrl, - strlist_t names, int secret, int allow_both); + strlist_t names, int secret, int allow_both, int subkeys_only); /*-- keygen.c --*/ const char *get_default_pubkey_algo (void);