overhauled the trustdb stuff
authorWerner Koch <wk@gnupg.org>
Thu, 5 Nov 1998 18:00:08 +0000 (18:00 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 5 Nov 1998 18:00:08 +0000 (18:00 +0000)
doc/FAQ
g10/trustdb.c

diff --git a/doc/FAQ b/doc/FAQ
index f82f298..2108073 100644 (file)
--- a/doc/FAQ
+++ b/doc/FAQ
      For more see the chapter "The Web of Trust" in the
      Manual [gpg: Oops: Internal error: manual not found - sorry]
 
-
-
+  Q: How do interpret some of the informational outputs:
+  A: While checking the validness of a key, GnuPG sometimes print
+     some informations which are prefixed with information about
+     the checked item:
+       "key 12345678.3456"
+     This is about the key with key ID 12345678 and the internal
+     number 3456, which is the record number of the so called
+     directory record in the trustdb.
+       "uid 12345678.3456/ACDE"
+     This is about the user ID for the same key; to identify the
+     user ID the last two bytes of a ripe-md-160 over the user ID
+     tring is printed.
+       "sig 12345678.3456/ACDE/9A8B7C6D"
+     This is about the signature with key ID 9A8B7C6D for the
+     above key and user ID, if it is a signature which is direct
+     on a key, the user ID part is empty (..//..).
 
index 43903a9..cc768d5 100644 (file)
@@ -98,6 +98,11 @@ static int list_sigs( ulong pubkey_id );
 static int do_check( TRUSTREC *drec, unsigned *trustlevel );
 static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec );
 
+static void upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig );
+static void upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
+                TRUSTREC *drec, RECNO_LIST *recno_list, int recheck,
+                TRUSTREC *urec, const byte *uidhash, int revoke );
+
 
 /* a table used to keep track of ultimately trusted keys
  * which are the ones from our secrings */
@@ -769,7 +774,12 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
 
        read_record( rn, &rec, RECTYPE_UID );
        uidrn = rec.r.uid.next;
-       /* fixme: continue if the uidrec is not marked valid */
+       if( !(rec.r.uid.uidflags & UIDF_CHECKED) )
+           continue; /* user id has not been checked */
+       if( !(rec.r.uid.uidflags & UIDF_VALID) )
+           continue; /* user id is not valid */
+       if( (rec.r.uid.uidflags & UIDF_REVOKED) )
+           continue; /* user id has been revoked */
 
        /* loop over all signature records */
        for( rn = rec.r.uid.siglist; rn; rn = sigrn ) {
@@ -1650,6 +1660,7 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
     PKT_signature *sigpkt = NULL;
     TRUSTREC tmp;
     u32 sigkid[2];
+    int revoke = 0;
 
     if( sigrec->r.sig.sig[sigidx].flag & SIGF_CHECKED )
        log_info(_("note: sig rec %lu[%d] in hintlist "
@@ -1664,7 +1675,7 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
     if( tmp.rectype != RECTYPE_DIR ) {
        /* we need the dir record */
        log_error(_("sig rec %lu[%d] in hintlist "
-                   "of %u does not point to a dir record\n"),
+                   "of %lu does not point to a dir record\n"),
                    sigrec->recnum, sigidx, hint_owner );
        return;
     }
@@ -1693,7 +1704,8 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
            sigpkt = node->pkt->pkt.signature;
            if( sigpkt->keyid[0] == sigkid[0]
                && sigpkt->keyid[1] == sigkid[1]
-               && (sigpkt->sig_class&~3) == 0x10 ) {
+               && ( (sigpkt->sig_class&~3) == 0x10
+                    || ( revoke = (sigpkt->sig_class == 0x30)) ) ) {
                state = 2;
                break; /* found */
            }
@@ -1715,23 +1727,29 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
        log_error(_("lid %lu: self-signature in hintlist\n"), lid );
        return;
     }
+
+    /* FiXME: handling fo SIGF_REVOKED is not correct! */
+
     if( !rc ) { /* valid signature */
        if( opt.verbose )
-           log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
-                      "Good signature (3)\n"),
+           log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
                    (ulong)keyid[1], lid, uhash[18], uhash[19],
-                   (ulong)sigpkt->keyid[1] );
+                   (ulong)sigpkt->keyid[1],
+                   revoke? _("Valid certificate revocation")
+                         : _("Good certificate") );
        sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED | SIGF_VALID;
