mirror of
https://github.com/zeek/zeek.git
synced 2025-10-07 09:08:20 +00:00
Moving protocol-specific BiFs out of bro.bif.
I hope I found them all ...
This commit is contained in:
parent
5dc630f722
commit
3959e254e2
22 changed files with 657 additions and 639 deletions
|
@ -562,7 +562,6 @@ void builtin_error(const char* msg, BroObj* arg)
|
||||||
|
|
||||||
void init_builtin_funcs()
|
void init_builtin_funcs()
|
||||||
{
|
{
|
||||||
ftp_port = internal_type("ftp_port")->AsRecordType();
|
|
||||||
bro_resources = internal_type("bro_resources")->AsRecordType();
|
bro_resources = internal_type("bro_resources")->AsRecordType();
|
||||||
net_stats = internal_type("NetStats")->AsRecordType();
|
net_stats = internal_type("NetStats")->AsRecordType();
|
||||||
matcher_stats = internal_type("matcher_stats")->AsRecordType();
|
matcher_stats = internal_type("matcher_stats")->AsRecordType();
|
||||||
|
|
|
@ -6,4 +6,5 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI
|
||||||
bro_plugin_begin(FTP)
|
bro_plugin_begin(FTP)
|
||||||
bro_plugin_cc(FTP.cc Plugin.cc)
|
bro_plugin_cc(FTP.cc Plugin.cc)
|
||||||
bro_plugin_bif(events.bif)
|
bro_plugin_bif(events.bif)
|
||||||
|
bro_plugin_bif(functions.bif)
|
||||||
bro_plugin_end()
|
bro_plugin_end()
|
||||||
|
|
|
@ -8,4 +8,5 @@ BRO_PLUGIN_BEGIN(FTP)
|
||||||
BRO_PLUGIN_ANALYZER("FTP", ftp::FTP_Analyzer);
|
BRO_PLUGIN_ANALYZER("FTP", ftp::FTP_Analyzer);
|
||||||
BRO_PLUGIN_SUPPORT_ANALYZER("FTP_ADAT");
|
BRO_PLUGIN_SUPPORT_ANALYZER("FTP_ADAT");
|
||||||
BRO_PLUGIN_BIF_FILE(events);
|
BRO_PLUGIN_BIF_FILE(events);
|
||||||
|
BRO_PLUGIN_BIF_FILE(functions);
|
||||||
BRO_PLUGIN_END
|
BRO_PLUGIN_END
|
||||||
|
|
220
src/analyzer/protocols/ftp/functions.bif
Normal file
220
src/analyzer/protocols/ftp/functions.bif
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
|
||||||
|
type ftp_port: record;
|
||||||
|
|
||||||
|
%%{
|
||||||
|
|
||||||
|
static Val* parse_port(const char* line)
|
||||||
|
{
|
||||||
|
RecordVal* r = new RecordVal(BifType::Record::ftp_port);
|
||||||
|
|
||||||
|
int bytes[6];
|
||||||
|
if ( line && sscanf(line, "%d,%d,%d,%d,%d,%d",
|
||||||
|
&bytes[0], &bytes[1], &bytes[2],
|
||||||
|
&bytes[3], &bytes[4], &bytes[5]) == 6 )
|
||||||
|
{
|
||||||
|
int good = 1;
|
||||||
|
|
||||||
|
for ( int i = 0; i < 6; ++i )
|
||||||
|
if ( bytes[i] < 0 || bytes[i] > 255 )
|
||||||
|
{
|
||||||
|
good = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 addr = (bytes[0] << 24) | (bytes[1] << 16) |
|
||||||
|
(bytes[2] << 8) | bytes[3];
|
||||||
|
uint32 port = (bytes[4] << 8) | bytes[5];
|
||||||
|
|
||||||
|
// Since port is unsigned, no need to check for < 0.
|
||||||
|
if ( port > 65535 )
|
||||||
|
{
|
||||||
|
port = 0;
|
||||||
|
good = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->Assign(0, new AddrVal(htonl(addr)));
|
||||||
|
r->Assign(1, new PortVal(port, TRANSPORT_TCP));
|
||||||
|
r->Assign(2, new Val(good, TYPE_BOOL));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r->Assign(0, new AddrVal(uint32(0)));
|
||||||
|
r->Assign(1, new PortVal(0, TRANSPORT_TCP));
|
||||||
|
r->Assign(2, new Val(0, TYPE_BOOL));
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Val* parse_eftp(const char* line)
|
||||||
|
{
|
||||||
|
RecordVal* r = new RecordVal(BifType::Record::ftp_port);
|
||||||
|
|
||||||
|
int net_proto = 0; // currently not used
|
||||||
|
IPAddr addr; // unspecified IPv6 address (all 128 bits zero)
|
||||||
|
int port = 0;
|
||||||
|
int good = 0;
|
||||||
|
|
||||||
|
if ( line )
|
||||||
|
{
|
||||||
|
while ( isspace(*line) ) // skip whitespace
|
||||||
|
++line;
|
||||||
|
|
||||||
|
char delimiter = *line;
|
||||||
|
char* next_delim;
|
||||||
|
|
||||||
|
if ( *line )
|
||||||
|
{
|
||||||
|
good = 1;
|
||||||
|
++line; // skip delimiter
|
||||||
|
|
||||||
|
net_proto = strtol(line, &next_delim, 10);
|
||||||
|
if ( *next_delim != delimiter )
|
||||||
|
good = 0;
|
||||||
|
|
||||||
|
line = next_delim;
|
||||||
|
if ( *line )
|
||||||
|
++line;
|
||||||
|
|
||||||
|
if ( *line && *line != delimiter )
|
||||||
|
{
|
||||||
|
const char* nptr = strchr(line, delimiter);
|
||||||
|
if ( nptr == NULL )
|
||||||
|
{
|
||||||
|
nptr = line + strlen(line);
|
||||||
|
good = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
string s(line, nptr-line); // extract IP address
|
||||||
|
IPAddr tmp(s);
|
||||||
|
// on error, "tmp" will have all 128 bits zero
|
||||||
|
if ( tmp == addr )
|
||||||
|
good = 0;
|
||||||
|
|
||||||
|
addr = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = strchr(line, delimiter);
|
||||||
|
|
||||||
|
if ( line != NULL )
|
||||||
|
{
|
||||||
|
++line; // now the port
|
||||||
|
port = strtol(line, &next_delim, 10);
|
||||||
|
if ( *next_delim != delimiter )
|
||||||
|
good = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
r->Assign(0, new AddrVal(addr));
|
||||||
|
r->Assign(1, new PortVal(port, TRANSPORT_TCP));
|
||||||
|
r->Assign(2, new Val(good, TYPE_BOOL));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
%%}
|
||||||
|
|
||||||
|
## Converts a string representation of the FTP PORT command to an ``ftp_port``.
|
||||||
|
##
|
||||||
|
## s: The string of the FTP PORT command, e.g., ``"10,0,0,1,4,31"``.
|
||||||
|
##
|
||||||
|
## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
|
||||||
|
##
|
||||||
|
## .. bro:see:: parse_eftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port
|
||||||
|
function parse_ftp_port%(s: string%): ftp_port
|
||||||
|
%{
|
||||||
|
return parse_port(s->CheckString());
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Converts a string representation of the FTP EPRT command to an ``ftp_port``.
|
||||||
|
## See `RFC 2428 <http://tools.ietf.org/html/rfc2428>`_.
|
||||||
|
## The format is ``EPRT<space><d><net-prt><d><net-addr><d><tcp-port><d>``,
|
||||||
|
## where ``<d>`` is a delimiter in the ASCII range 33-126 (usually ``|``).
|
||||||
|
##
|
||||||
|
## s: The string of the FTP EPRT command, e.g., ``"|1|10.0.0.1|1055|"``.
|
||||||
|
##
|
||||||
|
## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
|
||||||
|
##
|
||||||
|
## .. bro:see:: parse_ftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port
|
||||||
|
function parse_eftp_port%(s: string%): ftp_port
|
||||||
|
%{
|
||||||
|
return parse_eftp(s->CheckString());
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Converts the result of the FTP PASV command to an ``ftp_port``.
|
||||||
|
##
|
||||||
|
## str: The string containing the result of the FTP PASV command.
|
||||||
|
##
|
||||||
|
## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
|
||||||
|
##
|
||||||
|
## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_epsv fmt_ftp_port
|
||||||
|
function parse_ftp_pasv%(str: string%): ftp_port
|
||||||
|
%{
|
||||||
|
const char* s = str->CheckString();
|
||||||
|
const char* line = strchr(s, '(');
|
||||||
|
if ( line )
|
||||||
|
++line; // move past '('
|
||||||
|
else if ( (line = strstr(s, "PORT")) )
|
||||||
|
line += 5; // Skip over
|
||||||
|
else if ( (line = strchr(s, ',')) )
|
||||||
|
{ // Look for comma-separated list.
|
||||||
|
while ( --line >= s && isdigit(*line) )
|
||||||
|
; // Back up over preceding digits.
|
||||||
|
++line; // now points to first digit, or beginning of s
|
||||||
|
}
|
||||||
|
|
||||||
|
return parse_port(line);
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Converts the result of the FTP EPSV command to an ``ftp_port``.
|
||||||
|
## See `RFC 2428 <http://tools.ietf.org/html/rfc2428>`_.
|
||||||
|
## The format is ``<text> (<d><d><d><tcp-port><d>)``, where ``<d>`` is a
|
||||||
|
## delimiter in the ASCII range 33-126 (usually ``|``).
|
||||||
|
##
|
||||||
|
## str: The string containing the result of the FTP EPSV command.
|
||||||
|
##
|
||||||
|
## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
|
||||||
|
##
|
||||||
|
## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv fmt_ftp_port
|
||||||
|
function parse_ftp_epsv%(str: string%): ftp_port
|
||||||
|
%{
|
||||||
|
const char* s = str->CheckString();
|
||||||
|
const char* line = strchr(s, '(');
|
||||||
|
if ( line )
|
||||||
|
++line; // move past '('
|
||||||
|
return parse_eftp(line);
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Formats an IP address and TCP port as an FTP PORT command. For example,
|
||||||
|
## ``10.0.0.1`` and ``1055/tcp`` yields ``"10,0,0,1,4,31"``.
|
||||||
|
##
|
||||||
|
## a: The IP address.
|
||||||
|
##
|
||||||
|
## p: The TCP port.
|
||||||
|
##
|
||||||
|
## Returns: The FTP PORT string.
|
||||||
|
##
|
||||||
|
## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv parse_ftp_epsv
|
||||||
|
function fmt_ftp_port%(a: addr, p: port%): string
|
||||||
|
%{
|
||||||
|
const uint32* addr;
|
||||||
|
int len = a->AsAddr().GetBytes(&addr);
|
||||||
|
if ( len == 1 )
|
||||||
|
{
|
||||||
|
uint32 a = ntohl(addr[0]);
|
||||||
|
uint32 pn = p->Port();
|
||||||
|
return new StringVal(fmt("%d,%d,%d,%d,%d,%d",
|
||||||
|
a >> 24, (a >> 16) & 0xff,
|
||||||
|
(a >> 8) & 0xff, a & 0xff,
|
||||||
|
pn >> 8, pn & 0xff));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builtin_error("conversion of non-IPv4 address in fmt_ftp_port",
|
||||||
|
@ARG@[0]);
|
||||||
|
return new StringVal("");
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
|
@ -7,4 +7,5 @@ BRO_PLUGIN_BEGIN(HTTP)
|
||||||
BRO_PLUGIN_DESCRIPTION("HTTP Analyzer");
|
BRO_PLUGIN_DESCRIPTION("HTTP Analyzer");
|
||||||
BRO_PLUGIN_ANALYZER("HTTP", http::HTTP_Analyzer);
|
BRO_PLUGIN_ANALYZER("HTTP", http::HTTP_Analyzer);
|
||||||
BRO_PLUGIN_BIF_FILE(events);
|
BRO_PLUGIN_BIF_FILE(events);
|
||||||
|
BRO_PLUGIN_BIF_FILE(functions);
|
||||||
BRO_PLUGIN_END
|
BRO_PLUGIN_END
|
||||||
|
|
|
@ -6,4 +6,5 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI
|
||||||
bro_plugin_begin(Login)
|
bro_plugin_begin(Login)
|
||||||
bro_plugin_cc(Login.cc RSH.cc Telnet.cc Rlogin.cc NVT.cc Plugin.cc)
|
bro_plugin_cc(Login.cc RSH.cc Telnet.cc Rlogin.cc NVT.cc Plugin.cc)
|
||||||
bro_plugin_bif(events.bif)
|
bro_plugin_bif(events.bif)
|
||||||
|
bro_plugin_bif(functions.bif)
|
||||||
bro_plugin_end()
|
bro_plugin_end()
|
||||||
|
|
|
@ -16,4 +16,5 @@ BRO_PLUGIN_BEGIN(Login)
|
||||||
BRO_PLUGIN_SUPPORT_ANALYZER("Contents_Rsh");
|
BRO_PLUGIN_SUPPORT_ANALYZER("Contents_Rsh");
|
||||||
BRO_PLUGIN_SUPPORT_ANALYZER("Contents_Rlogin");
|
BRO_PLUGIN_SUPPORT_ANALYZER("Contents_Rlogin");
|
||||||
BRO_PLUGIN_BIF_FILE(events);
|
BRO_PLUGIN_BIF_FILE(events);
|
||||||
|
BRO_PLUGIN_BIF_FILE(functions);
|
||||||
BRO_PLUGIN_END
|
BRO_PLUGIN_END
|
||||||
|
|
62
src/analyzer/protocols/login/functions.bif
Normal file
62
src/analyzer/protocols/login/functions.bif
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
|
||||||
|
%%{
|
||||||
|
#include "Login.h"
|
||||||
|
%%}
|
||||||
|
|
||||||
|
## Returns the state of the given login (Telnet or Rlogin) connection.
|
||||||
|
##
|
||||||
|
## cid: The connection ID.
|
||||||
|
##
|
||||||
|
## Returns: False if the connection is not active or is not tagged as a
|
||||||
|
## login analyzer. Otherwise the function returns the state, which can
|
||||||
|
## be one of:
|
||||||
|
##
|
||||||
|
## - ``LOGIN_STATE_AUTHENTICATE``: The connection is in its
|
||||||
|
## initial authentication dialog.
|
||||||
|
## - ``LOGIN_STATE_LOGGED_IN``: The analyzer believes the user has
|
||||||
|
## successfully authenticated.
|
||||||
|
## - ``LOGIN_STATE_SKIP``: The analyzer has skipped any further
|
||||||
|
## processing of the connection.
|
||||||
|
## - ``LOGIN_STATE_CONFUSED``: The analyzer has concluded that it
|
||||||
|
## does not correctly know the state of the connection, and/or
|
||||||
|
## the username associated with it.
|
||||||
|
##
|
||||||
|
## .. bro:see:: set_login_state
|
||||||
|
function get_login_state%(cid: conn_id%): count
|
||||||
|
%{
|
||||||
|
Connection* c = sessions->FindConnection(cid);
|
||||||
|
if ( ! c )
|
||||||
|
return new Val(0, TYPE_BOOL);
|
||||||
|
|
||||||
|
analyzer::Analyzer* la = c->FindAnalyzer("Login");
|
||||||
|
if ( ! la )
|
||||||
|
return new Val(0, TYPE_BOOL);
|
||||||
|
|
||||||
|
return new Val(int(static_cast<analyzer::login::Login_Analyzer*>(la)->LoginState()),
|
||||||
|
TYPE_COUNT);
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Sets the login state of a connection with a login analyzer.
|
||||||
|
##
|
||||||
|
## cid: The connection ID.
|
||||||
|
##
|
||||||
|
## new_state: The new state of the login analyzer. See
|
||||||
|
## :bro:id:`get_login_state` for possible values.
|
||||||
|
##
|
||||||
|
## Returns: Returns false if *cid* is not an active connection
|
||||||
|
## or is not tagged as a login analyzer, and true otherwise.
|
||||||
|
##
|
||||||
|
## .. bro:see:: get_login_state
|
||||||
|
function set_login_state%(cid: conn_id, new_state: count%): bool
|
||||||
|
%{
|
||||||
|
Connection* c = sessions->FindConnection(cid);
|
||||||
|
if ( ! c )
|
||||||
|
return new Val(0, TYPE_BOOL);
|
||||||
|
|
||||||
|
analyzer::Analyzer* la = c->FindAnalyzer("Login");
|
||||||
|
if ( ! la )
|
||||||
|
return new Val(0, TYPE_BOOL);
|
||||||
|
|
||||||
|
static_cast<analyzer::login::Login_Analyzer*>(la)->SetLoginState(analyzer::login::login_state(new_state));
|
||||||
|
return new Val(1, TYPE_BOOL);
|
||||||
|
%}
|
|
@ -6,4 +6,5 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI
|
||||||
bro_plugin_begin(NetbiosSSN)
|
bro_plugin_begin(NetbiosSSN)
|
||||||
bro_plugin_cc(NetbiosSSN.cc Plugin.cc)
|
bro_plugin_cc(NetbiosSSN.cc Plugin.cc)
|
||||||
bro_plugin_bif(events.bif)
|
bro_plugin_bif(events.bif)
|
||||||
|
bro_plugin_bif(functions.bif)
|
||||||
bro_plugin_end()
|
bro_plugin_end()
|
||||||
|
|
|
@ -8,4 +8,5 @@ BRO_PLUGIN_BEGIN(NetbiosSSN)
|
||||||
BRO_PLUGIN_ANALYZER("NetbiosSSN", netbios_ssn::NetbiosSSN_Analyzer);
|
BRO_PLUGIN_ANALYZER("NetbiosSSN", netbios_ssn::NetbiosSSN_Analyzer);
|
||||||
BRO_PLUGIN_SUPPORT_ANALYZER("Contents_NetbiosSSN");
|
BRO_PLUGIN_SUPPORT_ANALYZER("Contents_NetbiosSSN");
|
||||||
BRO_PLUGIN_BIF_FILE(events);
|
BRO_PLUGIN_BIF_FILE(events);
|
||||||
|
BRO_PLUGIN_BIF_FILE(functions);
|
||||||
BRO_PLUGIN_END
|
BRO_PLUGIN_END
|
||||||
|
|
50
src/analyzer/protocols/netbios-ssn/functions.bif
Normal file
50
src/analyzer/protocols/netbios-ssn/functions.bif
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
## Decode a NetBIOS name. See http://support.microsoft.com/kb/194203.
|
||||||
|
##
|
||||||
|
## name: The encoded NetBIOS name, e.g., ``"FEEIEFCAEOEFFEECEJEPFDCAEOEBENEF"``.
|
||||||
|
##
|
||||||
|
## Returns: The decoded NetBIOS name, e.g., ``"THE NETBIOS NAME"``.
|
||||||
|
##
|
||||||
|
## .. bro:see:: decode_netbios_name_type
|
||||||
|
function decode_netbios_name%(name: string%): string
|
||||||
|
%{
|
||||||
|
char buf[16];
|
||||||
|
char result[16];
|
||||||
|
const u_char* s = name->Bytes();
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for ( i = 0, j = 0; i < 16; ++i )
|
||||||
|
{
|
||||||
|
char c0 = (j < name->Len()) ? toupper(s[j++]) : 'A';
|
||||||
|
char c1 = (j < name->Len()) ? toupper(s[j++]) : 'A';
|
||||||
|
buf[i] = ((c0 - 'A') << 4) + (c1 - 'A');
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0; i < 15; ++i )
|
||||||
|
{
|
||||||
|
if ( isalnum(buf[i]) || ispunct(buf[i]) ||
|
||||||
|
// \x01\x02 is seen in at least one case as the first two bytes.
|
||||||
|
// I think that any \x01 and \x02 should always be passed through.
|
||||||
|
buf[i] < 3 )
|
||||||
|
result[i] = buf[i];
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StringVal(i, result);
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Converts a NetBIOS name type to its corresponding numeric value.
|
||||||
|
## See http://support.microsoft.com/kb/163409.
|
||||||
|
##
|
||||||
|
## name: The NetBIOS name type.
|
||||||
|
##
|
||||||
|
## Returns: The numeric value of *name*.
|
||||||
|
##
|
||||||
|
## .. bro:see:: decode_netbios_name
|
||||||
|
function decode_netbios_name_type%(name: string%): count
|
||||||
|
%{
|
||||||
|
const u_char* s = name->Bytes();
|
||||||
|
char return_val = ((toupper(s[30]) - 'A') << 4) + (toupper(s[31]) - 'A');
|
||||||
|
return new Val(return_val, TYPE_COUNT);
|
||||||
|
%}
|
|
@ -6,4 +6,5 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI
|
||||||
bro_plugin_begin(SMTP)
|
bro_plugin_begin(SMTP)
|
||||||
bro_plugin_cc(SMTP.cc Plugin.cc)
|
bro_plugin_cc(SMTP.cc Plugin.cc)
|
||||||
bro_plugin_bif(events.bif)
|
bro_plugin_bif(events.bif)
|
||||||
|
bro_plugin_bif(functions.bif)
|
||||||
bro_plugin_end()
|
bro_plugin_end()
|
||||||
|
|
|
@ -7,4 +7,5 @@ BRO_PLUGIN_BEGIN(SMTP)
|
||||||
BRO_PLUGIN_DESCRIPTION("SMTP Analyzer");
|
BRO_PLUGIN_DESCRIPTION("SMTP Analyzer");
|
||||||
BRO_PLUGIN_ANALYZER("SMTP", smtp::SMTP_Analyzer);
|
BRO_PLUGIN_ANALYZER("SMTP", smtp::SMTP_Analyzer);
|
||||||
BRO_PLUGIN_BIF_FILE(events);
|
BRO_PLUGIN_BIF_FILE(events);
|
||||||
|
BRO_PLUGIN_BIF_FILE(functions);
|
||||||
BRO_PLUGIN_END
|
BRO_PLUGIN_END
|
||||||
|
|
17
src/analyzer/protocols/smtp/functions.bif
Normal file
17
src/analyzer/protocols/smtp/functions.bif
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
%%{
|
||||||
|
#include "analyzer/protocols/smtp/SMTP.h"
|
||||||
|
%%}
|
||||||
|
|
||||||
|
## Skips SMTP data until the next email in a connection.
|
||||||
|
##
|
||||||
|
## c: The SMTP connection.
|
||||||
|
##
|
||||||
|
## .. bro:see:: skip_http_entity_data
|
||||||
|
function skip_smtp_data%(c: connection%): any
|
||||||
|
%{
|
||||||
|
analyzer::Analyzer* sa = c->FindAnalyzer("SMTP");
|
||||||
|
if ( sa )
|
||||||
|
static_cast<analyzer::smtp::SMTP_Analyzer*>(sa)->SkipData();
|
||||||
|
return 0;
|
||||||
|
%}
|
|
@ -35,7 +35,7 @@ refine connection SOCKS_Conn += {
|
||||||
new PortVal(${request.port} | TCP_PORT_MASK),
|
new PortVal(${request.port} | TCP_PORT_MASK),
|
||||||
array_to_string(${request.user}));
|
array_to_string(${request.user}));
|
||||||
|
|
||||||
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(true);
|
static_cast<analyzer::socks::SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
@ -53,7 +53,7 @@ refine connection SOCKS_Conn += {
|
||||||
new PortVal(${reply.port} | TCP_PORT_MASK));
|
new PortVal(${reply.port} | TCP_PORT_MASK));
|
||||||
|
|
||||||
bro_analyzer()->ProtocolConfirmation();
|
bro_analyzer()->ProtocolConfirmation();
|
||||||
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(false);
|
static_cast<analyzer::socks::SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(false);
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ refine connection SOCKS_Conn += {
|
||||||
new PortVal(${request.port} | TCP_PORT_MASK),
|
new PortVal(${request.port} | TCP_PORT_MASK),
|
||||||
new StringVal(""));
|
new StringVal(""));
|
||||||
|
|
||||||
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(true);
|
static_cast<analyzer::socks::SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
@ -136,7 +136,7 @@ refine connection SOCKS_Conn += {
|
||||||
new PortVal(${reply.port} | TCP_PORT_MASK));
|
new PortVal(${reply.port} | TCP_PORT_MASK));
|
||||||
|
|
||||||
bro_analyzer()->ProtocolConfirmation();
|
bro_analyzer()->ProtocolConfirmation();
|
||||||
static_cast<SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(false);
|
static_cast<analyzer::socks::SOCKS_Analyzer*>(bro_analyzer())->EndpointDone(false);
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
@ -6,5 +6,6 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI
|
||||||
bro_plugin_begin(SSL)
|
bro_plugin_begin(SSL)
|
||||||
bro_plugin_cc(SSL.cc Plugin.cc)
|
bro_plugin_cc(SSL.cc Plugin.cc)
|
||||||
bro_plugin_bif(events.bif)
|
bro_plugin_bif(events.bif)
|
||||||
|
bro_plugin_bif(functions.bif)
|
||||||
bro_plugin_pac(ssl.pac ssl-analyzer.pac ssl-protocol.pac ssl-defs.pac)
|
bro_plugin_pac(ssl.pac ssl-analyzer.pac ssl-protocol.pac ssl-defs.pac)
|
||||||
bro_plugin_end()
|
bro_plugin_end()
|
||||||
|
|
|
@ -7,4 +7,5 @@ BRO_PLUGIN_BEGIN(SSL)
|
||||||
BRO_PLUGIN_DESCRIPTION("SSL Analyzer");
|
BRO_PLUGIN_DESCRIPTION("SSL Analyzer");
|
||||||
BRO_PLUGIN_ANALYZER("SSL", ssl::SSL_Analyzer);
|
BRO_PLUGIN_ANALYZER("SSL", ssl::SSL_Analyzer);
|
||||||
BRO_PLUGIN_BIF_FILE(events);
|
BRO_PLUGIN_BIF_FILE(events);
|
||||||
|
BRO_PLUGIN_BIF_FILE(functions);
|
||||||
BRO_PLUGIN_END
|
BRO_PLUGIN_END
|
||||||
|
|
132
src/analyzer/protocols/ssl/functions.bif
Normal file
132
src/analyzer/protocols/ssl/functions.bif
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
|
||||||
|
%%{
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/asn1.h>
|
||||||
|
#include <openssl/x509_vfy.h>
|
||||||
|
|
||||||
|
// This is the indexed map of X509 certificate stores.
|
||||||
|
static map<Val*, X509_STORE*> x509_stores;
|
||||||
|
|
||||||
|
// ### NOTE: while d2i_X509 does not take a const u_char** pointer,
|
||||||
|
// here we assume d2i_X509 does not write to <data>, so it is safe to
|
||||||
|
// convert data to a non-const pointer. Could some X509 guru verify
|
||||||
|
// this?
|
||||||
|
|
||||||
|
X509* d2i_X509_(X509** px, const u_char** in, int len)
|
||||||
|
{
|
||||||
|
#ifdef OPENSSL_D2I_X509_USES_CONST_CHAR
|
||||||
|
return d2i_X509(px, in, len);
|
||||||
|
#else
|
||||||
|
return d2i_X509(px, (u_char**)in, len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
%%}
|
||||||
|
|
||||||
|
|
||||||
|
## Verifies a certificate.
|
||||||
|
##
|
||||||
|
## der_cert: The X.509 certificate in DER format.
|
||||||
|
##
|
||||||
|
## cert_stack: Specifies a certificate chain to validate against, with index 0
|
||||||
|
## typically being the root CA. Bro uses the Mozilla root CA list
|
||||||
|
## by default.
|
||||||
|
##
|
||||||
|
## root_certs: A list of additional root certificates that extends
|
||||||
|
## *cert_stack*.
|
||||||
|
##
|
||||||
|
## Returns: A status code of the verification which can be converted into an
|
||||||
|
## ASCII string via :bro:id:`x509_err2str`.
|
||||||
|
##
|
||||||
|
## .. bro:see:: x509_err2str
|
||||||
|
function x509_verify%(der_cert: string, cert_stack: string_vec, root_certs: table_string_of_string%): count
|
||||||
|
%{
|
||||||
|
X509_STORE* ctx = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
// If this certificate store was built previously, just reuse the old one.
|
||||||
|
if ( x509_stores.count(root_certs) > 0 )
|
||||||
|
ctx = x509_stores[root_certs];
|
||||||
|
|
||||||
|
if ( ! ctx ) // lookup to see if we have this one built already!
|
||||||
|
{
|
||||||
|
ctx = X509_STORE_new();
|
||||||
|
TableVal* root_certs2 = root_certs->AsTableVal();
|
||||||
|
ListVal* idxs = root_certs2->ConvertToPureList();
|
||||||
|
|
||||||
|
// Build the validation store
|
||||||
|
for ( i = 0; i < idxs->Length(); ++i )
|
||||||
|
{
|
||||||
|
Val* key = idxs->Index(i);
|
||||||
|
StringVal *sv = root_certs2->Lookup(key)->AsStringVal();
|
||||||
|
const uint8* data = sv->Bytes();
|
||||||
|
X509* x = d2i_X509_(NULL, &data, sv->Len());
|
||||||
|
if ( ! x )
|
||||||
|
{
|
||||||
|
builtin_error(fmt("Root CA error: %s", ERR_error_string(ERR_peek_last_error(),NULL)));
|
||||||
|
return new Val((uint64) ERR_get_error(), TYPE_COUNT);
|
||||||
|
}
|
||||||
|
X509_STORE_add_cert(ctx, x);
|
||||||
|
}
|
||||||
|
delete idxs;
|
||||||
|
|
||||||
|
// Save the newly constructed certificate store into the cacheing map.
|
||||||
|
x509_stores[root_certs] = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8 *cert_data = der_cert->Bytes();
|
||||||
|
X509* cert = d2i_X509_(NULL, &cert_data, der_cert->Len());
|
||||||
|
if ( ! cert )
|
||||||
|
{
|
||||||
|
builtin_error(fmt("Certificate error: %s", ERR_error_string(ERR_peek_last_error(),NULL)));
|
||||||
|
return new Val((uint64) ERR_get_error(), TYPE_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
STACK_OF(X509)* untrusted_certs = sk_X509_new_null();
|
||||||
|
if ( ! untrusted_certs )
|
||||||
|
{
|
||||||
|
builtin_error(fmt("Untrusted certificate stack initialization error: %s", ERR_error_string(ERR_peek_last_error(),NULL)));
|
||||||
|
return new Val((uint64) ERR_get_error(), TYPE_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorVal *cert_stack_vec = cert_stack->AsVectorVal();
|
||||||
|
for ( i = 0; i < (int) cert_stack_vec->Size(); ++i )
|
||||||
|
{
|
||||||
|
StringVal *sv = cert_stack_vec->Lookup(i)->AsStringVal();
|
||||||
|
const uint8 *data = sv->Bytes();
|
||||||
|
X509* x = d2i_X509_(NULL, &data, sv->Len());
|
||||||
|
if ( ! x )
|
||||||
|
{
|
||||||
|
X509_free(cert);
|
||||||
|
sk_X509_pop_free(untrusted_certs, X509_free);
|
||||||
|
builtin_error(fmt("Untrusted certificate stack creation error: %s", ERR_error_string(ERR_peek_last_error(),NULL)));
|
||||||
|
return new Val((uint64) ERR_get_error(), TYPE_COUNT);
|
||||||
|
}
|
||||||
|
sk_X509_push(untrusted_certs, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_STORE_CTX csc;
|
||||||
|
X509_STORE_CTX_init(&csc, ctx, cert, untrusted_certs);
|
||||||
|
X509_STORE_CTX_set_time(&csc, 0, (time_t) network_time);
|
||||||
|
|
||||||
|
int result = X509_verify_cert(&csc);
|
||||||
|
X509_STORE_CTX_cleanup(&csc);
|
||||||
|
|
||||||
|
if ( untrusted_certs )
|
||||||
|
sk_X509_pop_free(untrusted_certs, X509_free);
|
||||||
|
X509_free(cert);
|
||||||
|
|
||||||
|
return new Val((uint64) csc.error, TYPE_COUNT);
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Converts a certificate verification error code into an ASCII string.
|
||||||
|
##
|
||||||
|
## err_num: The error code.
|
||||||
|
##
|
||||||
|
## Returns: A string representation of *err_num*.
|
||||||
|
##
|
||||||
|
## .. bro:see:: x509_verify
|
||||||
|
function x509_err2str%(err_num: count%): string
|
||||||
|
%{
|
||||||
|
return new StringVal(X509_verify_cert_error_string(err_num));
|
||||||
|
%}
|
|
@ -6,4 +6,5 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI
|
||||||
bro_plugin_begin(TCP)
|
bro_plugin_begin(TCP)
|
||||||
bro_plugin_cc(TCP.cc TCP_Endpoint.cc TCP_Reassembler.cc ContentLine.cc Stats.cc Plugin.cc)
|
bro_plugin_cc(TCP.cc TCP_Endpoint.cc TCP_Reassembler.cc ContentLine.cc Stats.cc Plugin.cc)
|
||||||
bro_plugin_bif(events.bif)
|
bro_plugin_bif(events.bif)
|
||||||
|
bro_plugin_bif(functions.bif)
|
||||||
bro_plugin_end()
|
bro_plugin_end()
|
||||||
|
|
|
@ -10,4 +10,5 @@ BRO_PLUGIN_BEGIN(TCP)
|
||||||
BRO_PLUGIN_SUPPORT_ANALYZER("ContentLine");
|
BRO_PLUGIN_SUPPORT_ANALYZER("ContentLine");
|
||||||
BRO_PLUGIN_SUPPORT_ANALYZER("Contents");
|
BRO_PLUGIN_SUPPORT_ANALYZER("Contents");
|
||||||
BRO_PLUGIN_BIF_FILE(events);
|
BRO_PLUGIN_BIF_FILE(events);
|
||||||
|
BRO_PLUGIN_BIF_FILE(functions);
|
||||||
BRO_PLUGIN_END
|
BRO_PLUGIN_END
|
||||||
|
|
159
src/analyzer/protocols/tcp/functions.bif
Normal file
159
src/analyzer/protocols/tcp/functions.bif
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
|
||||||
|
%%{
|
||||||
|
#include "analyzer/protocols/tcp/TCP.h"
|
||||||
|
%%}
|
||||||
|
|
||||||
|
## Get the originator sequence number of a TCP connection. Sequence numbers
|
||||||
|
## are absolute (i.e., they reflect the values seen directly in packet headers;
|
||||||
|
## they are not relative to the beginning of the connection).
|
||||||
|
##
|
||||||
|
## cid: The connection ID.
|
||||||
|
##
|
||||||
|
## Returns: The highest sequence number sent by a connection's originator, or 0
|
||||||
|
## if *cid* does not point to an active TCP connection.
|
||||||
|
##
|
||||||
|
## .. bro:see:: get_resp_seq
|
||||||
|
function get_orig_seq%(cid: conn_id%): count
|
||||||
|
%{
|
||||||
|
Connection* c = sessions->FindConnection(cid);
|
||||||
|
if ( ! c )
|
||||||
|
return new Val(0, TYPE_COUNT);
|
||||||
|
|
||||||
|
if ( c->ConnTransport() != TRANSPORT_TCP )
|
||||||
|
return new Val(0, TYPE_COUNT);
|
||||||
|
|
||||||
|
analyzer::Analyzer* tc = c->FindAnalyzer("TCP");
|
||||||
|
if ( tc )
|
||||||
|
return new Val(static_cast<analyzer::tcp::TCP_Analyzer*>(tc)->OrigSeq(),
|
||||||
|
TYPE_COUNT);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reporter->Error("connection does not have TCP analyzer");
|
||||||
|
return new Val(0, TYPE_COUNT);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Get the responder sequence number of a TCP connection. Sequence numbers
|
||||||
|
## are absolute (i.e., they reflect the values seen directly in packet headers;
|
||||||
|
## they are not relative to the beginning of the connection).
|
||||||
|
##
|
||||||
|
## cid: The connection ID.
|
||||||
|
##
|
||||||
|
## Returns: The highest sequence number sent by a connection's responder, or 0
|
||||||
|
## if *cid* does not point to an active TCP connection.
|
||||||
|
##
|
||||||
|
## .. bro:see:: get_orig_seq
|
||||||
|
function get_resp_seq%(cid: conn_id%): count
|
||||||
|
%{
|
||||||
|
Connection* c = sessions->FindConnection(cid);
|
||||||
|
if ( ! c )
|
||||||
|
return new Val(0, TYPE_COUNT);
|
||||||
|
|
||||||
|
if ( c->ConnTransport() != TRANSPORT_TCP )
|
||||||
|
return new Val(0, TYPE_COUNT);
|
||||||
|
|
||||||
|
analyzer::Analyzer* tc = c->FindAnalyzer("TCP");
|
||||||
|
if ( tc )
|
||||||
|
return new Val(static_cast<analyzer::tcp::TCP_Analyzer*>(tc)->RespSeq(),
|
||||||
|
TYPE_COUNT);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reporter->Error("connection does not have TCP analyzer");
|
||||||
|
return new Val(0, TYPE_COUNT);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Returns statistics about TCP gaps.
|
||||||
|
##
|
||||||
|
## Returns: A record with TCP gap statistics.
|
||||||
|
##
|
||||||
|
## .. bro:see:: do_profiling
|
||||||
|
## net_stats
|
||||||
|
## resource_usage
|
||||||
|
## dump_rule_stats
|
||||||
|
## get_matcher_stats
|
||||||
|
function get_gap_summary%(%): gap_info
|
||||||
|
%{
|
||||||
|
RecordVal* r = new RecordVal(gap_info);
|
||||||
|
r->Assign(0, new Val(tot_ack_events, TYPE_COUNT));
|
||||||
|
r->Assign(1, new Val(tot_ack_bytes, TYPE_COUNT));
|
||||||
|
r->Assign(2, new Val(tot_gap_events, TYPE_COUNT));
|
||||||
|
r->Assign(3, new Val(tot_gap_bytes, TYPE_COUNT));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Associates a file handle with a connection for writing TCP byte stream
|
||||||
|
## contents.
|
||||||
|
##
|
||||||
|
## cid: The connection ID.
|
||||||
|
##
|
||||||
|
## direction: Controls what sides of the connection to record. The argument can
|
||||||
|
## take one of the four values:
|
||||||
|
##
|
||||||
|
## - ``CONTENTS_NONE``: Stop recording the connection's content.
|
||||||
|
## - ``CONTENTS_ORIG``: Record the data sent by the connection
|
||||||
|
## originator (often the client).
|
||||||
|
## - ``CONTENTS_RESP``: Record the data sent by the connection
|
||||||
|
## responder (often the server).
|
||||||
|
## - ``CONTENTS_BOTH``: Record the data sent in both directions.
|
||||||
|
## Results in the two directions being
|
||||||
|
## intermixed in the file, in the order the
|
||||||
|
## data was seen by Bro.
|
||||||
|
##
|
||||||
|
## f: The file handle of the file to write the contents to.
|
||||||
|
##
|
||||||
|
## Returns: Returns false if *cid* does not point to an active connection, and
|
||||||
|
## true otherwise.
|
||||||
|
##
|
||||||
|
## .. note::
|
||||||
|
##
|
||||||
|
## The data recorded to the file reflects the byte stream, not the
|
||||||
|
## contents of individual packets. Reordering and duplicates are
|
||||||
|
## removed. If any data is missing, the recording stops at the
|
||||||
|
## missing data; this can happen, e.g., due to an
|
||||||
|
## :bro:id:`ack_above_hole` event.
|
||||||
|
##
|
||||||
|
## .. bro:see:: get_contents_file set_record_packets
|
||||||
|
function set_contents_file%(cid: conn_id, direction: count, f: file%): bool
|
||||||
|
%{
|
||||||
|
Connection* c = sessions->FindConnection(cid);
|
||||||
|
if ( ! c )
|
||||||
|
return new Val(0, TYPE_BOOL);
|
||||||
|
|
||||||
|
c->GetRootAnalyzer()->SetContentsFile(direction, f);
|
||||||
|
return new Val(1, TYPE_BOOL);
|
||||||
|
%}
|
||||||
|
|
||||||
|
## Returns the file handle of the contents file of a connection.
|
||||||
|
##
|
||||||
|
## cid: The connection ID.
|
||||||
|
##
|
||||||
|
## direction: Controls what sides of the connection to record. See
|
||||||
|
## :bro:id:`set_contents_file` for possible values.
|
||||||
|
##
|
||||||
|
## Returns: The :bro:type:`file` handle for the contents file of the
|
||||||
|
## connection identified by *cid*. If the connection exists
|
||||||
|
## but there is no contents file for *direction*, then the function
|
||||||
|
## generates an error and returns a file handle to ``stderr``.
|
||||||
|
##
|
||||||
|
## .. bro:see:: set_contents_file set_record_packets
|
||||||
|
function get_contents_file%(cid: conn_id, direction: count%): file
|
||||||
|
%{
|
||||||
|
Connection* c = sessions->FindConnection(cid);
|
||||||
|
BroFile* f = c ? c->GetRootAnalyzer()->GetContentsFile(direction) : 0;
|
||||||
|
|
||||||
|
if ( f )
|
||||||
|
{
|
||||||
|
Ref(f);
|
||||||
|
return new Val(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return some sort of error value.
|
||||||
|
if ( ! c )
|
||||||
|
builtin_error("unknown connection id in get_contents_file()", cid);
|
||||||
|
else
|
||||||
|
builtin_error("no contents file for given direction");
|
||||||
|
|
||||||
|
return new Val(new BroFile(stderr, "-", "w"));
|
||||||
|
%}
|
634
src/bro.bif
634
src/bro.bif
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
RecordType* ftp_port;
|
|
||||||
RecordType* net_stats;
|
RecordType* net_stats;
|
||||||
RecordType* bro_resources;
|
RecordType* bro_resources;
|
||||||
RecordType* matcher_stats;
|
RecordType* matcher_stats;
|
||||||
|
@ -1786,26 +1785,6 @@ function get_matcher_stats%(%): matcher_stats
|
||||||
return r;
|
return r;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
## Returns statistics about TCP gaps.
|
|
||||||
##
|
|
||||||
## Returns: A record with TCP gap statistics.
|
|
||||||
##
|
|
||||||
## .. bro:see:: do_profiling
|
|
||||||
## net_stats
|
|
||||||
## resource_usage
|
|
||||||
## dump_rule_stats
|
|
||||||
## get_matcher_stats
|
|
||||||
function get_gap_summary%(%): gap_info
|
|
||||||
%{
|
|
||||||
RecordVal* r = new RecordVal(gap_info);
|
|
||||||
r->Assign(0, new Val(tot_ack_events, TYPE_COUNT));
|
|
||||||
r->Assign(1, new Val(tot_ack_bytes, TYPE_COUNT));
|
|
||||||
r->Assign(2, new Val(tot_gap_events, TYPE_COUNT));
|
|
||||||
r->Assign(3, new Val(tot_gap_bytes, TYPE_COUNT));
|
|
||||||
|
|
||||||
return r;
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Generates a table of the size of all global variables. The table index is
|
## Generates a table of the size of all global variables. The table index is
|
||||||
## the variable name and the value is the variable size in bytes.
|
## the variable name and the value is the variable size in bytes.
|
||||||
##
|
##
|
||||||
|
@ -2541,273 +2520,6 @@ function addr_to_ptr_name%(a: addr%): string
|
||||||
return new StringVal(a->AsAddr().PtrName().c_str());
|
return new StringVal(a->AsAddr().PtrName().c_str());
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
||||||
%%{
|
|
||||||
static Val* parse_port(const char* line)
|
|
||||||
{
|
|
||||||
RecordVal* r = new RecordVal(ftp_port);
|
|
||||||
|
|
||||||
int bytes[6];
|
|
||||||
if ( line && sscanf(line, "%d,%d,%d,%d,%d,%d",
|
|
||||||
&bytes[0], &bytes[1], &bytes[2],
|
|
||||||
&bytes[3], &bytes[4], &bytes[5]) == 6 )
|
|
||||||
{
|
|
||||||
int good = 1;
|
|
||||||
|
|
||||||
for ( int i = 0; i < 6; ++i )
|
|
||||||
if ( bytes[i] < 0 || bytes[i] > 255 )
|
|
||||||
{
|
|
||||||
good = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 addr = (bytes[0] << 24) | (bytes[1] << 16) |
|
|
||||||
(bytes[2] << 8) | bytes[3];
|
|
||||||
uint32 port = (bytes[4] << 8) | bytes[5];
|
|
||||||
|
|
||||||
// Since port is unsigned, no need to check for < 0.
|
|
||||||
if ( port > 65535 )
|
|
||||||
{
|
|
||||||
port = 0;
|
|
||||||
good = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r->Assign(0, new AddrVal(htonl(addr)));
|
|
||||||
r->Assign(1, new PortVal(port, TRANSPORT_TCP));
|
|
||||||
r->Assign(2, new Val(good, TYPE_BOOL));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
r->Assign(0, new AddrVal(uint32(0)));
|
|
||||||
r->Assign(1, new PortVal(0, TRANSPORT_TCP));
|
|
||||||
r->Assign(2, new Val(0, TYPE_BOOL));
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Val* parse_eftp(const char* line)
|
|
||||||
{
|
|
||||||
RecordVal* r = new RecordVal(ftp_port);
|
|
||||||
|
|
||||||
int net_proto = 0; // currently not used
|
|
||||||
IPAddr addr; // unspecified IPv6 address (all 128 bits zero)
|
|
||||||
int port = 0;
|
|
||||||
int good = 0;
|
|
||||||
|
|
||||||
if ( line )
|
|
||||||
{
|
|
||||||
while ( isspace(*line) ) // skip whitespace
|
|
||||||
++line;
|
|
||||||
|
|
||||||
char delimiter = *line;
|
|
||||||
char* next_delim;
|
|
||||||
|
|
||||||
if ( *line )
|
|
||||||
{
|
|
||||||
good = 1;
|
|
||||||
++line; // skip delimiter
|
|
||||||
|
|
||||||
net_proto = strtol(line, &next_delim, 10);
|
|
||||||
if ( *next_delim != delimiter )
|
|
||||||
good = 0;
|
|
||||||
|
|
||||||
line = next_delim;
|
|
||||||
if ( *line )
|
|
||||||
++line;
|
|
||||||
|
|
||||||
if ( *line && *line != delimiter )
|
|
||||||
{
|
|
||||||
const char* nptr = strchr(line, delimiter);
|
|
||||||
if ( nptr == NULL )
|
|
||||||
{
|
|
||||||
nptr = line + strlen(line);
|
|
||||||
good = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
string s(line, nptr-line); // extract IP address
|
|
||||||
IPAddr tmp(s);
|
|
||||||
// on error, "tmp" will have all 128 bits zero
|
|
||||||
if ( tmp == addr )
|
|
||||||
good = 0;
|
|
||||||
|
|
||||||
addr = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
line = strchr(line, delimiter);
|
|
||||||
|
|
||||||
if ( line != NULL )
|
|
||||||
{
|
|
||||||
++line; // now the port
|
|
||||||
port = strtol(line, &next_delim, 10);
|
|
||||||
if ( *next_delim != delimiter )
|
|
||||||
good = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
r->Assign(0, new AddrVal(addr));
|
|
||||||
r->Assign(1, new PortVal(port, TRANSPORT_TCP));
|
|
||||||
r->Assign(2, new Val(good, TYPE_BOOL));
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
%%}
|
|
||||||
|
|
||||||
## Converts a string representation of the FTP PORT command to an ``ftp_port``.
|
|
||||||
##
|
|
||||||
## s: The string of the FTP PORT command, e.g., ``"10,0,0,1,4,31"``.
|
|
||||||
##
|
|
||||||
## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
|
|
||||||
##
|
|
||||||
## .. bro:see:: parse_eftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port
|
|
||||||
function parse_ftp_port%(s: string%): ftp_port
|
|
||||||
%{
|
|
||||||
return parse_port(s->CheckString());
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Converts a string representation of the FTP EPRT command to an ``ftp_port``.
|
|
||||||
## See `RFC 2428 <http://tools.ietf.org/html/rfc2428>`_.
|
|
||||||
## The format is ``EPRT<space><d><net-prt><d><net-addr><d><tcp-port><d>``,
|
|
||||||
## where ``<d>`` is a delimiter in the ASCII range 33-126 (usually ``|``).
|
|
||||||
##
|
|
||||||
## s: The string of the FTP EPRT command, e.g., ``"|1|10.0.0.1|1055|"``.
|
|
||||||
##
|
|
||||||
## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
|
|
||||||
##
|
|
||||||
## .. bro:see:: parse_ftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port
|
|
||||||
function parse_eftp_port%(s: string%): ftp_port
|
|
||||||
%{
|
|
||||||
return parse_eftp(s->CheckString());
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Converts the result of the FTP PASV command to an ``ftp_port``.
|
|
||||||
##
|
|
||||||
## str: The string containing the result of the FTP PASV command.
|
|
||||||
##
|
|
||||||
## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
|
|
||||||
##
|
|
||||||
## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_epsv fmt_ftp_port
|
|
||||||
function parse_ftp_pasv%(str: string%): ftp_port
|
|
||||||
%{
|
|
||||||
const char* s = str->CheckString();
|
|
||||||
const char* line = strchr(s, '(');
|
|
||||||
if ( line )
|
|
||||||
++line; // move past '('
|
|
||||||
else if ( (line = strstr(s, "PORT")) )
|
|
||||||
line += 5; // Skip over
|
|
||||||
else if ( (line = strchr(s, ',')) )
|
|
||||||
{ // Look for comma-separated list.
|
|
||||||
while ( --line >= s && isdigit(*line) )
|
|
||||||
; // Back up over preceding digits.
|
|
||||||
++line; // now points to first digit, or beginning of s
|
|
||||||
}
|
|
||||||
|
|
||||||
return parse_port(line);
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Converts the result of the FTP EPSV command to an ``ftp_port``.
|
|
||||||
## See `RFC 2428 <http://tools.ietf.org/html/rfc2428>`_.
|
|
||||||
## The format is ``<text> (<d><d><d><tcp-port><d>)``, where ``<d>`` is a
|
|
||||||
## delimiter in the ASCII range 33-126 (usually ``|``).
|
|
||||||
##
|
|
||||||
## str: The string containing the result of the FTP EPSV command.
|
|
||||||
##
|
|
||||||
## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]``
|
|
||||||
##
|
|
||||||
## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv fmt_ftp_port
|
|
||||||
function parse_ftp_epsv%(str: string%): ftp_port
|
|
||||||
%{
|
|
||||||
const char* s = str->CheckString();
|
|
||||||
const char* line = strchr(s, '(');
|
|
||||||
if ( line )
|
|
||||||
++line; // move past '('
|
|
||||||
return parse_eftp(line);
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Formats an IP address and TCP port as an FTP PORT command. For example,
|
|
||||||
## ``10.0.0.1`` and ``1055/tcp`` yields ``"10,0,0,1,4,31"``.
|
|
||||||
##
|
|
||||||
## a: The IP address.
|
|
||||||
##
|
|
||||||
## p: The TCP port.
|
|
||||||
##
|
|
||||||
## Returns: The FTP PORT string.
|
|
||||||
##
|
|
||||||
## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv parse_ftp_epsv
|
|
||||||
function fmt_ftp_port%(a: addr, p: port%): string
|
|
||||||
%{
|
|
||||||
const uint32* addr;
|
|
||||||
int len = a->AsAddr().GetBytes(&addr);
|
|
||||||
if ( len == 1 )
|
|
||||||
{
|
|
||||||
uint32 a = ntohl(addr[0]);
|
|
||||||
uint32 pn = p->Port();
|
|
||||||
return new StringVal(fmt("%d,%d,%d,%d,%d,%d",
|
|
||||||
a >> 24, (a >> 16) & 0xff,
|
|
||||||
(a >> 8) & 0xff, a & 0xff,
|
|
||||||
pn >> 8, pn & 0xff));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
builtin_error("conversion of non-IPv4 address in fmt_ftp_port",
|
|
||||||
@ARG@[0]);
|
|
||||||
return new StringVal("");
|
|
||||||
}
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Decode a NetBIOS name. See http://support.microsoft.com/kb/194203.
|
|
||||||
##
|
|
||||||
## name: The encoded NetBIOS name, e.g., ``"FEEIEFCAEOEFFEECEJEPFDCAEOEBENEF"``.
|
|
||||||
##
|
|
||||||
## Returns: The decoded NetBIOS name, e.g., ``"THE NETBIOS NAME"``.
|
|
||||||
##
|
|
||||||
## .. bro:see:: decode_netbios_name_type
|
|
||||||
function decode_netbios_name%(name: string%): string
|
|
||||||
%{
|
|
||||||
char buf[16];
|
|
||||||
char result[16];
|
|
||||||
const u_char* s = name->Bytes();
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
for ( i = 0, j = 0; i < 16; ++i )
|
|
||||||
{
|
|
||||||
char c0 = (j < name->Len()) ? toupper(s[j++]) : 'A';
|
|
||||||
char c1 = (j < name->Len()) ? toupper(s[j++]) : 'A';
|
|
||||||
buf[i] = ((c0 - 'A') << 4) + (c1 - 'A');
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( i = 0; i < 15; ++i )
|
|
||||||
{
|
|
||||||
if ( isalnum(buf[i]) || ispunct(buf[i]) ||
|
|
||||||
// \x01\x02 is seen in at least one case as the first two bytes.
|
|
||||||
// I think that any \x01 and \x02 should always be passed through.
|
|
||||||
buf[i] < 3 )
|
|
||||||
result[i] = buf[i];
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new StringVal(i, result);
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Converts a NetBIOS name type to its corresponding numeric value.
|
|
||||||
## See http://support.microsoft.com/kb/163409.
|
|
||||||
##
|
|
||||||
## name: The NetBIOS name type.
|
|
||||||
##
|
|
||||||
## Returns: The numeric value of *name*.
|
|
||||||
##
|
|
||||||
## .. bro:see:: decode_netbios_name
|
|
||||||
function decode_netbios_name_type%(name: string%): count
|
|
||||||
%{
|
|
||||||
const u_char* s = name->Bytes();
|
|
||||||
char return_val = ((toupper(s[30]) - 'A') << 4) + (toupper(s[31]) - 'A');
|
|
||||||
return new Val(return_val, TYPE_COUNT);
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Converts a string of bytes into its hexadecimal representation.
|
## Converts a string of bytes into its hexadecimal representation.
|
||||||
## For example, ``"04"`` would be converted to ``"3034"``.
|
## For example, ``"04"`` would be converted to ``"3034"``.
|
||||||
##
|
##
|
||||||
|
@ -3789,138 +3501,6 @@ function lookup_asn%(a: addr%) : count
|
||||||
return new Val(0, TYPE_COUNT);
|
return new Val(0, TYPE_COUNT);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%%{
|
|
||||||
#include <openssl/x509.h>
|
|
||||||
#include <openssl/asn1.h>
|
|
||||||
#include <openssl/x509_vfy.h>
|
|
||||||
|
|
||||||
// This is the indexed map of X509 certificate stores.
|
|
||||||
static map<Val*, X509_STORE*> x509_stores;
|
|
||||||
|
|
||||||
// ### NOTE: while d2i_X509 does not take a const u_char** pointer,
|
|
||||||
// here we assume d2i_X509 does not write to <data>, so it is safe to
|
|
||||||
// convert data to a non-const pointer. Could some X509 guru verify
|
|
||||||
// this?
|
|
||||||
|
|
||||||
X509* d2i_X509_(X509** px, const u_char** in, int len)
|
|
||||||
{
|
|
||||||
#ifdef OPENSSL_D2I_X509_USES_CONST_CHAR
|
|
||||||
return d2i_X509(px, in, len);
|
|
||||||
#else
|
|
||||||
return d2i_X509(px, (u_char**)in, len);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
%%}
|
|
||||||
|
|
||||||
|
|
||||||
## Verifies a certificate.
|
|
||||||
##
|
|
||||||
## der_cert: The X.509 certificate in DER format.
|
|
||||||
##
|
|
||||||
## cert_stack: Specifies a certificate chain to validate against, with index 0
|
|
||||||
## typically being the root CA. Bro uses the Mozilla root CA list
|
|
||||||
## by default.
|
|
||||||
##
|
|
||||||
## root_certs: A list of additional root certificates that extends
|
|
||||||
## *cert_stack*.
|
|
||||||
##
|
|
||||||
## Returns: A status code of the verification which can be converted into an
|
|
||||||
## ASCII string via :bro:id:`x509_err2str`.
|
|
||||||
##
|
|
||||||
## .. bro:see:: x509_err2str
|
|
||||||
function x509_verify%(der_cert: string, cert_stack: string_vec, root_certs: table_string_of_string%): count
|
|
||||||
%{
|
|
||||||
X509_STORE* ctx = 0;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
// If this certificate store was built previously, just reuse the old one.
|
|
||||||
if ( x509_stores.count(root_certs) > 0 )
|
|
||||||
ctx = x509_stores[root_certs];
|
|
||||||
|
|
||||||
if ( ! ctx ) // lookup to see if we have this one built already!
|
|
||||||
{
|
|
||||||
ctx = X509_STORE_new();
|
|
||||||
TableVal* root_certs2 = root_certs->AsTableVal();
|
|
||||||
ListVal* idxs = root_certs2->ConvertToPureList();
|
|
||||||
|
|
||||||
// Build the validation store
|
|
||||||
for ( i = 0; i < idxs->Length(); ++i )
|
|
||||||
{
|
|
||||||
Val* key = idxs->Index(i);
|
|
||||||
StringVal *sv = root_certs2->Lookup(key)->AsStringVal();
|
|
||||||
const uint8* data = sv->Bytes();
|
|
||||||
X509* x = d2i_X509_(NULL, &data, sv->Len());
|
|
||||||
if ( ! x )
|
|
||||||
{
|
|
||||||
builtin_error(fmt("Root CA error: %s", ERR_error_string(ERR_peek_last_error(),NULL)));
|
|
||||||
return new Val((uint64) ERR_get_error(), TYPE_COUNT);
|
|
||||||
}
|
|
||||||
X509_STORE_add_cert(ctx, x);
|
|
||||||
}
|
|
||||||
delete idxs;
|
|
||||||
|
|
||||||
// Save the newly constructed certificate store into the cacheing map.
|
|
||||||
x509_stores[root_certs] = ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8 *cert_data = der_cert->Bytes();
|
|
||||||
X509* cert = d2i_X509_(NULL, &cert_data, der_cert->Len());
|
|
||||||
if ( ! cert )
|
|
||||||
{
|
|
||||||
builtin_error(fmt("Certificate error: %s", ERR_error_string(ERR_peek_last_error(),NULL)));
|
|
||||||
return new Val((uint64) ERR_get_error(), TYPE_COUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
STACK_OF(X509)* untrusted_certs = sk_X509_new_null();
|
|
||||||
if ( ! untrusted_certs )
|
|
||||||
{
|
|
||||||
builtin_error(fmt("Untrusted certificate stack initialization error: %s", ERR_error_string(ERR_peek_last_error(),NULL)));
|
|
||||||
return new Val((uint64) ERR_get_error(), TYPE_COUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorVal *cert_stack_vec = cert_stack->AsVectorVal();
|
|
||||||
for ( i = 0; i < (int) cert_stack_vec->Size(); ++i )
|
|
||||||
{
|
|
||||||
StringVal *sv = cert_stack_vec->Lookup(i)->AsStringVal();
|
|
||||||
const uint8 *data = sv->Bytes();
|
|
||||||
X509* x = d2i_X509_(NULL, &data, sv->Len());
|
|
||||||
if ( ! x )
|
|
||||||
{
|
|
||||||
X509_free(cert);
|
|
||||||
sk_X509_pop_free(untrusted_certs, X509_free);
|
|
||||||
builtin_error(fmt("Untrusted certificate stack creation error: %s", ERR_error_string(ERR_peek_last_error(),NULL)));
|
|
||||||
return new Val((uint64) ERR_get_error(), TYPE_COUNT);
|
|
||||||
}
|
|
||||||
sk_X509_push(untrusted_certs, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
X509_STORE_CTX csc;
|
|
||||||
X509_STORE_CTX_init(&csc, ctx, cert, untrusted_certs);
|
|
||||||
X509_STORE_CTX_set_time(&csc, 0, (time_t) network_time);
|
|
||||||
|
|
||||||
int result = X509_verify_cert(&csc);
|
|
||||||
X509_STORE_CTX_cleanup(&csc);
|
|
||||||
|
|
||||||
if ( untrusted_certs )
|
|
||||||
sk_X509_pop_free(untrusted_certs, X509_free);
|
|
||||||
X509_free(cert);
|
|
||||||
|
|
||||||
return new Val((uint64) csc.error, TYPE_COUNT);
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Converts a certificate verification error code into an ASCII string.
|
|
||||||
##
|
|
||||||
## err_num: The error code.
|
|
||||||
##
|
|
||||||
## Returns: A string representation of *err_num*.
|
|
||||||
##
|
|
||||||
## .. bro:see:: x509_verify
|
|
||||||
function x509_err2str%(err_num: count%): string
|
|
||||||
%{
|
|
||||||
return new StringVal(X509_verify_cert_error_string(err_num));
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Converts UNIX file permissions given by a mode to an ASCII string.
|
## Converts UNIX file permissions given by a mode to an ASCII string.
|
||||||
##
|
##
|
||||||
## mode: The permissions (an octal number like 0644 converted to decimal).
|
## mode: The permissions (an octal number like 0644 converted to decimal).
|
||||||
|
@ -4108,81 +3688,6 @@ function set_record_packets%(cid: conn_id, do_record: bool%): bool
|
||||||
return new Val(1, TYPE_BOOL);
|
return new Val(1, TYPE_BOOL);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
## Associates a file handle with a connection for writing TCP byte stream
|
|
||||||
## contents.
|
|
||||||
##
|
|
||||||
## cid: The connection ID.
|
|
||||||
##
|
|
||||||
## direction: Controls what sides of the connection to record. The argument can
|
|
||||||
## take one of the four values:
|
|
||||||
##
|
|
||||||
## - ``CONTENTS_NONE``: Stop recording the connection's content.
|
|
||||||
## - ``CONTENTS_ORIG``: Record the data sent by the connection
|
|
||||||
## originator (often the client).
|
|
||||||
## - ``CONTENTS_RESP``: Record the data sent by the connection
|
|
||||||
## responder (often the server).
|
|
||||||
## - ``CONTENTS_BOTH``: Record the data sent in both directions.
|
|
||||||
## Results in the two directions being
|
|
||||||
## intermixed in the file, in the order the
|
|
||||||
## data was seen by Bro.
|
|
||||||
##
|
|
||||||
## f: The file handle of the file to write the contents to.
|
|
||||||
##
|
|
||||||
## Returns: Returns false if *cid* does not point to an active connection, and
|
|
||||||
## true otherwise.
|
|
||||||
##
|
|
||||||
## .. note::
|
|
||||||
##
|
|
||||||
## The data recorded to the file reflects the byte stream, not the
|
|
||||||
## contents of individual packets. Reordering and duplicates are
|
|
||||||
## removed. If any data is missing, the recording stops at the
|
|
||||||
## missing data; this can happen, e.g., due to an
|
|
||||||
## :bro:id:`ack_above_hole` event.
|
|
||||||
##
|
|
||||||
## .. bro:see:: get_contents_file set_record_packets
|
|
||||||
function set_contents_file%(cid: conn_id, direction: count, f: file%): bool
|
|
||||||
%{
|
|
||||||
Connection* c = sessions->FindConnection(cid);
|
|
||||||
if ( ! c )
|
|
||||||
return new Val(0, TYPE_BOOL);
|
|
||||||
|
|
||||||
c->GetRootAnalyzer()->SetContentsFile(direction, f);
|
|
||||||
return new Val(1, TYPE_BOOL);
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Returns the file handle of the contents file of a connection.
|
|
||||||
##
|
|
||||||
## cid: The connection ID.
|
|
||||||
##
|
|
||||||
## direction: Controls what sides of the connection to record. See
|
|
||||||
## :bro:id:`set_contents_file` for possible values.
|
|
||||||
##
|
|
||||||
## Returns: The :bro:type:`file` handle for the contents file of the
|
|
||||||
## connection identified by *cid*. If the connection exists
|
|
||||||
## but there is no contents file for *direction*, then the function
|
|
||||||
## generates an error and returns a file handle to ``stderr``.
|
|
||||||
##
|
|
||||||
## .. bro:see:: set_contents_file set_record_packets
|
|
||||||
function get_contents_file%(cid: conn_id, direction: count%): file
|
|
||||||
%{
|
|
||||||
Connection* c = sessions->FindConnection(cid);
|
|
||||||
BroFile* f = c ? c->GetRootAnalyzer()->GetContentsFile(direction) : 0;
|
|
||||||
|
|
||||||
if ( f )
|
|
||||||
{
|
|
||||||
Ref(f);
|
|
||||||
return new Val(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return some sort of error value.
|
|
||||||
if ( ! c )
|
|
||||||
builtin_error("unknown connection id in get_contents_file()", cid);
|
|
||||||
else
|
|
||||||
builtin_error("no contents file for given direction");
|
|
||||||
|
|
||||||
return new Val(new BroFile(stderr, "-", "w"));
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Sets an individual inactivity timeout for a connection and thus
|
## Sets an individual inactivity timeout for a connection and thus
|
||||||
## overrides the global inactivity timeout.
|
## overrides the global inactivity timeout.
|
||||||
##
|
##
|
||||||
|
@ -4203,145 +3708,6 @@ function set_inactivity_timeout%(cid: conn_id, t: interval%): interval
|
||||||
return new Val(old_timeout, TYPE_INTERVAL);
|
return new Val(old_timeout, TYPE_INTERVAL);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
## Returns the state of the given login (Telnet or Rlogin) connection.
|
|
||||||
##
|
|
||||||
## cid: The connection ID.
|
|
||||||
##
|
|
||||||
## Returns: False if the connection is not active or is not tagged as a
|
|
||||||
## login analyzer. Otherwise the function returns the state, which can
|
|
||||||
## be one of:
|
|
||||||
##
|
|
||||||
## - ``LOGIN_STATE_AUTHENTICATE``: The connection is in its
|
|
||||||
## initial authentication dialog.
|
|
||||||
## - ``LOGIN_STATE_LOGGED_IN``: The analyzer believes the user has
|
|
||||||
## successfully authenticated.
|
|
||||||
## - ``LOGIN_STATE_SKIP``: The analyzer has skipped any further
|
|
||||||
## processing of the connection.
|
|
||||||
## - ``LOGIN_STATE_CONFUSED``: The analyzer has concluded that it
|
|
||||||
## does not correctly know the state of the connection, and/or
|
|
||||||
## the username associated with it.
|
|
||||||
##
|
|
||||||
## .. bro:see:: set_login_state
|
|
||||||
function get_login_state%(cid: conn_id%): count
|
|
||||||
%{
|
|
||||||
Connection* c = sessions->FindConnection(cid);
|
|
||||||
if ( ! c )
|
|
||||||
return new Val(0, TYPE_BOOL);
|
|
||||||
|
|
||||||
analyzer::Analyzer* la = c->FindAnalyzer("Login");
|
|
||||||
if ( ! la )
|
|
||||||
return new Val(0, TYPE_BOOL);
|
|
||||||
|
|
||||||
return new Val(int(static_cast<analyzer::login::Login_Analyzer*>(la)->LoginState()),
|
|
||||||
TYPE_COUNT);
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Sets the login state of a connection with a login analyzer.
|
|
||||||
##
|
|
||||||
## cid: The connection ID.
|
|
||||||
##
|
|
||||||
## new_state: The new state of the login analyzer. See
|
|
||||||
## :bro:id:`get_login_state` for possible values.
|
|
||||||
##
|
|
||||||
## Returns: Returns false if *cid* is not an active connection
|
|
||||||
## or is not tagged as a login analyzer, and true otherwise.
|
|
||||||
##
|
|
||||||
## .. bro:see:: get_login_state
|
|
||||||
function set_login_state%(cid: conn_id, new_state: count%): bool
|
|
||||||
%{
|
|
||||||
Connection* c = sessions->FindConnection(cid);
|
|
||||||
if ( ! c )
|
|
||||||
return new Val(0, TYPE_BOOL);
|
|
||||||
|
|
||||||
analyzer::Analyzer* la = c->FindAnalyzer("Login");
|
|
||||||
if ( ! la )
|
|
||||||
return new Val(0, TYPE_BOOL);
|
|
||||||
|
|
||||||
static_cast<analyzer::login::Login_Analyzer*>(la)->SetLoginState(analyzer::login::login_state(new_state));
|
|
||||||
return new Val(1, TYPE_BOOL);
|
|
||||||
%}
|
|
||||||
|
|
||||||
%%{
|
|
||||||
#include "analyzer/protocols/tcp/TCP.h"
|
|
||||||
%%}
|
|
||||||
|
|
||||||
## Get the originator sequence number of a TCP connection. Sequence numbers
|
|
||||||
## are absolute (i.e., they reflect the values seen directly in packet headers;
|
|
||||||
## they are not relative to the beginning of the connection).
|
|
||||||
##
|
|
||||||
## cid: The connection ID.
|
|
||||||
##
|
|
||||||
## Returns: The highest sequence number sent by a connection's originator, or 0
|
|
||||||
## if *cid* does not point to an active TCP connection.
|
|
||||||
##
|
|
||||||
## .. bro:see:: get_resp_seq
|
|
||||||
function get_orig_seq%(cid: conn_id%): count
|
|
||||||
%{
|
|
||||||
Connection* c = sessions->FindConnection(cid);
|
|
||||||
if ( ! c )
|
|
||||||
return new Val(0, TYPE_COUNT);
|
|
||||||
|
|
||||||
if ( c->ConnTransport() != TRANSPORT_TCP )
|
|
||||||
return new Val(0, TYPE_COUNT);
|
|
||||||
|
|
||||||
analyzer::Analyzer* tc = c->FindAnalyzer("TCP");
|
|
||||||
if ( tc )
|
|
||||||
return new Val(static_cast<analyzer::tcp::TCP_Analyzer*>(tc)->OrigSeq(),
|
|
||||||
TYPE_COUNT);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reporter->Error("connection does not have TCP analyzer");
|
|
||||||
return new Val(0, TYPE_COUNT);
|
|
||||||
}
|
|
||||||
%}
|
|
||||||
|
|
||||||
## Get the responder sequence number of a TCP connection. Sequence numbers
|
|
||||||
## are absolute (i.e., they reflect the values seen directly in packet headers;
|
|
||||||
## they are not relative to the beginning of the connection).
|
|
||||||
##
|
|
||||||
## cid: The connection ID.
|
|
||||||
##
|
|
||||||
## Returns: The highest sequence number sent by a connection's responder, or 0
|
|
||||||
## if *cid* does not point to an active TCP connection.
|
|
||||||
##
|
|
||||||
## .. bro:see:: get_orig_seq
|
|
||||||
function get_resp_seq%(cid: conn_id%): count
|
|
||||||
%{
|
|
||||||
Connection* c = sessions->FindConnection(cid);
|
|
||||||
if ( ! c )
|
|
||||||
return new Val(0, TYPE_COUNT);
|
|
||||||
|
|
||||||
if ( c->ConnTransport() != TRANSPORT_TCP )
|
|
||||||
return new Val(0, TYPE_COUNT);
|
|
||||||
|
|
||||||
analyzer::Analyzer* tc = c->FindAnalyzer("TCP");
|
|
||||||
if ( tc )
|
|
||||||
return new Val(static_cast<analyzer::tcp::TCP_Analyzer*>(tc)->RespSeq(),
|
|
||||||
TYPE_COUNT);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reporter->Error("connection does not have TCP analyzer");
|
|
||||||
return new Val(0, TYPE_COUNT);
|
|
||||||
}
|
|
||||||
%}
|
|
||||||
|
|
||||||
%%{
|
|
||||||
#include "analyzer/protocols/smtp/SMTP.h"
|
|
||||||
%%}
|
|
||||||
|
|
||||||
## Skips SMTP data until the next email in a connection.
|
|
||||||
##
|
|
||||||
## c: The SMTP connection.
|
|
||||||
##
|
|
||||||
## .. bro:see:: skip_http_entity_data
|
|
||||||
function skip_smtp_data%(c: connection%): any
|
|
||||||
%{
|
|
||||||
analyzer::Analyzer* sa = c->FindAnalyzer("SMTP");
|
|
||||||
if ( sa )
|
|
||||||
static_cast<analyzer::smtp::SMTP_Analyzer*>(sa)->SkipData();
|
|
||||||
return 0;
|
|
||||||
%}
|
|
||||||
|
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
#
|
#
|
||||||
# Files and Directories
|
# Files and Directories
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue