Merge branch 'master' into topic/gilbert/plugin-api-tweak

Conflicts:
	testing/btest/Baseline/plugins.api-version-mismatch/output
	testing/btest/Baseline/plugins.hooks/output
	testing/btest/plugins/api-version-mismatch.sh
This commit is contained in:
Gilbert Clark 2014-11-24 16:21:23 -05:00
commit 7eadcad674
139 changed files with 3194 additions and 1385 deletions

151
CHANGES
View file

@ -1,4 +1,155 @@
2.3-310 | 2014-11-19 10:56:59 -0600
* Disable verbose bison output. (Jon Siwek)
2.3-309 | 2014-11-18 12:17:53 -0800
* New decompose_uri() function in base/utils/urls that splits a URI
into its pieces. (Anthony Kasza).
2.3-305 | 2014-11-18 11:09:04 -0800
* Improve coercion of &default expressions. Addresses BIT-1288. (Jon
Siwek)
2.3-303 | 2014-11-18 10:53:04 -0800
* For DH key exchanges, use p as the parameter for weak key
exchanges. (Johanna Amann)
2.3-301 | 2014-11-11 13:47:27 -0800
* Add builtin function enum_to_int() that converts an enum into a
integer. (Christian Struck)
2.3-297 | 2014-11-11 11:50:47 -0800
* Removing method from SSL analyzer that's no longer used. (Robin
Sommer)
2.3-296 | 2014-11-11 11:42:38 -0800
* A new analyzer parsing the MySQL wire protocol. Activity gets
logged into mysql.log. Supports protocol versions 9 and 10. (Vlad
Grigorescu)
2.3-278 | 2014-11-03 18:55:18 -0800
* Add new curves from draft-ietf-tls-negotiated-ff-dhe to SSL
analysis. (Johanna Amann)
2.3-274 | 2014-10-31 17:45:25 -0700
* Adding call to new binpac::init() function. (Robin Sommer)
2.3-272 | 2014-10-31 16:29:42 -0700
* Fix segfault if when statement's RHS is unitialized. Addresses
BIT-1176. (Jon Siwek)
* Fix checking vector indices via "in". Addresses BIT-1280. (Jon
Siwek)
2.3-268 | 2014-10-31 12:12:22 -0500
* BIT-1283: Fix crash when using &encrypt. (Jon Siwek)
2.3-267 | 2014-10-31 10:35:02 -0500
* BIT-1284: Allow arbitrary when statement timeout expressions
(Jon Siwek)
2.3-266 | 2014-10-31 09:21:28 -0500
* BIT-1166: Add configure options to fine tune local state dirs used
by BroControl. (Jon Siwek)
2.3-264 | 2014-10-30 13:25:57 -0500
* Fix some minor Coverity Scan complaints. (Jon Siwek)
2.3-263 | 2014-10-28 15:09:10 -0500
* Fix checking of fwrite return values (Johanna Amann)
2.3-260 | 2014-10-27 12:54:17 -0500
* Fix errors/warnings when compiling with -std=c++11 (Jon Siwek)
2.3-259 | 2014-10-27 10:04:04 -0500
* Documentation fixes. (Vicente Jimenez Aguilar and Stefano Azzalini)
2.3-256 | 2014-10-24 15:33:45 -0700
* Adding missing test baseline. (Robin Sommer)
2.3-255 | 2014-10-24 13:39:44 -0700
* Fixing unstable active-http test. (Robin Sommer)
2.3-254 | 2014-10-24 11:40:51 -0700
* Fix active-http.bro to deal reliably with empty server responses,
which will now be passed back as empty files. (Christian Struck)
2.3-248 | 2014-10-23 14:20:59 -0700
* Change order in which a plugin's scripts are loaded at startup.
(Robin Sommer)
2.3-247 | 2014-10-21 13:42:38 -0700
* Updates to the SSL analyzer. (Johanna Amann)
* Mark everything below 2048 bit as a weak key.
* Fix notice suppression.
* Add information about server-chosen protocol to ssl.log, if
provided by application_layer_next_protocol.
* Add boolean flag to ssl.log signaling if a session was
resumed. Remove the (usually not really that useful) session
ID that the client sent.
2.3-240 | 2014-10-21 13:36:33 -0700
* Fix Coverity-reported issues in DNP3 analyzer. (Seth Hall)
2.3-238 | 2014-10-16 06:51:49 -0700
* Fix multipart HTTP/MIME entity file analysis so that (1) singular
CR or LF characters in multipart body content are no longer
converted to a full CRLF (thus corrupting the file) and (2) it
also no longer considers the CRLF before the multipart boundary as
part of the content. Addresses BIT-1235. (Jon Siwek)
2.3-235 | 2014-10-15 10:20:47 -0500
* BIT-1273: Add error message for bad enum declaration syntax.
(Jon Siwek)
2.3-234 | 2014-10-14 14:42:09 -0500
* Documentation fixes. (Steve Smoot)
2.3-233 | 2014-10-09 16:00:27 -0500
* Change find-bro-logs unit test to follow symlinks. (Jon Siwek)
* Add error checks and messages to a test script (Daniel Thayer)
2.3-230 | 2014-10-08 08:15:17 -0700
* Further baseline normalization for plugin test portability. (Robin
Sommer)
2.3-229 | 2014-10-07 20:18:11 -0700
* Fix for test portability. (Robin Sommer)
2.3-228 | 2014-10-07 15:32:37 -0700 2.3-228 | 2014-10-07 15:32:37 -0700
* Include plugin unit tests into the top-level btest configuration. (Robin Sommer) * Include plugin unit tests into the top-level btest configuration. (Robin Sommer)

3
NEWS
View file

@ -25,6 +25,9 @@ New Functionality
See https://www.bro.org/sphinx-git/devel/plugins.html for more See https://www.bro.org/sphinx-git/devel/plugins.html for more
information on writing plugins. information on writing plugins.
- Bro now has supoprt for the MySQL wire protocol. Activity gets
logged into mysql.log.
Changed Functionality Changed Functionality
--------------------- ---------------------

View file

@ -1 +1 @@
2.3-228 2.3-310

@ -1 +1 @@
Subproject commit 3a4684801aafa0558383199e9abd711650b53af9 Subproject commit 77a86591dcf89d7252d3676d3f1199d6c927d073

@ -1 +1 @@
Subproject commit 95afe42e7474113a16cb2cb09ebdf8b552c59744 Subproject commit 977654dc51ab08a2afde32241f108cdb4a581d8f

@ -1 +1 @@
Subproject commit 33d0ed4a54a6ecf08a0b5fe18831aa413b437066 Subproject commit acb8fbe8e7bc6ace5135fb73dca8e29432cdc1ca

@ -1 +1 @@
Subproject commit 2f808bc8541378b1a4953cca02c58c43945d154f Subproject commit 39e865dec9611b9b53b609cbc8df519cebae0a1e

@ -1 +1 @@
Subproject commit 1efa4d10f943351efea96def68e598b053fd217a Subproject commit d67d89aaee32ad5edb9068db55d1310c2f36970a

2
cmake

@ -1 +1 @@
Subproject commit 03de0cc467d2334dcb851eddd843d59fef217909 Subproject commit 1316c07f7059647b6c4a496ea36e4b83bb5d8f0f

16
configure vendored
View file

@ -24,6 +24,13 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
--prefix=PREFIX installation directory [/usr/local/bro] --prefix=PREFIX installation directory [/usr/local/bro]
--scriptdir=PATH root installation directory for Bro scripts --scriptdir=PATH root installation directory for Bro scripts
[PREFIX/share/bro] [PREFIX/share/bro]
--localstatedir=PATH when using BroControl, path to store log files
and run-time data (within log/ and spool/ subdirs)
[PREFIX]
--spooldir=PATH when using BroControl, path to store run-time data
[PREFIX/spool]
--logdir=PATH when using BroControl, path to store log file
[PREFIX/logs]
--conf-files-dir=PATH config files installation directory [PREFIX/etc] --conf-files-dir=PATH config files installation directory [PREFIX/etc]
Optional Features: Optional Features:
@ -144,6 +151,15 @@ while [ $# -ne 0 ]; do
append_cache_entry BRO_ETC_INSTALL_DIR PATH $optarg append_cache_entry BRO_ETC_INSTALL_DIR PATH $optarg
user_set_conffilesdir="true" user_set_conffilesdir="true"
;; ;;
--localstatedir=*)
append_cache_entry BRO_LOCAL_STATE_DIR PATH $optarg
;;
--spooldir=*)
append_cache_entry BRO_SPOOL_DIR PATH $optarg
;;
--logdir=*)
append_cache_entry BRO_LOG_DIR PATH $optarg
;;
--enable-debug) --enable-debug)
append_cache_entry ENABLE_DEBUG BOOL true append_cache_entry ENABLE_DEBUG BOOL true
;; ;;

View file

@ -10,6 +10,6 @@ event bro_init()
print fmt("contents of v1: %s", v1); print fmt("contents of v1: %s", v1);
print fmt("length of v1: %d", |v1|); print fmt("length of v1: %d", |v1|);
print fmt("contents of v1: %s", v2); print fmt("contents of v2: %s", v2);
print fmt("length of v2: %d", |v2|); print fmt("length of v2: %d", |v2|);
} }

View file

@ -1,6 +1,6 @@
event bro_init() event bro_init()
{ {
local test_string = "The quick brown fox jumped over the lazy dog."; local test_string = "The quick brown fox jumps over the lazy dog.";
local test_pattern = /quick|lazy/; local test_pattern = /quick|lazy/;
if ( test_pattern in test_string ) if ( test_pattern in test_string )

View file

@ -260,7 +260,7 @@ originating host is referenced by ``c$id$orig_h`` which if given a
narrative relates to ``orig_h`` which is a member of ``id`` which is narrative relates to ``orig_h`` which is a member of ``id`` which is
a member of the data structure referred to as ``c`` that was passed a member of the data structure referred to as ``c`` that was passed
into the event handler. Given that the responder port into the event handler. Given that the responder port
``c$id$resp_p`` is ``53/tcp``, it's likely that Bro's base HTTP scripts ``c$id$resp_p`` is ``80/tcp``, it's likely that Bro's base HTTP scripts
can further populate the connection record. Let's load the can further populate the connection record. Let's load the
``base/protocols/http`` scripts and check the output of our script. ``base/protocols/http`` scripts and check the output of our script.

View file

@ -16,6 +16,7 @@ the 'dpkg-dev' package, please install it first.
} }
prefix=/opt/bro prefix=/opt/bro
localstatedir=/var/opt/bro
# During the packaging process, `dpkg-shlibs` will fail if used on a library # During the packaging process, `dpkg-shlibs` will fail if used on a library
# that links to other internal/project libraries unless an RPATH is used or # that links to other internal/project libraries unless an RPATH is used or
@ -31,7 +32,7 @@ cd ..
( cd build && make package ) ( cd build && make package )
# Full Bro package # Full Bro package
./configure --prefix=${prefix} --pkg-name-prefix=Bro --binary-package ./configure --prefix=${prefix} --localstatedir=${localstatedir} --pkg-name-prefix=Bro --binary-package
( cd build && make package ) ( cd build && make package )
# Broccoli # Broccoli
@ -42,6 +43,6 @@ cd ../..
# Broctl # Broctl
cd aux/broctl cd aux/broctl
./configure --prefix=${prefix} --binary-package ./configure --prefix=${prefix} --localstatedir=${localstatedir} --binary-package
( cd build && make package && mv *.deb ../../../build/ ) ( cd build && make package && mv *.deb ../../../build/ )
cd ../.. cd ../..

View file

@ -15,6 +15,7 @@ the 'rpm-build' package, please install it first.
} }
prefix=/opt/bro prefix=/opt/bro
localstatedir=/var/opt/bro
cd .. cd ..
@ -24,7 +25,7 @@ cd ..
( cd build && make package ) ( cd build && make package )
# Full Bro package # Full Bro package
./configure --prefix=${prefix} --pkg-name-prefix=Bro --binary-package ./configure --prefix=${prefix} --localstatedir=${localstatedir} --pkg-name-prefix=Bro --binary-package
( cd build && make package ) ( cd build && make package )
# Broccoli # Broccoli
@ -35,6 +36,6 @@ cd ../..
# Broctl # Broctl
cd aux/broctl cd aux/broctl
./configure --prefix=${prefix} --binary-package ./configure --prefix=${prefix} --localstatedir=${localstatedir} --binary-package
( cd build && make package && mv *.rpm ../../../build/ ) ( cd build && make package && mv *.rpm ../../../build/ )
cd ../.. cd ../..

View file

@ -46,6 +46,7 @@
@load base/protocols/http @load base/protocols/http
@load base/protocols/irc @load base/protocols/irc
@load base/protocols/modbus @load base/protocols/modbus
@load base/protocols/mysql
@load base/protocols/pop3 @load base/protocols/pop3
@load base/protocols/radius @load base/protocols/radius
@load base/protocols/snmp @load base/protocols/snmp

View file

@ -0,0 +1 @@
@load ./main

View file

@ -0,0 +1,38 @@
module MySQL;
export {
const commands: table[count] of string = {
[0] = "sleep",
[1] = "quit",
[2] = "init_db",
[3] = "query",
[4] = "field_list",
[5] = "create_db",
[6] = "drop_db",
[7] = "refresh",
[8] = "shutdown",
[9] = "statistics",
[10] = "process_info",
[11] = "connect",
[12] = "process_kill",
[13] = "debug",
[14] = "ping",
[15] = "time",
[16] = "delayed_insert",
[17] = "change_user",
[18] = "binlog_dump",
[19] = "table_dump",
[20] = "connect_out",
[21] = "register_slave",
[22] = "stmt_prepare",
[23] = "stmt_execute",
[24] = "stmt_send_long_data",
[25] = "stmt_close",
[26] = "stmt_reset",
[27] = "set_option",
[28] = "stmt_fetch",
[29] = "daemon",
[30] = "binlog_dump_gtid",
[31] = "reset_connection",
} &default=function(i: count): string { return fmt("unknown-%d", i); };
}

View file

@ -0,0 +1,116 @@
##! Implements base functionality for MySQL analysis. Generates the mysql.log file.
module MySQL;
@load ./consts
export {
redef enum Log::ID += { mysql::LOG };
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
## Unique ID for the connection.
uid: string &log;
## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log;
## The command that was issued
cmd: string &log;
## The argument issued to the command
arg: string &log;
## The result (error, OK, etc.) from the server
result: string &log &optional;
## Server message, if any
response: string &log &optional;
};
## Event that can be handled to access the MySQL record as it is sent on
## to the logging framework.
global log_mysql: event(rec: Info);
}
redef record connection += {
mysql: Info &optional;
};
const ports = { 1434/tcp, 3306/tcp };
event bro_init() &priority=5
{
Log::create_stream(mysql::LOG, [$columns=Info, $ev=log_mysql]);
Analyzer::register_for_ports(Analyzer::ANALYZER_MYSQL, ports);
}
event mysql_handshake(c: connection, username: string)
{
if ( ! c?$mysql )
{
local info: Info;
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
info$cmd = "login";
info$arg = username;
c$mysql = info;
}
}
event mysql_command_request(c: connection, command: count, arg: string) &priority=5
{
if ( ! c?$mysql )
{
local info: Info;
info$ts = network_time();
info$uid = c$uid;
info$id = c$id;
info$cmd = commands[command];
info$arg = sub(arg, /\0$/, "");
c$mysql = info;
}
}
event mysql_command_request(c: connection, command: count, arg: string) &priority=-5
{
if ( c?$mysql && c$mysql?$cmd && c$mysql$cmd == "quit" )
{
# We get no response for quits, so let's just log it now.
Log::write(mysql::LOG, c$mysql);
delete c$mysql;
}
}
event mysql_error(c: connection, code: count, msg: string) &priority=5
{
if ( c?$mysql )
{
c$mysql$result = "error";
c$mysql$response = msg;
}
}
event mysql_error(c: connection, code: count, msg: string) &priority=-5
{
if ( c?$mysql )
{
Log::write(mysql::LOG, c$mysql);
delete c$mysql;
}
}
event mysql_ok(c: connection, affected_rows: count) &priority=5
{
if ( c?$mysql )
{
c$mysql$result = "ok";
c$mysql$response = fmt("Affected rows: %d", affected_rows);
}
}
event mysql_ok(c: connection, affected_rows: count) &priority=-5
{
if ( c?$mysql )
{
Log::write(mysql::LOG, c$mysql);
delete c$mysql;
}
}