+       if( revoke )
+           sigrec->r.sig.sig[sigidx].flag |= SIGF_REVOKED;
     }
     else if( rc == G10ERR_NO_PUBKEY ) {
-       log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
-                  "very strange: no public key\n"),
+       log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
              (ulong)keyid[1], lid, uhash[18], uhash[19],
-              (ulong)sigpkt->keyid[1] );
+              (ulong)sigpkt->keyid[1],
+                _("very strange: no public key\n") );
        sigrec->r.sig.sig[sigidx].flag = SIGF_NOPUBKEY;
     }
     else {
-       log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: %s\n"),
+       log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
                    (ulong)keyid[1], lid, uhash[18], uhash[19],
                    (ulong)sigpkt->keyid[1], g10_errstr(rc) );
        sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED;
@@ -1923,8 +1941,8 @@ upd_key_record( KBNODE keyblock, KBNODE keynode, u32 *keyid,
 {
     TRUSTREC krec;
     KBNODE  node;
-    PKT_public_key *pk = keynode->pkt->pkt.public_key,;
-    ulon lid = drec->recnum;
+    PKT_public_key *pk = keynode->pkt->pkt.public_key;
+    ulong lid = drec->recnum;
     byte fpr[MAX_FINGERPRINT_LEN];
     size_t fprlen;
     ulong recno, newrecno;
@@ -1982,75 +2000,78 @@ upd_key_record( KBNODE keyblock, KBNODE keynode, u32 *keyid,
     }
 
     for( node=keynode->next; node; node = node->next ) {
+       PKT_signature *sig;
+
        if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
            break; /* ready */
-       else if( node->pkt->pkttype == PKT_PUBLIC_SIGNATURE ) {
-           PKT_signature *sig = node->pkt->pkt.signature;
+       else if( node->pkt->pkttype != PKT_SIGNATURE )
+           continue;
 
-           if( keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1] )
-               continue; /* not a self signature */
-           if( sig->sig_class == 0x18 && !keybind_seen ) { /* a keybinding */
-               if( keynode->pkt->pkttype == PKT_PUBLIC_KEY )
-                   continue; /* oops, not for a main key */
-               /* we check until we find a valid keybinding */
-               rc = check_key_signature( keyblock, node, NULL );
-               if( !rc ) {
-                   if( opt.verbose )
-                       log_info(_(
-                           "key %08lX.%lu: Good subkey binding\n"),
-                            (ulong)keyid_from_pk(pk,NULL), lid );
-                   krec.r.key.keyflags |= KEYF_CHECKED | KEYF_VALID;
-               }
-               else {
+       sig = node->pkt->pkt.signature;
+
+       if( keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1] )
+           continue; /* not a self signature */
+       if( sig->sig_class == 0x18 && !keybind_seen ) { /* a keybinding */
+           if( keynode->pkt->pkttype == PKT_PUBLIC_KEY )
+               continue; /* oops, not for a main key */
+           /* we check until we find a valid keybinding */
+           rc = check_key_signature( keyblock, node, NULL );
+           if( !rc ) {
+               if( opt.verbose )
                    log_info(_(
-                     "key %08lX.%lu: Invalid subkey binding: %s\n"),
-                       (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
-                   krec.r.key.keyflags |= KEYF_CHECKED;
-                   krec.r.key.keyflags &= ~KEYF_VALID;
-               }
-               keybind_seen = 1;
+                       "key %08lX.%lu: Good subkey binding\n"),
+                        (ulong)keyid_from_pk(pk,NULL), lid );
+               krec.r.key.keyflags |= KEYF_CHECKED | KEYF_VALID;
            }
-           else if( sig->sig_class == 0x20 && !revoke_seen ) {
-               if( keynode->pkt->pkttype == PKT_PUBLIC_SUBKEY )
-                   continue; /* a subkey is not expected here */
-               /* This is a key revocation certificate: check it */
-               rc = check_key_signature( keyblock, node, NULL );
-               if( !rc ) {
-                   if( opt.verbose )
-                       log_info(_(
-                           "key %08lX.%lu: Valid key revocation\n"),
-                            (ulong)keyid_from_pk(pk,NULL), lid );
-                   krec.r.key.keyflags |= KEYF_REVOKED;
-               }
-               else {
+           else {
+               log_info(_(
+                 "key %08lX.%lu: Invalid subkey binding: %s\n"),
+                   (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
+               krec.r.key.keyflags |= KEYF_CHECKED;
+               krec.r.key.keyflags &= ~KEYF_VALID;
+           }
+           keybind_seen = 1;
+       }
+       else if( sig->sig_class == 0x20 && !revoke_seen ) {
+           if( keynode->pkt->pkttype == PKT_PUBLIC_SUBKEY )
+               continue; /* a subkey is not expected here */
+           /* This is a key revocation certificate: check it */
+           rc = check_key_signature( keyblock, node, NULL );
+           if( !rc ) {
+               if( opt.verbose )
                    log_info(_(
-                     "key %08lX.%lu: Invalid key revocation: %s\n"),
-                     (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
-               }
-               revoke_seen = 1;
+                       "key %08lX.%lu: Valid key revocation\n"),
+                        (ulong)keyid_from_pk(pk,NULL), lid );
+               krec.r.key.keyflags |= KEYF_REVOKED;
            }
-           else if( sig->sig_class == 0x28 && !revoke_seen ) {
-               if( keynode->pkt->pkttype == PKT_PUBLIC_KEY )
-                   continue; /* a mainkey is not expected here */
-               /* This is a subkey revocation certificate: check it */
-               /* fixme: we should also check the revocation
-                * is newer tha the key (OpenPGP) */
-               rc = check_key_signature( keyblock, node, NULL );
-               if( !rc ) {
-                   if( opt.verbose )
-                       log_info(_(
-                           "key %08lX.%lu: Valid subkey revocation\n"),
-                            (ulong)keyid_from_pk(pk,NULL), lid );
-                   krec.r.key.keyflags |= KEYF_REVOKED;
-               }
-               else {
+           else {
+               log_info(_(
+                 "key %08lX.%lu: Invalid key revocation: %s\n"),
+                 (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
+           }
+           revoke_seen = 1;
+       }
+       else if( sig->sig_class == 0x28 && !revoke_seen ) {
+           if( keynode->pkt->pkttype == PKT_PUBLIC_KEY )
+               continue; /* a mainkey is not expected here */
+           /* This is a subkey revocation certificate: check it */
+           /* fixme: we should also check the revocation
+            * is newer than the key (OpenPGP) */
+           rc = check_key_signature( keyblock, node, NULL );
+           if( !rc ) {
+               if( opt.verbose )
                    log_info(_(
-                     "key %08lX.%lu: Invalid subkey binding: %s\n"),
-                     (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
-               }
-               revoke_seen = 1;
+                       "key %08lX.%lu: Valid subkey revocation\n"),
+                        (ulong)keyid_from_pk(pk,NULL), lid );
+               krec.r.key.keyflags |= KEYF_REVOKED;
            }
-       } /* end signature */
+           else {
+               log_info(_(
+                 "key %08lX.%lu: Invalid subkey binding: %s\n"),
+                 (ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
+           }
+           revoke_seen = 1;
+       }
     }
 
     write_record( &krec );
@@ -2076,22 +2097,24 @@ upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid,
     ulong lid = drec->recnum;
     PKT_user_id *uid = uidnode->pkt->pkt.user_id;
     TRUSTREC urec;
+    PKT_signature *selfsig = NULL;
     byte uidhash[20];
+    KBNODE node;
     ulong recno, newrecno;
+    int rc;
 
     /* see whether we already have an uid record */
-  WORK WORK
     rmd160_hash_buffer( uidhash, uid->name, uid->len );
     for( recno=drec->r.dir.uidlist; recno; recno = urec.r.uid.next ) {
        read_record( recno, &urec, RECTYPE_UID );
        if( !memcmp( uidhash, urec.r.uid.namehash, 20 ) )
            break;
     }
-    if( recno ) {
+    if( recno ) { /* we already have this record */
        ins_recno_list( recno_list, recno, RECTYPE_UID );
-       *uidrecno = recno;
     }
     else { /* new user id */
+       recheck = 1;
        memset( &urec, 0 , sizeof(urec) );
        urec.rectype = RECTYPE_UID;
        urec.r.uid.lid = drec->recnum;
@@ -2105,131 +2128,229 @@ upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid,
            drec->dirty = 1;
        }
        else { /* we already have an uid, append it to the list */
+           TRUSTREC save = urec;
            for( ; recno; recno = urec.r.key.next )
                read_record( recno, &urec, RECTYPE_UID );
            urec.r.uid.next = newrecno;
            write_record( &urec );
+           urec = save;
        }
-       *uidrecno = newrecno;
     }
+
+    if( recheck || !(urec.r.uid.uidflags & UIDF_CHECKED) ) {
+       /* check self signatures */
+       urec.r.uid.uidflags = 0;
+       for( node=uidnode->next; node; node = node->next ) {
+           PKT_signature *sig;
+
+           if( node->pkt->pkttype == PKT_USER_ID )
+               break; /* ready */
+           if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
+               break; /* ready */
+           if( node->pkt->pkttype != PKT_SIGNATURE )
+               continue;
+
+           sig = node->pkt->pkt.signature;
+
+           if( keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1] )
+               continue; /* not a self signature */
+
+           if( (sig->sig_class&~3) == 0x10 ) { /* regular self signature */
+               rc = check_key_signature( keyblock, node, NULL );
+               if( !rc ) {
+                   if( opt.verbose )
+                       log_info( "uid %08lX.%lu/%02X%02X: %s\n",
+                          (ulong)keyid[1], lid, uidhash[18], uidhash[19],
+                                 _("Good self-signature") );
+                   urec.r.uid.uidflags |= UIDF_CHECKED | UIDF_VALID;
+                   if( !selfsig )
+                       selfsig = sig; /* use the first valid sig */
+               }
+               else {
+                   log_info( "uid %08lX/%02X%02X: %s: %s\n",
+                              (ulong)keyid[1], uidhash[18], uidhash[19],
+                             _("Invalid self-signature"),
+                              g10_errstr(rc) );
+                   urec.r.uid.uidflags |= UIDF_CHECKED;
+               }
+           }
+           else if( sig->sig_class == 0x30 ) { /* cert revocation */
+               rc = check_key_signature( keyblock, node, NULL );
+               if( !rc ) {
+                   if( opt.verbose )
+                       log_info( "uid %08lX.%lu/%02X%02X: %s\n",
+                          (ulong)keyid[1], lid, uidhash[18], uidhash[19],
+                                _("Valid user ID revocation\n") );
+                   urec.r.uid.uidflags |= UIDF_CHECKED | UIDF_VALID;
+                   urec.r.uid.uidflags |= UIDF_REVOKED;
+               }
+               else {
+                   log_info("uid %08lX/%02X%02X: %s: %s\n",
+                               (ulong)keyid[1], uidhash[18], uidhash[19],
+                              _("Invalid user ID revocation"),
+                                                       g10_errstr(rc) );
+               }
+           }
+       }
+       write_record( &urec );
+    } /* end check self-signatures */
+
+
+    if( (urec.r.uid.uidflags & (UIDF_CHECKED|UIDF_VALID))
+       != (UIDF_CHECKED|UIDF_VALID) )
+       return; /* user ID is not valid, so no need to check more things */
+
+    /* check the preferences */
+    if( selfsig )
+       upd_pref_record( &urec, keyid, selfsig );
+
+    /* check non-self signatures */
+    for( node=uidnode->next; node; node = node->next ) {
+       PKT_signature *sig;
+
+       if( node->pkt->pkttype == PKT_USER_ID )
+           break; /* ready */
+       if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
+           break; /* ready */
+       if( node->pkt->pkttype != PKT_SIGNATURE )
+           continue;
+
+       sig = node->pkt->pkt.signature;
+
+       if( keyid[0] == sig->keyid[0] || keyid[1] == sig->keyid[1] )
+           continue; /* skip self signature */
+
+       if( (sig->sig_class&~3) == 0x10 ) { /* regular certification */
+           upd_cert_record( keyblock, node, keyid, drec, recno_list,
+                            recheck, &urec, uidhash, 0 );
+       }
+       else if( sig->sig_class == 0x30 ) { /* cert revocation */
+           upd_cert_record( keyblock, node, keyid, drec, recno_list,
+                            recheck, &urec, uidhash, 1 );
+       }
+    } /* end check certificates */
+
+    write_record( &urec );
 }
 
 
+
+/****************
+ *
+ *
+ */
 static void
-upd_pref_record( PKT_signature *sig, ulong lid, const u32 *keyid,
-                               TRUSTREC *urec, const byte *uidhash )
+upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig )
 {
     static struct {
        sigsubpkttype_t subpkttype;
        int preftype;
-    } prefs[] = {
+    } ptable[] = {
        { SIGSUBPKT_PREF_SYM,   PREFTYPE_SYM    },
        { SIGSUBPKT_PREF_HASH,  PREFTYPE_HASH   },
        { SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR  },
        { 0, 0 }
     };
     TRUSTREC prec;
+    ulong lid = urec->r.uid.lid ;
+    const byte *uidhash = urec->r.uid.namehash;
     const byte *s;
     size_t n;
     int k, i;
-    ulong recno_tbl[10];
-    int recno_idx = 0;
     ulong recno;
+    byte prefs_sig[200];
+    int n_prefs_sig = 0;
+    byte prefs_rec[200];
+    int n_prefs_rec = 0;
+
+    /* check for changed preferences */
+    for(k=0; ptable[k].subpkttype; k++ ) {
+       s = parse_sig_subpkt2( sig, ptable[k].subpkttype, &n );
+       if( s ) {
+           if( n_prefs_sig >= DIM(prefs_sig)-1 ) {
+               log_info("uid %08lX.%lu/%02X%02X: %s\n",
+                         (ulong)keyid[1], lid, uidhash[18], uidhash[19],
+                         _("Too many preferences") );
+               break;
+           }
+           prefs_sig[n_prefs_sig++] = ptable[k].preftype;
+           prefs_sig[n_prefs_sig++] = *s;
+       }
+    }
+    for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) {
+       read_record( recno, &prec, RECTYPE_PREF );
+       for(i = 0; i < ITEMS_PER_PREF_RECORD; i +=2 )  {
+           if( n_prefs_rec >= DIM(prefs_rec)-1 ) {
+               log_info("uid %08lX.%lu/%02X%02X: %s\n",
+                         (ulong)keyid[1], lid, uidhash[18], uidhash[19],
+                         _("Too many preferences items") );
+               break;
+           }
+           prefs_rec[n_prefs_rec++] = prec.r.pref.data[i];
+           prefs_rec[n_prefs_rec++] = prec.r.pref.data[i+1];
+       }
+    }
+    if( n_prefs_sig == n_prefs_rec
+       && !memcmp( prefs_sig, prefs_rec, n_prefs_sig ) )
+       return;  /* not chnaged */
 
-    /* First delete all pref records
+    /* Preferences have changed:  Delete all pref records
      * This is much simpler than checking whether we have to
      * do update the record at all - the record cache may care about it
-     * FIXME: We never get correct statistics if we do it like this */
+     */
     for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) {
        read_record( recno, &prec, RECTYPE_PREF );
        delete_record( recno );
     }
 
-    /* and write the new ones */
-    i = 0;
-    for(k=0; prefs[k].subpkttype; k++ ) {
-       s = parse_sig_subpkt2( sig, prefs[k].subpkttype, &n );
-       if( s ) {
-           while( n ) {
-               if( !i || i >= ITEMS_PER_PREF_RECORD ) {
-                   if( recno_idx >= DIM(recno_tbl)-1 ) {
-                       log_info("too many preferences\n");
-                       break;
-                   }
-                   if( i ) {
-                       recno_tbl[recno_idx]=tdbio_new_recnum();
-                       prec.recnum = recno_tbl[recno_idx++];
-                       write_record( &prec );
-                   }
-                   memset( &prec, 0, sizeof prec );
-                   prec.rectype = RECTYPE_PREF;
-                   prec.r.pref.lid = lid;
-                   i = 0;
-               }
-               prec.r.pref.data[i++] = prefs[k].preftype;
-               prec.r.pref.data[i++] = *s++;
-               n--;
+    if( n_prefs_sig > ITEMS_PER_PREF_RECORD )
+       log_info("cannot yet handle long preferences");
+
+    memset( &prec, 0, sizeof prec );
+    prec.recnum = tdbio_new_recnum();
+    prec.rectype = RECTYPE_PREF;
+    prec.r.pref.lid = lid;
+    if( n_prefs_sig <= ITEMS_PER_PREF_RECORD )
+       memcpy( prec.r.pref.data, prefs_sig, n_prefs_sig );
+    else { /* need more than one pref record */
+       TRUSTREC tmp;
+       ulong nextrn;
+       int n = n_prefs_sig;
+       byte *pp = prefs_sig;
+
+       memcpy( prec.r.pref.data, pp, ITEMS_PER_PREF_RECORD );
+       n -= ITEMS_PER_PREF_RECORD;
+       pp += ITEMS_PER_PREF_RECORD;
+       nextrn = prec.r.pref.next = tdbio_new_recnum();
+       do {
+           memset( &tmp, 0, sizeof tmp );
+           tmp.recnum = nextrn;
+           tmp.rectype = RECTYPE_PREF;
+           tmp.r.pref.lid = lid;
+           if( n <= ITEMS_PER_PREF_RECORD ) {
+               memcpy( tmp.r.pref.data, pp, n );
+               n = 0;
            }
-       }
-    }
-    if( i ) { /* write the last one */
-       recno_tbl[recno_idx]=tdbio_new_recnum();
-       prec.recnum = recno_tbl[recno_idx++];
-       write_record( &prec );
-    }
-    /* now link them together */
-    for(i=0; i < recno_idx-1; i++ ) {
-       read_record( recno_tbl[i], &prec, RECTYPE_PREF );
-       prec.r.pref.next = recno_tbl[i+1];
-       write_record( &prec );
+           else {
+               memcpy( tmp.r.pref.data, pp, ITEMS_PER_PREF_RECORD );
+               n -= ITEMS_PER_PREF_RECORD;
+               pp += ITEMS_PER_PREF_RECORD;
+               nextrn = tmp.r.pref.next = tdbio_new_recnum();
+           }
+           write_record( &tmp );
+       } while( n );
     }
-    /* don't need to write the last one, but update the uid */
-    urec->r.uid.prefrec = recno_idx? recno_tbl[0] : 0;
+    write_record( &prec );
+    urec->r.uid.prefrec = prec.recnum;
     urec->dirty = 1;
 }
 
 
-/****************
- * update self key signatures (class 0x10..0x13)
- */
-static void
-upd_self_key_sigs( PKT_signature *sig, TRUSTREC *urec,
-                  ulong lid, const u32 *keyid,  const byte *uidhash,
-                  KBNODE keyblock, KBNODE signode)
-{
-    int rc;
-
-    /* must verify this selfsignature here, so that we can
-     * build the preference record and validate the uid record
-     */
-    if( !(urec->r.uid.uidflags & UIDF_CHECKED) ) {
-       rc = check_key_signature( keyblock, signode, NULL );
-       if( !rc ) {
-           if( opt.verbose )
-               log_info(_(
-                    "key %08lX.%lu, uid %02X%02X: Good self-signature\n"),
-                  (ulong)keyid[1], lid, uidhash[18], uidhash[19] );
-           upd_pref_record( sig, lid, keyid, urec, uidhash );
-           urec->r.uid.uidflags = UIDF_CHECKED | UIDF_VALID;
-       }
-       else {
-           log_info(_("key %08lX, uid %02X%02X: Invalid self-signature: %s\n"),
-                   (ulong)keyid[1], uidhash[18], uidhash[19], g10_errstr(rc) );
-           urec->r.uid.uidflags = UIDF_CHECKED;
-       }
-       urec->dirty = 1;
-    }
-}
-
-
 
-/****************
- * update non-self key signatures (class 0x10..0x13)
- */
 static void
-upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec,
-                     ulong lid, const u32 *keyid,  const byte *uidhash,
-                     KBNODE keyblock, KBNODE signode, int fast)
+upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
+                TRUSTREC *drec, RECNO_LIST *recno_list, int recheck,
+                TRUSTREC *urec, const byte *uidhash, int revoke )
 {
     /* We simply insert the signature into the sig records but
      * avoid duplicate ones.  We do not check them here because
@@ -2240,6 +2361,8 @@ upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec,
      * be converted to a dir record as soon as a new public key is
      * inserted into the trustdb.
      */
+    ulong lid = drec->recnum;
+    PKT_signature *sig = signode->pkt->pkt.signature;
     TRUSTREC rec;
     ulong recno;
     TRUSTREC delrec;
@@ -2294,19 +2417,19 @@ upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec,
            }
            if( rec.r.sig.sig[i].lid == pk_lid ) {
                if( found_sig ) {
-                   log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
-                              "duplicated signature - deleted\n"),
-                         (ulong)keyid[1], lid, uidhash[18],
-                          uidhash[19], (ulong)sig->keyid[1] );
+                   log_info( "sig %08lX.%lu/%02X%02X/%08lX: %s\n",
+                             (ulong)keyid[1], lid, uidhash[18],
+                              uidhash[19], (ulong)sig->keyid[1],
+                            _("Duplicated certificate - deleted") );
                    rec.r.sig.sig[i].lid = 0;
                    rec.dirty = 1;
                    continue;
                }
                found_sig = 1;
            }
-           if( fast && (rec.r.sig.sig[i].flag & SIGF_CHECKED) )
+           if( !recheck && !revoke && (rec.r.sig.sig[i].flag & SIGF_CHECKED) )
                continue; /* we already checked this signature */
-           if( fast && (rec.r.sig.sig[i].flag & SIGF_NOPUBKEY) )
+           if( !recheck && (rec.r.sig.sig[i].flag & SIGF_NOPUBKEY) )
                continue; /* we do not have the public key */
 
            read_record( rec.r.sig.sig[i].lid, &tmp, 0 );
@@ -2315,28 +2438,35 @@ upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec,
                rc = check_key_signature( keyblock, signode, NULL );
                if( !rc ) { /* valid signature */
                    if( opt.verbose )
-                       log_info(_(
-                              "key %08lX.%lu, uid %02X%02X, sig %08lX: "
-                              "Good signature (1)\n"),
+                       log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
                                (ulong)keyid[1], lid, uidhash[18],
-                               uidhash[19], (ulong)sig->keyid[1] );
+                               uidhash[19], (ulong)sig->keyid[1],
+                               revoke? _("Valid certificate revocation")
+                                     : _("Good certificate") );
                    rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID;
+                   if( revoke )
+                       rec.r.sig.sig[i].flag |= SIGF_REVOKED;
                }
                else if( rc == G10ERR_NO_PUBKEY ) {
                    if( (rec.r.sig.sig[i].flag & SIGF_CHECKED) )
-                       log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
-                                  "public key lost\n"),
+                       log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
                                  (ulong)keyid[1], lid, uidhash[18],
-                                uidhash[19], (ulong)sig->keyid[1] );
+                                uidhash[19], (ulong)sig->keyid[1],
+                                _("public key lost") );
                    rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
