Stricter test of allowed signature packet compositions.
[gnupg.git] / g10 / trustdb.c
index 1222f49..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);
     }
 }
 
@@ -408,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;
 }
 
@@ -449,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)
@@ -495,13 +501,14 @@ trust_letter (unsigned int value)
    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. */
+   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)
+  else if(uid->is_revoked || (key && key->is_revoked))
     return                         _("[ revoked]");
   else if(uid->is_expired)
     return                         _("[ expired]");
@@ -623,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)
@@ -816,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)
     {
@@ -1050,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;
        }
@@ -1254,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)
     {
@@ -1394,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,
@@ -1408,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)
@@ -1443,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)) )
@@ -1455,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)
@@ -1517,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. 
@@ -1535,11 +1570,190 @@ 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
@@ -1748,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;
     }
 
@@ -1772,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;
     }
   
@@ -1785,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;
         }
       
@@ -1817,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;
 
@@ -1841,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;
     }
 
@@ -1947,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;
     }
 
@@ -2110,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;