View file

@ -158,6 +158,12 @@ export {
[26] = "brainpoolP256r1", [26] = "brainpoolP256r1",
[27] = "brainpoolP384r1", [27] = "brainpoolP384r1",
[28] = "brainpoolP512r1", [28] = "brainpoolP512r1",
# draft-ietf-tls-negotiated-ff-dhe-02
[256] = "ffdhe2432",
[257] = "ffdhe3072",
[258] = "ffdhe4096",
[259] = "ffdhe6144",
[260] = "ffdhe8192",
[0xFF01] = "arbitrary_explicit_prime_curves", [0xFF01] = "arbitrary_explicit_prime_curves",
[0xFF02] = "arbitrary_explicit_char2_curves" [0xFF02] = "arbitrary_explicit_char2_curves"
} &default=function(i: count):string { return fmt("unknown-%d", i); }; } &default=function(i: count):string { return fmt("unknown-%d", i); };

View file

@ -12,7 +12,7 @@ export {
## Time when the SSL connection was first detected. ## Time when the SSL connection was first detected.
ts: time &log; ts: time &log;
## Unique ID for the connection. ## Unique ID for the connection.
uid: string &log; uid: string &log;
## The connection's 4-tuple of endpoint addresses/ports. ## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log; id: conn_id &log;
## SSL/TLS version that the server offered. ## SSL/TLS version that the server offered.
@ -25,9 +25,25 @@ export {
## indicates the server name that the client was requesting. ## indicates the server name that the client was requesting.
server_name: string &log &optional; server_name: string &log &optional;
## Session ID offered by the client for session resumption. ## Session ID offered by the client for session resumption.
session_id: string &log &optional; ## Not used for logging.
session_id: string &optional;
## Flag to indicate if the session was resumed reusing
## the key material exchanged in an earlier connection.
resumed: bool &log &default=F;
## Flag to indicate if we saw a non-empty session ticket being
## sent by the client using an empty session ID. This value
## is used to determine if a session is being resumed. It's
## not logged.
client_ticket_empty_session_seen: bool &default=F;
## Flag to indicate if we saw a client key exchange message sent
## by the client. This value is used to determine if a session
## is being resumed. It's not logged.
client_key_exchange_seen: bool &default=F;
## Last alert that was seen during the connection. ## Last alert that was seen during the connection.
last_alert: string &log &optional; last_alert: string &log &optional;
## Next protocol the server chose using the application layer
## next protocol extension, if present.
next_protocol: string &log &optional;
## The analyzer ID used for the analyzer instance attached ## The analyzer ID used for the analyzer instance attached
## to each connection. It is not used for logging since it's a ## to each connection. It is not used for logging since it's a
@ -36,11 +52,11 @@ export {
## Flag to indicate if this ssl session has been established ## Flag to indicate if this ssl session has been established
## succesfully, or if it was aborted during the handshake. ## succesfully, or if it was aborted during the handshake.
established: bool &log &default=F; established: bool &log &default=F;
## Flag to indicate if this record already has been logged, to ## Flag to indicate if this record already has been logged, to
## prevent duplicates. ## prevent duplicates.
logged: bool &default=F; logged: bool &default=F;
}; };
## The default root CA bundle. By default, the mozilla-ca-list.bro ## The default root CA bundle. By default, the mozilla-ca-list.bro
@ -149,8 +165,11 @@ event ssl_client_hello(c: connection, version: count, possible_ts: time, client_
set_session(c); set_session(c);
# Save the session_id if there is one set. # Save the session_id if there is one set.
if ( session_id != /^\x00{32}$/ ) if ( |session_id| > 0 && session_id != /^\x00{32}$/ )
{
c$ssl$session_id = bytestring_to_hexstr(session_id); c$ssl$session_id = bytestring_to_hexstr(session_id);
c$ssl$client_ticket_empty_session_seen = F;
}
} }
event ssl_server_hello(c: connection, version: count, possible_ts: time, server_random: string, session_id: string, cipher: count, comp_method: count) &priority=5 event ssl_server_hello(c: connection, version: count, possible_ts: time, server_random: string, session_id: string, cipher: count, comp_method: count) &priority=5
@ -159,6 +178,9 @@ event ssl_server_hello(c: connection, version: count, possible_ts: time, server_
c$ssl$version = version_strings[version]; c$ssl$version = version_strings[version];
c$ssl$cipher = cipher_desc[cipher]; c$ssl$cipher = cipher_desc[cipher];
if ( c$ssl?$session_id && c$ssl$session_id == bytestring_to_hexstr(session_id) )
c$ssl$resumed = T;
} }
event ssl_server_curve(c: connection, curve: count) &priority=5 event ssl_server_curve(c: connection, curve: count) &priority=5
@ -180,6 +202,45 @@ event ssl_extension_server_name(c: connection, is_orig: bool, names: string_vec)
} }
} }
event ssl_extension_application_layer_protocol_negotiation(c: connection, is_orig: bool, protocols: string_vec)
{
set_session(c);
if ( is_orig )
return;
if ( |protocols| > 0 )
c$ssl$next_protocol = protocols[0];
}
event ssl_handshake_message(c: connection, is_orig: bool, msg_type: count, length: count) &priority=5
{
set_session(c);
if ( is_orig && msg_type == SSL::CLIENT_KEY_EXCHANGE )
c$ssl$client_key_exchange_seen = T;
}
# Extension event is fired _before_ the respective client or server hello.
# Important for client_ticket_empty_session_seen.
event ssl_extension(c: connection, is_orig: bool, code: count, val: string) &priority=5
{
set_session(c);
if ( is_orig && SSL::extensions[code] == "SessionTicket TLS" && |val| > 0 )
# In this case, we might have an empty ID. Set back to F in client_hello event
# if it is not empty after all.
c$ssl$client_ticket_empty_session_seen = T;
}
event ssl_change_cipher_spec(c: connection, is_orig: bool) &priority=5
{
set_session(c);
if ( is_orig && c$ssl$client_ticket_empty_session_seen && ! c$ssl$client_key_exchange_seen )
c$ssl$resumed = T;
}
event ssl_alert(c: connection, is_orig: bool, level: count, desc: count) &priority=5 event ssl_alert(c: connection, is_orig: bool, level: count, desc: count) &priority=5
{ {
set_session(c); set_session(c);

View file

@ -65,12 +65,14 @@ function request2curl(r: Request, bodyfile: string, headersfile: string): string
cmd = fmt("%s -m %.0f", cmd, r$max_time); cmd = fmt("%s -m %.0f", cmd, r$max_time);
if ( r?$client_data ) if ( r?$client_data )
cmd = fmt("%s -d -", cmd); cmd = fmt("%s -d @-", cmd);
if ( r?$addl_curl_args ) if ( r?$addl_curl_args )
cmd = fmt("%s %s", cmd, r$addl_curl_args); cmd = fmt("%s %s", cmd, r$addl_curl_args);
cmd = fmt("%s \"%s\"", cmd, str_shell_escape(r$url)); cmd = fmt("%s \"%s\"", cmd, str_shell_escape(r$url));
# Make sure file will exist even if curl did not write one.
cmd = fmt("%s && touch %s", cmd, str_shell_escape(bodyfile));
return cmd; return cmd;
} }

View file

@ -106,6 +106,15 @@ event Input::end_of_data(name: string, source:string)
local track_file = parts[2]; local track_file = parts[2];
# If the file is empty, still add it to the result$files table. This is needed
# because it is expected that the file was read even if it was empty.
local result = results[name];
if ( ! result?$files )
result$files = table();
if ( track_file !in result$files )
result$files[track_file] = vector();
Input::remove(name); Input::remove(name);
if ( name !in pending_files ) if ( name !in pending_files )

View file

@ -3,6 +3,28 @@
## A regular expression for matching and extracting URLs. ## A regular expression for matching and extracting URLs.
const url_regex = /^([a-zA-Z\-]{3,5})(:\/\/[^\/?#"'\r\n><]*)([^?#"'\r\n><]*)([^[:blank:]\r\n"'><]*|\??[^"'\r\n><]*)/ &redef; const url_regex = /^([a-zA-Z\-]{3,5})(:\/\/[^\/?#"'\r\n><]*)([^?#"'\r\n><]*)([^[:blank:]\r\n"'><]*|\??[^"'\r\n><]*)/ &redef;
## A URI, as parsed by :bro:id:`decompose_uri`.
type URI: record {
## The URL's scheme..
scheme: string &optional;
## The location, which could be a domain name or an IP address. Left empty if not
## specified.
netlocation: string;
## Port number, if included in URI.
portnum: count &optional;
## Full including the file name. Will be '/' if there's not path given.
path: string;
## Full file name, including extension, if there is a file name.
file_name: string &optional;
## The base filename, without extension, if there is a file name.
file_base: string &optional;
## The filename's extension, if there is a file name.
file_ext: string &optional;
## A table of all query parameters, mapping their keys to values, if there's a
## query.
params: table[string] of string &optional;
};
## Extracts URLs discovered in arbitrary text. ## Extracts URLs discovered in arbitrary text.
function find_all_urls(s: string): string_set function find_all_urls(s: string): string_set
{ {
@ -23,3 +45,84 @@ function find_all_urls_without_scheme(s: string): string_set
return return_urls; return return_urls;
} }
function decompose_uri(s: string): URI
{
local parts: string_array;
local u: URI = [$netlocation="", $path="/"];
if ( /\?/ in s)
{
# Parse query.
u$params = table();
parts = split1(s, /\?/);
s = parts[1];
local query: string = parts[2];
if ( /&/ in query )
{
local opv: table[count] of string = split(query, /&/);
for ( each in opv )
{
if ( /=/ in opv[each] )
{
parts = split1(opv[each], /=/);
u$params[parts[1]] = parts[2];
}
}
}
else
{
parts = split1(query, /=/);
u$params[parts[1]] = parts[2];
}
}
if ( /:\/\// in s )
{
# Parse scheme and remove from s.
parts = split1(s, /:\/\//);
u$scheme = parts[1];
s = parts[2];
}
if ( /\// in s )
{
# Parse path and remove from s.
parts = split1(s, /\//);
s = parts[1];
u$path = fmt("/%s", parts[2]);
if ( |u$path| > 1 && u$path[|u$path| - 1] != "/" )
{
local last_token: string = find_last(u$path, /\/.+/);
local full_filename = split1(last_token, /\//)[2];
if ( /\./ in full_filename )
{
u$file_name = full_filename;
u$file_base = split1(full_filename, /\./)[1];
u$file_ext = split1(full_filename, /\./)[2];
}
else
{
u$file_name = full_filename;
u$file_base = full_filename;
}
}
}
if ( /:/ in s )
{
# Parse location and port.
parts = split1(s, /:/);
u$netlocation = parts[1];
u$portnum = to_count(parts[2]);
}
else
u$netlocation = s;
return u;
}

View file

@ -0,0 +1,20 @@
##! Software identification and extraction for MySQL traffic.
@load base/frameworks/software
module MySQL;
export {
redef enum Software::Type += {
## Identifier for MySQL servers in the software framework.
SERVER,
};
}
event mysql_server_version(c: connection, ver: string)
{
if ( ver == "" )
return;
Software::found(c$id, [$unparsed_version=ver, $host=c$id$resp_h, $software_type=SERVER]);
}

View file

@ -22,7 +22,7 @@ export {
## The minimal key length in bits that is considered to be safe. Any shorter ## The minimal key length in bits that is considered to be safe. Any shorter
## (non-EC) key lengths will trigger the notice. ## (non-EC) key lengths will trigger the notice.
const notify_minimal_key_length = 1024 &redef; const notify_minimal_key_length = 2048 &redef;
## Warn if the DH key length is smaller than the certificate key length. This is ## Warn if the DH key length is smaller than the certificate key length. This is
## potentially unsafe because it gives a wrong impression of safety due to the ## potentially unsafe because it gives a wrong impression of safety due to the
@ -56,7 +56,7 @@ event ssl_established(c: connection) &priority=3
NOTICE([$note=Weak_Key, NOTICE([$note=Weak_Key,
$msg=fmt("Host uses weak certificate with %d bit key", key_length), $msg=fmt("Host uses weak certificate with %d bit key", key_length),
$conn=c, $suppress_for=1day, $conn=c, $suppress_for=1day,
$identifier=cat(c$id$orig_h, c$id$orig_p, key_length) $identifier=cat(c$id$resp_h, c$id$resp_h, key_length)
]); ]);
} }
@ -65,13 +65,13 @@ event ssl_dh_server_params(c: connection, p: string, q: string, Ys: string) &pri
if ( ! addr_matches_host(c$id$resp_h, notify_weak_keys) ) if ( ! addr_matches_host(c$id$resp_h, notify_weak_keys) )
return; return;
local key_length = |Ys| * 8; # key length in bits local key_length = |p| * 8; # length of the used prime number in bits
if ( key_length < notify_minimal_key_length ) if ( key_length < notify_minimal_key_length )
NOTICE([$note=Weak_Key, NOTICE([$note=Weak_Key,
$msg=fmt("Host uses weak DH parameters with %d key bits", key_length), $msg=fmt("Host uses weak DH parameters with %d key bits", key_length),
$conn=c, $suppress_for=1day, $conn=c, $suppress_for=1day,
$identifier=cat(c$id$orig_h, c$id$orig_p, key_length) $identifier=cat(c$id$resp_h, c$id$resp_p, key_length)
]); ]);
if ( notify_dh_length_shorter_cert_length && if ( notify_dh_length_shorter_cert_length &&
@ -86,7 +86,7 @@ event ssl_dh_server_params(c: connection, p: string, q: string, Ys: string) &pri
$msg=fmt("DH key length of %d bits is smaller certificate key length of %d bits", $msg=fmt("DH key length of %d bits is smaller certificate key length of %d bits",
key_length, c$ssl$cert_chain[0]$x509$certificate$key_length), key_length, c$ssl$cert_chain[0]$x509$certificate$key_length),
$conn=c, $suppress_for=1day, $conn=c, $suppress_for=1day,
$identifier=cat(c$id$orig_h, c$id$orig_p) $identifier=cat(c$id$resp_h, c$id$resp_p)
]); ]);
} }
} }

View file

@ -75,6 +75,7 @@
@load protocols/http/var-extraction-uri.bro @load protocols/http/var-extraction-uri.bro
@load protocols/modbus/known-masters-slaves.bro @load protocols/modbus/known-masters-slaves.bro
@load protocols/modbus/track-memmap.bro @load protocols/modbus/track-memmap.bro
@load protocols/mysql/software.bro
@load protocols/smtp/blocklists.bro @load protocols/smtp/blocklists.bro
@load protocols/smtp/detect-suspicious-orig.bro @load protocols/smtp/detect-suspicious-orig.bro
@load protocols/smtp/entities-excerpt.bro @load protocols/smtp/entities-excerpt.bro

View file

@ -265,6 +265,14 @@ void Attributes::CheckAttr(Attr* a)
// Ok. // Ok.
break; break;
Expr* e = a->AttrExpr();
if ( check_and_promote_expr(e, type) )
{
a->SetAttrExpr(e);
// Ok.
break;
}
a->AttrExpr()->Error("&default value has inconsistent type", type); a->AttrExpr()->Error("&default value has inconsistent type", type);
} }
@ -297,8 +305,11 @@ void Attributes::CheckAttr(Attr* a)
Expr* e = a->AttrExpr(); Expr* e = a->AttrExpr();
if ( check_and_promote_expr(e, ytype) ) if ( check_and_promote_expr(e, ytype) )
{
a->SetAttrExpr(e);
// Ok. // Ok.
break; break;
}
Error("&default value has inconsistent type 2"); Error("&default value has inconsistent type 2");
} }

View file

