bool AccessControl::isBannedAddress(const boost::asio::ip::address& source) { if (!_enabled) return false; bool banned = false; _packetCounterMutex.lock(); if (_banLifeTime > 0) { boost::posix_time::ptime now(boost::posix_time::microsec_clock::local_time()); std::vector<boost::asio::ip::address> parole; for (std::map<boost::asio::ip::address, boost::posix_time::ptime>::iterator iter = _banned.begin(); iter != _banned.end(); iter++) { boost::posix_time::time_duration timeDiff = now - iter->second; if (timeDiff.total_milliseconds() > _banLifeTime * 1000) parole.push_back(iter->first); } for (std::vector<boost::asio::ip::address>::iterator iter = parole.begin(); iter != parole.end(); iter++) { if (_autoNullRoute) { delNullRoute(*iter); } _banned.erase(*iter); } } if (isWhiteListed(source)) { banned = false; } else { if (_denyAllIncoming) { banned = true; } else { banned = _banned.find(source) != _banned.end(); } if (!banned) { banned = isBlackListed(source); } } _packetCounterMutex.unlock(); if (banned && _autoNullRoute) { addNullRoute(source); } return banned; }
SnippetRuleBase::Rules SnippetRuleBase:: lookup(Uri const& uri, StringRange const siteKey/*= {}*/) const { Rules result; if (isWhiteListed(uri, siteKey)) return result; if (!isDomainSpecificOnly(uri, siteKey)) { result = m_genericRules; } std::copy_if( m_specificRules.begin(), m_specificRules.end(), std::back_inserter(result), [&](auto* rule) { return rule->match(uri); } ); return result; }
void AccessControl::logPacket(const boost::asio::ip::address& source, std::size_t bytesRead, ViolationReport* pReport) { /**************************************************************************** * The packet rate ratio allows the transport to detect a potential DoS * * attack. It works by detecting the packet read rate per second as * * designated by the upper limit. If the value of packet rate is 50/100, * * the maximum packet rate before the SBC raises the alert level if a * * potential denial of service attack is 100 packets per second. * * When this happens, the transport layer checks if there is a particular * * IP that is sending more than its allowable rate of 50 packets per second.* * If the sender is violating the threshold, it will be banned for 1 hour * * which is the third parameter of 3600 seconds. * ****************************************************************************/ if (!_enabled) return; _packetCounterMutex.lock(); std::map<boost::asio::ip::address, unsigned int>::iterator iter = _packetCounter.find(source); if (iter != _packetCounter.end()) _packetCounter[source] = ++iter->second; else _packetCounter[source] = 1; if (++_currentIterationCount >= _packetsPerSecondThreshold) { boost::posix_time::ptime now(boost::posix_time::microsec_clock::local_time()); int currentCount = _currentIterationCount; _currentIterationCount = 0; boost::posix_time::time_duration timeDiff = now - _lastTime; if (timeDiff.total_milliseconds() <= 1000) { // // We got a ratelimit violation // OSS_LOG_WARNING("ALERT: Threshold Violation Detected. Rate " << currentCount << " >= " << _packetsPerSecondThreshold); if (pReport) pReport->thresholdViolated = true; std::size_t watermark = 0; boost::asio::ip::address suspect; for (std::map<boost::asio::ip::address, unsigned int>::iterator iter = _packetCounter.begin(); iter != _packetCounter.end(); iter++) { if (iter->second > watermark) { watermark = iter->second; suspect = iter->first; if (watermark >= _thresholdViolationRate && _autoBanThresholdViolators ) { if (!isWhiteListed(suspect)) { OSS_LOG_WARNING("ALERT: Threshold Violator Address = " << suspect.to_string() << " Packets sent within the last second is " << watermark << ". Violator is now in jail for a maximum of " << _banLifeTime << " seconds."); banAddress(suspect); if (pReport) pReport->violators.push_back(suspect.to_string()); } else { OSS_LOG_WARNING("ALERT: Threshold Violator Address = " << suspect.to_string() << " Packets sent within the last second is " << watermark << ". Violator is TRUSTED and will be allowed to bombard."); } } else if (watermark >= _thresholdViolationRate && !_autoBanThresholdViolators ) { OSS_LOG_WARNING("ALERT: Threshold Violator Address = " << suspect.to_string() << " Packets sent within the last second is " << watermark << ". Automatic ban is disabled. Allowing this IP to bombard."); } } } } // // Reset // _packetCounter.clear(); _lastTime = now; } _packetCounterMutex.unlock(); }
void enforcePolicy(unsigned long threadID, ostream& os) { TAStack oStack; TACallInfo info; TAHashPair hashPair; bool firstEntry; bool oStackHasSourceClass = false; bool hashCalculated = false; string objectAddress; string str1="", str2=""; size_t hash1, hash2; oStack = threadStacks[threadID]; objectAddress = oStack.top().first; info = oStack.top().second; firstEntry = true; //check if the frame on top of stack represents message to/using a whitelisted class/method if (isWhiteListed(info)) return; for(map<unsigned long, TAStack>::iterator it = threadStacks.begin(); it!= threadStacks.end(); ++it) { //skip own stack if ((*it).first == threadID) continue; TAStack tStack = (*it).second; //Potential access violation if (tStack.top().first == objectAddress) { TACallInfo info2 = tStack.top().second; //if whitelisted, continue to next thread if (isWhiteListed(info2)) continue; /* compute the hash for oStack and check if it has source class exactly once per call to this function. rather than performing this step outside the for loop (to execute it exactly once), we perform this step here because for about 75-80% input we will satisfy both "if" conditions above. this means that we would unnecessarily comput hash1 and make a call to hasSourceClass(oStack) if the step is performed outside the loop (or earlier than here). Note: Compiler optimizations in place too. -OFast results in a difficult to debug code since the code doesn't stop at breakpoints properly, and step-in/step-over results in a difficult to follow execution order -> different from the order in which the program is written. */ if (!hashCalculated) { //compute hash for this stack hash1 = getHashForStack(oStack); //check if this stack has any frame where the class name is one of the classes defined in the source (not a OS class) oStackHasSourceClass = hasSourceClass(oStack); hashCalculated = true; } //check if the stack(trace) contains a frame where the class name is one of the classes defined in the source (not a OS class) if (!oStackHasSourceClass && !hasSourceClass(tStack)) continue; //Check for duplication now: //first compute hash for the stack hash2 = getHashForStack(tStack); //then find if the hash pair exists hashPair = make_pair(hash1, hash2); if (hashPairs.find(hashPair) == hashPairs.end()) { //this is a new pair hashPairs.insert(hashPair); //Now create a new row for this frame in the output file. //If this is the first row for a violation on this object address if (firstEntry) { os<<"<tr>"<<"<td width='70'>#"<<objectAddress<<"</td><td width='70'>"<<info.tid<<"*"<<"</td><td width='750'>$"<<info.className<<":"<<info.methodName<<" ("<<info.stackDepth<<")"<<"</td><td>"; printStackTrace(oStack, os, info.stackDepth); os<<"</td></tr>"; firstEntry = false; } //create row for the other frame os<<"<tr>"<<"<td width='70'>"<<" "<<"</td><td width='70'>"<<info2.tid<<"</td><td width='750'>$"<<info2.className<<":"<<info2.methodName<<" ("<<info2.stackDepth<<")"<<"</td><td>"; printStackTrace(tStack, os, info2.stackDepth); os<<"</td></tr>"; //add these class to the set of violating classes violatingClasses.insert(info.className); violatingClasses.insert(info2.className); } } } }