mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
231 lines
6 KiB
C++
231 lines
6 KiB
C++
|
|
type ftp_port: record;
|
|
|
|
%%{
|
|
#include "zeek/Reporter.h"
|
|
|
|
static zeek::RecordValPtr parse_port(const std::string& line)
|
|
{
|
|
auto r = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::ftp_port);
|
|
|
|
bool good = false;
|
|
uint32_t port = 0;
|
|
uint32_t addr = 0;
|
|
|
|
int32_t bytes[6];
|
|
if ( line.size() >= 11 && sscanf(line.c_str(),
|
|
"%" SCNd32 ",%" SCNd32 ",%" SCNd32 ",%" SCNd32 ",%" SCNd32 ",%" SCNd32,
|
|
&bytes[0], &bytes[1], &bytes[2],
|
|
&bytes[3], &bytes[4], &bytes[5]) == 6 )
|
|
{
|
|
good = true;
|
|
|
|
for ( int b : bytes )
|
|
if ( b < 0 || b > 255 )
|
|
{
|
|
good = false;
|
|
break;
|
|
}
|
|
|
|
if ( good )
|
|
{
|
|
addr = (bytes[0] << 24) | (bytes[1] << 16) |
|
|
(bytes[2] << 8) | bytes[3];
|
|
port = (bytes[4] << 8) | bytes[5];
|
|
}
|
|
}
|
|
|
|
r->Assign(0, zeek::make_intrusive<zeek::AddrVal>(htonl(addr)));
|
|
r->Assign(1, zeek::val_mgr->Port(port, TRANSPORT_TCP));
|
|
r->Assign(2, good);
|
|
|
|
return r;
|
|
}
|
|
|
|
static zeek::RecordValPtr parse_eftp(const char* line)
|
|
{
|
|
auto r = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::ftp_port);
|
|
|
|
int net_proto = 0; // currently not used
|
|
zeek::IPAddr addr; // unspecified IPv6 address (all 128 bits zero)
|
|
int port = 0;
|
|
bool good = false;
|
|
|
|
if ( line )
|
|
{
|
|
while ( isspace(*line) ) // skip whitespace
|
|
++line;
|
|
|
|
char delimiter = *line;
|
|
char* next_delim;
|
|
|
|
if ( *line )
|
|
{
|
|
good = true;
|
|
++line; // skip delimiter
|
|
|
|
net_proto = strtol(line, &next_delim, 10);
|
|
if ( *next_delim != delimiter )
|
|
good = false;
|
|
|
|
line = next_delim;
|
|
if ( *line )
|
|
++line;
|
|
|
|
if ( *line && *line != delimiter )
|
|
{
|
|
const char* nptr = strchr(line, delimiter);
|
|
if ( nptr == NULL )
|
|
nptr = line + strlen(line);
|
|
|
|
std::string s(line, nptr-line); // extract IP address
|
|
struct in6_addr result;
|
|
good = zeek::IPAddr::ConvertString(s.c_str(), &result) ? 1 : 0;
|
|
if ( good )
|
|
addr = zeek::IPAddr(result);
|
|
}
|
|
|
|
line = strchr(line, delimiter);
|
|
|
|
if ( line != NULL )
|
|
{
|
|
++line; // now the port
|
|
port = strtol(line, &next_delim, 10);
|
|
if ( *next_delim != delimiter )
|
|
good = false;
|
|
|
|
if ( port < 0 || port > 65535 )
|
|
{
|
|
port = 0;
|
|
good = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
r->Assign(0, zeek::make_intrusive<zeek::AddrVal>(addr));
|
|
r->Assign(1, zeek::val_mgr->Port(port, TRANSPORT_TCP));
|
|
r->Assign(2, good);
|
|
|
|
return r;
|
|
}
|
|
%%}
|
|
|
|
## Converts a string representation of the FTP PORT command to an
|
|
## :zeek:type:`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]``.
|
|
##
|
|
## .. zeek: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->ToStdString());
|
|
%}
|
|
|
|
## Converts a string representation of the FTP EPRT command (see :rfc:`2428`)
|
|
## to an :zeek:type:`ftp_port`. 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]``.
|
|
##
|
|
## .. zeek: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 :zeek:type:`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]``.
|
|
##
|
|
## .. zeek: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();
|
|
|
|
if ( str->Len() == 0 )
|
|
return parse_port("");
|
|
|
|
const char* line = strchr(s, '(');
|
|
if ( line )
|
|
++line; // move past '('
|
|
else if ( line = strstr(s, "PORT"); line != nullptr )
|
|
line += 5; // Skip over
|
|
else if ( line = strchr(s, ','); line != nullptr )
|
|
{ // Look for comma-separated list.
|
|
do
|
|
{
|
|
// Back up over preceding digits. We'll end on the
|
|
// first digit or the beginning of s.
|
|
--line;
|
|
}
|
|
while ( line >= s && isdigit(*line) );
|
|
|
|
// Scoot forward one to point at the first digit or at the
|
|
// beginning of s.
|
|
++line;
|
|
}
|
|
|
|
// Make sure we didn't step past the end of the string.
|
|
if ( ! line || ( line - s ) > str->Len() )
|
|
return parse_port("");
|
|
else
|
|
return parse_port(std::string{line});
|
|
%}
|
|
|
|
## Converts the result of the FTP EPSV command (see :rfc:`2428`) to an
|
|
## :zeek:type:`ftp_port`. 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]``.
|
|
##
|
|
## .. zeek: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.
|
|
##
|
|
## .. zeek:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv parse_ftp_epsv
|
|
function fmt_ftp_port%(a: addr, p: port%): string
|
|
%{
|
|
const uint32_t* addr;
|
|
int len = a->AsAddr().GetBytes(&addr);
|
|
if ( len == 1 )
|
|
{
|
|
uint32_t a = ntohl(addr[0]);
|
|
uint32_t pn = p->Port();
|
|
return zeek::make_intrusive<zeek::StringVal>(zeek::util::fmt("%d,%d,%d,%d,%d,%d",
|
|
a >> 24, (a >> 16) & 0xff,
|
|
(a >> 8) & 0xff, a & 0xff,
|
|
pn >> 8, pn & 0xff));
|
|
}
|
|
else
|
|
{
|
|
zeek::emit_builtin_error("conversion of non-IPv4 address in fmt_ftp_port",
|
|
@ARG@[0]);
|
|
return zeek::val_mgr->EmptyString();
|
|
}
|
|
%}
|