@ -45,6 +45,13 @@ public:
attr_tag Tag() const { return tag; } attr_tag Tag() const { return tag; }
Expr* AttrExpr() const { return expr; } Expr* AttrExpr() const { return expr; }
// Up to the caller to decide if previous expr can be unref'd since it may
// not always be safe; e.g. expressions (at time of writing) don't always
// keep careful track of referencing their operands, so doing something
// like SetAttrExpr(coerce(AttrExpr())) must not completely unref the
// previous expr as the new expr depends on it.
void SetAttrExpr(Expr* e) { expr = e; }
int RedundantAttrOkay() const int RedundantAttrOkay() const
{ return tag == ATTR_REDEF || tag == ATTR_OPTIONAL; } { return tag == ATTR_REDEF || tag == ATTR_OPTIONAL; }

View file

@ -96,7 +96,7 @@ bool Brofiler::WriteStats()
map<pair<string, string>, uint64 >::const_iterator it; map<pair<string, string>, uint64 >::const_iterator it;
for ( it = usage_map.begin(); it != usage_map.end(); ++it ) for ( it = usage_map.begin(); it != usage_map.end(); ++it )
{ {
fprintf(f, "%"PRIu64"%c%s%c%s\n", it->second, delim, fprintf(f, "%" PRIu64"%c%s%c%s\n", it->second, delim,
it->first.first.c_str(), delim, it->first.second.c_str()); it->first.first.c_str(), delim, it->first.second.c_str());
} }

View file

@ -48,7 +48,7 @@ set(BISON_FLAGS "--debug")
bison_target(BIFParser builtin-func.y bison_target(BIFParser builtin-func.y
${CMAKE_CURRENT_BINARY_DIR}/bif_parse.cc ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.cc
HEADER ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.h HEADER ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.h
VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.output #VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/bif_parse.output
COMPILE_FLAGS "${BISON_FLAGS}") COMPILE_FLAGS "${BISON_FLAGS}")
flex_target(BIFScanner builtin-func.l ${CMAKE_CURRENT_BINARY_DIR}/bif_lex.cc) flex_target(BIFScanner builtin-func.l ${CMAKE_CURRENT_BINARY_DIR}/bif_lex.cc)
add_flex_bison_dependency(BIFScanner BIFParser) add_flex_bison_dependency(BIFScanner BIFParser)
@ -57,7 +57,7 @@ add_flex_bison_dependency(BIFScanner BIFParser)
bison_target(RuleParser rule-parse.y bison_target(RuleParser rule-parse.y
${CMAKE_CURRENT_BINARY_DIR}/rup.cc ${CMAKE_CURRENT_BINARY_DIR}/rup.cc
HEADER ${CMAKE_CURRENT_BINARY_DIR}/rup.h HEADER ${CMAKE_CURRENT_BINARY_DIR}/rup.h
VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/rule_parse.output #VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/rule_parse.output
COMPILE_FLAGS "${BISON_FLAGS}") COMPILE_FLAGS "${BISON_FLAGS}")
replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/rup.cc replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/rup.cc
${CMAKE_CURRENT_BINARY_DIR}/rule-parse.cc ${CMAKE_CURRENT_BINARY_DIR}/rule-parse.cc
@ -72,7 +72,7 @@ flex_target(RuleScanner rule-scan.l ${CMAKE_CURRENT_BINARY_DIR}/rule-scan.cc
bison_target(REParser re-parse.y bison_target(REParser re-parse.y
${CMAKE_CURRENT_BINARY_DIR}/rep.cc ${CMAKE_CURRENT_BINARY_DIR}/rep.cc
HEADER ${CMAKE_CURRENT_BINARY_DIR}/re-parse.h HEADER ${CMAKE_CURRENT_BINARY_DIR}/re-parse.h
VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/re_parse.output #VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/re_parse.output
COMPILE_FLAGS "${BISON_FLAGS}") COMPILE_FLAGS "${BISON_FLAGS}")
replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/rep.cc replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/rep.cc
${CMAKE_CURRENT_BINARY_DIR}/re-parse.cc ${CMAKE_CURRENT_BINARY_DIR}/re-parse.cc
@ -85,7 +85,7 @@ add_flex_bison_dependency(REScanner REParser)
bison_target(Parser parse.y bison_target(Parser parse.y
${CMAKE_CURRENT_BINARY_DIR}/p.cc ${CMAKE_CURRENT_BINARY_DIR}/p.cc
HEADER ${CMAKE_CURRENT_BINARY_DIR}/broparse.h HEADER ${CMAKE_CURRENT_BINARY_DIR}/broparse.h
VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/parse.output #VERBOSE ${CMAKE_CURRENT_BINARY_DIR}/parse.output
COMPILE_FLAGS "${BISON_FLAGS}") COMPILE_FLAGS "${BISON_FLAGS}")
replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/p.cc replace_yy_prefix_target(${CMAKE_CURRENT_BINARY_DIR}/p.cc
${CMAKE_CURRENT_BINARY_DIR}/parse.cc ${CMAKE_CURRENT_BINARY_DIR}/parse.cc

View file

@ -214,7 +214,7 @@ DNS_Mapping::DNS_Mapping(FILE* f)
char req_buf[512+1], name_buf[512+1]; char req_buf[512+1], name_buf[512+1];
int is_req_host; int is_req_host;
if ( sscanf(buf, "%lf %d %512s %d %512s %d %d %"PRIu32, &creation_time, if ( sscanf(buf, "%lf %d %512s %d %512s %d %d %" PRIu32, &creation_time,
&is_req_host, req_buf, &failed, name_buf, &map_type, &num_addrs, &is_req_host, req_buf, &failed, name_buf, &map_type, &num_addrs,
&req_ttl) != 8 ) &req_ttl) != 8 )
return; return;
@ -360,7 +360,7 @@ void DNS_Mapping::Clear()
void DNS_Mapping::Save(FILE* f) const void DNS_Mapping::Save(FILE* f) const
{ {
fprintf(f, "%.0f %d %s %d %s %d %d %"PRIu32"\n", creation_time, req_host != 0, fprintf(f, "%.0f %d %s %d %s %d %d %" PRIu32"\n", creation_time, req_host != 0,
req_host ? req_host : req_addr.AsString().c_str(), req_host ? req_host : req_addr.AsString().c_str(),
failed, (names && names[0]) ? names[0] : "*", failed, (names && names[0]) ? names[0] : "*",
map_type, num_addrs, req_ttl); map_type, num_addrs, req_ttl);

View file

@ -636,7 +636,7 @@ Val* BinaryExpr::Eval(Frame* f) const
return v_result; return v_result;
} }
if ( is_vec1 || is_vec2 ) if ( IsVector(Type()->Tag()) && (is_vec1 || is_vec2) )
{ // fold vector against scalar { // fold vector against scalar
VectorVal* vv = (is_vec1 ? v1 : v2)->AsVectorVal(); VectorVal* vv = (is_vec1 ? v1 : v2)->AsVectorVal();
VectorVal* v_result = new VectorVal(Type()->AsVectorType()); VectorVal* v_result = new VectorVal(Type()->AsVectorType());
@ -4703,8 +4703,14 @@ Val* InExpr::Fold(Val* v1, Val* v2) const
v2->Type()->Tag() == TYPE_SUBNET ) v2->Type()->Tag() == TYPE_SUBNET )
return new Val(v2->AsSubNetVal()->Contains(v1->AsAddr()), TYPE_BOOL); return new Val(v2->AsSubNetVal()->Contains(v1->AsAddr()), TYPE_BOOL);
TableVal* vt = v2->AsTableVal(); Val* res;
if ( vt->Lookup(v1, false) )
if ( is_vector(v2) )
res = v2->AsVectorVal()->Lookup(v1);
else
res = v2->AsTableVal()->Lookup(v1, false);
if ( res )
return new Val(1, TYPE_BOOL); return new Val(1, TYPE_BOOL);
else else
return new Val(0, TYPE_BOOL); return new Val(0, TYPE_BOOL);

View file

@ -527,7 +527,7 @@ void BroFile::SetAttrs(Attributes* arg_attrs)
if ( ef->AttrExpr() ) if ( ef->AttrExpr() )
InitEncrypt(ef->AttrExpr()->ExprVal()->AsString()->CheckString()); InitEncrypt(ef->AttrExpr()->ExprVal()->AsString()->CheckString());
else else
InitEncrypt(log_encryption_key->AsString()->CheckString()); InitEncrypt(opt_internal_string("log_encryption_key")->CheckString());
} }
if ( attrs->FindAttr(ATTR_RAW_OUTPUT) ) if ( attrs->FindAttr(ATTR_RAW_OUTPUT) )
@ -708,10 +708,10 @@ void BroFile::InitEncrypt(const char* keyfile)
secret_len = htonl(secret_len); secret_len = htonl(secret_len);
if ( ! (fwrite("BROENC1", 7, 1, f) && if ( fwrite("BROENC1", 7, 1, f) < 1 ||
fwrite(&secret_len, sizeof(secret_len), 1, f) && fwrite(&secret_len, sizeof(secret_len), 1, f) < 1 ||
fwrite(secret, ntohl(secret_len), 1, f) && fwrite(secret, ntohl(secret_len), 1, f) < 1 ||
fwrite(iv, iv_len, 1, f)) ) fwrite(iv, iv_len, 1, f) < 1 )
{ {
reporter->Error("can't write header to log file %s: %s", reporter->Error("can't write header to log file %s: %s",
name, strerror(errno)); name, strerror(errno));
@ -736,7 +736,7 @@ void BroFile::FinishEncrypt()
int outl; int outl;
EVP_SealFinal(cipher_ctx, cipher_buffer, &outl); EVP_SealFinal(cipher_ctx, cipher_buffer, &outl);
if ( outl && ! fwrite(cipher_buffer, outl, 1, f) ) if ( outl && fwrite(cipher_buffer, outl, 1, f) < 1 )
{ {
reporter->Error("write error for %s: %s", reporter->Error("write error for %s: %s",
name, strerror(errno)); name, strerror(errno));
@ -777,7 +777,7 @@ int BroFile::Write(const char* data, int len)
return 0; return 0;
} }
if ( outl && ! fwrite(cipher_buffer, outl, 1, f) ) if ( outl && fwrite(cipher_buffer, outl, 1, f) < 1 )
{ {
reporter->Error("write error for %s: %s", reporter->Error("write error for %s: %s",
name, strerror(errno)); name, strerror(errno));
@ -792,8 +792,7 @@ int BroFile::Write(const char* data, int len)
return 1; return 1;
} }
len = fwrite(data, 1, len, f); if ( fwrite(data, len, 1, f) < 1 )
if ( len <= 0 )
return false; return false;
if ( rotate_size && current_size < rotate_size && current_size + len >= rotate_size ) if ( rotate_size && current_size < rotate_size && current_size + len >= rotate_size )

View file

@ -22,7 +22,7 @@ static void bad_pipe_op(const char* which)
void Flare::Fire() void Flare::Fire()
{ {
char tmp; char tmp = 0;
for ( ; ; ) for ( ; ; )
{ {

View file

@ -48,14 +48,13 @@
#include "Reporter.h" #include "Reporter.h"
#include "plugin/Manager.h" #include "plugin/Manager.h"
using plugin::ValWrapper;
extern RETSIGTYPE sig_handler(int signo); extern RETSIGTYPE sig_handler(int signo);
const Expr* calling_expr = 0; const Expr* calling_expr = 0;
bool did_builtin_init = false; bool did_builtin_init = false;
vector<Func*> Func::unique_ids; vector<Func*> Func::unique_ids;
static std::pair<Val*, bool> empty_hook_result(NULL, false);
Func::Func() : scope(0), type(0) Func::Func() : scope(0), type(0)
{ {
@ -247,33 +246,29 @@ TraversalCode Func::Traverse(TraversalCallback* cb) const
HANDLE_TC_STMT_POST(tc); HANDLE_TC_STMT_POST(tc);
} }
ValWrapper* Func::HandlePluginResult(ValWrapper* plugin_result, val_list* args, function_flavor flavor) const std::pair<Val*, bool> Func::HandlePluginResult(std::pair<Val*, bool> plugin_result, val_list* args, function_flavor flavor) const
{ {
// We either have not received a plugin result, or the plugin result hasn't been processed (read: fall into ::Call method) // The plugin result hasn't been processed (read: fall into ::Call method)
if(!plugin_result)
return NULL;
if(!plugin_result->processed) if(!plugin_result.second)
{ {
if(plugin_result->value) if(plugin_result.first)
{ {
Unref(plugin_result->value); reporter->InternalError("plugin set processed flag to false but actually returned a value");
plugin_result->value = NULL;
} }
delete plugin_result; return plugin_result;
return NULL;
} }
switch ( flavor ) { switch ( flavor ) {
case FUNC_FLAVOR_EVENT: case FUNC_FLAVOR_EVENT:
if(plugin_result->value) if(plugin_result.first)
{ {
reporter->InternalError("plugin returned non-void result for event %s", this->Name()); reporter->InternalError("plugin returned non-void result for event %s", this->Name());
} }
break; break;
case FUNC_FLAVOR_HOOK: case FUNC_FLAVOR_HOOK:
if ( plugin_result->value->Type()->Tag() != TYPE_BOOL ) if ( plugin_result.first->Type()->Tag() != TYPE_BOOL )
{ {
reporter->InternalError("plugin returned non-bool for hook %s", this->Name()); reporter->InternalError("plugin returned non-bool for hook %s", this->Name());
} }
@ -285,14 +280,14 @@ ValWrapper* Func::HandlePluginResult(ValWrapper* plugin_result, val_list* args,
if ( (! yt) || yt->Tag() == TYPE_VOID ) if ( (! yt) || yt->Tag() == TYPE_VOID )
{ {
if(plugin_result && plugin_result->value) if(plugin_result.first)
{ {
reporter->InternalError("plugin returned non-void result for void method %s", this->Name()); reporter->InternalError("plugin returned non-void result for void method %s", this->Name());
} }
} }
else if ( plugin_result->value && plugin_result->value->Type()->Tag() != yt->Tag() && yt->Tag() != TYPE_ANY) else if ( plugin_result.first && plugin_result.first->Type()->Tag() != yt->Tag() && yt->Tag() != TYPE_ANY)
{ {
reporter->InternalError("plugin returned wrong type (got %d, expecting %d) for %s", plugin_result->value->Type()->Tag(), yt->Tag(), this->Name()); reporter->InternalError("plugin returned wrong type (got %d, expecting %d) for %s", plugin_result.first->Type()->Tag(), yt->Tag(), this->Name());
} }
break; break;
@ -347,14 +342,13 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const
if ( sample_logger ) if ( sample_logger )
sample_logger->FunctionSeen(this); sample_logger->FunctionSeen(this);
ValWrapper* plugin_result = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), 0); std::pair<Val*, bool> plugin_result = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), empty_hook_result);
plugin_result = HandlePluginResult(plugin_result, args, Flavor()); plugin_result = HandlePluginResult(plugin_result, args, Flavor());
if(plugin_result) if(plugin_result.second)
{ {
Val *result = plugin_result->value; Val *result = plugin_result.first;
delete plugin_result;
return result; return result;
} }
@ -570,13 +564,12 @@ Val* BuiltinFunc::Call(val_list* args, Frame* parent) const
if ( sample_logger ) if ( sample_logger )
sample_logger->FunctionSeen(this); sample_logger->FunctionSeen(this);
ValWrapper* plugin_result = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), 0); std::pair<Val*, bool> plugin_result = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), empty_hook_result);
plugin_result = HandlePluginResult(plugin_result, args, FUNC_FLAVOR_FUNCTION); plugin_result = HandlePluginResult(plugin_result, args, FUNC_FLAVOR_FUNCTION);
if(plugin_result) if(plugin_result.second)
{ {
Val *result = plugin_result->value; Val *result = plugin_result.first;
delete plugin_result;
return result; return result;
} }

View file

@ -3,6 +3,8 @@
#ifndef func_h #ifndef func_h
#define func_h #define func_h
#include <utility>
#include "BroList.h" #include "BroList.h"
#include "Obj.h" #include "Obj.h"
#include "Debug.h" #include "Debug.h"
@ -14,9 +16,6 @@ class Stmt;
class Frame; class Frame;
class ID; class ID;
class CallExpr; class CallExpr;
namespace plugin {
struct ValWrapper;
}
class Func : public BroObj { class Func : public BroObj {
public: public:
@ -74,7 +73,7 @@ protected:
Func(); Func();
// Helper function for handling result of plugin hook. // Helper function for handling result of plugin hook.
plugin::ValWrapper* HandlePluginResult(plugin::ValWrapper* plugin_result, val_list* args, function_flavor flavor) const; std::pair<Val*, bool> HandlePluginResult(std::pair<Val*, bool> plugin_result, val_list* args, function_flavor flavor) const;
DECLARE_ABSTRACT_SERIAL(Func); DECLARE_ABSTRACT_SERIAL(Func);

View file

@ -110,7 +110,7 @@ public:
T result = 0; T result = 0;
// loop optmized with Duff's Device // loop optmized with Duff's Device
register unsigned n = (size + 7) / 8; unsigned n = (size + 7) / 8;
switch ( size % 8 ) { switch ( size % 8 ) {
case 0: do { result ^= byte_lookup[offset++][*p++]; case 0: do { result ^= byte_lookup[offset++][*p++];
case 7: result ^= byte_lookup[offset++][*p++]; case 7: result ^= byte_lookup[offset++][*p++];

View file

@ -182,7 +182,7 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, uint64 seq, uint64 upper,
{ {
if ( DEBUG_reassem ) if ( DEBUG_reassem )
{ {
DEBUG_MSG("%.6f Reassembler::AddAndCheck seq=%"PRIu64", upper=%"PRIu64"\n", DEBUG_MSG("%.6f Reassembler::AddAndCheck seq=%" PRIu64", upper=%" PRIu64"\n",
network_time, seq, upper); network_time, seq, upper);
} }

View file

@ -707,7 +707,7 @@ RemoteSerializer::PeerID RemoteSerializer::Connect(const IPAddr& ip,
const size_t BUFSIZE = 1024; const size_t BUFSIZE = 1024;
char* data = new char[BUFSIZE]; char* data = new char[BUFSIZE];
snprintf(data, BUFSIZE, snprintf(data, BUFSIZE,
"%"PRI_PTR_COMPAT_UINT",%s,%s,%"PRIu16",%"PRIu32",%d", p->id, "%" PRI_PTR_COMPAT_UINT",%s,%s,%" PRIu16",%" PRIu32",%d", p->id,
ip.AsString().c_str(), zone_id.c_str(), port, uint32(retry), ip.AsString().c_str(), zone_id.c_str(), port, uint32(retry),
use_ssl); use_ssl);
@ -1267,7 +1267,7 @@ bool RemoteSerializer::Listen(const IPAddr& ip, uint16 port, bool expect_ssl,
const size_t BUFSIZE = 1024; const size_t BUFSIZE = 1024;
char* data = new char[BUFSIZE]; char* data = new char[BUFSIZE];
snprintf(data, BUFSIZE, "%s,%"PRIu16",%d,%d,%s,%"PRIu32, snprintf(data, BUFSIZE, "%s,%" PRIu16",%d,%d,%s,%" PRIu32,
ip.AsString().c_str(), port, expect_ssl, ipv6, zone_id.c_str(), ip.AsString().c_str(), port, expect_ssl, ipv6, zone_id.c_str(),
(uint32) retry); (uint32) retry);
@ -4075,7 +4075,7 @@ bool SocketComm::Connect(Peer* peer)
const size_t BUFSIZE = 1024; const size_t BUFSIZE = 1024;
char* data = new char[BUFSIZE]; char* data = new char[BUFSIZE];
snprintf(data, BUFSIZE, "%s,%"PRIu32, peer->ip.AsString().c_str(), snprintf(data, BUFSIZE, "%s,%" PRIu32, peer->ip.AsString().c_str(),
peer->port); peer->port);
if ( ! SendToParent(MSG_CONNECTED, peer, data) ) if ( ! SendToParent(MSG_CONNECTED, peer, data) )
@ -4190,7 +4190,7 @@ bool SocketComm::Listen()
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0 ) setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0 )
Error(fmt("can't set IPV6_V6ONLY, %s", strerror(errno))); Error(fmt("can't set IPV6_V6ONLY, %s", strerror(errno)));
if ( bind(fd, res->ai_addr, res->ai_addrlen) < 0 ) if ( ::bind(fd, res->ai_addr, res->ai_addrlen) < 0 )
{ {
Error(fmt("can't bind to %s:%s, %s", l_addr_str.c_str(), Error(fmt("can't bind to %s:%s, %s", l_addr_str.c_str(),
port_str, strerror(errno))); port_str, strerror(errno)));
@ -4287,7 +4287,7 @@ bool SocketComm::AcceptConnection(int fd)
const size_t BUFSIZE = 1024; const size_t BUFSIZE = 1024;
char* data = new char[BUFSIZE]; char* data = new char[BUFSIZE];
snprintf(data, BUFSIZE, "%s,%"PRIu32, peer->ip.AsString().c_str(), snprintf(data, BUFSIZE, "%s,%" PRIu32, peer->ip.AsString().c_str(),
peer->port); peer->port);
if ( ! SendToParent(MSG_CONNECTED, peer, data) ) if ( ! SendToParent(MSG_CONNECTED, peer, data) )

View file

@ -541,19 +541,19 @@ bool XMLSerializationFormat::Write(uint16 v, const char* tag)
bool XMLSerializationFormat::Write(uint32 v, const char* tag) bool XMLSerializationFormat::Write(uint32 v, const char* tag)
{ {
const char* tmp = fmt("%"PRIu32, v); const char* tmp = fmt("%" PRIu32, v);
return WriteElem(tag, "uint32", tmp, strlen(tmp)); return WriteElem(tag, "uint32", tmp, strlen(tmp));
} }
bool XMLSerializationFormat::Write(uint64 v, const char* tag) bool XMLSerializationFormat::Write(uint64 v, const char* tag)
{ {
const char* tmp = fmt("%"PRIu64, v); const char* tmp = fmt("%" PRIu64, v);
return WriteElem(tag, "uint64", tmp, strlen(tmp)); return WriteElem(tag, "uint64", tmp, strlen(tmp));
} }
bool XMLSerializationFormat::Write(int64 v, const char* tag) bool XMLSerializationFormat::Write(int64 v, const char* tag)
{ {
const char* tmp = fmt("%"PRId64, v); const char* tmp = fmt("%" PRId64, v);
return WriteElem(tag, "int64", tmp, strlen(tmp)); return WriteElem(tag, "int64", tmp, strlen(tmp));
} }

View file

@ -544,7 +544,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
if ( proto_typ != 0x0800 && proto_typ != 0x86dd ) if ( proto_typ != 0x0800 && proto_typ != 0x86dd )
{ {
// Not IPv4/IPv6 payload. // Not IPv4/IPv6 payload.
Weird(fmt("unknown_gre_protocol_%"PRIu16, proto_typ), ip_hdr, Weird(fmt("unknown_gre_protocol_%" PRIu16, proto_typ), ip_hdr,
encapsulation); encapsulation);
return; return;
} }

View file

@ -160,7 +160,7 @@ void ProfileLogger::Log()
file->Write(fmt("%.06f Connections expired due to inactivity: %d\n", file->Write(fmt("%.06f Connections expired due to inactivity: %d\n",
network_time, killed_by_inactivity)); network_time, killed_by_inactivity));
file->Write(fmt("%.06f Total reassembler data: %"PRIu64"K\n", network_time, file->Write(fmt("%.06f Total reassembler data: %" PRIu64"K\n", network_time,
Reassembler::TotalMemoryAllocation() / 1024)); Reassembler::TotalMemoryAllocation() / 1024));
// Signature engine. // Signature engine.

View file

@ -131,18 +131,19 @@ Trigger::Trigger(Expr* arg_cond, Stmt* arg_body, Stmt* arg_timeout_stmts,
arg_frame->SetDelayed(); arg_frame->SetDelayed();
} }
Val* timeout = arg_timeout ? arg_timeout->ExprVal() : 0; Val* timeout_val = arg_timeout ? arg_timeout->Eval(arg_frame) : 0;
// Make sure we don't get deleted if somebody calls a method like // Make sure we don't get deleted if somebody calls a method like
// Timeout() while evaluating the trigger. // Timeout() while evaluating the trigger.
Ref(this); Ref(this);
if ( ! Eval() && timeout ) if ( ! Eval() && timeout_val )
{ {
timer = new TriggerTimer(timeout->AsInterval(), this); timer = new TriggerTimer(timeout_val->AsInterval(), this);
timer_mgr->Add(timer); timer_mgr->Add(timer);
} }
Unref(timeout_val);
Unref(this); Unref(this);
} }
@ -206,7 +207,7 @@ bool Trigger::Eval()
return false; return false;
} }
if ( v->IsZero() ) if ( ! v || v->IsZero() )
{ {
// Not true. Perhaps next time... // Not true. Perhaps next time...
DBG_LOG(DBG_NOTIFIERS, "%s: trigger condition is false", Name()); DBG_LOG(DBG_NOTIFIERS, "%s: trigger condition is false", Name());

View file

@ -598,7 +598,7 @@ SupportAnalyzer* Analyzer::FirstSupportAnalyzer(bool orig)
void Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, void Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
uint64 seq, const IP_Hdr* ip, int caplen) uint64 seq, const IP_Hdr* ip, int caplen)
{ {
DBG_LOG(DBG_ANALYZER, "%s DeliverPacket(%d, %s, %"PRIu64", %p, %d) [%s%s]", DBG_LOG(DBG_ANALYZER, "%s DeliverPacket(%d, %s, %" PRIu64", %p, %d) [%s%s]",
fmt_analyzer(this).c_str(), len, is_orig ? "T" : "F", seq, ip, caplen, fmt_analyzer(this).c_str(), len, is_orig ? "T" : "F", seq, ip, caplen,
fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : ""); fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : "");
} }
@ -612,7 +612,7 @@ void Analyzer::DeliverStream(int len, const u_char* data, bool is_orig)
void Analyzer::Undelivered(uint64 seq, int len, bool is_orig) void Analyzer::Undelivered(uint64 seq, int len, bool is_orig)
{ {
DBG_LOG(DBG_ANALYZER, "%s Undelivered(%"PRIu64", %d, %s)", DBG_LOG(DBG_ANALYZER, "%s Undelivered(%" PRIu64", %d, %s)",
fmt_analyzer(this).c_str(), seq, len, is_orig ? "T" : "F"); fmt_analyzer(this).c_str(), seq, len, is_orig ? "T" : "F");
} }

View file

@ -21,6 +21,7 @@ add_subdirectory(irc)
add_subdirectory(login) add_subdirectory(login)
add_subdirectory(mime) add_subdirectory(mime)
add_subdirectory(modbus) add_subdirectory(modbus)
add_subdirectory(mysql)
add_subdirectory(ncp) add_subdirectory(ncp)
add_subdirectory(netbios) add_subdirectory(netbios)
add_subdirectory(netflow) add_subdirectory(netflow)

View file

@ -5,18 +5,18 @@ connection DNP3_Conn(bro_analyzer: BroAnalyzer) {
}; };
%header{ %header{
uint64 bytestring_to_time(const_bytestring time48, size_t length); uint64 bytestring_to_time(const_bytestring time48);
%} %}
%code{ %code{
uint64 bytestring_to_time(const_bytestring time48, size_t length) uint64 bytestring_to_time(const_bytestring time48)
{ {
/* In DNP3, a timestamp is represented by 6 bytes since epoch /* In DNP3, a timestamp is represented by 6 bytes since epoch
in milliseconds. The 6 bytes are stored in big endian format. */ in milliseconds. The 6 bytes are stored in big endian format. */
uint64 epochTime = 0; uint64 epochTime = 0;
for ( unsigned int i = 0; i < length; i++ ) for ( int i = time48.length() - 1; i >= 0; i-- )
epochTime = time48[length - i - 1] + epochTime * 256; epochTime = time48[i] + epochTime * 256;
return epochTime; return epochTime;
} }
@ -240,7 +240,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_frozen_counter_32wFlagTime( BifEvent::generate_dnp3_frozen_counter_32wFlagTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, count_value, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, count_value, bytestring_to_time(time48));
} }
return true; return true;
@ -254,7 +254,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_frozen_counter_16wFlagTime( BifEvent::generate_dnp3_frozen_counter_16wFlagTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, count_value, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, count_value, bytestring_to_time(time48));
} }
return true; return true;
@ -408,7 +408,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_frozen_analog_input_32wTime( BifEvent::generate_dnp3_frozen_analog_input_32wTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, frozen_value, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, frozen_value, bytestring_to_time(time48));
} }
return true; return true;
@ -422,7 +422,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_frozen_analog_input_16wTime( BifEvent::generate_dnp3_frozen_analog_input_16wTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, frozen_value, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, frozen_value, bytestring_to_time(time48));
} }
return true; return true;
@ -520,7 +520,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_analog_input_event_32wTime( BifEvent::generate_dnp3_analog_input_event_32wTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, value, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, value, bytestring_to_time(time48));
} }
return true; return true;
@ -534,7 +534,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_analog_input_event_16wTime( BifEvent::generate_dnp3_analog_input_event_16wTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, value, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, value, bytestring_to_time(time48));
} }
return true; return true;
@ -576,7 +576,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_analog_input_event_SPwTime( BifEvent::generate_dnp3_analog_input_event_SPwTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, value, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, value, bytestring_to_time(time48));
} }
return true; return true;
@ -590,7 +590,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_analog_input_event_DPwTime( BifEvent::generate_dnp3_analog_input_event_DPwTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, value_low, value_high, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, value_low, value_high, bytestring_to_time(time48));
} }
return true; return true;
@ -632,7 +632,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_frozen_analog_input_event_32wTime( BifEvent::generate_dnp3_frozen_analog_input_event_32wTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, frozen_value, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, frozen_value, bytestring_to_time(time48));
} }
return true; return true;
@ -646,7 +646,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_frozen_analog_input_event_16wTime( BifEvent::generate_dnp3_frozen_analog_input_event_16wTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, frozen_value, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, frozen_value, bytestring_to_time(time48));
} }
return true; return true;
@ -688,7 +688,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_frozen_analog_input_event_SPwTime( BifEvent::generate_dnp3_frozen_analog_input_event_SPwTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, frozen_value, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, frozen_value, bytestring_to_time(time48));
} }
return true; return true;
@ -702,7 +702,7 @@ flow DNP3_Flow(is_orig: bool) {
BifEvent::generate_dnp3_frozen_analog_input_event_DPwTime( BifEvent::generate_dnp3_frozen_analog_input_event_DPwTime(
connection()->bro_analyzer(), connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(), connection()->bro_analyzer()->Conn(),
is_orig(), flag, frozen_value_low, frozen_value_high, bytestring_to_time(time48, sizeof(time48))); is_orig(), flag, frozen_value_low, frozen_value_high, bytestring_to_time(time48));
} }
return true; return true;

View file

@ -416,7 +416,7 @@ void HTTP_Entity::SubmitHeader(mime::MIME_Header* h)
int64_t len = l - f + 1; int64_t len = l - f + 1;
if ( DEBUG_http ) if ( DEBUG_http )
DEBUG_MSG("Content-Range length = %"PRId64"\n", len); DEBUG_MSG("Content-Range length = %" PRId64"\n", len);
if ( len > 0 ) if ( len > 0 )
{ {
@ -466,6 +466,20 @@ void HTTP_Entity::SubmitAllHeaders()
if ( DEBUG_http ) if ( DEBUG_http )
DEBUG_MSG("%.6f end of headers\n", network_time); DEBUG_MSG("%.6f end of headers\n", network_time);
if ( Parent() &&
Parent()->MIMEContentType() == mime::CONTENT_TYPE_MULTIPART )
{
// Don't treat single \r or \n characters in the multipart body content
// as lines because the MIME_Entity code will implicitly add back a
// \r\n for each line it receives. We do this instead of setting
// plain delivery mode for the content line analyzer because
// the size of the content to deliver "plainly" may be unknown
// and just leaving it in that mode indefinitely screws up the
// detection of multipart boundaries.
http_message->content_line->SupressWeirds(true);
http_message->content_line->SetCRLFAsEOL(0);
}
// The presence of a message-body in a request is signaled by // The presence of a message-body in a request is signaled by
// the inclusion of a Content-Length or Transfer-Encoding // the inclusion of a Content-Length or Transfer-Encoding
// header field in the request's message-headers. // header field in the request's message-headers.
@ -655,6 +669,13 @@ void HTTP_Message::EndEntity(mime::MIME_Entity* entity)
current_entity = (HTTP_Entity*) entity->Parent(); current_entity = (HTTP_Entity*) entity->Parent();
if ( entity->Parent() &&
entity->Parent()->MIMEContentType() == mime::CONTENT_TYPE_MULTIPART )
{
content_line->SupressWeirds(false);
content_line->SetCRLFAsEOL();
}
// It is necessary to call Done when EndEntity is triggered by // It is necessary to call Done when EndEntity is triggered by
// SubmitAllHeaders (through EndOfData). // SubmitAllHeaders (through EndOfData).
if ( entity == top_level ) if ( entity == top_level )
@ -1039,7 +1060,7 @@ void HTTP_Analyzer::Undelivered(uint64 seq, int len, bool is_orig)
{ {
if ( msg ) if ( msg )
msg->SubmitEvent(mime::MIME_EVENT_CONTENT_GAP, msg->SubmitEvent(mime::MIME_EVENT_CONTENT_GAP,
fmt("seq=%"PRIu64", len=%d", seq, len)); fmt("seq=%" PRIu64", len=%d", seq, len));
} }
// Check if the content gap falls completely within a message body // Check if the content gap falls completely within a message body

View file

@ -99,6 +99,8 @@ enum {
// HTTP_MessageDone -> {Request,Reply}Made // HTTP_MessageDone -> {Request,Reply}Made
class HTTP_Message : public mime::MIME_Message { class HTTP_Message : public mime::MIME_Message {
friend class HTTP_Entity;
public: public:
HTTP_Message(HTTP_Analyzer* analyzer, tcp::ContentLine_Analyzer* cl, HTTP_Message(HTTP_Analyzer* analyzer, tcp::ContentLine_Analyzer* cl,
bool is_orig, int expect_body, int64_t init_header_length); bool is_orig, int expect_body, int64_t init_header_length);

View file

@ -553,6 +553,7 @@ void MIME_Entity::init()
data_buf_offset = -1; data_buf_offset = -1;
message = 0; message = 0;
delay_adding_implicit_CRLF = false;
} }
MIME_Entity::~MIME_Entity() MIME_Entity::~MIME_Entity()
@ -1003,12 +1004,33 @@ void MIME_Entity::DecodeDataLine(int len, const char* data, int trailing_CRLF)
void MIME_Entity::DecodeBinary(int len, const char* data, int trailing_CRLF) void MIME_Entity::DecodeBinary(int len, const char* data, int trailing_CRLF)
{ {
if ( delay_adding_implicit_CRLF )
{
delay_adding_implicit_CRLF = false;
DataOctet(CR);
DataOctet(LF);
}
DataOctets(len, data); DataOctets(len, data);
if ( trailing_CRLF ) if ( trailing_CRLF )
{ {
DataOctet(CR); if ( Parent() &&
DataOctet(LF); Parent()->MIMEContentType() == mime::CONTENT_TYPE_MULTIPART )
{
// For multipart body content, we want to keep all implicit CRLFs
// except for the last because that one belongs to the multipart
// boundary delimiter, not the content. Simply delaying the
// addition of implicit CRLFs until another chunk of content
// data comes in is a way to prevent the CRLF before the final
// message boundary from being accidentally added to the content.
delay_adding_implicit_CRLF = true;
}
else
{
DataOctet(CR);
DataOctet(LF);
}
} }
} }

View file

@ -173,6 +173,7 @@ protected:
int data_buf_offset; int data_buf_offset;
MIME_Message* message; MIME_Message* message;
bool delay_adding_implicit_CRLF;
}; };
// The reason I separate MIME_Message as an abstract class is to // The reason I separate MIME_Message as an abstract class is to

View file

@ -0,0 +1,10 @@
include(BroPlugin)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
bro_plugin_begin(Bro MySQL)
bro_plugin_cc(MySQL.cc Plugin.cc)
bro_plugin_bif(events.bif)
bro_plugin_pac(mysql.pac mysql-analyzer.pac mysql-protocol.pac)
bro_plugin_end()

View file

@ -0,0 +1,65 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "MySQL.h"
#include "analyzer/protocol/tcp/TCP_Reassembler.h"
#include "Reporter.h"
#include "events.bif.h"
using namespace analyzer::MySQL;
MySQL_Analyzer::MySQL_Analyzer(Connection* c)
: tcp::TCP_ApplicationAnalyzer("MySQL", c)
{
interp = new binpac::MySQL::MySQL_Conn(this);
had_gap = false;
}
MySQL_Analyzer::~MySQL_Analyzer()
{
delete interp;
}
void MySQL_Analyzer::Done()
{
tcp::TCP_ApplicationAnalyzer::Done();
interp->FlowEOF(true);
interp->FlowEOF(false);
}
void MySQL_Analyzer::EndpointEOF(bool is_orig)
{
tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
interp->FlowEOF(is_orig);
}
void MySQL_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
{
tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
assert(TCP());
if ( TCP()->IsPartial() )
return;
if ( had_gap )
// If only one side had a content gap, we could still try to
// deliver data to the other side if the script layer can
// handle this.
return;
try
{
interp->NewData(orig, data, data + len);
}
catch ( const binpac::Exception& e )
{
reporter->Weird(e.msg().c_str());
}
}
void MySQL_Analyzer::Undelivered(uint64 seq, int len, bool orig)
{
tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
had_gap = true;
interp->NewGap(orig, len);
}

View file

@ -0,0 +1,40 @@
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef ANALYZER_PROTOCOL_MYSQL_MYSQL_H
#define ANALYZER_PROTOCOL_MYSQL_MYSQL_H
#include "events.bif.h"
#include "analyzer/protocol/tcp/TCP.h"
#include "mysql_pac.h"
namespace analyzer { namespace MySQL {
class MySQL_Analyzer
: public tcp::TCP_ApplicationAnalyzer {
public:
MySQL_Analyzer(Connection* conn);
virtual ~MySQL_Analyzer();
// Overriden from Analyzer.
virtual void Done();
virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual void Undelivered(uint64 seq, int len, bool orig);
// Overriden from tcp::TCP_ApplicationAnalyzer.
virtual void EndpointEOF(bool is_orig);
static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new MySQL_Analyzer(conn); }
protected:
binpac::MySQL::MySQL_Conn* interp;
bool had_gap;
};
} } // namespace analyzer::*
#endif

