1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Bug 1831: TLS session resumption is not working for FTP transfers with TLS 1.3

https://winscp.net/tracker/1831

Source commit: ccd8c878571598701a86ed2f809eec31e822654a
This commit is contained in:
Martin Prikryl
2020-03-06 14:56:17 +00:00
parent 2f713de2e6
commit 22beed90db
2 changed files with 51 additions and 35 deletions

View File

@@ -54,6 +54,7 @@ CAsyncSslSocketLayer::CAsyncSslSocketLayer()
m_Main = NULL;
m_sessionid = NULL;
m_sessionreuse = true;
m_sessionreuse_failed = false;
FCertificate = NULL;
FPrivateKey = NULL;
@@ -636,6 +637,44 @@ BOOL CAsyncSslSocketLayer::Connect(LPCTSTR lpszHostAddress, UINT nHostPort)
return res;
}
int CAsyncSslSocketLayer::NewSessionCallback(struct ssl_st * Ssl, SSL_SESSION * Session)
{
CAsyncSslSocketLayer * Layer = LookupLayer(Ssl);
int Result = 0;
if (Layer->m_sessionreuse)
{
if (Layer->m_sessionid != Session)
{
if (Layer->m_sessionid == NULL)
{
if (SSL_session_reused(Layer->m_ssl))
{
Layer->LogSocketMessageRaw(FZ_LOG_PROGRESS, L"Session ID reused");
}
else
{
if ((Layer->m_Main != NULL) && !Layer->m_Main->m_sessionreuse_failed)
{
Layer->LogSocketMessageRaw(FZ_LOG_INFO, L"Main TLS session ID not reused, will not try again");
Layer->m_Main->m_sessionreuse_failed = true;
}
}
Layer->LogSocketMessageRaw(FZ_LOG_DEBUG, L"Saving session ID");
}
else
{
SSL_SESSION_free(Layer->m_sessionid);
Layer->LogSocketMessageRaw(FZ_LOG_INFO, L"Session ID changed");
}
Layer->m_sessionid = Session;
Result = 1;
}
}
return Result;
}
int CAsyncSslSocketLayer::InitSSLConnection(bool clientMode,
CAsyncSslSocketLayer* main, bool sessionreuse,
CFileZillaTools * tools,
@@ -683,6 +722,9 @@ int CAsyncSslSocketLayer::InitSSLConnection(bool clientMode,
USES_CONVERSION;
SSL_CTX_set_verify(m_ssl_ctx, SSL_VERIFY_PEER, verify_callback);
SSL_CTX_set_client_cert_cb(m_ssl_ctx, ProvideClientCert);
// https://www.mail-archive.com/openssl-users@openssl.org/msg86186.html
SSL_CTX_set_session_cache_mode(m_ssl_ctx, SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE | SSL_SESS_CACHE_NO_AUTO_CLEAR);
SSL_CTX_sess_set_new_cb(m_ssl_ctx, NewSessionCallback);
CFileStatus Dummy;
if (CFile::GetStatus((LPCTSTR)m_CertStorage, Dummy))
{
@@ -740,7 +782,12 @@ int CAsyncSslSocketLayer::InitSSLConnection(bool clientMode,
m_sessionreuse = sessionreuse;
if ((m_Main != NULL) && m_sessionreuse)
{
if (m_Main->m_sessionid != NULL)
if (m_Main->m_sessionid == NULL)
{
DebugFail();
SSL_set_session(m_ssl, NULL);
}
else if (!m_Main->m_sessionreuse_failed)
{
if (!SSL_set_session(m_ssl, m_Main->m_sessionid))
{
@@ -882,6 +929,7 @@ void CAsyncSslSocketLayer::ResetSslSession()
m_sessionid = NULL;
}
m_sessionreuse = true;
m_sessionreuse_failed = false;
m_sCriticalSection.Unlock();
}
@@ -1119,40 +1167,6 @@ void CAsyncSslSocketLayer::apps_ssl_info_callback(const SSL *s, int where, int r
}
if (where & SSL_CB_HANDSHAKE_DONE)
{
if (pLayer->m_sessionreuse)
{
SSL_SESSION * sessionid = SSL_get1_session(pLayer->m_ssl);
if (pLayer->m_sessionid != sessionid)
{
if (pLayer->m_sessionid == NULL)
{
if (SSL_session_reused(pLayer->m_ssl))
{
pLayer->LogSocketMessageRaw(FZ_LOG_PROGRESS, L"Session ID reused");
}
else
{
if ((pLayer->m_Main != NULL) && (pLayer->m_Main->m_sessionid != NULL))
{
pLayer->LogSocketMessageRaw(FZ_LOG_INFO, L"Main TLS session ID not reused, will not try again");
SSL_SESSION_free(pLayer->m_Main->m_sessionid);
pLayer->m_Main->m_sessionid = NULL;
}
}
pLayer->LogSocketMessageRaw(FZ_LOG_DEBUG, L"Saving session ID");
}
else
{
SSL_SESSION_free(pLayer->m_sessionid);
pLayer->LogSocketMessageRaw(FZ_LOG_INFO, L"Session ID changed");
}
pLayer->m_sessionid = sessionid;
}
else
{
SSL_SESSION_free(sessionid);
}
}
int error = SSL_get_verify_result(pLayer->m_ssl);
pLayer->DoLayerCallback(LAYERCALLBACK_LAYERSPECIFIC, SSL_VERIFY_CERT, error);
pLayer->m_bBlocking = TRUE;

View File

@@ -169,6 +169,7 @@ private:
static int verify_callback(int preverify_ok, X509_STORE_CTX * ctx);
static int ProvideClientCert(
SSL * Ssl, X509 ** Certificate, EVP_PKEY ** PrivateKey);
static int NewSessionCallback(struct ssl_st * Ssl, SSL_SESSION * Session);
static CAsyncSslSocketLayer * LookupLayer(SSL * Ssl);
bool m_bUseSSL;
@@ -201,6 +202,7 @@ private:
SSL* m_ssl; // current session handle
SSL_SESSION * m_sessionid;
bool m_sessionreuse;
bool m_sessionreuse_failed;
CAsyncSslSocketLayer * m_Main;
// Data channels for encrypted/unencrypted data