home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 217 / DPCS0306DVD.ISO / Toolkit / Internet / FileZilla / Server / FileZilla_Server-0.9.11.exe / source / AdminSocket.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-01-21  |  9.3 KB  |  417 lines

  1. // FileZilla Server - a Windows ftp server
  2.  
  3. // Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
  4.  
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9.  
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. // AdminSocket.cpp: Implementierung der Klasse CAdminSocket.
  20. //
  21. //////////////////////////////////////////////////////////////////////
  22.  
  23. #include "stdafx.h"
  24. #include "AdminSocket.h"
  25. #include "AdminInterface.h"
  26. #include "OptionTypes.h"
  27. #include "misc\md5.h"
  28. #include "Options.h"
  29. #include "version.h"
  30.  
  31. #define BUFSIZE 4096
  32.  
  33. //////////////////////////////////////////////////////////////////////
  34. // Konstruktion/Destruktion
  35. //////////////////////////////////////////////////////////////////////
  36.  
  37. CAdminSocket::CAdminSocket(CAdminInterface *pAdminInterface)
  38. {
  39.     ASSERT(pAdminInterface);
  40.     m_pAdminInterface = pAdminInterface;
  41.     m_bStillNeedAuth = TRUE;
  42.  
  43.     m_pRecvBuffer = new unsigned char[BUFSIZE];
  44.     m_nRecvBufferLen = BUFSIZE;
  45.     m_nRecvBufferPos = 0;
  46.     
  47.     SYSTEMTIME sTime;
  48.     GetSystemTime(&sTime);
  49.     VERIFY(SystemTimeToFileTime(&sTime, &m_LastRecvTime));
  50. }
  51.  
  52. CAdminSocket::~CAdminSocket()
  53. {
  54.     for (std::list<t_data>::iterator iter=m_SendBuffer.begin(); iter!=m_SendBuffer.end(); iter++)
  55.         delete [] iter->pData;
  56.  
  57.     delete [] m_pRecvBuffer;
  58. }
  59.  
  60. BOOL CAdminSocket::Init()
  61. {
  62.     char *buffer=new char[100];
  63.     char *p=buffer;
  64.     strcpy(buffer, "FZS");
  65.     p+=3;
  66.  
  67.     *p++=0;
  68.     *p++=4;
  69.     memcpy(p, &SERVER_VERSION, 4);
  70.     p+=4;
  71.     
  72.     *p++=0;
  73.     *p++=4;
  74.  
  75.     memcpy(p, &PROTOCOL_VERSION, 4);
  76.     p+=4;
  77.  
  78.     SOCKADDR_IN sockAddr;
  79.     memset(&sockAddr, 0, sizeof(sockAddr));
  80.  
  81.     int nSockAddrLen = sizeof(sockAddr);
  82.     
  83.     if (GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen) && sockAddr.sin_addr.S_un.S_addr == 0x0100007f)
  84.     {
  85.         BOOL res=Send(buffer, p-buffer) == p-buffer;
  86.         delete [] buffer;
  87.         if (!res)
  88.         {
  89.             Close();
  90.             return FALSE;
  91.         }
  92.         return FinishLogon();        
  93.     }
  94.     else
  95.     {
  96.         *p++=0;
  97.         
  98.         DWORD len = 20;
  99.         memcpy(p, &len, 4);
  100.         p+=4;
  101.  
  102.         *p++=0;
  103.         *p++=8;
  104.         
  105.         int i;
  106.         for (i=0;i<8; i++)
  107.         {
  108.             m_Nonce1[i]=(rand()*256)/(RAND_MAX+1);
  109.             *p++=m_Nonce1[i];
  110.         }
  111.         
  112.         *p++=0;
  113.         *p++=8;
  114.         
  115.         for (i=0;i<8; i++)
  116.         {
  117.             m_Nonce2[i]=(rand()*256)/(RAND_MAX+1);
  118.             *p++=m_Nonce2[i];
  119.         }
  120.     }
  121.  
  122.     int res=Send(buffer, p-buffer) == p-buffer;
  123.     delete [] buffer;
  124.     return res;
  125. }
  126.  
  127. BOOL CAdminSocket::SendCommand(int nType, int nID, const void *pData, int nDataLength)
  128. {
  129.     if (m_bStillNeedAuth)
  130.         return TRUE;
  131.  
  132.     t_data data;
  133.     data.pData = new unsigned char[nDataLength+5];
  134.     *data.pData=nType;
  135.     *data.pData |= nID << 2;
  136.     data.dwOffset = 0;
  137.     memcpy(data.pData + 1, &nDataLength, 4);
  138.     if (pData)
  139.         memcpy(data.pData+5, pData, nDataLength);
  140.  
  141.     data.dwLength = nDataLength + 5;
  142.  
  143.     m_SendBuffer.push_back(data);
  144.     
  145.     do
  146.     {
  147.         data=m_SendBuffer.front();
  148.         int nSent = Send(data.pData+data.dwOffset, data.dwLength-data.dwOffset);
  149.         if (!nSent)
  150.             return FALSE;
  151.         if (nSent == SOCKET_ERROR)
  152.         {
  153.             if (WSAGetLastError()!=WSAEWOULDBLOCK)
  154.                 return FALSE;
  155.             return TRUE;
  156.         }
  157.         
  158.         if ((unsigned int)nSent<(data.dwLength-data.dwOffset))
  159.             data.dwOffset+=nSent;
  160.         else
  161.         {
  162.             m_SendBuffer.pop_front();
  163.             delete [] data.pData;
  164.  
  165.             SYSTEMTIME sTime;
  166.             GetSystemTime(&sTime);
  167.             VERIFY(SystemTimeToFileTime(&sTime, &m_LastRecvTime));
  168.         }
  169.     } while (!m_SendBuffer.empty());
  170.  
  171.     return TRUE;
  172. }
  173.  
  174. void CAdminSocket::OnReceive(int nErrorCode)
  175. {
  176.     if (nErrorCode)
  177.     {
  178.         Close();
  179.         m_pAdminInterface->Remove(this);
  180.         return;
  181.     }
  182.     int numread = Receive(m_pRecvBuffer + m_nRecvBufferPos, m_nRecvBufferLen - m_nRecvBufferPos);
  183.     while (numread > 0)
  184.     {
  185.         SYSTEMTIME sTime;
  186.         GetSystemTime(&sTime);
  187.         VERIFY(SystemTimeToFileTime(&sTime, &m_LastRecvTime));
  188.  
  189.         m_nRecvBufferPos += numread;
  190.         if (m_nRecvBufferLen-m_nRecvBufferPos < (BUFSIZE/4))
  191.         {
  192.             unsigned char *tmp=m_pRecvBuffer;
  193.             m_nRecvBufferLen += BUFSIZE;
  194.             m_pRecvBuffer = new unsigned char[m_nRecvBufferLen];
  195.             memcpy(m_pRecvBuffer, tmp, m_nRecvBufferPos);
  196.             delete [] tmp;
  197.         }
  198.         numread=Receive(m_pRecvBuffer + m_nRecvBufferPos, m_nRecvBufferLen - m_nRecvBufferPos);
  199.     }
  200.     if (numread == 0)
  201.     {
  202.         ParseRecvBuffer();
  203.         Close();
  204.         m_pAdminInterface->Remove(this);
  205.         return;
  206.     }
  207.     else if (numread == SOCKET_ERROR)
  208.     {
  209.         if (WSAGetLastError() != WSAEWOULDBLOCK)
  210.         {
  211.             ParseRecvBuffer();
  212.             Close();
  213.             m_pAdminInterface->Remove(this);
  214.             return;
  215.         }
  216.     }
  217.     while (ParseRecvBuffer());
  218. }
  219.  
  220. void CAdminSocket::OnSend(int nErrorCode)
  221. {
  222.     if (nErrorCode)
  223.     {
  224.         Close();
  225.         m_pAdminInterface->Remove(this);
  226.         return;
  227.     }
  228.  
  229.     while (!m_SendBuffer.empty())
  230.     {
  231.         t_data data=m_SendBuffer.front();
  232.         int nSent = Send(data.pData+data.dwOffset, data.dwLength-data.dwOffset);
  233.         if (!nSent)
  234.         {
  235.             Close();
  236.             m_pAdminInterface->Remove(this);
  237.             return;
  238.         }
  239.         if (nSent == SOCKET_ERROR)
  240.         {
  241.             if (WSAGetLastError()!=WSAEWOULDBLOCK)
  242.             {
  243.                 Close();
  244.                 m_pAdminInterface->Remove(this);
  245.             }
  246.             return;
  247.         }
  248.         
  249.         if ((unsigned int)nSent<(data.dwLength-data.dwOffset))
  250.             data.dwOffset+=nSent;
  251.         else
  252.         {
  253.             m_SendBuffer.pop_front();
  254.             delete [] data.pData;
  255.         }
  256.     }
  257. }
  258.  
  259. BOOL CAdminSocket::ParseRecvBuffer()
  260. {
  261.     if (m_nRecvBufferPos<5)
  262.         return FALSE;
  263.  
  264.     if ((m_pRecvBuffer[0]&0x03) != 0)
  265.     {
  266.         SendCommand(_T("Protocol error: Unknown command type, closing connection."), 1);
  267.         Close();
  268.         m_pAdminInterface->Remove(this);
  269.         return FALSE;
  270.     }
  271.     else
  272.     {
  273.         DWORD len;
  274.         memcpy(&len, m_pRecvBuffer+1, 4);
  275.         if (len > 0xFFFFFF)
  276.         {
  277.             SendCommand(_T("Protocol error: Invalid data length, closing connection."), 1);
  278.             Close();
  279.             m_pAdminInterface->Remove(this);
  280.             return FALSE;
  281.         }
  282.         if (m_nRecvBufferPos < len+5)
  283.             return FALSE;
  284.         else
  285.         {
  286.             int nID = (m_pRecvBuffer[0]&0x7C)>>2;
  287.             if (m_bStillNeedAuth)
  288.             {
  289.                 if (nID)
  290.                 {
  291.                     SendCommand(_T("Protocol error: Not authenticated, closing connection."), 1);
  292.                     Close();
  293.                     m_pAdminInterface->Remove(this);
  294.                     return FALSE;
  295.                 }
  296.                 if (len != 16)
  297.                 {
  298.                     SendCommand(_T("Protocol error: Auth data len invalid, closing connection."), 1);
  299.                     Close();
  300.                     m_pAdminInterface->Remove(this);
  301.                     return FALSE;
  302.                 }
  303.                 MD5 md5;
  304.                 md5.update(m_Nonce1, 8);
  305.                 COptions options;
  306.                 CStdString pass = options.GetOption(OPTION_ADMINPASS);
  307.                 if (pass.GetLength() < 6)
  308.                 {
  309.                     SendCommand(_T("Protocol error: Server misconfigured, admin password not set correctly"), 1);
  310.                     Close();
  311.                     m_pAdminInterface->Remove(this);
  312.                     return FALSE;
  313.                 }
  314.                 md5.update((unsigned char *)pass.c_str(), pass.GetLength());
  315.                 md5.update(m_Nonce2, 8);
  316.                 md5.finalize();
  317.                 unsigned char *digest = md5.raw_digest();
  318.                 if (memcmp(m_pRecvBuffer + 5, digest, 16))
  319.                 {
  320.                     SendCommand(_T("Protocol error: Auth failed, closing connection."), 1);
  321.                     Close();
  322.                     m_pAdminInterface->Remove(this);
  323.                     return FALSE;
  324.                 }
  325.                 delete [] digest;
  326.  
  327.                 FinishLogon();
  328.             }
  329.             else
  330.                 m_pAdminInterface->ProcessCommand(this, nID, m_pRecvBuffer+5, len);
  331.             memmove(m_pRecvBuffer, m_pRecvBuffer+len+5, m_nRecvBufferPos-len-5);
  332.             m_nRecvBufferPos-=len+5;
  333.         }
  334.     }
  335.     return TRUE;
  336. }
  337.  
  338. BOOL CAdminSocket::SendCommand(LPCTSTR pszCommand, int nTextType)
  339. {
  340.     USES_CONVERSION;
  341.  
  342.     DWORD nDataLength;
  343.     const char *pszAscii = 0;
  344.  
  345.     if (!pszCommand)
  346.         nDataLength = 0;
  347.     else
  348.     {
  349.         pszAscii = T2CA(pszCommand);
  350.         nDataLength = strlen(pszAscii) + 1;
  351.     }
  352.  
  353.     t_data data;
  354.     data.pData = new unsigned char[nDataLength+5];
  355.     *data.pData = 2;
  356.     *data.pData |= 1 << 2;
  357.     data.dwOffset = 0;
  358.     memcpy(data.pData + 1, &nDataLength, 4);
  359.     *(data.pData+5) = nTextType;
  360.     if (pszAscii)
  361.         memcpy(reinterpret_cast<char *>(data.pData+6), pszAscii, nDataLength-1);
  362.  
  363.     data.dwLength = nDataLength + 5;
  364.  
  365.     m_SendBuffer.push_back(data);
  366.     
  367.     do 
  368.     {
  369.         data = m_SendBuffer.front();
  370.         int nSent = Send(data.pData+data.dwOffset, data.dwLength-data.dwOffset);
  371.         if (!nSent)
  372.             return FALSE;
  373.         if (nSent == SOCKET_ERROR)
  374.         {
  375.             if (WSAGetLastError()!=WSAEWOULDBLOCK)
  376.                 return FALSE;
  377.             return TRUE;
  378.         }
  379.         
  380.         if ((unsigned int)nSent<(data.dwLength-data.dwOffset))
  381.             data.dwOffset+=nSent;
  382.         else
  383.         {
  384.             m_SendBuffer.pop_front();
  385.             delete [] data.pData;
  386.         }
  387.     } while (!m_SendBuffer.empty());
  388.  
  389.     return TRUE;
  390. }
  391.  
  392. BOOL CAdminSocket::CheckForTimeout()
  393. {
  394.     SYSTEMTIME sTime;
  395.     FILETIME fTime;
  396.     GetSystemTime(&sTime);
  397.     VERIFY(SystemTimeToFileTime(&sTime, &fTime));
  398.     
  399.     _int64 LastRecvTime = ((_int64)m_LastRecvTime.dwHighDateTime << 32) + m_LastRecvTime.dwLowDateTime;
  400.     _int64 CurTime = ((_int64)fTime.dwHighDateTime << 32) + fTime.dwLowDateTime;
  401.  
  402.     if ((CurTime - LastRecvTime) > 600000000) // 60 seconds
  403.         return TRUE;
  404.  
  405.     return FALSE;
  406. }
  407.  
  408. BOOL CAdminSocket::FinishLogon()
  409. {
  410.     m_bStillNeedAuth = FALSE;
  411.  
  412.     //Logon successful
  413.     if (!SendCommand(1, 0, NULL, 0))
  414.         return FALSE;
  415.     return TRUE;
  416. }
  417.