Commit 1ab71cf1 authored by Asad Sajjad Ahmed's avatar Asad Sajjad Ahmed Committed by Dridi Boukelmoune

h2: the :scheme pseudo header is not optional

The :scheme pseudo header is not optional in H/2 except when doing CONNECT.
There is also a strict requirement for it appear only once.
Signed-off-by: 's avatarAsad Sajjad Ahmed <asadsa@varnish-software.com>

Conflicts:
	bin/varnishtest/tests/t02025.vtc
parent 2bf97ffa
......@@ -218,11 +218,14 @@ vtr_deliver_f h2_deliver;
vtr_minimal_response_f h2_minimal_response;
#endif /* TRANSPORT_MAGIC */
#define H2H_DECODE_FLAG_SCHEME_SEEN 0x1
/* http2/cache_http2_hpack.c */
struct h2h_decode {
unsigned magic;
#define H2H_DECODE_MAGIC 0xd092bde4
int flags;
h2_error error;
enum vhd_ret_e vhd_ret;
char *out;
......
......@@ -127,7 +127,7 @@ h2h_checkhdr(const struct http *hp, const char *b, size_t namelen, size_t len)
}
static h2_error
h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len)
h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len, int *flags)
{
/* XXX: This might belong in cache/cache_http.c */
const char *b0;
......@@ -188,9 +188,18 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len)
/* XXX: What to do about this one? (typically
"http" or "https"). For now set it as a normal
header, stripping the first ':'. */
if (*flags & H2H_DECODE_FLAG_SCHEME_SEEN) {
VSLb(hp->vsl, SLT_BogoHeader,
"Duplicate pseudo-header %.*s%.*s",
(int)namelen, b0,
(int)(len > 20 ? 20 : len), b);
return (H2SE_PROTOCOL_ERROR);
}
b++;
len-=1;
n = hp->nhd;
*flags |= H2H_DECODE_FLAG_SCHEME_SEEN;
for (p = b + namelen, u = 0; u < len-namelen;
p++, u++) {
......@@ -380,7 +389,8 @@ h2h_decode_bytes(struct h2_sess *h2, const uint8_t *in, size_t in_l)
d->out_u);
if (d->error)
break;
d->error = h2h_addhdr(hp, d->out, d->namelen, d->out_u);
d->error = h2h_addhdr(hp, d->out, d->namelen, d->out_u,
&d->flags);
if (d->error)
break;
d->out[d->out_u++] = '\0'; /* Zero guard */
......
......@@ -601,11 +601,13 @@ static h2_error
h2_end_headers(struct worker *wrk, struct h2_sess *h2,
struct req *req, struct h2_req *r2)
{
int scheme_seen;
h2_error h2e;
ssize_t cl;
ASSERT_RXTHR(h2);
assert(r2->state == H2_S_OPEN);
scheme_seen = h2->decode->flags & H2H_DECODE_FLAG_SCHEME_SEEN;
h2e = h2h_decode_fini(h2);
h2->new_req = NULL;
if (h2e != NULL) {
......@@ -656,10 +658,17 @@ h2_end_headers(struct worker *wrk, struct h2_sess *h2,
VSLb(h2->vsl, SLT_Debug, "Missing :method");
return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3087,3090
}
if (req->http->hd[HTTP_HDR_URL].b == NULL) {
VSLb(h2->vsl, SLT_Debug, "Missing :path");
return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3087,3090
}
if (!(scheme_seen)) {
VSLb(h2->vsl, SLT_Debug, "Missing :scheme");
return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3087,3090
}
AN(req->http->hd[HTTP_HDR_PROTO].b);
if (*req->http->hd[HTTP_HDR_URL].b == '*' &&
......
varnishtest "Dublicate pseudo-headers"
server s1 {
rxreq
txresp
} -start
varnish v1 -arg "-p feature=+http2" -vcl+backend {
} -start
#client c1 {
# txreq -url "/some/path" -url "/some/other/path"
# rxresp
# expect resp.status == 400
#} -run
#client c1 {
# txreq -req "GET" -req "POST"
# rxresp
# expect resp.status == 400
#} -run
#client c1 {
# txreq -proto "HTTP/1.1" -proto "HTTP/2.0"
# rxresp
# expect resp.status == 400
#} -run
client c1 {
stream 1 {
txreq -url "/some/path" -url "/some/other/path"
rxrst
} -run
} -run
client c1 {
stream 1 {
txreq -scheme "http" -scheme "https"
rxrst
} -run
} -run
client c1 {
stream 1 {
txreq -req "GET" -req "POST"
rxrst
} -run
} -run
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment