* mainproc.c (list_node): Show signature expiration date in with-colons
[gnupg.git] / g10 / trustdb.c
index 312290e..7f38bbc 100644 (file)
@@ -1,5 +1,6 @@
 /* trustdb.c
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ *                                             Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -287,9 +288,8 @@ verify_own_keys(void)
                             (ulong)kid[1]);
         }
     }
-  
-  /* the --trusted-key option is again deprecated; however we automagically
-   * add those keys to the trustdb */
+
+  /* Put any --trusted-key keys into the trustdb */
   for (k = user_utk_list; k; k = k->next) 
     {
       if ( add_utk (k->kid) ) 
@@ -425,7 +425,8 @@ init_trustdb()
   if( rc )
     log_fatal("can't init trustdb: %s\n", g10_errstr(rc) );
 
-  if(!tdbio_db_matches_options())
+  if(!tdbio_db_matches_options()
+     && (opt.trust_model==TM_CLASSIC || opt.trust_model==TM_OPENPGP))
     pending_check_trustdb=1;
 }
 
@@ -440,7 +441,7 @@ init_trustdb()
  * This function returns a letter for a trustvalue  Trust flags
  * are ignore.
  */
-int
+static int
 trust_letter (unsigned int value)
 {
   switch( (value & TRUST_MASK) ) 
@@ -452,7 +453,7 @@ trust_letter (unsigned int value)
     case TRUST_MARGINAL:  return 'm';
     case TRUST_FULLY:     return 'f';
     case TRUST_ULTIMATE:  return 'u';
-    default:              return 0;
+    default:              return '?';
     }
 }
 
@@ -463,13 +464,13 @@ trust_string (unsigned int value)
 {
   switch( (value & TRUST_MASK) ) 
     {
-    case TRUST_UNKNOWN:   return _("unknown trust");
+    case TRUST_UNKNOWN:   return _("unknown");
     case TRUST_EXPIRED:   return _("expired");
-    case TRUST_UNDEFINED: return _("undefined trust");
-    case TRUST_NEVER:     return _("do NOT trust");
-    case TRUST_MARGINAL:  return _("marginal trust");
-    case TRUST_FULLY:     return _("full trust");
-    case TRUST_ULTIMATE:  return _("ultimate trust");
+    case TRUST_UNDEFINED: return _("undefined");
+    case TRUST_NEVER:     return _("never");
+    case TRUST_MARGINAL:  return _("marginal");
+    case TRUST_FULLY:     return _("full");
+    case TRUST_ULTIMATE:  return _("ultimate");
     default:              return "err";
     }
 }
@@ -629,31 +630,48 @@ get_min_ownertrust (PKT_public_key *pk)
 }
 
 /*
- * Same as get_ownertrust but return a trust letter instead of an value.
+ * Same as get_ownertrust but this takes the minimum ownertrust value
+ * into into account, and will bump up the value as needed.
  */
-int
-get_ownertrust_info (PKT_public_key *pk)
+static int
+get_ownertrust_with_min (PKT_public_key *pk)
 {
-    unsigned int otrust,otrust_min;
-    int c;
+  unsigned int otrust,otrust_min;
 
-    otrust = get_ownertrust (pk);
-    otrust_min = get_min_ownertrust (pk);
-    if(otrust<otrust_min)
-      {
-       /* If the trust that the user has set is less than the trust
-          that was calculated from a trust signature chain, use the
-          higher of the two.  We do this here and not in
-          get_ownertrust since the underlying ownertrust should not
-          really be set - just the appearance of the ownertrust. */
+  otrust = get_ownertrust (pk);
+  otrust_min = get_min_ownertrust (pk);
+  if(otrust<otrust_min)
+    {
+      /* If the trust that the user has set is less than the trust
+        that was calculated from a trust signature chain, use the
+        higher of the two.  We do this here and not in
+        get_ownertrust since the underlying ownertrust should not
+        really be set - just the appearance of the ownertrust. */
 
-       otrust=otrust_min;
-      }
+      otrust=otrust_min;
+    }
 
-    c = trust_letter( (otrust & TRUST_MASK) );
-    if( !c )
-       c = '?';
-    return c;
+  return otrust;
+}
+
+/*
+ * Same as get_ownertrust but return a trust letter instead of an
+ * value.  This takes the minimum ownertrust value into account.
+ */
+int
+get_ownertrust_info (PKT_public_key *pk)
+{
+  return trust_letter(get_ownertrust_with_min(pk));
+}
+
+/*
+ * Same as get_ownertrust but return a trust string instead of an
+ * value.  This takes the minimum ownertrust value into account.
+ */
+const char *
+get_ownertrust_string (PKT_public_key *pk)
+{
+  return trust_string(get_ownertrust_with_min(pk));
 }
 
 /*
@@ -796,13 +814,15 @@ clear_ownertrusts (PKT_public_key *pk)
  * Note: Caller has to do a sync 
  */
 static void
