zeek/src/analyzer/protocol/ntp/ntp-analyzer.pac
Jon Siwek e2dc0092f3 Merge branch 'ntp-rewrite' of https://github.com/mauropalumbo75/zeek
* 'ntp-rewrite' of https://github.com/mauropalumbo75/zeek: (25 commits)
  update tests baseline
  Apply requested changes: - file dpd.sig and TODO comments for signature protocol detection removed - missing doc field filled in events.bif - rename OpCode and ReqCode fields into op_code and req_code respectively - removed unnecessary child method in NTP.h/.cc - main.zeek and ntp-protocol.pac reformatted
  minor changes in the documentation
  fix some initializations
  fix wrong assignment of control key_id/crypto_checksum
  code clean up
  add extension fields parsing
  add extended mac field with 20 byte digest (+4 byte key id)
  update tests and add a new one for key_id and mac
  fix auth field (key_id and mac) in standard and control msg
  remove old NTP record in init-bare.zeek
  fix key_id and digest (WIP)
  fix wrong Assign with reference_id
  add tests for ntp protocol (finished)
  add tests for ntp protocol (WIP)
  fix problem with time vals
  add ntp records to init-bare.zeek
  update ntp analyzer to val_mgr
  extend and refact script-side of NTP analyzer
  extend and refactor several fields
  ...
2019-06-15 19:11:34 -07:00

160 lines
4.5 KiB
JavaScript

%extern{
#include <math.h>
#define FRAC_16 pow(2,-16)
#define FRAC_32 pow(2,-32)
// NTP defines the epoch from 1900, not 1970
#define EPOCH_OFFSET -2208988800
%}
%header{
Val* proc_ntp_short(const NTP_Short_Time* t);
Val* proc_ntp_timestamp(const NTP_Time* t);
%}
%code{
Val* proc_ntp_short(const NTP_Short_Time* t)
{
if ( t->seconds() == 0 && t->fractions() == 0 )
return new Val(0.0, TYPE_INTERVAL);
return new Val(t->seconds() + t->fractions()*FRAC_16, TYPE_INTERVAL);
}
Val* proc_ntp_timestamp(const NTP_Time* t)
{
if ( t->seconds() == 0 && t->fractions() == 0)
return new Val(0.0, TYPE_TIME);
return new Val(EPOCH_OFFSET + t->seconds() + t->fractions()*FRAC_32, TYPE_TIME);
}
%}
refine flow NTP_Flow += {
# This builds the standard msg record
function BuildNTPStdMsg(nsm: NTP_std_msg): BroVal
%{
RecordVal* rv = new RecordVal(BifType::Record::NTP::StandardMessage);
rv->Assign(0, val_mgr->GetCount(${nsm.stratum}));
rv->Assign(1, new Val(pow(2, ${nsm.poll}), TYPE_INTERVAL));
rv->Assign(2, new Val(pow(2, ${nsm.precision}), TYPE_INTERVAL));
rv->Assign(3, proc_ntp_short(${nsm.root_delay}));
rv->Assign(4, proc_ntp_short(${nsm.root_dispersion}));
switch ( ${nsm.stratum} ) {
case 0:
// unknown stratum => kiss code
rv->Assign(5, bytestring_to_val(${nsm.reference_id}));
break;
case 1:
// reference clock => ref clock string
rv->Assign(6, bytestring_to_val(${nsm.reference_id}));
break;
default:
{
const uint8* d = ${nsm.reference_id}.data();
rv->Assign(7, new AddrVal(IPAddr(IPv4, (const uint32*) d, IPAddr::Network)));
}
break;
}
rv->Assign(8, proc_ntp_timestamp(${nsm.reference_ts}));
rv->Assign(9, proc_ntp_timestamp(${nsm.origin_ts}));
rv->Assign(10, proc_ntp_timestamp(${nsm.receive_ts}));
rv->Assign(11, proc_ntp_timestamp(${nsm.transmit_ts}));
if ( ${nsm.mac_len} == 20 )
{
rv->Assign(12, val_mgr->GetCount(${nsm.mac.key_id}));
rv->Assign(13, bytestring_to_val(${nsm.mac.digest}));
}
else if ( ${nsm.mac_len} == 24 )
{
rv->Assign(12, val_mgr->GetCount(${nsm.mac_ext.key_id}));
rv->Assign(13, bytestring_to_val(${nsm.mac_ext.digest}));
}
if ( ${nsm.has_exts} )
{
// TODO: add extension fields
rv->Assign(14, val_mgr->GetCount((uint32) ${nsm.exts}->size()));
}
return rv;
%}
# This builds the control msg record
function BuildNTPControlMsg(ncm: NTP_control_msg): BroVal
%{
RecordVal* rv = new RecordVal(BifType::Record::NTP::ControlMessage);
rv->Assign(0, val_mgr->GetCount(${ncm.OpCode}));
rv->Assign(1, val_mgr->GetBool(${ncm.R}));
rv->Assign(2, val_mgr->GetBool(${ncm.E}));
rv->Assign(3, val_mgr->GetBool(${ncm.M}));
rv->Assign(4, val_mgr->GetCount(${ncm.sequence}));
rv->Assign(5, val_mgr->GetCount(${ncm.status}));
rv->Assign(6, val_mgr->GetCount(${ncm.association_id}));
if ( ${ncm.c} > 0 )
rv->Assign(7, bytestring_to_val(${ncm.data}));
if ( ${ncm.has_control_mac} )
{
rv->Assign(8, val_mgr->GetCount(${ncm.mac.key_id}));
rv->Assign(9, bytestring_to_val(${ncm.mac.crypto_checksum}));
}
return rv;
%}
# This builds the mode7 msg record
function BuildNTPMode7Msg(m7: NTP_mode7_msg): BroVal
%{
RecordVal* rv = new RecordVal(BifType::Record::NTP::Mode7Message);
rv->Assign(0, val_mgr->GetCount(${m7.request_code}));
rv->Assign(1, val_mgr->GetBool(${m7.auth_bit}));
rv->Assign(2, val_mgr->GetCount(${m7.sequence}));
rv->Assign(3, val_mgr->GetCount(${m7.implementation}));
rv->Assign(4, val_mgr->GetCount(${m7.error_code}));
if ( ${m7.data_len} > 0 )
rv->Assign(5, bytestring_to_val(${m7.data}));
return rv;
%}
function proc_ntp_message(msg: NTP_PDU): bool
%{
connection()->bro_analyzer()->ProtocolConfirmation();
if ( ! ntp_message )
return false;
RecordVal* rv = new RecordVal(BifType::Record::NTP::Message);
rv->Assign(0, val_mgr->GetCount(${msg.version}));
rv->Assign(1, val_mgr->GetCount(${msg.mode}));
// The standard record
if ( ${msg.mode} > 0 && ${msg.mode} < 6 )
rv->Assign(2, BuildNTPStdMsg(${msg.std}));
else if ( ${msg.mode} == 6 )
rv->Assign(3, BuildNTPControlMsg(${msg.control}));
else if ( ${msg.mode} == 7 )
rv->Assign(4, BuildNTPMode7Msg(${msg.mode7}));
BifEvent::generate_ntp_message(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
is_orig(), rv);
return true;
%}
};
refine typeattr NTP_PDU += &let {
proc: bool = $context.flow.proc_ntp_message(this);
};