summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2021-10-28 11:57:01 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2021-10-28 11:57:01 +0000
commitcca6789200f87bdde1faac075b9e9dd6ed1ce7e8 (patch)
tree35b118a1d5bd1fae085ea8b3c42012dbffa64a64 /usr.sbin
parent63502ea3cb20aed4d7d0a7ea6cd10a86b7128702 (diff)
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@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/rpki-client/encoding.c52
-rw-r--r--usr.sbin/rpki-client/extern.h4
-rw-r--r--usr.sbin/rpki-client/rrdp.c25
-rw-r--r--usr.sbin/rpki-client/rrdp.h4
-rw-r--r--usr.sbin/rpki-client/rrdp_delta.c6
-rw-r--r--usr.sbin/rpki-client/rrdp_snapshot.c6
6 files changed, 71 insertions, 26 deletions
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 <claudio@openbsd.org>
*
@@ -64,6 +64,20 @@ err:
}
/*
+ * 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.
* Returns 0 on success or -1 for any errors.
@@ -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 <kristaps@bsd.lv>
*
@@ -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 <nils_fisher@hotmail.com>
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
@@ -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 <nils_fisher@hotmail.com>
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
@@ -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 <nils_fisher@hotmail.com>
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
@@ -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 <nils_fisher@hotmail.com>
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
@@ -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 *