Tommy 碎碎念

Tommy Wu's blog

« 上一篇 | 下一篇 »

修正 FileZilla 在同時使用多個 TLS 連線時, 只會有一個成功的問題.
post by tommy @ 17 六月, 2006 13:20
前一篇文章所提到的這個問題, 在經過近一天的追蹤後, 終於被我發現原因了. 這個問題並非只影響到 TLS 同時連線, 就算是非同時連線, 也可能發生.

這個問題, 只會發生在下列的情形:

  1. 有限定 FileZilla 所使用的 port 的範圍.
  2. 同時產生 CFtpControlSocket 物件, 所以程式在呼叫 srand() 時, 會傳入同一個種子. 後頭產生的亂數會一樣. (非必要, 只不過因為這樣, 會在同時連線的情形發生問題)
  3. 有使用 SSL/TLS 或 GSS 或 Proxy 等額外的 layer, 非單經的 TCP/IP 連線.
  4. 在 bind socket 時, 因為有限制 port 的範圍, 所以並非傳入 0, 由系統選取任意 port, 而是程式會亂數取該範圍的值, 然後依序試著去 bind 看有沒有被使用掉.
  5. port 的選取, 如果剛好選到被用掉的 port 時, 在 bind() 會失敗, 接下去會做一些 Close() 的動作, 清除掉 CFtpControlSocket 物件的一些值, 然後... 再次嘗試下一個 port 時, 就失去這些額外的 layer 設定, 而變成一個單純的 TCP/IP 連線. 雖然連線會成功, 但是後續 layer 上頭的動作會失敗.

所以, 只要是用到不能用的 port, 就會發生這個問題. 就算不是同時使用, 就算亂數的種子是不同的, 仍有可能發生. 會變成一個隨機發生的問題.

我的這個 patch, 會在 bind 失敗時, 再重新設定那些原本在 Connect 所設定的值, 然後再試下一個 port. 目前看來, 在我這兒的運作是正常的.

diff -Nur source.orig/FtpControlSocket.cpp source/FtpControlSocket.cpp
--- source.orig/FtpControlSocket.cpp Fri May 26 14:24:30 2006
+++ source/FtpControlSocket.cpp Sat Jun 17 13:01:58 2006
@@ -198,7 +198,7 @@
#define CONNECT_OPTSUTF8 -15
#define CONNECT_CLNT -16

-void CFtpControlSocket::Connect(t_server &server)
+BOOL CFtpControlSocket::InitConnect(t_server &server)
{
USES_CONVERSION;

@@ -219,14 +219,14 @@
if (!m_Operation.nOpMode)
m_Operation.nOpMode = CSMODE_CONNECT;
DoClose(FZ_REPLY_CRITICALERROR);
- return;
+ return FALSE;
}
if (m_Operation.nOpMode)
{
ShowStatus(_T("Internal error: m_Operation.nOpMode not zero in Connect"), 1);
m_Operation.nOpMode = CSMODE_CONNECT;
DoClose(FZ_REPLY_CRITICALERROR);
- return;
+ return FALSE;
}

m_Operation.nOpMode = CSMODE_CONNECT;
@@ -235,13 +235,13 @@
{
ShowStatus(_T("Internal error: m_pSslLayer not zero in Connect"), 1);
DoClose(FZ_REPLY_CRITICALERROR);
- return;
+ return FALSE;
}
if (m_pProxyLayer)
{
ShowStatus(_T("Internal error: m_pProxyLayer not zero in Connect"), 1);
DoClose(FZ_REPLY_CRITICALERROR);
- return;
+ return FALSE;
}

if (server.nServerType & FZ_SERVERTYPE_LAYER_SSL_IMPLICIT ||
@@ -328,11 +328,20 @@
{
ShowStatus(_T("Unable to initialize GSS api"), 1);
DoClose(FZ_REPLY_CRITICALERROR);
- return;
+ return FALSE;
}
}
m_Operation.nOpState = m_pGssLayer?CONNECT_GSS_INIT:CONNECT_INIT;
m_Operation.nOpMode = CSMODE_CONNECT;
+ return TRUE;
+}
+
+void CFtpControlSocket::Connect(t_server &server)
+{
+ USES_CONVERSION;
+
+ m_server = server;
+ if (!InitConnect(server)) return;

if (!Create())
{
@@ -3964,6 +3973,8 @@
ShowStatus(IDS_ERRORMSG_CANTCREATEDUETOPORTRANGE,1);
return FALSE;
}
+ m_Operation.nOpMode = 0;
+ if (!InitConnect(m_server)) return FALSE;
}
}
return TRUE;
diff -Nur source.orig/FtpControlSocket.h source/FtpControlSocket.h
--- source.orig/FtpControlSocket.h Fri May 26 14:19:06 2006
+++ source/FtpControlSocket.h Sat Jun 17 12:57:15 2006
@@ -49,6 +49,8 @@

// �berschreibungen
public:
+ t_server m_server;
+ BOOL InitConnect(t_server &server);
virtual void Connect(t_server &server);
virtual void OnTimer();
virtual BOOL IsReady();
 

可以到這兒抓這個 patch, 與使用這個 patch 加上 sftp UTF8 支援的版本:

http://www.teatime.com.tw/~tommy/mypatch/fz2224_ssl_connect.patch
http://www.teatime.com.tw/~tommy/filezilla.zip 

我不確定作者是否會採用我的作法, 因為有點 ugly. 不過就算不是這樣子, 也應該會解決這個問題吧.


2006/6/17: 下午作者回覆, 參考我的作法, 他做了一些修正, 已經放到 CVS 中了.

 

Del.icio.us Furl HEMiDEMi Technorati MyShare
迴響
暱稱:
標題:
個人網頁:
電子郵件:
authimage

迴響

  

Bad Behavior 已經阻擋了 60 個過去 7 天試圖闖關的垃圾迴響與引用。
Power by LifeType. Template design by JamesHuang. Valid XHTML and CSS