From 0a9827ca07f29a3b5d78a4efc7291c40b62b63dd Mon Sep 17 00:00:00 2001 From: David Shaw Date: Tue, 31 May 2005 03:59:24 +0000 Subject: [PATCH] * trustdb.h, trustdb.c (clean_subkeys_from_key): New. Walk through the subkeys on a key, and mark any that aren't usable for deletion. Note that a signing subkey is never marked for deletion since these keys are still useful after expiration or revocation. * keyedit.c (menu_clean_subkeys_from_key): New function to call clean_subkeys_from_key() on a key. Note that the strings here are not marked for translation yet. The UI is still in flux, and there is no point in annoying the translators twice. (keyedit_menu): Call it here as part of the "clean" command. --- g10/ChangeLog | 13 +++++++++ g10/keyedit.c | 59 +++++++++++++++++++++++++++++++-------- g10/trustdb.c | 76 +++++++++++++++++++++++++++++++++++++++++++++------ g10/trustdb.h | 1 + 4 files changed, 129 insertions(+), 20 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 2250bc9eb..ad94ca703 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,16 @@ +2005-05-30 David Shaw + + * trustdb.h, trustdb.c (clean_subkeys_from_key): New. Walk + through the subkeys on a key, and mark any that aren't usable for + deletion. Note that a signing subkey is never marked for deletion + since these keys are still useful after expiration or revocation. + + * keyedit.c (menu_clean_subkeys_from_key): New function to call + clean_subkeys_from_key() on a key. Note that the strings here are + not marked for translation yet. The UI is still in flux, and + there is no point in annoying the translators twice. + (keyedit_menu): Call it here as part of the "clean" command. + 2005-05-29 David Shaw * trustdb.h, trustdb.c (clean_uids_from_key): New. Walk through diff --git a/g10/keyedit.c b/g10/keyedit.c index d85c8885e..741204933 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -55,6 +55,7 @@ static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_delsig( KBNODE pub_keyblock ); static int menu_clean_sigs_from_uids(KBNODE keyblock); static int menu_clean_uids_from_key(KBNODE keyblock); +static int menu_clean_subkeys_from_key(KBNODE keyblock); static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ); @@ -2146,18 +2147,21 @@ keyedit_menu( const char *username, STRLIST locusr, modified=menu_clean_sigs_from_uids(keyblock); else if(ascii_strcasecmp(arg_string,"uids")==0) redisplay=modified=menu_clean_uids_from_key(keyblock); + else if(ascii_strcasecmp(arg_string,"subkeys")==0) + redisplay=modified=menu_clean_subkeys_from_key(keyblock); else if(ascii_strcasecmp(arg_string,"all")==0) { modified=menu_clean_sigs_from_uids(keyblock); modified+=menu_clean_uids_from_key(keyblock); + modified+=menu_clean_subkeys_from_key(keyblock); redisplay=modified; } else - tty_printf(_("Unable to clean `%s'\n"),arg_string); + tty_printf("Unable to clean `%s'\n",arg_string); } else - tty_printf(_("Please specify item to clean: `sigs'," - " `uids', or `all'\n")); + tty_printf("Please specify item to clean: `sigs'," + " `uids', `subkeys', or `all'\n"); } break; @@ -2549,7 +2553,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, /* the keys */ for( node = keyblock; node; node = node->next ) { if( node->pkt->pkttype == PKT_PUBLIC_KEY - || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) { + || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY + && !is_deleted_kbnode(node)) ) { PKT_public_key *pk = node->pkt->pkt.public_key; const char *otrust="err",*trust="err"; @@ -3150,7 +3155,7 @@ menu_clean_sigs_from_uids(KBNODE keyblock) int modified=0; int select_all=!count_selected_uids(keyblock); - for(uidnode=keyblock;uidnode;uidnode=uidnode->next) + for(uidnode=keyblock->next;uidnode;uidnode=uidnode->next) { if(uidnode->pkt->pkttype==PKT_USER_ID && (uidnode->flag&NODFLG_SELUID || select_all)) @@ -3163,8 +3168,8 @@ menu_clean_sigs_from_uids(KBNODE keyblock) if(deleted) { tty_printf(deleted==1? - _("User ID \"%s\": %d signature removed.\n"): - _("User ID \"%s\": %d signatures removed.\n"), + "User ID \"%s\": %d signature removed.\n": + "User ID \"%s\": %d signatures removed.\n", user,deleted); modified=1; } @@ -3182,9 +3187,7 @@ static int menu_clean_uids_from_key(KBNODE keyblock) { KBNODE node; - int modified; - - modified=clean_uids_from_key(keyblock,opt.verbose); + int modified=clean_uids_from_key(keyblock,0); if(modified) { @@ -3203,14 +3206,46 @@ menu_clean_uids_from_key(KBNODE keyblock) else reason=_("invalid"); - tty_printf(_("User ID \"%s\" removed: %s\n"),user,reason); + tty_printf("User ID \"%s\" removed: %s\n",user,reason); m_free(user); } } } else - tty_printf(_("No user IDs are removable.\n")); + tty_printf("No user IDs are removable.\n"); + + return modified; +} + +static int +menu_clean_subkeys_from_key(KBNODE keyblock) +{ + KBNODE node; + int modified=clean_subkeys_from_key(keyblock,0); + + if(modified) + { + for(node=keyblock->next;node;node=node->next) + { + if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY && is_deleted_kbnode(node)) + { + char *reason; + + if(node->pkt->pkt.public_key->is_revoked) + reason=_("revoked"); + else if(node->pkt->pkt.public_key->has_expired) + reason=_("expired"); + else + reason=_("invalid"); + + tty_printf("Subkey %s removed: %s\n", + keystr(node->pkt->pkt.public_key->keyid),reason); + } + } + } + else + tty_printf("No subkeys are removable.\n"); return modified; } diff --git a/g10/trustdb.c b/g10/trustdb.c index f69055756..d5e4e2333 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1644,7 +1644,7 @@ clean_sigs_from_uid(KBNODE keyblock,KBNODE uidnode,int noisy) int clean_uids_from_key(KBNODE keyblock,int noisy) { - int uidcount=0,delete_until_next,deleted=0; + int uidcount=0,delete_until_next=0,deleted=0; KBNODE node; assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY); @@ -1667,11 +1667,12 @@ clean_uids_from_key(KBNODE keyblock,int noisy) { if(node->pkt->pkttype==PKT_USER_ID) { + PKT_user_id *uid=node->pkt->pkt.user_id; + /* Skip valid user IDs, and non-self-signed user IDs if --allow-non-selfsigned-uid is set. */ - if(node->pkt->pkt.user_id->created - || (!node->pkt->pkt.user_id->is_expired - && !node->pkt->pkt.user_id->is_revoked + if(uid->created + || (!uid->is_expired && !uid->is_revoked && opt.allow_non_selfsigned_uid)) delete_until_next=0; else @@ -1682,12 +1683,11 @@ clean_uids_from_key(KBNODE keyblock,int noisy) if(noisy) { char *reason; - char *user=utf8_to_native(node->pkt->pkt.user_id->name, - node->pkt->pkt.user_id->len,0); + char *user=utf8_to_native(uid->name,uid->len,0); - if(node->pkt->pkt.user_id->is_revoked) + if(uid->is_revoked) reason=_("revoked"); - else if(node->pkt->pkt.user_id->is_expired) + else if(uid->is_expired) reason=_("expired"); else reason=_("invalid"); @@ -1708,6 +1708,66 @@ clean_uids_from_key(KBNODE keyblock,int noisy) return deleted; } +/* Another cleaning function. This only cleans encrypt-only subkeys + since an expired/revoked encryption key is basically useless, but + an expired/revoked key that can sign is still needed to verify old + signatures. */ +int +clean_subkeys_from_key(KBNODE keyblock,int noisy) +{ + int delete_until_next=0,deleted=0; + KBNODE node; + char *main_key=NULL; + + assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY); + + merge_keys_and_selfsig(keyblock); + + if(noisy) + main_key=m_strdup(keystr(keyblock->pkt->pkt.public_key->keyid)); + + for(node=keyblock->next;node;node=node->next) + { + if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY) + { + PKT_public_key *pk=node->pkt->pkt.public_key; + + /* If it is valid, not expired, and not revoked, leave it + alone. If a key can make signatures, leave it alone. */ + if(pk->pubkey_usage!=PUBKEY_USAGE_ENC + || (pk->is_valid && !pk->has_expired && !pk->is_revoked)) + delete_until_next=0; + else + { + delete_until_next=1; + deleted++; + + if(noisy) + { + char *reason; + + if(pk->is_revoked) + reason=_("revoked"); + else if(pk->has_expired) + reason=_("expired"); + else + reason=_("invalid"); + + log_info("removing subkey %s from key %s: %s\n", + keystr_from_pk(pk),main_key,reason); + } + } + } + + if(delete_until_next) + delete_kbnode(node); + } + + m_free(main_key); + + return deleted; +} + /* Used by validate_one_keyblock to confirm a regexp within a trust signature. Returns 1 for match, and 0 for no match or regex error. */ diff --git a/g10/trustdb.h b/g10/trustdb.h index b914063b1..1e1929400 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -83,6 +83,7 @@ int clear_ownertrusts (PKT_public_key *pk); int clean_sigs_from_uid(KBNODE keyblock,KBNODE uidnode,int noisy); int clean_uids_from_key(KBNODE keyblock,int noisy); +int clean_subkeys_from_key(KBNODE keyblock,int noisy); /*-- tdbdump.c --*/ void list_trustdb(const char *username);