-update_validity (PKT_public_key *pk, const byte *namehash,
+update_validity (PKT_public_key *pk, PKT_user_id *uid,
                  int depth, int validity)
 {
   TRUSTREC trec, vrec;
   int rc;
   ulong recno;
-  
+
+  namehash_from_uid(uid);
+
   rc = read_trust_record (pk, &trec);
   if (rc && rc != -1)
     {
@@ -826,7 +846,7 @@ update_validity (PKT_public_key *pk, const byte *namehash,
   while (recno)
     {
       read_record (recno, &vrec, RECTYPE_VALID);
-      if ( !memcmp (vrec.r.valid.namehash, namehash, 20) )
+      if ( !memcmp (vrec.r.valid.namehash, uid->namehash, 20) )
         break;
       recno = vrec.r.valid.next;
     }
@@ -836,10 +856,12 @@ update_validity (PKT_public_key *pk, const byte *namehash,
       memset (&vrec, 0, sizeof vrec);
       vrec.recnum = tdbio_new_recnum ();
       vrec.rectype = RECTYPE_VALID;
-      memcpy (vrec.r.valid.namehash, namehash, 20);
+      memcpy (vrec.r.valid.namehash, uid->namehash, 20);
       vrec.r.valid.next = trec.r.trust.validlist;
     }
   vrec.r.valid.validity = validity;
+  vrec.r.valid.full_count = uid->help_full_count;
+  vrec.r.valid.marginal_count = uid->help_marginal_count;
   write_record (&vrec);
   trec.r.trust.depth = depth;
   trec.r.trust.validlist = vrec.recnum;
@@ -872,14 +894,15 @@ clear_validity (PKT_public_key *pk)
       write_record(&trec);
     }
 
-  /* reset validity for all user IDs */
   recno = trec.r.trust.validlist;
   while (recno)
     {
       read_record (recno, &vrec, RECTYPE_VALID);
-      if ((vrec.r.valid.validity & TRUST_MASK))
+      if ((vrec.r.valid.validity & TRUST_MASK)
+         || vrec.r.valid.marginal_count || vrec.r.valid.full_count)
         {
           vrec.r.valid.validity &= ~TRUST_MASK;
+         vrec.r.valid.marginal_count = vrec.r.valid.full_count = 0;
           write_record (&vrec);
           any = 1;
         }
@@ -935,7 +958,7 @@ is_disabled(void *dummy,u32 *keyid)
  * otherwise, a reasonable value for the entire key is returned. 
  */
 unsigned int
-get_validity (PKT_public_key *pk, const byte *namehash)
+get_validity (PKT_public_key *pk, PKT_user_id *uid)
 {
   static int did_nextcheck;
   TRUSTREC trec, vrec;
@@ -945,8 +968,12 @@ get_validity (PKT_public_key *pk, const byte *namehash)
   u32 kid[2];
   PKT_public_key *main_pk;
 
+  if(uid)
+    namehash_from_uid(uid);
+  
   init_trustdb ();
-  if (!did_nextcheck)
+  if (!did_nextcheck
+      && (opt.trust_model==TM_CLASSIC || opt.trust_model==TM_OPENPGP))
     {
       ulong scheduled;
 
@@ -1003,7 +1030,7 @@ get_validity (PKT_public_key *pk, const byte *namehash)
       read_record (recno, &vrec, RECTYPE_VALID);
       if ( validity < (vrec.r.valid.validity & TRUST_MASK) )
         validity = (vrec.r.valid.validity & TRUST_MASK);
-      if ( namehash && !memcmp (vrec.r.valid.namehash, namehash, 20) )
+      if ( uid && !memcmp (vrec.r.valid.namehash, uid->namehash, 20) )
         break;
       recno = vrec.r.valid.next;
     }
@@ -1033,35 +1060,69 @@ get_validity (PKT_public_key *pk, const byte *namehash)
   return validity;
 }
 
-
 int
-get_validity_info (PKT_public_key *pk, const byte *namehash)
+get_validity_info (PKT_public_key *pk, PKT_user_id *uid)
 {
     int trustlevel;
-    int c;
 
-    trustlevel = get_validity (pk, namehash);
-    if( trustlevel & TRUST_FLAG_DISABLED )
-       return 'd';
+    trustlevel = get_validity (pk, uid);
     if( trustlevel & TRUST_FLAG_REVOKED )
        return 'r';
-    c = trust_letter ( (trustlevel & TRUST_MASK) );
-    if( !c )
-       c = '?';
-    return c;
+    return trust_letter ( trustlevel );
 }
 
+const char *
+get_validity_string (PKT_public_key *pk, PKT_user_id *uid)
+{
+  int trustlevel;
+
+  trustlevel = get_validity (pk, uid);
+  if( trustlevel & TRUST_FLAG_REVOKED )
+    return _("revoked");
+  return trust_string(trustlevel);
+}
+
+static void
+get_validity_counts (PKT_public_key *pk, PKT_user_id *uid)
+{
+  TRUSTREC trec, vrec;
+  ulong recno;
+
+  if(pk==NULL || uid==NULL)
+    BUG();
+
+  namehash_from_uid(uid);
+
+  uid->help_marginal_count=uid->help_full_count=0;
+
+  init_trustdb ();
+
+  if(read_trust_record (pk, &trec)!=0)
+    return;
+
+  /* loop over all user IDs */
+  recno = trec.r.trust.validlist;
+  while (recno)
+    {
+      read_record (recno, &vrec, RECTYPE_VALID);
 
+      if(memcmp(vrec.r.valid.namehash,uid->namehash,20)==0)
+       {
+         uid->help_marginal_count=vrec.r.valid.marginal_count;
+         uid->help_full_count=vrec.r.valid.full_count;
+         /*  printf("Fetched marginal %d, full %d\n",uid->help_marginal_count,uid->help_full_count); */
+         break;
+       }
 
+      recno = vrec.r.valid.next;
+    }
+}
 
 void
 list_trust_path( const char *username )
 {
 }
 
-
-
-
 /****************
  * Enumerate all keys, which are needed to build all trust paths for
  * the given key.  This function does not return the key itself or
@@ -1149,7 +1210,7 @@ mark_keyblock_seen (KeyHashTable tbl, KBNODE node)
 {
   for ( ;node; node = node->next )
     if (node->pkt->pkttype == PKT_PUBLIC_KEY
-        || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
+       || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
       {
         u32 aki[2];
 
@@ -1159,7 +1220,6 @@ mark_keyblock_seen (KeyHashTable tbl, KBNODE node)
 }
 
 
-
 static void
 dump_key_array (int depth, struct key_array *keys)
 {
@@ -1197,10 +1257,9 @@ dump_key_array (int depth, struct key_array *keys)
 
 
 static void
-store_validation_status (int depth, KBNODE keyblock)
+store_validation_status (int depth, KBNODE keyblock, KeyHashTable stored)
 {
   KBNODE node;
-  byte namehash[20];
   int status;
   int any = 0;
 
@@ -1209,7 +1268,6 @@ store_validation_status (int depth, KBNODE keyblock)
       if (node->pkt->pkttype == PKT_USER_ID)
         {
           PKT_user_id *uid = node->pkt->pkt.user_id;
-
           if (node->flag & 4)
             status = TRUST_FULLY;
           else if (node->flag & 2)
@@ -1221,13 +1279,11 @@ store_validation_status (int depth, KBNODE keyblock)
           
           if (status)
             {
-              if( uid->attrib_data )
-                rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len);
-              else
-                rmd160_hash_buffer (namehash, uid->name, uid->len );
-              
               update_validity (keyblock->pkt->pkt.public_key,
-                               namehash, depth, status);
+                              uid, depth, status);
+
+             mark_keyblock_seen(stored,keyblock);
+
               any = 1;
             }
         }
@@ -1449,9 +1505,10 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist,
 {
   struct key_item *kr;
   KBNODE node, uidnode=NULL;
+  PKT_user_id *uid=NULL;
   PKT_public_key *pk = kb->pkt->pkt.public_key;
   u32 main_kid[2];
-  int issigned=0, any_signed = 0, fully_count =0, marginal_count = 0;
+  int issigned=0, any_signed = 0;
 
   keyid_from_pk(pk, main_kid);
   for (node=kb; node; node = node->next)
@@ -1460,22 +1517,23 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist,
         {
           if (uidnode && issigned)
             {
-              if (fully_count >= opt.completes_needed
-                  || marginal_count >= opt.marginals_needed )
+              if (uid->help_full_count >= opt.completes_needed
+                  || uid->help_marginal_count >= opt.marginals_needed )
                 uidnode->flag |= 4; 
-              else if (fully_count || marginal_count)
+              else if (uid->help_full_count || uid->help_marginal_count)
                 uidnode->flag |= 2;
               uidnode->flag |= 1;
               any_signed = 1;
             }
           uidnode = node;
+         uid=uidnode->pkt->pkt.user_id;
           issigned = 0;
-          fully_count = marginal_count = 0;
+         get_validity_counts(pk,uid);
           mark_usable_uid_certs (kb, uidnode, main_kid, klist, 
                                  curtime, next_expire);
         }
       else if (node->pkt->pkttype == PKT_SIGNATURE 
-               && (node->flag & (1<<8)) )
+               && (node->flag & (1<<8)) && uid)
         {
          /* Note that we are only seeing unrevoked sigs here */
           PKT_signature *sig = node->pkt->pkt.signature;
@@ -1535,12 +1593,12 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist,
                    pk->trust_regexp=sig->trust_regexp;
                }
 
-             if (kr->ownertrust == TRUST_ULTIMATE)
-                fully_count = opt.completes_needed;
+              if (kr->ownertrust == TRUST_ULTIMATE)
+                uid->help_full_count = opt.completes_needed;
               else if (kr->ownertrust == TRUST_FULLY)
-                fully_count++;
+                uid->help_full_count++;
               else if (kr->ownertrust == TRUST_MARGINAL)
-                marginal_count++;
+                uid->help_marginal_count++;
               issigned = 1;
            }
         }
@@ -1548,10 +1606,10 @@ validate_one_keyblock (KBNODE kb, struct key_item *klist,
 
   if (uidnode && issigned)
     {
-      if (fully_count >= opt.completes_needed
-               || marginal_count >= opt.marginals_needed )
+      if (uid->help_full_count >= opt.completes_needed
+         || uid->help_marginal_count >= opt.marginals_needed )
         uidnode->flag |= 4; 
-      else if (fully_count || marginal_count)
+      else if (uid->help_full_count || uid->help_marginal_count)
         uidnode->flag |= 2;
       uidnode->flag |= 1;
       any_signed = 1;
@@ -1576,7 +1634,7 @@ search_skipfnc (void *opaque, u32 *kid)
  * Caller hast to release the returned array.  
  */
 static struct key_array *
-validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
+validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust,
                    struct key_item *klist, u32 curtime, u32 *next_expire)
 {
   KBNODE keyblock = NULL;
@@ -1600,7 +1658,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
   memset (&desc, 0, sizeof desc);
   desc.mode = KEYDB_SEARCH_MODE_FIRST;
   desc.skipfnc = search_skipfnc;
-  desc.skipfncvalue = visited;
+  desc.skipfncvalue = full_trust;
   rc = keydb_search (hd, &desc, 1);
   if (rc == -1)
     {
@@ -1643,10 +1701,12 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
       if (pk->has_expired || pk->is_revoked)
         {
           /* it does not make sense to look further at those keys */
-          mark_keyblock_seen (visited, keyblock);
+          mark_keyblock_seen (full_trust, keyblock);
         }
       else if (validate_one_keyblock (keyblock, klist, curtime, next_expire))
         {
+         KBNODE node;
+
           if (pk->expiredate && pk->expiredate >= curtime
               && pk->expiredate < *next_expire)
             *next_expire = pk->expiredate;
@@ -1656,8 +1716,17 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
             keys = m_realloc (keys, (maxkeys+1) * sizeof *keys);
           }
           keys[nkeys++].keyblock = keyblock;
-          /* this key is signed - don't check it again */
-          mark_keyblock_seen (visited, keyblock);
+
+         /* Optimization - if all uids are fully trusted, then we
+            never need to consider this key as a candidate again. */
+
+         for (node=keyblock; node; node = node->next)
+           if (node->pkt->pkttype == PKT_USER_ID && !(node->flag & 4))
+             break;
+
+         if(node==NULL)
+           mark_keyblock_seen (full_trust, keyblock);
+
           keyblock = NULL;
         }
 
@@ -1676,9 +1745,9 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable visited,
   return keys;
 } 
 
-
+/* Caller must sync */
 static void
-reset_unconnected_keys (KEYDB_HANDLE hd, KeyHashTable visited)
+reset_trust_records (KEYDB_HANDLE hd, KeyHashTable exclude)
 {
   int rc;
   KBNODE keyblock = NULL;
@@ -1694,8 +1763,11 @@ reset_unconnected_keys (KEYDB_HANDLE hd, KeyHashTable visited)
 
   memset (&desc, 0, sizeof desc);
   desc.mode = KEYDB_SEARCH_MODE_FIRST;
-  desc.skipfnc = search_skipfnc;
-  desc.skipfncvalue = visited;
+  if(exclude)
+    {
+      desc.skipfnc = search_skipfnc;
+      desc.skipfncvalue = exclude;
+    }
   rc = keydb_search (hd, &desc, 1);
   if (rc && rc != -1 )
     log_error ("keydb_search_first failed: %s\n", g10_errstr(rc));
@@ -1723,11 +1795,9 @@ reset_unconnected_keys (KEYDB_HANDLE hd, KeyHashTable visited)
         log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
     }
   if (opt.verbose)
-    log_info ("%d unconnected keys (%d trust records cleared)\n",
+    log_info ("%d keys processed (%d validity counts cleared)\n",
               count, nreset);
-  do_sync ();
-} 
-
+}
 
 /*
  * Run the key validation procedure.
@@ -1767,12 +1837,14 @@ validate_keys (int interactive)
   int depth;
   int key_count;
   int ot_unknown, ot_undefined, ot_never, ot_marginal, ot_full, ot_ultimate;
-  KeyHashTable visited;
+  KeyHashTable stored,used,full_trust;
   u32 start_time, next_expire;
 
   start_time = make_timestamp ();
   next_expire = 0xffffffff; /* set next expire to the year 2106 */
-  visited = new_key_hash_table ();
+  stored = new_key_hash_table ();
+  used = new_key_hash_table ();
+  full_trust = new_key_hash_table ();
   /* Fixme: Instead of always building a UTK list, we could just build it
    * here when needed */
   if (!utk_list)
@@ -1781,7 +1853,12 @@ validate_keys (int interactive)
       goto leave;
     }
 
