Commit 0f2060c5 authored by Dridi Boukelmoune's avatar Dridi Boukelmoune

h2: Manage missing :scheme as a custom error

There is room for further improvement in the dynamic between HPACK and
the HTTP/2 session, but this will serve as the first step.

Conflicts:
	include/tbl/h2_error.h
parent 33df4b37
...@@ -222,14 +222,12 @@ vtr_deliver_f h2_deliver; ...@@ -222,14 +222,12 @@ vtr_deliver_f h2_deliver;
vtr_minimal_response_f h2_minimal_response; vtr_minimal_response_f h2_minimal_response;
#endif /* TRANSPORT_MAGIC */ #endif /* TRANSPORT_MAGIC */
#define H2H_DECODE_FLAG_SCHEME_SEEN 0x1
/* http2/cache_http2_hpack.c */ /* http2/cache_http2_hpack.c */
struct h2h_decode { struct h2h_decode {
unsigned magic; unsigned magic;
#define H2H_DECODE_MAGIC 0xd092bde4 #define H2H_DECODE_MAGIC 0xd092bde4
int flags; unsigned has_scheme:1;
h2_error error; h2_error error;
enum vhd_ret_e vhd_ret; enum vhd_ret_e vhd_ret;
char *out; char *out;
......
...@@ -127,7 +127,8 @@ h2h_checkhdr(const struct http *hp, const char *b, size_t namelen, size_t len) ...@@ -127,7 +127,8 @@ h2h_checkhdr(const struct http *hp, const char *b, size_t namelen, size_t len)
} }
static h2_error static h2_error
h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len, int *flags) h2h_addhdr(struct h2h_decode *d, struct http *hp, char *b, size_t namelen,
size_t len)
{ {
/* XXX: This might belong in cache/cache_http.c */ /* XXX: This might belong in cache/cache_http.c */
const char *b0; const char *b0;
...@@ -188,7 +189,7 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len, int *flags) ...@@ -188,7 +189,7 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len, int *flags)
/* XXX: What to do about this one? (typically /* XXX: What to do about this one? (typically
"http" or "https"). For now set it as a normal "http" or "https"). For now set it as a normal
header, stripping the first ':'. */ header, stripping the first ':'. */
if (*flags & H2H_DECODE_FLAG_SCHEME_SEEN) { if (d->has_scheme) {
VSLb(hp->vsl, SLT_BogoHeader, VSLb(hp->vsl, SLT_BogoHeader,
"Duplicate pseudo-header %.*s%.*s", "Duplicate pseudo-header %.*s%.*s",
(int)namelen, b0, (int)namelen, b0,
...@@ -199,7 +200,7 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len, int *flags) ...@@ -199,7 +200,7 @@ h2h_addhdr(struct http *hp, char *b, size_t namelen, size_t len, int *flags)
b++; b++;
len-=1; len-=1;
n = hp->nhd; n = hp->nhd;
*flags |= H2H_DECODE_FLAG_SCHEME_SEEN; d->has_scheme = 1;
for (p = b + namelen, u = 0; u < len-namelen; for (p = b + namelen, u = 0; u < len-namelen;
p++, u++) { p++, u++) {
...@@ -302,6 +303,9 @@ h2h_decode_fini(const struct h2_sess *h2) ...@@ -302,6 +303,9 @@ h2h_decode_fini(const struct h2_sess *h2)
VSLb(h2->new_req->http->vsl, SLT_BogoHeader, VSLb(h2->new_req->http->vsl, SLT_BogoHeader,
"HPACK compression error/fini (%s)", VHD_Error(d->vhd_ret)); "HPACK compression error/fini (%s)", VHD_Error(d->vhd_ret));
ret = H2CE_COMPRESSION_ERROR; ret = H2CE_COMPRESSION_ERROR;
} else if (d->error == NULL && !d->has_scheme) {
VSLb(h2->vsl, SLT_Debug, "Missing :scheme");
ret = H2SE_MISSING_SCHEME; //rfc7540,l,3087,3090
} else } else
ret = d->error; ret = d->error;
FINI_OBJ(d); FINI_OBJ(d);
...@@ -389,8 +393,8 @@ h2h_decode_bytes(struct h2_sess *h2, const uint8_t *in, size_t in_l) ...@@ -389,8 +393,8 @@ h2h_decode_bytes(struct h2_sess *h2, const uint8_t *in, size_t in_l)
d->out_u); d->out_u);
if (d->error) if (d->error)
break; break;
d->error = h2h_addhdr(hp, d->out, d->namelen, d->out_u, d->error = h2h_addhdr(d, hp, d->out,
&d->flags); d->namelen, d->out_u);
if (d->error) if (d->error)
break; break;
d->out[d->out_u++] = '\0'; /* Zero guard */ d->out[d->out_u++] = '\0'; /* Zero guard */
......
...@@ -627,13 +627,11 @@ static h2_error ...@@ -627,13 +627,11 @@ static h2_error
h2_end_headers(struct worker *wrk, struct h2_sess *h2, h2_end_headers(struct worker *wrk, struct h2_sess *h2,
struct req *req, struct h2_req *r2) struct req *req, struct h2_req *r2)
{ {
int scheme_seen;
h2_error h2e; h2_error h2e;
ssize_t cl; ssize_t cl;
ASSERT_RXTHR(h2); ASSERT_RXTHR(h2);
assert(r2->state == H2_S_OPEN); assert(r2->state == H2_S_OPEN);
scheme_seen = h2->decode->flags & H2H_DECODE_FLAG_SCHEME_SEEN;
h2e = h2h_decode_fini(h2); h2e = h2h_decode_fini(h2);
h2->new_req = NULL; h2->new_req = NULL;
if (h2e != NULL) { if (h2e != NULL) {
...@@ -690,11 +688,6 @@ h2_end_headers(struct worker *wrk, struct h2_sess *h2, ...@@ -690,11 +688,6 @@ h2_end_headers(struct worker *wrk, struct h2_sess *h2,
return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3087,3090 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); AN(req->http->hd[HTTP_HDR_PROTO].b);
if (*req->http->hd[HTTP_HDR_URL].b == '*' && if (*req->http->hd[HTTP_HDR_URL].b == '*' &&
......
...@@ -171,6 +171,15 @@ H2_ERROR( ...@@ -171,6 +171,15 @@ H2_ERROR(
/* descr */ "http/2 rapid reset detected" /* descr */ "http/2 rapid reset detected"
) )
H2_ERROR(
/* name */ MISSING_SCHEME,
/* val */ 1, /* PROTOCOL_ERROR */
/* types */ 2,
/* goaway */ 1,
/* reason */ SC_NULL,
/* descr */ "Missing :scheme pseudo-header"
)
H2_ERROR( H2_ERROR(
/* name */ BROKE_WINDOW, /* name */ BROKE_WINDOW,
/* val */ 8, /* CANCEL */ /* val */ 8, /* CANCEL */
......
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