diff --git a/g10/ChangeLog b/g10/ChangeLog index 48a6e6eda..e31dc6acd 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,12 @@ +2005-06-09 David Shaw + + * keydb.h, kbnode.c (undelete_kbnode): New function to undelete a + kbnode. + + * trustdb.c (clean_uids_from_key): Further tweak the algorithm so + that the last good selfsig is kept when the chosen selfsig is a + revocation. + 2005-06-08 David Shaw * trustdb.c (clean_uids_from_key), keyedit.c diff --git a/g10/kbnode.c b/g10/kbnode.c index ecfac8264..cd3bf5fd2 100644 --- a/g10/kbnode.c +++ b/g10/kbnode.c @@ -1,5 +1,6 @@ /* kbnode.c - keyblock node utility functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -113,6 +114,11 @@ delete_kbnode( KBNODE node ) node->private_flag |= 1; } +void +undelete_kbnode( KBNODE node ) +{ + node->private_flag &= ~1; +} /**************** diff --git a/g10/keydb.h b/g10/keydb.h index db3d9e35c..f716a7390 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -1,6 +1,6 @@ /* keydb.h - Key database - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -293,6 +293,7 @@ KBNODE new_kbnode( PACKET *pkt ); KBNODE clone_kbnode( KBNODE node ); void release_kbnode( KBNODE n ); void delete_kbnode( KBNODE node ); +void undelete_kbnode( KBNODE node ); void add_kbnode( KBNODE root, KBNODE node ); void insert_kbnode( KBNODE root, KBNODE node, int pkttype ); void move_kbnode( KBNODE *root, KBNODE node, KBNODE where ); diff --git a/g10/trustdb.c b/g10/trustdb.c index 19dcb0a1c..9f71f6377 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1644,12 +1644,18 @@ clean_sigs_from_uid(KBNODE keyblock,KBNODE uidnode,int noisy) removed. To "remove" a user ID, we simply remove ALL signatures except the self-sig that caused the user ID to be remove-worthy. We don't actually remove the user ID packet itself since it might - be ressurected in a later merge. */ + be ressurected in a later merge. + + If this self-sig is a revocation, we also include the most recent + valid regular sig since it is hard to import the user ID otherwise. + TODO: change the import code to allow importing a uid with only a + revocation if the uid already exists on the keyring. */ int clean_uids_from_key(KBNODE keyblock,int noisy) { int delete_until_next=0,deleted=0; - KBNODE node; + KBNODE node,signode=NULL; + u32 sigdate=0; assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY); @@ -1663,6 +1669,12 @@ clean_uids_from_key(KBNODE keyblock,int noisy) { PKT_user_id *uid=node->pkt->pkt.user_id; + if(signode && !signode->pkt->pkt.signature->flags.chosen_selfsig) + undelete_kbnode(signode); + + sigdate=0; + signode=NULL; + /* Skip valid user IDs, and non-self-signed user IDs if --allow-non-selfsigned-uid is set. */ if(uid->created @@ -1694,12 +1706,27 @@ clean_uids_from_key(KBNODE keyblock,int noisy) } } } - else if(node->pkt->pkttype==PKT_SIGNATURE - && delete_until_next - && !node->pkt->pkt.signature->flags.chosen_selfsig) - delete_kbnode(node); + else if(node->pkt->pkttype==PKT_SIGNATURE) + { + PKT_signature *sig=node->pkt->pkt.signature; + + /* This isn't actually slow - the key signature validation + is cached from merge_keys_and_selfsig() */ + if(IS_UID_SIG(sig) && sig->timestamp>sigdate + && check_key_signature(keyblock,node,NULL)==0) + { + sigdate=sig->timestamp; + signode=node; + } + + if(delete_until_next && !sig->flags.chosen_selfsig) + delete_kbnode(node); + } } - + + if(signode && !signode->pkt->pkt.signature->flags.chosen_selfsig) + undelete_kbnode(signode); + return deleted; }