Fixed a couple of problems
[gnupg.git] / g10 / trustdb.c
index 9cf2eff..cff55ec 100644 (file)
@@ -1,6 +1,6 @@
 /* trustdb.c
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
- *               2004 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ *               2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -16,7 +16,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
@@ -27,7 +28,7 @@
 
 #ifndef DISABLE_REGEX
 #include <sys/types.h>
-#ifdef USE_GNU_REGEX
+#ifdef USE_INTERNAL_REGEX
 #include "_regex.h"
 #else
 #include <regex.h>
@@ -98,7 +99,7 @@ new_key_item (void)
 {
   struct key_item *k;
   
-  k = m_alloc_clear (sizeof *k);
+  k = xmalloc_clear (sizeof *k);
   return k;
 }
 
@@ -110,8 +111,8 @@ release_key_items (struct key_item *k)
   for (; k; k = k2)
     {
       k2 = k->next;
-      m_free (k->trust_regexp);
-      m_free (k);
+      xfree (k->trust_regexp);
+      xfree (k);
     }
 }
 
@@ -128,7 +129,7 @@ new_key_hash_table (void)
 {
   struct key_item **tbl;
 
-  tbl = m_alloc_clear (1024 * sizeof *tbl);
+  tbl = xmalloc_clear (1024 * sizeof *tbl);
   return tbl;
 }
 
@@ -141,7 +142,7 @@ release_key_hash_table (KeyHashTable tbl)
     return;
   for (i=0; i < 1024; i++)
     release_key_items (tbl[i]);
-  m_free (tbl);
+  xfree (tbl);
 }
 
 /* 
@@ -188,7 +189,7 @@ release_key_array ( struct key_array *keys )
     if (keys) {
         for (k=keys; k->keyblock; k++)
             release_kbnode (k->keyblock);
-        m_free (keys);
+        xfree (keys);
     }
 }
 
@@ -391,6 +392,7 @@ trust_model_string(void)
     case TM_PGP:      return "PGP";
     case TM_EXTERNAL: return "external";
     case TM_ALWAYS:   return "always";
+    case TM_DIRECT:   return "direct";
     default:          return "unknown";
     }
 }
@@ -407,7 +409,7 @@ setup_trustdb( int level, const char *dbname )
     if( trustdb_args.init )
        return 0;
     trustdb_args.level = level;
-    trustdb_args.dbname = dbname? m_strdup(dbname): NULL;
+    trustdb_args.dbname = dbname? xstrdup(dbname): NULL;
     return 0;
 }
 
@@ -448,7 +450,12 @@ init_trustdb()
        }
 
       if(opt.verbose)
-       log_info(_("using %s trust model\n"),trust_model_string());
+        {
+          log_info(_("using %s trust model\n"),trust_model_string());
+          if (opt.pka_trust_increase)
+            log_info(_("PKA verification is allowed to"
+                       " leverage trust to full\n"));
+        }
     }
 
   if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC)
@@ -488,6 +495,37 @@ trust_letter (unsigned int value)
     }
 }
 
+/* NOTE TO TRANSLATOR: these strings are similar to those in
+   trust_value_to_string(), but are a fixed length.  This is needed to
+   make attractive information listings where columns line up
+   properly.  The value "10" should be the length of the strings you
+   choose to translate to.  This is the length in printable columns.
+   It gets passed to atoi() so everything after the number is
+   essentially a comment and need not be translated.  Either key and
+   uid are both NULL, or neither are NULL. */
+const char *
+uid_trust_string_fixed(PKT_public_key *key,PKT_user_id *uid)
+{
+  if(!key && !uid)
+    return _("10 translator see trustdb.c:uid_trust_string_fixed");
+  else if(uid->is_revoked || (key && key->is_revoked))
+    return                         _("[ revoked]");
+  else if(uid->is_expired)
+    return                         _("[ expired]");
+  else if(key)
+    switch(get_validity(key,uid)&TRUST_MASK)
+      {
+      case TRUST_UNKNOWN:   return _("[ unknown]");
+      case TRUST_EXPIRED:   return _("[ expired]");
+      case TRUST_UNDEFINED: return _("[  undef ]");
+      case TRUST_MARGINAL:  return _("[marginal]");
+      case TRUST_FULLY:     return _("[  full  ]");
+      case TRUST_ULTIMATE:  return _("[ultimate]");
+      }
+
+  return "err";
+}
+
 /* The strings here are similar to those in
    pkclist.c:do_edit_ownertrust() */
 const char *
