Merge remote-tracking branch 'origin/master' into topic/script-reference

Conflicts:
	scripts/base/frameworks/notice/actions/pp-alarms.bro
	scripts/base/frameworks/notice/main.bro
	scripts/base/init-bare.bro
	src/event.bif
This commit is contained in:
Robin Sommer 2012-01-06 12:11:49 -08:00
commit 7646ef1aed
43 changed files with 410 additions and 1277 deletions

44
CHANGES
View file

@ -1,4 +1,48 @@
2.0-beta-177 | 2012-01-05 15:01:07 -0800
* Replace the --snaplen/-l command line option with a
scripting-layer option called "snaplen" (which can also be
redefined on the command line, e.g. `bro -i eth0 snaplen=65535`).
* Reduce snaplen default from 65535 to old default of 8192. Fixes
#720. (Jon Siwek)
2.0-beta-174 | 2012-01-04 12:47:10 -0800
* SSL improvements. (Seth Hall)
- Added the ssl_session_ticket_handshake event back.
- Fixed a few bugs.
- Removed the SSLv2.cc file since it's not used.
2.0-beta-169 | 2012-01-04 12:44:39 -0800
* Tuning the pretty-printed alarm mails, which now include the
covered time range into the subject. (Robin Sommer)
* Adding top-level "test" target to Makefile. (Robin Sommer)
* Adding SWIG as dependency to INSTALL. (Robin Sommer)
2.0-beta-155 | 2012-01-03 15:42:32 -0800
* Remove dead code related to record type inheritance. (Jon Siwek)
2.0-beta-152 | 2012-01-03 14:51:34 -0800
* Notices now record the transport-layer protocol. (Bernhard Amann)
2.0-beta-150 | 2012-01-03 14:42:45 -0800
* CMake 2.6 top-level 'install' target compat. Fixes #729. (Jon Siwek)
* Minor fixes to test process. Addresses #298.
* Increase timeout interval of communication-related btests. (Jon Siwek)
2.0-beta-145 | 2011-12-19 11:37:15 -0800
* Empty fields are now logged as "(empty)" by default. (Robin

14
INSTALL
View file

@ -14,10 +14,11 @@ before you begin:
* OpenSSL (headers and libraries) http://www.openssl.org
* Libmagic For identifying file types (e.g., in FTP transfers).
* SWIG http://www.swig.org
* Libz For decompressing HTTP bodies by the HTTP analyzer, and for
compressed Bro-to-Bro communication.
* Libmagic
* Libz
Bro can make uses of some optional libraries if they are found at
installation time:
@ -32,6 +33,7 @@ already come preinstalled:
* Flex (Fast Lexical Analyzer)
* Perl (Used only during the Bro build process)
Installation
============
@ -69,8 +71,10 @@ Running Bro
===========
Bro is a complex program and it takes a bit of time to get familiar
with it. A good place for newcomers to start is the
:doc:`quick start guide <quickstart>`.
with it. A good place for newcomers to start is the Quickstart Guide at
http://www.bro-ids.org/documentation/quickstart.bro.html
For developers that wish to run Bro directly from the ``build/``
directory (i.e., without performing ``make install``), they will have

View file

@ -14,7 +14,7 @@ HAVE_MODULES=git submodule | grep -v cmake >/dev/null
all: configured
$(MAKE) -C $(BUILD) $@
install: configured
install: configured all
$(MAKE) -C $(BUILD) $@
install-aux: configured
@ -60,6 +60,9 @@ bindist:
distclean:
rm -rf $(BUILD)
test:
@(cd testing && make )
configured:
@test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 )
@test -e $(BUILD)/Makefile || ( echo "Error: No build/Makefile found. Did you run configure?" && exit 1 )

51
NEWS Normal file
View file

@ -0,0 +1,51 @@
Release Notes
=============
This document summarizes the most important changes in the current Bro
release. For a complete list of changes, see the ``CHANGES`` file.
Bro 2.0
-------
As the version number jump suggests, Bro 2.0 is a major upgrade and
lots of things have changed. We have assembled a separate upprade
guide with the most important changes compared to Bro 1.5 at
http://www.bro-ids.org/documentation/upgrade.bro.html. You can find
the offline version of that document in ``doc/upgrade.rst.``.
Compared to the earlier 2.0 Beta version, the major changes in the
final release are:
* The default scripts now come with complete reference
documentation. See
http://www.bro-ids.org/documentation/index.html.
* libz and libmagic are now required dependencies.
* Reduced snaplen default from 65535 to old default of 8192. The
large value was introducing performance problems on many
systems.
* Replaced the --snaplen/-l command line option with a
scripting-layer option called "snaplen". The new option can also
be redefined on the command line, e.g. ``bro -i eth0
snaplen=65535``.
* Reintroduced the BRO_LOG_SUFFIX environment that the ASCII
logger now respects to add a suffix to the log files it creates.
* The ASCII logs now include further header information, and
fields set to an empty value are now logged as ``(empty)`` by
default (instead of ``-``, which is already used for fields that
are not set at all).
* Some NOTICES were renamed, and the signatures of some SSL events
have changed.
* Many smaller bug fixes, portability improvements, and general
polishing.

