Merge remote-tracking branch 'origin/topic/johanna/dtls'

* origin/topic/johanna/dtls:
  a few more small script-level fixes
  update test baselines
  add a simple leak test for dtls
  add signature for dtls client hello
  Make the plugin structure more... legal.
  Only force logging of SSL if it actually was the SSL analyzer that failed.
  DTLS working.
  Implement correct parsing of TLS record fragmentation.
  Make handshake analyzer flow-based. This means we can feed data to it in chunks, which makes dealing with fragmentation a little bit more convenient.
  When setting the SSL analyzer to fail, also stop processing data that already has been delivered to the analyzer, not just future data.
  First step for a DTLS analyzer.

BIT-1347 #merged

Conflicts:
	scripts/base/protocols/ssl/main.bro
	testing/btest/Baseline/plugins.hooks/output
This commit is contained in:
Robin Sommer 2015-03-23 12:33:42 -07:00
commit 99c50251d4
39 changed files with 1803 additions and 1178 deletions

View file

@ -1,4 +1,11 @@
2.3-595 | 2015-03-23 12:33:42 -0700
* DTLS analyzer. (Johanna Amann)
* Implement correct parsing of TLS record fragmentation. (Johanna
Amann)
2.3-582 | 2015-03-23 11:34:25 -0700 2.3-582 | 2015-03-23 11:34:25 -0700
* BIT-1313: In debug builds, "bro -B <x>" now supports "all" and * BIT-1313: In debug builds, "bro -B <x>" now supports "all" and

2
NEWS
View file

@ -63,6 +63,8 @@ New Functionality
- A new icmp_sent_payload event provides access to ICMP payload. - A new icmp_sent_payload event provides access to ICMP payload.
- Bro now parses DTLS traffic.
Changed Functionality Changed Functionality
--------------------- ---------------------

View file

@ -1 +1 @@
2.3-582 2.3-595

View file

@ -6,6 +6,11 @@ export {
const TLSv10 = 0x0301; const TLSv10 = 0x0301;
const TLSv11 = 0x0302; const TLSv11 = 0x0302;
const TLSv12 = 0x0303; const TLSv12 = 0x0303;
const DTLSv10 = 0xFEFF;
# DTLSv11 does not exist
const DTLSv12 = 0xFEFD;
## Mapping between the constants and string values for SSL/TLS versions. ## Mapping between the constants and string values for SSL/TLS versions.
const version_strings: table[count] of string = { const version_strings: table[count] of string = {
[SSLv2] = "SSLv2", [SSLv2] = "SSLv2",
@ -13,6 +18,8 @@ export {
[TLSv10] = "TLSv10", [TLSv10] = "TLSv10",
[TLSv11] = "TLSv11", [TLSv11] = "TLSv11",
[TLSv12] = "TLSv12", [TLSv12] = "TLSv12",
[DTLSv10] = "DTLSv10",
[DTLSv12] = "DTLSv12"
} &default=function(i: count):string { return fmt("unknown-%d", i); }; } &default=function(i: count):string { return fmt("unknown-%d", i); };
## TLS content types: ## TLS content types:

View file

@ -13,3 +13,10 @@ signature dpd_ssl_client {
payload /^(\x16\x03[\x00\x01\x02\x03]..\x01...\x03[\x00\x01\x02\x03]|...?\x01[\x00\x03][\x00\x01\x02\x03]).*/ payload /^(\x16\x03[\x00\x01\x02\x03]..\x01...\x03[\x00\x01\x02\x03]|...?\x01[\x00\x03][\x00\x01\x02\x03]).*/
tcp-state originator tcp-state originator
} }
signature dpd_dtls_client {
ip-proto == udp
# Client hello.
payload /^\x16\xfe[\xff\xfd]\x00\x00\x00\x00\x00\x00\x00...\x01...........\xfe[\xff\xfd].*/
enable "dtls"
}

View file

@ -85,6 +85,10 @@ event bro_init() &priority=5
Files::register_protocol(Analyzer::ANALYZER_SSL, Files::register_protocol(Analyzer::ANALYZER_SSL,
[$get_file_handle = SSL::get_file_handle, [$get_file_handle = SSL::get_file_handle,
$describe = SSL::describe_file]); $describe = SSL::describe_file]);
Files::register_protocol(Analyzer::ANALYZER_DTLS,
[$get_file_handle = SSL::get_file_handle,
$describe = SSL::describe_file]);
} }
event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5 event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5

View file

@ -92,16 +92,22 @@ redef record Info += {
delay_tokens: set[string] &optional; delay_tokens: set[string] &optional;
}; };
const ports = { const ssl_ports = {
443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp, 443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp,
989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp 989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp
}; };
redef likely_server_ports += { ports };
# There are no well known DTLS ports at the moment. Let's
# just add 443 for now for good measure - who knows :)
const dtls_ports = { 443/udp };
redef likely_server_ports += { ssl_ports, dtls_ports };
event bro_init() &priority=5 event bro_init() &priority=5
{ {
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl, $path="ssl"]); Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl, $path="ssl"]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SSL, ports); Analyzer::register_for_ports(Analyzer::ANALYZER_SSL, ssl_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_DTLS, dtls_ports);
} }
function set_session(c: connection) function set_session(c: connection)
@ -268,7 +274,7 @@ event connection_state_remove(c: connection) &priority=-5
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=5 event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=5
{ {
if ( atype == Analyzer::ANALYZER_SSL ) if ( atype == Analyzer::ANALYZER_SSL || atype == Analyzer::ANALYZER_DTLS )
{ {
set_session(c); set_session(c);
c$ssl$analyzer_id = aid; c$ssl$analyzer_id = aid;
@ -278,6 +284,6 @@ event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &pr
event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count, event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count,
reason: string) &priority=5 reason: string) &priority=5
{ {
if ( c?$ssl ) if ( c?$ssl && ( atype == Analyzer::ANALYZER_SSL || atype == Analyzer::ANALYZER_DTLS ) )
finish(c, T); finish(c, T);
} }

View file

@ -4,7 +4,9 @@ include(BroPlugin)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
bro_plugin_begin(Bro SSL) bro_plugin_begin(Bro SSL)
bro_plugin_cc(SSL.cc Plugin.cc) bro_plugin_cc(SSL.cc DTLS.cc Plugin.cc)
bro_plugin_bif(events.bif) bro_plugin_bif(events.bif)
bro_plugin_pac(ssl.pac ssl-analyzer.pac ssl-protocol.pac ssl-defs.pac) bro_plugin_pac(tls-handshake.pac tls-handshake-protocol.pac tls-handshake-analyzer.pac ssl-defs.pac)
bro_plugin_pac(ssl.pac ssl-dtls-analyzer.pac ssl-analyzer.pac ssl-dtls-protocol.pac ssl-protocol.pac ssl-defs.pac)
bro_plugin_pac(dtls.pac ssl-dtls-analyzer.pac dtls-analyzer.pac ssl-dtls-protocol.pac dtls-protocol.pac ssl-defs.pac)
bro_plugin_end() bro_plugin_end()

View file

@ -0,0 +1,65 @@
#include "DTLS.h"
#include "Reporter.h"
#include "util.h"
#include "events.bif.h"
#include "dtls_pac.h"
#include "tls-handshake_pac.h"
using namespace analyzer::dtls;
DTLS_Analyzer::DTLS_Analyzer(Connection* c)
: analyzer::Analyzer("DTLS", c)
{
interp = new binpac::DTLS::SSL_Conn(this);
handshake_interp = new binpac::TLSHandshake::Handshake_Conn(this);
}
DTLS_Analyzer::~DTLS_Analyzer()
{
delete interp;
delete handshake_interp;
}
void DTLS_Analyzer::Done()
{
Analyzer::Done();
interp->FlowEOF(true);
interp->FlowEOF(false);
handshake_interp->FlowEOF(true);
handshake_interp->FlowEOF(false);
}
void DTLS_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint64 seq, const IP_Hdr* ip, int caplen)
{
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
interp->NewData(orig, data, data + len);
}
void DTLS_Analyzer::EndOfData(bool is_orig)
{
Analyzer::EndOfData(is_orig);
interp->FlowEOF(is_orig);
handshake_interp->FlowEOF(is_orig);
}
void DTLS_Analyzer::SendHandshake(uint8 msg_type, uint32 length, const u_char* begin, const u_char* end, bool orig)
{
try
{
handshake_interp->NewData(orig, (const unsigned char*) &msg_type, (const unsigned char*) &msg_type + 1);
uint32 host_length = htonl(length);
// the parser inspects a uint24 - since it is big-endian, it should be ok to just skip
// the first byte of the uint32. Since we get the data from an uint24 from the dtls-parser, this should
// always yield the correct result.
handshake_interp->NewData(orig, (const unsigned char*) &host_length + 1, (const unsigned char*) &host_length + sizeof(host_length));
handshake_interp->NewData(orig, begin, end);
}
catch ( const binpac::Exception& e )
{
ProtocolViolation(fmt("Binpac exception: %s", e.c_msg()));
}
}

View file

@ -0,0 +1,38 @@
#ifndef ANALYZER_PROTOCOL_SSL_DTLS_H
#define ANALYZER_PROTOCOL_SSL_DTLS_H
#include "events.bif.h"
#include "analyzer/protocol/udp/UDP.h"
namespace binpac { namespace DTLS { class SSL_Conn; } }
namespace binpac { namespace TLSHandshake { class Handshake_Conn; } }
namespace analyzer { namespace dtls {
class DTLS_Analyzer : public analyzer::Analyzer {
public:
DTLS_Analyzer(Connection* conn);
virtual ~DTLS_Analyzer();
// Overriden from Analyzer.
virtual void Done();
virtual void DeliverPacket(int len, const u_char* data, bool orig,
uint64 seq, const IP_Hdr* ip, int caplen);
virtual void EndOfData(bool is_orig);
void SendHandshake(uint8 msg_type, uint32 length, const u_char* begin, const u_char* end, bool orig);
static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new DTLS_Analyzer(conn); }
protected:
binpac::DTLS::SSL_Conn* interp;
binpac::TLSHandshake::Handshake_Conn* handshake_interp;
};
} } // namespace analyzer::*
#endif

View file

