* trustdb.h, trustdb.c (mark_usable_uid_certs): Add flags for the

no-pubkey and chosen revocation cases.  (clean_uid): New function to
clean a user ID of unusable (as defined by mark_usable_uid_certs)
certs.

* keyedit.c (keyedit_menu, menu_clean_uids): Call it here for new
"clean" command that removes unusable sigs from a key.
This commit is contained in:
David Shaw 2005-04-24 18:35:30 +00:00
parent be90f3cacb
commit f02fe1dafb
4 changed files with 164 additions and 21 deletions

View File

@ -1,5 +1,13 @@
2005-04-24 David Shaw <dshaw@jabberwocky.com>
* trustdb.h, trustdb.c (mark_usable_uid_certs): Add flags for the
no-pubkey and chosen revocation cases.
(clean_uid): New function to clean a user ID of unusable (as
defined by mark_usable_uid_certs) certs.
* keyedit.c (keyedit_menu, menu_clean_uids): Call it here for new
"clean" command that removes unusable sigs from a key.
* trustdb.h, keyedit.c (keyedit_menu, menu_select_uid_namehash):
Allow specifying user ID via the namehash from --with-colons
--fixed-list-mode --list-keys. Suggested by Peter Palfrader.

View File

@ -53,6 +53,7 @@ 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 void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_addrevoker( KBNODE pub_keyblock,
KBNODE sec_keyblock, int sensitive );
@ -1327,7 +1328,7 @@ enum cmdids
cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF,
cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST,
cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdNOP
cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCLEAN, cmdNOP
};
static struct
@ -1426,6 +1427,7 @@ static struct
{ "enable" , cmdENABLEKEY , KEYEDIT_NOT_SK, N_("enable key") },
{ "disable" , cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key") },
{ "showphoto",cmdSHOWPHOTO , 0, N_("show selected photo IDs") },
{ "clean", cmdCLEAN , KEYEDIT_NOT_SK, NULL },
{ NULL, cmdNONE, 0, NULL }
};
@ -1952,7 +1954,7 @@ keyedit_menu( const char *username, STRLIST locusr,
{
int sensitive=0;
if(arg_string && ascii_strcasecmp(arg_string,"sensitive")==0)
if(ascii_strcasecmp(arg_string,"sensitive")==0)
sensitive=1;
if( menu_addrevoker( keyblock, sec_keyblock, sensitive ) ) {
redisplay = 1;
@ -2123,9 +2125,27 @@ keyedit_menu( const char *username, STRLIST locusr,
}
break;
case cmdSHOWPHOTO:
menu_showphoto(keyblock);
break;
case cmdSHOWPHOTO:
menu_showphoto(keyblock);
break;
case cmdCLEAN:
{
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)
{
tty_printf(_("Unable to clean `%s'\n"),arg_string);
break;
}
}
modified=menu_clean_uids(keyblock);
}
break;
case cmdQUIT:
if( have_commands )
@ -3108,6 +3128,41 @@ menu_delsig( KBNODE pub_keyblock )
return changed;
}
static int
menu_clean_uids(KBNODE keyblock)
{
KBNODE uidnode;
int modified=0;
int select_all=!count_selected_uids(keyblock);
for(uidnode=keyblock;uidnode;uidnode=uidnode->next)
{
if(uidnode->pkt->pkttype==PKT_USER_ID
&& (uidnode->flag&NODFLG_SELUID || select_all))
{
int deleted;
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);
if(deleted)
{
tty_printf(deleted==1?
_("User ID \"%s\": %d signature removed.\n"):
_("User ID \"%s\": %d signatures removed.\n"),
user,deleted);
modified=1;
}
else
tty_printf(_("User ID \"%s\": already clean.\n"),user);
m_free(user);
}
}
return modified;
}
/****************
* Remove some of the secondary keys

View File

@ -1,6 +1,6 @@
/* trustdb.c
* 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.
*
@ -1409,8 +1409,9 @@ is_in_klist (struct key_item *k, PKT_signature *sig)
* To do this, we first revmove all signatures which are not valid and
* from the remain ones we look for the latest one. If this is not a
* certification revocation signature we mark the signature by setting
* node flag bit 8. Note that flag bits 9 and 10 are used for internal
* purposes.
* node flag bit 8. Revocations are marked with flag 11, and sigs
* from unavailable keys are marked with flag 12. Note that flag bits
* 9 and 10 are used for internal purposes.
*/
static void
mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
@ -1423,34 +1424,44 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
/* first check all signatures */
for (node=uidnode->next; node; node = node->next)
{
node->flag &= ~(1<<8 | 1<<9 | 1<<10);
int rc;
node->flag &= ~(1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12);
if (node->pkt->pkttype == PKT_USER_ID
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
break; /* ready */
if (node->pkt->pkttype != PKT_SIGNATURE)
continue;
sig = node->pkt->pkt.signature;
if (sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1])
continue; /* ignore self-signatures */
if (main_kid
&& sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1])
continue; /* ignore self-signatures if we pass in a main_kid */
if (!IS_UID_SIG(sig) && !IS_UID_REV(sig))
continue; /* we only look at these signature classes */
if(sig->sig_class>=0x11 && sig->sig_class<=0x13 &&
sig->sig_class-0x10<opt.min_cert_level)
continue;
if (!is_in_klist (klist, sig))
continue; /* treat anything under our min_cert_level as an
invalid signature */
if (klist && !is_in_klist (klist, sig))
continue; /* no need to check it then */
if (check_key_signature (keyblock, node, NULL))
continue; /* ignore invalid signatures */
if ((rc=check_key_signature (keyblock, node, NULL)))
{
/* we ignore anything that won't verify, but tag the
no_pubkey case */
if(rc==G10ERR_NO_PUBKEY)
node->flag |= 1<<12;
continue;
}
node->flag |= 1<<9;
}
/* reset the remaining flags */
for (; node; node = node->next)
node->flag &= ~(1<<8 | 1<<9 | 1 << 10);
node->flag &= ~(1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12);
/* kbnode flag usage: bit 9 is here set for signatures to consider,
* bit 10 will be set by the loop to keep track of keyIDs already
* processed, bit 8 will be set for the usable signatures */
* processed, bit 8 will be set for the usable signatures, and bit
* 11 will be set for usable revocations. */
/* for each cert figure out the latest valid one */
for (node=uidnode->next; node; node = node->next)
@ -1458,7 +1469,7 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
KBNODE n, signode;
u32 kid[2];
u32 sigdate;
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
break;
if ( !(node->flag & (1<<9)) )
@ -1470,6 +1481,8 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
signode = node;
sigdate = sig->timestamp;
kid[0] = sig->keyid[0]; kid[1] = sig->keyid[1];
/* Now find the latest and greatest signature */
for (n=uidnode->next; n; n = n->next)
{
if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY)
@ -1532,6 +1545,7 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
sigdate = sig->timestamp;
}
}
sig = signode->pkt->pkt.signature;
if (IS_UID_SIG (sig))
{ /* this seems to be a usable one which is not revoked.
@ -1550,13 +1564,77 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
if (expire==0 || expire > curtime )
{
signode->flag |= (1<<8); /* yeah, found a good cert */
if (expire && expire < *next_expire)
if (next_expire && expire && expire < *next_expire)
*next_expire = expire;
}
}
else
signode->flag |= (1<<11);
}
}
int
clean_uid(KBNODE keyblock,KBNODE uidnode,int noisy)
{
int deleted=0;
KBNODE node;
assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
/* Passing in a 0 for current time here means that we'll never weed
out an expired sig. This is correct behavior since we want to
keep the most recent expired sig in a series. */
mark_usable_uid_certs(keyblock,uidnode,NULL,NULL,0,NULL);
/* What we want to do here is remove signatures that are not
considered as part of the trust calculations. Thus, all invalid
signatures are out, as are any signatures that aren't the last of
a series of uid sigs or revocations It breaks down like this:
coming out of mark_usable_uid_certs, if a sig is unflagged, it is
not even a candidate. If a sig has flag 9 or 10, that means it
was selected as a candidate and vetted. If a sig has flag 8 it
is a usable signature. If a sig has flag 11 it is a usable
revocation. If a sig has flag 12 it was issued by an unavailable
key. "Usable" here means the most recent valid
signature/revocation in a series from a particular signer.
Delete everything that isn't a usable uid sig (which might be
expired), a usable revocation, or a sig from an unavailable
key. */
for(node=uidnode->next;
node && node->pkt->pkttype==PKT_SIGNATURE;
node=node->next)
{
/* Keep usable uid sigs ... */
if(node->flag & (1<<8))
continue;
/* ... and usable revocations... */
if(node->flag & (1<<11))
continue;
/* ... and sigs from unavailable keys. */
if(node->flag & (1<<12))
continue;
/* Everything else we delete */
/* if 9 or 10 is set, but we get this far, it's superceded,
otherwise, it's invalid */
if(noisy)
log_info("removing signature issued by key %s: %s\n",
keystr(node->pkt->pkt.signature->keyid),
node->flag&(1<<9)?"superceded":"invalid");
delete_kbnode(node);
deleted++;
}
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. */

View File

@ -81,6 +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);
/*-- tdbdump.c --*/
void list_trustdb(const char *username);
void export_ownertrust(void);