mirror of
git://git.gnupg.org/gnupg.git
synced 2024-11-11 21:48:50 +01:00
gpg: Fix import's repair-key duplicate signature detection.
* g10/packet.h (PKG_siganture): Add field 'help_counter'.
* g10/key-check.c (sig_comparison): Take care of HELP_COUNTER.
(key_check_all_keysigs): De-duplicate on a per-block base.
--
The key_check_all_keysigs first does a detection of duplicate
signature. This is done over all signatures at once. The problem
here is for example:
key
uid_1
sig_uid_1.1
sig_uid_1.2
subkey_1
sig_sub_1.1
subkey_2
sig_sub_2.1
sig_sub_2.2 (duplicate of sig_sub_1.1)
Now the de-duplication deletes the first signature and keeps the
second. That works in most cases for foreign signature on userids but
in the above constellation the code simply removes sig_sub_1.1 so that
subkey_1 has no binding signature anymore. In a later step during
import the missing binding is detected and subkey_1 is removed because
it is not anymore valid. The sig_sub_2.2 will also be removed later
because it does not check out for subkey_2 (that is as expected).
The fix is to let the de-duplication work only on blocks (ie. within
the signatures of a user id or a subkey). This will not detect all
duplicates but that does not harm because later steps will detect and
remove them.
In the above case (with this patch applied) the second phase of
key_check_all_keysigs will reorder key signatures and move the
duplicate sig_sub_2.2 directly after sig_sub_1.1. This duplicates the
signature and for cleanness we should kick the de-duplication process
again. This will be done with a followup patch.
GnuPG-bug-id: 3994
Signed-off-by: Werner Koch <wk@gnupg.org>
(cherry picked from commit 26bce2f01d
)
This commit is contained in:
parent
36cc730fa5
commit
cedd754fcb
@ -72,6 +72,13 @@ sig_comparison (const void *av, const void *bv)
|
|||||||
a = an->pkt->pkt.signature;
|
a = an->pkt->pkt.signature;
|
||||||
b = bn->pkt->pkt.signature;
|
b = bn->pkt->pkt.signature;
|
||||||
|
|
||||||
|
/* Signatures with a different help counter are not identical for
|
||||||
|
* our purpose. */
|
||||||
|
if (a->help_counter < b->help_counter)
|
||||||
|
return -1;
|
||||||
|
if (a->help_counter > b->help_counter)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (a->digest_algo < b->digest_algo)
|
if (a->digest_algo < b->digest_algo)
|
||||||
return -1;
|
return -1;
|
||||||
if (a->digest_algo > b->digest_algo)
|
if (a->digest_algo > b->digest_algo)
|
||||||
@ -133,6 +140,7 @@ key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb,
|
|||||||
int bad_signature = 0;
|
int bad_signature = 0;
|
||||||
int missing_selfsig = 0;
|
int missing_selfsig = 0;
|
||||||
int modified = 0;
|
int modified = 0;
|
||||||
|
PKT_signature *sig;
|
||||||
|
|
||||||
log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
|
log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
|
||||||
pk = kb->pkt->pkt.public_key;
|
pk = kb->pkt->pkt.public_key;
|
||||||
@ -143,6 +151,7 @@ key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb,
|
|||||||
kbnode_t *sigs;
|
kbnode_t *sigs;
|
||||||
int i;
|
int i;
|
||||||
int last_i;
|
int last_i;
|
||||||
|
int block;
|
||||||
|
|
||||||
/* Count the sigs. */
|
/* Count the sigs. */
|
||||||
for (nsigs = 0, n = kb; n; n = n->next)
|
for (nsigs = 0, n = kb; n; n = n->next)
|
||||||
@ -166,14 +175,31 @@ key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
block = 0;
|
||||||
for (n = kb; n; n = n->next)
|
for (n = kb; n; n = n->next)
|
||||||
{
|
{
|
||||||
if (is_deleted_kbnode (n))
|
if (is_deleted_kbnode (n))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (n->pkt->pkttype != PKT_SIGNATURE)
|
if (n->pkt->pkttype != PKT_SIGNATURE)
|
||||||
continue;
|
{
|
||||||
|
switch (n->pkt->pkttype)
|
||||||
|
{
|
||||||
|
case PKT_PUBLIC_SUBKEY:
|
||||||
|
case PKT_SECRET_SUBKEY:
|
||||||
|
case PKT_USER_ID:
|
||||||
|
case PKT_ATTRIBUTE:
|
||||||
|
/* Bump the block number so that we only consider
|
||||||
|
* signatures below the same object as duplicates. */
|
||||||
|
block++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sig = n->pkt->pkt.signature;
|
||||||
|
sig->help_counter = block;
|
||||||
sigs[i] = n;
|
sigs[i] = n;
|
||||||
i ++;
|
i ++;
|
||||||
}
|
}
|
||||||
@ -194,7 +220,7 @@ key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb,
|
|||||||
{
|
{
|
||||||
if (DBG_PACKET)
|
if (DBG_PACKET)
|
||||||
{
|
{
|
||||||
PKT_signature *sig = sigs[i]->pkt->pkt.signature;
|
sig = sigs[i]->pkt->pkt.signature;
|
||||||
|
|
||||||
log_debug ("Signature appears multiple times, "
|
log_debug ("Signature appears multiple times, "
|
||||||
"deleting duplicate:\n");
|
"deleting duplicate:\n");
|
||||||
@ -244,7 +270,6 @@ key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb,
|
|||||||
{
|
{
|
||||||
PACKET *p;
|
PACKET *p;
|
||||||
int processed_current_component;
|
int processed_current_component;
|
||||||
PKT_signature *sig;
|
|
||||||
int rc;
|
int rc;
|
||||||
int dump_sig_params = 0;
|
int dump_sig_params = 0;
|
||||||
|
|
||||||
@ -577,7 +602,6 @@ key_check_all_keysigs (ctrl_t ctrl, int mode, kbnode_t kb,
|
|||||||
{
|
{
|
||||||
int has_selfsig = 0;
|
int has_selfsig = 0;
|
||||||
PACKET *p;
|
PACKET *p;
|
||||||
PKT_signature *sig;
|
|
||||||
|
|
||||||
current_component = NULL;
|
current_component = NULL;
|
||||||
for (n = kb; n; n = n->next)
|
for (n = kb; n; n = n->next)
|
||||||
|
@ -230,6 +230,7 @@ typedef struct
|
|||||||
const byte *trust_regexp;
|
const byte *trust_regexp;
|
||||||
struct revocation_key *revkey;
|
struct revocation_key *revkey;
|
||||||
int numrevkeys;
|
int numrevkeys;
|
||||||
|
int help_counter; /* Used internally bu some fucntions. */
|
||||||
pka_info_t *pka_info; /* Malloced PKA data or NULL if not
|
pka_info_t *pka_info; /* Malloced PKA data or NULL if not
|
||||||
available. See also flags.pka_tried. */
|
available. See also flags.pka_tried. */
|
||||||
char *signers_uid; /* Malloced value of the SIGNERS_UID
|
char *signers_uid; /* Malloced value of the SIGNERS_UID
|
||||||
|
Loading…
Reference in New Issue
Block a user