speedo: Improve speedo Makefile.
[gnupg.git] / g10 / getkey.c
index 65f5829..707a106 100644 (file)
@@ -128,7 +128,7 @@ void
 cache_public_key (PKT_public_key * pk)
 {
 #if MAX_PK_CACHE_ENTRIES
-  pk_cache_entry_t ce;
+  pk_cache_entry_t ce, ce2;
   u32 keyid[2];
 
   if (pk_cache_disabled)
@@ -140,6 +140,7 @@ cache_public_key (PKT_public_key * pk)
   if (is_ELGAMAL (pk->pubkey_algo)
       || pk->pubkey_algo == PUBKEY_ALGO_DSA
       || pk->pubkey_algo == PUBKEY_ALGO_ECDSA
+      || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
       || pk->pubkey_algo == PUBKEY_ALGO_ECDH
       || is_RSA (pk->pubkey_algo))
     {
@@ -158,11 +159,25 @@ cache_public_key (PKT_public_key * pk)
 
   if (pk_cache_entries >= MAX_PK_CACHE_ENTRIES)
     {
-      /* fixme: Use another algorithm to free some cache slots.  */
-      pk_cache_disabled = 1;
-      if (opt.verbose > 1)
-       log_info (_("too many entries in pk cache - disabled\n"));
-      return;
+      int n;
+
+      /* Remove the last 50% of the entries.  */
+      for (ce = pk_cache, n = 0; ce && n < pk_cache_entries/2; n++)
+        ce = ce->next;
+      if (ce != pk_cache && ce->next)
+        {
+          ce2 = ce->next;
+          ce->next = NULL;
+          ce = ce2;
+          for (; ce; ce = ce2)
+            {
+              ce2 = ce->next;
+              free_public_key (ce->pk);
+              xfree (ce);
+              pk_cache_entries--;
+            }
+        }
+      assert (pk_cache_entries < MAX_PK_CACHE_ENTRIES);
     }
   pk_cache_entries++;
   ce = xmalloc (sizeof *ce);
@@ -431,7 +446,7 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
 
   hd = keydb_new ();
   rc = keydb_search_kid (hd, keyid);
-  if (rc == -1)
+  if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
     {
       keydb_release (hd);
       return G10ERR_NO_PUBKEY;
@@ -444,8 +459,9 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
       return G10ERR_NO_PUBKEY;
     }
 
-  assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
-         || keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY);
+  assert (keyblock && keyblock->pkt
+          && (keyblock->pkt->pkttype == PKT_PUBLIC_KEY
+              || keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY));
 
   keyid_from_pk (keyblock->pkt->pkt.public_key, pkid);
   if (keyid[0] == pkid[0] && keyid[1] == pkid[1])
@@ -617,7 +633,7 @@ key_byname (GETKEY_CTX *retctx, strlist_t namelist,
        {
          gpg_error_t err;
 
-         err = classify_user_id (r->d, &ctx->items[n]);
+         err = classify_user_id (r->d, &ctx->items[n], 1);
 
          if (ctx->items[n].exact)
            ctx->exact = 1;
@@ -696,7 +712,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
 
   is_mbox = is_valid_mailbox (name);
 
-  /* Check whether we the default local search has been disabled.
+  /* Check whether the default local search has been disabled.
      This is the case if either the "nodefault" or the "local" keyword
      are in the list of auto key locate mechanisms.
 
@@ -872,12 +888,12 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
          if (!rc)
            {
              /* Key found.  */
-             log_info (_("automatically retrieved `%s' via %s\n"),
+             log_info (_("automatically retrieved '%s' via %s\n"),
                        name, mechanism);
              break;
            }
          if (rc != G10ERR_NO_PUBKEY || opt.verbose || no_fingerprint)
-           log_info (_("error retrieving `%s' via %s: %s\n"),
+           log_info (_("error retrieving '%s' via %s: %s\n"),
                      name, mechanism,
                      no_fingerprint ? _("No fingerprint") : g10_errstr (rc));
        }
@@ -992,7 +1008,7 @@ get_pubkey_byfprint_fast (PKT_public_key * pk,
 
   hd = keydb_new ();
   rc = keydb_search_fpr (hd, fprbuf);
-  if (rc == -1)
+  if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
     {
       keydb_release (hd);
       return G10ERR_NO_PUBKEY;
@@ -1139,7 +1155,7 @@ get_seckeyblock_byfprint (kbnode_t *ret_keyblock,
 
 
 \f
-/* The new function to return a key.  
+/* The new function to return a key.
    FIXME: Document it.  */
 gpg_error_t
 getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk,
@@ -1157,11 +1173,11 @@ getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk,
  * NULL the found keyblock is stored at this address.  WANT_SECRET
  * passed as true requires that a secret key is available for the
  * selected key.
- * 
+ *
  * If WANT_SECRET is true and NAME is NULL and a default key has been
  * defined that defined key is used.  In all other cases the first
- * available key is used. 
- * 
+ * available key is used.
+ *
  * FIXME: Explain what is up with unusable keys.
  *
  * FIXME: We also have the get_pubkey_byname function which has a
@@ -1184,7 +1200,7 @@ getkey_byname (getkey_ctx_t *retctx, PKT_public_key *pk,
 
   err = key_byname (retctx, namelist, pk, want_secret, with_unusable,
                     ret_keyblock, NULL);
-  
+
   /* FIXME: Check that we really return GPG_ERR_NO_SECKEY if
      WANT_SECRET has been used.  */
 
@@ -1221,6 +1237,38 @@ getkey_end (getkey_ctx_t ctx)
  ************* Merging stuff ********************
  ************************************************/
 
+/* Set the mainkey_id fields for all keys in KEYBLOCK.  This is
+   usually done by merge_selfsigs but at some places we only need the
+   main_kid but the the full merging.  The function also guarantees
+   that all pk->keyids are computed. */
+void
+setup_main_keyids (kbnode_t keyblock)
+{
+  u32 kid[2], mainkid[2];
+  kbnode_t kbctx, node;
+  PKT_public_key *pk;
+
+  if (keyblock->pkt->pkttype != PKT_PUBLIC_KEY)
+    BUG ();
+  pk = keyblock->pkt->pkt.public_key;
+
+  keyid_from_pk (pk, mainkid);
+  for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
+    {
+      if (!(node->pkt->pkttype == PKT_PUBLIC_KEY
+            || node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
+        continue;
+      pk = node->pkt->pkt.public_key;
+      keyid_from_pk (pk, kid); /* Make sure pk->keyid is set.  */
+      if (!pk->main_keyid[0] && !pk->main_keyid[1])
+        {
+          pk->main_keyid[0] = mainkid[0];
+          pk->main_keyid[1] = mainkid[1];
+        }
+    }
+}
+
+
 /* Merge all self-signatures with the keys.  */
 void
 merge_keys_and_selfsig (KBNODE keyblock)
@@ -1276,13 +1324,19 @@ parse_key_usage (PKT_signature * sig)
 
       if (flags)
        key_usage |= PUBKEY_USAGE_UNKNOWN;
+
+      if (!key_usage)
+       key_usage |= PUBKEY_USAGE_NONE;
     }
+  else if (p) /* Key flags of length zero.  */
+    key_usage |= PUBKEY_USAGE_NONE;
 
   /* We set PUBKEY_USAGE_UNKNOWN to indicate that this key has a
      capability that we do not handle.  This serves to distinguish
      between a zero key usage which we handle as the default
      capabilities for that algorithm, and a usage that we do not
-     handle. */
+     handle.  Likewise we use PUBKEY_USAGE_NONE to indicate that
+     key_flags have been given but they do not specify any usage.  */
 
   return key_usage;
 }
@@ -2450,7 +2504,7 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret)
   int no_suitable_key = 0;
 
   rc = 0;
-  while (!(rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems)))
+  while (!(rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems, NULL)))
     {
       /* If we are searching for the first key we have to make sure
          that the next iteration does not do an implicit reset.
@@ -2486,9 +2540,9 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret)
       release_kbnode (ctx->keyblock);
       ctx->keyblock = NULL;
     }
-  
+
 found:
-  if (rc && rc != -1)
+  if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
     log_error ("keydb_search failed: %s\n", g10_errstr (rc));
 
   if (!rc)
@@ -2496,9 +2550,9 @@ found:
       *ret_keyblock = ctx->keyblock; /* Return the keyblock.  */
       ctx->keyblock = NULL;
     }
-  else if (rc == -1 && no_suitable_key)
+  else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && no_suitable_key)
     rc = want_secret? G10ERR_UNU_SECKEY : G10ERR_UNU_PUBKEY;
-  else if (rc == -1)
+  else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
     rc = want_secret? G10ERR_NO_SECKEY : G10ERR_NO_PUBKEY;
 
   release_kbnode (ctx->keyblock);
@@ -2562,7 +2616,7 @@ enum_secret_keys (void **context, PKT_public_key *sk)
       while (!c->keyblock)
         {
           /* Loop over the list of secret keys.  */
-          do 
+          do
             {
               name = NULL;
               switch (c->state)
@@ -2572,12 +2626,12 @@ enum_secret_keys (void **context, PKT_public_key *sk)
                     name = opt.def_secret_key;
                   c->state = 1;
                   break;
-                  
+
                 case 1: /* Init list of keys to try.  */
                   c->sl = opt.secret_keys_to_try;
                   c->state++;
                   break;
-                  
+
                 case 2: /* Get next item from list.  */
                   if (c->sl)
                     {
@@ -2588,7 +2642,7 @@ enum_secret_keys (void **context, PKT_public_key *sk)
                     c->state++;
                   break;
 
-                default: /* No more names to check - stop.  */  
+                default: /* No more names to check - stop.  */
                   c->eof = 1;
                   return gpg_error (GPG_ERR_EOF);
                 }
@@ -2607,7 +2661,7 @@ enum_secret_keys (void **context, PKT_public_key *sk)
           else
             c->node = c->keyblock;
         }
-      
+
       /* Get the next key from the current keyblock.  */
       for (; c->node; c->node = c->node->next)
        {
@@ -2721,7 +2775,10 @@ get_user_id (u32 * keyid, size_t * rn)
            {
              if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1])
                {
-                 p = xmalloc (r->len);
+                  /* An empty string as user id is possible.  Make
+                     sure that the malloc allocates one byte and does
+                     not bail out.  */
+                 p = xmalloc (r->len? r->len : 1);
                  memcpy (p, r->name, r->len);
                  *rn = r->len;
                  return p;
@@ -2787,7 +2844,14 @@ parse_auto_key_locate (char *options)
 
       akl = xmalloc_clear (sizeof (*akl));
 
-      if (ascii_strcasecmp (tok, "nodefault") == 0)
+      if (ascii_strcasecmp (tok, "clear") == 0)
+       {
+          xfree (akl);
+          free_akl (opt.auto_key_locate);
+          opt.auto_key_locate = NULL;
+          continue;
+        }
+      else if (ascii_strcasecmp (tok, "nodefault") == 0)
        akl->type = AKL_NODEFAULT;
       else if (ascii_strcasecmp (tok, "local") == 0)
        akl->type = AKL_LOCAL;
@@ -2875,7 +2939,7 @@ have_secret_key_with_kid (u32 *keyid)
   desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
   desc.u.kid[0] = keyid[0];
   desc.u.kid[1] = keyid[1];
-  while (!result && !(err = keydb_search (kdbhd, &desc, 1)))
+  while (!result && !(err = keydb_search (kdbhd, &desc, 1, NULL)))
     {
       desc.mode = KEYDB_SEARCH_MODE_NEXT;
       err = keydb_get_keyblock (kdbhd, &keyblock);