mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 22:58:20 +00:00
Move old TCP analyzer into analyzer adapter in packet analysis tree
This commit is contained in:
parent
b171f94729
commit
f6e31107e1
25 changed files with 2243 additions and 2247 deletions
|
@ -130,7 +130,7 @@ void Connection::Done()
|
||||||
// somewhere, but it's session-related, so maybe not?
|
// somewhere, but it's session-related, so maybe not?
|
||||||
if ( ConnTransport() == TRANSPORT_TCP )
|
if ( ConnTransport() == TRANSPORT_TCP )
|
||||||
{
|
{
|
||||||
auto ta = static_cast<analyzer::tcp::TCP_Analyzer*>(adapter);
|
auto* ta = static_cast<packet_analysis::TCP::TCPSessionAdapter*>(adapter);
|
||||||
assert(ta->IsAnalyzer("TCP"));
|
assert(ta->IsAnalyzer("TCP"));
|
||||||
analyzer::tcp::TCP_Endpoint* to = ta->Orig();
|
analyzer::tcp::TCP_Endpoint* to = ta->Orig();
|
||||||
analyzer::tcp::TCP_Endpoint* tr = ta->Resp();
|
analyzer::tcp::TCP_Endpoint* tr = ta->Resp();
|
||||||
|
|
|
@ -30,7 +30,7 @@ bool RuleConditionTCPState::DoMatch(Rule* rule, RuleEndpointState* state,
|
||||||
if ( ! adapter || ! adapter->IsAnalyzer("TCP") )
|
if ( ! adapter || ! adapter->IsAnalyzer("TCP") )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto* ta = static_cast<analyzer::tcp::TCP_Analyzer*>(adapter);
|
auto* ta = static_cast<packet_analysis::TCP::TCPSessionAdapter*>(adapter);
|
||||||
|
|
||||||
if ( tcpstates & RULE_STATE_STATELESS )
|
if ( tcpstates & RULE_STATE_STATELESS )
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -81,14 +81,6 @@ Manager::~Manager()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::InitPreScript()
|
|
||||||
{
|
|
||||||
// Cache these tags.
|
|
||||||
analyzer_connsize = GetComponentTag("CONNSIZE");
|
|
||||||
analyzer_stepping = GetComponentTag("STEPPINGSTONE");
|
|
||||||
analyzer_tcpstats = GetComponentTag("TCPSTATS");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Manager::InitPostScript()
|
void Manager::InitPostScript()
|
||||||
{
|
{
|
||||||
const auto& id = detail::global_scope()->Find("Tunnel::vxlan_ports");
|
const auto& id = detail::global_scope()->Find("Tunnel::vxlan_ports");
|
||||||
|
@ -354,132 +346,6 @@ Manager::tag_set* Manager::LookupPort(TransportProto proto, uint32_t port, bool
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::BuildInitialAnalyzerTree(Connection* conn)
|
|
||||||
{
|
|
||||||
analyzer::tcp::TCP_Analyzer* tcp = nullptr;
|
|
||||||
packet_analysis::IP::SessionAdapter* root = nullptr;
|
|
||||||
analyzer::pia::PIA* pia = nullptr;
|
|
||||||
bool check_port = false;
|
|
||||||
|
|
||||||
switch ( conn->ConnTransport() ) {
|
|
||||||
|
|
||||||
case TRANSPORT_TCP:
|
|
||||||
root = tcp = new analyzer::tcp::TCP_Analyzer(conn);
|
|
||||||
pia = new analyzer::pia::PIA_TCP(conn);
|
|
||||||
check_port = true;
|
|
||||||
DBG_ANALYZER(conn, "activated TCP analyzer");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
reporter->InternalWarning("unknown protocol can't build analyzer tree");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool scheduled = ApplyScheduledAnalyzers(conn, false, root);
|
|
||||||
|
|
||||||
// Hmm... Do we want *just* the expected analyzer, or all
|
|
||||||
// other potential analyzers as well? For now we only take
|
|
||||||
// the scheduled ones.
|
|
||||||
if ( ! scheduled )
|
|
||||||
{ // Let's see if it's a port we know.
|
|
||||||
if ( check_port && ! zeek::detail::dpd_ignore_ports )
|
|
||||||
{
|
|
||||||
int resp_port = ntohs(conn->RespPort());
|
|
||||||
tag_set* ports = LookupPort(conn->ConnTransport(), resp_port, false);
|
|
||||||
|
|
||||||
if ( ports )
|
|
||||||
{
|
|
||||||
for ( tag_set::const_iterator j = ports->begin(); j != ports->end(); ++j )
|
|
||||||
{
|
|
||||||
Analyzer* analyzer = analyzer_mgr->InstantiateAnalyzer(*j, conn);
|
|
||||||
|
|
||||||
if ( ! analyzer )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
root->AddChildAnalyzer(analyzer, false);
|
|
||||||
DBG_ANALYZER_ARGS(conn, "activated %s analyzer due to port %d",
|
|
||||||
analyzer_mgr->GetComponentName(*j).c_str(), resp_port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( tcp )
|
|
||||||
{
|
|
||||||
// We have to decide whether to reassamble the stream.
|
|
||||||
// We turn it on right away if we already have an app-layer
|
|
||||||
// analyzer, reassemble_first_packets is true, or the user
|
|
||||||
// asks us to do so. In all other cases, reassembly may
|
|
||||||
// be turned on later by the TCP PIA.
|
|
||||||
|
|
||||||
bool reass = root->GetChildren().size() ||
|
|
||||||
zeek::detail::dpd_reassemble_first_packets ||
|
|
||||||
zeek::detail::tcp_content_deliver_all_orig ||
|
|
||||||
zeek::detail::tcp_content_deliver_all_resp;
|
|
||||||
|
|
||||||
if ( tcp_contents && ! reass )
|
|
||||||
{
|
|
||||||
static auto tcp_content_delivery_ports_orig = id::find_val<TableVal>("tcp_content_delivery_ports_orig");
|
|
||||||
static auto tcp_content_delivery_ports_resp = id::find_val<TableVal>("tcp_content_delivery_ports_resp");
|
|
||||||
const auto& dport = val_mgr->Port(ntohs(conn->RespPort()), TRANSPORT_TCP);
|
|
||||||
|
|
||||||
if ( ! reass )
|
|
||||||
reass = (bool)tcp_content_delivery_ports_orig->FindOrDefault(dport);
|
|
||||||
|
|
||||||
if ( ! reass )
|
|
||||||
reass = (bool)tcp_content_delivery_ports_resp->FindOrDefault(dport);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( reass )
|
|
||||||
tcp->EnableReassembly();
|
|
||||||
|
|
||||||
if ( IsEnabled(analyzer_stepping) )
|
|
||||||
{
|
|
||||||
// Add a SteppingStone analyzer if requested. The port
|
|
||||||
// should really not be hardcoded here, but as it can
|
|
||||||
// handle non-reassembled data, it doesn't really fit into
|
|
||||||
// our general framing ... Better would be to turn it
|
|
||||||
// on *after* we discover we have interactive traffic.
|
|
||||||
uint16_t resp_port = ntohs(conn->RespPort());
|
|
||||||
if ( resp_port == 22 || resp_port == 23 || resp_port == 513 )
|
|
||||||
{
|
|
||||||
static auto stp_skip_src = id::find_val<TableVal>("stp_skip_src");
|
|
||||||
auto src = make_intrusive<AddrVal>(conn->OrigAddr());
|
|
||||||
|
|
||||||
if ( ! stp_skip_src->FindOrDefault(src) )
|
|
||||||
tcp->AddChildAnalyzer(new analyzer::stepping_stone::SteppingStone_Analyzer(conn), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( IsEnabled(analyzer_tcpstats) )
|
|
||||||
// Add TCPStats analyzer. This needs to see packets so
|
|
||||||
// we cannot add it as a normal child.
|
|
||||||
tcp->AddChildPacketAnalyzer(new analyzer::tcp::TCPStats_Analyzer(conn));
|
|
||||||
|
|
||||||
if ( IsEnabled(analyzer_connsize) )
|
|
||||||
// Add ConnSize analyzer. Needs to see packets, not stream.
|
|
||||||
tcp->AddChildPacketAnalyzer(new analyzer::conn_size::ConnSize_Analyzer(conn));
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( IsEnabled(analyzer_connsize) )
|
|
||||||
// Add ConnSize analyzer. Needs to see packets, not stream.
|
|
||||||
root->AddChildAnalyzer(new analyzer::conn_size::ConnSize_Analyzer(conn));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( pia )
|
|
||||||
root->AddChildAnalyzer(pia->AsAnalyzer());
|
|
||||||
|
|
||||||
conn->SetSessionAdapter(root, pia);
|
|
||||||
root->Init();
|
|
||||||
root->InitChildren();
|
|
||||||
|
|
||||||
PLUGIN_HOOK_VOID(HOOK_SETUP_ANALYZER_TREE, HookSetupAnalyzerTree(conn));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Manager::ExpireScheduledAnalyzers()
|
void Manager::ExpireScheduledAnalyzers()
|
||||||
{
|
{
|
||||||
if ( ! run_state::network_time )
|
if ( ! run_state::network_time )
|
||||||
|
|
|
@ -67,12 +67,6 @@ public:
|
||||||
*/
|
*/
|
||||||
~Manager();
|
~Manager();
|
||||||
|
|
||||||
/**
|
|
||||||
* First-stage initializion of the manager. This is called early on
|
|
||||||
* during Bro's initialization, before any scripts are processed.
|
|
||||||
*/
|
|
||||||
void InitPreScript();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Second-stage initialization of the manager. This is called late
|
* Second-stage initialization of the manager. This is called late
|
||||||
* during Bro's initialization after any scripts are processed.
|
* during Bro's initialization after any scripts are processed.
|
||||||
|
@ -246,17 +240,6 @@ public:
|
||||||
*/
|
*/
|
||||||
Analyzer* InstantiateAnalyzer(const char* name, Connection* c);
|
Analyzer* InstantiateAnalyzer(const char* name, Connection* c);
|
||||||
|
|
||||||
/**
|
|
||||||
* Given the first packet of a connection, builds its initial
|
|
||||||
* analyzer tree.
|
|
||||||
*
|
|
||||||
* @param conn The connection to add the initial set of analyzers to.
|
|
||||||
*
|
|
||||||
* @return False if the tree cannot be built; that's usually an
|
|
||||||
* internal error.
|
|
||||||
*/
|
|
||||||
bool BuildInitialAnalyzerTree(Connection* conn);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules a particular analyzer for an upcoming connection. Once
|
* Schedules a particular analyzer for an upcoming connection. Once
|
||||||
* the connection is seen, BuildInitAnalyzerTree() will add the
|
* the connection is seen, BuildInitAnalyzerTree() will add the
|
||||||
|
@ -366,10 +349,6 @@ private:
|
||||||
analyzer_map_by_port analyzers_by_port_tcp;
|
analyzer_map_by_port analyzers_by_port_tcp;
|
||||||
analyzer_map_by_port analyzers_by_port_udp;
|
analyzer_map_by_port analyzers_by_port_udp;
|
||||||
|
|
||||||
Tag analyzer_connsize;
|
|
||||||
Tag analyzer_stepping;
|
|
||||||
Tag analyzer_tcpstats;
|
|
||||||
|
|
||||||
//// Data structures to track analyzed scheduled for future connections.
|
//// Data structures to track analyzed scheduled for future connections.
|
||||||
|
|
||||||
// The index for a scheduled connection.
|
// The index for a scheduled connection.
|
||||||
|
|
|
@ -35,7 +35,7 @@ Contents_Rsh_Analyzer::~Contents_Rsh_Analyzer()
|
||||||
|
|
||||||
void Contents_Rsh_Analyzer::DoDeliver(int len, const u_char* data)
|
void Contents_Rsh_Analyzer::DoDeliver(int len, const u_char* data)
|
||||||
{
|
{
|
||||||
analyzer::tcp::TCP_Analyzer* tcp = static_cast<analyzer::tcp::TCP_ApplicationAnalyzer*>(Parent())->TCP();
|
auto* tcp = static_cast<analyzer::tcp::TCP_ApplicationAnalyzer*>(Parent())->TCP();
|
||||||
assert(tcp);
|
assert(tcp);
|
||||||
|
|
||||||
int endp_state = IsOrig() ? tcp->OrigState() : tcp->RespState();
|
int endp_state = IsOrig() ? tcp->OrigState() : tcp->RespState();
|
||||||
|
|
|
@ -199,7 +199,7 @@ void PIA_TCP::Init()
|
||||||
|
|
||||||
if ( Parent()->IsAnalyzer("TCP") )
|
if ( Parent()->IsAnalyzer("TCP") )
|
||||||
{
|
{
|
||||||
tcp::TCP_Analyzer* tcp = static_cast<tcp::TCP_Analyzer*>(Parent());
|
auto* tcp = static_cast<packet_analysis::TCP::TCPSessionAdapter*>(Parent());
|
||||||
SetTCP(tcp);
|
SetTCP(tcp);
|
||||||
tcp->SetPIA(this);
|
tcp->SetPIA(this);
|
||||||
}
|
}
|
||||||
|
@ -375,14 +375,12 @@ void PIA_TCP::ActivateAnalyzer(analyzer::Tag tag, const zeek::detail::Rule* rule
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcp::TCP_Analyzer* tcp = (tcp::TCP_Analyzer*) Parent();
|
auto* tcp = static_cast<packet_analysis::TCP::TCPSessionAdapter*>(Parent());
|
||||||
|
|
||||||
tcp::TCP_Reassembler* reass_orig =
|
auto* reass_orig = new tcp::TCP_Reassembler(this, tcp, tcp::TCP_Reassembler::Direct,
|
||||||
new tcp::TCP_Reassembler(this, tcp, tcp::TCP_Reassembler::Direct,
|
|
||||||
tcp->Orig());
|
tcp->Orig());
|
||||||
|
|
||||||
tcp::TCP_Reassembler* reass_resp =
|
auto* reass_resp = new tcp::TCP_Reassembler(this, tcp, tcp::TCP_Reassembler::Direct,
|
||||||
new tcp::TCP_Reassembler(this, tcp, tcp::TCP_Reassembler::Direct,
|
|
||||||
tcp->Resp());
|
tcp->Resp());
|
||||||
|
|
||||||
uint64_t orig_seq = 0;
|
uint64_t orig_seq = 0;
|
||||||
|
|
|
@ -456,8 +456,7 @@ bool Contents_RPC::CheckResync(int& len, const u_char*& data, bool orig)
|
||||||
// is fully established we are in sync (since it's the first chunk
|
// is fully established we are in sync (since it's the first chunk
|
||||||
// of data after the SYN if its not established we need to
|
// of data after the SYN if its not established we need to
|
||||||
// resync.
|
// resync.
|
||||||
analyzer::tcp::TCP_Analyzer* tcp =
|
auto* tcp = static_cast<analyzer::tcp::TCP_ApplicationAnalyzer*>(Parent())->TCP();
|
||||||
static_cast<analyzer::tcp::TCP_ApplicationAnalyzer*>(Parent())->TCP();
|
|
||||||
assert(tcp);
|
assert(tcp);
|
||||||
|
|
||||||
if ( (IsOrig() ? tcp->OrigState() : tcp->RespState()) !=
|
if ( (IsOrig() ? tcp->OrigState() : tcp->RespState()) !=
|
||||||
|
|
|
@ -85,8 +85,7 @@ void ContentLine_Analyzer::DeliverStream(int len, const u_char* data,
|
||||||
|
|
||||||
if ( skip_partial )
|
if ( skip_partial )
|
||||||
{
|
{
|
||||||
TCP_Analyzer* tcp =
|
auto* tcp = static_cast<TCP_ApplicationAnalyzer*>(Parent())->TCP();
|
||||||
static_cast<TCP_ApplicationAnalyzer*>(Parent())->TCP();
|
|
||||||
|
|
||||||
if ( tcp && tcp->IsPartial() )
|
if ( tcp && tcp->IsPartial() )
|
||||||
return;
|
return;
|
||||||
|
@ -300,8 +299,7 @@ void ContentLine_Analyzer::CheckNUL()
|
||||||
// had been an initial SYN, so we check for whether
|
// had been an initial SYN, so we check for whether
|
||||||
// the connection has at most two bytes so far.
|
// the connection has at most two bytes so far.
|
||||||
|
|
||||||
TCP_Analyzer* tcp =
|
auto* tcp = static_cast<TCP_ApplicationAnalyzer*>(Parent())->TCP();
|
||||||
static_cast<TCP_ApplicationAnalyzer*>(Parent())->TCP();
|
|
||||||
|
|
||||||
if ( tcp )
|
if ( tcp )
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,6 @@ class Plugin : public zeek::plugin::Plugin {
|
||||||
public:
|
public:
|
||||||
zeek::plugin::Configuration Configure() override
|
zeek::plugin::Configuration Configure() override
|
||||||
{
|
{
|
||||||
AddComponent(new zeek::analyzer::Component("TCP", zeek::analyzer::tcp::TCP_Analyzer::Instantiate));
|
|
||||||
AddComponent(new zeek::analyzer::Component("TCPStats", zeek::analyzer::tcp::TCPStats_Analyzer::Instantiate));
|
AddComponent(new zeek::analyzer::Component("TCPStats", zeek::analyzer::tcp::TCPStats_Analyzer::Instantiate));
|
||||||
AddComponent(new zeek::analyzer::Component("CONTENTLINE", nullptr));
|
AddComponent(new zeek::analyzer::Component("CONTENTLINE", nullptr));
|
||||||
AddComponent(new zeek::analyzer::Component("Contents", nullptr));
|
AddComponent(new zeek::analyzer::Component("Contents", nullptr));
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,16 +6,11 @@
|
||||||
#include "zeek/IPAddr.h"
|
#include "zeek/IPAddr.h"
|
||||||
#include "zeek/analyzer/protocol/tcp/TCP_Endpoint.h"
|
#include "zeek/analyzer/protocol/tcp/TCP_Endpoint.h"
|
||||||
#include "zeek/analyzer/protocol/tcp/TCP_Flags.h"
|
#include "zeek/analyzer/protocol/tcp/TCP_Flags.h"
|
||||||
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
|
#include "zeek/packet_analysis/protocol/tcp/TCPSessionAdapter.h"
|
||||||
#include "zeek/Conn.h"
|
#include "zeek/Conn.h"
|
||||||
|
|
||||||
// We define two classes here:
|
|
||||||
// - TCP_Analyzer is the analyzer for the TCP protocol itself.
|
|
||||||
// - TCP_ApplicationAnalyzer is an abstract base class for analyzers for a
|
|
||||||
// protocol running on top of TCP.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace zeek::analyzer::pia { class PIA_TCP; }
|
namespace zeek::analyzer::pia { class PIA_TCP; }
|
||||||
|
namespace zeek::packet_analysis::TCP { class TCPSessionAdapter; }
|
||||||
|
|
||||||
namespace zeek::analyzer::tcp {
|
namespace zeek::analyzer::tcp {
|
||||||
|
|
||||||
|
@ -23,179 +18,13 @@ class TCP_Endpoint;
|
||||||
class TCP_Reassembler;
|
class TCP_Reassembler;
|
||||||
class TCP_ApplicationAnalyzer;
|
class TCP_ApplicationAnalyzer;
|
||||||
|
|
||||||
class TCP_Analyzer final : public packet_analysis::IP::SessionAdapter {
|
using TCP_Analyzer [[deprecated("Remove in v5.1. Use zeek::packet_analysis::TCP::TCPSessionAdapter.")]] =
|
||||||
public:
|
packet_analysis::TCP::TCPSessionAdapter;
|
||||||
explicit TCP_Analyzer(Connection* conn);
|
|
||||||
~TCP_Analyzer() override;
|
|
||||||
|
|
||||||
void EnableReassembly();
|
|
||||||
|
|
||||||
// Add a child analyzer that will always get the packets,
|
|
||||||
// independently of whether we do any reassembly.
|
|
||||||
void AddChildPacketAnalyzer(analyzer::Analyzer* a);
|
|
||||||
|
|
||||||
Analyzer* FindChild(analyzer::ID id) override;
|
|
||||||
Analyzer* FindChild(analyzer::Tag tag) override;
|
|
||||||
bool RemoveChildAnalyzer(analyzer::ID id) override;
|
|
||||||
|
|
||||||
// True if the connection has closed in some sense, false otherwise.
|
|
||||||
bool IsClosed() const { return orig->did_close || resp->did_close; }
|
|
||||||
bool BothClosed() const { return orig->did_close && resp->did_close; }
|
|
||||||
|
|
||||||
bool IsPartial() const { return is_partial; }
|
|
||||||
|
|
||||||
bool HadGap(bool orig) const;
|
|
||||||
|
|
||||||
TCP_Endpoint* Orig() const { return orig; }
|
|
||||||
TCP_Endpoint* Resp() const { return resp; }
|
|
||||||
int OrigState() const { return orig->state; }
|
|
||||||
int RespState() const { return resp->state; }
|
|
||||||
int OrigPrevState() const { return orig->prev_state; }
|
|
||||||
int RespPrevState() const { return resp->prev_state; }
|
|
||||||
uint32_t OrigSeq() const { return orig->LastSeq(); }
|
|
||||||
uint32_t RespSeq() const { return resp->LastSeq(); }
|
|
||||||
|
|
||||||
// True if either endpoint still has pending data. closing_endp
|
|
||||||
// is an endpoint that has indicated it is closing (i.e., for
|
|
||||||
// which we have seen a FIN) - for it, data is pending unless
|
|
||||||
// everything's been delivered up to the FIN. For its peer,
|
|
||||||
// the test is whether it has any outstanding, un-acked data.
|
|
||||||
bool DataPending(TCP_Endpoint* closing_endp);
|
|
||||||
|
|
||||||
void SetContentsFile(unsigned int direction, FilePtr f) override;
|
|
||||||
FilePtr GetContentsFile(unsigned int direction) const override;
|
|
||||||
|
|
||||||
// From Analyzer.h
|
|
||||||
void UpdateConnVal(RecordVal *conn_val) override;
|
|
||||||
|
|
||||||
int ParseTCPOptions(const struct tcphdr* tcp, bool is_orig);
|
|
||||||
|
|
||||||
static analyzer::Analyzer* Instantiate(Connection* conn)
|
|
||||||
{ return new TCP_Analyzer(conn); }
|
|
||||||
|
|
||||||
void AddExtraAnalyzers(Connection* conn) override {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class TCP_ApplicationAnalyzer;
|
|
||||||
friend class TCP_Reassembler;
|
|
||||||
friend class analyzer::pia::PIA_TCP;
|
|
||||||
|
|
||||||
// Analyzer interface.
|
|
||||||
void Init() override;
|
|
||||||
void Done() override;
|
|
||||||
void DeliverPacket(int len, const u_char* data, bool orig, uint64_t seq,
|
|
||||||
const IP_Hdr* ip, int caplen) override;
|
|
||||||
void DeliverStream(int len, const u_char* data, bool orig) override;
|
|
||||||
void Undelivered(uint64_t seq, int len, bool orig) override;
|
|
||||||
void FlipRoles() override;
|
|
||||||
bool IsReuse(double t, const u_char* pkt) override;
|
|
||||||
|
|
||||||
// Returns the TCP header pointed to by data (which we assume is
|
|
||||||
// aligned), updating data, len & caplen. Returns nil if the header
|
|
||||||
// isn't fully present.
|
|
||||||
const struct tcphdr* ExtractTCP_Header(const u_char*& data, int& len,
|
|
||||||
int& caplen);
|
|
||||||
|
|
||||||
// Returns true if the checksum is valid, false if not (and in which
|
|
||||||
// case also updates the status history of the endpoint).
|
|
||||||
bool ValidateChecksum(const IP_Hdr* ip, const struct tcphdr* tp, TCP_Endpoint* endpoint,
|
|
||||||
int len, int caplen);
|
|
||||||
|
|
||||||
void SetPartialStatus(TCP_Flags flags, bool is_orig);
|
|
||||||
|
|
||||||
// Update the state machine of the TCPs based on the activity. This
|
|
||||||
// includes our pseudo-states such as TCP_ENDPOINT_PARTIAL.
|
|
||||||
//
|
|
||||||
// On return, do_close is true if we should consider the connection
|
|
||||||
// as closed, and gen_event if we shouuld generate an event about
|
|
||||||
// this fact.
|
|
||||||
void UpdateStateMachine(double t,
|
|
||||||
TCP_Endpoint* endpoint, TCP_Endpoint* peer,
|
|
||||||
uint32_t base_seq, uint32_t ack_seq,
|
|
||||||
int len, int32_t delta_last, bool is_orig, TCP_Flags flags,
|
|
||||||
bool& do_close, bool& gen_event);
|
|
||||||
|
|
||||||
void UpdateInactiveState(double t,
|
|
||||||
TCP_Endpoint* endpoint, TCP_Endpoint* peer,
|
|
||||||
uint32_t base_seq, uint32_t ack_seq,
|
|
||||||
int len, bool is_orig, TCP_Flags flags,
|
|
||||||
bool& do_close, bool& gen_event);
|
|
||||||
|
|
||||||
void UpdateSYN_SentState(TCP_Endpoint* endpoint, TCP_Endpoint* peer,
|
|
||||||
int len, bool is_orig, TCP_Flags flags,
|
|
||||||
bool& do_close, bool& gen_event);
|
|
||||||
|
|
||||||
void UpdateEstablishedState(TCP_Endpoint* endpoint, TCP_Endpoint* peer,
|
|
||||||
TCP_Flags flags, bool& do_close, bool& gen_event);
|
|
||||||
|
|
||||||
void UpdateClosedState(double t, TCP_Endpoint* endpoint,
|
|
||||||
int32_t delta_last, TCP_Flags flags,
|
|
||||||
bool& do_close);
|
|
||||||
|
|
||||||
void UpdateResetState(int len, TCP_Flags flags);
|
|
||||||
|
|
||||||
void GeneratePacketEvent(uint64_t rel_seq, uint64_t rel_ack,
|
|
||||||
const u_char* data, int len, int caplen,
|
|
||||||
bool is_orig, TCP_Flags flags);
|
|
||||||
|
|
||||||
bool DeliverData(double t, const u_char* data, int len, int caplen,
|
|
||||||
const IP_Hdr* ip, const struct tcphdr* tp,
|
|
||||||
TCP_Endpoint* endpoint, uint64_t rel_data_seq,
|
|
||||||
bool is_orig, TCP_Flags flags);
|
|
||||||
|
|
||||||
void CheckRecording(bool need_contents, TCP_Flags flags);
|
|
||||||
void CheckPIA_FirstPacket(bool is_orig, const IP_Hdr* ip);
|
|
||||||
|
|
||||||
friend class session::detail::Timer;
|
|
||||||
void AttemptTimer(double t);
|
|
||||||
void PartialCloseTimer(double t);
|
|
||||||
void ExpireTimer(double t);
|
|
||||||
void ResetTimer(double t);
|
|
||||||
void DeleteTimer(double t);
|
|
||||||
void ConnDeleteTimer(double t);
|
|
||||||
|
|
||||||
void EndpointEOF(TCP_Reassembler* endp);
|
|
||||||
void ConnectionClosed(TCP_Endpoint* endpoint,
|
|
||||||
TCP_Endpoint* peer, bool gen_event);
|
|
||||||
void ConnectionFinished(bool half_finished);
|
|
||||||
void ConnectionReset();
|
|
||||||
void PacketWithRST();
|
|
||||||
|
|
||||||
void SetReassembler(tcp::TCP_Reassembler* rorig, tcp::TCP_Reassembler* rresp);
|
|
||||||
|
|
||||||
// A couple utility functions that may also be useful to derived analyzers.
|
|
||||||
static uint64_t get_relative_seq(const TCP_Endpoint* endpoint,
|
|
||||||
uint32_t cur_base, uint32_t last,
|
|
||||||
uint32_t wraps, bool* underflow = nullptr);
|
|
||||||
|
|
||||||
static int get_segment_len(int payload_len, TCP_Flags flags);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void SynWeirds(TCP_Flags flags, TCP_Endpoint* endpoint, int data_len) const;
|
|
||||||
|
|
||||||
TCP_Endpoint* orig;
|
|
||||||
TCP_Endpoint* resp;
|
|
||||||
|
|
||||||
analyzer_list packet_children;
|
|
||||||
|
|
||||||
unsigned int first_packet_seen: 2;
|
|
||||||
unsigned int reassembling: 1;
|
|
||||||
unsigned int is_partial: 1;
|
|
||||||
unsigned int is_active: 1;
|
|
||||||
unsigned int finished: 1;
|
|
||||||
|
|
||||||
// Whether we're waiting on final data delivery before closing
|
|
||||||
// this connection.
|
|
||||||
unsigned int close_deferred: 1;
|
|
||||||
|
|
||||||
// Whether to generate an event when we finally do close it.
|
|
||||||
unsigned int deferred_gen_event: 1;
|
|
||||||
|
|
||||||
// Whether we have seen the first ACK from the originator.
|
|
||||||
unsigned int seen_first_ACK: 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract base class for analyzers for a protocol running on top
|
||||||
|
* of TCP.
|
||||||
|
*/
|
||||||
class TCP_ApplicationAnalyzer : public analyzer::Analyzer {
|
class TCP_ApplicationAnalyzer : public analyzer::Analyzer {
|
||||||
public:
|
public:
|
||||||
TCP_ApplicationAnalyzer(const char* name, Connection* conn)
|
TCP_ApplicationAnalyzer(const char* name, Connection* conn)
|
||||||
|
@ -208,14 +37,9 @@ public:
|
||||||
|
|
||||||
// This may be nil if we are not directly associated with a TCP
|
// This may be nil if we are not directly associated with a TCP
|
||||||
// analyzer (e.g., we're part of a tunnel decapsulation pipeline).
|
// analyzer (e.g., we're part of a tunnel decapsulation pipeline).
|
||||||
TCP_Analyzer* TCP()
|
packet_analysis::TCP::TCPSessionAdapter* TCP();
|
||||||
{
|
|
||||||
return tcp ?
|
|
||||||
tcp :
|
|
||||||
static_cast<TCP_Analyzer*>(Conn()->FindAnalyzer("TCP"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTCP(TCP_Analyzer* arg_tcp) { tcp = arg_tcp; }
|
void SetTCP(packet_analysis::TCP::TCPSessionAdapter* arg_tcp) { tcp = arg_tcp; }
|
||||||
|
|
||||||
// The given endpoint's data delivery is complete.
|
// The given endpoint's data delivery is complete.
|
||||||
virtual void EndpointEOF(bool is_orig);
|
virtual void EndpointEOF(bool is_orig);
|
||||||
|
@ -225,7 +49,8 @@ public:
|
||||||
// is now fully closed, a connection_finished event will be
|
// is now fully closed, a connection_finished event will be
|
||||||
// generated; otherwise not.
|
// generated; otherwise not.
|
||||||
virtual void ConnectionClosed(analyzer::tcp::TCP_Endpoint* endpoint,
|
virtual void ConnectionClosed(analyzer::tcp::TCP_Endpoint* endpoint,
|
||||||
analyzer::tcp::TCP_Endpoint* peer, bool gen_event);
|
analyzer::tcp::TCP_Endpoint* peer,
|
||||||
|
bool gen_event);
|
||||||
virtual void ConnectionFinished(bool half_finished);
|
virtual void ConnectionFinished(bool half_finished);
|
||||||
virtual void ConnectionReset();
|
virtual void ConnectionReset();
|
||||||
|
|
||||||
|
@ -247,7 +72,7 @@ public:
|
||||||
virtual void SetEnv(bool orig, char* name, char* val);
|
virtual void SetEnv(bool orig, char* name, char* val);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TCP_Analyzer* tcp;
|
packet_analysis::TCP::TCPSessionAdapter* tcp;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TCP_SupportAnalyzer : public analyzer::SupportAnalyzer {
|
class TCP_SupportAnalyzer : public analyzer::SupportAnalyzer {
|
||||||
|
@ -257,7 +82,7 @@ public:
|
||||||
|
|
||||||
~TCP_SupportAnalyzer() override {}
|
~TCP_SupportAnalyzer() override {}
|
||||||
|
|
||||||
// These are passed on from TCP_Analyzer.
|
// These are passed on from TCPSessionAdapter.
|
||||||
virtual void EndpointEOF(bool is_orig) { }
|
virtual void EndpointEOF(bool is_orig) { }
|
||||||
virtual void ConnectionClosed(TCP_Endpoint* endpoint,
|
virtual void ConnectionClosed(TCP_Endpoint* endpoint,
|
||||||
TCP_Endpoint* peer, bool gen_event) { }
|
TCP_Endpoint* peer, bool gen_event) { }
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
namespace zeek::analyzer::tcp {
|
namespace zeek::analyzer::tcp {
|
||||||
|
|
||||||
TCP_Endpoint::TCP_Endpoint(TCP_Analyzer* arg_analyzer, bool arg_is_orig)
|
TCP_Endpoint::TCP_Endpoint(packet_analysis::TCP::TCPSessionAdapter* arg_analyzer, bool arg_is_orig)
|
||||||
{
|
{
|
||||||
contents_processor = nullptr;
|
contents_processor = nullptr;
|
||||||
prev_state = state = TCP_ENDPOINT_INACTIVE;
|
prev_state = state = TCP_ENDPOINT_INACTIVE;
|
||||||
|
|
|
@ -10,9 +10,13 @@ namespace zeek {
|
||||||
class Connection;
|
class Connection;
|
||||||
class IP_Hdr;
|
class IP_Hdr;
|
||||||
|
|
||||||
|
namespace packet_analysis::TCP { class TCPSessionAdapter; }
|
||||||
|
|
||||||
namespace analyzer::tcp {
|
namespace analyzer::tcp {
|
||||||
|
|
||||||
class TCP_Analyzer;
|
using TCP_Analyzer [[deprecated("Remove in v5.1. Use zeek::packet_analysis::TCP::TCPSessionAdapter.")]] =
|
||||||
|
zeek::packet_analysis::TCP::TCPSessionAdapter;
|
||||||
|
|
||||||
class TCP_Reassembler;
|
class TCP_Reassembler;
|
||||||
|
|
||||||
enum EndpointState {
|
enum EndpointState {
|
||||||
|
@ -29,12 +33,12 @@ enum EndpointState {
|
||||||
// One endpoint of a TCP connection.
|
// One endpoint of a TCP connection.
|
||||||
class TCP_Endpoint {
|
class TCP_Endpoint {
|
||||||
public:
|
public:
|
||||||
TCP_Endpoint(TCP_Analyzer* analyzer, bool is_orig);
|
TCP_Endpoint(packet_analysis::TCP::TCPSessionAdapter* analyzer, bool is_orig);
|
||||||
~TCP_Endpoint();
|
~TCP_Endpoint();
|
||||||
|
|
||||||
void Done();
|
void Done();
|
||||||
|
|
||||||
TCP_Analyzer* TCP() { return tcp_analyzer; }
|
packet_analysis::TCP::TCPSessionAdapter* TCP() { return tcp_analyzer; }
|
||||||
|
|
||||||
void SetPeer(TCP_Endpoint* p);
|
void SetPeer(TCP_Endpoint* p);
|
||||||
|
|
||||||
|
@ -212,7 +216,7 @@ public:
|
||||||
EndpointState state, prev_state;
|
EndpointState state, prev_state;
|
||||||
TCP_Endpoint* peer;
|
TCP_Endpoint* peer;
|
||||||
TCP_Reassembler* contents_processor;
|
TCP_Reassembler* contents_processor;
|
||||||
TCP_Analyzer* tcp_analyzer;
|
packet_analysis::TCP::TCPSessionAdapter* tcp_analyzer;
|
||||||
FilePtr contents_file;
|
FilePtr contents_file;
|
||||||
|
|
||||||
double start_time, last_time;
|
double start_time, last_time;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "zeek/File.h"
|
#include "zeek/File.h"
|
||||||
#include "zeek/analyzer/Analyzer.h"
|
#include "zeek/analyzer/Analyzer.h"
|
||||||
#include "zeek/analyzer/protocol/tcp/TCP.h"
|
#include "zeek/analyzer/protocol/tcp/TCP.h"
|
||||||
|
#include "zeek/packet_analysis/protocol/tcp/TCPSessionAdapter.h"
|
||||||
#include "zeek/ZeekString.h"
|
#include "zeek/ZeekString.h"
|
||||||
#include "zeek/Reporter.h"
|
#include "zeek/Reporter.h"
|
||||||
#include "zeek/RuleMatcher.h"
|
#include "zeek/RuleMatcher.h"
|
||||||
|
@ -21,7 +22,7 @@ constexpr bool DEBUG_tcp_connection_close = false;
|
||||||
constexpr bool DEBUG_tcp_match_undelivered = false;
|
constexpr bool DEBUG_tcp_match_undelivered = false;
|
||||||
|
|
||||||
TCP_Reassembler::TCP_Reassembler(analyzer::Analyzer* arg_dst_analyzer,
|
TCP_Reassembler::TCP_Reassembler(analyzer::Analyzer* arg_dst_analyzer,
|
||||||
TCP_Analyzer* arg_tcp_analyzer,
|
packet_analysis::TCP::TCPSessionAdapter* arg_tcp_analyzer,
|
||||||
TCP_Reassembler::Type arg_type,
|
TCP_Reassembler::Type arg_type,
|
||||||
TCP_Endpoint* arg_endp)
|
TCP_Endpoint* arg_endp)
|
||||||
: Reassembler(1, REASSEM_TCP)
|
: Reassembler(1, REASSEM_TCP)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "zeek/File.h"
|
#include "zeek/File.h"
|
||||||
|
|
||||||
namespace zeek {
|
namespace zeek {
|
||||||
|
namespace packet_analysis::TCP { class TCPSessionAdapter; }
|
||||||
|
|
||||||
class Connection;
|
class Connection;
|
||||||
|
|
||||||
|
@ -15,7 +16,8 @@ class Analyzer;
|
||||||
|
|
||||||
namespace tcp {
|
namespace tcp {
|
||||||
|
|
||||||
class TCP_Analyzer;
|
using TCP_Analyzer [[deprecated("Remove in v5.1. Use zeek::packet_analysis::TCP::TCPSessionAdapter.")]] =
|
||||||
|
zeek::packet_analysis::TCP::TCPSessionAdapter;
|
||||||
|
|
||||||
class TCP_Reassembler final : public Reassembler {
|
class TCP_Reassembler final : public Reassembler {
|
||||||
public:
|
public:
|
||||||
|
@ -25,7 +27,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
TCP_Reassembler(analyzer::Analyzer* arg_dst_analyzer,
|
TCP_Reassembler(analyzer::Analyzer* arg_dst_analyzer,
|
||||||
TCP_Analyzer* arg_tcp_analyzer,
|
packet_analysis::TCP::TCPSessionAdapter* arg_tcp_analyzer,
|
||||||
Type arg_type, TCP_Endpoint* arg_endp);
|
Type arg_type, TCP_Endpoint* arg_endp);
|
||||||
|
|
||||||
void Done();
|
void Done();
|
||||||
|
@ -33,7 +35,7 @@ public:
|
||||||
void SetDstAnalyzer(analyzer::Analyzer* analyzer) { dst_analyzer = analyzer; }
|
void SetDstAnalyzer(analyzer::Analyzer* analyzer) { dst_analyzer = analyzer; }
|
||||||
void SetType(Type arg_type) { type = arg_type; }
|
void SetType(Type arg_type) { type = arg_type; }
|
||||||
|
|
||||||
TCP_Analyzer* GetTCPAnalyzer() { return tcp_analyzer; }
|
packet_analysis::TCP::TCPSessionAdapter* GetTCPAnalyzer() { return tcp_analyzer; }
|
||||||
|
|
||||||
// Returns the volume of data buffered in the reassembler.
|
// Returns the volume of data buffered in the reassembler.
|
||||||
// First parameter returns data that is above a hole, and thus is
|
// First parameter returns data that is above a hole, and thus is
|
||||||
|
@ -66,7 +68,7 @@ public:
|
||||||
void AckReceived(uint64_t seq);
|
void AckReceived(uint64_t seq);
|
||||||
|
|
||||||
// Checks if we have delivered all contents that we can possibly
|
// Checks if we have delivered all contents that we can possibly
|
||||||
// deliver for this endpoint. Calls TCP_Analyzer::EndpointEOF()
|
// deliver for this endpoint. Calls TCPSessionAdapter::EndpointEOF()
|
||||||
// when so.
|
// when so.
|
||||||
void CheckEOF();
|
void CheckEOF();
|
||||||
|
|
||||||
|
@ -113,7 +115,7 @@ private:
|
||||||
FilePtr record_contents_file; // file on which to reassemble contents
|
FilePtr record_contents_file; // file on which to reassemble contents
|
||||||
|
|
||||||
analyzer::Analyzer* dst_analyzer;
|
analyzer::Analyzer* dst_analyzer;
|
||||||
TCP_Analyzer* tcp_analyzer;
|
packet_analysis::TCP::TCPSessionAdapter* tcp_analyzer;
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,7 +27,7 @@ function get_orig_seq%(cid: conn_id%): count
|
||||||
|
|
||||||
zeek::analyzer::Analyzer* tc = c->FindAnalyzer("TCP");
|
zeek::analyzer::Analyzer* tc = c->FindAnalyzer("TCP");
|
||||||
if ( tc )
|
if ( tc )
|
||||||
return zeek::val_mgr->Count(static_cast<zeek::analyzer::tcp::TCP_Analyzer*>(tc)->OrigSeq());
|
return zeek::val_mgr->Count(static_cast<zeek::packet_analysis::TCP::TCPSessionAdapter*>(tc)->OrigSeq());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
reporter->Error("connection does not have TCP analyzer");
|
reporter->Error("connection does not have TCP analyzer");
|
||||||
|
@ -56,7 +56,7 @@ function get_resp_seq%(cid: conn_id%): count
|
||||||
|
|
||||||
zeek::analyzer::Analyzer* tc = c->FindAnalyzer("TCP");
|
zeek::analyzer::Analyzer* tc = c->FindAnalyzer("TCP");
|
||||||
if ( tc )
|
if ( tc )
|
||||||
return zeek::val_mgr->Count(static_cast<zeek::analyzer::tcp::TCP_Analyzer*>(tc)->RespSeq());
|
return zeek::val_mgr->Count(static_cast<zeek::packet_analysis::TCP::TCPSessionAdapter*>(tc)->RespSeq());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
reporter->Error("connection does not have TCP analyzer");
|
reporter->Error("connection does not have TCP analyzer");
|
||||||
|
|
|
@ -36,7 +36,7 @@ static zeek::Connection* add_connection()
|
||||||
|
|
||||||
static zeek::analyzer::Analyzer* add_analyzer(zeek::Connection* conn)
|
static zeek::analyzer::Analyzer* add_analyzer(zeek::Connection* conn)
|
||||||
{
|
{
|
||||||
auto* tcp = new zeek::analyzer::tcp::TCP_Analyzer(conn);
|
auto* tcp = new zeek::packet_analysis::TCP::TCPSessionAdapter(conn);
|
||||||
auto* pia = new zeek::analyzer::pia::PIA_TCP(conn);
|
auto* pia = new zeek::analyzer::pia::PIA_TCP(conn);
|
||||||
auto a = zeek::analyzer_mgr->InstantiateAnalyzer(ZEEK_FUZZ_ANALYZER, conn);
|
auto a = zeek::analyzer_mgr->InstantiateAnalyzer(ZEEK_FUZZ_ANALYZER, conn);
|
||||||
tcp->AddChildAnalyzer(a);
|
tcp->AddChildAnalyzer(a);
|
||||||
|
|
|
@ -194,16 +194,7 @@ zeek::Connection* IPBasedAnalyzer::NewConn(const ConnTuple* id, const detail::Co
|
||||||
if ( flip )
|
if ( flip )
|
||||||
conn->FlipRoles();
|
conn->FlipRoles();
|
||||||
|
|
||||||
if ( ! new_plugin )
|
if ( ! BuildSessionAnalyzerTree(conn) )
|
||||||
{
|
|
||||||
if ( ! analyzer_mgr->BuildInitialAnalyzerTree(conn) )
|
|
||||||
{
|
|
||||||
conn->Done();
|
|
||||||
Unref(conn);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( ! BuildSessionAnalyzerTree(conn) )
|
|
||||||
{
|
{
|
||||||
conn->Done();
|
conn->Done();
|
||||||
Unref(conn);
|
Unref(conn);
|
||||||
|
|
|
@ -4,5 +4,5 @@ include(ZeekPlugin)
|
||||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
zeek_plugin_begin(PacketAnalyzer TCP_PKT)
|
zeek_plugin_begin(PacketAnalyzer TCP_PKT)
|
||||||
zeek_plugin_cc(TCP.cc Plugin.cc)
|
zeek_plugin_cc(TCP.cc TCPSessionAdapter.cc Plugin.cc)
|
||||||
zeek_plugin_end()
|
zeek_plugin_end()
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "zeek/plugin/Plugin.h"
|
#include "zeek/plugin/Plugin.h"
|
||||||
#include "zeek/packet_analysis/Component.h"
|
#include "zeek/packet_analysis/Component.h"
|
||||||
#include "zeek/packet_analysis/protocol/tcp/TCP.h"
|
#include "zeek/packet_analysis/protocol/tcp/TCP.h"
|
||||||
|
#include "zeek/packet_analysis/protocol/tcp/TCPSessionAdapter.h"
|
||||||
|
|
||||||
namespace zeek::plugin::Zeek_TCP {
|
namespace zeek::plugin::Zeek_TCP {
|
||||||
|
|
||||||
|
@ -12,6 +13,8 @@ public:
|
||||||
{
|
{
|
||||||
AddComponent(new zeek::packet_analysis::Component("TCP",
|
AddComponent(new zeek::packet_analysis::Component("TCP",
|
||||||
zeek::packet_analysis::TCP::TCPAnalyzer::Instantiate));
|
zeek::packet_analysis::TCP::TCPAnalyzer::Instantiate));
|
||||||
|
AddComponent(new zeek::analyzer::Component("TCP",
|
||||||
|
zeek::packet_analysis::TCP::TCPSessionAdapter::Instantiate));
|
||||||
|
|
||||||
zeek::plugin::Configuration config;
|
zeek::plugin::Configuration config;
|
||||||
config.name = "Zeek::TCP_PKT";
|
config.name = "Zeek::TCP_PKT";
|
||||||
|
|
|
@ -2,18 +2,41 @@
|
||||||
|
|
||||||
#include "zeek/packet_analysis/protocol/tcp/TCP.h"
|
#include "zeek/packet_analysis/protocol/tcp/TCP.h"
|
||||||
#include "zeek/RunState.h"
|
#include "zeek/RunState.h"
|
||||||
|
#include "zeek/analyzer/protocol/pia/PIA.h"
|
||||||
|
#include "zeek/packet_analysis/protocol/tcp/TCPSessionAdapter.h"
|
||||||
|
|
||||||
using namespace zeek::packet_analysis::TCP;
|
using namespace zeek::packet_analysis::TCP;
|
||||||
using namespace zeek::packet_analysis::IP;
|
using namespace zeek::packet_analysis::IP;
|
||||||
|
|
||||||
TCPAnalyzer::TCPAnalyzer() : IPBasedAnalyzer("TCP", TRANSPORT_TCP, TCP_PORT_MASK, false)
|
TCPAnalyzer::TCPAnalyzer() : IPBasedAnalyzer("TCP", TRANSPORT_TCP, TCP_PORT_MASK, false)
|
||||||
{
|
{
|
||||||
|
new_plugin = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TCPAnalyzer::~TCPAnalyzer()
|
TCPAnalyzer::~TCPAnalyzer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TCPAnalyzer::Initialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionAdapter* TCPAnalyzer::MakeSessionAdapter(Connection* conn)
|
||||||
|
{
|
||||||
|
auto* root = new TCPSessionAdapter(conn);
|
||||||
|
root->SetParent(this);
|
||||||
|
|
||||||
|
conn->EnableStatusUpdateTimer();
|
||||||
|
conn->SetInactivityTimeout(zeek::detail::udp_inactivity_timeout);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
zeek::analyzer::pia::PIA* TCPAnalyzer::MakePIA(Connection* conn)
|
||||||
|
{
|
||||||
|
return new analyzer::pia::PIA_TCP(conn);
|
||||||
|
}
|
||||||
|
|
||||||
bool TCPAnalyzer::BuildConnTuple(size_t len, const uint8_t* data, Packet* packet,
|
bool TCPAnalyzer::BuildConnTuple(size_t len, const uint8_t* data, Packet* packet,
|
||||||
ConnTuple& tuple)
|
ConnTuple& tuple)
|
||||||
{
|
{
|
||||||
|
@ -74,3 +97,13 @@ bool TCPAnalyzer::WantConnection(uint16_t src_port, uint16_t dst_port,
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TCPAnalyzer::DeliverPacket(Connection* c, double t, bool is_orig, int remaining, Packet* pkt)
|
||||||
|
{
|
||||||
|
auto* ta = static_cast<TCPSessionAdapter*>(c->GetSessionAdapter());
|
||||||
|
|
||||||
|
const u_char* data = pkt->ip_hdr->Payload();
|
||||||
|
int len = pkt->ip_hdr->PayloadLen();
|
||||||
|
|
||||||
|
ta->DeliverPacket(len, data, is_orig, {}, pkt->ip_hdr.get(), remaining);
|
||||||
|
}
|
||||||
|
|
|
@ -18,14 +18,12 @@ public:
|
||||||
return std::make_shared<TCPAnalyzer>();
|
return std::make_shared<TCPAnalyzer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Returns an adapter appropriate for this IP-based analyzer. This adapter is used to
|
* Initialize the analyzer. This method is called after the configuration
|
||||||
* hook into the session analyzer framework. This function can also be used to do any
|
* was read. Derived classes can override this method to implement custom
|
||||||
* extra initialization of connection timers, etc.
|
* initialization.
|
||||||
*
|
|
||||||
* TODO: this is a stub until the TCP analyzer moves to the packet analysis framework.
|
|
||||||
*/
|
*/
|
||||||
IP::SessionAdapter* MakeSessionAdapter(Connection* conn) override { return nullptr; }
|
void Initialize() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -35,6 +33,9 @@ protected:
|
||||||
bool BuildConnTuple(size_t len, const uint8_t* data, Packet* packet,
|
bool BuildConnTuple(size_t len, const uint8_t* data, Packet* packet,
|
||||||
ConnTuple& tuple) override;
|
ConnTuple& tuple) override;
|
||||||
|
|
||||||
|
void DeliverPacket(Connection* c, double t, bool is_orig, int remaining,
|
||||||
|
Packet* pkt) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upon seeing the first packet of a connection, checks whether we want
|
* Upon seeing the first packet of a connection, checks whether we want
|
||||||
* to analyze it (e.g. we may not want to look at partial connections)
|
* to analyze it (e.g. we may not want to look at partial connections)
|
||||||
|
@ -49,6 +50,19 @@ protected:
|
||||||
*/
|
*/
|
||||||
bool WantConnection(uint16_t src_port, uint16_t dst_port,
|
bool WantConnection(uint16_t src_port, uint16_t dst_port,
|
||||||
const u_char* data, bool& flip_roles) const override;
|
const u_char* data, bool& flip_roles) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an analyzer adapter appropriate for this IP-based analyzer. This adapter
|
||||||
|
* is used to hook into the session analyzer framework. This function can also be used
|
||||||
|
* to do any extra initialization of connection timers, etc.
|
||||||
|
*/
|
||||||
|
packet_analysis::IP::SessionAdapter* MakeSessionAdapter(Connection* conn) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a PIA appropriate for this IP-based analyzer. This method is optional to
|
||||||
|
* override in child classes, as not all analyzers need a PIA.
|
||||||
|
*/
|
||||||
|
analyzer::pia::PIA* MakePIA(Connection* conn) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
1933
src/packet_analysis/protocol/tcp/TCPSessionAdapter.cc
Normal file
1933
src/packet_analysis/protocol/tcp/TCPSessionAdapter.cc
Normal file
File diff suppressed because it is too large
Load diff
197
src/packet_analysis/protocol/tcp/TCPSessionAdapter.h
Normal file
197
src/packet_analysis/protocol/tcp/TCPSessionAdapter.h
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "zeek/packet_analysis/Analyzer.h"
|
||||||
|
#include "zeek/packet_analysis/Component.h"
|
||||||
|
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
|
||||||
|
#include "zeek/session/Manager.h"
|
||||||
|
#include "zeek/analyzer/protocol/tcp/TCP_Flags.h"
|
||||||
|
|
||||||
|
namespace zeek::analyzer::pia { class PIA_TCP; }
|
||||||
|
namespace zeek::analyzer::tcp {
|
||||||
|
|
||||||
|
class TCP_Endpoint;
|
||||||
|
class TCP_Reassembler;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace zeek::packet_analysis::TCP {
|
||||||
|
|
||||||
|
class TCPAnalyzer;
|
||||||
|
|
||||||
|
class TCPSessionAdapter final : public packet_analysis::IP::SessionAdapter {
|
||||||
|
public:
|
||||||
|
explicit TCPSessionAdapter(Connection* conn);
|
||||||
|
~TCPSessionAdapter() override;
|
||||||
|
|
||||||
|
void EnableReassembly();
|
||||||
|
|
||||||
|
// Add a child analyzer that will always get the packets,
|
||||||
|
// independently of whether we do any reassembly.
|
||||||
|
void AddChildPacketAnalyzer(analyzer::Analyzer* a);
|
||||||
|
|
||||||
|
Analyzer* FindChild(analyzer::ID id) override;
|
||||||
|
Analyzer* FindChild(analyzer::Tag tag) override;
|
||||||
|
bool RemoveChildAnalyzer(analyzer::ID id) override;
|
||||||
|
|
||||||
|
// True if the connection has closed in some sense, false otherwise.
|
||||||
|
bool IsClosed() const { return orig->did_close || resp->did_close; }
|
||||||
|
bool BothClosed() const { return orig->did_close && resp->did_close; }
|
||||||
|
|
||||||
|
bool IsPartial() const { return is_partial; }
|
||||||
|
|
||||||
|
bool HadGap(bool orig) const;
|
||||||
|
|
||||||
|
analyzer::tcp::TCP_Endpoint* Orig() const { return orig; }
|
||||||
|
analyzer::tcp::TCP_Endpoint* Resp() const { return resp; }
|
||||||
|
int OrigState() const { return orig->state; }
|
||||||
|
int RespState() const { return resp->state; }
|
||||||
|
int OrigPrevState() const { return orig->prev_state; }
|
||||||
|
int RespPrevState() const { return resp->prev_state; }
|
||||||
|
uint32_t OrigSeq() const { return orig->LastSeq(); }
|
||||||
|
uint32_t RespSeq() const { return resp->LastSeq(); }
|
||||||
|
|
||||||
|
// True if either endpoint still has pending data. closing_endp
|
||||||
|
// is an endpoint that has indicated it is closing (i.e., for
|
||||||
|
// which we have seen a FIN) - for it, data is pending unless
|
||||||
|
// everything's been delivered up to the FIN. For its peer,
|
||||||
|
// the test is whether it has any outstanding, un-acked data.
|
||||||
|
bool DataPending(analyzer::tcp::TCP_Endpoint* closing_endp);
|
||||||
|
|
||||||
|
void SetContentsFile(unsigned int direction, FilePtr f) override;
|
||||||
|
FilePtr GetContentsFile(unsigned int direction) const override;
|
||||||
|
|
||||||
|
// From Analyzer.h
|
||||||
|
void UpdateConnVal(RecordVal *conn_val) override;
|
||||||
|
|
||||||
|
int ParseTCPOptions(const struct tcphdr* tcp, bool is_orig);
|
||||||
|
|
||||||
|
static analyzer::Analyzer* Instantiate(Connection* conn)
|
||||||
|
{ return new TCPSessionAdapter(conn); }
|
||||||
|
|
||||||
|
void AddExtraAnalyzers(Connection* conn) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class analyzer::tcp::TCP_ApplicationAnalyzer;
|
||||||
|
friend class analyzer::tcp::TCP_Reassembler;
|
||||||
|
friend class analyzer::pia::PIA_TCP;
|
||||||
|
friend class packet_analysis::TCP::TCPAnalyzer;
|
||||||
|
|
||||||
|
// Analyzer interface.
|
||||||
|
void Init() override;
|
||||||
|
void Done() override;
|
||||||
|
void DeliverPacket(int len, const u_char* data, bool orig, uint64_t seq,
|
||||||
|
const IP_Hdr* ip, int caplen) override;
|
||||||
|
void DeliverStream(int len, const u_char* data, bool orig) override;
|
||||||
|
void Undelivered(uint64_t seq, int len, bool orig) override;
|
||||||
|
void FlipRoles() override;
|
||||||
|
bool IsReuse(double t, const u_char* pkt) override;
|
||||||
|
|
||||||
|
// Returns the TCP header pointed to by data (which we assume is
|
||||||
|
// aligned), updating data, len & caplen. Returns nil if the header
|
||||||
|
// isn't fully present.
|
||||||
|
const struct tcphdr* ExtractTCP_Header(const u_char*& data, int& len,
|
||||||
|
int& caplen);
|
||||||
|
|
||||||
|
// Returns true if the checksum is valid, false if not (and in which
|
||||||
|
// case also updates the status history of the endpoint).
|
||||||
|
bool ValidateChecksum(const IP_Hdr* ip, const struct tcphdr* tp, analyzer::tcp::TCP_Endpoint* endpoint,
|
||||||
|
int len, int caplen);
|
||||||
|
|
||||||
|
void SetPartialStatus(analyzer::tcp::TCP_Flags flags, bool is_orig);
|
||||||
|
|
||||||
|
// Update the state machine of the TCPs based on the activity. This
|
||||||
|
// includes our pseudo-states such as TCP_ENDPOINT_PARTIAL.
|
||||||
|
//
|
||||||
|
// On return, do_close is true if we should consider the connection
|
||||||
|
// as closed, and gen_event if we shouuld generate an event about
|
||||||
|
// this fact.
|
||||||
|
void UpdateStateMachine(double t,
|
||||||
|
analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer,
|
||||||
|
uint32_t base_seq, uint32_t ack_seq,
|
||||||
|
int len, int32_t delta_last, bool is_orig, analyzer::tcp::TCP_Flags flags,
|
||||||
|
bool& do_close, bool& gen_event);
|
||||||
|
|
||||||
|
void UpdateInactiveState(double t,
|
||||||
|
analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer,
|
||||||
|
uint32_t base_seq, uint32_t ack_seq,
|
||||||
|
int len, bool is_orig, analyzer::tcp::TCP_Flags flags,
|
||||||
|
bool& do_close, bool& gen_event);
|
||||||
|
|
||||||
|
void UpdateSYN_SentState(analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer,
|
||||||
|
int len, bool is_orig, analyzer::tcp::TCP_Flags flags,
|
||||||
|
bool& do_close, bool& gen_event);
|
||||||
|
|
||||||
|
void UpdateEstablishedState(analyzer::tcp::TCP_Endpoint* endpoint, analyzer::tcp::TCP_Endpoint* peer,
|
||||||
|
analyzer::tcp::TCP_Flags flags, bool& do_close, bool& gen_event);
|
||||||
|
|
||||||
|
void UpdateClosedState(double t, analyzer::tcp::TCP_Endpoint* endpoint,
|
||||||
|
int32_t delta_last, analyzer::tcp::TCP_Flags flags,
|
||||||
|
bool& do_close);
|
||||||
|
|
||||||
|
void UpdateResetState(int len, analyzer::tcp::TCP_Flags flags);
|
||||||
|
|
||||||
|
void GeneratePacketEvent(uint64_t rel_seq, uint64_t rel_ack,
|
||||||
|
const u_char* data, int len, int caplen,
|
||||||
|
bool is_orig, analyzer::tcp::TCP_Flags flags);
|
||||||
|
|
||||||
|
bool DeliverData(double t, const u_char* data, int len, int caplen,
|
||||||
|
const IP_Hdr* ip, const struct tcphdr* tp,
|
||||||
|
analyzer::tcp::TCP_Endpoint* endpoint, uint64_t rel_data_seq,
|
||||||
|
bool is_orig, analyzer::tcp::TCP_Flags flags);
|
||||||
|
|
||||||
|
void CheckRecording(bool need_contents, analyzer::tcp::TCP_Flags flags);
|
||||||
|
void CheckPIA_FirstPacket(bool is_orig, const IP_Hdr* ip);
|
||||||
|
|
||||||
|
friend class session::detail::Timer;
|
||||||
|
void AttemptTimer(double t);
|
||||||
|
void PartialCloseTimer(double t);
|
||||||
|
void ExpireTimer(double t);
|
||||||
|
void ResetTimer(double t);
|
||||||
|
void DeleteTimer(double t);
|
||||||
|
void ConnDeleteTimer(double t);
|
||||||
|
|
||||||
|
void EndpointEOF(analyzer::tcp::TCP_Reassembler* endp);
|
||||||
|
void ConnectionClosed(analyzer::tcp::TCP_Endpoint* endpoint,
|
||||||
|
analyzer::tcp::TCP_Endpoint* peer, bool gen_event);
|
||||||
|
void ConnectionFinished(bool half_finished);
|
||||||
|
void ConnectionReset();
|
||||||
|
void PacketWithRST();
|
||||||
|
|
||||||
|
void SetReassembler(analyzer::tcp::TCP_Reassembler* rorig, analyzer::tcp::TCP_Reassembler* rresp);
|
||||||
|
|
||||||
|
// A couple utility functions that may also be useful to derived analyzers.
|
||||||
|
static uint64_t get_relative_seq(const analyzer::tcp::TCP_Endpoint* endpoint,
|
||||||
|
uint32_t cur_base, uint32_t last,
|
||||||
|
uint32_t wraps, bool* underflow = nullptr);
|
||||||
|
|
||||||
|
static int get_segment_len(int payload_len, analyzer::tcp::TCP_Flags flags);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void SynWeirds(analyzer::tcp::TCP_Flags flags, analyzer::tcp::TCP_Endpoint* endpoint, int data_len) const;
|
||||||
|
|
||||||
|
analyzer::tcp::TCP_Endpoint* orig;
|
||||||
|
analyzer::tcp::TCP_Endpoint* resp;
|
||||||
|
|
||||||
|
analyzer::analyzer_list packet_children;
|
||||||
|
|
||||||
|
unsigned int first_packet_seen: 2;
|
||||||
|
unsigned int reassembling: 1;
|
||||||
|
unsigned int is_partial: 1;
|
||||||
|
unsigned int is_active: 1;
|
||||||
|
unsigned int finished: 1;
|
||||||
|
|
||||||
|
// Whether we're waiting on final data delivery before closing
|
||||||
|
// this connection.
|
||||||
|
unsigned int close_deferred: 1;
|
||||||
|
|
||||||
|
// Whether to generate an event when we finally do close it.
|
||||||
|
unsigned int deferred_gen_event: 1;
|
||||||
|
|
||||||
|
// Whether we have seen the first ACK from the originator.
|
||||||
|
unsigned int seen_first_ACK: 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace zeek::packet_analysis::tcp
|
|
@ -595,7 +595,6 @@ SetupResult setup(int argc, char** argv, Options* zopts)
|
||||||
trigger_mgr = new trigger::Manager();
|
trigger_mgr = new trigger::Manager();
|
||||||
|
|
||||||
plugin_mgr->InitPreScript();
|
plugin_mgr->InitPreScript();
|
||||||
analyzer_mgr->InitPreScript();
|
|
||||||
file_mgr->InitPreScript();
|
file_mgr->InitPreScript();
|
||||||
zeekygen_mgr->InitPreScript();
|
zeekygen_mgr->InitPreScript();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue