Repository: trafficserver Updated Branches: refs/heads/master 631763c42 -> 1e5d1732f
TS-1570: remap doesn't reject request with invalid characters after port Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/0c9fb914 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/0c9fb914 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/0c9fb914 Branch: refs/heads/master Commit: 0c9fb914fd1893dbed7df55cb1782aeaca495be3 Parents: 631763c Author: Cynthia Gu <czhen...@linkedin.com> Authored: Mon Dec 8 13:47:37 2014 -0800 Committer: Brian Geffon <bri...@apache.org> Committed: Mon Dec 8 13:47:37 2014 -0800 ---------------------------------------------------------------------- lib/ts/TsBuffer.h | 2 +- lib/ts/ink_inet.cc | 44 ++++++++++++++++++++++++++------------------ lib/ts/ink_inet.h | 3 ++- proxy/hdrs/HTTP.cc | 38 +++++++++++++++++++++++++++++++++++++- proxy/hdrs/HTTP.h | 1 + 5 files changed, 67 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0c9fb914/lib/ts/TsBuffer.h ---------------------------------------------------------------------- diff --git a/lib/ts/TsBuffer.h b/lib/ts/TsBuffer.h index d4fac87..006c821 100644 --- a/lib/ts/TsBuffer.h +++ b/lib/ts/TsBuffer.h @@ -246,7 +246,7 @@ namespace ts { This is convenient when tokenizing and @a p points at the token separator. - @note If @a *p is in the buffer then @a this is not changed + @note If @a *p is not in the buffer then @a this is not changed and an empty buffer is returned. This means the caller can simply pass the result of @c find and check for an empty buffer returned to detect no more separators. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0c9fb914/lib/ts/ink_inet.cc ---------------------------------------------------------------------- diff --git a/lib/ts/ink_inet.cc b/lib/ts/ink_inet.cc index a841a76..de874ff 100644 --- a/lib/ts/ink_inet.cc +++ b/lib/ts/ink_inet.cc @@ -193,17 +193,19 @@ char const* ats_ip_nptop( } int -ats_ip_parse(ts::ConstBuffer src, ts::ConstBuffer* addr, ts::ConstBuffer* port) { +ats_ip_parse(ts::ConstBuffer src, ts::ConstBuffer* addr, ts::ConstBuffer* port, ts::ConstBuffer* rest) { // In case the incoming arguments are null. ts::ConstBuffer localAddr, localPort; if (!addr) addr = &localAddr; if (!port) port = &localPort; addr->reset(); port->reset(); + if (rest) rest->reset(); // Let's see if we can find out what's in the address string. if (src) { - while (src && isspace(*src)) ++src; + bool colon_p = false; + while (src && ParseRules::is_ws(*src)) ++src; // Check for brackets. if ('[' == *src) { /* Ugly. In a number of places we must use bracket notation @@ -222,25 +224,31 @@ ats_ip_parse(ts::ConstBuffer src, ts::ConstBuffer* addr, ts::ConstBuffer* port) */ ++src; // skip bracket. *addr = src.splitOn(']'); - if (*addr && ':' == *src) { // found the closing bracket and port colon - ++src; // skip colon. - *port = src; - } // else it's a fail for unclosed brackets. + if (':' == *src) { + colon_p = true; + ++src; + } } else { - // See if there's exactly 1 colon - ts::ConstBuffer tmp = src.after(':'); - if (tmp && ! tmp.find(':')) { // 1 colon and no others - src.clip(tmp.data() - 1); // drop port from address. - *port = tmp; - } // else 0 or > 1 colon and no brackets means no port. - *addr = src; + *addr = src.splitOn(':'); + if (*addr) { + colon_p = true; + } else { // no colon found, use everything. + *addr = src; + src.reset(); + } } - // clip port down to digits. - if (*port) { - char const* spot = port->data(); - while (isdigit(*spot)) ++spot; - port->clip(spot); + if (colon_p) { + ts::ConstBuffer tmp(src); + while (ParseRules::is_digit(*src)) + ++src; + + if (tmp.data() == src.data()) { // no digits at all + src.set(tmp.data()-1, tmp.size()+1); // back up to include colon + } else { + *port = tmp.clip(src.data()); + } } + if (rest) *rest = src; } return *addr ? 0 : -1; // true if we found an address. } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0c9fb914/lib/ts/ink_inet.h ---------------------------------------------------------------------- diff --git a/lib/ts/ink_inet.h b/lib/ts/ink_inet.h index 9181f38..388ce3c 100644 --- a/lib/ts/ink_inet.h +++ b/lib/ts/ink_inet.h @@ -165,7 +165,8 @@ int ats_ip_parse( ts::ConstBuffer src, ///< [in] String to search. ts::ConstBuffer* addr, ///< [out] Range containing IP address. - ts::ConstBuffer* port ///< [out] Range containing port. + ts::ConstBuffer* port, ///< [out] Range containing port. + ts::ConstBuffer* rest = 0 ///< [out] Remnant past the addr/port if any. ); /** Check to see if a buffer contains only IP address characters. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0c9fb914/proxy/hdrs/HTTP.cc ---------------------------------------------------------------------- diff --git a/proxy/hdrs/HTTP.cc b/proxy/hdrs/HTTP.cc index ce28ba7..aab1228 100644 --- a/proxy/hdrs/HTTP.cc +++ b/proxy/hdrs/HTTP.cc @@ -952,7 +952,9 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const if (version == HTTP_VERSION(0, 9)) return PARSE_DONE; - return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof); + MIMEParseResult ret = mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof); + if (ret == PARSE_DONE) ret = validate_hdr_host(hh); // if we're done with the main parse, check HOST. + return ret; } #endif @@ -972,6 +974,7 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const goto start; parse_method1: + if (ParseRules::is_ws(*cur)) { GETNEXT(done); goto parse_method1; @@ -1089,11 +1092,44 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const parser->m_parsing_http = false; if (version == HTTP_VERSION(0, 9)) return PARSE_DONE; + + MIMEParseResult ret = mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof); + if (ret == PARSE_DONE) ret = validate_hdr_host(hh); // if we're done with the main parse, check HOST. + return ret; } return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof); } +MIMEParseResult +validate_hdr_host(HTTPHdrImpl* hh) { + MIMEParseResult ret = PARSE_DONE; + MIMEField* host_field = mime_hdr_field_find(hh->m_fields_impl, MIME_FIELD_HOST, MIME_LEN_HOST); + if (host_field) { + if (host_field->has_dups()) { + ret = PARSE_ERROR; // can't have more than 1 host field. + } else { + int host_len = 0; + char const* host_val = host_field->value_get(&host_len); + ts::ConstBuffer addr, port, rest, host(host_val, host_len); + if (0 == ats_ip_parse(host, &addr, &port, &rest)) { + if (port) { + if (port.size() > 5) return PARSE_ERROR; + int port_i = ink_atoi(port.data(), port.size()); + if ( port.size() > 5 || port_i >= 65536 || port_i <= 0) return PARSE_ERROR; + } + while (rest && PARSE_DONE == ret) { + if (!ParseRules::is_ws(*rest)) return PARSE_ERROR; + ++rest; + } + } else { + ret = PARSE_ERROR; + } + } + } + return ret; +} + /*------------------------------------------------------------------------- -------------------------------------------------------------------------*/ http://git-wip-us.apache.org/repos/asf/trafficserver/blob/0c9fb914/proxy/hdrs/HTTP.h ---------------------------------------------------------------------- diff --git a/proxy/hdrs/HTTP.h b/proxy/hdrs/HTTP.h index f9175e5..00a9c78 100644 --- a/proxy/hdrs/HTTP.h +++ b/proxy/hdrs/HTTP.h @@ -467,6 +467,7 @@ void http_parser_clear(HTTPParser *parser); MIMEParseResult http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end, bool must_copy_strings, bool eof); +MIMEParseResult validate_hdr_host(HTTPHdrImpl* hh); MIMEParseResult http_parser_parse_resp(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end, bool must_copy_strings, bool eof);