[vox] [Fwd: Key validity bug in GnuPG 1.2.1 and earlier]
ME
vox@lists.lugod.org
Mon, 5 May 2003 09:56:27 -0700 (PDT)
------=_20030505095627_22667
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
I know many of you use GPG, so I'm passing this on. This is likely not a
serious issue for most of you. FYI:
---------------------------- Original Message ----------------------------
Subject: Key validity bug in GnuPG 1.2.1 and earlier
From: "David Shaw" <dshaw@jabberwocky.com>
Date: Sat, May 3, 2003 18:35
To: bugtraq@securityfocus.com
--------------------------------------------------------------------------
As part of the development of GnuPG 1.2.2, a bug was discovered in the key
validation code. This bug causes keys with more than one user ID to give
all user IDs on the key the amount of validity given to the most-valid
key.
This bug does not impact any key with only one user ID. Photo IDs ("user
attribute IDs") do not count as an additional user ID for the purposes of
this bug.
For example, given a key with two user IDs:
Alice <alice@example.com>
and
Alice's other address <alice@corp.example.net>
If the encrypting user has a trust path to to the ID
alice@example.com, then this ID is fully valid, and there is no
warning message when encrypting to alice@example.com.
If the encrypting user has either an insufficient or no trust path to the
ID "alice@corp.example.net", then that ID is either not fully
valid, or not valid at all respectively. There should be a warning
message given when encrypting to this other user ID ("it is not
certain this key belongs to the user named in the user ID / do you want to
encrypt to it anyway?"), but due to the bug, the invalid user ID is
accepted as valid and no warning message is given.
This bug has been fixed in the newly released GnuPG 1.2.2, and
upgrading is the recommended fix for this problem. For those who
cannot upgrade for whatever reason, the attached patch fixes the
problem as well. The patch should apply (perhaps with some offsets) to
GnuPG 1.2,1, 1.2.0, or 1.0.7. Note that GnuPG 1.0.6 (and possibly
earlier) versions have the same problem, but these versions are too old to
successfully apply the patch. If you are using GnuPG 1.0.6 or earlier
versions, please upgrade.
The GnuPG Team (David, Stefan, Timo and Werner)
------=_20030505095627_22667
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="patch-gnupg-1.2.1-trustfix.txt"
Index: g10/trustdb.c
==================================================================RCS file: /cvs/gnupg/gnupg/g10/trustdb.c,v
retrieving revision 1.89.2.1
diff -u -r1.89.2.1 trustdb.c
--- g10/trustdb.c 2 Oct 2002 21:56:03 -0000 1.89.2.1
+++ g10/trustdb.c 4 May 2003 01:12:38 -0000
@@ -808,16 +808,27 @@
while (recno)
{
read_record (recno, &vrec, RECTYPE_VALID);
- if ( validity < (vrec.r.valid.validity & TRUST_MASK) )
- validity = (vrec.r.valid.validity & TRUST_MASK);
- if ( namehash && !memcmp (vrec.r.valid.namehash, namehash, 20) )
- break;
+ if(namehash)
+ {
+ /* If namehash is given we return the trust for that user ID
+ ONLY. If the namehash is not found, then there is no
+ validity at all (i.e. the user ID wasn't signed). */
+ if(memcmp(vrec.r.valid.namehash,namehash,20)==0)
+ {
+ validity=(vrec.r.valid.validity & TRUST_MASK);
+ break;
+ }
+ }
+ else
+ {
+ /* If no namehash is given, we take the maximum validity
+ over all user IDs */
+ if ( validity < (vrec.r.valid.validity & TRUST_MASK) )
+ validity = (vrec.r.valid.validity & TRUST_MASK);
+ }
recno = vrec.r.valid.next;
}
- if (recno) /* okay, use the user ID associated one */
- validity = (vrec.r.valid.validity & TRUST_MASK);
-
if ( (trec.r.trust.ownertrust & TRUST_FLAG_DISABLED) )
validity |= TRUST_FLAG_DISABLED;
Index: g10/pkclist.c
==================================================================RCS file: /cvs/gnupg/gnupg/g10/pkclist.c,v
retrieving revision 1.73.2.1
diff -u -r1.73.2.1 pkclist.c
--- g10/pkclist.c 17 Oct 2002 13:49:30 -0000 1.73.2.1
+++ g10/pkclist.c 4 May 2003 01:12:39 -0000
@@ -524,17 +524,23 @@
return 0;
if( !opt.batch && !rc ) {
- char *p;
u32 keyid[2];
- size_t n;
keyid_from_pk( pk, keyid);
tty_printf( "%4u%c/%08lX %s \"",
nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk( pk ) );
- p = get_user_id( keyid, &n );
- tty_print_utf8_string( p, n ),
- m_free(p);
+ /* If the pk was chosen by a particular user ID, this is the
+ one to ask about. */
+ if(pk->user_id)
+ tty_print_utf8_string(pk->user_id->name,pk->user_id->len);
+ else
+ {
+ size_t n;
+ char *p = get_user_id( keyid, &n );
+ tty_print_utf8_string( p, n );
+ m_free(p);
+ }
tty_printf("\"\n");
print_fingerprint (pk, NULL, 2);
tty_printf("\n");
@@ -887,8 +893,27 @@
}
else {
int trustlevel;
+
+ /* Fill in the namehash so we can get the validity
+ for this particular UID. If we start using it
+ in more places than here, it might be good to
+ fill this in for all PKs. */
+
+ if(pk->user_id)
+ {
+ pk->namehash=m_alloc(20);
+
+ if( pk->user_id->attrib_data )
+ rmd160_hash_buffer (pk->namehash,
+ pk->user_id->attrib_data,
+ pk->user_id->attrib_len);
+ else
+ rmd160_hash_buffer (pk->namehash,
+ pk->user_id->name,
+ pk->user_id->len );
+ }
- trustlevel = get_validity (pk, NULL);
+ trustlevel = get_validity (pk, pk->namehash);
if( (trustlevel & TRUST_FLAG_DISABLED) ) {
tty_printf(_("Public key is disabled.\n") );
}
@@ -901,8 +926,6 @@
}
else {
PK_LIST r;
- char *p;
- size_t n;
u32 keyid[2];
keyid_from_pk( pk, keyid);
@@ -911,9 +934,16 @@
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1],
datestr_from_pk( pk ) );
- p = get_user_id( keyid, &n );
- tty_print_utf8_string( p, n );
- m_free(p);
+ if(pk->user_id)
+ tty_print_utf8_string(pk->user_id->name,
+ pk->user_id->len);
+ else
+ {
+ size_t n;
+ char *p = get_user_id( keyid, &n );
+ tty_print_utf8_string( p, n );
+ m_free(p);
+ }
tty_printf("\"\n");
r = m_alloc( sizeof *r );
@@ -981,6 +1011,25 @@
}
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
int trustlevel;
+
+ /* Fill in the namehash so we can get the validity
+ for this particular UID. If we start using it
+ in more places than here, it might be good to
+ fill this in for all PKs. */
+
+ if(pk->user_id)
+ {
+ pk->namehash=m_alloc(20);
+
+ if( pk->user_id->attrib_data )
+ rmd160_hash_buffer (pk->namehash,
+ pk->user_id->attrib_data,
+ pk->user_id->attrib_len);
+ else
+ rmd160_hash_buffer (pk->namehash,
+ pk->user_id->name,
+ pk->user_id->len );
+ }
trustlevel = get_validity (pk, pk->namehash);
if( (trustlevel & TRUST_FLAG_DISABLED) ) {
------=_20030505095627_22667
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 8bit
Content-Disposition: inline
LS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS0KVmVyc2lvbjogR251UEcgdjEuMy4yLWN2cyAo
R05VL0xpbnV4KQpDb21tZW50OiBodHRwOi8vd3d3LmphYmJlcndvY2t5LmNvbS9kYXZpZC9rZXlz
LmFzYwoKaUQ4REJRRSt0RzVkNG1aY2gwbmh5OGtSQXRDWkFKMFZuRVgwQ1kwa0laekZ1TnUramZN
Z2JEMmJNQUNmUmV5NgpRcXZFcnRkTjhMVWllREduQTNQSWtiMD0KPW5kTGkKLS0tLS1FTkQgUEdQ
IFNJR05BVFVSRS0tLS0tCg==
------=_20030505095627_22667--