+                   if( revoke )
+                       rec.r.sig.sig[i].flag |= SIGF_REVOKED;
                }
                else {
-                   log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX:"
-                              " %s\n"),
+                   log_info("sig %08lX.%lu/%02X%02X/%08lX: %s: %s\n",
                                (ulong)keyid[1], lid, uidhash[18],
                                uidhash[19], (ulong)sig->keyid[1],
+                               revoke? _("Invalid certificate revocation")
+                                     : _("Invalid certificate"),
                                                    g10_errstr(rc));
                    rec.r.sig.sig[i].flag = SIGF_CHECKED;
+                   if( revoke )
+                       rec.r.sig.sig[i].flag |= SIGF_REVOKED;
                }
                rec.dirty = 1;
            }
@@ -2347,11 +2477,13 @@ upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec,
                    && (!tmp.r.sdir.pubkey_algo
                         || tmp.r.sdir.pubkey_algo == sig->pubkey_algo )) {
                    if( !(rec.r.sig.sig[i].flag & SIGF_NOPUBKEY) )
-                       log_info(_("key %08lX.%lu, uid %02X%02X: "
-                                  "has shadow dir %lu but not yet marked.\n"),
+                       log_info("uid %08lX.%lu/%02X%02X: "
+                                "has shadow dir %lu but not yet marked.\n",
                                (ulong)keyid[1], lid,
                                uidhash[18], uidhash[19], tmp.recnum );
                    rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
+                   if( revoke )
+                       rec.r.sig.sig[i].flag |= SIGF_REVOKED;
                    rec.dirty = 1;
                    /* fixme: should we verify that the record is
                     * in the hintlist? - This case here should anyway
@@ -2388,31 +2520,40 @@ upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec,
 
     if( !rc ) { /* valid signature */
        if( opt.verbose )
-           log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
-                      "Good signature (2)\n"),
+           log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
                          (ulong)keyid[1], lid, uidhash[18],
-                          uidhash[19], (ulong)sig->keyid[1] );
+                          uidhash[19], (ulong)sig->keyid[1],
+                               revoke? _("Valid certificate revocation")
+                                     : _("Good certificate") );
        newlid = pk_lid;  /* this is the pk of the signature */
        newflag = SIGF_CHECKED | SIGF_VALID;
