add support for using sni to enabled/disable 0-rtt (#9741)
diff --git a/doc/admin-guide/files/sni.yaml.en.rst b/doc/admin-guide/files/sni.yaml.en.rst
index 3bae962..b5b7a5b 100644
--- a/doc/admin-guide/files/sni.yaml.en.rst
+++ b/doc/admin-guide/files/sni.yaml.en.rst
@@ -218,6 +218,11 @@
ATS negotiates application protocol with the client on behalf of the origin server.
This only works with ``partial_blind_route``.
+
+server_max_early_data Inbound Specifies the maximum amount of early data in bytes that is permitted to be sent on a single connection.
+
+ If not specified, the value of :ts:cv:`proxy.config.ssl.server.max_early_data` is used.
+
========================= ========= ========================================================================================
Pre-warming TLS Tunnel
diff --git a/iocore/net/P_SNIActionPerformer.h b/iocore/net/P_SNIActionPerformer.h
index bc8e9cb..8375a5b 100644
--- a/iocore/net/P_SNIActionPerformer.h
+++ b/iocore/net/P_SNIActionPerformer.h
@@ -411,3 +411,29 @@
private:
std::string_view policy{};
};
+
+class ServerMaxEarlyData : public ActionItem
+{
+public:
+ ServerMaxEarlyData(uint32_t value) : server_max_early_data(value) {}
+ ~ServerMaxEarlyData() override {}
+
+ int
+ SNIAction(TLSSNISupport *snis, const Context &ctx) const override
+ {
+#if TS_HAS_TLS_EARLY_DATA
+ auto ssl_vc = dynamic_cast<SSLNetVConnection *>(snis);
+ if (ssl_vc) {
+ ssl_vc->hints_from_sni.server_max_early_data = server_max_early_data;
+ const uint32_t EARLY_DATA_DEFAULT_SIZE = 16384;
+ const uint32_t server_recv_max_early_data =
+ server_max_early_data > 0 ? std::max(server_max_early_data, EARLY_DATA_DEFAULT_SIZE) : 0;
+ ssl_vc->update_early_data_config(server_max_early_data, server_recv_max_early_data);
+ }
+#endif
+ return SSL_TLSEXT_ERR_OK;
+ }
+
+private:
+ uint32_t server_max_early_data = 0;
+};
diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h
index e2f1dcc..cb41b9a 100644
--- a/iocore/net/P_SSLNetVConnection.h
+++ b/iocore/net/P_SSLNetVConnection.h
@@ -141,6 +141,7 @@
void net_read_io(NetHandler *nh, EThread *lthread) override;
int64_t load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs) override;
void do_io_close(int lerrno = -1) override;
+ void update_early_data_config(uint32_t max_early_data, uint32_t recv_max_early_data);
////////////////////////////////////////////////////////////
// Instances of NetVConnection should be allocated //
diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
index bcb6b49..6153243 100644
--- a/iocore/net/SSLNetVConnection.cc
+++ b/iocore/net/SSLNetVConnection.cc
@@ -173,42 +173,7 @@
SSL_set_bio(ssl, rbio, wbio);
#if TS_HAS_TLS_EARLY_DATA
- // Must disable OpenSSL's internal anti-replay if external cache is used with
- // 0-rtt, otherwise session reuse will be broken. The freshness check described
- // in https://tools.ietf.org/html/rfc8446#section-8.3 is still performed. But we
- // still need to implement something to try to prevent replay atacks.
- //
- // We are now also disabling this when using OpenSSL's internal cache, since we
- // are calling "ssl_accept" non-blocking, it seems to be confusing the anti-replay
- // mechanism and causing session resumption to fail.
- SSLConfig::scoped_config params;
- if (SSL_version(ssl) >= TLS1_3_VERSION && params->server_max_early_data > 0) {
-#ifdef HAVE_SSL_SET_MAX_EARLY_DATA
- bool ret1 = false;
- bool ret2 = false;
- if ((ret1 = SSL_set_max_early_data(ssl, params->server_max_early_data)) == 1) {
- Debug("ssl_early_data", "SSL_set_max_early_data: success");
- } else {
- Debug("ssl_early_data", "SSL_set_max_early_data: failed");
- }
-
- if ((ret2 = SSL_set_recv_max_early_data(ssl, params->server_recv_max_early_data)) == 1) {
- Debug("ssl_early_data", "SSL_set_recv_max_early_data: success");
- } else {
- Debug("ssl_early_data", "SSL_set_recv_max_early_data: failed");
- }
-
- if (ret1 && ret2) {
- Debug("ssl_early_data", "Must disable anti-replay if 0-rtt is enabled.");
- SSL_set_options(ssl, SSL_OP_NO_ANTI_REPLAY);
- }
-#else
- // If SSL_set_max_early_data is unavailable, it's probably BoringSSL,
- // and SSL_set_early_data_enabled should be available.
- SSL_set_early_data_enabled(ssl, 1);
- Warning("max_early_data is not used due to library limitations");
-#endif
- }
+ update_early_data_config(SSLConfigParams::server_max_early_data, SSLConfigParams::server_recv_max_early_data);
#endif
}
this->_bindSSLObject();
@@ -2125,7 +2090,7 @@
int ssl_error = SSL_ERROR_NONE;
#if TS_HAS_TLS_EARLY_DATA
- if (SSLConfigParams::server_max_early_data > 0 && !this->_early_data_finish) {
+ if (!this->_early_data_finish) {
#if HAVE_SSL_READ_EARLY_DATA
size_t nread = 0;
#else
@@ -2375,7 +2340,10 @@
return SSL_ERROR_NONE;
}
- if (SSLConfigParams::server_max_early_data > 0 && !this->_early_data_finish) {
+ bool early_data_enabled = this->hints_from_sni.server_max_early_data.has_value() ?
+ this->hints_from_sni.server_max_early_data.value() > 0 :
+ SSLConfigParams::server_max_early_data > 0;
+ if (early_data_enabled && !this->_early_data_finish) {
bool had_error_on_reading_early_data = false;
bool finished_reading_early_data = false;
Debug("ssl_early_data", "More early data to read.");
@@ -2435,7 +2403,6 @@
Debug("ssl_early_data", "SSL_READ_EARLY_DATA_SUCCESS: size = %" PRId64, nread);
}
}
-
return ssl_error;
}
}
@@ -2489,3 +2456,45 @@
}
SSL_set_max_proto_version(this->ssl, ver);
}
+
+void
+SSLNetVConnection::update_early_data_config(uint32_t max_early_data, uint32_t recv_max_early_data)
+{
+#if TS_HAS_TLS_EARLY_DATA
+ // Must disable OpenSSL's internal anti-replay if external cache is used with
+ // 0-rtt, otherwise session reuse will be broken. The freshness check described
+ // in https://tools.ietf.org/html/rfc8446#section-8.3 is still performed. But we
+ // still need to implement something to try to prevent replay atacks.
+ //
+ // We are now also disabling this when using OpenSSL's internal cache, since we
+ // are calling "ssl_accept" non-blocking, it seems to be confusing the anti-replay
+ // mechanism and causing session resumption to fail.
+ if (SSL_version(ssl) >= TLS1_3_VERSION) {
+#ifdef HAVE_SSL_SET_MAX_EARLY_DATA
+ bool ret1 = false;
+ bool ret2 = false;
+ if ((ret1 = SSL_set_max_early_data(ssl, max_early_data)) == 1) {
+ Debug("ssl_early_data", "SSL_set_max_early_data %u: success", max_early_data);
+ } else {
+ Debug("ssl_early_data", "SSL_set_max_early_data %u: failed", max_early_data);
+ }
+
+ if ((ret2 = SSL_set_recv_max_early_data(ssl, recv_max_early_data)) == 1) {
+ Debug("ssl_early_data", "SSL_set_recv_max_early_data %u: success", recv_max_early_data);
+ } else {
+ Debug("ssl_early_data", "SSL_set_recv_max_early_data %u: failed", recv_max_early_data);
+ }
+
+ if (ret1 && ret2) {
+ Debug("ssl_early_data", "Must disable anti-replay if 0-rtt is enabled.");
+ SSL_set_options(ssl, SSL_OP_NO_ANTI_REPLAY);
+ }
+#else
+ // If SSL_set_max_early_data is unavailable, it's probably BoringSSL,
+ // and SSL_set_early_data_enabled should be available.
+ SSL_set_early_data_enabled(ssl, max_early_data > 0 ? 1 : 0);
+ Warning("max_early_data is not used due to library limitations");
+#endif
+ }
+#endif
+}
diff --git a/iocore/net/SSLSNIConfig.cc b/iocore/net/SSLSNIConfig.cc
index 5bc378d..4d35767 100644
--- a/iocore/net/SSLSNIConfig.cc
+++ b/iocore/net/SSLSNIConfig.cc
@@ -144,6 +144,8 @@
ai->actions.push_back(std::make_unique<HTTP2BufferWaterMark>(item.http2_buffer_water_mark.value()));
}
+ ai->actions.push_back(std::make_unique<ServerMaxEarlyData>(item.server_max_early_data));
+
ai->actions.push_back(std::make_unique<SNI_IpAllow>(item.ip_allow, item.fqdn));
// set the next hop properties
diff --git a/iocore/net/TLSSNISupport.h b/iocore/net/TLSSNISupport.h
index 15812b2..7276fd9 100644
--- a/iocore/net/TLSSNISupport.h
+++ b/iocore/net/TLSSNISupport.h
@@ -54,6 +54,7 @@
struct HintsFromSNI {
std::optional<uint32_t> http2_buffer_water_mark;
+ std::optional<uint32_t> server_max_early_data;
} hints_from_sni;
protected:
diff --git a/iocore/net/YamlSNIConfig.cc b/iocore/net/YamlSNIConfig.cc
index 209223b..3ae5c4f 100644
--- a/iocore/net/YamlSNIConfig.cc
+++ b/iocore/net/YamlSNIConfig.cc
@@ -157,7 +157,8 @@
TS_valid_tls_version_min_in,
TS_valid_tls_version_max_in,
#endif
- TS_host_sni_policy};
+ TS_host_sni_policy,
+ TS_server_max_early_data};
namespace YAML
{
@@ -357,6 +358,13 @@
if (node[TS_valid_tls_version_max_in]) {
item.valid_tls_version_max_in = TLS_PROTOCOLS_DESCRIPTOR.get(node[TS_valid_tls_version_max_in].as<std::string>());
}
+
+ if (node[TS_server_max_early_data]) {
+ item.server_max_early_data = node[TS_server_max_early_data].as<uint32_t>();
+ } else {
+ item.server_max_early_data = SSLConfigParams::server_max_early_data;
+ }
+
return true;
}
};
diff --git a/iocore/net/YamlSNIConfig.h b/iocore/net/YamlSNIConfig.h
index fba88a5..755b82e 100644
--- a/iocore/net/YamlSNIConfig.h
+++ b/iocore/net/YamlSNIConfig.h
@@ -58,6 +58,7 @@
TSDECL(http2);
TSDECL(http2_buffer_water_mark);
TSDECL(host_sni_policy);
+TSDECL(server_max_early_data);
#undef TSDECL
struct YamlSNIConfig {
@@ -89,6 +90,7 @@
int valid_tls_version_max_in = -1;
std::vector<int> tunnel_alpn{};
std::optional<int> http2_buffer_water_mark;
+ uint32_t server_max_early_data = 0;
bool tunnel_prewarm_srv = false;
uint32_t tunnel_prewarm_min = 0;
diff --git a/tests/gold_tests/tls/test-0rtt-s_client.py b/tests/gold_tests/tls/test-0rtt-s_client.py
index b0033bd..797181b 100644
--- a/tests/gold_tests/tls/test-0rtt-s_client.py
+++ b/tests/gold_tests/tls/test-0rtt-s_client.py
@@ -23,19 +23,30 @@
import os
import shlex
import h2_early_decode
+import argparse
def main():
- ats_port = sys.argv[1]
- http_ver = sys.argv[2]
- test = sys.argv[3]
- sess_file_path = os.path.join(sys.argv[4], 'sess.dat')
- early_data_file_path = os.path.join(sys.argv[4], 'early_{0}_{1}.txt'.format(http_ver, test))
+ parser = argparse.ArgumentParser(description='Process some args.')
+ parser.add_argument('-p', '--ats-port', type=int, dest='ats_port', required=True, help='ATS port number')
+ parser.add_argument('-v', '--http-version', type=str, dest='http_ver', choices=['h1', 'h2'], required=True, help='HTTP version')
+ parser.add_argument('-t', '--test-name', type=str, dest='test_name', required=True, help='Name of the test to run')
+ parser.add_argument('-r', '--run-dir', type=str, dest='run_dir', required=True, help='Path to the autest run directory')
+ parser.add_argument('-s', '--server-name', type=str, dest='sni', required=False, help='Server Name')
+ args = parser.parse_args()
+
+ sess_file_path = os.path.join(args.run_dir, 'sess.dat')
+ early_data_file_path = os.path.join(args.run_dir, 'early_{0}_{1}.txt'.format(args.http_ver, args.test_name))
+
+ if args.sni != '':
+ sni_str = '-servername {0}'.format(args.sni)
+ else:
+ sni_str = ''
s_client_cmd_1 = shlex.split(
- 'openssl s_client -connect 127.0.0.1:{0} -tls1_3 -quiet -sess_out {1}'.format(ats_port, sess_file_path))
+ f'openssl s_client -connect 127.0.0.1:{args.ats_port} -tls1_3 -quiet -sess_out {sess_file_path} {sni_str}')
s_client_cmd_2 = shlex.split(
- 'openssl s_client -connect 127.0.0.1:{0} -tls1_3 -quiet -sess_in {1} -early_data {2}'.format(ats_port, sess_file_path, early_data_file_path))
+ f'openssl s_client -connect 127.0.0.1:{args.ats_port} -tls1_3 -quiet -sess_in {sess_file_path} -early_data {early_data_file_path} {sni_str}')
create_sess_proc = subprocess.Popen(s_client_cmd_1, env=os.environ.copy(
), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
@@ -53,7 +64,7 @@
reuse_sess_proc.kill()
output = reuse_sess_proc.communicate()[0]
- if http_ver == 'h2':
+ if args.http_ver == 'h2':
lines = output.split(bytes('\n', 'utf-8'))
data = b''
for line in lines:
diff --git a/tests/gold_tests/tls/tls_0rtt_server.test.py b/tests/gold_tests/tls/tls_0rtt_server.test.py
index 0dfc116..69a7f75 100644
--- a/tests/gold_tests/tls/tls_0rtt_server.test.py
+++ b/tests/gold_tests/tls/tls_0rtt_server.test.py
@@ -27,7 +27,8 @@
Condition.HasOpenSSLVersion('1.1.1'),
)
-ts = Test.MakeATSProcess('ts', enable_tls=True)
+ts1 = Test.MakeATSProcess('ts1', enable_tls=True)
+ts2 = Test.MakeATSProcess('ts2', enable_tls=True)
server = Test.MakeOriginServer('server')
request_header1 = {
@@ -97,25 +98,25 @@
server.addResponse('sessionlog.json', request_header5, response_header5)
server.addResponse('sessionlog.json', request_header6, response_header6)
-ts.addSSLfile('ssl/server.pem')
-ts.addSSLfile('ssl/server.key')
+ts1.addSSLfile('ssl/server.pem')
+ts1.addSSLfile('ssl/server.key')
-ts.Setup.Copy('test-0rtt-s_client.py')
-ts.Setup.Copy('h2_early_decode.py')
-ts.Setup.Copy('early_h1_get.txt')
-ts.Setup.Copy('early_h1_post.txt')
-ts.Setup.Copy('early_h2_get.txt')
-ts.Setup.Copy('early_h2_post.txt')
-ts.Setup.Copy('early_h2_multi1.txt')
-ts.Setup.Copy('early_h2_multi2.txt')
+ts1.Setup.Copy('test-0rtt-s_client.py')
+ts1.Setup.Copy('h2_early_decode.py')
+ts1.Setup.Copy('early_h1_get.txt')
+ts1.Setup.Copy('early_h1_post.txt')
+ts1.Setup.Copy('early_h2_get.txt')
+ts1.Setup.Copy('early_h2_post.txt')
+ts1.Setup.Copy('early_h2_multi1.txt')
+ts1.Setup.Copy('early_h2_multi2.txt')
-ts.Disk.records_config.update({
+ts1.Disk.records_config.update({
'proxy.config.diags.debug.enabled': 1,
- 'proxy.config.diags.debug.tags': 'http',
+ 'proxy.config.diags.debug.tags': 'http|ssl_early_data|ssl',
'proxy.config.exec_thread.autoconfig.enabled': 0,
'proxy.config.exec_thread.limit': 8,
- 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
- 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir),
+ 'proxy.config.ssl.server.cert.path': '{0}'.format(ts1.Variables.SSLDir),
+ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts1.Variables.SSLDir),
'proxy.config.ssl.session_cache.value': 2,
'proxy.config.ssl.session_cache.size': 512000,
'proxy.config.ssl.session_cache.timeout': 7200,
@@ -126,72 +127,149 @@
'proxy.config.ssl.server.cipher_suite': 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'
})
-ts.Disk.ssl_multicert_config.AddLine(
+ts1.Disk.ssl_multicert_config.AddLine(
'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
)
-ts.Disk.remap_config.AddLine(
+ts1.Disk.remap_config.AddLine(
'map / http://127.0.0.1:{0}'.format(server.Variables.Port)
)
+ts1.Disk.sni_yaml.AddLines([
+ 'sni:',
+ '- fqdn: example-no.com',
+ ' server_max_early_data: 0'
+])
+
+ts2.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'http|ssl_early_data|ssl',
+ 'proxy.config.exec_thread.autoconfig.enabled': 0,
+ 'proxy.config.exec_thread.limit': 8,
+ 'proxy.config.ssl.server.cert.path': '{0}'.format(ts1.Variables.SSLDir),
+ 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts1.Variables.SSLDir),
+ 'proxy.config.ssl.session_cache.value': 2,
+ 'proxy.config.ssl.session_cache.size': 512000,
+ 'proxy.config.ssl.session_cache.timeout': 7200,
+ 'proxy.config.ssl.session_cache.num_buckets': 32768,
+ 'proxy.config.ssl.server.session_ticket.enable': 1,
+ 'proxy.config.ssl.server.max_early_data': 0,
+ 'proxy.config.ssl.server.allow_early_data_params': 0,
+ 'proxy.config.ssl.server.cipher_suite': 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'
+})
+
+ts2.Disk.ssl_multicert_config.AddLine(
+ 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
+)
+
+ts2.Disk.remap_config.AddLine(
+ 'map / http://127.0.0.1:{0}'.format(server.Variables.Port)
+)
+
+ts2.Disk.sni_yaml.AddLines([
+ 'sni:',
+ '- fqdn: example-yes.com',
+ ' server_max_early_data: 16384'
+])
+
tr = Test.AddTestRun('Basic Curl Test')
-tr.Processes.Default.Command = 'curl https://127.0.0.1:{0} -k'.format(ts.Variables.ssl_port)
+tr.Processes.Default.Command = 'curl -k --resolve example.com:{0}:127.0.0.1 https://example.com:{0}'.format(ts1.Variables.ssl_port)
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.StartBefore(server)
-tr.Processes.Default.StartBefore(Test.Processes.ts)
+tr.Processes.Default.StartBefore(ts1)
tr.Processes.Default.Streams.All = Testers.ContainsExpression('curl test', 'Making sure the basics still work')
tr.Processes.Default.Streams.All += Testers.ExcludesExpression('early data accepted', '')
tr.StillRunningAfter = server
-tr.StillRunningAfter += ts
+tr.StillRunningAfter += ts1
tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/1.1 GET)')
-tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py {ts.Variables.ssl_port} h1 get {Test.RunDirectory}'
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts1.Variables.ssl_port} -v h1 -t get -r {Test.RunDirectory}'
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.All = Testers.ContainsExpression('early data accepted', '')
tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')
tr.StillRunningAfter = server
-tr.StillRunningAfter += ts
+tr.StillRunningAfter += ts1
tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/1.1 POST)')
-tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py {ts.Variables.ssl_port} h1 post {Test.RunDirectory}'
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts1.Variables.ssl_port} -v h1 -t post -r {Test.RunDirectory}'
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.All = Testers.ContainsExpression('HTTP/1.1 425 Too Early', '')
tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')
tr.Processes.Default.Streams.All += Testers.ExcludesExpression('early data accepted', '')
tr.StillRunningAfter = server
-tr.StillRunningAfter += ts
+tr.StillRunningAfter += ts1
tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/2 GET)')
-tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py {ts.Variables.ssl_port} h2 get {Test.RunDirectory}'
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts1.Variables.ssl_port} -v h2 -t get -r {Test.RunDirectory}'
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.All = Testers.ContainsExpression('early data accepted', '')
tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')
tr.StillRunningAfter = server
-tr.StillRunningAfter += ts
+tr.StillRunningAfter += ts1
tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/2 POST)')
-tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py {ts.Variables.ssl_port} h2 post {Test.RunDirectory}'
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts1.Variables.ssl_port} -v h2 -t post -r {Test.RunDirectory}'
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.All = Testers.ContainsExpression(':status 425', 'Only safe methods are allowed')
tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')
tr.Processes.Default.Streams.All += Testers.ExcludesExpression('early data accepted', '')
tr.StillRunningAfter = server
-tr.StillRunningAfter += ts
+tr.StillRunningAfter += ts1
tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/2 Multiplex)')
-tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py {ts.Variables.ssl_port} h2 multi1 {Test.RunDirectory}'
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts1.Variables.ssl_port} -v h2 -t multi1 -r {Test.RunDirectory}'
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.All = Testers.ContainsExpression('early data accepted multi_1', '')
tr.Processes.Default.Streams.All += Testers.ContainsExpression('early data accepted multi_2', '')
tr.Processes.Default.Streams.All += Testers.ContainsExpression('early data accepted multi_3', '')
tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')
tr.StillRunningAfter = server
-tr.StillRunningAfter += ts
+tr.StillRunningAfter += ts1
tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/2 Multiplex with POST)')
-tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py {ts.Variables.ssl_port} h2 multi2 {Test.RunDirectory}'
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts1.Variables.ssl_port} -v h2 -t multi2 -r {Test.RunDirectory}'
tr.Processes.Default.ReturnCode = 0
tr.Processes.Default.Streams.All = Testers.ContainsExpression('early data accepted multi_1', '')
tr.Processes.Default.Streams.All += Testers.ContainsExpression(':status 425', 'Only safe methods are allowed')
tr.Processes.Default.Streams.All += Testers.ContainsExpression('early data accepted multi_3', '')
tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')
+tr.StillRunningAfter = server
+tr.StillRunningAfter += ts1
+
+tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/1.1 GET) SNI Provided')
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts1.Variables.ssl_port} -v h1 -t get -r {Test.RunDirectory} -s example.com'
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.All = Testers.ContainsExpression('early data accepted', '')
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')
+tr.StillRunningAfter = server
+tr.StillRunningAfter += ts1
+
+tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/1.1 GET) Disabled By SNI Config')
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts1.Variables.ssl_port} -v h1 -t get -r {Test.RunDirectory} -s example-no.com'
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression('early data accepted', '')
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')
+tr.StillRunningAfter = server
+
+tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/1.1 GET) Disabled In General')
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts2.Variables.ssl_port} -v h1 -t get -r {Test.RunDirectory}'
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.StartBefore(ts2)
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression('early data accepted', '')
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')
+tr.StillRunningAfter = server
+tr.StillRunningAfter += ts2
+
+tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/1.1 GET) Disabled In General SNI Provided')
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts2.Variables.ssl_port} -v h1 -t get -r {Test.RunDirectory} -s example.com'
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.All = Testers.ExcludesExpression('early data accepted', '')
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')
+tr.StillRunningAfter = server
+tr.StillRunningAfter += ts2
+
+tr = Test.AddTestRun('TLSv1.3 0-RTT Support (HTTP/1.1 GET) Enabled By SNI Config')
+tr.Processes.Default.Command = f'{sys.executable} test-0rtt-s_client.py -p {ts2.Variables.ssl_port} -v h1 -t get -r {Test.RunDirectory} -s example-yes.com'
+tr.Processes.Default.ReturnCode = 0
+tr.Processes.Default.Streams.All = Testers.ContainsExpression('early data accepted', '')
+tr.Processes.Default.Streams.All += Testers.ExcludesExpression('curl test', '')