aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>1998-07-15 18:05:01 +0000
committerWerner Koch <[email protected]>1998-07-15 18:05:01 +0000
commit3c53ea75ced5879589287e63617b133adc237f05 (patch)
tree44cce123387f3e9eeba8f0518f886e330e7a46fa
parentsync (diff)
downloadgnupg-3c53ea75ced5879589287e63617b133adc237f05.tar.gz
gnupg-3c53ea75ced5879589287e63617b133adc237f05.zip
sync
-rw-r--r--TODO3
-rw-r--r--g10/keydb.h2
-rw-r--r--g10/sig-check.c2
-rw-r--r--g10/tdbio.c6
-rw-r--r--g10/tdbio.h10
-rw-r--r--g10/trustdb.c264
-rwxr-xr-xtools/mk-tdatabin35443 -> 11769 bytes
7 files changed, 196 insertions, 91 deletions
diff --git a/TODO b/TODO
index b5cd73422..73ed027fb 100644
--- a/TODO
+++ b/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
diff --git a/g10/keydb.h b/g10/keydb.h
index a0398092a..51da9a628 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -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 --*/
diff --git a/g10/sig-check.c b/g10/sig-check.c
index f600a4d1e..1dda44529 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.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 )
diff --git a/g10/tdbio.c b/g10/tdbio.c
index 425e51cbb..9355f4c6e 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -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 )
diff --git a/g10/tdbio.h b/g10/tdbio.h
index 7229d7222..2d28131cd 100644
--- a/g10/tdbio.h
+++ b/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 );
diff --git a/g10/trustdb.c b/g10/trustdb.c
index 593e12cd2..b2e478ceb 100644
--- a/g10/trustdb.c
+++ b/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->pkttype == PKT_SIGNATURE ) {
+ PKT_signature *sig = node->pkt->pkt.signature;
+
+ 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( node->pkt->pkt.signature->sig_class == 0x20 )
- *revoked = 1;
- else
- node->flag |= 1; /* mark signature valid */
-
- 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 */
+ 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
+ */
+ }
}
}
+ /* 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);
+ }
+ }
-
-
-
-
-
-
-
-
- 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;
+ /* 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;
}
diff --git a/tools/mk-tdata b/tools/mk-tdata
index 3b9e1c016..7fcfb389f 100755
--- a/tools/mk-tdata
+++ b/tools/mk-tdata
Binary files differ