bool CClientList::AttachToAlreadyKnown(CUpDownClient** client, CClientReqSocket* sender){ POSITION pos1, pos2; CUpDownClient* tocheck = (*client); CUpDownClient* found_client = NULL; CUpDownClient* found_client2 = NULL; for (pos1 = list.GetHeadPosition(); (pos2 = pos1) != NULL; ){ list.GetNext(pos1); CUpDownClient* cur_client = list.GetAt(pos2); if (tocheck->Compare(cur_client,false)){ //matching userhash found_client2 = cur_client; } if (tocheck->Compare(cur_client,true)){ //matching IP found_client = cur_client; break; } } if (found_client == NULL) found_client = found_client2; if (found_client != NULL){ if (tocheck == found_client){ //we found the same client instance (client may have sent more than one OP_HELLO). do not delete that client! return true; } if (sender){ if (found_client->socket){ if (found_client->socket->IsConnected() && (found_client->GetIP() != tocheck->GetIP() || found_client->GetUserPort() != tocheck->GetUserPort() ) ) { // if found_client is connected and has the IS_IDENTIFIED, it's safe to say that the other one is a bad guy if (found_client->Credits() && found_client->Credits()->GetCurrentIdentState(found_client->GetIP()) == IS_IDENTIFIED){ if (thePrefs.GetLogBannedClients()) AddDebugLogLine(false, _T("Clients: %s (%s), Banreason: Userhash invalid"), tocheck->GetUserName(), ipstr(tocheck->GetConnectIP())); tocheck->Ban(); return false; } //IDS_CLIENTCOL Warning: Found matching client, to a currently connected client: %s (%s) and %s (%s) if (thePrefs.GetLogBannedClients()) AddDebugLogLine(true,GetResString(IDS_CLIENTCOL), tocheck->GetUserName(), ipstr(tocheck->GetConnectIP()), found_client->GetUserName(), ipstr(found_client->GetConnectIP())); return false; } found_client->socket->client = 0; found_client->socket->Safe_Delete(); } found_client->socket = sender; tocheck->socket = 0; } *client = 0; delete tocheck; *client = found_client; return true; } return false; }
// Check all clients that uploaded corrupted data, // and ban them if they didn't upload enough good data too. void CCorruptionBlackBox::EvaluateData() { CCBBClientMap::iterator it = m_badClients.begin(); for (; it != m_badClients.end(); ++it) { uint32 ip = it->first; uint64 bad = it->second.m_downloaded; if (!bad) { wxFAIL; // this should not happen continue; } uint64 good = 0; CCBBClientMap::iterator it2 = m_goodClients.find(ip); if (it2 != m_goodClients.end()) { good = it2->second.m_downloaded; } int nCorruptPercentage = bad * 100 / (bad + good); if (nCorruptPercentage > CBB_BANTHRESHOLD) { CUpDownClient* pEvilClient = theApp->clientlist->FindClientByIP(ip); wxString clientName; if (pEvilClient != NULL) { clientName = pEvilClient->GetClientShortInfo(); AddDebugLogLineN(logPartFile, CFormat(wxT("CorruptionBlackBox(%s): Banning: Found client which sent %d of %d corrupted data, %s")) % m_partNumber % bad % (good + bad) % pEvilClient->GetClientFullInfo()); theApp->clientlist->AddTrackClient(pEvilClient); pEvilClient->Ban(); // Identified as sender of corrupt data // Stop download right away pEvilClient->SetDownloadState(DS_BANNED); if (pEvilClient->Disconnected(wxT("Upload of corrupted data"))) { pEvilClient->Safe_Delete(); } } else { clientName = Uint32toStringIP(ip); theApp->clientlist->AddBannedClient(ip); } AddLogLineN(CFormat(_("Banned client %s for sending %s corrupt data of %s total for the file '%s'")) % clientName % CastItoXBytes(bad) % CastItoXBytes(good + bad) % m_fileName); } else { CUpDownClient* pSuspectClient = theApp->clientlist->FindClientByIP(ip); if (pSuspectClient != NULL) { AddDebugLogLineN(logPartFile, CFormat(wxT("CorruptionBlackBox(%s): Reporting: Found client which probably sent %d of %d corrupted data, but it is within the acceptable limit, %s")) % m_partNumber % bad % (good + bad) % pSuspectClient->GetClientFullInfo()); theApp->clientlist->AddTrackClient(pSuspectClient); } else { AddDebugLogLineN(logPartFile, CFormat(wxT("CorruptionBlackBox(%s): Reporting: Found client which probably sent %d of %d corrupted data, but it is within the acceptable limit, %s")) % m_partNumber % bad % (good + bad) % Uint32toStringIP(ip)); } } } }
bool CClientList::AttachToAlreadyKnown(CUpDownClient** client, CClientTCPSocket* sender) { CUpDownClient* tocheck = (*client); CUpDownClient* found_client = FindMatchingClient( tocheck ); if ( tocheck == found_client ) { // We found the same client instance (client may have sent more than one OP_HELLO). do not delete that client! return true; } if (found_client != NULL){ if (sender) { if (found_client->GetSocket()) { if (found_client->IsConnected() && (found_client->GetIP() != tocheck->GetIP() || found_client->GetUserPort() != tocheck->GetUserPort() ) ) { // if found_client is connected and has the IS_IDENTIFIED, it's safe to say that the other one is a bad guy if (found_client->IsIdentified()){ AddDebugLogLineN(logClient, wxT("Client: ") + tocheck->GetUserName() + wxT("(") + tocheck->GetFullIP() + wxT("), Banreason: Userhash invalid")); tocheck->Ban(); return false; } AddDebugLogLineN(logClient, wxT("WARNING! Found matching client, to a currently connected client: ") + tocheck->GetUserName() + wxT("(") + tocheck->GetFullIP() + wxT(") and ") + found_client->GetUserName() + wxT("(") + found_client->GetFullIP() + wxT(")")); return false; } found_client->GetSocket()->Safe_Delete(); } found_client->SetSocket( sender ); tocheck->SetSocket( NULL ); } *client = 0; tocheck->Safe_Delete(); *client = found_client; return true; } return false; }
void CCorruptionBlackBox::CorruptedData(uint32 nStartPos, uint32 nEndPos){ if (nEndPos - nStartPos >= EMBLOCKSIZE){ ASSERT( false ); return; } // convert pos to relative block pos uint16 nPart = nStartPos / PARTSIZE; uint32 nRelStartPos = nStartPos - nPart*PARTSIZE; uint32 nRelEndPos = nEndPos - nPart*PARTSIZE; if (nRelEndPos >= PARTSIZE){ ASSERT( false ); return; } if (nPart >= m_aaRecords.GetCount()){ //ASSERT( false ); m_aaRecords.SetSize(nPart+1); } uint32 nDbgVerifiedBytes = 0; CArray<uint32, uint32> aGuiltyClients; for (int i= 0; i < m_aaRecords[nPart].GetCount(); i++){ if (m_aaRecords[nPart][i].m_BBRStatus == BBR_NONE){ if (m_aaRecords[nPart][i].m_nStartPos >= nRelStartPos && m_aaRecords[nPart][i].m_nEndPos <= nRelEndPos){ nDbgVerifiedBytes += (m_aaRecords[nPart][i].m_nEndPos-m_aaRecords[nPart][i].m_nStartPos)+1; m_aaRecords[nPart][i].m_BBRStatus = BBR_CORRUPTED; aGuiltyClients.Add(m_aaRecords[nPart][i].m_dwIP); } else if (m_aaRecords[nPart][i].m_nStartPos < nRelStartPos && m_aaRecords[nPart][i].m_nEndPos > nRelEndPos){ // need to split it 2* uint32 nTmpEndPos1 = m_aaRecords[nPart][i].m_nEndPos; uint32 nTmpStartPos1 = nRelEndPos + 1; uint32 nTmpStartPos2 = m_aaRecords[nPart][i].m_nStartPos; uint32 nTmpEndPos2 = nRelStartPos - 1; m_aaRecords[nPart][i].m_nEndPos = nRelEndPos; m_aaRecords[nPart][i].m_nStartPos = nRelStartPos; m_aaRecords[nPart].Add(CCBBRecord(nTmpStartPos1, nTmpEndPos1, m_aaRecords[nPart][i].m_dwIP, m_aaRecords[nPart][i].m_BBRStatus)); m_aaRecords[nPart].Add(CCBBRecord(nTmpStartPos2, nTmpEndPos2, m_aaRecords[nPart][i].m_dwIP, m_aaRecords[nPart][i].m_BBRStatus)); nDbgVerifiedBytes += (m_aaRecords[nPart][i].m_nEndPos-m_aaRecords[nPart][i].m_nStartPos)+1; m_aaRecords[nPart][i].m_BBRStatus = BBR_CORRUPTED; aGuiltyClients.Add(m_aaRecords[nPart][i].m_dwIP); } else if (m_aaRecords[nPart][i].m_nStartPos >= nRelStartPos && m_aaRecords[nPart][i].m_nStartPos <= nRelEndPos){ // need to split it uint32 nTmpEndPos = m_aaRecords[nPart][i].m_nEndPos; uint32 nTmpStartPos = nRelEndPos + 1; m_aaRecords[nPart][i].m_nEndPos = nRelEndPos; m_aaRecords[nPart].Add(CCBBRecord(nTmpStartPos, nTmpEndPos, m_aaRecords[nPart][i].m_dwIP, m_aaRecords[nPart][i].m_BBRStatus)); nDbgVerifiedBytes += (m_aaRecords[nPart][i].m_nEndPos-m_aaRecords[nPart][i].m_nStartPos)+1; m_aaRecords[nPart][i].m_BBRStatus = BBR_CORRUPTED; aGuiltyClients.Add(m_aaRecords[nPart][i].m_dwIP); } else if (m_aaRecords[nPart][i].m_nEndPos >= nRelStartPos && m_aaRecords[nPart][i].m_nEndPos <= nRelEndPos){ // need to split it uint32 nTmpStartPos = m_aaRecords[nPart][i].m_nStartPos; uint32 nTmpEndPos = nRelStartPos - 1; m_aaRecords[nPart][i].m_nStartPos = nRelStartPos; m_aaRecords[nPart].Add(CCBBRecord(nTmpStartPos, nTmpEndPos, m_aaRecords[nPart][i].m_dwIP, m_aaRecords[nPart][i].m_BBRStatus)); nDbgVerifiedBytes += (m_aaRecords[nPart][i].m_nEndPos-m_aaRecords[nPart][i].m_nStartPos)+1; m_aaRecords[nPart][i].m_BBRStatus = BBR_CORRUPTED; aGuiltyClients.Add(m_aaRecords[nPart][i].m_dwIP); } } } // check if any IPs are already banned, so we can skip the test for those for(int k = 0; k < aGuiltyClients.GetCount();){ // remove doubles for(int y = k+1; y < aGuiltyClients.GetCount();){ if (aGuiltyClients[k] == aGuiltyClients[y]) aGuiltyClients.RemoveAt(y); else y++; } if (theApp.clientlist->IsBannedClient(aGuiltyClients[k])){ AddDebugLogLine(DLP_DEFAULT, false, _T("CorruptionBlackBox: Suspicous IP (%s) is already banned, skipping recheck"), ipstr(aGuiltyClients[k])); aGuiltyClients.RemoveAt(k); } else k++; } AddDebugLogLine(DLP_HIGH, false, _T("Found and marked %u recorded bytes of %u as corrupted in the CorruptionBlackBox records, %u clients involved"), nDbgVerifiedBytes, (nEndPos-nStartPos)+1, aGuiltyClients.GetCount()); if (aGuiltyClients.GetCount() > 0){ // parse all recorded data for this file to produce a statistic for the involved clients // first init arrays for the statistic CArray<uint32, uint32> aDataCorrupt; CArray<uint32, uint32> aDataVerified; aDataCorrupt.SetSize(aGuiltyClients.GetCount()); aDataVerified.SetSize(aGuiltyClients.GetCount()); for (int j = 0; j < aGuiltyClients.GetCount(); j++) aDataCorrupt[j] = aDataVerified[j] = 0; // now the parsing for (int nPart = 0; nPart < m_aaRecords.GetCount(); nPart++){ for (int i = 0; i < m_aaRecords[nPart].GetCount(); i++){ for(int k = 0; k < aGuiltyClients.GetCount(); k++){ if (m_aaRecords[nPart][i].m_dwIP == aGuiltyClients[k]){ if (m_aaRecords[nPart][i].m_BBRStatus == BBR_CORRUPTED){ // corrupted data records are always counted as at least blocksize or bigger aDataCorrupt[k] += max((m_aaRecords[nPart][i].m_nEndPos-m_aaRecords[nPart][i].m_nStartPos)+1, EMBLOCKSIZE); } else if(m_aaRecords[nPart][i].m_BBRStatus == BBR_VERIFIED){ aDataVerified[k] += (m_aaRecords[nPart][i].m_nEndPos-m_aaRecords[nPart][i].m_nStartPos)+1; } } } } } for(int k = 0; k < aGuiltyClients.GetCount(); k++){ // calculate the percentage of corrupted data for each client and ban // him if the limit is reached int nCorruptPercentage; if ((aDataVerified[k] + aDataCorrupt[k]) > 0) nCorruptPercentage = (int)(((uint64)aDataCorrupt[k]*100)/(aDataVerified[k] + aDataCorrupt[k])); else { AddDebugLogLine(DLP_HIGH, false, _T("CorruptionBlackBox: Programm Error: No records for guilty client found!")); ASSERT( false ); nCorruptPercentage = 0; } if ( nCorruptPercentage > CBB_BANTHRESHOLD){ CUpDownClient* pEvilClient = theApp.clientlist->FindClientByIP(aGuiltyClients[k]); if (pEvilClient != NULL){ AddDebugLogLine(DLP_HIGH, false, _T("CorruptionBlackBox: Banning: Found client which send %s of %s corrupted data, %s"), CastItoXBytes(aDataCorrupt[k]), CastItoXBytes((aDataVerified[k] + aDataCorrupt[k])), pEvilClient->DbgGetClientInfo()); theApp.clientlist->AddTrackClient(pEvilClient); pEvilClient->Ban(_T("Identified as sender of corrupt data")); } else{ AddDebugLogLine(DLP_HIGH, false, _T("CorruptionBlackBox: Banning: Found client which send %s of %s corrupted data, %s"), CastItoXBytes(aDataCorrupt[k]), CastItoXBytes((aDataVerified[k] + aDataCorrupt[k])), ipstr(aGuiltyClients[k])); theApp.clientlist->AddBannedClient(aGuiltyClients[k]); } } else{ CUpDownClient* pSuspectClient = theApp.clientlist->FindClientByIP(aGuiltyClients[k]); if (pSuspectClient != NULL){ AddDebugLogLine(DLP_DEFAULT, false, _T("CorruptionBlackBox: Reporting: Found client which probably send %s of %s corrupted data, but it is within the acceptable limit, %s"), CastItoXBytes(aDataCorrupt[k]), CastItoXBytes((aDataVerified[k] + aDataCorrupt[k])), pSuspectClient->DbgGetClientInfo()); theApp.clientlist->AddTrackClient(pSuspectClient); } else AddDebugLogLine(DLP_DEFAULT, false, _T("CorruptionBlackBox: Reporting: Found client which probably send %s of %s corrupted data, but it is within the acceptable limit, %s"), CastItoXBytes(aDataCorrupt[k]), CastItoXBytes((aDataVerified[k] + aDataCorrupt[k])), ipstr(aGuiltyClients[k])); } } } }