From 971e83ef9c284ff82fdeedb7851fed5b3386dd1a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 19 Jan 2011 13:22:50 -0500 Subject: [PATCH 1/2] Fix two more SIZE_T_CEILING issues This patch imposes (very long) limits on the length of a line in a directory document, and on the length of a certificate. I don't think it should actually be possible to overrun these remotely, since we already impose a maximum size on any directory object we're downloading, but a little defensive programming never hurt anybody. Roger emailed me that doorss reported these on IRC, but nobody seems to have put them on the bugtracker. --- changes/routerparse_maxima | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changes/routerparse_maxima diff --git a/changes/routerparse_maxima b/changes/routerparse_maxima new file mode 100644 index 0000000000..340f2c3c2d --- /dev/null +++ b/changes/routerparse_maxima @@ -0,0 +1,4 @@ + o Minor bugfixes + - Check for and reject overly long directory certificates and + directory tokens before they have a chance to hit any + assertions. Bugfix on 0.2.1.28. Found by doorss. From c8f94eed12c0a7e8226bdadcd26570e29152f299 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 19 Jan 2011 13:25:17 -0500 Subject: [PATCH 2/2] Oops; actually add the code to the last patch. :/ --- src/or/routerparse.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 3778509051..aa0687d883 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1583,6 +1583,10 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, authority_cert_t * authority_cert_parse_from_string(const char *s, const char **end_of_string) { + /** Reject any certificate at least this big; it is probably an overflow, an + * attack, a bug, or some other nonsense. */ +#define MAX_CERT_SIZE (128*1024) + authority_cert_t *cert = NULL, *old_cert; smartlist_t *tokens = NULL; char digest[DIGEST_LEN]; @@ -1609,6 +1613,12 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) ++eos; len = eos - s; + if (len > MAX_CERT_SIZE) { + log_warn(LD_DIR, "Certificate is far too big (at %lu bytes long); " + "rejecting", (unsigned long)len); + return NULL; + } + tokens = smartlist_create(); area = memarea_new(); if (tokenize_string(area,s, eos, tokens, dir_key_certificate_table, 0) < 0) { @@ -3024,6 +3034,9 @@ get_next_token(memarea_t *area, /** Reject any object at least this big; it is probably an overflow, an * attack, a bug, or some other nonsense. */ #define MAX_UNPARSED_OBJECT_SIZE (128*1024) + /** Reject any line at least this big; it is probably an overflow, an + * attack, a bug, or some other nonsense. */ +#define MAX_LINE_LENGTH (128*1024) const char *next, *eol, *obstart; size_t obname_len; @@ -3043,6 +3056,10 @@ get_next_token(memarea_t *area, eol = memchr(*s, '\n', eos-*s); if (!eol) eol = eos; + if (eol - *s > MAX_LINE_LENGTH) { + RET_ERR("Line far too long"); + } + next = find_whitespace_eos(*s, eol); if (!strcmp_len(*s, "opt", next-*s)) {