void CSocks4StateMachine::process_send_command_request(bool entry) { if (entry) { // Prepare the request command buffer m_buffer[0] = SOCKS4_VERSION; switch (m_proxyCommand) { case PROXY_CMD_CONNECT: m_buffer[1] = SOCKS4_CMD_CONNECT; break; case PROXY_CMD_BIND: m_buffer[1] = SOCKS4_CMD_BIND; break; case PROXY_CMD_UDP_ASSOCIATE: m_ok = false; return; break; } RawPokeUInt16(m_buffer+2, ENDIAN_HTONS(m_peerAddress->Service())); // Special processing for SOCKS4a switch (m_proxyData.m_proxyType) { case PROXY_SOCKS4a: PokeUInt32(m_buffer+4, StringIPtoUint32(wxT("0.0.0.1"))); break; case PROXY_SOCKS4: default: PokeUInt32(m_buffer+4, StringIPtoUint32(m_peerAddress->IPAddress())); break; } // Common processing for SOCKS4/SOCKS4a unsigned int offsetUser = 8; unsigned char lenUser = m_proxyData.m_userName.Len(); memcpy(m_buffer + offsetUser, unicode2char(m_proxyData.m_userName), lenUser); m_buffer[offsetUser + lenUser] = 0; // Special processing for SOCKS4a switch (m_proxyData.m_proxyType) { case PROXY_SOCKS4a: { unsigned int offsetDomain = offsetUser + lenUser + 1; unsigned char lenDomain = m_peerAddress->Hostname().Len(); memcpy(m_buffer + offsetDomain, unicode2char(m_peerAddress->Hostname()), lenDomain); m_buffer[offsetDomain + lenDomain] = 0; m_packetLenght = 1 + 1 + 2 + 4 + lenUser + 1 + lenDomain + 1; break; } case PROXY_SOCKS4: default: m_packetLenght = 1 + 1 + 2 + 4 + lenUser + 1; break; } // Send the command packet ProxyWrite(*m_proxyClientSocket, m_buffer, m_packetLenght); } }
void CDownloadQueue::AddToResolve(const CMD4Hash& fileid, const wxString& pszHostname, uint16 port, const wxString& hash, uint8 cryptoptions) { // double checking if ( !GetFileByID(fileid) ) { return; } wxMutexLocker lock( m_mutex ); Hostname_Entry entry = { fileid, pszHostname, port, hash, cryptoptions }; m_toresolve.push_front(entry); // Check if there are other DNS lookups on queue if (m_toresolve.size() == 1) { // Check if it is a simple dot address uint32 ip = StringIPtoUint32(pszHostname); if (ip) { OnHostnameResolved(ip); } else { CAsyncDNS* dns = new CAsyncDNS(pszHostname, DNS_SOURCE, theApp); if ((dns->Create() != wxTHREAD_NO_ERROR) || (dns->Run() != wxTHREAD_NO_ERROR)) { dns->Delete(); m_toresolve.pop_front(); } } } }
void CSocks5StateMachine::process_send_command_request(bool entry) { if (entry) { // Prepare the request command buffer m_buffer[0] = SOCKS5_VERSION; switch (m_proxyCommand) { case PROXY_CMD_CONNECT: m_buffer[1] = SOCKS5_CMD_CONNECT; break; case PROXY_CMD_BIND: m_buffer[1] = SOCKS5_CMD_BIND; break; case PROXY_CMD_UDP_ASSOCIATE: m_buffer[1] = SOCKS5_CMD_UDP_ASSOCIATE; break; } m_buffer[2] = SOCKS5_RSV; m_buffer[3] = SOCKS5_ATYP_IPV4_ADDRESS; PokeUInt32( m_buffer+4, StringIPtoUint32(m_peerAddress->IPAddress()) ); RawPokeUInt16( m_buffer+8, ENDIAN_HTONS( m_peerAddress->Service() ) ); // Send the command packet m_packetLenght = 10; ProxyWrite(*m_proxyClientSocket, m_buffer, m_packetLenght); } }
wxDatagramSocket &CDatagramSocketProxy::SendTo( wxIPaddress &addr, const void* buf, wxUint32 nBytes ) { wxMutexLocker lock(m_socketLocker); m_lastUDPOperation = UDP_OPERATION_SEND_TO; m_lastUDPOverhead = PROXY_UDP_OVERHEAD_IPV4; if (m_proxyTCPSocket.GetUseProxy()) { if (m_udpSocketOk) { m_proxyTCPSocket.GetBuffer()[0] = SOCKS5_RSV; // Reserved m_proxyTCPSocket.GetBuffer()[1] = SOCKS5_RSV; // Reserved m_proxyTCPSocket.GetBuffer()[2] = 0; // FRAG m_proxyTCPSocket.GetBuffer()[3] = SOCKS5_ATYP_IPV4_ADDRESS; PokeUInt32( m_proxyTCPSocket.GetBuffer()+4, StringIPtoUint32(addr.IPAddress())); RawPokeUInt16( m_proxyTCPSocket.GetBuffer()+8, ENDIAN_HTONS( addr.Service() ) ); memcpy(m_proxyTCPSocket.GetBuffer() + PROXY_UDP_OVERHEAD_IPV4, buf, nBytes); nBytes += PROXY_UDP_OVERHEAD_IPV4; wxDatagramSocket::SendTo( m_proxyTCPSocket.GetProxyBoundAddress(), m_proxyTCPSocket.GetBuffer(), nBytes); // Uncomment here to see the buffer contents on console // DumpMem(m_proxyTCPSocket.GetBuffer(), nBytes, wxT("SendTo"), 3); } } else { wxDatagramSocket::SendTo(addr, buf, nBytes); } return *this; }
void CMuleUDPSocket::OnReceive(int errorCode) { AddDebugLogLineN(logMuleUDP, CFormat(wxT("Got UDP callback for read: Error %i Socket state %i")) % errorCode % Ok()); char buffer[UDP_BUFFER_SIZE]; amuleIPV4Address addr; unsigned length = 0; bool error = false; int lastError = 0; { wxMutexLocker lock(m_mutex); if (errorCode || (m_socket == NULL) || !m_socket->IsOk()) { DestroySocket(); CreateSocket(); return; } length = m_socket->RecvFrom(addr, buffer, UDP_BUFFER_SIZE); lastError = m_socket->LastError(); error = lastError != 0; } const uint32 ip = StringIPtoUint32(addr.IPAddress()); const uint16 port = addr.Service(); if (error) { OnReceiveError(lastError, ip, port); } else if (length < 2) { // 2 bytes (protocol and opcode) is the smallets possible packet. AddDebugLogLineN(logMuleUDP, m_name + wxT(": Invalid Packet received")); } else if (!ip) { // wxFAIL; AddLogLineNS(wxT("Unknown ip receiving a UDP packet! Ignoring: '") + addr.IPAddress() + wxT("'")); } else if (!port) { // wxFAIL; AddLogLineNS(wxT("Unknown port receiving a UDP packet! Ignoring")); } else if (theApp->clientlist->IsBannedClient(ip)) { AddDebugLogLineN(logMuleUDP, m_name + wxT(": Dropped packet from banned IP ") + addr.IPAddress()); } else { AddDebugLogLineN(logMuleUDP, (m_name + wxT(": Packet received (")) << addr.IPAddress() << wxT(":") << port << wxT("): ") << length << wxT("b")); OnPacketReceived(ip, port, (byte*)buffer, length); } }
void CDownloadQueue::OnHostnameResolved(uint32 ip) { wxMutexLocker lock( m_mutex ); wxASSERT( m_toresolve.size() ); Hostname_Entry resolved = m_toresolve.front(); m_toresolve.pop_front(); if ( ip ) { CPartFile* file = GetFileByID( resolved.fileid ); if ( file ) { CMemFile sources(1+4+2); sources.WriteUInt8(1); // No. Sources sources.WriteUInt32(ip); sources.WriteUInt16(resolved.port); sources.WriteUInt8(resolved.cryptoptions); if (resolved.cryptoptions & 0x80) { wxASSERT(!resolved.hash.IsEmpty()); CMD4Hash sourcehash; sourcehash.Decode(resolved.hash); sources.WriteHash(sourcehash); } sources.Seek(0,wxFromStart); file->AddSources(sources, 0, 0, SF_LINK, true); } } while (m_toresolve.size()) { Hostname_Entry entry = m_toresolve.front(); // Check if it is a simple dot address uint32 tmpIP = StringIPtoUint32(entry.strHostname); if (tmpIP) { OnHostnameResolved(tmpIP); } else { CAsyncDNS* dns = new CAsyncDNS(entry.strHostname, DNS_SOURCE, theApp); if ((dns->Create() != wxTHREAD_NO_ERROR) || (dns->Run() != wxTHREAD_NO_ERROR)) { dns->Delete(); m_toresolve.pop_front(); } else { break; } } } }
void CKadDlg::OnBnClickedBootstrapClient(wxCommandEvent& WXUNUSED(evt)) { if (FindWindowById(ID_NODECONNECT)->IsEnabled()) { // Ip is reversed since StringIPtoUint32 returns anti-host and kad expects host order uint32 ip = StringIPtoUint32( dynamic_cast<wxTextCtrl*>(FindWindowById(ID_NODE_IP4))->GetValue() + wxT(".") + dynamic_cast<wxTextCtrl*>(FindWindowById(ID_NODE_IP3))->GetValue() + wxT(".") + dynamic_cast<wxTextCtrl*>(FindWindowById(ID_NODE_IP2))->GetValue() + wxT(".") + dynamic_cast<wxTextCtrl*>(FindWindowById(ID_NODE_IP1))->GetValue() ); if (ip == 0) { wxMessageBox(_("Invalid ip to bootstrap"), _("WARNING"), wxOK | wxICON_EXCLAMATION, this); } else { unsigned long port; if (dynamic_cast<wxTextCtrl*>(FindWindowById(ID_NODE_PORT))->GetValue().ToULong(&port)) { theApp->BootstrapKad(ip, port); } else { wxMessageBox(_("Invalid port to bootstrap"), _("WARNING"), wxOK | wxICON_EXCLAMATION, this); } } } else { wxMessageBox(_("Please fill all fields required"), _("Message"), wxOK | wxICON_INFORMATION, this); } }
int CEncryptedStreamSocket::Negotiate(const uint8* pBuffer, uint32 nLen) { uint32_t nRead = 0; wxASSERT( m_nReceiveBytesWanted > 0 ); //DumpMem(pBuffer, nLen, wxT("Negotiate buffer: ")); try { while (m_NegotiatingState != ONS_COMPLETE && m_nReceiveBytesWanted > 0) { if (m_nReceiveBytesWanted > 512) { wxFAIL; return 0; } const uint32_t nToRead = std::min(nLen - nRead, m_nReceiveBytesWanted); //printf("Reading %i bytes, add from %i position on %i position\n",nToRead, nRead, (int)m_pfiReceiveBuffer.GetPosition()); //DumpMem(pBuffer + nRead, nToRead, wxT("Recv Buffer: ")); m_pfiReceiveBuffer.Write(pBuffer + nRead, nToRead); nRead += nToRead; m_nReceiveBytesWanted -= nToRead; if (m_nReceiveBytesWanted > 0) { return nRead; } if (m_NegotiatingState != ONS_BASIC_CLIENTA_RANDOMPART && m_NegotiatingState != ONS_BASIC_SERVER_DHANSWER) { // We have the keys, decrypt //printf("We have the keys, so decrypt away on %s\n", (const char*) unicode2char(DbgGetIPString())); m_pfiReceiveBuffer.Encrypt(); } m_pfiReceiveBuffer.Seek(0); switch (m_NegotiatingState) { case ONS_NONE: // would be a bug wxFAIL; return 0; case ONS_BASIC_CLIENTA_RANDOMPART: { //printf("We are on ONS_BASIC_CLIENTA_RANDOMPART, create the keys on %s\n", (const char*) unicode2char(DbgGetIPString())); // This creates the send/receive keys. uint8_t achKeyData[21]; md4cpy(achKeyData, thePrefs::GetUserHash().GetHash()); m_pfiReceiveBuffer.Read(achKeyData + 17, 4); achKeyData[16] = MAGICVALUE_REQUESTER; //DumpMem(achKeyData, sizeof(achKeyData), wxT("ach:")); MD5Sum md5(achKeyData, sizeof(achKeyData)); //DumpMem(md5.GetRawHash(), 16, wxT("Md5:")); m_pfiReceiveBuffer.SetKey(md5); achKeyData[16] = MAGICVALUE_SERVER; md5.Calculate(achKeyData, sizeof(achKeyData)); m_pfiSendBuffer.SetKey(md5); m_NegotiatingState = ONS_BASIC_CLIENTA_MAGICVALUE; m_nReceiveBytesWanted = 4; break; } case ONS_BASIC_CLIENTA_MAGICVALUE: { // Check the magic value to confirm encryption works. //printf("Creating magic value on negotiate on %s\n", (const char*) unicode2char(DbgGetIPString())); 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 //printf("Magic value works on %s\n", (const char*) unicode2char(DbgGetIPString())); m_NegotiatingState = ONS_BASIC_CLIENTA_METHODTAGSPADLEN; m_nReceiveBytesWanted = 3; } else { //printf("Wrong magic value: 0x%x != 0x%x on %s\n",dwValue, MAGICVALUE_SYNC, (const char*)unicode2char(DbgGetIPString())); //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: { // Get encryption method and padding. // Might fall back to padding process, but the bytes will be ignored. //printf("Getting encryption method on negotiation\n"); m_dbgbyEncryptionSupported = m_pfiReceiveBuffer.ReadUInt8(); m_dbgbyEncryptionRequested = m_pfiReceiveBuffer.ReadUInt8(); if (m_dbgbyEncryptionRequested != ENM_OBFUSCATION) { //printf("Unsupported encryption method!\n"); // 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 > 0) { // No padding break; } } case ONS_BASIC_CLIENTA_PADDING: { //printf("Negotiating on padding, completing\n"); // ignore the random bytes, send the response, set status complete CMemFile 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); amuleIPV4Address address; GetPeer(address); const uint8_t byPaddingLen = theApp->serverconnect->AwaitingTestFromIP(StringIPtoUint32(address.IPAddress())) ? 16 : (thePrefs::GetCryptTCPPaddingLength() + 1); uint8_t byPadding = (uint8_t)(GetRandomUint8() % byPaddingLen); fileResponse.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) { fileResponse.WriteUInt8((uint8_t)rand()); } SendNegotiatingData(fileResponse.GetRawBuffer(), (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: { //printf("Negotiating on magic value\n"); 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: { //printf("Negotiating on client B pad length\n"); 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: //printf("Negotiating on client B padding, handshake complete\n"); // 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: { wxASSERT( !m_cryptDHA.IsZero() ); uint8_t 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 = a_exp_b_mod_c(cryptDHAnswer, m_cryptDHA, cryptDHPrime); m_cryptDHA = 0; //DEBUG_ONLY( ZeroMemory(aBuffer, sizeof(aBuffer)) ); wxASSERT( cryptResult.MinEncodedSize() <= PRIMESIZE_BYTES ); // create the keys cryptResult.Encode(aBuffer, PRIMESIZE_BYTES); aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_REQUESTER; MD5Sum md5(aBuffer, sizeof(aBuffer)); m_pfiSendBuffer.SetKey(md5); aBuffer[PRIMESIZE_BYTES] = MAGICVALUE_SERVER; md5.Calculate(aBuffer, sizeof(aBuffer)); m_pfiReceiveBuffer.SetKey(md5); 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 > 0) { break; } case ONS_BASIC_SERVER_PADDING: { // ignore the random bytes (they are decrypted already), send the response, set status complete CMemFile 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); // Server callback connection only allows 16 bytes of padding. uint8_t byPadding = (uint8_t)(GetRandomUint8() % 16); fileResponse.WriteUInt8(byPadding); for (int i = 0; i < byPadding; i++) { fileResponse.WriteUInt8((uint8_t)rand()); } m_NegotiatingState = ONS_BASIC_SERVER_DELAYEDSENDING; SendNegotiatingData(fileResponse.GetRawBuffer(), (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: wxFAIL; } m_pfiReceiveBuffer.ResetData(); } return nRead; } catch(...) { // can only be caused by a bug in negationhandling, not by the datastream //error->Delete(); //printf("Bug on negotiation?\n"); wxFAIL; OnError(ERR_ENCRYPTION); m_pfiReceiveBuffer.ResetData(); return (-1); } }
int CEncryptedStreamSocket::Read(void* lpBuf, uint32_t nBufLen) { CSocketClientProxy::Read(lpBuf, nBufLen); m_nObfusicationBytesReceived = CSocketClientProxy::LastCount(); m_bFullReceive = m_nObfusicationBytesReceived == (uint32)nBufLen; //printf("Read %i bytes on %s, socket %p\n", m_nObfusicationBytesReceived, (const char*) unicode2char(DbgGetIPString()), this); if (m_nObfusicationBytesReceived == (uint32_t)SOCKET_ERROR || m_nObfusicationBytesReceived <= 0) { return m_nObfusicationBytesReceived; } switch (m_StreamCryptState) { case ECS_NONE: // disabled, just pass it through return m_nObfusicationBytesReceived; case ECS_PENDING: case ECS_PENDING_SERVER: //printf("Received %i bytes before sending?\n", m_nObfusicationBytesReceived); wxFAIL; //DebugLogError(_T("CEncryptedStreamSocket Received data before sending on outgoing connection")); m_StreamCryptState = ECS_NONE; return m_nObfusicationBytesReceived; case ECS_UNKNOWN: { //printf("Receiving encrypted data on ECS_UNKNOWN\n"); uint32_t nRead = 1; bool bNormalHeader = false; switch (((uint8_t*)lpBuf)[0]) { case OP_EDONKEYPROT: case OP_PACKEDPROT: case OP_EMULEPROT: bNormalHeader = true; break; } if (!bNormalHeader) { //printf("Not a normal header, negotiating encryption\n"); StartNegotiation(false); const uint32 nNegRes = Negotiate((uint8_t*)lpBuf + nRead, m_nObfusicationBytesReceived - nRead); if (nNegRes == (uint32_t)(-1)) { return 0; } nRead += nNegRes; if (nRead != (uint32_t)m_nObfusicationBytesReceived) { // 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 didn't receive our response yet) //DebugLogError(_T("CEncryptedStreamSocket: Client %s sent more data then expected while negotiating, disconnecting (1)"), DbgGetIPString()); //printf("On error: encryption\n"); OnError(ERR_ENCRYPTION); } return 0; } else { // doesn't seem to be encrypted //printf("Encrypted data doesn't seem to be encrypted\n"); 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 workaround // until 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 amuleIPV4Address address; GetPeer(address); uint32_t ip = StringIPtoUint32(address.IPAddress()); if (thePrefs::IsClientCryptLayerRequiredStrict() || (!theApp->serverconnect->AwaitingTestFromIP(ip) && !theApp->clientlist->IsKadFirewallCheckIP(ip)) ) { OnError(ERR_ENCRYPTION_NOTALLOWED); return 0; } else { //AddDebugLogLine(DLP_DEFAULT, false, _T("Incoming unencrypted firewallcheck connection permitted despite RequireEncryption setting - %s"), DbgGetIPString() ); } } return m_nObfusicationBytesReceived; // buffer was unchanged, we can just pass it through } } case ECS_ENCRYPTING: //printf("Encryption enabled on data receiving, decrypting and passing along\n"); // basic obfusication enabled and set, so decrypt and pass along m_pfiReceiveBuffer.RC4Crypt((uint8_t*)lpBuf, (uint8_t*)lpBuf, m_nObfusicationBytesReceived); //DumpMem(lpBuf, m_nObfusicationBytesReceived, wxT("Directly decrypted data:")); return m_nObfusicationBytesReceived; case ECS_NEGOTIATING:{ //printf("Negotiating on data receive\n"); const uint32_t nRead = Negotiate((uint8_t*)lpBuf, m_nObfusicationBytesReceived); if (nRead == (uint32_t)(-1)) { //printf("-> Encryption read error on negotiation\n"); return 0; } else if (nRead != (uint32_t)m_nObfusicationBytesReceived && m_StreamCryptState != ECS_ENCRYPTING) { //printf("-> Too much data, bailing out of negotiation step\n"); // 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_nObfusicationBytesReceived && m_StreamCryptState == ECS_ENCRYPTING) { //printf("-> Handshake negotiation finished\n"); // 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, (uint8_t*)lpBuf + nRead, m_nObfusicationBytesReceived - nRead); return m_nObfusicationBytesReceived - nRead; } else { //printf("-> Negotiation went probably ok\n"); return 0; } } default: wxFAIL; return m_nObfusicationBytesReceived; } }