Skip to content

Commit 497e475

Browse files
committed
TS-3100: Extend tr-pass to allow malformed HTTP GET requests to be blind
tunneled.
1 parent 9e2689b commit 497e475

File tree

5 files changed

+97
-72
lines changed

5 files changed

+97
-72
lines changed

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
-*- coding: utf-8 -*-
22
Changes with Apache Traffic Server 5.3.0
3+
*) [TS-3100] Extend tr-pass to allow malformed HTTP GET requested to be blind
4+
tunneled.
5+
36
*) [TS-3140] Traffic Server asserts during response redirect.
47

58
*) [TS-3309] Document TLS session ticket rotation.

proxy/hdrs/HTTP.h

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ class HTTPHdr: public MIMEHdr
549549

550550
HTTPType type_get() const;
551551

552-
HTTPVersion version_get();
552+
HTTPVersion version_get() const;
553553
void version_set(HTTPVersion version);
554554

555555
const char *method_get(int *length);
@@ -662,6 +662,9 @@ class HTTPHdr: public MIMEHdr
662662
// Utility routines
663663
bool is_cache_control_set(const char *cc_directive_wks);
664664
bool is_pragma_no_cache_set();
665+
bool is_keep_alive_set() const;
666+
HTTPKeepAlive keep_alive_get() const;
667+
665668

666669
protected:
667670
/** Load the target cache.
@@ -1006,12 +1009,71 @@ http_hdr_version_get(HTTPHdrImpl *hh)
10061009
-------------------------------------------------------------------------*/
10071010

10081011
inline HTTPVersion
1009-
HTTPHdr::version_get()
1012+
HTTPHdr::version_get() const
10101013
{
10111014
ink_assert(valid());
10121015
return HTTPVersion(http_hdr_version_get(m_http));
10131016
}
10141017

1018+
/*-------------------------------------------------------------------------
1019+
-------------------------------------------------------------------------*/
1020+
1021+
inline static HTTPKeepAlive
1022+
is_header_keep_alive(const HTTPVersion & http_version, const MIMEField* con_hdr)
1023+
{
1024+
enum {
1025+
CON_TOKEN_NONE = 0,
1026+
CON_TOKEN_KEEP_ALIVE,
1027+
CON_TOKEN_CLOSE
1028+
};
1029+
1030+
int con_token = CON_TOKEN_NONE;
1031+
HTTPKeepAlive keep_alive = HTTP_NO_KEEPALIVE;
1032+
// *unknown_tokens = false;
1033+
1034+
if (con_hdr) {
1035+
if (con_hdr->value_get_index("keep-alive", 10) >= 0)
1036+
con_token = CON_TOKEN_KEEP_ALIVE;
1037+
else if (con_hdr->value_get_index("close", 5) >= 0)
1038+
con_token = CON_TOKEN_CLOSE;
1039+
}
1040+
1041+
if (HTTPVersion(1, 0) == http_version) {
1042+
keep_alive = (con_token == CON_TOKEN_KEEP_ALIVE) ? (HTTP_KEEPALIVE) : (HTTP_NO_KEEPALIVE);
1043+
} else if (HTTPVersion(1, 1) == http_version) {
1044+
// We deviate from the spec here. If the we got a response where
1045+
// where there is no Connection header and the request 1.0 was
1046+
// 1.0 don't treat this as keep-alive since Netscape-Enterprise/3.6 SP1
1047+
// server doesn't
1048+
keep_alive = ((con_token == CON_TOKEN_KEEP_ALIVE) ||
1049+
(con_token == CON_TOKEN_NONE && HTTPVersion(1, 1) == http_version)) ? (HTTP_KEEPALIVE)
1050+
: (HTTP_NO_KEEPALIVE);
1051+
} else {
1052+
keep_alive = HTTP_NO_KEEPALIVE;
1053+
}
1054+
return (keep_alive);
1055+
}
1056+
1057+
inline HTTPKeepAlive
1058+
HTTPHdr::keep_alive_get() const
1059+
{
1060+
HTTPKeepAlive retval = HTTP_NO_KEEPALIVE;
1061+
const MIMEField *pc = this->field_find(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION);
1062+
if (pc != NULL) {
1063+
retval = is_header_keep_alive(this->version_get(), pc);
1064+
} else {
1065+
const MIMEField *c = this->field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
1066+
retval = is_header_keep_alive(this->version_get(), c);
1067+
}
1068+
return retval;
1069+
}
1070+
1071+
inline bool
1072+
HTTPHdr::is_keep_alive_set() const
1073+
{
1074+
return this->keep_alive_get() == HTTP_KEEPALIVE;
1075+
}
1076+
10151077
/*-------------------------------------------------------------------------
10161078
-------------------------------------------------------------------------*/
10171079

