void CServerSocket::OnConnect(int nErrorCode) { CAsyncSocketEx::OnConnect(nErrorCode); // deadlake PROXYSUPPORT - changed to AsyncSocketEx switch (nErrorCode) { case 0: { if (cur_server->HasDynIP()) { SOCKADDR_IN sockAddr = {0}; int nSockAddrLen = sizeof(sockAddr); GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen); cur_server->SetIP(sockAddr.sin_addr.S_un.S_addr); CServer* pServer = theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort()); if (pServer) pServer->SetIP(sockAddr.sin_addr.S_un.S_addr); } SetConnectionState(CS_WAITFORLOGIN); break; } case WSAEADDRNOTAVAIL: case WSAECONNREFUSED: //case WSAENETUNREACH: // let this error default to 'fatal error' as it does not inrease the server's failed count case WSAETIMEDOUT: case WSAEADDRINUSE: if (thePrefs.GetVerbose()) DebugLogError(_T("Failed to connect to server %s; %s"), cur_server->GetAddress(), GetErrorMessage(nErrorCode, 1)); m_bIsDeleting = true; SetConnectionState(CS_SERVERDEAD); serverconnect->DestroySocket(this); return; //==> remove PROXY [shadow2004] #if defined(PROXY) // deadlake PROXYSUPPORT case WSAECONNABORTED: if (m_ProxyConnectFailed) { if (thePrefs.GetVerbose()) DebugLogError(_T("Failed to connect to server %s; %s"), cur_server->GetAddress(), GetErrorMessage(nErrorCode, 1)); m_ProxyConnectFailed = false; m_bIsDeleting = true; SetConnectionState(CS_SERVERDEAD); serverconnect->DestroySocket(this); return; } #endif //PROXY //<== remove PROXY [shadow2004] default: if (thePrefs.GetVerbose()) DebugLogError(_T("Failed to connect to server %s; %s"), cur_server->GetAddress(), GetErrorMessage(nErrorCode, 1)); m_bIsDeleting = true; SetConnectionState(CS_FATALERROR); serverconnect->DestroySocket(this); return; } }
void CServerSocket::OnConnect(int nErrorCode) { //Xman // MAella -QOS- /* CAsyncSocketEx::OnConnect(nErrorCode); */ CEMSocket::OnConnect(nErrorCode); //Xman end switch (nErrorCode) { case 0: SetConnectionState(CS_WAITFORLOGIN); break; case WSAEADDRNOTAVAIL: case WSAECONNREFUSED: //case WSAENETUNREACH: // let this error default to 'fatal error' as it does not increase the server's failed count case WSAETIMEDOUT: case WSAEADDRINUSE: if (thePrefs.GetVerbose()) DebugLogError(_T("Failed to connect to server %s; %s"), cur_server->GetAddress(), GetFullErrorMessage(nErrorCode)); m_bIsDeleting = true; SetConnectionState(CS_SERVERDEAD); serverconnect->DestroySocket(this); return; case WSAECONNABORTED: if (m_bProxyConnectFailed) { if (thePrefs.GetVerbose()) DebugLogError(_T("Failed to connect to server %s; %s"), cur_server->GetAddress(), GetFullErrorMessage(nErrorCode)); m_bProxyConnectFailed = false; m_bIsDeleting = true; SetConnectionState(CS_SERVERDEAD); serverconnect->DestroySocket(this); return; } /* fall through */ default: if (thePrefs.GetVerbose()) DebugLogError(_T("Failed to connect to server %s; %s"), cur_server->GetAddress(), GetFullErrorMessage(nErrorCode)); m_bIsDeleting = true; SetConnectionState(CS_FATALERROR); serverconnect->DestroySocket(this); return; } }
DWORD CNetF::GetMSSFromSocket(SOCKET socket){ DWORD dwError; if (m_pGetPerTcpConnectionEStats != NULL){ sockaddr_in sa_remote = {0}; int sa_remote_len = sizeof(sa_remote); getpeername(socket, reinterpret_cast<sockaddr*>(&sa_remote), &sa_remote_len); sockaddr_in sa_local = {0}; int sa_local_len = sizeof(sa_local); getsockname(socket, reinterpret_cast<sockaddr*>(&sa_local), &sa_local_len); if (sa_local.sin_addr.S_un.S_addr == INADDR_ANY || sa_local.sin_addr.S_un.S_addr == INADDR_NONE){ const ULONG bestIfAddr = GetBestInterfaceIP(sa_remote.sin_addr.S_un.S_addr); if (bestIfAddr != INADDR_NONE) sa_local.sin_addr.S_un.S_addr = bestIfAddr; } MIB_TCPROW tcprow; tcprow.dwState = MIB_TCP_STATE_ESTAB; tcprow.dwLocalAddr = sa_local.sin_addr.S_un.S_addr; tcprow.dwLocalPort = sa_local.sin_port; tcprow.dwRemoteAddr = sa_remote.sin_addr.S_un.S_addr; tcprow.dwRemotePort = sa_remote.sin_port; TCP_ESTATS_SYN_OPTS_ROS_v0 synopts = {0}; if ((dwError = m_pGetPerTcpConnectionEStats(&tcprow, static_cast<TCP_ESTATS_TYPE>(TcpConnectionEstatsSynOpts), NULL, 0, 0 , reinterpret_cast<PUCHAR>(&synopts), 0, sizeof(synopts), NULL, 0, 0)) == NO_ERROR){ const DWORD dwIfMtu = GetBestInterfaceMTU(sa_remote.sin_addr.S_un.S_addr); if (dwIfMtu == 0 || (dwIfMtu - 40) > synopts.MssRcvd) return synopts.MssRcvd; else return dwIfMtu - 40; } else DebugLogError(_T(__FUNCTION__) _T(": Failed to retrieve MSS option for destination %s: %s"), ipstr(sa_remote.sin_addr), GetErrorMessage(dwError, 1)); } return 0; }
void CServerConnect::CheckForTimeout() { DWORD dwServerConnectTimeout = CONSERVTIMEOUT; // If we are using a proxy, increase server connection timeout to default connection timeout if (thePrefs.GetProxySettings().UseProxy) dwServerConnectTimeout = max(dwServerConnectTimeout, CONNECTION_TIMEOUT); DWORD dwCurTick = GetTickCount(); DWORD tmpkey; CServerSocket* tmpsock; POSITION pos = connectionattemps.GetStartPosition(); while (pos){ connectionattemps.GetNextAssoc(pos,tmpkey,tmpsock); if (!tmpsock){ if (thePrefs.GetVerbose()) DebugLogError(_T("Error: Socket invalid at timeoutcheck")); connectionattemps.RemoveKey(tmpkey); return; } if (dwCurTick - tmpkey > dwServerConnectTimeout){ LogWarning(GetResString(IDS_ERR_CONTIMEOUT), tmpsock->cur_server->GetListName(), tmpsock->cur_server->GetAddress(), tmpsock->cur_server->GetPort()); connectionattemps.RemoveKey(tmpkey); DestroySocket(tmpsock); if (singleconnecting) StopConnectionTry(); else TryAnotherConnectionRequest(); } } }
int CALLBACK AcceptConnectionCond(LPWSABUF lpCallerId, LPWSABUF /*lpCallerData*/, LPQOS /*lpSQOS*/, LPQOS /*lpGQOS*/, LPWSABUF /*lpCalleeId*/, LPWSABUF /*lpCalleeData*/, GROUP FAR* /*g*/, DWORD /*dwCallbackData*/) { if (lpCallerId && lpCallerId->buf && lpCallerId->len >= sizeof SOCKADDR_IN) { LPSOCKADDR_IN pSockAddr = (LPSOCKADDR_IN)lpCallerId->buf; ASSERT( pSockAddr->sin_addr.S_un.S_addr != 0 && pSockAddr->sin_addr.S_un.S_addr != INADDR_NONE ); if (CGlobalVariable::ipfilter->IsFiltered(pSockAddr->sin_addr.S_un.S_addr)){ if (thePrefs.GetLogFilteredIPs()) AddDebugLogLine(false, _T("Rejecting connection attempt (IP=%s) - IP filter (%s)"), ipstr(pSockAddr->sin_addr.S_un.S_addr), CGlobalVariable::ipfilter->GetLastHit()); _iAcceptConnectionCondRejected = 1; return CF_REJECT; } if (CGlobalVariable::clientlist->IsBannedClient(pSockAddr->sin_addr.S_un.S_addr)){ if (thePrefs.GetLogBannedClients()){ CUpDownClient* pClient = CGlobalVariable::clientlist->FindClientByIP(pSockAddr->sin_addr.S_un.S_addr); AddDebugLogLine(false, _T("Rejecting connection attempt of banned client %s %s"), ipstr(pSockAddr->sin_addr.S_un.S_addr), pClient->DbgGetClientInfo()); } _iAcceptConnectionCondRejected = 2; return CF_REJECT; } } else { if (thePrefs.GetVerbose()) DebugLogError(_T("Client TCP socket: AcceptConnectionCond unexpected lpCallerId")); } return CF_ACCEPT; }
// unfortunatly sending cannot be made transparent for the derived class, because of WSA_WOULDBLOCK // together with the fact that each byte must pass the keystream only once int CEncryptedStreamSocket::Send(const void* lpBuf, int nBufLen, int nFlags){ if (!IsEncryptionLayerReady()){ ASSERT( false ); // must be a bug return 0; } else if (m_bServerCrypt && m_StreamCryptState == ECS_ENCRYPTING && m_pfiSendBuffer != NULL){ ASSERT( m_NegotiatingState == ONS_BASIC_SERVER_DELAYEDSENDING ); // handshakedata was delayed to put it into one frame with the first paypload to the server // do so now with the payload attached int nRes = SendNegotiatingData(lpBuf, nBufLen, nBufLen); ASSERT( nRes != SOCKET_ERROR ); (void)nRes; return nBufLen; // report a full send, even if we didn't for some reason - the data is know in our buffer and will be handled later } else if (m_NegotiatingState == ONS_BASIC_SERVER_DELAYEDSENDING) ASSERT( false ); if (m_StreamCryptState == ECS_UNKNOWN){ //this happens when the encryption option was not set on a outgoing connection //or if we try to send before receiving on a incoming connection - both shouldn't happen m_StreamCryptState = ECS_NONE; DebugLogError(_T("CEncryptedStreamSocket: Overwriting State ECS_UNKNOWN with ECS_NONE because of premature Send() (%s)"), DbgGetIPString()); } return CAsyncSocketEx::Send(lpBuf, nBufLen, nFlags); }
void CUPnPImplMiniLib::DeletePorts(bool bSkipLock){ // this function itself blocking, because its called at the end of eMule and we need to wait for it to finish // before going on anyway. It might be caled from the non-blocking StartDiscovery() function too however CSingleLock lockTest(&m_mutBusy); if (bSkipLock || lockTest.Lock(0)){ if (m_nOldTCPPort != 0){ if (m_pURLs == NULL || m_pURLs->controlURL == NULL || m_pIGDData == NULL){ ASSERT( false ); return; } const char achTCP[] = "TCP"; char achPort[10]; sprintf(achPort, "%u", m_nOldTCPPort); int nResult = UPNP_DeletePortMapping(m_pURLs->controlURL, m_pIGDData->servicetype, achPort, achTCP, NULL); if (nResult == UPNPCOMMAND_SUCCESS){ DebugLog(_T("Sucessfully removed mapping for port %u (%s)"), m_nOldTCPPort, _T("TCP")); m_nOldTCPPort = 0; } else DebugLogWarning(_T("Failed to remove mapping for port %u (%s)"), m_nOldTCPPort, _T("TCP")); } else{ DebugLog(_T("No UPnP Mappings to remove, aborting")); return; // UDP port cannot be set if TCP port was empty } if (m_nOldUDPPort != 0){ const char achTCP[] = "UDP"; char achPort[10]; sprintf(achPort, "%u", m_nOldUDPPort); int nResult = UPNP_DeletePortMapping(m_pURLs->controlURL, m_pIGDData->servicetype, achPort, achTCP, NULL); if (nResult == UPNPCOMMAND_SUCCESS){ DebugLog(_T("Sucessfully removed mapping for port %u (%s)"), m_nOldUDPPort, _T("UDP")); m_nOldTCPPort = 0; } else DebugLogWarning(_T("Failed to remove mapping for port %u (%s)"), m_nOldUDPPort, _T("UDP")); } if (m_nOldTCPWebPort != 0){ const char achTCP[] = "TCP"; char achPort[10]; sprintf(achPort, "%u", m_nOldTCPWebPort); int nResult = UPNP_DeletePortMapping(m_pURLs->controlURL, m_pIGDData->servicetype, achPort, achTCP, 0); if (nResult == UPNPCOMMAND_SUCCESS){ DebugLog(_T("Sucessfully removed mapping for webinterface port %u (%s)"), m_nOldTCPPort, _T("TCP")); m_nOldTCPWebPort = 0; } else DebugLogWarning(_T("Failed to remove mapping for webinterface port %u (%s)"), m_nOldTCPPort, _T("TCP")); } } else DebugLogError(_T("Unable to remove port mappings - implementation still busy")); }
int CEncryptedDatagramSocket::DecryptReceivedServer(BYTE* pbyBufIn, int nBufLen, BYTE** ppbyBufOut, uint32 dwBaseKey, uint32 dbgIP) const{ int nResult = nBufLen; *ppbyBufOut = pbyBufIn; if (nResult <= CRYPT_HEADER_WITHOUTPADDING || !thePrefs.IsServerCryptLayerUDPEnabled() || dwBaseKey == 0) return nResult; if(pbyBufIn[0] == OP_EDONKEYPROT) return nResult; // no encrypted packet (see description on top) // might be an encrypted packet, try to decrypt uchar achKeyData[7]; memcpy(achKeyData, &dwBaseKey, 4); achKeyData[4] = MAGICVALUE_UDP_SERVERCLIENT; memcpy(achKeyData + 5, pbyBufIn + 1, 2); // random key part sent from remote server MD5Sum md5(achKeyData, sizeof(achKeyData)); RC4_Key_Struct keyReceiveKey; RC4CreateKey(md5.GetRawHash(), 16, &keyReceiveKey, true); uint32 dwValue; RC4Crypt(pbyBufIn + 3, (uchar*)&dwValue, sizeof(dwValue), &keyReceiveKey); if (dwValue == MAGICVALUE_UDP_SYNC_SERVER){ // yup this is an encrypted packet if (thePrefs.GetDebugServerUDPLevel() > 0) DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from ServerIP: %s"), ipstr(dbgIP)) ); uint8 byPadLen; RC4Crypt(pbyBufIn + 7, (uchar*)&byPadLen, 1, &keyReceiveKey); byPadLen &= 15; nResult -= CRYPT_HEADER_WITHOUTPADDING; if (nResult <= byPadLen){ DebugLogError(_T("Invalid obfuscated UDP packet from ServerIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dbgIP), byPadLen); return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk } if (byPadLen > 0) RC4Crypt(NULL, NULL, byPadLen, &keyReceiveKey); nResult -= byPadLen; *ppbyBufOut = pbyBufIn + (nBufLen - nResult); RC4Crypt((uchar*)*ppbyBufOut, (uchar*)*ppbyBufOut, nResult, &keyReceiveKey); //Xman // Maella -Accurate measure of bandwidth: eDonkey data + control, network adapter- /* theStats.AddDownDataOverheadCrypt(nBufLen - nResult); */ theApp.pBandWidthControl->AddeMuleInObfuscation(nBufLen - nResult); //Xman end return nResult; // done } else{ DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from ServerIP: %s"), ipstr(dbgIP)); return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk } }
bool CServerSocket::PacketReceived(Packet* packet) { #ifndef _DEBUG try { #endif theStats.AddDownDataOverheadServer(packet->size); if (packet->prot == OP_PACKEDPROT) { uint32 uComprSize = packet->size; if (!packet->UnPackPacket(250000)){ if (thePrefs.GetVerbose()) DebugLogError(_T("Failed to decompress server TCP packet: protocol=0x%02x opcode=0x%02x size=%u"), packet ? packet->prot : 0, packet ? packet->opcode : 0, packet ? packet->size : 0); return true; } packet->prot = OP_EDONKEYPROT; if (thePrefs.GetDebugServerTCPLevel() > 1) Debug(_T("Received compressed server TCP packet; opcode=0x%02x size=%u uncompr size=%u\n"), packet->opcode, uComprSize, packet->size); } if (packet->prot == OP_EDONKEYPROT) { ProcessPacket((const BYTE*)packet->pBuffer, packet->size, packet->opcode); } else { if (thePrefs.GetVerbose()) DebugLogWarning(_T("Received server TCP packet with unknown protocol: protocol=0x%02x opcode=0x%02x size=%u"), packet ? packet->prot : 0, packet ? packet->opcode : 0, packet ? packet->size : 0); } #ifndef _DEBUG } catch(...) { if (thePrefs.GetVerbose()) DebugLogError(_T("Error: Unhandled exception while processing server TCP packet: protocol=0x%02x opcode=0x%02x size=%u"), packet ? packet->prot : 0, packet ? packet->opcode : 0, packet ? packet->size : 0); ASSERT(0); return false; } #endif return true; }
int CEncryptedDatagramSocket::DecryptReceivedClient(BYTE* pbyBufIn, int nBufLen, BYTE** ppbyBufOut, uint32 dwIP) const{ int nResult = nBufLen; *ppbyBufOut = pbyBufIn; if (nResult <= CRYPT_HEADER_WITHOUTPADDING || !thePrefs.IsClientCryptLayerSupported()) return nResult; switch (pbyBufIn[0]){ case OP_EMULEPROT: case OP_KADEMLIAPACKEDPROT: case OP_KADEMLIAHEADER: case OP_UDPRESERVEDPROT1: case OP_UDPRESERVEDPROT2: case OP_PACKEDPROT: return nResult; // no encrypted packet (see description on top) } // might be an encrypted packet, try to decrypt uchar achKeyData[23]; md4cpy(achKeyData, thePrefs.GetUserHash()); achKeyData[20] = MAGICVALUE_UDP; memcpy(achKeyData + 16, &dwIP, 4); memcpy(achKeyData + 21, pbyBufIn + 1, 2); // random key part sent from remote client MD5Sum md5(achKeyData, sizeof(achKeyData)); RC4_Key_Struct keyReceiveKey; RC4CreateKey(md5.GetRawHash(), 16, &keyReceiveKey, true); uint32 dwValue; RC4Crypt(pbyBufIn + 3, (uchar*)&dwValue, sizeof(dwValue), &keyReceiveKey); if (dwValue == MAGICVALUE_UDP_SYNC_CLIENT){ // yup this is an encrypted packet DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from clientIP: %s"), ipstr(dwIP)) ); uint8 byPadLen; RC4Crypt(pbyBufIn + 7, (uchar*)&byPadLen, 1, &keyReceiveKey); nResult -= CRYPT_HEADER_WITHOUTPADDING; if (nResult <= byPadLen){ DebugLogError(_T("Invalid obfuscated UDP packet from clientIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dwIP), byPadLen); return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk } if (byPadLen > 0) RC4Crypt(NULL, NULL, byPadLen, &keyReceiveKey); nResult -= byPadLen; *ppbyBufOut = pbyBufIn + (nBufLen - nResult); RC4Crypt((uchar*)*ppbyBufOut, (uchar*)*ppbyBufOut, nResult, &keyReceiveKey); theStats.AddDownDataOverheadCrypt(nBufLen - nResult); return nResult; // done } else{ DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: %s"), ipstr(dwIP)); return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk } }
bool CUpDownClient::ProcessPeerCacheAcknowledge(const uchar* packet, UINT size) { const bool bDebug = (thePrefs.GetDebugClientTCPLevel() > 0); if (bDebug) DebugRecv("OP_PeerCacheAck", this); if (socket == NULL){ ASSERT(0); return false; } m_bPeerCacheUpHit = false; CSafeMemFile data(packet, size); UINT uAck = data.ReadUInt8(); if (uAck == 1) { // Cache hit if (bDebug) Debug(_T(" Cache hit\n")); // PC-TODO: If this socket is closed, PeerCache also closes the socket which it had opened to the // remote client! So, to give the remote client a chance to receive all the data from the PeerCache, // we have to keep this socket open, although it's not needed nor could it be reused! if (m_pPCUpSocket == NULL){ if (thePrefs.GetVerbose()) DebugLogError(_T("PeerCacheAck received - missing socket; %s"), DbgGetClientInfo()); ASSERT(0); return false; } // m_pPCUpSocket->Safe_Delete(); // m_pPCUpSocket = NULL; m_pPCUpSocket->SetTimeOut(MIN2MS(60)); // set socket timeout to 1 hour ?? m_bPeerCacheUpHit = true; } else if (uAck == 0) { // Cache miss, keep uploading if (bDebug) Debug(_T(" Cache miss\n")); } else{ ASSERT(0); return false; } // PC-TODO: Since we can not close the PC socket, what exactly do we need this ACK-packet for? ; UpdateDisplayedInfo(); return true; }
void CClientList::TrackBadRequest(const CUpDownClient* upcClient, int nIncreaseCounter){ CDeletedClient* pResult = NULL; if (upcClient->GetIP() == 0){ ASSERT( false ); return; } if (m_trackedClientsList.Lookup(upcClient->GetIP(), pResult)){ pResult->m_dwInserted = ::GetTickCount(); pResult->m_cBadRequest += nIncreaseCounter; // morph some extra verbose tracking, read http://forum.emule-project.net/index.php?showtopic=136682 DebugLogError( _T("Client: %s (%s), Increased badrequestcounter to %d"), upcClient->GetUserName(), ipstr(upcClient->GetConnectIP()),pResult->m_cBadRequest); } else{ CDeletedClient* ccToAdd = new CDeletedClient(upcClient); ccToAdd->m_cBadRequest = nIncreaseCounter; // morph some extra verbose tracking, read http://forum.emule-project.net/index.php?showtopic=136682 // nIncreaseCounter equals ccToAdd->m_cBadRequest here so i will rather use the first // anyway, pResult->m_cBadRequest is utterly wrong because pResult is a NULL-pointer here DebugLogError( _T("Client: %s (%s), Increased set badrequestcounter to %d"), upcClient->GetUserName(), ipstr(upcClient->GetConnectIP()),nIncreaseCounter); m_trackedClientsList.SetAt(upcClient->GetIP(), ccToAdd); } }
int CClientUDPSocket::SendTo(char* lpBuf,int nBufLen,uint32 dwIP, uint16 nPort){ // NOTE: *** This function is invoked from a *different* thread! uint32 result = CAsyncSocket::SendTo(lpBuf,nBufLen,nPort,ipstr(dwIP)); if (result == (uint32)SOCKET_ERROR){ uint32 error = GetLastError(); if (error == WSAEWOULDBLOCK){ m_bWouldBlock = true; return -1; } if (thePrefs.GetVerbose()) DebugLogError(_T("Error: Client UDP socket, failed to send data to %s:%u: %s"), ipstr(dwIP), nPort, GetErrorMessage(error, 1)); } return 0; }
DWORD CNetF::GetBestInterfaceMTU(const ULONG dest_addr){ SOCKADDR_INET saDestinationAddress = {0}; MIB_IFROW rowIf = {0}; DWORD dwBestIfIndex; DWORD dwError; saDestinationAddress.Ipv4.sin_family = AF_INET; saDestinationAddress.Ipv4.sin_addr.S_un.S_addr = dest_addr; if (m_pGetBestInterface != NULL && m_pGetIfEntry != NULL){ if ((dwError = m_pGetBestInterface(dest_addr, &dwBestIfIndex)) == NO_ERROR){ rowIf.dwIndex = dwBestIfIndex; if ((dwError = m_pGetIfEntry(&rowIf)) == NO_ERROR){ return rowIf.dwMtu; } else{ DebugLogError(_T(__FUNCTION__) _T(": Failed to retrieve best interface mtu to dest %s: %s"), ipstr(dest_addr), GetErrorMessage(dwError, 1)); } } else{ DebugLogError(_T(__FUNCTION__) _T(": Failed to retrieve best interface index for destination %s: %s"), ipstr(dest_addr), GetErrorMessage(dwError, 1)); } } return 0; }
ULONG CNetF::GetBestInterfaceIP(const ULONG dest_addr){ SOCKADDR_INET saBestInterfaceAddress = {0}; SOCKADDR_INET saDestinationAddress = {0}; MIB_IPFORWARD_ROW2 rowBestRoute = {0}; DWORD dwBestIfIndex; DWORD dwError; saDestinationAddress.Ipv4.sin_family = AF_INET; saDestinationAddress.Ipv4.sin_addr.S_un.S_addr = dest_addr; if (m_pGetBestInterface != NULL && m_pGetBestRoute2 != NULL){ if ((dwError = m_pGetBestInterface(dest_addr, &dwBestIfIndex)) == NO_ERROR){ if ((dwError = m_pGetBestRoute2(NULL, dwBestIfIndex, NULL, &saDestinationAddress, 0, &rowBestRoute, &saBestInterfaceAddress)) == NO_ERROR){ return saBestInterfaceAddress.Ipv4.sin_addr.S_un.S_addr; } else{ DebugLogError(_T(__FUNCTION__) _T(": Failed to retrieve best route source ip address to dest %s: %s"), ipstr(dest_addr), GetErrorMessage(dwError, 1)); } } else{ DebugLogError(_T(__FUNCTION__) _T(": Failed to retrieve best interface index for destination %s: %s"), ipstr(dest_addr), GetErrorMessage(dwError, 1)); } } return INADDR_NONE; }
void CEncryptedStreamSocket::CryptPrepareSendData(uchar* pBuffer, uint32_t nLen){ if (!IsEncryptionLayerReady()){ ASSERT( false ); // must be a bug return; } if (m_StreamCryptState == ECS_UNKNOWN){ //this happens when the encryption option was not set on a outgoing connection //or if we try to send before receiving on a incoming connection - both shouldn't happen m_StreamCryptState = ECS_NONE; DebugLogError(_T("CEncryptedStreamSocket: Overwriting State ECS_UNKNOWN with ECS_NONE because of premature Send() (%s)"), DbgGetIPString()); } if (m_StreamCryptState == ECS_ENCRYPTING) RC4Crypt(pBuffer, pBuffer, nLen, m_pRC4SendKey); }
void CUPnPImplMiniLib::StopAsyncFind(){ CSingleLock lockTest(&m_mutBusy); m_bAbortDiscovery = true; // if there is a thread, tell him to abort as soon as possible - he won't sent a Resultmessage when aborted if (!lockTest.Lock(7000)) // give the thread 7 seconds to exit gracefully - it should never really take that long { // that quite bad, something seems to be locked up. There isn't a good solution here, we need the thread to quit // or it might try to access a deleted object later, but termianting him is quite bad too. Well.. DebugLogError(_T("Waiting for UPnP StartDiscoveryThread to quit failed, trying to terminate the thread...")); if (m_hThreadHandle != 0){ if (TerminateThread(m_hThreadHandle, 0)) DebugLogError(_T("...OK")); else DebugLogError(_T("...Failed")); } else ASSERT( false ); m_hThreadHandle = 0; } else { DebugLog(_T("Aborted any possible UPnP StartDiscoveryThread")); m_bAbortDiscovery = false; m_hThreadHandle = 0; } }
void CClientUDPSocket::OnSend(int nErrorCode){ if (nErrorCode){ if (thePrefs.GetVerbose()) DebugLogError(_T("Error: Client UDP socket, error on send event: %s"), GetErrorMessage(nErrorCode, 1)); return; } // ZZ:UploadBandWithThrottler (UDP) --> sendLocker.Lock(); m_bWouldBlock = false; if(!controlpacket_queue.IsEmpty()) { theApp.uploadBandwidthThrottler->QueueForSendingControlPacket(this); } sendLocker.Unlock(); // <-- ZZ:UploadBandWithThrottler (UDP) }
Int32 CImplMswSocketTCP::Receive( Byte* buffer, UInt32 size ) { Int32 recvBytes = 0; recvBytes = recv( m_Socket, (char*) buffer, size, 0 ); if( recvBytes < 0 ) { int errorCode = WSAGetLastError(); if( errorCode == WSAEWOULDBLOCK ) { return -2; } DebugLogError( "CImplMswSocketTCP::Receive - Failed to receive data"); return -1; } return recvBytes; }
void CServerConnect::TryAnotherConnectionRequest() { if (connectionattemps.GetCount() < (thePrefs.IsSafeServerConnectEnabled() ? 1 : 2)) { CServer* next_server = theApp.serverlist->GetNextServer(m_bTryObfuscated); if (next_server == NULL) { if (connectionattemps.GetCount() == 0) { if (m_bTryObfuscated && !thePrefs.IsClientCryptLayerRequired()){ // try all servers on the non-obfuscated port next m_bTryObfuscated = false; ConnectToAnyServer(0, true, true, true); } else if (m_idRetryTimer == 0) { // 05-Nov-2003: If we have a very short server list, we could put serious load on those few servers // if we start the next connection tries without waiting. LogWarning(LOG_STATUSBAR, GetResString(IDS_OUTOFSERVERS)); AddLogLine(false, GetResString(IDS_RECONNECT), CS_RETRYCONNECTTIME); m_uStartAutoConnectPos = 0; // default: start at 0 VERIFY( (m_idRetryTimer = SetTimer(NULL, 0, 1000*CS_RETRYCONNECTTIME, RetryConnectTimer)) != NULL ); if (thePrefs.GetVerbose() && !m_idRetryTimer) DebugLogError(_T("Failed to create 'server connect retry' timer - %s"), GetErrorMessage(GetLastError())); } } return; } // Barry - Only auto-connect to static server option if (thePrefs.GetAutoConnectToStaticServersOnly()) { if (next_server->IsStaticMember()) ConnectToServer(next_server, true, !m_bTryObfuscated); } else ConnectToServer(next_server, true, !m_bTryObfuscated); } }
void CServerConnect::InitLocalIP() { m_nLocalIP = 0; // Using 'gethostname/gethostbyname' does not solve the problem when we have more than // one IP address. Using 'gethostname/gethostbyname' even seems to return the last IP // address which we got. e.g. if we already got an IP from our ISP, // 'gethostname/gethostbyname' will returned that (primary) IP, but if we add another // IP by opening a VPN connection, 'gethostname' will still return the same hostname, // but 'gethostbyname' will return the 2nd IP. // To weaken that problem at least for users which are binding eMule to a certain IP, // we use the explicitly specified bind address as our local IP address. if (thePrefs.GetBindAddrA() != NULL) { unsigned long ulBindAddr = inet_addr(thePrefs.GetBindAddrA()); if (ulBindAddr != INADDR_ANY && ulBindAddr != INADDR_NONE) { m_nLocalIP = ulBindAddr; return; } } // Don't use 'gethostbyname(NULL)'. The winsock DLL may be replaced by a DLL from a third party // which is not fully compatible to the original winsock DLL. ppl reported crash with SCORSOCK.DLL // when using 'gethostbyname(NULL)'. __try{ char szHost[256]; if (gethostname(szHost, sizeof szHost) == 0){ hostent* pHostEnt = gethostbyname(szHost); if (pHostEnt != NULL && pHostEnt->h_length == 4 && pHostEnt->h_addr_list[0] != NULL) m_nLocalIP = *((uint32*)pHostEnt->h_addr_list[0]); } } __except(EXCEPTION_EXECUTE_HANDLER){ // at least two ppl reported crashs when using 'gethostbyname' with third party winsock DLLs if (thePrefs.GetVerbose()) DebugLogError(_T("Unknown exception in CServerConnect::InitLocalIP")); ASSERT(0); } }
void CServerSocket::OnError(int nErrorCode) { SetConnectionState(CS_DISCONNECTED); if (thePrefs.GetVerbose()) DebugLogError(GetResString(IDS_ERR_SOCKET), cur_server->GetListName(), cur_server->GetAddress(), cur_server->GetPort(), GetFullErrorMessage(nErrorCode)); }
int CEncryptedDatagramSocket::DecryptReceivedClient(BYTE* pbyBufIn, int nBufLen, BYTE** ppbyBufOut, uint32 dwIP, uint32* nReceiverVerifyKey, uint32* nSenderVerifyKey) const{ int nResult = nBufLen; *ppbyBufOut = pbyBufIn; if (nReceiverVerifyKey == NULL || nSenderVerifyKey == NULL){ ASSERT( false ); return nResult; } *nReceiverVerifyKey = 0; *nSenderVerifyKey = 0; if (nResult <= CRYPT_HEADER_WITHOUTPADDING /*|| !thePrefs.IsClientCryptLayerSupported()*/) return nResult; switch (pbyBufIn[0]){ case OP_EMULEPROT: case OP_KADEMLIAPACKEDPROT: case OP_KADEMLIAHEADER: case OP_UDPRESERVEDPROT1: case OP_UDPRESERVEDPROT2: case OP_PACKEDPROT: return nResult; // no encrypted packet (see description on top) } // might be an encrypted packet, try to decrypt RC4_Key_Struct keyReceiveKey; uint32 dwValue = 0; // check the marker bit which type this packet could be and which key to test first, this is only an indicator since old clients have it set random // see the header for marker bits explanation byte byCurrentTry = ((pbyBufIn[0] & 0x03) == 3) ? 1 : (pbyBufIn[0] & 0x03); byte byTries; if (Kademlia::CKademlia::GetPrefs() == NULL) { // if kad never run, no point in checking anything except for ed2k encryption byTries = 1; byCurrentTry = 1; } else byTries = 3; bool bKadRecvKeyUsed = false; bool bKad = false; do{ byTries--; MD5Sum md5; if (byCurrentTry == 0) { // kad packet with NodeID as key bKad = true; bKadRecvKeyUsed = false; if (Kademlia::CKademlia::GetPrefs()) { uchar achKeyData[18]; memcpy(achKeyData, Kademlia::CKademlia::GetPrefs()->GetKadID().GetData(), 16); memcpy(achKeyData + 16, pbyBufIn + 1, 2); // random key part sent from remote client md5.Calculate(achKeyData, sizeof(achKeyData)); } } else if (byCurrentTry == 1) { // ed2k packet bKad = false; bKadRecvKeyUsed = false; uchar achKeyData[23]; md4cpy(achKeyData, thePrefs.GetUserHash()); achKeyData[20] = MAGICVALUE_UDP; memcpy(achKeyData + 16, &dwIP, 4); memcpy(achKeyData + 21, pbyBufIn + 1, 2); // random key part sent from remote client md5.Calculate(achKeyData, sizeof(achKeyData)); } else if (byCurrentTry == 2) { // kad packet with ReceiverKey as key bKad = true; bKadRecvKeyUsed = true; if (Kademlia::CKademlia::GetPrefs()) { uchar achKeyData[6]; PokeUInt32(achKeyData, Kademlia::CPrefs::GetUDPVerifyKey(dwIP)); memcpy(achKeyData + 4, pbyBufIn + 1, 2); // random key part sent from remote client md5.Calculate(achKeyData, sizeof(achKeyData)); } } else ASSERT( false ); RC4CreateKey(md5.GetRawHash(), 16, &keyReceiveKey, true); RC4Crypt(pbyBufIn + 3, (uchar*)&dwValue, sizeof(dwValue), &keyReceiveKey); byCurrentTry = (byCurrentTry + 1) % 3; } while (dwValue != MAGICVALUE_UDP_SYNC_CLIENT && byTries > 0); // try to decrypt as ed2k as well as kad packet if needed (max 3 rounds) if (dwValue == MAGICVALUE_UDP_SYNC_CLIENT){ // yup this is an encrypted packet // debugoutput notices // the following cases are "allowed" but shouldn't happen given that there is only our implementation yet if (bKad && (pbyBufIn[0] & 0x01) != 0) DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, ed2k bit)"), ipstr(dwIP)); else if (bKad && !bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) != 0) DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, nodeid key, recvkey bit)"), ipstr(dwIP)); else if (bKad && bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) == 0) DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, recvkey key, nodeid bit)"), ipstr(dwIP)); uint8 byPadLen; RC4Crypt(pbyBufIn + 7, (uchar*)&byPadLen, 1, &keyReceiveKey); nResult -= CRYPT_HEADER_WITHOUTPADDING; if (nResult <= byPadLen){ DebugLogError(_T("Invalid obfuscated UDP packet from clientIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dwIP), byPadLen); return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk } if (byPadLen > 0) RC4Crypt(NULL, NULL, byPadLen, &keyReceiveKey); nResult -= byPadLen; if (bKad){ if (nResult <= 8){ DebugLogError(_T("Obfuscated Kad packet with mismatching size (verify keys missing) received from clientIP: %s"), ipstr(dwIP)); return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk; } // read the verify keys RC4Crypt(pbyBufIn + CRYPT_HEADER_WITHOUTPADDING + byPadLen, (uchar*)nReceiverVerifyKey, 4, &keyReceiveKey); RC4Crypt(pbyBufIn + CRYPT_HEADER_WITHOUTPADDING + byPadLen + 4, (uchar*)nSenderVerifyKey, 4, &keyReceiveKey); nResult -= 8; } *ppbyBufOut = pbyBufIn + (nBufLen - nResult); RC4Crypt((uchar*)*ppbyBufOut, (uchar*)*ppbyBufOut, nResult, &keyReceiveKey); //Xman // Maella -Accurate measure of bandwidth: eDonkey data + control, network adapter- /* theStats.AddDownDataOverheadCrypt(nBufLen - nResult); */ theApp.pBandWidthControl->AddeMuleInObfuscation(nBufLen - nResult); //Xman end //DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from clientIP: %s, Key: %s, RKey: %u, SKey: %u"), ipstr(dwIP), bKad ? (bKadRecvKeyUsed ? _T("ReceiverKey") : _T("NodeID")) : _T("UserHash") // , nReceiverVerifyKey != 0 ? *nReceiverVerifyKey : 0, nSenderVerifyKey != 0 ? *nSenderVerifyKey : 0) ); return nResult; // done } else{ DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: %s, Possible RecvKey: %u"), ipstr(dwIP), Kademlia::CPrefs::GetUDPVerifyKey(dwIP)); return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk } }
int CEncryptedDatagramSocket::DecryptReceivedClient(BYTE* pbyBufIn, int nBufLen, BYTE** ppbyBufOut, uint32 dwIP, uint16* nReceiverVerifyKey, uint16* nSenderVerifyKey) const{ int nResult = nBufLen; *ppbyBufOut = pbyBufIn; if (nResult <= CRYPT_HEADER_WITHOUTPADDING /*|| !thePrefs.IsClientCryptLayerSupported()*/) return nResult; if (nReceiverVerifyKey == NULL || nSenderVerifyKey == NULL){ ASSERT( false ); return nResult; } switch (pbyBufIn[0]){ case OP_EMULEPROT: case OP_KADEMLIAPACKEDPROT: case OP_KADEMLIAHEADER: case OP_UDPRESERVEDPROT1: case OP_UDPRESERVEDPROT2: case OP_PACKEDPROT: return nResult; // no encrypted packet (see description on top) } bool bKad = (pbyBufIn[0] & 0x01) == 0; // check the marker bit if this is a kad or ed2k packet, this is only an indicator since old clients have it set random // might be an encrypted packet, try to decrypt RC4_Key_Struct keyReceiveKey; uint32 dwValue = 0; bool bFlipTry = false; do{ bKad = bFlipTry ? !bKad : bKad; MD5Sum md5; if (bKad){ if (Kademlia::CKademlia::GetPrefs()) { uchar achKeyData[18]; memcpy(achKeyData, Kademlia::CKademlia::GetPrefs()->GetKadID().GetData(), 16); memcpy(achKeyData + 16, pbyBufIn + 1, 2); // random key part sent from remote client md5.Calculate(achKeyData, sizeof(achKeyData)); } } else{ uchar achKeyData[23]; md4cpy(achKeyData, thePrefs.GetUserHash()); achKeyData[20] = MAGICVALUE_UDP; memcpy(achKeyData + 16, &dwIP, 4); memcpy(achKeyData + 21, pbyBufIn + 1, 2); // random key part sent from remote client md5.Calculate(achKeyData, sizeof(achKeyData)); } RC4CreateKey(md5.GetRawHash(), 16, &keyReceiveKey, true); RC4Crypt(pbyBufIn + 3, (uchar*)&dwValue, sizeof(dwValue), &keyReceiveKey); bFlipTry = !bFlipTry; // next round try the other possibility } while (dwValue != MAGICVALUE_UDP_SYNC_CLIENT && bFlipTry); // try to decrypt as ed2k as well as kad packet if needed (max 2 rounds) if (dwValue == MAGICVALUE_UDP_SYNC_CLIENT){ // yup this is an encrypted packet DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from clientIP: %s"), ipstr(dwIP)) ); uint8 byPadLen; RC4Crypt(pbyBufIn + 7, (uchar*)&byPadLen, 1, &keyReceiveKey); nResult -= CRYPT_HEADER_WITHOUTPADDING; if (nResult <= byPadLen){ DebugLogError(_T("Invalid obfuscated UDP packet from clientIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dwIP), byPadLen); return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk } if (byPadLen > 0) RC4Crypt(NULL, NULL, byPadLen, &keyReceiveKey); nResult -= byPadLen; if (bKad){ if (nResult <= 4){ DebugLogError(_T("Obfuscated Kad packet with mismatching size (verify keys missing) received from clientIP: %s"), ipstr(dwIP)); return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk; } // read the verify keys *nReceiverVerifyKey = PeekUInt16(pbyBufIn + CRYPT_HEADER_WITHOUTPADDING + byPadLen); *nSenderVerifyKey = PeekUInt16(pbyBufIn + CRYPT_HEADER_WITHOUTPADDING + byPadLen + 2); nResult -= 4; } else{ *nReceiverVerifyKey = 0; *nSenderVerifyKey = 0; } *ppbyBufOut = pbyBufIn + (nBufLen - nResult); RC4Crypt((uchar*)*ppbyBufOut, (uchar*)*ppbyBufOut, nResult, &keyReceiveKey); theStats.AddDownDataOverheadCrypt(nBufLen - nResult); return nResult; // done } else{ DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: %s"), ipstr(dwIP)); return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk } }
int CEncryptedStreamSocket::Negotiate(const uchar* pBuffer, uint32_t nLen){ uint32_t nRead = 0; ASSERT( m_nReceiveBytesWanted > 0 ); try{ while (m_NegotiatingState != ONS_COMPLETE && m_nReceiveBytesWanted > 0){ if (m_nReceiveBytesWanted > 512){ ASSERT( false ); return 0; } if (m_pfiReceiveBuffer == NULL){ BYTE* pReceiveBuffer = (BYTE*)malloc(512); // use a fixed size buffer if (pReceiveBuffer == NULL) AfxThrowMemoryException(); m_pfiReceiveBuffer = new CSafeMemFile(pReceiveBuffer, 512); } const uint32_t nToRead = min(nLen - nRead, m_nReceiveBytesWanted); m_pfiReceiveBuffer->Write(pBuffer + nRead, nToRead); nRead += nToRead; m_nReceiveBytesWanted -= nToRead; if (m_nReceiveBytesWanted > 0) return nRead; const uint32_t nCurrentBytesLen = (uint32_t)m_pfiReceiveBuffer->GetPosition(); if (m_NegotiatingState != ONS_BASIC_CLIENTA_RANDOMPART && m_NegotiatingState != ONS_BASIC_SERVER_DHANSWER){ // don't have the keys yet BYTE* pCryptBuffer = m_pfiReceiveBuffer->Detach(); RC4Crypt(pCryptBuffer, pCryptBuffer, nCurrentBytesLen, m_pRC4ReceiveKey); m_pfiReceiveBuffer->Attach(pCryptBuffer, 512); } m_pfiReceiveBuffer->SeekToBegin(); switch (m_NegotiatingState){ case ONS_NONE: // would be a bug ASSERT( false ); return 0; case ONS_BASIC_CLIENTA_RANDOMPART:{ ASSERT( m_pRC4ReceiveKey == NULL ); uchar achKeyData[21]; md4cpy(achKeyData, thePrefs.GetUserHash()); achKeyData[16] = MAGICVALUE_REQUESTER; m_pfiReceiveBuffer->Read(achKeyData + 17, 4); // random key part sent from remote client MD5Sum md5(achKeyData, sizeof(achKeyData)); m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); achKeyData[16] = MAGICVALUE_SERVER; md5.Calculate(achKeyData, sizeof(achKeyData)); m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); m_NegotiatingState = ONS_BASIC_CLIENTA_MAGICVALUE; m_nReceiveBytesWanted = 4; break; } case ONS_BASIC_CLIENTA_MAGICVALUE:{ uint32_t dwValue = m_pfiReceiveBuffer->ReadUInt32(); if (dwValue == MAGICVALUE_SYNC){ // yup, the one or the other way it worked, this is an encrypted stream //DEBUG_ONLY( DebugLog(_T("Received proper magic value, clientIP: %s"), DbgGetIPString()) ); // set the receiver key m_NegotiatingState = ONS_BASIC_CLIENTA_METHODTAGSPADLEN; m_nReceiveBytesWanted = 3; } else{ DebugLogError(_T("CEncryptedStreamSocket: Received wrong magic value from clientIP %s on a supposly encrytped stream / Wrong Header"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } break; } case ONS_BASIC_CLIENTA_METHODTAGSPADLEN: m_dbgbyEncryptionSupported = m_pfiReceiveBuffer->ReadUInt8(); m_dbgbyEncryptionRequested = m_pfiReceiveBuffer->ReadUInt8(); if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION) AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Client %s preffered unsupported encryption method (%i)"), DbgGetIPString(), m_dbgbyEncryptionRequested); m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8(); m_NegotiatingState = ONS_BASIC_CLIENTA_PADDING; //if (m_nReceiveBytesWanted > 16) // AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Client %s sent more than 16 (%i) padding bytes"), DbgGetIPString(), m_nReceiveBytesWanted); if (m_nReceiveBytesWanted > 0) break; case ONS_BASIC_CLIENTA_PADDING:{ // ignore the random bytes, send the response, set status complete CSafeMemFile fileResponse(26); fileResponse.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySelectedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version, so no need to look which the other client preferred fileResponse.WriteUInt8(bySelectedEncryptionMethod); SOCKADDR_IN sockAddr = {0}; int nSockAddrLen = sizeof(sockAddr); GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen); const uint8_t byPaddingLen = theApp.serverconnect->AwaitingTestFromIP(sockAddr.sin_addr.S_un.S_addr) ? 16 : (thePrefs.GetCryptTCPPaddingLength() + 1); uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % byPaddingLen); fileResponse.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) fileResponse.WriteUInt8(static_cast<uint8_t>(rand() & 0xFF)); SendNegotiatingData(fileResponse.GetBuffer(), (uint32_t)fileResponse.GetLength()); m_NegotiatingState = ONS_COMPLETE; m_StreamCryptState = ECS_ENCRYPTING; //DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (incoming)"), DbgGetIPString()) ); break; } case ONS_BASIC_CLIENTB_MAGICVALUE:{ if (m_pfiReceiveBuffer->ReadUInt32() != MAGICVALUE_SYNC){ DebugLogError(_T("CEncryptedStreamSocket: EncryptedstreamSyncError: Client sent wrong Magic Value as answer, cannot complete handshake (%s)"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } m_NegotiatingState = ONS_BASIC_CLIENTB_METHODTAGSPADLEN; m_nReceiveBytesWanted = 2; break; } case ONS_BASIC_CLIENTB_METHODTAGSPADLEN:{ m_dbgbyEncryptionMethodSet = m_pfiReceiveBuffer->ReadUInt8(); if (m_dbgbyEncryptionMethodSet != ENM_OBFUSCATION){ DebugLogError( _T("CEncryptedStreamSocket: Client %s set unsupported encryption method (%i), handshake failed"), DbgGetIPString(), m_dbgbyEncryptionMethodSet); OnError(ERR_ENCRYPTION); return (-1); } m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8(); m_NegotiatingState = ONS_BASIC_CLIENTB_PADDING; if (m_nReceiveBytesWanted > 0) break; } case ONS_BASIC_CLIENTB_PADDING: // ignore the random bytes, the handshake is complete m_NegotiatingState = ONS_COMPLETE; m_StreamCryptState = ECS_ENCRYPTING; //DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished Obufscation handshake with client %s (outgoing)"), DbgGetIPString()) ); break; case ONS_BASIC_SERVER_DHANSWER:{ ASSERT( !m_cryptDHA.IsZero() ); uchar aBuffer[PRIMESIZE_BYTES + 1]; m_pfiReceiveBuffer->Read(aBuffer, PRIMESIZE_BYTES); CryptoPP::Integer cryptDHAnswer((byte*)aBuffer, PRIMESIZE_BYTES); CryptoPP::Integer cryptDHPrime((byte*)dh768_p, PRIMESIZE_BYTES); // our fixed prime CryptoPP::Integer cryptResult = CryptoPP::a_exp_b_mod_c(cryptDHAnswer, m_cryptDHA, cryptDHPrime); m_cryptDHA = 0; DEBUG_ONLY( ZeroMemory(aBuffer, sizeof(aBuffer)) ); ASSERT( cryptResult.MinEncodedSize() <= PRIMESIZE_BYTES ); // create the keys cryptResult.Encode(aBuffer, PRIMESIZE_BYTES); aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_REQUESTER; MD5Sum md5(aBuffer, sizeof(aBuffer)); m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_SERVER; md5.Calculate(aBuffer, sizeof(aBuffer)); m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL); m_NegotiatingState = ONS_BASIC_SERVER_MAGICVALUE; m_nReceiveBytesWanted = 4; break; } case ONS_BASIC_SERVER_MAGICVALUE:{ uint32_t dwValue = m_pfiReceiveBuffer->ReadUInt32(); if (dwValue == MAGICVALUE_SYNC){ // yup, the one or the other way it worked, this is an encrypted stream DebugLog(_T("Received proper magic value after DH-Agreement from Serverconnection IP: %s"), DbgGetIPString()); // set the receiver key m_NegotiatingState = ONS_BASIC_SERVER_METHODTAGSPADLEN; m_nReceiveBytesWanted = 3; } else{ DebugLogError(_T("CEncryptedStreamSocket: Received wrong magic value after DH-Agreement from Serverconnection"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return (-1); } break; } case ONS_BASIC_SERVER_METHODTAGSPADLEN: m_dbgbyEncryptionSupported = m_pfiReceiveBuffer->ReadUInt8(); m_dbgbyEncryptionRequested = m_pfiReceiveBuffer->ReadUInt8(); if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION) AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Server %s preffered unsupported encryption method (%i)"), DbgGetIPString(), m_dbgbyEncryptionRequested); m_nReceiveBytesWanted = m_pfiReceiveBuffer->ReadUInt8(); m_NegotiatingState = ONS_BASIC_SERVER_PADDING; if (m_nReceiveBytesWanted > 16) AddDebugLogLine(DLP_LOW, false, _T("CEncryptedStreamSocket: Server %s sent more than 16 (%i) padding bytes"), DbgGetIPString(), m_nReceiveBytesWanted); if (m_nReceiveBytesWanted > 0) break; case ONS_BASIC_SERVER_PADDING:{ // ignore the random bytes (they are decrypted already), send the response, set status complete CSafeMemFile fileResponse(26); fileResponse.WriteUInt32(MAGICVALUE_SYNC); const uint8_t bySelectedEncryptionMethod = ENM_OBFUSCATION; // we do not support any further encryption in this version, so no need to look which the other client preferred fileResponse.WriteUInt8(bySelectedEncryptionMethod); uint8_t byPadding = (uint8_t)(cryptRandomGen.GenerateByte() % 16); fileResponse.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) fileResponse.WriteUInt8(static_cast<uint8_t>(rand() & 0xFF)); m_NegotiatingState = ONS_BASIC_SERVER_DELAYEDSENDING; SendNegotiatingData(fileResponse.GetBuffer(), (uint32_t)fileResponse.GetLength(), 0, true); // don't actually send it right now, store it in our sendbuffer m_StreamCryptState = ECS_ENCRYPTING; DEBUG_ONLY( DebugLog(_T("CEncryptedStreamSocket: Finished DH Obufscation handshake with Server %s"), DbgGetIPString()) ); break; } default: ASSERT( false ); } m_pfiReceiveBuffer->SeekToBegin(); } if (m_pfiReceiveBuffer != NULL) free(m_pfiReceiveBuffer->Detach()); delete m_pfiReceiveBuffer; m_pfiReceiveBuffer = NULL; return nRead; } catch(CFileException* error){ // can only be caused by a bug in negationhandling, not by the datastream error->Delete(); ASSERT( false ); OnError(ERR_ENCRYPTION); if (m_pfiReceiveBuffer != NULL) free(m_pfiReceiveBuffer->Detach()); delete m_pfiReceiveBuffer; m_pfiReceiveBuffer = NULL; return (-1); } }
int CEncryptedStreamSocket::Receive(void* lpBuf, int nBufLen, int nFlags){ m_nObfuscationBytesReceived = CAsyncSocketEx::Receive(lpBuf, nBufLen, nFlags); m_bFullReceive = m_nObfuscationBytesReceived == (uint32_t)nBufLen; if(m_nObfuscationBytesReceived == SOCKET_ERROR || m_nObfuscationBytesReceived <= 0){ return m_nObfuscationBytesReceived; } switch (m_StreamCryptState) { case ECS_NONE: // disabled, just pass it through return m_nObfuscationBytesReceived; case ECS_PENDING: case ECS_PENDING_SERVER: ASSERT( false ); DebugLogError(_T("CEncryptedStreamSocket Received data before sending on outgoing connection")); m_StreamCryptState = ECS_NONE; return m_nObfuscationBytesReceived; case ECS_UNKNOWN:{ uint32_t nRead = 1; bool bNormalHeader = false; switch (((uchar*)lpBuf)[0]){ case OP_EDONKEYPROT: case OP_PACKEDPROT: case OP_EMULEPROT: bNormalHeader = true; break; } if (!bNormalHeader){ StartNegotiation(false); const uint32_t nNegRes = Negotiate((uchar*)lpBuf + nRead, m_nObfuscationBytesReceived - nRead); if (nNegRes == (-1)) return 0; nRead += nNegRes; if (nRead != (uint32_t)m_nObfuscationBytesReceived){ // this means we have more data then the current negotiation step required (or there is a bug) and this should never happen // (note: even if it just finished the handshake here, there still can be no data left, since the other client didnt received our response yet) DebugLogError(_T("CEncryptedStreamSocket: Client %s sent more data then expected while negotiating, disconnecting (1)"), DbgGetIPString()); OnError(ERR_ENCRYPTION); } return 0; } else{ // doesn't seems to be encrypted m_StreamCryptState = ECS_NONE; // if we require an encrypted connection, cut the connection here. This shouldn't happen that often // at least with other up-to-date eMule clients because they check for incompability before connecting if possible if (thePrefs.IsClientCryptLayerRequired()){ // TODO: Remove me when i have been solved // Even if the Require option is enabled, we currently have to accept unencrypted connection which are made // for lowid/firewall checks from servers and other from us selected client. Otherwise, this option would // always result in a lowid/firewalled status. This is of course not nice, but we can't avoid this walkarround // untill servers and kad completely support encryption too, which will at least for kad take a bit // only exception is the .ini option ClientCryptLayerRequiredStrict which will even ignore test connections // Update: New server now support encrypted callbacks SOCKADDR_IN sockAddr = {0}; int nSockAddrLen = sizeof(sockAddr); GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen); if (thePrefs.IsClientCryptLayerRequiredStrict() || (!theApp.serverconnect->AwaitingTestFromIP(sockAddr.sin_addr.S_un.S_addr) && !theApp.clientlist->IsKadFirewallCheckIP(sockAddr.sin_addr.S_un.S_addr)) ) { #if defined(_DEBUG) || defined(_BETA) // TODO: Remove after testing AddDebugLogLine(DLP_DEFAULT, false, _T("Rejected incoming connection because Obfuscation was required but not used %s"), DbgGetIPString() ); #endif OnError(ERR_ENCRYPTION_NOTALLOWED); return 0; } else AddDebugLogLine(DLP_DEFAULT, false, _T("Incoming unencrypted firewallcheck connection permitted despite RequireEncryption setting - %s"), DbgGetIPString() ); } return m_nObfuscationBytesReceived; // buffer was unchanged, we can just pass it through } } case ECS_ENCRYPTING: // basic obfuscation enabled and set, so decrypt and pass along RC4Crypt((uchar*)lpBuf, (uchar*)lpBuf, m_nObfuscationBytesReceived, m_pRC4ReceiveKey); return m_nObfuscationBytesReceived; case ECS_NEGOTIATING:{ const uint32_t nRead = Negotiate((uchar*)lpBuf, m_nObfuscationBytesReceived); if (nRead == (-1)) return 0; else if (nRead != (uint32_t)m_nObfuscationBytesReceived && m_StreamCryptState != ECS_ENCRYPTING){ // this means we have more data then the current negotiation step required (or there is a bug) and this should never happen DebugLogError(_T("CEncryptedStreamSocket: Client %s sent more data then expected while negotiating, disconnecting (2)"), DbgGetIPString()); OnError(ERR_ENCRYPTION); return 0; } else if (nRead != (uint32_t)m_nObfuscationBytesReceived && m_StreamCryptState == ECS_ENCRYPTING){ // we finished the handshake and if we this was an outgoing connection it is allowed (but strange and unlikely) that the client sent payload DebugLogWarning(_T("CEncryptedStreamSocket: Client %s has finished the handshake but also sent payload on a outgoing connection"), DbgGetIPString()); memmove(lpBuf, (uchar*)lpBuf + nRead, m_nObfuscationBytesReceived - nRead); return m_nObfuscationBytesReceived - nRead; } else return 0; } default: ASSERT( false ); return m_nObfuscationBytesReceived; } }
bool CServerSocket::ProcessPacket(const BYTE* packet, uint32 size, uint8 opcode) { try { switch (opcode) { case OP_SERVERMESSAGE:{ if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("ServerMsg - OP_ServerMessage\n")); CServer* pServer = cur_server ? theApp.serverlist->GetServerByAddress(cur_server->GetAddress(), cur_server->GetPort()) : NULL; CSafeMemFile data(packet, size); CString strMessages(data.ReadString(pServer ? pServer->GetUnicodeSupport() : false)); if (thePrefs.GetDebugServerTCPLevel() > 0){ UINT uAddData = (UINT)(data.GetLength() - data.GetPosition()); if (uAddData > 0){ Debug(_T("*** NOTE: OP_ServerMessage: ***AddData: %u bytes\n"), uAddData); DebugHexDump(packet + data.GetPosition(), uAddData); } } // 16.40 servers do not send separate OP_SERVERMESSAGE packets for each line; // instead of this they are sending all text lines with one OP_SERVERMESSAGE packet. int iPos = 0; CString message = strMessages.Tokenize(_T("\r\n"), iPos); while (!message.IsEmpty()) { bool bOutputMessage = true; if (_tcsnicmp(message, _T("server version"), 14) == 0){ CString strVer = message.Mid(14); strVer.Trim(); strVer = strVer.Left(64); // truncate string to avoid misuse by servers in showing ads if (pServer){ UINT nVerMaj, nVerMin; if (_stscanf(strVer, _T("%u.%u"), &nVerMaj, &nVerMin) == 2) strVer.Format(_T("%u.%02u"), nVerMaj, nVerMin); pServer->SetVersion(strVer); theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer(pServer); theApp.emuledlg->serverwnd->UpdateMyInfo(); } if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("%s\n"), message); } else if (_tcsncmp(message, _T("ERROR"), 5) == 0){ LogError(LOG_STATUSBAR, _T("%s %s (%s:%u) - %s"), GetResString(IDS_ERROR), pServer ? pServer->GetListName() : GetResString(IDS_PW_SERVER), cur_server ? cur_server->GetAddress() : _T(""), cur_server ? cur_server->GetPort() : 0, message.Mid(5).Trim(_T(" :"))); bOutputMessage = false; } else if (_tcsncmp(message, _T("WARNING"), 7) == 0){ LogWarning(LOG_STATUSBAR, _T("%s %s (%s:%u) - %s"), GetResString(IDS_WARNING), pServer ? pServer->GetListName() : GetResString(IDS_PW_SERVER), cur_server ? cur_server->GetAddress() : _T(""), cur_server ? cur_server->GetPort() : 0, message.Mid(7).Trim(_T(" :"))); bOutputMessage = false; } if (message.Find(_T("[emDynIP: ")) != -1 && message.Find(_T("]")) != -1 && message.Find(_T("[emDynIP: ")) < message.Find(_T("]"))){ CString dynip = message.Mid(message.Find(_T("[emDynIP: ")) + 10, message.Find(_T("]")) - (message.Find(_T("[emDynIP: ")) + 10)); dynip.Trim(); if (dynip.GetLength() && dynip.GetLength() < 51){ // Verify that we really received a DN. if (pServer && inet_addr(CStringA(dynip)) == INADDR_NONE){ // Update the dynIP of this server, but do not reset it's IP // which we just determined during connecting. CString strOldDynIP = pServer->GetDynIP(); pServer->SetDynIP(dynip); // If a dynIP-server changed its address or, if this is the // first time we get the dynIP-address for a server which we // already have as non-dynIP in our list, we need to remove // an already available server with the same 'dynIP:port'. if (strOldDynIP.CompareNoCase(pServer->GetDynIP()) != 0) theApp.serverlist->RemoveDuplicatesByAddress(pServer); if (cur_server) cur_server->SetDynIP(dynip); theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer(pServer); theApp.emuledlg->serverwnd->UpdateMyInfo(); } } } if (bOutputMessage) { if (m_bStartNewMessageLog) { m_bStartNewMessageLog = false; theApp.emuledlg->AddServerMessageLine(LOG_INFO, _T("")); if (cur_server) { CString strMsg; if (IsObfusicating()) strMsg.Format(_T("%s: ") + GetResString(IDS_CONNECTEDTOOBFUSCATED) + _T(" (%s:%u)"), CTime::GetCurrentTime().Format(thePrefs.GetDateTimeFormat4Log()), cur_server->GetListName(), cur_server->GetAddress(), cur_server->GetObfuscationPortTCP()); else strMsg.Format(_T("%s: ") + GetResString(IDS_CONNECTEDTO) + _T(" (%s:%u)"), CTime::GetCurrentTime().Format(thePrefs.GetDateTimeFormat4Log()), cur_server->GetListName(), cur_server->GetAddress(), cur_server->GetPort()); theApp.emuledlg->AddServerMessageLine(LOG_SUCCESS, strMsg); } } theApp.emuledlg->AddServerMessageLine(LOG_INFO, message); } message = strMessages.Tokenize(_T("\r\n"), iPos); } break; } case OP_IDCHANGE:{ if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("ServerMsg - OP_IDChange\n")); if (size < sizeof(LoginAnswer_Struct)){ throw GetResString(IDS_ERR_BADSERVERREPLY); } LoginAnswer_Struct* la = (LoginAnswer_Struct*)packet; // save TCP flags in 'cur_server' CServer* pServer = NULL; ASSERT( cur_server ); if (cur_server){ if (size >= sizeof(LoginAnswer_Struct)+4){ DWORD dwFlags = *((uint32*)(packet + sizeof(LoginAnswer_Struct))); if (thePrefs.GetDebugServerTCPLevel() > 0){ CString strInfo; strInfo.AppendFormat(_T(" TCP Flags=0x%08x"), dwFlags); const DWORD dwKnownBits = SRV_TCPFLG_COMPRESSION | SRV_TCPFLG_NEWTAGS | SRV_TCPFLG_UNICODE | SRV_TCPFLG_RELATEDSEARCH | SRV_TCPFLG_TYPETAGINTEGER | SRV_TCPFLG_LARGEFILES | SRV_TCPFLG_TCPOBFUSCATION; if (dwFlags & ~dwKnownBits) strInfo.AppendFormat(_T(" ***UnkBits=0x%08x"), dwFlags & ~dwKnownBits); if (dwFlags & SRV_TCPFLG_COMPRESSION) strInfo.AppendFormat(_T(" Compression=1")); if (dwFlags & SRV_TCPFLG_NEWTAGS) strInfo.AppendFormat(_T(" NewTags=1")); if (dwFlags & SRV_TCPFLG_UNICODE) strInfo.AppendFormat(_T(" Unicode=1")); if (dwFlags & SRV_TCPFLG_RELATEDSEARCH) strInfo.AppendFormat(_T(" RelatedSearch=1")); if (dwFlags & SRV_TCPFLG_TYPETAGINTEGER) strInfo.AppendFormat(_T(" IntTypeTags=1")); if (dwFlags & SRV_TCPFLG_LARGEFILES) strInfo.AppendFormat(_T(" LargeFiles=1")); if (dwFlags & SRV_TCPFLG_TCPOBFUSCATION) strInfo.AppendFormat(_T(" TCP_Obfscation=1")); Debug(_T("%s\n"), strInfo); } cur_server->SetTCPFlags(dwFlags); } else cur_server->SetTCPFlags(0); // copy TCP flags into the server in the server list pServer = theApp.serverlist->GetServerByAddress(cur_server->GetAddress(), cur_server->GetPort()); if (pServer) pServer->SetTCPFlags(cur_server->GetTCPFlags()); } uint32 dwServerReportedIP = 0; uint32 dwObfuscationTCPPort = 0; if (size >= 20){ dwServerReportedIP = *((uint32*)(packet + 12)); if (::IsLowID(dwServerReportedIP)){ ASSERT( false ); dwServerReportedIP = 0; } ASSERT( dwServerReportedIP == la->clientid || ::IsLowID(la->clientid) ); dwObfuscationTCPPort = *((uint32*)(packet + 16)); if (cur_server != NULL && dwObfuscationTCPPort != 0) cur_server->SetObfuscationPortTCP((uint16)dwObfuscationTCPPort); if (pServer != NULL && dwObfuscationTCPPort != 0) pServer->SetObfuscationPortTCP((uint16)dwObfuscationTCPPort); } //Xman // Maella -Activate Smart Low ID check- /* if (la->clientid == 0) { uint8 state = thePrefs.GetSmartIdState(); if ( state > 0 ) { if (state == 1) theApp.emuledlg->RefreshUPnP(false); // refresh the UPnP mappings once state++; if( state > 2 ) thePrefs.SetSmartIdState(0); else thePrefs.SetSmartIdState(state); } break; } if( thePrefs.GetSmartIdCheck() ){ if (!IsLowID(la->clientid)) thePrefs.SetSmartIdState(1); else{ uint8 state = thePrefs.GetSmartIdState(); if ( state > 0 ) { if (state == 1) theApp.emuledlg->RefreshUPnP(false); // refresh the UPnP mappings once state++; if( state > 2 ) thePrefs.SetSmartIdState(0); else thePrefs.SetSmartIdState(state); if (!m_bManualSingleConnect) break; // if this is a connect to any/multiple server connection try, disconnect and try another one } } } */ if(la->clientid == 0){ // Reset attempts counter thePrefs.SetSmartIdState(0); } else if(la->clientid >= 16777216){ // High ID => reset attempts counter thePrefs.SetSmartIdState(0); } else if(thePrefs.GetSmartIdCheck() == true){ // Low ID => Check and increment attempts counter uint8 attempts = thePrefs.GetSmartIdState(); if(attempts < 3){ //zz_fly :: not needed, rebind upnp on ipchange :: start //Official UPNP /* if (!thePrefs.m_bUseACATUPnPCurrent && (attempts == 1)) theApp.emuledlg->RefreshUPnP(false); // refresh the UPnP mappings once */ //zz_fly :: end SetConnectionState(CS_ERROR); thePrefs.SetSmartIdState(++attempts); AddLogLine(true, _T("LowID -- Trying Again (attempts %i)"), attempts); break; // Retries } else if (!m_bManualSingleConnect) break; // if this is a connect to any/multiple server connection try, disconnect and try another one } //Xman end // we need to know our client's HighID when sending our shared files (done indirectly on SetConnectionState) serverconnect->clientid = la->clientid; if (connectionstate != CS_CONNECTED) { SetConnectionState(CS_CONNECTED); theApp.OnlineSig(); // Added By Bouc7 } serverconnect->SetClientID(la->clientid); if (::IsLowID(la->clientid) && dwServerReportedIP != 0) theApp.SetPublicIP(dwServerReportedIP); AddLogLine(false, GetResString(IDS_NEWCLIENTID), la->clientid); //Xman -Reask sources after IP change- v4 if(serverconnect->GetClientID() != 0 && theApp.last_valid_ip != 0 && serverconnect->GetClientID() != theApp.last_valid_ip && serverconnect->GetClientID() != theApp.last_valid_serverid) { //remark: this code doesn't trigger when changing low->hidh-ID and we already had //a session with this HighID-IP. This is because we don't know when this last lowID-session was. //but there is no need to trigger when changing low to high-id but keeping the IP, we can'tt loose the waiting-position! { // Public IP has been changed, it's necessary to inform all sources about it // All sources would be informed during their next session refresh (with TCP) // about the new IP. // ==> Quick start [TPT] - Max if(thePrefs.GetQuickStart() && thePrefs.GetQuickStartAfterIPChange()) { theApp.downloadqueue->quickflag = 0; theApp.downloadqueue->quickflags = 0; } // <== Quick start [TPT] - Max if(GetTickCount() - theApp.last_ip_change > FILEREASKTIME + 60000){ theApp.clientlist->TrigReaskForDownload(true); theApp.last_ip_change=::GetTickCount(); theApp.m_bneedpublicIP=false; AddLogLine(false, _T("Change from %u (%s ID) to %u (%s ID) detected%s"), theApp.last_valid_serverid, (theApp.last_valid_serverid < 16777216) ? _T("low") : _T("high"), serverconnect->GetClientID(), (serverconnect->GetClientID() < 16777216) ? _T("low") : _T("high"), _T(", all sources will be reasked immediately")); } else { theApp.clientlist->TrigReaskForDownload(false); theApp.last_ip_change=::GetTickCount(); theApp.m_bneedpublicIP=false; AddLogLine(false, _T("Change from %u (%s ID) to %u (%s ID) detected%s"), theApp.last_valid_serverid, (theApp.last_valid_serverid < 16777216) ? _T("low") : _T("high"), serverconnect->GetClientID(), (serverconnect->GetClientID() < 16777216) ? _T("low") : _T("high"), _T(", all sources will be reasked within the next 10 minutes")); } // ==> UPnP support [MoNKi] - leuk_he /* // official UPNP theApp.emuledlg->RefreshUPnP(false); // refresh the UPnP mappings once // official UPNP */ theApp.RebindUPnP(); // <== UPnP support [MoNKi] - leuk_he } } if(serverconnect->GetClientID() != 0 && theApp.last_ip_change==0) theApp.last_ip_change=::GetTickCount(); if(serverconnect->GetClientID() != 0 && serverconnect->GetClientID() != theApp.last_valid_serverid){ // Keep track of a change of the global IP theApp.last_valid_serverid = serverconnect->GetClientID(); } theApp.last_valid_ip=theApp.GetPublicIP(true); //can also be 0 theApp.last_traffic_reception=::GetTickCount(); theApp.internetmaybedown=false; //we have to reopen here if we are using server only // Xman end theApp.downloadqueue->ResetLocalServerRequests(); break; } case OP_SEARCHRESULT:{ if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("ServerMsg - OP_SearchResult\n")); CServer* cur_srv = (serverconnect) ? serverconnect->GetCurrentServer() : NULL; CServer* pServer = cur_srv ? theApp.serverlist->GetServerByAddress(cur_srv->GetAddress(), cur_srv->GetPort()) : NULL; (void)pServer; bool bMoreResultsAvailable; UINT uSearchResults = theApp.searchlist->ProcessSearchAnswer(packet, size, true/*pServer ? pServer->GetUnicodeSupport() : false*/, cur_srv ? cur_srv->GetIP() : 0, cur_srv ? cur_srv->GetPort() : (uint16)0, &bMoreResultsAvailable); theApp.emuledlg->searchwnd->LocalEd2kSearchEnd(uSearchResults, bMoreResultsAvailable); break; } case OP_FOUNDSOURCES_OBFU: case OP_FOUNDSOURCES:{ if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("ServerMsg - OP_FoundSources%s; Sources=%u %s\n"), (opcode == OP_FOUNDSOURCES_OBFU) ? _T("_OBFU") : _T(""), (UINT)packet[16], DbgGetFileInfo(packet)); ASSERT( cur_server ); if (cur_server) { CSafeMemFile sources(packet, size); uchar fileid[16]; sources.ReadHash16(fileid); if (CPartFile* file = theApp.downloadqueue->GetFileByID(fileid)) file->AddSources(&sources,cur_server->GetIP(), cur_server->GetPort(), (opcode == OP_FOUNDSOURCES_OBFU)); } break; } case OP_SERVERSTATUS:{ if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("ServerMsg - OP_ServerStatus\n")); // FIXME some statuspackets have a different size -> why? structur? if (size < 8) break;//throw "Invalid status packet"; uint32 cur_user = PeekUInt32(packet); uint32 cur_files = PeekUInt32(packet+4); CServer* pServer = cur_server ? theApp.serverlist->GetServerByAddress(cur_server->GetAddress(), cur_server->GetPort()) : NULL; if (pServer){ pServer->SetUserCount(cur_user); pServer->SetFileCount(cur_files); theApp.emuledlg->ShowUserCount(); theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer(pServer); theApp.emuledlg->serverwnd->UpdateMyInfo(); } if (thePrefs.GetDebugServerTCPLevel() > 0){ if (size > 8){ Debug(_T("*** NOTE: OP_ServerStatus: ***AddData: %u bytes\n"), size - 8); DebugHexDump(packet + 8, size - 8); } } break; } case OP_SERVERIDENT:{ // OP_SERVERIDENT - this is sent by the server only if we send a OP_GETSERVERLIST if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("ServerMsg - OP_ServerIdent\n")); if (size<16+4+2+4){ if (thePrefs.GetVerbose()) DebugLogError(_T("%s"), GetResString(IDS_ERR_KNOWNSERVERINFOREC)); break;// throw "Invalid server info received"; } CServer* pServer = cur_server ? theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort()) : NULL; CString strInfo; CSafeMemFile data(packet, size); uint8 aucHash[16]; data.ReadHash16(aucHash); if (thePrefs.GetDebugServerTCPLevel() > 0) strInfo.AppendFormat(_T("Hash=%s (%s)"), md4str(aucHash), DbgGetHashTypeString(aucHash)); uint32 nServerIP = data.ReadUInt32(); uint16 nServerPort = data.ReadUInt16(); if (thePrefs.GetDebugServerTCPLevel() > 0) strInfo.AppendFormat(_T(" IP=%s:%u"), ipstr(nServerIP), nServerPort); UINT nTags = data.ReadUInt32(); if (thePrefs.GetDebugServerTCPLevel() > 0) strInfo.AppendFormat(_T(" Tags=%u"), nTags); CString strName; CString strDescription; for (UINT i = 0; i < nTags; i++){ CTag tag(&data, pServer ? pServer->GetUnicodeSupport() : false); if (tag.GetNameID() == ST_SERVERNAME){ if (tag.IsStr()){ strName = tag.GetStr(); if (thePrefs.GetDebugServerTCPLevel() > 0) strInfo.AppendFormat(_T(" Name=%s"), strName); } } else if (tag.GetNameID() == ST_DESCRIPTION){ if (tag.IsStr()){ strDescription = tag.GetStr(); if (thePrefs.GetDebugServerTCPLevel() > 0) strInfo.AppendFormat(_T(" Desc=%s"), strDescription); } } else if (thePrefs.GetDebugServerTCPLevel() > 0) strInfo.AppendFormat(_T(" ***UnkTag: 0x%02x=%u"), tag.GetNameID(), tag.GetInt()); } if (thePrefs.GetDebugServerTCPLevel() > 0){ strInfo += _T('\n'); Debug(_T("%s"), strInfo); UINT uAddData = (UINT)(data.GetLength() - data.GetPosition()); if (uAddData > 0){ Debug(_T("*** NOTE: OP_ServerIdent: ***AddData: %u bytes\n"), uAddData); DebugHexDump(packet + data.GetPosition(), uAddData); } } if (pServer){ pServer->SetListName(strName); pServer->SetDescription(strDescription); if (((uint32*)aucHash)[0] == 0x2A2A2A2A){ const CString& rstrVersion = pServer->GetVersion(); if (!rstrVersion.IsEmpty()) pServer->SetVersion(_T("eFarm ") + rstrVersion); else pServer->SetVersion(_T("eFarm")); } theApp.emuledlg->ShowConnectionState(); theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer(pServer); } break; } // tecxx 1609 2002 - add server's serverlist to own serverlist case OP_SERVERLIST:{ if (!thePrefs.GetAddServersFromServer()) break; if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("ServerMsg - OP_ServerList\n")); try{ CSafeMemFile servers(packet, size); UINT count = servers.ReadUInt8(); // check if packet is valid if (1 + count*(4+2) > size) count = 0; int addcount = 0; while(count) { uint32 ip = servers.ReadUInt32(); uint16 port = servers.ReadUInt16(); CServer* srv = new CServer(port, ipstr(ip)); srv->SetListName(srv->GetFullIP()); srv->SetPreference(SRV_PR_LOW); if (!theApp.emuledlg->serverwnd->serverlistctrl.AddServer(srv, true)) delete srv; else addcount++; count--; } if (addcount) AddLogLine(false, GetResString(IDS_NEWSERVERS), addcount); if (thePrefs.GetDebugServerTCPLevel() > 0){ UINT uAddData = (UINT)(servers.GetLength() - servers.GetPosition()); if (uAddData > 0){ Debug(_T("*** NOTE: OP_ServerList: ***AddData: %u bytes\n"), uAddData); DebugHexDump(packet + servers.GetPosition(), uAddData); } } } catch(CFileException* error){ if (thePrefs.GetVerbose()) DebugLogError(_T("%s"), GetResString(IDS_ERR_BADSERVERLISTRECEIVED)); error->Delete(); } break; } case OP_CALLBACKREQUESTED:{ if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("ServerMsg - OP_CallbackRequested: %s\n"), (size >= 23) ? _T("With Cryptflag and Userhash") : _T("Without Cryptflag and Userhash")); if (size >= 6) { uint32 dwIP = PeekUInt32(packet); if (theApp.ipfilter->IsFiltered(dwIP)){ theStats.filteredclients++; if (thePrefs.GetLogFilteredIPs()) AddDebugLogLine(false, _T("Ignored callback request (IP=%s) - IP filter (%s)"), ipstr(dwIP), theApp.ipfilter->GetLastHit()); break; } if (theApp.clientlist->IsBannedClient(dwIP)){ if (thePrefs.GetLogBannedClients()){ CUpDownClient* pClient = theApp.clientlist->FindClientByIP(dwIP); //Xman Code Fix /* AddDebugLogLine(false, _T("Ignored callback request from banned client %s; %s"), ipstr(dwIP), pClient->DbgGetClientInfo()); */ AddDebugLogLine(false, _T("Ignored callback request from banned client %s; %s"), ipstr(dwIP), pClient ? pClient->DbgGetClientInfo() : _T("unknown")); //Xman end } break; } uint16 nPort = PeekUInt16(packet+4); uint8 byCryptOptions = 0; uchar achUserHash[16]; if (size >= 23){ byCryptOptions = packet[6]; md4cpy(achUserHash, packet + 7); } CUpDownClient* client = theApp.clientlist->FindClientByIP(dwIP,nPort); if (client == NULL) { client = new CUpDownClient(0,nPort,dwIP,0,0,true); //Xman Code Improvement don't search new generated clients in lists /* theApp.clientlist->AddClient(client); */ theApp.clientlist->AddClient(client, true); //Xman end } if (size >= 23 && client->HasValidHash()){ if (md4cmp(client->GetUserHash(), achUserHash) != 0){ DebugLogError(_T("Reported Userhash from OP_CALLBACKREQUESTED differs with our stored hash")); // disable crypt support since we dont know which hash is true client->SetCryptLayerRequest(false); client->SetCryptLayerSupport(false); client->SetCryptLayerRequires(false); } else{ client->SetConnectOptions(byCryptOptions, true, false); client->SetDirectUDPCallbackSupport(false); } } else if (size >= 23){ client->SetUserHash(achUserHash); client->SetCryptLayerSupport((byCryptOptions & 0x01) != 0); client->SetCryptLayerRequest((byCryptOptions & 0x02) != 0); client->SetCryptLayerRequires((byCryptOptions & 0x04) != 0); client->SetDirectUDPCallbackSupport(false); } client->TryToConnect(); } break; } case OP_CALLBACK_FAIL:{ if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("ServerMsg - OP_Callback_Fail %s\n"), DbgGetHexDump(packet, size)); break; } case OP_REJECT:{ if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("ServerMsg - OP_Reject %s\n"), DbgGetHexDump(packet, size)); // this could happen if we send a command with the wrong protocol (e.g. sending a compressed packet to // a server which does not support that protocol). if (thePrefs.GetVerbose()) DebugLogError(_T("Server rejected last command")); break; } default: if (thePrefs.GetDebugServerTCPLevel() > 0) Debug(_T("***NOTE: ServerMsg - Unknown message; opcode=0x%02x %s\n"), opcode, DbgGetHexDump(packet, size)); ; } return true; } catch(CFileException* error) { if (thePrefs.GetVerbose()) { TCHAR szError[MAX_CFEXP_ERRORMSG]; error->m_strFileName = _T("server packet"); error->GetErrorMessage(szError, ARRSIZE(szError)); ProcessPacketError(size, opcode, szError); } ASSERT(0); error->Delete(); if (opcode==OP_SEARCHRESULT || opcode==OP_FOUNDSOURCES) return true; } catch(CMemoryException* error) { ProcessPacketError(size, opcode, _T("CMemoryException")); ASSERT(0); error->Delete(); if (opcode==OP_SEARCHRESULT || opcode==OP_FOUNDSOURCES) return true; } catch(CString error) { ProcessPacketError(size, opcode, error); ASSERT(0); } #ifndef _DEBUG catch(...) { ProcessPacketError(size, opcode, _T("Unknown exception")); ASSERT(0); } #endif SetConnectionState(CS_DISCONNECTED); return false; }
bool CClientUDPSocket::ProcessPacket(const BYTE* packet, uint16 size, uint8 opcode, uint32 ip, uint16 port) { switch(opcode) { case OP_REASKCALLBACKUDP: { if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_ReaskCallbackUDP", NULL, NULL, ip); theStats.AddDownDataOverheadOther(size); CUpDownClient* buddy = theApp.clientlist->GetBuddy(); if( buddy ) { if( size < 17 || buddy->socket == NULL ) break; if (!md4cmp(packet, buddy->GetBuddyID())) { PokeUInt32(const_cast<BYTE*>(packet)+10, ip); PokeUInt16(const_cast<BYTE*>(packet)+14, port); Packet* response = new Packet(OP_EMULEPROT); response->opcode = OP_REASKCALLBACKTCP; response->pBuffer = new char[size]; memcpy(response->pBuffer, packet+10, size-10); response->size = size-10; if (thePrefs.GetDebugClientTCPLevel() > 0) DebugSend("OP__ReaskCallbackTCP", buddy); theStats.AddUpDataOverheadFileRequest(response->size); buddy->socket->SendPacket(response); } } break; } case OP_REASKFILEPING: { theStats.AddDownDataOverheadFileRequest(size); CSafeMemFile data_in(packet, size); uchar reqfilehash[16]; data_in.ReadHash16(reqfilehash); CKnownFile* reqfile = theApp.sharedfiles->GetFileByID(reqfilehash); if (!reqfile) { if (thePrefs.GetDebugClientUDPLevel() > 0) { DebugRecv("OP_ReaskFilePing", NULL, reqfilehash, ip); DebugSend("OP__FileNotFound", NULL); } Packet* response = new Packet(OP_FILENOTFOUND,0,OP_EMULEPROT); theStats.AddUpDataOverheadFileRequest(response->size); SendPacket(response, ip, port); break; } CUpDownClient* sender = theApp.uploadqueue->GetWaitingClientByIP_UDP(ip, port); if (sender) { if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_ReaskFilePing", sender, reqfilehash); //Make sure we are still thinking about the same file if (md4cmp(reqfilehash, sender->GetUploadFileID()) == 0) { sender->AddAskedCount(); sender->SetLastUpRequest(); //I messed up when I first added extended info to UDP //I should have originally used the entire ProcessExtenedInfo the first time. //So now I am forced to check UDPVersion to see if we are sending all the extended info. //For now on, we should not have to change anything here if we change //anything to the extended info data as this will be taken care of in ProcessExtendedInfo() //Update extended info. if (sender->GetUDPVersion() > 3) { sender->ProcessExtendedInfo(&data_in, reqfile); } //Update our complete source counts. else if (sender->GetUDPVersion() > 2) { uint16 nCompleteCountLast= sender->GetUpCompleteSourcesCount(); uint16 nCompleteCountNew = data_in.ReadUInt16(); sender->SetUpCompleteSourcesCount(nCompleteCountNew); if (nCompleteCountLast != nCompleteCountNew) { reqfile->UpdatePartsInfo(); } } CSafeMemFile data_out(128); if(sender->GetUDPVersion() > 3) { if (reqfile->IsPartFile()) ((CPartFile*)reqfile)->WritePartStatus(&data_out); else data_out.WriteUInt16(0); } data_out.WriteUInt16(theApp.uploadqueue->GetWaitingPosition(sender)); if (thePrefs.GetDebugClientUDPLevel() > 0) DebugSend("OP__ReaskAck", sender); Packet* response = new Packet(&data_out, OP_EMULEPROT); response->opcode = OP_REASKACK; theStats.AddUpDataOverheadFileRequest(response->size); theApp.clientudp->SendPacket(response, ip, port); } else { DebugLogError(_T("Client UDP socket; ReaskFilePing; reqfile does not match")); TRACE(_T("reqfile: %s\n"), DbgGetFileInfo(reqfile->GetFileHash())); TRACE(_T("sender->GetRequestFile(): %s\n"), sender->GetRequestFile() ? DbgGetFileInfo(sender->GetRequestFile()->GetFileHash()) : _T("(null)")); } } else { if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_ReaskFilePing", NULL, reqfilehash, ip); if (((uint32)theApp.uploadqueue->GetWaitingUserCount() + 50) > thePrefs.GetQueueSize()) { if (thePrefs.GetDebugClientUDPLevel() > 0) DebugSend("OP__QueueFull", NULL); Packet* response = new Packet(OP_QUEUEFULL,0,OP_EMULEPROT); theStats.AddUpDataOverheadFileRequest(response->size); SendPacket(response, ip, port); } } break; } case OP_QUEUEFULL: { theStats.AddDownDataOverheadFileRequest(size); CUpDownClient* sender = theApp.downloadqueue->GetDownloadClientByIP_UDP(ip, port); if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_QueueFull", sender, NULL, ip); if (sender){ sender->SetRemoteQueueFull(true); sender->UDPReaskACK(0); } break; } case OP_REASKACK: { theStats.AddDownDataOverheadFileRequest(size); CUpDownClient* sender = theApp.downloadqueue->GetDownloadClientByIP_UDP(ip, port); if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_ReaskAck", sender, NULL, ip); if (sender){ CSafeMemFile data_in(packet, size); if ( sender->GetUDPVersion() > 3 ) { sender->ProcessFileStatus(true, &data_in, sender->GetRequestFile()); } uint16 nRank = data_in.ReadUInt16(); sender->SetRemoteQueueFull(false); sender->UDPReaskACK(nRank); sender->AddAskedCountDown(); } break; } case OP_FILENOTFOUND: { theStats.AddDownDataOverheadFileRequest(size); CUpDownClient* sender = theApp.downloadqueue->GetDownloadClientByIP_UDP(ip, port); if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_FileNotFound", sender, NULL, ip); if (sender){ sender->UDPReaskFNF(); // may delete 'sender'! sender = NULL; } break; } case OP_PORTTEST: { if (thePrefs.GetDebugClientUDPLevel() > 0) DebugRecv("OP_PortTest", NULL, NULL, ip); theStats.AddDownDataOverheadOther(size); if (size == 1){ if (packet[0] == 0x12){ bool ret = theApp.listensocket->SendPortTestReply('1', true); AddDebugLogLine(true, _T("UDP Portcheck packet arrived - ACK sent back (status=%i)"), ret); } } break; } default: theStats.AddDownDataOverheadOther(size); if (thePrefs.GetDebugClientUDPLevel() > 0) { CUpDownClient* sender = theApp.downloadqueue->GetDownloadClientByIP_UDP(ip, port); Debug(_T("Unknown client UDP packet: host=%s:%u (%s) opcode=0x%02x size=%u\n"), ipstr(ip), port, sender ? sender->DbgGetClientInfo() : _T(""), opcode, size); } return false; } return true; }
void CListenSocket::OnAccept(int nErrorCode) { if (!nErrorCode) { m_nPendingConnections++; if (m_nPendingConnections < 1){ ASSERT(0); m_nPendingConnections = 1; } if (TooManySockets(true) && !CGlobalVariable::serverconnect->IsConnecting()){ StopListening(); return; } else if (!bListening) ReStartListening(); //If the client is still at maxconnections, this will allow it to go above it.. But if you don't, you will get a lowID on all servers. uint32 nFataErrors = 0; while (m_nPendingConnections > 0) { m_nPendingConnections--; CClientReqSocket* newclient; SOCKADDR_IN SockAddr = {0}; int iSockAddrLen = sizeof SockAddr; if (thePrefs.GetConditionalTCPAccept() && !thePrefs.GetProxySettings().UseProxy) { _iAcceptConnectionCondRejected = 0; SOCKET sNew = WSAAccept(m_SocketData.hSocket, (SOCKADDR*)&SockAddr, &iSockAddrLen, AcceptConnectionCond, 0); if (sNew == INVALID_SOCKET){ DWORD nError = GetLastError(); if (nError == WSAEWOULDBLOCK){ DebugLogError(LOG_STATUSBAR, _T("%hs: Backlogcounter says %u connections waiting, Accept() says WSAEWOULDBLOCK - setting counter to zero!"), __FUNCTION__, m_nPendingConnections); m_nPendingConnections = 0; break; } else{ if (nError != WSAECONNREFUSED || _iAcceptConnectionCondRejected == 0){ DebugLogError(LOG_STATUSBAR, _T("%hs: Backlogcounter says %u connections waiting, Accept() says %s - setting counter to zero!"), __FUNCTION__, m_nPendingConnections, GetErrorMessage(nError, 1)); nFataErrors++; } else if (_iAcceptConnectionCondRejected == 1) theStats.filteredclients++; } if (nFataErrors > 10){ // the question is what todo on a error. We cant just ignore it because then the backlog will fill up // and lock everything. We can also just endlos try to repeat it because this will lock up eMule // this should basically never happen anyway // however if we are in such a position, try to reinitalize the socket. DebugLogError(LOG_STATUSBAR, _T("%hs: Accept() Error Loop, recreating socket"), __FUNCTION__); Close(); StartListening(); m_nPendingConnections = 0; break; } continue; } newclient = new CClientReqSocket; VERIFY( newclient->InitAsyncSocketExInstance() ); newclient->m_SocketData.hSocket = sNew; newclient->AttachHandle(sNew); AddConnection(); } else { newclient = new CClientReqSocket; if (!Accept(*newclient, (SOCKADDR*)&SockAddr, &iSockAddrLen)){ newclient->Safe_Delete(); DWORD nError = GetLastError(); if (nError == WSAEWOULDBLOCK){ DebugLogError(LOG_STATUSBAR, _T("%hs: Backlogcounter says %u connections waiting, Accept() says WSAEWOULDBLOCK - setting counter to zero!"), __FUNCTION__, m_nPendingConnections); m_nPendingConnections = 0; break; } else{ DebugLogError(LOG_STATUSBAR, _T("%hs: Backlogcounter says %u connections waiting, Accept() says %s - setting counter to zero!"), __FUNCTION__, m_nPendingConnections, GetErrorMessage(nError, 1)); nFataErrors++; } if (nFataErrors > 10){ // the question is what todo on a error. We cant just ignore it because then the backlog will fill up // and lock everything. We can also just endlos try to repeat it because this will lock up eMule // this should basically never happen anyway // however if we are in such a position, try to reinitalize the socket. DebugLogError(LOG_STATUSBAR, _T("%hs: Accept() Error Loop, recreating socket"), __FUNCTION__); Close(); StartListening(); m_nPendingConnections = 0; break; } continue; } AddConnection(); if (SockAddr.sin_addr.S_un.S_addr == 0) // for safety.. { iSockAddrLen = sizeof SockAddr; newclient->GetPeerName((SOCKADDR*)&SockAddr, &iSockAddrLen); DebugLogWarning(_T("SockAddr.sin_addr.S_un.S_addr == 0; GetPeerName returned %s"), ipstr(SockAddr.sin_addr.S_un.S_addr)); } ASSERT( SockAddr.sin_addr.S_un.S_addr != 0 && SockAddr.sin_addr.S_un.S_addr != INADDR_NONE ); if (CGlobalVariable::ipfilter->IsFiltered(SockAddr.sin_addr.S_un.S_addr)){ if (thePrefs.GetLogFilteredIPs()) AddDebugLogLine(false, _T("Rejecting connection attempt (IP=%s) - IP filter (%s)"), ipstr(SockAddr.sin_addr.S_un.S_addr), CGlobalVariable::ipfilter->GetLastHit()); newclient->Safe_Delete(); theStats.filteredclients++; continue; } if (CGlobalVariable::clientlist->IsBannedClient(SockAddr.sin_addr.S_un.S_addr)){ if (thePrefs.GetLogBannedClients()){ CUpDownClient* pClient = CGlobalVariable::clientlist->FindClientByIP(SockAddr.sin_addr.S_un.S_addr); AddDebugLogLine(false, _T("Rejecting connection attempt of banned client %s %s"), ipstr(SockAddr.sin_addr.S_un.S_addr), pClient->DbgGetClientInfo()); } newclient->Safe_Delete(); continue; } } newclient->AsyncSelect(FD_WRITE | FD_READ | FD_CLOSE); } ASSERT( m_nPendingConnections >= 0 ); } }
void CClientUDPSocket::OnReceive(int nErrorCode) { if (nErrorCode) { if (thePrefs.GetVerbose()) DebugLogError(_T("Error: Client UDP socket, error on receive event: %s"), GetErrorMessage(nErrorCode, 1)); } BYTE buffer[5000]; SOCKADDR_IN sockAddr = {0}; int iSockAddrLen = sizeof sockAddr; int length = ReceiveFrom(buffer, sizeof buffer, (SOCKADDR*)&sockAddr, &iSockAddrLen); if (length >= 1 && !(theApp.ipfilter->IsFiltered(sockAddr.sin_addr.S_un.S_addr) || theApp.clientlist->IsBannedClient(sockAddr.sin_addr.S_un.S_addr))) { CString strError; try { switch (buffer[0]) { case OP_EMULEPROT: { if (length >= 2) ProcessPacket(buffer+2, length-2, buffer[1], sockAddr.sin_addr.S_un.S_addr, ntohs(sockAddr.sin_port)); else throw CString(_T("eMule packet too short")); break; } case OP_KADEMLIAPACKEDPROT: { theStats.AddDownDataOverheadKad(length); if (length >= 2) { uint32 nNewSize = length*10+300; byte* unpack = new byte[nNewSize]; uLongf unpackedsize = nNewSize-2; int iZLibResult = uncompress(unpack+2, &unpackedsize, buffer+2, length-2); if (iZLibResult == Z_OK) { unpack[0] = OP_KADEMLIAHEADER; unpack[1] = buffer[1]; try { Kademlia::CKademlia::processPacket(unpack, unpackedsize+2, ntohl(sockAddr.sin_addr.S_un.S_addr), ntohs(sockAddr.sin_port)); } catch(...) { delete[] unpack; throw; } } else { delete[] unpack; CString strError; strError.Format(_T("Failed to uncompress Kad packet: zip error: %d (%hs)"), iZLibResult, zError(iZLibResult)); throw strError; } delete[] unpack; } else throw CString(_T("Kad packet (compressed) too short")); break; } case OP_KADEMLIAHEADER: { theStats.AddDownDataOverheadKad(length); if (length >= 2) Kademlia::CKademlia::processPacket(buffer, length, ntohl(sockAddr.sin_addr.S_un.S_addr), ntohs(sockAddr.sin_port)); else throw CString(_T("Kad packet too short")); break; } default: { CString strError; strError.Format(_T("Unknown protocol 0x%02x"), buffer[0]); throw strError; } } } catch(CFileException* error) { error->Delete(); strError = _T("Invalid packet received"); } catch(CMemoryException* error) { error->Delete(); strError = _T("Memory exception"); } catch(CString error) { strError = error; } catch(Kademlia::CIOException* error) { error->Delete(); strError = _T("Invalid packet received"); } catch(CException* error) { error->Delete(); strError = _T("General packet error"); } catch(...) { strError = _T("Unknown exception"); ASSERT(0); } if (thePrefs.GetVerbose() && !strError.IsEmpty()) { CString strClientInfo; CUpDownClient* client; if (buffer[0] == OP_EMULEPROT) client = theApp.clientlist->FindClientByIP_UDP(sockAddr.sin_addr.S_un.S_addr, ntohs(sockAddr.sin_port)); else client = theApp.clientlist->FindClientByIP_KadPort(sockAddr.sin_addr.S_un.S_addr, ntohs(sockAddr.sin_port)); if (client) strClientInfo = client->DbgGetClientInfo(); else strClientInfo.Format(_T("%s:%u"), ipstr(sockAddr.sin_addr), ntohs(sockAddr.sin_port)); DebugLogWarning(_T("Client UDP socket: prot=0x%02x opcode=0x%02x size=%u %s: %s"), buffer[0], buffer[1], length, strError, strClientInfo); } } else if (length == SOCKET_ERROR) { DWORD dwError = WSAGetLastError(); if (dwError == WSAECONNRESET) { // Depending on local and remote OS and depending on used local (remote?) router we may receive // WSAECONNRESET errors. According some KB articles, this is a special way of winsock to report // that a sent UDP packet was not received by the remote host because it was not listening on // the specified port -> no eMule running there. // // TODO: So, actually we should do something with this information and drop the related Kad node // or eMule client... ; } if (thePrefs.GetVerbose() && dwError != WSAECONNRESET) { CString strClientInfo; if (iSockAddrLen > 0 && sockAddr.sin_addr.S_un.S_addr != 0 && sockAddr.sin_addr.S_un.S_addr != INADDR_NONE) strClientInfo.Format(_T(" from %s:%u"), ipstr(sockAddr.sin_addr), ntohs(sockAddr.sin_port)); DebugLogError(_T("Error: Client UDP socket, failed to receive data%s: %s"), strClientInfo, GetErrorMessage(dwError, 1)); } } }