-  /* mark all UTKs as visited and set validity to ultimate */
+  kdb = keydb_new (0);
+
+  reset_trust_records (kdb,NULL);
+
+  /* mark all UTKs as used and fully_trusted and set validity to
+     ultimate */
   for (k=utk_list; k; k = k->next)
     {
       KBNODE keyblock;
@@ -1794,21 +1871,14 @@ validate_keys (int interactive)
                        " trusted key %08lX not found\n"), (ulong)k->kid[1]);
           continue;
         }
-      mark_keyblock_seen (visited, keyblock);
+      mark_keyblock_seen (used, keyblock);
+      mark_keyblock_seen (stored, keyblock);
+      mark_keyblock_seen (full_trust, keyblock);
       pk = keyblock->pkt->pkt.public_key;
       for (node=keyblock; node; node = node->next)
         {
           if (node->pkt->pkttype == PKT_USER_ID)
-            {
-              byte namehash[20];
-              PKT_user_id *uid = node->pkt->pkt.user_id;
-              
-              if( uid->attrib_data )
-                rmd160_hash_buffer (namehash,uid->attrib_data,uid->attrib_len);
-              else
-                rmd160_hash_buffer (namehash, uid->name, uid->len );
-              update_validity (pk, namehash, 0, TRUST_ULTIMATE);
-            }
+           update_validity (pk, node->pkt->pkt.user_id, 0, TRUST_ULTIMATE);
         }
       if ( pk->expiredate && pk->expiredate >= start_time
            && pk->expiredate < next_expire)
