From: Amos Jeffries Date: Tue, 13 Aug 2019 13:50:06 +0000 (+0000) Subject: Ignore malformed Host header in intercept and reverse proxy mode (#456) X-Git-Tag: SQUID_5_0_1~55 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2a51e34e92092b7409a5fe51b8df4792e8748ab8;p=thirdparty%2Fsquid.git Ignore malformed Host header in intercept and reverse proxy mode (#456) --- diff --git a/src/client_side.cc b/src/client_side.cc index 818d5b4643..f47c25d675 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1145,7 +1145,7 @@ prepareAcceleratedURL(ConnStateData * conn, const Http1::RequestParserPointer &h vport = conn->clientConnection->local.port(); char *host = NULL; - if (vhost && (host = hp->getHeaderField("Host"))) { + if (vhost && (host = hp->getHostHeaderField())) { debugs(33, 5, "ACCEL VHOST REWRITE: vhost=" << host << " + vport=" << vport); char thost[256]; if (vport > 0) { @@ -1201,7 +1201,7 @@ buildUrlFromHost(ConnStateData * conn, const Http1::RequestParserPointer &hp) { char *uri = nullptr; /* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */ - if (const char *host = hp->getHeaderField("Host")) { + if (const char *host = hp->getHostHeaderField()) { const SBuf &scheme = AnyP::UriScheme(conn->transferProtocol.protocol).image(); const int url_sz = scheme.length() + strlen(host) + hp->requestUri().length() + 32; uri = static_cast(xcalloc(url_sz, 1)); diff --git a/src/http/one/Parser.cc b/src/http/one/Parser.cc index 8b262a99dc..f3444d71c0 100644 --- a/src/http/one/Parser.cc +++ b/src/http/one/Parser.cc @@ -210,18 +210,19 @@ Http::One::Parser::grabMimeBlock(const char *which, const size_t limit) return true; } -// arbitrary maximum-length for headers which can be found by Http1Parser::getHeaderField() +// arbitrary maximum-length for headers which can be found by Http1Parser::getHostHeaderField() #define GET_HDR_SZ 1024 // BUG: returns only the first header line with given name, // ignores multi-line headers and obs-fold headers char * -Http::One::Parser::getHeaderField(const char *name) +Http::One::Parser::getHostHeaderField() { - if (!headerBlockSize() || !name) + if (!headerBlockSize()) return NULL; LOCAL_ARRAY(char, header, GET_HDR_SZ); + const char *name = "Host"; const int namelen = strlen(name); debugs(25, 5, "looking for " << name); @@ -256,6 +257,11 @@ Http::One::Parser::getHeaderField(const char *name) // prevent buffer overrun on char header[]; p.chop(0, sizeof(header)-1); + // currently only used for pre-parse Host header, ensure valid domain[:port] or ip[:port] + static const auto hostChars = CharacterSet("host",":[].-_") + CharacterSet::ALPHA + CharacterSet::DIGIT; + if (p.findFirstNotOf(hostChars) != SBuf::npos) + break; // error. line contains character not accepted in Host header + // return the header field-value SBufToCstring(header, p); debugs(25, 5, "returning " << header); diff --git a/src/http/one/Parser.h b/src/http/one/Parser.h index f449e8334c..24b0ec549a 100644 --- a/src/http/one/Parser.h +++ b/src/http/one/Parser.h @@ -84,7 +84,7 @@ public: const AnyP::ProtocolVersion & messageProtocol() const {return msgProtocol_;} /** - * Scan the mime header block (badly) for a header with the given name. + * Scan the mime header block (badly) for a Host header. * * BUG: omits lines when searching for headers with obs-fold or multiple entries. * @@ -92,7 +92,7 @@ public: * * \return A pointer to a field-value of the first matching field-name, or NULL. */ - char *getHeaderField(const char *name); + char *getHostHeaderField(); /// the remaining unprocessed section of buffer const SBuf &remaining() const {return buf_;}