mirror of
https://github.com/curl/curl.git
synced 2026-08-11 14:52:02 +03:00
FTP: fix TLS session reuse on the data connection
FTP servers using SSL can be configured to check TLS session reuse on the DATA connection. They hand out a new session on every CONTROL connect and require to see the client using exactly that one when up-/downloading on DATA. This means: 1. We have to configure the SSL filter on the DATA connection with exactly the same peers. 2. We have to remember the SSL session on the CONTROL connection - separately from the session cache. The SSL filter on the DATA connection then looks for a session at the CONTROL filter and, if present, uses that. Tests: Enable `require_ssl_reuse` in our pytest setup for vsftpd. This reproduces the problem reported in #22225 and verifies the fix. Skip ftp+SSL pytests for rustls, as we have no possibility to reuse sessions in that backend. Schannel: we do not run these tests with the backend. I expect it has similar problems but am not able to verify. Reported-by: Laurent Sabourin Fixes #22225 Closes #22246
This commit is contained in:
parent
0a7ec0ea4d
commit
84ecfb3ecc
17 changed files with 485 additions and 190 deletions
|
|
@ -106,9 +106,7 @@ def httpd(env) -> Generator[Httpd, None, None]:
|
|||
@pytest.fixture(scope="session")
|
||||
def nghttpx(env, httpd) -> Generator[Union[Nghttpx, bool], None, None]:
|
||||
nghttpx = NghttpxQuic(env=env)
|
||||
if nghttpx.exists():
|
||||
if not nghttpx.supports_h3() and env.have_h3_curl():
|
||||
log.warning("nghttpx does not support QUIC, but curl does")
|
||||
if nghttpx.exists() and nghttpx.supports_h3() and env.have_h3_curl():
|
||||
nghttpx.clear_logs()
|
||||
assert nghttpx.initial_start()
|
||||
yield nghttpx
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ log = logging.getLogger(__name__)
|
|||
|
||||
|
||||
@pytest.mark.skipif(condition=not Env.has_vsftpd(), reason="missing vsftpd")
|
||||
@pytest.mark.skipif(condition=Env.curl_uses_lib('rustls-ffi'),
|
||||
reason="rustls does not support TLS session reuse")
|
||||
@pytest.mark.skipif(condition=Env.curl_uses_lib('libressl'),
|
||||
reason="libressl fails on TLS session reuse")
|
||||
class TestVsFTPD:
|
||||
|
||||
SUPPORTS_SSL = True
|
||||
|
|
@ -101,31 +105,39 @@ class TestVsFTPD:
|
|||
self.check_downloads(curl, srcfile, count)
|
||||
r.check_stats_timelines()
|
||||
|
||||
@pytest.mark.parametrize("docname", [
|
||||
'data-1k', 'data-1m', 'data-10m'
|
||||
@pytest.mark.parametrize("docname,count,secure", [
|
||||
['data-1k', 10, True],
|
||||
['data-1m', 5, True],
|
||||
['data-1m', 5, False],
|
||||
['data-10m', 2,True]
|
||||
])
|
||||
def test_31_03_download_10_serial(self, env: Env, vsftpds: VsFTPD, docname):
|
||||
def test_31_03_download_10_serial(self, env: Env, vsftpds: VsFTPD, docname, count, secure):
|
||||
curl = CurlClient(env=env)
|
||||
srcfile = os.path.join(vsftpds.docs_dir, f'{docname}')
|
||||
count = 10
|
||||
url = f'ftp://{env.ftp_domain}:{vsftpds.port}/{docname}?[0-{count-1}]'
|
||||
r = curl.ftp_ssl_get(urls=[url], with_stats=True)
|
||||
xargs = []
|
||||
if not secure:
|
||||
xargs.append('--insecure')
|
||||
r = curl.ftp_ssl_get(urls=[url], with_stats=True, extra_args=xargs)
|
||||
r.check_stats(count=count, http_status=226)
|
||||
self.check_downloads(curl, srcfile, count)
|
||||
assert r.total_connects == count + 1, 'should reuse the control conn'
|
||||
r.check_stats_timelines()
|
||||
|
||||
@pytest.mark.parametrize("docname", [
|
||||
'data-1k', 'data-1m', 'data-10m'
|
||||
@pytest.mark.parametrize("docname,count,secure", [
|
||||
['data-1k', 10, True],
|
||||
['data-1m', 5, True],
|
||||
['data-1m', 5, False],
|
||||
['data-10m', 2,True]
|
||||
])
|
||||
def test_31_04_download_10_parallel(self, env: Env, vsftpds: VsFTPD, docname):
|
||||
def test_31_04_download_10_parallel(self, env: Env, vsftpds: VsFTPD, docname, count, secure):
|
||||
curl = CurlClient(env=env)
|
||||
srcfile = os.path.join(vsftpds.docs_dir, f'{docname}')
|
||||
count = 10
|
||||
url = f'ftp://{env.ftp_domain}:{vsftpds.port}/{docname}?[0-{count-1}]'
|
||||
r = curl.ftp_ssl_get(urls=[url], with_stats=True, extra_args=[
|
||||
'--parallel'
|
||||
])
|
||||
xargs = ['--parallel']
|
||||
if not secure:
|
||||
xargs.append('--insecure')
|
||||
r = curl.ftp_ssl_get(urls=[url], with_stats=True, extra_args=xargs)
|
||||
r.check_stats(count=count, http_status=226)
|
||||
self.check_downloads(curl, srcfile, count)
|
||||
assert r.total_connects > count + 1, 'should have used several control conns'
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ log = logging.getLogger(__name__)
|
|||
|
||||
|
||||
@pytest.mark.skipif(condition=not Env.has_vsftpd(), reason="missing vsftpd")
|
||||
@pytest.mark.skipif(condition=Env.curl_uses_lib('rustls-ffi'),
|
||||
reason="rustls does not support TLS session reuse")
|
||||
@pytest.mark.skipif(condition=Env.curl_uses_lib('libressl'),
|
||||
reason="libressl fails on TLS session reuse")
|
||||
class TestFtpsVsFTPD:
|
||||
|
||||
SUPPORTS_SSL = True
|
||||
|
|
@ -101,15 +105,20 @@ class TestFtpsVsFTPD:
|
|||
self.check_downloads(curl, srcfile, count)
|
||||
r.check_stats_timelines()
|
||||
|
||||
@pytest.mark.parametrize("docname", [
|
||||
'data-1k', 'data-1m', 'data-10m'
|
||||
@pytest.mark.parametrize("docname,count,secure", [
|
||||
['data-1k', 10, True],
|
||||
['data-1m', 5, True],
|
||||
['data-1m', 5, False],
|
||||
['data-10m', 2,True]
|
||||
])
|
||||
def test_32_03_download_10_serial(self, env: Env, vsftpds: VsFTPD, docname):
|
||||
def test_32_03_download_10_serial(self, env: Env, vsftpds: VsFTPD, docname, count, secure):
|
||||
curl = CurlClient(env=env)
|
||||
srcfile = os.path.join(vsftpds.docs_dir, f'{docname}')
|
||||
count = 10
|
||||
url = f'ftps://{env.ftp_domain}:{vsftpds.port}/{docname}?[0-{count-1}]'
|
||||
r = curl.ftp_get(urls=[url], with_stats=True)
|
||||
xargs = []
|
||||
if not secure:
|
||||
xargs.append('--insecure')
|
||||
r = curl.ftp_get(urls=[url], with_stats=True, extra_args=xargs)
|
||||
r.check_stats(count=count, http_status=226)
|
||||
self.check_downloads(curl, srcfile, count)
|
||||
assert r.total_connects == count + 1, 'should reuse the control conn'
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ class VsFTPD:
|
|||
f'rsa_cert_file={creds.cert_file}',
|
||||
f'rsa_private_key_file={creds.pkey_file}',
|
||||
# require_ssl_reuse=YES means ctrl and data connection need to use the same session
|
||||
'require_ssl_reuse=NO',
|
||||
'require_ssl_reuse=YES',
|
||||
])
|
||||
if self._ssl_implicit:
|
||||
conf.extend([
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue