changed trustdb design
authorWerner Koch <wk@gnupg.org>
Tue, 21 Jul 1998 12:53:38 +0000 (12:53 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 21 Jul 1998 12:53:38 +0000 (12:53 +0000)
20 files changed:
THANKS
TODO
doc/DETAILS
g10/ChangeLog
g10/Makefile.am
g10/OPTIONS
g10/g10.c
g10/getkey.c
g10/import.c
g10/keydb.h
g10/keygen.c
g10/keyid.c
g10/pkclist.c
g10/tdbio.c
g10/tdbio.h
g10/trustdb.c
g10/trustdb.h
tools/mk-tdata [deleted file]
util/ChangeLog
util/argparse.c

diff --git a/THANKS b/THANKS
index 70a8274..b30466c 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -14,7 +14,7 @@ Ernst Molitor         ernst.molitor@uni-bonn.de
 Frank Heckenbach       heckenb@mi.uni-erlangen.de
 Hendrik Buschkamp      buschkamp@rheumanet.org
 Ian McKellar           imckellar@harvestroad.com.au
-James Troup            J.J.Troup@scm.brad.ac.uk
+James Troup            james@nocrew.org
 Jean-loup Gailly       gzip@prep.ai.mit.edu
 Jens Bachem            bachem@rrz.uni-koeln.de
 Jörg Schilling         schilling@fokus.gmd.de
diff --git a/TODO b/TODO
index 73ed027..3c05ad0 100644 (file)
--- a/TODO
+++ b/TODO
     * add checking of armor trailers
     * remove all "Fixmes"
 
-    * bug: g10/trustdb.c#build_sigrecs called to often by do_list_path
-      and remove the bad kludge. Maybe we should put all sigs into the trustdb
-      and mark them as valid/invalid/nopubkey, and how do we check, that
-      we have a self-signature -> put this stuff into a kind of directory
-      record, as it does not belong to the pubkey record?
-
     * add an option to create a new user id.
 
     * add an option to re-create a public key from a secret key. Think about
index 1be782a..661a4a1 100644 (file)
@@ -100,7 +100,8 @@ Record type 3:      (key record)
      1 byte  reserved
      1 u32   LID
      1 u32   next   - next key record
-     8 bytes reserved
+     7 bytes reserved
+     1 byte  keyflags
      1 byte  pubkey algorithm
      1 byte  length of the fingerprint (in bytes)
      20 bytes fingerprint of the public key
@@ -118,7 +119,8 @@ Record type 4: (uid record)
      1 u32  next   next userid
      1 u32  pointer to preference record
      1 u32  siglist  list of valid signatures
-     2 byte reserved
+     1 byte uidflags
+     1 byte reserved
      20 bytes ripemd160 hash of the username.
 
 
index f6f935a..badb5cd 100644 (file)
@@ -1,3 +1,19 @@
+Tue Jul 21 14:37:09 1998  Werner Koch  (wk@(none))
+
+       * import.c (import_one): Now creates a trustdb record.
+
+       * g10.c (main): New command --check-trustdb
+
+Mon Jul 20 11:15:07 1998  Werner Koch  (wk@(none))
+
+       * genkey.c (generate_keypair): Default key is now DSA with
+       encryption only ElGamal subkey.
+
+Thu Jul 16 10:58:33 1998  Werner Koch  (wk@isil.d.shuttle.de)
+
+       * keyid.c (keyid_from_fingerprint): New.
+       * getkey.c (get_pubkey_byfprint): New.
+
 Tue Jul 14 18:09:51 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * keyid.c (fingerprint_from_pk): Add argument and changed all callers.
index be695d8..e97fb8c 100644 (file)
@@ -6,7 +6,7 @@ OMIT_DEPENDENCIES = zlib.h zconf.h
 LDFLAGS = @LDFLAGS@ @DYNLINK_LDFLAGS@
 needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a
 
-noinst_PROGRAMS = gpgd
+#noinst_PROGRAMS = gpgd
 bin_PROGRAMS = gpg gpgm
 
 common_source =  \
@@ -67,10 +67,10 @@ gpg_SOURCES  = g10.c                \
 gpgm_SOURCES = dearmor.c     \
              $(common_source)
 
-gpgd_SOURCES = gpgd.c \
-             ks-proto.h \
-             ks-proto.c \
-             $(common_source)
+#gpgd_SOURCES = gpgd.c \
+#             ks-proto.h \
+#             ks-proto.c \
+#             $(common_source)
 
 
 LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@
index 8e9cf8a..aa8b46d 100644 (file)
@@ -36,6 +36,14 @@ list-secret-keys
 export-secret-keys
 # export secret keys (which may be usefuil in some cases)
 
+check-trustdb
+
+
+
+
+
+
+
 #-----------------------------------------------
 #--- options
 #-----------------------------------------------
index 308b582..dbd277d 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -52,43 +52,44 @@ static ARGPARSE_OPTS opts[] = {
     { 300, NULL, 0, N_("@Commands:\n ") },
 
   #ifdef IS_G10
-    { 's', "sign",      0, N_("|[file]|make a signature")},
-    { 539, "clearsign", 0, N_("|[file]|make a clear text signature") },
-    { 'b', "detach-sign", 0, N_("make a detached signature")},
-    { 'e', "encrypt",   0, N_("encrypt data")},
-    { 'c', "symmetric", 0, N_("encryption only with symmetric cipher")},
-    { 507, "store",     0, N_("store only")},
-    { 'd', "decrypt",   0, N_("decrypt data (default)")},
-    { 550, "verify"   , 0, N_("verify a signature")},
+    { 's', "sign",      256, N_("|[file]|make a signature")},
+    { 539, "clearsign", 256, N_("|[file]|make a clear text signature") },
+    { 'b', "detach-sign", 256, N_("make a detached signature")},
+    { 'e', "encrypt",   256, N_("encrypt data")},
+    { 'c', "symmetric", 256, N_("encryption only with symmetric cipher")},
+    { 507, "store",     256, N_("store only")},
+    { 'd', "decrypt",   256, N_("decrypt data (default)")},
+    { 550, "verify"   , 256, N_("verify a signature")},
   #endif
-    { 551, "list-keys", 0, N_("list keys")},
-    { 552, "list-sigs", 0, N_("list keys and signatures")},
-    { 508, "check-sigs",0, N_("check key signatures")},
-    { 515, "fingerprint", 0, N_("list keys and fingerprints")},
-    { 558, "list-secret-keys", 0, N_("list secret keys")},
+    { 551, "list-keys", 256, N_("list keys")},
+    { 552, "list-sigs", 256, N_("list keys and signatures")},
+    { 508, "check-sigs",256, N_("check key signatures")},
+    { 515, "fingerprint", 256, N_("list keys and fingerprints")},
+    { 558, "list-secret-keys", 256, N_("list secret keys")},
   #ifdef IS_G10
-    { 503, "gen-key",   0, N_("generate a new key pair")},
-    { 554, "add-key",   0, N_("add a subkey to a key pair")},
-    { 506, "sign-key"  ,0, N_("make a signature on a key in the keyring")},
-    { 505, "delete-key",0, N_("remove key from the public keyring")},
-    { 524, "edit-key"  ,0, N_("edit a key signature")},
-    { 525, "change-passphrase", 0, N_("change the passphrase of your secret keyring")},
-    { 542, "gen-revoke",0, N_("generate a revocation certificate")},
+    { 503, "gen-key",   256, N_("generate a new key pair")},
+    { 554, "add-key",   256, N_("add a subkey to a key pair")},
+    { 506, "sign-key"  ,256, N_("make a signature on a key in the keyring")},
+    { 505, "delete-key",256, N_("remove key from the public keyring")},
+    { 524, "edit-key"  ,256, N_("edit a key signature")},
+    { 525, "change-passphrase", 256, N_("change the passphrase of your secret keyring")},
+    { 542, "gen-revoke",256, N_("generate a revocation certificate")},
   #endif
-    { 537, "export"          , 0, N_("export keys") },
-    { 563, "export-secret-keys" , 0, "@" },
+    { 537, "export"          , 256, N_("export keys") },
+    { 563, "export-secret-keys" , 256, "@" },
     { 565, "do-not-export-rsa", 0, "@" },
-    { 530, "import",      0     , N_("import/merge keys")},
-    { 521, "list-packets",0,N_("list only the sequence of packets")},
+    { 530, "import",      256     , N_("import/merge keys")},
+    { 521, "list-packets",256,N_("list only the sequence of packets")},
   #ifdef IS_G10MAINT
-    { 564, "list-ownertrust", 0, "list the ownertrust values"},
-    { 546, "dearmor", 0, N_("De-Armor a file or stdin") },
-    { 547, "enarmor", 0, N_("En-Armor a file or stdin") },
-    { 555, "print-md" , 0, N_("|algo [files]|print message digests")},
-    { 516, "print-mds" , 0, N_("print all message digests")},
+    { 564, "list-ownertrust", 256, N_("list the ownertrust values")},
+    { 567, "check-trustdb",0 , N_("|[NAMES]|check the trust database")},
+    { 546, "dearmor", 256, N_("De-Armor a file or stdin") },
+    { 547, "enarmor", 256, N_("En-Armor a file or stdin") },
+    { 555, "print-md" , 256, N_("|algo [files]|print message digests")},
+    { 516, "print-mds" , 256, N_("print all message digests")},
     #ifdef MAINTAINER_OPTIONS
-    { 513, "gen-prime" , 0, "@" },
-    { 548, "gen-random" , 0, "@" },
+    { 513, "gen-prime" , 256, "@" },
+    { 548, "gen-random" , 256, "@" },
     #endif
   #endif
 
@@ -143,6 +144,7 @@ static ARGPARSE_OPTS opts[] = {
   #ifdef IS_G10MAINT
     { 514, "test"      , 0, "@" },
     { 564, "list-ownertrust",0 , "@"},
+    { 567, "check-trustdb",0 , "@"},
     { 531, "list-trustdb",0 , "@"},
     { 533, "list-trust-path",0, "@"},
   #endif
@@ -182,7 +184,7 @@ enum cmd_values { aNull = 0,
     aListSigs, aKeyadd, aListSecretKeys,
     aExport, aExportSecret,
     aCheckKeys, aGenRevoke, aPrimegen, aPrintMD, aPrintMDs,
-    aListTrustDB, aListTrustPath, aListOwnerTrust,
+    aCheckTrustDB, aListTrustDB, aListTrustPath, aListOwnerTrust,
     aDeArmor, aEnArmor, aGenRandom,
 aTest };
 
@@ -195,7 +197,6 @@ static void set_cmd( enum cmd_values *ret_cmd,
 #ifdef IS_G10MAINT
 static void print_hex( byte *p, size_t n );
 static void print_mds( const char *fname, int algo );
-static void do_test(int);
 #endif
 
 const char *
@@ -541,6 +542,7 @@ main( int argc, char **argv )
          #endif
          case 516: set_cmd( &cmd, aPrintMDs); break;
          case 531: set_cmd( &cmd, aListTrustDB); break;
+         case 567: set_cmd( &cmd, aCheckTrustDB); break;
          case 533: set_cmd( &cmd, aListTrustPath); break;
          case 540: break; /* dummy */
          case 546: set_cmd( &cmd, aDeArmor); break;
@@ -1032,6 +1034,15 @@ main( int argc, char **argv )
        }
        break;
 
+      case aCheckTrustDB:
+       if( !argc )
+           check_trustdb(NULL);
+       else {
+           for( ; argc; argc--, argv++ )
+               check_trustdb( *argv );
+       }
+       break;
+
       case aListTrustPath:
        if( argc != 2 )
            wrong_args("--list-trust-path [-- -]<maxdepth> <username>");
index b73a006..912c919 100644 (file)
@@ -464,6 +464,20 @@ get_pubkey_byname( PKT_public_key *pk, const char *name )
 }
 
 
+/****************
+ * Search for a key with the given fingerprint.
+ */
+int
+get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint, size_t fprint_len)
+{
+    int rc;
+
+    if( fprint_len == 20 || fprint_len == 16 )
+       rc = lookup( pk, fprint_len, NULL, fprint, NULL );
+    else
+       rc = G10ERR_GENERAL; /* Oops */
+    return rc;
+}
 
 /****************
  * Search for a key with the given fingerprint and return the
index d32852c..ec143dc 100644 (file)
@@ -381,6 +381,17 @@ import_one( const char *fname, KBNODE keyblock )
        else
            log_info_f(fname, _("key %08lX: not changed\n"), (ulong)keyid[1] );
     }
+    if( !rc ) {
+       rc = query_trust_record( pk_orig );
+       if( rc && rc != -1 )
+           log_error("trustdb error: %s\n", g10_errstr(rc) );
+       else if( rc == -1 ) {
+           rc = insert_trust_record( pk_orig );
+           if( rc )
+               log_error("key %08lX: trustdb insert failed: %s\n",
+                                       (ulong)keyid[1], g10_errstr(rc) );
+       }
+    }
 
   leave:
     release_kbnode( keyblock_orig );
index 51da9a6..bbd803f 100644 (file)
@@ -112,6 +112,8 @@ void add_secret_keyring( const char *name );
 int get_pubkey( PKT_public_key *pk, u32 *keyid );
 int get_pubkey_byname( PKT_public_key *pk, const char *name );
 int get_seckey( PKT_secret_key *sk, u32 *keyid );
+int get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint,
+                                                size_t fprint_len );
 int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
                                                 size_t fprint_len );
 int seckey_available( u32 *keyid );
@@ -125,12 +127,13 @@ int pubkey_letter( int algo );
 u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid );
 u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid );
 u32 keyid_from_sig( PKT_signature *sig, u32 *keyid );
+u32 keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid );
 unsigned nbits_from_pk( PKT_public_key *pk );
 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 --*/
index b114b84..0eaeafe 100644 (file)
@@ -371,7 +371,7 @@ check_valid_days( const char *s )
 
 
 /****************
- * Returns o to create both a DSA and a ElGamal key.
+ * Returns: 0 to create both a DSA and a ElGamal key.
  */
 static int
 ask_algo( int *ret_v4, int addmode )
@@ -756,7 +756,7 @@ generate_keypair()
 
     algo = ask_algo( &v4, 0 );
     if( !algo ) {
-       algo = PUBKEY_ALGO_ELGAMAL;
+       algo = PUBKEY_ALGO_ELGAMAL_E;
        both = 1;
        tty_printf(_("DSA keypair will have 1024 bits.\n"));
     }
index 2e5c6aa..de0319f 100644 (file)
@@ -189,6 +189,43 @@ keyid_from_pk( PKT_public_key *pk, u32 *keyid )
 }
 
 
