Skip to content

Commit

Permalink
Fix invalid parsing of multiple Set-Cookie headers (#1787)
Browse files Browse the repository at this point in the history
* Update the copyright year in some source files

* Fix invalid parsing of multiple Set-Cookie headers

There are two different cookie headers: 'Cookie' header
and 'Set-Cookie' header, but in tempesta they have the
same ID, which is less then TFW_HTTP_HDR_NONSINGULAR.
So both this headers processed as a singular headers
for HTTP1 and as a non-signular headers for HTTP2,
because of known exception in appropriate RFS. But
according to RFS 7230 3.2.2 'Set-Cookie' header also
should be processed as a non-signular header for HTTP1.
So add new ID for 'Set-Cookie' header which is greater
then TFW_HTTP_HDR_NONSINGULAR to provide it's procession
as a non-signular header both for HTTP1 and HTTP2.
Appropriate unit test also implemented for this case.

Closes #1690
  • Loading branch information
EvgeniiMekhanik committed Jan 23, 2023
1 parent a9c9bd6 commit ec339e5
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 11 deletions.
16 changes: 14 additions & 2 deletions fw/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Tempesta FW
*
* Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com).
* Copyright (C) 2015-2022 Tempesta Technologies, Inc.
* Copyright (C) 2015-2023 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -204,7 +204,6 @@ typedef enum {
TFW_HTTP_HDR_USER_AGENT,
TFW_HTTP_HDR_SERVER = TFW_HTTP_HDR_USER_AGENT,
TFW_HTTP_HDR_COOKIE,
TFW_HTTP_HDR_SET_COOKIE = TFW_HTTP_HDR_COOKIE,
TFW_HTTP_HDR_REFERER,
TFW_HTTP_HDR_IF_NONE_MATCH,
TFW_HTTP_HDR_ETAG = TFW_HTTP_HDR_IF_NONE_MATCH,
Expand All @@ -214,6 +213,7 @@ typedef enum {
TFW_HTTP_HDR_NONSINGULAR,

TFW_HTTP_HDR_CONNECTION = TFW_HTTP_HDR_NONSINGULAR,
TFW_HTTP_HDR_SET_COOKIE,
TFW_HTTP_HDR_X_FORWARDED_FOR,
TFW_HTTP_HDR_FORWARDED,
TFW_HTTP_HDR_KEEP_ALIVE,
Expand Down Expand Up @@ -685,6 +685,18 @@ tfw_h2_pseudo_index(unsigned short status)
}
}

/*
* Currently the size of request header table is equal to size of
* response header table. Don't forget to split this function in
* two different functions in case of adding new header to request
* or response header table.
*/
static inline size_t
tfw_http_msg_header_table_size(void)
{
return TFW_HTTP_HDR_RAW - TFW_HTTP_HDR_REGULAR - 1;
}

typedef void (*tfw_http_cache_cb_t)(TfwHttpMsg *);

/* External HTTP functions. */
Expand Down
8 changes: 4 additions & 4 deletions fw/http_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* HTTP message manipulation helpers for the protocol processing.
*
* Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com).
* Copyright (C) 2015-2021 Tempesta Technologies, Inc.
* Copyright (C) 2015-2023 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -128,7 +128,7 @@ static inline unsigned int
__tfw_http_msg_spec_hid(const TfwStr *hdr, const TfwHdrDef array[])
{
const TfwHdrDef *def;
size_t size = TFW_HTTP_HDR_RAW - TFW_HTTP_HDR_REGULAR;
size_t size = tfw_http_msg_header_table_size();
/* TODO: return error if @hdr can't be applied to response or client. */
def = (TfwHdrDef *)__tfw_http_msg_find_hdr(hdr, array, size,
sizeof(TfwHdrDef));
Expand Down Expand Up @@ -161,7 +161,7 @@ tfw_http_msg_resp_spec_hid(const TfwStr *hdr)
};

BUILD_BUG_ON(ARRAY_SIZE(resp_hdrs) !=
TFW_HTTP_HDR_RAW - TFW_HTTP_HDR_REGULAR);
tfw_http_msg_header_table_size());

return __tfw_http_msg_spec_hid(hdr, resp_hdrs);
}
Expand Down Expand Up @@ -191,7 +191,7 @@ tfw_http_msg_req_spec_hid(const TfwStr *hdr)
};

BUILD_BUG_ON(ARRAY_SIZE(req_hdrs) !=
TFW_HTTP_HDR_RAW - TFW_HTTP_HDR_REGULAR);
tfw_http_msg_header_table_size());

return __tfw_http_msg_spec_hid(hdr, req_hdrs);
}
Expand Down
5 changes: 3 additions & 2 deletions fw/http_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Tempesta FW
*
* Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com).
* Copyright (C) 2015-2022 Tempesta Technologies, Inc.
* Copyright (C) 2015-2023 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -1007,11 +1007,12 @@ process_trailer_hdr(TfwHttpMsg *hm, TfwStr *hdr, unsigned int id)
case TFW_HTTP_HDR_HOST:
case TFW_HTTP_HDR_CONTENT_LENGTH:
case TFW_HTTP_HDR_CONTENT_TYPE:
case TFW_HTTP_HDR_COOKIE: /* and TFW_HTTP_HDR_SET_COOKIE */
case TFW_HTTP_HDR_COOKIE:
case TFW_HTTP_HDR_IF_NONE_MATCH:
case TFW_HTTP_HDR_X_FORWARDED_FOR:
case TFW_HTTP_HDR_TRANSFER_ENCODING:
case TFW_HTTP_HDR_CONTENT_ENCODING:
case TFW_HTTP_HDR_SET_COOKIE:
case TFW_HTTP_HDR_FORWARDED:
return CSTR_NEQ;
}
Expand Down
71 changes: 68 additions & 3 deletions fw/t/unit/test_http1_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Tempesta FW
*
* Copyright (C) 2014 NatSys Lab. (info@natsys-lab.com).
* Copyright (C) 2015-2022 Tempesta Technologies, Inc.
* Copyright (C) 2015-2023 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -2691,8 +2691,8 @@ TEST(http1_parser, set_cookie)
FOR_RESP("HTTP/1.1 200 OK\r\n"
"Content-Length: 10\r\n"
"Set-Cookie: __Host-id=1; Secure; Path=/; domain=example.com\r\n"
"\r\n"
"0123456789")
"\r\n"
"0123456789")
{
TfwStr *s_parsed = &resp->h_tbl->tbl[TFW_HTTP_HDR_SET_COOKIE];
TfwStr s_expected = {
Expand All @@ -2713,6 +2713,71 @@ TEST(http1_parser, set_cookie)
test_string_split(&s_expected, s_parsed);
}

/* Multiple Set-Cookie headers */
FOR_RESP("HTTP/1.1 200 OK\r\n"
"Content-Length: 10\r\n"
"Set-Cookie: sessionid=38afes7a8; HttpOnly; Path=/\r\n"
"Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; "
"Secure; HttpOnly\r\n"
"Set-Cookie: __Host-id=1; Secure; Path=/; domain=example.com\r\n"
"\r\n"
"0123456789")
{
const TfwStr *dup, *dup_end;
TfwStr *s_parsed = &resp->h_tbl->tbl[TFW_HTTP_HDR_SET_COOKIE];
TfwStr s_expected[] = {
{
.chunks = (TfwStr []) {
{ .data = "Set-Cookie:" , .len = 11 },
{ .data = " " , .len = 1,
.flags = TFW_STR_OWS },
{ .data = "sessionid=" , .len = 10,
.flags = TFW_STR_NAME },
{ .data = "38afes7a8" , .len = 9,
.flags = TFW_STR_VALUE },
{ .data = "; HttpOnly; Path=/" , .len = 18 }
},
.len = 49,
.nchunks = 5,
},
{
.chunks = (TfwStr []) {
{ .data = "Set-Cookie:" , .len = 11 },
{ .data = " " , .len = 1,
.flags = TFW_STR_OWS },
{ .data = "id=" , .len = 3,
.flags = TFW_STR_NAME },
{ .data = "a3fWa" , .len = 5,
.flags = TFW_STR_VALUE },
{ .data = "; Expires=Wed, 21 Oct 2015 07:28:00 "
"GMT; Secure; HttpOnly",
.len = 57 }
},
.len = 77,
.nchunks = 5
},
{
.chunks = (TfwStr []) {
{ .data = "Set-Cookie:" , .len = 11 },
{ .data = " " , .len = 1,
.flags = TFW_STR_OWS },
{ .data = "__Host-id=" , .len = 10,
.flags = TFW_STR_NAME },
{ .data = "1" , .len = 1,
.flags = TFW_STR_VALUE },
{ .data = "; Secure; Path=/; domain=example.com",
.len = 36 }
},
.len = 59,
.nchunks = 5
}
};
unsigned long idx = 0;
TFW_STR_FOR_EACH_DUP(dup, s_parsed, dup_end)
test_string_split(&s_expected[idx++], dup);
EXPECT_TRUE(idx == ARRAY_SIZE(s_expected));
}

/* No space after semicolon */
EXPECT_BLOCK_RESP("HTTP/1.1 200 OK\r\n"
"Content-Length: 10\r\n"
Expand Down

0 comments on commit ec339e5

Please sign in to comment.