g10: Default to the "good" TOFU policy for keys signed by a UTK.
authorNeal H. Walfield <neal@g10code.com>
Wed, 14 Sep 2016 13:17:27 +0000 (15:17 +0200)
committerNeal H. Walfield <neal@g10code.com>
Wed, 14 Sep 2016 13:22:08 +0000 (15:22 +0200)
* g10/tofu.c (signed_by_utk): New function.
(get_trust): If a key is signed by an ultimately trusted key, then
set any bindings to good.

--
Signed-off-by: Neal H. Walfield <neal@g10code.com>
g10/tofu.c

index 7cf3fc7..da11d40 100644 (file)
@@ -1285,6 +1285,48 @@ cross_sigs (kbnode_t a, kbnode_t b)
   return 1;
 }
 
+/* Return whether the key was signed by an ultimately trusted key.  */
+static int
+signed_by_utk (kbnode_t a)
+{
+  kbnode_t n;
+
+  for (n = a; n; n = n->next)
+    {
+      PKT_signature *sig;
+
+      if (n->pkt->pkttype != PKT_SIGNATURE)
+        continue;
+
+      sig = n->pkt->pkt.signature;
+
+      if (! (sig->sig_class == 0x10
+             || sig->sig_class == 0x11
+             || sig->sig_class == 0x12
+             || sig->sig_class == 0x13))
+        /* Not a signature over a user id.  */
+        continue;
+
+      /* SIG is on SIGNEE's keyblock.  If SIG was generated by the
+         signer, then it's a match.  */
+      if (tdb_keyid_is_utk (sig->keyid))
+        {
+          /* Match!  */
+          if (DBG_TRUST)
+            log_debug ("TOFU: %s is signed by an ultimately trusted key.\n",
+                       pk_keyid_str (a->pkt->pkt.public_key));
+
+          return 1;
+        }
+    }
+
+  if (DBG_TRUST)
+    log_debug ("TOFU: %s is NOT signed by an ultimately trusted key.\n",
+               pk_keyid_str (a->pkt->pkt.public_key));
+
+  return 0;
+}
+
 
 enum
   {
@@ -2121,6 +2163,61 @@ get_trust (ctrl_t ctrl, PKT_public_key *pk,
    * In summary: POLICY is ask or none.
    */
 
+  /* Before continuing, see if the key is signed by an ultimately
+     trusted key.  */
+  {
+    int fingerprint_raw_len = strlen (fingerprint) / 2;
+    char fingerprint_raw[fingerprint_raw_len];
+    int len = 0;
+    int is_signed_by_utk = 0;
+
+    if (fingerprint_raw_len != 20
+        || ((len = hex2bin (fingerprint,
+                            fingerprint_raw, fingerprint_raw_len))
+            != strlen (fingerprint)))
+      {
+        if (DBG_TRUST)
+          log_debug ("TOFU: Bad fingerprint: %s (len: %zd, parsed: %d)\n",
+                     fingerprint, strlen (fingerprint), len);
+      }
+    else
+      {
+        int lookup_err;
+        kbnode_t kb;
+
+        lookup_err = get_pubkey_byfprint (NULL, &kb,
+                                          fingerprint_raw,
+                                          fingerprint_raw_len);
+        if (lookup_err)
+          {
+            if (DBG_TRUST)
+              log_debug ("TOFU: Looking up %s: %s\n",
+                         fingerprint, gpg_strerror (lookup_err));
+          }
+        else
+          {
+            is_signed_by_utk = signed_by_utk (kb);
+            release_kbnode (kb);
+          }
+      }
+
+    if (is_signed_by_utk)
+      {
+        if (record_binding (dbs, fingerprint, email, user_id,
+                            TOFU_POLICY_GOOD, 0, now) != 0)
+          {
+            log_error (_("error setting TOFU binding's trust level"
+                         " to %s\n"), "good");
+            trust_level = _tofu_GET_TRUST_ERROR;
+          }
+        else
+          trust_level = TRUST_FULLY;
+
+        goto out;
+      }
+  }
+
+
   /* Look for conflicts.  This is needed in all 3 cases.  */
   conflict_set = build_conflict_set (dbs, fingerprint, email);
   conflict_set_count = strlist_length (conflict_set);