10
README
View file

@ -4,13 +4,15 @@ Bro Network Security Monitor
Bro is a powerful framework for network analysis and security
monitoring. Please see the INSTALL file for installation instructions
and pointers for getting started. For more documentation, research
publications, and community contact information, see Bro's home page:
and pointers for getting started. NEWS contains releases notes for the
current version, and CHANGES has the complete history of changes.
Please see COPYING for licensing information.
For more documentation, research publications, and community contact
information, please see Bro's home page:
http://www.bro-ids.org
Please see COPYING for licensing information.
On behalf of the Bro Development Team,
Vern Paxson & Robin Sommer,

View file

@ -1 +1 @@
2.0-beta-145
2.0-beta-177

@ -1 +1 @@
Subproject commit d7b8a43759bfcbe1381d132d8ab388937e52a6d4
Subproject commit c5cee3d5746ed3d5c14348c1f264d19404caa761

@ -1 +1 @@
Subproject commit a42e4d133b94622c612055047f8534d5122e6e88
Subproject commit d3d5934310a94452b1dddabb2e75f6c5c86b4860

View file

@ -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?
---------------------------------------------------------------------------------------------------------------------------------

View file

@ -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
-----------

View file

@ -14,14 +14,17 @@ export {
## 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 != ""));
}
@ -44,34 +50,45 @@ function pp_open()
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;
}
@ -93,7 +110,7 @@ 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 )
@ -154,31 +171,25 @@ function pretty_print_alarm(out: file, n: Info)
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);
@ -191,6 +202,12 @@ function pretty_print_alarm(out: file, n: Info)
return;
}
if ( reading_traces() )
{
do_msg(out, n, line1, line2, line3, h1, "<skipped>", h2, "<skipped>");
return;
}
when ( local h1name = lookup_addr(h1) )
{
if ( h2 == 0.0.0.0 )

View file

@ -74,7 +74,11 @@ export {
## 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 )

View file

@ -2331,6 +2331,9 @@ const ignore_keep_alive_rexmit = F &redef;
## .. bro:see:: tunnel_port
const parse_udp_tunnels = F &redef;
## 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

View file

@ -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<bro_uint_t>(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<bro_uint_t>(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 <b>reserved</b> (always zero)
* \param seq <b>reserved</b> (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);
}

View file

@ -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;

View file

@ -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];

View file

@ -426,20 +426,9 @@ public:
std::list<std::string>* 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);

View file

@ -4574,7 +4574,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 +4605,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 +4625,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 +4640,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 +4663,28 @@ 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. 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.
##
## See `Wikipedia <http://en.wikipedia.org/wiki/Transport_Layer_Security>`__ for
## more information about the SSL/TLS protocol.
##
## c: The connection.
##
## ticket_lifetime_hint: A hint to the client indicating how long the ticket should
## be valid.
##
## ticket: The raw ticket.
##
## .. 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

View file

@ -97,7 +97,7 @@ extern char version[];
char* command_line_policy = 0;
vector<string> 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 <interface> | read from given interface\n");
fprintf(stderr, " -l|--snaplen <snaplen> | number of bytes per packet to capture from interfaces (default 65535)\n");
fprintf(stderr, " -p|--prefix <prefix> | add given prefix to policy file resolution\n");
fprintf(stderr, " -r|--readfile <readfile> | read from given tcpdump file\n");
fprintf(stderr, " -y|--flowfile <file>[=<ident>] | 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();

View file

@ -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> expr init anonymous_function
%type <event_expr> event
%type <stmt> stmt stmt_list func_body for_head
%type <type> type opt_type refined_type enum_body
%type <type> type opt_type enum_body
%type <func_type> func_hdr func_params
%type <type_l> type_list
%type <type_decl> 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; }

View file

@ -144,7 +144,7 @@ refine connection SSL_Conn += {
if ( ssl_client_hello )
{
vector<int>* cipher_suites = new vector<int>();
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());
@ -206,6 +206,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
%{
if ( ssl_extension )
@ -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);
};

View file

@ -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);
};

View file

@ -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 - -

View file

@ -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 - -

View file

@ -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 - - - - - - - -

View file

@ -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 = <skipped> 125.190.109.199 = <skipped>

View file

@ -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 - - - - - - - -

View file

@ -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 - - - - -

View file

@ -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

View file

@ -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

View file

@ -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 = {

View file

@ -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 = {

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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"]);
}

View file

@ -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

View file

@ -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

View file

@ -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 \

View file

@ -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;
}