@@ -556,7 +594,7 @@ check_trustdb ()
       validate_keys (0);
     }
   else
-    log_info (_("no need for a trustdb check with \"%s\" trust model\n"),
+    log_info (_("no need for a trustdb check with `%s' trust model\n"),
              trust_model_string());
 }
 
@@ -571,7 +609,7 @@ update_trustdb()
   if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC)
     validate_keys (1);
   else
-    log_info (_("no need for a trustdb update with \"%s\" trust model\n"),
+    log_info (_("no need for a trustdb update with `%s' trust model\n"),
              trust_model_string());
 }
 
@@ -592,6 +630,20 @@ trustdb_pending_check(void)
   return pending_check_trustdb;
 }
 
+/* If the trustdb is dirty, and we're interactive, update it.
+   Otherwise, check it unless no-auto-check-trustdb is set. */
+void
+trustdb_check_or_update(void)
+{
+  if(trustdb_pending_check())
+    {
+      if(opt.interactive)
+       update_trustdb();
+      else if(!opt.no_auto_check_trustdb)
+       check_trustdb();
+    }
+}
+
 void
 read_trust_options(byte *trust_model,ulong *created,ulong *nextcheck,
                   byte *marginals,byte *completes,byte *cert_depth)
@@ -785,7 +837,7 @@ update_min_ownertrust (u32 *kid, unsigned int new_trust )
   TRUSTREC rec;
   int rc;
 
