mirror of
https://github.com/zeek/zeek.git
synced 2025-10-11 11:08:20 +00:00
Documenting Analyzer API, plus some cleanup.
This commit is contained in:
parent
20be34526f
commit
2bbce6b15f
8 changed files with 646 additions and 206 deletions
|
@ -16,7 +16,6 @@ public:
|
|||
{ return new AYIYA_Analyzer(conn); }
|
||||
|
||||
protected:
|
||||
friend class AnalyzerTimer;
|
||||
void ExpireTimer(double t);
|
||||
|
||||
binpac::AYIYA::AYIYA_Conn* interp;
|
||||
|
|
|
@ -16,7 +16,6 @@ public:
|
|||
{ return new GTPv1_Analyzer(conn); }
|
||||
|
||||
protected:
|
||||
friend class AnalyzerTimer;
|
||||
void ExpireTimer(double t);
|
||||
|
||||
binpac::GTPv1::GTPv1_Conn* interp;
|
||||
|
|
|
@ -19,7 +19,6 @@ public:
|
|||
{ return new Syslog_Analyzer_binpac(conn); }
|
||||
|
||||
protected:
|
||||
friend class AnalyzerTimer;
|
||||
void ExpireTimer(double t);
|
||||
|
||||
int did_session_done;
|
||||
|
|
|
@ -1556,12 +1556,6 @@ void TCP_Analyzer::ConnDeleteTimer(double t)
|
|||
Conn()->DeleteTimer(t);
|
||||
}
|
||||
|
||||
// The following need to be consistent with bro.init.
|
||||
#define CONTENTS_NONE 0
|
||||
#define CONTENTS_ORIG 1
|
||||
#define CONTENTS_RESP 2
|
||||
#define CONTENTS_BOTH 3
|
||||
|
||||
void TCP_Analyzer::SetContentsFile(unsigned int direction, BroFile* f)
|
||||
{
|
||||
if ( direction == CONTENTS_NONE )
|
||||
|
|
|
@ -47,7 +47,6 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
friend class AnalyzerTimer;
|
||||
void ExpireTimer(double t);
|
||||
|
||||
bool valid_orig;
|
||||
|
|
|
@ -7,8 +7,39 @@
|
|||
#include "../PIA.h"
|
||||
#include "../Event.h"
|
||||
|
||||
namespace analyzer {
|
||||
|
||||
|
||||
class AnalyzerTimer : public Timer {
|
||||
public:
|
||||
AnalyzerTimer(Analyzer* arg_analyzer, analyzer_timer_func arg_timer,
|
||||
double arg_t, int arg_do_expire, TimerType arg_type);
|
||||
|
||||
virtual ~AnalyzerTimer();
|
||||
|
||||
void Dispatch(double t, int is_expire);
|
||||
|
||||
protected:
|
||||
AnalyzerTimer() {}
|
||||
|
||||
void Init(Analyzer* analyzer, analyzer_timer_func timer, int do_expire);
|
||||
|
||||
Analyzer* analyzer;
|
||||
analyzer_timer_func timer;
|
||||
int do_expire;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using namespace analyzer;
|
||||
|
||||
AnalyzerTimer::AnalyzerTimer(Analyzer* arg_analyzer, analyzer_timer_func arg_timer,
|
||||
double arg_t, int arg_do_expire, TimerType arg_type)
|
||||
: Timer(arg_t, arg_type)
|
||||
{
|
||||
Init(arg_analyzer, arg_timer, arg_do_expire);
|
||||
}
|
||||
|
||||
AnalyzerTimer::~AnalyzerTimer()
|
||||
{
|
||||
analyzer->RemoveTimer(this);
|
||||
|
|
|
@ -17,270 +17,556 @@ class PIA;
|
|||
class IP_Hdr;
|
||||
class TCP_ApplicationAnalyzer;
|
||||
|
||||
namespace analyzer { class Analyzer; }
|
||||
|
||||
namespace analyzer {
|
||||
|
||||
typedef list<Analyzer*> analyzer_list;
|
||||
|
||||
typedef uint32 ID;
|
||||
|
||||
typedef void (Analyzer::*analyzer_timer_func)(double t);
|
||||
|
||||
// FIXME: This is a copy of ConnectionTimer, which we may eventually be
|
||||
// able to get rid of.
|
||||
class AnalyzerTimer : public Timer {
|
||||
public:
|
||||
AnalyzerTimer(Analyzer* arg_analyzer, analyzer_timer_func arg_timer,
|
||||
double arg_t, int arg_do_expire, TimerType arg_type)
|
||||
: Timer(arg_t, arg_type)
|
||||
{ Init(arg_analyzer, arg_timer, arg_do_expire); }
|
||||
virtual ~AnalyzerTimer();
|
||||
|
||||
void Dispatch(double t, int is_expire);
|
||||
|
||||
protected:
|
||||
AnalyzerTimer() {}
|
||||
|
||||
void Init(Analyzer* analyzer, analyzer_timer_func timer, int do_expire);
|
||||
|
||||
Analyzer* analyzer;
|
||||
analyzer_timer_func timer;
|
||||
int do_expire;
|
||||
};
|
||||
|
||||
|
||||
// Main analyzer interface.
|
||||
//
|
||||
// Each analyzer is part of a tree, having a parent analyzer and an
|
||||
// arbitrary number of child analyzers. Each analyzer also has a list of
|
||||
// *suppport analyzers*. All its input first passes through this list of
|
||||
// support analyzers, which can perform arbitrary preprocessing. Support
|
||||
// analyzers share the same interface as regular analyzers, except that
|
||||
// they are unidirectional, i.e., they see only one side of a connection.
|
||||
//
|
||||
// When overiding any of these methods, always make sure to call the
|
||||
// base-class version first.
|
||||
|
||||
class Analyzer;
|
||||
class AnalyzerTimer;
|
||||
class SupportAnalyzer;
|
||||
class OutputHandler;
|
||||
|
||||
typedef list<Analyzer*> analyzer_list;
|
||||
typedef uint32 ID;
|
||||
typedef void (Analyzer::*analyzer_timer_func)(double t);
|
||||
|
||||
/**
|
||||
* XXX
|
||||
*/
|
||||
class OutputHandler {
|
||||
public:
|
||||
virtual ~OutputHandler() { }
|
||||
|
||||
virtual void DeliverPacket(int len, const u_char* data,
|
||||
bool orig, int seq,
|
||||
const IP_Hdr* ip, int caplen)
|
||||
{ }
|
||||
virtual void DeliverStream(int len, const u_char* data,
|
||||
bool orig) { }
|
||||
virtual void Undelivered(int seq, int len, bool orig) { }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Main analyzer interface.
|
||||
*
|
||||
* Each analyzer is part of a tree, having a parent analyzer and an arbitrary
|
||||
* number of child analyzers. Each analyzer also has a list of
|
||||
* SupportAnalyzer. All analyzer input first passes through this list of
|
||||
* support analyzers, which can perform arbitrary preprocessing.
|
||||
*
|
||||
* When overiding any of the class' methods, always make sure to call the
|
||||
* base-class version first.
|
||||
*/
|
||||
class Analyzer {
|
||||
public:
|
||||
// "name" must match the one used in
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name A name for the protocol the analyzer is parsing. The
|
||||
* name must match the one the corresponding Component registers.
|
||||
*
|
||||
* @param conn The connection the analyzer is associated with.
|
||||
*/
|
||||
Analyzer(const char* name, Connection* conn);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~Analyzer();
|
||||
|
||||
/**
|
||||
* Initializes the analyzer before input processing starts.
|
||||
*/
|
||||
virtual void Init();
|
||||
|
||||
/**
|
||||
* Finishes the analyzer's operation after all input has been parsed.
|
||||
*/
|
||||
virtual void Done();
|
||||
|
||||
// Pass data to the analyzer (it's automatically passed through its
|
||||
// support analyzers first). We have packet-wise and stream-wise
|
||||
// interfaces. For the packet-interface, some analyzers may require
|
||||
// more information than others, so IP/caplen and seq may or may
|
||||
// not be set.
|
||||
void NextPacket(int len, const u_char* data, bool orig,
|
||||
/**
|
||||
* Passes packet input to the analyzer for processing. The analyzer
|
||||
* will process the input with any support analyzers first and then
|
||||
* forward the data to DeliverStream(), which derived classes can
|
||||
* override.
|
||||
*
|
||||
* Note that there is a separate method for stream input,
|
||||
* NextStream().
|
||||
*
|
||||
* @param len The number of bytes passed in.
|
||||
*
|
||||
* @param data Pointer the input to process.
|
||||
*
|
||||
* @param is_orig True if this is originator-side input.
|
||||
*
|
||||
* @param seq Current sequence number, if available (only supported
|
||||
* if the data is coming from the TCP analyzer.
|
||||
*
|
||||
* @param ip An IP packet header associated with the data, if
|
||||
* available.
|
||||
*
|
||||
* @param caplen The packet's capture length, if available.
|
||||
*/
|
||||
void NextPacket(int len, const u_char* data, bool is_orig,
|
||||
int seq = -1, const IP_Hdr* ip = 0, int caplen = 0);
|
||||
|
||||
/**
|
||||
* Passes stream input to the analyzer for processing. The analyzer
|
||||
* will process the input with any support analyzers first and then
|
||||
* forward the data to DeliverStream(), which derived classes can
|
||||
* override.
|
||||
*
|
||||
* Note that there is a separate method for packet input,
|
||||
* NextPacket().
|
||||
*
|
||||
* @param len The number of bytes passed in.
|
||||
*
|
||||
* @param data Pointer the input to process.
|
||||
*
|
||||
* @param is_orig True if this is originator-side input.
|
||||
*/
|
||||
void NextStream(int len, const u_char* data, bool is_orig);
|
||||
|
||||
// Used for data that can't be delivered (e.g., due to a previous
|
||||
// sequence hole/gap).
|
||||
/**
|
||||
* Informs the analyzer about a gap in the TCP stream, i.e., data
|
||||
* that can't be delivered. This method triggers Undelivered(), which
|
||||
* derived classes can override.
|
||||
*
|
||||
* @param seq The sequence number of the first byte of gap.
|
||||
*
|
||||
* @param len The length of the gap.
|
||||
*
|
||||
* @param is_orig True if this is about originator-side input.
|
||||
*/
|
||||
void NextUndelivered(int seq, int len, bool is_orig);
|
||||
|
||||
// Report message boundary. (See EndOfData() below.)
|
||||
void NextEndOfData(bool orig);
|
||||
/**
|
||||
* Reports a message boundary. This is a generic method that can be
|
||||
* used by an Analyzer if all data of a PDU has been delivered, e.g.,
|
||||
* to report that HTTP body has been delivered completely by the HTTP
|
||||
* analyzer before it starts with the next body. A final EndOfData()
|
||||
* is automatically generated by the analyzer's Done() method. This
|
||||
* method triggers EndOfData(), which derived classes can override.
|
||||
*
|
||||
* @param is_orig True if this is about originator-side input.
|
||||
*/
|
||||
void NextEndOfData(bool is_orig);
|
||||
|
||||
// Pass data on to all child analyzer(s). For SupportAnalyzers (see
|
||||
// below), this is overridden to pass it on to the next sibling (or
|
||||
// finally to the parent, if it's the last support analyzer).
|
||||
//
|
||||
// If we have an associated OutputHandler (see below), the data is
|
||||
// additionally passed to that, too. For SupportAnalyzers, it is *only*
|
||||
// delivered to the OutputHandler.
|
||||
/**
|
||||
* Forwards packet input on to all child analyzers. If the analyzer
|
||||
* has an associated OutputHandlers, that one receives the input as
|
||||
* well.
|
||||
*
|
||||
* Parameters are the same as for NextPacket().
|
||||
*/
|
||||
virtual void ForwardPacket(int len, const u_char* data,
|
||||
bool orig, int seq,
|
||||
const IP_Hdr* ip, int caplen);
|
||||
|
||||
/**
|
||||
* Forwards stream input on to all child analyzers. If the analyzer
|
||||
* has an associated OutputHandlers, that one receives the input as
|
||||
* well.
|
||||
*
|
||||
* Parameters are the same as for NextStream().
|
||||
*/
|
||||
virtual void ForwardStream(int len, const u_char* data, bool orig);
|
||||
|
||||
/**
|
||||
* Forwards a sequence gap on to all child analyzers.
|
||||
*
|
||||
* Parameters are the same as for NextUndelivered().
|
||||
*/
|
||||
virtual void ForwardUndelivered(int seq, int len, bool orig);
|
||||
|
||||
// Report a message boundary to all child analyzers
|
||||
/**
|
||||
* Forwards an end-of-data notification on to all child analyzers.
|
||||
*
|
||||
* Parameters are the same as for NextPacket().
|
||||
*/
|
||||
virtual void ForwardEndOfData(bool orig);
|
||||
|
||||
ID GetID() const { return id; }
|
||||
Connection* Conn() const { return conn; }
|
||||
|
||||
// An OutputHandler can be used to get access to data extracted by this
|
||||
// analyzer (i.e., all data which is passed to
|
||||
// Forward{Packet,Stream,Undelivered}). We take the ownership of
|
||||
// the handler.
|
||||
class OutputHandler {
|
||||
public:
|
||||
virtual ~OutputHandler() { }
|
||||
|
||||
virtual void DeliverPacket(int len, const u_char* data,
|
||||
bool orig, int seq,
|
||||
const IP_Hdr* ip, int caplen)
|
||||
{ }
|
||||
virtual void DeliverStream(int len, const u_char* data,
|
||||
bool orig) { }
|
||||
virtual void Undelivered(int seq, int len, bool orig) { }
|
||||
};
|
||||
|
||||
OutputHandler* GetOutputHandler() const { return output_handler; }
|
||||
void SetOutputHandler(OutputHandler* handler)
|
||||
{ output_handler = handler; }
|
||||
|
||||
// If an analyzer was triggered by a signature match, this returns the
|
||||
// name of the signature; nil if not.
|
||||
const Rule* Signature() const { return signature; }
|
||||
void SetSignature(const Rule* sig) { signature = sig; }
|
||||
|
||||
void SetSkip(bool do_skip) { skip = do_skip; }
|
||||
bool Skipping() const { return skip; }
|
||||
|
||||
bool IsFinished() const { return finished; }
|
||||
|
||||
Tag GetAnalyzerTag() const { return tag; }
|
||||
const string& GetAnalyzerName() const;
|
||||
bool IsAnalyzer(const char* name);
|
||||
|
||||
// Management of the tree.
|
||||
//
|
||||
// We immediately discard an added analyzer if there's already a child
|
||||
// of the same type.
|
||||
void AddChildAnalyzer(Analyzer* analyzer)
|
||||
{ AddChildAnalyzer(analyzer, true); }
|
||||
Analyzer* AddChildAnalyzer(Tag tag);
|
||||
|
||||
void RemoveChildAnalyzer(Analyzer* analyzer);
|
||||
void RemoveChildAnalyzer(ID id);
|
||||
|
||||
bool HasChildAnalyzer(Tag tag);
|
||||
|
||||
// Recursive; returns nil if not found.
|
||||
Analyzer* FindChild(ID id);
|
||||
|
||||
// Recursive; returns first found, or nil.
|
||||
Analyzer* FindChild(Tag tag);
|
||||
|
||||
// Recursive; returns first found, or nil.
|
||||
Analyzer* FindChild(const string& name);
|
||||
|
||||
const analyzer_list& GetChildren() { return children; }
|
||||
|
||||
Analyzer* Parent() const { return parent; }
|
||||
void SetParent(Analyzer* p) { parent = p; }
|
||||
|
||||
// Remove this child analyzer from the parent's list.
|
||||
void Remove() { assert(parent); parent->RemoveChildAnalyzer(this); }
|
||||
|
||||
// Management of support analyzers. Support analyzers are associated
|
||||
// with a direction, and will only see data in the corresponding flow.
|
||||
//
|
||||
// We immediately discard an added analyzer if there's already a child
|
||||
// of the same type for the same direction.
|
||||
|
||||
// Adds to tail of list.
|
||||
void AddSupportAnalyzer(SupportAnalyzer* analyzer);
|
||||
|
||||
void RemoveSupportAnalyzer(SupportAnalyzer* analyzer);
|
||||
|
||||
// These are the methods where the analyzer actually gets its input.
|
||||
// Each analyzer has only to implement the schemes it supports.
|
||||
|
||||
// Packet-wise (or more generally chunk-wise) input. "data" points
|
||||
// to the payload that the analyzer is supposed to examine. If it's
|
||||
// part of a full packet, "ip" points to its IP header. An analyzer
|
||||
// may or may not require to be given the full packet (and its caplen)
|
||||
// as well.
|
||||
/**
|
||||
* Hook for accessing packet input for parsing. This is called by
|
||||
* NextDeliverPacket() and can be overridden by derived classes.
|
||||
* Parameters are the same.
|
||||
*/
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
// Stream-wise payload input.
|
||||
/**
|
||||
* Hook for accessing stream input for parsing. This is called by
|
||||
* NextDeliverStream() and can be overridden by derived classes.
|
||||
* Parameters are the same.
|
||||
*/
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
|
||||
// If a parent analyzer can't turn a sequence of packets into a stream
|
||||
// (e.g., due to holes), it can pass the remaining data through this
|
||||
// method to the child.
|
||||
/**
|
||||
* Hook for accessing input gap during parsing. This is called by
|
||||
* NextUndelivered() and can be overridden by derived classes.
|
||||
* Parameters are the same.
|
||||
*/
|
||||
virtual void Undelivered(int seq, int len, bool orig);
|
||||
|
||||
// Report a message boundary. This is a generic method that can be used
|
||||
// by specific Analyzers if all data of a message has been delivered,
|
||||
// e.g., to report that HTTP body has been delivered completely by the
|
||||
// HTTP analyzer before it starts with the next body. EndOfData() is
|
||||
// automatically generated by the analyzer's Done() method.
|
||||
/**
|
||||
* Hook for accessing end-of-data notifications. This is called by
|
||||
* NextEndOfData() and can be overridden by derived classes.
|
||||
* Parameters are the same.
|
||||
*/
|
||||
virtual void EndOfData(bool is_orig);
|
||||
|
||||
// Occasionally we may find during analysis that we got the direction
|
||||
// of the connection wrong. In these cases, this method is called
|
||||
// to swap state if necessary. This will not happen after payload
|
||||
// has already been passed on, so most analyzers don't need to care.
|
||||
/**
|
||||
* Signals the analyzer that its associated connection had its
|
||||
* endpoint flipped. This can happen if during analysis it turns out
|
||||
* that we got the direction of the connection wrong. In these
|
||||
* cases, this method is called to swap state if necessary. This
|
||||
* will not happen after payload has already been passed on, so most
|
||||
* analyzers don't need to care.
|
||||
*/
|
||||
virtual void FlipRoles();
|
||||
|
||||
// Feedback about protocol conformance, to be called by the
|
||||
// analyzer's processing. The methods raise the correspondiong
|
||||
// protocol_confirmation and protocol_violation events.
|
||||
/**
|
||||
* Returns the analyzer instance's internal ID. These IDs are unique
|
||||
* across all analyzer instantiated and can thus be used to indentify
|
||||
* a specific instance.
|
||||
*/
|
||||
ID GetID() const { return id; }
|
||||
|
||||
// Report that we believe we're parsing the right protocol. This
|
||||
// should be called as early as possible during a connection's
|
||||
// life-time. The protocol_confirmed event is only raised once per
|
||||
// analyzer, even if the method is called multiple times.
|
||||
virtual void ProtocolConfirmation();
|
||||
/**
|
||||
* Returns the connection that the analyzer is associated with.
|
||||
*/
|
||||
Connection* Conn() const { return conn; }
|
||||
|
||||
// Return whether the analyzer previously called ProtocolConfirmation()
|
||||
// at least once before.
|
||||
bool ProtocolConfirmed() const
|
||||
{ return protocol_confirmed; }
|
||||
/**
|
||||
* Returns the OutputHandler associated with the connection, or null
|
||||
* if none.
|
||||
*/
|
||||
OutputHandler* GetOutputHandler() const { return output_handler; }
|
||||
|
||||
// Report that we found a significant protocol violation which might
|
||||
// indicate that the analyzed data is in fact not the expected
|
||||
// protocol. The protocol_violation event is raised once per call to
|
||||
// this method so that the script-level may build up some notion of
|
||||
// how "severely" protocol semantics are violated.
|
||||
/**
|
||||
* Associates an OutputHandler with the connnection.
|
||||
*
|
||||
* @param handler The handler.
|
||||
*/
|
||||
void SetOutputHandler(OutputHandler* handler)
|
||||
{ output_handler = handler; }
|
||||
|
||||
/**
|
||||
* If this analyzer was activated by a signature match, this returns
|
||||
* the signature that did so. Returns null otherwise.
|
||||
*/
|
||||
const Rule* Signature() const { return signature; }
|
||||
|
||||
/**
|
||||
* Sets the signature that activated this analyzer, if any.
|
||||
*
|
||||
* @param sig The signature.
|
||||
*/
|
||||
void SetSignature(const Rule* sig) { signature = sig; }
|
||||
|
||||
/**
|
||||
* Signals the analyzer to skip all further input processsing. The \a
|
||||
* Next*() methods check this flag and discard the input if its set.
|
||||
*
|
||||
* @param do_skipe If true, further processing will be skipped.
|
||||
*/
|
||||
void SetSkip(bool do_skip) { skip = do_skip; }
|
||||
|
||||
/**
|
||||
* Returns true if the analyzer has been told to skip processing all
|
||||
* further input.
|
||||
*/
|
||||
bool Skipping() const { return skip; }
|
||||
|
||||
/**
|
||||
* Returns true if Done() has been called.
|
||||
*/
|
||||
bool IsFinished() const { return finished; }
|
||||
|
||||
/**
|
||||
* Returns the tag associated with the analyzer's type.
|
||||
*/
|
||||
Tag GetAnalyzerTag() const { return tag; }
|
||||
|
||||
/**
|
||||
* Returns a textual description of the analyzer's type. This is
|
||||
* what's passed to the constructor and usally corresponds to the
|
||||
* protocol name, e.g., "HTTP".
|
||||
*/
|
||||
const string& GetAnalyzerName() const;
|
||||
|
||||
/**
|
||||
* Returns true if this analyzer's type matches the name passes in.
|
||||
* This is shortcut for comparing GetAnalyzerName() with the given
|
||||
* name.
|
||||
*
|
||||
* @param name The name to check.
|
||||
*/
|
||||
bool IsAnalyzer(const char* name);
|
||||
|
||||
/**
|
||||
* Adds a new child analyzer to the analyzer tree. If an analyzer of
|
||||
* the same type already exists, the one passes in is silenty
|
||||
* discarded.
|
||||
*
|
||||
* @param analyzer The ananlyzer to add. Takes ownership.
|
||||
*/
|
||||
void AddChildAnalyzer(Analyzer* analyzer)
|
||||
{ AddChildAnalyzer(analyzer, true); }
|
||||
|
||||
/**
|
||||
* Adds a new child analyzer to the analyzer tree. If an analyzer of
|
||||
* the same type already exists, the one passes in is silenty
|
||||
* discarded.
|
||||
*
|
||||
* @param tag The type of analyzer to add.
|
||||
*/
|
||||
Analyzer* AddChildAnalyzer(Tag tag);
|
||||
|
||||
/**
|
||||
* Removes a child analyzer. It's ok for the analyzer to not to be a
|
||||
* child, in which case the method does nothing.
|
||||
*
|
||||
* @param analyzer The analyzer to remove.
|
||||
*/
|
||||
void RemoveChildAnalyzer(Analyzer* analyzer);
|
||||
|
||||
/**
|
||||
* Removes a child analyzer. It's ok for the analyzer to not to be a
|
||||
* child, in which case the method does nothing.
|
||||
*
|
||||
* @param tag The type of analyzer to remove.
|
||||
*/
|
||||
void RemoveChildAnalyzer(ID id);
|
||||
|
||||
/**
|
||||
* Returns true if analyzer has a direct child of a given type.
|
||||
*
|
||||
* @param tag The type of analyzer to check for.
|
||||
*/
|
||||
bool HasChildAnalyzer(Tag tag);
|
||||
|
||||
/**
|
||||
* Recursively searches all (direct or indirect) childs of the
|
||||
* analyzer for an analyzer with a specific ID.
|
||||
*
|
||||
* @param id The analyzer id to search. This is the ID that GetID()
|
||||
* returns.
|
||||
*
|
||||
* @return The analyzer, or null if not found.
|
||||
*/
|
||||
Analyzer* FindChild(ID id);
|
||||
|
||||
/**
|
||||
* Recursively searches all (direct or indirect) childs of the
|
||||
* analyzer for an analyzer of a given type.
|
||||
*
|
||||
* @param tag The analyzer type to search.
|
||||
*
|
||||
* @return The first analyzer of the given type found, or null if
|
||||
* none.
|
||||
*/
|
||||
Analyzer* FindChild(Tag tag);
|
||||
|
||||
/**
|
||||
* Recursively searches all (direct or indirect) childs of the
|
||||
* analyzer for an analyzer of a given type.
|
||||
*
|
||||
* @param name The naem of the analyzer type to search (e.g.,
|
||||
* "HTTP").
|
||||
*
|
||||
* @return The first analyzer of the given type found, or null if
|
||||
* none.
|
||||
*/
|
||||
Analyzer* FindChild(const string& name);
|
||||
|
||||
/**
|
||||
* Returns a list of all direct child analyzers.
|
||||
*/
|
||||
const analyzer_list& GetChildren() { return children; }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the parent analyzer, or null if this instance
|
||||
* has not yet been added to an analyzer tree.
|
||||
*/
|
||||
Analyzer* Parent() const { return parent; }
|
||||
|
||||
/**
|
||||
* Sets the parent analyzer.
|
||||
*
|
||||
* @param p The new parent.
|
||||
*/
|
||||
void SetParent(Analyzer* p) { parent = p; }
|
||||
|
||||
/**
|
||||
* Remove the analyzer form its parent. The analyzer must have a
|
||||
* parent associated with it.
|
||||
*/
|
||||
void Remove() { assert(parent); parent->RemoveChildAnalyzer(this); }
|
||||
|
||||
/**
|
||||
* Appends a support analyzer to the current list.
|
||||
*
|
||||
* @param analyzer The support analyzer to add.
|
||||
*/
|
||||
void AddSupportAnalyzer(SupportAnalyzer* analyzer);
|
||||
|
||||
/**
|
||||
* Remove a support analyzer.
|
||||
*
|
||||
* @param analyzer The analyzer to remove. The function is a no-op if
|
||||
* that analyzer is not part of the list of support analyzer.
|
||||
*/
|
||||
void RemoveSupportAnalyzer(SupportAnalyzer* analyzer);
|
||||
|
||||
/**
|
||||
* Signals Bro's protocol detection that the analyzer has recognized
|
||||
* the input to indeed conform to the expected protocol. This should
|
||||
* be called as early as possible during a connection's life-time. It
|
||||
* may turn into \c protocol_confirmed event at the script-layer (but
|
||||
* only once per analyzer for each connection, even if the method is
|
||||
* called multiple times).
|
||||
*/
|
||||
virtual void ProtocolConfirmation();
|
||||
|
||||
/**
|
||||
* Signals Bro's protocol detection that the analyzer has found a
|
||||
* severe protocol violation that could indicate that it's not
|
||||
* parsing the expected protocol. This turns into \c
|
||||
* protocol_violation events at the script-layer (one such event is
|
||||
* raised for each call to this method so that the script-layer can
|
||||
* built up a notion of how prevalent protocol violations are; the
|
||||
* more, the less likely it's the right protocol).
|
||||
*
|
||||
* @param reason A textual description of the error encountered.
|
||||
*
|
||||
* @param data An optional pointer to the malformed data.
|
||||
*
|
||||
* @param len If \a data is given, the length of it.
|
||||
*/
|
||||
virtual void ProtocolViolation(const char* reason,
|
||||
const char* data = 0, int len = 0);
|
||||
|
||||
virtual unsigned int MemoryAllocation() const;
|
||||
/**
|
||||
* Returns true if ProtocolConfirmation() has been called at least
|
||||
* once.
|
||||
*/
|
||||
bool ProtocolConfirmed() const
|
||||
{ return protocol_confirmed; }
|
||||
|
||||
// Called whenever the connection value needs to be updated. Per
|
||||
// default, this method will be called for each analyzer in the tree.
|
||||
// Analyzers can use this method to attach additional data to the
|
||||
// connections. A call to BuildConnVal will in turn trigger a call to
|
||||
// UpdateConnVal.
|
||||
/**
|
||||
* Called whenever the connection value is updated. Per default, this
|
||||
* method will be called for each analyzer in the tree. Analyzers can
|
||||
* use this method to attach additional data to the connections. A
|
||||
* call to BuildConnVal() will in turn trigger a call to
|
||||
* UpdateConnVal().
|
||||
*
|
||||
* @param conn_val The connenction value being updated.
|
||||
*/
|
||||
virtual void UpdateConnVal(RecordVal *conn_val);
|
||||
|
||||
// The following methods are proxies: calls are directly forwarded
|
||||
// to the connection instance. These are for convenience only,
|
||||
// allowing us to reuse more of the old analyzer code unchanged.
|
||||
/**
|
||||
* Convinience function that forwards directly to
|
||||
* Connection::BuildConnVal().
|
||||
*/
|
||||
RecordVal* BuildConnVal();
|
||||
|
||||
/**
|
||||
* Convinience function that forwards directly to the corresponding
|
||||
* Connection::Event().
|
||||
*/
|
||||
void Event(EventHandlerPtr f, const char* name = 0);
|
||||
|
||||
/**
|
||||
* Convinience function that forwards directly to the corresponding
|
||||
* Connection::Event().
|
||||
*/
|
||||
void Event(EventHandlerPtr f, Val* v1, Val* v2 = 0);
|
||||
|
||||
/**
|
||||
* Convinience function that forwards directly to
|
||||
* Connection::ConnectionEvent().
|
||||
*/
|
||||
void ConnectionEvent(EventHandlerPtr f, val_list* vl);
|
||||
|
||||
/**
|
||||
* Convinience function that forwards directly to the corresponding
|
||||
* Connection::Weird().
|
||||
*/
|
||||
void Weird(const char* name, const char* addl = "");
|
||||
|
||||
/**
|
||||
* Internal method.
|
||||
*/
|
||||
virtual unsigned int MemoryAllocation() const;
|
||||
|
||||
protected:
|
||||
friend class AnalyzerTimer;
|
||||
friend class Manager;
|
||||
friend class ::Connection;
|
||||
friend class ::TCP_ApplicationAnalyzer;
|
||||
|
||||
// Associates a connection with this analyzer. Must be called if
|
||||
// we're using the default ctor.
|
||||
/**
|
||||
* Associates a connection with this analyzer. Must be called if
|
||||
* using the default ctor.
|
||||
*
|
||||
* @param c The connection.
|
||||
*/
|
||||
void SetConnection(Connection* c) { conn = c; }
|
||||
|
||||
// Creates the given timer to expire at time t. If do_expire
|
||||
// is true, then the timer is also evaluated when Bro terminates,
|
||||
// otherwise not.
|
||||
/**
|
||||
* Instantiates a new timer associated with the analyzer.
|
||||
*
|
||||
* @param timer The callback function to execute when the timer
|
||||
* fires.
|
||||
*
|
||||
* @param t The absolute time when the timer will fire.
|
||||
*
|
||||
* @param do_expire If true, the timer will also fire when Bro
|
||||
* terminates even if \a t has not been reache yet.
|
||||
*
|
||||
* @param type The timer's type.
|
||||
*/
|
||||
void AddTimer(analyzer_timer_func timer, double t, int do_expire,
|
||||
TimerType type);
|
||||
|
||||
void RemoveTimer(Timer* t);
|
||||
/**
|
||||
* Cancels all timers added previously via AddTimer().
|
||||
*/
|
||||
void CancelTimers();
|
||||
|
||||
/**
|
||||
* Removes a given timer. This is an internal method and shouldn't be
|
||||
* used by derived class. It does not cancel the timer.
|
||||
*/
|
||||
void RemoveTimer(Timer* t);
|
||||
|
||||
/**
|
||||
* Returnsn true if the analyzer has associated an SupportAnalyzer of a given type.
|
||||
*
|
||||
* @param tag The type to check for.
|
||||
*
|
||||
* @param orig True if asking about the originator side.
|
||||
*/
|
||||
bool HasSupportAnalyzer(Tag tag, bool orig);
|
||||
|
||||
/**
|
||||
* Adds a a new child analyzer with the option whether to intialize
|
||||
* it. This is an internal method.
|
||||
*
|
||||
* @param analyzer The analyzer to add. Takes ownership.
|
||||
*
|
||||
* @param init If true, Init() will be calle.d
|
||||
*/
|
||||
void AddChildAnalyzer(Analyzer* analyzer, bool init);
|
||||
|
||||
/**
|
||||
* Inits all child analyzers. This is an internal method.
|
||||
*/
|
||||
void InitChildren();
|
||||
|
||||
/**
|
||||
* Reorganizes the child data structure. This is an internal method.
|
||||
*/
|
||||
void AppendNewChildren();
|
||||
|
||||
private:
|
||||
|
@ -313,39 +599,109 @@ private:
|
|||
static ID id_counter;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience macro to add a new timer.
|
||||
*/
|
||||
#define ADD_ANALYZER_TIMER(timer, t, do_expire, type) \
|
||||
AddTimer(analyzer::analyzer_timer_func(timer), (t), (do_expire), (type))
|
||||
|
||||
/**
|
||||
* Internal convenience macro to iterate over the list of child analyzers.
|
||||
*/
|
||||
#define LOOP_OVER_CHILDREN(var) \
|
||||
for ( analyzer::analyzer_list::iterator var = children.begin(); \
|
||||
var != children.end(); var++ )
|
||||
|
||||
/**
|
||||
* Internal convenience macro to iterate over the constant list of child
|
||||
* analyzers.
|
||||
*/
|
||||
#define LOOP_OVER_CONST_CHILDREN(var) \
|
||||
for ( analyzer::analyzer_list::const_iterator var = children.begin(); \
|
||||
var != children.end(); var++ )
|
||||
|
||||
/**
|
||||
* Convenience macro to iterate over a given list of child analyzers.
|
||||
*/
|
||||
#define LOOP_OVER_GIVEN_CHILDREN(var, the_kids) \
|
||||
for ( analyzer::analyzer_list::iterator var = the_kids.begin(); \
|
||||
var != the_kids.end(); var++ )
|
||||
|
||||
/**
|
||||
* Convenience macro to iterate over a given constant list of child
|
||||
* analyzers.
|
||||
*/
|
||||
#define LOOP_OVER_GIVEN_CONST_CHILDREN(var, the_kids) \
|
||||
for ( analyzer::analyzer_list::const_iterator var = the_kids.begin(); \
|
||||
var != the_kids.end(); var++ )
|
||||
|
||||
/**
|
||||
* Support analyzer preprocess input before it reaches an analyzer's main
|
||||
* processing. They share the input interface with of an Analyzer but they
|
||||
* are uni-directional: they receive data only from one side of a connection.
|
||||
*
|
||||
*/
|
||||
class SupportAnalyzer : public Analyzer {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name A name for the protocol the analyzer is parsing. The
|
||||
* name must match the one the corresponding Component registers.
|
||||
*
|
||||
* @param conn The connection the analyzer is associated with.
|
||||
*
|
||||
* @param arg_orig: If true, this is a support analyzer for the
|
||||
* connection originator side, and otherwise for the responder side.
|
||||
*/
|
||||
SupportAnalyzer(const char* name, Connection* conn, bool arg_orig)
|
||||
: Analyzer(name, conn) { orig = arg_orig; sibling = 0; }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~SupportAnalyzer() {}
|
||||
|
||||
/**
|
||||
* Returns true if this is a support analyzer for the connection's
|
||||
* originator side.
|
||||
*/
|
||||
bool IsOrig() const { return orig; }
|
||||
|
||||
/**
|
||||
* Passes packet input to the next sibling SupportAnalyzer if any, or
|
||||
* on to the associated main analyzer if none. If however there's an
|
||||
* output handler associated with this support analyzer, the data is
|
||||
* passed only to there.
|
||||
*
|
||||
* Parameters same as for Analyzer::ForwardPacket.
|
||||
*/
|
||||
virtual void ForwardPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
/**
|
||||
* Passes stream input to the next sibling SupportAnalyzer if any, or
|
||||
* on to the associated main analyzer if none. If however there's an
|
||||
* output handler associated with this support analyzer, the data is
|
||||
* passed only to there.
|
||||
*
|
||||
* Parameters same as for Analyzer::ForwardStream.
|
||||
*/
|
||||
virtual void ForwardStream(int len, const u_char* data, bool orig);
|
||||
|
||||
/**
|
||||
* Passes gap information to the next sibling SupportAnalyzer if any,
|
||||
* or on to the associated main analyzer if none. If however there's
|
||||
* an output handler associated with this support analyzer, the gap is
|
||||
* passed only to there.
|
||||
*
|
||||
* Parameters same as for Analyzer::ForwardPacket.
|
||||
*/
|
||||
virtual void ForwardUndelivered(int seq, int len, bool orig);
|
||||
|
||||
/**
|
||||
* Returns the analyzer next sibling, or null if none.
|
||||
*/
|
||||
SupportAnalyzer* Sibling() const { return sibling; }
|
||||
|
||||
protected:
|
||||
|
@ -359,22 +715,85 @@ private:
|
|||
SupportAnalyzer* sibling;
|
||||
};
|
||||
|
||||
// The following need to be consistent with bro.init.
|
||||
#define CONTENTS_NONE 0
|
||||
#define CONTENTS_ORIG 1
|
||||
#define CONTENTS_RESP 2
|
||||
#define CONTENTS_BOTH 3
|
||||
|
||||
/**
|
||||
* Base class for analyzers parsing transport-layer protocols.
|
||||
*/
|
||||
class TransportLayerAnalyzer : public Analyzer {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name A name for the protocol the analyzer is parsing. The
|
||||
* name must match the one the corresponding Component registers.
|
||||
*
|
||||
* @param conn The connection the analyzer is associated with.
|
||||
*/
|
||||
TransportLayerAnalyzer(const char* name, Connection* conn)
|
||||
: Analyzer(name, conn) { pia = 0; }
|
||||
|
||||
/**
|
||||
* Overridden from parent class.
|
||||
*/
|
||||
virtual void Done();
|
||||
|
||||
/**
|
||||
* Returns true if the analyzer determines that in fact a new
|
||||
* connection has started without the connection statement having
|
||||
* terminated the previous one, i.e., the new data is arriving at
|
||||
* what's the analyzer for the previous instance. This is used only
|
||||
* for TCP.
|
||||
*/
|
||||
virtual bool IsReuse(double t, const u_char* pkt) = 0;
|
||||
|
||||
/**
|
||||
* Associates a file with the analyzer in which to record all
|
||||
* analyzed input. This must only be called with derived classes that
|
||||
* overide the method; the default implementation will abort.
|
||||
*
|
||||
* @param direction One of the CONTENTS_* constants indicating which
|
||||
* direction of the input stream is to be recorded.
|
||||
*
|
||||
* @param f The file to record to.
|
||||
*
|
||||
*/
|
||||
virtual void SetContentsFile(unsigned int direction, BroFile* f);
|
||||
|
||||
/**
|
||||
* Returns an associated contents file, if any. This must only be
|
||||
* called with derived classes that overide the method; the default
|
||||
* implementation will abort.
|
||||
*
|
||||
* @param direction One of the CONTENTS_* constants indicating which
|
||||
* direction the query is for.
|
||||
*/
|
||||
virtual BroFile* GetContentsFile(unsigned int direction) const;
|
||||
|
||||
/**
|
||||
* Associates a PIA with this analyzer. A PIA takes the
|
||||
* transport-layer input and determine which protocol analyzer(s) to
|
||||
* use for parsing it.
|
||||
*/
|
||||
void SetPIA(PIA* arg_PIA) { pia = arg_PIA; }
|
||||
|
||||
/**
|
||||
* Returns the associated PIA, or null of none. Does not take
|
||||
* ownership.
|
||||
*/
|
||||
PIA* GetPIA() const { return pia; }
|
||||
|
||||
// Raises packet_contents event.
|
||||
/**
|
||||
* Helper to raise a \c packet_contents event.
|
||||
*
|
||||
* @param data The dass to pass to the event.
|
||||
*
|
||||
* @param len The length of \a data.
|
||||
*/
|
||||
void PacketContents(const u_char* data, int len);
|
||||
|
||||
private:
|
||||
|
|
|
@ -170,7 +170,7 @@ void HTTP_Entity::Deliver(int len, const char* data, int trailing_CRLF)
|
|||
DeliverBody(len, data, trailing_CRLF);
|
||||
}
|
||||
|
||||
class HTTP_Entity::UncompressedOutput : public analyzer::Analyzer::OutputHandler {
|
||||
class HTTP_Entity::UncompressedOutput : public analyzer::OutputHandler {
|
||||
public:
|
||||
UncompressedOutput(HTTP_Entity* e) { entity = e; }
|
||||
virtual ~UncompressedOutput() { }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue