diff options
Diffstat (limited to 'libs/libcurl/src/vtls/x509asn1.c')
-rw-r--r-- | libs/libcurl/src/vtls/x509asn1.c | 214 |
1 files changed, 118 insertions, 96 deletions
diff --git a/libs/libcurl/src/vtls/x509asn1.c b/libs/libcurl/src/vtls/x509asn1.c index 6e1fbfab49..1b4821484c 100644 --- a/libs/libcurl/src/vtls/x509asn1.c +++ b/libs/libcurl/src/vtls/x509asn1.c @@ -22,39 +22,39 @@ *
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
- defined(USE_MBEDTLS)
+ defined(USE_MBEDTLS) || defined(USE_RUSTLS)
-#if defined(USE_WOLFSSL) || defined(USE_SCHANNEL)
+#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
+ defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_RUSTLS)
#define WANT_PARSEX509 /* uses Curl_parseX509() */
#endif
#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
- defined(USE_MBEDTLS)
+ defined(USE_MBEDTLS) || defined(USE_RUSTLS)
#define WANT_EXTRACT_CERTINFO /* uses Curl_extract_certinfo() */
-#define WANT_PARSEX509 /* ... uses Curl_parseX509() */
#endif
#include <curl/curl.h>
-#include "urldata.h"
-#include "strcase.h"
-#include "curl_ctype.h"
+#include "../urldata.h"
+#include "../strcase.h"
+#include "../curl_ctype.h"
#include "hostcheck.h"
-#include "vtls/vtls.h"
-#include "vtls/vtls_int.h"
-#include "sendf.h"
-#include "inet_pton.h"
-#include "curl_base64.h"
+#include "vtls.h"
+#include "vtls_int.h"
+#include "../sendf.h"
+#include "../curlx/inet_pton.h"
+#include "../curlx/base64.h"
#include "x509asn1.h"
-#include "dynbuf.h"
+#include "../curlx/dynbuf.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
/*
* Constants.
@@ -64,10 +64,10 @@ #define CURL_ASN1_MAX ((size_t) 0x40000) /* 256K */
/* ASN.1 classes. */
-#define CURL_ASN1_UNIVERSAL 0
-#define CURL_ASN1_APPLICATION 1
-#define CURL_ASN1_CONTEXT_SPECIFIC 2
-#define CURL_ASN1_PRIVATE 3
+/* #define CURL_ASN1_UNIVERSAL 0 */
+/* #define CURL_ASN1_APPLICATION 1 */
+/* #define CURL_ASN1_CONTEXT_SPECIFIC 2 */
+/* #define CURL_ASN1_PRIVATE 3 */
/* ASN.1 types. */
#define CURL_ASN1_BOOLEAN 1
@@ -76,27 +76,27 @@ #define CURL_ASN1_OCTET_STRING 4
#define CURL_ASN1_NULL 5
#define CURL_ASN1_OBJECT_IDENTIFIER 6
-#define CURL_ASN1_OBJECT_DESCRIPTOR 7
-#define CURL_ASN1_INSTANCE_OF 8
-#define CURL_ASN1_REAL 9
+/* #define CURL_ASN1_OBJECT_DESCRIPTOR 7 */
+/* #define CURL_ASN1_INSTANCE_OF 8 */
+/* #define CURL_ASN1_REAL 9 */
#define CURL_ASN1_ENUMERATED 10
-#define CURL_ASN1_EMBEDDED 11
+/* #define CURL_ASN1_EMBEDDED 11 */
#define CURL_ASN1_UTF8_STRING 12
-#define CURL_ASN1_RELATIVE_OID 13
-#define CURL_ASN1_SEQUENCE 16
-#define CURL_ASN1_SET 17
+/* #define CURL_ASN1_RELATIVE_OID 13 */
+/* #define CURL_ASN1_SEQUENCE 16 */
+/* #define CURL_ASN1_SET 17 */
#define CURL_ASN1_NUMERIC_STRING 18
#define CURL_ASN1_PRINTABLE_STRING 19
#define CURL_ASN1_TELETEX_STRING 20
-#define CURL_ASN1_VIDEOTEX_STRING 21
+/* #define CURL_ASN1_VIDEOTEX_STRING 21 */
#define CURL_ASN1_IA5_STRING 22
#define CURL_ASN1_UTC_TIME 23
#define CURL_ASN1_GENERALIZED_TIME 24
-#define CURL_ASN1_GRAPHIC_STRING 25
+/* #define CURL_ASN1_GRAPHIC_STRING 25 */
#define CURL_ASN1_VISIBLE_STRING 26
-#define CURL_ASN1_GENERAL_STRING 27
+/* #define CURL_ASN1_GENERAL_STRING 27 */
#define CURL_ASN1_UNIVERSAL_STRING 28
-#define CURL_ASN1_CHARACTER_STRING 29
+/* #define CURL_ASN1_CHARACTER_STRING 29 */
#define CURL_ASN1_BMP_STRING 30
@@ -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,10 +247,16 @@ 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
/*
- * Search the null terminated OID or OID identifier in local table.
+ * Search the null-terminated OID or OID identifier in local table.
* Return the table entry pointer or NULL if not found.
*/
static const struct Curl_OID *searchOID(const char *oid)
@@ -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.
*
@@ -270,7 +291,7 @@ static CURLcode bool2str(struct dynbuf *store, {
if(end - beg != 1)
return CURLE_BAD_FUNCTION_ARGUMENT;
- return Curl_dyn_add(store, *beg ? "TRUE": "FALSE");
+ return curlx_dyn_add(store, *beg ? "TRUE": "FALSE");
}
/*
@@ -284,7 +305,7 @@ static CURLcode octet2str(struct dynbuf *store, CURLcode result = CURLE_OK;
while(!result && beg < end)
- result = Curl_dyn_addf(store, "%02x:", (unsigned char) *beg++);
+ result = curlx_dyn_addf(store, "%02x:", (unsigned char) *beg++);
return result;
}
@@ -323,7 +344,7 @@ static CURLcode int2str(struct dynbuf *store, do
val = (val << 8) | *(const unsigned char *) beg++;
while(beg < end);
- return Curl_dyn_addf(store, "%s%x", val >= 10 ? "0x" : "", val);
+ return curlx_dyn_addf(store, "%s%x", val >= 10 ? "0x" : "", val);
}
/*
@@ -366,7 +387,7 @@ utf8asn1str(struct dynbuf *to, int type, const char *from, const char *end) if(type == CURL_ASN1_UTF8_STRING) {
/* Just copy. */
if(inlength)
- result = Curl_dyn_addn(to, from, inlength);
+ result = curlx_dyn_addn(to, from, inlength);
}
else {
while(!result && (from < end)) {
@@ -405,7 +426,7 @@ utf8asn1str(struct dynbuf *to, int type, const char *from, const char *end) charsize++;
}
buf[0] = (char) wc;
- result = Curl_dyn_addn(to, buf, charsize);
+ result = curlx_dyn_addn(to, buf, charsize);
}
}
return result;
@@ -428,7 +449,7 @@ static CURLcode encodeOID(struct dynbuf *store, x = y / 40;
y -= x * 40;
- result = Curl_dyn_addf(store, "%u.%u", x, y);
+ result = curlx_dyn_addf(store, "%u.%u", x, y);
if(result)
return result;
@@ -441,7 +462,7 @@ static CURLcode encodeOID(struct dynbuf *store, y = *(const unsigned char *) beg++;
x = (x << 7) | (y & 0x7F);
} while(y & 0x80);
- result = Curl_dyn_addf(store, ".%u", x);
+ result = curlx_dyn_addf(store, ".%u", x);
}
return result;
}
@@ -459,16 +480,16 @@ static CURLcode OID2str(struct dynbuf *store, if(beg < end) {
if(symbolic) {
struct dynbuf buf;
- Curl_dyn_init(&buf, CURL_X509_STR_MAX);
+ curlx_dyn_init(&buf, CURL_X509_STR_MAX);
result = encodeOID(&buf, beg, end);
if(!result) {
- const struct Curl_OID *op = searchOID(Curl_dyn_ptr(&buf));
+ const struct Curl_OID *op = searchOID(curlx_dyn_ptr(&buf));
if(op)
- result = Curl_dyn_add(store, op->textoid);
+ result = curlx_dyn_add(store, op->textoid);
else
- result = Curl_dyn_add(store, Curl_dyn_ptr(&buf));
- Curl_dyn_free(&buf);
+ result = curlx_dyn_add(store, curlx_dyn_ptr(&buf));
+ curlx_dyn_free(&buf);
}
}
else
@@ -547,12 +568,12 @@ static CURLcode GTime2str(struct dynbuf *store, tzl = end - tzp;
}
- return Curl_dyn_addf(store,
- "%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
- beg, beg + 4, beg + 6,
- beg + 8, beg + 10, sec1, sec2,
- fracl ? ".": "", (int)fracl, fracp,
- sep, (int)tzl, tzp);
+ return curlx_dyn_addf(store,
+ "%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
+ beg, beg + 4, beg + 6,
+ beg + 8, beg + 10, sec1, sec2,
+ fracl ? ".": "", (int)fracl, fracp,
+ sep, (int)tzl, tzp);
}
#ifdef UNITTESTS
@@ -601,10 +622,10 @@ static CURLcode UTime2str(struct dynbuf *store, tzp++;
tzl = end - tzp;
- return Curl_dyn_addf(store, "%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
- 20 - (*beg >= '5'), beg, beg + 2, beg + 4,
- beg + 6, beg + 8, sec,
- (int)tzl, tzp);
+ return curlx_dyn_addf(store, "%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
+ 20 - (*beg >= '5'), beg, beg + 2, beg + 4,
+ beg + 6, beg + 8, sec,
+ (int)tzl, tzp);
}
/*
@@ -637,7 +658,7 @@ static CURLcode ASN1tostr(struct dynbuf *store, result = octet2str(store, elem->beg, elem->end);
break;
case CURL_ASN1_NULL:
- result = Curl_dyn_addn(store, "", 1);
+ result = curlx_dyn_addn(store, "", 1);
break;
case CURL_ASN1_OBJECT_IDENTIFIER:
result = OID2str(store, elem->beg, elem->end, TRUE);
@@ -681,7 +702,7 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn) CURLcode result = CURLE_OK;
bool added = FALSE;
struct dynbuf temp;
- Curl_dyn_init(&temp, CURL_X509_STR_MAX);
+ curlx_dyn_init(&temp, CURL_X509_STR_MAX);
for(p1 = dn->beg; p1 < dn->end;) {
p1 = getASN1Element(&rdn, p1, dn->end);
@@ -704,12 +725,12 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn) result = CURLE_BAD_FUNCTION_ARGUMENT;
goto error;
}
- Curl_dyn_reset(&temp);
+ curlx_dyn_reset(&temp);
result = ASN1tostr(&temp, &oid, 0);
if(result)
goto error;
- str = Curl_dyn_ptr(&temp);
+ str = curlx_dyn_ptr(&temp);
if(!str) {
result = CURLE_BAD_FUNCTION_ARGUMENT;
@@ -722,20 +743,20 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn) ;
if(added) {
if(p3 - str > 2)
- result = Curl_dyn_addn(store, "/", 1);
+ result = curlx_dyn_addn(store, "/", 1);
else
- result = Curl_dyn_addn(store, ", ", 2);
+ result = curlx_dyn_addn(store, ", ", 2);
if(result)
goto error;
}
/* Encode attribute name. */
- result = Curl_dyn_add(store, str);
+ result = curlx_dyn_add(store, str);
if(result)
goto error;
/* Generate equal sign. */
- result = Curl_dyn_addn(store, "=", 1);
+ result = curlx_dyn_addn(store, "=", 1);
if(result)
goto error;
@@ -743,12 +764,12 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn) result = ASN1tostr(store, &value, 0);
if(result)
goto error;
- Curl_dyn_reset(&temp);
+ curlx_dyn_reset(&temp);
added = TRUE; /* use separator for next */
}
}
error:
- Curl_dyn_free(&temp);
+ curlx_dyn_free(&temp);
return result;
}
@@ -926,8 +947,8 @@ static CURLcode ssl_push_certinfo_dyn(struct Curl_easy *data, const char *label,
struct dynbuf *ptr)
{
- size_t valuelen = Curl_dyn_len(ptr);
- char *value = Curl_dyn_ptr(ptr);
+ size_t valuelen = curlx_dyn_len(ptr);
+ char *value = curlx_dyn_ptr(ptr);
CURLcode result = Curl_ssl_push_certinfo_len(data, certnum, label,
value, valuelen);
@@ -945,7 +966,7 @@ static CURLcode do_pubkey_field(struct Curl_easy *data, int certnum, CURLcode result;
struct dynbuf out;
- Curl_dyn_init(&out, CURL_X509_STR_MAX);
+ curlx_dyn_init(&out, CURL_X509_STR_MAX);
/* Generate a certificate information record for the public key. */
@@ -953,7 +974,7 @@ static CURLcode do_pubkey_field(struct Curl_easy *data, int certnum, if(!result) {
if(data->set.ssl.certinfo)
result = ssl_push_certinfo_dyn(data, certnum, label, &out);
- Curl_dyn_free(&out);
+ curlx_dyn_free(&out);
}
return result;
}
@@ -1005,7 +1026,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum, len = ((elem.end - q) * 8);
if(len) {
unsigned int i;
- for(i = *(unsigned char *) q; !(i & 0x80); i <<= 1)
+ for(i = *(const unsigned char *) q; !(i & 0x80); i <<= 1)
len--;
}
if(len > 32)
@@ -1089,7 +1110,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(certnum)
return CURLE_OK;
- Curl_dyn_init(&out, CURL_X509_STR_MAX);
+ curlx_dyn_init(&out, CURL_X509_STR_MAX);
/* Prepare the certificate information for curl_easy_getinfo(). */
/* Extract the certificate ASN.1 elements. */
@@ -1105,7 +1126,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Issuer. */
result = DNtostr(&out, &cert.issuer);
@@ -1116,20 +1137,20 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Version (always fits in less than 32 bits). */
version = 0;
for(ptr = cert.version.beg; ptr < cert.version.end; ptr++)
version = (version << 8) | *(const unsigned char *) ptr;
if(data->set.ssl.certinfo) {
- result = Curl_dyn_addf(&out, "%x", version);
+ result = curlx_dyn_addf(&out, "%x", version);
if(result)
goto done;
result = ssl_push_certinfo_dyn(data, certnum, "Version", &out);
if(result)
goto done;
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
}
/* Serial number. */
@@ -1141,7 +1162,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Signature algorithm .*/
result = dumpAlgo(&out, ¶m, cert.signatureAlgorithm.beg,
@@ -1154,7 +1175,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Start Date. */
result = ASN1tostr(&out, &cert.notBefore, 0);
@@ -1165,7 +1186,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Expire Date. */
result = ASN1tostr(&out, &cert.notAfter, 0);
@@ -1176,7 +1197,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Public Key Algorithm. */
result = dumpAlgo(&out, ¶m, cert.subjectPublicKeyAlgorithm.beg,
@@ -1190,13 +1211,13 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, goto done;
}
- rc = do_pubkey(data, certnum, Curl_dyn_ptr(&out),
+ rc = do_pubkey(data, certnum, curlx_dyn_ptr(&out),
¶m, &cert.subjectPublicKey);
if(rc) {
result = CURLE_OUT_OF_MEMORY; /* the most likely error */
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Signature. */
result = ASN1tostr(&out, &cert.signature, 0);
@@ -1207,12 +1228,12 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(result)
goto done;
}
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Generate PEM certificate. */
- result = Curl_base64_encode(cert.certificate.beg,
- cert.certificate.end - cert.certificate.beg,
- &certptr, &clen);
+ result = curlx_base64_encode(cert.certificate.beg,
+ cert.certificate.end - cert.certificate.beg,
+ &certptr, &clen);
if(result)
goto done;
@@ -1225,22 +1246,22 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, -----END CERTIFICATE-----\n
*/
- Curl_dyn_reset(&out);
+ curlx_dyn_reset(&out);
/* Build the certificate string. */
- result = Curl_dyn_add(&out, "-----BEGIN CERTIFICATE-----\n");
+ result = curlx_dyn_add(&out, "-----BEGIN CERTIFICATE-----\n");
if(!result) {
size_t j = 0;
while(!result && (j < clen)) {
size_t chunksize = (clen - j) > 64 ? 64 : (clen - j);
- result = Curl_dyn_addn(&out, &certptr[j], chunksize);
+ result = curlx_dyn_addn(&out, &certptr[j], chunksize);
if(!result)
- result = Curl_dyn_addn(&out, "\n", 1);
+ result = curlx_dyn_addn(&out, "\n", 1);
j += chunksize;
}
if(!result)
- result = Curl_dyn_add(&out, "-----END CERTIFICATE-----\n");
+ result = curlx_dyn_add(&out, "-----END CERTIFICATE-----\n");
}
free(certptr);
if(!result)
@@ -1250,10 +1271,11 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, done:
if(result)
failf(data, "Failed extracting certificate chain");
- Curl_dyn_free(&out);
+ curlx_dyn_free(&out);
return result;
}
#endif /* WANT_EXTRACT_CERTINFO */
-#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
+#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP
+ or USE_MBEDTLS or USE_RUSTLS */
|