]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Ignore malformed Host header in intercept and reverse proxy mode (#456)
authorAmos Jeffries <yadij@users.noreply.github.com>
Tue, 13 Aug 2019 13:50:06 +0000 (13:50 +0000)
committerSquid Anubis <squid-anubis@squid-cache.org>
Tue, 13 Aug 2019 13:50:10 +0000 (13:50 +0000)
src/client_side.cc
src/http/one/Parser.cc
src/http/one/Parser.h

index 818d5b4643375b11c41cb32247c8b55a7d3198dc..f47c25d6752592d1c743f7fcb225fabc08c5c552 100644 (file)
@@ -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<char *>(xcalloc(url_sz, 1));
index 8b262a99dc724d4bd6c5ad0f3c0a3bac94709d49..f3444d71c01967430f14dfd2d5a2c26fe321095e 100644 (file)
@@ -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);
index f449e8334c0280eb1b6dc41914ed1b8a3623fbf9..24b0ec549a2e7d48ee71ed0e1299cb5d1d96aa7e 100644 (file)
@@ -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_;}