SIP: Fix up DPD and the TCP analyzer a bit.

This commit is contained in:
Vlad Grigorescu 2015-03-19 19:57:05 -04:00
parent 1ea5463037
commit e2134d3cb9
9 changed files with 175 additions and 9 deletions

View file

@ -1,5 +1,17 @@
signature dpd_sip {
signature dpd_sip_udp_req {
ip-proto == udp
payload /.* SIP\/[0-9]\.[0-9]\x0d\x0a/
enable "sip"
}
signature dpd_sip_udp_resp {
ip-proto == udp
payload /^( SIP\/[0-9]\.[0-9]\x0d\x0a|SIP\/[0-9]\.[0-9] [0-9][0-9][0-9] )/
enable "sip"
}
signature dpd_sip_tcp {
ip-proto == tcp
payload /^( SIP\/[0-9]\.[0-9]\x0d\x0a|SIP\/[0-9]\.[0-9] [0-9][0-9][0-9] )/
enable "sip_tcp"
}

View file

@ -85,13 +85,9 @@ redef record connection += {
sip_state: State &optional;
};
const ports = { 5060/udp };
redef likely_server_ports += { ports };
event bro_init() &priority=5
{
Log::create_stream(SIP::LOG, [$columns=Info, $ev=log_sip]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SIP, ports);
}
function new_sip_session(c: connection): Info
@ -209,8 +205,6 @@ event connection_state_remove(c: connection) &priority=-5
{
for ( r in c$sip_state$pending )
{
# We don't use pending elements at index 0.
if ( r == 0 ) next;
Log::write(SIP::LOG, c$sip_state$pending[r]);
}
}

View file

@ -8,3 +8,8 @@ bro_plugin_cc(SIP.cc Plugin.cc)
bro_plugin_bif(events.bif)
bro_plugin_pac(sip.pac sip-analyzer.pac sip-protocol.pac)
bro_plugin_end()
bro_plugin_begin(Bro SIP_TCP)
bro_plugin_cc(SIP_TCP.cc Plugin_TCP.cc)
bro_plugin_pac(sip_TCP.pac sip-protocol.pac sip-analyzer.pac)
bro_plugin_end()

View file

@ -0,0 +1,20 @@
//See the file in the main distribution directory for copyright.
#include "plugin/Plugin.h"
#include "SIP_TCP.h"
namespace plugin {
namespace Bro_SIP_TCP {
class Plugin : public plugin::Plugin {
public:
plugin::Configuration Configure()
{
AddComponent(new ::analyzer::Component("SIP_TCP", ::analyzer::sip_tcp::SIP_Analyzer::Instantiate));
plugin::Configuration config;
config.name = "Bro::SIP_TCP";
config.description = "SIP analyzer (TCP)";
return config;
}
} plugin;
}
}

View file

@ -27,6 +27,10 @@ void SIP_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
if ( len > 6 && data[0] == 'S' && data[1] == 'I' && data[2] == 'P' && data[3] == '/' )
real_orig = false;
// Sometimes we see some packets with just '\r\n' - ignore those
if ( len == 2 && data[0] == '\r')
return;
Analyzer::DeliverPacket(len, data, real_orig, seq, ip, caplen);
try

View file

@ -0,0 +1,65 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "SIP_TCP.h"
#include "analyzer/protocol/tcp/TCP_Reassembler.h"
#include "events.bif.h"
using namespace analyzer::sip_tcp;
SIP_Analyzer::SIP_Analyzer(Connection* conn)
: tcp::TCP_ApplicationAnalyzer("SIP_TCP", conn)
{
interp = new binpac::SIP_TCP::SIP_Conn(this);
had_gap = false;
}
SIP_Analyzer::~SIP_Analyzer()
{
delete interp;
}
void SIP_Analyzer::Done()
{
tcp::TCP_ApplicationAnalyzer::Done();
interp->FlowEOF(true);
interp->FlowEOF(false);
}
void SIP_Analyzer::EndpointEOF(bool is_orig)
{
tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
interp->FlowEOF(is_orig);
}
void SIP_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
{
tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
assert(TCP());
if ( TCP()->IsPartial() )
return;
if ( had_gap )
// If only one side had a content gap, we could still try to
// deliver data to the other side if the script layer can
// handle this.
return;
try
{
interp->NewData(orig, data, data + len);
}
catch ( const binpac::Exception& e )
{
printf("BinPAC Exception: %s\n", e.c_msg());
ProtocolViolation(e.c_msg());
}
}
void SIP_Analyzer::Undelivered(uint64 seq, int len, bool orig)
{
tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
had_gap = true;
interp->NewGap(orig, len);
}

View file

@ -0,0 +1,37 @@
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef ANALYZER_PROTOCOL_SIP_SIP_TCP_H
#define ANALYZER_PROTOCOL_SIP_SIP_TCP_H
#include "analyzer/protocol/tcp/TCP.h"
#include "sip_TCP_pac.h"
namespace analyzer { namespace sip_tcp {
class SIP_Analyzer : public tcp::TCP_ApplicationAnalyzer {
public:
SIP_Analyzer(Connection* conn);
virtual ~SIP_Analyzer();
virtual void Done();
virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual void Undelivered(uint64 seq, int len, bool orig);
// Overriden from tcp::TCP_ApplicationAnalyzer.
virtual void EndpointEOF(bool is_orig);
static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new SIP_Analyzer(conn); }
protected:
binpac::SIP_TCP::SIP_Conn* interp;
bool had_gap;
};
} } // namespace analyzer::*
#endif

View file

@ -18,6 +18,7 @@ refine flow SIP_Flow += {
function proc_sip_request(method: bytestring, uri: bytestring, vers: SIP_Version): bool
%{
connection()->bro_analyzer()->ProtocolConfirmation();
if ( sip_request )
{
BifEvent::generate_sip_request(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(),
@ -32,6 +33,7 @@ refine flow SIP_Flow += {
function proc_sip_reply(vers: SIP_Version, code: int, reason: bytestring): bool
%{
connection()->bro_analyzer()->ProtocolConfirmation();
if ( sip_reply )
{
BifEvent::generate_sip_reply(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(),

View file

@ -0,0 +1,27 @@
# BinPAC file for SIP over TCP
# Based heavily on the HTTP BinPAC analyzer
%include binpac.pac
%include bro.pac
%extern{
#include "events.bif.h"
%}
analyzer SIP_TCP withcontext {
connection: SIP_Conn;
flow: SIP_Flow;
};
connection SIP_Conn(bro_analyzer: BroAnalyzer) {
upflow = SIP_Flow(true);
downflow = SIP_Flow(false);
};
%include sip-protocol.pac
flow SIP_Flow(is_orig: bool) {
datagram = SIP_PDU(is_orig) withcontext(connection, this);
};
%include sip-analyzer.pac