From: W.C.A. Wijngaards Date: Wed, 23 Jun 2021 12:05:59 +0000 (+0200) Subject: - Fix #503: DNS over HTTPS response truncated. X-Git-Tag: release-1.13.2rc1~141 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9d681b627fd874588afe60335b46c53ad3aebf67;p=thirdparty%2Funbound.git - Fix #503: DNS over HTTPS response truncated. --- diff --git a/doc/Changelog b/doc/Changelog index 645667296..9ac461e5a 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +23 June 2021: Wouter + - Fix #503: DNS over HTTPS response truncated. + 21 June 2021: George - Fix #495: Documentation or implementation of "verbosity" option. diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index ca40fac5c..52b0a2ee9 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -2678,18 +2678,45 @@ static int http2_buffer_uri_query(struct http2_session* h2_session, return 0; } - if(!(b64len = sldns_b64url_pton( - (char const *)start, length, - sldns_buffer_current(h2_stream->qbuffer), - expectb64len)) || b64len < 0) { - lock_basic_lock(&http2_query_buffer_count_lock); - http2_query_buffer_count -= expectb64len; - lock_basic_unlock(&http2_query_buffer_count_lock); - sldns_buffer_free(h2_stream->qbuffer); - h2_stream->qbuffer = NULL; - /* return without error, method can be an - * unknown POST */ - return 1; + if(sldns_b64_contains_nonurl((char const*)start, length)) { + char buf[65536+4]; + verbose(VERB_ALGO, "HTTP2 stream contains wrong b64 encoding"); + /* copy to the scratch buffer temporarily to terminate the + * string with a zero */ + if(length+1 > sizeof(buf)) { + /* too long */ + lock_basic_lock(&http2_query_buffer_count_lock); + http2_query_buffer_count -= expectb64len; + lock_basic_unlock(&http2_query_buffer_count_lock); + sldns_buffer_free(h2_stream->qbuffer); + h2_stream->qbuffer = NULL; + return 1; + } + memmove(buf, start, length); + buf[length] = 0; + if(!(b64len = sldns_b64_pton(buf, sldns_buffer_current( + h2_stream->qbuffer), expectb64len)) || b64len < 0) { + lock_basic_lock(&http2_query_buffer_count_lock); + http2_query_buffer_count -= expectb64len; + lock_basic_unlock(&http2_query_buffer_count_lock); + sldns_buffer_free(h2_stream->qbuffer); + h2_stream->qbuffer = NULL; + return 1; + } + } else { + if(!(b64len = sldns_b64url_pton( + (char const *)start, length, + sldns_buffer_current(h2_stream->qbuffer), + expectb64len)) || b64len < 0) { + lock_basic_lock(&http2_query_buffer_count_lock); + http2_query_buffer_count -= expectb64len; + lock_basic_unlock(&http2_query_buffer_count_lock); + sldns_buffer_free(h2_stream->qbuffer); + h2_stream->qbuffer = NULL; + /* return without error, method can be an + * unknown POST */ + return 1; + } } sldns_buffer_skip(h2_stream->qbuffer, (size_t)b64len); return 1; diff --git a/sldns/parseutil.c b/sldns/parseutil.c index 9f289d359..ba71df55d 100644 --- a/sldns/parseutil.c +++ b/sldns/parseutil.c @@ -790,3 +790,18 @@ int sldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target, } return sldns_b64_pton_base(src, srcsize, target, targsize, 1); } + +int sldns_b64_contains_nonurl(char const *src, size_t srcsize) +{ + const char* s = src; + while(*s && srcsize) { + char d = *s++; + srcsize--; + /* the '+' and the '/' and padding '=' is not allowed in b64 + * url encoding */ + if(d == '+' || d == '/' || d == '=') { + return 1; + } + } + return 0; +} diff --git a/sldns/parseutil.h b/sldns/parseutil.h index 7eb23317f..74d7c7275 100644 --- a/sldns/parseutil.h +++ b/sldns/parseutil.h @@ -102,6 +102,7 @@ size_t sldns_b64_pton_calculate_size(size_t srcsize); int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize); int sldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target, size_t targsize); +int sldns_b64_contains_nonurl(char const *src, size_t srcsize); /** * calculates the size needed to store the result of b32_ntop