⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socmfc.cpp

📁 MiniCA V2.0版本源码。《小型CA系统V2.1含源码》发表以来
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    pEx->Delete();
    Close();
    AfxThrowWSocketException(nError);
  }
}

void CWSocket::ConnectViaSocks5(LPCTSTR lpszHostAddress, UINT nHostPort, LPCTSTR lpszSocksServer, UINT nSocksPort, LPCTSTR lpszUserName, LPCTSTR lpszPassword, DWORD dwConnectionTimeout, BOOL bUDP)
{
  USES_CONVERSION;
  ASSERT(IsCreated()); //must have been created first

  //connect to the proxy
  Connect(lpszSocksServer, nSocksPort);

  try
  {  
    BOOL bAuthenticate = (lpszUserName != NULL);

    //Fill in a connection request packet
    WSOCKET_SOCKS5_IDENTIFIER_PACKET request;
    request.VER = 5;
    request.NMETHODS = 1;
    request.METHODS[0] = 0;
    if (bAuthenticate)
    {
      request.NMETHODS++;
      request.METHODS[1] = 2;
    }

    Send(&request, bAuthenticate ? 4 : 3);

    //Wait for the connection reply
    WSOCKET_SOCKS5_METHODSELECTION_MESSAGE reply;
    memset(&reply, 0, sizeof(reply));
    int nDataReceived = 0;
    while (nDataReceived < sizeof(reply))
    {
      if (IsReadible(dwConnectionTimeout))
      {
        int nData = Receive(((BYTE*) &reply) + nDataReceived, sizeof(reply) - nDataReceived);
        nDataReceived += nData;
      }
      else
        AfxThrowWSocketException(WSAETIMEDOUT);
    }

    //Validate the response
    if ((bAuthenticate && ((reply.METHOD != 0) && (reply.METHOD != 2))) || (!bAuthenticate && (reply.METHOD != 0)))
      AfxThrowWSocketException(WSAECONNREFUSED);

    if (bAuthenticate && reply.METHOD == 2)
    {
      LPSTR pszAsciiUserName = T2A((LPTSTR) lpszUserName);
      LPSTR pszAsciiPassword = T2A((LPTSTR) lpszPassword);
      int nUserNameLength = (int) strlen(pszAsciiUserName);
      int nPasswordLength = 0;
      if (pszAsciiPassword)
        nPasswordLength = (int) strlen(pszAsciiPassword);

      if ((nUserNameLength > 255) || (nPasswordLength > 255))
        AfxThrowWSocketException(ERROR_INVALID_PARAMETER);

      int nUserRequestLength = 3 + nUserNameLength + nPasswordLength;
      BYTE* pUserRequest = new BYTE[nUserRequestLength];
      pUserRequest[0] = 1;
      pUserRequest[1] = (BYTE) nUserNameLength;
      CopyMemory(&(pUserRequest[2]), pszAsciiUserName, nUserNameLength);
      pUserRequest[2 + nUserNameLength] = (BYTE) nPasswordLength;
      CopyMemory(pUserRequest + 3 + nUserNameLength, pszAsciiPassword, nPasswordLength);
      Send(pUserRequest, nUserRequestLength);

      //Wait for the login reply
      WSOCKET_SOCKS5_USERNAME_AUTHENTICATION_REPLY reply;
      memset(&reply, 0, sizeof(reply));
      int nDataReceived = 0;
      while (nDataReceived < sizeof(reply))
      {
        if (IsReadible(dwConnectionTimeout))
        {
          int nData = Receive(((BYTE*) &reply) + nDataReceived, sizeof(reply) - nDataReceived);
          nDataReceived += nData;
        }
        else
          AfxThrowWSocketException(WSAETIMEDOUT);
      }

      if (reply.STATUS != 0)
        AfxThrowWSocketException(ERROR_ACCESS_DENIED);
    }

	  //Determine if the address is in dotted notation
	  LPSTR lpszAscii = T2A((LPTSTR) lpszHostAddress);
	  unsigned long nAddr = inet_addr(lpszAscii);
	  if (nAddr == INADDR_NONE)
	  {
      //verify that the host name is less than 256 bytes which is the limit of the hostname which Socks5 can accomadate
      int nHostLength = (int) strlen(lpszAscii);
      if (nHostLength > 255)
        AfxThrowWSocketException(ERROR_INVALID_PARAMETER);

      WSOCKET_SOCKS5_HOSTNAME_REQUEST_DETAILS requestDetails;
      memset(&requestDetails, 0, sizeof(requestDetails));
      requestDetails.Base.VER = 5;
      if (bUDP)
        requestDetails.Base.CMD = 3;
      else
        requestDetails.Base.CMD = 1;
      requestDetails.Base.ATYP = 3;
      requestDetails.DST_HOST.LENGTH = (BYTE) nHostLength;
      memcpy(requestDetails.DST_HOST.HOST, lpszAscii, nHostLength);
      WORD* pPort = (WORD*) (requestDetails.DST_HOST.HOST + nHostLength);
      *pPort = htons((u_short) nHostPort);
      int nRequestDetailsSize = sizeof(requestDetails) - 256 + nHostLength + 1;

      Send(&requestDetails, nRequestDetailsSize);
	  }
    else
    {
      WSOCKET_SOCKS5_IP4_REQUEST_DETAILS requestDetails;
      memset(&requestDetails, 0, sizeof(requestDetails));
      requestDetails.Base.VER = 5;
      requestDetails.Base.CMD = 1;
      requestDetails.Base.ATYP = 1;
      requestDetails.DST_IP.S_un.S_addr = nAddr;
      requestDetails.DSTPORT = htons((u_short) nHostPort);
      Send(&requestDetails, sizeof(requestDetails));
    }

    ReadSocks5ConnectReply(dwConnectionTimeout);
  }
  catch(CWSocketException* pEx)
  {
    //Close the socket before we rethrow the exception
    int nError = pEx->m_nError;
    pEx->Delete();
    Close();
    AfxThrowWSocketException(nError);
  }
}

