Fix length checks in X509_cmp_time to avoid out-of-bounds reads.
Also tighten X509_cmp_time to reject more than three fractional seconds in the time; and to reject trailing garbage after the offset. CVE-2015-1789 (Imported from upstream's 9bc3665ac9e3c36f7762acd3691e1115d250b030) Change-Id: I2091b2d1b691c177d58dc7960e2e7eb4c97b1f69 Reviewed-on: https://boringssl-review.googlesource.com/5124 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
parent
184494dfcc
commit
d87021d246
@ -1829,49 +1829,89 @@ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
|
|||||||
ASN1_TIME atm;
|
ASN1_TIME atm;
|
||||||
long offset;
|
long offset;
|
||||||
char buff1[24],buff2[24],*p;
|
char buff1[24],buff2[24],*p;
|
||||||
int i,j;
|
int i, j, remaining;
|
||||||
|
|
||||||
p=buff1;
|
p=buff1;
|
||||||
i=ctm->length;
|
remaining = ctm->length;
|
||||||
str=(char *)ctm->data;
|
str=(char *)ctm->data;
|
||||||
|
/* Note that the following (historical) code allows much more slack in
|
||||||
|
* the time format than RFC5280. In RFC5280, the representation is
|
||||||
|
* fixed:
|
||||||
|
* UTCTime: YYMMDDHHMMSSZ
|
||||||
|
* GeneralizedTime: YYYYMMDDHHMMSSZ */
|
||||||
if (ctm->type == V_ASN1_UTCTIME)
|
if (ctm->type == V_ASN1_UTCTIME)
|
||||||
{
|
{
|
||||||
if ((i < 11) || (i > 17)) return 0;
|
/* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */
|
||||||
|
int min_length = sizeof("YYMMDDHHMMZ") - 1;
|
||||||
|
int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
|
||||||
|
if (remaining < min_length || remaining > max_length)
|
||||||
|
return 0;
|
||||||
memcpy(p,str,10);
|
memcpy(p,str,10);
|
||||||
p+=10;
|
p+=10;
|
||||||
str+=10;
|
str+=10;
|
||||||
|
remaining -= 10;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (i < 13) return 0;
|
/* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */
|
||||||
|
int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
|
||||||
|
int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
|
||||||
|
if (remaining < min_length || remaining > max_length)
|
||||||
|
return 0;
|
||||||
memcpy(p,str,12);
|
memcpy(p,str,12);
|
||||||
p+=12;
|
p+=12;
|
||||||
str+=12;
|
str+=12;
|
||||||
|
remaining -= 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*str == 'Z') || (*str == '-') || (*str == '+'))
|
if ((*str == 'Z') || (*str == '-') || (*str == '+'))
|
||||||
{ *(p++)='0'; *(p++)='0'; }
|
{ *(p++)='0'; *(p++)='0'; }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* SS (seconds) */
|
||||||
|
if (remaining < 2)
|
||||||
|
return 0;
|
||||||
*(p++)= *(str++);
|
*(p++)= *(str++);
|
||||||
*(p++)= *(str++);
|
*(p++)= *(str++);
|
||||||
/* Skip any fractional seconds... */
|
remaining -= 2;
|
||||||
if (*str == '.')
|
/* Skip any (up to three) fractional seconds...
|
||||||
|
* TODO(emilia): in RFC5280, fractional seconds are forbidden.
|
||||||
|
* Can we just kill them altogether? */
|
||||||
|
if (remaining && *str == '.')
|
||||||
{
|
{
|
||||||
str++;
|
str++;
|
||||||
while ((*str >= '0') && (*str <= '9')) str++;
|
remaining--;
|
||||||
|
for (i = 0; i < 3 && remaining; i++, str++, remaining--)
|
||||||
|
{
|
||||||
|
if (*str < '0' || *str > '9')
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
*(p++)='Z';
|
*(p++)='Z';
|
||||||
*(p++)='\0';
|
*(p++)='\0';
|
||||||
|
|
||||||
|
/* We now need either a terminating 'Z' or an offset. */
|
||||||
|
if (!remaining)
|
||||||
|
return 0;
|
||||||
if (*str == 'Z')
|
if (*str == 'Z')
|
||||||
|
{
|
||||||
|
if (remaining != 1)
|
||||||
|
return 0;
|
||||||
offset=0;
|
offset=0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* (+-)HHMM */
|
||||||
if ((*str != '+') && (*str != '-'))
|
if ((*str != '+') && (*str != '-'))
|
||||||
return 0;
|
return 0;
|
||||||
|
/* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */
|
||||||
|
if (remaining != 5)
|
||||||
|
return 0;
|
||||||
|
if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
|
||||||
|
str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
|
||||||
|
return 0;
|
||||||
offset=((str[1]-'0')*10+(str[2]-'0'))*60;
|
offset=((str[1]-'0')*10+(str[2]-'0'))*60;
|
||||||
offset+=(str[3]-'0')*10+(str[4]-'0');
|
offset+=(str[3]-'0')*10+(str[4]-'0');
|
||||||
if (*str == '-')
|
if (*str == '-')
|
||||||
|
Loading…
Reference in New Issue
Block a user