]> 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)
committerAmos Jeffries <yadij@users.noreply.github.com>
Sun, 18 Aug 2019 08:25:41 +0000 (20:25 +1200)
src/client_side.cc
src/http/one/Parser.cc
src/http/one/Parser.h

index ba1006dce3d99f8f58d313d0f57c5b34b66ab287..7c0121a56525f128e6887ce70994bbe5fc3cf2d4 100644 (file)
@@ -1142,7 +1142,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) {
@@ -1198,7 +1198,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 069bdacee0a05596ccad33d0386795a816b7a753..c51ebe081d06fc0a1de14046a2eb64a414a043dd 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 a5b0e154a67a7a220355d1d2cc936149ae85dc6b..046a96f3b19150ab4bc3d59c56da3271ee0a39c4 100644 (file)
@@ -78,7 +78,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.
      *
@@ -86,7 +86,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_;}