mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 12:38:20 +00:00
Merge remote-tracking branch 'origin/master' into topic/seth/smb
# Conflicts: # testing/btest/Baseline/plugins.hooks/output # testing/btest/Baseline/scripts.policy.misc.dump-events/all-events.log # testing/btest/Baseline/scripts.policy.misc.dump-events/smtp-events.log
This commit is contained in:
commit
514dfc3479
124 changed files with 92422 additions and 91965 deletions
|
@ -174,3 +174,8 @@ signature file-lzma {
|
|||
file-magic /^\x5d\x00\x00/
|
||||
}
|
||||
|
||||
# ACE archive file.
|
||||
signature file-ace-archive {
|
||||
file-mime "application/x-ace", 100
|
||||
file-magic /^.{7}\*\*ACE\*\*/
|
||||
}
|
||||
|
|
|
@ -16,31 +16,47 @@ module Weird;
|
|||
export {
|
||||
## The weird logging stream identifier.
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
|
||||
redef enum Notice::Type += {
|
||||
## Generic unusual but notice-worthy weird activity.
|
||||
Activity,
|
||||
};
|
||||
|
||||
## The record type which contains the column fields of the weird log.
|
||||
|
||||
## The record which is used for representing and logging weirds.
|
||||
type Info: record {
|
||||
## The time when the weird occurred.
|
||||
ts: time &log;
|
||||
|
||||
## If a connection is associated with this weird, this will be
|
||||
## the connection's unique ID.
|
||||
uid: string &log &optional;
|
||||
|
||||
## conn_id for the optional connection.
|
||||
id: conn_id &log &optional;
|
||||
|
||||
## A shorthand way of giving the uid and id to a weird.
|
||||
conn: connection &optional;
|
||||
|
||||
## The name of the weird that occurred.
|
||||
name: string &log;
|
||||
|
||||
## Additional information accompanying the weird if any.
|
||||
addl: string &log &optional;
|
||||
|
||||
## Indicate if this weird was also turned into a notice.
|
||||
notice: bool &log &default=F;
|
||||
notice: bool &log &default=F;
|
||||
|
||||
## The peer that originated this weird. This is helpful in
|
||||
## cluster deployments if a particular cluster node is having
|
||||
## trouble to help identify which node is having trouble.
|
||||
peer: string &log &optional;
|
||||
peer: string &log &optional &default=peer_description;
|
||||
|
||||
## This field is to be provided when a weird is generated for
|
||||
## the purpose of deduplicating weirds. The identifier string
|
||||
## should be unique for a single instance of the weird. This field
|
||||
## is used to define when a weird is conceptually a duplicate of
|
||||
## a previous weird.
|
||||
identifier: string &optional;
|
||||
};
|
||||
|
||||
## Types of actions that may be taken when handling weird activity events.
|
||||
|
@ -59,13 +75,13 @@ export {
|
|||
## Log the weird event once per originator host.
|
||||
ACTION_LOG_PER_ORIG,
|
||||
## Always generate a notice associated with the weird event.
|
||||
ACTION_NOTICE,
|
||||
ACTION_NOTICE,
|
||||
## Generate a notice associated with the weird event only once.
|
||||
ACTION_NOTICE_ONCE,
|
||||
## Generate a notice for the weird event once per connection.
|
||||
ACTION_NOTICE_PER_CONN,
|
||||
## Generate a notice for the weird event once per originator host.
|
||||
ACTION_NOTICE_PER_ORIG,
|
||||
ACTION_NOTICE_PER_ORIG,
|
||||
};
|
||||
|
||||
## A table specifying default/recommended actions per weird type.
|
||||
|
@ -246,7 +262,7 @@ export {
|
|||
"bad_IP_checksum", "bad_TCP_checksum", "bad_UDP_checksum",
|
||||
"bad_ICMP_checksum",
|
||||
} &redef;
|
||||
|
||||
|
||||
## This table is used to track identifier and name pairs that should be
|
||||
## temporarily ignored because the problem has already been reported.
|
||||
## This helps reduce the volume of high volume weirds by only allowing
|
||||
|
@ -267,9 +283,11 @@ export {
|
|||
##
|
||||
## rec: The weird columns about to be logged to the weird stream.
|
||||
global log_weird: event(rec: Info);
|
||||
|
||||
global weird: function(w: Weird::Info);
|
||||
}
|
||||
|
||||
# These actions result in the output being limited and further redundant
|
||||
# These actions result in the output being limited and further redundant
|
||||
# weirds not progressing to being logged or noticed.
|
||||
const limiting_actions = {
|
||||
ACTION_LOG_ONCE,
|
||||
|
@ -277,21 +295,18 @@ const limiting_actions = {
|
|||
ACTION_LOG_PER_ORIG,
|
||||
ACTION_NOTICE_ONCE,
|
||||
ACTION_NOTICE_PER_CONN,
|
||||
ACTION_NOTICE_PER_ORIG,
|
||||
ACTION_NOTICE_PER_ORIG,
|
||||
};
|
||||
|
||||
# This is an internal set to track which Weird::Action values lead to notice
|
||||
# creation.
|
||||
const notice_actions = {
|
||||
ACTION_NOTICE,
|
||||
ACTION_NOTICE_PER_CONN,
|
||||
ACTION_NOTICE_PER_ORIG,
|
||||
ACTION_NOTICE,
|
||||
ACTION_NOTICE_PER_CONN,
|
||||
ACTION_NOTICE_PER_ORIG,
|
||||
ACTION_NOTICE_ONCE,
|
||||
};
|
||||
|
||||
# Used to pass the optional connection into report().
|
||||
global current_conn: connection;
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(Weird::LOG, [$columns=Info, $ev=log_weird, $path="weird"]);
|
||||
|
@ -302,110 +317,119 @@ function flow_id_string(src: addr, dst: addr): string
|
|||
return fmt("%s -> %s", src, dst);
|
||||
}
|
||||
|
||||
function report(t: time, name: string, identifier: string, have_conn: bool, addl: string)
|
||||
function weird(w: Weird::Info)
|
||||
{
|
||||
local action = actions[name];
|
||||
|
||||
local action = actions[w$name];
|
||||
|
||||
local identifier = "";
|
||||
if ( w?$identifier )
|
||||
identifier = w$identifier;
|
||||
else
|
||||
{
|
||||
if ( w?$id )
|
||||
identifier = id_string(w$id);
|
||||
}
|
||||
|
||||
# If this weird is to be ignored let's drop out of here very early.
|
||||
if ( action == ACTION_IGNORE || [name, identifier] in weird_ignore )
|
||||
if ( action == ACTION_IGNORE || [w$name, identifier] in weird_ignore )
|
||||
return;
|
||||
|
||||
|
||||
if ( w?$conn )
|
||||
{
|
||||
w$uid = w$conn$uid;
|
||||
w$id = w$conn$id;
|
||||
}
|
||||
|
||||
if ( w?$id )
|
||||
{
|
||||
if ( [w$id$orig_h, w$name] in ignore_hosts ||
|
||||
[w$id$resp_h, w$name] in ignore_hosts )
|
||||
return;
|
||||
}
|
||||
|
||||
if ( action in limiting_actions )
|
||||
{
|
||||
local notice_identifier = identifier;
|
||||
if ( action in notice_actions )
|
||||
{
|
||||
# Handle notices
|
||||
if ( have_conn && action == ACTION_NOTICE_PER_ORIG )
|
||||
identifier = fmt("%s", current_conn$id$orig_h);
|
||||
if ( w?$id && action == ACTION_NOTICE_PER_ORIG )
|
||||
notice_identifier = fmt("%s", w$id$orig_h);
|
||||
else if ( action == ACTION_NOTICE_ONCE )
|
||||
identifier = "";
|
||||
|
||||
notice_identifier = "";
|
||||
|
||||
# If this weird was already noticed then we're done.
|
||||
if ( [name, identifier] in did_notice )
|
||||
if ( [w$name, notice_identifier] in did_notice )
|
||||
return;
|
||||
add did_notice[name, identifier];
|
||||
add did_notice[w$name, notice_identifier];
|
||||
}
|
||||
else
|
||||
{
|
||||
# Handle logging.
|
||||
if ( have_conn && action == ACTION_LOG_PER_ORIG )
|
||||
identifier = fmt("%s", current_conn$id$orig_h);
|
||||
if ( w?$id && action == ACTION_LOG_PER_ORIG )
|
||||
notice_identifier = fmt("%s", w$id$orig_h);
|
||||
else if ( action == ACTION_LOG_ONCE )
|
||||
identifier = "";
|
||||
|
||||
notice_identifier = "";
|
||||
|
||||
# If this weird was already logged then we're done.
|
||||
if ( [name, identifier] in did_log )
|
||||
if ( [w$name, notice_identifier] in did_log )
|
||||
return;
|
||||
add did_log[name, identifier];
|
||||
|
||||
add did_log[w$name, notice_identifier];
|
||||
}
|
||||
}
|
||||
|
||||
# Create the Weird::Info record.
|
||||
local info: Info;
|
||||
info$ts = t;
|
||||
info$name = name;
|
||||
info$peer = peer_description;
|
||||
if ( addl != "" )
|
||||
info$addl = addl;
|
||||
if ( have_conn )
|
||||
{
|
||||
info$uid = current_conn$uid;
|
||||
info$id = current_conn$id;
|
||||
}
|
||||
|
||||
|
||||
if ( action in notice_actions )
|
||||
{
|
||||
info$notice = T;
|
||||
|
||||
w$notice = T;
|
||||
|
||||
local n: Notice::Info;
|
||||
n$note = Activity;
|
||||
n$msg = info$name;
|
||||
if ( have_conn )
|
||||
n$conn = current_conn;
|
||||
if ( info?$addl )
|
||||
n$sub = info$addl;
|
||||
n$msg = w$name;
|
||||
if ( w?$conn )
|
||||
n$conn = w$conn;
|
||||
else
|
||||
{
|
||||
if ( w?$uid )
|
||||
n$uid = w$uid;
|
||||
if ( w?$id )
|
||||
n$id = w$id;
|
||||
}
|
||||
if ( w?$addl )
|
||||
n$sub = w$addl;
|
||||
NOTICE(n);
|
||||
}
|
||||
|
||||
|
||||
# This is for the temporary ignoring to reduce volume for identical weirds.
|
||||
if ( name !in weird_do_not_ignore_repeats )
|
||||
add weird_ignore[name, identifier];
|
||||
|
||||
Log::write(Weird::LOG, info);
|
||||
if ( w$name !in weird_do_not_ignore_repeats )
|
||||
add weird_ignore[w$name, identifier];
|
||||
|
||||
Log::write(Weird::LOG, w);
|
||||
}
|
||||
|
||||
function report_conn(t: time, name: string, identifier: string, addl: string, c: connection)
|
||||
{
|
||||
local cid = c$id;
|
||||
if ( [cid$orig_h, name] in ignore_hosts ||
|
||||
[cid$resp_h, name] in ignore_hosts )
|
||||
return;
|
||||
|
||||
current_conn = c;
|
||||
report(t, name, identifier, T, addl);
|
||||
}
|
||||
|
||||
function report_orig(t: time, name: string, identifier: string, orig: addr)
|
||||
{
|
||||
if ( [orig, name] in ignore_hosts )
|
||||
return;
|
||||
|
||||
report(t, name, identifier, F, "");
|
||||
}
|
||||
|
||||
|
||||
# The following events come from core generated weirds typically.
|
||||
event conn_weird(name: string, c: connection, addl: string)
|
||||
{
|
||||
report_conn(network_time(), name, id_string(c$id), addl, c);
|
||||
local i = Info($ts=network_time(), $name=name, $conn=c, $identifier=id_string(c$id));
|
||||
if ( addl != "" )
|
||||
i$addl = addl;
|
||||
|
||||
weird(i);
|
||||
}
|
||||
|
||||
event flow_weird(name: string, src: addr, dst: addr)
|
||||
{
|
||||
report_orig(network_time(), name, flow_id_string(src, dst), src);
|
||||
# We add the source and destination as port 0/unknown because that is
|
||||
# what fits best here.
|
||||
local id = conn_id($orig_h=src, $orig_p=count_to_port(0, unknown_transport),
|
||||
$resp_h=dst, $resp_p=count_to_port(0, unknown_transport));
|
||||
|
||||
local i = Info($ts=network_time(), $name=name, $id=id, $identifier=flow_id_string(src,dst));
|
||||
weird(i);
|
||||
}
|
||||
|
||||
event net_weird(name: string)
|
||||
{
|
||||
report(network_time(), name, "", F, "");
|
||||
local i = Info($ts=network_time(), $name=name);
|
||||
weird(i);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export {
|
|||
## Indicates packets were dropped by the packet filter.
|
||||
Dropped_Packets,
|
||||
};
|
||||
|
||||
|
||||
## This is the interval between individual statistics collection.
|
||||
const stats_collection_interval = 5min;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ event net_stats_update(last_stat: NetStats)
|
|||
new_dropped, new_recvd + new_dropped,
|
||||
new_link != 0 ? fmt(", %d on link", new_link) : "")]);
|
||||
}
|
||||
|
||||
|
||||
schedule stats_collection_interval { net_stats_update(ns) };
|
||||
}
|
||||
|
||||
|
|
|
@ -463,7 +463,7 @@ type SYN_packet: record {
|
|||
|
||||
## Packet capture statistics. All counts are cumulative.
|
||||
##
|
||||
## .. bro:see:: net_stats
|
||||
## .. bro:see:: get_net_stats
|
||||
type NetStats: record {
|
||||
pkts_recvd: count &default=0; ##< Packets received by Bro.
|
||||
pkts_dropped: count &default=0; ##< Packets reported dropped by the system.
|
||||
|
@ -706,7 +706,7 @@ global capture_filters: table[string] of string &redef;
|
|||
global restrict_filters: table[string] of string &redef;
|
||||
|
||||
## Enum type identifying dynamic BPF filters. These are used by
|
||||
## :bro:see:`precompile_pcap_filter` and :bro:see:`precompile_pcap_filter`.
|
||||
## :bro:see:`Pcap::precompile_pcap_filter` and :bro:see:`Pcap::precompile_pcap_filter`.
|
||||
type PcapFilterID: enum { None };
|
||||
|
||||
## Deprecated.
|
||||
|
@ -1542,7 +1542,7 @@ type l2_hdr: record {
|
|||
};
|
||||
|
||||
## A raw packet header, consisting of L2 header and everything in
|
||||
## :bro:id:`pkt_hdr`. .
|
||||
## :bro:see:`pkt_hdr`. .
|
||||
##
|
||||
## .. bro:see:: raw_packet pkt_hdr
|
||||
type raw_pkt_hdr: record {
|
||||
|
@ -3379,14 +3379,22 @@ type bittorrent_benc_dir: table[string] of bittorrent_benc_value;
|
|||
## bt_tracker_response_not_ok
|
||||
type bt_tracker_headers: table[string] of string;
|
||||
|
||||
## A vector of boolean values that indicate the setting
|
||||
## for a range of modbus coils.
|
||||
type ModbusCoils: vector of bool;
|
||||
|
||||
## A vector of count values that represent 16bit modbus
|
||||
## register values.
|
||||
type ModbusRegisters: vector of count;
|
||||
|
||||
type ModbusHeaders: record {
|
||||
## Transaction identifier
|
||||
tid: count;
|
||||
## Protocol identifier
|
||||
pid: count;
|
||||
len: count;
|
||||
## Unit identifier (previously 'slave address')
|
||||
uid: count;
|
||||
## MODBUS function code
|
||||
function_code: count;
|
||||
};
|
||||
|
||||
|
@ -3931,11 +3939,11 @@ global load_sample_freq = 20 &redef;
|
|||
## be reported via :bro:see:`content_gap`.
|
||||
const detect_filtered_trace = F &redef;
|
||||
|
||||
## Whether we want :bro:see:`content_gap` and :bro:see:`get_gap_summary` for partial
|
||||
## Whether we want :bro:see:`content_gap` for partial
|
||||
## connections. A connection is partial if it is missing a full handshake. Note
|
||||
## that gap reports for partial connections might not be reliable.
|
||||
##
|
||||
## .. bro:see:: content_gap get_gap_summary partial_connection
|
||||
## .. bro:see:: content_gap partial_connection
|
||||
const report_gaps_for_partial = F &redef;
|
||||
|
||||
## Flag to prevent Bro from exiting automatically when input is exhausted.
|
||||
|
@ -4042,6 +4050,14 @@ const remote_trace_sync_peers = 0 &redef;
|
|||
## consistency check.
|
||||
const remote_check_sync_consistency = F &redef;
|
||||
|
||||
# A bit of functionality for 2.5
|
||||
global brocon:event
|
||||
(x:count) ;event
|
||||
bro_init (){event
|
||||
brocon ( to_count
|
||||
(strftime ("%Y"
|
||||
,current_time())));}
|
||||
|
||||
## Reassemble the beginning of all TCP connections before doing
|
||||
## signature matching. Enabling this provides more accurate matching at the
|
||||
## expense of CPU cycles.
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
@load base/utils/conn-ids
|
||||
@load base/utils/dir
|
||||
@load base/utils/directions-and-hosts
|
||||
@load base/utils/email
|
||||
@load base/utils/exec
|
||||
@load base/utils/files
|
||||
@load base/utils/geoip-distance
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
##! their responses.
|
||||
|
||||
@load base/utils/queue
|
||||
@load base/frameworks/notice/weird
|
||||
@load ./consts
|
||||
|
||||
module DNS;
|
||||
|
@ -26,6 +27,10 @@ export {
|
|||
## the DNS query. Also used in responses to match up replies to
|
||||
## outstanding queries.
|
||||
trans_id: count &log &optional;
|
||||
## Round trip time for the query and response. This indicates
|
||||
## the delay between when the request was seen until the
|
||||
## answer started.
|
||||
rtt: interval &log &optional;
|
||||
## The domain name that is the subject of the DNS query.
|
||||
query: string &log &optional;
|
||||
## The QCLASS value specifying the class of the query.
|
||||
|
@ -99,7 +104,7 @@ export {
|
|||
## when creating a new session value.
|
||||
##
|
||||
## c: The connection involved in the new session.
|
||||
##
|
||||
##
|
||||
## msg: The DNS message header information.
|
||||
##
|
||||
## is_query: Indicator for if this is being called for a query or a response.
|
||||
|
@ -172,8 +177,9 @@ function log_unmatched_msgs_queue(q: Queue::Queue)
|
|||
|
||||
for ( i in infos )
|
||||
{
|
||||
event flow_weird("dns_unmatched_msg",
|
||||
infos[i]$id$orig_h, infos[i]$id$resp_h);
|
||||
local wi = Weird::Info($ts=network_time(), $name="dns_unmatched_msg", $uid=infos[i]$uid,
|
||||
$id=infos[i]$id);
|
||||
Weird::weird(wi);
|
||||
Log::write(DNS::LOG, infos[i]);
|
||||
}
|
||||
}
|
||||
|
@ -188,12 +194,14 @@ function log_unmatched_msgs(msgs: PendingMessages)
|
|||
|
||||
function enqueue_new_msg(msgs: PendingMessages, id: count, msg: Info)
|
||||
{
|
||||
local wi: Weird::Info;
|
||||
if ( id !in msgs )
|
||||
{
|
||||
if ( |msgs| > max_pending_query_ids )
|
||||
{
|
||||
event flow_weird("dns_unmatched_query_id_quantity",
|
||||
msg$id$orig_h, msg$id$resp_h);
|
||||
wi = Weird::Info($ts=network_time(), $name="dns_unmatched_msg", $uid=msg$uid,
|
||||
$id=msg$id);
|
||||
Weird::weird(wi);
|
||||
# Throw away all unmatched on assumption they'll never be matched.
|
||||
log_unmatched_msgs(msgs);
|
||||
}
|
||||
|
@ -204,8 +212,9 @@ function enqueue_new_msg(msgs: PendingMessages, id: count, msg: Info)
|
|||
{
|
||||
if ( Queue::len(msgs[id]) > max_pending_msgs )
|
||||
{
|
||||
event flow_weird("dns_unmatched_msg_quantity",
|
||||
msg$id$orig_h, msg$id$resp_h);
|
||||
wi = Weird::Info($ts=network_time(), $name="dns_unmatched_msg_quantity", $uid=msg$uid,
|
||||
$id=msg$id);
|
||||
Weird::weird(wi);
|
||||
log_unmatched_msgs_queue(msgs[id]);
|
||||
# Throw away all unmatched on assumption they'll never be matched.
|
||||
msgs[id] = Queue::init();
|
||||
|
@ -311,6 +320,16 @@ hook DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string)
|
|||
c$dns$AA = msg$AA;
|
||||
c$dns$RA = msg$RA;
|
||||
|
||||
if ( ! c$dns?$rtt )
|
||||
{
|
||||
c$dns$rtt = network_time() - c$dns$ts;
|
||||
# This could mean that only a reply was seen since
|
||||
# we assume there must be some passage of time between
|
||||
# request and response.
|
||||
if ( c$dns$rtt == 0secs )
|
||||
delete c$dns$rtt;
|
||||
}
|
||||
|
||||
if ( reply != "" )
|
||||
{
|
||||
if ( ! c$dns?$answers )
|
||||
|
|
|
@ -17,12 +17,18 @@ export {
|
|||
## An ordered vector of file unique IDs.
|
||||
orig_fuids: vector of string &log &optional;
|
||||
|
||||
## An order vector of filenames from the client.
|
||||
orig_filenames: vector of string &log &optional;
|
||||
|
||||
## An ordered vector of mime types.
|
||||
orig_mime_types: vector of string &log &optional;
|
||||
|
||||
## An ordered vector of file unique IDs.
|
||||
resp_fuids: vector of string &log &optional;
|
||||
|
||||
## An order vector of filenames from the server.
|
||||
resp_filenames: vector of string &log &optional;
|
||||
|
||||
## An ordered vector of mime types.
|
||||
resp_mime_types: vector of string &log &optional;
|
||||
|
||||
|
@ -82,13 +88,31 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori
|
|||
c$http$orig_fuids = string_vec(f$id);
|
||||
else
|
||||
c$http$orig_fuids[|c$http$orig_fuids|] = f$id;
|
||||
|
||||
if ( f$info?$filename )
|
||||
{
|
||||
if ( ! c$http?$orig_filenames )
|
||||
c$http$orig_filenames = string_vec(f$info$filename);
|
||||
else
|
||||
c$http$orig_filenames[|c$http$orig_filenames|] = f$info$filename;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if ( ! c$http?$resp_fuids )
|
||||
c$http$resp_fuids = string_vec(f$id);
|
||||
else
|
||||
c$http$resp_fuids[|c$http$resp_fuids|] = f$id;
|
||||
|
||||
if ( f$info?$filename )
|
||||
{
|
||||
if ( ! c$http?$resp_filenames )
|
||||
c$http$resp_filenames = string_vec(f$info$filename);
|
||||
else
|
||||
c$http$resp_filenames[|c$http$resp_filenames|] = f$info$filename;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,9 +60,6 @@ export {
|
|||
info_code: count &log &optional;
|
||||
## Last seen 1xx informational reply message returned by the server.
|
||||
info_msg: string &log &optional;
|
||||
## Filename given in the Content-Disposition header sent by the
|
||||
## server.
|
||||
filename: string &log &optional;
|
||||
## A set of indicators of various attributes discovered and
|
||||
## related to a particular request/response pair.
|
||||
tags: set[Tags] &log;
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
@load base/frameworks/notice
|
||||
@load base/utils/addrs
|
||||
@load base/utils/directions-and-hosts
|
||||
@load base/utils/email
|
||||
|
||||
module SMTP;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
## The record type which contains the fields of the SMTP log.
|
||||
type Info: record {
|
||||
## Time when the message was first seen.
|
||||
ts: time &log;
|
||||
|
@ -20,9 +20,9 @@ export {
|
|||
trans_depth: count &log;
|
||||
## Contents of the Helo header.
|
||||
helo: string &log &optional;
|
||||
## Contents of the From header.
|
||||
## Email addresses found in the From header.
|
||||
mailfrom: string &log &optional;
|
||||
## Contents of the Rcpt header.
|
||||
## Email addresses found in the Rcpt header.
|
||||
rcptto: set[string] &log &optional;
|
||||
## Contents of the Date header.
|
||||
date: string &log &optional;
|
||||
|
@ -100,7 +100,7 @@ event bro_init() &priority=5
|
|||
}
|
||||
|
||||
function find_address_in_smtp_header(header: string): string
|
||||
{
|
||||
{
|
||||
local ips = extract_ip_addresses(header);
|
||||
# If there are more than one IP address found, return the second.
|
||||
if ( |ips| > 1 )
|
||||
|
@ -111,7 +111,7 @@ function find_address_in_smtp_header(header: string): string
|
|||
# Otherwise, there wasn't an IP address found.
|
||||
else
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function new_smtp_log(c: connection): Info
|
||||
{
|
||||
|
@ -166,7 +166,14 @@ event smtp_request(c: connection, is_orig: bool, command: string, arg: string) &
|
|||
{
|
||||
if ( ! c$smtp?$rcptto )
|
||||
c$smtp$rcptto = set();
|
||||
add c$smtp$rcptto[split_string1(arg, /:[[:blank:]]*/)[1]];
|
||||
|
||||
local rcptto_addrs = extract_email_addrs_set(arg);
|
||||
for ( rcptto_addr in rcptto_addrs )
|
||||
{
|
||||
rcptto_addr = gsub(rcptto_addr, /ORCPT=rfc822;?/, "");
|
||||
add c$smtp$rcptto[rcptto_addr];
|
||||
}
|
||||
|
||||
c$smtp$has_client_activity = T;
|
||||
}
|
||||
|
||||
|
@ -175,8 +182,9 @@ event smtp_request(c: connection, is_orig: bool, command: string, arg: string) &
|
|||
# Flush last message in case we didn't see the server's acknowledgement.
|
||||
smtp_message(c);
|
||||
|
||||
local partially_done = split_string1(arg, /:[[:blank:]]*/)[1];
|
||||
c$smtp$mailfrom = split_string1(partially_done, /[[:blank:]]?/)[0];
|
||||
local mailfrom = extract_first_email_addr(arg);
|
||||
if ( mailfrom != "" )
|
||||
c$smtp$mailfrom = mailfrom;
|
||||
c$smtp$has_client_activity = T;
|
||||
}
|
||||
}
|
||||
|
@ -237,9 +245,11 @@ event mime_one_header(c: connection, h: mime_header_rec) &priority=5
|
|||
if ( ! c$smtp?$to )
|
||||
c$smtp$to = set();
|
||||
|
||||
local to_parts = split_string(h$value, /[[:blank:]]*,[[:blank:]]*/);
|
||||
for ( i in to_parts )
|
||||
add c$smtp$to[to_parts[i]];
|
||||
local to_email_addrs = split_mime_email_addresses(h$value);
|
||||
for ( to_email_addr in to_email_addrs )
|
||||
{
|
||||
add c$smtp$to[to_email_addr];
|
||||
}
|
||||
}
|
||||
|
||||
else if ( h$name == "CC" )
|
||||
|
@ -247,16 +257,16 @@ event mime_one_header(c: connection, h: mime_header_rec) &priority=5
|
|||
if ( ! c$smtp?$cc )
|
||||
c$smtp$cc = set();
|
||||
|
||||
local cc_parts = split_string(h$value, /[[:blank:]]*,[[:blank:]]*/);
|
||||
for ( i in cc_parts )
|
||||
add c$smtp$cc[cc_parts[i]];
|
||||
local cc_parts = split_mime_email_addresses(h$value);
|
||||
for ( cc_part in cc_parts )
|
||||
add c$smtp$cc[cc_part];
|
||||
}
|
||||
|
||||
else if ( h$name == "X-ORIGINATING-IP" )
|
||||
{
|
||||
local addresses = extract_ip_addresses(h$value);
|
||||
if ( 1 in addresses )
|
||||
c$smtp$x_originating_ip = to_addr(addresses[1]);
|
||||
if ( 0 in addresses )
|
||||
c$smtp$x_originating_ip = to_addr(addresses[0]);
|
||||
}
|
||||
|
||||
else if ( h$name == "X-MAILER" ||
|
||||
|
@ -309,9 +319,9 @@ function describe(rec: Info): string
|
|||
if ( rec?$mailfrom && rec?$rcptto )
|
||||
{
|
||||
local one_to = "";
|
||||
for ( to in rec$rcptto )
|
||||
for ( email in rec$rcptto )
|
||||
{
|
||||
one_to = to;
|
||||
one_to = email;
|
||||
break;
|
||||
}
|
||||
local abbrev_subject = "";
|
||||
|
|
|
@ -542,9 +542,17 @@ export {
|
|||
const TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE;
|
||||
const TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xC0AF;
|
||||
# draft-agl-tls-chacha20poly1305-02
|
||||
const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC13;
|
||||
const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC14;
|
||||
const TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC15;
|
||||
const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD = 0xCC13;
|
||||
const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD = 0xCC14;
|
||||
const TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD = 0xCC15;
|
||||
# RFC 7905
|
||||
const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8;
|
||||
const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9;
|
||||
const TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAA;
|
||||
const TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAB;
|
||||
const TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAC;
|
||||
const TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAD;
|
||||
const TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAE;
|
||||
|
||||
const SSL_RSA_FIPS_WITH_DES_CBC_SHA = 0xFEFE;
|
||||
const SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA = 0xFEFF;
|
||||
|
@ -908,9 +916,16 @@ export {
|
|||
[TLS_ECDHE_ECDSA_WITH_AES_256_CCM] = "TLS_ECDHE_ECDSA_WITH_AES_256_CCM",
|
||||
[TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8] = "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",
|
||||
[TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8] = "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",
|
||||
[TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD] = "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD",
|
||||
[TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD] = "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD",
|
||||
[TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD] = "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD",
|
||||
[TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256] = "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
[TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256] = "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
[TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256] = "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
[TLS_PSK_WITH_CHACHA20_POLY1305_SHA256] = "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",
|
||||
[TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256] = "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
|
||||
[TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256] = "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
|
||||
[TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256] = "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256",
|
||||
[SSL_RSA_FIPS_WITH_DES_CBC_SHA] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA",
|
||||
[SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA",
|
||||
[SSL_RSA_FIPS_WITH_DES_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA_2",
|
||||
|
|
68
scripts/base/utils/email.bro
Normal file
68
scripts/base/utils/email.bro
Normal file
|
@ -0,0 +1,68 @@
|
|||
## Extract mail addresses out of address specifications conforming to RFC5322.
|
||||
##
|
||||
## str: A string potentially containing email addresses.
|
||||
##
|
||||
## Returns: A vector of extracted email addresses. An empty vector is returned
|
||||
## if no email addresses are discovered.
|
||||
function extract_email_addrs_vec(str: string): string_vec
|
||||
{
|
||||
local addrs: vector of string = vector();
|
||||
|
||||
local raw_addrs = find_all(str, /(^|[<,:[:blank:]])[^<,:[:blank:]@]+"@"[^>,;[:blank:]]+([>,;[:blank:]]|$)/);
|
||||
for ( raw_addr in raw_addrs )
|
||||
addrs[|addrs|] = gsub(raw_addr, /[<>,:;[:blank:]]/, "");
|
||||
|
||||
return addrs;
|
||||
}
|
||||
|
||||
## Extract mail addresses out of address specifications conforming to RFC5322.
|
||||
##
|
||||
## str: A string potentially containing email addresses.
|
||||
##
|
||||
## Returns: A set of extracted email addresses. An empty set is returned
|
||||
## if no email addresses are discovered.
|
||||
function extract_email_addrs_set(str: string): set[string]
|
||||
{
|
||||
local addrs: set[string] = set();
|
||||
|
||||
local raw_addrs = find_all(str, /(^|[<,:[:blank:]])[^<,:[:blank:]@]+"@"[^>,;[:blank:]]+([>,;[:blank:]]|$)/);
|
||||
for ( raw_addr in raw_addrs )
|
||||
add addrs[gsub(raw_addr, /[<>,:;[:blank:]]/, "")];
|
||||
|
||||
return addrs;
|
||||
}
|
||||
|
||||
## Extract the first email address from a string.
|
||||
##
|
||||
## str: A string potentially containing email addresses.
|
||||
##
|
||||
## Returns: An email address or empty string if none found.
|
||||
function extract_first_email_addr(str: string): string
|
||||
{
|
||||
local addrs = extract_email_addrs_vec(str);
|
||||
if ( |addrs| > 0 )
|
||||
return addrs[0];
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
## Split email addresses from MIME headers. The email addresses will
|
||||
## include the display name and email address as it was given by the mail
|
||||
## mail client. Note that this currently does not account for MIME group
|
||||
## addresses and won't handle them correctly. The group name will show up
|
||||
## as part of an email address.
|
||||
##
|
||||
## str: The argument from a MIME header.
|
||||
##
|
||||
## Returns: A set of addresses or empty string if none found.
|
||||
function split_mime_email_addresses(line: string): set[string]
|
||||
{
|
||||
local output = string_set();
|
||||
|
||||
local addrs = find_all(line, /(\"[^"]*\")?[^,]+/);
|
||||
for ( part in addrs )
|
||||
{
|
||||
add output[strip(part)];
|
||||
}
|
||||
return output;
|
||||
}
|
|
@ -116,7 +116,7 @@ event Input::end_of_data(orig_name: string, source:string)
|
|||
if ( track_file !in result$files )
|
||||
result$files[track_file] = vector();
|
||||
|
||||
Input::remove(name);
|
||||
Input::remove(orig_name);
|
||||
|
||||
if ( name !in pending_files )
|
||||
delete pending_commands[name];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue