mirror of
https://github.com/curl/curl.git
synced 2026-08-24 19:03:40 +03:00
x509asn1: add parse recursion limit
For ASN.1 tags with indefinite length, curl's own parser for TLS backends that do not support certificate inspection calls itself recursively. A malicious server certificate can then lead to high recursion level exhausting the stack space. This PR limits the recursion level to 16 which should be safe on all architectures. Added unit test 1657 to verify behaviour. Fixes #16135 Reported-by: z2_ Closes #16137
This commit is contained in:
parent
dc3252bedd
commit
65fca12e63
6 changed files with 188 additions and 6 deletions
|
|
@ -178,8 +178,11 @@ static const char *getASN1Element(struct Curl_asn1Element *elem,
|
|||
const char *beg, const char *end)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
static const char *getASN1Element(struct Curl_asn1Element *elem,
|
||||
const char *beg, const char *end)
|
||||
#define CURL_ASN1_MAX_RECURSIONS 16
|
||||
|
||||
static const char *getASN1Element_(struct Curl_asn1Element *elem,
|
||||
const char *beg, const char *end,
|
||||
size_t lvl)
|
||||
{
|
||||
unsigned char b;
|
||||
size_t len;
|
||||
|
|
@ -190,7 +193,8 @@ static const char *getASN1Element(struct Curl_asn1Element *elem,
|
|||
Returns a pointer in source string after the parsed element, or NULL
|
||||
if an error occurs. */
|
||||
if(!beg || !end || beg >= end || !*beg ||
|
||||
(size_t)(end - beg) > CURL_ASN1_MAX)
|
||||
((size_t)(end - beg) > CURL_ASN1_MAX) ||
|
||||
lvl >= CURL_ASN1_MAX_RECURSIONS)
|
||||
return NULL;
|
||||
|
||||
/* Process header byte. */
|
||||
|
|
@ -216,7 +220,7 @@ static const char *getASN1Element(struct Curl_asn1Element *elem,
|
|||
return NULL;
|
||||
elem->beg = beg;
|
||||
while(beg < end && *beg) {
|
||||
beg = getASN1Element(&lelem, beg, end);
|
||||
beg = getASN1Element_(&lelem, beg, end, lvl + 1);
|
||||
if(!beg)
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -243,6 +247,12 @@ static const char *getASN1Element(struct Curl_asn1Element *elem,
|
|||
return elem->end;
|
||||
}
|
||||
|
||||
static const char *getASN1Element(struct Curl_asn1Element *elem,
|
||||
const char *beg, const char *end)
|
||||
{
|
||||
return getASN1Element_(elem, beg, end, 0);
|
||||
}
|
||||
|
||||
#ifdef WANT_EXTRACT_CERTINFO
|
||||
|
||||
/*
|
||||
|
|
@ -259,6 +269,17 @@ static const struct Curl_OID *searchOID(const char *oid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef UNITTESTS
|
||||
/* used by unit1657.c */
|
||||
CURLcode Curl_x509_getASN1Element(struct Curl_asn1Element *elem,
|
||||
const char *beg, const char *end)
|
||||
{
|
||||
if(getASN1Element(elem, beg, end))
|
||||
return CURLE_OK;
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convert an ASN.1 Boolean value into its string representation.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
/* used by unit1656.c */
|
||||
CURLcode Curl_x509_GTime2str(struct dynbuf *store,
|
||||
const char *beg, const char *end);
|
||||
/* used by unit1657.c */
|
||||
CURLcode Curl_x509_getASN1Element(struct Curl_asn1Element *elem,
|
||||
const char *beg, const char *end);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue