diff --git a/doc/conf.py.in b/doc/conf.py.in
index 0e103b719f..2e93e82502 100644
--- a/doc/conf.py.in
+++ b/doc/conf.py.in
@@ -24,7 +24,7 @@ sys.path.insert(0, os.path.abspath('sphinx-sources/ext'))
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['bro', 'rst_directive', 'sphinx.ext.todo']
+extensions = ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static']
@@ -40,7 +40,7 @@ master_doc = 'index'
# General information about the project.
project = u'Bro'
-copyright = u'2011, The Bro Project'
+copyright = u'2012, The Bro Project'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -169,6 +169,7 @@ html_sidebars = {
# Output file base name for HTML help builder.
htmlhelp_basename = 'Broxygen'
+html_add_permalinks = None
# -- Options for LaTeX output --------------------------------------------------
@@ -208,7 +209,6 @@ latex_documents = [
# If false, no module index is generated.
#latex_domain_indices = True
-
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
diff --git a/doc/ext/adapt-toc.py b/doc/ext/adapt-toc.py
new file mode 100644
index 0000000000..12ee006977
--- /dev/null
+++ b/doc/ext/adapt-toc.py
@@ -0,0 +1,29 @@
+
+import sys
+import re
+
+# Removes the first TOC level, which is just the page title.
+def process_html_toc(app, pagename, templatename, context, doctree):
+
+ if not "toc" in context:
+ return
+
+ toc = context["toc"]
+
+ lines = toc.strip().split("\n")
+ lines = lines[2:-2]
+
+ toc = "\n".join(lines)
+ toc = "
" + toc
+
+ context["toc"] = toc
+
+ # print >>sys.stderr, pagename
+ # print >>sys.stderr, context["toc"]
+ # print >>sys.stderr, "-----"
+ # print >>sys.stderr, toc
+ # print >>sys.stderr, "===="
+
+def setup(app):
+ app.connect('html-page-context', process_html_toc)
+
diff --git a/doc/faq.rst b/doc/faq.rst
index bdb1f50292..510d03c5af 100644
--- a/doc/faq.rst
+++ b/doc/faq.rst
@@ -28,6 +28,23 @@ Here are some pointers to more information:
Lothar Braun et. al evaluates packet capture performance on
commodity hardware
+Are there any gotchas regarding interface configuration for live capture? Or why might I be seeing abnormally large packets much greater than interface MTU?
+-------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+Some NICs offload the reassembly of traffic into "superpackets" so that
+fewer packets are then passed up the stack (e.g. "TCP segmentation
+offload", or "generic segmentation offload"). The result is that the
+capturing application will observe packets much larger than the MTU size
+of the interface they were captured from and may also interfere with the
+maximum packet capture length, ``snaplen``, so it's a good idea to disable
+an interface's offloading features.
+
+You can use the ``ethtool`` program on Linux to view and disable
+offloading features of an interface. See this page for more explicit
+directions:
+
+http://securityonion.blogspot.com/2011/10/when-is-full-packet-capture-not-full.html
+
What does an error message like ``internal error: NB-DNS error`` mean?
---------------------------------------------------------------------------------------------------------------------------------
diff --git a/doc/quickstart.rst b/doc/quickstart.rst
index 0534186cde..da780e70df 100644
--- a/doc/quickstart.rst
+++ b/doc/quickstart.rst
@@ -31,15 +31,15 @@ See the `bro downloads page`_ for currently supported/targeted platforms.
* RPM
-.. console::
+ .. console::
- sudo yum localinstall Bro-all*.rpm
+ sudo yum localinstall Bro-all*.rpm
* DEB
-.. console::
+ .. console::
- sudo gdebi Bro-all-*.deb
+ sudo gdebi Bro-all-*.deb
* MacOS Disk Image with Installer
@@ -56,26 +56,32 @@ Building From Source
Required Dependencies
~~~~~~~~~~~~~~~~~~~~~
+The following dependencies are required to build Bro:
+
* RPM/RedHat-based Linux:
-.. console::
+ .. console::
- sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel
+ sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel
* DEB/Debian-based Linux:
-.. console::
+ .. console::
- sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev
+ sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev
* FreeBSD
Most required dependencies should come with a minimal FreeBSD install
except for the following.
-.. console::
+ .. console::
- sudo pkg_add -r cmake swig bison python
+ sudo pkg_add -r bash cmake swig bison python
+
+ Note that ``bash`` needs to be in ``PATH``, which by default it is
+ not. The FreeBSD package installs the binary into
+ ``/usr/local/bin``.
* Mac OS X
@@ -99,21 +105,21 @@ sending emails.
* RPM/RedHat-based Linux:
-.. console::
+ .. console::
- sudo yum install GeoIP-devel sendmail
+ sudo yum install GeoIP-devel sendmail
* DEB/Debian-based Linux:
-.. console::
+ .. console::
- sudo apt-get install libgeoip-dev sendmail
+ sudo apt-get install libgeoip-dev sendmail
* Ports-based FreeBSD
-.. console::
+ .. console::
- sudo pkg_add -r GeoIP
+ sudo pkg_add -r GeoIP
sendmail is typically already available.
diff --git a/doc/upgrade.rst b/doc/upgrade.rst
index 71cc5e401d..885f8f8b8c 100644
--- a/doc/upgrade.rst
+++ b/doc/upgrade.rst
@@ -168,10 +168,6 @@ New Default Settings
are loaded. See ``PacketFilter::all_packets`` for how to revert to old
behavior.
-- By default, Bro now sets a libpcap snaplen of 65535. Depending on
- the OS, this may have performance implications and you can use the
- ``--snaplen`` option to change the value.
-
API Changes
-----------
diff --git a/scripts/base/frameworks/notice/actions/pp-alarms.bro b/scripts/base/frameworks/notice/actions/pp-alarms.bro
index 1d6f8c7515..82fda6db6c 100644
--- a/scripts/base/frameworks/notice/actions/pp-alarms.bro
+++ b/scripts/base/frameworks/notice/actions/pp-alarms.bro
@@ -10,18 +10,21 @@ module Notice;
export {
## Activate pretty-printed alarm summaries.
const pretty_print_alarms = T &redef;
-
+
## Address to send the pretty-printed reports to. Default if not set is
## :bro:id:`Notice::mail_dest`.
const mail_dest_pretty_printed = "" &redef;
-
## If an address from one of these networks is reported, we mark
- ## the entry with an addition quote symbol (that is, ">"). Many MUAs
+ ## the entry with an additional quote symbol (i.e., ">"). Many MUAs
## then highlight such lines differently.
global flag_nets: set[subnet] &redef;
-
+
## Function that renders a single alarm. Can be overidden.
global pretty_print_alarm: function(out: file, n: Info) &redef;
+
+ ## Force generating mail file, even if reading from traces or no mail
+ ## destination is defined. This is mainly for testing.
+ global force_email_summaries = F &redef;
}
# We maintain an old-style file recording the pretty-printed alarms.
@@ -32,6 +35,9 @@ global pp_alarms_open: bool = F;
# Returns True if pretty-printed alarm summaries are activated.
function want_pp() : bool
{
+ if ( force_email_summaries )
+ return T;
+
return (pretty_print_alarms && ! reading_traces()
&& (mail_dest != "" || mail_dest_pretty_printed != ""));
}
@@ -41,38 +47,49 @@ function pp_open()
{
if ( pp_alarms_open )
return;
-
+
pp_alarms_open = T;
pp_alarms = open(pp_alarms_name);
-
- local dest = mail_dest_pretty_printed != "" ? mail_dest_pretty_printed
- : mail_dest;
-
- local headers = email_headers("Alarm summary", dest);
- write_file(pp_alarms, headers + "\n");
}
# Closes and mails out the current output file.
-function pp_send()
+function pp_send(rinfo: Log::RotationInfo)
{
if ( ! pp_alarms_open )
return;
-
+
write_file(pp_alarms, "\n\n--\n[Automatically generated]\n\n");
close(pp_alarms);
-
- system(fmt("/bin/cat %s | %s -t -oi && /bin/rm %s",
- pp_alarms_name, sendmail, pp_alarms_name));
-
pp_alarms_open = F;
+
+ local from = strftime("%H:%M:%S", rinfo$open);
+ local to = strftime("%H:%M:%S", rinfo$close);
+ local subject = fmt("Alarm summary from %s-%s", from, to);
+ local dest = mail_dest_pretty_printed != "" ? mail_dest_pretty_printed
+ : mail_dest;
+
+ if ( dest == "" )
+ # No mail destination configured, just leave the file alone. This is mainly for
+ # testing.
+ return;
+
+ local headers = email_headers(subject, dest);
+
+ local header_name = pp_alarms_name + ".tmp";
+ local header = open(header_name);
+ write_file(header, headers + "\n");
+ close(header);
+
+ system(fmt("/bin/cat %s %s | %s -t -oi && /bin/rm -f %s %s",
+ header_name, pp_alarms_name, sendmail, header_name, pp_alarms_name));
}
# Postprocessor function that triggers the email.
function pp_postprocessor(info: Log::RotationInfo): bool
{
if ( want_pp() )
- pp_send();
-
+ pp_send(info);
+
return T;
}
@@ -80,7 +97,7 @@ event bro_init()
{
if ( ! want_pp() )
return;
-
+
# This replaces the standard non-pretty-printing filter.
Log::add_filter(Notice::ALARM_LOG,
[$name="alarm-mail", $writer=Log::WRITER_NONE,
@@ -92,13 +109,13 @@ event notice(n: Notice::Info) &priority=-5
{
if ( ! want_pp() )
return;
-
- if ( ACTION_LOG !in n$actions )
+
+ if ( ACTION_ALARM !in n$actions )
return;
-
+
if ( ! pp_alarms_open )
pp_open();
-
+
pretty_print_alarm(pp_alarms, n);
}
@@ -108,12 +125,12 @@ function do_msg(out: file, n: Info, line1: string, line2: string, line3: string,
@ifdef ( Notice::ACTION_ADD_GEODATA ) # Make tests happy, cyclic dependency.
if ( n?$remote_location && n$remote_location?$country_code )
country = fmt(" (remote location %s)", n$remote_location$country_code);
-@endif
-
+@endif
+
line1 = cat(line1, country);
-
+
local resolved = "";
-
+
if ( host1 != 0.0.0.0 )
resolved = fmt("%s # %s = %s", resolved, host1, name1);
@@ -133,64 +150,64 @@ function do_msg(out: file, n: Info, line1: string, line2: string, line3: string,
function pretty_print_alarm(out: file, n: Info)
{
local pdescr = "";
-
+
@if ( Cluster::is_enabled() )
pdescr = "local";
-
+
if ( n?$src_peer )
pdescr = n$src_peer?$descr ? n$src_peer$descr : fmt("%s", n$src_peer$host);
pdescr = fmt("<%s> ", pdescr);
@endif
-
+
local msg = fmt( "%s%s", pdescr, n$msg);
-
+
local who = "";
local h1 = 0.0.0.0;
local h2 = 0.0.0.0;
-
+
local orig_p = "";
local resp_p = "";
-
+
if ( n?$id )
{
- orig_p = fmt(":%s", n$id$orig_p);
- resp_p = fmt(":%s", n$id$resp_p);
+ h1 = n$id$orig_h;
+ h2 = n$id$resp_h;
+ who = fmt("%s:%s -> %s:%s", h1, n$id$orig_p, h2, n$id$resp_p);
}
-
- if ( n?$src && n?$dst )
+ else if ( n?$src && n?$dst )
{
h1 = n$src;
h2 = n$dst;
- who = fmt("%s%s -> %s%s", h1, orig_p, h2, resp_p);
-
- if ( n?$uid )
- who = fmt("%s (uid %s)", who, n$uid );
+ who = fmt("%s -> %s", h1, h2);
}
-
else if ( n?$src )
{
- local p = "";
-
- if ( n?$p )
- p = fmt(":%s", n$p);
-
h1 = n$src;
- who = fmt("%s%s", h1, p);
+ who = fmt("%s%s", h1, (n?$p ? fmt(":%s", n$p) : ""));
}
-
+
+ if ( n?$uid )
+ who = fmt("%s (uid %s)", who, n$uid );
+
local flag = (h1 in flag_nets || h2 in flag_nets);
-
+
local line1 = fmt(">%s %D %s %s", (flag ? ">" : " "), network_time(), n$note, who);
local line2 = fmt(" %s", msg);
local line3 = n?$sub ? fmt(" %s", n$sub) : "";
-
+
if ( h1 == 0.0.0.0 )
{
do_msg(out, n, line1, line2, line3, h1, "", h2, "");
return;
}
-
+
+ if ( reading_traces() )
+ {
+ do_msg(out, n, line1, line2, line3, h1, "", h2, "");
+ return;
+ }
+
when ( local h1name = lookup_addr(h1) )
{
if ( h2 == 0.0.0.0 )
diff --git a/scripts/base/frameworks/notice/main.bro b/scripts/base/frameworks/notice/main.bro
index 9982041978..7fb8d6df77 100644
--- a/scripts/base/frameworks/notice/main.bro
+++ b/scripts/base/frameworks/notice/main.bro
@@ -73,8 +73,12 @@ export {
## reference to the actual connection will be deleted after applying
## the notice policy.
iconn: icmp_conn &optional;
-
- ## The type of the notice.
+
+ ## The transport protocol. Filled automatically when either conn, iconn
+ ## or p is specified.
+ proto: transport_proto &log &optional;
+
+ ## The :bro:enum:`Notice::Type` of the notice.
note: Type &log;
## The human readable message for the notice.
msg: string &log &optional;
@@ -535,8 +539,12 @@ function apply_policy(n: Notice::Info)
n$p = n$id$resp_p;
}
+ if ( n?$p )
+ n$proto = get_port_transport_proto(n$p);
+
if ( n?$iconn )
{
+ n$proto = icmp;
if ( ! n?$src )
n$src = n$iconn$orig_h;
if ( ! n?$dst )
diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro
index de05f93543..200947938d 100644
--- a/scripts/base/init-bare.bro
+++ b/scripts/base/init-bare.bro
@@ -2331,6 +2331,9 @@ const ignore_keep_alive_rexmit = F &redef;
## .. bro:see:: tunnel_port
const parse_udp_tunnels = F &redef;
-# Load the logging framework here because it uses fairly deep integration with
+## Number of bytes per packet to capture from live interfaces.
+const snaplen = 8192 &redef;
+
+# Load the logging framework here because it uses fairly deep integration with
# BiFs and script-land defined types.
@load base/frameworks/logging
diff --git a/scripts/base/protocols/conn/contents.bro b/scripts/base/protocols/conn/contents.bro
index feabb1303c..2e6b547ab1 100644
--- a/scripts/base/protocols/conn/contents.bro
+++ b/scripts/base/protocols/conn/contents.bro
@@ -1,23 +1,27 @@
##! This script can be used to extract either the originator's data or the
##! responders data or both. By default nothing is extracted, and in order
##! to actually extract data the ``c$extract_orig`` and/or the
-##! ``c$extract_resp`` variable must be set to T. One way to achieve this
-##! would be to handle the connection_established event elsewhere and set the
-##! extract_orig and extract_resp options there. However, there may be trouble
-##! with the timing due the event queue delay.
-##! This script does not work well in a cluster context unless it has a
-##! remotely mounted disk to write the content files to.
+##! ``c$extract_resp`` variable must be set to ``T``. One way to achieve this
+##! would be to handle the :bro:id:`connection_established` event elsewhere
+##! and set the ``extract_orig`` and ``extract_resp`` options there.
+##! However, there may be trouble with the timing due to event queue delay.
+##!
+##! .. note::
+##!
+##! This script does not work well in a cluster context unless it has a
+##! remotely mounted disk to write the content files to.
@load base/utils/files
module Conn;
export {
- ## The prefix given to files as they are opened on disk.
+ ## The prefix given to files containing extracted connections as they are
+ ## opened on disk.
const extraction_prefix = "contents" &redef;
- ## If this variable is set to T, then all contents of all files will be
- ## extracted.
+ ## If this variable is set to ``T``, then all contents of all connections
+ ## will be extracted.
const default_extract = F &redef;
}
diff --git a/scripts/base/protocols/conn/inactivity.bro b/scripts/base/protocols/conn/inactivity.bro
index 04dab62470..28df192de3 100644
--- a/scripts/base/protocols/conn/inactivity.bro
+++ b/scripts/base/protocols/conn/inactivity.bro
@@ -4,7 +4,7 @@
module Conn;
export {
- ## Define inactivty timeouts by the service detected being used over
+ ## Define inactivity timeouts by the service detected being used over
## the connection.
const analyzer_inactivity_timeouts: table[AnalyzerTag] of interval = {
# For interactive services, allow longer periods of inactivity.
diff --git a/scripts/base/protocols/conn/main.bro b/scripts/base/protocols/conn/main.bro
index 751fe8f6cf..34ec12fa56 100644
--- a/scripts/base/protocols/conn/main.bro
+++ b/scripts/base/protocols/conn/main.bro
@@ -1,17 +1,33 @@
+##! This script manages the tracking/logging of general information regarding
+##! TCP, UDP, and ICMP traffic. For UDP and ICMP, "connections" are to
+##! be interpreted using flow semantics (sequence of packets from a source
+##! host/post to a destination host/port). Further, ICMP "ports" are to
+##! be interpreted as the source port meaning the ICMP message type and
+##! the destination port being the ICMP message code.
+
@load base/utils/site
module Conn;
export {
+ ## The connection logging stream identifier.
redef enum Log::ID += { LOG };
+ ## The record type which contains column fields of the connection log.
type Info: record {
## This is the time of the first packet.
ts: time &log;
+ ## A unique identifier of a connection.
uid: string &log;
+ ## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log;
+ ## The transport layer protocol of the connection.
proto: transport_proto &log;
+ ## An identification of an application protocol being sent over the
+ ## the connection.
service: string &log &optional;
+ ## How long the connection lasted. For 3-way or 4-way connection
+ ## tear-downs, this will not include the final ACK.
duration: interval &log &optional;
## The number of payload bytes the originator sent. For TCP
## this is taken from sequence numbers and might be inaccurate
@@ -51,8 +67,8 @@ export {
## have been completed prior to the packet loss.
missed_bytes: count &log &default=0;
- ## Records the state history of (TCP) connections as
- ## a string of letters.
+ ## Records the state history of connections as a string of letters.
+ ## For TCP connections the meaning of those letters is:
##
## ====== ====================================================
## Letter Meaning
@@ -71,7 +87,8 @@ export {
## originator and lower case then means the responder.
## Also, there is compression. We only record one "d" in each direction,
## for instance. I.e., we just record that data went in that direction.
- ## This history is not meant to encode how much data that happened to be.
+ ## This history is not meant to encode how much data that happened to
+ ## be.
history: string &log &optional;
## Number of packets the originator sent.
## Only set if :bro:id:`use_conn_size_analyzer` = T
@@ -85,7 +102,9 @@ export {
## Number IP level bytes the responder sent. See ``orig_pkts``.
resp_ip_bytes: count &log &optional;
};
-
+
+ ## Event that can be handled to access the :bro:type:`Conn::Info`
+ ## record as it is sent on to the logging framework.
global log_conn: event(rec: Info);
}
diff --git a/scripts/base/protocols/dns/consts.bro b/scripts/base/protocols/dns/consts.bro
index b57170dded..fbf4aba008 100644
--- a/scripts/base/protocols/dns/consts.bro
+++ b/scripts/base/protocols/dns/consts.bro
@@ -4,9 +4,9 @@
module DNS;
export {
- const PTR = 12;
- const EDNS = 41;
- const ANY = 255;
+ const PTR = 12; ##< RR TYPE value for a domain name pointer.
+ const EDNS = 41; ##< An OPT RR TYPE value described by EDNS.
+ const ANY = 255; ##< A QTYPE value describing a request for all records.
## Mapping of DNS query type codes to human readable string representation.
const query_types = {
@@ -29,50 +29,43 @@ export {
[ANY] = "*",
} &default = function(n: count): string { return fmt("query-%d", n); };
- const code_types = {
- [0] = "X0",
- [1] = "Xfmt",
- [2] = "Xsrv",
- [3] = "Xnam",
- [4] = "Ximp",
- [5] = "X[",
- } &default="?";
-
## Errors used for non-TSIG/EDNS types.
const base_errors = {
- [0] = "NOERROR", ##< No Error
- [1] = "FORMERR", ##< Format Error
- [2] = "SERVFAIL", ##< Server Failure
- [3] = "NXDOMAIN", ##< Non-Existent Domain
- [4] = "NOTIMP", ##< Not Implemented
- [5] = "REFUSED", ##< Query Refused
- [6] = "YXDOMAIN", ##< Name Exists when it should not
- [7] = "YXRRSET", ##< RR Set Exists when it should not
- [8] = "NXRRSet", ##< RR Set that should exist does not
- [9] = "NOTAUTH", ##< Server Not Authoritative for zone
- [10] = "NOTZONE", ##< Name not contained in zone
- [11] = "unassigned-11", ##< available for assignment
- [12] = "unassigned-12", ##< available for assignment
- [13] = "unassigned-13", ##< available for assignment
- [14] = "unassigned-14", ##< available for assignment
- [15] = "unassigned-15", ##< available for assignment
- [16] = "BADVERS", ##< for EDNS, collision w/ TSIG
- [17] = "BADKEY", ##< Key not recognized
- [18] = "BADTIME", ##< Signature out of time window
- [19] = "BADMODE", ##< Bad TKEY Mode
- [20] = "BADNAME", ##< Duplicate key name
- [21] = "BADALG", ##< Algorithm not supported
- [22] = "BADTRUNC", ##< draft-ietf-dnsext-tsig-sha-05.txt
- [3842] = "BADSIG", ##< 16 <= number collision with EDNS(16);
- ##< this is a translation from TSIG(16)
+ [0] = "NOERROR", # No Error
+ [1] = "FORMERR", # Format Error
+ [2] = "SERVFAIL", # Server Failure
+ [3] = "NXDOMAIN", # Non-Existent Domain
+ [4] = "NOTIMP", # Not Implemented
+ [5] = "REFUSED", # Query Refused
+ [6] = "YXDOMAIN", # Name Exists when it should not
+ [7] = "YXRRSET", # RR Set Exists when it should not
+ [8] = "NXRRSet", # RR Set that should exist does not
+ [9] = "NOTAUTH", # Server Not Authoritative for zone
+ [10] = "NOTZONE", # Name not contained in zone
+ [11] = "unassigned-11", # available for assignment
+ [12] = "unassigned-12", # available for assignment
+ [13] = "unassigned-13", # available for assignment
+ [14] = "unassigned-14", # available for assignment
+ [15] = "unassigned-15", # available for assignment
+ [16] = "BADVERS", # for EDNS, collision w/ TSIG
+ [17] = "BADKEY", # Key not recognized
+ [18] = "BADTIME", # Signature out of time window
+ [19] = "BADMODE", # Bad TKEY Mode
+ [20] = "BADNAME", # Duplicate key name
+ [21] = "BADALG", # Algorithm not supported
+ [22] = "BADTRUNC", # draft-ietf-dnsext-tsig-sha-05.txt
+ [3842] = "BADSIG", # 16 <= number collision with EDNS(16);
+ # this is a translation from TSIG(16)
} &default = function(n: count): string { return fmt("rcode-%d", n); };
- # This deciphers EDNS Z field values.
+ ## This deciphers EDNS Z field values.
const edns_zfield = {
[0] = "NOVALUE", # regular entry
[32768] = "DNS_SEC_OK", # accepts DNS Sec RRs
} &default="?";
+ ## Possible values of the CLASS field in resource records or QCLASS field
+ ## in query messages.
const classes = {
[1] = "C_INTERNET",
[2] = "C_CSNET",
@@ -81,4 +74,4 @@ export {
[254] = "C_NONE",
[255] = "C_ANY",
} &default = function(n: count): string { return fmt("qclass-%d", n); };
-}
\ No newline at end of file
+}
diff --git a/scripts/base/protocols/dns/main.bro b/scripts/base/protocols/dns/main.bro
index b8cfc7b44e..56107fd02d 100644
--- a/scripts/base/protocols/dns/main.bro
+++ b/scripts/base/protocols/dns/main.bro
@@ -1,38 +1,80 @@
+##! Base DNS analysis script which tracks and logs DNS queries along with
+##! their responses.
+
@load ./consts
module DNS;
export {
+ ## The DNS logging stream identifier.
redef enum Log::ID += { LOG };
+ ## The record type which contains the column fields of the DNS log.
type Info: record {
+ ## The earliest time at which a DNS protocol message over the
+ ## associated connection is observed.
ts: time &log;
+ ## A unique identifier of the connection over which DNS messages
+ ## are being transferred.
uid: string &log;
+ ## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log;
+ ## The transport layer protocol of the connection.
proto: transport_proto &log;
+ ## A 16 bit identifier assigned by the program that generated the
+ ## DNS query. Also used in responses to match up replies to
+ ## outstanding queries.
trans_id: count &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.
qclass: count &log &optional;
+ ## A descriptive name for the class of the query.
qclass_name: string &log &optional;
+ ## A QTYPE value specifying the type of the query.
qtype: count &log &optional;
+ ## A descriptive name for the type of the query.
qtype_name: string &log &optional;
+ ## The response code value in DNS response messages.
rcode: count &log &optional;
+ ## A descriptive name for the response code value.
rcode_name: string &log &optional;
+ ## Whether the message is a query (F) or response (T).
QR: bool &log &default=F;
+ ## The Authoritative Answer bit for response messages specifies that
+ ## the responding name server is an authority for the domain name
+ ## in the question section.
AA: bool &log &default=F;
+ ## The Truncation bit specifies that the message was truncated.
TC: bool &log &default=F;
+ ## The Recursion Desired bit indicates to a name server to recursively
+ ## purse the query.
RD: bool &log &default=F;
+ ## The Recursion Available bit in a response message indicates if
+ ## the name server supports recursive queries.
RA: bool &log &default=F;
+ ## A reserved field that is currently supposed to be zero in all
+ ## queries and responses.
Z: count &log &default=0;
+ ## The set of resource descriptions in answer of the query.
answers: vector of string &log &optional;
+ ## The caching intervals of the associated RRs described by the
+ ## ``answers`` field.
TTLs: vector of interval &log &optional;
- ## This value indicates if this request/response pair is ready to be logged.
+ ## This value indicates if this request/response pair is ready to be
+ ## logged.
ready: bool &default=F;
+ ## The total number of resource records in a reply message's answer
+ ## section.
total_answers: count &optional;
+ ## The total number of resource records in a reply message's answer,
+ ## authority, and additional sections.
total_replies: count &optional;
};
+ ## A record type which tracks the status of DNS queries for a given
+ ## :bro:type:`connection`.
type State: record {
## Indexed by query id, returns Info record corresponding to
## query/response which haven't completed yet.
@@ -44,11 +86,21 @@ export {
finished_answers: set[count] &optional;
};
+ ## An event that can be handled to access the :bro:type:`DNS::Info`
+ ## record as it is sent to the logging framework.
global log_dns: event(rec: Info);
## This is called by the specific dns_*_reply events with a "reply" which
## may not represent the full data available from the resource record, but
## it's generally considered a summarization of the response(s).
+ ##
+ ## c: The connection record for which to fill in DNS reply data.
+ ##
+ ## msg: The DNS message header information for the response.
+ ##
+ ## ans: The general information of a RR response.
+ ##
+ ## reply: The specific response information according to RR type/class.
global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string);
}
diff --git a/scripts/base/protocols/ssl/main.bro b/scripts/base/protocols/ssl/main.bro
index 4b2fa39696..4c6721fcd8 100644
--- a/scripts/base/protocols/ssl/main.bro
+++ b/scripts/base/protocols/ssl/main.bro
@@ -1,3 +1,5 @@
+##! Base SSL analysis script.
+
@load ./consts
module SSL;
@@ -6,6 +8,7 @@ export {
redef enum Log::ID += { LOG };
type Info: record {
+ ## Time when the SSL connection began.
ts: time &log;
uid: string &log;
id: conn_id &log;
diff --git a/scripts/base/protocols/syslog/main.bro b/scripts/base/protocols/syslog/main.bro
index 2acc843ea8..f4afa6d34d 100644
--- a/scripts/base/protocols/syslog/main.bro
+++ b/scripts/base/protocols/syslog/main.bro
@@ -8,6 +8,7 @@ export {
redef enum Log::ID += { LOG };
type Info: record {
+ ## Timestamp of when the syslog message was seen.
ts: time &log;
uid: string &log;
id: conn_id &log;
diff --git a/scripts/policy/protocols/conn/known-hosts.bro b/scripts/policy/protocols/conn/known-hosts.bro
index 017b6c8a25..8914a5a22a 100644
--- a/scripts/policy/protocols/conn/known-hosts.bro
+++ b/scripts/policy/protocols/conn/known-hosts.bro
@@ -8,8 +8,10 @@
module Known;
export {
+ ## The known-hosts logging stream identifier.
redef enum Log::ID += { HOSTS_LOG };
-
+
+ ## The record type which contains the column fields of the known-hosts log.
type HostsInfo: record {
## The timestamp at which the host was detected.
ts: time &log;
@@ -19,7 +21,7 @@ export {
};
## The hosts whose existence should be logged and tracked.
- ## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS
+ ## See :bro:type:`Host` for possible choices.
const host_tracking = LOCAL_HOSTS &redef;
## The set of all known addresses to store for preventing duplicate
@@ -28,7 +30,9 @@ export {
## Maintain the list of known hosts for 24 hours so that the existence
## of each individual address is logged each day.
global known_hosts: set[addr] &create_expire=1day &synchronized &redef;
-
+
+ ## An event that can be handled to access the :bro:type:`Known::HostsInfo`
+ ## record as it is sent on to the logging framework.
global log_known_hosts: event(rec: HostsInfo);
}
diff --git a/scripts/policy/protocols/conn/known-services.bro b/scripts/policy/protocols/conn/known-services.bro
index 9d58f3a9fb..f494a30f82 100644
--- a/scripts/policy/protocols/conn/known-services.bro
+++ b/scripts/policy/protocols/conn/known-services.bro
@@ -8,29 +8,41 @@
module Known;
export {
+ ## The known-services logging stream identifier.
redef enum Log::ID += { SERVICES_LOG };
-
+
+ ## The record type which contains the column fields of the known-services
+ ## log.
type ServicesInfo: record {
+ ## The time at which the service was detected.
ts: time &log;
+ ## The host address on which the service is running.
host: addr &log;
+ ## The port number on which the service is running.
port_num: port &log;
+ ## The transport-layer protocol which the service uses.
port_proto: transport_proto &log;
+ ## A set of protocols that match the service's connection payloads.
service: set[string] &log;
-
- done: bool &default=F;
};
## The hosts whose services should be tracked and logged.
+ ## See :bro:type:`Host` for possible choices.
const service_tracking = LOCAL_HOSTS &redef;
-
+
+ ## Tracks the set of daily-detected services for preventing the logging
+ ## of duplicates, but can also be inspected by other scripts for
+ ## different purposes.
global known_services: set[addr, port] &create_expire=1day &synchronized;
-
+
+ ## Event that can be handled to access the :bro:type:`Known::ServicesInfo`
+ ## record as it is sent on to the logging framework.
global log_known_services: event(rec: ServicesInfo);
}
redef record connection += {
- ## This field is to indicate whether or not the processing for detecting
- ## and logging the service for this connection is complete.
+ # This field is to indicate whether or not the processing for detecting
+ # and logging the service for this connection is complete.
known_services_done: bool &default=F;
};
diff --git a/src/BroDoc.cc b/src/BroDoc.cc
index 91aed5ec62..b20db727ff 100644
--- a/src/BroDoc.cc
+++ b/src/BroDoc.cc
@@ -170,13 +170,26 @@ void BroDoc::WriteDocFile() const
{
WriteToDoc(".. Automatically generated. Do not edit.\n\n");
+ WriteToDoc(":tocdepth: 3\n\n");
+
WriteSectionHeading(doc_title.c_str(), '=');
- WriteToDoc("\n:download:`Original Source File <%s>`\n\n",
- downloadable_filename.c_str());
+ WriteStringList(".. bro:namespace:: %s\n", modules);
- WriteSectionHeading("Overview", '-');
- WriteStringList("%s\n", "%s\n\n", summary);
+ WriteToDoc("\n");
+
+ // WriteSectionHeading("Overview", '-');
+ WriteStringList("%s\n", summary);
+
+ WriteToDoc("\n");
+
+ if ( ! modules.empty() )
+ {
+ WriteToDoc(":Namespace%s: ", (modules.size() > 1 ? "s" : ""));
+ // WriteStringList(":bro:namespace:`%s`", modules);
+ WriteStringList("``%s``, ", "``%s``", modules);
+ WriteToDoc("\n");
+ }
if ( ! imports.empty() )
{
@@ -196,39 +209,38 @@ void BroDoc::WriteDocFile() const
WriteToDoc("\n");
}
+ WriteToDoc(":Source File: :download:`%s`\n",
+ downloadable_filename.c_str());
+
WriteToDoc("\n");
WriteInterface("Summary", '~', '#', true, true);
- if ( ! modules.empty() )
- {
- WriteSectionHeading("Namespaces", '~');
- WriteStringList(".. bro:namespace:: %s\n", modules);
- WriteToDoc("\n");
- }
-
if ( ! notices.empty() )
- WriteBroDocObjList(notices, "Notices", '~');
+ WriteBroDocObjList(notices, "Notices", '#');
- WriteInterface("Public Interface", '-', '~', true, false);
+ if ( port_analysis.size() || packet_filter.size() )
+ WriteSectionHeading("Configuration Changes", '#');
if ( ! port_analysis.empty() )
{
- WriteSectionHeading("Port Analysis", '-');
+ WriteSectionHeading("Port Analysis", '^');
WriteToDoc("Loading this script makes the following changes to "
":bro:see:`dpd_config`.\n\n");
- WriteStringList("%s", port_analysis);
+ WriteStringList("%s, ", "%s", port_analysis);
}
if ( ! packet_filter.empty() )
{
- WriteSectionHeading("Packet Filter", '-');
+ WriteSectionHeading("Packet Filter", '^');
WriteToDoc("Loading this script makes the following changes to "
":bro:see:`capture_filters`.\n\n");
WriteToDoc("Filters added::\n\n");
WriteToDoc("%s\n", packet_filter.c_str());
}
+ WriteInterface("Detailed Interface", '~', '#', true, false);
+
#if 0 // Disabled for now.
BroDocObjList::const_iterator it;
bool hasPrivateIdentifiers = false;
@@ -243,7 +255,7 @@ void BroDoc::WriteDocFile() const
}
if ( hasPrivateIdentifiers )
- WriteInterface("Private Interface", '-', '~', false, false);
+ WriteInterface("Private Interface", '~', '#', false, false);
#endif
}
diff --git a/src/SSLv2.cc b/src/SSLv2.cc
deleted file mode 100644
index 9fa654048d..0000000000
--- a/src/SSLv2.cc
+++ /dev/null
@@ -1,944 +0,0 @@
-#include "SSLv2.h"
-#include "SSLv3.h"
-
-// --- Initalization of static variables --------------------------------------
-
-uint SSLv2_Interpreter::totalConnections = 0;
-uint SSLv2_Interpreter::analyzedConnections = 0;
-uint SSLv2_Interpreter::openedConnections = 0;
-uint SSLv2_Interpreter::failedConnections = 0;
-uint SSLv2_Interpreter::weirdConnections = 0;
-uint SSLv2_Interpreter::totalRecords = 0;
-uint SSLv2_Interpreter::clientHelloRecords = 0;
-uint SSLv2_Interpreter::serverHelloRecords = 0;
-uint SSLv2_Interpreter::clientMasterKeyRecords = 0;
-uint SSLv2_Interpreter::errorRecords = 0;
-
-
-// --- SSLv2_Interpreter -------------------------------------------------------
-
-/*!
- * The Constructor.
- *
- * \param proxy Pointer to the SSLProxy_Analyzer who created this instance.
- */
-SSLv2_Interpreter::SSLv2_Interpreter(SSLProxy_Analyzer* proxy)
-: SSL_Interpreter(proxy)
- {
- ++totalConnections;
- records = 0;
- bAnalyzedCounted = false;
- connState = START;
-
- pServerCipherSpecs = 0;
- pClientCipherSpecs = 0;
- bClientWantsCachedSession = false;
- usedCipherSpec = (SSLv2_CipherSpec) 0;
-
- pConnectionId = 0;
- pChallenge = 0;
- pSessionId = 0;
- pMasterClearKey = 0;
- pMasterEncryptedKey = 0;
- pClientReadKey = 0;
- pServerReadKey = 0;
- }
-
-/*!
- * The Destructor.
- */
-SSLv2_Interpreter::~SSLv2_Interpreter()
- {
- if ( connState != CLIENT_MASTERKEY_SEEN &&
- connState != CACHED_SESSION &&
- connState != START && // we only complain if we saw some data
- connState != ERROR_SEEN )
- ++failedConnections;
-
- if ( connState != CLIENT_MASTERKEY_SEEN && connState != CACHED_SESSION )
- ++weirdConnections;
-
- delete pServerCipherSpecs;
- delete pClientCipherSpecs;
- delete pConnectionId;
- delete pChallenge;
- delete pSessionId;
- delete pMasterClearKey;
- delete pMasterEncryptedKey;
- delete pClientReadKey;
- delete pServerReadKey;
- }
-
-/*!
- * This method implements SSL_Interpreter::BuildInterpreterEndpoints()
- */
-void SSLv2_Interpreter::BuildInterpreterEndpoints()
- {
- orig = new SSLv2_Endpoint(this, 1);
- resp = new SSLv2_Endpoint(this, 0);
- }
-
-/*!
- * This method prints some counters.
- */
-void SSLv2_Interpreter::printStats()
- {
- printf("SSLv2:\n");
- printf("totalConnections = %u\n", totalConnections);
- printf("analyzedConnections = %u\n", analyzedConnections);
- printf("openedConnections = %u\n", openedConnections);
- printf("failedConnections = %u\n", failedConnections);
- printf("weirdConnections = %u\n", weirdConnections);
-
- printf("totalRecords = %u\n", totalRecords);
- printf("clientHelloRecords = %u\n", clientHelloRecords);
- printf("serverHelloRecords = %u\n", serverHelloRecords);
- printf("clientMasterKeyRecords = %u\n", clientMasterKeyRecords);
- printf("errorRecords = %u\n", errorRecords);
-
- printf("SSL_RecordBuilder::maxAllocCount = %u\n", SSL_RecordBuilder::maxAllocCount);
- printf("SSL_RecordBuilder::maxFragmentCount = %u\n", SSL_RecordBuilder::maxFragmentCount);
- printf("SSL_RecordBuilder::fragmentedHeaders = %u\n", SSL_RecordBuilder::fragmentedHeaders);
- }
-
-/*!
- * \return the current state of the ssl connection
- */
-SSLv2_States SSLv2_Interpreter::ConnState()
- {
- return connState;
- }
-
-/*!
- * This method is called by SSLv2_Endpoint::Deliver(). It is the main entry
- * point of this class. The header of the given SSLV2 record is analyzed and
- * its contents are then passed to the corresponding analyzer method. After
- * the record has been analyzed, the ssl connection state is updated.
- *
- * \param s Pointer to the endpoint which sent the record
- * \param length length of SSLv2 record
- * \param data pointer to SSLv2 record to analyze
- */
-void SSLv2_Interpreter::NewSSLRecord(SSL_InterpreterEndpoint* s,
- int length, const u_char* data)
- {
- ++records;
- ++totalRecords;
-
- if ( ! bAnalyzedCounted )
- {
- ++analyzedConnections;
- bAnalyzedCounted = true;
- }
-
- // We should see a maximum of 4 cleartext records.
- if ( records == 5 )
- { // so this should never happen
- Weird("SSLv2: Saw more than 4 records, skipping connection...");
- proxy->SetSkip(1);
- return;
- }
-
- // SSLv2 record header analysis
- uint32 recordLength = 0; // data length of SSLv2 record
- bool isEscape = false;
- uint8 padding = 0;
- const u_char* contents;
-
- if ( (data[0] & 0x80) > 0 )
- { // we have a two-byte record header
- recordLength = ((data[0] & 0x7f) << 8) | data[1];
- contents = data + 2;
- if ( recordLength + 2 != uint32(length) )
- {
- // This should never happen, otherwise
- // we have a bug in the SSL_RecordBuilder.
- Weird("SSLv2: FATAL: recordLength doesn't match data block length!");
- connState = ERROR_REQUIRED;
- proxy->SetSkip(1);
- return;
- }
- }
- else
- { // We have a three-byte record header.
- recordLength = ((data[0] & 0x3f) << 8) | data[1];
- isEscape = (data[0] & 0x40) != 0;
- padding = data[2];
- contents = data + 3;
- if ( recordLength + 3 != uint32(length) )
- {
- // This should never happen, otherwise
- // we have a bug in the SSL_RecordBuilder.
- Weird("SSLv2: FATAL: recordLength doesn't match data block length!");
- connState = ERROR_REQUIRED;
- proxy->SetSkip(1);
- return;
- }
-
- if ( padding == 0 && ! isEscape )
- Weird("SSLv2: 3 Byte record header, but no escape, no padding!");
- }
-
- if ( recordLength == 0 )
- {
- Weird("SSLv2: Record length is zero (no record data)!");
- return;
- }
-
- if ( isEscape )
- Weird("SSLv2: Record has escape bit set (security escape)!");
-
- if ( padding > 0 && connState != CACHED_SESSION &&
- connState != CLIENT_MASTERKEY_SEEN )
- Weird("SSLv2 record with padding > 0 in cleartext!");
-
- // MISSING:
- // A final consistency check is done when a block cipher is used
- // and the protocol is using encryption. The amount of data present
- // in a record (RECORD-LENGTH))must be a multiple of the cipher's
- // block size. If the received record is not a multiple of the
- // cipher's block size then the record is considered damaged, and it
- // is to be treated as if an "I/O Error" had occurred (i.e. an
- // unrecoverable error is asserted and the connection is closed).
-
- switch ( connState ) {
- case START:
- // Only CLIENT-HELLLOs allowed here.
- if ( contents[0] != SSLv2_MT_CLIENT_HELLO )
- {
- Weird("SSLv2: First packet is not a CLIENT-HELLO!");
- analyzeRecord(s, recordLength, contents);
- connState = ERROR_REQUIRED;
- }
- else
- connState = ClientHelloRecord(s, recordLength, contents);
- break;
-
- case CLIENT_HELLO_SEEN:
- // Only SERVER-HELLOs or ERRORs allowed here.
- if ( contents[0] == SSLv2_MT_SERVER_HELLO )
- connState = ServerHelloRecord(s, recordLength, contents);
- else if ( contents[0] == SSLv2_MT_ERROR )
- connState = ErrorRecord(s, recordLength, contents);
- else
- {
- Weird("SSLv2: State violation in CLIENT_HELLO_SEEN!");
- analyzeRecord(s, recordLength, contents);
- connState = ERROR_REQUIRED;
- }
- break;
-
- case NEW_SESSION:
- // We expect a client master key.
- if ( contents[0] == SSLv2_MT_CLIENT_MASTER_KEY )
- connState = ClientMasterKeyRecord(s, recordLength, contents);
- else if ( contents[0] == SSLv2_MT_ERROR )
- connState = ErrorRecord(s, recordLength, contents);
- else
- {
- Weird("SSLv2: State violation in NEW_SESSION or encrypted record!");
- analyzeRecord(s, recordLength, contents);
- connState = ERROR_REQUIRED;
- }
-
- delete pServerCipherSpecs;
- pServerCipherSpecs = 0;
- break;
-
- case CACHED_SESSION:
- delete pServerCipherSpecs;
- pServerCipherSpecs = 0;
- // No break here.
-
- case CLIENT_MASTERKEY_SEEN:
- // If no error record, no further analysis.
- if ( contents[0] == SSLv2_MT_ERROR &&
- recordLength == SSLv2_ERROR_RECORD_SIZE )
- connState = ErrorRecord(s, recordLength, contents);
- else
- {
- // So we finished the cleartext handshake.
- // Skip all further data.
-
- proxy->SetSkip(1);
- ++openedConnections;
- }
- break;
-
- case ERROR_REQUIRED:
- if ( contents[0] == SSLv2_MT_ERROR )
- connState = ErrorRecord(s, recordLength, contents);
- else
- {
- // We lost tracking: this should not happen.
- Weird("SSLv2: State inconsistency in ERROR_REQUIRED (lost tracking!)!");
- analyzeRecord(s, recordLength, contents);
- connState = ERROR_REQUIRED;
- }
- break;
-
- case ERROR_SEEN:
- // We don't have recoverable errors in cleartext phase,
- // so we shouldn't see anymore packets.
- Weird("SSLv2: Traffic after error record!");
- analyzeRecord(s, recordLength, contents);
- break;
-
- default:
- reporter->InternalError("SSLv2: unknown state");
- break;
- }
- }
-
-/*!
- * This method is called whenever the connection tracking failed. It calls
- * the corresponding analyzer method for the given SSLv2 record, but does not
- * update the ssl connection state.
- *
- * \param s Pointer to the endpoint which sent the record
- * \param length length of SSLv2 record
- * \param data pointer to SSLv2 record to analyze
- */
-void SSLv2_Interpreter::analyzeRecord(SSL_InterpreterEndpoint* s,
- int length, const u_char* data)
- {
- switch ( data[0] ) {
- case SSLv2_MT_ERROR:
- ErrorRecord(s, length, data);
- break;
-
- case SSLv2_MT_CLIENT_HELLO:
- ClientHelloRecord(s, length, data);
- break;
-
- case SSLv2_MT_CLIENT_MASTER_KEY:
- ClientMasterKeyRecord(s, length, data);
- break;
-
- case SSLv2_MT_SERVER_HELLO:
- ServerHelloRecord(s, length, data);
- break;
-
- case SSLv2_MT_CLIENT_FINISHED:
- case SSLv2_MT_SERVER_VERIFY:
- case SSLv2_MT_SERVER_FINISHED:
- case SSLv2_MT_REQUEST_CERTIFICATE:
- case SSLv2_MT_CLIENT_CERTIFICATE:
- Weird("SSLv2: Encrypted record type seems to be in cleartext");
- break;
-
- default:
- // Unknown record type.
- Weird("SSLv2: Unknown record type or encrypted record");
- break;
- }
- }
-
-/*!
- * This method analyses a SSLv2 CLIENT-HELLO record.
- *
- * \param s Pointer to the endpoint which sent the record
- * \param length length of SSLv2 CLIENT-HELLO record
- * \param data pointer to SSLv2 CLIENT-HELLO record to analyze
- *
- * \return the updated state of the current ssl connection
- */
-SSLv2_States SSLv2_Interpreter::ClientHelloRecord(SSL_InterpreterEndpoint* s,
- int recordLength, const u_char* recordData)
- {
- // This method gets the record's data (without the header).
- ++clientHelloRecords;
-
- if ( s != orig )
- Weird("SSLv2: CLIENT-HELLO record from server!");
-
- // There should not be any pending data in the SSLv2 reassembler,
- // because the client should wait for a server response.
- if ( ((SSLv2_Endpoint*) s)->isDataPending() )
- Weird("SSLv2: Pending data in SSL_RecordBuilder after CLIENT-HELLO!");
-
- // Client hello minimum header size check.
- if ( recordLength < SSLv2_CLIENT_HELLO_HEADER_SIZE )
- {
- Weird("SSLv2: CLIENT-HELLO is too small!");
- return ERROR_REQUIRED;
- }
-
- // Extract the data of the client hello header.
- SSLv2_ClientHelloHeader ch;
- ch.clientVersion = uint16(recordData[1] << 8) | recordData[2];
- ch.cipherSpecLength = uint16(recordData[3] << 8) | recordData[4];
- ch.sessionIdLength = uint16(recordData[5] << 8) | recordData[6];
- ch.challengeLength = uint16(recordData[7] << 8) | recordData[8];
-
- if ( ch.clientVersion != SSLProxy_Analyzer::SSLv20 &&
- ch.clientVersion != SSLProxy_Analyzer::SSLv30 &&
- ch.clientVersion != SSLProxy_Analyzer::SSLv31 )
- {
- Weird("SSLv2: Unsupported SSL-Version in CLIENT-HELLO");
- return ERROR_REQUIRED;
- }
-
- if ( ch.challengeLength + ch.cipherSpecLength + ch.sessionIdLength +
- SSLv2_CLIENT_HELLO_HEADER_SIZE != recordLength )
- {
- Weird("SSLv2: Size inconsistency in CLIENT-HELLO");
- return ERROR_REQUIRED;
- }
-
- // The CIPHER-SPECS-LENGTH must be > 0 and a multiple of 3.
- if ( ch.cipherSpecLength == 0 || ch.cipherSpecLength % 3 != 0 )
- {
- Weird("SSLv2: Nonconform CIPHER-SPECS-LENGTH in CLIENT-HELLO.");
- return ERROR_REQUIRED;
- }
-
- // The SESSION-ID-LENGTH must either be zero or 16.
- if ( ch.sessionIdLength != 0 && ch.sessionIdLength != 16 )
- Weird("SSLv2: Nonconform SESSION-ID-LENGTH in CLIENT-HELLO.");
-
- if ( (ch.challengeLength < 16) || (ch.challengeLength > 32))
- Weird("SSLv2: Nonconform CHALLENGE-LENGTH in CLIENT-HELLO.");
-
- const u_char* ptr = recordData;
- ptr += SSLv2_CLIENT_HELLO_HEADER_SIZE + ch.cipherSpecLength;
-
- pSessionId = new SSL_DataBlock(ptr, ch.sessionIdLength);
-
- // If decrypting, store the challenge.
- if ( ssl_store_key_material && ch.challengeLength <= 32 )
- pChallenge = new SSL_DataBlock(ptr, ch.challengeLength);
-
- bClientWantsCachedSession = ch.sessionIdLength != 0;
-
- TableVal* currentCipherSuites =
- analyzeCiphers(s, ch.cipherSpecLength,
- recordData + SSLv2_CLIENT_HELLO_HEADER_SIZE);
-
- fire_ssl_conn_attempt(ch.clientVersion, currentCipherSuites);
-
- return CLIENT_HELLO_SEEN;
- }
-
-/*!
- * This method analyses a SSLv2 SERVER-HELLO record.
- *
- * \param s Pointer to the endpoint which sent the record
- * \param length length of SSLv2 SERVER-HELLO record
- * \param data pointer to SSLv2 SERVER-HELLO record to analyze
- *
- * \return the updated state of the current ssl connection
- */
-SSLv2_States SSLv2_Interpreter::ServerHelloRecord(SSL_InterpreterEndpoint* s,
- int recordLength, const u_char* recordData)
- {
- ++serverHelloRecords;
- TableVal* currentCipherSuites = NULL;
-
- if ( s != resp )
- Weird("SSLv2: SERVER-HELLO from client!");
-
- if ( recordLength < SSLv2_SERVER_HELLO_HEADER_SIZE )
- {
- Weird("SSLv2: SERVER-HELLO is too small!");
- return ERROR_REQUIRED;
- }
-
- // Extract the data of the client hello header.
- SSLv2_ServerHelloHeader sh;
- sh.sessionIdHit = recordData[1];
- sh.certificateType = recordData[2];
- sh.serverVersion = uint16(recordData[3] << 8) | recordData[4];
- sh.certificateLength = uint16(recordData[5] << 8) | recordData[6];
- sh.cipherSpecLength = uint16(recordData[7] << 8) | recordData[8];
- sh.connectionIdLength = uint16(recordData[9] << 8) | recordData[10];
-
- if ( sh.serverVersion != SSLProxy_Analyzer::SSLv20 )
- {
- Weird("SSLv2: Unsupported SSL-Version in SERVER-HELLO");
- return ERROR_REQUIRED;
- }
-
- if ( sh.certificateLength + sh.cipherSpecLength +
- sh.connectionIdLength +
- SSLv2_SERVER_HELLO_HEADER_SIZE != recordLength )
- {
- Weird("SSLv2: Size inconsistency in SERVER-HELLO");
- return ERROR_REQUIRED;
- }
-
- // The length of the CONNECTION-ID must be between 16 and 32 bytes.
- if ( sh.connectionIdLength < 16 || sh.connectionIdLength > 32 )
- Weird("SSLv2: Nonconform CONNECTION-ID-LENGTH in SERVER-HELLO");
-
- // If decrypting, store the connection ID.
- if ( ssl_store_key_material && sh.connectionIdLength <= 32 )
- {
- const u_char* ptr = recordData;
-
- ptr += SSLv2_SERVER_HELLO_HEADER_SIZE + sh.cipherSpecLength +
- sh.certificateLength;
-
- pConnectionId = new SSL_DataBlock(ptr, sh.connectionIdLength);
- }
-
- if ( sh.sessionIdHit == 0 )
- {
- // Generating reusing-connection event.
- EventHandlerPtr event = ssl_session_insertion;
-
- if ( event )
- {
- TableVal* sessionIDTable =
- MakeSessionID(
- recordData +
- SSLv2_SERVER_HELLO_HEADER_SIZE +
- sh.certificateLength +
- sh.cipherSpecLength,
- sh.connectionIdLength);
-
- val_list* vl = new val_list;
- vl->append(proxy->BuildConnVal());
- vl->append(sessionIDTable);
-
- proxy->ConnectionEvent(ssl_session_insertion, vl);
- }
- }
-
- SSLv2_States nextState;
-
- if ( sh.sessionIdHit != 0 )
- { // we're using a cached session
-
- // There should not be any pending data in the SSLv2
- // reassembler, because the server should wait for a
- // client response.
- if ( ((SSLv2_Endpoint*) s)->isDataPending() )
- {
- // But turns out some SSL Implementations do this
- // when using a cached session.
- }
-
- // Consistency check for SESSION-ID-HIT.
- if ( ! bClientWantsCachedSession )
- Weird("SSLv2: SESSION-ID hit in SERVER-HELLO, but no SESSION-ID in CLIENT-HELLO!");
-
- // If the SESSION-ID-HIT flag is non-zero then the
- // CERTIFICATE-TYPE, CERTIFICATE-LENGTH and
- // CIPHER-SPECS-LENGTH fields will be zero.
- if ( sh.certificateType != 0 || sh.certificateLength != 0 ||
- sh.cipherSpecLength != 0 )
- Weird("SSLv2: SESSION-ID-HIT, but session data in SERVER-HELLO");
-
- // Generate reusing-connection event.
- if ( pSessionId )
- {
- fire_ssl_conn_reused(pSessionId);
- delete pSessionId;
- pSessionId = 0;
- }
-
- nextState = CACHED_SESSION;
- }
- else
- { // we're starting a new session
-
- // There should not be any pending data in the SSLv2
- // reassembler, because the server should wait for
- // a client response.
- if ( ((SSLv2_Endpoint*) s)->isDataPending() )
- Weird("SSLv2: Pending data in SSL_RecordBuilder after SERVER-HELLO (new session)!");
-
- // TODO: check certificate length ???
- if ( sh.certificateLength == 0 )
- Weird("SSLv2: No certificate in SERVER-HELLO!");
-
- // The CIPHER-SPECS-LENGTH must be > zero and a multiple of 3.
- if ( sh.cipherSpecLength == 0 )
- Weird("SSLv2: No CIPHER-SPECS in SERVER-HELLO!");
-
- if ( sh.cipherSpecLength % 3 != 0 )
- {
- Weird("SSLv2: Nonconform CIPHER-SPECS-LENGTH in SERVER-HELLO");
- return ERROR_REQUIRED;
- }
-
- const u_char* ptr = recordData;
- ptr += sh.certificateLength + SSLv2_SERVER_HELLO_HEADER_SIZE;
- currentCipherSuites = analyzeCiphers(s, sh.cipherSpecLength, ptr);
-
- nextState = NEW_SESSION;
- }
-
- // Check if at least one cipher is supported by the client.
- if ( pClientCipherSpecs && pServerCipherSpecs )
- {
- bool bFound = false;
- for ( int i = 0; i < pClientCipherSpecs->len; i += 3 )
- {
- for ( int j = 0; j < pServerCipherSpecs->len; j += 3 )
- {
- if ( memcmp(pClientCipherSpecs + i,
- pServerCipherSpecs + j, 3) == 0 )
- {
- bFound = true;
- i = pClientCipherSpecs->len;
- break;
- }
- }
- }
-
- if ( ! bFound )
- {
- Weird("SSLv2: Client's and server's CIPHER-SPECS don't match!");
- nextState = ERROR_REQUIRED;
- }
-
- delete pClientCipherSpecs;
- pClientCipherSpecs = 0;
- }
-
- // Certificate analysis.
- if ( sh.certificateLength > 0 && ssl_analyze_certificates != 0 )
- {
- analyzeCertificate(s, recordData + SSLv2_SERVER_HELLO_HEADER_SIZE,
- sh.certificateLength, sh.certificateType, false);
- }
-
- if ( nextState == NEW_SESSION )
- // generate server-reply event
- fire_ssl_conn_server_reply(sh.serverVersion, currentCipherSuites);
-
- else if ( nextState == CACHED_SESSION )
- { // generate server-reply event
- fire_ssl_conn_server_reply(sh.serverVersion, currentCipherSuites);
- // Generate a connection-established event with a dummy
- // cipher suite, since we can't remember session information
- // (yet).
- // Note: A new session identifier is sent encrypted in SSLv2!
- fire_ssl_conn_established(sh.serverVersion, 0xABCD);
- }
- else
- // Unref, since the table is not delivered to any event.
- Unref(currentCipherSuites);
-
- return nextState;
- }
-
-/*!
- * This method analyses a SSLv2 CLIENT-MASTER-KEY record.
- *
- * \param s Pointer to the endpoint which sent the record
- * \param length length of SSLv2 CLIENT-MASTER-KEY record
- * \param data pointer to SSLv2 CLIENT-MASTER-KEY record to analyze
- *
- * \return the updated state of the current ssl connection
- */
-SSLv2_States SSLv2_Interpreter::
- ClientMasterKeyRecord(SSL_InterpreterEndpoint* s, int recordLength,
- const u_char* recordData)
- {
- ++clientMasterKeyRecords;
- SSLv2_States nextState = CLIENT_MASTERKEY_SEEN;
-
- if ( s != orig )
- Weird("SSLv2: CLIENT-MASTER-KEY from server!");
-
- if ( recordLength < SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE )
- {
- Weird("SSLv2: CLIENT-MASTER-KEY is too small!");
- return ERROR_REQUIRED;
- }
-
- // Extract the data of the client master key header.
- SSLv2_ClientMasterKeyHeader cmk;
- cmk.cipherKind =
- ((recordData[1] << 16) | recordData[2] << 8) | recordData[3];
- cmk.clearKeyLength = uint16(recordData[4] << 8) | recordData[5];
- cmk.encryptedKeyLength = uint16(recordData[6] << 8) | recordData[7];
- cmk.keyArgLength = uint16(recordData[8] << 8) | recordData[9];
-
- if ( cmk.clearKeyLength + cmk.encryptedKeyLength + cmk.keyArgLength +
- SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE != recordLength )
- {
- Weird("SSLv2: Size inconsistency in CLIENT-MASTER-KEY");
- return ERROR_REQUIRED;
- }
-
- // Check if cipher is supported by the server.
- if ( pServerCipherSpecs )
- {
- bool bFound = false;
- for ( int i = 0; i < pServerCipherSpecs->len; i += 3 )
- {
- uint32 cipherSpec =
- ((pServerCipherSpecs->data[i] << 16) |
- pServerCipherSpecs->data[i+1] << 8) |
- pServerCipherSpecs->data[i+2];
-
- if ( cmk.cipherKind == cipherSpec )
- {
- bFound = true;
- break;
- }
- }
-
- if ( ! bFound )
- {
- Weird("SSLv2: Client chooses unadvertised cipher in CLIENT-MASTER-KEY!");
- nextState = ERROR_REQUIRED;
- }
- else
- nextState = CLIENT_MASTERKEY_SEEN;
-
- delete pServerCipherSpecs;
- pServerCipherSpecs = 0;
- }
-
- // TODO: check if cipher has been advertised before.
-
- SSL_CipherSpec* pCipherSpecTemp = 0;
-
- HashKey h(static_cast(cmk.cipherKind));
- pCipherSpecTemp = (SSL_CipherSpec*) SSL_CipherSpecDict.Lookup(&h);
- if ( ! pCipherSpecTemp || ! (pCipherSpecTemp->flags & SSL_FLAG_SSLv20) )
- Weird("SSLv2: Unknown CIPHER-SPEC in CLIENT-MASTER-KEY!");
- else
- { // check for conistency of clearKeyLength
- if ( cmk.clearKeyLength * 8 != pCipherSpecTemp->clearKeySize )
- {
- Weird("SSLv2: Inconsistency of clearKeyLength in CLIENT-MASTER-KEY!");
- // nextState = ERROR_REQUIRED;
- }
-
- // TODO: check for consistency of encryptedKeyLength.
- // TODO: check for consistency of keyArgLength.
-// switch ( cmk.cipherKind )
-// {
-// case SSL_CK_RC4_128_WITH_MD5:
-// case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
-// if ( cmk.keyArgLength != 0 )
-// {
-// Weird("SSLv2: Inconsistency of keyArgLength in CLIENT-MASTER-KEY!");
-// //nextState = ERROR_REQUIRED;
-// }
-// break;
-// case SSL_CK_DES_64_CBC_WITH_MD5:
-// case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
-// case SSL_CK_RC2_128_CBC_WITH_MD5:
-// case SSL_CK_IDEA_128_CBC_WITH_MD5:
-// case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
-// if ( cmk.keyArgLength != 8 )
-// {
-// Weird("SSLv2: Inconsistency of keyArgLength in CLIENT-MASTER-KEY!");
-// }
-// break;
-// }
- }
-
- // Remember the used cipher spec.
- usedCipherSpec = SSLv2_CipherSpec(cmk.cipherKind);
-
- // If decrypting, store the clear key part of the master key.
- if ( ssl_store_key_material /* && cmk.clearKeyLength == 11 */ )
- {
- pMasterClearKey =
- new SSL_DataBlock((recordData + SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE), cmk.clearKeyLength);
-
- pMasterEncryptedKey =
- new SSL_DataBlock((recordData + SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE + cmk.clearKeyLength ), cmk.encryptedKeyLength);
- }
-
- if ( nextState == CLIENT_MASTERKEY_SEEN )
- fire_ssl_conn_established(SSLProxy_Analyzer::SSLv20,
- cmk.cipherKind);
-
- return nextState;
- }
-
-
-/*!
- * This method analyses a SSLv2 ERROR record.
- *
- * \param s Pointer to the endpoint which sent the record
- * \param length length of SSLv2 ERROR record
- * \param data pointer to SSLv2 ERROR record to analyze
- *
- * \return the updated state of the current ssl connection
- */
-SSLv2_States SSLv2_Interpreter::ErrorRecord(SSL_InterpreterEndpoint* s,
- int recordLength, const u_char* recordData)
- {
- ++errorRecords;
-
- if ( unsigned(recordLength) != SSLv2_ERROR_RECORD_SIZE )
- {
- Weird("SSLv2: Size mismatch in Error Record!");
- return ERROR_REQUIRED;
- }
-
- SSLv2_ErrorRecord er;
- er.errorCode = (recordData[1] << 8) | recordData[2];
- SSL3x_AlertLevel al = SSL3x_AlertLevel(255);
-
- switch ( er.errorCode ) {
- case SSLv2_PE_NO_CIPHER:
- // The client doesn't support a cipher which the server
- // supports. Only from client to server and not recoverable!
- al = SSL3x_ALERT_LEVEL_FATAL;
- break;
-
- case SSLv2_PE_NO_CERTIFICATE:
- if ( s == orig )
- // from client to server: not recoverable
- al = SSL3x_ALERT_LEVEL_FATAL;
- else
- // from server to client: recoverable
- al = SSL3x_ALERT_LEVEL_WARNING;
- break;
-
- case SSLv2_PE_BAD_CERTIFICATE:
- if ( s == orig )
- // from client to server: not recoverable
- al = SSL3x_ALERT_LEVEL_FATAL;
- else
- // from server to client: recoverable
- al = SSL3x_ALERT_LEVEL_WARNING;
- break;
-
- case SSLv2_PE_UNSUPPORTED_CERTIFICATE_TYPE:
- if ( s == orig )
- // from client to server: not recoverable
- al = SSL3x_ALERT_LEVEL_FATAL;
- else
- // from server to client: recoverable
- al = SSL3x_ALERT_LEVEL_WARNING;
- break;
-
- default:
- al = SSL3x_ALERT_LEVEL_FATAL;
- break;
- }
-
- fire_ssl_conn_alert(SSLProxy_Analyzer::SSLv20, al, er.errorCode);
-
- return ERROR_SEEN;
- }
-
-/*!
- * This method analyses a set of SSLv2 cipher suites.
- *
- * \param s Pointer to the endpoint which sent the cipher suites
- * \param length length of cipher suites
- * \param data pointer to cipher suites to analyze
- *
- * \return a pointer to a Bro TableVal (of type cipher_suites_list) which contains
- * the cipher suites list of the current analyzed record
- */
-TableVal* SSLv2_Interpreter::analyzeCiphers(SSL_InterpreterEndpoint* s,
- int length, const u_char* data)
- {
- if ( length > MAX_CIPHERSPEC_SIZE )
- {
- if ( s == orig )
- Weird("SSLv2: Client has CipherSpecs > MAX_CIPHERSPEC_SIZE");
- else
- Weird("SSLv2: Server has CipherSpecs > MAX_CIPHERSPEC_SIZE");
- }
- else
- { // cipher specs are not too big
- if ( ssl_compare_cipherspecs )
- { // store cipher specs for state analysis
- if ( s == resp )
- pServerCipherSpecs =
- new SSL_DataBlock(data, length);
- else
- pClientCipherSpecs =
- new SSL_DataBlock(data, length);
- }
- }
-
- const u_char* pCipher = data;
- bool bExtractCipherSuite = false;
- TableVal* pCipherTable = 0;
-
- // We only extract the cipher suite when the corresponding
- // ssl events are defined (otherwise we do work for nothing
- // and suffer a memory leak).
- // FIXME: This check needs to be done only once!
- if ( (s == orig && ssl_conn_attempt) ||
- (s == resp && ssl_conn_server_reply) )
- {
- pCipherTable = new TableVal(cipher_suites_list);
- bExtractCipherSuite = true;
- }
-
- for ( int i = 0; i < length; i += 3 )
- {
- SSL_CipherSpec* pCurrentCipherSpec;
- uint32 cipherSpecID =
- ((pCipher[0] << 16) | pCipher[1] << 8) | pCipher[2];
-
- // Check for unknown cipher specs.
- HashKey h(static_cast(cipherSpecID));
- pCurrentCipherSpec =
- (SSL_CipherSpec*) SSL_CipherSpecDict.Lookup(&h);
-
- if ( ! pCurrentCipherSpec )
- {
- if ( s == orig )
- Weird("SSLv2: Unknown CIPHER-SPEC in CLIENT-HELLO!");
- else
- Weird("SSLv2: Unknown CIPHER-SPEC in SERVER-HELLO!");
- }
-
- if ( bExtractCipherSuite )
- {
- Val* index = new Val(cipherSpecID, TYPE_COUNT);
- pCipherTable->Assign(index, 0);
- Unref(index);
- }
-
- pCipher += 3;
- }
-
- return pCipherTable;
- }
-
-// --- SSLv2_EndPoint ---------------------------------------------------------
-
-/*!
- * The constructor.
- *
- * \param interpreter Pointer to the SSLv2 interpreter to whom this endpoint belongs to
- * \param is_orig true if this is the originating endpoint of the ssl connection,
- * false otherwise
- */
-SSLv2_Endpoint::SSLv2_Endpoint(SSLv2_Interpreter* interpreter, int is_orig)
-: SSL_InterpreterEndpoint(interpreter, is_orig)
- {
- sentRecords = 0;
- }
-
-/*!
- * The destructor.
- */
-SSLv2_Endpoint::~SSLv2_Endpoint()
- {
- }
-
-/*!
- * This method is called by the SSLProxy_Analyzer with a complete reassembled
- * SSLv2 record. It passes the record to SSLv2_Interpreter::NewSSLRecord().
- *
- * \param t reserved (always zero)
- * \param seq reserved (always zero)
- * \param len length of the data block containing the ssl record
- * \param data pointer to the data block containing the ssl record
- */
-void SSLv2_Endpoint::Deliver(int len, const u_char* data)
- {
- ++((SSLv2_Endpoint*)peer)->sentRecords;
-
- ((SSLv2_Interpreter*)interpreter)->NewSSLRecord(this, len, data);
- }
diff --git a/src/Serializer.h b/src/Serializer.h
index db09cc837f..93581d83ce 100644
--- a/src/Serializer.h
+++ b/src/Serializer.h
@@ -121,7 +121,7 @@ protected:
// This will be increased whenever there is an incompatible change
// in the data format.
- static const uint32 DATA_FORMAT_VERSION = 20;
+ static const uint32 DATA_FORMAT_VERSION = 21;
ChunkedIO* io;
diff --git a/src/Type.cc b/src/Type.cc
index cd40583aae..4d80eda6f7 100644
--- a/src/Type.cc
+++ b/src/Type.cc
@@ -876,74 +876,12 @@ void CommentedTypeDecl::DescribeReST(ODesc* d) const
}
}
-RecordField::RecordField(int arg_base, int arg_offset, int arg_total_offset)
- {
- base = arg_base;
- offset = arg_offset;
- total_offset = arg_total_offset;
- }
-
RecordType::RecordType(type_decl_list* arg_types) : BroType(TYPE_RECORD)
{
types = arg_types;
- base = 0;
- fields = 0;
num_fields = types ? types->length() : 0;
}
-RecordType::RecordType(TypeList* arg_base, type_decl_list* refinements)
- : BroType(TYPE_RECORD)
- {
- if ( refinements )
- arg_base->Append(new RecordType(refinements));
-
- Init(arg_base);
- }
-
-void RecordType::Init(TypeList* arg_base)
- {
- assert(false); // Is this ever used?
-
- base = arg_base;
-
- if ( ! base )
- Internal("empty RecordType");
-
- fields = new PDict(RecordField)(ORDERED);
- types = 0;
-
- type_list* t = base->Types();
-
- loop_over_list(*t, i)
- {
- BroType* ti = (*t)[i];
-
- if ( ti->Tag() != TYPE_RECORD )
- (*t)[i]->Error("non-record in base type list");
-
- RecordType* rti = ti->AsRecordType();
- int n = rti->NumFields();
-
- for ( int j = 0; j < n; ++j )
- {
- const TypeDecl* tdij = rti->FieldDecl(j);
-
- if ( fields->Lookup(tdij->id) )
- {
- reporter->Error("duplicate field %s", tdij->id);
- continue;
- }
-
- RecordField* rf = new RecordField(i, j, fields->Length());
-
- if ( fields->Insert(tdij->id, rf) )
- Internal("duplicate field when constructing record");
- }
- }
-
- num_fields = fields->Length();
- }
-
RecordType::~RecordType()
{
if ( types )
@@ -953,9 +891,6 @@ RecordType::~RecordType()
delete types;
}
-
- delete fields;
- Unref(base);
}
int RecordType::HasField(const char* field) const
@@ -971,17 +906,7 @@ BroType* RecordType::FieldType(const char* field) const
BroType* RecordType::FieldType(int field) const
{
- if ( types )
- return (*types)[field]->type;
- else
- {
- RecordField* rf = fields->NthEntry(field);
- if ( ! rf )
- Internal("missing field in RecordType::FieldType");
- BroType* bt = (*base->Types())[rf->base];
- RecordType* rbt = bt->AsRecordType();
- return rbt->FieldType(rf->offset);
- }
+ return (*types)[field]->type;
}
Val* RecordType::FieldDefault(int field) const
@@ -998,26 +923,14 @@ Val* RecordType::FieldDefault(int field) const
int RecordType::FieldOffset(const char* field) const
{
- if ( types )
+ loop_over_list(*types, i)
{
- loop_over_list(*types, i)
- {
- TypeDecl* td = (*types)[i];
- if ( streq(td->id, field) )
- return i;
- }
-
- return -1;
+ TypeDecl* td = (*types)[i];
+ if ( streq(td->id, field) )
+ return i;
}
- else
- {
- RecordField* rf = fields->Lookup(field);
- if ( ! rf )
- return -1;
- else
- return rf->total_offset;
- }
+ return -1;
}
const char* RecordType::FieldName(int field) const
@@ -1027,33 +940,12 @@ const char* RecordType::FieldName(int field) const
const TypeDecl* RecordType::FieldDecl(int field) const
{
- if ( types )
- return (*types)[field];
- else
- {
- RecordField* rf = fields->NthEntry(field);
- if ( ! rf )
- reporter->InternalError("missing field in RecordType::FieldDecl");
-
- BroType* bt = (*base->Types())[rf->base];
- RecordType* rbt = bt->AsRecordType();
- return rbt->FieldDecl(rf->offset);
- }
+ return (*types)[field];
}
TypeDecl* RecordType::FieldDecl(int field)
{
- if ( types )
- return (*types)[field];
- else
- {
- RecordField* rf = fields->NthEntry(field);
- if ( ! rf )
- Internal("missing field in RecordType::FieldDecl");
- BroType* bt = (*base->Types())[rf->base];
- RecordType* rbt = bt->AsRecordType();
- return rbt->FieldDecl(rf->offset);
- }
+ return (*types)[field];
}
void RecordType::Describe(ODesc* d) const
@@ -1151,11 +1043,6 @@ void RecordType::DescribeFields(ODesc* d) const
d->SP();
}
}
- else
- {
- d->AddCount(1);
- base->Describe(d);
- }
}
}
@@ -1208,9 +1095,6 @@ bool RecordType::DoSerialize(SerialInfo* info) const
else if ( ! SERIALIZE(false) )
return false;
- SERIALIZE_OPTIONAL(base);
-
- // We don't serialize the fields as we can reconstruct them.
return true;
}
@@ -1245,13 +1129,6 @@ bool RecordType::DoUnserialize(UnserialInfo* info)
else
types = 0;
- BroType* type;
- UNSERIALIZE_OPTIONAL(type, BroType::Unserialize(info, TYPE_LIST));
- base = (TypeList*) type;
-
- if ( base )
- Init(base);
-
return true;
}
@@ -1594,21 +1471,6 @@ bool VectorType::DoUnserialize(UnserialInfo* info)
return yield_type != 0;
}
-BroType* refine_type(TypeList* base, type_decl_list* refinements)
- {
- type_list* t = base->Types();
-
- if ( t->length() == 1 && ! refinements )
- { // Just a direct reference to a single type.
- BroType* rt = (*t)[0]->Ref();
- Unref(base);
- return rt;
- }
-
- return new RecordType(base, refinements);
- }
-
-
BroType* base_type(TypeTag tag)
{
static BroType* base_types[NUM_TYPES];
diff --git a/src/Type.h b/src/Type.h
index 5ebc5761a3..e935ba2267 100644
--- a/src/Type.h
+++ b/src/Type.h
@@ -426,20 +426,9 @@ public:
std::list* comments;
};
-class RecordField {
-public:
- RecordField(int arg_base, int arg_offset, int arg_total_offset);
-
- int base; // which base element it belongs to
- int offset; // where it is in that base
- int total_offset; // where it is in the aggregate record
-};
-declare(PDict,RecordField);
-
class RecordType : public BroType {
public:
RecordType(type_decl_list* types);
- RecordType(TypeList* base, type_decl_list* refinements);
~RecordType();
@@ -473,15 +462,11 @@ public:
void DescribeFieldsReST(ODesc* d, bool func_args) const;
protected:
- RecordType() { fields = 0; base = 0; types = 0; }
-
- void Init(TypeList* arg_base);
+ RecordType() { types = 0; }
DECLARE_SERIAL(RecordType)
int num_fields;
- PDict(RecordField)* fields;
- TypeList* base;
type_decl_list* types;
};
@@ -587,10 +572,6 @@ protected:
BroType* yield_type;
};
-
-// Returns the given type refinement, or error_type() if it's illegal.
-extern BroType* refine_type(TypeList* base, type_decl_list* refinements);
-
// Returns the BRO basic (non-parameterized) type with the given type.
extern BroType* base_type(TypeTag tag);
diff --git a/src/bro.bif b/src/bro.bif
index bc948dd562..121f310682 100644
--- a/src/bro.bif
+++ b/src/bro.bif
@@ -1,4 +1,8 @@
-# Definitions of Bro built-in functions.
+##! A collection of built-in functions that implement a variety of things
+##! such as general programming algorithms, string processing, math functions,
+##! introspection, type conversion, file/directory manipulation, packet
+##! filtering, inter-process communication and controlling protocol analyzer
+##! behavior.
%%{ // C segment
#include
diff --git a/src/const.bif b/src/const.bif
index 96630e300b..bc960caeb6 100644
--- a/src/const.bif
+++ b/src/const.bif
@@ -1,4 +1,6 @@
-# Documentation and default values for these are located in policy/bro.init.
+##! Declaration of various scripting-layer constants that the Bro core uses
+##! internally. Documentation and default values for the scripting-layer
+##! variables themselves are found in :doc:`/scripts/base/init-bare`.
const ignore_keep_alive_rexmit: bool;
const skip_http_data: bool;
diff --git a/src/event.bif b/src/event.bif
index 2ad5832506..001f0b84f1 100644
--- a/src/event.bif
+++ b/src/event.bif
@@ -1,3 +1,8 @@
+##! The events that the C/C++ core of Bro can generate. This is mostly
+##! consisting of high-level network events that protocol analyzers detect,
+##! but there are also several general-utility events generated by internal
+##! Bro frameworks.
+
#
# Documentation conventions:
#
@@ -4574,7 +4579,8 @@ event ssh_server_version%(c: connection, version: string%);
## maps them to descriptive names.
##
## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello
-## x509_certificate x509_error x509_extension ssl_max_cipherspec_size
+## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
+## ssl_max_cipherspec_size
event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%);
## Generated for an SSL/TLS servers's initial *hello* message. SSL/TLS sessions
@@ -4604,7 +4610,8 @@ event ssl_client_hello%(c: connection, version: count, possible_ts: time, sessio
## standardized as part of the SSL/TLS protocol.
##
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension
-## x509_certificate x509_error x509_extension ssl_max_cipherspec_size
+## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
+## ssl_max_cipherspec_size
event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%);
## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS sessions
@@ -4623,7 +4630,7 @@ event ssl_server_hello%(c: connection, version: count, possible_ts: time, sessio
## val: The raw extension value that was sent in the message.
##
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello
-## x509_certificate x509_error x509_extension
+## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);
## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with
@@ -4638,7 +4645,7 @@ event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);
## c: The connection.
##
## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello
-## x509_certificate x509_error x509_extension
+## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
event ssl_established%(c: connection%);
## Generated for SSL/TLS alert records. SSL/TLS sessions start with an unencrypted
@@ -4661,9 +4668,30 @@ event ssl_established%(c: connection%);
## defined as part of the SSL/TLS protocol.
##
## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello
-## x509_certificate x509_error x509_extension
+## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%);
+## Generated for SSL/TLS handshake messages that are a part of the stateless-server
+## session resumption mechanism. SSL/TLS sessions start with an unencrypted
+## handshake, and Bro extracts as much information out of that as it can. This
+## event is raised when an SSL/TLS server passes session ticket to the client that
+## can later be used for resuming the session. The mechanism is described in
+## :rfc:`4507`
+##
+## See `Wikipedia `__ for
+## more information about the SSL/TLS protocol.
+##
+## c: The connection.
+##
+## ticket_lifetime_hint: A hint from the server about how long the ticket
+## should be stored by the client.
+##
+## ticket: The raw ticket data.
+##
+## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello
+## x509_certificate x509_error x509_extension ssl_alert
+event ssl_session_ticket_handshake%(c: connection, ticket_lifetime_hint: count, ticket: string%);
+
## Generated for x509 certificates seen in SSL/TLS connections. During the initial
## SSL/TLS handshake, certificates are exchanged in the clear. Bro raises this
## event for each certificate seen (including both a site's primary cert, and
diff --git a/src/main.cc b/src/main.cc
index b4a27862c9..3d096c7d51 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -97,7 +97,7 @@ extern char version[];
char* command_line_policy = 0;
vector params;
char* proc_status_file = 0;
-int snaplen = 65535; // really want "capture entire packet"
+int snaplen = 0; // this gets set from the scripting-layer's value
int FLAGS_use_binpac = false;
@@ -145,7 +145,6 @@ void usage()
fprintf(stderr, " -g|--dump-config | dump current config into .state dir\n");
fprintf(stderr, " -h|--help|-? | command line help\n");
fprintf(stderr, " -i|--iface | read from given interface\n");
- fprintf(stderr, " -l|--snaplen | number of bytes per packet to capture from interfaces (default 65535)\n");
fprintf(stderr, " -p|--prefix | add given prefix to policy file resolution\n");
fprintf(stderr, " -r|--readfile | read from given tcpdump file\n");
fprintf(stderr, " -y|--flowfile [=] | read from given flow file\n");
@@ -372,7 +371,6 @@ int main(int argc, char** argv)
{"filter", required_argument, 0, 'f'},
{"help", no_argument, 0, 'h'},
{"iface", required_argument, 0, 'i'},
- {"snaplen", required_argument, 0, 'l'},
{"doc-scripts", no_argument, 0, 'Z'},
{"prefix", required_argument, 0, 'p'},
{"readfile", required_argument, 0, 'r'},
@@ -481,10 +479,6 @@ int main(int argc, char** argv)
interfaces.append(optarg);
break;
- case 'l':
- snaplen = atoi(optarg);
- break;
-
case 'p':
prefixes.append(optarg);
break;
@@ -833,6 +827,8 @@ int main(int argc, char** argv)
}
}
+ snaplen = internal_val("snaplen")->AsCount();
+
// Initialize the secondary path, if it's needed.
secondary_path = new SecondaryPath();
diff --git a/src/parse.y b/src/parse.y
index 495931aae0..7ab6c6bd32 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -2,7 +2,7 @@
// See the file "COPYING" in the main distribution directory for copyright.
%}
-%expect 88
+%expect 87
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
@@ -53,7 +53,7 @@
%type expr init anonymous_function
%type event
%type stmt stmt_list func_body for_head
-%type type opt_type refined_type enum_body
+%type type opt_type enum_body
%type func_hdr func_params
%type type_list
%type type_decl formal_args_decl
@@ -1104,7 +1104,7 @@ decl:
}
}
- | TOK_TYPE global_id ':' refined_type opt_attr ';'
+ | TOK_TYPE global_id ':' type opt_attr ';'
{
add_type($2, $4, $5, 0);
@@ -1134,7 +1134,7 @@ decl:
}
}
- | TOK_EVENT event_id ':' refined_type opt_attr ';'
+ | TOK_EVENT event_id ':' type_list opt_attr ';'
{
add_type($2, $4, $5, 1);
@@ -1220,13 +1220,6 @@ func_params:
{ $$ = new FuncType($2, base_type(TYPE_VOID), 0); }
;
-refined_type:
- type_list '{' type_decl_list '}'
- { $$ = refine_type($1, $3); }
- | type_list
- { $$ = refine_type($1, 0); }
- ;
-
opt_type:
':' type
{ $$ = $2; }
diff --git a/src/ssl-analyzer.pac b/src/ssl-analyzer.pac
index 79e00f2033..f41fb8639b 100644
--- a/src/ssl-analyzer.pac
+++ b/src/ssl-analyzer.pac
@@ -144,7 +144,7 @@ refine connection SSL_Conn += {
if ( ssl_client_hello )
{
vector* cipher_suites = new vector();
- if ( cipher_suites16 )
+ if ( cipher_suites16 )
std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*cipher_suites));
else
std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*cipher_suites), to_int());
@@ -205,6 +205,18 @@ refine connection SSL_Conn += {
return true;
%}
+
+ function proc_session_ticket_handshake(rec: SessionTicketHandshake, is_orig: bool): bool
+ %{
+ if ( ssl_session_ticket_handshake )
+ {
+ BifEvent::generate_ssl_session_ticket_handshake(bro_analyzer(),
+ bro_analyzer()->Conn(),
+ ${rec.ticket_lifetime_hint},
+ new StringVal(${rec.data}.length(), (const char*) ${rec.data}.data()));
+ }
+ return true;
+ %}
function proc_ssl_extension(rec: SSLRecord, type: int, data: bytestring) : bool
%{
@@ -269,13 +281,14 @@ refine connection SSL_Conn += {
der_cert);
// Are there any X509 extensions?
+ //printf("Number of x509 extensions: %d\n", X509_get_ext_count(pTemp));
if ( x509_extension && X509_get_ext_count(pTemp) > 0 )
{
int num_ext = X509_get_ext_count(pTemp);
for ( int k = 0; k < num_ext; ++k )
{
unsigned char *pBuffer = 0;
- int length = 0;
+ uint length = 0;
X509_EXTENSION* ex = X509_get_ext(pTemp, k);
if (ex)
@@ -283,7 +296,7 @@ refine connection SSL_Conn += {
ASN1_STRING *pString = X509_EXTENSION_get_data(ex);
length = ASN1_STRING_to_UTF8(&pBuffer, pString);
//i2t_ASN1_OBJECT(&pBuffer, length, obj)
-
+ // printf("extension length: %u\n", length);
// -1 indicates an error.
if ( length < 0 )
continue;
@@ -442,6 +455,10 @@ refine typeattr Handshake += &let {
proc : bool = $context.connection.proc_handshake(this, rec.is_orig);
};
+refine typeattr SessionTicketHandshake += &let {
+ proc : bool = $context.connection.proc_session_ticket_handshake(this, rec.is_orig);
+}
+
refine typeattr UnknownRecord += &let {
proc : bool = $context.connection.proc_unknown_record(rec);
};
diff --git a/src/ssl-protocol.pac b/src/ssl-protocol.pac
index 24207ac78b..627645e4da 100644
--- a/src/ssl-protocol.pac
+++ b/src/ssl-protocol.pac
@@ -61,17 +61,10 @@ type RecordText(rec: SSLRecord) = case $context.connection.state() of {
-> plaintext : PlaintextRecord(rec);
};
-type PossibleEncryptedHandshake(rec: SSLRecord) = case $context.connection.state() of {
- # Deal with encrypted handshakes before the server cipher spec change.
- STATE_CLIENT_FINISHED, STATE_CLIENT_ENCRYPTED
- -> ct : CiphertextRecord(rec);
- default -> hs : Handshake(rec);
-};
-
type PlaintextRecord(rec: SSLRecord) = case rec.content_type of {
CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec);
ALERT -> alert : Alert(rec);
- HANDSHAKE -> handshake : PossibleEncryptedHandshake(rec);
+ HANDSHAKE -> handshake : Handshake(rec);
APPLICATION_DATA -> app_data : ApplicationData(rec);
V2_ERROR -> v2_error : V2Error(rec);
V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec);
@@ -260,18 +253,19 @@ enum AnalyzerState {
######################################################################
enum HandshakeType {
- HELLO_REQUEST = 0,
- CLIENT_HELLO = 1,
- SERVER_HELLO = 2,
- CERTIFICATE = 11,
- SERVER_KEY_EXCHANGE = 12,
- CERTIFICATE_REQUEST = 13,
- SERVER_HELLO_DONE = 14,
- CERTIFICATE_VERIFY = 15,
- CLIENT_KEY_EXCHANGE = 16,
- FINISHED = 20,
- CERTIFICATE_URL = 21, # RFC 3546
- CERTIFICATE_STATUS = 22, # RFC 3546
+ HELLO_REQUEST = 0,
+ CLIENT_HELLO = 1,
+ SERVER_HELLO = 2,
+ SESSION_TICKET = 4, # RFC 5077
+ CERTIFICATE = 11,
+ SERVER_KEY_EXCHANGE = 12,
+ CERTIFICATE_REQUEST = 13,
+ SERVER_HELLO_DONE = 14,
+ CERTIFICATE_VERIFY = 15,
+ CLIENT_KEY_EXCHANGE = 16,
+ FINISHED = 20,
+ CERTIFICATE_URL = 21, # RFC 3546
+ CERTIFICATE_STATUS = 22, # RFC 3546
};
%code{
@@ -281,6 +275,7 @@ enum HandshakeType {
case HELLO_REQUEST: return string("HELLO_REQUEST");
case CLIENT_HELLO: return string("CLIENT_HELLO");
case SERVER_HELLO: return string("SERVER_HELLO");
+ case SESSION_TICKET: return string("SESSION_TICKET");
case CERTIFICATE: return string("CERTIFICATE");
case SERVER_KEY_EXCHANGE: return string("SERVER_KEY_EXCHANGE");
case CERTIFICATE_REQUEST: return string("CERTIFICATE_REQUEST");
@@ -452,8 +447,7 @@ type V2ServerHello(rec: SSLRecord) = record {
cert_data : bytestring &length = cert_len;
ciphers : uint24[ciph_len/3];
conn_id_data : bytestring &length = conn_id_len;
-} #&length = 8 + cert_len + ciph_len + conn_id_len,
-&let {
+} &let {
state_changed : bool =
(session_id_hit > 0 ?
$context.connection.transition(STATE_CLIENT_HELLO_RCVD,
@@ -603,7 +597,7 @@ type CertificateVerify(rec: SSLRecord) = record {
######################################################################
# The finished messages are always sent after encryption is in effect,
-# so we will not be able to read those message.
+# so we will not be able to read those messages.
type Finished(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient;
} &let {
@@ -615,13 +609,17 @@ type Finished(rec: SSLRecord) = record {
$context.connection.lost_track();
};
+type SessionTicketHandshake(rec: SSLRecord) = record {
+ ticket_lifetime_hint: uint32;
+ data: bytestring &restofdata;
+};
######################################################################
# V3 Handshake Protocol (7.)
######################################################################
type UnknownHandshake(hs: Handshake, is_orig: bool) = record {
- cont : bytestring &restofdata &transient;
+ data : bytestring &restofdata &transient;
} &let {
state_changed : bool = $context.connection.lost_track();
};
@@ -631,19 +629,20 @@ type Handshake(rec: SSLRecord) = record {
length : uint24;
body : case msg_type of {
- HELLO_REQUEST -> hello_request : HelloRequest(rec);
- CLIENT_HELLO -> client_hello : ClientHello(rec);
- SERVER_HELLO -> server_hello : ServerHello(rec);
- CERTIFICATE -> certificate : Certificate(rec);
- SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec);
- CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec);
- SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec);
- CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec);
- CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec);
- FINISHED -> finished : Finished(rec);
- CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient;
- CERTIFICATE_STATUS -> certificate_status : bytestring &restofdata &transient;
- default -> unknown_handshake : UnknownHandshake(this, rec.is_orig);
+ HELLO_REQUEST -> hello_request : HelloRequest(rec);
+ CLIENT_HELLO -> client_hello : ClientHello(rec);
+ SERVER_HELLO -> server_hello : ServerHello(rec);
+ SESSION_TICKET -> session_ticket : SessionTicketHandshake(rec);
+ CERTIFICATE -> certificate : Certificate(rec);
+ SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec);
+ CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec);
+ SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec);
+ CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec);
+ CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec);
+ FINISHED -> finished : Finished(rec);
+ CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient;
+ CERTIFICATE_STATUS -> certificate_status : bytestring &restofdata &transient;
+ default -> unknown_handshake : UnknownHandshake(this, rec.is_orig);
} &length = to_int()(length);
};
diff --git a/src/strings.bif b/src/strings.bif
index 5301dfcf5e..9c9bd576b1 100644
--- a/src/strings.bif
+++ b/src/strings.bif
@@ -1,4 +1,5 @@
-# Definitions of Bro built-in functions related to strings.
+##! Definitions of built-in functions related to string processing and
+##! manipulation.
%%{ // C segment
diff --git a/src/types.bif b/src/types.bif
index da6bd6e031..4657584a90 100644
--- a/src/types.bif
+++ b/src/types.bif
@@ -1,3 +1,4 @@
+##! Declaration of various types that the Bro core uses internally.
enum dce_rpc_ptype %{
DCE_RPC_REQUEST,
@@ -134,8 +135,8 @@ enum createmode_t %{
EXCLUSIVE = 2,
%}
-# Decleare record types that we want to access from the even engine. These are
-# defined in bro.init.
+# Declare record types that we want to access from the event engine. These are
+# defined in init-bare.bro.
type info_t: record;
type fattr_t: record;
type diropargs_t: record;
diff --git a/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log b/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log
index 33f55ce608..59d70896fb 100644
--- a/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log
+++ b/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log
@@ -3,6 +3,6 @@
#empty_field (empty)
#unset_field -
#path notice
-#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
-#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
-1324314350.184962 - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 100/100 - 1.2.3.4 - - 100 manager-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - -
+#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
+#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
+1325633225.777902 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 100/100 - 1.2.3.4 - - 100 manager-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - -
diff --git a/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log b/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log
index 437b1465a1..58346b79e6 100644
--- a/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log
+++ b/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log
@@ -3,7 +3,7 @@
#empty_field (empty)
#unset_field -
#path notice
-#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
-#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
-1324314359.357148 - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 3/2 - 1.2.3.4 - - 3 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - -
-1324314359.357148 - - - - - Test_Notice Threshold crossed by metric_index(host=6.5.4.3) 2/2 - 6.5.4.3 - - 2 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 6.5.4.3 - -
+#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
+#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
+1325633274.875473 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 3/2 - 1.2.3.4 - - 3 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - -
+1325633274.875473 - - - - - - Test_Notice Threshold crossed by metric_index(host=6.5.4.3) 2/2 - 6.5.4.3 - - 2 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 6.5.4.3 - -
diff --git a/testing/btest/Baseline/scripts.base.frameworks.notice.cluster/manager-1.notice.log b/testing/btest/Baseline/scripts.base.frameworks.notice.cluster/manager-1.notice.log
index fb1e1b3d47..10888b21ec 100644
--- a/testing/btest/Baseline/scripts.base.frameworks.notice.cluster/manager-1.notice.log
+++ b/testing/btest/Baseline/scripts.base.frameworks.notice.cluster/manager-1.notice.log
@@ -3,6 +3,6 @@
#empty_field (empty)
#unset_field -
#path notice
-#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
-#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
-1324314363.721823 - - - - - Test_Notice test notice! - - - - - worker-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
+#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
+#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
+1325633122.490990 - - - - - - Test_Notice test notice! - - - - - worker-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
diff --git a/testing/btest/Baseline/scripts.base.frameworks.notice.mail-alarms/alarm-mail.txt b/testing/btest/Baseline/scripts.base.frameworks.notice.mail-alarms/alarm-mail.txt
new file mode 100644
index 0000000000..e2cd51edd1
--- /dev/null
+++ b/testing/btest/Baseline/scripts.base.frameworks.notice.mail-alarms/alarm-mail.txt
@@ -0,0 +1,4 @@
+> 2005-10-07-23:23:55 Test_Notice 141.42.64.125:56730/tcp -> 125.190.109.199:80/tcp (uid arKYeMETxOg)
+ test
+ # 141.42.64.125 = 125.190.109.199 =
+
diff --git a/testing/btest/Baseline/scripts.base.frameworks.notice.suppression-cluster/manager-1.notice.log b/testing/btest/Baseline/scripts.base.frameworks.notice.suppression-cluster/manager-1.notice.log
index 9e6e1b1916..5deac88071 100644
--- a/testing/btest/Baseline/scripts.base.frameworks.notice.suppression-cluster/manager-1.notice.log
+++ b/testing/btest/Baseline/scripts.base.frameworks.notice.suppression-cluster/manager-1.notice.log
@@ -3,6 +3,6 @@
#empty_field (empty)
#unset_field -
#path notice
-#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
-#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
-1324314378.560010 - - - - - Test_Notice test notice! - - - - - worker-2 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
+#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
+#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
+1325633150.723248 - - - - - - Test_Notice test notice! - - - - - worker-2 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
diff --git a/testing/btest/Baseline/scripts.base.frameworks.notice.suppression/notice.log b/testing/btest/Baseline/scripts.base.frameworks.notice.suppression/notice.log
index d134c97049..1d168d7613 100644
--- a/testing/btest/Baseline/scripts.base.frameworks.notice.suppression/notice.log
+++ b/testing/btest/Baseline/scripts.base.frameworks.notice.suppression/notice.log
@@ -3,6 +3,6 @@
#empty_field (empty)
#unset_field -
#path notice
-#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude
-#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double
-1324314387.663586 - - - - - Test_Notice test - - - - - bro Notice::ACTION_LOG 6 3600.000000 F - - - - -
+#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude
+#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double
+1325633207.922993 - - - - - - Test_Notice test - - - - - bro Notice::ACTION_LOG 6 3600.000000 F - - - - -
diff --git a/testing/btest/scripts/base/frameworks/cluster/start-it-up.bro b/testing/btest/scripts/base/frameworks/cluster/start-it-up.bro
index d1eb94d5e1..b8ee4c33e8 100644
--- a/testing/btest/scripts/base/frameworks/cluster/start-it-up.bro
+++ b/testing/btest/scripts/base/frameworks/cluster/start-it-up.bro
@@ -3,7 +3,7 @@
# @TEST-EXEC: btest-bg-run proxy-2 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-2 bro %INPUT
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
-# @TEST-EXEC: btest-bg-wait -k 2
+# @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff manager-1/.stdout
# @TEST-EXEC: btest-diff proxy-1/.stdout
# @TEST-EXEC: btest-diff proxy-2/.stdout
@@ -23,4 +23,4 @@ redef Cluster::nodes = {
event remote_connection_handshake_done(p: event_peer)
{
print "Connected to a peer";
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/scripts/base/frameworks/communication/communication_log_baseline.bro b/testing/btest/scripts/base/frameworks/communication/communication_log_baseline.bro
index c3078684af..3a4c1253eb 100644
--- a/testing/btest/scripts/base/frameworks/communication/communication_log_baseline.bro
+++ b/testing/btest/scripts/base/frameworks/communication/communication_log_baseline.bro
@@ -1,7 +1,7 @@
#
# @TEST-EXEC: btest-bg-run receiver bro -b ../receiver.bro
# @TEST-EXEC: btest-bg-run sender bro -b ../sender.bro
-# @TEST-EXEC: btest-bg-wait -k 2
+# @TEST-EXEC: btest-bg-wait -k 10
#
# Don't diff the receiver log just because port is always going to change
# @TEST-EXEC: egrep -v 'pid|socket buffer size' sender/communication.log >send.log
diff --git a/testing/btest/scripts/base/frameworks/control/configuration_update.bro b/testing/btest/scripts/base/frameworks/control/configuration_update.bro
index eb86ec58e8..9b16faee69 100644
--- a/testing/btest/scripts/base/frameworks/control/configuration_update.bro
+++ b/testing/btest/scripts/base/frameworks/control/configuration_update.bro
@@ -1,7 +1,7 @@
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65531/tcp
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT test-redef frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=configuration_update
# @TEST-EXEC: btest-bg-run controller2 BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=shutdown
-# @TEST-EXEC: btest-bg-wait 1
+# @TEST-EXEC: btest-bg-wait 10
# @TEST-EXEC: btest-diff controllee/.stdout
redef Communication::nodes = {
@@ -23,4 +23,4 @@ event bro_init()
event bro_done()
{
print test_var;
- }
\ No newline at end of file
+ }
diff --git a/testing/btest/scripts/base/frameworks/control/id_value.bro b/testing/btest/scripts/base/frameworks/control/id_value.bro
index 90a5367f76..e06fa46e74 100644
--- a/testing/btest/scripts/base/frameworks/control/id_value.bro
+++ b/testing/btest/scripts/base/frameworks/control/id_value.bro
@@ -1,6 +1,6 @@
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT only-for-controllee frameworks/control/controllee Communication::listen_port=65532/tcp
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65532/tcp Control::cmd=id_value Control::arg=test_var
-# @TEST-EXEC: btest-bg-wait -k 1
+# @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff controller/.stdout
redef Communication::nodes = {
diff --git a/testing/btest/scripts/base/frameworks/control/shutdown.bro b/testing/btest/scripts/base/frameworks/control/shutdown.bro
index 73319a7c4a..9953a8382a 100644
--- a/testing/btest/scripts/base/frameworks/control/shutdown.bro
+++ b/testing/btest/scripts/base/frameworks/control/shutdown.bro
@@ -1,6 +1,6 @@
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65530/tcp
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65530/tcp Control::cmd=shutdown
-# @TEST-EXEC: btest-bg-wait 1
+# @TEST-EXEC: btest-bg-wait 10
redef Communication::nodes = {
# We're waiting for connections from this host for control.
diff --git a/testing/btest/scripts/base/frameworks/logging/remote-types.bro b/testing/btest/scripts/base/frameworks/logging/remote-types.bro
index 9af45cf991..4e866cc985 100644
--- a/testing/btest/scripts/base/frameworks/logging/remote-types.bro
+++ b/testing/btest/scripts/base/frameworks/logging/remote-types.bro
@@ -1,7 +1,7 @@
#
# @TEST-EXEC: btest-bg-run sender bro --pseudo-realtime %INPUT ../sender.bro
# @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro
-# @TEST-EXEC: btest-bg-wait -k 1
+# @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff receiver/test.log
# @TEST-EXEC: cmp receiver/test.log sender/test.log
diff --git a/testing/btest/scripts/base/frameworks/logging/remote.bro b/testing/btest/scripts/base/frameworks/logging/remote.bro
index b244c72cdf..8ed3405aed 100644
--- a/testing/btest/scripts/base/frameworks/logging/remote.bro
+++ b/testing/btest/scripts/base/frameworks/logging/remote.bro
@@ -3,7 +3,7 @@
# @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro
# @TEST-EXEC: sleep 1
-# @TEST-EXEC: btest-bg-wait -k 1
+# @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff sender/test.log
# @TEST-EXEC: btest-diff sender/test.failure.log
# @TEST-EXEC: btest-diff sender/test.success.log
diff --git a/testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro b/testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro
index 4b7f177f15..23b87053ab 100644
--- a/testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro
+++ b/testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro
@@ -3,7 +3,7 @@
# @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
-# @TEST-EXEC: btest-bg-wait -k 6
+# @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff manager-1/metrics.log
@TEST-START-FILE cluster-layout.bro
diff --git a/testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro b/testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro
index 89d771e05e..45d44898aa 100644
--- a/testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro
+++ b/testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro
@@ -3,7 +3,7 @@
# @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
-# @TEST-EXEC: btest-bg-wait -k 5
+# @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff manager-1/notice.log
@TEST-START-FILE cluster-layout.bro
diff --git a/testing/btest/scripts/base/frameworks/notice/cluster.bro b/testing/btest/scripts/base/frameworks/notice/cluster.bro
index f44ba72f3a..125d021d82 100644
--- a/testing/btest/scripts/base/frameworks/notice/cluster.bro
+++ b/testing/btest/scripts/base/frameworks/notice/cluster.bro
@@ -2,7 +2,7 @@
# @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT
# @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
-# @TEST-EXEC: btest-bg-wait -k 6
+# @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff manager-1/notice.log
@TEST-START-FILE cluster-layout.bro
diff --git a/testing/btest/scripts/base/frameworks/notice/mail-alarms.bro b/testing/btest/scripts/base/frameworks/notice/mail-alarms.bro
new file mode 100644
index 0000000000..3116b1025a
--- /dev/null
+++ b/testing/btest/scripts/base/frameworks/notice/mail-alarms.bro
@@ -0,0 +1,17 @@
+# @TEST-EXEC: bro -C -r $TRACES/web.trace %INPUT
+# @TEST-EXEC: btest-diff alarm-mail.txt
+
+redef Notice::policy += { [$action = Notice::ACTION_ALARM, $priority = 1 ] };
+redef Notice::force_email_summaries = T;
+
+redef enum Notice::Type += {
+ Test_Notice,
+};
+
+event connection_established(c: connection)
+ {
+ NOTICE([$note=Test_Notice, $conn=c, $msg="test", $identifier="static"]);
+ }
+
+
+
diff --git a/testing/btest/scripts/base/frameworks/notice/suppression-cluster.bro b/testing/btest/scripts/base/frameworks/notice/suppression-cluster.bro
index a7e720d5f5..e084fb74e0 100644
--- a/testing/btest/scripts/base/frameworks/notice/suppression-cluster.bro
+++ b/testing/btest/scripts/base/frameworks/notice/suppression-cluster.bro
@@ -3,7 +3,7 @@
# @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
-# @TEST-EXEC: btest-bg-wait -k 5
+# @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff manager-1/notice.log
@TEST-START-FILE cluster-layout.bro
diff --git a/testing/external/scripts/diff-all b/testing/external/scripts/diff-all
index 329bbb7f00..1fd633b1e9 100755
--- a/testing/external/scripts/diff-all
+++ b/testing/external/scripts/diff-all
@@ -22,7 +22,16 @@ files_cwd=`ls $@`
files_baseline=`cd $TEST_BASELINE && ls $@`
for i in `echo $files_cwd $files_baseline | sort | uniq`; do
- if [[ "$i" != "loaded_scripts.log" && "$i" != "prof.log" ]]; then
+ if [[ "$i" != "loaded_scripts.log" && "$i" != "prof.log" && "$i" != "debug.log" ]]; then
+
+ if [[ "$i" == "reporter.log" ]]; then
+ # Do not diff the reporter.log if it only complains about missing
+ # GeoIP support.
+ if ! egrep -v "^#|Bro was not configured for GeoIP support" $i; then
+ continue
+ fi
+ fi
+
if ! btest-diff $i; then
echo "" >>$diag
echo "#### btest-diff $i" >>$diag
diff --git a/testing/scripts/diff-canonifier-external b/testing/scripts/diff-canonifier-external
index 76210cc494..1f953183d3 100755
--- a/testing/scripts/diff-canonifier-external
+++ b/testing/scripts/diff-canonifier-external
@@ -5,3 +5,4 @@
`dirname $0`/diff-remove-timestamps \
| `dirname $0`/diff-remove-uids \
| `dirname $0`/diff-remove-mime-types \
+ | `dirname $0`/diff-remove-x509-names \
diff --git a/testing/scripts/diff-remove-x509-names b/testing/scripts/diff-remove-x509-names
new file mode 100755
index 0000000000..6209edfc65
--- /dev/null
+++ b/testing/scripts/diff-remove-x509-names
@@ -0,0 +1,32 @@
+#! /usr/bin/awk -f
+#
+# A diff canonifier that removes all X.509 Distinguished Name subject fields
+# because that output can differ depending on installed OpenSSL version.
+
+BEGIN { FS="\t"; OFS="\t"; s_col = -1; i_col = -1 }
+
+/^#fields/ {
+ for ( i = 2; i < NF; ++i )
+ {
+ if ( $i == "subject" )
+ s_col = i-1;
+ if ( $i == "issuer_subject" )
+ i_col = i-1;
+ }
+}
+
+s_col >= 0 {
+ if ( $s_col != "-" )
+ # Mark that it's set, but ignore content.
+ $s_col = "+";
+}
+
+i_col >= 0 {
+ if ( $i_col != "-" )
+ # Mark that it's set, but ignore content.
+ $i_col = "+";
+}
+
+{
+ print;
+}