zeek/src/ssl-record-layer.pac

141 lines
3.2 KiB
JavaScript

# $Id:$
# binpac analyzer representing the SSLv3 record layer
#
# This additional layering in the analyzer hierarchy is necessary due to
# fragmentation that can be introduced in the SSL record layer.
%include binpac.pac
%include bro.pac
analyzer SSLRecordLayer withcontext {
analyzer : SSLRecordLayerAnalyzer;
flow : SSLRecordLayerFlow;
};
%include ssl-defs.pac
%extern{
#include "ssl_pac.h"
using binpac::SSL::SSLAnalyzer;
%}
extern type const_bytestring;
type SSLPDU = record {
head0 : uint8;
head1 : uint8;
head2 : uint8;
head3 : uint8;
head4 : uint8;
fragment : bytestring &restofdata;
} &length = 5 + length, &byteorder = bigendian, &let {
version : int =
$context.analyzer.determine_ssl_version(head0, head1, head2);
length : int = case version of {
UNKNOWN_VERSION -> 0;
SSLv20 -> (((head0 & 0x7f) << 8) | head1) - 3;
default -> (head3 << 8) | head4;
};
fw : bool = case version of {
UNKNOWN_VERSION ->
$context.analyzer.forward_record(const_bytestring(),
UNKNOWN_OR_V2_ENCRYPTED, UNKNOWN_VERSION,
$context.flow.is_orig)
&& $context.flow.discard_data();
SSLv20 -> $context.analyzer.forward_v2_record(head2, head3, head4,
fragment, $context.flow.is_orig);
default -> $context.analyzer.forward_record(fragment, head0,
(head1 << 8) | head2, $context.flow.is_orig);
};
};
# binpac-specific definitions
analyzer SSLRecordLayerAnalyzer {
upflow = SSLRecordLayerFlow(true);
downflow = SSLRecordLayerFlow(false);
%member{
SSLAnalyzer* ssl_analyzer_;
int ssl_version_;
int record_length_;
%}
%init{
ssl_analyzer_ = 0;
ssl_version_ = UNKNOWN_VERSION;
record_length_ = 0;
%}
%eof{
ssl_analyzer_->FlowEOF(true);
ssl_analyzer_->FlowEOF(false);
%}
function set_ssl_analyzer(a : SSLAnalyzer) : void
%{ ssl_analyzer_ = a; %}
function ssl_version() : int %{ return ssl_version_; %}
function record_length() : int %{ return record_length_; %}
function determine_ssl_version(head0 : uint8, head1 : uint8,
head2 : uint8) : int
%{
if ( head0 >= 20 && head0 <= 23 &&
head1 == 0x03 && head2 < 0x03 )
// This is most probably SSL version 3.
ssl_version_ = (head1 << 8) | head2;
else if ( head0 >= 128 && head2 < 5 && head2 != 3 )
// Not very strong evidence, but we suspect
// this to be SSLv2.
ssl_version_ = SSLv20;
else
ssl_version_ = UNKNOWN_VERSION;
return ssl_version_;
%}
function forward_record(fragment : const_bytestring, type : int,
version : uint16, is_orig : bool) : bool
%{
return ssl_analyzer_->next_record(fragment, type,
version, is_orig);
%}
function forward_v2_record(b1 : uint8, b2 : uint8, b3 : uint8,
fragment : const_bytestring,
is_orig : bool) : bool
%{
uint8* buffer = new uint8[2 + fragment.length()];
// Byte 1 is the record type.
buffer[0] = b2;
buffer[1] = b3;
memcpy(buffer + 2, fragment.begin(), fragment.length());
const_bytestring bs(buffer, 2 + fragment.length());
bool ret = ssl_analyzer_->next_record(bs, 300 + b1, SSLv20,
is_orig);
delete [] buffer;
return ret;
%}
};
flow SSLRecordLayerFlow(is_orig : bool) {
flowunit = SSLPDU withcontext(connection, this);
function discard_data() : bool
%{
flow_buffer_->DiscardData();
return true;
%}
};