123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528 |
- // SNFMulti.hpp
- //
- // (C) Copyright 2006 - 2020 ARM Research Labs, LLC.
- // See www.armresearch.com for the copyright terms.
- //
- // 20060121_M
- // This file creates an API for multi-threaded systems to use the SNF engine.
- //
- // This API is C++ oriented, meaning it throws exceptions and so forth.
- // For use in shared objects and DLLs, the functions in here will be wrapped
- // in a C style interface appropriate to that platform.
- //
- // The interface is based on the following structure.
- //
- // The application "Opens" one or more rulebases.
- // The application "Opens" some number of scanners referencing opened rulebases.
- // Each scanner handles one thread's worth of scanning, so it is presumed that
- // each processing thread in the calling application will have one scanner to itself.
- //
- // Rulebases can be reloaded asynchronously. The scanner's grab a reference to the
- // rulebase each time they restart. The grabbing and swapping in of new rulebases is
- // a very short critical section.
-
- #pragma once
-
- #include <stdexcept>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <ctime>
- #include <string>
- #include "../CodeDweller/faults.hpp"
-
- #ifdef WIN32
-
- // Required because threading.hpp includes windows.h.
- #include <winsock2.h>
-
- #endif
-
- #include "../CodeDweller/threading.hpp"
- #include "GBUdb.hpp"
- #include "FilterChain.hpp"
- #include "snf_engine.hpp"
- #include "snf_match.h"
- #include "snfCFGmgr.hpp"
- #include "snfLOGmgr.hpp"
- #include "snfNETmgr.hpp"
- #include "snfGBUdbmgr.hpp"
- #include "snfXCImgr.hpp"
-
- #include <cassert>
-
- namespace cd = codedweller;
-
- extern const char* SNF_ENGINE_VERSION;
-
- // snf Result Code Constants
-
- const int snf_SUCCESS = 0;
- const int snf_ERROR_CMD_LINE = 65;
- const int snf_ERROR_LOG_FILE = 66;
- const int snf_ERROR_RULE_FILE = 67;
- const int snf_ERROR_RULE_DATA = 68;
- const int snf_ERROR_RULE_AUTH = 73;
- const int snf_ERROR_MSG_FILE = 69;
- const int snf_ERROR_ALLOCATION = 70;
- const int snf_ERROR_BAD_MATRIX = 71;
- const int snf_ERROR_MAX_EVALS = 72;
- const int snf_ERROR_UNKNOWN = 99;
-
- // Settings & Other Constants
-
- const int snf_ScanHorizon = 32768; // Maximum length of message to check.
- const int snf_MAX_RULEBASES = 10; // 10 Rulebases is plenty. Most use just 1
- const int snf_MAX_SCANNERS = 500; // 500 Scanners at once should be plenty
-
- const int SHUTDOWN = -999; // Shutdown Cursor Value.
-
- // snfCFGPacket encapsulates configuration and rulebase data.
- // The rulebase handler can write to it.
- // Others can only read from it.
- // The engine handler creates and owns one of these. It uses it to
- // grab() and drop() cfg and rulebase data from the rulebase handler.
-
- class snf_RulebaseHandler; // We need to know this exists.
-
- class snfCFGPacket { // Our little bundle of, er, cfg stuff.
-
- friend class snf_RulebaseHandler; // RulebaseHandler has write access.
-
- private:
- snf_RulebaseHandler* MyRulebase; // Where to grab() and drop()
- TokenMatrix* MyTokenMatrix; // We combine the current token matrix
- snfCFGData* MyCFGData; // and the current cfg data for each scan.
-
- std::set<int> RulePanics; // Set of known rule panic IDs.
-
- public:
- snfCFGPacket(snf_RulebaseHandler* R); // Constructor grab()s the Rulebase.
- ~snfCFGPacket(); // Destructor drop()s the Rulebase.
-
- TokenMatrix* Tokens(); // Consumers read the Token Matrix and
- snfCFGData* Config(); // the snfCFGData.
-
- bool bad(); // If anything is missing it's not good.
-
- bool isRulePanic(int R); // Test for a rule panic.
- };
-
- class ScriptCaller : private cd::Thread { // Calls system() in separate thread.
- private:
- 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 DieFlag; // Die flag when it's time to leave.
-
- std::string ScriptToRun(); // Safely grab the script.
- bool hasGuardExpired(); // True if guard time has expired.
- void myTask(); // Thread task overload.
-
- volatile int myLastResult; // Last result of system() call.
-
- public:
- ScriptCaller(std::string Name); // Constructor.
- ~ScriptCaller(); // Destructor.
-
- void SystemCall(std::string S); // Set system call text.
- void GuardTime(int T); // Change guard time.
- void trigger(); // Trigger if possible.
- int LastResult(); // Return myLastResult.
-
- const static cd::ThreadType Type; // The thread's type.
-
- 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 cd::Thread { // Rulebase maintenance thread.
- private:
-
- snf_RulebaseHandler& MyRulebase; // We know our rulebase.
- bool TimeToStop; // We know if it's time to stop.
-
- std::string RulebaseFileCheckName; // We keep track of these files.
- std::string ConfigFileCheckName;
- std::string IgnoreListCheckFileName;
- time_t RulebaseFileTimestamp; // We watch their timestamps.
- time_t ConfigurationTimestamp;
- time_t IgnoreListTimestamp;
-
- void captureFileStats(); // Get stats for later comparison.
- bool StatsAreDifferent(); // Check file stats for changes.
-
- void myTask(); // How do we do this refresh thing?
-
- ScriptCaller RulebaseGetter; // Reloader owns a RulebaseGetter.
- bool RulebaseGetterIsTurnedOn; // True if we should run the getter.
- void captureGetterConfig(); // Get RulebaseGetter config.
-
- public:
- snf_Reloader(snf_RulebaseHandler& R); // Setup takes some work.
- ~snf_Reloader(); // Tear down takes some work.
-
- const static cd::ThreadType Type; // The thread's type.
-
- };
-
- class snf_RulebaseHandler { // Engine Core Manager.
-
- friend class snfCFGPacket;
-
- private:
-
- cd::Mutex MyMutex; // This handler's mutex.
-
- snf_Reloader* MyReloader; // Reloader engine (when in use).
-
- int volatile ReferenceCount; // Associated scanners count.
-
- snfCFGData* volatile Configuration; // Configuration for this handler.
- 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.
-
- bool volatile RefreshInProgress; // Flag for locking the refresh process.
-
- int volatile MyGeneration; // Generation (reload) number.
-
- void _snf_LoadNewRulebase(); // Internal function to load new rulebase.
-
- cd::Mutex XCIServerCommandMutex; // XCI Server Command Serializer.
- snfXCIServerCommandHandler* myXCIServerCommandHandler; // ptr to Installed Srv Cmd Handler.
-
- void grab(snfCFGPacket& CP); // Activate this Rulebase for a scan.
- void drop(snfCFGPacket& CP); // Deactiveate this Rulebase after it.
-
- public:
-
- class ConfigurationError : public std::runtime_error { // When the configuration won't load.
- public: ConfigurationError(const std::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 std::runtime_error { // Exception when authentication fails.
- public: AuthenticationError(const std::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 std::runtime_error { // Exception when we can't allocate something.
- public: AllocationError(const std::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 std::runtime_error { // Exception when something else happens.
- public: Panic(const std::string& w):runtime_error(w) {}
- };
-
- //// Plugin Components.
-
- snfCFGmgr MyCFGmgr; // Configuration manager.
- snfLOGmgr MyLOGmgr; // Logging manager.
- snfNETmgr MyNETmgr; // Communications manager.
- snfGBUdbmgr MyGBUdbmgr; // GBUdb manager.
- GBUdb MyGBUdb; // GBUdb for this rulebase.
- snfXCImgr MyXCImgr; // XCI manager.
-
- //// Methods.
-
- snf_RulebaseHandler(): // Initialization is straight forward.
- MyReloader(0),
- ReferenceCount(0),
- Rulebase(NULL),
- CurrentCount(0),
- OldRulebase(NULL),
- RetiringCount(0),
- RefreshInProgress(false),
- MyGeneration(0),
- myXCIServerCommandHandler(0){
- MyNETmgr.linkLOGmgr(MyLOGmgr); // Link the NET manager to the LOGmgr.
- MyNETmgr.linkGBUdbmgr(MyGBUdbmgr); // Link the NET manager to the GBUdbmgr.
- MyGBUdbmgr.linkGBUdb(MyGBUdb); // Link the GBUdb manager to it's db.
- MyGBUdbmgr.linkLOGmgr(MyLOGmgr); // Link the GBUdb manager to the LOGmgr.
- MyLOGmgr.linkNETmgr(MyNETmgr); // Link the LOG manager to the NETmgr.
- MyLOGmgr.linkGBUdb(MyGBUdb); // Link the LOG manager to the GBUdb.
- MyXCImgr.linkHome(this); // Link the XCI manager to this.
- }
-
- ~snf_RulebaseHandler(); // Shutdown checks for safety.
-
- bool isReady(); // Is the object is active.
- bool isBusy(); // Is a refresh/open in progress.
- int getReferenceCount(); // How many Engines using this handler.
- int getCurrentCount(); // How many Engines active in the current rb.
- int getRetiringCount(); // How many Engines active in the old rb.
- void open(const char* path, // Lights up this hanlder.
- const char* licenseid,
- const char* authentication);
-
- bool AutoRefresh(bool On); // Turn on/off auto refresh.
- bool AutoRefresh(); // True if AutoRefresh is on.
- void refresh(); // Reloads the rulebase and config.
-
- void close(); // Closes this handler.
-
- void use(); // Make use of this Rulebase Handler.
- void unuse(); // Finish with this Rulebase Handler.
-
- int Generation(); // Returns the generation number.
-
- void addRulePanic(int RuleID); // Synchronously add a RulePanic.
- bool testXHDRInjectOn(); // Safely look ahead at XHDRInjectOn.
-
- IPTestRecord& performIPTest(IPTestRecord& I); // Perform an IP test.
- void logThisIPTest(IPTestRecord& I, std::string Action); // Log an IP test result & action.
-
- 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.
- std::string processXCIServerCommandRequest(snf_xci& X); // Handle a parsed XCI Srvr Cmd request.
- };
-
- // IPTestEngine w/ GBUdb interface.
- // This will plug into the FilterChain to evaluate IPs on the fly.
-
- class snf_IPTestEngine : public FilterChainIPTester {
-
- private:
-
- GBUdb* Lookup; // Where we find our GBUdb.
- snfScanData* ScanData; // Where we find our ScanData.
- snfCFGData* CFGData; // Where we find our CFG data.
- snfLOGmgr* LOGmgr; // Where we find our LOG manager.
-
- public:
-
- snf_IPTestEngine(); // Initialize internal pointers to NULL.
- void setGBUdb(GBUdb& G); // Setup the GBUdb lookup.
- void setScanData(snfScanData& D); // Setup the ScanData object.
- void setCFGData(snfCFGData& C); // (Re)Set the config data to use.
- void setLOGmgr(snfLOGmgr& L); // Setup the LOGmgr to use.
-
- std::string& test(std::string& input, std::string& output); // Our obligatory test function.
- };
-
- // 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);
- }
- };
-
- // Here's where we pull it all together.
-
- class snf_EngineHandler {
-
- private:
-
- 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.
-
- 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.
-
- std::string extractMessageID(const unsigned char* Msg, const int Len); // Get log safe Message-ID or substitute.
-
- public:
-
- 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 std::runtime_error { // Exception when XHDR Inject/File fails.
- public: XHDRError(const std::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 std::runtime_error { // Exception too many evaluators.
- public: MaxEvals(const std::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 std::runtime_error { // Exception when there is a collision.
- public: Busy(const std::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.
- CurrentMatrix(NULL),
- MyRulebase(NULL),
- MyScanData(snf_ScanHorizon),
- ResultsCount(0),
- ResultsRemaining(0),
- ResultCursor(NULL) {}
-
- ~snf_EngineHandler(); // Shutdown clenas up and checks for safety.
-
- void open(snf_RulebaseHandler* Handler); // Light up the engine.
- bool isReady(); // Is the Engine good to go? (doubles as busy)
- void close(); // Close down the engine.
-
- int scanMessageFile( // Scan this message file.
- const std::string MessageFilePath, // -- this is the file (and id)
- const int MessageSetupTime = 0, // -- setup time already used.
- 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 std::string MessageName = "", // -- this is the message identifier.
- const int MessageSetupTime = 0, // -- setup time used (for logging).
- 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.
-
- 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.
-
- class snf_MultiEngineHandler {
-
- private:
-
- cd::Mutex RulebaseScan; // This handler's mutex.
- int RulebaseCursor; // Next Rulebase to search.
- snf_RulebaseHandler RulebaseHandlers[snf_MAX_RULEBASES]; // Array of Rulebase Handlers
-
- int RoundRulebaseCursor(); // Gets round robin Rulebase handle candidates.
-
- cd::Mutex EngineScan; // Serializes searching the Engine list.
- int EngineCursor; // Next Engine to search.
- snf_EngineHandler EngineHandlers[snf_MAX_SCANNERS]; // Array of Engine Handlers
-
- int RoundEngineCursor(); // Gets round robin Engine handle candidates.
-
- public:
-
- class TooMany : public std::runtime_error { // Exception when no more handle slots.
- public: TooMany(const std::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 std::runtime_error { // Exception when authentication fails.
- public: AuthenticationError(const std::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 std::runtime_error { // Exception when there is a collision.
- public: Busy(const std::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():
- RulebaseCursor(0),
- EngineCursor(0) {}
-
- ~snf_MultiEngineHandler(); // Clean up, safety check, shut down.
-
- // snf_OpenRulebase()
- // Grab the first available rulebse handler and light it up.
-
- int OpenRulebase(const char* path, const char* licenseid, const char* authentication);
-
- // snf_RefreshRulebase()
- // Reload the rulebase associated with the handler.
-
- void RefreshRulebase(int RulebaseHandle);
-
- // snf_CloseRulebase()
- // Shut down this Rulebase handler.
-
- void CloseRulebase(int RulebaseHandle);
-
- // snf_OpenEngine()
- // Grab the first available Engine handler and light it up
-
- int OpenEngine(int RulebaseHandle);
-
- // snf_CloseEngine()
- // Shut down this Engine handler.
-
- void CloseEngine(int EngineHandle);
-
- // snf_Scan()
- // Scan the MessageBuffer with this Engine.
-
- int Scan(int EngineHandle, const unsigned char* MessageBuffer, int MessageLength);
-
- // The Engine prvides detailed match results through this function.
-
- int getResults(int EngineHandle, snf_match* matchbfr);
-
- // The Engine provies the scan depth through this function.
-
- int getDepth(int EngineHandle);
-
- };
|