+       if( revoke )
+           newflag |= SIGF_REVOKED;
     }
     else if( rc == G10ERR_NO_PUBKEY ) {
        if( opt.verbose > 1 )
-           log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: "
-                      "no public key\n"),
-                         (ulong)keyid[1], lid, uidhash[18],
-                          uidhash[19], (ulong)sig->keyid[1] );
+           log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
+                    (ulong)keyid[1], lid, uidhash[18],
+                     uidhash[19], (ulong)sig->keyid[1], g10_errstr(rc) );
        newlid = create_shadow_dir( sig, lid );
        newflag = SIGF_NOPUBKEY;
+       if( revoke )
+           newflag |= SIGF_REVOKED;
     }
     else {
-       log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: %s\n"),
+       log_info( "sig %08lX.%lu/%02X%02X/%08lX: %s: %s\n",
                    (ulong)keyid[1], lid, uidhash[18], uidhash[19],
-                             (ulong)sig->keyid[1], g10_errstr(rc));
+                             (ulong)sig->keyid[1],
+               revoke? _("Invalid certificate revocation")
+                     : _("Invalid certificate"),
+                                           g10_errstr(rc));
        newlid = create_shadow_dir( sig, lid );
        newflag = SIGF_CHECKED;
+       if( revoke )
+           newflag |= SIGF_REVOKED;
     }
 