View file

@ -0,0 +1,21 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "plugin/Plugin.h"
#include "MySQL.h"
namespace plugin {
namespace Bro_MySQL {
class Plugin : public plugin::Plugin {
public:
plugin::Configuration Configure()
{
AddComponent(new ::analyzer::Component("MySQL", ::analyzer::MySQL::MySQL_Analyzer::Instantiate));
plugin::Configuration config;
config.name = "Bro::MySQL";
config.description = "MySQL analyzer";
return config;
}
} plugin;
}
}

View file

@ -0,0 +1,65 @@
## Generated for a command request from a MySQL client.
##
## See the MySQL `documentation <http://dev.mysql.com/doc/internals/en/client-server-protocol.html>`__
## for more information about the MySQL protocol.
##
## c: The connection.
##
## command: The numerical code of the command issued.
##
## arg: The argument for the command (empty string if not provided).
##
## .. bro:see:: mysql_error mysql_ok mysql_server_version mysql_handshake_response
event mysql_command_request%(c: connection, command: count, arg: string%);
## Generated for an unsuccessful MySQL response.
##
## See the MySQL `documentation <http://dev.mysql.com/doc/internals/en/client-server-protocol.html>`__
## for more information about the MySQL protocol.
##
## c: The connection.
##
## code: The error code.
##
## msg: Any extra details about the error (empty string if not provided).
##
## .. bro:see:: mysql_command_request mysql_ok mysql_server_version mysql_handshake_response
event mysql_error%(c: connection, code: count, msg: string%);
## Generated for a successful MySQL response.
##
## See the MySQL `documentation <http://dev.mysql.com/doc/internals/en/client-server-protocol.html>`__
## for more information about the MySQL protocol.
##
## c: The connection.
##
## affected_rows: The number of rows that were affected.
##
## .. bro:see:: mysql_command_request mysql_error mysql_server_version mysql_handshake_response
event mysql_ok%(c: connection, affected_rows: count%);
## Generated for the initial server handshake packet, which includes the MySQL server version.
##
## See the MySQL `documentation <http://dev.mysql.com/doc/internals/en/client-server-protocol.html>`__
## for more information about the MySQL protocol.
##
## c: The connection.
##
## ver: The server version string.
##
## .. bro:see:: mysql_command_request mysql_error mysql_ok mysql_handshake_response
event mysql_server_version%(c: connection, ver: string%);
## Generated for a client handshake response packet, which includes the username the client is attempting
## to connect as.
##
## See the MySQL `documentation <http://dev.mysql.com/doc/internals/en/client-server-protocol.html>`__
## for more information about the MySQL protocol.
##
## c: The connection.
##
## username: The username supplied by the client
##
## .. bro:see:: mysql_command_request mysql_error mysql_ok mysql_server_version
event mysql_handshake%(c: connection, username: string%);

View file

@ -0,0 +1,98 @@
# See the file "COPYING" in the main distribution directory for copyright.
refine flow MySQL_Flow += {
function proc_mysql_initial_handshake_packet(msg: Initial_Handshake_Packet): bool
%{
if ( mysql_server_version )
{
if ( ${msg.version} == 10 )
BifEvent::generate_mysql_server_version(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
bytestring_to_val(${msg.handshake10.server_version}));
if ( ${msg.version} == 9 )
BifEvent::generate_mysql_server_version(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
bytestring_to_val(${msg.handshake9.server_version}));
}
return true;
%}
function proc_mysql_handshake_response_packet(msg: Handshake_Response_Packet): bool
%{
if ( mysql_handshake )
{
if ( ${msg.version} == 10 )
BifEvent::generate_mysql_handshake(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
bytestring_to_val(${msg.v10_response.username}));
if ( ${msg.version} == 9 )
BifEvent::generate_mysql_handshake(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
bytestring_to_val(${msg.v9_response.username}));
}
return true;
%}
function proc_mysql_command_request_packet(msg: Command_Request_Packet): bool
%{
if ( mysql_command_request )
BifEvent::generate_mysql_command_request(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
${msg.command},
bytestring_to_val(${msg.arg}));
return true;
%}
function proc_err_packet(msg: ERR_Packet): bool
%{
if ( mysql_error )
BifEvent::generate_mysql_error(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
${msg.code},
bytestring_to_val(${msg.msg}));
return true;
%}
function proc_ok_packet(msg: OK_Packet): bool
%{
if ( mysql_ok )
BifEvent::generate_mysql_ok(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
${msg.rows});
return true;
%}
function proc_resultset(msg: Resultset): bool
%{
if ( mysql_ok )
BifEvent::generate_mysql_ok(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
${msg.rows}->size());
return true;
%}
};
refine typeattr Initial_Handshake_Packet += &let {
proc = $context.flow.proc_mysql_initial_handshake_packet(this);
};
refine typeattr Handshake_Response_Packet += &let {
proc = $context.flow.proc_mysql_handshake_response_packet(this);
};
refine typeattr Command_Request_Packet += &let {
proc = $context.flow.proc_mysql_command_request_packet(this);
};
refine typeattr ERR_Packet += &let {
proc = $context.flow.proc_err_packet(this);
};
refine typeattr OK_Packet += &let {
proc = $context.flow.proc_ok_packet(this);
};
refine typeattr Resultset += &let {
proc = $context.flow.proc_resultset(this);
};

View file

