Skip to content

Commit

Permalink
Fix unit tests.
Browse files Browse the repository at this point in the history
- Rename `__extract_request_authority` and move it to
 `http_parser.c` as a not static function, to have ability
 to use it in unit tests.

- Fix unit tests according to changes in `match_host`
  function.
  • Loading branch information
EvgeniiMekhanik committed May 24, 2023
1 parent 46df8b4 commit 5b0caf5
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 45 deletions.
35 changes: 1 addition & 34 deletions fw/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -5615,39 +5615,6 @@ tfw_h1_req_process(TfwStream *stream, struct sk_buff *skb)
return hmsib;
}

static void
__extract_request_authority(TfwHttpReq *req)
{
int hid = 0;
TfwStr *hdrs = req->h_tbl->tbl;

if (TFW_MSG_H2(req)) {
/* RFC 9113, sec-8.3.1:
* The recipient of an HTTP/2 request MUST NOT use
* the Host header field to determine the target
* URI if ":authority" is present.*/
if (!TFW_STR_EMPTY(&hdrs[TFW_HTTP_HDR_H2_AUTHORITY]))
hid = TFW_HTTP_HDR_H2_AUTHORITY;
else
hid = TFW_HTTP_HDR_HOST;
__h2_msg_hdr_val(&hdrs[hid], &req->host);
} else {
/* req->host can be only filled by HTTP/1.x parser from
* absoluteURI, so we act as described by RFC 9112, sec-3.2.2
* (https://www.rfc-editor.org/rfc/rfc9112.html#section-3.2.2):
* When an origin server receives a request with an
* absolute-form of request-target, the origin server
* MUST ignore the received Host header field (if any)
* and instead use the host information of the request-target.
*/
if (TFW_STR_EMPTY(&req->host)) {
tfw_http_msg_clnthdr_val(req, &hdrs[TFW_HTTP_HDR_HOST],
TFW_HTTP_HDR_HOST,
&req->host);
}
}
}