-    if( delrec.recnum ) { /* we can reuse a deleted slot */
+    if( delrec.recnum ) { /* we can reuse a deleted/unused slot */
        delrec.r.sig.sig[delrecidx].lid = newlid;
        delrec.r.sig.sig[delrecidx].flag= newflag;
        write_record( &delrec );
@@ -2434,80 +2575,6 @@ upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec,
 }
 
 
-
-/****************
- * Note: A signature made with a secondary key is not considered a
- *      self-signature.
- */
-static void
-upd_sig_record( PKT_signature *sig, TRUSTREC *drec,
-               u32 *keyid, ulong *uidrecno, byte *uidhash,
-               KBNODE keyblock, KBNODE signode, int fast)
-{
-    TRUSTREC urec;
-    ulong lid = drec->recnum;
-
-    if( !*uidrecno ) {
-       switch( sig->sig_class ) {
-         case 0x20:
-         case 0x28: /* We do not need uids for [sub]key revications */
-         case 0x18: /* or subkey binding */
-           memset( &urec, 0, sizeof urec ); /* to catch errors */
-           break;
-
-         default:
-           log_error("key %08lX: signature (class %02x) without user id\n",
-                                        (ulong)keyid[1], sig->sig_class );
-           return;
-       }
-    }
-    else
-       read_record( *uidrecno, &urec, RECTYPE_UID );
-
-    if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
-       if( (sig->sig_class&~3) == 0x10 ) {
-           upd_self_key_sigs( sig, &urec, lid, keyid, uidhash,
-                                               keyblock, signode );
-       }
-       else if( sig->sig_class == 0x18 ) { /* key binding */
-       }
-       else if( sig->sig_class == 0x20 ) { /* key revocation */
-           /* FIXME */
-       }
-       else if( sig->sig_class == 0x28 ) { /* subkey revocation */
-           /* FIXME */
-       }
-       else if( sig->sig_class == 0x30 ) { /* cert revocation */
-           /* FIXME */
-       }
-    }
-    else if( (sig->sig_class&~3) == 0x10 ) {
-       upd_nonself_key_sigs( sig, &urec, lid, keyid, uidhash,
-                                               keyblock, signode, fast );
-    }
-    else if( sig->sig_class == 0x18 ) { /* key binding */
-       log_info(_("key %08lX: bogus key binding by %08lX\n"),
-                                (ulong)keyid[1], (ulong)sig->keyid[1] );
-    }
-    else if( sig->sig_class == 0x20 ) { /* key revocation */
-       log_info(_("key %08lX: bogus key revocation by %08lX\n"),
-                                (ulong)keyid[1], (ulong)sig->keyid[1] );
-    }
-    else if( sig->sig_class == 0x28 ) { /* subkey revocation */
-       log_info(_("key %08lX: bogus subkey revocation by %08lX\n"),
-                                (ulong)keyid[1], (ulong)sig->keyid[1] );
-    }
-    else if( sig->sig_class == 0x30 ) { /* cert revocation */
-       /* fixme: a signator wants to revoke his certification signature */
-    }
-
-    if( urec.dirty ) {
-       write_record( &urec );
-       urec.dirty = 0;
-    }
-}
-
-
 /****************
  * Update all the info from the public keyblock.
  * The key must already exist in the keydb.
@@ -2528,8 +2595,6 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
     int rc = 0;
     u32 keyid[2]; /* keyid of primary key */
     ulong recno, lastrecno;
-    ulong uidrecno = 0;
-    byte uidhash[20];
     RECNO_LIST recno_list = NULL; /* list of verified records */
     /* fixme: replace recno_list by a lookup on node->recno */
 
@@ -2566,8 +2631,6 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
                            &drec, &recno_list, recheck );
     }
 
-
-  WORk - WORK
     /* delete keyrecords from the trustdb which are not anymore used */
     /* should we really do this, or is it better to keep them and */
     /* mark as unused? */
@@ -2626,12 +2689,9 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
     if( rc )
        rc = tdbio_cancel_transaction();
     else {
-       if( drec.dirty ) {
-           drec.r.dir.dirflags &= ~DIRF_CHECKED; /* reset flag */
-           write_record( &drec );
-       }
+       write_record( &drec );
        if( modified && tdbio_is_dirty() )
-           *modified = 0;
+           *modified = 1;
        rc = tdbio_end_transaction();
     }
     rel_recno_list( &recno_list );