Merge branch 'master' into topic/jsiwek/filter-rotation

This commit is contained in:
Jon Siwek 2011-09-07 12:30:47 -05:00
commit d2bf33ee19
161 changed files with 1345 additions and 946 deletions

View file

@ -3,7 +3,8 @@
module Cluster;
export {
redef enum Log::ID += { CLUSTER };
redef enum Log::ID += { LOG };
type Info: record {
ts: time;
message: string;
@ -106,5 +107,5 @@ event bro_init() &priority=5
terminate();
}
Log::create_stream(CLUSTER, [$columns=Info]);
Log::create_stream(Cluster::LOG, [$columns=Info]);
}

View file

@ -22,10 +22,5 @@ redef record_all_packets = T;
# do remote logging since we forward the notice event directly.
event bro_init()
{
Log::add_filter(Notice::NOTICE,
[
$name="cluster-worker",
$pred=function(rec: Notice::Info): bool { return F; }
]
);
Log::disable_stream(Notice::LOG);
}

View file

@ -6,7 +6,7 @@
module Communication;
export {
redef enum Log::ID += { COMMUNICATION };
redef enum Log::ID += { LOG };
const default_port_ssl = 47756/tcp &redef;
const default_port_clear = 47757/tcp &redef;
@ -107,21 +107,18 @@ const src_names = {
[REMOTE_SRC_SCRIPT] = "script",
};
event bro_init()
event bro_init() &priority=5
{
Log::create_stream(COMMUNICATION, [$columns=Info]);
if ( |nodes| > 0 )
enable_communication();
Log::create_stream(Communication::LOG, [$columns=Info]);
}
function do_script_log_common(level: count, src: count, msg: string)
{
Log::write(COMMUNICATION, [$ts = network_time(),
$level = (level == REMOTE_LOG_INFO ? "info" : "error"),
$src_name = src_names[src],
$peer = get_event_peer()$descr,
$message = msg]);
Log::write(Communication::LOG, [$ts = network_time(),
$level = (level == REMOTE_LOG_INFO ? "info" : "error"),
$src_name = src_names[src],
$peer = get_event_peer()$descr,
$message = msg]);
}
# This is a core generated event.
@ -147,9 +144,9 @@ function connect_peer(peer: string)
local id = connect(node$host, p, class, node$retry, node$ssl);
if ( id == PEER_ID_NONE )
Log::write(COMMUNICATION, [$ts = network_time(),
$peer = get_event_peer()$descr,
$message = "can't trigger connect"]);
Log::write(Communication::LOG, [$ts = network_time(),
$peer = get_event_peer()$descr,
$message = "can't trigger connect"]);
pending_peers[id] = node;
}
@ -275,15 +272,18 @@ event remote_state_inconsistency(operation: string, id: string,
local msg = fmt("state inconsistency: %s should be %s but is %s before %s",
id, expected_old, real_old, operation);
Log::write(COMMUNICATION, [$ts = network_time(),
$peer = get_event_peer()$descr,
$message = msg]);
Log::write(Communication::LOG, [$ts = network_time(),
$peer = get_event_peer()$descr,
$message = msg]);
}
# Actually initiate the connections that need to be established.
event bro_init() &priority = -10 # let others modify nodes
{
if ( |nodes| > 0 )
enable_communication();
for ( tag in nodes )
{
if ( ! nodes[tag]$connect )

View file

@ -7,7 +7,7 @@ module DPD;
redef signature_files += "base/frameworks/dpd/dpd.sig";
export {
redef enum Log::ID += { DPD };
redef enum Log::ID += { LOG };
type Info: record {
## Timestamp for when protocol analysis failed.
@ -38,9 +38,9 @@ redef record connection += {
dpd: Info &optional;
};
event bro_init()
event bro_init() &priority=5
{
Log::create_stream(DPD, [$columns=Info]);
Log::create_stream(DPD::LOG, [$columns=Info]);
# Populate the internal DPD analysis variable.
for ( a in dpd_config )
@ -104,5 +104,5 @@ event protocol_violation(c: connection, atype: count, aid: count,
reason: string) &priority=-5
{
if ( c?$dpd )
Log::write(DPD, c$dpd);
Log::write(DPD::LOG, c$dpd);
}

View file

@ -25,7 +25,7 @@
module Intel;
export {
redef enum Log::ID += { INTEL };
redef enum Log::ID += { LOG };
redef enum Notice::Type += {
## This notice should be used in all detector scripts to indicate
@ -101,7 +101,7 @@ export {
event bro_init()
{
Log::create_stream(INTEL, [$columns=Info]);
Log::create_stream(Intel::LOG, [$columns=Info]);
}
@ -163,7 +163,7 @@ function insert(item: Item): bool
}
if ( err_msg != "" )
Log::write(INTEL, [$ts=network_time(), $level="warn", $message=fmt(err_msg)]);
Log::write(Intel::LOG, [$ts=network_time(), $level="warn", $message=fmt(err_msg)]);
return F;
}
@ -272,6 +272,6 @@ function matcher(item: QueryItem): bool
}
if ( err_msg != "" )
Log::write(INTEL, [$ts=network_time(), $level="error", $message=fmt(err_msg)]);
Log::write(Intel::LOG, [$ts=network_time(), $level="error", $message=fmt(err_msg)]);
return F;
}

View file

@ -177,8 +177,47 @@ function __default_rotation_postprocessor(info: RotationInfo) : bool
function default_path_func(id: ID, path: string, rec: any) : string
{
# TODO for Seth: Do what you want. :)
return path;
local id_str = fmt("%s", id);
local parts = split1(id_str, /::/);
if ( |parts| == 2 )
{
# TODO: the core shouldn't be suggesting paths anymore. Only
# statically defined paths should be sent into here. This
# is only to cope with the core generated paths.
if ( to_lower(parts[2]) != path )
return path;
# Example: Notice::LOG -> "notice"
if ( parts[2] == "LOG" )
{
local module_parts = split_n(parts[1], /[^A-Z][A-Z][a-z]*/, T, 4);
local output = "";
if ( 1 in module_parts )
output = module_parts[1];
if ( 2 in module_parts && module_parts[2] != "" )
output = cat(output, sub_bytes(module_parts[2],1,1), "_", sub_bytes(module_parts[2], 2, |module_parts[2]|));
if ( 3 in module_parts && module_parts[3] != "" )
output = cat(output, "_", module_parts[3]);
if ( 4 in module_parts && module_parts[4] != "" )
output = cat(output, sub_bytes(module_parts[4],1,1), "_", sub_bytes(module_parts[4], 2, |module_parts[4]|));
# TODO: There seems to be some problem with the split function
# not putting \0 at the end of the string. fmt will make
# a better internal string.
return fmt("%s", to_lower(output));
}
# Example: Notice::POLICY_LOG -> "notice_policy"
if ( /_LOG$/ in parts[2] )
parts[2] = sub(parts[2], /_LOG$/, "");
return cat(to_lower(parts[1]),"_",to_lower(parts[2]));
}
else
{
# In case there is a logging stream in the global namespace.
return to_lower(id_str);
}
}
# Run post-processor on file. If there isn't any postprocessor defined,
@ -222,7 +261,7 @@ function add_filter(id: ID, filter: Filter) : bool
# definition.
if ( ! filter?$path_func )
filter$path_func = default_path_func;
filters[id, filter$name] = filter;
return __add_filter(id, filter);
}

View file

@ -0,0 +1,42 @@
##! This script defines a postprocessing function that can be applied
##! to a logging filter in order to automatically SCP (secure copy)
##! a log stream (or a subset of it) to a remote host at configurable
##! rotation time intervals.
module Log;
export {
## This postprocessor SCP's the rotated-log to all the remote hosts
## defined in :bro:id:`Log::scp_destinations` and then deletes
## the local copy of the rotated-log. It's not active when
## reading from trace files.
global scp_postprocessor: function(info: Log::RotationInfo): bool;
## A container that describes the remote destination for the SCP command
## argument as ``user@host:path``.
type SCPDestination: record {
user: string;
host: string;
path: string;
};
## A table indexed by a particular log writer and filter path, that yields
## a set remote destinations. The :bro:id:`Log::scp_postprocessor`
## function queries this table upon log rotation and performs a secure
## copy of the rotated-log to each destination in the set.
global scp_destinations: table[Writer, string] of set[SCPDestination];
}
function scp_postprocessor(info: Log::RotationInfo): bool
{
if ( reading_traces() || [info$writer, info$path] !in scp_destinations )
return T;
local command = "";
for ( d in scp_destinations[info$writer, info$path] )
command += fmt("scp %s %s@%s:%s;", info$fname, d$user, d$host, d$path);
command += fmt("/bin/rm %s", info$fname);
system(command);
return T;
}

View file

@ -11,7 +11,7 @@ export {
const include_header = T &redef;
## Prefix for the header line if included.
const header_prefix = "# " &redef;
const header_prefix = "#" &redef;
## Separator between fields.
const separator = "\t" &redef;

View file

@ -5,7 +5,7 @@
module Metrics;
export {
redef enum Log::ID += { METRICS };
redef enum Log::ID += { LOG };
type ID: enum {
NOTHING,
@ -124,7 +124,7 @@ global thresholds: table[ID, string, Index] of count = {} &create_expire=renotic
event bro_init() &priority=5
{
Log::create_stream(METRICS, [$columns=Info, $ev=log_metrics]);
Log::create_stream(Metrics::LOG, [$columns=Info, $ev=log_metrics]);
}
function index2str(index: Index): string
@ -151,7 +151,7 @@ function write_log(ts: time, filter: Filter, data: MetricTable)
$value=val];
if ( filter$log )
Log::write(METRICS, m);
Log::write(Metrics::LOG, m);
}
}

View file

@ -9,15 +9,13 @@ module Notice;
export {
redef enum Log::ID += {
## This is the primary logging stream for notices. It must always be
## referenced with the module name included because the name is
## also used by the global function :bro:id:`NOTICE`.
NOTICE,
## This is the primary logging stream for notices.
LOG,
## This is the notice policy auditing log. It records what the current
## notice policy is at Bro init time.
NOTICE_POLICY,
POLICY_LOG,
## This is the alarm stream.
ALARM,
ALARM_LOG,
};
## Scripts creating new notices need to redef this enum to add their own
@ -41,7 +39,9 @@ export {
## Indicates that the notice should be sent to the email address(es)
## configured in the :bro:id:`Notice::mail_dest` variable.
ACTION_EMAIL,
## Indicates that the notice should be alarmed.
## Indicates that the notice should be alarmed. A readable ASCII
## version of the alarm log is emailed in bulk to the address(es)
## configured in :bro:id:`Notice::mail_dest`.
ACTION_ALARM,
};
@ -136,7 +136,8 @@ export {
## Local system sendmail program.
const sendmail = "/usr/sbin/sendmail" &redef;
## Email address to send notices with the :bro:enum:`ACTION_EMAIL` action.
## Email address to send notices with the :bro:enum:`ACTION_EMAIL` action
## or to send bulk alarm logs on rotation with :bro:enum:`ACTION_ALARM`.
const mail_dest = "" &redef;
## Address that emails will be from.
@ -146,6 +147,11 @@ export {
## Text string prefixed to the subject of all emails sent out.
const mail_subject_prefix = "[Bro]" &redef;
## A log postprocessing function that implements emailing the contents
## of a log upon rotation to any configured :bro:id:`Notice::mail_dest`.
## The rotated log is removed upon being sent.
global log_mailing_postprocessor: function(info: Log::RotationInfo): bool;
## This is the event that is called as the entry point to the
## notice framework by the global :bro:id:`NOTICE` function. By the time
## this event is generated, default values have already been filled out in
@ -171,7 +177,14 @@ export {
## by default with the built in :bro:enum:`ACTION_EMAIL` and
## :bro:enum:`ACTION_PAGE` actions.
global email_notice_to: function(n: Info, dest: string, extend: bool);
## Constructs mail headers to which an email body can be appended for
## sending with sendmail.
## subject_desc: a subject string to use for the mail
## dest: recipient string to use for the mail
## Returns: a string of mail headers to which an email body can be appended
global email_headers: function(subject_desc: string, dest: string): string;
## This is an internally used function, please ignore it. It's only used
## for filling out missing details of :bro:type:`Notice:Info` records
## before the synchronous and asynchronous event pathways have begun.
@ -186,21 +199,48 @@ export {
# priority.
global ordered_policy: vector of PolicyItem = vector();
event bro_init()
function log_mailing_postprocessor(info: Log::RotationInfo): bool
{
Log::create_stream(NOTICE_POLICY, [$columns=PolicyItem]);
Log::create_stream(Notice::NOTICE, [$columns=Info, $ev=log_notice]);
Log::create_stream(ALARM, [$columns=Notice::Info]);
# Make sure that this log is output as text so that it can be packaged
# up and emailed later.
Log::add_filter(ALARM, [$name="default", $writer=Log::WRITER_ASCII]);
if ( ! reading_traces() && mail_dest != "" )
{
local headers = email_headers(fmt("Log Contents: %s", info$fname),
mail_dest);
local tmpfilename = fmt("%s.mailheaders.tmp", info$fname);
local tmpfile = open(tmpfilename);
write_file(tmpfile, headers);
close(tmpfile);
system(fmt("/bin/cat %s %s | %s -t -oi && /bin/rm %s %s",
tmpfilename, info$fname, sendmail, tmpfilename, info$fname));
}
return T;
}
# This extra export section here is just because this redefinition should
# be documented as part of the "public API" of this script, but the redef
# needs to occur after the postprocessor function implementation.
export {
## By default, an ASCII version of the the alarm log is emailed daily to any
## configured :bro:id:`Notice::mail_dest` if not operating on trace files.
redef Log::rotation_control += {
[Log::WRITER_ASCII, "alarm-mail"] =
[$interv=24hrs, $postprocessor=log_mailing_postprocessor]
};
}
event bro_init() &priority=5
{
Log::create_stream(Notice::LOG, [$columns=Info, $ev=log_notice]);
Log::create_stream(Notice::POLICY_LOG, [$columns=PolicyItem]);
Log::create_stream(Notice::ALARM_LOG, [$columns=Notice::Info]);
# If Bro is configured for mailing notices, set up mailing for alarms.
# Make sure that this alarm log is also output as text so that it can
# be packaged up and emailed later.
if ( ! reading_traces() && mail_dest != "" )
Log::add_filter(Notice::ALARM_LOG, [$name="alarm-mail",
$path="alarm-mail",
$writer=Log::WRITER_ASCII]);
}
# TODO: need a way to call a Bro script level callback during file rotation.
# we need more than a just $postprocessor.
#redef Log::rotation_control += {
# [Log::WRITER_ASCII, "alarm"] = [$postprocessor="mail-alarms"];
#};
# TODO: fix this.
#function notice_tags(n: Notice::Info) : table[string] of string
@ -220,20 +260,24 @@ event bro_init()
# return tgs;
# }
function email_headers(subject_desc: string, dest: string): string
{
local header_text = string_cat(
"From: ", mail_from, "\n",
"Subject: ", mail_subject_prefix, " ", subject_desc, "\n",
"To: ", dest, "\n",
"User-Agent: Bro-IDS/", bro_version(), "\n");
if ( reply_to != "" )
header_text = string_cat(header_text, "Reply-To: ", reply_to, "\n");
return header_text;
}
function email_notice_to(n: Notice::Info, dest: string, extend: bool)
{
if ( reading_traces() || dest == "" )
return;
local email_text = string_cat(
"From: ", mail_from, "\n",
"Subject: ", mail_subject_prefix, " ", fmt("%s", n$note), "\n",
"To: ", dest, "\n",
# TODO: BiF to get version (the resource_usage Bif seems like overkill).
"User-Agent: Bro-IDS/?.?.?\n");
if ( reply_to != "" )
email_text = string_cat(email_text, "Reply-To: ", reply_to, "\n");
local email_text = email_headers(fmt("%s", n$note), dest);
# The notice emails always start off with the human readable message.
email_text = string_cat(email_text, "\n", n$msg, "\n");
@ -257,9 +301,9 @@ event notice(n: Notice::Info) &priority=-5
if ( ACTION_EMAIL in n$actions )
email_notice_to(n, mail_dest, T);
if ( ACTION_LOG in n$actions )
Log::write(Notice::NOTICE, n);
Log::write(Notice::LOG, n);
if ( ACTION_ALARM in n$actions )
Log::write(ALARM, n);
Log::write(Notice::ALARM_LOG, n);
}
# Executes a script with all of the notice fields put into the
@ -348,10 +392,7 @@ event bro_init() &priority=10
for ( pi in policy )
{
if ( pi$priority < 0 || pi$priority > 10 )
{
print "All Notice::PolicyItem priorities must be within 0 and 10";
exit();
}
Reporter::fatal("All Notice::PolicyItem priorities must be within 0 and 10");
if ( pi$priority !in tmp )
tmp[pi$priority] = set();
@ -368,7 +409,7 @@ event bro_init() &priority=10
{
pi$position = |ordered_policy|;
ordered_policy[|ordered_policy|] = pi;
Log::write(NOTICE_POLICY, pi);
Log::write(Notice::POLICY_LOG, pi);
}
}
}

View file

@ -5,7 +5,7 @@
module Weird;
export {
redef enum Log::ID += { WEIRD };
redef enum Log::ID += { LOG };
redef enum Notice::Type += {
## Generic unusual but alarm-worthy activity.
@ -259,9 +259,9 @@ global did_inconsistency_msg: set[conn_id];
# Used to pass the optional connection into report_weird().
global current_conn: connection;
event bro_init()
event bro_init() &priority=5
{
Log::create_stream(WEIRD, [$columns=Info, $ev=log_weird]);
Log::create_stream(Weird::LOG, [$columns=Info, $ev=log_weird]);
}
function report_weird(t: time, name: string, id: string, have_conn: bool,
@ -311,7 +311,7 @@ function report_weird(t: time, name: string, id: string, have_conn: bool,
add weird_ignore[id][name];
}
Log::write(WEIRD, info);
Log::write(Weird::LOG, info);
}
function report_weird_conn(t: time, name: string, id: string, addl: string,

View file

@ -9,7 +9,7 @@
module PacketFilter;
export {
redef enum Log::ID += { PACKET_FILTER };
redef enum Log::ID += { LOG };
redef enum Notice::Type += {
## This notice is generated if a packet filter is unable to be compiled.
@ -121,7 +121,7 @@ function install()
NOTICE([$note=Compile_Failure,
$msg=fmt("Compiling packet filter failed"),
$sub=default_filter]);
exit();
Reporter::fatal(fmt("Bad pcap filter '%s'", default_filter));
}
# Do an audit log for the packet filter.
@ -144,11 +144,11 @@ function install()
$sub=default_filter]);
}
Log::write(PACKET_FILTER, info);
Log::write(PacketFilter::LOG, info);
}
event bro_init() &priority=10
{
Log::create_stream(PACKET_FILTER, [$columns=Info]);
Log::create_stream(PacketFilter::LOG, [$columns=Info]);
PacketFilter::install();
}

View file

@ -5,9 +5,13 @@
module Reporter;
export {
redef enum Log::ID += { REPORTER };
redef enum Log::ID += { LOG };
type Level: enum { INFO, WARNING, ERROR };
type Level: enum {
INFO,
WARNING,
ERROR
};
type Info: record {
ts: time &log;
@ -19,22 +23,22 @@ export {
};
}
event bro_init()
event bro_init() &priority=5
{
Log::create_stream(REPORTER, [$columns=Info]);
Log::create_stream(Reporter::LOG, [$columns=Info]);
}
event reporter_info(t: time, msg: string, location: string)
{
Log::write(REPORTER, [$ts=t, $level=INFO, $message=msg, $location=location]);
Log::write(Reporter::LOG, [$ts=t, $level=INFO, $message=msg, $location=location]);
}
event reporter_warning(t: time, msg: string, location: string)
{
Log::write(REPORTER, [$ts=t, $level=WARNING, $message=msg, $location=location]);
Log::write(Reporter::LOG, [$ts=t, $level=WARNING, $message=msg, $location=location]);
}
event reporter_error(t: time, msg: string, location: string)
{
Log::write(REPORTER, [$ts=t, $level=ERROR, $message=msg, $location=location]);
Log::write(Reporter::LOG, [$ts=t, $level=ERROR, $message=msg, $location=location]);
}

View file

@ -25,7 +25,7 @@ export {
Signature_Summary,
};
redef enum Log::ID += { SIGNATURES };
redef enum Log::ID += { LOG };
## These are the default actions you can apply to signature matches.
## All of them write the signature record to the logging stream unless
@ -114,7 +114,7 @@ global did_sig_log: set[string] &read_expire = 1 hr;
event bro_init()
{
Log::create_stream(SIGNATURES, [$columns=Info, $ev=log_signature]);
Log::create_stream(Signatures::LOG, [$columns=Info, $ev=log_signature]);
}
# Returns true if the given signature has already been triggered for the given
@ -174,7 +174,7 @@ event signature_match(state: signature_state, msg: string, data: string)
$event_msg=fmt("%s: %s", src_addr, msg),
$sig_id=sig_id,
$sub_msg=data];
Log::write(SIGNATURES, info);
Log::write(Signatures::LOG, info);
}
local notice = F;
@ -248,7 +248,7 @@ event signature_match(state: signature_state, msg: string, data: string)
fmt("%s has triggered signature %s on %d hosts",
orig, sig_id, hcount);
Log::write(SIGNATURES,
Log::write(Signatures::LOG,
[$note=Multiple_Sig_Responders,
$src_addr=orig, $sig_id=sig_id, $event_msg=msg,
$host_count=hcount, $sub_msg=horz_scan_msg]);
@ -265,7 +265,7 @@ event signature_match(state: signature_state, msg: string, data: string)
fmt("%s has triggered %d different signatures on host %s",
orig, vcount, resp);
Log::write(SIGNATURES,
Log::write(Signatures::LOG,
[$ts=network_time(),
$note=Multiple_Signatures,
$src_addr=orig,

View file

@ -11,7 +11,7 @@ module Software;
export {
redef enum Log::ID += { SOFTWARE };
redef enum Log::ID += { LOG };
type Type: enum {
UNKNOWN,
@ -103,7 +103,7 @@ export {
event bro_init()
{
Log::create_stream(SOFTWARE, [$columns=Info, $ev=log_software]);
Log::create_stream(Software::LOG, [$columns=Info, $ev=log_software]);
}
function parse_mozilla(unparsed_version: string,
@ -379,7 +379,7 @@ event software_register(id: conn_id, info: Info)
return;
}
Log::write(SOFTWARE, info);
Log::write(Software::LOG, info);
ts[info$name] = info;
}

View file

@ -3,7 +3,7 @@
module Conn;
export {
redef enum Log::ID += { CONN };
redef enum Log::ID += { LOG };
type Info: record {
## This is the time of the first packet.
@ -95,7 +95,7 @@ redef record connection += {
event bro_init() &priority=5
{
Log::create_stream(CONN, [$columns=Info, $ev=log_conn]);
Log::create_stream(Conn::LOG, [$columns=Info, $ev=log_conn]);
}
function conn_state(c: connection, trans: transport_proto): string
@ -216,6 +216,6 @@ event connection_state_remove(c: connection) &priority=5
event connection_state_remove(c: connection) &priority=-5
{
Log::write(CONN, c$conn);
Log::write(Conn::LOG, c$conn);
}

View file

@ -3,7 +3,7 @@
module DNS;
export {
redef enum Log::ID += { DNS };
redef enum Log::ID += { LOG };
type Info: record {
ts: time &log;
@ -77,7 +77,7 @@ redef dpd_config += { [ANALYZER_DNS_TCP_BINPAC] = [$ports = dns_tcp_ports] };
event bro_init() &priority=5
{
Log::create_stream(DNS, [$columns=Info, $ev=log_dns]);
Log::create_stream(DNS::LOG, [$columns=Info, $ev=log_dns]);
}
function new_session(c: connection, trans_id: count): Info
@ -163,7 +163,7 @@ event do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &pri
{
if ( c$dns$ready )
{
Log::write(DNS, c$dns);
Log::write(DNS::LOG, c$dns);
add c$dns_state$finished_answers[c$dns$trans_id];
# This record is logged and no longer pending.
delete c$dns_state$pending[c$dns$trans_id];
@ -275,6 +275,6 @@ event connection_state_remove(c: connection) &priority=-5
# If Bro is expiring state, we should go ahead and log all unlogged
# request/response pairs now.
for ( trans_id in c$dns_state$pending )
Log::write(DNS, c$dns_state$pending[trans_id]);
Log::write(DNS::LOG, c$dns_state$pending[trans_id]);
}

View file

@ -14,7 +14,7 @@
module FTP;
export {
redef enum Log::ID += { FTP };
redef enum Log::ID += { LOG };
## This setting changes if passwords used in FTP sessions are captured or not.
const default_capture_password = F &redef;
@ -95,7 +95,7 @@ global ftp_data_expected: table[addr, port] of ExpectedConn &create_expire=5mins
event bro_init() &priority=5
{
Log::create_stream(FTP, [$columns=Info, $ev=log_ftp]);
Log::create_stream(FTP::LOG, [$columns=Info, $ev=log_ftp]);
}
## A set of commands where the argument can be expected to refer
@ -165,7 +165,7 @@ function ftp_message(s: Info)
else
s$arg=arg;
Log::write(FTP, s);
Log::write(FTP::LOG, s);
}
# The MIME and file_size fields are specific to file transfer commands

View file

@ -4,7 +4,7 @@
module HTTP;
export {
redef enum Log::ID += { HTTP };
redef enum Log::ID += { LOG };
## Indicate a type of attack or compromise in the record to be logged.
type Tags: enum {
@ -86,7 +86,7 @@ redef record connection += {
# Initialize the HTTP logging stream.
event bro_init() &priority=5
{
Log::create_stream(HTTP, [$columns=Info, $ev=log_http]);
Log::create_stream(HTTP::LOG, [$columns=Info, $ev=log_http]);
}
# DPD configuration.
@ -230,7 +230,7 @@ event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) &
# The reply body is done so we're ready to log.
if ( ! is_orig )
{
Log::write(HTTP, c$http);
Log::write(HTTP::LOG, c$http);
delete c$http_state$pending[c$http_state$current_response];
}
}
@ -242,7 +242,7 @@ event connection_state_remove(c: connection)
{
for ( r in c$http_state$pending )
{
Log::write(HTTP, c$http_state$pending[r]);
Log::write(HTTP::LOG, c$http_state$pending[r]);
}
}
}

View file

@ -73,7 +73,7 @@ event file_transferred(c: connection, prefix: string, descr: string,
local tmp = irc$command;
irc$command = "DCC";
Log::write(IRC, irc);
Log::write(IRC::LOG, irc);
irc$command = tmp;
if ( irc$extract_file && irc?$extraction_file )

View file

@ -7,7 +7,7 @@
module IRC;
export {
redef enum Log::ID += { IRC };
redef enum Log::ID += { LOG };
type Tag: enum {
EMPTY
@ -44,7 +44,7 @@ redef dpd_config += { [ANALYZER_IRC] = [$ports = irc_ports] };
event bro_init() &priority=5
{
Log::create_stream(IRC, [$columns=Info, $ev=irc_log]);
Log::create_stream(IRC::LOG, [$columns=Info, $ev=irc_log]);
}
function new_session(c: connection): Info
@ -78,7 +78,7 @@ event irc_nick_message(c: connection, is_orig: bool, who: string, newnick: strin
{
if ( is_orig )
{
Log::write(IRC, c$irc);
Log::write(IRC::LOG, c$irc);
c$irc$nick = newnick;
}
}
@ -98,7 +98,7 @@ event irc_user_message(c: connection, is_orig: bool, user: string, host: string,
{
if ( is_orig )
{
Log::write(IRC, c$irc);
Log::write(IRC::LOG, c$irc);
c$irc$user = user;
}
}
@ -118,7 +118,7 @@ event irc_join_message(c: connection, is_orig: bool, info_list: irc_join_list) &
{
c$irc$value = l$channel;
c$irc$addl = (l$password != "" ? fmt(" with channel key: '%s'", l$password) : "");
Log::write(IRC, c$irc);
Log::write(IRC::LOG, c$irc);
}
}
}

View file

@ -1,4 +0,0 @@
@load ./main
@load ./file-ident
@load ./file-extract
@load ./file-hash

View file

@ -1,62 +0,0 @@
@load ./file-ident
@load base/utils/files
module MIME;
export {
## Pattern of file mime types to extract from MIME bodies.
const extract_file_types = /NO_DEFAULT/ &redef;
## The on-disk prefix for files to be extracted from MIME entity bodies.
const extraction_prefix = "mime-item" &redef;
redef record Info += {
## Optionally write the file to disk. Must be set prior to first
## data chunk being seen in an event.
extract_file: bool &default=F;
## Store the file handle here for the file currently being extracted.
extraction_file: file &log &optional;
};
redef record State += {
## Store a count of the number of files that have been transferred in
## this conversation to create unique file names on disk.
num_extracted_files: count &default=0;
};
}
event mime_segment_data(c: connection, length: count, data: string) &priority=5
{
if ( extract_file_types in c$mime$mime_type )
c$mime$extract_file = T;
}
event mime_segment_data(c: connection, length: count, data: string) &priority=3
{
if ( c$mime$extract_file && c$mime$content_len == 0 )
{
local suffix = fmt("%d.dat", ++c$mime_state$num_extracted_files);
local fname = generate_extraction_filename(extraction_prefix, c, suffix);
c$mime$extraction_file = open(fname);
enable_raw_output(c$mime$extraction_file);
}
}
event mime_segment_data(c: connection, length: count, data: string) &priority=-5
{
if ( c$mime$extract_file && c$mime?$extraction_file )
print c$mime$extraction_file, data;
}
event mime_end_entity(c: connection) &priority=-3
{
# TODO: this check is only due to a bug in mime_end_entity that
# causes the event to be generated twice for the same real event.
if ( ! c?$mime )
return;
if ( c$mime?$extraction_file )
close(c$mime$extraction_file);
}

View file

@ -1,79 +0,0 @@
@load ./file-ident
@load base/frameworks/notice
module MIME;
export {
redef enum Notice::Type += {
## Indicates that an MD5 sum was calculated for a MIME message.
MD5,
};
redef record Info += {
## The calculated MD5 sum for the MIME entity.
md5: string &log &optional;
## Optionally calculate the file's MD5 sum. Must be set prior to the
## first data chunk being see in an event.
calc_md5: bool &default=F;
## This boolean value indicates if an MD5 sum is being calculated
## for the current file transfer.
calculating_md5: bool &default=F;
};
## Generate MD5 sums for these filetypes.
const generate_md5 = /application\/x-dosexec/ # Windows and DOS executables
| /application\/x-executable/ # *NIX executable binary
&redef;
}
event mime_segment_data(c: connection, length: count, data: string) &priority=-5
{
if ( ! c?$mime ) return;
if ( c$mime$content_len == 0 )
{
if ( generate_md5 in c$mime$mime_type )
c$mime$calc_md5 = T;
if ( c$mime$calc_md5 )
{
c$mime$calculating_md5 = T;
md5_hash_init(c$id);
}
}
if ( c$mime$calculating_md5 )
md5_hash_update(c$id, data);
}
## In the event of a content gap during the MIME transfer, detect the state for
## the MD5 sum calculation and stop calculating the MD5 since it would be
## incorrect anyway.
event content_gap(c: connection, is_orig: bool, seq: count, length: count) &priority=5
{
if ( is_orig || ! c?$mime ) return;
if ( c$mime$calculating_md5 )
{
c$mime$calculating_md5 = F;
md5_hash_finish(c$id);
}
}
event mime_end_entity(c: connection) &priority=-3
{
# TODO: this check is only due to a bug in mime_end_entity that
# causes the event to be generated twice for the same real event.
if ( ! c?$mime )
return;
if ( c$mime$calculating_md5 )
{
c$mime$md5 = md5_hash_finish(c$id);
NOTICE([$note=MD5, $msg=fmt("Calculated a hash for a MIME entity from %s", c$id$orig_h),
$sub=c$mime$md5, $conn=c]);
}
}

View file

@ -1,16 +0,0 @@
@load ./main
module MIME;
export {
redef record Info += {
## Sniffed MIME type for the transfer.
mime_type: string &log &optional;
};
}
event mime_segment_data(c: connection, length: count, data: string) &priority=7
{
if ( c$mime$content_len == 0 )
c$mime$mime_type = split1(identify_data(data, T), /;/)[1];
}

View file

@ -1,101 +0,0 @@
##! The mime script does analysis of MIME encoded messages seen in certain
##! protocols (only SMTP and POP3 at the moment).
@load base/utils/strings
module MIME;
export {
redef enum Log::ID += { MIME };
# Let's assume for now that nothing transferring files using
# MIME attachments is multiplexing for simplicity's sake.
# We can make the assumption that one connection == one file (at a time)
type Info: record {
## This is the timestamp of when the MIME content transfer began.
ts: time &log;
uid: string &log;
id: conn_id &log;
## The application layer protocol over which the transfer was seen.
app_protocol: string &log &optional;
## The filename seen in the Content-Disposition header.
filename: string &log &optional;
## Track how many byte of the MIME encoded file have been seen.
content_len: count &log &default=0;
};
type State: record {
## Track the number of MIME encoded files transferred during this session.
level: count &default=0;
};
global log_mime: event(rec: Info);
}
redef record connection += {
mime: Info &optional;
mime_state: State &optional;
};
event bro_init()
{
Log::create_stream(MIME, [$columns=Info, $ev=log_mime]);
}
function new_mime_session(c: connection): Info
{
local info: Info;
info$ts=network_time();
info$uid=c$uid;
info$id=c$id;
return info;
}
function set_session(c: connection, new_entity: bool)
{
if ( ! c?$mime_state )
c$mime_state = [];
if ( ! c?$mime || new_entity )
c$mime = new_mime_session(c);
}
event mime_begin_entity(c: connection) &priority=10
{
set_session(c, T);
++c$mime_state$level;
if ( |c$service| > 0 )
c$mime$app_protocol = join_string_set(c$service, ",");
}
# This has priority -10 because other handlers need to know the current
# content_len before it's updated by this handler.
event mime_segment_data(c: connection, length: count, data: string) &priority=-10
{
c$mime$content_len = c$mime$content_len + length;
}
event mime_one_header(c: connection, h: mime_header_rec)
{
if ( h$name == "CONTENT-DISPOSITION" &&
/[fF][iI][lL][eE][nN][aA][mM][eE]/ in h$value )
c$mime$filename = sub(h$value, /^.*[fF][iI][lL][eE][nN][aA][mM][eE]=/, "");
}
event mime_end_entity(c: connection) &priority=-5
{
# This check and the delete below are just to cope with a bug where
# mime_end_entity can be generated multiple times for the same event.
if ( ! c?$mime )
return;
# Don't log anything if there wasn't any content.
if ( c$mime$content_len > 0 )
Log::write(MIME, c$mime);
delete c$mime;
}

View file

@ -12,7 +12,7 @@ export {
MD5,
};
redef enum Log::ID += { SMTP_ENTITIES };
redef enum Log::ID += { ENTITIES_LOG };
type EntityInfo: record {
## This is the timestamp of when the MIME content transfer began.
@ -74,7 +74,7 @@ export {
event bro_init() &priority=5
{
Log::create_stream(SMTP_ENTITIES, [$columns=EntityInfo, $ev=log_mime]);
Log::create_stream(SMTP::ENTITIES_LOG, [$columns=EntityInfo, $ev=log_mime]);
}
function set_session(c: connection, new_entity: bool)
@ -185,7 +185,7 @@ event mime_end_entity(c: connection) &priority=-5
# Only log is there was some content.
if ( c$smtp$current_entity$content_len > 0 )
Log::write(SMTP_ENTITIES, c$smtp$current_entity);
Log::write(SMTP::ENTITIES_LOG, c$smtp$current_entity);
delete c$smtp$current_entity;
}

View file

@ -5,7 +5,7 @@
module SMTP;
export {
redef enum Log::ID += { SMTP };
redef enum Log::ID += { LOG };
type Info: record {
ts: time &log;
@ -73,7 +73,7 @@ redef dpd_config += { [ANALYZER_SMTP] = [$ports = ports] };
event bro_init() &priority=5
{
Log::create_stream(SMTP, [$columns=SMTP::Info, $ev=log_smtp]);
Log::create_stream(SMTP::LOG, [$columns=SMTP::Info, $ev=log_smtp]);
}
function find_address_in_smtp_header(header: string): string
@ -119,7 +119,7 @@ function set_smtp_session(c: connection)
function smtp_message(c: connection)
{
if ( c$smtp$has_client_activity )
Log::write(SMTP, c$smtp);
Log::write(SMTP::LOG, c$smtp);
}
event smtp_request(c: connection, is_orig: bool, command: string, arg: string) &priority=5

View file

@ -14,7 +14,7 @@
module SSH;
export {
redef enum Log::ID += { SSH };
redef enum Log::ID += { LOG };
redef enum Notice::Type += {
## This indicates that a heuristically detected "successful" SSH
@ -79,7 +79,7 @@ redef record connection += {
event bro_init() &priority=5
{
Log::create_stream(SSH, [$columns=Info, $ev=log_ssh]);
Log::create_stream(SSH::LOG, [$columns=Info, $ev=log_ssh]);
}
function set_session(c: connection)
@ -149,11 +149,11 @@ event SSH::heuristic_successful_login(c: connection) &priority=-5
$msg="Heuristically detected successful SSH login.",
$conn=c]);
Log::write(SSH, c$ssh);
Log::write(SSH::LOG, c$ssh);
}
event SSH::heuristic_failed_login(c: connection) &priority=-5
{
Log::write(SSH, c$ssh);
Log::write(SSH::LOG, c$ssh);
}
event connection_state_remove(c: connection) &priority=-5

View file

@ -4,7 +4,7 @@
module SSL;
export {
redef enum Log::ID += { SSL };
redef enum Log::ID += { LOG };
redef enum Notice::Type += {
Self_Signed_Cert
@ -43,7 +43,7 @@ redef record connection += {
event bro_init() &priority=5
{
Log::create_stream(SSL, [$columns=Info, $ev=log_ssl]);
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl]);
}
redef capture_filters += {
@ -117,6 +117,6 @@ event ssl_established(c: connection) &priority=-5
{
set_session(c);
Log::write(SSL, c$ssl);
Log::write(SSL::LOG, c$ssl);
}

View file

@ -5,7 +5,7 @@
module Syslog;
export {
redef enum Log::ID += { SYSLOG };
redef enum Log::ID += { LOG };
type Info: record {
ts: time &log;
@ -29,7 +29,7 @@ redef record connection += {
event bro_init() &priority=5
{
Log::create_stream(SYSLOG, [$columns=Info]);
Log::create_stream(Syslog::LOG, [$columns=Info]);
}
event syslog_message(c: connection, facility: count, severity: count, msg: string) &priority=5
@ -48,5 +48,5 @@ event syslog_message(c: connection, facility: count, severity: count, msg: strin
event syslog_message(c: connection, facility: count, severity: count, msg: string) &priority=-5
{
Log::write(SYSLOG, c$syslog);
Log::write(Syslog::LOG, c$syslog);
}