aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2019-10-16 06:58:26 +0000
committerNIIBE Yutaka <[email protected]>2019-10-16 06:58:26 +0000
commitf2734381ae1431e395a0bed16df2f4d5d13aa2c5 (patch)
treee21bfffab769465605c35c944a4c38b82c0247d0
parentgpg: Also delete key-binding signature when deleting a subkey. (diff)
downloadgnupg-f2734381ae1431e395a0bed16df2f4d5d13aa2c5.tar.gz
gnupg-f2734381ae1431e395a0bed16df2f4d5d13aa2c5.zip
gpg: Fix get_best_pubkey_byname to consider the first match.
* 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 <[email protected]>
-rw-r--r--g10/getkey.c58
1 files changed, 39 insertions, 19 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index 9b3dd0827..2aad96ef6 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -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)