static bool
__check_authority_correctness(TfwHttpReq *req)
{
Expand All @@ -5671,7 +5638,7 @@ __check_authority_correctness(TfwHttpReq *req)
static int
tfw_http_req_process_authority_host(TfwHttpReq *req)
{
__extract_request_authority(req);
tfw_http_set_req_host(req);

if (!__check_authority_correctness(req)) {
tfw_http_req_parse_drop(req, 400, "Invalid authority");
Expand Down
33 changes: 33 additions & 0 deletions fw/http_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -12583,3 +12583,36 @@ tfw_http_parse_is_done(TfwHttpMsg *hm)
{
return test_bit(TFW_HTTP_B_FULLY_PARSED, hm->flags);
}

void
tfw_http_set_req_host(TfwHttpReq *req)
{
int hid = 0;
TfwStr *hdrs = req->h_tbl->tbl;

if (TFW_MSG_H2(req)) {
/* RFC 9113, sec-8.3.1:
* The recipient of an HTTP/2 request MUST NOT use
* the Host header field to determine the target
* URI if ":authority" is present.*/
if (!TFW_STR_EMPTY(&hdrs[TFW_HTTP_HDR_H2_AUTHORITY]))
hid = TFW_HTTP_HDR_H2_AUTHORITY;
else
hid = TFW_HTTP_HDR_HOST;
__h2_msg_hdr_val(&hdrs[hid], &req->host);
} else {
/* req->host can be only filled by HTTP/1.x parser from
* absoluteURI, so we act as described by RFC 9112, sec-3.2.2
* (https://www.rfc-editor.org/rfc/rfc9112.html#section-3.2.2):
* When an origin server receives a request with an
* absolute-form of request-target, the origin server
* MUST ignore the received Host header field (if any)
* and instead use the host information of the request-target.
*/
if (TFW_STR_EMPTY(&req->host)) {
tfw_http_msg_clnthdr_val(req, &hdrs[TFW_HTTP_HDR_HOST],
TFW_HTTP_HDR_HOST,
&req->host);
}
}
}
1 change: 1 addition & 0 deletions fw/http_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,5 @@ int h2_set_hdr_if_mod_since(TfwHttpReq *req, const TfwCachedHeaderState *cstate)
void h2_set_hdr_authority(TfwHttpReq *req, const TfwCachedHeaderState *cstate);
void h2_set_hdr_if_nmatch(TfwHttpReq *req, const TfwCachedHeaderState *cstate);
unsigned char tfw_http_meth_str2id(const TfwStr *m_hdr);
void tfw_http_set_req_host(TfwHttpReq *req);
#endif /* __TFW_HTTP_PARSER_H__ */
54 changes: 43 additions & 11 deletions fw/t/unit/test_http_match.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ test_chain_match(void)
static void
set_tfw_str(TfwStr *str, const char *cstr)
{
memset(str, 0, sizeof(TfwStr));
str->data = (void *)cstr;
str->len = strlen(cstr);
}
Expand Down Expand Up @@ -769,9 +770,36 @@ TEST(http_match, choose_host)
int match_id;

/* Special headers must be compound */
TFW_STR2(hdr1, "Host: ", "example.eu");
TFW_STR2(hdr2, "Host: ", "example.de");
TFW_STR2(hdr3, "Host: ", "example.net");
TfwStr hdr1 = {
.chunks = (TfwStr []) {
{ .data = "Host:" , .len = 5 },
{ .data = "example.eu", .len = 10,
.flags = TFW_STR_HDR_VALUE | TFW_STR_VALUE },
},
.len = 15,
.nchunks = 2
};

TfwStr hdr2 = {
.chunks = (TfwStr []) {
{ .data = "Host:" , .len = 5 },
{ .data = "example.de", .len = 10,
.flags = TFW_STR_HDR_VALUE | TFW_STR_VALUE },
},
.len = 15,
.nchunks = 2
};

TfwStr hdr3 = {
.chunks = (TfwStr []) {
{ .data = "Host:" , .len = 5 },
{ .data = "example.net", .len = 11,
.flags = TFW_STR_HDR_VALUE | TFW_STR_VALUE },
},
.len = 16,
.nchunks = 2
};

TfwStr hdr4 = {
.chunks = (TfwStr []) {
{ .data = "Forwarded:" , .len = 10 },
Expand Down Expand Up @@ -808,7 +836,6 @@ TEST(http_match, choose_host)
/* Host not specified. */
match_id = test_chain_match();
EXPECT_EQ(-1, match_id);

/* Host specified by URI. */
set_tfw_str(&test_req->host, "example.com");
match_id = test_chain_match();
Expand All @@ -818,13 +845,15 @@ TEST(http_match, choose_host)
* Host specified by URI and Host header
* host from uri must be matched.
*/
test_req->h_tbl->tbl[TFW_HTTP_HDR_HOST] = *hdr1;
test_req->h_tbl->tbl[TFW_HTTP_HDR_HOST] = hdr1;
tfw_http_set_req_host(test_req);
match_id = test_chain_match();
EXPECT_EQ(1, match_id);

/* Host specified by Host header */
set_tfw_str(&test_req->host, "");
test_req->h_tbl->tbl[TFW_HTTP_HDR_HOST] = *hdr1;
test_req->h_tbl->tbl[TFW_HTTP_HDR_HOST] = hdr1;
tfw_http_set_req_host(test_req);
match_id = test_chain_match();
EXPECT_EQ(2, match_id);

Expand All @@ -833,20 +862,22 @@ TEST(http_match, choose_host)
* and URI. Host from uri must be matched.
*/
set_tfw_str(&test_req->host, "example.com");
test_req->h_tbl->tbl[TFW_HTTP_HDR_HOST] = *hdr1;
test_req->h_tbl->tbl[TFW_HTTP_HDR_HOST] = hdr1;
test_req->h_tbl->tbl[TFW_HTTP_HDR_FORWARDED] = hdr4;
tfw_http_set_req_host(test_req);
match_id = test_chain_match();
EXPECT_EQ(1, match_id);

/*
* Host specified by Host and Forwarded headers.
* Host from Forwarded header must be matched.
* Host from Forwarded header must NOT be matched.
*/
set_tfw_str(&test_req->host, "");
test_req->h_tbl->tbl[TFW_HTTP_HDR_HOST] = *hdr2;
test_req->h_tbl->tbl[TFW_HTTP_HDR_HOST] = hdr2;
test_req->h_tbl->tbl[TFW_HTTP_HDR_FORWARDED] = hdr4;
tfw_http_set_req_host(test_req);
match_id = test_chain_match();
EXPECT_EQ(3, match_id);
EXPECT_EQ(-1, match_id);

/*
* HTTP2!
Expand All @@ -856,8 +887,9 @@ TEST(http_match, choose_host)
__set_bit(TFW_HTTP_B_H2, test_req->flags);
set_tfw_str(&test_req->host, "");
test_req->h_tbl->tbl[TFW_HTTP_HDR_H2_AUTHORITY] = hdr5;
test_req->h_tbl->tbl[TFW_HTTP_HDR_HOST] = *hdr3;
test_req->h_tbl->tbl[TFW_HTTP_HDR_HOST] = hdr3;
test_req->h_tbl->tbl[TFW_HTTP_HDR_FORWARDED] = hdr4;
tfw_http_set_req_host(test_req);
match_id = test_chain_match();
EXPECT_EQ(2, match_id);
}
Expand Down
2 changes: 2 additions & 0 deletions fw/t/unit/test_http_parser_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,8 @@ do_split_and_parse(int type, int chunk_mode)
r = tfw_h2_parse_req_finish(req);
}

tfw_http_set_req_host(req);

if (chunk_mode == CHUNK_OFF
|| CHUNK_SIZES[chunk_size_index] >= frames_max_sz)
/*
Expand Down

0 comments on commit 5b0caf5

Please sign in to comment.