@ -0,0 +1,407 @@
# See the file "COPYING" in the main distribution directory for copyright.
#
# All information is from the MySQL internals documentation at:
# <http://dev.mysql.com/doc/internals/en/client-server-protocol.html>
#
# Basic Types
type uint24le = record {
byte3 : uint8;
byte2 : uint8;
byte1 : uint8;
};
type LengthEncodedInteger = record {
length : uint8;
integer : LengthEncodedIntegerLookahead(length);
};
type LengthEncodedIntegerLookahead(length: uint8) = record {
val: case length of {
0xfb -> i0 : empty;
0xfc -> i2 : uint16;
0xfd -> i3 : uint24le;
0xfe -> i4 : uint64;
0xff -> err_packet: empty;
default -> one : empty;
};
};
type LengthEncodedString = record {
len: LengthEncodedInteger;
val: bytestring &length=to_int()(len);
};
%header{
class to_int
{
public:
int operator()(uint24le* num) const
{
return (num->byte1() << 16) | (num->byte2() << 8) | num->byte3();
}
int operator()(LengthEncodedInteger* lei) const
{
if ( lei->length() < 0xfb )
return lei->length();
else if ( lei->length() == 0xfc )
return lei->integer()->i2();
else if ( lei->length() == 0xfd )
return to_int()(lei->integer()->i3());
else if ( lei->length() == 0xfe )
return lei->integer()->i4();
else
return 0;
}
int operator()(LengthEncodedIntegerLookahead* lei) const
{
if ( lei->length() < 0xfb )
return lei->length();
else if ( lei->length() == 0xfc )
return lei->i2();
else if ( lei->length() == 0xfd )
return to_int()(lei->i3());
else if ( lei->length() == 0xfe )
return lei->i4();
else
return 0;
}
};
%}
extern type to_int;
# Enums
enum command_consts {
COM_SLEEP = 0x00,
COM_QUIT = 0x01,
COM_INIT_DB = 0x02,
COM_QUERY = 0x03,
COM_FIELD_LIST = 0x04,
COM_CREATE_DB = 0x05,
COM_DROP_DB = 0x06,
COM_REFRESH = 0x07,
COM_SHUTDOWN = 0x08,
COM_STATISTICS = 0x09,
COM_PROCESS_INFO = 0x0a,
COM_CONNECT = 0x0b,
COM_PROCESS_KILL = 0x0c,
COM_DEBUG = 0x0d,
COM_PING = 0x0e,
COM_TIME = 0x0f,
COM_DELAYED_INSERT = 0x10,
COM_CHANGE_USER = 0x11,
COM_BINLOG_DUMP = 0x12,
COM_TABLE_DUMP = 0x13,
COM_CONNECT_OUT = 0x14,
COM_REGISTER_SLAVE = 0x15,
COM_STMT_PREPARE = 0x16,
COM_STMT_EXECUTE = 0x17,
COM_STMT_SEND_LONG_DATA = 0x18,
COM_STMT_CLOSE = 0x19,
COM_STMT_RESET = 0x1a,
COM_SET_OPTION = 0x1b,
COM_STMT_FETCH = 0x1c,
COM_DAEMON = 0x1d,
COM_BINLOG_DUMP_GTID = 0x1e
};
enum state {
CONNECTION_PHASE = 0,
COMMAND_PHASE = 1,
};
enum Expected {
NO_EXPECTATION,
EXPECT_STATUS,
EXPECT_COLUMN_DEFINITION,
EXPECT_COLUMN_COUNT,
EXPECT_EOF1,
EXPECT_EOF2,
EXPECT_RESULTSET,
EXPECT_QUERY_RESPONSE,
};
type NUL_String = RE/[^\0]*/;
# MySQL PDU
type MySQL_PDU(is_orig: bool) = record {
hdr : Header;
msg : case is_orig of {
false -> server_msg: Server_Message(hdr.seq_id);
true -> client_msg: Client_Message(state);
} &requires(state);
} &let {
state : int = $context.connection.get_state();
} &length=hdr.len &byteorder=bigendian;
type Header = record {
le_len: uint24le;
seq_id: uint8;
} &let {
len : uint32 = to_int()(le_len) + 4;
} &length=4;
type Server_Message(seq_id: uint8) = case seq_id of {
0 -> initial_handshake: Initial_Handshake_Packet;
default -> command_response : Command_Response;
};
type Client_Message(state: int) = case state of {
CONNECTION_PHASE -> connection_phase: Handshake_Response_Packet;
COMMAND_PHASE -> command_phase : Command_Request_Packet;
};
# Handshake Request
type Initial_Handshake_Packet = record {
version : uint8;
pkt : case version of {
10 -> handshake10 : Handshake_v10;
9 -> handshake9 : Handshake_v9;
default -> error : ERR_Packet;
};
} &let {
set_version : bool = $context.connection.set_version(version);
};
type Handshake_v10 = record {
server_version : NUL_String;
connection_id : uint32;
auth_plugin_data_part_1 : bytestring &length=8;
filler_1 : uint8;
capability_flag_1 : uint16;
character_set : uint8;
status_flags : uint16;
capability_flags_2 : uint16;
auth_plugin_data_len : uint8;
auth_plugin_name : NUL_String;
};
type Handshake_v9 = record {
server_version : NUL_String;
connection_id : uint32;
scramble : NUL_String;
};
# Handshake Response
type Handshake_Response_Packet = case $context.connection.get_version() of {
10 -> v10_response : Handshake_Response_Packet_v10;
9 -> v9_response : Handshake_Response_Packet_v9;
} &let {
version : uint8 = $context.connection.get_version();
} &byteorder=bigendian;
type Handshake_Response_Packet_v10 = record {
cap_flags : uint32;
max_pkt_size : uint32;
char_set : uint8;
pad : padding[23];
username : NUL_String;
password : bytestring &restofdata;
};
type Handshake_Response_Packet_v9 = record {
cap_flags : uint16;
max_pkt_size : uint24le;
username : NUL_String;
auth_response : NUL_String;
have_db : case ( cap_flags & 0x8 ) of {
0x8 -> database : NUL_String;
0x0 -> none : empty;
};
password : bytestring &restofdata;
};
# Command Request
type Command_Request_Packet = record {
command : uint8;
arg : bytestring &restofdata;
} &let {
update_expectation : bool = $context.connection.set_next_expected(EXPECT_COLUMN_COUNT);
};
# Command Response
type Command_Response = case $context.connection.get_expectation() of {
EXPECT_COLUMN_COUNT -> col_count_meta : ColumnCountMeta;
EXPECT_COLUMN_DEFINITION -> col_defs : ColumnDefinitions;
EXPECT_RESULTSET -> resultset : Resultset;
EXPECT_STATUS -> status : Command_Response_Status;
EXPECT_EOF1 -> eof1 : EOF1;
EXPECT_EOF2 -> eof2 : EOF2;
default -> unknow : empty;
};
type Command_Response_Status = record {
pkt_type: uint8;
response: case pkt_type of {
0x00 -> data_ok: OK_Packet;
0xfe -> data_eof: EOF_Packet;
0xff -> data_err: ERR_Packet;
default -> unknown: empty;
};
};
type ColumnCountMeta = record {
byte : uint8;
pkt_type: case byte of {
0x00 -> ok : OK_Packet;
0xff -> err : ERR_Packet;
# 0xfb -> Not implemented
default -> col_count: ColumnCount(byte);
};
};
type ColumnCount(byte: uint8) = record {
le_column_count : LengthEncodedIntegerLookahead(byte);
} &let {
col_num : uint32 = to_int()(le_column_count);
update_col_num : bool = $context.connection.set_col_count(col_num);
update_expectation : bool = $context.connection.set_next_expected(EXPECT_COLUMN_DEFINITION);
};
type ColumnDefinitions = record {
defs : ColumnDefinition41[1];
} &let {
update_expectation : bool = $context.connection.set_next_expected(EXPECT_EOF1);
};
type EOF1 = record {
eof : EOF_Packet;
} &let {
update_expectation : bool = $context.connection.set_next_expected(EXPECT_RESULTSET);
};
type EOF2 = record {
eof : EOF_Packet;
} &let {
update_expectation : bool = $context.connection.set_next_expected(NO_EXPECTATION);
};
type Resultset = record {
rows : ResultsetRow[] &until($input.length()==0);
} &let {
update_expectation : bool = $context.connection.set_next_expected(EXPECT_EOF2);
};
type ResultsetRow = record {
fields: LengthEncodedString[$context.connection.get_col_count()];
};
type ColumnDefinition41 = record {
catalog : LengthEncodedString;
schema : LengthEncodedString;
table : LengthEncodedString;
org_table: LengthEncodedString;
name : LengthEncodedString;
org_name : LengthEncodedString;
next_len : LengthEncodedInteger;
char_set : uint16;
col_len : uint32;
type : uint8;
flags : uint16;
decimals : uint8;
filler : padding[2];
};
type ColumnDefinition320 = record {
table : LengthEncodedString;
name : LengthEncodedString;
length_of_col_len: LengthEncodedInteger;
col_len : uint24le;
type_len : LengthEncodedInteger;
type : uint8;
};
type OK_Packet = record {
le_rows : LengthEncodedInteger;
todo : bytestring &restofdata;
} &let {
rows : uint32 = to_int()(le_rows);
update_state: bool = $context.connection.update_state(COMMAND_PHASE);
};
type ERR_Packet = record {
code : uint16;
state: bytestring &length=6;
msg : bytestring &restofdata;
} &let {
update_state: bool = $context.connection.update_state(COMMAND_PHASE);
};
type EOF_Packet = record {
warnings: uint16;
status : uint16;
} &let {
update_state: bool = $context.connection.update_state(COMMAND_PHASE);
};
# State tracking
refine connection MySQL_Conn += {
%member{
uint8 version_;
int state_;
Expected expected_;
uint32 col_count_;
%}
%init{
version_ = 0;
state_ = CONNECTION_PHASE;
expected_ = EXPECT_STATUS;
col_count_ = 0;
%}
function get_version(): uint8
%{
return version_;
%}
function set_version(v: uint8): bool
%{
version_ = v;
return true;
%}
function get_state(): int
%{
return state_;
%}
function update_state(s: state): bool
%{
state_ = s;
return true;
%}
function get_expectation(): Expected
%{
return expected_;
%}
function set_next_expected(e: Expected): bool
%{
expected_ = e;
return true;
%}
function get_col_count(): uint32
%{
return col_count_;
%}
function set_col_count(i: uint32): bool
%{
col_count_ = i;
return true;
%}
};

View file

@ -0,0 +1,37 @@
# See the file "COPYING" in the main distribution directory for copyright.
#
# Analyzer for MySQL
# - mysql-protocol.pac: describes the MySQL protocol messages
# - mysql-analyzer.pac: describes the MySQL analyzer code
%include binpac.pac
%include bro.pac
%extern{
#include "events.bif.h"
%}
analyzer MySQL withcontext {
connection: MySQL_Conn;
flow: MySQL_Flow;
};
# Our connection consists of two flows, one in each direction.
connection MySQL_Conn(bro_analyzer: BroAnalyzer) {
upflow = MySQL_Flow(true);
downflow = MySQL_Flow(false);
};
%include mysql-protocol.pac
# Now we define the flow:
flow MySQL_Flow(is_orig: bool) {
# There are two options here: flowunit or datagram.
# flowunit = MySQL_PDU(is_orig) withcontext(connection, this);
flowunit = MySQL_PDU(is_orig) withcontext(connection, this);
# Using flowunit will cause the anlayzer to buffer incremental input.
# This is needed for &oneline and &length. If you don't need this, you'll
# get better performance with datagram.
};
%include mysql-analyzer.pac

View file

@ -21,7 +21,9 @@ static const char* smtp_cmd_word[] = {
#include "SMTP_cmd.def" #include "SMTP_cmd.def"
}; };
#define SMTP_CMD_WORD(code) ((code >= 0) ? smtp_cmd_word[code] : "(UNKNOWN)") static const char* unknown_cmd = "(UNKNOWN)";
#define SMTP_CMD_WORD(code) ((code >= 0) ? smtp_cmd_word[code] : unknown_cmd)
SMTP_Analyzer::SMTP_Analyzer(Connection* conn) SMTP_Analyzer::SMTP_Analyzer(Connection* conn)
@ -83,7 +85,7 @@ void SMTP_Analyzer::Undelivered(uint64 seq, int len, bool is_orig)
if ( len <= 0 ) if ( len <= 0 )
return; return;
const char* buf = fmt("seq = %"PRIu64", len = %d", seq, len); const char* buf = fmt("seq = %" PRIu64", len = %d", seq, len);
int buf_len = strlen(buf); int buf_len = strlen(buf);
Unexpected(is_orig, "content gap", buf_len, buf); Unexpected(is_orig, "content gap", buf_len, buf);
@ -422,7 +424,6 @@ void SMTP_Analyzer::NewReply(const int reply_code)
if ( state == SMTP_AFTER_GAP && reply_code > 0 ) if ( state == SMTP_AFTER_GAP && reply_code > 0 )
{ {
state = SMTP_GAP_RECOVERY; state = SMTP_GAP_RECOVERY;
const char* unknown_cmd = SMTP_CMD_WORD(-1);
RequestEvent(strlen(unknown_cmd), unknown_cmd, 0, ""); RequestEvent(strlen(unknown_cmd), unknown_cmd, 0, "");
/* /*
if ( line_after_gap ) if ( line_after_gap )

View file

@ -84,7 +84,7 @@ StringVal* asn1_oid_to_val(const ASN1Encoding* oid)
if ( i > 0 ) if ( i > 0 )
{ {
rval += "."; rval += ".";
snprintf(tmp, sizeof(tmp), "%"PRIu64, subidentifier_values[i]); snprintf(tmp, sizeof(tmp), "%" PRIu64, subidentifier_values[i]);
rval += tmp; rval += tmp;
} }
else else

View file

@ -24,12 +24,6 @@ public:
static analyzer::Analyzer* Instantiate(Connection* conn) static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new SSL_Analyzer(conn); } { return new SSL_Analyzer(conn); }
static bool Available()
{
return ( ssl_client_hello || ssl_server_hello ||
ssl_established || ssl_extension || ssl_alert );
}
protected: protected:
binpac::SSL::SSL_Conn* interp; binpac::SSL::SSL_Conn* interp;
bool had_gap; bool had_gap;

View file

@ -32,6 +32,7 @@ void ContentLine_Analyzer::InitState()
seq_to_skip = 0; seq_to_skip = 0;
plain_delivery_length = 0; plain_delivery_length = 0;
is_plain = 0; is_plain = 0;
suppress_weirds = false;
InitBuffer(0); InitBuffer(0);
} }
@ -258,7 +259,7 @@ int ContentLine_Analyzer::DoDeliverOnce(int len, const u_char* data)
else else
{ {
if ( Conn()->FlagEvent(SINGULAR_LF) ) if ( ! suppress_weirds && Conn()->FlagEvent(SINGULAR_LF) )
Conn()->Weird("line_terminated_with_single_LF"); Conn()->Weird("line_terminated_with_single_LF");
buf[offset++] = c; buf[offset++] = c;
} }
@ -277,7 +278,7 @@ int ContentLine_Analyzer::DoDeliverOnce(int len, const u_char* data)
} }
if ( last_char == '\r' ) if ( last_char == '\r' )
if ( Conn()->FlagEvent(SINGULAR_CR) ) if ( ! suppress_weirds && Conn()->FlagEvent(SINGULAR_CR) )
Conn()->Weird("line_terminated_with_single_CR"); Conn()->Weird("line_terminated_with_single_CR");
last_char = c; last_char = c;
@ -307,7 +308,7 @@ void ContentLine_Analyzer::CheckNUL()
; // Ignore it. ; // Ignore it.
else else
{ {
if ( Conn()->FlagEvent(NUL_IN_LINE) ) if ( ! suppress_weirds && Conn()->FlagEvent(NUL_IN_LINE) )
Conn()->Weird("NUL_in_line"); Conn()->Weird("NUL_in_line");
flag_NULs = 0; flag_NULs = 0;
} }

View file

@ -15,6 +15,9 @@ public:
ContentLine_Analyzer(Connection* conn, bool orig); ContentLine_Analyzer(Connection* conn, bool orig);
~ContentLine_Analyzer(); ~ContentLine_Analyzer();
void SupressWeirds(bool enable)
{ suppress_weirds = enable; }
// If enabled, flag (first) line with embedded NUL. Default off. // If enabled, flag (first) line with embedded NUL. Default off.
void SetIsNULSensitive(bool enable) void SetIsNULSensitive(bool enable)
{ flag_NULs = enable; } { flag_NULs = enable; }
@ -96,6 +99,8 @@ protected:
// Don't deliver further data. // Don't deliver further data.
int skip_deliveries; int skip_deliveries;
bool suppress_weirds;
// If true, flag (first) line with embedded NUL. // If true, flag (first) line with embedded NUL.
unsigned int flag_NULs:1; unsigned int flag_NULs:1;

View file

@ -1901,7 +1901,7 @@ void TCP_ApplicationAnalyzer::DeliverPacket(int len, const u_char* data,
const IP_Hdr* ip, int caplen) const IP_Hdr* ip, int caplen)
{ {
Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen);
DBG_LOG(DBG_ANALYZER, "TCP_ApplicationAnalyzer ignoring DeliverPacket(%d, %s, %"PRIu64", %p, %d) [%s%s]", DBG_LOG(DBG_ANALYZER, "TCP_ApplicationAnalyzer ignoring DeliverPacket(%d, %s, %" PRIu64", %p, %d) [%s%s]",
len, is_orig ? "T" : "F", seq, ip, caplen, len, is_orig ? "T" : "F", seq, ip, caplen,
fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : ""); fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : "");
} }
@ -2053,7 +2053,7 @@ int TCPStats_Endpoint::DataSent(double /* t */, uint64 seq, int len, int caplen,
num_rxmit_bytes += len; num_rxmit_bytes += len;
} }
DEBUG_MSG("%.6f rexmit %"PRIu64" + %d <= %"PRIu64" data_in_flight = %d\n", DEBUG_MSG("%.6f rexmit %" PRIu64" + %d <= %" PRIu64" data_in_flight = %d\n",
network_time, seq, len, max_top_seq, data_in_flight); network_time, seq, len, max_top_seq, data_in_flight);
if ( tcp_rexmit ) if ( tcp_rexmit )

View file

@ -188,7 +188,7 @@ void TCP_Reassembler::Undelivered(uint64 up_to_seq)
if ( DEBUG_tcp_contents ) if ( DEBUG_tcp_contents )
{ {
DEBUG_MSG("%.6f Undelivered: IsOrig()=%d up_to_seq=%"PRIu64", last_reassm=%"PRIu64", " DEBUG_MSG("%.6f Undelivered: IsOrig()=%d up_to_seq=%" PRIu64", last_reassm=%" PRIu64", "
"endp: FIN_cnt=%d, RST_cnt=%d, " "endp: FIN_cnt=%d, RST_cnt=%d, "
"peer: FIN_cnt=%d, RST_cnt=%d\n", "peer: FIN_cnt=%d, RST_cnt=%d\n",
network_time, IsOrig(), up_to_seq, last_reassem_seq, network_time, IsOrig(), up_to_seq, last_reassem_seq,
@ -219,7 +219,7 @@ void TCP_Reassembler::Undelivered(uint64 up_to_seq)
{ {
if ( DEBUG_tcp_contents ) if ( DEBUG_tcp_contents )
{ {
DEBUG_MSG("%.6f Undelivered: IsOrig()=%d, seq=%"PRIu64", len=%"PRIu64", " DEBUG_MSG("%.6f Undelivered: IsOrig()=%d, seq=%" PRIu64", len=%" PRIu64", "
"skip_deliveries=%d\n", "skip_deliveries=%d\n",
network_time, IsOrig(), last_reassem_seq, network_time, IsOrig(), last_reassem_seq,
up_to_seq - last_reassem_seq, up_to_seq - last_reassem_seq,
@ -350,7 +350,7 @@ void TCP_Reassembler::RecordBlock(DataBlock* b, BroFile* f)
void TCP_Reassembler::RecordGap(uint64 start_seq, uint64 upper_seq, BroFile* f) void TCP_Reassembler::RecordGap(uint64 start_seq, uint64 upper_seq, BroFile* f)
{ {
if ( f->Write(fmt("\n<<gap %"PRIu64">>\n", upper_seq - start_seq)) ) if ( f->Write(fmt("\n<<gap %" PRIu64">>\n", upper_seq - start_seq)) )
return; return;
reporter->Error("TCP_Reassembler contents gap write failed"); reporter->Error("TCP_Reassembler contents gap write failed");
@ -420,7 +420,7 @@ void TCP_Reassembler::BlockInserted(DataBlock* start_block)
void TCP_Reassembler::Overlap(const u_char* b1, const u_char* b2, uint64 n) void TCP_Reassembler::Overlap(const u_char* b1, const u_char* b2, uint64 n)
{ {
if ( DEBUG_tcp_contents ) if ( DEBUG_tcp_contents )
DEBUG_MSG("%.6f TCP contents overlap: %"PRIu64" IsOrig()=%d\n", network_time, n, IsOrig()); DEBUG_MSG("%.6f TCP contents overlap: %" PRIu64" IsOrig()=%d\n", network_time, n, IsOrig());
if ( rexmit_inconsistency && if ( rexmit_inconsistency &&
memcmp((const void*) b1, (const void*) b2, n) && memcmp((const void*) b1, (const void*) b2, n) &&
@ -465,7 +465,7 @@ int TCP_Reassembler::DataSent(double t, uint64 seq, int len,
if ( DEBUG_tcp_contents ) if ( DEBUG_tcp_contents )
{ {
DEBUG_MSG("%.6f DataSent: IsOrig()=%d seq=%"PRIu64" upper=%"PRIu64" ack=%"PRIu64"\n", DEBUG_MSG("%.6f DataSent: IsOrig()=%d seq=%" PRIu64" upper=%" PRIu64" ack=%" PRIu64"\n",
network_time, IsOrig(), seq, upper_seq, ack); network_time, IsOrig(), seq, upper_seq, ack);
} }

View file

@ -2,8 +2,8 @@
##! such as general programming algorithms, string processing, math functions, ##! such as general programming algorithms, string processing, math functions,
##! introspection, type conversion, file/directory manipulation, packet ##! introspection, type conversion, file/directory manipulation, packet
##! filtering, interprocess communication and controlling protocol analyzer ##! filtering, interprocess communication and controlling protocol analyzer
##! behavior. ##! behavior.
##! ##!
##! You'll find most of Bro's built-in functions that aren't protocol-specific ##! You'll find most of Bro's built-in functions that aren't protocol-specific
##! in this file. ##! in this file.
@ -2159,6 +2159,23 @@ function counts_to_addr%(v: index_vec%): addr
} }
%} %}
## Converts an :bro:type:`enum` to an :bro:type:`int`.
##
## e: The :bro:type:`enum` to convert.
##
## Returns: The :bro:type:`enum` as the :bro:type:`int` value that it
## to corresponds.
function enum_to_int%(e: any%): int
%{
if ( e->Type()->Tag() != TYPE_ENUM )
{
builtin_error("enum_to_int() requires enum value");
return new Val(-1, TYPE_INT);
}
return new Val(e->AsEnum(), TYPE_INT);
%}
## Converts a :bro:type:`string` to an :bro:type:`int`. ## Converts a :bro:type:`string` to an :bro:type:`int`.
## ##
## str: The :bro:type:`string` to convert. ## str: The :bro:type:`string` to convert.

View file

@ -357,7 +357,7 @@ cq_remove(register struct cq_handle *hp, register double pri,
/* The priority must be positive and the cookie non-null */ /* The priority must be positive and the cookie non-null */
if (pri <= 0.0 || cookie == NULL) if (pri <= 0.0 || cookie == NULL)
return (-0); return (0);
bp = hp->buckets + PRI2BUCKET(hp, pri); bp = hp->buckets + PRI2BUCKET(hp, pri);
if (! BUCKETINUSE(bp)) if (! BUCKETINUSE(bp))
@ -370,7 +370,7 @@ cq_remove(register struct cq_handle *hp, register double pri,
} }
if ( ! bp ) if ( ! bp )
return (-0); return (0);
/* Unlink entry */ /* Unlink entry */
if ( ! bp2 ) { if ( ! bp2 ) {

View file

@ -506,6 +506,7 @@ bool PktSrc::ApplyBPFFilter(int index, const struct pcap_pkthdr *hdr, const u_ch
{ {
Error(fmt("BPF filter %d not compiled", index)); Error(fmt("BPF filter %d not compiled", index));
Close(); Close();
return false;
} }
if ( code->MatchesAnything() ) if ( code->MatchesAnything() )

View file

@ -266,7 +266,11 @@ protected:
Properties() Properties()
{ {
selectable_fd = -1;
link_type = -1;
hdr_size = -1;
netmask = PCAP_NETMASK_UNKNOWN; netmask = PCAP_NETMASK_UNKNOWN;
is_live = false;
} }
}; };

View file

@ -21,6 +21,9 @@ PcapSource::PcapSource(const std::string& path, bool is_live)
{ {
props.path = path; props.path = path;
props.is_live = is_live; props.is_live = is_live;
pd = 0;
memset(&current_hdr, 0, sizeof(current_hdr));
memset(&last_hdr, 0, sizeof(last_hdr));
last_data = 0; last_data = 0;
} }

View file

@ -775,6 +775,9 @@ int main(int argc, char** argv)
// DEBUG_MSG("HMAC key: %s\n", md5_digest_print(shared_hmac_md5_key)); // DEBUG_MSG("HMAC key: %s\n", md5_digest_print(shared_hmac_md5_key));
init_hash_function(); init_hash_function();
// Must come after hash initialization.
binpac::init();
ERR_load_crypto_strings(); ERR_load_crypto_strings();
OPENSSL_add_all_algorithms_conf(); OPENSSL_add_all_algorithms_conf();
SSL_library_init(); SSL_library_init();

View file

@ -127,7 +127,11 @@ static void parser_new_enum (void)
{ {
/* Starting a new enum definition. */ /* Starting a new enum definition. */
assert(cur_enum_type == NULL); assert(cur_enum_type == NULL);
cur_enum_type = new EnumType(cur_decl_type_id->Name());
if ( cur_decl_type_id )
cur_enum_type = new EnumType(cur_decl_type_id->Name());
else
reporter->FatalError("incorrect syntax for enum type declaration");
} }
static void parser_redef_enum (ID *id) static void parser_redef_enum (ID *id)

View file

@ -172,7 +172,7 @@ bool Manager::ActivateDynamicPluginInternal(const std::string& name, bool ok_if_
// Load {bif,scripts}/__load__.bro automatically. // Load {bif,scripts}/__load__.bro automatically.
string init = dir + "lib/bif/__load__.bro"; string init = dir + "scripts/__load__.bro";
if ( is_file(init) ) if ( is_file(init) )
{ {
@ -180,7 +180,7 @@ bool Manager::ActivateDynamicPluginInternal(const std::string& name, bool ok_if_
scripts_to_load.push_back(init); scripts_to_load.push_back(init);
} }
init = dir + "scripts/__load__.bro"; init = dir + "lib/bif/__load__.bro";
if ( is_file(init) ) if ( is_file(init) )
{ {
@ -559,7 +559,7 @@ int Manager::HookLoadFile(const string& file)
return rc; return rc;
} }
ValWrapper* Manager::HookCallFunction(const Func* func, Frame* parent, val_list* vargs) const std::pair<Val*, bool> Manager::HookCallFunction(const Func* func, Frame* parent, val_list* vargs) const
{ {
HookArgumentList args; HookArgumentList args;
@ -573,7 +573,7 @@ ValWrapper* Manager::HookCallFunction(const Func* func, Frame* parent, val_list*
hook_list* l = hooks[HOOK_CALL_FUNCTION]; hook_list* l = hooks[HOOK_CALL_FUNCTION];
ValWrapper* v = 0; std::pair<Val*, bool> v;
if ( l ) if ( l )
for ( hook_list::iterator i = l->begin(); i != l->end(); ++i ) for ( hook_list::iterator i = l->begin(); i != l->end(); ++i )
@ -582,9 +582,11 @@ ValWrapper* Manager::HookCallFunction(const Func* func, Frame* parent, val_list*
v = p->HookCallFunction(func, parent, vargs); v = p->HookCallFunction(func, parent, vargs);
if ( v && v-> processed) if ( v.second )
{
break; break;
} }
}
if ( HavePluginForHook(META_HOOK_POST) ) if ( HavePluginForHook(META_HOOK_POST) )
MetaHookPost(HOOK_CALL_FUNCTION, args, HookArgument(v)); MetaHookPost(HOOK_CALL_FUNCTION, args, HookArgument(v));

View file

@ -3,6 +3,7 @@
#ifndef PLUGIN_MANAGER_H #ifndef PLUGIN_MANAGER_H
#define PLUGIN_MANAGER_H #define PLUGIN_MANAGER_H
#include <utility>
#include <map> #include <map>
#include "Plugin.h" #include "Plugin.h"
@ -244,7 +245,7 @@ public:
* functions and events, it may be any Val and must be ignored). If no * functions and events, it may be any Val and must be ignored). If no
* plugin handled the call, the method returns null. * plugin handled the call, the method returns null.
*/ */
ValWrapper* HookCallFunction(const Func* func, Frame *parent, val_list* args) const; std::pair<Val*, bool> HookCallFunction(const Func* func, Frame *parent, val_list* args) const;
/** /**
* Hook that filters the queuing of an event. * Hook that filters the queuing of an event.

View file

@ -133,21 +133,14 @@ void HookArgument::Describe(ODesc* d) const
break; break;
case WRAPPED_VAL: case WRAPPED_VAL:
if ( arg.wrapper ) d->Add("wrapped(");
if(wrapper.first)
{ {
d->Add("wrapped("); wrapper.first->Describe(d);
if(arg.wrapper->value)
{
arg.wrapper->value->Describe(d);
}
else
d->Add("<null>");
d->Add(")");
} }
else else
{
d->Add("<null>"); d->Add("<null>");
} d->Add(")");
break; break;
@ -298,9 +291,10 @@ int Plugin::HookLoadFile(const std::string& file, const std::string& ext)
return -1; return -1;
} }
ValWrapper* Plugin::HookCallFunction(const Func* func, Frame *parent, val_list* args) std::pair<Val*, bool> Plugin::HookCallFunction(const Func* func, Frame *parent, val_list* args)
{ {
return 0; std::pair<Val*, bool> result(NULL, false);
return result;
} }
bool Plugin::HookQueueEvent(Event* event) bool Plugin::HookQueueEvent(Event* event)

View file

@ -5,6 +5,7 @@
#include <list> #include <list>
#include <string> #include <string>
#include <utility>
#include "config.h" #include "config.h"
#include "analyzer/Component.h" #include "analyzer/Component.h"
@ -26,34 +27,6 @@ class Manager;
class Component; class Component;
class Plugin; class Plugin;
/**
* In certain cases, functions may have well-defined return types but still return NULL values (e.g. delayed functions, opaque types).
* Thus, it's necessary to explicitly define whether or not a plugin has handled a function in addition to recording the value it has
* returned.
*
* Plugins' function handlers return a result of this type.
*/
struct ValWrapper {
Val* value; //< value being wrapped by this object
bool processed; //< true if execution should *STOP* (read: the plugin is replacing a method), and false if execution should *CONTINUE* (read: bro should execute a method)
/**
Wrapper for a specific value. If we're setting a value, we assume we've processed something.
@param value value to be wrapped
*/
ValWrapper(Val* value)
: value(value), processed(true) { }
/**
Wrapper for a specific value. If we're setting 'processed', we assume there's a reason we're not setting a Val and set that to NULL.
@param processed whether or not an execution of a function was handled by the plugin
*/
ValWrapper(bool processed)
: value(NULL), processed(processed) { }
};
/** /**
* Hook types that a plugin may define. Each label maps to the corresponding * Hook types that a plugin may define. Each label maps to the corresponding
* virtual method in \a Plugin. * virtual method in \a Plugin.
@ -238,9 +211,9 @@ public:
HookArgument(void* p) { type = VOIDP; arg.voidp = p; } HookArgument(void* p) { type = VOIDP; arg.voidp = p; }
/** /**
* Constructor with a ValWrapper argument. * Constructor with a wrapped Val argument.
*/ */
HookArgument(ValWrapper* a) { type = WRAPPED_VAL; arg.wrapper = a; } HookArgument(std::pair<Val*, bool> a) { type = WRAPPED_VAL; wrapper = a; }
/** /**
* Constructor with a Frame argument. * Constructor with a Frame argument.
@ -293,7 +266,7 @@ public:
* Returns the value for a Bro wrapped value argument. The argument's type must * Returns the value for a Bro wrapped value argument. The argument's type must
* match accordingly. * match accordingly.
*/ */
const ValWrapper* AsValWrapper() const { assert(type == VAL_WRAPPER); return arg.wrapper; } const std::pair<Val*, bool> AsValWrapper() const { assert(type == VAL_WRAPPER); return wrapper; }
/** /**
* Returns the value for a Bro frame argument. The argument's type must * Returns the value for a Bro frame argument. The argument's type must
@ -335,11 +308,11 @@ private:
const Frame* frame; const Frame* frame;
int int_; int int_;
const Val* val; const Val* val;
const ValWrapper* wrapper;
const val_list* vals; const val_list* vals;
const void* voidp; const void* voidp;
} arg; } arg;
std::pair<Val*, bool> wrapper; // Outside union because it has dtor.
std::string arg_string; // Outside union because it has dtor. std::string arg_string; // Outside union because it has dtor.
}; };
@ -620,14 +593,13 @@ protected:
* in place as long as it ensures matching types and correct reference * in place as long as it ensures matching types and correct reference
* counting. * counting.
* *
* @return If the plugin handled the call, a ValWrapper with the * @return If the plugin handled the call, a std::pair<Val*, bool> with the
* processed flag set to true, and a value set on the object with * processed flag set to true, and a value set on the object with
* a+1 reference count containing the result value to pass back to the * a+1 reference count containing the result value to pass back to the
* interpreter. If the plugin did not handle the call, it may either * interpreter. If the plugin did not handle the call, it must
* return NULL *or* return a ValWrapper with the processed flag set to * return a ValWrapper with the processed flag set to 'false'.
* 'false'.
*/ */
virtual ValWrapper* HookCallFunction(const Func* func, Frame *parent, val_list* args); virtual std::pair<Val*, bool> HookCallFunction(const Func* func, Frame *parent, val_list* args);
/** /**
* Hook into raising events. Whenever the script interpreter is about * Hook into raising events. Whenever the script interpreter is about

View file

@ -0,0 +1,6 @@
A, 0
B, 1
C, 2
AV, 10
BV, 11
CV, 12

View file

@ -1,5 +1,6 @@
2 1080 2 1080
1 137 1 137
1 1434
1 161 1 161
1 162 1 162
1 1812 1 1812
@ -11,6 +12,7 @@
1 25 1 25
1 2811 1 2811
1 3128 1 3128
1 3306
1 3544 1 3544
1 443 1 443
1 502 1 502
@ -42,8 +44,8 @@
1 992 1 992
1 993 1 993
1 995 1 995
46 and 48 and
45 or 47 or
46 port 48 port
32 tcp 34 tcp
14 udp 14 udp

View file

@ -3,7 +3,7 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path loaded_scripts #path loaded_scripts
#open 2014-09-06-01-19-42 #open 2014-10-31-20-38-14
#fields name #fields name
#types string #types string
scripts/base/init-bare.bro scripts/base/init-bare.bro
@ -73,6 +73,7 @@ scripts/base/init-bare.bro
build/scripts/base/bif/plugins/Bro_Login.functions.bif.bro build/scripts/base/bif/plugins/Bro_Login.functions.bif.bro
build/scripts/base/bif/plugins/Bro_MIME.events.bif.bro build/scripts/base/bif/plugins/Bro_MIME.events.bif.bro
build/scripts/base/bif/plugins/Bro_Modbus.events.bif.bro build/scripts/base/bif/plugins/Bro_Modbus.events.bif.bro
build/scripts/base/bif/plugins/Bro_MySQL.events.bif.bro
build/scripts/base/bif/plugins/Bro_NCP.events.bif.bro build/scripts/base/bif/plugins/Bro_NCP.events.bif.bro
build/scripts/base/bif/plugins/Bro_NetBIOS.events.bif.bro build/scripts/base/bif/plugins/Bro_NetBIOS.events.bif.bro
build/scripts/base/bif/plugins/Bro_NetBIOS.functions.bif.bro build/scripts/base/bif/plugins/Bro_NetBIOS.functions.bif.bro
@ -114,4 +115,4 @@ scripts/base/init-bare.bro
build/scripts/base/bif/plugins/Bro_SQLiteWriter.sqlite.bif.bro build/scripts/base/bif/plugins/Bro_SQLiteWriter.sqlite.bif.bro
scripts/policy/misc/loaded-scripts.bro scripts/policy/misc/loaded-scripts.bro
scripts/base/utils/paths.bro scripts/base/utils/paths.bro
#close 2014-09-06-01-19-42 #close 2014-10-31-20-38-14

View file

@ -3,7 +3,7 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path loaded_scripts #path loaded_scripts
#open 2014-09-06-01-20-32 #open 2014-10-31-20-38-48
#fields name #fields name
#types string #types string
scripts/base/init-bare.bro scripts/base/init-bare.bro
@ -73,6 +73,7 @@ scripts/base/init-bare.bro
build/scripts/base/bif/plugins/Bro_Login.functions.bif.bro build/scripts/base/bif/plugins/Bro_Login.functions.bif.bro
build/scripts/base/bif/plugins/Bro_MIME.events.bif.bro build/scripts/base/bif/plugins/Bro_MIME.events.bif.bro
build/scripts/base/bif/plugins/Bro_Modbus.events.bif.bro build/scripts/base/bif/plugins/Bro_Modbus.events.bif.bro
build/scripts/base/bif/plugins/Bro_MySQL.events.bif.bro
build/scripts/base/bif/plugins/Bro_NCP.events.bif.bro build/scripts/base/bif/plugins/Bro_NCP.events.bif.bro
build/scripts/base/bif/plugins/Bro_NetBIOS.events.bif.bro build/scripts/base/bif/plugins/Bro_NetBIOS.events.bif.bro
build/scripts/base/bif/plugins/Bro_NetBIOS.functions.bif.bro build/scripts/base/bif/plugins/Bro_NetBIOS.functions.bif.bro
@ -217,6 +218,9 @@ scripts/base/init-default.bro
scripts/base/protocols/modbus/__load__.bro scripts/base/protocols/modbus/__load__.bro
scripts/base/protocols/modbus/consts.bro scripts/base/protocols/modbus/consts.bro
scripts/base/protocols/modbus/main.bro scripts/base/protocols/modbus/main.bro
scripts/base/protocols/mysql/__load__.bro
scripts/base/protocols/mysql/main.bro
scripts/base/protocols/mysql/consts.bro
scripts/base/protocols/pop3/__load__.bro scripts/base/protocols/pop3/__load__.bro
scripts/base/protocols/radius/__load__.bro scripts/base/protocols/radius/__load__.bro
scripts/base/protocols/radius/main.bro scripts/base/protocols/radius/main.bro
@ -243,4 +247,4 @@ scripts/base/init-default.bro
scripts/base/misc/find-checksum-offloading.bro scripts/base/misc/find-checksum-offloading.bro
scripts/base/misc/find-filtered-trace.bro scripts/base/misc/find-filtered-trace.bro
scripts/policy/misc/loaded-scripts.bro scripts/policy/misc/loaded-scripts.bro
#close 2014-09-06-01-20-32 #close 2014-10-31-20-38-48

View file

@ -21,6 +21,7 @@ known_services
loaded_scripts loaded_scripts
modbus modbus
modbus_register_change modbus_register_change
mysql
notice notice
notice_alarm notice_alarm
packet_filter packet_filter

View file

@ -7,6 +7,6 @@
# bro data_struct_vector_declaration.bro # bro data_struct_vector_declaration.bro
contents of v1: [1, 2, 3, 4] contents of v1: [1, 2, 3, 4]
length of v1: 4 length of v1: 4
contents of v1: [1, 2, 3, 4] contents of v2: [1, 2, 3, 4]
length of v2: 4 length of v2: 4

View file

@ -6,6 +6,6 @@
# bro data_type_pattern_01.bro # bro data_type_pattern_01.bro
The The
brown fox jumped over the brown fox jumps over the
dog. dog.

View file

@ -0,0 +1,5 @@
7.0
[i=1, d=3.0]
237, 101.0
-5, 101.0
-37, -8.1

View file

@ -16,7 +16,7 @@
[one] = 1.0, [one] = 1.0,
[three] = 3.0 [three] = 3.0
} }
0 0.0
{ {
[42] = forty-two, [42] = forty-two,
[37] = thirty-seven [37] = thirty-seven

View file

@ -0,0 +1,11 @@
[zero, one, , , , five, , seven]
vec[0] = zero.exe
vec[1] = one.exe
vec[2] = <not set>
vec[3] = <not set>
vec[4] = <not set>
vec[5] = five.exe
vec[6] = <not set>
vec[7] = seven.exe
vec[8] = <not set>
vec[9] = <not set>

View file

@ -0,0 +1,38 @@
error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.when-unitialized-rhs/when-unitialized-rhs.bro, line 9: value used but not set (crashMe)
error in /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.when-unitialized-rhs/when-unitialized-rhs.bro, line 14: value used but not set (x)
1
2
3
4
5
6
7
8
9
10
2nd when stmt executing, 999
1st when stmt executing, not anymore you don't
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

View file

@ -1 +1 @@
fatal error in XXX line 1: plugin's API version does not match Bro (expected 2, got 42 in XXX fatal error in /home/robin/bro/master/scripts/base/init-bare.bro, line 1: plugin's API version does not match Bro (expected 2, got 42 in /home/robin/bro/master/testing/btest/.tmp/plugins.api-version-mismatch//lib/XXX)

View file

@ -3,5 +3,5 @@ Demo::Foo - <Insert description> (dynamic, version 1.0)
[Event] plugin_event [Event] plugin_event
plugin: automatically loaded at startup plugin: automatically loaded at startup
calling bif, Hello from the plugin!
plugin: manually loaded plugin: manually loaded
calling bif, Hello from the plugin!

View file

@ -4,21 +4,19 @@ Demo::Foo - <Insert description> (dynamic, version 1.0)
=== ===
plugin: automatically loaded at startup plugin: automatically loaded at startup
calling bif, Hello from the plugin!
=== ===
plugin: automatically loaded at startup plugin: automatically loaded at startup
calling bif, Hello from the plugin!
plugin: manually loaded plugin: manually loaded
calling bif, Hello from the plugin!
=-= =-=
=-= =-=
=== ===
plugin: automatically loaded at startup plugin: automatically loaded at startup
===
plugin: automatically loaded at startup
plugin: manually loaded
calling bif, Hello from the plugin! calling bif, Hello from the plugin!
=== ===
plugin: automatically loaded at startup plugin: automatically loaded at startup
calling bif, Hello from the plugin!
plugin: manually loaded plugin: manually loaded
===
plugin: automatically loaded at startup
calling bif, Hello from the plugin! calling bif, Hello from the plugin!
plugin: manually loaded

File diff suppressed because it is too large Load diff

View file

@ -1,39 +1,39 @@
FILE_NEW FILE_NEW
file #0, 0, 0 file #0, 0, 0
FILE_BOF_BUFFER FILE_BOF_BUFFER
test^M^J test
FILE_OVER_NEW_CONNECTION FILE_OVER_NEW_CONNECTION
FILE_STATE_REMOVE FILE_STATE_REMOVE
file #0, 6, 0 file #0, 4, 0
[orig_h=141.142.228.5, orig_p=57262/tcp, resp_h=54.243.88.146, resp_p=80/tcp] [orig_h=141.142.228.5, orig_p=57262/tcp, resp_h=54.243.88.146, resp_p=80/tcp]
source: HTTP source: HTTP
MD5: 9f06243abcb89c70e0c331c61d871fa7 MD5: 098f6bcd4621d373cade4e832627b4f6
SHA1: fde773a18bb29f5ed65e6f0a7aa717fd1fa485d4 SHA1: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
SHA256: 837ccb607e312b170fac7383d7ccfd61fa5072793f19a25e75fbacb56539b86b SHA256: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
FILE_NEW FILE_NEW
file #1, 0, 0 file #1, 0, 0
FILE_BOF_BUFFER FILE_BOF_BUFFER
test2^M^J test2
FILE_OVER_NEW_CONNECTION FILE_OVER_NEW_CONNECTION
FILE_STATE_REMOVE FILE_STATE_REMOVE
file #1, 7, 0 file #1, 5, 0
[orig_h=141.142.228.5, orig_p=57262/tcp, resp_h=54.243.88.146, resp_p=80/tcp] [orig_h=141.142.228.5, orig_p=57262/tcp, resp_h=54.243.88.146, resp_p=80/tcp]
source: HTTP source: HTTP
MD5: d68af81ef370b3873d50f09140068810 MD5: ad0234829205b9033196ba818f7a872b
SHA1: 51a7b6f2d91f6a87822dc04560f2972bc14fc97e SHA1: 109f4b3c50d7b0df729d299bc6f8e9ef9066971f
SHA256: de0edd0ac4a705aff70f34734e90a1d0a1d8b76abe4bb53f3ea934bc105b3b17 SHA256: 60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
FILE_NEW FILE_NEW
file #2, 0, 0 file #2, 0, 0
FILE_BOF_BUFFER FILE_BOF_BUFFER
test3^M^J test3
FILE_OVER_NEW_CONNECTION FILE_OVER_NEW_CONNECTION
FILE_STATE_REMOVE FILE_STATE_REMOVE
file #2, 7, 0 file #2, 5, 0
[orig_h=141.142.228.5, orig_p=57262/tcp, resp_h=54.243.88.146, resp_p=80/tcp] [orig_h=141.142.228.5, orig_p=57262/tcp, resp_h=54.243.88.146, resp_p=80/tcp]
source: HTTP source: HTTP
MD5: 1a3d75d44753ad246f0bd333cdaf08b0 MD5: 8ad8757baa8564dc136c1e07507f4a98
SHA1: 4f98809ab09272dfcc58266e3f23ae2393f70e76 SHA1: 3ebfa301dc59196f18593c45e519287a23297589
SHA256: 018c67a2c30ed9977e1dddfe98cac542165dac355cf9764c91a362613e752933 SHA256: fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13
FILE_NEW FILE_NEW
file #3, 0, 0 file #3, 0, 0
FILE_BOF_BUFFER FILE_BOF_BUFFER

View file

@ -6,12 +6,12 @@ MIME_TYPE
text/plain text/plain
FILE_OVER_NEW_CONNECTION FILE_OVER_NEW_CONNECTION
FILE_STATE_REMOVE FILE_STATE_REMOVE
file #0, 79, 0 file #0, 77, 0
[orig_h=10.10.1.4, orig_p=1470/tcp, resp_h=74.53.140.153, resp_p=25/tcp] [orig_h=10.10.1.4, orig_p=1470/tcp, resp_h=74.53.140.153, resp_p=25/tcp]
source: SMTP source: SMTP
MD5: 92bca2e6cdcde73647125da7dccbdd07 MD5: 58aff3af22807bc5f4b6357c0038256c
SHA1: b7e497be8a9f5e2c4b6980fceb015360f98f4a13 SHA1: c39dc8cd0f8d8b1f7fc8b362c41e69fdf20f668a
SHA256: 785a8a044d1454ec88837108f443bbb30cc4f529393ffd57118261036bfe59f5 SHA256: 8d057f3af311c20675eea767a9df5fa31ff3597c6d5d50fd0cdc34766c40204d
FILE_NEW FILE_NEW
file #1, 0, 0 file #1, 0, 0
FILE_BOF_BUFFER FILE_BOF_BUFFER

View file

@ -10,4 +10,3 @@ Find the attachment
GPS GPS

View file

@ -3,9 +3,9 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path ssl #path ssl
#open 2014-04-26-16-44-47 #open 2014-08-08-17-13-20
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name session_id last_alert established cert_chain_fuids client_cert_chain_fuids subject issuer client_subject client_issuer #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established cert_chain_fuids client_cert_chain_fuids subject issuer client_subject client_issuer
#types time string addr port addr port string string string string string string bool vector[string] vector[string] string string string string #types time string addr port addr port string string string string bool string string bool vector[string] vector[string] string string string string
1348168976.508038 CXWv6p3arKYeMETxOg 192.168.57.103 60108 192.168.57.101 2811 TLSv10 TLS_RSA_WITH_AES_256_CBC_SHA - - - - T FBtbj87tgpyeDSj31,F8TfgZ31c1dFu8Kt2k FVNYOh2BeQBb7MpCPe,FwjBou1e5DbpE0eOgk,FbYQmk4x4M4Bx3PZme CN=host/alpha,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Globus Simple CA,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid 1348168976.508038 CXWv6p3arKYeMETxOg 192.168.57.103 60108 192.168.57.101 2811 TLSv10 TLS_RSA_WITH_AES_256_CBC_SHA - - F - - T FBtbj87tgpyeDSj31,F8TfgZ31c1dFu8Kt2k FVNYOh2BeQBb7MpCPe,FwjBou1e5DbpE0eOgk,FbYQmk4x4M4Bx3PZme CN=host/alpha,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Globus Simple CA,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid
1348168976.551422 CjhGID4nQcgTWjvg4c 192.168.57.103 35391 192.168.57.101 55968 TLSv10 TLS_RSA_WITH_NULL_SHA - - - - T F4SSqN31HDIrrH5Q8h,FJHp5Pf6VLQsRQK3,FHACqa3dX9BXRV2av,FNnDVT1NURRWeoLLN3 FFWYVj4BcvQb35WIaf,Fj16G835fnJgnVlKU6,FGONoc1Nj0Ka5zlxDa CN=932373381,CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid 1348168976.551422 CjhGID4nQcgTWjvg4c 192.168.57.103 35391 192.168.57.101 55968 TLSv10 TLS_RSA_WITH_NULL_SHA - - F - - T F4SSqN31HDIrrH5Q8h,FJHp5Pf6VLQsRQK3,FHACqa3dX9BXRV2av,FNnDVT1NURRWeoLLN3 FFWYVj4BcvQb35WIaf,Fj16G835fnJgnVlKU6,FGONoc1Nj0Ka5zlxDa CN=932373381,CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=917532944,CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid CN=Jon Siwek,OU=local,OU=simpleCA-alpha,OU=GlobusTest,O=Grid
#close 2014-04-26-16-44-47 #close 2014-08-08-17-13-20

View file

@ -0,0 +1,21 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path mysql
#open 2014-09-05-03-02-01
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p cmd arg result response
#types time string addr port addr port string string string string
1362452327.618353 CsRx2w45OKnoww6xl4 192.168.1.3 55845 192.168.1.8 3306 login root_nope error Access denied for user 'root_nope'@'lumberjack.home' (using password: NO)
1362452330.947463 CRJuHdVW0XPVINV8a 192.168.1.3 55846 192.168.1.8 3306 login root_nope error Access denied for user 'root_nope'@'lumberjack.home' (using password: YES)
1362452332.571339 CPbrpk1qSsw6ESzHV4 192.168.1.3 55847 192.168.1.8 3306 login root_nope error Access denied for user 'root_nope'@'lumberjack.home' (using password: YES)
1362452334.559420 C6pKV8GSxOnSLghOa 192.168.1.3 55857 192.168.1.8 3306 login root_nope error Access denied for user 'root_nope'@'lumberjack.home' (using password: YES)
1362452336.361958 CIPOse170MGiRM1Qf4 192.168.1.3 55860 192.168.1.8 3306 login root_nope error Access denied for user 'root_nope'@'lumberjack.home' (using password: YES)
1362452357.320858 C7XEbhP654jzLoe3a 192.168.1.3 55861 192.168.1.8 3306 login root error Access denied for user 'root'@'lumberjack.home' (using password: NO)
1362452358.565340 CJ3xTn1c4Zw9TmAE05 192.168.1.3 55862 192.168.1.8 3306 login root error Access denied for user 'root'@'lumberjack.home' (using password: YES)
1362452360.410803 CMXxB5GvmoxJFXdTa 192.168.1.3 55863 192.168.1.8 3306 login root error Access denied for user 'root'@'lumberjack.home' (using password: YES)
1362452361.886123 Caby8b1slFea8xwSmb 192.168.1.3 55864 192.168.1.8 3306 login root error Access denied for user 'root'@'lumberjack.home' (using password: YES)
1362452372.452858 Che1bq3i2rO3KD1Syg 192.168.1.3 55865 192.168.1.8 3306 login root ok Affected rows: 0
1362452372.454995 Che1bq3i2rO3KD1Syg 192.168.1.3 55865 192.168.1.8 3306 query select @@version_comment limit 1 ok Affected rows: 1
1362452372.991997 Che1bq3i2rO3KD1Syg 192.168.1.3 55865 192.168.1.8 3306 quit (empty) - -
#close 2014-09-05-03-02-01

Some files were not shown because too many files have changed in this diff Show more