@ -4,6 +4,7 @@
#include "plugin/Plugin.h" #include "plugin/Plugin.h"
#include "SSL.h" #include "SSL.h"
#include "DTLS.h"
namespace plugin { namespace plugin {
namespace Bro_SSL { namespace Bro_SSL {
@ -13,10 +14,11 @@ public:
plugin::Configuration Configure() plugin::Configuration Configure()
{ {
AddComponent(new ::analyzer::Component("SSL", ::analyzer::ssl::SSL_Analyzer::Instantiate)); AddComponent(new ::analyzer::Component("SSL", ::analyzer::ssl::SSL_Analyzer::Instantiate));
AddComponent(new ::analyzer::Component("DTLS", ::analyzer::dtls::DTLS_Analyzer::Instantiate));
plugin::Configuration config; plugin::Configuration config;
config.name = "Bro::SSL"; config.name = "Bro::SSL";
config.description = "SSL analyzer"; config.description = "SSL/TLS and DTLS analyzers";
return config; return config;
} }
} plugin; } plugin;

View file

@ -5,6 +5,8 @@
#include "util.h" #include "util.h"
#include "events.bif.h" #include "events.bif.h"
#include "ssl_pac.h"
#include "tls-handshake_pac.h"
using namespace analyzer::ssl; using namespace analyzer::ssl;
@ -12,12 +14,14 @@ SSL_Analyzer::SSL_Analyzer(Connection* c)
: tcp::TCP_ApplicationAnalyzer("SSL", c) : tcp::TCP_ApplicationAnalyzer("SSL", c)
{ {
interp = new binpac::SSL::SSL_Conn(this); interp = new binpac::SSL::SSL_Conn(this);
handshake_interp = new binpac::TLSHandshake::Handshake_Conn(this);
had_gap = false; had_gap = false;
} }
SSL_Analyzer::~SSL_Analyzer() SSL_Analyzer::~SSL_Analyzer()
{ {
delete interp; delete interp;
delete handshake_interp;
} }
void SSL_Analyzer::Done() void SSL_Analyzer::Done()
@ -26,12 +30,15 @@ void SSL_Analyzer::Done()
interp->FlowEOF(true); interp->FlowEOF(true);
interp->FlowEOF(false); interp->FlowEOF(false);
handshake_interp->FlowEOF(true);
handshake_interp->FlowEOF(false);
} }
void SSL_Analyzer::EndpointEOF(bool is_orig) void SSL_Analyzer::EndpointEOF(bool is_orig)
{ {
tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig); tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
interp->FlowEOF(is_orig); interp->FlowEOF(is_orig);
handshake_interp->FlowEOF(is_orig);
} }
void SSL_Analyzer::DeliverStream(int len, const u_char* data, bool orig) void SSL_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
@ -57,6 +64,18 @@ void SSL_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
} }
} }
void SSL_Analyzer::SendHandshake(const u_char* begin, const u_char* end, bool orig)
{
try
{
handshake_interp->NewData(orig, begin, end);
}
catch ( const binpac::Exception& e )
{
ProtocolViolation(fmt("Binpac exception: %s", e.c_msg()));
}
}
void SSL_Analyzer::Undelivered(uint64 seq, int len, bool orig) void SSL_Analyzer::Undelivered(uint64 seq, int len, bool orig)
{ {
tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);

View file

@ -4,7 +4,10 @@
#include "events.bif.h" #include "events.bif.h"
#include "analyzer/protocol/tcp/TCP.h" #include "analyzer/protocol/tcp/TCP.h"
#include "ssl_pac.h"
namespace binpac { namespace SSL { class SSL_Conn; } }
namespace binpac { namespace TLSHandshake { class Handshake_Conn; } }
namespace analyzer { namespace ssl { namespace analyzer { namespace ssl {
@ -18,6 +21,8 @@ public:
virtual void DeliverStream(int len, const u_char* data, bool orig); virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual void Undelivered(uint64 seq, int len, bool orig); virtual void Undelivered(uint64 seq, int len, bool orig);
void SendHandshake(const u_char* begin, const u_char* end, bool orig);
// Overriden from tcp::TCP_ApplicationAnalyzer. // Overriden from tcp::TCP_ApplicationAnalyzer.
virtual void EndpointEOF(bool is_orig); virtual void EndpointEOF(bool is_orig);
@ -26,6 +31,7 @@ public:
protected: protected:
binpac::SSL::SSL_Conn* interp; binpac::SSL::SSL_Conn* interp;
binpac::TLSHandshake::Handshake_Conn* handshake_interp;
bool had_gap; bool had_gap;
}; };

View file

@ -0,0 +1,150 @@
refine connection SSL_Conn += {
%member{
struct message_info {
uint64 message_first_sequence; // the minumum dtls sequence number for this handshake fragment
bool first_sequence_seen; // did we actually see the fragment with the smallest number
uint64 message_last_sequence; // the mazimum dtls sequence number for this handshake fragment
uint16 message_handshake_sequence; // the handshake sequence number of this handshake (to identify)
uint32 message_length; // data length of this handshake (data in buffer)
uint32 message_sequence_seen; // a bitfield that shows which sequence numbers we already saw, offset from first_seq.
u_char* buffer;
} server, client;
%}
%init{
memset(&server, 0, sizeof(server));
memset(&client, 0, sizeof(client));
%}
%cleanup{
delete [] server.buffer;
delete [] client.buffer;
%}
function proc_dtls(pdu: SSLRecord, sequence: uint64): bool
%{
//fprintf(stderr, "Type: %d, sequence number: %d, epoch: %d\n", ${pdu.content_type}, sequence, ${pdu.epoch});
return true;
%}
function proc_handshake(pdu: SSLRecord, rec: Handshake): bool
%{
uint32 foffset = to_int()(${rec.fragment_offset});
uint32 flength = to_int()(${rec.fragment_length});
uint32 length = to_int()(${rec.length});
uint64 sequence_number = to_int()(${pdu.sequence_number});
//fprintf(stderr, "Handshake type: %d, length: %u, seq: %u, foffset: %u, flength: %u\n", ${rec.msg_type}, to_int()(${rec.length}), ${rec.message_seq}, to_int()(${rec.fragment_offset}), to_int()(${rec.fragment_length}));
if ( foffset == 0 && length == flength )
{
//fprintf(stderr, "Complete fragment, forwarding...\n");
bro_analyzer()->SendHandshake(${rec.msg_type}, length, ${rec.data}.begin(), ${rec.data}.end(), ${pdu.is_orig});
return true;
}
// if we fall through here, the message has to be reassembled. Let's first get the right info record...
message_info* i;
if ( ${pdu.is_orig} )
i = &client;
else
i = &server;
if ( length > MAX_DTLS_HANDSHAKE_RECORD )
{
bro_analyzer()->ProtocolViolation(fmt("DTLS record length %u larger than allowed maximum.", length));
return true;
}
if ( i->message_handshake_sequence != ${rec.message_seq} || i->message_length != length || i->buffer == 0 )
{
// cannot resume reassembling. Let's abandon the current data and try anew...
delete [] i->buffer;
memset(i, 0, sizeof(message_info));
i->message_handshake_sequence = ${rec.message_seq};
i->message_length = length;
i->buffer = new u_char[length];
// does not have to be the first sequence number - we cannot figure that out at this point. If it is not,
// we will fix that later...
i->message_first_sequence = sequence_number;
}
// if we arrive here, we are actually ready to resume.
if ( i->message_first_sequence > sequence_number )
{
if ( i->first_sequence_seen )
{
bro_analyzer()->ProtocolViolation("Saw second and different first message fragment for handshake.");
return true;
}
// first sequence number was incorrect, let's fix that.
uint64 diff = i->message_first_sequence - sequence_number;
i->message_sequence_seen = i->message_sequence_seen << diff;
i->message_first_sequence = sequence_number;
}
// if we have offset 0, we know the smallest number...
if ( foffset == 0 )
i->first_sequence_seen = true;
// check if we already saw the message
if ( ( i->message_sequence_seen & ( 1 << (sequence_number - i->message_first_sequence) ) ) != 0 )
return true; // do not handle same message fragment twice
// copy data from fragment to buffer
if ( ${rec.data}.length() != flength )
{
bro_analyzer()->ProtocolViolation(fmt("DTLS handshake record length does not match packet length"));
return true;
}
if ( foffset + flength > length )
{
bro_analyzer()->ProtocolViolation(fmt("DTLS handshake fragment trying to write past end of buffer"));
return true;
}
// store that we handled fragment
i->message_sequence_seen |= 1 << (sequence_number - i->message_first_sequence);
memcpy(i->buffer + foffset, ${rec.data}.data(), ${rec.data}.length());
//fprintf(stderr, "Copied to buffer offset %u length %u\n", foffset, ${rec.data}.length());
// store last fragment information if this is the last fragment...
// check if we saw all fragments so far. If yes, forward...
if ( foffset + flength == length )
i->message_last_sequence = sequence_number;
if ( i->message_last_sequence != 0 && i->first_sequence_seen )
{
uint64 total_length = i->message_last_sequence - i->message_first_sequence;
if ( total_length > 32 )
{
bro_analyzer()->ProtocolViolation(fmt("DTLS Message fragmented over more than 32 pieces. Cannot reassemble."));
return true;
}
if ( ( ~(i->message_sequence_seen) & ( ( 1<<(total_length+1) ) -1 ) ) == 0 )
{
//fprintf(stderr, "ALl fragments here. Total length %u\n", length);
bro_analyzer()->SendHandshake(${rec.msg_type}, length, i->buffer, i->buffer + length, ${pdu.is_orig});
}
}
return true;
%}
};
refine typeattr SSLRecord += &let {
proc: bool = $context.connection.proc_dtls(this, to_int()(sequence_number));
};
refine typeattr Handshake += &let {
proc: bool = $context.connection.proc_handshake(rec, this);
};

View file

@ -0,0 +1,60 @@
######################################################################
# initial datatype for binpac
######################################################################
type DTLSPDU(is_orig: bool) = record {
records: SSLRecord(is_orig)[] &transient;
};
type SSLRecord(is_orig: bool) = record {
content_type: uint8;
version: uint16;
# the epoch signalizes that a changecipherspec message has been received. Hence, everything with
# an epoch > 0 should be encrypted
epoch: uint16;
sequence_number: uint48;
length: uint16;
cont: case valid of {
true -> rec: RecordText(this)[] &length=length;
false -> swallow: bytestring &restofdata;
};
} &byteorder = bigendian, &let {
# Do not parse body if packet version invalid
valid: bool = $context.connection.dtls_version_ok(version);
};
type RecordText(rec: SSLRecord) = case rec.epoch of {
0 -> plaintext : PlaintextRecord(rec);
default -> ciphertext : CiphertextRecord(rec);
};
refine casetype PlaintextRecord += {
HANDSHAKE -> handshake : Handshake(rec);
};
type Handshake(rec: SSLRecord) = record {
msg_type: uint8;
length: uint24;
message_seq: uint16;
fragment_offset: uint24;
fragment_length: uint24;
data: bytestring &restofdata;
}
refine connection SSL_Conn += {
function dtls_version_ok(version: uint16): uint16
%{
switch ( version ) {
case DTLSv10:
case DTLSv12:
return true;
default:
bro_analyzer()->ProtocolViolation(fmt("Invalid version in DTLS connection. Packet reported version: %d", version));
return false;
}
%}
};

View file

@ -0,0 +1,36 @@
# binpac file for SSL analyzer
%include binpac.pac
%include bro.pac
%extern{
#include "events.bif.h"
namespace analyzer { namespace dtls { class DTLS_Analyzer; } }
typedef analyzer::dtls::DTLS_Analyzer* DTLSAnalyzer;
#include "DTLS.h"
%}
extern type DTLSAnalyzer;
analyzer DTLS withcontext {
connection: SSL_Conn;
flow: DTLS_Flow;
};
connection SSL_Conn(bro_analyzer: DTLSAnalyzer) {
upflow = DTLS_Flow(true);
downflow = DTLS_Flow(false);
};
%include ssl-dtls-protocol.pac
%include dtls-protocol.pac
flow DTLS_Flow(is_orig: bool) {
datagram = DTLSPDU(is_orig) withcontext(connection, this);
}
%include ssl-dtls-analyzer.pac
%include dtls-analyzer.pac
%include ssl-defs.pac

View file

@ -0,0 +1,30 @@
function proc_certificate(is_orig: bool, certificates : bytestring[]) : bool
%{
if ( certificates->size() == 0 )
return true;
ODesc common;
common.AddRaw("Analyzer::ANALYZER_SSL");
common.Add(bro_analyzer()->Conn()->StartTime());
common.AddRaw(is_orig ? "T" : "F", 1);
bro_analyzer()->Conn()->IDString(&common);
for ( unsigned int i = 0; i < certificates->size(); ++i )
{
const bytestring& cert = (*certificates)[i];
ODesc file_handle;
file_handle.Add(common.Description());
file_handle.Add(i);
string file_id = file_mgr->HashHandle(file_handle.Description());
file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()),
cert.length(), bro_analyzer()->GetAnalyzerTag(),
bro_analyzer()->Conn(), is_orig, file_id);
file_mgr->EndOfFile(file_id);
}
return true;
%}

View file

@ -0,0 +1,42 @@
function proc_client_hello(
version : uint16, ts : double,
client_random : bytestring,
session_id : uint8[],
cipher_suites16 : uint16[],
cipher_suites24 : uint24[]) : bool
%{
if ( ! version_ok(version) )
{
bro_analyzer()->ProtocolViolation(fmt("unsupported client SSL version 0x%04x", version));
bro_analyzer()->SetSkip(true);
}
else
bro_analyzer()->ProtocolConfirmation();
if ( ssl_client_hello )
{
vector<int>* cipher_suites = new vector<int>();
if ( cipher_suites16 )
std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*cipher_suites));
else
std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*cipher_suites), to_int());
VectorVal* cipher_vec = new VectorVal(internal_type("index_vec")->AsVectorType());
for ( unsigned int i = 0; i < cipher_suites->size(); ++i )
{
Val* ciph = new Val((*cipher_suites)[i], TYPE_COUNT);
cipher_vec->Assign(i, ciph);
}
BifEvent::generate_ssl_client_hello(bro_analyzer(), bro_analyzer()->Conn(),
version, ts, new StringVal(client_random.length(),
(const char*) client_random.data()),
to_string_val(session_id),
cipher_vec);
delete cipher_suites;
}
return true;
%}

View file

@ -0,0 +1,36 @@
function proc_server_hello(
version : uint16, ts : double,
server_random : bytestring,
session_id : uint8[],
cipher_suites16 : uint16[],
cipher_suites24 : uint24[],
comp_method : uint8) : bool
%{
if ( ! version_ok(version) )
{
bro_analyzer()->ProtocolViolation(fmt("unsupported server SSL version 0x%04x", version));
bro_analyzer()->SetSkip(true);
}
if ( ssl_server_hello )
{
vector<int>* ciphers = new vector<int>();
if ( cipher_suites16 )
std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*ciphers));
else
std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*ciphers), to_int());
BifEvent::generate_ssl_server_hello(bro_analyzer(),
bro_analyzer()->Conn(),
version, ts, new StringVal(server_random.length(),
(const char*) server_random.data()),
to_string_val(session_id),
ciphers->size()==0 ? 0 : ciphers->at(0), comp_method);
delete ciphers;
}
return true;
%}

View file

@ -1,352 +1,19 @@
# Analyzer for SSL (Bro-specific part). # Analyzer for SSL (Bro-specific part).
%extern{
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
#include "util.h"
#include "file_analysis/Manager.h"
%}
%header{
class extract_certs {
public:
bytestring const& operator() (X509Certificate* cert) const
{
return cert->certificate();
}
};
string orig_label(bool is_orig);
string handshake_type_label(int type);
%}
%code{
string orig_label(bool is_orig)
{
return string(is_orig ? "originator" :"responder");
}
string handshake_type_label(int type)
{
switch ( type ) {
case HELLO_REQUEST: return string("HELLO_REQUEST");
case CLIENT_HELLO: return string("CLIENT_HELLO");
case SERVER_HELLO: return string("SERVER_HELLO");
case SESSION_TICKET: return string("SESSION_TICKET");
case CERTIFICATE: return string("CERTIFICATE");
case SERVER_KEY_EXCHANGE: return string("SERVER_KEY_EXCHANGE");
case CERTIFICATE_REQUEST: return string("CERTIFICATE_REQUEST");
case SERVER_HELLO_DONE: return string("SERVER_HELLO_DONE");
case CERTIFICATE_VERIFY: return string("CERTIFICATE_VERIFY");
case CLIENT_KEY_EXCHANGE: return string("CLIENT_KEY_EXCHANGE");
case FINISHED: return string("FINISHED");
case CERTIFICATE_URL: return string("CERTIFICATE_URL");
case CERTIFICATE_STATUS: return string("CERTIFICATE_STATUS");
default: return string(fmt("UNKNOWN (%d)", type));
}
}
%}
function to_string_val(data : uint8[]) : StringVal
%{
char tmp[32];
memset(tmp, 0, sizeof(tmp));
// Just return an empty string if the string is longer than 32 bytes
if ( data && data->size() <= 32 )
{
for ( unsigned int i = data->size(); i > 0; --i )
tmp[i-1] = (*data)[i-1];
}
return new StringVal(32, tmp);
%}
function version_ok(vers : uint16) : bool
%{
switch ( vers ) {
case SSLv20:
case SSLv30:
case TLSv10:
case TLSv11:
case TLSv12:
return true;
default:
return false;
}
%}
refine connection SSL_Conn += { refine connection SSL_Conn += {
%member{ %include proc-client-hello.pac
int established_; %include proc-server-hello.pac
%} %include proc-certificate.pac
%init{ function proc_v2_certificate(is_orig: bool, cert : bytestring) : bool
established_ = false;
%}
%cleanup{
%}
function proc_alert(rec: SSLRecord, level : int, desc : int) : bool
%{
BifEvent::generate_ssl_alert(bro_analyzer(), bro_analyzer()->Conn(),
${rec.is_orig}, level, desc);
return true;
%}
function proc_client_hello(rec: SSLRecord,
version : uint16, ts : double,
client_random : bytestring,
session_id : uint8[],
cipher_suites16 : uint16[],
cipher_suites24 : uint24[]) : bool
%{
if ( ! version_ok(version) )
{
bro_analyzer()->ProtocolViolation(fmt("unsupported client SSL version 0x%04x", version));
bro_analyzer()->SetSkip(true);
}
else
bro_analyzer()->ProtocolConfirmation();
if ( ssl_client_hello )
{
vector<int>* cipher_suites = new vector<int>();
if ( cipher_suites16 )
std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*cipher_suites));
else
std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*cipher_suites), to_int());
VectorVal* cipher_vec = new VectorVal(internal_type("index_vec")->AsVectorType());
for ( unsigned int i = 0; i < cipher_suites->size(); ++i )
{
Val* ciph = new Val((*cipher_suites)[i], TYPE_COUNT);
cipher_vec->Assign(i, ciph);
}
BifEvent::generate_ssl_client_hello(bro_analyzer(), bro_analyzer()->Conn(),
version, ts, new StringVal(client_random.length(),
(const char*) client_random.data()),
to_string_val(session_id),
cipher_vec);
delete cipher_suites;
}
return true;
%}
function proc_server_hello(rec: SSLRecord,
version : uint16, ts : double,
server_random : bytestring,
session_id : uint8[],
cipher_suites16 : uint16[],
cipher_suites24 : uint24[],
comp_method : uint8) : bool
%{
if ( ! version_ok(version) )
{
bro_analyzer()->ProtocolViolation(fmt("unsupported server SSL version 0x%04x", version));
bro_analyzer()->SetSkip(true);
}
if ( ssl_server_hello )
{
vector<int>* ciphers = new vector<int>();
if ( cipher_suites16 )
std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*ciphers));
else
std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*ciphers), to_int());
BifEvent::generate_ssl_server_hello(bro_analyzer(),
bro_analyzer()->Conn(),
version, ts, new StringVal(server_random.length(),
(const char*) server_random.data()),
to_string_val(session_id),
ciphers->size()==0 ? 0 : ciphers->at(0), comp_method);
delete ciphers;
}
return true;
%}
function proc_session_ticket_handshake(rec: SessionTicketHandshake, is_orig: bool): bool
%{
if ( ssl_session_ticket_handshake )
{
BifEvent::generate_ssl_session_ticket_handshake(bro_analyzer(),
bro_analyzer()->Conn(),
${rec.ticket_lifetime_hint},
new StringVal(${rec.data}.length(), (const char*) ${rec.data}.data()));
}
return true;
%}
function proc_ssl_extension(rec: SSLRecord, type: int, sourcedata: const_bytestring) : bool
%{
// We cheat a little bit here. We want to throw this event
// for every extension we encounter, even those that are
// handled by more specialized events later. To access the
// parsed data, we use sourcedata, which contains the whole
// data blob of the extension, including headers. We skip
// over those (4 bytes).
size_t length = sourcedata.length();
if ( length < 4 )
{
// This should be impossible due to the binpac parser
// and protocol description
bro_analyzer()->ProtocolViolation(fmt("Impossible extension length: %zu", length));
bro_analyzer()->SetSkip(true);
return true;
}
length -= 4;
const unsigned char* data = sourcedata.begin() + 4;
if ( ssl_extension )
BifEvent::generate_ssl_extension(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig}, type,
new StringVal(length, reinterpret_cast<const char*>(data)));
return true;
%}
function proc_ec_point_formats(rec: SSLRecord, point_format_list: uint8[]) : bool
%{
VectorVal* points = new VectorVal(internal_type("index_vec")->AsVectorType());
if ( point_format_list )
{
for ( unsigned int i = 0; i < point_format_list->size(); ++i )
points->Assign(i, new Val((*point_format_list)[i], TYPE_COUNT));
}
BifEvent::generate_ssl_extension_ec_point_formats(bro_analyzer(), bro_analyzer()->Conn(),
${rec.is_orig}, points);
return true;
%}
function proc_elliptic_curves(rec: SSLRecord, list: uint16[]) : bool
%{
VectorVal* curves = new VectorVal(internal_type("index_vec")->AsVectorType());
if ( list )
{
for ( unsigned int i = 0; i < list->size(); ++i )
curves->Assign(i, new Val((*list)[i], TYPE_COUNT));
}
BifEvent::generate_ssl_extension_elliptic_curves(bro_analyzer(), bro_analyzer()->Conn(),
${rec.is_orig}, curves);
return true;
%}
function proc_apnl(rec: SSLRecord, protocols: ProtocolName[]) : bool
%{
VectorVal* plist = new VectorVal(internal_type("string_vec")->AsVectorType());
if ( protocols )
{
for ( unsigned int i = 0; i < protocols->size(); ++i )
plist->Assign(i, new StringVal((*protocols)[i]->name().length(), (const char*) (*protocols)[i]->name().data()));
}
BifEvent::generate_ssl_extension_application_layer_protocol_negotiation(bro_analyzer(), bro_analyzer()->Conn(),
${rec.is_orig}, plist);
return true;
%}
function proc_server_name(rec: SSLRecord, list: ServerName[]) : bool
%{
VectorVal* servers = new VectorVal(internal_type("string_vec")->AsVectorType());
if ( list )
{
for ( unsigned int i = 0, j = 0; i < list->size(); ++i )
{
ServerName* servername = (*list)[i];
if ( servername->name_type() != 0 )
{
bro_analyzer()->Weird(fmt("Encountered unknown type in server name ssl extension: %d", servername->name_type()));
continue;
}
if ( servername->host_name() )
servers->Assign(j++, new StringVal(servername->host_name()->host_name().length(), (const char*) servername->host_name()->host_name().data()));
else
bro_analyzer()->Weird("Empty server_name extension in ssl connection");
}
}
BifEvent::generate_ssl_extension_server_name(bro_analyzer(), bro_analyzer()->Conn(),
${rec.is_orig}, servers);
return true;
%}
function proc_certificate(rec: SSLRecord, certificates : bytestring[]) : bool
%{
if ( certificates->size() == 0 )
return true;
ODesc common;
common.AddRaw("Analyzer::ANALYZER_SSL");
common.Add(bro_analyzer()->Conn()->StartTime());
common.AddRaw(${rec.is_orig} ? "T" : "F", 1);
bro_analyzer()->Conn()->IDString(&common);
for ( unsigned int i = 0; i < certificates->size(); ++i )
{
const bytestring& cert = (*certificates)[i];
ODesc file_handle;
file_handle.Add(common.Description());
file_handle.Add(i);
string file_id = file_mgr->HashHandle(file_handle.Description());
file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()),
cert.length(), bro_analyzer()->GetAnalyzerTag(),
bro_analyzer()->Conn(), ${rec.is_orig}, file_id);
file_mgr->EndOfFile(file_id);
}
return true;
%}
function proc_v2_certificate(rec: SSLRecord, cert : bytestring) : bool
%{ %{
vector<bytestring>* cert_list = new vector<bytestring>(1,cert); vector<bytestring>* cert_list = new vector<bytestring>(1,cert);
bool ret = proc_certificate(rec, cert_list); bool ret = proc_certificate(is_orig, cert_list);
delete cert_list; delete cert_list;
return ret; return ret;
%} %}
function proc_v3_certificate(rec: SSLRecord, cl : X509Certificate[]) : bool
%{
vector<X509Certificate*>* certs = cl;
vector<bytestring>* cert_list = new vector<bytestring>();
std::transform(certs->begin(), certs->end(),
std::back_inserter(*cert_list), extract_certs());
bool ret = proc_certificate(rec, cert_list);
delete cert_list;
return ret;
%}
function proc_v2_client_master_key(rec: SSLRecord, cipher_kind: int) : bool function proc_v2_client_master_key(rec: SSLRecord, cipher_kind: int) : bool
%{ %{
@ -356,209 +23,38 @@ refine connection SSL_Conn += {
return true; return true;
%} %}
function proc_unknown_handshake(hs: Handshake, is_orig: bool) : bool function proc_handshake(rec: SSLRecord, data: bytestring, is_orig: bool) : bool
%{ %{
bro_analyzer()->ProtocolViolation(fmt("unknown handshake message (%d) from %s", bro_analyzer()->SendHandshake(data.begin(), data.end(), is_orig);
${hs.msg_type}, orig_label(is_orig).c_str()));
return true; return true;
%} %}
function proc_unknown_record(rec: SSLRecord) : bool
%{
bro_analyzer()->ProtocolViolation(fmt("unknown SSL record type (%d) from %s",
${rec.content_type},
orig_label(${rec.is_orig}).c_str()));
return true;
%}
function proc_ciphertext_record(rec : SSLRecord) : bool
%{
if ( client_state_ == STATE_ENCRYPTED &&
server_state_ == STATE_ENCRYPTED &&
established_ == false )
{
established_ = true;
BifEvent::generate_ssl_established(bro_analyzer(),
bro_analyzer()->Conn());
}
BifEvent::generate_ssl_encrypted_data(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig}, ${rec.content_type}, ${rec.length});
return true;
%}
function proc_heartbeat(rec : SSLRecord, type: uint8, payload_length: uint16, data: bytestring) : bool
%{
BifEvent::generate_ssl_heartbeat(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig}, ${rec.length}, type, payload_length,
new StringVal(data.length(), (const char*) data.data()));
return true;
%}
function proc_check_v2_server_hello_version(version: uint16) : bool
%{
if ( version != SSLv20 )
{
bro_analyzer()->ProtocolViolation(fmt("Invalid version in SSL server hello. Version: %d", version));
bro_analyzer()->SetSkip(true);
return false;
}
return true;
%}
function proc_certificate_status(rec : SSLRecord, status_type: uint8, response: bytestring) : bool
%{
if ( status_type == 1 ) // ocsp
{
BifEvent::generate_ssl_stapled_ocsp(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig},
new StringVal(response.length(),
(const char*) response.data()));
}
return true;
%}
function proc_ec_server_key_exchange(rec: SSLRecord, curve_type: uint8, curve: uint16) : bool
%{
if ( curve_type == NAMED_CURVE )
BifEvent::generate_ssl_server_curve(bro_analyzer(),
bro_analyzer()->Conn(), curve);
return true;
%}
function proc_dh_server_key_exchange(rec: SSLRecord, p: bytestring, g: bytestring, Ys: bytestring) : bool
%{
BifEvent::generate_ssl_dh_server_params(bro_analyzer(),
bro_analyzer()->Conn(),
new StringVal(p.length(), (const char*) p.data()),
new StringVal(g.length(), (const char*) g.data()),
new StringVal(Ys.length(), (const char*) Ys.data())
);
return true;
%}
function proc_ccs(rec: SSLRecord) : bool
%{
BifEvent::generate_ssl_change_cipher_spec(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig});
return true;
%}
function proc_handshake(rec: SSLRecord, msg_type: uint8, length: uint24) : bool
%{
BifEvent::generate_ssl_handshake_message(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig}, msg_type, to_int()(length));
return true;
%}
}; };
refine typeattr Alert += &let {
proc : bool = $context.connection.proc_alert(rec, level, description);
};
refine typeattr V2Error += &let { refine typeattr V2Error += &let {
proc : bool = $context.connection.proc_alert(rec, -1, error_code); proc : bool = $context.connection.proc_alert(rec, -1, error_code);
}; };
refine typeattr Heartbeat += &let {
proc : bool = $context.connection.proc_heartbeat(rec, type, payload_length, data);
};
refine typeattr ClientHello += &let {
proc : bool = $context.connection.proc_client_hello(rec, client_version,
gmt_unix_time, random_bytes,
session_id, csuits, 0);
};
refine typeattr V2ClientHello += &let { refine typeattr V2ClientHello += &let {
proc : bool = $context.connection.proc_client_hello(rec, client_version, 0, proc : bool = $context.connection.proc_client_hello(client_version, 0,
challenge, session_id, 0, ciphers); challenge, session_id, 0, ciphers);
}; };
refine typeattr ServerHello += &let {
proc : bool = $context.connection.proc_server_hello(rec, server_version,
gmt_unix_time, random_bytes, session_id, cipher_suite, 0,
compression_method);
};
refine typeattr V2ServerHello += &let { refine typeattr V2ServerHello += &let {
check_v2 : bool = $context.connection.proc_check_v2_server_hello_version(server_version); check_v2 : bool = $context.connection.proc_check_v2_server_hello_version(server_version);
proc : bool = $context.connection.proc_server_hello(rec, server_version, 0, proc : bool = $context.connection.proc_server_hello(server_version, 0,
conn_id_data, 0, 0, ciphers, 0) &requires(check_v2) &if(check_v2 == true); conn_id_data, 0, 0, ciphers, 0) &requires(check_v2) &if(check_v2 == true);
cert : bool = $context.connection.proc_v2_certificate(rec, cert_data) cert : bool = $context.connection.proc_v2_certificate(rec.is_orig, cert_data)
&requires(proc) &requires(check_v2) &if(check_v2 == true); &requires(proc) &requires(check_v2) &if(check_v2 == true);
}; };
refine typeattr Certificate += &let {
proc : bool = $context.connection.proc_v3_certificate(rec, certificates);
};
refine typeattr V2ClientMasterKey += &let { refine typeattr V2ClientMasterKey += &let {
proc : bool = $context.connection.proc_v2_client_master_key(rec, cipher_kind); proc : bool = $context.connection.proc_v2_client_master_key(rec, cipher_kind);
}; };
refine typeattr UnknownHandshake += &let {
proc : bool = $context.connection.proc_unknown_handshake(hs, is_orig);
};
refine typeattr SessionTicketHandshake += &let {
proc : bool = $context.connection.proc_session_ticket_handshake(this, rec.is_orig);
}
refine typeattr UnknownRecord += &let {
proc : bool = $context.connection.proc_unknown_record(rec);
};
refine typeattr CiphertextRecord += &let {
proc : bool = $context.connection.proc_ciphertext_record(rec);
}
refine typeattr SSLExtension += &let {
proc : bool = $context.connection.proc_ssl_extension(rec, type, sourcedata);
};
refine typeattr EcPointFormats += &let {
proc : bool = $context.connection.proc_ec_point_formats(rec, point_format_list);
};
refine typeattr EllipticCurves += &let {
proc : bool = $context.connection.proc_elliptic_curves(rec, elliptic_curve_list);
};
refine typeattr ApplicationLayerProtocolNegotiationExtension += &let {
proc : bool = $context.connection.proc_apnl(rec, protocol_name_list);
};
refine typeattr ServerNameExt += &let {
proc : bool = $context.connection.proc_server_name(rec, server_names);
};
refine typeattr CertificateStatus += &let {
proc : bool = $context.connection.proc_certificate_status(rec, status_type, response);
};
refine typeattr EcServerKeyExchange += &let {
proc : bool = $context.connection.proc_ec_server_key_exchange(rec, curve_type, curve);
};
refine typeattr DhServerKeyExchange += &let {
proc : bool = $context.connection.proc_dh_server_key_exchange(rec, dh_p, dh_g, dh_Ys);
};
refine typeattr ChangeCipherSpec += &let {
proc : bool = $context.connection.proc_ccs(rec);
};
refine typeattr Handshake += &let { refine typeattr Handshake += &let {
proc : bool = $context.connection.proc_handshake(rec, msg_type, length); proc : bool = $context.connection.proc_handshake(rec, data, rec.is_orig);
}; };

View file

@ -1,5 +1,86 @@
# Some common definitions for the SSL and SSL record-layer analyzers. # Some common definitions for the SSL and SSL record-layer analyzers.
type uint24 = record {
byte1 : uint8;
byte2 : uint8;
byte3 : uint8;
};
type uint48 = record {
byte1 : uint8;
byte2 : uint8;
byte3 : uint8;
byte4 : uint8;
byte5 : uint8;
byte6 : uint8;
};
%header{
string orig_label(bool is_orig);
%}
%code{
string orig_label(bool is_orig)
{
return string(is_orig ? "originator" :"responder");
}
%}
%header{
class to_int {
public:
int operator()(uint24 * num) const
{
return (num->byte1() << 16) | (num->byte2() << 8) | num->byte3();
}
uint64 operator()(uint48 * num) const
{
return ((uint64)num->byte1() << 40) | ((uint64)num->byte2() << 32) | ((uint64)num->byte3() << 24) |
((uint64)num->byte4() << 16) | ((uint64)num->byte5() << 8) | (uint64)num->byte6();
}
};
string state_label(int state_nr);
%}
extern type to_int;
function to_string_val(data : uint8[]) : StringVal
%{
char tmp[32];
memset(tmp, 0, sizeof(tmp));
// Just return an empty string if the string is longer than 32 bytes
if ( data && data->size() <= 32 )
{
for ( unsigned int i = data->size(); i > 0; --i )
tmp[i-1] = (*data)[i-1];
}
return new StringVal(32, tmp);
%}
function version_ok(vers : uint16) : bool
%{
switch ( vers ) {
case SSLv20:
case SSLv30:
case TLSv10:
case TLSv11:
case TLSv12:
case DTLSv10:
case DTLSv12:
return true;
default:
return false;
}
%}
%extern{ %extern{
#include <string> #include <string>
using std::string; using std::string;
@ -7,6 +88,9 @@ using std::string;
#include "events.bif.h" #include "events.bif.h"
%} %}
# a maximum of 100k for one record seems safe
let MAX_DTLS_HANDSHAKE_RECORD: uint32 = 100000;
enum ContentType { enum ContentType {
CHANGE_CIPHER_SPEC = 20, CHANGE_CIPHER_SPEC = 20,
ALERT = 21, ALERT = 21,
@ -27,7 +111,11 @@ enum SSLVersions {
SSLv30 = 0x0300, SSLv30 = 0x0300,
TLSv10 = 0x0301, TLSv10 = 0x0301,
TLSv11 = 0x0302, TLSv11 = 0x0302,
TLSv12 = 0x0303 TLSv12 = 0x0303,
DTLSv10 = 0xFEFF,
# DTLSv11 does not exist.
DTLSv12 = 0xFEFD
}; };
enum SSLExtensions { enum SSLExtensions {

View file

@ -0,0 +1,106 @@
%extern{
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
#include "util.h"
#include "file_analysis/Manager.h"
%}
refine connection SSL_Conn += {
%member{
int established_;
%}
%init{
established_ = false;
%}
%cleanup{
%}
function proc_alert(rec: SSLRecord, level : int, desc : int) : bool
%{
BifEvent::generate_ssl_alert(bro_analyzer(), bro_analyzer()->Conn(),
${rec.is_orig}, level, desc);
return true;
%}
function proc_unknown_record(rec: SSLRecord) : bool
%{
bro_analyzer()->ProtocolViolation(fmt("unknown SSL record type (%d) from %s",
${rec.content_type},
orig_label(${rec.is_orig}).c_str()));
return true;
%}
function proc_ciphertext_record(rec : SSLRecord) : bool
%{
if ( client_state_ == STATE_ENCRYPTED &&
server_state_ == STATE_ENCRYPTED &&
established_ == false )
{
established_ = true;
BifEvent::generate_ssl_established(bro_analyzer(),
bro_analyzer()->Conn());
}
BifEvent::generate_ssl_encrypted_data(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig}, ${rec.content_type}, ${rec.length});
return true;
%}
function proc_heartbeat(rec : SSLRecord, type: uint8, payload_length: uint16, data: bytestring) : bool
%{
BifEvent::generate_ssl_heartbeat(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig}, ${rec.length}, type, payload_length,
new StringVal(data.length(), (const char*) data.data()));
return true;
%}
function proc_check_v2_server_hello_version(version: uint16) : bool
%{
if ( version != SSLv20 )
{
bro_analyzer()->ProtocolViolation(fmt("Invalid version in SSL server hello. Version: %d", version));
bro_analyzer()->SetSkip(true);
return false;
}
return true;
%}
function proc_ccs(rec: SSLRecord) : bool
%{
BifEvent::generate_ssl_change_cipher_spec(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig});
return true;
%}
};
refine typeattr Alert += &let {
proc : bool = $context.connection.proc_alert(rec, level, description);
};
refine typeattr Heartbeat += &let {
proc : bool = $context.connection.proc_heartbeat(rec, type, payload_length, data);
};
refine typeattr UnknownRecord += &let {
proc : bool = $context.connection.proc_unknown_record(rec);
};
refine typeattr CiphertextRecord += &let {
proc : bool = $context.connection.proc_ciphertext_record(rec);
}
refine typeattr ChangeCipherSpec += &let {
proc : bool = $context.connection.proc_ccs(rec);
};

View file

