From acac94aa90349840fdb9387cc2813d5420f9a71b Mon Sep 17 00:00:00 2001 From: David Shaw Date: Mon, 30 May 2005 03:43:30 +0000 Subject: [PATCH] * trustdb.h, trustdb.c (clean_uids_from_key): New. Walk through the user IDs on a key, and mark any that aren't valid for deletion. * keyedit.c (menu_clean_uids_from_key): New function to call clean_uids_from_key() on a key. (keyedit_menu): Call it from here as part of the "clean" command. --- g10/ChangeLog | 10 +++++++ g10/keyedit.c | 70 ++++++++++++++++++++++++++++++++++++++--------- g10/trustdb.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++- g10/trustdb.h | 3 ++- 4 files changed, 144 insertions(+), 14 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 87608c3be..2250bc9eb 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,13 @@ +2005-05-29 David Shaw + + * trustdb.h, trustdb.c (clean_uids_from_key): New. Walk through + the user IDs on a key, and mark any that aren't valid for + deletion. + + * keyedit.c (menu_clean_uids_from_key): New function to call + clean_uids_from_key() on a key. + (keyedit_menu): Call it from here as part of the "clean" command. + 2005-05-26 David Shaw * g10.c (main): Default {export|import}-unusable-sigs to off until diff --git a/g10/keyedit.c b/g10/keyedit.c index cc7ff7278..d85c8885e 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -53,7 +53,8 @@ static void show_key_and_fingerprint( KBNODE keyblock ); static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, int photo ); static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_delsig( KBNODE pub_keyblock ); -static int menu_clean_uids(KBNODE keyblock); +static int menu_clean_sigs_from_uids(KBNODE keyblock); +static int menu_clean_uids_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 ); @@ -2138,17 +2139,25 @@ keyedit_menu( const char *username, STRLIST locusr, { if(*arg_string) { - if(ascii_strcasecmp(arg_string,"sigs")!=0 - && ascii_strcasecmp(arg_string,"signatures")!=0 - && ascii_strcasecmp(arg_string,"certs")!=0 - && ascii_strcasecmp(arg_string,"certificates")!=0) + if(ascii_strcasecmp(arg_string,"sigs")==0 + || ascii_strcasecmp(arg_string,"signatures")==0 + || ascii_strcasecmp(arg_string,"certs")==0 + || ascii_strcasecmp(arg_string,"certificates")==0) + 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,"all")==0) { - tty_printf(_("Unable to clean `%s'\n"),arg_string); - break; + modified=menu_clean_sigs_from_uids(keyblock); + modified+=menu_clean_uids_from_key(keyblock); + redisplay=modified; } + else + tty_printf(_("Unable to clean `%s'\n"),arg_string); } - - modified=menu_clean_uids(keyblock); + else + tty_printf(_("Please specify item to clean: `sigs'," + " `uids', or `all'\n")); } break; @@ -2699,7 +2708,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker, i = 0; for( node = keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_USER_ID ) + if( node->pkt->pkttype == PKT_USER_ID + && !is_deleted_kbnode(node)) { PKT_user_id *uid = node->pkt->pkt.user_id; ++i; @@ -3134,7 +3144,7 @@ menu_delsig( KBNODE pub_keyblock ) } static int -menu_clean_uids(KBNODE keyblock) +menu_clean_sigs_from_uids(KBNODE keyblock) { KBNODE uidnode; int modified=0; @@ -3149,7 +3159,7 @@ menu_clean_uids(KBNODE keyblock) char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name, uidnode->pkt->pkt.user_id->len, 0); - deleted=clean_uid(keyblock,uidnode,opt.verbose); + deleted=clean_sigs_from_uid(keyblock,uidnode,opt.verbose); if(deleted) { tty_printf(deleted==1? @@ -3168,6 +3178,42 @@ menu_clean_uids(KBNODE keyblock) return modified; } +static int +menu_clean_uids_from_key(KBNODE keyblock) +{ + KBNODE node; + int modified; + + modified=clean_uids_from_key(keyblock,opt.verbose); + + if(modified) + { + for(node=keyblock->next;node;node=node->next) + { + if(node->pkt->pkttype==PKT_USER_ID && is_deleted_kbnode(node)) + { + char *reason; + char *user=utf8_to_native(node->pkt->pkt.user_id->name, + node->pkt->pkt.user_id->len,0); + + if(node->pkt->pkt.user_id->is_revoked) + reason=_("revoked"); + else if(node->pkt->pkt.user_id->is_expired) + reason=_("expired"); + else + reason=_("invalid"); + + tty_printf(_("User ID \"%s\" removed: %s\n"),user,reason); + + m_free(user); + } + } + } + else + tty_printf(_("No user IDs are removable.\n")); + + return modified; +} /**************** * Remove some of the secondary keys diff --git a/g10/trustdb.c b/g10/trustdb.c index 751f1b4ef..f69055756 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1574,7 +1574,7 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode, } int -clean_uid(KBNODE keyblock,KBNODE uidnode,int noisy) +clean_sigs_from_uid(KBNODE keyblock,KBNODE uidnode,int noisy) { int deleted=0; KBNODE node; @@ -1635,6 +1635,79 @@ clean_uid(KBNODE keyblock,KBNODE uidnode,int noisy) return deleted; } +/* This is substantially easier than clean_sigs_from_uid since we just + have to establish if the uid has a valid self-sig, is not revoked, + and is not expired. Note that this does not take into account + whether the uid has a trust path to it - just whether the keyholder + themselves has certified the uid. Returns how many user IDs were + removed. */ +int +clean_uids_from_key(KBNODE keyblock,int noisy) +{ + int uidcount=0,delete_until_next,deleted=0; + KBNODE node; + + assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY); + + merge_keys_and_selfsig(keyblock); + + /* First count how many user IDs we have. We need to be careful + that we don't delete them all as some keys could actually have NO + valid user IDs. 2440 requires at least 1 user ID packet, valid + or not. */ + for(node=keyblock->next; + node && node->pkt->pkttype!=PKT_PUBLIC_SUBKEY; + node=node->next) + if(node->pkt->pkttype==PKT_USER_ID) + uidcount++; + + for(node=keyblock->next; + node && node->pkt->pkttype!=PKT_PUBLIC_SUBKEY && uidcount>deleted+1; + node=node->next) + { + if(node->pkt->pkttype==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 + && opt.allow_non_selfsigned_uid)) + delete_until_next=0; + else + { + delete_until_next=1; + deleted++; + + if(noisy) + { + char *reason; + char *user=utf8_to_native(node->pkt->pkt.user_id->name, + node->pkt->pkt.user_id->len,0); + + if(node->pkt->pkt.user_id->is_revoked) + reason=_("revoked"); + else if(node->pkt->pkt.user_id->is_expired) + reason=_("expired"); + else + reason=_("invalid"); + + log_info("removing user ID \"%s\" from key %s: %s\n", + user,keystr(keyblock->pkt->pkt.public_key->keyid), + reason); + + m_free(user); + } + } + } + + if(delete_until_next) + delete_kbnode(node); + } + + 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 a9f98c712..b914063b1 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -81,7 +81,8 @@ const char *get_ownertrust_string (PKT_public_key *pk); void update_ownertrust (PKT_public_key *pk, unsigned int new_trust ); int clear_ownertrusts (PKT_public_key *pk); -int clean_uid(KBNODE keyblock,KBNODE uidnode,int noisy); +int clean_sigs_from_uid(KBNODE keyblock,KBNODE uidnode,int noisy); +int clean_uids_from_key(KBNODE keyblock,int noisy); /*-- tdbdump.c --*/ void list_trustdb(const char *username);