@@ -1819,7 +1889,6 @@ validate_keys (int interactive)
     }
 
   klist = utk_list;
-  kdb = keydb_new (0);
 
   log_info(_("%d marginal(s) needed, %d complete(s) needed, %s trust model\n"),
           opt.marginals_needed,opt.completes_needed,
@@ -1886,7 +1955,8 @@ validate_keys (int interactive)
         }
 
       /* Find all keys which are signed by a key in kdlist */
-      keys = validate_key_list (kdb, visited, klist, start_time, &next_expire);
+      keys = validate_key_list (kdb, full_trust, klist,
+                               start_time, &next_expire);
       if (!keys) 
         {
           log_error ("validate_key_list failed\n");
@@ -1901,14 +1971,14 @@ validate_keys (int interactive)
       if (opt.verbose > 1)
         dump_key_array (depth, keys);
 
-      log_info (_("checking at depth %d signed=%d"
+      for (kar=keys; kar->keyblock; kar++)
+          store_validation_status (depth, kar->keyblock, stored);
+
+      log_info (_("checking at depth %d valid=%d"
                   " ot(-/q/n/m/f/u)=%d/%d/%d/%d/%d/%d\n"), 
                 depth, key_count, ot_unknown, ot_undefined,
                 ot_never, ot_marginal, ot_full, ot_ultimate ); 
 
-      for (kar=keys; kar->keyblock; kar++)
-          store_validation_status (depth, kar->keyblock);
-
       /* Build a new kdlist from all fully valid keys in KEYS */
       if (klist != utk_list)
         release_key_items (klist);
@@ -1919,39 +1989,52 @@ validate_keys (int interactive)
             {
               if (node->pkt->pkttype == PKT_USER_ID && (node->flag & 4))
                 {
-                  k = new_key_item ();
-                  keyid_from_pk (kar->keyblock->pkt->pkt.public_key, k->kid);
-                  k->ownertrust = get_ownertrust (kar->keyblock
-                                                  ->pkt->pkt.public_key);
-                 k->min_ownertrust = get_min_ownertrust (kar->keyblock
-                                                       ->pkt->pkt.public_key);
-                 k->trust_depth=
-                   kar->keyblock->pkt->pkt.public_key->trust_depth;
-                 k->trust_value=
-                   kar->keyblock->pkt->pkt.public_key->trust_value;
-                 if(kar->keyblock->pkt->pkt.public_key->trust_regexp)
-                   k->trust_regexp=
-                     m_strdup(kar->keyblock->pkt->
-                              pkt.public_key->trust_regexp);
-                  k->next = klist;
-                  klist = k;
-                  break;
-                }
-            }
-        }
+                 u32 kid[2];
+
+                 /* have we used this key already? */
+                  keyid_from_pk (kar->keyblock->pkt->pkt.public_key, kid);
+                 if(test_key_hash_table(used,kid)==0)
+                   {
+                     /* Normally we add both the primary and subkey
+                        ids to the hash via mark_keyblock_seen, but
+                        since we aren't using this hash as a skipfnc,
+                        that doesn't matter here. */
+                     add_key_hash_table (used,kid);
+                     k = new_key_item ();
+                     k->kid[0]=kid[0];
+                     k->kid[1]=kid[1];
+                     k->ownertrust =
+                       get_ownertrust (kar->keyblock->pkt->pkt.public_key);
+                     k->min_ownertrust =
+                       get_min_ownertrust(kar->keyblock->pkt->pkt.public_key);
+                     k->trust_depth=
+                       kar->keyblock->pkt->pkt.public_key->trust_depth;
+                     k->trust_value=
+                       kar->keyblock->pkt->pkt.public_key->trust_value;
+                     if(kar->keyblock->pkt->pkt.public_key->trust_regexp)
+                       k->trust_regexp=
+                         m_strdup(kar->keyblock->pkt->
+                                  pkt.public_key->trust_regexp);
+                     k->next = klist;
+                     klist = k;
+                     break;
+                   }
+               }
+           }
+       }
       release_key_array (keys);
       keys = NULL;
       if (!klist)
         break; /* no need to dive in deeper */
     }
 
-  reset_unconnected_keys (kdb, visited);
-
  leave:
   keydb_release (kdb);
   release_key_array (keys);
   release_key_items (klist);
-  release_key_hash_table (visited);
+  release_key_hash_table (full_trust);
+  release_key_hash_table (used);
+  release_key_hash_table (stored);
   if (!rc && !quit) /* mark trustDB as checked */
     {
       if (next_expire == 0xffffffff || next_expire < start_time )