gpg: Fix get_best_pubkey_byname to consider the first match.
authorNIIBE Yutaka <gniibe@fsij.org>
Wed, 16 Oct 2019 06:58:26 +0000 (15:58 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Wed, 16 Oct 2019 06:58:26 +0000 (15:58 +0900)
* g10/getkey.c (get_best_pubkey_byname): Always use PK0 to search
by get_pubkey_byname.  Add initial call to pubkey_cmp to fill
BEST at first before the loop.

--

Fixes-commit: 44604209c1cfe18532d13eda63d8c1f86a6e12ec
GnuPG-bug-id: 4713
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
g10/getkey.c

index 9b3dd08..2aad96e 100644 (file)
@@ -1353,13 +1353,16 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
   struct getkey_ctx_s *ctx = NULL;
   int is_mbox = is_valid_mailbox (name);
   int wkd_tried = 0;
-  PKT_public_key *pk2;
+  PKT_public_key pk0;
 
   log_assert (ret_keyblock != NULL);
 
   if (retctx)
     *retctx = NULL;
 
+  memset (&pk0, 0, sizeof pk0);
+  pk0.req_usage = pk? pk->req_usage : 0;
+
  start_over:
   if (ctx)  /* Clear  in case of a start over.  */
     {
@@ -1369,7 +1372,7 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
       ctx = NULL;
     }
   err = get_pubkey_byname (ctrl, mode,
-                           &ctx, pk, name, ret_keyblock,
+                           &ctx, &pk0, name, ret_keyblock,
                            NULL, include_unusable);
   if (err)
     {
@@ -1377,8 +1380,6 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
       return err;
     }
 
-  pk2 = (*ret_keyblock)->pkt->pkt.public_key;
-
   /* If the keyblock was retrieved from the local database and the key
    * has expired, do further checks.  However, we can do this only if
    * the caller requested a keyblock.  */
@@ -1394,9 +1395,9 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
        * Unfortunately that does not yet work because KEYUPDATE is
        * only updated during import iff the key has actually changed
        * (see import.c:import_one).  */
-      if (!wkd_tried && pk2->keyorg == KEYORG_WKD
-          && (pk2->keyupdate + 3*3600) < now
-          && (pk2->has_expired || only_expired_enc_subkeys (*ret_keyblock)))
+      if (!wkd_tried && pk0.keyorg == KEYORG_WKD
+          && (pk0.keyupdate + 3*3600) < now
+          && (pk0.has_expired || only_expired_enc_subkeys (*ret_keyblock)))
         {
           if (opt.verbose)
             log_info (_("checking for a fresh copy of an expired key via %s\n"),
@@ -1406,7 +1407,10 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
           found = !keyserver_import_wkd (ctrl, name, 0, NULL, NULL);
           glo_ctrl.in_auto_key_retrieve--;
           if (found)
-            goto start_over;
+            {
+              release_public_key_parts (&pk0);
+              goto start_over;
+            }
         }
     }
 
@@ -1416,13 +1420,16 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
       struct pubkey_cmp_cookie best = { 0 };
       struct pubkey_cmp_cookie new = { 0 };
       kbnode_t new_keyblock;
-      u32 *keyid = pk_keyid (pk2);
 
-      ctx->exact = 1;
-      ctx->nitems = 1;
-      ctx->items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
-      ctx->items[0].u.kid[0] = keyid[0];
-      ctx->items[0].u.kid[1] = keyid[1];
+      copy_public_key (&new.key, &pk0);
+      if (pubkey_cmp (ctrl, name, &best, &new, *ret_keyblock) >= 0)
+        {
+          release_public_key_parts (&new.key);
+          free_user_id (new.uid);
+        }
+      else
+        best = new;
+      new.uid = NULL;
 
       while (getkey_next (ctrl, ctx, &new.key, &new_keyblock) == 0)
         {
@@ -1475,9 +1482,10 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
                     }
                   else
                     {
-                      keyid = pk_keyid (&best.key);
+                      u32 *keyid = pk_keyid (&best.key);
                       ctx->exact = 1;
                       ctx->nitems = 1;
+                      ctx->req_usage = pk0.req_usage;
                       ctx->items[0].mode = KEYDB_SEARCH_MODE_LONG_KID;
                       ctx->items[0].u.kid[0] = keyid[0];
                       ctx->items[0].u.kid[1] = keyid[1];
@@ -1490,13 +1498,25 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
             }
 
           if (pk)
-            {
-              release_public_key_parts (pk);
-              *pk = best.key;
-            }
+            *pk = best.key;
           else
             release_public_key_parts (&best.key);
+          release_public_key_parts (&pk0);
         }
+      else
+        {
+          if (pk)
+            *pk = pk0;
+          else
+            release_public_key_parts (&pk0);
+        }
+    }
+  else
+    {
+      if (pk)
+        *pk = pk0;
+      else
+        release_public_key_parts (&pk0);
     }
 
   if (err && ctx)