void CWSocket::ReadSocks5ConnectReply(DWORD dwTimeout)
{
  //The local variables which will receive the data
  int nBufSize = max(sizeof(WSOCKET_SOCKS5_IP4_REQUEST_DETAILS), sizeof(WSOCKET_SOCKS5_HOSTNAME_REQUEST_DETAILS));
  BYTE* pRawRequest = new BYTE[nBufSize];
  
  //retrieve the reponse
  DWORD dwCurrentReadOffset = 0;
  BOOL bMoreDataToRead = TRUE;
	while (bMoreDataToRead)
	{
    if (IsReadible(dwTimeout))
    {
      int nBufRemaining = nBufSize - dwCurrentReadOffset;
      int nData = Receive(pRawRequest + dwCurrentReadOffset, nBufRemaining);

      //Increment the count of data received
		  dwCurrentReadOffset += nData;							   

      //Try to parse out what we received
      if (dwCurrentReadOffset >= sizeof(WSOCKET_SOCKS5_BASE_REQUEST_DETAILS)) 
      {
        WSOCKET_SOCKS5_BASE_REQUEST_DETAILS* pBaseRequest = (WSOCKET_SOCKS5_BASE_REQUEST_DETAILS*) pRawRequest;
        if (pBaseRequest->ATYP == 1)
        {
          //An IP 4 address type destination
          bMoreDataToRead = (dwCurrentReadOffset < sizeof(WSOCKET_SOCKS5_IP4_REQUEST_DETAILS));
          if (!bMoreDataToRead)
          {
            if (pBaseRequest->CMD != 0)
            {
              delete [] pRawRequest;
              AfxThrowWSocketException(ERROR_BAD_NET_RESP);
            }
          }
        }
        else if (pBaseRequest->ATYP == 3)
        {
          //A domain name type destination
          if (dwCurrentReadOffset > sizeof(WSOCKET_SOCKS5_BASE_REQUEST_DETAILS))
          {
            WSOCKET_SOCKS5_HOSTNAME_REQUEST_DETAILS* pHostnameRequest = (WSOCKET_SOCKS5_HOSTNAME_REQUEST_DETAILS*) pRawRequest;
            bMoreDataToRead = (dwCurrentReadOffset < ((sizeof(WSOCKET_SOCKS5_HOSTNAME_REQUEST_DETAILS) - 256) + pHostnameRequest->DST_HOST.LENGTH));
            if (!bMoreDataToRead)
            {
              if (pBaseRequest->CMD != 0)
              {
                delete [] pRawRequest;
                AfxThrowWSocketException(ERROR_BAD_NET_RESP);
              }
            }
          }
        }
        else
        {
          delete [] pRawRequest;
          AfxThrowWSocketException(ERROR_INVALID_PARAMETER);
        }
      }
    }
    else
    {
      delete [] pRawRequest;
      AfxThrowWSocketException(WSAETIMEDOUT);
    }
  }

  delete [] pRawRequest;
}

