sync
authorWerner Koch <wk@gnupg.org>
Wed, 15 Jul 1998 18:05:01 +0000 (18:05 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 15 Jul 1998 18:05:01 +0000 (18:05 +0000)
TODO
g10/keydb.h
g10/sig-check.c
g10/tdbio.c
g10/tdbio.h
g10/trustdb.c
tools/mk-tdata

diff --git a/TODO b/TODO
index b5cd734..73ed027 100644 (file)
--- a/TODO
+++ b/TODO
@@ -4,6 +4,9 @@
 
     * invalid packets (Marco)
 
 
     * 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
     * what about the CR,LF in cleartext singatures?
 
     * add option --restore-ownertrust
index a039809..51da9a6 100644 (file)
@@ -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 );
 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 --*/
 byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
 
 /*-- kbnode.c --*/
index f600a4d..1dda445 100644 (file)
@@ -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
 /****************
  * 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 )
  */
 int
 check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
index 425e51c..9355f4c 100644 (file)
@@ -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;
     }
        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 ) {
     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
 
 /****************
  * Write the record at RECNUM
+ * FIXME: create/update keyhash record.
  */
 int
  */
 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;
 {
     byte buf[TRUST_RECORD_LEN], *p;
     int rc = 0;
     int i, n;
+    ulong recnum = rec->recnum;
 
     if( db_fd == -1 )
        open_db();
 
     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.
  * 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 )
  */
 int
 tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec )
index 7229d72..2d28131 100644 (file)
 
 struct trust_record {
     int  rectype;
 
 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 */
     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 */
        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;
            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 );
 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 );
 ulong tdbio_new_recnum(void);
 int tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec );
 int tdbio_update_sigflag( ulong lid, int sigflag );
index 593e12c..b2e478c 100644 (file)
@@ -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 = 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) );
                    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.
 /****************
  * 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 )
 {
 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;
     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;
 
     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 );
 
     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) );
     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 = 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;
 
     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 );
            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 );
 
            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 );
        }
        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 );
 
            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 */
     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;
 }
 
 
 }
 
 
index 3b9e1c0..7fcfb38 100755 (executable)
Binary files a/tools/mk-tdata and b/tools/mk-tdata differ