Skip to content

Commit

Permalink
Merge branch 'master' into quic-latest
Browse files Browse the repository at this point in the history
* master:
  reuse multiple times (#7992)
  Test bad request behavior (#7884)
  Fix BoringSSL build (#8001)
  Update TSHttpTxnAborted API to distinguish client/server aborts (#7901)
  Enforce case for well known methods (#7886)
  Add null checks for http_load (#7995)
  • Loading branch information
maskit committed Jun 29, 2021
2 parents 837bd0e + 2edeae4 commit d232a12
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 24 deletions.
6 changes: 5 additions & 1 deletion doc/developer-guide/api/functions/TSHttpTxnAborted.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Synopsis
#include <ts/ts.h>
.. c:function:: TSReturnCode TSHttpTxnAborted(TSHttpTxn txnp)
.. c:function:: TSReturnCode TSHttpTxnAborted(TSHttpTxn txnp, bool *client_abort)
Description
-----------
Expand All @@ -37,6 +37,10 @@ Description
transaction is aborted. This function should be used to determine whether
a transaction has been aborted before attempting to cache the results.
Broadly, transaction aborts can be classified into either client side aborts or
server side. To distinguish between these, we have another boolean parameter
which gets set to TRUE in case of client side aborts.
Return values
-------------
Expand Down
3 changes: 2 additions & 1 deletion include/ts/ts.h
Original file line number Diff line number Diff line change
Expand Up @@ -2363,10 +2363,11 @@ tsapi TSReturnCode TSAIOThreadNumSet(int thread_num);

/**
Check if transaction was aborted (due client/server errors etc.)
Client_abort is set as True, in case the abort was caused by the Client.
@return 1 if transaction was aborted
*/
tsapi TSReturnCode TSHttpTxnAborted(TSHttpTxn txnp);
tsapi TSReturnCode TSHttpTxnAborted(TSHttpTxn txnp, bool *client_abort);

tsapi TSVConn TSVConnCreate(TSEventFunc event_funcp, TSMutex mutexp);
tsapi TSVConn TSVConnFdCreate(int fd);
Expand Down
2 changes: 2 additions & 0 deletions iocore/net/SSLUtils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,8 @@ SSLPrivateKeyHandler(SSL_CTX *ctx, const SSLConfigParams *params, const char *ke
}
}
}
#else
void *e = nullptr;
#endif
if (pkey == nullptr) {
scoped_BIO bio(BIO_new_mem_buf(secret_data, secret_data_len));
Expand Down
3 changes: 2 additions & 1 deletion plugins/esi/esi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,8 @@ removeCacheKey(TSHttpTxn txnp)
static void
cacheNodeList(ContData *cont_data)
{
if (TSHttpTxnAborted(cont_data->txnp) == TS_SUCCESS) {
bool client_abort;
if (TSHttpTxnAborted(cont_data->txnp, &client_abort) == TS_SUCCESS) {
TSDebug(cont_data->debug_tag, "[%s] Not caching node list as txn has been aborted", __FUNCTION__);
return;
}
Expand Down
4 changes: 2 additions & 2 deletions plugins/lua/ts_lua_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -767,8 +767,8 @@ ts_lua_http_is_aborted(lua_State *L)
ts_lua_http_ctx *http_ctx;

GET_HTTP_CONTEXT(http_ctx, L);

if (TSHttpTxnAborted(http_ctx->txnp)) {
bool client_abort = false;
if (TSHttpTxnAborted(http_ctx->txnp, &client_abort)) {
lua_pushnumber(L, 1);
} else {
lua_pushnumber(L, 0);
Expand Down
2 changes: 1 addition & 1 deletion proxy/hdrs/HTTP.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const
ink_assert(url_start);
ink_assert(url_end);

int method_wks_idx = hdrtoken_tokenize(method_start, static_cast<int>(method_end - method_start));
int method_wks_idx = hdrtoken_method_tokenize(method_start, static_cast<int>(method_end - method_start));
http_hdr_method_set(heap, hh, method_start, method_wks_idx, static_cast<int>(method_end - method_start), must_copy_strings);

ink_assert(hh->u.req.m_url_impl != nullptr);
Expand Down
24 changes: 24 additions & 0 deletions proxy/hdrs/HdrToken.cc
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,30 @@ hdrtoken_tokenize_dfa(const char *string, int string_len, const char **wks_strin
return wks_idx;
}

/*-------------------------------------------------------------------------
Have to work around that methods are case insensitive while the DFA is
case insensitive.
-------------------------------------------------------------------------*/

int
hdrtoken_method_tokenize(const char *string, int string_len)
{
const char *string_out;
int retval = -1;
if (hdrtoken_is_wks(string)) {
retval = hdrtoken_wks_to_index(string);
return retval;
}
retval = hdrtoken_tokenize(string, string_len, &string_out);
if (retval >= 0) {
if (strncmp(string, string_out, string_len) != 0) {
// Not a case match
retval = -1;
}
}
return retval;
}

/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/

Expand Down
1 change: 1 addition & 0 deletions proxy/hdrs/HdrToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ extern uint32_t hdrtoken_str_flags[];
extern void hdrtoken_init();
extern int hdrtoken_tokenize_dfa(const char *string, int string_len, const char **wks_string_out = nullptr);
inkcoreapi extern int hdrtoken_tokenize(const char *string, int string_len, const char **wks_string_out = nullptr);
extern int hdrtoken_method_tokenize(const char *string, int string_len);
extern const char *hdrtoken_string_to_wks(const char *string);
extern const char *hdrtoken_string_to_wks(const char *string, int length);

Expand Down
6 changes: 4 additions & 2 deletions src/traffic_server/InkAPI.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5676,16 +5676,18 @@ TSHttpTxnShutDown(TSHttpTxn txnp, TSEvent event)
}

TSReturnCode
TSHttpTxnAborted(TSHttpTxn txnp)
TSHttpTxnAborted(TSHttpTxn txnp, bool *client_abort)
{
sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);

HttpSM *sm = (HttpSM *)txnp;
*client_abort = false;
HttpSM *sm = (HttpSM *)txnp;
switch (sm->t_state.squid_codes.log_code) {
case SQUID_LOG_ERR_CLIENT_ABORT:
case SQUID_LOG_ERR_CLIENT_READ_ERROR:
case SQUID_LOG_TCP_SWAPFAIL:
// check for client abort and cache read error
*client_abort = true;
return TS_SUCCESS;
default:
break;
Expand Down
24 changes: 24 additions & 0 deletions tests/gold_tests/headers/gold/bad_method.gold
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
HTTP/1.1 501 Unsupported method ('gET')
Content-Type: text/html;charset=utf-8
Content-Length: 496
Date: ``
Age: 0
Connection: keep-alive
Server: ATS/``

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Error response</title>
</head>
<body>
<h1>Error response</h1>
<p>Error code: 501</p>
<p>Message: Unsupported method ('gET').</p>
<p>Error code explanation: HTTPStatus.NOT_IMPLEMENTED - Server does not support this operation.</p>
</body>
</html>
HTTP/1.1 200 OK
``
17 changes: 16 additions & 1 deletion tests/gold_tests/headers/good_request_after_bad.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
'''
Test.ContinueOnFail = True
ts = Test.MakeATSProcess("ts", enable_cache=True)

Test.ContinueOnFail = True
ts.Disk.records_config.update({'proxy.config.diags.debug.tags': 'http',
'proxy.config.diags.debug.enabled': 0,
})

Test.ContinueOnFail = True
server = Test.MakeOriginServer("server")
request_header = {"headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""}
response_header = {
Expand Down Expand Up @@ -91,3 +92,17 @@
tr.Processes.Default.Streams.All = Testers.ContainsExpression(
r"HTTP/1.1 501 Unsupported method \('TRACE'\)",
"microserver does not support TRACE")

# Methods are case sensitive. Verify that "gET" is not confused with "GET".
tr = Test.AddTestRun("mixed case method")
tr.Processes.Default.Command = 'printf "gET / HTTP/1.1\r\nHost:bob\r\n\r\nGET / HTTP/1.1\r\nHost: boa\r\n\r\n" | nc 127.0.0.1 {}'.format(
ts.Variables.port)
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.stdout = 'gold/bad_method.gold'

# mangled termination
tr = Test.AddTestRun("mangled line termination")
tr.Processes.Default.Command = 'printf "GET / HTTP/1.1\r\nHost:bob\r\n \r\nGET / HTTP/1.1\r\nHost: boa\r\n\r\n" | nc 127.0.0.1 {}'.format(
ts.Variables.port)
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.stdout = 'gold/bad_good_request.gold'
61 changes: 47 additions & 14 deletions tests/gold_tests/tls/tls_session_reuse.test.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,34 +103,67 @@
'proxy.config.ssl.server.session_ticket.enable': 1,
})


def check_session(ev, test):
retval = False
f = open(test.GetContent(ev), 'r')
err = "Session ids match"
if not f:
err = "Failed to open {0}".format(openssl_output)
return (retval, "Check that session ids match", err)

content = f.read()
match = re.findall('Session-ID: ([0-9A-F]+)', content)

if match:
if all(i == j for i, j in zip(match, match[1:])):
err = "{0} reused successfully {1} times".format(match[0], len(match) - 1)
retval = True
else:
err = "Session is not being reused as expected"
else:
err = "Didn't find session id"
return (retval, "Check that session ids match", err)


tr = Test.AddTestRun("TLSv1.2 Session ID")
tr.Command = \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_out {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_in {1}' \
.format(ts1.Variables.ssl_port, os.path.join(Test.RunDirectory, 'sess.dat'))
tr.ReturnCode = 0
tr.Processes.Default.StartBefore(server)
tr.Processes.Default.StartBefore(ts1)
tr.Processes.Default.Streams.All = Testers.ContainsExpression('Reused, TLSv', '')
tr.Processes.Default.Streams.All += Testers.ContainsExpression('Protocol : TLSv1.2', '')
tr.Processes.Default.Streams.All.Content = Testers.Lambda(check_session)
tr.StillRunningAfter = server

tr = Test.AddTestRun("TLSv1.2 Session Ticket")
tr.Command = \
tr1 = Test.AddTestRun("TLSv1.2 Session Ticket")
tr1.Command = \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -sess_out {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -sess_in {1}' \
.format(ts2.Variables.ssl_port, os.path.join(Test.RunDirectory, 'sess.dat'))
tr.ReturnCode = 0
tr.Processes.Default.StartBefore(ts2)
tr.Processes.Default.Streams.All = Testers.ContainsExpression('Reused, TLSv', '')
tr.Processes.Default.Streams.All += Testers.ContainsExpression('Protocol : TLSv1.2', '')
tr.StillRunningAfter = server
tr1.ReturnCode = 0
tr1.Processes.Default.StartBefore(ts2)
tr1.Processes.Default.Streams.All.Content = Testers.Lambda(check_session)
tr1.StillRunningAfter = server

tr = Test.AddTestRun("Disabled Session Cache")
tr.Command = \
tr2 = Test.AddTestRun("Disabled Session Cache")
tr2.Command = \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_out {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_in {1} && ' \
'echo -e "GET / HTTP/1.1\r\n" | openssl s_client -tls1_2 -connect 127.0.0.1:{0} -no_ticket -sess_in {1}' \
.format(ts3.Variables.ssl_port, os.path.join(Test.RunDirectory, 'sess.dat'))
tr.ReturnCode = 0
tr.Processes.Default.StartBefore(ts3)
tr.Processes.Default.Streams.All = Testers.ExcludesExpression('Reused', '')
tr2.ReturnCode = 0
tr2.Processes.Default.StartBefore(ts3)
tr2.Processes.Default.Streams.All = Testers.ExcludesExpression('Reused', '')
14 changes: 13 additions & 1 deletion tools/http_load/http_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,12 @@ handle_connect(int cnum, struct timeval *nowP, int double_check)
SSL_load_error_strings();
SSL_library_init();
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if (ssl_ctx == NULL) {
(void)fprintf(stderr, "%s: failed to create SSL_CTX\n", argv0);
ERR_print_errors_fp(stderr);
return;
}

/* For some reason this does not seem to work, but indications are that it should...
Maybe something with how we create connections? TODO: Fix it... */
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, cert_verify_callback);
Expand All @@ -1187,6 +1193,12 @@ handle_connect(int cnum, struct timeval *nowP, int double_check)
if (flags != -1)
(void)fcntl(connections[cnum].conn_fd, F_SETFL, flags & ~(int)O_NDELAY);
connections[cnum].ssl = SSL_new(ssl_ctx);
if (connections[cnum].ssl == NULL) {
(void)fprintf(stderr, "%s: failed to create SSL\n", argv0);
ERR_print_errors_fp(stderr);
close_connection(cnum);
return;
}
SSL_set_fd(connections[cnum].ssl, connections[cnum].conn_fd);
r = SSL_connect(connections[cnum].ssl);
if (r <= 0) {
Expand Down Expand Up @@ -2802,7 +2814,7 @@ close_connection(int cnum)
ev.data.u32 = cnum;
if (epoll_ctl(epfd, EPOLL_CTL_DEL, connections[cnum].conn_fd, &ev) < 0)
perror("epoll delete fd");
if (urls[connections[cnum].url_num].protocol == PROTO_HTTPS)
if (urls[connections[cnum].url_num].protocol == PROTO_HTTPS && connections[cnum].ssl != NULL)
SSL_free(connections[cnum].ssl);
(void)close(connections[cnum].conn_fd);
} else {
Expand Down

0 comments on commit d232a12

Please sign in to comment.