Ver Fonte

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

https://winscp.net/tracker/1831

Source commit: ccd8c878571598701a86ed2f809eec31e822654a
Martin Prikryl há 5 anos atrás
pai
commit
22beed90db

+ 49 - 35
source/filezilla/AsyncSslSocketLayer.cpp

@@ -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/[email protected]/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;

+ 2 - 0
source/filezilla/AsyncSslSocketLayer.h

@@ -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