BOOL CWSocket::IsReadible(DWORD dwTimeout)
{
  ASSERT(IsCreated()); //must have been created first

  timeval timeout;
  timeout.tv_sec = dwTimeout/1000;
  timeout.tv_usec = (dwTimeout%1000)*1000;
  fd_set fds;
  FD_ZERO(&fds);
  FD_SET(m_hSocket, &fds);
  int nStatus = select(0, &fds, NULL, NULL, &timeout);
  if (nStatus == SOCKET_ERROR)
    AfxThrowWSocketException();

  return !(nStatus == 0);
}

BOOL CWSocket::IsWritable(DWORD dwTimeout)
{
  ASSERT(IsCreated()); //must have been created first

  timeval timeout;
  timeout.tv_sec = dwTimeout/1000;
  timeout.tv_usec = (dwTimeout%1000)*1000;
  fd_set fds;
  FD_ZERO(&fds);
  FD_SET(m_hSocket, &fds);
  int nStatus = select(0, NULL, &fds, NULL, &timeout);
  if (nStatus == SOCKET_ERROR)
    AfxThrowWSocketException();

  return !(nStatus == 0);
}

BOOL CWSocket::IsCreated() const
{
  return (m_hSocket != INVALID_SOCKET);
}

CWSocket::operator SOCKET()
{
  return m_hSocket;
}