-  pk = m_alloc_clear (sizeof *pk);
+  pk = xmalloc_clear (sizeof *pk);
   rc = get_pubkey (pk, kid);
   if (rc)
     {
@@ -1019,14 +1071,14 @@ get_validity (PKT_public_key *pk, PKT_user_id *uid)
   keyid_from_pk (pk, kid);
   if (pk->main_keyid[0] != kid[0] || pk->main_keyid[1] != kid[1])
     { /* this is a subkey - get the mainkey */
-      main_pk = m_alloc_clear (sizeof *main_pk);
+      main_pk = xmalloc_clear (sizeof *main_pk);
       rc = get_pubkey (main_pk, pk->main_keyid);
       if (rc)
         {
-         char *tempkeystr=m_strdup(keystr(pk->main_keyid));
+         char *tempkeystr=xstrdup(keystr(pk->main_keyid));
           log_error ("error getting main key %s of subkey %s: %s\n",
                      tempkeystr, keystr(kid), g10_errstr(rc));
-         m_free(tempkeystr);
+         xfree(tempkeystr);
           validity = TRUST_UNKNOWN; 
           goto leave;
        }
@@ -1034,6 +1086,14 @@ get_validity (PKT_public_key *pk, PKT_user_id *uid)
   else
     main_pk = pk;
 
+  if(opt.trust_model==TM_DIRECT)
+    {
+      /* Note that this happens BEFORE any user ID stuff is checked.
+        The direct trust model applies to keys as a whole. */
+      validity=get_ownertrust(main_pk);
+      goto leave;
+    }
+
   rc = read_trust_record (main_pk, &trec);
   if (rc && rc != -1)
     {
@@ -1215,7 +1275,7 @@ ask_ownertrust (u32 *kid,int minimum)
   int rc;
   int ot;
 
-  pk = m_alloc_clear (sizeof *pk);
+  pk = xmalloc_clear (sizeof *pk);
   rc = get_pubkey (pk, kid);
   if (rc)
     {
@@ -1355,8 +1415,9 @@ is_in_klist (struct key_item *k, PKT_signature *sig)
  * To do this, we first revmove all signatures which are not valid and
  * from the remain ones we look for the latest one.  If this is not a
  * certification revocation signature we mark the signature by setting
- * node flag bit 8.  Note that flag bits 9 and 10 are used for internal
- * purposes.  
+ * node flag bit 8.  Revocations are marked with flag 11, and sigs
+ * from unavailable keys are marked with flag 12.  Note that flag bits
+ * 9 and 10 are used for internal purposes.
  */
 static void
 mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
@@ -1369,34 +1430,44 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
   /* first check all signatures */
   for (node=uidnode->next; node; node = node->next)
     {
-      node->flag &= ~(1<<8 | 1<<9 | 1<<10);
+      int rc;
+
+      node->flag &= ~(1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12);
       if (node->pkt->pkttype == PKT_USER_ID
           || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
         break; /* ready */
       if (node->pkt->pkttype != PKT_SIGNATURE)
         continue;
-      
       sig = node->pkt->pkt.signature;
-      if (sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1])
-        continue; /* ignore self-signatures */
+      if (main_kid
+         && sig->keyid[0] == main_kid[0] && sig->keyid[1] == main_kid[1])
+        continue; /* ignore self-signatures if we pass in a main_kid */
       if (!IS_UID_SIG(sig) && !IS_UID_REV(sig))
         continue; /* we only look at these signature classes */
       if(sig->sig_class>=0x11 && sig->sig_class<=0x13 &&
         sig->sig_class-0x10<opt.min_cert_level)
-       continue;
-      if (!is_in_klist (klist, sig))
+       continue; /* treat anything under our min_cert_level as an
+                    invalid signature */
+      if (klist && !is_in_klist (klist, sig))
         continue;  /* no need to check it then */
-      if (check_key_signature (keyblock, node, NULL))
-        continue; /* ignore invalid signatures */
+      if ((rc=check_key_signature (keyblock, node, NULL)))
+       {
+         /* we ignore anything that won't verify, but tag the
+            no_pubkey case */
+         if(rc==G10ERR_NO_PUBKEY)
+           node->flag |= 1<<12;
+         continue;
+       }
       node->flag |= 1<<9;
     }      
   /* reset the remaining flags */
   for (; node; node = node->next)
-      node->flag &= ~(1<<8 | 1<<9 | 1 << 10);
+      node->flag &= ~(1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12);
 
   /* kbnode flag usage: bit 9 is here set for signatures to consider,
    * bit 10 will be set by the loop to keep track of keyIDs already
-   * processed, bit 8 will be set for the usable signatures */
+   * processed, bit 8 will be set for the usable signatures, and bit
+   * 11 will be set for usable revocations. */
 
   /* for each cert figure out the latest valid one */
   for (node=uidnode->next; node; node = node->next)
@@ -1404,7 +1475,7 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
       KBNODE n, signode;
       u32 kid[2];
       u32 sigdate;
-      
+
       if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
         break;
       if ( !(node->flag & (1<<9)) )
@@ -1416,6 +1487,8 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
       signode = node;
       sigdate = sig->timestamp;
       kid[0] = sig->keyid[0]; kid[1] = sig->keyid[1];
+
+      /* Now find the latest and greatest signature */
       for (n=uidnode->next; n; n = n->next)
         {
           if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY)
@@ -1478,6 +1551,7 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
               sigdate = sig->timestamp;
             }
         }
+
       sig = signode->pkt->pkt.signature;
       if (IS_UID_SIG (sig))
         { /* this seems to be a usable one which is not revoked. 
@@ -1496,13 +1570,192 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
           if (expire==0 || expire > curtime )
             {
               signode->flag |= (1<<8); /* yeah, found a good cert */
-              if (expire && expire < *next_expire)
+              if (next_expire && expire && expire < *next_expire)
                 *next_expire = expire;
             }
         }
+      else
+       signode->flag |= (1<<11);
     }
 }
 
+static int
+clean_sigs_from_uid(KBNODE keyblock,KBNODE uidnode,int noisy,int self_only)
+{
+  int deleted=0;
+  KBNODE node;
+  u32 keyid[2];
+
+  assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
+
+  keyid_from_pk(keyblock->pkt->pkt.public_key,keyid);
+
+  /* Passing in a 0 for current time here means that we'll never weed
+     out an expired sig.  This is correct behavior since we want to
+     keep the most recent expired sig in a series. */
+  mark_usable_uid_certs(keyblock,uidnode,NULL,NULL,0,NULL);
+
+  /* What we want to do here is remove signatures that are not
+     considered as part of the trust calculations.  Thus, all invalid
+     signatures are out, as are any signatures that aren't the last of
+     a series of uid sigs or revocations It breaks down like this:
+     coming out of mark_usable_uid_certs, if a sig is unflagged, it is
+     not even a candidate.  If a sig has flag 9 or 10, that means it
+     was selected as a candidate and vetted.  If a sig has flag 8 it
+     is a usable signature.  If a sig has flag 11 it is a usable
+     revocation.  If a sig has flag 12 it was issued by an unavailable
+     key.  "Usable" here means the most recent valid
+     signature/revocation in a series from a particular signer.
+
+     Delete everything that isn't a usable uid sig (which might be
+     expired), a usable revocation, or a sig from an unavailable
+     key. */
+
+  for(node=uidnode->next;
+      node && node->pkt->pkttype==PKT_SIGNATURE;
+      node=node->next)
+    {
+      int keep=self_only?(node->pkt->pkt.signature->keyid[0]==keyid[0]
+                         && node->pkt->pkt.signature->keyid[1]==keyid[1]):1;
+
+      /* Keep usable uid sigs ... */
+      if((node->flag & (1<<8)) && keep)
+       continue;
+
+      /* ... and usable revocations... */
+      if((node->flag & (1<<11)) && keep)
+       continue;
+
+      /* ... and sigs from unavailable keys. */
+      /* disabled for now since more people seem to want sigs from
+        unavailable keys removed altogether.  */
+      /*
+       if(node->flag & (1<<12))
+       continue;
+      */
+
+      /* Everything else we delete */
+
+      /* At this point, if 12 is set, the signing key was unavailable.
+        If 9 or 10 is set, it's superceded.  Otherwise, it's
+        invalid. */
+
+      if(noisy)
+       log_info("removing signature from key %s on user ID \"%s\": %s\n",
+                keystr(node->pkt->pkt.signature->keyid),
+                uidnode->pkt->pkt.user_id->name,
+                node->flag&(1<<12)?"key unavailable":
+                node->flag&(1<<9)?"signature superceded":"invalid signature");
+
+      delete_kbnode(node);
+      deleted++;
+    }
+    
+  return deleted;
+}
+
+/* This is substantially easier than clean_sigs_from_uid since we just
+   have to establish if the uid has a valid self-sig, is not revoked,
+   and is not expired.  Note that this does not take into account
+   whether the uid has a trust path to it - just whether the keyholder
+   themselves has certified the uid.  Returns true if the uid was
+   compacted.  To "compact" a user ID, we simply remove ALL signatures
+   except the self-sig that caused the user ID to be remove-worthy.
+   We don't actually remove the user ID packet itself since it might
+   be ressurected in a later merge.  Note that this function requires
+   that the caller has already done a merge_keys_and_selfsig().
+
+   TODO: change the import code to allow importing a uid with only a
+   revocation if the uid already exists on the keyring. */
+
+static int
+clean_uid_from_key(KBNODE keyblock,KBNODE uidnode,int noisy)
+{
+  KBNODE node;
+  PKT_user_id *uid=uidnode->pkt->pkt.user_id;
+  int deleted=0;
+
+  assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
+  assert(uidnode->pkt->pkttype==PKT_USER_ID);
+
+  /* Skip valid user IDs, compacted user IDs, and non-self-signed user
+     IDs if --allow-non-selfsigned-uid is set. */
+  if(uid->created || uid->flags.compacted
+     || (!uid->is_expired && !uid->is_revoked
+        && opt.allow_non_selfsigned_uid))
+    return 0;
+
+  for(node=uidnode->next;
+      node && node->pkt->pkttype==PKT_SIGNATURE;
+      node=node->next)
+    if(!node->pkt->pkt.signature->flags.chosen_selfsig)
+      {
+       delete_kbnode(node);
+       deleted=1;
+       uidnode->pkt->pkt.user_id->flags.compacted=1;
+      }
+
+  if(noisy)
+    {
+      const char *reason;
+      char *user=utf8_to_native(uid->name,uid->len,0);
+
+      if(uid->is_revoked)
+       reason=_("revoked");
+      else if(uid->is_expired)
+       reason=_("expired");
+      else
+       reason=_("invalid");
+
+      log_info("compacting user ID \"%s\" on key %s: %s\n",
+              user,keystr_from_pk(keyblock->pkt->pkt.public_key),
+              reason);
+
+      xfree(user);
+    }
+
+  return deleted;
+}
+
+/* Needs to be called after a merge_keys_and_selfsig() */
+void
+clean_one_uid(KBNODE keyblock,KBNODE uidnode,int noisy,int self_only,
+             int *uids_cleaned,int *sigs_cleaned)
+{
+  int dummy;
+
+  assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
+  assert(uidnode->pkt->pkttype==PKT_USER_ID);
+
+  if(!uids_cleaned)
+    uids_cleaned=&dummy;
+
+  if(!sigs_cleaned)
+    sigs_cleaned=&dummy;
+
+  /* Do clean_uid_from_key first since if it fires off, we don't
+     have to bother with the other */
+  *uids_cleaned+=clean_uid_from_key(keyblock,uidnode,noisy);
+  if(!uidnode->pkt->pkt.user_id->flags.compacted)
+    *sigs_cleaned+=clean_sigs_from_uid(keyblock,uidnode,noisy,self_only);
+}
+
+void
+clean_key(KBNODE keyblock,int noisy,int self_only,
+         int *uids_cleaned,int *sigs_cleaned)
+{
+  KBNODE uidnode;
+
+  merge_keys_and_selfsig(keyblock);
+
+  for(uidnode=keyblock->next;
+      uidnode && uidnode->pkt->pkttype!=PKT_PUBLIC_SUBKEY;
+      uidnode=uidnode->next)
+    if(uidnode->pkt->pkttype==PKT_USER_ID)
+      clean_one_uid(keyblock,uidnode,noisy,self_only,
+                   uids_cleaned,sigs_cleaned);
+}
+
 /* Used by validate_one_keyblock to confirm a regexp within a trust
    signature.  Returns 1 for match, and 0 for no match or regex
    error. */
@@ -1527,7 +1780,7 @@ check_regexp(const char *expr,const char *string)
   regfree(&pat);
 
   if(DBG_TRUST)
-    log_debug("regexp \"%s\" on \"%s\": %s\n",expr,string,ret==0?"YES":"NO");
+    log_debug("regexp `%s' on `%s': %s\n",expr,string,ret==0?"YES":"NO");
 
   return (ret==0);
 #endif
@@ -1709,14 +1962,14 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust,
   KEYDB_SEARCH_DESC desc;
   
   maxkeys = 1000;
-  keys = m_alloc ((maxkeys+1) * sizeof *keys);
+  keys = xmalloc ((maxkeys+1) * sizeof *keys);
   nkeys = 0;
   
   rc = keydb_search_reset (hd);
   if (rc)
     {
       log_error ("keydb_search_reset failed: %s\n", g10_errstr(rc));
-      m_free (keys);
+      xfree (keys);
       return NULL;
     }
 
@@ -1733,7 +1986,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust,
   if (rc)
     {
       log_error ("keydb_search_first failed: %s\n", g10_errstr(rc));
-      m_free (keys);
+      xfree (keys);
       return NULL;
     }
   
@@ -1746,7 +1999,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust,
       if (rc) 
         {
           log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
-          m_free (keys);
+          xfree (keys);
           return NULL;
         }
       
@@ -1778,7 +2031,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust,
 
           if (nkeys == maxkeys) {
             maxkeys += 1000;
-            keys = m_realloc (keys, (maxkeys+1) * sizeof *keys);
+            keys = xrealloc (keys, (maxkeys+1) * sizeof *keys);
           }
           keys[nkeys++].keyblock = keyblock;
 
@@ -1802,7 +2055,7 @@ validate_key_list (KEYDB_HANDLE hd, KeyHashTable full_trust,
   if (rc && rc != -1) 
     {
       log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
-      m_free (keys);
+      xfree (keys);
       return NULL;
     }
 
@@ -1908,7 +2161,8 @@ validate_keys (int interactive)
    * here when needed */
   if (!utk_list)
     {
-      log_info (_("no ultimately trusted keys found\n"));
+      if (!opt.quiet)
+        log_info (_("no ultimately trusted keys found\n"));
       goto leave;
     }
 
@@ -1987,7 +2241,7 @@ validate_keys (int interactive)
            {
              if(DBG_TRUST)
                log_debug("key %08lX%08lX:"
-                         " overriding ownertrust \"%s\" with \"%s\"\n",
+                         " overriding ownertrust `%s' with `%s'\n",
                          (ulong)k->kid[0],(ulong)k->kid[1],
                          trust_value_to_string(k->ownertrust),
                          trust_value_to_string(min));
@@ -2071,7 +2325,7 @@ validate_keys (int interactive)
                        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->
+                         xstrdup(kar->keyblock->pkt->
                                   pkt.public_key->trust_regexp);
                      k->next = klist;
                      klist = k;