mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
sync
This commit is contained in:
parent
0a76a4465b
commit
3c53ea75ce
3
TODO
3
TODO
@ -4,6 +4,9 @@
|
||||
|
||||
* invalid packets (Marco)
|
||||
|
||||
* add some sanity checks to read_keyblock, so that we are sure that
|
||||
the minimal requirements are met (?)
|
||||
|
||||
* what about the CR,LF in cleartext singatures?
|
||||
|
||||
* add option --restore-ownertrust
|
||||
|
@ -130,7 +130,7 @@ unsigned nbits_from_sk( PKT_secret_key *sk );
|
||||
const char *datestr_from_pk( PKT_public_key *pk );
|
||||
const char *datestr_from_sk( PKT_secret_key *sk );
|
||||
const char *datestr_from_sig( PKT_signature *sig );
|
||||
byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf. size_t *ret_len );
|
||||
byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf; size_t *ret_len );
|
||||
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
|
||||
|
||||
/*-- kbnode.c --*/
|
||||
|
@ -250,7 +250,7 @@ hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig )
|
||||
/****************
|
||||
* check the signature pointed to by NODE. This is a key signature.
|
||||
* If the function detects a self-signature, it uses the PK from
|
||||
* NODE and does not read any public key.
|
||||
* ROOT and does not read any public key.
|
||||
*/
|
||||
int
|
||||
check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
|
||||
|
@ -287,6 +287,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
|
||||
log_error(_("trustdb: read failed (n=%d): %s\n"), n, strerror(errno) );
|
||||
return G10ERR_READ_FILE;
|
||||
}
|
||||
rec->recnum = recnum;
|
||||
p = buf;
|
||||
rec->rectype = *p++;
|
||||
if( expected && rec->rectype != expected ) {
|
||||
@ -383,13 +384,15 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
|
||||
|
||||
/****************
|
||||
* Write the record at RECNUM
|
||||
* FIXME: create/update keyhash record.
|
||||
*/
|
||||
int
|
||||
tdbio_write_record( ulong recnum, TRUSTREC *rec )
|
||||
tdbio_write_record( TRUSTREC *rec )
|
||||
{
|
||||
byte buf[TRUST_RECORD_LEN], *p;
|
||||
int rc = 0;
|
||||
int i, n;
|
||||
ulong recnum = rec->recnum;
|
||||
|
||||
if( db_fd == -1 )
|
||||
open_db();
|
||||
@ -506,6 +509,7 @@ tdbio_new_recnum()
|
||||
* The local_id of PK is set to the correct value
|
||||
*
|
||||
* Note: To increase performance, we could use a index search here.
|
||||
* tdbio_write_record shoudl create this index automagically
|
||||
*/
|
||||
int
|
||||
tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec )
|
||||
|
10
g10/tdbio.h
10
g10/tdbio.h
@ -42,7 +42,11 @@
|
||||
|
||||
struct trust_record {
|
||||
int rectype;
|
||||
struct trust_record *next;
|
||||
struct trust_record *next; /* help pointer to build lists in memory */
|
||||
struct trust_record *help_pref;
|
||||
struct trust_record *help_sig;
|
||||
int mark;
|
||||
ulong recnum;
|
||||
union {
|
||||
struct { /* version record: */
|
||||
byte version; /* should be 1 */
|
||||
@ -72,7 +76,7 @@ struct trust_record {
|
||||
struct { /* user id reord */
|
||||
ulong lid; /* point back to the directory record */
|
||||
ulong next; /* points to next user id record */
|
||||
ulong prefrec; /* recno of reference record */
|
||||
ulong prefrec; /* recno of preference record */
|
||||
ulong siglist; /* list of valid signatures (w/o self-sig)*/
|
||||
byte namehash[20]; /* ripemd hash of the username */
|
||||
} uid;
|
||||
@ -127,7 +131,7 @@ int tdbio_set_dbname( const char *new_dbname, int create );
|
||||
const char *tdbio_get_dbname(void);
|
||||
void tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp );
|
||||
int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected );
|
||||
int tdbio_write_record( ulong recnum, TRUSTREC *rec );
|
||||
int tdbio_write_record( TRUSTREC *rec );
|
||||
ulong tdbio_new_recnum(void);
|
||||
int tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec );
|
||||
int tdbio_update_sigflag( ulong lid, int sigflag );
|
||||
|
266
g10/trustdb.c
266
g10/trustdb.c
@ -259,7 +259,7 @@ walk_sigrecs( SIGREC_CONTEXT *c, int create )
|
||||
rc = build_sigrecs( c->local_id );
|
||||
if( rc ) {
|
||||
if( rc == G10ERR_BAD_CERT )
|
||||
rc = -1; /* maybe no selcficnature */
|
||||
rc = -1; /* maybe no selfsignature */
|
||||
if( rc != -1 )
|
||||
log_info(_("%lu: error building sigs on the fly: %s\n"),
|
||||
c->local_id, g10_errstr(rc) );
|
||||
@ -1441,6 +1441,31 @@ query_trust_record( PKT_public_key *pk )
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* helper function for insert_trust_record()
|
||||
*/
|
||||
static void
|
||||
rel_mem_uidnode( u32 *keyid, int err, TRUSTREC *rec )
|
||||
{
|
||||
TRUSTREC *r, *r2;
|
||||
|
||||
if( err )
|
||||
log_error("key %08lX, uid %02X%02X: invalid user id - removed\n",
|
||||
(ulong)keyid[1], rec->r.uid.namehash[18], rec->r.uid.namehash[19] );
|
||||
for(r=rec->help_pref; r; r = r2 ) {
|
||||
r2 = r->next;
|
||||
m_free(r);
|
||||
}
|
||||
for(r=rec->help_sig; r; r = r2 ) {
|
||||
r2 = r->next;
|
||||
m_free(r);
|
||||
}
|
||||
|
||||
m_free(rec);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Insert a trust record into the TrustDB
|
||||
* This function fails if this record already exists.
|
||||
@ -1448,17 +1473,20 @@ query_trust_record( PKT_public_key *pk )
|
||||
int
|
||||
insert_trust_record( PKT_public_key *orig_pk )
|
||||
{
|
||||
TRUSTREC dirrec, *rec;
|
||||
TRUSTREC **keylist_tail, *keylist;
|
||||
TRUSTREC **uidlist_tail, *uidlist;
|
||||
TRUSTREC dirrec, *rec, *rec2;
|
||||
TRUSTREC *keylist_head, **keylist_tail;
|
||||
TRUSTREC *uidlist_head, **uidlist_tail, uidlist;
|
||||
KBNODE keyblock = NULL;
|
||||
KBNODE node;
|
||||
u32 keyid[2];
|
||||
u32 keyid[2]; /* of primary key */
|
||||
ulong knum, dnum;
|
||||
byte *fingerprint;
|
||||
size_t fingerlen;
|
||||
int rc = 0;
|
||||
|
||||
/* prepare dir record */
|
||||
memset( &dirrec, 0, sizeof dirrec );
|
||||
dirrec.rectype = RECTYPE_DIR;
|
||||
|
||||
if( orig_pk->local_id )
|
||||
log_bug("pk->local_id=%lu\n", (ulong)pk->local_id );
|
||||
@ -1474,124 +1502,190 @@ insert_trust_record( PKT_public_key *orig_pk )
|
||||
if( rc ) { /* that should never happen */
|
||||
log_error( "insert_trust_record: keyblock not found: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* prepare dir record */
|
||||
memset( &dirrec, 0, sizeof dirrec );
|
||||
dirrec.rectype = RECTYPE_DIR;
|
||||
dirrec.r.dir.lid = tdbio_new_recnum();
|
||||
|
||||
keylist = NULL;
|
||||
keylist_tail = &dirrec.r.dir.keylist;
|
||||
/* build data structure as linked lists in memory */
|
||||
keylist_head = NULL; keylist_tail = &keylist_head;
|
||||
uidlist_head = NULL; uidlist_tail = &uidlist_head;
|
||||
uidlist = NULL;
|
||||
uidlist_tail = &dirrec.r.dir.uidlist;
|
||||
/* loop over the keyblock */
|
||||
keyid[0] = keyid[1] = 0;
|
||||
for( node=keyblock; node; node = node->next ) {
|
||||
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
|
||||
PKT_public_key *pk = node->pkt->pkt.public_key;
|
||||
|
||||
if( keylist && node->pkt->pkttype == PKT_PUBLIC_KEY )
|
||||
BUG(); /* more than one primary key */
|
||||
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
|
||||
if( keylist_head )
|
||||
BUG(); /* more than one primary key */
|
||||
keyid_from_pk( pk, keyid );
|
||||
}
|
||||
fingerprint = fingerprint_from_pk( orig_pk, &fingerlen );
|
||||
rec = m_alloc_clear( sizeof *rec );
|
||||
rec->rectype = RECTYPE_KEY;
|
||||
rec->r.key.pubkey_algo = pk->pubkey_algo;
|
||||
rec->r.key.fingerprint_len = fingerlen;
|
||||
memcpy(rec->r.key.fingerprint, fingerprint, fingerlen );
|
||||
|
||||
if( keylist )
|
||||
keylist_tail = &keylist->next;
|
||||
*keylist_tail = keylist = rec;
|
||||
*keylist_tail = rec; keylist_tail = &rec->next;
|
||||
}
|
||||
else if( node->pkt->pkttype == PKT_USER_ID ) {
|
||||
PKT_user_id *uid = node->pkt->pkt.user_id;
|
||||
|
||||
rec = m_alloc_clear( sizeof *rec );
|
||||
rec->rectype = RECTYPE_UID;
|
||||
rmd160_hash_buffer( rec->r.uid.namehash, uid->name, uid->len );
|
||||
|
||||
if( uidlist )
|
||||
uidlist_tail = &uidlist->next;
|
||||
*uidlist_tail = uidlist = rec;
|
||||
uidlist = rec;
|
||||
*uidlist_tail = rec; uidlist_tail = &rec->next;
|
||||
}
|
||||
if( node->pkt->pkttype == PKT_SIGNATURE
|
||||
&& ( (node->pkt->pkt.signature->sig_class&~3) == 0x10
|
||||
|| node->pkt->pkt.signature->sig_class == 0x20
|
||||
|| node->pkt->pkt.signature->sig_class == 0x30) ) {
|
||||
int selfsig;
|
||||
rc = check_key_signature( keyblock, node, &selfsig );
|
||||
if( !rc ) {
|
||||
rc = set_signature_packets_local_id( node->pkt->pkt.signature );
|
||||
if( rc )
|
||||
log_fatal("set_signature_packets_local_id failed: %s\n",
|
||||
g10_errstr(rc));
|
||||
if( selfsig ) {
|
||||
node->flag |= 2; /* mark signature valid */
|
||||
*selfsig_okay = 1;
|
||||
}
|
||||
else if( node->pkt->pkt.signature->sig_class == 0x20 )
|
||||
*revoked = 1;
|
||||
else
|
||||
node->flag |= 1; /* mark signature valid */
|
||||
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
PKT_signature *sig = node->pkt->pkt.signature;
|
||||
|
||||
if( node->pkt->pkt.signature->sig_class != 0x20 ) {
|
||||
if( !dups )
|
||||
dups = new_lid_table();
|
||||
if( ins_lid_table_item( dups,
|
||||
node->pkt->pkt.signature->local_id, 0) )
|
||||
node->flag |= 4; /* mark as duplicate */
|
||||
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
|
||||
&& (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
|
||||
/* must verify this selfsignature here, so that we can
|
||||
* build the preference record and validate the uid record
|
||||
*/
|
||||
if( !uidlist ) {
|
||||
log_error("key %08lX: self-signature without user id\n",
|
||||
(ulong)keyid[1] );
|
||||
}
|
||||
else if( (rc = check_key_signature( keyblock, node, NULL ))) {
|
||||
log_error("key %08lX, uid %02X%02X: "
|
||||
"invalid self-signature: %s\n",
|
||||
(ulong)keyid[1], uidlist->namehash[18],
|
||||
uidlist->namehash[19], g10_errstr(rc) );
|
||||
rc = 0;
|
||||
}
|
||||
else { /* build the prefrecord */
|
||||
assert(uidlist);
|
||||
uidlist->mark |= 1; /* mark valid */
|
||||
}
|
||||
}
|
||||
if( DBG_TRUST )
|
||||
log_debug("trustdb: sig from %08lX.%lu: %s%s\n",
|
||||
(ulong)node->pkt->pkt.signature->keyid[1],
|
||||
node->pkt->pkt.signature->local_id,
|
||||
g10_errstr(rc), (node->flag&4)?" (dup)":"" );
|
||||
else if( 0 /* is revocation sig etc */ ) {
|
||||
/* handle it here */
|
||||
}
|
||||
else { /* not a selfsignature */
|
||||
/* put all this sigs into a list and mark them as unchecked
|
||||
* we can't check here because we probably have not
|
||||
* all keys of other signators - we do it on deman
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
knum = tdbio_new_recnum();
|
||||
/* build dir record */
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.rectype = RECTYPE_DIR;
|
||||
rec.r.dir.local_id = dnum;
|
||||
rec.r.dir.keyid[0] = keyid[0];
|
||||
rec.r.dir.keyid[1] = keyid[1];
|
||||
rec.r.dir.keyrec = knum;
|
||||
rec.r.dir.no_sigs = 0;
|
||||
/* and the key record */
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.rectype = RECTYPE_KEY;
|
||||
rec.r.key.owner = dnum;
|
||||
rec.r.key.keyid[0] = keyid[0];
|
||||
rec.r.key.keyid[1] = keyid[1];
|
||||
rec.r.key.pubkey_algo = pk->pubkey_algo;
|
||||
rec.r.key.fingerprint_len = fingerlen;
|
||||
memcpy(rec.r.key.fingerprint, fingerprint, fingerlen );
|
||||
rec.r.key.ownertrust = 0;
|
||||
if( tdbio_write_record( knum, &rec ) ) {
|
||||
log_error("wrinting key record failed\n");
|
||||
return G10ERR_TRUSTDB;
|
||||
/* delete all invalid marked userids and their preferences and sigs */
|
||||
/* (ugly code - I know) */
|
||||
while( (rec=uidlist_head) && !(rec->mark & 1) ) {
|
||||
uidlist_head = rec->next;
|
||||
rel_mem_uidnode(keyid, 1, rec);
|
||||
}
|
||||
for( ; rec; rec = rec->next ) {
|
||||
if( rec->next && !(rec->next->mark & 1) ) {
|
||||
TRUSTREC *r = rec->next;
|
||||
rec->next = r->next;
|
||||
rel_mem_uidnode(keyid, 1, r);
|
||||
}
|
||||
}
|
||||
|
||||
/* check that we have at least one userid */
|
||||
if( !uidlist_head ) {
|
||||
log_error("key %08lX: no user ids - rejected\n", (ulong)keyid[1] );
|
||||
rc = G10ERR_BAD_CERT,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* insert the record numbers to build the real (on disk) list */
|
||||
/* fixme: should start a transaction here */
|
||||
dirrec.recnum = tdbio_new_recnum();
|
||||
dirrec.r.dir.lid = dirrec.recnum;
|
||||
/* fixme: how do we set sigflag???*/
|
||||
/* (list of keys) */
|
||||
for(rec=keylist_head; rec; rec = rec->next ) {
|
||||
rec->r.key.lid = dirrec.recnum;
|
||||
rec->recnum = tdbio_new_recnum();
|
||||
}
|
||||
for(rec=keylist_head; rec; rec = rec->next )
|
||||
rec->r.key.next = rec->next? rec->next->recnum : 0;
|
||||
dirrec.r.dir.keylist = keylist_head->recnum;
|
||||
/* (list of user ids) */
|
||||
for(rec=uidlist_head; rec; rec = rec->next ) {
|
||||
rec->r.uid.lid = dirrec.recnum;
|
||||
rec->recnum = tdbio_new_recnum();
|
||||
/* (preference records) */
|
||||
for( rec2 = rec->help_pref; rec2; rec2 = rec2->next ) {
|
||||
rec2->r.pref.lid = dirrec.recnum;
|
||||
rec2->recnum = tdbio_new_recnum();
|
||||
}
|
||||
for( rec2 = rec->help_pref; rec2; rec2 = rec2->next )
|
||||
rec2->r.pref.next = rec2->next? rec2->next->recnum : 0;
|
||||
rec->r.uid.prefrec = rec->help_pref->recnum;
|
||||
/* (signature list) */
|
||||
for( rec2 = rec->help_sig; rec2; rec2 = rec2->next ) {
|
||||
rec2->r.sig.lid = dirrec.recnum;
|
||||
rec2->recnum = tdbio_new_recnum();
|
||||
}
|
||||
for( rec2 = rec->help_sig; rec2; rec2 = rec2->next )
|
||||
rec2->r.sig.next = rec2->next? rec2->next->recnum : 0;
|
||||
rec->r.uid.siglist = rec->help_sig->recnum;
|
||||
}
|
||||
for(rec=uidlist_head; rec; rec = rec->next )
|
||||
rec->r.uid.next = rec->next? rec->next->recnum : 0;
|
||||
dirrec.r.dir.uidlist = uidlist_head->recnum;
|
||||
|
||||
/* write all records */
|
||||
for(rec=keylist_head; rec; rec = rec->next ) {
|
||||
assert( rec->rectype == RECTYPE_KEY );
|
||||
if( tdbio_write_record( rec ) ) {
|
||||
log_error("writing key record failed\n");
|
||||
rc = G10ERR_TRUSTDB;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
for(rec=uidlist_head; rec; rec = rec->next ) {
|
||||
assert( rec->rectype == RECTYPE_UID );
|
||||
if( tdbio_write_record( rec ) ) {
|
||||
log_error("writing uid record failed\n");
|
||||
rc = G10ERR_TRUSTDB;
|
||||
goto leave;
|
||||
}
|
||||
for( rec2=rec->help_pref; rec2; rec2 = rec2->next ); {
|
||||
assert( rec2->rectype == RECTYPE_PREF );
|
||||
if( tdbio_write_record( rec2 ) ) {
|
||||
log_error("writing pref record failed\n");
|
||||
rc = G10ERR_TRUSTDB;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
for( rec2=rec->help_sig; rec2; rec2 = rec2->next ); {
|
||||
assert( rec2->rectype == RECTYPE_SIG );
|
||||
if( tdbio_write_record( rec2 ) ) {
|
||||
log_error("writing sig record failed\n");
|
||||
rc = G10ERR_TRUSTDB;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( tdbio_write_record( dirrec.r.dir.lid, &dirrec ) ) {
|
||||
log_error("writing dir record failed\n");
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
|
||||
/* and store the LID */
|
||||
orig_pk->local_id = dnum;
|
||||
orig_pk->local_id = dirrec.r.dir.lid;
|
||||
|
||||
return 0;
|
||||
leave:
|
||||
for( rec=dirrec.r.dir.uidlist; rec; rec = rec2 ) {
|
||||
rec2 = rec->next;
|
||||
rel_mem_uidnode(rec);
|
||||
}
|
||||
for( rec=dirrec.r.dir.keylist; rec; rec = rec2 ) {
|
||||
rec2 = rec->next;
|
||||
m_free(rec);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
BIN
tools/mk-tdata
BIN
tools/mk-tdata
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user