+/****************
+ * Get the keyid from the fingerprint. This function is simple for most
+ * keys, but has to do a keylookup for old stayle keys.
+ */
+u32
+keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
+{
+    u32 dummy_keyid[2];
+
+    if( !keyid )
+       keyid = dummy_keyid;
+
+    if( fprint_len != 20 ) {
+       /* This is special as we have to lookup the key first */
+       PKT_public_key pk;
+       int rc;
+
+       memset( &pk, 0, sizeof pk );
+       rc = get_pubkey_byfprint( &pk, fprint, fprint_len );
+       if( rc ) {
+           log_error("Oops: keyid_from_fingerprint: no pubkey\n");
+           keyid[0] = 0;
+           keyid[1] = 0;
+       }
+       else
+           keyid_from_pk( &pk, keyid );
+    }
+    else {
+       const byte *dp = fprint;
+       keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
+       keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
+    }
+
+    return keyid[1];
+}
+
+
 u32
 keyid_from_sig( PKT_signature *sig, u32 *keyid )
 {
index e509f00..7fbe065 100644 (file)
@@ -49,7 +49,7 @@ query_ownertrust( ulong lid )
     PKT_public_key *pk ;
     int changed=0;
 
-    rc = keyid_from_trustdb( lid, keyid );
+    rc = keyid_from_lid( lid, keyid );
     if( rc ) {
        log_error("ooops: can't get keyid for lid %lu\n", lid);
        return 0;
index 9355f4c..ac12661 100644 (file)
@@ -147,11 +147,11 @@ create_db( const char *fname )
     fp =fopen( fname, "w" );
     if( !fp )
        log_fatal_f( fname, _("can't create %s: %s\n"), strerror(errno) );
-    fwrite_8( fp, 2 );
+    fwrite_8( fp, 1 ); /* record type */
     fwrite_8( fp, 'g' );
     fwrite_8( fp, 'p' );
     fwrite_8( fp, 'g' );
-    fwrite_8( fp, 1 ); /* version */
+    fwrite_8( fp, 2 ); /* version */
     fwrite_zeros( fp, 3 ); /* reserved */
     fwrite_32( fp, 0 ); /* not locked */
     fwrite_32( fp, make_timestamp() ); /* created */
@@ -183,11 +183,12 @@ open_db()
 
 
 void
-tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp )
+tdbio_dump_record( TRUSTREC *rec, FILE *fp  )
 {
     int i, any;
+    ulong rnum = rec->recnum;
 
-    fprintf(fp, "rec %5lu, type=", rnum );
+    fprintf(fp, "rec %5lu, ", rnum );
 
     switch( rec->rectype ) {
       case 0: fprintf(fp, "free\n");
@@ -201,30 +202,36 @@ tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp    )
                    rec->r.dir.uidlist,
                    rec->r.dir.cacherec,
                    rec->r.dir.ownertrust );
-       if( rec->r.dir.sigflag == 1 )
-           fputs(", (none)", fp );
-       else if( rec->r.dir.sigflag == 2 )
-           fputs(", (invalid)", fp );
-       else if( rec->r.dir.sigflag == 3 )
-           fputs(", (revoked)", fp );
-       else if( rec->r.dir.sigflag )
-           fputs(", (??)", fp );
+       if( rec->r.dir.dirflags & DIRF_ERROR )
+           fputs(", error", fp );
+       if( rec->r.dir.dirflags & DIRF_CHECKED )
+           fputs(", checked", fp );
+       if( rec->r.dir.dirflags & DIRF_REVOKED )
+           fputs(", revoked", fp );
+       if( rec->r.dir.dirflags & DIRF_MISKEY )
+           fputs(", miskey", fp );
        putc('\n', fp);
        break;
       case RECTYPE_KEY:
-       fprintf(fp, "key %lu, next=%lu, algo=%d, flen=%d\n",
+       fprintf(fp, "key %lu, next=%lu, algo=%d, flen=%d",
                   rec->r.key.lid,
                   rec->r.key.next,
                   rec->r.key.pubkey_algo,
                   rec->r.key.fingerprint_len );
+       if( rec->r.key.keyflags & KEYF_REVOKED )
+           fputs(", revoked", fp );
+       putc('\n', fp);
        break;
       case RECTYPE_UID:
-       fprintf(fp, "uid %lu, next=%lu, pref=%lu, sig=%lu, hash=%02X%02X\n",
+       fprintf(fp, "uid %lu, next=%lu, pref=%lu, sig=%lu, hash=%02X%02X",
                    rec->r.uid.lid,
                    rec->r.uid.next,
                    rec->r.uid.prefrec,
                    rec->r.uid.siglist,
                    rec->r.uid.namehash[18], rec->r.uid.namehash[19]);
+       if( rec->r.uid.uidflags & UIDF_REVOKED )
+           fputs(", revoked", fp );
+       putc('\n', fp);
        break;
       case RECTYPE_PREF:
        fprintf(fp, "pref %lu, next=%lu\n",
@@ -253,11 +260,11 @@ tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp    )
       case RECTYPE_HTBL:
        fprintf(fp, "htbl\n");
        break;
-      case RECTYPE_HTBL:
+      case RECTYPE_HLST:
        fprintf(fp, "hlst\n");
        break;
       default:
-       fprintf(fp, "%d (unknown)\n", rec->rectype );
+       fprintf(fp, "unknown type %d\n", rec->rectype );
        break;
     }
 }
@@ -330,7 +337,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
        rec->r.dir.uidlist  = buftoulong(p); p += 4;
        rec->r.dir.cacherec = buftoulong(p); p += 4;
        rec->r.dir.ownertrust = *p++;
-       rec->r.dir.sigflag    = *p++;
+       rec->r.dir.dirflags   = *p++;
        if( rec->r.dir.lid != recnum ) {
            log_error_f( db_name, "dir LID != recnum (%lu,%lu)\n",
                                         rec->r.dir.lid, (ulong)recnum );
@@ -340,7 +347,8 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
       case RECTYPE_KEY:   /* public key record */
        rec->r.key.lid      = buftoulong(p); p += 4;
        rec->r.key.next     = buftoulong(p); p += 4;
-       p += 8;
+       p += 7;
+       rec->r.key.keyflags = *p++;
        rec->r.key.pubkey_algo = *p++;
        rec->r.key.fingerprint_len = *p++;
        if( rec->r.key.fingerprint_len < 1 || rec->r.key.fingerprint_len > 20 )
@@ -352,7 +360,8 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
        rec->r.uid.next     = buftoulong(p); p += 4;
        rec->r.uid.prefrec  = buftoulong(p); p += 4;
        rec->r.uid.siglist  = buftoulong(p); p += 4;
-       p += 2;
+       rec->r.uid.uidflags = *p++;
+       p ++;
        memcpy( rec->r.uid.namehash, p, 20);
        break;
       case RECTYPE_PREF:  /* preference record */
@@ -413,14 +422,15 @@ tdbio_write_record( TRUSTREC *rec )
        ulongtobuf(p, rec->r.dir.uidlist); p += 4;
        ulongtobuf(p, rec->r.dir.cacherec); p += 4;
        *p++ = rec->r.dir.ownertrust;
-       *p++ = rec->r.dir.sigflag;
+       *p++ = rec->r.dir.dirflags;
        assert( rec->r.dir.lid == recnum );
        break;
 
       case RECTYPE_KEY:
        ulongtobuf(p, rec->r.key.lid); p += 4;
        ulongtobuf(p, rec->r.key.next); p += 4;
-       p += 8;
+       p += 7;
+       *p++ = rec->r.key.keyflags;
        *p++ = rec->r.key.pubkey_algo;
        *p++ = rec->r.key.fingerprint_len;
        memcpy( p, rec->r.key.fingerprint, 20); p += 20;
@@ -431,7 +441,8 @@ tdbio_write_record( TRUSTREC *rec )
        ulongtobuf(p, rec->r.uid.next); p += 4;
        ulongtobuf(p, rec->r.uid.prefrec); p += 4;
        ulongtobuf(p, rec->r.uid.siglist); p += 4;
-       p += 2;
+       *p++ = rec->r.uid.uidflags;
+       p++;
        memcpy( p, rec->r.uid.namehash, 20 ); p += 20;
        break;
 
@@ -472,6 +483,15 @@ tdbio_write_record( TRUSTREC *rec )
     return rc;
 }
 
+int
+tdbio_delete_record( ulong recnum )
+{
+    TRUSTREC rec;
+
+    rec.recnum = recnum;
+    rec.rectype = 0;
+    return tdbio_write_record( &rec );
+}
 
 /****************
  * create a new record and return its record number
@@ -495,7 +515,8 @@ tdbio_new_recnum()
      * returns another recnum */
     memset( &rec, 0, sizeof rec );
     rec.rectype = 0; /* free record */
-    rc = tdbio_write_record(recnum, &rec );
+    rec.recnum = recnum;
+    rc = tdbio_write_record( &rec );
     if( rc )
        log_fatal_f(db_name,_("failed to append a record: %s\n"),
                                            g10_errstr(rc));
@@ -530,10 +551,10 @@ tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec )
        if( rec->r.key.pubkey_algo == pk->pubkey_algo
            && !memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) ) {
            /* found: read the dir record for this key */
-           rc = tdbio_read_record( rec->r.key.lid, rec, RECTYPE_DIR);
+           recnum = rec->r.key.lid;
+           rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
            if( rc )
                break;
-
            if( pk->local_id && pk->local_id != recnum )
                log_error_f(db_name,
                           "found record, but LID from memory does "
@@ -549,22 +570,13 @@ tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec )
 }
 
 