@ -0,0 +1,134 @@
######################################################################
# General definitions
######################################################################
type PlaintextRecord(rec: SSLRecord) = case rec.content_type of {
CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec);
ALERT -> alert : Alert(rec);
HEARTBEAT -> heartbeat: Heartbeat(rec);
APPLICATION_DATA -> app_data : ApplicationData(rec);
default -> unknown_record : UnknownRecord(rec);
};
######################################################################
# Encryption Tracking
######################################################################
enum AnalyzerState {
STATE_CLEAR,
STATE_ENCRYPTED
};
%code{
string state_label(int state_nr)
{
switch ( state_nr ) {
case STATE_CLEAR:
return string("CLEAR");
case STATE_ENCRYPTED:
return string("ENCRYPTED");
default:
return string(fmt("UNKNOWN (%d)", state_nr));
}
}
%}
######################################################################
# Change Cipher Spec Protocol (7.1.)
######################################################################
type ChangeCipherSpec(rec: SSLRecord) = record {
type : uint8;
} &length = 1, &let {
state_changed : bool =
$context.connection.startEncryption(rec.is_orig);
};
######################################################################
# Alert Protocol (7.2.)
######################################################################
type Alert(rec: SSLRecord) = record {
level : uint8;
description: uint8;
};
######################################################################
# V3 Application Data
######################################################################
# Application data should always be encrypted, so we should not
# reach this point.
type ApplicationData(rec: SSLRecord) = record {
data : bytestring &restofdata &transient;
};
######################################################################
# V3 Heartbeat
######################################################################
type Heartbeat(rec: SSLRecord) = record {
type : uint8;
payload_length : uint16;
data : bytestring &restofdata;
};
######################################################################
# Fragmentation (6.2.1.)
######################################################################
type UnknownRecord(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient;
};
type CiphertextRecord(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient;
};
######################################################################
# binpac analyzer for SSL including
######################################################################
refine connection SSL_Conn += {
%member{
int client_state_;
int server_state_;
int record_layer_version_;
%}
%init{
server_state_ = STATE_CLEAR;
client_state_ = STATE_CLEAR;
record_layer_version_ = UNKNOWN_VERSION;
%}
function client_state() : int %{ return client_state_; %}
function server_state() : int %{ return client_state_; %}
function state(is_orig: bool) : int
%{
if ( is_orig )
return client_state_;
else
return server_state_;
%}
function startEncryption(is_orig: bool) : bool
%{
if ( is_orig )
client_state_ = STATE_ENCRYPTED;
else
server_state_ = STATE_ENCRYPTED;
return true;
%}
};

View file

