diff --git a/g10/getkey.c b/g10/getkey.c index 6fb3d867f..56dbfa0b6 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -543,10 +543,11 @@ get_seckey (PKT_public_key *pk, u32 *keyid) static int -skip_unusable (void *dummy, u32 * keyid, PKT_user_id * uid) +skip_unusable (void *dummy, u32 * keyid, int uid_no) { int unusable = 0; KBNODE keyblock; + PKT_public_key *pk; (void) dummy; @@ -557,28 +558,38 @@ skip_unusable (void *dummy, u32 * keyid, PKT_user_id * uid) goto leave; } + pk = keyblock->pkt->pkt.public_key; + /* Is the user ID in question revoked/expired? */ - if (uid) + if (uid_no) { KBNODE node; + int uids_seen = 0; for (node = keyblock; node; node = node->next) { if (node->pkt->pkttype == PKT_USER_ID) { - if (cmp_user_ids (uid, node->pkt->pkt.user_id) == 0 - && (node->pkt->pkt.user_id->is_revoked - || node->pkt->pkt.user_id->is_expired)) - { - unusable = 1; - break; - } + PKT_user_id *user_id = node->pkt->pkt.user_id; + + uids_seen ++; + if (uids_seen != uid_no) + continue; + + if (user_id->is_revoked || user_id->is_expired) + unusable = 1; + + break; } } + + /* If UID_NO is non-zero, then the keyblock better have at least + that many UIDs. */ + assert (uids_seen == uid_no); } if (!unusable) - unusable = pk_is_disabled (keyblock->pkt->pkt.public_key); + unusable = pk_is_disabled (pk); leave: release_kbnode (keyblock); diff --git a/g10/keyring.c b/g10/keyring.c index a5178ace4..81d2174ce 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -1148,7 +1148,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, for (n=any_skip?0:ndesc; n < ndesc; n++) { if (desc[n].skipfnc - && desc[n].skipfnc (desc[n].skipfncvalue, aki, uid)) + && desc[n].skipfnc (desc[n].skipfncvalue, aki, uid_no)) break; } if (n == ndesc) diff --git a/kbx/keybox-search-desc.h b/kbx/keybox-search-desc.h index ec7a3c139..fd8ffe427 100644 --- a/kbx/keybox-search-desc.h +++ b/kbx/keybox-search-desc.h @@ -57,7 +57,13 @@ typedef struct gpg_pkt_user_id_s *gpg_pkt_user_id_t; struct keydb_search_desc { KeydbSearchMode mode; - int (*skipfnc)(void *, u32 *, gpg_pkt_user_id_t); + /* Callback used to filter results. The first parameter is + SKIPFUNCVALUE. The second is the keyid. The third is the + 1-based index of the UID packet that matched the search criteria + (or 0, if none). + + Return non-zero if the result should be skipped. */ + int (*skipfnc)(void *, u32 *, int); void *skipfncvalue; const unsigned char *sn; int snlen; /* -1 := sn is a hex string */ diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index 05b6859d2..cb07c97fd 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -1010,8 +1010,8 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc, if (desc[n].skipfnc && blob_get_first_keyid (blob, kid) - && desc[n].skipfnc (desc[n].skipfncvalue, kid, NULL)) - break; + && desc[n].skipfnc (desc[n].skipfncvalue, kid, uid_no)) + break; } if (n == ndesc) break; /* got it */