+/****************
+ * Delete the Userid UIDLID from DIRLID
+ */
 int
-tdbio_update_sigflag( ulong lid, int sigflag )
+tdbio_delete_uidrec( ulong dirlid, ulong uidlid )
 {
-    TRUSTREC rec;
-
-    if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
-       log_error("update_sigflag: read failed\n");
-       return G10ERR_TRUSTDB;
-    }
-
-    rec.r.dir.sigflag = sigflag;
-    if( tdbio_write_record( lid, &rec ) ) {
-       log_error("update_sigflag: write failed\n");
-       return G10ERR_TRUSTDB;
-    }
-
-    return 0;
+    return G10ERR_GENERAL; /* not implemented */
 }
 
+
index 2d28131..8eec40e 100644 (file)
 #define RECTYPE_HLST 11
 
 
+
+#define DIRF_CHECKED  1 /* everything has been checked, the other bits are
+                          valid */
+#define DIRF_MISKEY   2 /* some keys are missing, so they could not be checked*/
+#define DIRF_ERROR    4 /* severe errors: the key is not valid for some reasons
+                          but we mark it to avoid duplicate checks */
+#define DIRF_REVOKED  8 /* the complete key has been revoked */
+
+#define KEYF_REVOKED DIRF_REVOKED   /* this key has been revoked
+                                      (only useful on subkeys)*/
+#define UIDF_REVOKED DIRF_REVOKED   /* this user id has been revoked */
+
+
 struct trust_record {
     int  rectype;
     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 {
@@ -64,11 +76,12 @@ struct trust_record {
            ulong uidlist;  /* list of uid records */
            ulong cacherec; /* the cache record */
            byte ownertrust;
-           byte sigflag;
+           byte dirflags;
        } dir;
        struct {            /* primary public key record */
            ulong lid;
            ulong next;    /* next key */
+           byte keyflags;
            byte pubkey_algo;
            byte fingerprint_len;
            byte fingerprint[20];
@@ -78,6 +91,7 @@ struct trust_record {
            ulong next;    /* points to next user id record */
            ulong prefrec;   /* recno of preference record */
            ulong siglist;   /* list of valid signatures (w/o self-sig)*/
+           byte uidflags;
            byte namehash[20]; /* ripemd hash of the username */
        } uid;
        struct {            /* preference reord */
@@ -90,7 +104,7 @@ struct trust_record {
            ulong next;   /* recnno of next record or NULL for last one */
            struct {
                ulong lid;       /* of pubkey record of signator (0=unused) */
-               byte flag;       /* reserved */
+               byte flag;       /* SIGRF_xxxxx */
            } sig[SIGS_PER_RECORD];
        } sig;
        struct {            /* cache record */
@@ -113,14 +127,15 @@ struct trust_record {
 typedef struct trust_record TRUSTREC;
 
 typedef struct {
-    ulong     local_id;    /* localid of the pubkey */
+    ulong     lid;        /* localid */
     ulong     sigrec;
-    ulong     sig_id;     /* returned signature id */
+    ulong     sig_lid;    /* returned signatures LID */
     unsigned  sig_flag;    /* returned signature record flag */
     struct {              /* internal data */
        int init_done;
        int eof;
        TRUSTREC rec;
+       ulong nextuid;
        int index;
     } ctl;
 } SIGREC_CONTEXT;
@@ -129,12 +144,13 @@ typedef struct {
 /*-- tdbio.c --*/
 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 );
+void tdbio_dump_record( TRUSTREC *rec, FILE *fp );
 int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected );
 int tdbio_write_record( TRUSTREC *rec );
+int tdbio_delete_record( ulong recnum );
 ulong tdbio_new_recnum(void);
 int tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec );
-int tdbio_update_sigflag( ulong lid, int sigflag );
+int tdbio_delete_uidrec( ulong dirlid, ulong uidlid );
 
 
 #define buftoulong( p )  ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
index b2e478c..b82d26a 100644 (file)
@@ -87,9 +87,9 @@ static void upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag );
 static void print_user_id( const char *text, u32 *keyid );
 static int do_list_path( TRUST_INFO *stack, int depth, int max_depth,
                         LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist );
+static int update_sigs_by_lid( ulong lid );
 
 static int list_sigs( ulong pubkey_id );
-static int build_sigrecs( ulong local_id );
 static int propagate_trust( TRUST_SEG_LIST tslist );
 static int do_check( TRUSTREC *drec, unsigned *trustlevel );
 
@@ -179,7 +179,7 @@ upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag )
  * the signature packet in our trustdb or insert them into the trustdb
  */
 static int
-set_signature_packets_local_id( PKT_signature *sig )
+set_signature_packets_lid( PKT_signature *sig )
 {
     PKT_public_key *pk = m_alloc_clear( sizeof *pk );
     TRUSTREC rec;
@@ -204,24 +204,34 @@ set_signature_packets_local_id( PKT_signature *sig )
 
 
 
-static int
-keyid_from_local_id( ulong lid, u32 *keyid )
+/****************
+ * Return the keyid from the primary key identified by LID.
+ */
+int
+keyid_from_lid( ulong lid, u32 *keyid )
 {
     TRUSTREC rec;
     int rc;
 
     rc = tdbio_read_record( lid, &rec, RECTYPE_DIR );
     if( rc ) {
-       log_error(_("error reading record with local_id %lu: %s\n"),
+       log_error("error reading dir record for LID %lu: %s\n",
                                                    lid, g10_errstr(rc));
        return G10ERR_TRUSTDB;
     }
-    if( rec.rectype != RECTYPE_DIR ) {
-       log_error(_("record with local_id %lu is not a dir record\n"), lid);
+    if( !rec.r.dir.keylist ) {
+       log_error("no primary key for LID %lu\n", lid );
        return G10ERR_TRUSTDB;
     }
-    keyid[0] = rec.r.dir.keyid[0];
-    keyid[1] = rec.r.dir.keyid[1];
+    rc = tdbio_read_record( rec.r.dir.keylist, &rec, RECTYPE_KEY );
+    if( rc ) {
+       log_error("error reading primary key for LID %lu: %s\n",
+                                                   lid, g10_errstr(rc));
+       return G10ERR_TRUSTDB;
+    }
+    keyid_from_fingerprint( rec.r.key.fingerprint, rec.r.key.fingerprint_len,
+                           keyid );
+
     return 0;
 }
 
@@ -247,48 +257,52 @@ walk_sigrecs( SIGREC_CONTEXT *c, int create )
     r = &c->ctl.rec;
     if( !c->ctl.init_done ) {
        c->ctl.init_done = 1;
-       if( !c->sigrec ) {
-           rc = tdbio_read_record( c->local_id, r, RECTYPE_DIR );
-           if( rc ) {
-               log_error(_("%lu: error reading dir record: %s\n"),
-                                       c->local_id, g10_errstr(rc));
-               return rc;
-           }
-           c->sigrec = r->r.dir.sigrec;
-           if( !c->sigrec && create && !r->r.dir.no_sigs ) {
-               rc = build_sigrecs( c->local_id );
+       rc = tdbio_read_record( c->lid, r, RECTYPE_DIR );
+       if( rc ) {
+           log_error("LID %lu: error reading dir record: %s\n",
+                                   c->lid, g10_errstr(rc));
+           return rc;
+       }
+       c->ctl.nextuid = r->r.dir.uidlist;
+       /* force a read (what a bad bad hack) */
+       c->ctl.index = SIGS_PER_RECORD;
+       r->r.sig.next = 0;
+    }
+
+    /* need a loop to skip over deleted sigs */
+    do {
+       if( c->ctl.index >= SIGS_PER_RECORD ) { /* read the record */
+           rnum = r->r.sig.next;
+           if( !rnum && c->ctl.nextuid ) { /* read next uid record */
+               rc = tdbio_read_record( c->ctl.nextuid, r, RECTYPE_UID );
                if( rc ) {
-                   if( rc == G10ERR_BAD_CERT )
-                       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) );
+                   log_error("error reading next uidrec: %s\n",
+                                                   g10_errstr(rc));
                    c->ctl.eof = 1;
                    return rc;
                }
-               rc = tdbio_read_record( c->local_id, r, RECTYPE_DIR );
-               if( rc ) {
-                   log_error(_("%lu: error re-reading dir record: %s\n"),
-                                           c->local_id, g10_errstr(rc));
-                   return rc;
+               if( !r->r.uid.siglist && create ) {
+                   rc = update_sigs_by_lid( c->lid );
+                   if( rc ) {
+                       if( rc == G10ERR_BAD_CERT )
+                           rc = -1;  /* maybe no selfsignature */
+                       if( rc != -1 )
+                           log_info("LID %lu: "
+                                    "error building sigs on the fly: %s\n",
+                                     c->lid, g10_errstr(rc) );
+                       c->ctl.eof = 1;
+                       return rc;
+                   }
+                   rc = tdbio_read_record( c->ctl.nextuid, r, RECTYPE_UID );
+                   if( rc ) {
+                       log_error("LID %lu: error re-reading uid record: %s\n",
+                                               c->lid, g10_errstr(rc));
+                       return rc;
+                   }
                }
-               c->sigrec = r->r.dir.sigrec;
-           }
-           if( !c->sigrec ) {
-               c->ctl.eof = 1;
-               return -1;
+               c->ctl.nextuid = r->r.uid.next;
+               rnum = r->r.uid.siglist;
            }
-       }
-       /* force a read */
-       c->ctl.index = SIGS_PER_RECORD;
-       r->r.sig.chain = c->sigrec;
-    }
-
-    /* enter loop to skip deleted sigs */
-    do {
-       if( c->ctl.index >= SIGS_PER_RECORD ) {
-           /* read the record */
-           rnum = r->r.sig.chain;
            if( !rnum ) {
                c->ctl.eof = 1;
                return -1;  /* return eof */
@@ -299,15 +313,16 @@ walk_sigrecs( SIGREC_CONTEXT *c, int create )
                c->ctl.eof = 1;
                return rc;
            }
-           if( r->r.sig.owner != c->local_id ) {
+           if( r->r.sig.lid != c->lid ) {
                log_error(_("chained sigrec %lu has a wrong owner\n"), rnum );
                c->ctl.eof = 1;
                return G10ERR_TRUSTDB;
            }
            c->ctl.index = 0;
        }
-    } while( !r->r.sig.sig[c->ctl.index++].local_id );
-    c->sig_id = r->r.sig.sig[c->ctl.index-1].local_id;
+    } while( !r->r.sig.sig[c->ctl.index++].lid );
+
+    c->sig_lid = r->r.sig.sig[c->ctl.index-1].lid;
     c->sig_flag = r->r.sig.sig[c->ctl.index-1].flag;
     return 0;
 }
@@ -333,13 +348,6 @@ verify_own_keys()
     u32 keyid[2];
 
     while( !(rc=enum_secret_keys( &enum_context, sk) ) ) {
-       /* To be sure that it is a secret key of our own,
-        * we should check it, but this needs a passphrase
-        * for every key and this is boring for the user.
-        * Anyway, access to the seret keyring should be
-        * granted to the user only as it is poosible to
-        * crack it with dictionary attacks.
-        */
        keyid_from_sk( sk, keyid );
 
        if( DBG_TRUST )
@@ -383,7 +391,6 @@ verify_own_keys()
            log_error(_("key %08lX: already in ultikey_table\n"),
                                                        (ulong)keyid[1]);
 
-
        release_secret_key_parts( sk );
        release_public_key_parts( pk );
     }
@@ -421,7 +428,7 @@ static void
 print_keyid( FILE *fp, ulong lid )
 {
     u32 ki[2];
-    if( keyid_from_trustdb( lid, ki ) )
+    if( keyid_from_lid( lid, ki ) )
        fprintf(fp, "????????.%lu", lid );
     else
        fprintf(fp, "%08lX.%lu", (ulong)ki[1], lid );
@@ -454,36 +461,36 @@ do_list_sigs( ulong root, ulong pubkey, int depth,
     u32 keyid[2];
 
     memset( &sx, 0, sizeof sx );
-    sx.local_id = pubkey;
+    sx.lid = pubkey;
     for(;;) {
        rc = walk_sigrecs( &sx, 0 );
        if( rc )
            break;
-       rc = keyid_from_local_id( sx.sig_id, keyid );
+       rc = keyid_from_lid( sx.sig_lid, keyid );
        if( rc ) {
            printf("%6u: %*s????????.%lu:%02x\n", *lineno, depth*4, "",
-                                                  sx.sig_id, sx.sig_flag );
+                                                  sx.sig_lid, sx.sig_flag );
            ++*lineno;
        }
        else {
            printf("%6u: %*s%08lX.%lu:%02x ", *lineno, depth*4, "",
-                             (ulong)keyid[1], sx.sig_id, sx.sig_flag );
+                             (ulong)keyid[1], sx.sig_lid, sx.sig_flag );
            /* check whether we already checked this pubkey */
-           if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) {
+           if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) {
                print_user_id("[ultimately trusted]", keyid);
                ++*lineno;
            }
-           else if( sx.sig_id == pubkey ) {
+           else if( sx.sig_lid == pubkey ) {
                printf("[self-signature]\n");
                ++*lineno;
            }
-           else if( sx.sig_id == root ) {
+           else if( sx.sig_lid == root ) {
                printf("[closed]\n");
                ++*lineno;
            }
-           else if( ins_lid_table_item( lids, sx.sig_id, *lineno ) ) {
+           else if( ins_lid_table_item( lids, sx.sig_lid, *lineno ) ) {
                unsigned refline;
-               qry_lid_table_flag( lids, sx.sig_id, &refline );
+               qry_lid_table_flag( lids, sx.sig_lid, &refline );
                printf("[see line %u]\n", refline);
                ++*lineno;
            }
@@ -494,7 +501,7 @@ do_list_sigs( ulong root, ulong pubkey, int depth,
            else {
                print_user_id( "", keyid );
                ++*lineno;
-               rc = do_list_sigs( root, sx.sig_id, depth+1, lids, lineno );
+               rc = do_list_sigs( root, sx.sig_lid, depth+1, lids, lineno );
                if( rc )
                    break;
            }
@@ -514,11 +521,9 @@ list_sigs( ulong pubkey_id )
     LOCAL_ID_INFO *lids;
     unsigned lineno = 1;
 
-    rc = keyid_from_local_id( pubkey_id, keyid );
-    if( rc ) {
-       log_error("Hmmm, no pubkey record for local_id %lu\n", pubkey_id);
+    rc = keyid_from_lid( pubkey_id, keyid );
+    if( rc )
        return rc;
-    }
     printf("Signatures of %08lX.%lu ", (ulong)keyid[1], pubkey_id );
     print_user_id("", keyid);
     printf("----------------------\n");
@@ -530,6 +535,70 @@ list_sigs( ulong pubkey_id )
     return rc;
 }
 
+/****************
+ * List all records of a public key
+ */
+static int
+list_records( ulong lid )
+{
+    int rc;
+    TRUSTREC dr, ur, rec;
+    ulong recno;
+
+    rc = tdbio_read_record( lid, &dr, RECTYPE_DIR );
+    if( rc ) {
+       log_error("lid %lu: read dir record failed: %s\n", lid, g10_errstr(rc));
+       return rc;
+    }
+    tdbio_dump_record( &dr, stdout );
+
+    for( recno=dr.r.dir.keylist; recno; recno = rec.r.key.next ) {
+       rc = tdbio_read_record( recno, &rec, RECTYPE_KEY );
+       if( rc ) {
+           log_error("lid %lu: read key record failed: %s\n",
+                                               lid, g10_errstr(rc));
+           return rc;
+       }
+       tdbio_dump_record( &rec, stdout );
+    }
+
+    for( recno=dr.r.dir.uidlist; recno; recno = ur.r.uid.next ) {
+       rc = tdbio_read_record( recno, &ur, RECTYPE_UID );
+       if( rc ) {
+           log_error("lid %lu: read uid record failed: %s\n",
+                                               lid, g10_errstr(rc));
+           return rc;
+       }
+       tdbio_dump_record( &ur, stdout );
+       /* preference records */
+       for(recno=ur.r.uid.prefrec; recno; recno = rec.r.pref.next ) {
+           rc = tdbio_read_record( recno, &rec, RECTYPE_PREF );
+           if( rc ) {
+               log_error("lid %lu: read pref record failed: %s\n",
+                                                   lid, g10_errstr(rc));
+               return rc;
+           }
+           tdbio_dump_record( &rec, stdout );
+       }
+       /* sig records */
+       for(recno=ur.r.uid.siglist; recno; recno = rec.r.sig.next ) {
+           rc = tdbio_read_record( recno, &rec, RECTYPE_SIG );
+           if( rc ) {
+               log_error("lid %lu: read sig record failed: %s\n",
+                                                   lid, g10_errstr(rc));
+               return rc;
+           }
+           tdbio_dump_record( &rec, stdout );
+       }
+    }
+
+    /* add cache record dump here */
+
+
+
+    return rc;
+}
+
 
 
 /****************
@@ -551,29 +620,28 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth,
        return 0;
     }
     memset( &sx, 0, sizeof sx );
-    sx.local_id = stack[depth-1].lid;
-    /* loop over all signatures. If we do not have any, try to
-     * create them */
+    sx.lid = stack[depth-1].lid;
+    /* loop over all signatures. If we do not have any, try to create them */
     while( !(rc = walk_sigrecs( &sx, 1 )) ) {
        TRUST_SEG_LIST tsl, t2, tl;
        int i;
 
-       stack[depth].lid = sx.sig_id;
+       stack[depth].lid = sx.sig_lid;
        stack[depth].trust = 0;
-       if( qry_lid_table_flag( lids, sx.sig_id, &last_depth) ) {
-           /*printf("%2lu/%d: marked\n", sx.sig_id, depth );*/
-           ins_lid_table_item( lids, sx.sig_id, depth);
+       if( qry_lid_table_flag( lids, sx.sig_lid, &last_depth) ) {
+           /*printf("%2lu/%d: marked\n", sx.sig_lid, depth );*/
+           ins_lid_table_item( lids, sx.sig_lid, depth);
            last_depth = depth;
        }
        else if( depth  < last_depth ) {
-           /*printf("%2lu/%d: last_depth=%u - updated\n", sx.sig_id, depth, last_depth);*/
+           /*printf("%2lu/%d: last_depth=%u - updated\n", sx.sig_lid, depth, last_depth);*/
            last_depth = depth;
-           upd_lid_table_flag( lids, sx.sig_id, depth);
+           upd_lid_table_flag( lids, sx.sig_lid, depth);
        }
 
        if( last_depth < depth )
-           /*printf("%2lu/%d: already visited\n", sx.sig_id, depth)*/;
-       else if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) {
+           /*printf("%2lu/%d: already visited\n", sx.sig_lid, depth)*/;
+       else if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) {
            /* found end of path; store it, ordered by path length */
            tsl = m_alloc( sizeof *tsl + depth*sizeof(TRUST_INFO) );
            tsl->nseg = depth+1;
@@ -592,7 +660,7 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth,
                tl->next = tsl;
            }
            /*putchar('.'); fflush(stdout);*/
-           /*printf("%2lu/%d: found\n", sx.sig_id, depth);*/
+           /*printf("%2lu/%d: found\n", sx.sig_lid, depth);*/
        }
        else {
            rc = do_list_path( stack, depth+1, max_depth, lids, tslist);
@@ -604,209 +672,327 @@ do_list_path( TRUST_INFO *stack, int depth, int max_depth,
 }
 
 
+/****************
+ * find the uid record given the uid packet and the dir-record.
+ * Returns: 0 = found
+ *        -1 = No such uid-record
+ *        or other error
+ */
+static int
+find_urec( TRUSTREC *dir, PKT_user_id *uid, TRUSTREC *urec )
+{
+    byte nhash[20];
+    ulong recno;
+    int rc;
+
+    assert(dir->rectype == RECTYPE_DIR );
+    rmd160_hash_buffer( nhash, uid->name, uid->len );
+    for( recno=dir->r.dir.uidlist; recno; recno = urec->r.uid.next ) {
+       rc = tdbio_read_record( recno, urec, RECTYPE_UID );
+       if( rc )
+           return rc == -1 ? G10ERR_READ_FILE : rc;
+       if( !memcmp( nhash, urec->r.uid.namehash, 20 ) )
+           return 0;
+    }
+
+    return -1;
+}
+
 
 /****************
- * Check all the sigs of the given keyblock and mark them
- * as checked. Valid signatures which are duplicates are
- * also marked [shall we check them at all?]
- * FIXME: what shall we do if we have duplicate signatures where only
- *       some of them are bad?
+ * Test whether zthe signature lid is already in the (in mem) list.
+ * Returns: True if it is a duplicate
  */
 static int
-check_sigs( KBNODE keyblock, int *selfsig_okay, int *revoked )
+test_dupsig( TRUSTREC *rec, ulong lid )
+{
+    int i;
+    ulong alid;
+
+    for( ; rec; rec = rec->next ) {
+       for(i=0; i < SIGS_PER_RECORD && (alid = rec->r.sig.sig[i].lid); i++ )
+           if( alid == lid )
+               return 1;
+    }
+    return 0;
+}
+
+
+/****************
+ * release the sigrec from the uidlist
+ */
+static void
+rel_uidsigs( TRUSTREC *urec )
+{
+    TRUSTREC *r2, *rec;
+    assert( urec->rectype == RECTYPE_UID );
+
+    for(rec=urec->next ; rec; rec = r2 ) {
+       assert( rec->rectype == RECTYPE_SIG );
+       r2 = rec->next;
+       m_free( rec );
+    }
+    urec->next = NULL;
+}
+
+static int
+no_selfsig_del( ulong lid, u32 *keyid, TRUSTREC *urec )
 {
-    KBNODE node;
     int rc;
-    LOCAL_ID_INFO *dups = NULL;
 
-    *selfsig_okay = 0;
-    *revoked = 0;
-    for( node=keyblock; node; node = node->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 */
-
-               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 */
-               }
+    log_error("key %08lX.%lu, uid %02X%02X: "
+             "no self-signature - user id removed\n",
+             (ulong)keyid[1], lid, urec->r.uid.namehash[18],
+             urec->r.uid.namehash[19] );
+    rel_uidsigs( urec );
+    rc = tdbio_delete_uidrec( lid, urec->recnum );
+    if( rc )
+       log_error("no_selfsig_del: delete_uid %lu failed: %s\n",
+                                       lid, g10_errstr(rc) );
+    return rc;
+}
+
+/****************
+ * Write the signature records from the in-mem list at urec
+ * (The sequence of signatures does not matter)
+ */
+static int
+write_sigs_from_urec( ulong lid, u32 *keyid, TRUSTREC *urec )
+{
+    int rc;
+    TRUSTREC *rec, srec;
+    ulong nextrecno;
+    ulong recno;
+
+    nextrecno = urec->r.uid.siglist;
+    urec->r.uid.siglist = 0; /* end of list marker */
+    for( rec = urec->next; rec; rec = rec->next ) {
+       assert( rec->rectype == RECTYPE_SIG );
+       if( nextrecno ) { /* read the sig record, so it can be reused */
+           rc = tdbio_read_record( nextrecno, &srec, RECTYPE_SIG );
+           if( rc ) {
+               log_error("write_sig_from_urec: read sigrecno %lu failed: %s\n",
+                                                 nextrecno, g10_errstr(rc) );
+               return rc;
            }
-           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)":"" );
+           recno = nextrecno;
+           nextrecno = srec.r.sig.next;
+       }
+       else
+           recno = tdbio_new_recnum();
+
+       /* link together (the sequence of signatures does not matter) */
+       rec->r.sig.next = urec->r.uid.siglist;
+       urec->r.uid.siglist = recno;
+       rec->r.sig.lid = lid;
+       /* and write */
+       rec->recnum = recno;
+       rc = tdbio_write_record( rec );
+       if( rc ) {
+           log_error("write_sig_from_urec: write sigrecno %lu failed: %s\n",
+                                                 recno, g10_errstr(rc) );
+           return rc;
        }
     }
-    if( dups )
-       release_lid_table(dups);
-    return 0;
-}
 
+    /* write the urec back */
+    rc = tdbio_write_record( urec );
+    if( rc ) {
+       log_error("write_sig_from_urec: write urec %lu failed: %s\n",
+                                           urec->recnum, g10_errstr(rc) );
+       return rc;
+    }
+
+    /* delete remaining old sigrecords */
+    while( nextrecno ) {
+       rc = tdbio_read_record( nextrecno, &srec, RECTYPE_SIG );
+       if( rc ) {
+           log_error("write_sig_from_urec: read sigrecno %lu failed: %s\n",
+                                             nextrecno, g10_errstr(rc) );
+           return rc;
+       }
+       rc = tdbio_delete_record( nextrecno );
+       if( rc ) {
+           log_error("write_sig_from_urec: delete old %lu failed: %s\n",
+                                             nextrecno, g10_errstr(rc) );
+           return rc;
+
+       }
+       nextrecno = srec.r.sig.next;
+    }
+
+    return rc;
+}
 
 /****************
  * If we do not have sigrecs for the given key, build them and write them
  * to the trustdb
  */
 static int
-build_sigrecs( ulong lid )
+update_sigs( TRUSTREC *dir )
 {
-    TRUSTREC rec, krec, rec2;
-   KBNODE keyblock = NULL;
-   KBNODE node;
+    TRUSTREC *rec, krec;
+    TRUSTREC urec;
+    TRUSTREC *sigrec_list;
+    KBNODE keyblock = NULL;
+    KBNODE node;
+    int i, sigidx, have_urec ;
+    ulong lid = dir->r.dir.lid;
+    u32 keyid[2];
+    int miskey=0;
     int rc=0;
-    int i, selfsig, revoked;
-    ulong rnum, rnum2;
-    ulong first_sigrec = 0;
 
     if( DBG_TRUST )
-       log_debug("trustdb: build_sigrecs for LID %lu\n", lid );
+       log_debug("update_sigs for %lu\n", lid );
 
-    /* get the keyblock */
-    if( (rc=tdbio_read_record( lid, &rec, RECTYPE_DIR )) ) {
-       log_error( "build_sigrecs: can't read dir record %lu\n"), lid );
-       goto leave;
-    }
-    if( (rc=tdbio_read_record( rec.r.dir.keylist, &krec, RECTYPE_KEY )) ) {
-       log_error("build_sigrecs: can't read primary key record %lu\n"), lid);
+    if( (rc=tdbio_read_record( dir->r.dir.keylist, &krec, RECTYPE_KEY )) ) {
+       log_error("update_sigs: can't read primary key for %lu\n", lid);
        goto leave;
     }
     rc = get_keyblock_byfprint( &keyblock, krec.r.key.fingerprint,
                                           krec.r.key.fingerprint_len );
     if( rc ) {
-       log_error( "build_sigrecs: keyblock for %lu not found: %s\n",
+       log_error( "update_sigs: keyblock for %lu not found: %s\n",
                                                    lid, g10_errstr(rc) );
        goto leave;
     }
 
     /* check all key signatures */
-    rc = check_sigs( keyblock, &selfsig, &revoked );
-    if( rc ) {
-       log_error(_("build_sigrecs: check_sigs failed\n") );
-       goto leave;
-    }
-    if( !selfsig ) {
-       log_error(_("build_sigrecs: self-signature missing\n") );
-       tdbio_update_sigflag( lid, 2 );
-       rc = G10ERR_BAD_CERT;
-       goto leave;
-    }
-    if( revoked ) {
-       log_info(_("build_sigrecs: key has been revoked\n") );
-       tdbio_update_sigflag( lid, 3 );
-    }
-    else
-       tdbio_update_sigflag( lid, 0 ); /* assume we have sigs */
-
-    /* valid key signatures are now marked; we can now build the sigrecs */
-    memset( &rec, 0, sizeof rec );
-    rec.rectype = RECTYPE_SIG;
-    i = 0;
-    rnum = rnum2 = 0;
+    assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY );
+    have_urec = 0;
+    sigrec_list = NULL;
+    sigidx = 0;
     for( node=keyblock; node; node = node->next ) {
-       /* insert sigs which are not a selfsig nor a duplicate */
-       if( (node->flag & 1) && !(node->flag & 4) ) {
-           assert( node->pkt->pkttype == PKT_SIGNATURE );
-           if( !node->pkt->pkt.signature->local_id )  {
-               /* the next function should always succeed, because
-                * we have already checked the signature, and for this
-                * it was necessary to have the pubkey. The only reason
-                * this can fail are I/O errors of the trustdb or a
-                * remove operation on the pubkey database - which should
-                * not disturb us, because we have to change them anyway. */
-               rc = set_signature_packets_local_id( node->pkt->pkt.signature );
+       if( node->pkt->pkttype == PKT_PUBLIC_KEY )
+           keyid_from_pk( node->pkt->pkt.public_key, keyid );
+       else if( node->pkt->pkttype == PKT_USER_ID ) {
+           if( have_urec && !(urec.mark & 1) ) {
+              if( (rc = no_selfsig_del(lid, keyid, &urec )) )
+                  goto leave;
+               have_urec = 0;
+           }
+           if( have_urec ) {
+               rc = write_sigs_from_urec( lid, keyid, &urec );
                if( rc )
-                   log_fatal(_("set_signature_packets_local_id failed: %s\n"),
-                                                             g10_errstr(rc));
+                   goto leave;
+               rel_uidsigs( &urec );
            }
-           if( i == SIGS_PER_RECORD ) {
-               /* write the record */
-               rnum = tdbio_new_recnum();
-               if( rnum2 ) { /* write the stored record */
-                   rec2.r.sig.lid  = lid;
-                   rec2.r.sig.next = rnum; /* the next record number */
-                   rc = tdbio_write_record( rnum2, &rec2 );
-                   if( rc ) {
-                       log_error(_("build_sigrecs: write_record failed\n") );
-                       goto leave;
-                   }
-                   if( !first_sigrec )
-                       first_sigrec = rnum2;
-               }
-               rec2 = rec;
-               rnum2 = rnum;
-               memset( &rec, 0, sizeof rec );
-               rec.rectype = RECTYPE_SIG;
-               i = 0;
+           rc = find_urec( dir, node->pkt->pkt.user_id, &urec );
+           urec.next = NULL;
+           urec.mark = 0;
+           have_urec = sigidx = 0;
+           if( rc == -1 ) {
+               log_info("update_sigs: new user id for %lu\n", lid );
+               /* fixme: we should add the new user id here */
            }
-           rec.r.sig.sig[i].lid  = node->pkt->pkt.signature->local_id;
-           rec.r.sig.sig[i].flag = 0;
-           i++;
-       }
-    }
-    if( i || rnum2 ) {
-       /* write the record */
-       rnum = tdbio_new_recnum();
-       if( rnum2 ) { /* write the stored record */
-           rec2.r.sig.lid  = lid;
-           rec2.r.sig.next = rnum;
-           rc = tdbio_write_record( rnum2, &rec2 );
-           if( rc ) {
-               log_error(_("build_sigrecs: write_record failed\n") );
+           else if( rc ) {
+               log_error("update_sigs: find_urec %lu failed: %s\n",
+                                               lid, g10_errstr(rc) );
                goto leave;
            }
-           if( !first_sigrec )
-               first_sigrec = rnum2;
+           else
+               have_urec = 1;
        }
-       if( i ) { /* write the pending record */
-           rec.r.sig.lid = lid;
-           rec.r.sig.next = 0;
-           rc = tdbio_write_record( rnum, &rec );
-           if( rc ) {
-               log_error(_("build_sigrecs: write_record failed\n") );
-               goto leave;
+       else if( have_urec && node->pkt->pkttype == PKT_SIGNATURE ) {
+           PKT_signature *sig = node->pkt->pkt.signature;
+
+           if( (sig->sig_class&~3) == 0x10 ) {
+               rc = check_key_signature( keyblock, node, &i );
+               if( rc == G10ERR_NO_PUBKEY ) {
+                   log_info("key %08lX.%lu, uid %02X%02X: "
+                             "no public key for signature %08lX\n",
+                             (ulong)keyid[1], lid, urec.r.uid.namehash[18],
+                             urec.r.uid.namehash[19], (ulong)sig->keyid[1] );
+                   miskey = 1;
+               }
+               else if( rc )
+                   log_error("key %08lX.%lu, uid %02X%02X: "
+                             "invalid %ssignature: %s\n",
+                             (ulong)keyid[1], lid, urec.r.uid.namehash[18],
+                             urec.r.uid.namehash[19],
+                             i?"self-":"",g10_errstr(rc));
+               else if( i ) /* mark that we have a valid selfsignature */
+                   urec.mark |= 1;
+               else if( (rc = set_signature_packets_lid( sig )) )
+                   log_error("key %08lX.%lu, uid %02X%02X: "
+                             "can't get LID of signer: %s\n",
+                             (ulong)keyid[1], lid, urec.r.uid.namehash[18],
+                             urec.r.uid.namehash[19], g10_errstr(rc));
+               else if( !test_dupsig( urec.next, sig->local_id ) ) {
+                   /* put the valid signature into a list */
+                   rec = urec.next;
+                   if( !rec || sigidx == SIGS_PER_RECORD ) {
+                       rec = m_alloc_clear( sizeof *rec );
+                       rec->rectype = RECTYPE_SIG;
+                       rec->next = urec.next;
+                       urec.next = rec;
+                       sigidx = 0;
+                   }
+                   rec->r.sig.sig[sigidx].lid = sig->local_id;
+                   rec->r.sig.sig[sigidx].flag = 0;
+                   sigidx++;
+                   log_debug("key %08lX.%lu, uid %02X%02X: "
+                             "signed by LID %lu\n",
+                             (ulong)keyid[1], lid, urec.r.uid.namehash[18],
+                             urec.r.uid.namehash[19], sig->local_id);
+               }
+               else if( DBG_TRUST )
+                   log_debug("key %08lX.%lu, uid %02X%02X: "
+                             "duplicate signature by LID %lu\n",
+                             (ulong)keyid[1], lid, urec.r.uid.namehash[18],
+                             urec.r.uid.namehash[19], sig->local_id );
+               rc = 0;
+           }
+           else {
+               /* fixme: handle other sig classes here */
            }
-           if( !first_sigrec )
-               first_sigrec = rnum;
        }
     }
-    if( first_sigrec ) { /* update the uid records */
-       if( (rc =tdbio_read_record( pubkeyid, &rec, RECTYPE_DIR )) ) {
-           log_error(_("update_dir_record: read failed\n"));
+    if( have_urec && !(urec.mark & 1) ) {
+       if( (rc = no_selfsig_del(lid, keyid, &urec )) )
            goto leave;
-       }
-       rec.r.dir.sigrec = first_sigrec;
-       if( (rc=tdbio_write_record( pubkeyid, &rec )) ) {
-           log_error(_("update_dir_record: write failed\n"));
+       have_urec = 0;
+    }
+    if( have_urec ) {
+       rc = write_sigs_from_urec( lid, keyid, &urec );
+       if( rc )
            goto leave;
-       }
+       rel_uidsigs( &urec );
     }
+    dir->r.dir.dirflags |= DIRF_CHECKED;
+    if( miskey )
+       dir->r.dir.dirflags |= DIRF_MISKEY;
     else
-       tdbio_update_sigflag( lid, revoked? 3:1 ); /* no signatures */
+       dir->r.dir.dirflags &= ~DIRF_MISKEY;
+    rc = tdbio_write_record( dir );
+    if( rc ) {
+       log_error("update_sigs: write dir record failed: %s\n", g10_errstr(rc));
+       return rc;
+    }
 
   leave:
+    /* fixme: need more cleanup in case of an error */
     release_kbnode( keyblock );
     if( DBG_TRUST )
-       log_debug(_("trustdb: build_sigrecs: %s\n"), g10_errstr(rc) );
+       log_debug("update_sigs for %lu: %s\n", lid, g10_errstr(rc) );
+    return rc;
+}
+
+
+static int
+update_sigs_by_lid( ulong lid )
+{
+    int rc;
+    TRUSTREC rec;
+
+    rc = tdbio_read_record( lid, &rec, RECTYPE_DIR );
+    if( rc ) {
+       log_error("LID %lu: error reading dir record: %s\n",
+                               lid, g10_errstr(rc));
+       return rc;
+    }
+    if( !(rec.r.dir.dirflags & DIRF_CHECKED) )
+       rc = update_sigs( &rec );
     return rc;
 }
 
@@ -814,7 +1000,7 @@ build_sigrecs( ulong lid )
  * Make a list of trust paths
  */
 static int
-make_tsl( ulong pubkey_id, TRUST_SEG_LIST *ret_tslist )
+make_tsl( ulong lid, TRUST_SEG_LIST *ret_tslist )
 {
     int i, rc;
     LOCAL_ID_INFO *lids = new_lid_table();
@@ -824,17 +1010,17 @@ make_tsl( ulong pubkey_id, TRUST_SEG_LIST *ret_tslist )
 
     tslist = *ret_tslist = NULL;
 
-    if( !qry_lid_table_flag( ultikey_table, pubkey_id, NULL ) ) {
+    if( !qry_lid_table_flag( ultikey_table, lid, NULL ) ) {
        tslist = m_alloc( sizeof *tslist );
        tslist->nseg = 1;
        tslist->dup = 0;
-       tslist->seg[0].lid = pubkey_id;
+       tslist->seg[0].lid = lid;
        tslist->seg[0].trust = 0;
        tslist->next = NULL;
        rc = 0;
     }
     else {
-       stack[0].lid = pubkey_id;
+       stack[0].lid = lid;
        stack[0].trust = 0;
        rc = do_list_path( stack, 1, max_depth, lids, &tslist );
     }
@@ -901,17 +1087,6 @@ propagate_trust( TRUST_SEG_LIST tslist )
 }
 
 
-
-/****************
- * check whether we already build signature records
- * Return: true if we have.
- */
-static int
-do_we_have_sigs( TRUSTREC *dr )
-{
-}
-
-
 /****************
  * we have the pubkey record and all needed informations are in the trustdb
  * but nothing more is known.
@@ -934,41 +1109,36 @@ do_check( TRUSTREC *dr, unsigned *trustlevel )
 
     if( !dr->r.dir.keylist ) {
        log_error("Ooops, no keys\n");
-       return G10ERR_TRUSTDB
+       return G10ERR_TRUSTDB;
     }
     if( !dr->r.dir.uidlist ) {
        log_error("Ooops, no user ids\n");
-       return G10ERR_TRUSTDB
-    }
-
-    /* verify the cache */
-
-    /* do we have sigrecs */
-    if( !do_we_have_sigs( dr ) ) { /* no sigrecs, so build them */
-       rc = build_sigrecs( dr->lid );
-       if( !rc ) /* and read again */
-           rc = tdbio_read_record( dr->lid, dr, RECTYPE_DIR );
+       return G10ERR_TRUSTDB;
     }
 
+    /* did we already check the signatures */
+    if( !(dr->r.dir.dirflags & DIRF_CHECKED) ) /* no - do it now */
+       rc = update_sigs( dr );
 
-   !!!!WORK!!!!
-
-    if( dr->r.dir.no_sigs == 3 )
+    if( dr->r.dir.dirflags & DIRF_REVOKED )
        tflags |= TRUST_FLAG_REVOKED;
 
-    if( !rc && !dr->r.dir.sigrec ) {
-       /* See whether this is our own key */
-       if( !qry_lid_table_flag( ultikey_table, pubkeyid, NULL ) )
+  #if 0
+    if( !rc && !dr->r.dir.siglist ) {
+       /* We do not have any signatures; check whether it is one of our
+        * secret keys */
+       if( !qry_lid_table_flag( ultikey_table, dr->r.dir.lid, NULL ) )
            *trustlevel = tflags | TRUST_ULTIMATE;
        return 0;
     }
+  #endif
     if( rc )
        return rc;  /* error while looking for sigrec or building sigrecs */
 
     /* fixme: take it from the cache if it is valid */
 
     /* Make a list of all possible trust-paths */
-    rc = make_tsl( pubkeyid, &tslist );
+    rc = make_tsl( dr->r.dir.lid, &tslist );
     if( rc )
        return rc;
     rc = propagate_trust( tslist );
@@ -1023,7 +1193,7 @@ do_check( TRUSTREC *dr, unsigned *trustlevel )
            m_free(tsl);
        }
     }
-    last_trust_web_key = pubkeyid;
+    last_trust_web_key = dr->r.dir.lid;
     last_trust_web_tslist = tslist;
     return 0;
 }
@@ -1079,11 +1249,13 @@ list_trustdb( const char *username )
 
        if( (rc = get_pubkey_byname( pk, username )) )
            log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
-       else if( (rc=tdbio_search_record( pk, &rec )) && rc != -1 )
+       else if( (rc=tdbio_search_dir_record( pk, &rec )) && rc != -1 )
            log_error("problem finding '%s' in trustdb: %s\n",
                                                username, g10_errstr(rc));
        else if( rc == -1 )
            log_error("user '%s' not in trustdb\n", username);
+       else if( (rc = list_records( pk->local_id)) )
+           log_error("user '%s' read problem: %s\n", username, g10_errstr(rc));
        else if( (rc = list_sigs( pk->local_id )) )
            log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
        free_public_key( pk );
@@ -1097,27 +1269,40 @@ list_trustdb( const char *username )
            putchar('-');
        putchar('\n');
        for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ )
-           tdbio_dump_record( recnum, &rec, stdout );
+           tdbio_dump_record( &rec, stdout );
     }
 }
 
 /****************
- * make a list of all owner trust value.
+ * make a list of all defined owner trust value.
  */
 void
 list_ownertrust()
 {
     TRUSTREC rec;
+    TRUSTREC rec2;
     ulong recnum;
     int i;
     byte *p;
+    int rc;
 
     for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
-       if( rec.rectype == RECTYPE_KEY ) {
-           p = rec.r.key.fingerprint;
-           for(i=0; i < rec.r.key.fingerprint_len; i++, p++ )
+       if( rec.rectype == RECTYPE_DIR ) {
+           if( !rec.r.dir.keylist ) {
+               log_error("Oops; directory record w/o primary key\n");
+               continue;
+           }
+           if( !rec.r.dir.ownertrust )
+               continue;
+           rc = tdbio_read_record( rec.r.dir.keylist, &rec2, RECTYPE_KEY);
+           if( rc ) {
+               log_error("error reading key record: %s\n", g10_errstr(rc));
+               continue;
+           }
+           p = rec2.r.key.fingerprint;
+           for(i=0; i < rec2.r.key.fingerprint_len; i++, p++ )
                printf("%02X", *p );
-           printf(":%u:\n", (unsigned)rec.r.key.ownertrust );
+           printf(":%u:\n", (unsigned)rec.r.dir.ownertrust );
        }
     }
 }
@@ -1138,7 +1323,7 @@ list_trust_path( int max_depth, const char *username )
 
     if( (rc = get_pubkey_byname( pk, username )) )
        log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
-    else if( (rc=tdbio_search_record( pk, &rec )) && rc != -1 )
+    else if( (rc=tdbio_search_dir_record( pk, &rec )) && rc != -1 )
        log_error("problem finding '%s' in trustdb: %s\n",
                                            username, g10_errstr(rc));
     else if( rc == -1 ) {
@@ -1212,6 +1397,48 @@ list_trust_path( int max_depth, const char *username )
 
 
 /****************
+ * Check the complete trustdb or only the entries for the given username
+ */
+void
+check_trustdb( const char *username )
+{
+    TRUSTREC rec;
+    int rc;
+
+    if( username ) {
+       PKT_public_key *pk = m_alloc_clear( sizeof *pk );
+
+       if( (rc = get_pubkey_byname( pk, username )) )
+           log_error("user '%s' not found: %s\n", username, g10_errstr(rc) );
+       else if( (rc=tdbio_search_dir_record( pk, &rec )) && rc != -1 )
+           log_error("problem finding '%s' in trustdb: %s\n",
+                                               username, g10_errstr(rc));
+       else if( rc == -1 )
+           log_error("user '%s' not in trustdb\n", username);
+       else if( (rc = update_sigs( &rec )) )
+           log_error("lid %lu: check failed: %s\n",
+                                       rec.recnum, g10_errstr(rc));
+       else
+           log_info("lid %lu: checked: %s\n", rec.recnum, g10_errstr(rc));
+       free_public_key( pk );
+    }
+    else {
+       ulong recnum;
+
+       for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
+           if( rec.rectype == RECTYPE_DIR ) {
+               rc = update_sigs( &rec );
+               if( rc )
+                   log_error("lid %lu: check failed: %s\n",
+                                                recnum, g10_errstr(rc) );
+               else
+                   log_info("lid %lu: checked\n", recnum );
+           }
+       }
+    }
+}
+
+/****************
  * Get the trustlevel for this PK.
  * Note: This does not ask any questions
  * Returns: 0 okay of an errorcode
@@ -1385,35 +1612,15 @@ get_ownertrust( ulong lid, unsigned *r_otrust )
        log_error("get_ownertrust: read dir record failed\n");
        return G10ERR_TRUSTDB;
     }
-    if( tdbio_read_record( rec.r.dir.keyrec, &rec, RECTYPE_KEY ) ) {
-       log_error("get_ownertrust: read key record failed\n");
-       return G10ERR_TRUSTDB;
-    }
     if( r_otrust )
-       *r_otrust = rec.r.key.ownertrust;
-    return 0;
-}
-
-int
-keyid_from_trustdb( ulong lid, u32 *keyid )
-{
-    TRUSTREC rec;
-
-    if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
-       log_error("keyid_from_trustdb: read record failed\n");
-       return G10ERR_TRUSTDB;
-    }
-    if( keyid ) {
-       keyid[0] = rec.r.dir.keyid[0];
-       keyid[1] = rec.r.dir.keyid[1];
-    }
+       *r_otrust = rec.r.dir.ownertrust;
     return 0;
 }
 
 
 /****************
  * This function simply looks for the key in the trustdb
- * and sets PK->local_id.
+ * and makes sure that pk->local_id is set to the coreect value.
  * Return: 0 = found
  *        -1 = not found
  *       other = error
@@ -1431,7 +1638,7 @@ query_trust_record( PKT_public_key *pk )
        }
     }
     else { /* no local_id: scan the trustdb */
-       if( (rc=tdbio_search_record( pk, &rec )) && rc != -1 ) {
+       if( (rc=tdbio_search_dir_record( pk, &rec )) && rc != -1 ) {
            log_error("query_trust_record: search_record failed: %s\n",
                                                            g10_errstr(rc));
            return rc;
@@ -1457,10 +1664,6 @@ rel_mem_uidnode( u32 *keyid, int err, TRUSTREC *rec )
        r2 = r->next;
        m_free(r);
     }
-    for(r=rec->help_sig; r; r = r2 ) {
-       r2 = r->next;
-       m_free(r);
-    }
 
     m_free(rec);
 }
@@ -1469,17 +1672,19 @@ rel_mem_uidnode( u32 *keyid, int err, TRUSTREC *rec )
 /****************
  * Insert a trust record into the TrustDB
  * This function fails if this record already exists.
+ *
+ * We build everything we can do at this point. We cannot build
+ * the sig records, because their LIDs are needed and we may not have them.
  */
 int
 insert_trust_record( PKT_public_key *orig_pk )
 {
     TRUSTREC dirrec, *rec, *rec2;
-    TRUSTREC *keylist_head, **keylist_tail;
-    TRUSTREC *uidlist_head, **uidlist_tail, uidlist;
+    TRUSTREC *keylist_head, **keylist_tail, *keylist;
+    TRUSTREC *uidlist_head, **uidlist_tail, *uidlist;
     KBNODE keyblock = NULL;
     KBNODE node;
     u32 keyid[2]; /* of primary key */
-    ulong knum, dnum;
     byte *fingerprint;
     size_t fingerlen;
     int rc = 0;
@@ -1489,9 +1694,9 @@ insert_trust_record( PKT_public_key *orig_pk )
     dirrec.rectype = RECTYPE_DIR;
 
     if( orig_pk->local_id )
-       log_bug("pk->local_id=%lu\n", (ulong)pk->local_id );
+       log_bug("pk->local_id=%lu\n", (ulong)orig_pk->local_id );
 
-    fingerprint = fingerprint_from_pk( orig_pk, &fingerlen );
+    fingerprint = fingerprint_from_pk( orig_pk, NULL, &fingerlen );
 
     /* fixme: assert that we do not have this record.
      * we can do this by searching for the primary keyid
@@ -1506,9 +1711,8 @@ insert_trust_record( PKT_public_key *orig_pk )
     }
 
     /* build data structure as linked lists in memory */
-    keylist_head = NULL; keylist_tail = &keylist_head;
-    uidlist_head = NULL; uidlist_tail = &uidlist_head;
-    uidlist = NULL;
+    keylist_head = NULL; keylist_tail = &keylist_head; keylist = NULL;
+    uidlist_head = NULL; uidlist_tail = &uidlist_head; uidlist = NULL;
     keyid[0] = keyid[1] = 0;
     for( node=keyblock; node; node = node->next ) {
        if( node->pkt->pkttype == PKT_PUBLIC_KEY
@@ -1520,7 +1724,7 @@ insert_trust_record( PKT_public_key *orig_pk )
                    BUG();  /* more than one primary key */
                keyid_from_pk( pk, keyid );
            }
-           fingerprint = fingerprint_from_pk( orig_pk, &fingerlen );
+           fingerprint = fingerprint_from_pk( orig_pk, NULL, &fingerlen );
            rec = m_alloc_clear( sizeof *rec );
            rec->rectype = RECTYPE_KEY;
            rec->r.key.pubkey_algo = pk->pubkey_algo;
@@ -1554,8 +1758,8 @@ insert_trust_record( PKT_public_key *orig_pk )
                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) );
+                             (ulong)keyid[1], uidlist->r.uid.namehash[18],
+                             uidlist->r.uid.namehash[19], g10_errstr(rc) );
                    rc = 0;
                }
                else { /* build the prefrecord */
@@ -1567,10 +1771,6 @@ insert_trust_record( PKT_public_key *orig_pk )
                /* 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
-                */
            }
        }
     }
@@ -1592,7 +1792,7 @@ insert_trust_record( PKT_public_key *orig_pk )
     /* 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,
+       rc = G10ERR_BAD_CERT;
        goto leave;
     }
 
@@ -1600,7 +1800,6 @@ insert_trust_record( PKT_public_key *orig_pk )
     /* 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;
@@ -1620,15 +1819,7 @@ insert_trust_record( PKT_public_key *orig_pk )
        }
        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;
+       rec->r.uid.prefrec = rec->help_pref? rec->help_pref->recnum : 0;
     }
     for(rec=uidlist_head; rec; rec = rec->next )
        rec->r.uid.next = rec->next? rec->next->recnum : 0;
@@ -1650,7 +1841,7 @@ insert_trust_record( PKT_public_key *orig_pk )
            rc = G10ERR_TRUSTDB;
            goto leave;
        }
-       for( rec2=rec->help_pref; rec2; rec2 = rec2->next ); {
+       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");
@@ -1658,29 +1849,33 @@ insert_trust_record( PKT_public_key *orig_pk )
                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 ) ) {
+    if( tdbio_write_record( &dirrec ) ) {
        log_error("writing dir record failed\n");
        return G10ERR_TRUSTDB;
     }
 
     /* and store the LID */
     orig_pk->local_id = dirrec.r.dir.lid;
+    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;
+           pk->local_id = dirrec.r.dir.lid;
+       }
+       else if( node->pkt->pkttype == PKT_SIGNATURE ) {
+           PKT_signature *sig = node->pkt->pkt.signature;
+           sig->local_id = dirrec.r.dir.lid;
+       }
+    }
+
 
   leave:
-    for( rec=dirrec.r.dir.uidlist; rec; rec = rec2 ) {
+    for(rec=uidlist_head; rec; rec = rec->next ) {
        rec2 = rec->next;
-       rel_mem_uidnode(rec);
+       rel_mem_uidnode(NULL, 0, rec );
     }
-    for( rec=dirrec.r.dir.keylist; rec; rec = rec2 ) {
+    for(rec=keylist_head; rec; rec = rec->next ) {
        rec2 = rec->next;
        m_free(rec);
     }
@@ -1693,29 +1888,17 @@ int
 update_ownertrust( ulong lid, unsigned new_trust )
 {
     TRUSTREC rec;
-    ulong recnum;
 
     if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) {
        log_error("update_ownertrust: read dir failed\n");
        return G10ERR_TRUSTDB;
     }
-    recnum = rec.r.dir.keyrec;
-    if( tdbio_read_record( recnum, &rec, RECTYPE_KEY ) ) {
-       log_error("update_ownertrust: read key failed\n");
-       return G10ERR_TRUSTDB;
-    }
-    /* check keyid, fingerprint etc ? */
-
-    rec.r.key.ownertrust = new_trust;
-    if( tdbio_write_record( recnum, &rec ) ) {
+    rec.r.dir.ownertrust = new_trust;
+    if( tdbio_write_record( &rec ) ) {
        log_error("update_ownertrust: write failed\n");
        return G10ERR_TRUSTDB;
     }
-
     return 0;
 }
 
 
-
-
-
index 705ffaf..aaf0d4a 100644 (file)
 void list_trustdb(const char *username);
 void list_trust_path( int max_depth, const char *username );
 void list_ownertrust(void);
+void check_trustdb( const char *username );
 int init_trustdb( int level, const char *dbname );
 int check_trust( PKT_public_key *pk, unsigned *r_trustlevel );
 int query_trust_info( PKT_public_key *pk );
 int enum_trust_web( void **context, ulong *lid );
 int get_ownertrust( ulong lid, unsigned *r_otrust );
-int keyid_from_trustdb( ulong lid, u32 *keyid );
+int keyid_from_lid( ulong lid, u32 *keyid );
 int query_trust_record( PKT_public_key *pk );
 int insert_trust_record( PKT_public_key *pk );
 int update_ownertrust( ulong lid, unsigned new_trust );
diff --git a/tools/mk-tdata b/tools/mk-tdata
deleted file mode 100755 (executable)
index 7fcfb38..0000000
Binary files a/tools/mk-tdata and /dev/null differ
index 6b4a76f..a52ea0a 100644 (file)
@@ -1,3 +1,11 @@
+Tue Jul 21 10:35:48 1998  Werner Koch  (wk@(none))
+
+       * argparse.c: New option flag to distinguish options and commands.
+
+Sat Jul 18 19:49:30 1998  Werner Koch  (wk@(none))
+
+       * argparse.c (arg_parse): Added -? as alias for -h
+
 Thu Jul  9 14:47:20 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * secmem.c (secmem_init): Drops setuid if called with 0.
index 9a9909e..766d461 100644 (file)
  *              4 = takes ulong argument
  *     Bit 3 : argument is optional (r_type will the be set to 0)
  *     Bit 4 : allow 0x etc. prefixed values.
+ *     Bit 7 : this is an command and not an option
  *  If can stop the option processing by setting opts to NULL, the function will
  *  then return 0.
  * @Return Value
  *   Returns the args.r_opt or 0 if ready
- *   r_opt may be -2 to indicate an unknown option.
+ *   r_opt may be -2/-7 to indicate an unknown option/command.
  * @See Also
  *   ArgExpand
  * @Notes
@@ -157,6 +158,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
                s = "%s:%u: keyword too long\n";
            else if( arg->r_opt == -3 )
                s = "%s:%u: missing argument\n";
+           else if( arg->r_opt == -7 )
+               s = "%s:%u: invalid command\n";
            else
                s = "%s:%u: invalid option\n";
            log_error(s, filename, *lineno );
@@ -164,6 +167,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
        else {
            if( arg->r_opt == -3 )
                s = "Missing argument for option \"%.50s\"\n";
+           else if( arg->r_opt == -7 )
+               s = "Invalid command \"%.50s\"\n";
            else
                s = "Invalid option \"%.50s\"\n";
            log_error(s, arg->internal.last? arg->internal.last:"[??]" );
@@ -220,8 +225,8 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
                arg->r_opt = opts[index].short_opt;
                if( inverse )
                    arg->r_opt = -arg->r_opt;
-               if( !opts[index].short_opt )
-                   arg->r_opt = -2;           /* unknown option */
+               if( !opts[index].short_opt )     /* unknown command/option */
+                   arg->r_opt = (opts[index].flags & 256)? -7:-2;
                else if( (opts[index].flags & 8) ) /* no argument */
                    arg->r_opt = -3;           /* error */
                else                           /* no or optiona argument */
@@ -279,7 +284,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
            index = i;
            arg->r_opt = opts[index].short_opt;
            if( !opts[index].short_opt ) {
-               arg->r_opt = -2;   /* unknown option */
+               arg->r_opt = (opts[index].flags & 256)? -7:-2;
                state = -1;        /* skip rest of line and leave */
            }
            else
@@ -390,7 +395,7 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
 
        arg->r_opt = opts[i].short_opt;
        if( !opts[i].short_opt ) {
-           arg->r_opt = -2; /* unknown option */
+           arg->r_opt = (opts[i].flags & 256)? -7:-2;
            arg->r.ret_str = s+2;
        }
        else if( (opts[i].flags & 7) ) {
@@ -438,12 +443,12 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
                    break;
        }
 
-       if( !opts[i].short_opt && *s == 'h' )
+       if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) )
            show_help(opts, arg->flags);
 
        arg->r_opt = opts[i].short_opt;
        if( !opts[i].short_opt ) {
-           arg->r_opt = -2; /* unknown option */
+           arg->r_opt = (opts[i].flags & 256)? -7:-2;
            arg->internal.inarg++; /* point to the next arg */
            arg->r.ret_str = s;
        }