@ -2,30 +2,6 @@
# To be used in conjunction with an SSL record-layer analyzer. # To be used in conjunction with an SSL record-layer analyzer.
# Separation is necessary due to possible fragmentation of SSL records. # Separation is necessary due to possible fragmentation of SSL records.
######################################################################
# General definitions
######################################################################
type uint24 = record {
byte1 : uint8;
byte2 : uint8;
byte3 : uint8;
};
%header{
class to_int {
public:
int operator()(uint24 * num) const
{
return (num->byte1() << 16) | (num->byte2() << 8) | num->byte3();
}
};
string state_label(int state_nr);
%}
extern type to_int;
type SSLRecord(is_orig: bool) = record { type SSLRecord(is_orig: bool) = record {
head0 : uint8; head0 : uint8;
head1 : uint8; head1 : uint8;
@ -58,160 +34,18 @@ type RecordText(rec: SSLRecord) = case $context.connection.state(rec.is_orig) of
-> plaintext : PlaintextRecord(rec); -> plaintext : PlaintextRecord(rec);
}; };
type PlaintextRecord(rec: SSLRecord) = case rec.content_type of { refine casetype PlaintextRecord += {
CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec);
ALERT -> alert : Alert(rec);
HANDSHAKE -> handshake : Handshake(rec); HANDSHAKE -> handshake : Handshake(rec);
HEARTBEAT -> heartbeat: Heartbeat(rec);
APPLICATION_DATA -> app_data : ApplicationData(rec);
V2_ERROR -> v2_error : V2Error(rec); V2_ERROR -> v2_error : V2Error(rec);
V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec); V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec);
V2_CLIENT_MASTER_KEY -> v2_client_master_key : V2ClientMasterKey(rec); V2_CLIENT_MASTER_KEY -> v2_client_master_key : V2ClientMasterKey(rec);
V2_SERVER_HELLO -> v2_server_hello : V2ServerHello(rec); V2_SERVER_HELLO -> v2_server_hello : V2ServerHello(rec);
default -> unknown_record : UnknownRecord(rec);
}; };
###################################################################### # Handshakes are parsed by the handshake analyzer.
# TLS Extensions type Handshake(rec: SSLRecord) = record {
###################################################################### data: bytestring &restofdata;
type SSLExtension(rec: SSLRecord) = record {
type: uint16;
data_len: uint16;
# Pretty code ahead. Deal with the fact that perhaps extensions are
# not really present and we do not want to fail because of that.
ext: case type of {
EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION -> apnl: ApplicationLayerProtocolNegotiationExtension(rec)[] &until($element == 0 || $element != 0);
EXT_ELLIPTIC_CURVES -> elliptic_curves: EllipticCurves(rec)[] &until($element == 0 || $element != 0);
EXT_EC_POINT_FORMATS -> ec_point_formats: EcPointFormats(rec)[] &until($element == 0 || $element != 0);
# EXT_STATUS_REQUEST -> status_request: StatusRequest(rec)[] &until($element == 0 || $element != 0);
EXT_SERVER_NAME -> server_name: ServerNameExt(rec)[] &until($element == 0 || $element != 0);
default -> data: bytestring &restofdata;
}; };
} &length=data_len+4 &exportsourcedata;
type ServerNameHostName() = record {
length: uint16;
host_name: bytestring &length=length;
};
type ServerName() = record {
name_type: uint8; # has to be 0 for host-name
name: case name_type of {
0 -> host_name: ServerNameHostName;
default -> data : bytestring &restofdata &transient; # unknown name
};
};
type ServerNameExt(rec: SSLRecord) = record {
length: uint16;
server_names: ServerName[] &until($input.length() == 0);
} &length=length+2;
# Do not parse for now. Structure is correct, but only contains asn.1 data that we would not use further.
#type OcspStatusRequest(rec: SSLRecord) = record {
# responder_id_list_length: uint16;
# responder_id_list: bytestring &length=responder_id_list_length;
# request_extensions_length: uint16;
# request_extensions: bytestring &length=request_extensions_length;
#};
#
#type StatusRequest(rec: SSLRecord) = record {
# status_type: uint8; # 1 -> ocsp
# req: case status_type of {
# 1 -> ocsp_status_request: OcspStatusRequest(rec);
# default -> data : bytestring &restofdata &transient; # unknown
# };
#};
type EcPointFormats(rec: SSLRecord) = record {
length: uint8;
point_format_list: uint8[length];
};
type EllipticCurves(rec: SSLRecord) = record {
length: uint16;
elliptic_curve_list: uint16[length/2];
};
type ProtocolName() = record {
length: uint8;
name: bytestring &length=length;
};
type ApplicationLayerProtocolNegotiationExtension(rec: SSLRecord) = record {
length: uint16;
protocol_name_list: ProtocolName[] &until($input.length() == 0);
} &length=length+2;
######################################################################
# Encryption Tracking
######################################################################
enum AnalyzerState {
STATE_CLEAR,
STATE_ENCRYPTED
};
%code{
string state_label(int state_nr)
{
switch ( state_nr ) {
case STATE_CLEAR:
return string("CLEAR");
case STATE_ENCRYPTED:
return string("ENCRYPTED");
default:
return string(fmt("UNKNOWN (%d)", state_nr));
}
}
%}
######################################################################
# SSLv3 Handshake Protocols (7.)
######################################################################
enum HandshakeType {
HELLO_REQUEST = 0,
CLIENT_HELLO = 1,
SERVER_HELLO = 2,
SESSION_TICKET = 4, # RFC 5077
CERTIFICATE = 11,
SERVER_KEY_EXCHANGE = 12,
CERTIFICATE_REQUEST = 13,
SERVER_HELLO_DONE = 14,
CERTIFICATE_VERIFY = 15,
CLIENT_KEY_EXCHANGE = 16,
FINISHED = 20,
CERTIFICATE_URL = 21, # RFC 3546
CERTIFICATE_STATUS = 22, # RFC 3546
};
######################################################################
# V3 Change Cipher Spec Protocol (7.1.)
######################################################################
type ChangeCipherSpec(rec: SSLRecord) = record {
type : uint8;
} &length = 1, &let {
state_changed : bool =
$context.connection.startEncryption(rec.is_orig);
};
######################################################################
# V3 Alert Protocol (7.2.)
######################################################################
type Alert(rec: SSLRecord) = record {
level : uint8;
description: uint8;
};
###################################################################### ######################################################################
# V2 Error Records (SSLv2 2.7.) # V2 Error Records (SSLv2 2.7.)
@ -224,53 +58,6 @@ type V2Error(rec: SSLRecord) = record {
}; };
######################################################################
# V3 Application Data
######################################################################
# Application data should always be encrypted, so we should not
# reach this point.
type ApplicationData(rec: SSLRecord) = record {
data : bytestring &restofdata &transient;
};
######################################################################
# V3 Heartbeat
######################################################################
type Heartbeat(rec: SSLRecord) = record {
type : uint8;
payload_length : uint16;
data : bytestring &restofdata;
};
######################################################################
# V3 Hello Request (7.4.1.1.)
######################################################################
# Hello Request is empty
type HelloRequest(rec: SSLRecord) = empty;
######################################################################
# V3 Client Hello (7.4.1.2.)
######################################################################
type ClientHello(rec: SSLRecord) = record {
client_version : uint16;
gmt_unix_time : uint32;
random_bytes : bytestring &length = 28;
session_len : uint8;
session_id : uint8[session_len];
csuit_len : uint16 &check(csuit_len > 1 && csuit_len % 2 == 0);
csuits : uint16[csuit_len/2];
cmeth_len : uint8 &check(cmeth_len > 0);
cmeths : uint8[cmeth_len];
# This weirdness is to deal with the possible existence or absence
# of the following fields.
ext_len: uint16[] &until($element == 0 || $element != 0);
extensions : SSLExtension(rec)[] &until($input.length() == 0);
};
###################################################################### ######################################################################
# V2 Client Hello (SSLv2 2.5.) # V2 Client Hello (SSLv2 2.5.)
@ -288,26 +75,6 @@ type V2ClientHello(rec: SSLRecord) = record {
}; };
######################################################################
# V3 Server Hello (7.4.1.3.)
######################################################################
type ServerHello(rec: SSLRecord) = record {
server_version : uint16;
gmt_unix_time : uint32;
random_bytes : bytestring &length = 28;
session_len : uint8;
session_id : uint8[session_len];
cipher_suite : uint16[1];
compression_method : uint8;
# This weirdness is to deal with the possible existence or absence
# of the following fields.
ext_len: uint16[] &until($element == 0 || $element != 0);
extensions : SSLExtension(rec)[] &until($input.length() == 0);
} &let {
cipher_set : bool =
$context.connection.set_cipher(cipher_suite[0]);
};
###################################################################### ######################################################################
# V2 Server Hello (SSLv2 2.6.) # V2 Server Hello (SSLv2 2.6.)
@ -329,298 +96,6 @@ type V2ServerHello(rec: SSLRecord) = record {
}; };
######################################################################
# V3 Server Certificate (7.4.2.)
######################################################################
type X509Certificate = record {
length : uint24;
certificate : bytestring &length = to_int()(length);
};
type Certificate(rec: SSLRecord) = record {
length : uint24;
certificates : X509Certificate[] &until($input.length() == 0);
} &length = to_int()(length)+3;
# OCSP Stapling
type CertificateStatus(rec: SSLRecord) = record {
status_type: uint8; # 1 = ocsp, everything else is undefined
length : uint24;
response: bytestring &restofdata;
};
######################################################################
# V3 Server Key Exchange Message (7.4.3.)
######################################################################
# Usually, the server key exchange does not contain any information
# that we are interested in.
#
# The exception is when we are using an ECDHE, DHE or DH-Anon suite.
# In this case, we can extract information about the chosen cipher from
# here.
type ServerKeyExchange(rec: SSLRecord) = case $context.connection.chosen_cipher() of {
TLS_ECDH_ECDSA_WITH_NULL_SHA,
TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_NULL_SHA,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDH_RSA_WITH_NULL_SHA,
TLS_ECDH_RSA_WITH_RC4_128_SHA,
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_NULL_SHA,
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDH_ANON_WITH_NULL_SHA,
TLS_ECDH_ANON_WITH_RC4_128_SHA,
TLS_ECDH_ANON_WITH_3DES_EDE_CBC_SHA,
TLS_ECDH_ANON_WITH_AES_128_CBC_SHA,
TLS_ECDH_ANON_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_PSK_WITH_RC4_128_SHA,
TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_PSK_WITH_NULL_SHA,
TLS_ECDHE_PSK_WITH_NULL_SHA256,
TLS_ECDHE_PSK_WITH_NULL_SHA384,
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
-> ec_server_key_exchange : EcServerKeyExchange(rec);
# DHE suites
TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
TLS_DHE_DSS_WITH_DES_CBC_SHA,
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
TLS_DHE_RSA_WITH_DES_CBC_SHA,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA,
TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA,
TLS_DHE_DSS_WITH_RC4_128_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD,
TLS_DHE_DSS_WITH_AES_128_CBC_RMD,
TLS_DHE_DSS_WITH_AES_256_CBC_RMD,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD,
TLS_DHE_RSA_WITH_AES_128_CBC_RMD,
TLS_DHE_RSA_WITH_AES_256_CBC_RMD,
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
TLS_DHE_PSK_WITH_RC4_128_SHA,
TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
TLS_DHE_DSS_WITH_SEED_CBC_SHA,
TLS_DHE_RSA_WITH_SEED_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
TLS_DHE_PSK_WITH_NULL_SHA256,
TLS_DHE_PSK_WITH_NULL_SHA384,
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256,
TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384,
TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256,
TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384,
TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256,
TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384,
TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS_DHE_RSA_WITH_AES_128_CCM,
TLS_DHE_RSA_WITH_AES_256_CCM,
TLS_DHE_RSA_WITH_AES_128_CCM_8,
TLS_DHE_RSA_WITH_AES_256_CCM_8,
TLS_DHE_PSK_WITH_AES_128_CCM,
TLS_DHE_PSK_WITH_AES_256_CCM,
TLS_PSK_DHE_WITH_AES_128_CCM_8,
TLS_PSK_DHE_WITH_AES_256_CCM_8,
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
# DH-anon suites
TLS_DH_ANON_EXPORT_WITH_RC4_40_MD5,
TLS_DH_ANON_WITH_RC4_128_MD5,
TLS_DH_ANON_EXPORT_WITH_DES40_CBC_SHA,
TLS_DH_ANON_WITH_DES_CBC_SHA,
TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA,
TLS_DH_ANON_WITH_AES_128_CBC_SHA,
TLS_DH_ANON_WITH_AES_256_CBC_SHA,
TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA,
TLS_DH_ANON_WITH_AES_128_CBC_SHA256,
TLS_DH_ANON_WITH_AES_256_CBC_SHA256,
TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA,
TLS_DH_ANON_WITH_SEED_CBC_SHA,
TLS_DH_ANON_WITH_AES_128_GCM_SHA256,
TLS_DH_ANON_WITH_AES_256_GCM_SHA384,
TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA256,
TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA256,
TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256,
TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384,
TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256,
TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384,
TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256,
TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384
# DH non-anon suites do not send a ServerKeyExchange
-> dh_server_key_exchange : DhServerKeyExchange(rec);
default
-> key : bytestring &restofdata &transient;
};
# For the moment, we really only are interested in the curve name. If it
# is not set (if the server sends explicit parameters), we do not bother.
# We also do not parse the actual signature data following the named curve.
type EcServerKeyExchange(rec: SSLRecord) = record {
curve_type: uint8;
curve: uint16; # only if curve_type = 3 (NAMED_CURVE)
data: bytestring &restofdata &transient;
};
# For both, dh_anon and dhe the ServerKeyExchange starts with a ServerDHParams
# structure. After that, they start to differ, but we do not care about that.
type DhServerKeyExchange(rec: SSLRecord) = record {
dh_p_length: uint16;
dh_p: bytestring &length=dh_p_length;
dh_g_length: uint16;
dh_g: bytestring &length=dh_g_length;
dh_Ys_length: uint16;
dh_Ys: bytestring &length=dh_Ys_length;
data: bytestring &restofdata &transient;
};
######################################################################
# V3 Certificate Request (7.4.4.)
######################################################################
# For now, ignore Certificate Request Details; just eat up message.
type CertificateRequest(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient;
};
######################################################################
# V3 Server Hello Done (7.4.5.)
######################################################################
# Server Hello Done is empty
type ServerHelloDone(rec: SSLRecord) = empty;
######################################################################
# V3 Client Certificate (7.4.6.)
######################################################################
# Client Certificate is identical to Server Certificate;
# no further definition here
######################################################################
# V3 Client Key Exchange Message (7.4.7.)
######################################################################
# For now ignore details of ClientKeyExchange (most of it is
# encrypted anyway); just eat up message.
type ClientKeyExchange(rec: SSLRecord) = record {
key : bytestring &restofdata &transient;
};
###################################################################### ######################################################################
# V2 Client Master Key (SSLv2 2.5.) # V2 Client Master Key (SSLv2 2.5.)
###################################################################### ######################################################################
@ -641,75 +116,6 @@ type V2ClientMasterKey(rec: SSLRecord) = record {
}; };
######################################################################
# V3 Certificate Verify (7.4.8.)
######################################################################
# For now, ignore Certificate Verify; just eat up the message.
type CertificateVerify(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient;
};
######################################################################
# V3 Finished (7.4.9.)
######################################################################
# The finished messages are always sent after encryption is in effect,
# so we will not be able to read those messages.
type Finished(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient;
};
type SessionTicketHandshake(rec: SSLRecord) = record {
ticket_lifetime_hint: uint32;
data: bytestring &restofdata;
};
######################################################################
# V3 Handshake Protocol (7.)
######################################################################
type UnknownHandshake(hs: Handshake, is_orig: bool) = record {
data : bytestring &restofdata &transient;
};
type Handshake(rec: SSLRecord) = record {
msg_type : uint8;
length : uint24;
body : case msg_type of {
HELLO_REQUEST -> hello_request : HelloRequest(rec);
CLIENT_HELLO -> client_hello : ClientHello(rec);
SERVER_HELLO -> server_hello : ServerHello(rec);
SESSION_TICKET -> session_ticket : SessionTicketHandshake(rec);
CERTIFICATE -> certificate : Certificate(rec);
SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec);
CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec);
SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec);
CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec);
CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec);
FINISHED -> finished : Finished(rec);
CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient;
CERTIFICATE_STATUS -> certificate_status : CertificateStatus(rec);
default -> unknown_handshake : UnknownHandshake(this, rec.is_orig);
} &length = to_int()(length);
};
######################################################################
# Fragmentation (6.2.1.)
######################################################################
type UnknownRecord(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient;
};
type CiphertextRecord(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient;
};
###################################################################### ######################################################################
# initial datatype for binpac # initial datatype for binpac
###################################################################### ######################################################################
@ -725,28 +131,6 @@ type SSLPDU(is_orig: bool) = record {
refine connection SSL_Conn += { refine connection SSL_Conn += {
%member{
int client_state_;
int server_state_;
int record_layer_version_;
uint32 chosen_cipher_;
%}
%init{
server_state_ = STATE_CLEAR;
client_state_ = STATE_CLEAR;
record_layer_version_ = UNKNOWN_VERSION;
chosen_cipher_ = NO_CHOSEN_CIPHER;
%}
function chosen_cipher() : int %{ return chosen_cipher_; %}
function set_cipher(cipher: uint32) : bool
%{
chosen_cipher_ = cipher;
return true;
%}
function determine_ssl_record_layer(head0 : uint8, head1 : uint8, function determine_ssl_record_layer(head0 : uint8, head1 : uint8,
head2 : uint8, head3: uint8, head4: uint8, is_orig: bool) : int head2 : uint8, head3: uint8, head4: uint8, is_orig: bool) : int
%{ %{
@ -824,24 +208,4 @@ refine connection SSL_Conn += {
return UNKNOWN_VERSION; return UNKNOWN_VERSION;
%} %}
function client_state() : int %{ return client_state_; %}
function server_state() : int %{ return client_state_; %}
function state(is_orig: bool) : int
%{
if ( is_orig )
return client_state_;
else
return server_state_;
%}
function startEncryption(is_orig: bool) : bool
%{
if ( is_orig )
client_state_ = STATE_ENCRYPTED;
else
server_state_ = STATE_ENCRYPTED;
return true;
%}
}; };

View file

@ -10,23 +10,32 @@
%extern{ %extern{
#include "events.bif.h" #include "events.bif.h"
namespace analyzer { namespace ssl { class SSL_Analyzer; } }
typedef analyzer::ssl::SSL_Analyzer* SSLAnalyzer;
#include "SSL.h"
%} %}
extern type SSLAnalyzer;
analyzer SSL withcontext { analyzer SSL withcontext {
connection: SSL_Conn; connection: SSL_Conn;
flow: SSL_Flow; flow: SSL_Flow;
}; };
connection SSL_Conn(bro_analyzer: BroAnalyzer) { connection SSL_Conn(bro_analyzer: SSLAnalyzer) {
upflow = SSL_Flow(true); upflow = SSL_Flow(true);
downflow = SSL_Flow(false); downflow = SSL_Flow(false);
}; };
%include ssl-dtls-protocol.pac
%include ssl-protocol.pac %include ssl-protocol.pac
flow SSL_Flow(is_orig: bool) { flow SSL_Flow(is_orig: bool) {
flowunit = SSLPDU(is_orig) withcontext(connection, this); flowunit = SSLPDU(is_orig) withcontext(connection, this);
} }
%include ssl-dtls-analyzer.pac
%include ssl-analyzer.pac %include ssl-analyzer.pac
%include ssl-defs.pac %include ssl-defs.pac

View file

@ -0,0 +1,273 @@
# Analyzer for SSL/TLS Handshake protocol (Bro-specific part).
%extern{
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
#include "util.h"
#include "file_analysis/Manager.h"
%}
%header{
class extract_certs {
public:
bytestring const& operator() (X509Certificate* cert) const
{
return cert->certificate();
}
};
string orig_label(bool is_orig);
string handshake_type_label(int type);
%}
refine connection Handshake_Conn += {
%include proc-client-hello.pac
%include proc-server-hello.pac
%include proc-certificate.pac
function proc_session_ticket_handshake(rec: SessionTicketHandshake, is_orig: bool): bool
%{
if ( ssl_session_ticket_handshake )
{
BifEvent::generate_ssl_session_ticket_handshake(bro_analyzer(),
bro_analyzer()->Conn(),
${rec.ticket_lifetime_hint},
new StringVal(${rec.data}.length(), (const char*) ${rec.data}.data()));
}
return true;
%}
function proc_ssl_extension(rec: HandshakeRecord, type: int, sourcedata: const_bytestring) : bool
%{
// We cheat a little bit here. We want to throw this event
// for every extension we encounter, even those that are
// handled by more specialized events later. To access the
// parsed data, we use sourcedata, which contains the whole
// data blob of the extension, including headers. We skip
// over those (4 bytes).
size_t length = sourcedata.length();
if ( length < 4 )
{
// This should be impossible due to the binpac parser
// and protocol description
bro_analyzer()->ProtocolViolation(fmt("Impossible extension length: %zu", length));
bro_analyzer()->SetSkip(true);
return true;
}
length -= 4;
const unsigned char* data = sourcedata.begin() + 4;
if ( ssl_extension )
BifEvent::generate_ssl_extension(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig}, type,
new StringVal(length, reinterpret_cast<const char*>(data)));
return true;
%}
function proc_ec_point_formats(rec: HandshakeRecord, point_format_list: uint8[]) : bool
%{
VectorVal* points = new VectorVal(internal_type("index_vec")->AsVectorType());
if ( point_format_list )
{
for ( unsigned int i = 0; i < point_format_list->size(); ++i )
points->Assign(i, new Val((*point_format_list)[i], TYPE_COUNT));
}
BifEvent::generate_ssl_extension_ec_point_formats(bro_analyzer(), bro_analyzer()->Conn(),
${rec.is_orig}, points);
return true;
%}
function proc_elliptic_curves(rec: HandshakeRecord, list: uint16[]) : bool
%{
VectorVal* curves = new VectorVal(internal_type("index_vec")->AsVectorType());
if ( list )
{
for ( unsigned int i = 0; i < list->size(); ++i )
curves->Assign(i, new Val((*list)[i], TYPE_COUNT));
}
BifEvent::generate_ssl_extension_elliptic_curves(bro_analyzer(), bro_analyzer()->Conn(),
${rec.is_orig}, curves);
return true;
%}
function proc_apnl(rec: HandshakeRecord, protocols: ProtocolName[]) : bool
%{
VectorVal* plist = new VectorVal(internal_type("string_vec")->AsVectorType());
if ( protocols )
{
for ( unsigned int i = 0; i < protocols->size(); ++i )
plist->Assign(i, new StringVal((*protocols)[i]->name().length(), (const char*) (*protocols)[i]->name().data()));
}
BifEvent::generate_ssl_extension_application_layer_protocol_negotiation(bro_analyzer(), bro_analyzer()->Conn(),
${rec.is_orig}, plist);
return true;
%}
function proc_server_name(rec: HandshakeRecord, list: ServerName[]) : bool
%{
VectorVal* servers = new VectorVal(internal_type("string_vec")->AsVectorType());
if ( list )
{
for ( unsigned int i = 0, j = 0; i < list->size(); ++i )
{
ServerName* servername = (*list)[i];
if ( servername->name_type() != 0 )
{
bro_analyzer()->Weird(fmt("Encountered unknown type in server name ssl extension: %d", servername->name_type()));
continue;
}
if ( servername->host_name() )
servers->Assign(j++, new StringVal(servername->host_name()->host_name().length(), (const char*) servername->host_name()->host_name().data()));
else
bro_analyzer()->Weird("Empty server_name extension in ssl connection");
}
}
BifEvent::generate_ssl_extension_server_name(bro_analyzer(), bro_analyzer()->Conn(),
${rec.is_orig}, servers);
return true;
%}
function proc_v3_certificate(is_orig: bool, cl : X509Certificate[]) : bool
%{
vector<X509Certificate*>* certs = cl;
vector<bytestring>* cert_list = new vector<bytestring>();
std::transform(certs->begin(), certs->end(),
std::back_inserter(*cert_list), extract_certs());
bool ret = proc_certificate(is_orig, cert_list);
delete cert_list;
return ret;
%}
function proc_unknown_handshake(hs: HandshakeRecord, is_orig: bool) : bool
%{
bro_analyzer()->ProtocolViolation(fmt("unknown handshake message (%d) from %s",
${hs.msg_type}, orig_label(is_orig).c_str()));
return true;
%}
function proc_certificate_status(rec : HandshakeRecord, status_type: uint8, response: bytestring) : bool
%{
if ( status_type == 1 ) // ocsp
{
BifEvent::generate_ssl_stapled_ocsp(bro_analyzer(),
bro_analyzer()->Conn(), ${rec.is_orig},
new StringVal(response.length(),
(const char*) response.data()));
}
return true;
%}
function proc_ec_server_key_exchange(rec: HandshakeRecord, curve_type: uint8, curve: uint16) : bool
%{
if ( curve_type == NAMED_CURVE )
BifEvent::generate_ssl_server_curve(bro_analyzer(),
bro_analyzer()->Conn(), curve);
return true;
%}
function proc_dh_server_key_exchange(rec: HandshakeRecord, p: bytestring, g: bytestring, Ys: bytestring) : bool
%{
BifEvent::generate_ssl_dh_server_params(bro_analyzer(),
bro_analyzer()->Conn(),
new StringVal(p.length(), (const char*) p.data()),
new StringVal(g.length(), (const char*) g.data()),
new StringVal(Ys.length(), (const char*) Ys.data())
);
return true;
%}
function proc_handshake(is_orig: bool, msg_type: uint8, length: uint24) : bool
%{
BifEvent::generate_ssl_handshake_message(bro_analyzer(),
bro_analyzer()->Conn(), is_orig, msg_type, to_int()(length));
return true;
%}
};
refine typeattr ClientHello += &let {
proc : bool = $context.connection.proc_client_hello(client_version,
gmt_unix_time, random_bytes,
session_id, csuits, 0);
};
refine typeattr ServerHello += &let {
proc : bool = $context.connection.proc_server_hello(server_version,
gmt_unix_time, random_bytes, session_id, cipher_suite, 0,
compression_method);
};
refine typeattr Certificate += &let {
proc : bool = $context.connection.proc_v3_certificate(rec.is_orig, certificates);
};
refine typeattr UnknownHandshake += &let {
proc : bool = $context.connection.proc_unknown_handshake(hs, is_orig);
};
refine typeattr SessionTicketHandshake += &let {
proc : bool = $context.connection.proc_session_ticket_handshake(this, rec.is_orig);
}
refine typeattr SSLExtension += &let {
proc : bool = $context.connection.proc_ssl_extension(rec, type, sourcedata);
};
refine typeattr EcPointFormats += &let {
proc : bool = $context.connection.proc_ec_point_formats(rec, point_format_list);
};
refine typeattr EllipticCurves += &let {
proc : bool = $context.connection.proc_elliptic_curves(rec, elliptic_curve_list);
};
refine typeattr ApplicationLayerProtocolNegotiationExtension += &let {
proc : bool = $context.connection.proc_apnl(rec, protocol_name_list);
};
refine typeattr ServerNameExt += &let {
proc : bool = $context.connection.proc_server_name(rec, server_names);
};
refine typeattr CertificateStatus += &let {
proc : bool = $context.connection.proc_certificate_status(rec, status_type, response);
};
refine typeattr EcServerKeyExchange += &let {
proc : bool = $context.connection.proc_ec_server_key_exchange(rec, curve_type, curve);
};
refine typeattr DhServerKeyExchange += &let {
proc : bool = $context.connection.proc_dh_server_key_exchange(rec, dh_p, dh_g, dh_Ys);
};
refine typeattr Handshake += &let {
proc : bool = $context.connection.proc_handshake(rec.is_orig, rec.msg_type, rec.msg_length);
};

View file

@ -0,0 +1,538 @@
######################################################################
# Handshake Protocols (7.)
######################################################################
enum HandshakeType {
HELLO_REQUEST = 0,
CLIENT_HELLO = 1,
SERVER_HELLO = 2,
HELLO_VERIFY_REQUEST = 3, # DTLS
SESSION_TICKET = 4, # RFC 5077
CERTIFICATE = 11,
SERVER_KEY_EXCHANGE = 12,
CERTIFICATE_REQUEST = 13,
SERVER_HELLO_DONE = 14,
CERTIFICATE_VERIFY = 15,
CLIENT_KEY_EXCHANGE = 16,
FINISHED = 20,
CERTIFICATE_URL = 21, # RFC 3546
CERTIFICATE_STATUS = 22, # RFC 3546
};
######################################################################
# V3 Handshake Protocol (7.)
######################################################################
type HandshakeRecord(is_orig: bool) = record {
msg_type: uint8;
msg_length: uint24;
rec: Handshake(this);
} &length=(to_int()(msg_length) + 4);
type Handshake(rec: HandshakeRecord) = case rec.msg_type of {
HELLO_REQUEST -> hello_request : HelloRequest(rec);
CLIENT_HELLO -> client_hello : ClientHello(rec);
SERVER_HELLO -> server_hello : ServerHello(rec);
HELLO_VERIFY_REQUEST -> hello_verify_request : HelloVerifyRequest(rec);
SESSION_TICKET -> session_ticket : SessionTicketHandshake(rec);
CERTIFICATE -> certificate : Certificate(rec);
SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec);
CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec);
SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec);
CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec);
CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec);
FINISHED -> finished : Finished(rec);
CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient;
CERTIFICATE_STATUS -> certificate_status : CertificateStatus(rec);
default -> unknown_handshake : UnknownHandshake(rec, rec.is_orig);
}
type HandshakePDU(is_orig: bool) = record {
records: HandshakeRecord(is_orig)[] &transient;
} &byteorder = bigendian;
type UnknownHandshake(hs: HandshakeRecord, is_orig: bool) = record {
data : bytestring &restofdata &transient;
};
######################################################################
# V3 Hello Request (7.4.1.1.)
######################################################################
# Hello Request is empty
type HelloRequest(rec: HandshakeRecord) = empty;
######################################################################
# V3 Client Hello (7.4.1.2.)
######################################################################
type ClientHello(rec: HandshakeRecord) = record {
client_version : uint16;
gmt_unix_time : uint32;
random_bytes : bytestring &length = 28;
session_len : uint8;
session_id : uint8[session_len];
dtls_cookie: case client_version of {
DTLSv10 -> cookie: ClientHelloCookie(rec);
default -> nothing: bytestring &length=0;
};
csuit_len : uint16 &check(csuit_len > 1 && csuit_len % 2 == 0);
csuits : uint16[csuit_len/2];
cmeth_len : uint8 &check(cmeth_len > 0);
cmeths : uint8[cmeth_len];
# This weirdness is to deal with the possible existence or absence
# of the following fields.
ext_len: uint16[] &until($element == 0 || $element != 0);
extensions : SSLExtension(rec)[] &until($input.length() == 0);
};
type ClientHelloCookie(rec: HandshakeRecord) = record {
cookie_len : uint8;
cookie : bytestring &length = cookie_len;
};
######################################################################
# V3 Server Hello (7.4.1.3.)
######################################################################
type ServerHello(rec: HandshakeRecord) = record {
server_version : uint16;
gmt_unix_time : uint32;
random_bytes : bytestring &length = 28;
session_len : uint8;
session_id : uint8[session_len];
cipher_suite : uint16[1];
compression_method : uint8;
# This weirdness is to deal with the possible existence or absence
# of the following fields.
ext_len: uint16[] &until($element == 0 || $element != 0);
extensions : SSLExtension(rec)[] &until($input.length() == 0);
} &let {
cipher_set : bool =
$context.connection.set_cipher(cipher_suite[0]);
};
######################################################################
# DTLS Hello Verify Request
######################################################################
type HelloVerifyRequest(rec: HandshakeRecord) = record {
version: uint16;
cookie_length: uint8;
cookie: bytestring &length=cookie_length;
};
######################################################################
# V3 Server Certificate (7.4.2.)
######################################################################
type X509Certificate = record {
length : uint24;
certificate : bytestring &length = to_int()(length);
};
type Certificate(rec: HandshakeRecord) = record {
length : uint24;
certificates : X509Certificate[] &until($input.length() == 0);
} &length = to_int()(length)+3;
# OCSP Stapling
type CertificateStatus(rec: HandshakeRecord) = record {
status_type: uint8; # 1 = ocsp, everything else is undefined
length : uint24;
response: bytestring &restofdata;
};
######################################################################
# V3 Server Key Exchange Message (7.4.3.)
######################################################################
# Usually, the server key exchange does not contain any information
# that we are interested in.
#
# The exception is when we are using an ECDHE, DHE or DH-Anon suite.
# In this case, we can extract information about the chosen cipher from
# here.
type ServerKeyExchange(rec: HandshakeRecord) = case $context.connection.chosen_cipher() of {
TLS_ECDH_ECDSA_WITH_NULL_SHA,
TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_NULL_SHA,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDH_RSA_WITH_NULL_SHA,
TLS_ECDH_RSA_WITH_RC4_128_SHA,
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_NULL_SHA,
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDH_ANON_WITH_NULL_SHA,
TLS_ECDH_ANON_WITH_RC4_128_SHA,
TLS_ECDH_ANON_WITH_3DES_EDE_CBC_SHA,
TLS_ECDH_ANON_WITH_AES_128_CBC_SHA,
TLS_ECDH_ANON_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_PSK_WITH_RC4_128_SHA,
TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_PSK_WITH_NULL_SHA,
TLS_ECDHE_PSK_WITH_NULL_SHA256,
TLS_ECDHE_PSK_WITH_NULL_SHA384,
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
-> ec_server_key_exchange : EcServerKeyExchange(rec);
# DHE suites
TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
TLS_DHE_DSS_WITH_DES_CBC_SHA,
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
TLS_DHE_RSA_WITH_DES_CBC_SHA,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA,
TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA,
TLS_DHE_DSS_WITH_RC4_128_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD,
TLS_DHE_DSS_WITH_AES_128_CBC_RMD,
TLS_DHE_DSS_WITH_AES_256_CBC_RMD,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD,
TLS_DHE_RSA_WITH_AES_128_CBC_RMD,
TLS_DHE_RSA_WITH_AES_256_CBC_RMD,
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
TLS_DHE_PSK_WITH_RC4_128_SHA,
TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
TLS_DHE_DSS_WITH_SEED_CBC_SHA,
TLS_DHE_RSA_WITH_SEED_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
TLS_DHE_PSK_WITH_NULL_SHA256,
TLS_DHE_PSK_WITH_NULL_SHA384,
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256,
TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384,
TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256,
TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384,
TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256,
TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384,
TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
TLS_DHE_RSA_WITH_AES_128_CCM,
TLS_DHE_RSA_WITH_AES_256_CCM,
TLS_DHE_RSA_WITH_AES_128_CCM_8,
TLS_DHE_RSA_WITH_AES_256_CCM_8,
TLS_DHE_PSK_WITH_AES_128_CCM,
TLS_DHE_PSK_WITH_AES_256_CCM,
TLS_PSK_DHE_WITH_AES_128_CCM_8,
TLS_PSK_DHE_WITH_AES_256_CCM_8,
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
# DH-anon suites
TLS_DH_ANON_EXPORT_WITH_RC4_40_MD5,
TLS_DH_ANON_WITH_RC4_128_MD5,
TLS_DH_ANON_EXPORT_WITH_DES40_CBC_SHA,
TLS_DH_ANON_WITH_DES_CBC_SHA,
TLS_DH_ANON_WITH_3DES_EDE_CBC_SHA,
TLS_DH_ANON_WITH_AES_128_CBC_SHA,
TLS_DH_ANON_WITH_AES_256_CBC_SHA,
TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA,
TLS_DH_ANON_WITH_AES_128_CBC_SHA256,
TLS_DH_ANON_WITH_AES_256_CBC_SHA256,
TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA,
TLS_DH_ANON_WITH_SEED_CBC_SHA,
TLS_DH_ANON_WITH_AES_128_GCM_SHA256,
TLS_DH_ANON_WITH_AES_256_GCM_SHA384,
TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA256,
TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA256,
TLS_DH_ANON_WITH_ARIA_128_CBC_SHA256,
TLS_DH_ANON_WITH_ARIA_256_CBC_SHA384,
TLS_DH_ANON_WITH_ARIA_128_GCM_SHA256,
TLS_DH_ANON_WITH_ARIA_256_GCM_SHA384,
TLS_DH_ANON_WITH_CAMELLIA_128_GCM_SHA256,
TLS_DH_ANON_WITH_CAMELLIA_256_GCM_SHA384
# DH non-anon suites do not send a ServerKeyExchange
-> dh_server_key_exchange : DhServerKeyExchange(rec);
default
-> key : bytestring &restofdata &transient;
};
# For the moment, we really only are interested in the curve name. If it
# is not set (if the server sends explicit parameters), we do not bother.
# We also do not parse the actual signature data following the named curve.
type EcServerKeyExchange(rec: HandshakeRecord) = record {
curve_type: uint8;
curve: uint16; # only if curve_type = 3 (NAMED_CURVE)
data: bytestring &restofdata &transient;
};
# For both, dh_anon and dhe the ServerKeyExchange starts with a ServerDHParams
# structure. After that, they start to differ, but we do not care about that.
type DhServerKeyExchange(rec: HandshakeRecord) = record {
dh_p_length: uint16;
dh_p: bytestring &length=dh_p_length;
dh_g_length: uint16;
dh_g: bytestring &length=dh_g_length;
dh_Ys_length: uint16;
dh_Ys: bytestring &length=dh_Ys_length;
data: bytestring &restofdata &transient;
};
######################################################################
# V3 Certificate Request (7.4.4.)
######################################################################
# For now, ignore Certificate Request Details; just eat up message.
type CertificateRequest(rec: HandshakeRecord) = record {
cont : bytestring &restofdata &transient;
};
######################################################################
# V3 Server Hello Done (7.4.5.)
######################################################################
# Server Hello Done is empty
type ServerHelloDone(rec: HandshakeRecord) = empty;
######################################################################
# V3 Client Certificate (7.4.6.)
######################################################################
# Client Certificate is identical to Server Certificate;
# no further definition here
######################################################################
# V3 Client Key Exchange Message (7.4.7.)
######################################################################
# For now ignore details of ClientKeyExchange (most of it is
# encrypted anyway); just eat up message.
type ClientKeyExchange(rec: HandshakeRecord) = record {
key : bytestring &restofdata &transient;
};
######################################################################
# V3 Certificate Verify (7.4.8.)
######################################################################
# For now, ignore Certificate Verify; just eat up the message.
type CertificateVerify(rec: HandshakeRecord) = record {
cont : bytestring &restofdata &transient;
};
######################################################################
# V3 Finished (7.4.9.)
######################################################################
# The finished messages are always sent after encryption is in effect,
# so we will not be able to read those messages.
type Finished(rec: HandshakeRecord) = record {
cont : bytestring &restofdata &transient;
};
type SessionTicketHandshake(rec: HandshakeRecord) = record {
ticket_lifetime_hint: uint32;
data: bytestring &restofdata;
};
######################################################################
# TLS Extensions
######################################################################
type SSLExtension(rec: HandshakeRecord) = record {
type: uint16;
data_len: uint16;
# Pretty code ahead. Deal with the fact that perhaps extensions are
# not really present and we do not want to fail because of that.
ext: case type of {
EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION -> apnl: ApplicationLayerProtocolNegotiationExtension(rec)[] &until($element == 0 || $element != 0);
EXT_ELLIPTIC_CURVES -> elliptic_curves: EllipticCurves(rec)[] &until($element == 0 || $element != 0);
EXT_EC_POINT_FORMATS -> ec_point_formats: EcPointFormats(rec)[] &until($element == 0 || $element != 0);
# EXT_STATUS_REQUEST -> status_request: StatusRequest(rec)[] &until($element == 0 || $element != 0);
EXT_SERVER_NAME -> server_name: ServerNameExt(rec)[] &until($element == 0 || $element != 0);
default -> data: bytestring &restofdata;
};
} &length=data_len+4 &exportsourcedata;
type ServerNameHostName() = record {
length: uint16;
host_name: bytestring &length=length;
};
type ServerName() = record {
name_type: uint8; # has to be 0 for host-name
name: case name_type of {
0 -> host_name: ServerNameHostName;
default -> data : bytestring &restofdata &transient; # unknown name
};
};
type ServerNameExt(rec: HandshakeRecord) = record {
length: uint16;
server_names: ServerName[] &until($input.length() == 0);
} &length=length+2;
# Do not parse for now. Structure is correct, but only contains asn.1 data that we would not use further.
#type OcspStatusRequest(rec: HandshakeRecord) = record {
# responder_id_list_length: uint16;
# responder_id_list: bytestring &length=responder_id_list_length;
# request_extensions_length: uint16;
# request_extensions: bytestring &length=request_extensions_length;
#};
#
#type StatusRequest(rec: HandshakeRecord) = record {
# status_type: uint8; # 1 -> ocsp
# req: case status_type of {
# 1 -> ocsp_status_request: OcspStatusRequest(rec);
# default -> data : bytestring &restofdata &transient; # unknown
# };
#};
type EcPointFormats(rec: HandshakeRecord) = record {
length: uint8;
point_format_list: uint8[length];
};
type EllipticCurves(rec: HandshakeRecord) = record {
length: uint16;
elliptic_curve_list: uint16[length/2];
};
type ProtocolName() = record {
length: uint8;
name: bytestring &length=length;
};
type ApplicationLayerProtocolNegotiationExtension(rec: HandshakeRecord) = record {
length: uint16;
protocol_name_list: ProtocolName[] &until($input.length() == 0);
} &length=length+2;
refine connection Handshake_Conn += {
%member{
uint32 chosen_cipher_;
%}
%init{
chosen_cipher_ = NO_CHOSEN_CIPHER;
%}
function chosen_cipher() : int %{ return chosen_cipher_; %}
function set_cipher(cipher: uint32) : bool
%{
chosen_cipher_ = cipher;
return true;
%}
};

View file

@ -0,0 +1,23 @@
# Binpac analyzer just for the TLS handshake protocol and nothing else
%include binpac.pac
%include bro.pac
analyzer TLSHandshake withcontext {
connection: Handshake_Conn;
flow: Handshake_Flow;
};
connection Handshake_Conn(bro_analyzer: BroAnalyzer) {
upflow = Handshake_Flow(true);
downflow = Handshake_Flow(false);
};
%include ssl-defs.pac
%include tls-handshake-protocol.pac
flow Handshake_Flow(is_orig: bool) {
flowunit = HandshakePDU(is_orig) withcontext(connection, this);
}
%include tls-handshake-analyzer.pac

View file

@ -14,7 +14,7 @@
1 3128 1 3128
1 3306 1 3306
1 3544 1 3544
1 443 2 443
1 502 1 502
1 5072 1 5072
1 514 1 514
@ -44,8 +44,8 @@
1 992 1 992
1 993 1 993
1 995 1 995
49 and 50 and
48 or 49 or
49 port 50 port
34 tcp 34 tcp
15 udp 16 udp

View file

@ -12,6 +12,7 @@
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 53/udp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 53/udp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5353/udp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5353/udp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5355/udp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5355/udp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DTLS, 443/udp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 21/tcp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 21/tcp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 2811/tcp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 2811/tcp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_GTPV1, 2123/udp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_GTPV1, 2123/udp)) -> <no result>
@ -65,6 +66,7 @@
0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 53/udp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 53/udp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5353/udp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5353/udp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5355/udp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5355/udp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DTLS, 443/udp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 21/tcp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 21/tcp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 2811/tcp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 2811/tcp)) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_GTPV1, 2123/udp)) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_GTPV1, 2123/udp)) -> <no result>
@ -108,6 +110,7 @@
0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DHCP, {67<...>/udp})) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DHCP, {67<...>/udp})) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DNP3_TCP, {20000<...>/tcp})) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DNP3_TCP, {20000<...>/tcp})) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DNS, {5355<...>/udp})) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DNS, {5355<...>/udp})) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DTLS, {443/udp})) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_FTP, {2811<...>/tcp})) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_FTP, {2811<...>/tcp})) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_GTPV1, {2152<...>/udp})) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_GTPV1, {2152<...>/udp})) -> <no result>
0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_HTTP, {631<...>/tcp})) -> <no result> 0.000000 MetaHookPost CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_HTTP, {631<...>/tcp})) -> <no result>
@ -125,6 +128,7 @@
0.000000 MetaHookPost CallFunction(Cluster::is_enabled, <frame>, ()) -> <no result> 0.000000 MetaHookPost CallFunction(Cluster::is_enabled, <frame>, ()) -> <no result>
0.000000 MetaHookPost CallFunction(Cluster::is_enabled, <null>, ()) -> <no result> 0.000000 MetaHookPost CallFunction(Cluster::is_enabled, <null>, ()) -> <no result>
0.000000 MetaHookPost CallFunction(Files::register_analyzer_add_callback, <frame>, (Files::ANALYZER_EXTRACT, FileExtract::on_add{ if (!FileExtract::args?$extract_filename) FileExtract::args$extract_filename = cat(extract-, FileExtract::f$last_active, -, FileExtract::f$source, -, FileExtract::f$id)FileExtract::f$info$extracted = FileExtract::args$extract_filenameFileExtract::args$extract_filename = build_path_compressed(FileExtract::prefix, FileExtract::args$extract_filename)mkdir(FileExtract::prefix)})) -> <no result> 0.000000 MetaHookPost CallFunction(Files::register_analyzer_add_callback, <frame>, (Files::ANALYZER_EXTRACT, FileExtract::on_add{ if (!FileExtract::args?$extract_filename) FileExtract::args$extract_filename = cat(extract-, FileExtract::f$last_active, -, FileExtract::f$source, -, FileExtract::f$id)FileExtract::f$info$extracted = FileExtract::args$extract_filenameFileExtract::args$extract_filename = build_path_compressed(FileExtract::prefix, FileExtract::args$extract_filename)mkdir(FileExtract::prefix)})) -> <no result>
0.000000 MetaHookPost CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_DTLS, [get_file_handle=SSL::get_file_handle{ return ()}, describe=SSL::describe_file{ <init> SSL::cid{ if (SSL::f$source != SSL || !SSL::f?$info || !SSL::f$info?$x509 || !SSL::f$info$x509?$certificate) return ()for ([SSL::cid] in SSL::f$conns) { if (SSL::f$conns[SSL::cid]?$ssl) { SSL::c = SSL::f$conns[SSL::cid]return (cat(SSL::c$id$resp_h, :, SSL::c$id$resp_p))}}return (cat(Serial: , SSL::f$info$x509$certificate$serial, Subject: , SSL::f$info$x509$certificate$subject, Issuer: , SSL::f$info$x509$certificate$issuer))}}])) -> <no result>
0.000000 MetaHookPost CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_FTP_DATA, [get_file_handle=FTP::get_file_handle{ if (!FTP::c$id$resp_h, FTP::c$id$resp_p in FTP::ftp_data_expected) return ()return (cat(Analyzer::ANALYZER_FTP_DATA, FTP::c$start_time, FTP::c$id, FTP::is_orig))}, describe=FTP::describe_file{ <init> FTP::cid{ if (FTP::f$source != FTP) return ()for ([FTP::cid] in FTP::f$conns) { if (FTP::f$conns[FTP::cid]?$ftp) return (FTP::describe(FTP::f$conns[FTP::cid]$ftp))}return ()}}])) -> <no result> 0.000000 MetaHookPost CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_FTP_DATA, [get_file_handle=FTP::get_file_handle{ if (!FTP::c$id$resp_h, FTP::c$id$resp_p in FTP::ftp_data_expected) return ()return (cat(Analyzer::ANALYZER_FTP_DATA, FTP::c$start_time, FTP::c$id, FTP::is_orig))}, describe=FTP::describe_file{ <init> FTP::cid{ if (FTP::f$source != FTP) return ()for ([FTP::cid] in FTP::f$conns) { if (FTP::f$conns[FTP::cid]?$ftp) return (FTP::describe(FTP::f$conns[FTP::cid]$ftp))}return ()}}])) -> <no result>
0.000000 MetaHookPost CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_HTTP, [get_file_handle=HTTP::get_file_handle{ if (!HTTP::c?$http) return ()if (HTTP::c$http$range_request && !HTTP::is_orig) { return (cat(Analyzer::ANALYZER_HTTP, HTTP::is_orig, HTTP::c$id$orig_h, HTTP::build_url(HTTP::c$http)))}else{ HTTP::mime_depth = HTTP::is_orig ? HTTP::c$http$orig_mime_depth : HTTP::c$http$resp_mime_depthreturn (cat(Analyzer::ANALYZER_HTTP, HTTP::c$start_time, HTTP::is_orig, HTTP::c$http$trans_depth, HTTP::mime_depth, id_string(HTTP::c$id)))}}, describe=HTTP::describe_file{ <init> HTTP::cid{ if (HTTP::f$source != HTTP) return ()for ([HTTP::cid] in HTTP::f$conns) { if (HTTP::f$conns[HTTP::cid]?$http) return (HTTP::build_url_http(HTTP::f$conns[HTTP::cid]$http))}return ()}}])) -> <no result> 0.000000 MetaHookPost CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_HTTP, [get_file_handle=HTTP::get_file_handle{ if (!HTTP::c?$http) return ()if (HTTP::c$http$range_request && !HTTP::is_orig) { return (cat(Analyzer::ANALYZER_HTTP, HTTP::is_orig, HTTP::c$id$orig_h, HTTP::build_url(HTTP::c$http)))}else{ HTTP::mime_depth = HTTP::is_orig ? HTTP::c$http$orig_mime_depth : HTTP::c$http$resp_mime_depthreturn (cat(Analyzer::ANALYZER_HTTP, HTTP::c$start_time, HTTP::is_orig, HTTP::c$http$trans_depth, HTTP::mime_depth, id_string(HTTP::c$id)))}}, describe=HTTP::describe_file{ <init> HTTP::cid{ if (HTTP::f$source != HTTP) return ()for ([HTTP::cid] in HTTP::f$conns) { if (HTTP::f$conns[HTTP::cid]?$http) return (HTTP::build_url_http(HTTP::f$conns[HTTP::cid]$http))}return ()}}])) -> <no result>
0.000000 MetaHookPost CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_IRC_DATA, [get_file_handle=IRC::get_file_handle{ return (cat(Analyzer::ANALYZER_IRC_DATA, IRC::c$start_time, IRC::c$id, IRC::is_orig))}, describe=anonymous-function{ return ()}])) -> <no result> 0.000000 MetaHookPost CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_IRC_DATA, [get_file_handle=IRC::get_file_handle{ return (cat(Analyzer::ANALYZER_IRC_DATA, IRC::c$start_time, IRC::c$id, IRC::is_orig))}, describe=anonymous-function{ return ()}])) -> <no result>
@ -192,7 +196,7 @@
0.000000 MetaHookPost CallFunction(Log::__create_stream, <frame>, (Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird])) -> <no result> 0.000000 MetaHookPost CallFunction(Log::__create_stream, <frame>, (Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird])) -> <no result>
0.000000 MetaHookPost CallFunction(Log::__create_stream, <frame>, (X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509])) -> <no result> 0.000000 MetaHookPost CallFunction(Log::__create_stream, <frame>, (X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509])) -> <no result>
0.000000 MetaHookPost CallFunction(Log::__create_stream, <frame>, (mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql])) -> <no result> 0.000000 MetaHookPost CallFunction(Log::__create_stream, <frame>, (mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql])) -> <no result>
0.000000 MetaHookPost CallFunction(Log::__write, <frame>, (PacketFilter::LOG, [ts=1426793275.574315, node=bro, filter=ip or not ip, init=T, success=T])) -> <no result> 0.000000 MetaHookPost CallFunction(Log::__write, <frame>, (PacketFilter::LOG, [ts=1427139545.064324, node=bro, filter=ip or not ip, init=T, success=T])) -> <no result>
0.000000 MetaHookPost CallFunction(Log::add_default_filter, <frame>, (Cluster::LOG)) -> <no result> 0.000000 MetaHookPost CallFunction(Log::add_default_filter, <frame>, (Cluster::LOG)) -> <no result>
0.000000 MetaHookPost CallFunction(Log::add_default_filter, <frame>, (Communication::LOG)) -> <no result> 0.000000 MetaHookPost CallFunction(Log::add_default_filter, <frame>, (Communication::LOG)) -> <no result>
0.000000 MetaHookPost CallFunction(Log::add_default_filter, <frame>, (Conn::LOG)) -> <no result> 0.000000 MetaHookPost CallFunction(Log::add_default_filter, <frame>, (Conn::LOG)) -> <no result>
@ -286,7 +290,7 @@
0.000000 MetaHookPost CallFunction(Log::create_stream, <frame>, (Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird])) -> <no result> 0.000000 MetaHookPost CallFunction(Log::create_stream, <frame>, (Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird])) -> <no result>
0.000000 MetaHookPost CallFunction(Log::create_stream, <frame>, (X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509])) -> <no result> 0.000000 MetaHookPost CallFunction(Log::create_stream, <frame>, (X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509])) -> <no result>
0.000000 MetaHookPost CallFunction(Log::create_stream, <frame>, (mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql])) -> <no result> 0.000000 MetaHookPost CallFunction(Log::create_stream, <frame>, (mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql])) -> <no result>
0.000000 MetaHookPost CallFunction(Log::write, <frame>, (PacketFilter::LOG, [ts=1426793275.574315, node=bro, filter=ip or not ip, init=T, success=T])) -> <no result> 0.000000 MetaHookPost CallFunction(Log::write, <frame>, (PacketFilter::LOG, [ts=1427139545.064324, node=bro, filter=ip or not ip, init=T, success=T])) -> <no result>
0.000000 MetaHookPost CallFunction(Notice::want_pp, <frame>, ()) -> <no result> 0.000000 MetaHookPost CallFunction(Notice::want_pp, <frame>, ()) -> <no result>
0.000000 MetaHookPost CallFunction(PacketFilter::build, <frame>, ()) -> <no result> 0.000000 MetaHookPost CallFunction(PacketFilter::build, <frame>, ()) -> <no result>
0.000000 MetaHookPost CallFunction(PacketFilter::combine_filters, <frame>, (ip or not ip, and, )) -> <no result> 0.000000 MetaHookPost CallFunction(PacketFilter::combine_filters, <frame>, (ip or not ip, and, )) -> <no result>
@ -549,6 +553,7 @@
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 53/udp)) 0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 53/udp))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5353/udp)) 0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5353/udp))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5355/udp)) 0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5355/udp))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_DTLS, 443/udp))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 21/tcp)) 0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 21/tcp))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 2811/tcp)) 0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 2811/tcp))
0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_GTPV1, 2123/udp)) 0.000000 MetaHookPre CallFunction(Analyzer::__register_for_port, <frame>, (Analyzer::ANALYZER_GTPV1, 2123/udp))
@ -602,6 +607,7 @@
0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 53/udp)) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 53/udp))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5353/udp)) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5353/udp))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5355/udp)) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DNS, 5355/udp))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_DTLS, 443/udp))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 21/tcp)) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 21/tcp))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 2811/tcp)) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_FTP, 2811/tcp))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_GTPV1, 2123/udp)) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_port, <frame>, (Analyzer::ANALYZER_GTPV1, 2123/udp))
@ -645,6 +651,7 @@
0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DHCP, {67<...>/udp})) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DHCP, {67<...>/udp}))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DNP3_TCP, {20000<...>/tcp})) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DNP3_TCP, {20000<...>/tcp}))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DNS, {5355<...>/udp})) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DNS, {5355<...>/udp}))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_DTLS, {443/udp}))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_FTP, {2811<...>/tcp})) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_FTP, {2811<...>/tcp}))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_GTPV1, {2152<...>/udp})) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_GTPV1, {2152<...>/udp}))
0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_HTTP, {631<...>/tcp})) 0.000000 MetaHookPre CallFunction(Analyzer::register_for_ports, <frame>, (Analyzer::ANALYZER_HTTP, {631<...>/tcp}))
@ -662,6 +669,7 @@
0.000000 MetaHookPre CallFunction(Cluster::is_enabled, <frame>, ()) 0.000000 MetaHookPre CallFunction(Cluster::is_enabled, <frame>, ())
0.000000 MetaHookPre CallFunction(Cluster::is_enabled, <null>, ()) 0.000000 MetaHookPre CallFunction(Cluster::is_enabled, <null>, ())
0.000000 MetaHookPre CallFunction(Files::register_analyzer_add_callback, <frame>, (Files::ANALYZER_EXTRACT, FileExtract::on_add{ if (!FileExtract::args?$extract_filename) FileExtract::args$extract_filename = cat(extract-, FileExtract::f$last_active, -, FileExtract::f$source, -, FileExtract::f$id)FileExtract::f$info$extracted = FileExtract::args$extract_filenameFileExtract::args$extract_filename = build_path_compressed(FileExtract::prefix, FileExtract::args$extract_filename)mkdir(FileExtract::prefix)})) 0.000000 MetaHookPre CallFunction(Files::register_analyzer_add_callback, <frame>, (Files::ANALYZER_EXTRACT, FileExtract::on_add{ if (!FileExtract::args?$extract_filename) FileExtract::args$extract_filename = cat(extract-, FileExtract::f$last_active, -, FileExtract::f$source, -, FileExtract::f$id)FileExtract::f$info$extracted = FileExtract::args$extract_filenameFileExtract::args$extract_filename = build_path_compressed(FileExtract::prefix, FileExtract::args$extract_filename)mkdir(FileExtract::prefix)}))
0.000000 MetaHookPre CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_DTLS, [get_file_handle=SSL::get_file_handle{ return ()}, describe=SSL::describe_file{ <init> SSL::cid{ if (SSL::f$source != SSL || !SSL::f?$info || !SSL::f$info?$x509 || !SSL::f$info$x509?$certificate) return ()for ([SSL::cid] in SSL::f$conns) { if (SSL::f$conns[SSL::cid]?$ssl) { SSL::c = SSL::f$conns[SSL::cid]return (cat(SSL::c$id$resp_h, :, SSL::c$id$resp_p))}}return (cat(Serial: , SSL::f$info$x509$certificate$serial, Subject: , SSL::f$info$x509$certificate$subject, Issuer: , SSL::f$info$x509$certificate$issuer))}}]))
0.000000 MetaHookPre CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_FTP_DATA, [get_file_handle=FTP::get_file_handle{ if (!FTP::c$id$resp_h, FTP::c$id$resp_p in FTP::ftp_data_expected) return ()return (cat(Analyzer::ANALYZER_FTP_DATA, FTP::c$start_time, FTP::c$id, FTP::is_orig))}, describe=FTP::describe_file{ <init> FTP::cid{ if (FTP::f$source != FTP) return ()for ([FTP::cid] in FTP::f$conns) { if (FTP::f$conns[FTP::cid]?$ftp) return (FTP::describe(FTP::f$conns[FTP::cid]$ftp))}return ()}}])) 0.000000 MetaHookPre CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_FTP_DATA, [get_file_handle=FTP::get_file_handle{ if (!FTP::c$id$resp_h, FTP::c$id$resp_p in FTP::ftp_data_expected) return ()return (cat(Analyzer::ANALYZER_FTP_DATA, FTP::c$start_time, FTP::c$id, FTP::is_orig))}, describe=FTP::describe_file{ <init> FTP::cid{ if (FTP::f$source != FTP) return ()for ([FTP::cid] in FTP::f$conns) { if (FTP::f$conns[FTP::cid]?$ftp) return (FTP::describe(FTP::f$conns[FTP::cid]$ftp))}return ()}}]))
0.000000 MetaHookPre CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_HTTP, [get_file_handle=HTTP::get_file_handle{ if (!HTTP::c?$http) return ()if (HTTP::c$http$range_request && !HTTP::is_orig) { return (cat(Analyzer::ANALYZER_HTTP, HTTP::is_orig, HTTP::c$id$orig_h, HTTP::build_url(HTTP::c$http)))}else{ HTTP::mime_depth = HTTP::is_orig ? HTTP::c$http$orig_mime_depth : HTTP::c$http$resp_mime_depthreturn (cat(Analyzer::ANALYZER_HTTP, HTTP::c$start_time, HTTP::is_orig, HTTP::c$http$trans_depth, HTTP::mime_depth, id_string(HTTP::c$id)))}}, describe=HTTP::describe_file{ <init> HTTP::cid{ if (HTTP::f$source != HTTP) return ()for ([HTTP::cid] in HTTP::f$conns) { if (HTTP::f$conns[HTTP::cid]?$http) return (HTTP::build_url_http(HTTP::f$conns[HTTP::cid]$http))}return ()}}])) 0.000000 MetaHookPre CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_HTTP, [get_file_handle=HTTP::get_file_handle{ if (!HTTP::c?$http) return ()if (HTTP::c$http$range_request && !HTTP::is_orig) { return (cat(Analyzer::ANALYZER_HTTP, HTTP::is_orig, HTTP::c$id$orig_h, HTTP::build_url(HTTP::c$http)))}else{ HTTP::mime_depth = HTTP::is_orig ? HTTP::c$http$orig_mime_depth : HTTP::c$http$resp_mime_depthreturn (cat(Analyzer::ANALYZER_HTTP, HTTP::c$start_time, HTTP::is_orig, HTTP::c$http$trans_depth, HTTP::mime_depth, id_string(HTTP::c$id)))}}, describe=HTTP::describe_file{ <init> HTTP::cid{ if (HTTP::f$source != HTTP) return ()for ([HTTP::cid] in HTTP::f$conns) { if (HTTP::f$conns[HTTP::cid]?$http) return (HTTP::build_url_http(HTTP::f$conns[HTTP::cid]$http))}return ()}}]))
0.000000 MetaHookPre CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_IRC_DATA, [get_file_handle=IRC::get_file_handle{ return (cat(Analyzer::ANALYZER_IRC_DATA, IRC::c$start_time, IRC::c$id, IRC::is_orig))}, describe=anonymous-function{ return ()}])) 0.000000 MetaHookPre CallFunction(Files::register_protocol, <frame>, (Analyzer::ANALYZER_IRC_DATA, [get_file_handle=IRC::get_file_handle{ return (cat(Analyzer::ANALYZER_IRC_DATA, IRC::c$start_time, IRC::c$id, IRC::is_orig))}, describe=anonymous-function{ return ()}]))
@ -729,7 +737,7 @@
0.000000 MetaHookPre CallFunction(Log::__create_stream, <frame>, (Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird])) 0.000000 MetaHookPre CallFunction(Log::__create_stream, <frame>, (Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird]))
0.000000 MetaHookPre CallFunction(Log::__create_stream, <frame>, (X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509])) 0.000000 MetaHookPre CallFunction(Log::__create_stream, <frame>, (X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509]))
0.000000 MetaHookPre CallFunction(Log::__create_stream, <frame>, (mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql])) 0.000000 MetaHookPre CallFunction(Log::__create_stream, <frame>, (mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql]))
0.000000 MetaHookPre CallFunction(Log::__write, <frame>, (PacketFilter::LOG, [ts=1426793275.574315, node=bro, filter=ip or not ip, init=T, success=T])) 0.000000 MetaHookPre CallFunction(Log::__write, <frame>, (PacketFilter::LOG, [ts=1427139545.064324, node=bro, filter=ip or not ip, init=T, success=T]))
0.000000 MetaHookPre CallFunction(Log::add_default_filter, <frame>, (Cluster::LOG)) 0.000000 MetaHookPre CallFunction(Log::add_default_filter, <frame>, (Cluster::LOG))
0.000000 MetaHookPre CallFunction(Log::add_default_filter, <frame>, (Communication::LOG)) 0.000000 MetaHookPre CallFunction(Log::add_default_filter, <frame>, (Communication::LOG))
0.000000 MetaHookPre CallFunction(Log::add_default_filter, <frame>, (Conn::LOG)) 0.000000 MetaHookPre CallFunction(Log::add_default_filter, <frame>, (Conn::LOG))
@ -823,7 +831,7 @@
0.000000 MetaHookPre CallFunction(Log::create_stream, <frame>, (Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird])) 0.000000 MetaHookPre CallFunction(Log::create_stream, <frame>, (Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird]))
0.000000 MetaHookPre CallFunction(Log::create_stream, <frame>, (X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509])) 0.000000 MetaHookPre CallFunction(Log::create_stream, <frame>, (X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509]))
0.000000 MetaHookPre CallFunction(Log::create_stream, <frame>, (mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql])) 0.000000 MetaHookPre CallFunction(Log::create_stream, <frame>, (mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql]))
0.000000 MetaHookPre CallFunction(Log::write, <frame>, (PacketFilter::LOG, [ts=1426793275.574315, node=bro, filter=ip or not ip, init=T, success=T])) 0.000000 MetaHookPre CallFunction(Log::write, <frame>, (PacketFilter::LOG, [ts=1427139545.064324, node=bro, filter=ip or not ip, init=T, success=T]))
0.000000 MetaHookPre CallFunction(Notice::want_pp, <frame>, ()) 0.000000 MetaHookPre CallFunction(Notice::want_pp, <frame>, ())
0.000000 MetaHookPre CallFunction(PacketFilter::build, <frame>, ()) 0.000000 MetaHookPre CallFunction(PacketFilter::build, <frame>, ())
0.000000 MetaHookPre CallFunction(PacketFilter::combine_filters, <frame>, (ip or not ip, and, )) 0.000000 MetaHookPre CallFunction(PacketFilter::combine_filters, <frame>, (ip or not ip, and, ))
@ -1086,6 +1094,7 @@
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_DNS, 53/udp) 0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_DNS, 53/udp)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_DNS, 5353/udp) 0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_DNS, 5353/udp)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_DNS, 5355/udp) 0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_DNS, 5355/udp)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_DTLS, 443/udp)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_FTP, 21/tcp) 0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_FTP, 21/tcp)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_FTP, 2811/tcp) 0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_FTP, 2811/tcp)
0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_GTPV1, 2123/udp) 0.000000 | HookCallFunction Analyzer::__register_for_port(Analyzer::ANALYZER_GTPV1, 2123/udp)
@ -1139,6 +1148,7 @@
0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_DNS, 53/udp) 0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_DNS, 53/udp)
0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_DNS, 5353/udp) 0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_DNS, 5353/udp)
0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_DNS, 5355/udp) 0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_DNS, 5355/udp)
0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_DTLS, 443/udp)
0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_FTP, 21/tcp) 0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_FTP, 21/tcp)
0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_FTP, 2811/tcp) 0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_FTP, 2811/tcp)
0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_GTPV1, 2123/udp) 0.000000 | HookCallFunction Analyzer::register_for_port(Analyzer::ANALYZER_GTPV1, 2123/udp)
@ -1182,6 +1192,7 @@
0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_DHCP, {67<...>/udp}) 0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_DHCP, {67<...>/udp})
0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_DNP3_TCP, {20000<...>/tcp}) 0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_DNP3_TCP, {20000<...>/tcp})
0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_DNS, {5355<...>/udp}) 0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_DNS, {5355<...>/udp})
0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_DTLS, {443/udp})
0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_FTP, {2811<...>/tcp}) 0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_FTP, {2811<...>/tcp})
0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_GTPV1, {2152<...>/udp}) 0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_GTPV1, {2152<...>/udp})
0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_HTTP, {631<...>/tcp}) 0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_HTTP, {631<...>/tcp})
@ -1198,6 +1209,7 @@
0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_TEREDO, {3544/udp}) 0.000000 | HookCallFunction Analyzer::register_for_ports(Analyzer::ANALYZER_TEREDO, {3544/udp})
0.000000 | HookCallFunction Cluster::is_enabled() 0.000000 | HookCallFunction Cluster::is_enabled()
0.000000 | HookCallFunction Files::register_analyzer_add_callback(Files::ANALYZER_EXTRACT, FileExtract::on_add{ if (!FileExtract::args?$extract_filename) FileExtract::args$extract_filename = cat(extract-, FileExtract::f$last_active, -, FileExtract::f$source, -, FileExtract::f$id)FileExtract::f$info$extracted = FileExtract::args$extract_filenameFileExtract::args$extract_filename = build_path_compressed(FileExtract::prefix, FileExtract::args$extract_filename)mkdir(FileExtract::prefix)}) 0.000000 | HookCallFunction Files::register_analyzer_add_callback(Files::ANALYZER_EXTRACT, FileExtract::on_add{ if (!FileExtract::args?$extract_filename) FileExtract::args$extract_filename = cat(extract-, FileExtract::f$last_active, -, FileExtract::f$source, -, FileExtract::f$id)FileExtract::f$info$extracted = FileExtract::args$extract_filenameFileExtract::args$extract_filename = build_path_compressed(FileExtract::prefix, FileExtract::args$extract_filename)mkdir(FileExtract::prefix)})
0.000000 | HookCallFunction Files::register_protocol(Analyzer::ANALYZER_DTLS, [get_file_handle=SSL::get_file_handle{ return ()}, describe=SSL::describe_file{ <init> SSL::cid{ if (SSL::f$source != SSL || !SSL::f?$info || !SSL::f$info?$x509 || !SSL::f$info$x509?$certificate) return ()for ([SSL::cid] in SSL::f$conns) { if (SSL::f$conns[SSL::cid]?$ssl) { SSL::c = SSL::f$conns[SSL::cid]return (cat(SSL::c$id$resp_h, :, SSL::c$id$resp_p))}}return (cat(Serial: , SSL::f$info$x509$certificate$serial, Subject: , SSL::f$info$x509$certificate$subject, Issuer: , SSL::f$info$x509$certificate$issuer))}}])
0.000000 | HookCallFunction Files::register_protocol(Analyzer::ANALYZER_FTP_DATA, [get_file_handle=FTP::get_file_handle{ if (!FTP::c$id$resp_h, FTP::c$id$resp_p in FTP::ftp_data_expected) return ()return (cat(Analyzer::ANALYZER_FTP_DATA, FTP::c$start_time, FTP::c$id, FTP::is_orig))}, describe=FTP::describe_file{ <init> FTP::cid{ if (FTP::f$source != FTP) return ()for ([FTP::cid] in FTP::f$conns) { if (FTP::f$conns[FTP::cid]?$ftp) return (FTP::describe(FTP::f$conns[FTP::cid]$ftp))}return ()}}]) 0.000000 | HookCallFunction Files::register_protocol(Analyzer::ANALYZER_FTP_DATA, [get_file_handle=FTP::get_file_handle{ if (!FTP::c$id$resp_h, FTP::c$id$resp_p in FTP::ftp_data_expected) return ()return (cat(Analyzer::ANALYZER_FTP_DATA, FTP::c$start_time, FTP::c$id, FTP::is_orig))}, describe=FTP::describe_file{ <init> FTP::cid{ if (FTP::f$source != FTP) return ()for ([FTP::cid] in FTP::f$conns) { if (FTP::f$conns[FTP::cid]?$ftp) return (FTP::describe(FTP::f$conns[FTP::cid]$ftp))}return ()}}])
0.000000 | HookCallFunction Files::register_protocol(Analyzer::ANALYZER_HTTP, [get_file_handle=HTTP::get_file_handle{ if (!HTTP::c?$http) return ()if (HTTP::c$http$range_request && !HTTP::is_orig) { return (cat(Analyzer::ANALYZER_HTTP, HTTP::is_orig, HTTP::c$id$orig_h, HTTP::build_url(HTTP::c$http)))}else{ HTTP::mime_depth = HTTP::is_orig ? HTTP::c$http$orig_mime_depth : HTTP::c$http$resp_mime_depthreturn (cat(Analyzer::ANALYZER_HTTP, HTTP::c$start_time, HTTP::is_orig, HTTP::c$http$trans_depth, HTTP::mime_depth, id_string(HTTP::c$id)))}}, describe=HTTP::describe_file{ <init> HTTP::cid{ if (HTTP::f$source != HTTP) return ()for ([HTTP::cid] in HTTP::f$conns) { if (HTTP::f$conns[HTTP::cid]?$http) return (HTTP::build_url_http(HTTP::f$conns[HTTP::cid]$http))}return ()}}]) 0.000000 | HookCallFunction Files::register_protocol(Analyzer::ANALYZER_HTTP, [get_file_handle=HTTP::get_file_handle{ if (!HTTP::c?$http) return ()if (HTTP::c$http$range_request && !HTTP::is_orig) { return (cat(Analyzer::ANALYZER_HTTP, HTTP::is_orig, HTTP::c$id$orig_h, HTTP::build_url(HTTP::c$http)))}else{ HTTP::mime_depth = HTTP::is_orig ? HTTP::c$http$orig_mime_depth : HTTP::c$http$resp_mime_depthreturn (cat(Analyzer::ANALYZER_HTTP, HTTP::c$start_time, HTTP::is_orig, HTTP::c$http$trans_depth, HTTP::mime_depth, id_string(HTTP::c$id)))}}, describe=HTTP::describe_file{ <init> HTTP::cid{ if (HTTP::f$source != HTTP) return ()for ([HTTP::cid] in HTTP::f$conns) { if (HTTP::f$conns[HTTP::cid]?$http) return (HTTP::build_url_http(HTTP::f$conns[HTTP::cid]$http))}return ()}}])
0.000000 | HookCallFunction Files::register_protocol(Analyzer::ANALYZER_IRC_DATA, [get_file_handle=IRC::get_file_handle{ return (cat(Analyzer::ANALYZER_IRC_DATA, IRC::c$start_time, IRC::c$id, IRC::is_orig))}, describe=anonymous-function{ return ()}]) 0.000000 | HookCallFunction Files::register_protocol(Analyzer::ANALYZER_IRC_DATA, [get_file_handle=IRC::get_file_handle{ return (cat(Analyzer::ANALYZER_IRC_DATA, IRC::c$start_time, IRC::c$id, IRC::is_orig))}, describe=anonymous-function{ return ()}])
@ -1265,7 +1277,7 @@
0.000000 | HookCallFunction Log::__create_stream(Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird]) 0.000000 | HookCallFunction Log::__create_stream(Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird])
0.000000 | HookCallFunction Log::__create_stream(X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509]) 0.000000 | HookCallFunction Log::__create_stream(X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509])
0.000000 | HookCallFunction Log::__create_stream(mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql]) 0.000000 | HookCallFunction Log::__create_stream(mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql])
0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1426793275.574315, node=bro, filter=ip or not ip, init=T, success=T]) 0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1427139545.064324, node=bro, filter=ip or not ip, init=T, success=T])
0.000000 | HookCallFunction Log::add_default_filter(Cluster::LOG) 0.000000 | HookCallFunction Log::add_default_filter(Cluster::LOG)
0.000000 | HookCallFunction Log::add_default_filter(Communication::LOG) 0.000000 | HookCallFunction Log::add_default_filter(Communication::LOG)
0.000000 | HookCallFunction Log::add_default_filter(Conn::LOG) 0.000000 | HookCallFunction Log::add_default_filter(Conn::LOG)
@ -1359,7 +1371,7 @@
0.000000 | HookCallFunction Log::create_stream(Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird]) 0.000000 | HookCallFunction Log::create_stream(Weird::LOG, [columns=<no value description>, ev=Weird::log_weird, path=weird])
0.000000 | HookCallFunction Log::create_stream(X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509]) 0.000000 | HookCallFunction Log::create_stream(X509::LOG, [columns=<no value description>, ev=X509::log_x509, path=x509])
0.000000 | HookCallFunction Log::create_stream(mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql]) 0.000000 | HookCallFunction Log::create_stream(mysql::LOG, [columns=<no value description>, ev=MySQL::log_mysql, path=mysql])
0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1426793275.574315, node=bro, filter=ip or not ip, init=T, success=T]) 0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1427139545.064324, node=bro, filter=ip or not ip, init=T, success=T])
0.000000 | HookCallFunction Notice::want_pp() 0.000000 | HookCallFunction Notice::want_pp()
0.000000 | HookCallFunction PacketFilter::build() 0.000000 | HookCallFunction PacketFilter::build()
0.000000 | HookCallFunction PacketFilter::combine_filters(ip or not ip, and, ) 0.000000 | HookCallFunction PacketFilter::combine_filters(ip or not ip, and, )

View file

@ -0,0 +1,10 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path ssl
#open 2015-03-12-22-40-14
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established cert_chain_fuids client_cert_chain_fuids subject issuer client_subject client_issuer
#types time string addr port addr port string string string string bool string string bool vector[string] vector[string] string string string string
1425932016.520157 CXWv6p3arKYeMETxOg 192.168.6.86 63721 104.236.167.107 4433 DTLSv10 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA secp256r1 - F - - T FZi2Ct2AcCswhiIjKe (empty) CN=bro CN=bro - -
#close 2015-03-12-22-40-14

View file

@ -0,0 +1,10 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path x509
#open 2015-03-12-22-40-14
#fields ts id certificate.version certificate.serial certificate.subject certificate.issuer certificate.not_valid_before certificate.not_valid_after certificate.key_alg certificate.sig_alg certificate.key_type certificate.key_length certificate.exponent certificate.curve san.dns san.uri san.email san.ip basic_constraints.ca basic_constraints.path_len
#types time string count string string string time time string string string count string string vector[string] vector[string] vector[string] vector[addr] bool count
1425932016.611299 FZi2Ct2AcCswhiIjKe 3 E8E48E456C32945F CN=bro CN=bro 1425931873.000000 1457467873.000000 rsaEncryption sha1WithRSAEncryption rsa 2048 65537 - - - - - T -
#close 2015-03-12-22-40-14

