Server : Apache/2.4.43 (Win64) OpenSSL/1.1.1g PHP/7.4.6 System : Windows NT USER-PC 6.1 build 7601 (Windows 7 Professional Edition Service Pack 1) AMD64 User : User ( 0) PHP Version : 7.4.6 Disable Function : NONE Directory : C:/xampp/FileZillaFTP/source/interface/ |
// FileZilla Server - a Windows ftp server // Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de> // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // AdminSocket.cpp: Implementierung der Klasse CAdminSocket. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "AdminSocket.h" #include "MainFrm.h" #include "../iputils.h" #include "../OptionTypes.h" #include "../platform.h" #include "../misc\md5.h" ////////////////////////////////////////////////////////////////////// // Konstruktion/Destruktion ////////////////////////////////////////////////////////////////////// #define BUFSIZE 4096 CAdminSocket::CAdminSocket(CMainFrame *pMainFrame) { ASSERT(pMainFrame); m_pMainFrame = pMainFrame; m_pRecvBuffer = new unsigned char[BUFSIZE]; m_nRecvBufferLen = BUFSIZE; m_nRecvBufferPos = 0; m_nConnectionState = 0; m_bClosed = FALSE; } CAdminSocket::~CAdminSocket() { delete [] m_pRecvBuffer; for (std::list<t_data>::iterator iter=m_SendBuffer.begin(); iter!=m_SendBuffer.end(); iter++) delete [] iter->pData; } void CAdminSocket::OnConnect(int nErrorCode) { if (!nErrorCode) { if (!m_nConnectionState) { m_pMainFrame->ShowStatus(_T("Connected, waiting for authentication"), 0); m_nConnectionState = 1; } m_pMainFrame->OnAdminInterfaceConnected(); } else { m_pMainFrame->ShowStatus(_T("Error, could not connect to server"), 1); Close(); } } void CAdminSocket::OnReceive(int nErrorCode) { if (nErrorCode) { m_pMainFrame->ShowStatus(_T("OnReceive failed, closing connection"), 1); Close(); return; } if (!m_nConnectionState) { m_pMainFrame->ShowStatus(_T("Connected, waiting for authentication"), 0); m_nConnectionState = 1; } int numread = Receive(m_pRecvBuffer + m_nRecvBufferPos, m_nRecvBufferLen - m_nRecvBufferPos); if (numread > 0) { m_nRecvBufferPos += numread; if (m_nRecvBufferLen-m_nRecvBufferPos < (BUFSIZE/4)) { unsigned char *tmp = m_pRecvBuffer; m_nRecvBufferLen += BUFSIZE; m_pRecvBuffer = new unsigned char[m_nRecvBufferLen]; memcpy(m_pRecvBuffer, tmp, m_nRecvBufferPos); delete [] tmp; } } if (!numread) { Close(); return; } else if (numread == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { Close(); return; } } while (ParseRecvBuffer()); } void CAdminSocket::OnSend(int nErrorCode) { if (nErrorCode) { Close(); return; } if (!m_nConnectionState) return; while (!m_SendBuffer.empty()) { t_data data = m_SendBuffer.front(); int nSent = Send(data.pData + data.dwOffset, data.dwLength - data.dwOffset); if (!nSent) { Close(); return; } if (nSent == SOCKET_ERROR) { if (WSAGetLastError()!=WSAEWOULDBLOCK) Close(); return; } if ((DWORD)nSent < (data.dwLength - data.dwOffset)) data.dwOffset += nSent; else { m_SendBuffer.pop_front(); delete [] data.pData; } } } void CAdminSocket::Close() { if (m_nConnectionState) m_pMainFrame->ShowStatus(_T("Connection to server closed."), 1); m_nConnectionState = 0; if (!m_bClosed) { m_bClosed = TRUE; m_pMainFrame->PostMessage(WM_APP + 1, 0, 0); } } BOOL CAdminSocket::ParseRecvBuffer() { DWORD len; switch (m_nConnectionState) { case 1: { if (m_nRecvBufferPos<3) return FALSE; if (m_pRecvBuffer[0] != 'F' || m_pRecvBuffer[1] != 'Z' || m_pRecvBuffer[2] != 'S') { CString str; str.Format(_T("Protocol error: Unknown protocol identifier (0x%d 0x%d 0x%d). Most likely connected to the wrong port."), (int)m_pRecvBuffer[0], (int)m_pRecvBuffer[1], (int)m_pRecvBuffer[2]); m_pMainFrame->ShowStatus(str, 1); Close(); return FALSE; } if (m_nRecvBufferPos < 5) return FALSE; len = m_pRecvBuffer[3] * 256 + m_pRecvBuffer[4]; if (len != 4) { CString str; str.Format(_T("Protocol error: Invalid server version length (%d)."), len); m_pMainFrame->ShowStatus(str, 1); Close(); return FALSE; } if (m_nRecvBufferPos < 9) return FALSE; int version = (int)GET32(m_pRecvBuffer + 5); if (version != SERVER_VERSION) { CString str; str.Format(_T("Protocol warning: Server version mismatch: Server version is %d.%d.%d.%d, interface version is %d.%d.%d.%d"), (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, (version >> 0) & 0xFF, (SERVER_VERSION >> 24) & 0xFF, (SERVER_VERSION >> 16) & 0xFF, (SERVER_VERSION >> 8) & 0xFF, (SERVER_VERSION >> 0) & 0xFF); m_pMainFrame->ShowStatus(str, 1); } if (m_nRecvBufferPos<11) return FALSE; len = m_pRecvBuffer[9] * 256 + m_pRecvBuffer[10]; if (len != 4) { CString str; str.Format(_T("Protocol error: Invalid protocol version length (%d)."), len); m_pMainFrame->ShowStatus(str, 1); Close(); return FALSE; } if (m_nRecvBufferPos<15) return FALSE; version = (int)GET32(m_pRecvBuffer + 11); if (version != PROTOCOL_VERSION) { CString str; str.Format(_T("Protocol error: Protocol version mismatch: Server protocol version is %d.%d.%d.%d, interface protocol version is %d.%d.%d.%d"), (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, (version >> 0) & 0xFF, (PROTOCOL_VERSION >> 24) & 0xFF, (PROTOCOL_VERSION >> 16) & 0xFF, (PROTOCOL_VERSION >> 8) & 0xFF, (PROTOCOL_VERSION >> 0) & 0xFF); m_pMainFrame->ShowStatus(str, 1); Close(); return FALSE; } memmove(m_pRecvBuffer, m_pRecvBuffer+15, m_nRecvBufferPos-15); m_nRecvBufferPos-=15; m_nConnectionState = 2; } break; case 2: if (m_nRecvBufferPos<5) return FALSE; if ((m_pRecvBuffer[0]&0x03) > 2) { CString str; str.Format(_T("Protocol error: Unknown command type (%d), closing connection."), (int)(m_pRecvBuffer[0]&0x03)); m_pMainFrame->ShowStatus(str, 1); Close(); return FALSE; } len = (int)GET32(m_pRecvBuffer + 1); if (len + 5 <= m_nRecvBufferPos) { if ((m_pRecvBuffer[0]&0x03) == 0 && (m_pRecvBuffer[0]&0x7C)>>2 == 0) { if (len<4) { m_pMainFrame->ShowStatus(_T("Invalid auth data"), 1); Close(); return FALSE; } unsigned char *p = m_pRecvBuffer + 5; unsigned int noncelen1 = *p*256 + p[1]; if ((noncelen1+2) > (len-2)) { m_pMainFrame->ShowStatus(_T("Invalid auth data"), 1); Close(); return FALSE; } unsigned int noncelen2 = p[2 + noncelen1]*256 + p[2 + noncelen1 +1]; if ((noncelen1+noncelen2+4) > len) { m_pMainFrame->ShowStatus(_T("Invalid auth data"), 1); Close(); return FALSE; } MD5 md5; if (noncelen1) md5.update(p+2, noncelen1); char* utf8 = ConvToNetwork(m_Password); if (!utf8) { m_pMainFrame->ShowStatus(_T("Can't convert password to UTF-8"), 1); Close(); return FALSE; } md5.update((const unsigned char *)utf8, strlen(utf8)); delete [] utf8; if (noncelen2) md5.update(p+noncelen1+4, noncelen2); md5.finalize(); memmove(m_pRecvBuffer, m_pRecvBuffer+len+5, m_nRecvBufferPos-len-5); m_nRecvBufferPos-=len+5; unsigned char *digest = md5.raw_digest(); SendCommand(0, digest, 16); delete [] digest; m_nConnectionState=3; return TRUE; } else if ((m_pRecvBuffer[0]&0x03) == 1 && (m_pRecvBuffer[0]&0x7C)>>2 == 0) { m_nConnectionState=3; m_pMainFrame->ParseReply((m_pRecvBuffer[0]&0x7C)>>2, m_pRecvBuffer+5, len); } else { CString str; str.Format(_T("Protocol error: Unknown command ID (%d), closing connection."), (int)(m_pRecvBuffer[0]&0x7C)>>2); m_pMainFrame->ShowStatus(str, 1); Close(); return FALSE; } memmove(m_pRecvBuffer, m_pRecvBuffer+len+5, m_nRecvBufferPos-len-5); m_nRecvBufferPos-=len+5; } break; case 3: if (m_nRecvBufferPos < 5) return FALSE; int nType = *m_pRecvBuffer & 0x03; int nID = (*m_pRecvBuffer & 0x7C) >> 2; if (nType > 2 || nType < 1) { CString str; str.Format(_T("Protocol error: Unknown command type (%d), closing connection."), nType); m_pMainFrame->ShowStatus(str, 1); Close(); return FALSE; } else { len = (unsigned int)GET32(m_pRecvBuffer + 1); if (len > 0xFFFFFF) { CString str; str.Format(_T("Protocol error: Invalid data length (%u) for command (%d:%d)"), len, nType, nID); m_pMainFrame->ShowStatus(str, 1); Close(); return FALSE; } if (m_nRecvBufferPos < len+5) return FALSE; else { if (nType == 1) m_pMainFrame->ParseReply(nID, m_pRecvBuffer + 5, len); else if (nType == 2) m_pMainFrame->ParseStatus(nID, m_pRecvBuffer + 5, len); else { CString str; str.Format(_T("Protocol warning: Command type %d not implemented."), nType); m_pMainFrame->ShowStatus(str, 1); } memmove(m_pRecvBuffer, m_pRecvBuffer+len+5, m_nRecvBufferPos-len-5); m_nRecvBufferPos-=len+5; } } break; } return TRUE; } BOOL CAdminSocket::SendCommand(int nType) { t_data data; data.pData = new unsigned char[5]; data.pData[0] = nType << 2; data.dwOffset = 0; DWORD dwDataLength = 0; memcpy(data.pData + 1, &dwDataLength, 4); data.dwLength = 5; m_SendBuffer.push_back(data); do { data=m_SendBuffer.front(); int nSent = Send(data.pData+data.dwOffset, data.dwLength-data.dwOffset); if (!nSent) { Close(); return FALSE; } if (nSent == SOCKET_ERROR) { if (WSAGetLastError()!=WSAEWOULDBLOCK) { Close(); return FALSE; } return TRUE; } if ((DWORD)nSent < (data.dwLength-data.dwOffset)) data.dwOffset+=nSent; else { m_SendBuffer.pop_front(); delete [] data.pData; } } while (!m_SendBuffer.empty()); return TRUE; } BOOL CAdminSocket::SendCommand(int nType, void *pData, int nDataLength) { ASSERT((pData && nDataLength) || (!pData && !nDataLength)); t_data data; data.pData = new unsigned char[nDataLength+5]; data.pData[0] = nType << 2; data.dwOffset = 0; memcpy(data.pData + 1, &nDataLength, 4); if (pData) memcpy(data.pData+5, pData, nDataLength); data.dwLength = nDataLength + 5; m_SendBuffer.push_back(data); do { data=m_SendBuffer.front(); int nSent = Send(data.pData+data.dwOffset, data.dwLength-data.dwOffset); if (!nSent) { Close(); return FALSE; } if (nSent == SOCKET_ERROR) { if (WSAGetLastError()!=WSAEWOULDBLOCK) { Close(); return FALSE; } return TRUE; } if ((DWORD)nSent < (data.dwLength-data.dwOffset)) data.dwOffset += nSent; else { m_SendBuffer.pop_front(); delete [] data.pData; } } while (!m_SendBuffer.empty()); return TRUE; } BOOL CAdminSocket::IsConnected() { return m_nConnectionState == 3; } void CAdminSocket::OnClose(int nErrorCode) { Close(); } void CAdminSocket::DoClose() { m_bClosed = true; Close(); } bool CAdminSocket::IsLocal() { CString ip; UINT port; if (!GetPeerName(ip, port)) return false; return IsLocalhost(ip); }