void CWSocket::ConnectViaHTTPProxy(LPCTSTR lpszHostAddress, UINT nHostPort, LPCTSTR lpszHTTPProxy, UINT nHTTPProxyPort, CString& sProxyResponse, LPCTSTR lpszUserName, LPCTSTR lpszPassword, DWORD dwConnectionTimeout, LPCTSTR lpszUserAgent)
{
  USES_CONVERSION;
  ASSERT(IsCreated()); //must have been created first

  //connect to the proxy
  Connect(lpszHTTPProxy, nHTTPProxyPort);

  try
  {  
    //Form the HTTP CONNECT request header
    CString sLine;
    sLine.Format(_T("CONNECT %s:%d HTTP/1.0\r\n"), lpszHostAddress, nHostPort);
    CString sRequest(sLine);
    
    //Form the authorization line if required  
    if (lpszUserName != NULL)
    {
      //Base64 encode the username password combination
      CBase64 base64;
      CString sUserNamePassword;
      sUserNamePassword.Format(_T("%s:%s"), lpszUserName, lpszPassword);
      char* pszUserNamePassword = T2A((LPTSTR) (LPCTSTR) sUserNamePassword);
      int nUserNamePasswordLength = (int) strlen(pszUserNamePassword);
      int nEncodedLength = base64.EncodeGetRequiredLength(nUserNamePasswordLength);
      LPSTR pszEncoded = (LPSTR) _alloca(nEncodedLength + 1);
      base64.Encode((const BYTE*) pszUserNamePassword, nUserNamePasswordLength, pszEncoded, &nEncodedLength);
      pszEncoded[nEncodedLength] = '\0';

      //Form the Authorization header line and add it to the request
      sLine.Format(_T("Proxy-authorization: Basic %s\r\n"), A2T(pszEncoded));
      sRequest += sLine;
    }

    //Form the user agent line if required
    if (lpszUserAgent != NULL)
    {
      //Add the User Agent line to the request
      sLine.Format(_T("User-Agent: %s\r\n"), lpszUserAgent);
      sRequest += sLine;
    }

    //Add the final line feed to the request
    sRequest += _T("\r\n");

    //Finally send the request to the HTTP proxy
    LPSTR pszRequest = T2A((LPTSTR) (LPCTSTR) sRequest);
    Send(pszRequest, (int) strlen(pszRequest));

    //Read the proxy response
    ReadHTTPProxyResponse(dwConnectionTimeout, sProxyResponse);

    //Next make sure that we got a HTTP code of 200 to indicate success
    int nFirstSpace = sProxyResponse.Find(_T(" "));
    if (nFirstSpace != -1)
    {
      CString sResponseCode = sProxyResponse.Right(sProxyResponse.GetLength() - nFirstSpace - 1);
      int nResponseCode = _ttoi(sResponseCode);
      if (nResponseCode != 200)
        AfxThrowWSocketException(ERROR_CONNECTION_REFUSED);
    }
  }
  catch(CWSocketException* pEx)
  {
    //Close the socket before we rethrow the exception
    int nError = pEx->m_nError;
    pEx->Delete();
    Close();
    AfxThrowWSocketException(nError);
  }
}

void CWSocket::ReadHTTPProxyResponse(DWORD dwTimeout, CString& sResponse)
{
  USES_CONVERSION;
  ASSERT(IsCreated()); //must have been created first

  //The local variables which will receive the data
  DWORD dwGrowBy = 4096;
  BYTE* pRawRequest = new BYTE[dwGrowBy];
  DWORD dwBufSize = dwGrowBy;
  DWORD dwRawRequestSize = 0;
  
  //retrieve the reponse
  BOOL bMoreDataToRead = TRUE;
	while (bMoreDataToRead)
	{
    //check the socket for readability
    if (!IsReadible(dwTimeout))
    {
      //Null terminate the data
  	  pRawRequest[dwRawRequestSize] = '\0';
      TRACE(_T("CWSocket::ReadHTTPProxyResponse, Timed out waiting for response from socket\n"));
			AfxThrowWSocketException(WSAETIMEDOUT);
    }

		//receive the data from the socket
    dwRawRequestSize += Receive(pRawRequest + dwRawRequestSize, 1);

    //NULL terminate the data received
	  pRawRequest[dwRawRequestSize] = '\0';

    //Check to see if the terminator character(s) have been found
    if (dwRawRequestSize >= 4)
    {
      bMoreDataToRead = !((pRawRequest[dwRawRequestSize-4] == '\r') && (pRawRequest[dwRawRequestSize-3] == '\n') &&
                          (pRawRequest[dwRawRequestSize-2] == '\r') && (pRawRequest[dwRawRequestSize-1] == '\n'));
    }

    if (dwRawRequestSize >= dwBufSize) //No space left in the current buffer
    {
      //Allocate the new receive buffer
      dwBufSize += dwGrowBy; //Grow the buffer by the specified amount
      LPBYTE pNewBuf = new BYTE[dwBufSize];

      //copy the old contents over to the new buffer and assign 
      //the new buffer to the local variable used for retreiving 
      //from the socket
      CopyMemory(pNewBuf, pRawRequest, dwRawRequestSize);
      delete [] pRawRequest;
      pRawRequest = pNewBuf;
    }
	}

  //Form the CString out parameter
  sResponse = A2T((char*) pRawRequest);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -