From: claudio Date: Thu, 28 Oct 2021 11:57:00 +0000 (+0000) Subject: Limit the size of the base64 blob inside the RRDP XML to be less than X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=1aea4e0e02a89c998e095b7a64772ea99c79fde2;p=openbsd Limit the size of the base64 blob inside the RRDP XML to be less than MAX_FILE_SIZE after base64 decoding it. This way hostile RRDP servers do less damage. OK beck@ tb@ --- diff --git a/usr.sbin/rpki-client/encoding.c b/usr.sbin/rpki-client/encoding.c index bef98659ea5..55c22a8cd82 100644 --- a/usr.sbin/rpki-client/encoding.c +++ b/usr.sbin/rpki-client/encoding.c @@ -1,4 +1,4 @@ -/* $OpenBSD: encoding.c,v 1.7 2021/10/27 21:56:58 beck Exp $ */ +/* $OpenBSD: encoding.c,v 1.8 2021/10/28 11:57:00 claudio Exp $ */ /* * Copyright (c) 2020 Claudio Jeker * @@ -63,6 +63,20 @@ err: return NULL; } +/* + * Return the size of the data blob in outlen for an inlen sized base64 buffer. + * Returns 0 on success and -1 if inlen would overflow an int. + */ +int +base64_decode_len(size_t inlen, size_t *outlen) +{ + *outlen = 0; + if (inlen >= INT_MAX - 3) + return -1; + *outlen = ((inlen + 3) / 4) * 3 + 1; + return 0; +} + /* * Decode base64 encoded string into binary buffer returned in out. * The out buffer size is stored in outlen. @@ -74,7 +88,8 @@ base64_decode(const unsigned char *in, size_t inlen, { static EVP_ENCODE_CTX *ctx; unsigned char *to; - int tolen; + size_t tolen; + int evplen; if (ctx == NULL && (ctx = EVP_ENCODE_CTX_new()) == NULL) err(1, "EVP_ENCODE_CTX_new"); @@ -82,19 +97,19 @@ base64_decode(const unsigned char *in, size_t inlen, *out = NULL; *outlen = 0; - if (inlen >= INT_MAX - 3) + if (base64_decode_len(inlen, &tolen) == -1) return -1; - tolen = ((inlen + 3) / 4) * 3 + 1; if ((to = malloc(tolen)) == NULL) return -1; + evplen = tolen; EVP_DecodeInit(ctx); - if (EVP_DecodeUpdate(ctx, to, &tolen, in, inlen) == -1) + if (EVP_DecodeUpdate(ctx, to, &evplen, in, inlen) == -1) goto fail; - *outlen = tolen; - if (EVP_DecodeFinal(ctx, to + tolen, &tolen) == -1) + *outlen = evplen; + if (EVP_DecodeFinal(ctx, to + evplen, &evplen) == -1) goto fail; - *outlen += tolen; + *outlen += evplen; *out = to; return 0; @@ -103,6 +118,24 @@ fail: return -1; } +/* + * Return the size of the base64 blob in outlen for a inlen sized binary buffer. + * Returns 0 on success and -1 if inlen would overflow the calculation. + */ +int +base64_encode_len(size_t inlen, size_t *outlen) +{ + *outlen = 0; + if (inlen >= INT_MAX / 2) + return -1; + *outlen = ((inlen + 2) / 3) * 4 + 1; + return 0; +} + +/* + * Encode a binary buffer into a base64 encoded string returned in out. + * Returns 0 on success or -1 for any errors. + */ int base64_encode(const unsigned char *in, size_t inlen, char **out) { @@ -111,9 +144,8 @@ base64_encode(const unsigned char *in, size_t inlen, char **out) *out = NULL; - if (inlen >= INT_MAX / 2) + if (base64_encode_len(inlen, &tolen) == -1) return -1; - tolen = ((inlen + 2) / 3) * 4 + 1; if ((to = malloc(tolen)) == NULL) return -1; diff --git a/usr.sbin/rpki-client/extern.h b/usr.sbin/rpki-client/extern.h index 023ac81e67c..685acdbd746 100644 --- a/usr.sbin/rpki-client/extern.h +++ b/usr.sbin/rpki-client/extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.83 2021/10/28 09:02:19 beck Exp $ */ +/* $OpenBSD: extern.h,v 1.84 2021/10/28 11:57:00 claudio Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons * @@ -534,8 +534,10 @@ void cryptoerrx(const char *, ...) /* Encoding functions for hex and base64. */ unsigned char *load_file(const char *, size_t *); +int base64_decode_len(size_t, size_t *); int base64_decode(const unsigned char *, size_t, unsigned char **, size_t *); +int base64_encode_len(size_t, size_t *); int base64_encode(const unsigned char *, size_t, char **); char *hex_encode(const unsigned char *, size_t); diff --git a/usr.sbin/rpki-client/rrdp.c b/usr.sbin/rpki-client/rrdp.c index 9271881a2e8..5883d9c2fca 100644 --- a/usr.sbin/rpki-client/rrdp.c +++ b/usr.sbin/rpki-client/rrdp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rrdp.c,v 1.15 2021/10/26 16:12:54 claudio Exp $ */ +/* $OpenBSD: rrdp.c,v 1.16 2021/10/28 11:57:00 claudio Exp $ */ /* * Copyright (c) 2020 Nils Fisher * Copyright (c) 2021 Claudio Jeker @@ -80,7 +80,7 @@ struct publish_xml { char *uri; char *data; char hash[SHA256_DIGEST_LENGTH]; - int data_length; + size_t data_length; enum publish_type type; }; @@ -622,27 +622,34 @@ free_publish_xml(struct publish_xml *pxml) * Add buf to the base64 data string, ensure that this remains a proper * string by NUL-terminating the string. */ -void +int publish_add_content(struct publish_xml *pxml, const char *buf, int length) { - int new_length; + size_t newlen, outlen; /* * optmisiation, this often gets called with '\n' as the * only data... seems wasteful */ if (length == 1 && buf[0] == '\n') - return; + return 0; /* append content to data */ - new_length = pxml->data_length + length; - pxml->data = realloc(pxml->data, new_length + 1); + if (SIZE_MAX - length - 1 <= pxml->data_length) + return -1; + newlen = pxml->data_length + length; + if (base64_decode_len(newlen, &outlen) == -1 || + outlen > MAX_FILE_SIZE) + return -1; + + pxml->data = realloc(pxml->data, newlen + 1); if (pxml->data == NULL) err(1, "%s", __func__); memcpy(pxml->data + pxml->data_length, buf, length); - pxml->data[new_length] = '\0'; - pxml->data_length = new_length; + pxml->data[newlen] = '\0'; + pxml->data_length = newlen; + return 0; } /* diff --git a/usr.sbin/rpki-client/rrdp.h b/usr.sbin/rpki-client/rrdp.h index be39db2cba3..9a230b7155c 100644 --- a/usr.sbin/rpki-client/rrdp.h +++ b/usr.sbin/rpki-client/rrdp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rrdp.h,v 1.4 2021/10/24 17:16:09 claudio Exp $ */ +/* $OpenBSD: rrdp.h,v 1.5 2021/10/28 11:57:00 claudio Exp $ */ /* * Copyright (c) 2020 Nils Fisher * Copyright (c) 2021 Claudio Jeker @@ -46,7 +46,7 @@ struct publish_xml; struct publish_xml *new_publish_xml(enum publish_type, char *, char *, size_t); void free_publish_xml(struct publish_xml *); -void publish_add_content(struct publish_xml *, +int publish_add_content(struct publish_xml *, const char *, int); int publish_done(struct rrdp *, struct publish_xml *); diff --git a/usr.sbin/rpki-client/rrdp_delta.c b/usr.sbin/rpki-client/rrdp_delta.c index c47db38a1e9..450e6667e74 100644 --- a/usr.sbin/rpki-client/rrdp_delta.c +++ b/usr.sbin/rpki-client/rrdp_delta.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rrdp_delta.c,v 1.3 2021/10/24 17:16:09 claudio Exp $ */ +/* $OpenBSD: rrdp_delta.c,v 1.4 2021/10/28 11:57:00 claudio Exp $ */ /* * Copyright (c) 2020 Nils Fisher * Copyright (c) 2021 Claudio Jeker @@ -218,9 +218,11 @@ static void delta_content_handler(void *data, const char *content, int length) { struct delta_xml *dxml = data; + XML_Parser p = dxml->parser; if (dxml->scope == DELTA_SCOPE_PUBLISH) - publish_add_content(dxml->pxml, content, length); + if (publish_add_content(dxml->pxml, content, length) == -1) + PARSE_FAIL(p, "parse failed - content too big"); } struct delta_xml * diff --git a/usr.sbin/rpki-client/rrdp_snapshot.c b/usr.sbin/rpki-client/rrdp_snapshot.c index 63e8b8af239..4b4e062ffd7 100644 --- a/usr.sbin/rpki-client/rrdp_snapshot.c +++ b/usr.sbin/rpki-client/rrdp_snapshot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rrdp_snapshot.c,v 1.2 2021/10/24 17:16:09 claudio Exp $ */ +/* $OpenBSD: rrdp_snapshot.c,v 1.3 2021/10/28 11:57:00 claudio Exp $ */ /* * Copyright (c) 2020 Nils Fisher * Copyright (c) 2021 Claudio Jeker @@ -194,9 +194,11 @@ static void snapshot_content_handler(void *data, const char *content, int length) { struct snapshot_xml *sxml = data; + XML_Parser p = sxml->parser; if (sxml->scope == SNAPSHOT_SCOPE_PUBLISH) - publish_add_content(sxml->pxml, content, length); + if (publish_add_content(sxml->pxml, content, length) == -1) + PARSE_FAIL(p, "parse failed - content too big"); } struct snapshot_xml *