proxy/hdrs/MIME.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,7 @@ class MIMEHdr:public HdrHeapSDKHandle
905905

906906
MIMEField *field_create(const char *name = NULL, int length = -1);
907907
MIMEField *field_find(const char *name, int length);
908+
const MIMEField *field_find(const char *name, int length) const;
908909
void field_attach(MIMEField * field);
909910
void field_detach(MIMEField * field, bool detach_all_dups = true);
910911
void field_delete(MIMEField * field, bool delete_all_dups = true);
@@ -1101,6 +1102,14 @@ MIMEHdr::field_find(const char *name, int length)
11011102
return mime_hdr_field_find(m_mime, name, length);
11021103
}
11031104

1105+
inline const MIMEField *
1106+
MIMEHdr::field_find(const char *name, int length) const
1107+
{
1108+
// ink_assert(valid());
1109+
MIMEField *retval = mime_hdr_field_find(const_cast<MIMEHdr *>(this)->m_mime, name, length);
1110+
return retval;
1111+
}
1112+
11041113
/*-------------------------------------------------------------------------
11051114
-------------------------------------------------------------------------*/
11061115

proxy/http/HttpSM.cc

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -680,11 +680,25 @@ HttpSM::state_read_client_request_header(int event, void *data)
680680
// We need to handle EOS as well as READ_READY because the client
681681
// may have sent all of the data already followed by a fIN and that
682682
// should be OK.
683-
if ((event == VC_EVENT_READ_READY || event == VC_EVENT_EOS) &&
684-
state == PARSE_ERROR &&
685-
is_transparent_passthrough_allowed() &&
683+
if (is_transparent_passthrough_allowed() &&
686684
ua_raw_buffer_reader != NULL) {
687-
685+
bool do_blind_tunnel = false;
686+
// If we had a parse error and we're done reading data
687+
// blind tunnel
688+
if ((event == VC_EVENT_READ_READY || event == VC_EVENT_EOS) &&
689+
state == PARSE_ERROR) {
690+
do_blind_tunnel = true;
691+
692+
// If we had a GET request that has data after the
693+
// get request, do blind tunnel
694+
} else if (state == PARSE_DONE &&
695+
t_state.hdr_info.client_request.method_get_wksidx() ==
696+
HTTP_WKSIDX_GET &&
697+
ua_raw_buffer_reader->read_avail() > 0 &&
698+
!t_state.hdr_info.client_request.is_keep_alive_set()) {
699+
do_blind_tunnel = true;
700+
}
701+
if (do_blind_tunnel) {
688702
DebugSM("http", "[%" PRId64 "] first request on connection failed parsing, switching to passthrough.", sm_id);
689703

690704
t_state.transparent_passthrough = true;
@@ -703,6 +717,7 @@ HttpSM::state_read_client_request_header(int event, void *data)
703717
t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
704718
}
705719
return 0;
720+
}
706721
}
707722

708723
// Check to see if we are done parsing the header

proxy/http/HttpTransact.cc

Lines changed: 2 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -69,47 +69,6 @@ extern HttpBodyFactory *body_factory;
6969

7070
static const char local_host_ip_str[] = "127.0.0.1";
7171

