[master] 6fa596b Fail (400) on both buplicate Host: and Content-Length: headers

Poul-Henning Kamp phk at FreeBSD.org
Tue Sep 9 10:02:41 CEST 2014


commit 6fa596b91fc6d09a5dab29eb77ee571465e72280
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Sep 9 08:02:10 2014 +0000

    Fail (400) on both buplicate Host: and Content-Length: headers

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index c006ca6..59d8703 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -959,11 +959,11 @@ int http_IsStatus(const struct http *hp, int);
 void http_SetStatus(struct http *to, uint16_t status);
 const char *http_GetReq(const struct http *hp);
 int http_HdrIs(const struct http *hp, const char *hdr, const char *val);
-int http_IsHdr(const txt *hh, const char *hdr);
 void http_CopyHome(const struct http *hp);
 void http_Unset(struct http *hp, const char *hdr);
 void http_MarkHeader(const struct http *, const char *hdr, unsigned hdrlen,
     uint8_t flag);
+unsigned http_CountHdr(const struct http *hp, const char *hdr);
 void http_CollectHdr(struct http *hp, const char *hdr);
 void http_VSL_log(const struct http *hp);
 void HTTP_Merge(struct objcore *, struct dstat *, struct http *to);
diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index 7e2474c..17212a9 100644
--- a/bin/varnishd/cache/cache_http.c
+++ b/bin/varnishd/cache/cache_http.c
@@ -230,7 +230,7 @@ http_PutField(const struct http *to, int field, const char *string)
 
 /*--------------------------------------------------------------------*/
 
-int
+static int
 http_IsHdr(const txt *hh, const char *hdr)
 {
 	unsigned l;
@@ -282,6 +282,26 @@ http_MarkHeader(const struct http *hp, const char *hdr, unsigned hdrlen,
 }
 
 /*--------------------------------------------------------------------
+ * Count how many instances we have of this header
+ */
+
+unsigned
+http_CountHdr(const struct http *hp, const char *hdr)
+{
+	unsigned retval = 0;
+	unsigned u;
+
+	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
+
+	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
+		Tcheck(hp->hd[u]);
+		if (http_IsHdr(&hp->hd[u], hdr))
+			retval++;
+	}
+	return (retval);
+}
+
+/*--------------------------------------------------------------------
  * This function collapses multiple headerlines of the same name.
  * The lines are joined with a comma, according to [rfc2616, 4.2bot, p32]
  */
diff --git a/bin/varnishd/cache/cache_http1_proto.c b/bin/varnishd/cache/cache_http1_proto.c
index ab01b35..fc98f47 100644
--- a/bin/varnishd/cache/cache_http1_proto.c
+++ b/bin/varnishd/cache/cache_http1_proto.c
@@ -426,31 +426,6 @@ http1_body_status(const struct http *hp, struct http_conn *htc)
 
 /*--------------------------------------------------------------------*/
 
-static uint16_t
-http1_request_check_host_hdr(const struct http *hp)
-{
-	int u;
-	int seen_host = 0;
-
-	for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
-		if (hp->hd[u].b == NULL)
-			continue;
-		AN(hp->hd[u].b);
-		AN(hp->hd[u].e);
-		if (http_IsHdr(&hp->hd[u], H_Host)) {
-			if (seen_host) {
-				VSLb(hp->vsl, SLT_Error,
-				    "Duplicated Host header");
-				return (400);
-			}
-			seen_host = 1;
-		}
-	}
-	return (0);
-}
-
-/*--------------------------------------------------------------------*/
-
 static void
 http1_proto_ver(struct http *hp)
 {
@@ -519,9 +494,11 @@ HTTP1_DissectRequest(struct http_conn *htc, struct http *hp)
 		return (retval);
 	http1_proto_ver(hp);
 
-	retval = http1_request_check_host_hdr(hp);
-	if (retval != 0)
-		return (retval);
+	if (http_CountHdr(hp, H_Host) > 1)
+		return (400);
+
+	if (http_CountHdr(hp, H_Content_Length) > 1)
+		return (400);
 
 	/* RFC2616, section 5.2, point 1 */
 	if (!strncasecmp(hp->hd[HTTP_HDR_URL].b, "http://", 7)) {
diff --git a/bin/varnishtest/tests/b00037.vtc b/bin/varnishtest/tests/b00037.vtc
index 848bdd4..7112cff 100644
--- a/bin/varnishtest/tests/b00037.vtc
+++ b/bin/varnishtest/tests/b00037.vtc
@@ -10,6 +10,16 @@ varnish v1 -vcl+backend {
 
 client c1 {
 	txreq -hdr "Host: foo" -hdr "Host: bar"
+	rxresp
+	expect resp.status == 400
 } -run
 
 varnish v1 -expect client_req_400 == 1
+
+client c1 {
+	txreq -hdr "Content-Length: 12" -bodylen 12
+	rxresp
+	expect resp.status == 400
+} -run
+
+varnish v1 -expect client_req_400 == 2
diff --git a/bin/varnishtest/tests/r00102.vtc b/bin/varnishtest/tests/r00102.vtc
index cf8a1bb..b8b56b3 100644
--- a/bin/varnishtest/tests/r00102.vtc
+++ b/bin/varnishtest/tests/r00102.vtc
@@ -17,14 +17,12 @@ varnish v1 -vcl+backend {
 
 client c1 {
 	txreq -req POST -url "/" \
-		-hdr "Content-Length: 10" \
 		-body "123456789\n"
 	rxresp
 	expect resp.status == 200
 	expect resp.http.X-Varnish == "1001"
 
 	txreq -req POST -url "/" \
-		-hdr "Content-Length: 10" \
 		-body "123456789\n"
 	rxresp
 	expect resp.status == 200



More information about the varnish-commit mailing list