View file

@ -0,0 +1 @@
10000

View file

@ -0,0 +1,10 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path ssl
#open 2015-03-12-01-22-34
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established cert_chain_fuids client_cert_chain_fuids subject issuer client_subject client_issuer
#types time string addr port addr port string string string string bool string string bool vector[string] vector[string] string string string string
1426117218.083491 CXWv6p3arKYeMETxOg 192.168.6.86 61454 104.236.167.107 4433 TLSv12 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 secp256r1 104.236.167.107 F - - F FsQdqWuF9t3e4W0d (empty) - - - -
#close 2015-03-12-01-22-34

Binary file not shown.

View file

@ -0,0 +1,15 @@
# Needs perftools support.
#
# @TEST-GROUP: leaks
#
# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks
#
# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local btest-bg-run bro bro -b -m -r $TRACES/tls/dtls-openssl.pcap %INPUT
# @TEST-EXEC: btest-bg-wait 30
@load base/protocols/ssl
event ssl_established(c: connection) &priority=3
{
print "established";
}

View file

@ -0,0 +1,5 @@
# This tests a normal SSL connection and the log it outputs.
# @TEST-EXEC: bro -r $TRACES/tls/dtls-openssl.pcap %INPUT
# @TEST-EXEC: btest-diff ssl.log
# @TEST-EXEC: btest-diff x509.log

View file

@ -0,0 +1,12 @@
# Test a heavily fragmented tls connection
# @TEST-EXEC: cat $TRACES/tls/tls-fragmented-handshake.pcap.gz | gunzip | bro -r - %INPUT
# @TEST-EXEC: btest-diff ssl.log
# @TEST-EXEC: btest-diff .stdout
# Certificate has 10,000 alternative names :)
event x509_ext_subject_alternative_name(f: fa_file, ext: X509::SubjectAlternativeName)
{
print |ext$dns|;
}