72-
73-
// someday, reduce the amount of duplicate code between this
74-
// function and _process_xxx_connection_field_in_outgoing_header
75-
inline static HTTPKeepAlive
76-
is_header_keep_alive(const HTTPVersion & http_version, const HTTPVersion & request_http_version, MIMEField* con_hdr /*, bool* unknown_tokens */)
77-
{
78-
enum
79-
{
80-
CON_TOKEN_NONE = 0,
81-
CON_TOKEN_KEEP_ALIVE,
82-
CON_TOKEN_CLOSE
83-
};
84-
85-
int con_token = CON_TOKEN_NONE;
86-
HTTPKeepAlive keep_alive = HTTP_NO_KEEPALIVE;
87-
// *unknown_tokens = false;
88-
89-
if (con_hdr) {
90-
if (con_hdr->value_get_index("keep-alive", 10) >= 0)
91-
con_token = CON_TOKEN_KEEP_ALIVE;
92-
else if (con_hdr->value_get_index("close", 5) >= 0)
93-
con_token = CON_TOKEN_CLOSE;
94-
}
95-
96-
if (HTTPVersion(1, 0) == http_version) {
97-
keep_alive = (con_token == CON_TOKEN_KEEP_ALIVE) ? (HTTP_KEEPALIVE) : (HTTP_NO_KEEPALIVE);
98-
} else if (HTTPVersion(1, 1) == http_version) {
99-
// We deviate from the spec here. If the we got a response where
100-
// where there is no Connection header and the request 1.0 was
101-
// 1.0 don't treat this as keep-alive since Netscape-Enterprise/3.6 SP1
102-
// server doesn't
103-
keep_alive = ((con_token == CON_TOKEN_KEEP_ALIVE) ||
104-
(con_token == CON_TOKEN_NONE && HTTPVersion(1, 1) == request_http_version)) ? (HTTP_KEEPALIVE)
105-
: (HTTP_NO_KEEPALIVE);
106-
} else {
107-
keep_alive = HTTP_NO_KEEPALIVE;
108-
}
109-
110-
return (keep_alive);
111-
}
112-
11372
inline static bool
11473
is_request_conditional(HTTPHdr* header)
11574
{
@@ -5468,14 +5427,7 @@ HttpTransact::initialize_state_variables_from_request(State* s, HTTPHdr* obsolet
54685427
if (!s->txn_conf->keep_alive_enabled_in) {
54695428
s->client_info.keep_alive = HTTP_NO_KEEPALIVE;
54705429
} else {
5471-
// If there is a Proxy-Connection header use that, otherwise use the Connection header
5472-
if (pc != NULL) {
5473-
s->client_info.keep_alive = is_header_keep_alive(s->client_info.http_version, s->client_info.http_version, pc);
5474-
} else {
5475-
MIMEField *c = incoming_request->field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
5476-
5477-
s->client_info.keep_alive = is_header_keep_alive(s->client_info.http_version, s->client_info.http_version, c);
5478-
}
5430+
s->client_info.keep_alive = incoming_request->keep_alive_get();
54795431
}
54805432

54815433
if (s->client_info.keep_alive == HTTP_KEEPALIVE && s->client_info.http_version == HTTPVersion(1, 1)) {
@@ -5582,23 +5534,7 @@ HttpTransact::initialize_state_variables_from_response(State* s, HTTPHdr* incomi
55825534
* if we sent "Connection: close" We need check the response
55835535
* header regardless of what we sent to the server
55845536
*/
5585-
MIMEField *c_hdr;
5586-
if ((s->current.request_to != ORIGIN_SERVER) &&
5587-
(s->current.request_to == PARENT_PROXY ||
5588-
s->current.request_to == ICP_SUGGESTED_HOST)) {
5589-
c_hdr = s->hdr_info.server_response.field_find(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION);
5590-
5591-
// If there is a Proxy-Connection header use that,
5592-
// otherwise use the Connection header
5593-
if (c_hdr == NULL) {
5594-
c_hdr = s->hdr_info.server_response.field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
5595-
}
5596-
} else {
5597-
c_hdr = s->hdr_info.server_response.field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
5598-
}
5599-
5600-
s->current.server->keep_alive = is_header_keep_alive(s->hdr_info.server_response.version_get(),
5601-
s->hdr_info.server_request.version_get(), c_hdr);
5537+
s->current.server->keep_alive = s->hdr_info.server_response.keep_alive_get();
56025538

56035539
// Don't allow an upgrade request to Keep Alive
56045540
if (s->is_upgrade_request) {

0 commit comments

Comments
 (0)