// snf_HeaderFinder.hpp // Copyright (C) 2007 - 2020 ARM Research Labs, LLC. // See www.armresearch.com for the copyright terms. // // SNF Header Finder used for identifying headers in a message. A header match // is defined by the name of the header, it's ordinal, and some string that is // contained in that header. If the pattern is matched then one or more bits // are set in a 32 bit status flag. Usually, one bit at a time. Other matchers // that intend to set the same bits as are already set are turned off to save // cycles. // // The initial implementation of this engine is for turning off GBUdb learning // when one of the defined headers is matched. Other uses are likely to be // developed. This engine will have to evolve as that occurrs. // // The evaluation of the status flag is defined by the application. #pragma once #include #include #include #include struct HeaderFinderPattern { // Input pattern for header finder. std::string Header; // Header name to match. int Ordinal; // Which instance to match. int Context; // Context link (for pairing patterns). std::string Contains; // What to find in the header. unsigned long int Directive; // What directive to present. HeaderFinderPattern(): // When constructing a finder parttern Header(""),Ordinal(0),Context(0),Contains(""),Directive(0){} // initialize it like this. HeaderFinderPattern(const HeaderFinderPattern& P); // Copy constructor. void clear(); // Do this to make fresh and clean. HeaderFinderPattern& operator=(const HeaderFinderPattern& R); // Assignment operator. const bool operator<(const HeaderFinderPattern& R) const; // Comparator for set<> living. }; typedef std::set HeaderDirectiveSet; // Convenient set typedef. typedef std::set::iterator HeaderDirectiveIterator; // Convenient iterator typedef. typedef std::map NameOrdinalMap; // Header Ordinal Count Map. // Upon construction the HeaderFinder scans the headers for matching directives // and leaves the composite results ready for inspection via the () operator. // UnfoldHeaders() strips and unfolds the headers then passes them to // MatchHeaders() which tracks the ordinals for matching directives and passes // those headers to CheckContent() to see if the required patterns are found. // CheckContent() then updates the Directives if the appropriate content is // found. class snfScanData; // Yes, this does exist. class HeaderFinder { // Header Finder Object. private: snfScanData* ScanData; // Scanner control data. const HeaderDirectiveSet& HeaderDirectives; // Handle for the directives/patterns. const unsigned char* Bfr; // Message buffer. const int Len; // Message length. std::vector ImpossibleBytes; // Cache of known impossible bytes. unsigned long int Directives; // Composite result given this message. std::set ActivatedContexts; // Set of activated contexts. NameOrdinalMap Ordinals; // Map of current header ordinals. void CheckContent(std::string& Header, const HeaderFinderPattern& P); // Check for a match in the header. void MatchHeaders(std::string& Header); // Check that the header matches. bool ByteIsImpossible(unsigned char b); // Is b not first byte of any pattern? void UnfoldHeaders(); // Unfold and check headers. public: HeaderFinder( // The constructor reads the message. snfScanData* EngineScanData, // -- Scanner control data ptr. const HeaderDirectiveSet& Patterns, // -- this is the set of patterns. const unsigned char* MessageBuffer, // -- this is the message buffer. const int MessageLength // -- this is the length of the buffer. ); const unsigned long int operator()() const; // How to read the composite directives. std::string EstablishedSourceIP; // Source IP from directive if any. };