You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SNFMulti.hpp 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. // SNFMulti.hpp
  2. //
  3. // (C) Copyright 2006 - 2020 ARM Research Labs, LLC.
  4. // See www.armresearch.com for the copyright terms.
  5. //
  6. // 20060121_M
  7. // This file creates an API for multi-threaded systems to use the SNF engine.
  8. //
  9. // This API is C++ oriented, meaning it throws exceptions and so forth.
  10. // For use in shared objects and DLLs, the functions in here will be wrapped
  11. // in a C style interface appropriate to that platform.
  12. //
  13. // The interface is based on the following structure.
  14. //
  15. // The application "Opens" one or more rulebases.
  16. // The application "Opens" some number of scanners referencing opened rulebases.
  17. // Each scanner handles one thread's worth of scanning, so it is presumed that
  18. // each processing thread in the calling application will have one scanner to itself.
  19. //
  20. // Rulebases can be reloaded asynchronously. The scanner's grab a reference to the
  21. // rulebase each time they restart. The grabbing and swapping in of new rulebases is
  22. // a very short critical section.
  23. #pragma once
  24. #include <stdexcept>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #include <ctime>
  28. #include <string>
  29. #include "../CodeDweller/faults.hpp"
  30. #include "../CodeDweller/threading.hpp"
  31. #include "GBUdb.hpp"
  32. #include "FilterChain.hpp"
  33. #include "snf_engine.hpp"
  34. #include "snf_match.h"
  35. #include "snfCFGmgr.hpp"
  36. #include "snfLOGmgr.hpp"
  37. #include "snfNETmgr.hpp"
  38. #include "snfGBUdbmgr.hpp"
  39. #include "snfXCImgr.hpp"
  40. #include "snf_saccades.hpp"
  41. #include <cassert>
  42. namespace cd = codedweller;
  43. extern const char* SNF_ENGINE_VERSION;
  44. // snf Result Code Constants
  45. const int snf_SUCCESS = 0;
  46. const int snf_ERROR_CMD_LINE = 65;
  47. const int snf_ERROR_LOG_FILE = 66;
  48. const int snf_ERROR_RULE_FILE = 67;
  49. const int snf_ERROR_RULE_DATA = 68;
  50. const int snf_ERROR_RULE_AUTH = 73;
  51. const int snf_ERROR_MSG_FILE = 69;
  52. const int snf_ERROR_ALLOCATION = 70;
  53. const int snf_ERROR_BAD_MATRIX = 71;
  54. const int snf_ERROR_MAX_EVALS = 72;
  55. const int snf_ERROR_UNKNOWN = 99;
  56. // Settings & Other Constants
  57. const int snf_ScanHorizon = 32768; // Maximum length of message to check.
  58. const int snf_MAX_RULEBASES = 10; // 10 Rulebases is plenty. Most use just 1
  59. const int snf_MAX_SCANNERS = 500; // 500 Scanners at once should be plenty
  60. const int SHUTDOWN = -999; // Shutdown Cursor Value.
  61. // snfCFGPacket encapsulates configuration and rulebase data.
  62. // The rulebase handler can write to it.
  63. // Others can only read from it.
  64. // The engine handler creates and owns one of these. It uses it to
  65. // grab() and drop() cfg and rulebase data from the rulebase handler.
  66. class snf_RulebaseHandler; // We need to know this exists.
  67. class snfCFGPacket { // Our little bundle of, er, cfg stuff.
  68. friend class snf_RulebaseHandler; // RulebaseHandler has write access.
  69. private:
  70. snf_RulebaseHandler* MyRulebase; // Where to grab() and drop()
  71. TokenMatrix* MyTokenMatrix; // We combine the current token matrix
  72. snfCFGData* MyCFGData; // and the current cfg data for each scan.
  73. std::set<int> RulePanics; // Set of known rule panic IDs.
  74. public:
  75. snfCFGPacket(snf_RulebaseHandler* R); // Constructor grab()s the Rulebase.
  76. ~snfCFGPacket(); // Destructor drop()s the Rulebase.
  77. TokenMatrix* Tokens(); // Consumers read the Token Matrix and
  78. snfCFGData* Config(); // the snfCFGData.
  79. bool bad(); // If anything is missing it's not good.
  80. bool isRulePanic(int R); // Test for a rule panic.
  81. };
  82. class ScriptCaller : private cd::Thread { // Calls system() in separate thread.
  83. private:
  84. cd::Mutex MyMutex; // Protects internal data.
  85. std::string SystemCallText; // Text to send to system().
  86. cd::Timeout GuardTimer; // Guard time between triggers.
  87. volatile bool GoFlag; // Go flag true when triggered.
  88. volatile bool DieFlag; // Die flag when it's time to leave.
  89. std::string ScriptToRun(); // Safely grab the script.
  90. bool hasGuardExpired(); // True if guard time has expired.
  91. void myTask(); // Thread task overload.
  92. volatile int myLastResult; // Last result of system() call.
  93. public:
  94. ScriptCaller(std::string Name); // Constructor.
  95. ~ScriptCaller(); // Destructor.
  96. void SystemCall(std::string S); // Set system call text.
  97. void GuardTime(int T); // Change guard time.
  98. void trigger(); // Trigger if possible.
  99. int LastResult(); // Return myLastResult.
  100. const static cd::ThreadType Type; // The thread's type.
  101. const static cd::ThreadState CallingSystem; // State when in system() call.
  102. const static cd::ThreadState PendingGuardTime; // State when waiting for guard time.
  103. const static cd::ThreadState StandingBy; // State when waiting around.
  104. const static cd::ThreadState Disabled; // State when unable to run.
  105. };
  106. class snf_Reloader : private cd::Thread { // Rulebase maintenance thread.
  107. private:
  108. snf_RulebaseHandler& MyRulebase; // We know our rulebase.
  109. bool TimeToStop; // We know if it's time to stop.
  110. std::string RulebaseFileCheckName; // We keep track of these files.
  111. std::string ConfigFileCheckName;
  112. std::string IgnoreListCheckFileName;
  113. time_t RulebaseFileTimestamp; // We watch their timestamps.
  114. time_t ConfigurationTimestamp;
  115. time_t IgnoreListTimestamp;
  116. void captureFileStats(); // Get stats for later comparison.
  117. bool StatsAreDifferent(); // Check file stats for changes.
  118. void myTask(); // How do we do this refresh thing?
  119. ScriptCaller RulebaseGetter; // Reloader owns a RulebaseGetter.
  120. bool RulebaseGetterIsTurnedOn; // True if we should run the getter.
  121. void captureGetterConfig(); // Get RulebaseGetter config.
  122. public:
  123. snf_Reloader(snf_RulebaseHandler& R); // Setup takes some work.
  124. ~snf_Reloader(); // Tear down takes some work.
  125. const static cd::ThreadType Type; // The thread's type.
  126. };
  127. class snf_RulebaseHandler { // Engine Core Manager.
  128. friend class snfCFGPacket;
  129. private:
  130. cd::Mutex MyMutex; // This handler's mutex.
  131. snf_Reloader* MyReloader; // Reloader engine (when in use).
  132. int volatile ReferenceCount; // Associated scanners count.
  133. snfCFGData* volatile Configuration; // Configuration for this handler.
  134. TokenMatrix* volatile Rulebase; // Rulebase for this handler.
  135. int volatile CurrentCount; // Active current scanners count.
  136. TokenMatrix* volatile OldRulebase; // Retiring rulebase holder.
  137. int volatile RetiringCount; // Active retiring scanners count.
  138. bool volatile RefreshInProgress; // Flag for locking the refresh process.
  139. int volatile MyGeneration; // Generation (reload) number.
  140. void _snf_LoadNewRulebase(); // Internal function to load new rulebase.
  141. cd::Mutex XCIServerCommandMutex; // XCI Server Command Serializer.
  142. snfXCIServerCommandHandler* myXCIServerCommandHandler; // ptr to Installed Srv Cmd Handler.
  143. void grab(snfCFGPacket& CP); // Activate this Rulebase for a scan.
  144. void drop(snfCFGPacket& CP); // Deactiveate this Rulebase after it.
  145. public:
  146. class ConfigurationError : public std::runtime_error { // When the configuration won't load.
  147. public: ConfigurationError(const std::string& w):runtime_error(w) {}
  148. };
  149. class FileError : public std::runtime_error { // Exception: rulebase file won't load.
  150. public: FileError(const std::string& w):runtime_error(w) {}
  151. };
  152. class AuthenticationError : public std::runtime_error { // Exception when authentication fails.
  153. public: AuthenticationError(const std::string& w):runtime_error(w) {}
  154. };
  155. class IgnoreListError : public std::runtime_error { // When the ignore list won't load.
  156. public: IgnoreListError(const std::string& w):runtime_error(w) {}
  157. };
  158. class AllocationError : public std::runtime_error { // Exception when we can't allocate something.
  159. public: AllocationError(const std::string& w):runtime_error(w) {}
  160. };
  161. class Busy : public std::runtime_error { // Exception when there is a collision.
  162. public: Busy(const std::string& w):runtime_error(w) {}
  163. };
  164. class Panic : public std::runtime_error { // Exception when something else happens.
  165. public: Panic(const std::string& w):runtime_error(w) {}
  166. };
  167. //// Plugin Components.
  168. snfCFGmgr MyCFGmgr; // Configuration manager.
  169. snfLOGmgr MyLOGmgr; // Logging manager.
  170. snfNETmgr MyNETmgr; // Communications manager.
  171. snfGBUdbmgr MyGBUdbmgr; // GBUdb manager.
  172. GBUdb MyGBUdb; // GBUdb for this rulebase.
  173. snfXCImgr MyXCImgr; // XCI manager.
  174. //// Methods.
  175. snf_RulebaseHandler(): // Initialization is straight forward.
  176. MyReloader(0),
  177. ReferenceCount(0),
  178. Rulebase(NULL),
  179. CurrentCount(0),
  180. OldRulebase(NULL),
  181. RetiringCount(0),
  182. RefreshInProgress(false),
  183. MyGeneration(0),
  184. myXCIServerCommandHandler(0){
  185. MyNETmgr.linkLOGmgr(MyLOGmgr); // Link the NET manager to the LOGmgr.
  186. MyNETmgr.linkGBUdbmgr(MyGBUdbmgr); // Link the NET manager to the GBUdbmgr.
  187. MyGBUdbmgr.linkGBUdb(MyGBUdb); // Link the GBUdb manager to it's db.
  188. MyGBUdbmgr.linkLOGmgr(MyLOGmgr); // Link the GBUdb manager to the LOGmgr.
  189. MyLOGmgr.linkNETmgr(MyNETmgr); // Link the LOG manager to the NETmgr.
  190. MyLOGmgr.linkGBUdb(MyGBUdb); // Link the LOG manager to the GBUdb.
  191. MyXCImgr.linkHome(this); // Link the XCI manager to this.
  192. }
  193. ~snf_RulebaseHandler(); // Shutdown checks for safety.
  194. bool isReady(); // Is the object is active.
  195. bool isBusy(); // Is a refresh/open in progress.
  196. int getReferenceCount(); // How many Engines using this handler.
  197. int getCurrentCount(); // How many Engines active in the current rb.
  198. int getRetiringCount(); // How many Engines active in the old rb.
  199. void open(const char* path, // Lights up this hanlder.
  200. const char* licenseid,
  201. const char* authentication);
  202. bool AutoRefresh(bool On); // Turn on/off auto refresh.
  203. bool AutoRefresh(); // True if AutoRefresh is on.
  204. void refresh(); // Reloads the rulebase and config.
  205. void close(); // Closes this handler.
  206. void use(); // Make use of this Rulebase Handler.
  207. void unuse(); // Finish with this Rulebase Handler.
  208. int Generation(); // Returns the generation number.
  209. void addRulePanic(int RuleID); // Synchronously add a RulePanic.
  210. bool testXHDRInjectOn(); // Safely look ahead at XHDRInjectOn.
  211. IPTestRecord& performIPTest(IPTestRecord& I); // Perform an IP test.
  212. void logThisIPTest(IPTestRecord& I, std::string Action); // Log an IP test result & action.
  213. void logThisError(std::string ContextName, int Code, std::string Text); // Log an error message.
  214. void logThisInfo(std::string ContextName, int Code, std::string Text); // Log an informational message.
  215. std::string PlatformVersion(std::string NewPlatformVersion); // Set platform version info.
  216. std::string PlatformVersion(); // Get platform version info.
  217. std::string PlatformConfiguration(); // Get platform configuration.
  218. std::string EngineVersion(); // Get engine version info.
  219. void XCIServerCommandHandler(snfXCIServerCommandHandler& XCH); // Registers a new XCI Srvr Cmd handler.
  220. std::string processXCIServerCommandRequest(snf_xci& X); // Handle a parsed XCI Srvr Cmd request.
  221. };
  222. // IPTestEngine w/ GBUdb interface.
  223. // This will plug into the FilterChain to evaluate IPs on the fly.
  224. class snf_IPTestEngine : public FilterChainIPTester {
  225. private:
  226. GBUdb* Lookup; // Where we find our GBUdb.
  227. snfScanData* ScanData; // Where we find our ScanData.
  228. snfCFGData* CFGData; // Where we find our CFG data.
  229. snfLOGmgr* LOGmgr; // Where we find our LOG manager.
  230. public:
  231. snf_IPTestEngine(); // Initialize internal pointers to NULL.
  232. void setGBUdb(GBUdb& G); // Setup the GBUdb lookup.
  233. void setScanData(snfScanData& D); // Setup the ScanData object.
  234. void setCFGData(snfCFGData& C); // (Re)Set the config data to use.
  235. void setLOGmgr(snfLOGmgr& L); // Setup the LOGmgr to use.
  236. std::string& test(std::string& input, std::string& output); // Our obligatory test function.
  237. };
  238. class snf_SaccadesHandler {
  239. private:
  240. cd::Mutex MyMutex;
  241. saccades_engine MyEngine;
  242. void lockAndLearn(std::vector<saccade>& Matches) {
  243. cd::ScopeMutex SafetyFirst(MyMutex);
  244. MyEngine.learn(Matches);
  245. }
  246. std::vector<saccade> grabSaccades() {
  247. cd::ScopeMutex SafetyFirst(MyMutex);
  248. return MyEngine.recall();
  249. }
  250. int TimeToPeekCounter;
  251. static const int TimeToPeekReset = 32;
  252. public:
  253. static const int AlwaysScanLength = 2048;
  254. snf_SaccadesHandler() :
  255. MyEngine(128),
  256. TimeToPeekCounter(0) {}
  257. void applySaccades(EvaluationMatrix* Scanner, std::vector<unsigned char>& Data);
  258. void learnMatches(MatchRecord* Matches);
  259. };
  260. // How to spot strangers in the IP reputations.
  261. class snf_IPStrangerList {
  262. private:
  263. cd::Mutex myMutex;
  264. std::set<cd::IP4Address> listA;
  265. std::set<cd::IP4Address> listB;
  266. bool usingANotB;
  267. cd::Timeout listExpiration;
  268. std::set<cd::IP4Address>& myActiveList() {
  269. if(usingANotB) return listA;
  270. else return listB;
  271. }
  272. void swapOutOldLists() {
  273. if(listExpiration.isExpired()) {
  274. usingANotB = !usingANotB;
  275. myActiveList().clear();
  276. listExpiration.restart();
  277. }
  278. }
  279. std::set<cd::IP4Address>& myCurrentList() {
  280. swapOutOldLists();
  281. return myActiveList();
  282. }
  283. public:
  284. static const int TwoHours = (2 * (60 * (60 * 1000)));
  285. snf_IPStrangerList() : usingANotB(true), listExpiration(TwoHours) {}
  286. bool isStranger(cd::IP4Address a) {
  287. cd::ScopeMutex JustMe(myMutex);
  288. swapOutOldLists();
  289. bool foundStranger = (0 < listA.count(a)) || (0 < listB.count(a));
  290. return foundStranger;
  291. }
  292. void addStranger(cd::IP4Address a) {
  293. cd::ScopeMutex JustMe(myMutex);
  294. myCurrentList().insert(a);
  295. }
  296. };
  297. // Here's where we pull it all together.
  298. class snf_EngineHandler {
  299. private:
  300. cd::Mutex MyMutex; // This handler's mutex.
  301. cd::Mutex FileScan; // File scan entry mutex.
  302. EvaluationMatrix* volatile CurrentMatrix; // Matrix for the latest scan.
  303. snf_RulebaseHandler* volatile MyRulebase; // My RulebaseHandler.
  304. snfScanData MyScanData; // Local snfScanData record.
  305. snf_IPTestEngine MyIPTestEngine; // Local IP Test Engine.
  306. int ResultsCount; // Count of Match Records for getResults
  307. int ResultsRemaining; // Count of Match Records ahead of cursor.
  308. MatchRecord* FinalResult; // Final (winning) result of the scan.
  309. MatchRecord* ResultCursor; // Current Match Record for getResults.
  310. std::string extractMessageID(const unsigned char* Msg, const int Len); // Get log safe Message-ID or substitute.
  311. public:
  312. class FileError : public std::runtime_error { // Exception when a file won't open.
  313. public: FileError(const std::string& w):runtime_error(w) {}
  314. };
  315. class XHDRError : public std::runtime_error { // Exception when XHDR Inject/File fails.
  316. public: XHDRError(const std::string& w):runtime_error(w) {}
  317. };
  318. class BadMatrix : public std::runtime_error { // Exception out of bounds of matrix.
  319. public: BadMatrix(const std::string& w):runtime_error(w) {}
  320. };
  321. class MaxEvals : public std::runtime_error { // Exception too many evaluators.
  322. public: MaxEvals(const std::string& w):runtime_error(w) {}
  323. };
  324. class AllocationError : public std::runtime_error { // Exception when we can't allocate something.
  325. public: AllocationError(const std::string& w):runtime_error(w) {}
  326. };
  327. class Busy : public std::runtime_error { // Exception when there is a collision.
  328. public: Busy(const std::string& w):runtime_error(w) {}
  329. };
  330. class Panic : public std::runtime_error { // Exception when something else happens.
  331. public: Panic(const std::string& w):runtime_error(w) {}
  332. };
  333. snf_EngineHandler(): // Initialization is simple.
  334. CurrentMatrix(NULL),
  335. MyRulebase(NULL),
  336. MyScanData(snf_ScanHorizon),
  337. ResultsCount(0),
  338. ResultsRemaining(0),
  339. ResultCursor(NULL) {}
  340. ~snf_EngineHandler(); // Shutdown clenas up and checks for safety.
  341. void open(snf_RulebaseHandler* Handler); // Light up the engine.
  342. bool isReady(); // Is the Engine good to go? (doubles as busy)
  343. void close(); // Close down the engine.
  344. int scanMessageFile( // Scan this message file.
  345. const std::string MessageFilePath, // -- this is the file (and id)
  346. const int MessageSetupTime = 0, // -- setup time already used.
  347. const cd::IP4Address MessageSource = 0UL // -- message source IP (for injection).
  348. );
  349. int scanMessage( // Scan this message.
  350. const unsigned char* MessageBuffer, // -- this is the message buffer.
  351. const int MessageLength, // -- this is the length of the buffer.
  352. const std::string MessageName = "", // -- this is the message identifier.
  353. const int MessageSetupTime = 0, // -- setup time used (for logging).
  354. const cd::IP4Address MessageSource = 0UL // -- message source IP (for injection).
  355. );
  356. int getResults(snf_match* MatchBuffer); // Get the next match buffer.
  357. int getDepth(); // Get the scan depth.
  358. const std::string getClassicLog(); // Get classic log entries for last scan.
  359. const std::string getXMLLog(); // Get XML log entries or last scan.
  360. const std::string getXHDRs(); // Get XHDRs for last scan.
  361. };
  362. // Here's the class that pulls it all together.
  363. class snf_MultiEngineHandler {
  364. private:
  365. cd::Mutex RulebaseScan; // This handler's mutex.
  366. int RulebaseCursor; // Next Rulebase to search.
  367. snf_RulebaseHandler RulebaseHandlers[snf_MAX_RULEBASES]; // Array of Rulebase Handlers
  368. int RoundRulebaseCursor(); // Gets round robin Rulebase handle candidates.
  369. cd::Mutex EngineScan; // Serializes searching the Engine list.
  370. int EngineCursor; // Next Engine to search.
  371. snf_EngineHandler EngineHandlers[snf_MAX_SCANNERS]; // Array of Engine Handlers
  372. int RoundEngineCursor(); // Gets round robin Engine handle candidates.
  373. public:
  374. class TooMany : public std::runtime_error { // Exception when no more handle slots.
  375. public: TooMany(const std::string& w):runtime_error(w) {}
  376. };
  377. class FileError : public std::runtime_error { // Exception when a file won't open.
  378. public: FileError(const std::string& w):runtime_error(w) {}
  379. };
  380. class AuthenticationError : public std::runtime_error { // Exception when authentication fails.
  381. public: AuthenticationError(const std::string& w):runtime_error(w) {}
  382. };
  383. class AllocationError : public std::runtime_error { // Exception when we can't allocate something.
  384. public: AllocationError(const std::string& w):runtime_error(w) {}
  385. };
  386. class Busy : public std::runtime_error { // Exception when there is a collision.
  387. public: Busy(const std::string& w):runtime_error(w) {}
  388. };
  389. class Panic : public std::runtime_error { // Exception when something else happens.
  390. public: Panic(const std::string& w):runtime_error(w) {}
  391. };
  392. snf_MultiEngineHandler():
  393. RulebaseCursor(0),
  394. EngineCursor(0) {}
  395. ~snf_MultiEngineHandler(); // Clean up, safety check, shut down.
  396. // snf_OpenRulebase()
  397. // Grab the first available rulebse handler and light it up.
  398. int OpenRulebase(const char* path, const char* licenseid, const char* authentication);
  399. // snf_RefreshRulebase()
  400. // Reload the rulebase associated with the handler.
  401. void RefreshRulebase(int RulebaseHandle);
  402. // snf_CloseRulebase()
  403. // Shut down this Rulebase handler.
  404. void CloseRulebase(int RulebaseHandle);
  405. // snf_OpenEngine()
  406. // Grab the first available Engine handler and light it up
  407. int OpenEngine(int RulebaseHandle);
  408. // snf_CloseEngine()
  409. // Shut down this Engine handler.
  410. void CloseEngine(int EngineHandle);
  411. // snf_Scan()
  412. // Scan the MessageBuffer with this Engine.
  413. int Scan(int EngineHandle, const unsigned char* MessageBuffer, int MessageLength);
  414. // The Engine prvides detailed match results through this function.
  415. int getResults(int EngineHandle, snf_match* matchbfr);
  416. // The Engine provies the scan depth through this function.
  417. int getDepth(int EngineHandle);
  418. };