1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-31 11:41:32 +01:00

common: When classifying keyids and fingerprints, reject trailing junk.

* common/userids.c (classify_user_id): Trim any trailing whitespace.
Before assuming that a hexstring corresponds to a key id or
fingerprint, make sure that it is NUL terminated.

--
Signed-off-by: Neal H. Walfield <neal@g10code.com>
GnuPG-bug-id: 1206
Debian-bug-id: 575084
This commit is contained in:
Neal H. Walfield 2015-11-06 12:31:16 +01:00
parent e8c53fca95
commit f99830b728

View File

@ -1,6 +1,7 @@
/* userids.c - Utility functions for user ids. /* userids.c - Utility functions for user ids.
* Copyright (C) 2001, 2003, 2004, 2006, * Copyright (C) 2001, 2003, 2004, 2006,
* 2009 Free Software Foundation, Inc. * 2009 Free Software Foundation, Inc.
* Copyright (C) 2015 g10 Code GmbH
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -70,6 +71,8 @@ gpg_error_t
classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack) classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
{ {
const char *s; const char *s;
char *s2 = NULL;
int rc = 0;
int hexprefix = 0; int hexprefix = 0;
int hexlength; int hexlength;
int mode = 0; int mode = 0;
@ -83,14 +86,22 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
function. */ function. */
memset (desc, 0, sizeof *desc); memset (desc, 0, sizeof *desc);
/* Skip leading spaces. */ /* Skip leading and trailing spaces. */
for(s = name; *s && spacep (s); s++ ) for(s = name; *s && spacep (s); s++ )
; ;
if (s[strlen(s) - 1] == ' ')
{
s2 = xstrdup (s);
while (s2[strlen(s2) - 1] == ' ')
s2[strlen(s2) - 1] = 0;
s = s2;
}
switch (*s) switch (*s)
{ {
case 0: /* Empty string is an error. */ case 0: /* Empty string is an error. */
return gpg_error (GPG_ERR_INV_USER_ID); rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
case '.': /* An email address, compare from end. Note that this case '.': /* An email address, compare from end. Note that this
has not yet been implemented in the search code. */ has not yet been implemented in the search code. */
@ -138,7 +149,10 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
case '/': /* Subject's DN. */ case '/': /* Subject's DN. */
s++; s++;
if (!*s || spacep (s)) /* No DN or prefixed with a space. */ if (!*s || spacep (s)) /* No DN or prefixed with a space. */
return gpg_error (GPG_ERR_INV_USER_ID); {
rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
}
desc->u.name = s; desc->u.name = s;
mode = KEYDB_SEARCH_MODE_SUBJECT; mode = KEYDB_SEARCH_MODE_SUBJECT;
break; break;
@ -152,7 +166,10 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
{ /* "#/" indicates an issuer's DN. */ { /* "#/" indicates an issuer's DN. */
s++; s++;
if (!*s || spacep (s)) /* No DN or prefixed with a space. */ if (!*s || spacep (s)) /* No DN or prefixed with a space. */
return gpg_error (GPG_ERR_INV_USER_ID); {
rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
}
desc->u.name = s; desc->u.name = s;
mode = KEYDB_SEARCH_MODE_ISSUER; mode = KEYDB_SEARCH_MODE_ISSUER;
} }
@ -162,7 +179,10 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
{ {
/* Check for an invalid digit in the serial number. */ /* Check for an invalid digit in the serial number. */
if (!strchr("01234567890abcdefABCDEF", *si)) if (!strchr("01234567890abcdefABCDEF", *si))
return gpg_error (GPG_ERR_INV_USER_ID); {
rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
}
} }
desc->sn = (const unsigned char*)s; desc->sn = (const unsigned char*)s;
desc->snlen = -1; desc->snlen = -1;
@ -172,7 +192,10 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
{ {
s = si+1; s = si+1;
if (!*s || spacep (s)) /* No DN or prefixed with a space. */ if (!*s || spacep (s)) /* No DN or prefixed with a space. */
return gpg_error (GPG_ERR_INV_USER_ID); {
rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
}
desc->u.name = s; desc->u.name = s;
mode = KEYDB_SEARCH_MODE_ISSUER_SN; mode = KEYDB_SEARCH_MODE_ISSUER_SN;
} }
@ -187,14 +210,23 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
se = strchr (++s,':'); se = strchr (++s,':');
if (!se) if (!se)
return gpg_error (GPG_ERR_INV_USER_ID); {
rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
}
for (i=0,si=s; si < se; si++, i++ ) for (i=0,si=s; si < se; si++, i++ )
{ {
if (!strchr("01234567890abcdefABCDEF", *si)) if (!strchr("01234567890abcdefABCDEF", *si))
return gpg_error (GPG_ERR_INV_USER_ID); /* Invalid digit. */ {
rc = gpg_error (GPG_ERR_INV_USER_ID); /* Invalid digit. */
goto out;
}
} }
if (i != 32 && i != 40) if (i != 32 && i != 40)
return gpg_error (GPG_ERR_INV_USER_ID); /* Invalid length of fpr. */ {
rc = gpg_error (GPG_ERR_INV_USER_ID); /* Invalid length of fpr. */
goto out;
}
for (i=0,si=s; si < se; i++, si +=2) for (i=0,si=s; si < se; i++, si +=2)
desc->u.fpr[i] = hextobyte(si); desc->u.fpr[i] = hextobyte(si);
for (; i < 20; i++) for (; i < 20; i++)
@ -207,7 +239,10 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
case '&': /* Keygrip*/ case '&': /* Keygrip*/
{ {
if (hex2bin (s+1, desc->u.grip, 20) < 0) if (hex2bin (s+1, desc->u.grip, 20) < 0)
return gpg_error (GPG_ERR_INV_USER_ID); /* Invalid. */ {
rc = gpg_error (GPG_ERR_INV_USER_ID); /* Invalid. */
goto out;
}
mode = KEYDB_SEARCH_MODE_KEYGRIP; mode = KEYDB_SEARCH_MODE_KEYGRIP;
} }
break; break;
@ -231,7 +266,10 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
{ {
if (hexprefix) /* A "0x" prefix without a correct if (hexprefix) /* A "0x" prefix without a correct
termination is an error. */ termination is an error. */
return gpg_error (GPG_ERR_INV_USER_ID); {
rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
}
/* The first characters looked like a hex number, but the /* The first characters looked like a hex number, but the
entire string is not. */ entire string is not. */
hexlength = 0; hexlength = 0;
@ -240,7 +278,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
if (desc->exact) if (desc->exact)
hexlength--; /* Remove the bang. */ hexlength--; /* Remove the bang. */
if (hexlength == 8 if ((hexlength == 8 && s[hexlength] == 0)
|| (!hexprefix && hexlength == 9 && *s == '0')) || (!hexprefix && hexlength == 9 && *s == '0'))
{ {
/* Short keyid. */ /* Short keyid. */
@ -249,7 +287,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
desc->u.kid[1] = strtoul( s, NULL, 16 ); desc->u.kid[1] = strtoul( s, NULL, 16 );
mode = KEYDB_SEARCH_MODE_SHORT_KID; mode = KEYDB_SEARCH_MODE_SHORT_KID;
} }
else if (hexlength == 16 else if ((hexlength == 16 && s[hexlength] == 0)
|| (!hexprefix && hexlength == 17 && *s == '0')) || (!hexprefix && hexlength == 17 && *s == '0'))
{ {
/* Long keyid. */ /* Long keyid. */
@ -261,7 +299,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
desc->u.kid[1] = strtoul (s+8, NULL, 16); desc->u.kid[1] = strtoul (s+8, NULL, 16);
mode = KEYDB_SEARCH_MODE_LONG_KID; mode = KEYDB_SEARCH_MODE_LONG_KID;
} }
else if (hexlength == 32 else if ((hexlength == 32 && s[hexlength] == 0)
|| (!hexprefix && hexlength == 33 && *s == '0')) || (!hexprefix && hexlength == 33 && *s == '0'))
{ {
/* MD5 fingerprint. */ /* MD5 fingerprint. */
@ -273,12 +311,15 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
{ {
int c = hextobyte(s); int c = hextobyte(s);
if (c == -1) if (c == -1)
return gpg_error (GPG_ERR_INV_USER_ID); {
rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
}
desc->u.fpr[i] = c; desc->u.fpr[i] = c;
} }
mode = KEYDB_SEARCH_MODE_FPR16; mode = KEYDB_SEARCH_MODE_FPR16;
} }
else if (hexlength == 40 else if ((hexlength == 40 && s[hexlength] == 0)
|| (!hexprefix && hexlength == 41 && *s == '0')) || (!hexprefix && hexlength == 41 && *s == '0'))
{ {
/* SHA1/RMD160 fingerprint. */ /* SHA1/RMD160 fingerprint. */
@ -289,7 +330,10 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
{ {
int c = hextobyte(s); int c = hextobyte(s);
if (c == -1) if (c == -1)
return gpg_error (GPG_ERR_INV_USER_ID); {
rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
}
desc->u.fpr[i] = c; desc->u.fpr[i] = c;
} }
mode = KEYDB_SEARCH_MODE_FPR20; mode = KEYDB_SEARCH_MODE_FPR20;
@ -367,10 +411,13 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
else else
{ {
/* Hex number with a prefix but with a wrong length. */ /* Hex number with a prefix but with a wrong length. */
return gpg_error (GPG_ERR_INV_USER_ID); rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
} }
} }
desc->mode = mode; desc->mode = mode;
return 0; out:
xfree (s2);
return rc;
} }