From: s_kawamoto Date: Sat, 15 Oct 2011 17:11:32 +0000 (+0900) Subject: Fix bugs of asyncronous socket control. X-Git-Url: http://git.sourceforge.jp/view?p=ffftp%2Fffftp.git;a=commitdiff_plain;h=f453e0e463e50f18f50f051f23fa08c8eb28dd54 Fix bugs of asyncronous socket control. Fix bugs of simultaneous connection. Change to reuse SSL sessions. This version may be nearly stable (not for 1.99 but for 1.98b). --- diff --git a/FFFTP_Eng_Release/FFFTP.exe b/FFFTP_Eng_Release/FFFTP.exe index c7125c4..091989f 100644 Binary files a/FFFTP_Eng_Release/FFFTP.exe and b/FFFTP_Eng_Release/FFFTP.exe differ diff --git a/Release/FFFTP.exe b/Release/FFFTP.exe index 4a6ab28..8374b77 100644 Binary files a/Release/FFFTP.exe and b/Release/FFFTP.exe differ diff --git a/common.h b/common.h index b22bbe1..beea818 100644 --- a/common.h +++ b/common.h @@ -1028,8 +1028,6 @@ typedef struct transpacket { int Mode; /* 転送モード (EXIST_xxx) */ HWND hWndTrans; /* 転送中ダイアログのウインドウハンドル */ int Abort; /* 転送中止フラグ (ABORT_xxx) */ - // 暗号化通信対応 - int CryptMode; /* 暗号化通信モード (CRYPT_xxx) */ // 同時接続対応 int ThreadCount; struct transpacket *Next; diff --git a/connect.c b/connect.c index d008b59..09fca6e 100644 --- a/connect.c +++ b/connect.c @@ -1304,7 +1304,7 @@ static SOCKET DoConnectCrypt(int CryptMode, HOSTDATA* HostData, char *Host, char // ; if(CryptMode == CRYPT_FTPIS) { - if(AttachSSL(ContSock)) + if(AttachSSL(ContSock, INVALID_SOCKET)) { while((Sts = ReadReplyMessage(ContSock, Buf, 1024, &CancelFlg, TmpBuf) / 100) == FTP_PRELIM) ; @@ -1419,7 +1419,7 @@ static SOCKET DoConnectCrypt(int CryptMode, HOSTDATA* HostData, char *Host, char { if(IsOpenSSLLoaded() && (Sts = command(ContSock, Reply, &CancelFlg, "AUTH TLS")) == 234) { - if(AttachSSL(ContSock)) + if(AttachSSL(ContSock, INVALID_SOCKET)) { if((Sts = command(ContSock, Reply, &CancelFlg, "PBSZ 0")) == 200) { diff --git a/getput.c b/getput.c index 8526053..17b5e23 100644 --- a/getput.c +++ b/getput.c @@ -107,6 +107,8 @@ static int IsSpecialDevice(char *Fname); static int MirrorDelNotify(int Cur, int Notify, TRANSPACKET *Pkt); static BOOL CALLBACK MirrorDeleteDialogCallBack(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); static void SetErrorMsg(char *fmt, ...); +// 同時接続対応 +static char* GetErrMsg(); /*===== ローカルなワーク =====*/ @@ -141,7 +143,11 @@ static int KeepDlg = NO; /* 転送中ダイアログを消さないかどうか static int MoveToForeground = NO; /* ウインドウを前面に移動するかどうか (YES/NO) */ static char CurDir[FMAX_PATH+1] = { "" }; -static char ErrMsg[ERR_MSG_LEN+7]; +// 同時接続対応 +//static char ErrMsg[ERR_MSG_LEN+7]; +static char ErrMsg[MAX_DATA_CONNECTION+1][ERR_MSG_LEN+7]; +static DWORD ErrMsgThreadId[MAX_DATA_CONNECTION+1]; +static HANDLE hErrMsgMutex; // 同時接続対応 static int WaitForMainThread = NO; @@ -175,6 +181,8 @@ int MakeTransferThread(void) hListAccMutex = CreateMutex( NULL, FALSE, NULL ); hRunMutex = CreateMutex( NULL, TRUE, NULL ); + // 同時接続対応 + hErrMsgMutex = CreateMutex( NULL, FALSE, NULL ); ClearAll = NO; ForceAbort = NO; @@ -236,6 +244,8 @@ void CloseTransferThread(void) CloseHandle( hListAccMutex ); CloseHandle( hRunMutex ); + // 同時接続対応 + CloseHandle( hErrMsgMutex ); return; } @@ -682,7 +692,8 @@ static ULONG WINAPI TransferThread(void *Dummy) BackgrndMessageProc(); Sleep(1); } - memset(ErrMsg, NUL, ERR_MSG_LEN+7); +// memset(ErrMsg, NUL, ERR_MSG_LEN+7); + memset(GetErrMsg(), NUL, ERR_MSG_LEN+7); // Canceled = NO; Canceled[ThreadCount] = NO; @@ -1304,12 +1315,12 @@ static int DownLoadNonPassive(TRANSPACKET *Pkt, int *CancelCheckWork) ReleaseMutex(hListAccMutex); // FTPS対応 // iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); - if(AskCryptMode() == CRYPT_FTPES || AskCryptMode() == CRYPT_FTPIS) + if(IsSSLAttached(Pkt->ctrl_skt)) { - if(AttachSSL(data_socket)) + if(AttachSSL(data_socket, Pkt->ctrl_skt)) iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); else - iRetCode = FTP_ERROR; + iRetCode = 500; } else iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); @@ -1380,12 +1391,12 @@ static int DownLoadPassive(TRANSPACKET *Pkt, int *CancelCheckWork) ReleaseMutex(hListAccMutex); // FTPS対応 // iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); - if(AskCryptMode() == CRYPT_FTPES || AskCryptMode() == CRYPT_FTPIS) + if(IsSSLAttached(Pkt->ctrl_skt)) { - if(AttachSSL(data_socket)) + if(AttachSSL(data_socket, Pkt->ctrl_skt)) iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); else - iRetCode = FTP_ERROR; + iRetCode = 500; } else iRetCode = DownLoadFile(Pkt, data_socket, CreateMode, CancelCheckWork); @@ -2094,7 +2105,9 @@ static BOOL CALLBACK UpDownErrorDialogProc(HWND hDlg, UINT message, WPARAM wPara { case WM_INITDIALOG : SendDlgItemMessage(hDlg, UPDOWN_ERR_FNAME, WM_SETTEXT, 0, (LPARAM)lParam); - SendDlgItemMessage(hDlg, UPDOWN_ERR_MSG, WM_SETTEXT, 0, (LPARAM)ErrMsg); + // 同時接続対応 +// SendDlgItemMessage(hDlg, UPDOWN_ERR_MSG, WM_SETTEXT, 0, (LPARAM)ErrMsg); + SendDlgItemMessage(hDlg, UPDOWN_ERR_MSG, WM_SETTEXT, 0, (LPARAM)GetErrMsg()); return(TRUE); case WM_COMMAND : @@ -2340,12 +2353,12 @@ static int UpLoadNonPassive(TRANSPACKET *Pkt) ReleaseMutex(hListAccMutex); // FTPS対応 // iRetCode = UpLoadFile(Pkt, data_socket); - if(AskCryptMode() == CRYPT_FTPES || AskCryptMode() == CRYPT_FTPIS) + if(IsSSLAttached(Pkt->ctrl_skt)) { - if(AttachSSL(data_socket)) + if(AttachSSL(data_socket, Pkt->ctrl_skt)) iRetCode = UpLoadFile(Pkt, data_socket); else - iRetCode = FTP_ERROR; + iRetCode = 500; } else iRetCode = UpLoadFile(Pkt, data_socket); @@ -2422,12 +2435,12 @@ static int UpLoadPassive(TRANSPACKET *Pkt) ReleaseMutex(hListAccMutex); // FTPS対応 // iRetCode = UpLoadFile(Pkt, data_socket); - if(AskCryptMode() == CRYPT_FTPES || AskCryptMode() == CRYPT_FTPIS) + if(IsSSLAttached(Pkt->ctrl_skt)) { - if(AttachSSL(data_socket)) + if(AttachSSL(data_socket, Pkt->ctrl_skt)) iRetCode = UpLoadFile(Pkt, data_socket); else - iRetCode = FTP_ERROR; + iRetCode = 500; } else iRetCode = UpLoadFile(Pkt, data_socket); @@ -3561,10 +3574,14 @@ static void SetErrorMsg(char *fmt, ...) { va_list Args; - if(strlen(ErrMsg) == 0) + // 同時接続対応 +// if(strlen(ErrMsg) == 0) + if(strlen(GetErrMsg()) == 0) { va_start(Args, fmt); - wvsprintf(ErrMsg, fmt, Args); + // 同時接続対応 +// wvsprintf(ErrMsg, fmt, Args); + wvsprintf(GetErrMsg(), fmt, Args); va_end(Args); } return; @@ -3606,3 +3623,39 @@ int CheckPathViolation(TRANSPACKET *packet) } +// 同時接続対応 +static char* GetErrMsg() +{ + char* r; + DWORD ThreadId; + int i; + r = NULL; + WaitForSingleObject(hErrMsgMutex, INFINITE); + ThreadId = GetCurrentThreadId(); + i = 0; + while(i < MAX_DATA_CONNECTION + 1) + { + if(ErrMsgThreadId[i] == ThreadId) + { + r = ErrMsg[i]; + break; + } + i++; + } + if(!r) + { + i = 0; + while(i < MAX_DATA_CONNECTION + 1) + { + if(ErrMsgThreadId[i] == 0) + { + ErrMsgThreadId[i] = ThreadId; + r = ErrMsg[i]; + break; + } + i++; + } + } + ReleaseMutex(hErrMsgMutex); + return r; +} diff --git a/socket.c b/socket.c index b3d4163..8773978 100644 --- a/socket.c +++ b/socket.c @@ -271,6 +271,8 @@ static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LP break; case WM_ASYNC_DBASE : + // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり + RegistAsyncTableDbase((HANDLE)wParam); // スレッド衝突のバグ修正 WaitForSingleObject(hAsyncTblAccMutex, INFINITE); for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++) @@ -291,31 +293,6 @@ static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LP break; } } - // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり - if(Pos == MAX_SIGNAL_ENTRY_DBASE) - { - for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++) - { - if(SignalDbase[Pos].Async == 0) - { - SignalDbase[Pos].Async = (HANDLE)wParam; - SignalDbase[Pos].Done = 0; - SignalDbase[Pos].ErrorDb = 0; - if(HIWORD(lParam) != 0) - { - SignalDbase[Pos].ErrorDb = 1; -#if DBG_MSG - DoPrintf("##### SignalDatabase: error"); -#endif - } - SignalDbase[Pos].Done = 1; -#if DBG_MSG - DoPrintf("##### SignalDatabase: Done"); -#endif - break; - } - } - } // スレッド衝突のバグ修正 ReleaseMutex(hAsyncTblAccMutex); break; @@ -738,6 +715,9 @@ int do_closesocket(SOCKET s) #endif CancelCheckWork = NO; + // スレッド衝突のバグ修正 + WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0); + UnRegistAsyncTable(s); // FTPS対応 // Ret = closesocket(s); Ret = closesocketS(s); @@ -755,10 +735,12 @@ int do_closesocket(SOCKET s) Ret = 0; } - WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0); + // スレッド衝突のバグ修正 +// WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0); if(BackgrndMessageProc() == YES) CancelCheckWork = YES; - UnRegistAsyncTable(s); + // スレッド衝突のバグ修正 +// UnRegistAsyncTable(s); #if DBG_MSG DoPrintf("# Exit close"); diff --git a/socketwrapper.c b/socketwrapper.c index 48ebfcf..acf23c3 100644 --- a/socketwrapper.c +++ b/socketwrapper.c @@ -30,6 +30,8 @@ typedef int (__cdecl* _SSL_read)(SSL*, void*, int); typedef int (__cdecl* _SSL_get_error)(SSL*, int); typedef X509* (__cdecl* _SSL_get_peer_certificate)(const SSL*); typedef long (__cdecl* _SSL_get_verify_result)(const SSL*); +typedef SSL_SESSION* (__cdecl* _SSL_get_session)(SSL*); +typedef int (__cdecl* _SSL_set_session)(SSL*, SSL_SESSION*); typedef BIO_METHOD* (__cdecl* _BIO_s_mem)(); typedef BIO* (__cdecl* _BIO_new)(BIO_METHOD*); typedef int (__cdecl* _BIO_free)(BIO*); @@ -37,7 +39,6 @@ typedef long (__cdecl* _BIO_ctrl)(BIO*, int, long, void*); typedef void (__cdecl* _X509_free)(X509*); typedef int (__cdecl* _X509_print_ex)(BIO*, X509*, unsigned long, unsigned long); typedef X509_NAME* (__cdecl* _X509_get_subject_name)(X509*); -typedef X509_NAME* (__cdecl* _X509_get_issuer_name)(X509*); typedef int (__cdecl* _X509_NAME_print_ex)(BIO*, X509_NAME*, int, unsigned long); _SSL_load_error_strings p_SSL_load_error_strings; @@ -58,6 +59,8 @@ _SSL_read p_SSL_read; _SSL_get_error p_SSL_get_error; _SSL_get_peer_certificate p_SSL_get_peer_certificate; _SSL_get_verify_result p_SSL_get_verify_result; +_SSL_get_session p_SSL_get_session; +_SSL_set_session p_SSL_set_session; _BIO_s_mem p_BIO_s_mem; _BIO_new p_BIO_new; _BIO_free p_BIO_free; @@ -65,7 +68,6 @@ _BIO_ctrl p_BIO_ctrl; _X509_free p_X509_free; _X509_print_ex p_X509_print_ex; _X509_get_subject_name p_X509_get_subject_name; -_X509_get_issuer_name p_X509_get_issuer_name; _X509_NAME_print_ex p_X509_NAME_print_ex; #define MAX_SSL_SOCKET 64 @@ -124,7 +126,9 @@ BOOL LoadOpenSSL() || !(p_SSL_read = (_SSL_read)GetProcAddress(g_hOpenSSL, "SSL_read")) || !(p_SSL_get_error = (_SSL_get_error)GetProcAddress(g_hOpenSSL, "SSL_get_error")) || !(p_SSL_get_peer_certificate = (_SSL_get_peer_certificate)GetProcAddress(g_hOpenSSL, "SSL_get_peer_certificate")) - || !(p_SSL_get_verify_result = (_SSL_get_verify_result)GetProcAddress(g_hOpenSSL, "SSL_get_verify_result"))) + || !(p_SSL_get_verify_result = (_SSL_get_verify_result)GetProcAddress(g_hOpenSSL, "SSL_get_verify_result")) + || !(p_SSL_get_session = (_SSL_get_session)GetProcAddress(g_hOpenSSL, "SSL_get_session")) + || !(p_SSL_set_session = (_SSL_set_session)GetProcAddress(g_hOpenSSL, "SSL_set_session"))) { if(g_hOpenSSL) FreeLibrary(g_hOpenSSL); @@ -140,7 +144,6 @@ BOOL LoadOpenSSL() || !(p_X509_free = (_X509_free)GetProcAddress(g_hOpenSSLCommon, "X509_free")) || !(p_X509_print_ex = (_X509_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_print_ex")) || !(p_X509_get_subject_name = (_X509_get_subject_name)GetProcAddress(g_hOpenSSLCommon, "X509_get_subject_name")) - || !(p_X509_get_issuer_name = (_X509_get_issuer_name)GetProcAddress(g_hOpenSSLCommon, "X509_get_issuer_name")) || !(p_X509_NAME_print_ex = (_X509_NAME_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_NAME_print_ex"))) { if(g_hOpenSSL) @@ -330,11 +333,13 @@ BOOL IsHostNameMatched(LPCSTR HostName, LPCSTR CommonName) return bResult; } -BOOL AttachSSL(SOCKET s) +BOOL AttachSSL(SOCKET s, SOCKET parent) { BOOL r; DWORD Time; SSL** ppSSL; + SSL** ppSSLParent; + SSL_SESSION* pSession; if(!g_bOpenSSLLoaded) return FALSE; r = FALSE; @@ -350,8 +355,20 @@ BOOL AttachSSL(SOCKET s) { if(p_SSL_set_fd(*ppSSL, s) != 0) { - r = TRUE; + if(parent != INVALID_SOCKET) + { + if(ppSSLParent = FindSSLPointerFromSocket(parent)) + { + if(pSession = p_SSL_get_session(*ppSSLParent)) + { + if(p_SSL_set_session(*ppSSL, pSession) == 1) + { + } + } + } + } // SSLのネゴシエーションには時間がかかる場合がある + r = TRUE; while(p_SSL_connect(*ppSSL) != 1) { LeaveCriticalSection(&g_OpenSSLLock); @@ -364,6 +381,14 @@ BOOL AttachSSL(SOCKET s) } EnterCriticalSection(&g_OpenSSLLock); } + if(ConfirmSSLCertificate(*ppSSL)) + { + } + else + { + DetachSSL(s); + r = FALSE; + } } else { @@ -371,14 +396,6 @@ BOOL AttachSSL(SOCKET s) DetachSSL(s); EnterCriticalSection(&g_OpenSSLLock); } - if(ConfirmSSLCertificate(*ppSSL)) - { - } - else - { - DetachSSL(s); - r = FALSE; - } } } } @@ -437,7 +454,7 @@ SOCKET acceptS(SOCKET s, struct sockaddr *addr, int *addrlen) { SOCKET r; r = accept(s, addr, addrlen); - if(!AttachSSL(r)) + if(!AttachSSL(r, INVALID_SOCKET)) { closesocket(r); return INVALID_SOCKET; @@ -449,7 +466,7 @@ int connectS(SOCKET s, const struct sockaddr *name, int namelen) { int r; r = connect(s, name, namelen); - if(!AttachSSL(r)) + if(!AttachSSL(r, INVALID_SOCKET)) return SOCKET_ERROR; return r; } diff --git a/socketwrapper.h b/socketwrapper.h index 7556d10..574d915 100644 --- a/socketwrapper.h +++ b/socketwrapper.h @@ -16,7 +16,7 @@ BOOL IsOpenSSLLoaded(); void SetSSLTimeoutCallback(DWORD Timeout, LPSSLTIMEOUTCALLBACK pCallback); void SetSSLConfirmCallback(LPSSLCONFIRMCALLBACK pCallback); BOOL IsHostNameMatched(LPCSTR HostName, LPCSTR CommonName); -BOOL AttachSSL(SOCKET s); +BOOL AttachSSL(SOCKET s, SOCKET parent); BOOL DetachSSL(SOCKET s); BOOL IsSSLAttached(SOCKET s); SOCKET socketS(int af, int type, int protocol);