[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