// SNFMulti.cpp | // SNFMulti.cpp | ||||
// | // | ||||
// (C) Copyright 2006 - 2009 ARM Research Labs, LLC | |||||
// (C) Copyright 2006 - 2020 ARM Research Labs, LLC | |||||
// See www.armresearch.com for the copyright terms. | // See www.armresearch.com for the copyright terms. | ||||
// | // | ||||
// 20060121_M | // 20060121_M | ||||
//// Script Caller Methods | //// Script Caller Methods | ||||
const ThreadType ScriptCaller::Type("Script Caller"); // Script caller thread type mnemonic. | |||||
const cd::ThreadType ScriptCaller::Type("Script Caller"); // Script caller thread type mnemonic. | |||||
const ThreadState ScriptCaller::CallingSystem("In system()"); // Script caller "CallingSystem" state. | |||||
const ThreadState ScriptCaller::PendingGuardTime("Guard Time"); // Script caller "GuardTime" state. | |||||
const ThreadState ScriptCaller::StandingBy("Standby"); // Script caller "Standby" state. | |||||
const ThreadState ScriptCaller::Disabled("Disabled"); // State when unable to run. | |||||
const cd::ThreadState ScriptCaller::CallingSystem("In system()"); // Script caller "CallingSystem" state. | |||||
const cd::ThreadState ScriptCaller::PendingGuardTime("Guard Time"); // Script caller "GuardTime" state. | |||||
const cd::ThreadState ScriptCaller::StandingBy("Standby"); // Script caller "Standby" state. | |||||
const cd::ThreadState ScriptCaller::Disabled("Disabled"); // State when unable to run. | |||||
const int ScriptGuardDefault = 180000; // 3 Minute Default Guard Time. | const int ScriptGuardDefault = 180000; // 3 Minute Default Guard Time. | ||||
ScriptCaller::ScriptCaller(string S) : // Script caller constructor (with name). | |||||
ScriptCaller::ScriptCaller(std::string S) : // Script caller constructor (with name). | |||||
Thread(ScriptCaller::Type, S), // Set up the thread type and name. | Thread(ScriptCaller::Type, S), // Set up the thread type and name. | ||||
GuardTimer(ScriptGuardDefault), // Initialize the guard time. | GuardTimer(ScriptGuardDefault), // Initialize the guard time. | ||||
GoFlag(false), // Not ready to go yet. | GoFlag(false), // Not ready to go yet. | ||||
ScriptCaller::~ScriptCaller() { // Destructor. | ScriptCaller::~ScriptCaller() { // Destructor. | ||||
DieFlag = true; // Set the die flag. | DieFlag = true; // Set the die flag. | ||||
Sleeper WaitATic(1000); // One second sleeper. | |||||
cd::Sleeper WaitATic(1000); // One second sleeper. | |||||
for(int x = 10; x > 0; x--) { // We don't join, we might get stuck. | for(int x = 10; x > 0; x--) { // We don't join, we might get stuck. | ||||
if(false == isRunning()) break; // If we're still running then wait | if(false == isRunning()) break; // If we're still running then wait | ||||
WaitATic(); // up to 10 seconds, then just exit. | WaitATic(); // up to 10 seconds, then just exit. | ||||
} // If the thread is stuck it will | } // If the thread is stuck it will | ||||
} // just get closed. | } // just get closed. | ||||
string ScriptCaller::ScriptToRun() { // Safely grab the SystemCallText. | |||||
ScopeMutex Freeze(MyMutex); // Protect the string. | |||||
std::string ScriptCaller::ScriptToRun() { // Safely grab the SystemCallText. | |||||
cd::ScopeMutex Freeze(MyMutex); // Protect the string. | |||||
return SystemCallText; // Grab a copy of the text. | return SystemCallText; // Grab a copy of the text. | ||||
} | } | ||||
bool ScriptCaller::hasGuardExpired() { // True if guard time has expired. | bool ScriptCaller::hasGuardExpired() { // True if guard time has expired. | ||||
ScopeMutex Freeze(MyMutex); // Protect the timer. | |||||
cd::ScopeMutex Freeze(MyMutex); // Protect the timer. | |||||
return GuardTimer.isExpired(); // If it has expired we're true. | return GuardTimer.isExpired(); // If it has expired we're true. | ||||
} | } | ||||
void ScriptCaller::SystemCall(string S) { // Set the SystemCall text. | |||||
ScopeMutex Freeze(MyMutex); // Protect the string object. | |||||
void ScriptCaller::SystemCall(std::string S) { // Set the SystemCall text. | |||||
cd::ScopeMutex Freeze(MyMutex); // Protect the string object. | |||||
SystemCallText = S; // Set it's data. | SystemCallText = S; // Set it's data. | ||||
} | } | ||||
const int MinimumGuardTime = 60000; // Minimum Guard Time 1 minute. | const int MinimumGuardTime = 60000; // Minimum Guard Time 1 minute. | ||||
void ScriptCaller::GuardTime(int T) { // Set the Guard Time. | void ScriptCaller::GuardTime(int T) { // Set the Guard Time. | ||||
if(MinimumGuardTime > T) T = MinimumGuardTime; // Enforce our lower limit. | if(MinimumGuardTime > T) T = MinimumGuardTime; // Enforce our lower limit. | ||||
ScopeMutex Freeze(MyMutex); // Protect the Guard Timer. | |||||
cd::ScopeMutex Freeze(MyMutex); // Protect the Guard Timer. | |||||
GuardTimer.setDuration(T); // Set the duration. | GuardTimer.setDuration(T); // Set the duration. | ||||
GuardTimer.restart(); // Restart the timer. | GuardTimer.restart(); // Restart the timer. | ||||
} | } | ||||
} | } | ||||
void ScriptCaller::myTask() { // Safely call system() when triggered. | void ScriptCaller::myTask() { // Safely call system() when triggered. | ||||
Sleeper WaitATic(1000); // One second sleeper. | |||||
cd::Sleeper WaitATic(1000); // One second sleeper. | |||||
while(false == DieFlag) { // While it's not time to die: | while(false == DieFlag) { // While it's not time to die: | ||||
WaitATic(); // Pause for 1 sec each round. | WaitATic(); // Pause for 1 sec each round. | ||||
string ScriptThisRound = ScriptToRun(); // Grab the current script. | |||||
std::string ScriptThisRound = ScriptToRun(); // Grab the current script. | |||||
if(0 < ScriptToRun().length()) { // If script text is defined and | if(0 < ScriptToRun().length()) { // If script text is defined and | ||||
if(true == GoFlag) { // If GoFlag is triggered and | if(true == GoFlag) { // If GoFlag is triggered and | ||||
if(hasGuardExpired()) { // Guard time is expired: | if(hasGuardExpired()) { // Guard time is expired: | ||||
// How to get timestamps on critical files. | // How to get timestamps on critical files. | ||||
time_t getFileTimestamp(string FileName) { | |||||
time_t getFileTimestamp(std::string FileName) { | |||||
struct stat FileNameStat; // First we need a stat buffer. | struct stat FileNameStat; // First we need a stat buffer. | ||||
if(0 != stat(FileName.c_str(), &FileNameStat)) { // If we can't get the stat we | if(0 != stat(FileName.c_str(), &FileNameStat)) { // If we can't get the stat we | ||||
return 0; // will return 0; | return 0; // will return 0; | ||||
} | } | ||||
} | } | ||||
const string snfReloadContext = "--RELOADING--"; // Context for info and error logs. | |||||
const std::string snfReloadContext = "--RELOADING--"; // Context for info and error logs. | |||||
void snf_Reloader::myTask() { // How do we do this refresh thing? | void snf_Reloader::myTask() { // How do we do this refresh thing? | ||||
Sleeper WaitATic(1000); // Wait a second between checks. | |||||
cd::Sleeper WaitATic(1000); // Wait a second between checks. | |||||
while(!TimeToStop) { // While it's not time to stop: | while(!TimeToStop) { // While it's not time to stop: | ||||
if( | if( | ||||
} | } | ||||
} | } | ||||
const ThreadType snf_Reloader::Type("snf_Reloader"); // The thread's type. | |||||
const cd::ThreadType snf_Reloader::Type("snf_Reloader"); // The thread's type. | |||||
snf_Reloader::snf_Reloader(snf_RulebaseHandler& R) : // When we are created, we | snf_Reloader::snf_Reloader(snf_RulebaseHandler& R) : // When we are created, we | ||||
Thread(snf_Reloader::Type, "Reloader"), // brand and name our thread. | Thread(snf_Reloader::Type, "Reloader"), // brand and name our thread. | ||||
cd::RuntimeCheck FileUTCGoodTimestampLength("SNFMulti.cpp:FileUTC snprintf(...) == CorrectTimestampLength"); | cd::RuntimeCheck FileUTCGoodTimestampLength("SNFMulti.cpp:FileUTC snprintf(...) == CorrectTimestampLength"); | ||||
string FileUTC(string FileName) { // Gets a files UTC. | |||||
std::string FileUTC(std::string FileName) { // Gets a files UTC. | |||||
struct stat FileNameStat; // First we need a stat buffer. | struct stat FileNameStat; // First we need a stat buffer. | ||||
string t; // We also need a Timestamp holder. | |||||
std::string t; // We also need a Timestamp holder. | |||||
if(0 != stat(FileName.c_str(), &FileNameStat)) { // If we can't get the stat we | if(0 != stat(FileName.c_str(), &FileNameStat)) { // If we can't get the stat we | ||||
t.append("00000000000000"); return t; // will return all zeroz to | t.append("00000000000000"); return t; // will return all zeroz to | ||||
} // make sure we should get the file. | } // make sure we should get the file. | ||||
RefreshInProgress = false; // we are no longer "in refresh" | RefreshInProgress = false; // we are no longer "in refresh" | ||||
throw ConfigurationError("_snf_LoadNewRulebase() MyCFGmgr.load() failed"); // throw the Configuration exception. | throw ConfigurationError("_snf_LoadNewRulebase() MyCFGmgr.load() failed"); // throw the Configuration exception. | ||||
} | } | ||||
string RuleFilePath = MyCFGmgr.RuleFilePath(); // Get our rulebase file path and our | |||||
string SecurityKey = MyCFGmgr.SecurityKey(); // security key from the CFG manager. | |||||
std::string RuleFilePath = MyCFGmgr.RuleFilePath(); // Get our rulebase file path and our | |||||
std::string SecurityKey = MyCFGmgr.SecurityKey(); // security key from the CFG manager. | |||||
if(0>=RuleFilePath.length()) { // If we don't have a path, we're hosed. | if(0>=RuleFilePath.length()) { // If we don't have a path, we're hosed. | ||||
RefreshInProgress = false; // We are no longer "in refresh" | RefreshInProgress = false; // We are no longer "in refresh" | ||||
throw FileError("_snf_LoadNewRulebase() Zero length RuleFilePath"); // Can't load a RB file with no path! | throw FileError("_snf_LoadNewRulebase() Zero length RuleFilePath"); // Can't load a RB file with no path! | ||||
/**** This section needs work ****/ | /**** This section needs work ****/ | ||||
try { | try { | ||||
string IgnoreListPath = CFGData.paths_workspace_path; | |||||
std::string IgnoreListPath = CFGData.paths_workspace_path; | |||||
IgnoreListPath.append("GBUdbIgnoreList.txt"); | IgnoreListPath.append("GBUdbIgnoreList.txt"); | ||||
if(0 == MyGBUdb.readIgnoreList(IgnoreListPath.c_str())) // We must have at least 1 IP listed. | if(0 == MyGBUdb.readIgnoreList(IgnoreListPath.c_str())) // We must have at least 1 IP listed. | ||||
throw ConfigurationError( | throw ConfigurationError( | ||||
try { | try { | ||||
AutoRefresh(false); // Stop AutoRefresh if it's on. | AutoRefresh(false); // Stop AutoRefresh if it's on. | ||||
} | } | ||||
catch(exception& e) { throw; } // Rethrow good exceptions. | |||||
catch(const std::exception& e) { throw e; } // Rethrow good exceptions. | |||||
catch(...) { throw Panic("snf_RulebaseHandler::close() AutoRefresh(false) panic!"); } // Panic blank exceptions. | catch(...) { throw Panic("snf_RulebaseHandler::close() AutoRefresh(false) panic!"); } // Panic blank exceptions. | ||||
try { | try { | ||||
MyXCImgr.stop(); // Stop the XCI manager. | MyXCImgr.stop(); // Stop the XCI manager. | ||||
} | } | ||||
catch(exception& e) { throw; } // Rethrow good exceptions. | |||||
catch(const std::exception& e) { throw e; } // Rethrow good exceptions. | |||||
catch(...) { throw Panic("snf_RulebaseHandler::close() MyXCImgr.stop() panic!"); } // Panic blank exceptions. | catch(...) { throw Panic("snf_RulebaseHandler::close() MyXCImgr.stop() panic!"); } // Panic blank exceptions. | ||||
if(isBusy() || 0<CurrentCount || 0<ReferenceCount) { // Check that there is no activity. | if(isBusy() || 0<CurrentCount || 0<ReferenceCount) { // Check that there is no activity. | ||||
try { | try { | ||||
MyLOGmgr.stop(); // Stop the LOG manager. | MyLOGmgr.stop(); // Stop the LOG manager. | ||||
} | } | ||||
catch(exception& e) { throw; } // Rethrow good exceptions. | |||||
catch(const std::exception& e) { throw e; } // Rethrow good exceptions. | |||||
catch(...) { throw Panic("snf_RulebaseHandler::close() MyLOGmgr.stop() panic!"); } // Panic blank exceptions. | catch(...) { throw Panic("snf_RulebaseHandler::close() MyLOGmgr.stop() panic!"); } // Panic blank exceptions. | ||||
try { | try { | ||||
MyNETmgr.stop(); // Stop the NET manager. | MyNETmgr.stop(); // Stop the NET manager. | ||||
} | } | ||||
catch(exception& e) { throw; } // Rethrow good exceptions. | |||||
catch(const std::exception& e) { throw e; } // Rethrow good exceptions. | |||||
catch(...) { throw Panic("snf_RulebaseHandler::close() MyNETmgr.stop() panic!"); } // Panic blank exceptions. | catch(...) { throw Panic("snf_RulebaseHandler::close() MyNETmgr.stop() panic!"); } // Panic blank exceptions. | ||||
try { | try { | ||||
MyGBUdbmgr.stop(); // Stop the GBUdb manager. | MyGBUdbmgr.stop(); // Stop the GBUdb manager. | ||||
} | } | ||||
catch(exception& e) { throw; } // Rethrow good exceptions. | |||||
catch(const std::exception& e) { throw e; } // Rethrow good exceptions. | |||||
catch(...) { throw Panic("snf_RulebaseHandler::close() MyGBUdbmgr.stop() panic!"); } // Panic blank exceptions. | catch(...) { throw Panic("snf_RulebaseHandler::close() MyGBUdbmgr.stop() panic!"); } // Panic blank exceptions. | ||||
try { | try { | ||||
if(NULL!=Rulebase) {delete Rulebase; Rulebase=NULL;} // If we have a Rulebase destroy it. | if(NULL!=Rulebase) {delete Rulebase; Rulebase=NULL;} // If we have a Rulebase destroy it. | ||||
} | } | ||||
catch(exception& e) { throw; } // Rethrow good exceptions. | |||||
catch(const std::exception& e) { throw e; } // Rethrow good exceptions. | |||||
catch(...) { throw Panic("snf_RulebaseHandler::close() delete Rulebase panic!"); } // Panic blank exceptions. | catch(...) { throw Panic("snf_RulebaseHandler::close() delete Rulebase panic!"); } // Panic blank exceptions. | ||||
try { | try { | ||||
if(NULL!=OldRulebase) {delete OldRulebase; OldRulebase=NULL;} // Shouldn't happen, but just in case. | if(NULL!=OldRulebase) {delete OldRulebase; OldRulebase=NULL;} // Shouldn't happen, but just in case. | ||||
} | } | ||||
catch(exception& e) { throw; } // Rethrow good exceptions. | |||||
catch(const std::exception& e) { throw e; } // Rethrow good exceptions. | |||||
catch(...) { throw Panic("snf_RulebaseHandler::close() delete OldRulebase panic!"); } // Panic blank exceptions. | catch(...) { throw Panic("snf_RulebaseHandler::close() delete OldRulebase panic!"); } // Panic blank exceptions. | ||||
} | } | ||||
// the operation goes out of scope the configuration packet drop()s with it. | // the operation goes out of scope the configuration packet drop()s with it. | ||||
void snf_RulebaseHandler::grab(snfCFGPacket& CP) { // Activate this Rulebase. | void snf_RulebaseHandler::grab(snfCFGPacket& CP) { // Activate this Rulebase. | ||||
ScopeMutex HoldStillPlease(MyMutex); // Lock the rulebase until we're done. | |||||
cd::ScopeMutex HoldStillPlease(MyMutex); // Lock the rulebase until we're done. | |||||
CurrentCount++; // Boost the count for myself. | CurrentCount++; // Boost the count for myself. | ||||
CP.MyTokenMatrix = Rulebase; // Grab the current rulebase. | CP.MyTokenMatrix = Rulebase; // Grab the current rulebase. | ||||
CP.MyCFGData = MyCFGmgr.ActiveConfiguration(); // Grab the active configuration. | CP.MyCFGData = MyCFGmgr.ActiveConfiguration(); // Grab the active configuration. | ||||
void snf_RulebaseHandler::drop(snfCFGPacket& CP) { // Deactiveate this Rulebase. | void snf_RulebaseHandler::drop(snfCFGPacket& CP) { // Deactiveate this Rulebase. | ||||
const TokenMatrix* t = CP.MyTokenMatrix; // Grab the token matrix pointer. | const TokenMatrix* t = CP.MyTokenMatrix; // Grab the token matrix pointer. | ||||
CP.MyCFGData = NULL; // Null the configuration pointer. | CP.MyCFGData = NULL; // Null the configuration pointer. | ||||
ScopeMutex HoldStillPlease(MyMutex); // Lock the rulebase until we're done. | |||||
cd::ScopeMutex HoldStillPlease(MyMutex); // Lock the rulebase until we're done. | |||||
if(t==Rulebase) { // If we're dropping the current rulebase | if(t==Rulebase) { // If we're dropping the current rulebase | ||||
CurrentCount--; // then reduce the current count. | CurrentCount--; // then reduce the current count. | ||||
} else // If not that then... | } else // If not that then... | ||||
// will have a consistent result based on their last grab(). | // will have a consistent result based on their last grab(). | ||||
void snf_RulebaseHandler::addRulePanic(int RuleID) { // Add a rule panic id dynamically. | void snf_RulebaseHandler::addRulePanic(int RuleID) { // Add a rule panic id dynamically. | ||||
ScopeMutex JustMe(MyMutex); // Freeze the rulebase while we adjust | |||||
cd::ScopeMutex JustMe(MyMutex); // Freeze the rulebase while we adjust | |||||
MyCFGmgr.ActiveConfiguration() // the active configuration to | MyCFGmgr.ActiveConfiguration() // the active configuration to | ||||
->RulePanicHandler.IntegerSet.insert(RuleID); // insert the new rule panic ruleid. | ->RulePanicHandler.IntegerSet.insert(RuleID); // insert the new rule panic ruleid. | ||||
} // When we're done, unlock and move on. | } // When we're done, unlock and move on. | ||||
return I; // Return the processed record. | return I; // Return the processed record. | ||||
} | } | ||||
void snf_RulebaseHandler::logThisIPTest(IPTestRecord& I, string Action) { // Log an IP test result & action. | |||||
void snf_RulebaseHandler::logThisIPTest(IPTestRecord& I, std::string Action) { // Log an IP test result & action. | |||||
MyLOGmgr.logThisIPTest(I, Action); | MyLOGmgr.logThisIPTest(I, Action); | ||||
} | } | ||||
void snf_RulebaseHandler::logThisError( // Log an error message. | void snf_RulebaseHandler::logThisError( // Log an error message. | ||||
string ContextName, int Code, string Text | |||||
std::string ContextName, int Code, std::string Text | |||||
) { | ) { | ||||
MyLOGmgr.logThisError(ContextName, Code, Text); | MyLOGmgr.logThisError(ContextName, Code, Text); | ||||
} | } | ||||
void snf_RulebaseHandler::logThisInfo( // Log an informational message. | void snf_RulebaseHandler::logThisInfo( // Log an informational message. | ||||
string ContextName, int Code, string Text | |||||
std::string ContextName, int Code, std::string Text | |||||
) { | ) { | ||||
MyLOGmgr.logThisInfo(ContextName, Code, Text); | MyLOGmgr.logThisInfo(ContextName, Code, Text); | ||||
} | } | ||||
string snf_RulebaseHandler::PlatformVersion(string NewPlatformVersion) { // Set platform version info. | |||||
std::string snf_RulebaseHandler::PlatformVersion(std::string NewPlatformVersion) { // Set platform version info. | |||||
return MyLOGmgr.PlatformVersion(NewPlatformVersion); | return MyLOGmgr.PlatformVersion(NewPlatformVersion); | ||||
} | } | ||||
string snf_RulebaseHandler::PlatformVersion() { // Get platform version info. | |||||
std::string snf_RulebaseHandler::PlatformVersion() { // Get platform version info. | |||||
return MyLOGmgr.PlatformVersion(); | return MyLOGmgr.PlatformVersion(); | ||||
} | } | ||||
string snf_RulebaseHandler::PlatformConfiguration() { // Get platform configuration. | |||||
ScopeMutex LockAndGrab(MyMutex); // Freeze things for a moment and | |||||
std::string snf_RulebaseHandler::PlatformConfiguration() { // Get platform configuration. | |||||
cd::ScopeMutex LockAndGrab(MyMutex); // Freeze things for a moment and | |||||
return MyCFGmgr.ActiveConfiguration()->PlatformElementContents; // copy the platform configuration. | return MyCFGmgr.ActiveConfiguration()->PlatformElementContents; // copy the platform configuration. | ||||
} | } | ||||
string snf_RulebaseHandler::EngineVersion() { // Get engine version info. | |||||
std::string snf_RulebaseHandler::EngineVersion() { // Get engine version info. | |||||
return MyLOGmgr.EngineVersion(); | return MyLOGmgr.EngineVersion(); | ||||
} | } | ||||
void snf_RulebaseHandler:: | void snf_RulebaseHandler:: | ||||
XCIServerCommandHandler(snfXCIServerCommandHandler& XCH) { // Registers a new XCI Srvr Cmd handler. | XCIServerCommandHandler(snfXCIServerCommandHandler& XCH) { // Registers a new XCI Srvr Cmd handler. | ||||
ScopeMutex ThereCanBeOnlyOne(XCIServerCommandMutex); // Serialize access to this resource. | |||||
cd::ScopeMutex ThereCanBeOnlyOne(XCIServerCommandMutex); // Serialize access to this resource. | |||||
myXCIServerCommandHandler = &XCH; // Assign the new handler as provided. | myXCIServerCommandHandler = &XCH; // Assign the new handler as provided. | ||||
} | } | ||||
string snf_RulebaseHandler::processXCIServerCommandRequest(snf_xci& X) { // Handle a parsed XCI Srvr Cmd request. | |||||
ScopeMutex ThereCanBeOnlyOne(XCIServerCommandMutex); // Serialize access to this resource. | |||||
std::string snf_RulebaseHandler::processXCIServerCommandRequest(snf_xci& X) { // Handle a parsed XCI Srvr Cmd request. | |||||
cd::ScopeMutex ThereCanBeOnlyOne(XCIServerCommandMutex); // Serialize access to this resource. | |||||
if(0 == myXCIServerCommandHandler) { // If we don't have a handler then | if(0 == myXCIServerCommandHandler) { // If we don't have a handler then | ||||
snfXCIServerCommandHandler H; // create a base handler and | snfXCIServerCommandHandler H; // create a base handler and | ||||
return H.processXCIRequest(X); // return it's default response. | return H.processXCIRequest(X); // return it's default response. | ||||
// always considered the source and second if they are in the GBUdb ignore list | // always considered the source and second if they are in the GBUdb ignore list | ||||
// then GBUdb training bypass is established. | // then GBUdb training bypass is established. | ||||
string& snf_IPTestEngine::test(string& input, string& output) { // Perform IP lookups and put IPs into ScanData. | |||||
std::string& snf_IPTestEngine::test(std::string& input, std::string& output) { // Perform IP lookups and put IPs into ScanData. | |||||
if(NULL == Lookup || NULL == ScanData) { // If we are not set up properly then we | if(NULL == Lookup || NULL == ScanData) { // If we are not set up properly then we | ||||
output = "{IPTest Config Error}"; // will return an error string. | output = "{IPTest Config Error}"; // will return an error string. | ||||
try { // If we're out of IP records, no analysis. | try { // If we're out of IP records, no analysis. | ||||
IPScanRecord& I = ScanData->newIPScanRecord(); // Grab a new IP scan record and | IPScanRecord& I = ScanData->newIPScanRecord(); // Grab a new IP scan record and | ||||
IP4Address IP = input; // Convert the string to an IP. | |||||
cd::IP4Address IP = input; // Convert the string to an IP. | |||||
// Identify forced Source IP addresses | // Identify forced Source IP addresses | ||||
output = "{"; // Next we start to build our IP data insert. | output = "{"; // Next we start to build our IP data insert. | ||||
ostringstream S; // We will use a string stream for formatting. | |||||
std::ostringstream S; // We will use a string stream for formatting. | |||||
switch(R.Flag()) { // Identify the flag data for this IP. | switch(R.Flag()) { // Identify the flag data for this IP. | ||||
case Good: S << "Good "; break; | case Good: S << "Good "; break; | ||||
case Bad: S << "Bad "; break; | case Bad: S << "Bad "; break; | ||||
// a bad outcome. | // a bad outcome. | ||||
bool snf_RulebaseHandler::testXHDRInjectOn() { | bool snf_RulebaseHandler::testXHDRInjectOn() { | ||||
ScopeMutex HoldStillPlease(MyMutex); // Lock the rulebase until we're done. | |||||
cd::ScopeMutex HoldStillPlease(MyMutex); // Lock the rulebase until we're done. | |||||
snfCFGData* myCFG = MyCFGmgr.ActiveConfiguration(); // Grab the active configuration. | snfCFGData* myCFG = MyCFGmgr.ActiveConfiguration(); // Grab the active configuration. | ||||
bool myXHDRInjectOnFlag = (LogOutputMode_Inject == myCFG->XHDROutput_Mode); // True if output mode is inject. | bool myXHDRInjectOnFlag = (LogOutputMode_Inject == myCFG->XHDROutput_Mode); // True if output mode is inject. | ||||
return myXHDRInjectOnFlag; // return the result. | return myXHDRInjectOnFlag; // return the result. | ||||
} | } | ||||
int snf_EngineHandler::scanMessageFile( // Scan this message file. | int snf_EngineHandler::scanMessageFile( // Scan this message file. | ||||
const string MessageFilePath, // -- this is the file path (and id) | |||||
const std::string MessageFilePath, // -- this is the file path (and id) | |||||
const int MessageSetupTime, // -- setup time already used. | const int MessageSetupTime, // -- setup time already used. | ||||
const IP4Address MessageSource // -- message source IP (for injection). | |||||
const cd::IP4Address MessageSource // -- message source IP (for injection). | |||||
) { | ) { | ||||
Timer AdditionalSetupTime; | |||||
ScopeMutex DoingAFileScan(FileScan); // Protect MyScanData @ this entry. | |||||
cd::Timer AdditionalSetupTime; | |||||
cd::ScopeMutex DoingAFileScan(FileScan); // Protect MyScanData @ this entry. | |||||
// Preliminary setup. Clearing the ScanData resets the ReadyToClear flag | // Preliminary setup. Clearing the ScanData resets the ReadyToClear flag | ||||
// and allows us to set some data for more accurate tracking and so that if | // and allows us to set some data for more accurate tracking and so that if | ||||
// Now that the preliminaries are established we can begin our work. | // Now that the preliminaries are established we can begin our work. | ||||
int MessageFileSize = 0; // Here will be the size of it. | int MessageFileSize = 0; // Here will be the size of it. | ||||
ifstream MessageFile; // Here will be our input file. | |||||
std::ifstream MessageFile; // Here will be our input file. | |||||
MessageFile.exceptions( // It will throw exceptions for | MessageFile.exceptions( // It will throw exceptions for | ||||
ifstream::eofbit | ifstream::failbit | ifstream::badbit // these unwanted events. | |||||
std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit // these unwanted events. | |||||
); | ); | ||||
try { // Try opening the message file. | try { // Try opening the message file. | ||||
MessageFile.open(MessageFilePath.c_str(), ios::in | ios::binary); // Open the file, binary mode. | |||||
MessageFile.seekg(0, ios::end); // Find the end of the file, | |||||
MessageFile.open(MessageFilePath.c_str(), | |||||
std::ios::in | std::ios::binary); // Open the file, binary mode. | |||||
MessageFile.seekg(0, std::ios::end); // Find the end of the file, | |||||
MessageFileSize = MessageFile.tellg(); // read that position as the size, | MessageFileSize = MessageFile.tellg(); // read that position as the size, | ||||
MessageFile.seekg(0, ios::beg); // then go back to the beginning. | |||||
MessageFile.seekg(0, std::ios::beg); // then go back to the beginning. | |||||
MyScanData.ScanSize = MessageFileSize; // Capture the message file size. | MyScanData.ScanSize = MessageFileSize; // Capture the message file size. | ||||
} | } | ||||
catch(...) { // Trouble? Throw FileError. | catch(...) { // Trouble? Throw FileError. | ||||
bool isXHeaderInjectionOn = MyRulebase->testXHDRInjectOn(); | bool isXHeaderInjectionOn = MyRulebase->testXHDRInjectOn(); | ||||
bool noNeedToReadFullFile = (false == isXHeaderInjectionOn); | bool noNeedToReadFullFile = (false == isXHeaderInjectionOn); | ||||
if(noNeedToReadFullFile) { | if(noNeedToReadFullFile) { | ||||
MessageFileSize = min(MessageFileSize, snf_ScanHorizon); | |||||
MessageFileSize = std::min(MessageFileSize, snf_ScanHorizon); | |||||
} | } | ||||
vector<unsigned char> MessageBuffer; // Allocate a buffer and size | |||||
std::vector<unsigned char> MessageBuffer; // Allocate a buffer and size | |||||
try { MessageBuffer.resize(MessageFileSize, 0); } // it to fit the message. | try { MessageBuffer.resize(MessageFileSize, 0); } // it to fit the message. | ||||
catch(...) { // Trouble? Throw AllocationError. | catch(...) { // Trouble? Throw AllocationError. | ||||
MyRulebase->MyLOGmgr.logThisError( // Log the error. | MyRulebase->MyLOGmgr.logThisError( // Log the error. | ||||
XHDRInjStage = "Open Temp File"; // Update our process monitor. | XHDRInjStage = "Open Temp File"; // Update our process monitor. | ||||
string TempFileName = MessageFilePath; // Prepare a temp file name | |||||
std::string TempFileName = MessageFilePath; // Prepare a temp file name | |||||
TempFileName.append(".tmp"); // based on the message file. | TempFileName.append(".tmp"); // based on the message file. | ||||
ofstream TempFile; // Here will be our temp file. | |||||
TempFile.exceptions(ofstream::failbit | ofstream::badbit); // It will throw these exceptions. | |||||
TempFile.open(TempFileName.c_str(), ios::binary | ios::trunc); // Open and truncate the file. | |||||
std::ofstream TempFile; // Here will be our temp file. | |||||
TempFile.exceptions(std::ofstream::failbit | std::ofstream::badbit); // It will throw these exceptions. | |||||
TempFile.open(TempFileName.c_str(), | |||||
std::ios::binary | std::ios::trunc); // Open and truncate the file. | |||||
// If our insert point is the top of the message we'll skip this. | // If our insert point is the top of the message we'll skip this. | ||||
XHDRInjStage = "XHDR <CR><LF> to <LF>"; | XHDRInjStage = "XHDR <CR><LF> to <LF>"; | ||||
if(true == UseLFOnly) { // If we are using <LF> only: | if(true == UseLFOnly) { // If we are using <LF> only: | ||||
string ReworkedHeaders = ""; // Make a new string and rework | |||||
std::string ReworkedHeaders = ""; // Make a new string and rework | |||||
for( // our headers. | for( // our headers. | ||||
string::iterator iS = MyScanData.XHDRsText.begin(); // Run through the headers one | |||||
std::string::iterator iS = MyScanData.XHDRsText.begin(); // Run through the headers one | |||||
iS != MyScanData.XHDRsText.end(); iS++ // byte at a time. | iS != MyScanData.XHDRsText.end(); iS++ // byte at a time. | ||||
) { | ) { | ||||
if('\r' != (*iS)) ReworkedHeaders.push_back(*iS); // Strip out any <CR> chars. | if('\r' != (*iS)) ReworkedHeaders.push_back(*iS); // Strip out any <CR> chars. | ||||
TempFile.close(); // Close the file (flushing it). | TempFile.close(); // Close the file (flushing it). | ||||
Sleeper PauseBeforeRetry(300); // Delay to use between retries. | |||||
cd::Sleeper PauseBeforeRetry(300); // Delay to use between retries. | |||||
XHDRInjStage = "Drop Msg"; // Update our process monitor. | XHDRInjStage = "Drop Msg"; // Update our process monitor. | ||||
} | } | ||||
} | } | ||||
catch(XHDRError& e) { // For full XHDRError exceptions. | catch(XHDRError& e) { // For full XHDRError exceptions. | ||||
string ERROR_MSG_XHDRi = "ERROR_MSG_XHDRi: "; // Format the XHDRInj error msg. | |||||
std::string ERROR_MSG_XHDRi = "ERROR_MSG_XHDRi: "; // Format the XHDRInj error msg. | |||||
ERROR_MSG_XHDRi.append(XHDRInjStage); | ERROR_MSG_XHDRi.append(XHDRInjStage); | ||||
ERROR_MSG_XHDRi.append(" "); | ERROR_MSG_XHDRi.append(" "); | ||||
ERROR_MSG_XHDRi.append(e.what()); | ERROR_MSG_XHDRi.append(e.what()); | ||||
); | ); | ||||
throw; // Rethrow any XHDRError exceptions. | throw; // Rethrow any XHDRError exceptions. | ||||
} | } | ||||
catch(exception& e) { // For ordinary runtime exceptions. | |||||
string ERROR_MSG_XHDRi = "ERROR_MSG_XHDRi: "; // Format the XHDRInj error msg. | |||||
catch(const std::exception& e) { // For ordinary runtime exceptions. | |||||
std::string ERROR_MSG_XHDRi = "ERROR_MSG_XHDRi: "; // Format the XHDRInj error msg. | |||||
ERROR_MSG_XHDRi.append(XHDRInjStage); | ERROR_MSG_XHDRi.append(XHDRInjStage); | ||||
ERROR_MSG_XHDRi.append(" "); | ERROR_MSG_XHDRi.append(" "); | ||||
ERROR_MSG_XHDRi.append(e.what()); | ERROR_MSG_XHDRi.append(e.what()); | ||||
throw XHDRError(ERROR_MSG_XHDRi); // Rethrow as XHDRError exceptions. | throw XHDRError(ERROR_MSG_XHDRi); // Rethrow as XHDRError exceptions. | ||||
} | } | ||||
catch(...) { // If we encounter a problem then | catch(...) { // If we encounter a problem then | ||||
string ERROR_MSG_XHDRi = "ERROR_MSG_XHDRi: "; // Format the XHDRInj error msg. | |||||
std::string ERROR_MSG_XHDRi = "ERROR_MSG_XHDRi: "; // Format the XHDRInj error msg. | |||||
ERROR_MSG_XHDRi.append(XHDRInjStage); | ERROR_MSG_XHDRi.append(XHDRInjStage); | ||||
MyRulebase->MyLOGmgr.logThisError( // Log the error. | MyRulebase->MyLOGmgr.logThisError( // Log the error. | ||||
MyScanData, "scanMessageFile().xhdr.inject", | MyScanData, "scanMessageFile().xhdr.inject", | ||||
snf_ERROR_MSG_FILE, ERROR_MSG_XHDRi | snf_ERROR_MSG_FILE, ERROR_MSG_XHDRi | ||||
); | ); | ||||
string XHDRError_msg = "Message Rewrite Failed: "; // Format our throw message with | |||||
std::string XHDRError_msg = "Message Rewrite Failed: "; // Format our throw message with | |||||
XHDRError_msg.append(XHDRInjStage); // our detailed stage data and | XHDRError_msg.append(XHDRInjStage); // our detailed stage data and | ||||
throw XHDRError(XHDRError_msg); // throw our special exception. | throw XHDRError(XHDRError_msg); // throw our special exception. | ||||
} | } | ||||
if(MyScanData.XHeaderFileOn) { | if(MyScanData.XHeaderFileOn) { | ||||
try { | try { | ||||
ofstream XHDRFile; // Output file will be XHDRFile. | |||||
XHDRFile.exceptions(ofstream::failbit | ofstream::badbit); // These events will throw exceptions. | |||||
string XHDRFileName = MessageFilePath; // Build the XHDR file name by adding | |||||
XHDRFileName.append(".xhdr"); // .xhdr to the message file name. | |||||
XHDRFile.open(XHDRFileName.c_str(), ios::binary | ios::trunc); // Open (and truncate) the file. | |||||
std::ofstream XHDRFile; // Output file will be XHDRFile. | |||||
XHDRFile.exceptions(std::ofstream::failbit | std::ofstream::badbit); // These events will throw exceptions. | |||||
std::string XHDRFileName = MessageFilePath; // Build the XHDR file name by adding | |||||
XHDRFileName.append(".xhdr"); // .xhdr to the message file name. | |||||
XHDRFile.open(XHDRFileName.c_str(), | |||||
std::ios::binary | std::ios::trunc); // Open (and truncate) the file. | |||||
XHDRFile << MyScanData.XHDRsText; // Spit out the XHDRs. | XHDRFile << MyScanData.XHDRsText; // Spit out the XHDRs. | ||||
XHDRFile.close(); // All done. | XHDRFile.close(); // All done. | ||||
} | } | ||||
return ScanResultCode; // Return the actual result, of course. | return ScanResultCode; // Return the actual result, of course. | ||||
} | } | ||||
string snf_EngineHandler::extractMessageID( // Find and return the first Message-ID | |||||
std::string snf_EngineHandler::extractMessageID( // Find and return the first Message-ID | |||||
const unsigned char* Msg, // Input the Message buffer to search | const unsigned char* Msg, // Input the Message buffer to search | ||||
const int Len // and the length of the buffer. | const int Len // and the length of the buffer. | ||||
) { | ) { | ||||
string ExtractedID = ""; // Start with an empty string. | |||||
std::string ExtractedID = ""; // Start with an empty string. | |||||
bool FoundID = false; // Haven't found it yet. | bool FoundID = false; // Haven't found it yet. | ||||
int C = 0; // Cursor position. | int C = 0; // Cursor position. | ||||
while(!FoundID && (C < (Len - 12))) { // Loop through the Msg looking for | while(!FoundID && (C < (Len - 12))) { // Loop through the Msg looking for | ||||
M.endex = R->MatchEndPosition; | M.endex = R->MatchEndPosition; | ||||
} | } | ||||
void snf_SaccadesHandler::applySaccades(EvaluationMatrix* Scanner, vector<unsigned char>& Data) { | |||||
void snf_SaccadesHandler::applySaccades(EvaluationMatrix* Scanner, std::vector<unsigned char>& Data) { | |||||
if(NULL == Scanner) return; | if(NULL == Scanner) return; | ||||
bool isTimeToPeek = (0 >= TimeToPeekCounter); | bool isTimeToPeek = (0 >= TimeToPeekCounter); | ||||
--TimeToPeekCounter; | --TimeToPeekCounter; | ||||
} | } | ||||
vector<saccade> Saccades = grabSaccades(); | |||||
for(vector<saccade>::iterator i = Saccades.begin(); i != Saccades.end(); i++) { | |||||
std::vector<saccade> Saccades = grabSaccades(); | |||||
for(std::vector<saccade>::iterator i = Saccades.begin(); i != Saccades.end(); i++) { | |||||
const saccade& s = (*i); | const saccade& s = (*i); | ||||
if(s.start >= Data.size()) break; | if(s.start >= Data.size()) break; | ||||
Scanner->evaluateSegment(Data, s.start, s.finish); | Scanner->evaluateSegment(Data, s.start, s.finish); | ||||
void snf_SaccadesHandler::learnMatches(MatchRecord* Matches) { | void snf_SaccadesHandler::learnMatches(MatchRecord* Matches) { | ||||
if(NULL == Matches) return; | if(NULL == Matches) return; | ||||
vector<saccade> MatchesToLearn; | |||||
std::vector<saccade> MatchesToLearn; | |||||
saccade WatchForHeaderWhiteRules(0, AlwaysScanLength); | saccade WatchForHeaderWhiteRules(0, AlwaysScanLength); | ||||
MatchesToLearn.push_back(WatchForHeaderWhiteRules); | MatchesToLearn.push_back(WatchForHeaderWhiteRules); | ||||
int snf_EngineHandler::scanMessage( // Scan this message (in buffer). | int snf_EngineHandler::scanMessage( // Scan this message (in buffer). | ||||
const unsigned char* inputMessageBuffer, // -- this is the message buffer. | const unsigned char* inputMessageBuffer, // -- this is the message buffer. | ||||
const int inputMessageLength, // -- this is the length of the buffer. | const int inputMessageLength, // -- this is the length of the buffer. | ||||
const string MessageName, // -- this is the message identifier. | |||||
const std::string MessageName, // -- this is the message identifier. | |||||
const int MessageSetupTime, // -- setup time used (for logging). | const int MessageSetupTime, // -- setup time used (for logging). | ||||
const IP4Address MessageSource // -- message source IP (for injection). | |||||
const cd::IP4Address MessageSource // -- message source IP (for injection). | |||||
) { | ) { | ||||
ScopeTimer ScanTimeCapture(MyScanData.ScanTime); // Start the scan time clock. | |||||
cd::ScopeTimer ScanTimeCapture(MyScanData.ScanTime); // Start the scan time clock. | |||||
unsigned char* MessageBuffer = NULL; // Explicitly initialize these two | unsigned char* MessageBuffer = NULL; // Explicitly initialize these two | ||||
int MessageLength = 0; // so the compiler will be happy. | int MessageLength = 0; // so the compiler will be happy. | ||||
// Protect this engine - only one scan at a time per EngineHandler ;-) | // Protect this engine - only one scan at a time per EngineHandler ;-) | ||||
ScopeMutex ScannerIsBusy(MyMutex); // Serialize this... | |||||
cd::ScopeMutex ScannerIsBusy(MyMutex); // Serialize this... | |||||
// Preliminary job setup. | // Preliminary job setup. | ||||
// Set up our filter chain. | // Set up our filter chain. | ||||
stringstream PrependedHeaders; // Use this to prepend X-Headers. | |||||
std::stringstream PrependedHeaders; // Use this to prepend X-Headers. | |||||
FilterChainCBFR IU(MessageBuffer, MessageLength, PrependedHeaders); // Set up the filter chain. | FilterChainCBFR IU(MessageBuffer, MessageLength, PrependedHeaders); // Set up the filter chain. | ||||
FilterChainHeaderAnalysis IV(&IU, MyIPTestEngine); // Include header analysis. | FilterChainHeaderAnalysis IV(&IU, MyIPTestEngine); // Include header analysis. | ||||
FilterChainBase64 IW(&IV); // Include Base64 decoding. | FilterChainBase64 IW(&IV); // Include Base64 decoding. | ||||
if(0UL != MyScanData.CallerForcedSourceIP()) { // If the caller forced the source IP: | if(0UL != MyScanData.CallerForcedSourceIP()) { // If the caller forced the source IP: | ||||
PrependedHeaders // Make a phantom Received header | PrependedHeaders // Make a phantom Received header | ||||
<< "Received: Caller.Forced.Source.IP [" // showing that the caller forced | << "Received: Caller.Forced.Source.IP [" // showing that the caller forced | ||||
<< (string) MyScanData.CallerForcedSourceIP() << "]\n"; // the source IP. | |||||
<< (std::string) MyScanData.CallerForcedSourceIP() << "]\n"; // the source IP. | |||||
} else | } else | ||||
// If not forced by the caller but a | // If not forced by the caller but a | ||||
if(0UL != MyScanData.HeaderDirectiveSourceIP()) { // header directive forced the source IP: | if(0UL != MyScanData.HeaderDirectiveSourceIP()) { // header directive forced the source IP: | ||||
PrependedHeaders // Make a phantom Received header | PrependedHeaders // Make a phantom Received header | ||||
<< "Received: Header.Directive.Source.IP [" // showing that a header directive | << "Received: Header.Directive.Source.IP [" // showing that a header directive | ||||
<< (string) MyScanData.HeaderDirectiveSourceIP() << "]\n"; // established the source IP. | |||||
<< (std::string) MyScanData.HeaderDirectiveSourceIP() << "]\n"; // established the source IP. | |||||
} | } | ||||
// Most of the time we will extract the source IP the normal way. | // Most of the time we will extract the source IP the normal way. | ||||
); | ); | ||||
throw; | throw; | ||||
} | } | ||||
catch(exception& e) { // Other exceptions. | |||||
catch(const std::exception& e) { // Other exceptions. | |||||
MyRulebase->MyLOGmgr.logThisError( // Log the error. | MyRulebase->MyLOGmgr.logThisError( // Log the error. | ||||
MyScanData, "scanMessage()", | MyScanData, "scanMessage()", | ||||
snf_ERROR_UNKNOWN, "ERROR_EXCEPTION" | snf_ERROR_UNKNOWN, "ERROR_EXCEPTION" | ||||
// GBUdb training is enabled. | // GBUdb training is enabled. | ||||
bool discoveredNewIP = false; | bool discoveredNewIP = false; | ||||
IP4Address theSourceIP = MyScanData.SourceIPRecord().IP; | |||||
cd::IP4Address theSourceIP = MyScanData.SourceIPRecord().IP; | |||||
switch(ScanResultType) { // Evaluate the scan result. | switch(ScanResultType) { // Evaluate the scan result. | ||||
case NoPattern: // On no pattern (benefit of doubt) or | case NoPattern: // On no pattern (benefit of doubt) or | ||||
int snf_EngineHandler::getResults(snf_match* MatchBuffer){ // Get the next match buffer. | int snf_EngineHandler::getResults(snf_match* MatchBuffer){ // Get the next match buffer. | ||||
ScopeMutex SerializeThis(MyMutex); // Serialize this... | |||||
cd::ScopeMutex SerializeThis(MyMutex); // Serialize this... | |||||
if(NULL == MatchBuffer) { // If we were given the reset signal | if(NULL == MatchBuffer) { // If we were given the reset signal | ||||
MyScanData.MatchRecordsCursor = MyScanData.MatchRecords.begin(); // Move the cursor to the beginning | MyScanData.MatchRecordsCursor = MyScanData.MatchRecords.begin(); // Move the cursor to the beginning | ||||
MyScanData.MatchRecordsDelivered = 0; // and reset the delivered count. | MyScanData.MatchRecordsDelivered = 0; // and reset the delivered count. | ||||
} | } | ||||
int snf_EngineHandler::getDepth(){ // Get the scan depth. | int snf_EngineHandler::getDepth(){ // Get the scan depth. | ||||
ScopeMutex SerializeThis(MyMutex); // Protect our reading. | |||||
cd::ScopeMutex SerializeThis(MyMutex); // Protect our reading. | |||||
return MyScanData.ScanDepth; // Return the latest scan depth. | return MyScanData.ScanDepth; // Return the latest scan depth. | ||||
} | } | ||||
const string snf_EngineHandler::getClassicLog() { // Get classic log entries for last scan. | |||||
ScopeMutex SerializeThis(MyMutex); // Serialize this... | |||||
const std::string snf_EngineHandler::getClassicLog() { // Get classic log entries for last scan. | |||||
cd::ScopeMutex SerializeThis(MyMutex); // Serialize this... | |||||
return MyScanData.ClassicLogText; // Return the log text. | return MyScanData.ClassicLogText; // Return the log text. | ||||
} | } | ||||
const string snf_EngineHandler::getXMLLog() { // Get XML log entries or last scan. | |||||
ScopeMutex SerializeThis(MyMutex); // Serialize this... | |||||
const std::string snf_EngineHandler::getXMLLog() { // Get XML log entries or last scan. | |||||
cd::ScopeMutex SerializeThis(MyMutex); // Serialize this... | |||||
return MyScanData.XMLLogText; // Return the log text. | return MyScanData.XMLLogText; // Return the log text. | ||||
} | } | ||||
const string snf_EngineHandler::getXHDRs() { // Get XHDRs for last scan. | |||||
ScopeMutex SerializeThis(MyMutex); // Serialize this... | |||||
const std::string snf_EngineHandler::getXHDRs() { // Get XHDRs for last scan. | |||||
cd::ScopeMutex SerializeThis(MyMutex); // Serialize this... | |||||
return MyScanData.XHDRsText; // Return the XHeaders text. | return MyScanData.XHDRsText; // Return the XHeaders text. | ||||
} | } | ||||
{ RulebaseScan.unlock(); throw FileError(e.what()); } | { RulebaseScan.unlock(); throw FileError(e.what()); } | ||||
catch(snf_RulebaseHandler::Busy& e) | catch(snf_RulebaseHandler::Busy& e) | ||||
{ RulebaseScan.unlock(); throw Panic(e.what()); } // Wasn't busy above!! Shoudn't be here!!! | { RulebaseScan.unlock(); throw Panic(e.what()); } // Wasn't busy above!! Shoudn't be here!!! | ||||
catch(exception& e) | |||||
{ RulebaseScan.unlock(); throw; } | |||||
catch(const std::exception& e) | |||||
{ RulebaseScan.unlock(); throw e; } | |||||
catch(...) { | catch(...) { | ||||
RulebaseScan.unlock(); | RulebaseScan.unlock(); | ||||
throw Panic("snf_MultiEngineHandler::OpenRulebase() ???"); | throw Panic("snf_MultiEngineHandler::OpenRulebase() ???"); | ||||
catch(snf_RulebaseHandler::Busy& e) { | catch(snf_RulebaseHandler::Busy& e) { | ||||
throw Busy(e.what()); | throw Busy(e.what()); | ||||
} | } | ||||
catch(exception& e) { | |||||
throw; | |||||
catch(const std::exception& e) { | |||||
throw e; | |||||
} | } | ||||
catch(...) { | catch(...) { | ||||
throw Panic("snf_MultiEngineHandler::RefreshRulebase() ???"); | throw Panic("snf_MultiEngineHandler::RefreshRulebase() ???"); | ||||
catch(snf_RulebaseHandler::Busy& e) { // A busy throw we can understand. | catch(snf_RulebaseHandler::Busy& e) { // A busy throw we can understand. | ||||
RulebaseScan.unlock(); throw Busy(e.what()); | RulebaseScan.unlock(); throw Busy(e.what()); | ||||
} | } | ||||
catch(exception& e) { // Other exceptions? rethrow. | |||||
RulebaseScan.unlock(); throw; | |||||
catch(const std::exception& e) { // Other exceptions? rethrow. | |||||
RulebaseScan.unlock(); throw e; | |||||
} | } | ||||
catch(...) { // Any other throw is big trouble. | catch(...) { // Any other throw is big trouble. | ||||
RulebaseScan.unlock(); | RulebaseScan.unlock(); | ||||
{ EngineScan.unlock(); throw AllocationError(e.what()); } | { EngineScan.unlock(); throw AllocationError(e.what()); } | ||||
catch(snf_EngineHandler::Busy& e) | catch(snf_EngineHandler::Busy& e) | ||||
{ EngineScan.unlock(); throw Panic(e.what()); } // Not busy above should not be busy now!!! | { EngineScan.unlock(); throw Panic(e.what()); } // Not busy above should not be busy now!!! | ||||
catch(exception& e) { | |||||
catch(const std::exception& e) { | |||||
EngineScan.unlock(); | EngineScan.unlock(); | ||||
throw; | |||||
throw e; | |||||
} | } | ||||
catch(...) { | catch(...) { | ||||
EngineScan.unlock(); | EngineScan.unlock(); | ||||
{ EngineScan.unlock(); throw AllocationError(e.what()); } | { EngineScan.unlock(); throw AllocationError(e.what()); } | ||||
catch(snf_EngineHandler::Busy& e) | catch(snf_EngineHandler::Busy& e) | ||||
{ EngineScan.unlock(); throw Busy(e.what()); } | { EngineScan.unlock(); throw Busy(e.what()); } | ||||
catch(exception& e) { | |||||
catch(const std::exception& e) { | |||||
EngineScan.unlock(); | EngineScan.unlock(); | ||||
throw; | |||||
throw e; | |||||
} | } | ||||
catch(...) { | catch(...) { | ||||
EngineScan.unlock(); | EngineScan.unlock(); | ||||
throw AllocationError(e.what()); | throw AllocationError(e.what()); | ||||
} | } | ||||
catch(snf_EngineHandler::Busy& e) { throw Busy(e.what()); } | catch(snf_EngineHandler::Busy& e) { throw Busy(e.what()); } | ||||
catch(exception& e) { throw; } | |||||
catch(const std::exception& e) { throw e; } | |||||
catch(...) { throw Panic("snf_MultiEngineHandler::Scan() ???"); } | catch(...) { throw Panic("snf_MultiEngineHandler::Scan() ???"); } | ||||
return ScanResult; // Return the results. | return ScanResult; // Return the results. | ||||
} | } | ||||
throw AllocationError(e.what()); | throw AllocationError(e.what()); | ||||
} | } | ||||
catch(snf_EngineHandler::Busy& e) { throw Busy(e.what()); } | catch(snf_EngineHandler::Busy& e) { throw Busy(e.what()); } | ||||
catch(exception& e) { throw; } | |||||
catch(const std::exception& e) { throw e; } | |||||
catch(...) { throw Panic("snf_MultiEngineHandler::getResults() ???"); } | catch(...) { throw Panic("snf_MultiEngineHandler::getResults() ???"); } | ||||
return ResultCount; // Return the results. | return ResultCount; // Return the results. | ||||
throw AllocationError(e.what()); | throw AllocationError(e.what()); | ||||
} | } | ||||
catch(snf_EngineHandler::Busy& e) { throw Busy(e.what()); } | catch(snf_EngineHandler::Busy& e) { throw Busy(e.what()); } | ||||
catch(exception& e) { throw; } | |||||
catch(const std::exception& e) { throw e; } | |||||
catch(...) { throw Panic("snf_MultiEngineHandler::getDepth() ???"); } | catch(...) { throw Panic("snf_MultiEngineHandler::getDepth() ???"); } | ||||
return DepthResult; // Return the results. | return DepthResult; // Return the results. |
// SNFMulti.hpp | // SNFMulti.hpp | ||||
// | // | ||||
// (C) Copyright 2006 - 2009 ARM Research Labs, LLC. | |||||
// (C) Copyright 2006 - 2020 ARM Research Labs, LLC. | |||||
// See www.armresearch.com for the copyright terms. | // See www.armresearch.com for the copyright terms. | ||||
// | // | ||||
// 20060121_M | // 20060121_M | ||||
// rulebase each time they restart. The grabbing and swapping in of new rulebases is | // rulebase each time they restart. The grabbing and swapping in of new rulebases is | ||||
// a very short critical section. | // a very short critical section. | ||||
#ifndef _ARM_SNFMulti | |||||
#define _ARM_SNFMulti | |||||
#pragma once | |||||
#include <stdexcept> | #include <stdexcept> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <ctime> | #include <ctime> | ||||
#include <string> | |||||
#include <string> | |||||
#include "../CodeDweller/faults.hpp" | #include "../CodeDweller/faults.hpp" | ||||
#include "../CodeDweller/threading.hpp" | #include "../CodeDweller/threading.hpp" | ||||
#include "GBUdb.hpp" | #include "GBUdb.hpp" | ||||
#include "snfLOGmgr.hpp" | #include "snfLOGmgr.hpp" | ||||
#include "snfNETmgr.hpp" | #include "snfNETmgr.hpp" | ||||
#include "snfGBUdbmgr.hpp" | #include "snfGBUdbmgr.hpp" | ||||
#include "snfXCImgr.hpp" | |||||
#include "snf_saccades.hpp" | |||||
#include "snfXCImgr.hpp" | |||||
#include "snf_saccades.hpp" | |||||
#include <cassert> | #include <cassert> | ||||
namespace cd = codedweller; | |||||
extern const char* SNF_ENGINE_VERSION; | extern const char* SNF_ENGINE_VERSION; | ||||
// snf Result Code Constants | // snf Result Code Constants | ||||
TokenMatrix* MyTokenMatrix; // We combine the current token matrix | TokenMatrix* MyTokenMatrix; // We combine the current token matrix | ||||
snfCFGData* MyCFGData; // and the current cfg data for each scan. | snfCFGData* MyCFGData; // and the current cfg data for each scan. | ||||
set<int> RulePanics; // Set of known rule panic IDs. | |||||
std::set<int> RulePanics; // Set of known rule panic IDs. | |||||
public: | public: | ||||
snfCFGPacket(snf_RulebaseHandler* R); // Constructor grab()s the Rulebase. | snfCFGPacket(snf_RulebaseHandler* R); // Constructor grab()s the Rulebase. | ||||
bool isRulePanic(int R); // Test for a rule panic. | bool isRulePanic(int R); // Test for a rule panic. | ||||
}; | }; | ||||
class ScriptCaller : private Thread { // Calls system() in separate thread. | |||||
class ScriptCaller : private cd::Thread { // Calls system() in separate thread. | |||||
private: | private: | ||||
Mutex MyMutex; // Protects internal data. | |||||
string SystemCallText; // Text to send to system(). | |||||
Timeout GuardTimer; // Guard time between triggers. | |||||
cd::Mutex MyMutex; // Protects internal data. | |||||
std::string SystemCallText; // Text to send to system(). | |||||
cd::Timeout GuardTimer; // Guard time between triggers. | |||||
volatile bool GoFlag; // Go flag true when triggered. | volatile bool GoFlag; // Go flag true when triggered. | ||||
volatile bool DieFlag; // Die flag when it's time to leave. | volatile bool DieFlag; // Die flag when it's time to leave. | ||||
string ScriptToRun(); // Safely grab the script. | |||||
std::string ScriptToRun(); // Safely grab the script. | |||||
bool hasGuardExpired(); // True if guard time has expired. | bool hasGuardExpired(); // True if guard time has expired. | ||||
void myTask(); // Thread task overload. | void myTask(); // Thread task overload. | ||||
volatile int myLastResult; // Last result of system() call. | volatile int myLastResult; // Last result of system() call. | ||||
public: | public: | ||||
ScriptCaller(string Name); // Constructor. | |||||
ScriptCaller(std::string Name); // Constructor. | |||||
~ScriptCaller(); // Destructor. | ~ScriptCaller(); // Destructor. | ||||
void SystemCall(string S); // Set system call text. | |||||
void SystemCall(std::string S); // Set system call text. | |||||
void GuardTime(int T); // Change guard time. | void GuardTime(int T); // Change guard time. | ||||
void trigger(); // Trigger if possible. | void trigger(); // Trigger if possible. | ||||
int LastResult(); // Return myLastResult. | int LastResult(); // Return myLastResult. | ||||
const static ThreadType Type; // The thread's type. | |||||
const static cd::ThreadType Type; // The thread's type. | |||||
const static ThreadState CallingSystem; // State when in system() call. | |||||
const static ThreadState PendingGuardTime; // State when waiting for guard time. | |||||
const static ThreadState StandingBy; // State when waiting around. | |||||
const static ThreadState Disabled; // State when unable to run. | |||||
const static cd::ThreadState CallingSystem; // State when in system() call. | |||||
const static cd::ThreadState PendingGuardTime; // State when waiting for guard time. | |||||
const static cd::ThreadState StandingBy; // State when waiting around. | |||||
const static cd::ThreadState Disabled; // State when unable to run. | |||||
}; | }; | ||||
class snf_Reloader : private Thread { // Rulebase maintenance thread. | |||||
class snf_Reloader : private cd::Thread { // Rulebase maintenance thread. | |||||
private: | private: | ||||
snf_RulebaseHandler& MyRulebase; // We know our rulebase. | snf_RulebaseHandler& MyRulebase; // We know our rulebase. | ||||
bool TimeToStop; // We know if it's time to stop. | bool TimeToStop; // We know if it's time to stop. | ||||
string RulebaseFileCheckName; // We keep track of these files. | |||||
string ConfigFileCheckName; | |||||
string IgnoreListCheckFileName; | |||||
std::string RulebaseFileCheckName; // We keep track of these files. | |||||
std::string ConfigFileCheckName; | |||||
std::string IgnoreListCheckFileName; | |||||
time_t RulebaseFileTimestamp; // We watch their timestamps. | time_t RulebaseFileTimestamp; // We watch their timestamps. | ||||
time_t ConfigurationTimestamp; | time_t ConfigurationTimestamp; | ||||
time_t IgnoreListTimestamp; | time_t IgnoreListTimestamp; | ||||
snf_Reloader(snf_RulebaseHandler& R); // Setup takes some work. | snf_Reloader(snf_RulebaseHandler& R); // Setup takes some work. | ||||
~snf_Reloader(); // Tear down takes some work. | ~snf_Reloader(); // Tear down takes some work. | ||||
const static ThreadType Type; // The thread's type. | |||||
const static cd::ThreadType Type; // The thread's type. | |||||
}; | }; | ||||
private: | private: | ||||
Mutex MyMutex; // This handler's mutex. | |||||
cd::Mutex MyMutex; // This handler's mutex. | |||||
snf_Reloader* MyReloader; // Reloader engine (when in use). | snf_Reloader* MyReloader; // Reloader engine (when in use). | ||||
int volatile ReferenceCount; // Associated scanners count. | int volatile ReferenceCount; // Associated scanners count. | ||||
snfCFGData* volatile Configuration; // Configuration for this handler. | snfCFGData* volatile Configuration; // Configuration for this handler. | ||||
TokenMatrix* volatile Rulebase; // Rulebase for this handler. | |||||
int volatile CurrentCount; // Active current scanners count. | |||||
TokenMatrix* volatile Rulebase; // Rulebase for this handler. | |||||
int volatile CurrentCount; // Active current scanners count. | |||||
TokenMatrix* volatile OldRulebase; // Retiring rulebase holder. | |||||
int volatile RetiringCount; // Active retiring scanners count. | |||||
TokenMatrix* volatile OldRulebase; // Retiring rulebase holder. | |||||
int volatile RetiringCount; // Active retiring scanners count. | |||||
bool volatile RefreshInProgress; // Flag for locking the refresh process. | |||||
bool volatile RefreshInProgress; // Flag for locking the refresh process. | |||||
int volatile MyGeneration; // Generation (reload) number. | |||||
int volatile MyGeneration; // Generation (reload) number. | |||||
void _snf_LoadNewRulebase(); // Internal function to load new rulebase. | |||||
void _snf_LoadNewRulebase(); // Internal function to load new rulebase. | |||||
Mutex XCIServerCommandMutex; // XCI Server Command Serializer. | |||||
cd::Mutex XCIServerCommandMutex; // XCI Server Command Serializer. | |||||
snfXCIServerCommandHandler* myXCIServerCommandHandler; // ptr to Installed Srv Cmd Handler. | snfXCIServerCommandHandler* myXCIServerCommandHandler; // ptr to Installed Srv Cmd Handler. | ||||
void grab(snfCFGPacket& CP); // Activate this Rulebase for a scan. | void grab(snfCFGPacket& CP); // Activate this Rulebase for a scan. | ||||
void drop(snfCFGPacket& CP); // Deactiveate this Rulebase after it. | |||||
void drop(snfCFGPacket& CP); // Deactiveate this Rulebase after it. | |||||
public: | public: | ||||
class ConfigurationError : public runtime_error { // When the configuration won't load. | |||||
public: ConfigurationError(const string& w):runtime_error(w) {} | |||||
class ConfigurationError : public std::runtime_error { // When the configuration won't load. | |||||
public: ConfigurationError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class FileError : public runtime_error { // Exception: rulebase file won't load. | |||||
public: FileError(const string& w):runtime_error(w) {} | |||||
class FileError : public std::runtime_error { // Exception: rulebase file won't load. | |||||
public: FileError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class AuthenticationError : public runtime_error { // Exception when authentication fails. | |||||
public: AuthenticationError(const string& w):runtime_error(w) {} | |||||
class AuthenticationError : public std::runtime_error { // Exception when authentication fails. | |||||
public: AuthenticationError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class IgnoreListError : public runtime_error { // When the ignore list won't load. | |||||
public: IgnoreListError(const string& w):runtime_error(w) {} | |||||
class IgnoreListError : public std::runtime_error { // When the ignore list won't load. | |||||
public: IgnoreListError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class AllocationError : public runtime_error { // Exception when we can't allocate something. | |||||
public: AllocationError(const string& w):runtime_error(w) {} | |||||
class AllocationError : public std::runtime_error { // Exception when we can't allocate something. | |||||
public: AllocationError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class Busy : public runtime_error { // Exception when there is a collision. | |||||
public: Busy(const string& w):runtime_error(w) {} | |||||
class Busy : public std::runtime_error { // Exception when there is a collision. | |||||
public: Busy(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class Panic : public runtime_error { // Exception when something else happens. | |||||
public: Panic(const string& w):runtime_error(w) {} | |||||
class Panic : public std::runtime_error { // Exception when something else happens. | |||||
public: Panic(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
//// Plugin Components. | //// Plugin Components. | ||||
OldRulebase(NULL), | OldRulebase(NULL), | ||||
RetiringCount(0), | RetiringCount(0), | ||||
RefreshInProgress(false), | RefreshInProgress(false), | ||||
MyGeneration(0), | |||||
MyGeneration(0), | |||||
myXCIServerCommandHandler(0){ | myXCIServerCommandHandler(0){ | ||||
MyNETmgr.linkLOGmgr(MyLOGmgr); // Link the NET manager to the LOGmgr. | MyNETmgr.linkLOGmgr(MyLOGmgr); // Link the NET manager to the LOGmgr. | ||||
MyNETmgr.linkGBUdbmgr(MyGBUdbmgr); // Link the NET manager to the GBUdbmgr. | MyNETmgr.linkGBUdbmgr(MyGBUdbmgr); // Link the NET manager to the GBUdbmgr. | ||||
int Generation(); // Returns the generation number. | int Generation(); // Returns the generation number. | ||||
void addRulePanic(int RuleID); // Synchronously add a RulePanic. | |||||
void addRulePanic(int RuleID); // Synchronously add a RulePanic. | |||||
bool testXHDRInjectOn(); // Safely look ahead at XHDRInjectOn. | bool testXHDRInjectOn(); // Safely look ahead at XHDRInjectOn. | ||||
IPTestRecord& performIPTest(IPTestRecord& I); // Perform an IP test. | IPTestRecord& performIPTest(IPTestRecord& I); // Perform an IP test. | ||||
void logThisIPTest(IPTestRecord& I, string Action); // Log an IP test result & action. | |||||
void logThisIPTest(IPTestRecord& I, std::string Action); // Log an IP test result & action. | |||||
void logThisError(string ContextName, int Code, string Text); // Log an error message. | |||||
void logThisInfo(string ContextName, int Code, string Text); // Log an informational message. | |||||
string PlatformVersion(string NewPlatformVersion); // Set platform version info. | |||||
string PlatformVersion(); // Get platform version info. | |||||
string PlatformConfiguration(); // Get platform configuration. | |||||
string EngineVersion(); // Get engine version info. | |||||
void logThisError(std::string ContextName, int Code, std::string Text); // Log an error message. | |||||
void logThisInfo(std::string ContextName, int Code, std::string Text); // Log an informational message. | |||||
std::string PlatformVersion(std::string NewPlatformVersion); // Set platform version info. | |||||
std::string PlatformVersion(); // Get platform version info. | |||||
std::string PlatformConfiguration(); // Get platform configuration. | |||||
std::string EngineVersion(); // Get engine version info. | |||||
void XCIServerCommandHandler(snfXCIServerCommandHandler& XCH); // Registers a new XCI Srvr Cmd handler. | void XCIServerCommandHandler(snfXCIServerCommandHandler& XCH); // Registers a new XCI Srvr Cmd handler. | ||||
string processXCIServerCommandRequest(snf_xci& X); // Handle a parsed XCI Srvr Cmd request. | |||||
std::string processXCIServerCommandRequest(snf_xci& X); // Handle a parsed XCI Srvr Cmd request. | |||||
}; | }; | ||||
// IPTestEngine w/ GBUdb interface. | // IPTestEngine w/ GBUdb interface. | ||||
void setCFGData(snfCFGData& C); // (Re)Set the config data to use. | void setCFGData(snfCFGData& C); // (Re)Set the config data to use. | ||||
void setLOGmgr(snfLOGmgr& L); // Setup the LOGmgr to use. | void setLOGmgr(snfLOGmgr& L); // Setup the LOGmgr to use. | ||||
string& test(string& input, string& output); // Our obligatory test function. | |||||
std::string& test(std::string& input, std::string& output); // Our obligatory test function. | |||||
}; | |||||
class snf_SaccadesHandler { | |||||
private: | |||||
cd::Mutex MyMutex; | |||||
saccades_engine MyEngine; | |||||
void lockAndLearn(std::vector<saccade>& Matches) { | |||||
cd::ScopeMutex SafetyFirst(MyMutex); | |||||
MyEngine.learn(Matches); | |||||
} | |||||
std::vector<saccade> grabSaccades() { | |||||
cd::ScopeMutex SafetyFirst(MyMutex); | |||||
return MyEngine.recall(); | |||||
} | |||||
int TimeToPeekCounter; | |||||
static const int TimeToPeekReset = 32; | |||||
public: | |||||
static const int AlwaysScanLength = 2048; | |||||
snf_SaccadesHandler() : | |||||
MyEngine(128), | |||||
TimeToPeekCounter(0) {} | |||||
void applySaccades(EvaluationMatrix* Scanner, std::vector<unsigned char>& Data); | |||||
void learnMatches(MatchRecord* Matches); | |||||
}; | |||||
// How to spot strangers in the IP reputations. | |||||
class snf_IPStrangerList { | |||||
private: | |||||
cd::Mutex myMutex; | |||||
std::set<cd::IP4Address> listA; | |||||
std::set<cd::IP4Address> listB; | |||||
bool usingANotB; | |||||
cd::Timeout listExpiration; | |||||
std::set<cd::IP4Address>& myActiveList() { | |||||
if(usingANotB) return listA; | |||||
else return listB; | |||||
} | |||||
void swapOutOldLists() { | |||||
if(listExpiration.isExpired()) { | |||||
usingANotB = !usingANotB; | |||||
myActiveList().clear(); | |||||
listExpiration.restart(); | |||||
} | |||||
} | |||||
std::set<cd::IP4Address>& myCurrentList() { | |||||
swapOutOldLists(); | |||||
return myActiveList(); | |||||
} | |||||
public: | |||||
static const int TwoHours = (2 * (60 * (60 * 1000))); | |||||
snf_IPStrangerList() : usingANotB(true), listExpiration(TwoHours) {} | |||||
bool isStranger(cd::IP4Address a) { | |||||
cd::ScopeMutex JustMe(myMutex); | |||||
swapOutOldLists(); | |||||
bool foundStranger = (0 < listA.count(a)) || (0 < listB.count(a)); | |||||
return foundStranger; | |||||
} | |||||
void addStranger(cd::IP4Address a) { | |||||
cd::ScopeMutex JustMe(myMutex); | |||||
myCurrentList().insert(a); | |||||
} | |||||
}; | }; | ||||
class snf_SaccadesHandler { | |||||
private: | |||||
Mutex MyMutex; | |||||
saccades_engine MyEngine; | |||||
void lockAndLearn(vector<saccade>& Matches) { | |||||
ScopeMutex SafetyFirst(MyMutex); | |||||
MyEngine.learn(Matches); | |||||
} | |||||
vector<saccade> grabSaccades() { | |||||
ScopeMutex SafetyFirst(MyMutex); | |||||
return MyEngine.recall(); | |||||
} | |||||
int TimeToPeekCounter; | |||||
static const int TimeToPeekReset = 32; | |||||
public: | |||||
static const int AlwaysScanLength = 2048; | |||||
snf_SaccadesHandler() : | |||||
MyEngine(128), | |||||
TimeToPeekCounter(0) {} | |||||
void applySaccades(EvaluationMatrix* Scanner, vector<unsigned char>& Data); | |||||
void learnMatches(MatchRecord* Matches); | |||||
}; | |||||
// How to spot strangers in the IP reputations. | |||||
class snf_IPStrangerList { | |||||
private: | |||||
Mutex myMutex; | |||||
set<IP4Address> listA; | |||||
set<IP4Address> listB; | |||||
bool usingANotB; | |||||
Timeout listExpiration; | |||||
set<IP4Address>& myActiveList() { | |||||
if(usingANotB) return listA; | |||||
else return listB; | |||||
} | |||||
void swapOutOldLists() { | |||||
if(listExpiration.isExpired()) { | |||||
usingANotB = !usingANotB; | |||||
myActiveList().clear(); | |||||
listExpiration.restart(); | |||||
} | |||||
} | |||||
set<IP4Address>& myCurrentList() { | |||||
swapOutOldLists(); | |||||
return myActiveList(); | |||||
} | |||||
public: | |||||
static const int TwoHours = (2 * (60 * (60 * 1000))); | |||||
snf_IPStrangerList() : usingANotB(true), listExpiration(TwoHours) {} | |||||
bool isStranger(IP4Address a) { | |||||
ScopeMutex JustMe(myMutex); | |||||
swapOutOldLists(); | |||||
bool foundStranger = (0 < listA.count(a)) || (0 < listB.count(a)); | |||||
return foundStranger; | |||||
} | |||||
void addStranger(IP4Address a) { | |||||
ScopeMutex JustMe(myMutex); | |||||
myCurrentList().insert(a); | |||||
} | |||||
}; | |||||
// Here's where we pull it all together. | // Here's where we pull it all together. | ||||
class snf_EngineHandler { | class snf_EngineHandler { | ||||
private: | private: | ||||
Mutex MyMutex; // This handler's mutex. | |||||
Mutex FileScan; // File scan entry mutex. | |||||
cd::Mutex MyMutex; // This handler's mutex. | |||||
cd::Mutex FileScan; // File scan entry mutex. | |||||
EvaluationMatrix* volatile CurrentMatrix; // Matrix for the latest scan. | |||||
snf_RulebaseHandler* volatile MyRulebase; // My RulebaseHandler. | |||||
EvaluationMatrix* volatile CurrentMatrix; // Matrix for the latest scan. | |||||
snf_RulebaseHandler* volatile MyRulebase; // My RulebaseHandler. | |||||
snfScanData MyScanData; // Local snfScanData record. | |||||
snf_IPTestEngine MyIPTestEngine; // Local IP Test Engine. | |||||
snfScanData MyScanData; // Local snfScanData record. | |||||
snf_IPTestEngine MyIPTestEngine; // Local IP Test Engine. | |||||
int ResultsCount; // Count of Match Records for getResults | |||||
int ResultsRemaining; // Count of Match Records ahead of cursor. | |||||
MatchRecord* FinalResult; // Final (winning) result of the scan. | |||||
MatchRecord* ResultCursor; // Current Match Record for getResults. | |||||
int ResultsCount; // Count of Match Records for getResults | |||||
int ResultsRemaining; // Count of Match Records ahead of cursor. | |||||
MatchRecord* FinalResult; // Final (winning) result of the scan. | |||||
MatchRecord* ResultCursor; // Current Match Record for getResults. | |||||
string extractMessageID(const unsigned char* Msg, const int Len); // Get log safe Message-ID or substitute. | |||||
std::string extractMessageID(const unsigned char* Msg, const int Len); // Get log safe Message-ID or substitute. | |||||
public: | public: | ||||
class FileError : public runtime_error { // Exception when a file won't open. | |||||
public: FileError(const string& w):runtime_error(w) {} | |||||
class FileError : public std::runtime_error { // Exception when a file won't open. | |||||
public: FileError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class XHDRError : public runtime_error { // Exception when XHDR Inject/File fails. | |||||
public: XHDRError(const string& w):runtime_error(w) {} | |||||
class XHDRError : public std::runtime_error { // Exception when XHDR Inject/File fails. | |||||
public: XHDRError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class BadMatrix : public runtime_error { // Exception out of bounds of matrix. | |||||
public: BadMatrix(const string& w):runtime_error(w) {} | |||||
class BadMatrix : public std::runtime_error { // Exception out of bounds of matrix. | |||||
public: BadMatrix(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class MaxEvals : public runtime_error { // Exception too many evaluators. | |||||
public: MaxEvals(const string& w):runtime_error(w) {} | |||||
class MaxEvals : public std::runtime_error { // Exception too many evaluators. | |||||
public: MaxEvals(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class AllocationError : public runtime_error { // Exception when we can't allocate something. | |||||
public: AllocationError(const string& w):runtime_error(w) {} | |||||
class AllocationError : public std::runtime_error { // Exception when we can't allocate something. | |||||
public: AllocationError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class Busy : public runtime_error { // Exception when there is a collision. | |||||
public: Busy(const string& w):runtime_error(w) {} | |||||
class Busy : public std::runtime_error { // Exception when there is a collision. | |||||
public: Busy(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class Panic : public runtime_error { // Exception when something else happens. | |||||
public: Panic(const string& w):runtime_error(w) {} | |||||
class Panic : public std::runtime_error { // Exception when something else happens. | |||||
public: Panic(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
snf_EngineHandler(): // Initialization is simple. | snf_EngineHandler(): // Initialization is simple. | ||||
void close(); // Close down the engine. | void close(); // Close down the engine. | ||||
int scanMessageFile( // Scan this message file. | int scanMessageFile( // Scan this message file. | ||||
const string MessageFilePath, // -- this is the file (and id) | |||||
const std::string MessageFilePath, // -- this is the file (and id) | |||||
const int MessageSetupTime = 0, // -- setup time already used. | const int MessageSetupTime = 0, // -- setup time already used. | ||||
const IP4Address MessageSource = 0UL // -- message source IP (for injection). | |||||
const cd::IP4Address MessageSource = 0UL // -- message source IP (for injection). | |||||
); | ); | ||||
int scanMessage( // Scan this message. | |||||
const unsigned char* MessageBuffer, // -- this is the message buffer. | |||||
const int MessageLength, // -- this is the length of the buffer. | |||||
const string MessageName = "", // -- this is the message identifier. | |||||
int scanMessage( // Scan this message. | |||||
const unsigned char* MessageBuffer, // -- this is the message buffer. | |||||
const int MessageLength, // -- this is the length of the buffer. | |||||
const std::string MessageName = "", // -- this is the message identifier. | |||||
const int MessageSetupTime = 0, // -- setup time used (for logging). | const int MessageSetupTime = 0, // -- setup time used (for logging). | ||||
const IP4Address MessageSource = 0UL // -- message source IP (for injection). | |||||
const cd::IP4Address MessageSource = 0UL // -- message source IP (for injection). | |||||
); | ); | ||||
int getResults(snf_match* MatchBuffer); // Get the next match buffer. | |||||
int getDepth(); // Get the scan depth. | |||||
int getResults(snf_match* MatchBuffer); // Get the next match buffer. | |||||
int getDepth(); // Get the scan depth. | |||||
const string getClassicLog(); // Get classic log entries for last scan. | |||||
const string getXMLLog(); // Get XML log entries or last scan. | |||||
const string getXHDRs(); // Get XHDRs for last scan. | |||||
const std::string getClassicLog(); // Get classic log entries for last scan. | |||||
const std::string getXMLLog(); // Get XML log entries or last scan. | |||||
const std::string getXHDRs(); // Get XHDRs for last scan. | |||||
}; | }; | ||||
// Here's the class that pulls it all together. | // Here's the class that pulls it all together. | ||||
private: | private: | ||||
Mutex RulebaseScan; // This handler's mutex. | |||||
cd::Mutex RulebaseScan; // This handler's mutex. | |||||
int RulebaseCursor; // Next Rulebase to search. | int RulebaseCursor; // Next Rulebase to search. | ||||
snf_RulebaseHandler RulebaseHandlers[snf_MAX_RULEBASES]; // Array of Rulebase Handlers | snf_RulebaseHandler RulebaseHandlers[snf_MAX_RULEBASES]; // Array of Rulebase Handlers | ||||
int RoundRulebaseCursor(); // Gets round robin Rulebase handle candidates. | int RoundRulebaseCursor(); // Gets round robin Rulebase handle candidates. | ||||
Mutex EngineScan; // Serializes searching the Engine list. | |||||
cd::Mutex EngineScan; // Serializes searching the Engine list. | |||||
int EngineCursor; // Next Engine to search. | int EngineCursor; // Next Engine to search. | ||||
snf_EngineHandler EngineHandlers[snf_MAX_SCANNERS]; // Array of Engine Handlers | snf_EngineHandler EngineHandlers[snf_MAX_SCANNERS]; // Array of Engine Handlers | ||||
public: | public: | ||||
class TooMany : public runtime_error { // Exception when no more handle slots. | |||||
public: TooMany(const string& w):runtime_error(w) {} | |||||
class TooMany : public std::runtime_error { // Exception when no more handle slots. | |||||
public: TooMany(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class FileError : public runtime_error { // Exception when a file won't open. | |||||
public: FileError(const string& w):runtime_error(w) {} | |||||
class FileError : public std::runtime_error { // Exception when a file won't open. | |||||
public: FileError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class AuthenticationError : public runtime_error { // Exception when authentication fails. | |||||
public: AuthenticationError(const string& w):runtime_error(w) {} | |||||
class AuthenticationError : public std::runtime_error { // Exception when authentication fails. | |||||
public: AuthenticationError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class AllocationError : public runtime_error { // Exception when we can't allocate something. | |||||
public: AllocationError(const string& w):runtime_error(w) {} | |||||
class AllocationError : public std::runtime_error { // Exception when we can't allocate something. | |||||
public: AllocationError(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class Busy : public runtime_error { // Exception when there is a collision. | |||||
public: Busy(const string& w):runtime_error(w) {} | |||||
class Busy : public std::runtime_error { // Exception when there is a collision. | |||||
public: Busy(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
class Panic : public runtime_error { // Exception when something else happens. | |||||
public: Panic(const string& w):runtime_error(w) {} | |||||
class Panic : public std::runtime_error { // Exception when something else happens. | |||||
public: Panic(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
snf_MultiEngineHandler(): | snf_MultiEngineHandler(): | ||||
int getDepth(int EngineHandle); | int getDepth(int EngineHandle); | ||||
}; | }; | ||||
#endif |
const unsigned char* MessageBuffer, // This is the message itself | const unsigned char* MessageBuffer, // This is the message itself | ||||
int MessageLength // and it is this size. | int MessageLength // and it is this size. | ||||
) { | ) { | ||||
string TimeStamp; (*myLOGmgr).Timestamp(TimeStamp); // Grab a timestamp. | |||||
ostringstream XML; // Make formatting easier with this. | |||||
std::string TimeStamp; (*myLOGmgr).Timestamp(TimeStamp); // Grab a timestamp. | |||||
std::ostringstream XML; // Make formatting easier with this. | |||||
//-- <sample...> | //-- <sample...> | ||||
XML << "<sample node=\'" << CFGData.node_licenseid << "\' " | XML << "<sample node=\'" << CFGData.node_licenseid << "\' " | ||||
<< "time=\'" << TimeStamp << "\' " | << "time=\'" << TimeStamp << "\' " | ||||
<< "result=\'" << ScanData.CompositeFinalResult << "\'>" << endl; | |||||
<< "result=\'" << ScanData.CompositeFinalResult << "\'>" << std::endl; | |||||
//-- <ip...> | //-- <ip...> | ||||
XML << "<ip range=\'"; | XML << "<ip range=\'"; | ||||
string IPRange; | |||||
std::string IPRange; | |||||
switch(ScanData.SourceIPRange()) { | switch(ScanData.SourceIPRange()) { | ||||
case Unknown: { IPRange = "Unknown"; break; } // Unknown - not defined. | case Unknown: { IPRange = "Unknown"; break; } // Unknown - not defined. | ||||
case White: { IPRange = "White"; break; } // This is a good guy. | case White: { IPRange = "White"; break; } // This is a good guy. | ||||
XML << IPRange << "\' ip=\'" << (std::string) cd::IP4Address(IP.getAddress()) << "\' t=\'"; | XML << IPRange << "\' ip=\'" << (std::string) cd::IP4Address(IP.getAddress()) << "\' t=\'"; | ||||
string IPType; | |||||
std::string IPType; | |||||
switch(ScanData.SourceIPRecord().GBUdbData.Flag()) { | switch(ScanData.SourceIPRecord().GBUdbData.Flag()) { | ||||
case Good: { IPType = "Good"; break; } | case Good: { IPType = "Good"; break; } | ||||
case Bad: { IPType = "Bad"; break; } | case Bad: { IPType = "Bad"; break; } | ||||
XML << IPType << "\' b=\'" << ScanData.SourceIPRecord().GBUdbData.Bad() | XML << IPType << "\' b=\'" << ScanData.SourceIPRecord().GBUdbData.Bad() | ||||
<< "\' g=\'" << ScanData.SourceIPRecord().GBUdbData.Good() | << "\' g=\'" << ScanData.SourceIPRecord().GBUdbData.Good() | ||||
<< "\'/>" << endl; | |||||
<< "\'/>" << std::endl; | |||||
//-- <match...> as many as needed | //-- <match...> as many as needed | ||||
if(0 < ScanData.MatchRecords.size()) { // If we have match records - emit them. | if(0 < ScanData.MatchRecords.size()) { // If we have match records - emit them. | ||||
list<snf_match>::iterator iM; // Grab an iterator. | |||||
std::list<snf_match>::iterator iM; // Grab an iterator. | |||||
for( // Emit each snf_match entry. | for( // Emit each snf_match entry. | ||||
iM = ScanData.MatchRecords.begin(); | iM = ScanData.MatchRecords.begin(); | ||||
iM != ScanData.MatchRecords.end(); | iM != ScanData.MatchRecords.end(); | ||||
//-- <msg...> | //-- <msg...> | ||||
XML << "<msg size=\'" << ScanData.ScanSize << "'>" << endl; // Starting with the msg element. | |||||
XML << "<msg size=\'" << ScanData.ScanSize << "'>" << std::endl; // Starting with the msg element. | |||||
cd::to_base64 EncodedMessageData( | cd::to_base64 EncodedMessageData( | ||||
reinterpret_cast<const char*>(MessageBuffer), MessageLength); // Encode the message to base64. | reinterpret_cast<const char*>(MessageBuffer), MessageLength); // Encode the message to base64. | ||||
for(int l = 0; l < SampleLineLength && i < MessageLength; l++, i++) { // that are a reasonable length. | for(int l = 0; l < SampleLineLength && i < MessageLength; l++, i++) { // that are a reasonable length. | ||||
XML << EncodedMessageData.at(i); // Emit one character at a time... | XML << EncodedMessageData.at(i); // Emit one character at a time... | ||||
} // At the end of a reasonable | } // At the end of a reasonable | ||||
XML << endl; // length we terminate the line. | |||||
XML << std::endl; // length we terminate the line. | |||||
} | } | ||||
XML << "</msg>" << endl; // End of the <msg> element. | |||||
XML << "</msg>" << std::endl; // End of the <msg> element. | |||||
//-- done with the sample! | //-- done with the sample! | ||||
XML << "</sample>" << endl; | |||||
XML << "</sample>" << std::endl; | |||||
// Last thing we do is post the formatted string to the buffer. | // Last thing we do is post the formatted string to the buffer. | ||||
const unsigned int SampleSafetyLimit = 100000; // 100 Kbyte limit on samples. | const unsigned int SampleSafetyLimit = 100000; // 100 Kbyte limit on samples. | ||||
SamplesBuffer.append(XML.str()); // Append the XML to the buffer. | SamplesBuffer.append(XML.str()); // Append the XML to the buffer. | ||||
} | } | ||||
string snfNETmgr::getSamples() { // Synchronized way to get Samples. | |||||
std::string snfNETmgr::getSamples() { // Synchronized way to get Samples. | |||||
cd::ScopeMutex DoNotDisturb(myMutex); // Lock the mutex to protect our work. | cd::ScopeMutex DoNotDisturb(myMutex); // Lock the mutex to protect our work. | ||||
string SamplesBatch = SamplesBuffer; // Copy the samples to a new string. | |||||
std::string SamplesBatch = SamplesBuffer; // Copy the samples to a new string. | |||||
SamplesBuffer.clear(); // Clear the samples buffer. | SamplesBuffer.clear(); // Clear the samples buffer. | ||||
return SamplesBatch; // Return a batch of Samples. | return SamplesBatch; // Return a batch of Samples. | ||||
} | } | ||||
void snfNETmgr::sendReport(const string& S) { // How to send a status report. | |||||
void snfNETmgr::sendReport(const std::string& S) { // How to send a status report. | |||||
const unsigned int ReportSafetyLimit = 100000; // 100 Kbytes limit on reports. | const unsigned int ReportSafetyLimit = 100000; // 100 Kbytes limit on reports. | ||||
cd::ScopeMutex DoNotDisturb(myMutex); // Lock the mutex for a moment. | cd::ScopeMutex DoNotDisturb(myMutex); // Lock the mutex for a moment. | ||||
if(ReportSafetyLimit < ReportsBuffer.length()) // If the reports buffer is full | if(ReportSafetyLimit < ReportsBuffer.length()) // If the reports buffer is full | ||||
ReportsBuffer.append(S); // Append the report. | ReportsBuffer.append(S); // Append the report. | ||||
} | } | ||||
string snfNETmgr::getReports() { // Synchronized way to get Reports. | |||||
std::string snfNETmgr::getReports() { // Synchronized way to get Reports. | |||||
cd::ScopeMutex DoNotDisturb(myMutex); // Lock the mutex to protect our work. | cd::ScopeMutex DoNotDisturb(myMutex); // Lock the mutex to protect our work. | ||||
string ReportsBatch = ReportsBuffer; // Copy the reports to a new string. | |||||
std::string ReportsBatch = ReportsBuffer; // Copy the reports to a new string. | |||||
ReportsBuffer.clear(); // Clear the reports buffer. | ReportsBuffer.clear(); // Clear the reports buffer. | ||||
return ReportsBatch; // Return a batch of Reports. | return ReportsBatch; // Return a batch of Reports. | ||||
} | } | ||||
cd::RuntimeCheck RulebaseUTCGoodTimestampLength("SNFNetmgr.cpp:RulebaseUTC snprintf(...) == CorrectTimestampLength"); | cd::RuntimeCheck RulebaseUTCGoodTimestampLength("SNFNetmgr.cpp:RulebaseUTC snprintf(...) == CorrectTimestampLength"); | ||||
string& snfNETmgr::RulebaseUTC(string& t) { // Gets local rulebase file UTC. | |||||
std::string& snfNETmgr::RulebaseUTC(std::string& t) { // Gets local rulebase file UTC. | |||||
struct stat RulebaseStat; // First we need a stat buffer. | struct stat RulebaseStat; // First we need a stat buffer. | ||||
if(0 != stat(RulebaseFilePath.c_str(), &RulebaseStat)) { // If we can't get the stat we | if(0 != stat(RulebaseFilePath.c_str(), &RulebaseStat)) { // If we can't get the stat we | ||||
t.append("000000000000"); return t; // will return 000000000000 to | t.append("000000000000"); return t; // will return 000000000000 to | ||||
return t; // and return it to the caller. | return t; // and return it to the caller. | ||||
} | } | ||||
unsigned long snfNETmgr::ResolveHostIPFromName(const string& N) { // Host name resolution tool. | |||||
unsigned long snfNETmgr::ResolveHostIPFromName(const std::string& N) { // Host name resolution tool. | |||||
cd::ScopeMutex OneAtATimePlease(ResolverMutex); // Resolve only one at a time. | cd::ScopeMutex OneAtATimePlease(ResolverMutex); // Resolve only one at a time. | ||||
unsigned long IP = inet_addr(N.c_str()); // See if it's an IP. | unsigned long IP = inet_addr(N.c_str()); // See if it's an IP. | ||||
if (INADDR_NONE == IP) { // If it's not an IP resolve it. | if (INADDR_NONE == IP) { // If it's not an IP resolve it. | ||||
// Sensitivity to this entropy has millisecond resolution. This is a cross- | // Sensitivity to this entropy has millisecond resolution. This is a cross- | ||||
// platform solution that depends only on our own code ;-) | // platform solution that depends only on our own code ;-) | ||||
void snfNETmgr::evolvePad(string Entropy) { // Add entropy and evolve. | |||||
void snfNETmgr::evolvePad(std::string Entropy) { // Add entropy and evolve. | |||||
cd::ScopeMutex OneAtATimePlease(PadMutex); // Protect the one time pad. | cd::ScopeMutex OneAtATimePlease(PadMutex); // Protect the one time pad. | ||||
myLOGmgr->Timestamp(Entropy); // Time matters ;-) | myLOGmgr->Timestamp(Entropy); // Time matters ;-) | ||||
for(unsigned int a = 0; a < Entropy.length(); a++) { // Add the entropy to our generator. | for(unsigned int a = 0; a < Entropy.length(); a++) { // Add the entropy to our generator. | ||||
if(CurrentHandshake.size() != SNFHandshakeSize) { // If we don't have one make one! | if(CurrentHandshake.size() != SNFHandshakeSize) { // If we don't have one make one! | ||||
CurrentHandshake = OneTimePad(SNFHandshakeSize); // Set up a default handshake to use | CurrentHandshake = OneTimePad(SNFHandshakeSize); // Set up a default handshake to use | ||||
try { // if we can't remember the real one. | try { // if we can't remember the real one. | ||||
ifstream HSF(HandshakeFilePath.c_str(), ios::binary); // Open the handshake file. | |||||
std::ifstream HSF(HandshakeFilePath.c_str(), std::ios::binary); // Open the handshake file. | |||||
char* bfr = reinterpret_cast<char*>(&CurrentHandshake[0]); // Manufacture a proper pointer. | char* bfr = reinterpret_cast<char*>(&CurrentHandshake[0]); // Manufacture a proper pointer. | ||||
HSF.read(bfr, SNFHandshakeSize); // Read the data (overwrite the HSB). | HSF.read(bfr, SNFHandshakeSize); // Read the data (overwrite the HSB). | ||||
HSF.close(); // Close the file. | HSF.close(); // Close the file. | ||||
PadBuffer& snfNETmgr::Handshake(PadBuffer& NewHandshake) { // Store a new handshake. | PadBuffer& snfNETmgr::Handshake(PadBuffer& NewHandshake) { // Store a new handshake. | ||||
CurrentHandshake = NewHandshake; // Grab the new handshake | CurrentHandshake = NewHandshake; // Grab the new handshake | ||||
try { // then try to store it... | try { // then try to store it... | ||||
ofstream HSF(HandshakeFilePath.c_str(), ios::binary | ios::trunc); // Open the handshake file. | |||||
std::ofstream HSF( | |||||
HandshakeFilePath.c_str(), std::ios::binary | std::ios::trunc); // Open the handshake file. | |||||
char* bfr = reinterpret_cast<char*>(&NewHandshake[0]); // Access the raw buffer. | char* bfr = reinterpret_cast<char*>(&NewHandshake[0]); // Access the raw buffer. | ||||
HSF.write(bfr, NewHandshake.size()); // Replace the old handshake | HSF.write(bfr, NewHandshake.size()); // Replace the old handshake | ||||
HSF.close(); // close the file. | HSF.close(); // close the file. | ||||
return NewHandshake; // Return what we were given. | return NewHandshake; // Return what we were given. | ||||
} | } | ||||
void snfNETmgr::postUpdateTrigger(string& updateUTC) { // Post an update trigger file. | |||||
void snfNETmgr::postUpdateTrigger(std::string& updateUTC) { // Post an update trigger file. | |||||
try { // Safely post an update trigger. | try { // Safely post an update trigger. | ||||
ofstream HSF(UpdateReadyFilePath.c_str(), ios::binary | ios::trunc); // Open/create the trigger file. | |||||
std::ofstream HSF( | |||||
UpdateReadyFilePath.c_str(), std::ios::binary | std::ios::trunc); // Open/create the trigger file. | |||||
char* bfr = reinterpret_cast<char*>(&updateUTC[0]); // Access the raw UTC buffer. | char* bfr = reinterpret_cast<char*>(&updateUTC[0]); // Access the raw UTC buffer. | ||||
HSF.write(bfr, updateUTC.size()); // Write the update timestamp. | HSF.write(bfr, updateUTC.size()); // Write the update timestamp. | ||||
HSF.close(); // close the file. | HSF.close(); // close the file. | ||||
// Utility to read a line from a non-blocking TCPHost & check the timeout. | // Utility to read a line from a non-blocking TCPHost & check the timeout. | ||||
const unsigned int MaxReadLineLength = 1024; // How long a line can be. | const unsigned int MaxReadLineLength = 1024; // How long a line can be. | ||||
string readLineTimeout(cd::TCPHost& S, cd::Timeout& T) { // Read a line from S until T. | |||||
std::string readLineTimeout(cd::TCPHost& S, cd::Timeout& T) { // Read a line from S until T. | |||||
cd::Sleeper WaitForMoreData(50); // How long to wait when no data. | cd::Sleeper WaitForMoreData(50); // How long to wait when no data. | ||||
string LineBuffer = ""; // Buffer for the line. | |||||
std::string LineBuffer = ""; // Buffer for the line. | |||||
while( // Keep going as long as: | while( // Keep going as long as: | ||||
false == T.isExpired() && // our timeout has not expired AND | false == T.isExpired() && // our timeout has not expired AND | ||||
MaxReadLineLength > LineBuffer.length() // we haven't reached our limit. | MaxReadLineLength > LineBuffer.length() // we haven't reached our limit. | ||||
// Keep these things in scope. This is how we roll. | // Keep these things in scope. This is how we roll. | ||||
string HostName; | |||||
std::string HostName; | |||||
int HostPort; | int HostPort; | ||||
string Secret; | |||||
string Node; | |||||
std::string Secret; | |||||
std::string Node; | |||||
// Grab our configuration data (marchng orders). | // Grab our configuration data (marchng orders). | ||||
cd::PollTimer WaitForOpen(10, 340); // Expand 10ms to 340ms between tries. | cd::PollTimer WaitForOpen(10, 340); // Expand 10ms to 340ms between tries. | ||||
while(!SessionDog.isExpired()) { // Wait & Watch for a good connection. | while(!SessionDog.isExpired()) { // Wait & Watch for a good connection. | ||||
try { SyncServer.open(); } // Try opening the connection. | try { SyncServer.open(); } // Try opening the connection. | ||||
catch(exception& e) { // If we get an exception then | |||||
string ConnectFailMessage = "snfNETmgr::sync().open() "; // format a useful message about | |||||
catch(const std::exception& e) { // If we get an exception then | |||||
std::string ConnectFailMessage = "snfNETmgr::sync().open() "; // format a useful message about | |||||
ConnectFailMessage.append(e.what()); // the error and then throw | ConnectFailMessage.append(e.what()); // the error and then throw | ||||
throw SyncFailed(ConnectFailMessage); // a SyncFailed exception. | throw SyncFailed(ConnectFailMessage); // a SyncFailed exception. | ||||
} | } | ||||
// Start communicating. | // Start communicating. | ||||
string LineBuffer = ""; // Input Line Buffer. | |||||
std::string LineBuffer = ""; // Input Line Buffer. | |||||
// Read challenge | // Read challenge | ||||
//--- Encode our response as base64 and send it. | //--- Encode our response as base64 and send it. | ||||
cd::to_base64 ResponseTxt(ResponseBin); // Encode the cyphertext as base64. | cd::to_base64 ResponseTxt(ResponseBin); // Encode the cyphertext as base64. | ||||
string ResponseTxtString; // Create a handy string and place | |||||
std::string ResponseTxtString; // Create a handy string and place | |||||
ResponseTxtString.assign(ResponseTxt.begin(), ResponseTxt.end()); // the base 64 text into it. | ResponseTxtString.assign(ResponseTxt.begin(), ResponseTxt.end()); // the base 64 text into it. | ||||
string ResponseMsg; // Build an appropriate response | |||||
std::string ResponseMsg; // Build an appropriate response | |||||
ResponseMsg.append("<snf><sync><response nodeid=\'"); // identifying this node | ResponseMsg.append("<snf><sync><response nodeid=\'"); // identifying this node | ||||
ResponseMsg.append(Node); // with the license id | ResponseMsg.append(Node); // with the license id | ||||
ResponseMsg.append("\' text=\'"); // and providing an appropriately | ResponseMsg.append("\' text=\'"); // and providing an appropriately | ||||
CurrentThreadState(SYNC_Send_GBUdb_Alerts); | CurrentThreadState(SYNC_Send_GBUdb_Alerts); | ||||
string ClientReport; | |||||
std::string ClientReport; | |||||
ClientReport.append("<snf><sync><client>\n"); | ClientReport.append("<snf><sync><client>\n"); | ||||
sendDataTimeout(SyncServer, SessionDog, ClientReport); | sendDataTimeout(SyncServer, SessionDog, ClientReport); | ||||
ClientReport = ""; | ClientReport = ""; | ||||
// Insert our GBUdb Alerts. | // Insert our GBUdb Alerts. | ||||
list<GBUdbAlert> Alerts; // Make a list of GBUdb Alerts. | |||||
std::list<GBUdbAlert> Alerts; // Make a list of GBUdb Alerts. | |||||
myGBUdbmgr->GetAlertsForSync(Alerts); // Get them from our GBUdb. | myGBUdbmgr->GetAlertsForSync(Alerts); // Get them from our GBUdb. | ||||
list<GBUdbAlert>::iterator iA; | |||||
std::list<GBUdbAlert>::iterator iA; | |||||
for(iA = Alerts.begin(); iA != Alerts.end(); iA++) { // Convert each alert in our list | for(iA = Alerts.begin(); iA != Alerts.end(); iA++) { // Convert each alert in our list | ||||
ClientReport.append((*iA).toXML()); // into XML, follow it up | ClientReport.append((*iA).toXML()); // into XML, follow it up | ||||
ClientReport.append("\n"); // with a new line, and send it | ClientReport.append("\n"); // with a new line, and send it | ||||
**/ | **/ | ||||
if(0 < ReportsBuffer.length()) { // If we have reports to send | if(0 < ReportsBuffer.length()) { // If we have reports to send | ||||
string DataToSend = getReports(); // get (and clear) the reports and | |||||
std::string DataToSend = getReports(); // get (and clear) the reports and | |||||
sendDataTimeout(SyncServer, SessionDog, DataToSend); // send them (mindful of timeout). | sendDataTimeout(SyncServer, SessionDog, DataToSend); // send them (mindful of timeout). | ||||
} | } | ||||
if(SessionDog.isExpired()) throw SyncFailed("Out Of Time"); // Check our session time. | if(SessionDog.isExpired()) throw SyncFailed("Out Of Time"); // Check our session time. | ||||
***/ | ***/ | ||||
if(0 < SamplesBuffer.length()) { // If we have samples to send | if(0 < SamplesBuffer.length()) { // If we have samples to send | ||||
string DataToSend = getSamples(); // get (and clear) the samples and | |||||
std::string DataToSend = getSamples(); // get (and clear) the samples and | |||||
sendDataTimeout(SyncServer, SessionDog, DataToSend); // send them (mindful of timeout). | sendDataTimeout(SyncServer, SessionDog, DataToSend); // send them (mindful of timeout). | ||||
} | } | ||||
if(SessionDog.isExpired()) throw SyncFailed("Out Of Time"); // Check our session time. | if(SessionDog.isExpired()) throw SyncFailed("Out Of Time"); // Check our session time. | ||||
CurrentThreadState(SYNC_Read_Server_Response); | CurrentThreadState(SYNC_Read_Server_Response); | ||||
string ServerResponse; | |||||
string ResponseLine; | |||||
while(string::npos == ResponseLine.find("</snf>\n")) { // Until we find the ending... | |||||
std::string ServerResponse; | |||||
std::string ResponseLine; | |||||
while(std::string::npos == ResponseLine.find("</snf>\n")) { // Until we find the ending... | |||||
ResponseLine = readLineTimeout(SyncServer, SessionDog); // Read a line. | ResponseLine = readLineTimeout(SyncServer, SessionDog); // Read a line. | ||||
if(0 >= ResponseLine.length()) { // If we get an empty line | if(0 >= ResponseLine.length()) { // If we get an empty line | ||||
throw SyncFailed("sync() server response empty line"); // then it's an error. | throw SyncFailed("sync() server response empty line"); // then it's an error. | ||||
(*myLOGmgr).RecordSyncEvent(); // Finished that -- so log the event. | (*myLOGmgr).RecordSyncEvent(); // Finished that -- so log the event. | ||||
} | } | ||||
catch (exception& e) { // SYNC Failed and we know more. | |||||
catch (const std::exception& e) { // SYNC Failed and we know more. | |||||
const int snf_UNKNOWN_ERROR = 99; // Report an error (unknown code) | const int snf_UNKNOWN_ERROR = 99; // Report an error (unknown code) | ||||
string ERROR_SYNC_FAILEDmsg = CurrentThreadState().Name; // Format a useful state message. | |||||
std::string ERROR_SYNC_FAILEDmsg = CurrentThreadState().Name; // Format a useful state message. | |||||
ERROR_SYNC_FAILEDmsg.append(": "); | ERROR_SYNC_FAILEDmsg.append(": "); | ||||
ERROR_SYNC_FAILEDmsg.append(e.what()); | ERROR_SYNC_FAILEDmsg.append(e.what()); | ||||
(*myLOGmgr).logThisError( // Log the error (if possible) | (*myLOGmgr).logThisError( // Log the error (if possible) | ||||
} | } | ||||
catch (...) { // SYNC Failed if we're here. | catch (...) { // SYNC Failed if we're here. | ||||
const int snf_UNKNOWN_ERROR = 99; // Report an error (unknown code) | const int snf_UNKNOWN_ERROR = 99; // Report an error (unknown code) | ||||
string ERROR_SYNC_FAILEDmsg = CurrentThreadState().Name; // Format a useful state message. | |||||
std::string ERROR_SYNC_FAILEDmsg = CurrentThreadState().Name; // Format a useful state message. | |||||
ERROR_SYNC_FAILEDmsg.append(": Panic!"); | ERROR_SYNC_FAILEDmsg.append(": Panic!"); | ||||
(*myLOGmgr).logThisError( // Log the error (if possible) | (*myLOGmgr).logThisError( // Log the error (if possible) | ||||
"SNF_NETWORK", snf_UNKNOWN_ERROR, ERROR_SYNC_FAILEDmsg | "SNF_NETWORK", snf_UNKNOWN_ERROR, ERROR_SYNC_FAILEDmsg |
// Configuration data | // Configuration data | ||||
string License; // Node (license) Id? | |||||
string SecurityKey; // Security key for this rulebase? | |||||
string RulebaseFilePath; // Where we can find our rulebase? | |||||
string HandshakeFilePath; // Where do we keep our handshake? | |||||
string UpdateReadyFilePath; // Where do I put update trigger files? | |||||
string SyncHostName; // Where do we connect to sync? | |||||
std::string License; // Node (license) Id? | |||||
std::string SecurityKey; // Security key for this rulebase? | |||||
std::string RulebaseFilePath; // Where we can find our rulebase? | |||||
std::string HandshakeFilePath; // Where do we keep our handshake? | |||||
std::string UpdateReadyFilePath; // Where do I put update trigger files? | |||||
std::string SyncHostName; // Where do we connect to sync? | |||||
int SyncHostPort; // What port do we use to sync? | int SyncHostPort; // What port do we use to sync? | ||||
int SyncSecsOverride; // How may secs between sync (override)? | int SyncSecsOverride; // How may secs between sync (override)? | ||||
int SyncSecsConfigured; // How many secs to sync (nominally)? | int SyncSecsConfigured; // How many secs to sync (nominally)? | ||||
PadBuffer& Handshake(PadBuffer& NewHandshake); // Store a new handshake. | PadBuffer& Handshake(PadBuffer& NewHandshake); // Store a new handshake. | ||||
PadBuffer CurrentHandshake; // Where we keep our current handshake. | PadBuffer CurrentHandshake; // Where we keep our current handshake. | ||||
void postUpdateTrigger(string& updateUTC); // Post an update trigger file. | |||||
void postUpdateTrigger(std::string& updateUTC); // Post an update trigger file. | |||||
string SamplesBuffer; // Message Samples Appended Together. | |||||
string getSamples(); // Syncrhonized way to get Samples. | |||||
string ReportsBuffer; // Status Reports Appended Together. | |||||
string getReports(); // Synchronized way to get Reports. | |||||
std::string SamplesBuffer; // Message Samples Appended Together. | |||||
std::string getSamples(); // Syncrhonized way to get Samples. | |||||
std::string ReportsBuffer; // Status Reports Appended Together. | |||||
std::string getReports(); // Synchronized way to get Reports. | |||||
public: | public: | ||||
void linkGBUdbmgr(snfGBUdbmgr& G); // Set the GBUdbmgr. | void linkGBUdbmgr(snfGBUdbmgr& G); // Set the GBUdbmgr. | ||||
void configure(snfCFGData& CFGData); // Update the configuration. | void configure(snfCFGData& CFGData); // Update the configuration. | ||||
class SyncFailed : public runtime_error { // Thrown if sync doesn't work. | |||||
public: SyncFailed(const string& w):runtime_error(w) {} | |||||
class SyncFailed : public std::runtime_error { // Thrown if sync doesn't work. | |||||
public: SyncFailed(const std::string& w):runtime_error(w) {} | |||||
}; | }; | ||||
// Operations | // Operations | ||||
int MessageLength // and it is this size. | int MessageLength // and it is this size. | ||||
); | ); | ||||
void sendReport(const string& StatusReportText); // Send a status report... | |||||
void sendReport(const std::string& StatusReportText); // Send a status report... | |||||
void sync(); // Do the whole "sync" thing. | void sync(); // Do the whole "sync" thing. | ||||
// Utility Functions | // Utility Functions | ||||
unsigned long ResolveHostIPFromName(const string& N); // Find the IP. | |||||
string& RulebaseUTC(string& t); // Gets local rulebase file UTC. | |||||
unsigned long ResolveHostIPFromName(const std::string& N); // Find the IP. | |||||
std::string& RulebaseUTC(std::string& t); // Gets local rulebase file UTC. | |||||
const static cd::ThreadType Type; // The thread's type. | const static cd::ThreadType Type; // The thread's type. | ||||
UnfoldHeaders(); // Unfold the headers. | UnfoldHeaders(); // Unfold the headers. | ||||
} | } | ||||
cd::IP4Address extractIPFromSourceHeader(string& Header) { // Return first IP found in header. | |||||
const string Digits = "0123456789"; | |||||
cd::IP4Address extractIPFromSourceHeader(std::string& Header) { // Return first IP found in header. | |||||
const std::string Digits = "0123456789"; | |||||
unsigned int EndOfName = Header.find_first_of(":"); | unsigned int EndOfName = Header.find_first_of(":"); | ||||
unsigned int StartOfIP = Header.find_first_of(Digits, EndOfName); | unsigned int StartOfIP = Header.find_first_of(Digits, EndOfName); | ||||
const string IPCharacters = ".0123456789"; | |||||
const std::string IPCharacters = ".0123456789"; | |||||
unsigned int EndOfIP = Header.find_first_not_of(IPCharacters, StartOfIP); | unsigned int EndOfIP = Header.find_first_not_of(IPCharacters, StartOfIP); | ||||
bool NoExtraCharactersAfterIP = (string::npos == EndOfIP); | |||||
bool NoExtraCharactersAfterIP = (std::string::npos == EndOfIP); | |||||
if(NoExtraCharactersAfterIP) EndOfIP = Header.length(); | if(NoExtraCharactersAfterIP) EndOfIP = Header.length(); | ||||
unsigned int IPLength = EndOfIP - StartOfIP; | unsigned int IPLength = EndOfIP - StartOfIP; | ||||
cd::IP4Address ExtractedIP = Header.substr(StartOfIP, IPLength); | cd::IP4Address ExtractedIP = Header.substr(StartOfIP, IPLength); | ||||
return ExtractedIP; | return ExtractedIP; | ||||
} | } | ||||
void HeaderFinder::CheckContent(string& Header, const HeaderFinderPattern& P) { // Check for a match in the header. | |||||
void HeaderFinder::CheckContent(std::string& Header, const HeaderFinderPattern& P) { // Check for a match in the header. | |||||
bool HeaderContainsFinderPattern = ( | bool HeaderContainsFinderPattern = ( | ||||
string::npos != Header.find(P.Contains, P.Header.length()) | |||||
std::string::npos != Header.find(P.Contains, P.Header.length()) | |||||
); | ); | ||||
if(HeaderContainsFinderPattern) { | if(HeaderContainsFinderPattern) { | ||||
} | } | ||||
void HeaderFinder::MatchHeaders(string& Header) { // Check that the header matches. | |||||
void HeaderFinder::MatchHeaders(std::string& Header) { // Check that the header matches. | |||||
if(0 >= Header.length()) return; // If there's nothing to look at, done! | if(0 >= Header.length()) return; // If there's nothing to look at, done! | ||||
HeaderFinderPattern Key; // We will need a handy key. | HeaderFinderPattern Key; // We will need a handy key. | ||||
Key.Header.push_back(Header.at(0)); // Set up a minimal header string. | Key.Header.push_back(Header.at(0)); // Set up a minimal header string. | ||||
} | } | ||||
void captureThisHeader( // Capture the header and move pos. | void captureThisHeader( // Capture the header and move pos. | ||||
string& Output, // Here is the output string. | |||||
std::string& Output, // Here is the output string. | |||||
int& Pos, // Here is the current position. | int& Pos, // Here is the current position. | ||||
const unsigned char* Bfr, // Here is the buffer pointer. | const unsigned char* Bfr, // Here is the buffer pointer. | ||||
const int Len // Here is the length of the buffer. | const int Len // Here is the length of the buffer. | ||||
void HeaderFinder::UnfoldHeaders() { // Unfold and check headers. | void HeaderFinder::UnfoldHeaders() { // Unfold and check headers. | ||||
if(0 >= HeaderDirectives.size()) return; // Skip this if we have no patterns. | if(0 >= HeaderDirectives.size()) return; // Skip this if we have no patterns. | ||||
if(0 >= Len) return; // Skip if we have no message. | if(0 >= Len) return; // Skip if we have no message. | ||||
string TestHeader; // The header under test. | |||||
std::string TestHeader; // The header under test. | |||||
int Position = 0; // Position in Bfr. | int Position = 0; // Position in Bfr. | ||||
for(;;) { // Scan through all of the headers. | for(;;) { // Scan through all of the headers. |