From deeaac89f55ef6a4dc1e859b0fb0f4e4ed6e86cd Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 11 Feb 2025 14:44:23 +0100 Subject: [PATCH 1/4] gpg: Lookup key for merging/inserting only by primary key. * g10/getkey.c (get_keyblock_byfpr_fast): Add arg primary_only and implement. * g10/import.c (import_one_real): Simplify filling the fpr buffer with zeroes. (import_one_real): Find key only by primary fingerprint. -- This should have been done early: When looking up the original keyblock we want to update, we need to lookup it up only using the primary key. This avoids to find a key which has the primary key also has a subkey. GnuPG-bug-id: 7527 (ported by dkg from commit 25d748c3dfc0102f9e54afea59ff26b3969bd8c1 from STABLE-BRANCH-2-4) Reference link: https://salsa.debian.org/debian/gnupg2/-/blob/debian/2.2.46-6/debian/patches/from-2.4/gpg-Lookup-key-for-merging-inserting-only-by-primary-key.patch Signed-off-by: baogen shang --- g10/getkey.c | 23 ++++++++++++++++++++--- g10/import.c | 6 +++--- g10/keydb.h | 1 + 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/g10/getkey.c b/g10/getkey.c index 4642174..4747176 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1970,7 +1970,7 @@ get_pubkey_byfprint_fast (PKT_public_key * pk, gpg_error_t err; KBNODE keyblock; - err = get_keyblock_byfprint_fast (&keyblock, NULL, fprint, fprint_len, 0); + err = get_keyblock_byfprint_fast (&keyblock, NULL, 0, fprint, fprint_len, 0); if (!err) { if (pk) @@ -1987,10 +1987,13 @@ get_pubkey_byfprint_fast (PKT_public_key * pk, * R_HD may be NULL. If LOCK is set the handle has been opend in * locked mode and keydb_disable_caching () has been called. On error * R_KEYBLOCK is set to NULL but R_HD must be released by the caller; - * it may have a value of NULL, though. This allows to do an insert - * operation on a locked keydb handle. */ + * it may have a value of NULL, though. This allows one to do an insert + * operation on a locked keydb handle. If PRIMARY_ONLY is set + * the function returns a keyblock which has the requested fingerprint + * has primary key.*/ gpg_error_t get_keyblock_byfprint_fast (kbnode_t *r_keyblock, KEYDB_HANDLE *r_hd, + int primary_only, const byte *fprint, size_t fprint_len, int lock) { gpg_error_t err; @@ -1998,6 +2001,8 @@ get_keyblock_byfprint_fast (kbnode_t *r_keyblock, KEYDB_HANDLE *r_hd, kbnode_t keyblock; byte fprbuf[MAX_FINGERPRINT_LEN]; int i; + byte tmpfpr[MAX_FINGERPRINT_LEN]; + size_t tmpfprlen; if (r_keyblock) *r_keyblock = NULL; @@ -2031,6 +2036,7 @@ get_keyblock_byfprint_fast (kbnode_t *r_keyblock, KEYDB_HANDLE *r_hd, if (r_hd) *r_hd = hd; + again: err = keydb_search_fpr (hd, fprbuf); if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) { @@ -2050,6 +2056,17 @@ get_keyblock_byfprint_fast (kbnode_t *r_keyblock, KEYDB_HANDLE *r_hd, log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY || keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY); + if (primary_only) + { + fingerprint_from_pk (keyblock->pkt->pkt.public_key, tmpfpr, &tmpfprlen); + if (fprint_len != tmpfprlen || memcmp (fprint, tmpfpr, fprint_len)) + { + release_kbnode (keyblock); + keyblock = NULL; + goto again; + } + } + /* Not caching key here since it won't have all of the fields properly set. */ diff --git a/g10/import.c b/g10/import.c index 0ce702e..b2a1462 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1859,7 +1859,6 @@ import_one_real (ctrl_t ctrl, int mod_key = 0; int same_key = 0; int non_self = 0; - size_t an; char pkstrbuf[PUBKEY_STRING_SIZE]; int merge_keys_done = 0; KEYDB_HANDLE hd = NULL; @@ -1879,8 +1878,8 @@ import_one_real (ctrl_t ctrl, pk = node->pkt->pkt.public_key; fingerprint_from_pk (pk, fpr2, &fpr2len); - for (an = fpr2len; an < MAX_FINGERPRINT_LEN; an++) - fpr2[an] = 0; + if (MAX_FINGERPRINT_LEN > fpr2len) + memset (fpr2+fpr2len, 0, MAX_FINGERPRINT_LEN - fpr2len); keyid_from_pk( pk, keyid ); uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); @@ -2028,6 +2027,7 @@ import_one_real (ctrl_t ctrl, /* Do we have this key already in one of our pubrings ? */ err = get_keyblock_byfprint_fast (&keyblock_orig, &hd, + 1 /*primary only */, fpr2, fpr2len, 1/*locked*/); if ((err && gpg_err_code (err) != GPG_ERR_NO_PUBKEY diff --git a/g10/keydb.h b/g10/keydb.h index 0f8d711..7457479 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -403,6 +403,7 @@ gpg_error_t get_pubkey_byfprint_fast (PKT_public_key *pk, the user ids. */ gpg_error_t get_keyblock_byfprint_fast (kbnode_t *r_keyblock, KEYDB_HANDLE *r_hd, + int primary_only, const byte *fprint, size_t fprint_len, int lock); -- 2.33.0