Merge branch 'topic/script-reference' into topic/bif_cleanup

Conflicts:
	src/bro.bif
This commit is contained in:
Matthias Vallentin 2011-12-15 22:54:52 -08:00
commit 3ab03874b5
29 changed files with 10871 additions and 2604 deletions

View file

@ -24,7 +24,7 @@ sys.path.insert(0, os.path.abspath('sphinx-sources/ext'))
# Add any Sphinx extension module names here, as strings. They can be extensions # Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['bro', 'rst_directive'] extensions = ['bro', 'rst_directive', 'sphinx.ext.todo']
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static'] templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static']
@ -217,3 +217,6 @@ man_pages = [
('index', 'bro', u'Bro Documentation', ('index', 'bro', u'Bro Documentation',
[u'The Bro Project'], 1) [u'The Bro Project'], 1)
] ]
# -- Options for todo plugin --------------------------------------------
todo_include_todos=True

View file

@ -43,13 +43,14 @@ Basics
====== ======
The data fields that a stream records are defined by a record type The data fields that a stream records are defined by a record type
specified when it is created. Let's look at the script generating specified when it is created. Let's look at the script generating Bro's
Bro's connection summaries as an example, connection summaries as an example,
``base/protocols/conn/main.bro``. It defines a record ``Conn::Info`` :doc:`scripts/base/protocols/conn/main`. It defines a record
that lists all the fields that go into ``conn.log``, each marked with :bro:type:`Conn::Info` that lists all the fields that go into
a ``&log`` attribute indicating that it is part of the information ``conn.log``, each marked with a ``&log`` attribute indicating that it
written out. To write a log record, the script then passes an instance is part of the information written out. To write a log record, the
of ``Conn::Info`` to the logging framework's ``Log::write`` function. script then passes an instance of :bro:type:`Conn::Info` to the logging
framework's :bro:id:`Log::write` function.
By default, each stream automatically gets a filter named ``default`` By default, each stream automatically gets a filter named ``default``
that generates the normal output by recording all record fields into a that generates the normal output by recording all record fields into a
@ -66,7 +67,7 @@ To create new a new output file for an existing stream, you can add a
new filter. A filter can, e.g., restrict the set of fields being new filter. A filter can, e.g., restrict the set of fields being
logged: logged:
.. code:: bro: .. code:: bro
event bro_init() event bro_init()
{ {
@ -85,14 +86,15 @@ Note the fields that are set for the filter:
``path`` ``path``
The filename for the output file, without any extension (which The filename for the output file, without any extension (which
may be automatically added by the writer). Default path values may be automatically added by the writer). Default path values
are generated by taking the stream's ID and munging it are generated by taking the stream's ID and munging it slightly.
slightly. ``Conn::LOG`` is converted into ``conn``, :bro:enum:`Conn::LOG` is converted into ``conn``,
``PacketFilter::LOG`` is converted into ``packet_filter``, and :bro:enum:`PacketFilter::LOG` is converted into
``Notice::POLICY_LOG`` is converted into ``notice_policy``. ``packet_filter``, and :bro:enum:`Notice::POLICY_LOG` is
converted into ``notice_policy``.
``include`` ``include``
A set limiting the fields to the ones given. The names A set limiting the fields to the ones given. The names
correspond to those in the ``Conn::LOG`` record, with correspond to those in the :bro:type:`Conn::Info` record, with
sub-records unrolled by concatenating fields (separated with sub-records unrolled by concatenating fields (separated with
dots). dots).
@ -158,10 +160,10 @@ further for example to log information by subnets or even by IP
address. Be careful, however, as it is easy to create many files very address. Be careful, however, as it is easy to create many files very
quickly ... quickly ...
.. sidebar: .. sidebar:: A More Generic Path Function
The show ``split_log`` method has one draw-back: it can be used The ``split_log`` method has one draw-back: it can be used
only with the ``Conn::Log`` stream as the record type is hardcoded only with the :bro:enum:`Conn::Log` stream as the record type is hardcoded
into its argument list. However, Bro allows to do a more generic into its argument list. However, Bro allows to do a more generic
variant: variant:
@ -201,8 +203,8 @@ Extending
You can add further fields to a log stream by extending the record You can add further fields to a log stream by extending the record
type that defines its content. Let's say we want to add a boolean type that defines its content. Let's say we want to add a boolean
field ``is_private`` to ``Conn::Info`` that indicates whether the field ``is_private`` to :bro:type:`Conn::Info` that indicates whether the
originator IP address is part of the RFC1918 space: originator IP address is part of the :rfc:`1918` space:
.. code:: bro .. code:: bro
@ -234,10 +236,10 @@ Notes:
- For extending logs this way, one needs a bit of knowledge about how - For extending logs this way, one needs a bit of knowledge about how
the script that creates the log stream is organizing its state the script that creates the log stream is organizing its state
keeping. Most of the standard Bro scripts attach their log state to keeping. Most of the standard Bro scripts attach their log state to
the ``connection`` record where it can then be accessed, just as the the :bro:type:`connection` record where it can then be accessed, just
``c$conn`` above. For example, the HTTP analysis adds a field ``http as the ``c$conn`` above. For example, the HTTP analysis adds a field
: HTTP::Info`` to the ``connection`` record. See the script ``http`` of type :bro:type:`HTTP::Info` to the :bro:type:`connection`
reference for more information. record. See the script reference for more information.
- When extending records as shown above, the new fields must always be - When extending records as shown above, the new fields must always be
declared either with a ``&default`` value or as ``&optional``. declared either with a ``&default`` value or as ``&optional``.
@ -251,8 +253,8 @@ Sometimes it is helpful to do additional analysis of the information
being logged. For these cases, a stream can specify an event that will being logged. For these cases, a stream can specify an event that will
be generated every time a log record is written to it. All of Bro's be generated every time a log record is written to it. All of Bro's
default log streams define such an event. For example, the connection default log streams define such an event. For example, the connection
log stream raises the event ``Conn::log_conn(rec: Conn::Info)``: You log stream raises the event :bro:id:`Conn::log_conn`. You
could use that for example for flagging when an a connection to could use that for example for flagging when a connection to
specific destination exceeds a certain duration: specific destination exceeds a certain duration:
.. code:: bro .. code:: bro
@ -279,11 +281,32 @@ real-time.
Rotation Rotation
-------- --------
By default, no log rotation occurs, but it's globally controllable for all
filters by redefining the :bro:id:`Log::default_rotation_interval` option:
.. code:: bro
redef Log::default_rotation_interval = 1 hr;
Or specifically for certain :bro:type:`Log::Filter` instances by setting
their ``interv`` field. Here's an example of changing just the
:bro:enum:`Conn::LOG` stream's default filter rotation.
.. code:: bro
event bro_init()
{
local f = Log::get_filter(Conn::LOG, "default");
f$interv = 1 min;
Log::remove_filter(Conn::LOG, "default");
Log::add_filter(Conn::LOG, f);
}
ASCII Writer Configuration ASCII Writer Configuration
-------------------------- --------------------------
The ASCII writer has a number of options for customizing the format of The ASCII writer has a number of options for customizing the format of
its output, see XXX.bro. its output, see :doc:`scripts/base/frameworks/logging/writers/ascii`.
Adding Streams Adding Streams
============== ==============
@ -321,8 +344,8 @@ example for the ``Foo`` module:
Log::create_stream(Foo::LOG, [$columns=Info, $ev=log_foo]); Log::create_stream(Foo::LOG, [$columns=Info, $ev=log_foo]);
} }
You can also the state to the ``connection`` record to make it easily You can also add the state to the :bro:type:`connection` record to make
accessible across event handlers: it easily accessible across event handlers:
.. code:: bro .. code:: bro
@ -330,7 +353,7 @@ accessible across event handlers:
foo: Info &optional; foo: Info &optional;
} }
Now you can use the ``Log::write`` method to output log records and Now you can use the :bro:id:`Log::write` method to output log records and
save the logged ``Foo::Info`` record into the connection record: save the logged ``Foo::Info`` record into the connection record:
.. code:: bro .. code:: bro
@ -343,9 +366,9 @@ save the logged ``Foo::Info`` record into the connection record:
} }
See the existing scripts for how to work with such a new connection See the existing scripts for how to work with such a new connection
field. A simple example is ``base/protocols/syslog/main.bro``. field. A simple example is :doc:`scripts/base/protocols/syslog/main`.
When you are developing scripts that add data to the ``connection`` When you are developing scripts that add data to the :bro:type:`connection`
record, care must be given to when and how long data is stored. record, care must be given to when and how long data is stored.
Normally data saved to the connection record will remain there for the Normally data saved to the connection record will remain there for the
duration of the connection and from a practical perspective it's not duration of the connection and from a practical perspective it's not

View file

@ -6,113 +6,621 @@ Types
The Bro scripting language supports the following built-in types. The Bro scripting language supports the following built-in types.
.. TODO: add documentation
.. bro:type:: void
.. bro:type:: bool .. bro:type:: bool
Reflects a value with one of two meanings: true or false. The two
``bool`` constants are ``T`` and ``F``.
.. bro:type:: int .. bro:type:: int
A numeric type representing a signed integer. An ``int`` constant
is a string of digits preceded by a ``+`` or ``-`` sign, e.g.
``-42`` or ``+5``. When using type inferencing use care so that the
intended type is inferred, e.g. ``local size_difference = 0`` will
infer the :bro:type:`count` while ``local size_difference = +0``
will infer :bro:type:`int`.
.. bro:type:: count .. bro:type:: count
A numeric type representing an unsigned integer. A ``count``
constant is a string of digits, e.g. ``1234`` or ``0``.
.. bro:type:: counter .. bro:type:: counter
An alias to :bro:type:`count`
.. TODO: is there anything special about this type?
.. bro:type:: double .. bro:type:: double
A numeric type representing a double-precision floating-point
number. Floating-point constants are written as a string of digits
with an optional decimal point, optional scale-factor in scientific
notation, and optional ``+`` or ``-`` sign. Examples are ``-1234``,
``-1234e0``, ``3.14159``, and ``.003e-23``.
.. bro:type:: time .. bro:type:: time
A temporal type representing an absolute time. There is currently
no way to specify a ``time`` constant, but one can use the
:bro:id:`current_time` or :bro:id:`network_time` built-in functions
to assign a value to a ``time``-typed variable.
.. bro:type:: interval .. bro:type:: interval
A temporal type representing a relative time. An ``interval``
constant can be written as a numeric constant followed by a time
unit where the time unit is one of ``usec``, ``sec``, ``min``,
``hr``, or ``day`` which respectively represent microseconds,
seconds, minutes, hours, and days. Whitespace between the numeric
constant and time unit is optional. Appending the letter "s" to the
time unit in order to pluralize it is also optional (to no semantic
effect). Examples of ``interval`` constants are ``3.5 min`` and
``3.5mins``. An ``interval`` can also be negated, for example ``-
12 hr`` represents "twelve hours in the past". Intervals also
support addition, subtraction, multiplication, division, and
comparison operations.
.. bro:type:: string .. bro:type:: string
A type used to hold character-string values which represent text.
String constants are created by enclosing text in double quotes (")
and the backslash character (\) introduces escape sequences.
Note that Bro represents strings internally as a count and vector of
bytes rather than a NUL-terminated byte string (although string
constants are also automatically NUL-terminated). This is because
network traffic can easily introduce NULs into strings either by
nature of an application, inadvertently, or maliciously. And while
NULs are allowed in Bro strings, when present in strings passed as
arguments to many functions, a run-time error can occur as their
presence likely indicates a sort of problem. In that case, the
string will also only be represented to the user as the literal
"<string-with-NUL>" string.
.. bro:type:: pattern .. bro:type:: pattern
A type representing regular-expression patterns which can be used
for fast text-searching operations. Pattern constants are created
by enclosing text within forward slashes (/) and is the same syntax
as the patterns supported by the `flex lexical analyzer
<http://flex.sourceforge.net/manual/Patterns.html>`_. The speed of
regular expression matching does not depend on the complexity or
size of the patterns. Patterns support two types of matching, exact
and embedded.
In exact matching the ``==`` equality relational operator is used
with one :bro:type:`string` operand and one :bro:type:`pattern`
operand to check whether the full string exactly matches the
pattern. In this case, the ``^`` beginning-of-line and ``$``
end-of-line anchors are redundant since pattern is implicitly
anchored to the beginning and end of the line to facilitate an exact
match. For example::
"foo" == /foo|bar/
yields true, while::
/foo|bar/ == "foobar"
yields false. The ``!=`` operator would yield the negation of ``==``.
In embedded matching the ``in`` operator is again used with one
:bro:type:`string` operand and one :bro:type:`pattern` operand
(which must be on the left-hand side), but tests whether the pattern
appears anywhere within the given string. For example::
/foo|bar/ in "foobar"
yields true, while::
/^oob/ in "foobar"
is false since "oob" does not appear at the start of "foobar". The
``!in`` operator would yield the negation of ``in``.
.. bro:type:: enum .. bro:type:: enum
A type allowing the specification of a set of related values that
have no further structure. The only operations allowed on
enumerations are equality comparisons and they do not have
associated values or ordering. An example declaration:
.. code:: bro
type color: enum { Red, White, Blue, };
The last comma is after ``Blue`` is optional.
.. bro:type:: timer .. bro:type:: timer
.. TODO: is this a type that's exposed to users?
.. bro:type:: port .. bro:type:: port
A type representing transport-level port numbers. Besides TCP and
UDP ports, there is a concept of an ICMP "port" where the source
port is the ICMP message type and the destination port the ICMP
message code. A ``port`` constant is written as an unsigned integer
followed by one of ``/tcp``, ``/udp``, ``/icmp``, or ``/unknown``.
Ports can be compared for equality and also for ordering. When
comparing order across transport-level protocols, ``/unknown`` <
``/tcp`` < ``/udp`` < ``icmp``, for example ``65535/tcp`` is smaller
than ``0/udp``.
.. bro:type:: addr .. bro:type:: addr
.. bro:type:: net A type representing an IP address. Currently, Bro defaults to only
supporting IPv4 addresses unless configured/built with
``--enable-brov6``, in which case, IPv6 addresses are supported.
IPv4 address constants are written in "dotted quad" format,
``A1.A2.A3.A4``, where Ai all lie between 0 and 255.
IPv6 address constants are written as colon-separated hexadecimal form
as described by :rfc:`2373`.
Hostname constants can also be used, but since a hostname can
correspond to multiple IP addresses, the type of such variable is a
:bro:type:`set` of :bro:type:`addr` elements. For example:
.. code:: bro
local a = www.google.com;
Addresses can be compared for (in)equality using ``==`` and ``!=``.
They can also be masked with ``/`` to produce a :bro:type:`subnet`:
.. code:: bro
local a: addr = 192.168.1.100;
local s: subnet = 192.168.0.0/16;
if ( a/16 == s )
print "true";
And checked for inclusion within a :bro:type:`subnet` using ``in`` :
.. code:: bro
local a: addr = 192.168.1.100;
local s: subnet = 192.168.0.0/16;
if ( a in s )
print "true";
.. bro:type:: subnet .. bro:type:: subnet
A type representing a block of IP addresses in CIDR notation. A
``subnet`` constant is written as an :bro:type:`addr` followed by a
slash (/) and then the network prefix size specified as a decimal
number. For example, ``192.168.0.0/16``.
.. bro:type:: any .. bro:type:: any
Used to bypass strong typing. For example, a function can take an
argument of type ``any`` when it may be of different types.
.. bro:type:: table .. bro:type:: table
.. bro:type:: union An associate array that maps from one set of values to another. The
values being mapped are termed the *index* or *indices* and the
result of the mapping is called the *yield*. Indexing into tables
is very efficient, and internally it is just a single hash table
lookup.
.. bro:type:: record The table declaration syntax is::
.. bro:type:: types table [ type^+ ] of type
.. bro:type:: func where *type^+* is one or more types, separated by commas. For example:
.. bro:type:: file .. code:: bro
.. bro:type:: vector global a: table[count] of string;
.. TODO: below are kind of "special cases" that bro knows about? declares a table indexed by :bro:type:`count` values and yielding
:bro:type:`string` values. The yield type can also be more complex:
.. code:: bro
global a: table[count] of table[addr, port] of string;
which declared a table indexed by :bro:type:`count` and yielding
another :bro:type:`table` which is indexed by an :bro:type:`addr`
and :bro:type:`port` to yield a :bro:type:`string`.
Initialization of tables occurs by enclosing a set of initializers within
braces, for example:
.. code:: bro
global t: table[count] of string = {
[11] = "eleven",
[5] = "five",
};
Accessing table elements if provided by enclosing values within square
brackets (``[]``), for example:
.. code:: bro
t[13] = "thirteen";
And membership can be tested with ``in``:
.. code:: bro
if ( 13 in t )
...
Iterate over tables with a ``for`` loop:
.. code:: bro
local t: table[count] of string;
for ( n in t )
...
local services: table[addr, port] of string;
for ( [a, p] in services )
...
Remove individual table elements with ``delete``:
.. code:: bro
delete t[13];
Nothing happens if the element with value ``13`` isn't present in
the table.
Table size can be obtained by placing the table identifier between
vertical pipe (|) characters:
.. code:: bro
|t|
.. bro:type:: set .. bro:type:: set
A set is like a :bro:type:`table`, but it is a collection of indices
that do not map to any yield value. They are declared with the
syntax::
set [ type^+ ]
where *type^+* is one or more types separated by commas.
Sets are initialized by listing elements enclosed by curly braces:
.. code:: bro
global s: set[port] = { 21/tcp, 23/tcp, 80/tcp, 443/tcp };
global s2: set[port, string] = { [21/tcp, "ftp"], [23/tcp, "telnet"] };
The types are explicitly shown in the example above, but they could
have been left to type inference.
Set membership is tested with ``in``:
.. code:: bro
if ( 21/tcp in s )
...
Elements are added with ``add``:
.. code:: bro
add s[22/tcp];
And removed with ``delete``:
.. code:: bro
delete s[21/tcp];
Set size can be obtained by placing the set identifier between
vertical pipe (|) characters:
.. code:: bro
|s|
.. bro:type:: vector
A vector is like a :bro:type:`table`, except it's always indexed by a
:bro:type:`count`. A vector is declared like:
.. code:: bro
global v: vector of string;
And can be initialized with the vector constructor:
.. code:: bro
global v: vector of string = vector("one", "two", "three");
Adding an element to a vector involves accessing/assigning it:
.. code:: bro
v[3] = "four"
Note how the vector indexing is 0-based.
Vector size can be obtained by placing the vector identifier between
vertical pipe (|) characters:
.. code:: bro
|v|
.. bro:type:: record
A ``record`` is a collection of values. Each value has a field name
and a type. Values do not need to have the same type and the types
have no restrictions. An example record type definition:
.. code:: bro
type MyRecordType: record {
c: count;
s: string &optional;
};
Access to a record field uses the dollar sign (``$``) operator:
.. code:: bro
global r: MyRecordType;
r$c = 13;
Record assignment can be done field by field or as a whole like:
.. code:: bro
r = [$c = 13, $s = "thirteen"];
When assigning a whole record value, all fields that are not
:bro:attr:`&optional` or have a :bro:attr:`&default` attribute must
be specified.
To test for existence of field that is :bro:attr:`&optional`, use the
``?$`` operator:
.. code:: bro
if ( r?$s )
...
.. bro:type:: file
Bro supports writing to files, but not reading from them. For
example, declare, open, and write to a file and finally close it
like:
.. code:: bro
global f: file = open("myfile");
print f, "hello, world";
close(f);
Writing to files like this for logging usually isn't recommend, for better
logging support see :doc:`/logging`.
.. bro:type:: func
See :bro:type:`function`.
.. bro:type:: function .. bro:type:: function
Function types in Bro are declared using::
function( argument* ): type
where *argument* is a (possibly empty) comma-separated list of
arguments, and *type* is an optional return type. For example:
.. code:: bro
global greeting: function(name: string): string;
Here ``greeting`` is an identifier with a certain function type.
The function body is not defined yet and ``greeting`` could even
have different function body values at different times. To define
a function including a body value, the syntax is like:
.. code:: bro
function greeting(name: string): string
{
return "Hello, " + name;
}
Note that in the definition above, it's not necessary for us to have
done the first (forward) declaration of ``greeting`` as a function
type, but when it is, the argument list and return type much match
exactly.
Function types don't need to have a name and can be assigned anonymously:
.. code:: bro
greeting = function(name: string): string { return "Hi, " + name; };
And finally, the function can be called like:
.. code:: bro
print greeting("Dave");
.. bro:type:: event .. bro:type:: event
Event handlers are nearly identical in both syntax and semantics to
a :bro:type:`function`, with the two differences being that event
handlers have no return type since they never return a value, and
you cannot call an event handler. Instead of directly calling an
event handler from a script, event handler bodies are executed when
they are invoked by one of three different methods:
- From the event engine
When the event engine detects an event for which you have
defined a corresponding event handler, it queues an event for
that handler. The handler is invoked as soon as the event
engine finishes processing the current packet and flushing the
invocation of other event handlers that were queued first.
- With the ``event`` statement from a script
Immediately queuing invocation of an event handler occurs like:
.. code:: bro
event password_exposed(user, password);
This assumes that ``password_exposed`` was previously declared
as an event handler type with compatible arguments.
- Via the ``schedule`` expression in a script
This delays the invocation of event handlers until some time in
the future. For example:
.. code:: bro
schedule 5 secs { password_exposed(user, password) };
Multiple event handler bodies can be defined for the same event handler
identifier and the body of each will be executed in turn. Ordering
of execution can be influenced with :bro:attr:`&priority`.
Attributes Attributes
---------- ----------
The Bro scripting language supports the following built-in attributes. Attributes occur at the end of type/event declarations and change their
behavior. The syntax is ``&key`` or ``&key=val``, e.g., ``type T:
.. TODO: add documentation set[count] &read_expire=5min`` or ``event foo() &priority=-3``. The Bro
scripting language supports the following built-in attributes.
.. bro:attr:: &optional .. bro:attr:: &optional
Allows record field to be missing. For example the type ``record {
a: int, b: port &optional }`` could be instantiated both as
singleton ``[$a=127.0.0.1]`` or pair ``[$a=127.0.0.1, $b=80/tcp]``.
.. bro:attr:: &default .. bro:attr:: &default
Uses a default value for a record field or container elements. For
example, ``table[int] of string &default="foo" }`` would create
table that returns The :bro:type:`string` ``"foo"`` for any
non-existing index.
.. bro:attr:: &redef .. bro:attr:: &redef
Allows for redefinition of initial object values. This is typically
used with constants, for example, ``const clever = T &redef;`` would
allow the constant to be redifined at some later point during script
execution.
.. bro:attr:: &rotate_interval .. bro:attr:: &rotate_interval
Rotates a file after a specified interval.
.. bro:attr:: &rotate_size .. bro:attr:: &rotate_size
Rotates af file after it has reached a given size in bytes.
.. bro:attr:: &add_func .. bro:attr:: &add_func
.. TODO: needs to be documented.
.. bro:attr:: &delete_func .. bro:attr:: &delete_func
.. TODO: needs to be documented.
.. bro:attr:: &expire_func .. bro:attr:: &expire_func
Called right before a container element expires.
.. bro:attr:: &read_expire .. bro:attr:: &read_expire
Specifies a read expiration timeout for container elements. That is,
the element expires after the given amount of time since the last
time it has been read. Note that a write also counts as a read.
.. bro:attr:: &write_expire .. bro:attr:: &write_expire
Specifies a write expiration timeout for container elements. That
is, the element expires after the given amount of time since the
last time it has been written.
.. bro:attr:: &create_expire .. bro:attr:: &create_expire
Specifies a creation expiration timeout for container elements. That
is, the element expires after the given amount of time since it has
been inserted into the container, regardless of any reads or writes.
.. bro:attr:: &persistent .. bro:attr:: &persistent
Makes a variable persistent, i.e., its value is writen to disk (per
default at shutdown time).
.. bro:attr:: &synchronized .. bro:attr:: &synchronized
Synchronizes variable accesses across nodes. The value of a
``&synchronized`` variable is automatically propagated to all peers
when it changes.
.. bro:attr:: &postprocessor .. bro:attr:: &postprocessor
.. TODO: needs to be documented.
.. bro:attr:: &encrypt .. bro:attr:: &encrypt
Encrypts files right before writing them to disk.
.. TODO: needs to be documented in more detail.
.. bro:attr:: &match .. bro:attr:: &match
.. TODO: needs to be documented.
.. bro:attr:: &disable_print_hook .. bro:attr:: &disable_print_hook
Deprecated. Will be removed.
.. bro:attr:: &raw_output .. bro:attr:: &raw_output
Opens a file in raw mode, i.e., non-ASCII characters are not
escaped.
.. bro:attr:: &mergeable .. bro:attr:: &mergeable
Prefers set union to assignment for synchronized state. This
attribute is used in conjunction with :bro:attr:`&synchronized`
container types: when the same container is updated at two peers
with different value, the propagation of the state causes a race
condition, where the last update succeeds. This can cause
inconsistencies and can be avoided by unifying the two sets, rather
than merely overwriting the old value.
.. bro:attr:: &priority .. bro:attr:: &priority
Specifies the execution priority of an event handler. Higher values
are executed before lower ones. The default value is 0.
.. bro:attr:: &group .. bro:attr:: &group
Groups event handlers such that those in the same group can be
jointly activated or deactivated.
.. bro:attr:: &log .. bro:attr:: &log
Writes a record field to the associated log stream.
.. bro:attr:: (&tracked) .. bro:attr:: (&tracked)
.. TODO: needs documented or removed if it's not used anywhere.

View file

@ -34,7 +34,7 @@ Let's look at an example signature first:
This signature asks Bro to match the regular expression ``.*root`` on This signature asks Bro to match the regular expression ``.*root`` on
all TCP connections going to port 80. When the signature triggers, Bro all TCP connections going to port 80. When the signature triggers, Bro
will raise an event ``signature_match`` of the form: will raise an event :bro:id:`signature_match` of the form:
.. code:: bro .. code:: bro
@ -45,20 +45,20 @@ triggered the match, ``msg`` is the string specified by the
signature's event statement (``Found root!``), and data is the last signature's event statement (``Found root!``), and data is the last
piece of payload which triggered the pattern match. piece of payload which triggered the pattern match.
To turn such ``signature_match`` events into actual alarms, you can To turn such :bro:id:`signature_match` events into actual alarms, you can
load Bro's ``signature.bro`` script. This script contains a default load Bro's :doc:`/scripts/base/frameworks/signatures/main` script.
event handler that raises ``SensitiveSignature`` :doc:`Notices <notice>` This script contains a default event handler that raises
:bro:enum:`Signatures::Sensitive_Signature` :doc:`Notices <notice>`
(as well as others; see the beginning of the script). (as well as others; see the beginning of the script).
As signatures are independent of Bro's policy scripts, they are put As signatures are independent of Bro's policy scripts, they are put
into their own file(s). There are two ways to specify which files into their own file(s). There are two ways to specify which files
contain signatures: By using the ``-s`` flag when you invoke Bro, or contain signatures: By using the ``-s`` flag when you invoke Bro, or
by extending the Bro variable ``signatures_files`` using the ``+=`` by extending the Bro variable :bro:id:`signature_files` using the ``+=``
operator. If a signature file is given without a path, it is searched operator. If a signature file is given without a path, it is searched
along the normal ``BROPATH``. The default extension of the file name along the normal ``BROPATH``. The default extension of the file name
is ``.sig``, and Bro appends that automatically when neccesary. is ``.sig``, and Bro appends that automatically when neccesary.
Signature language Signature language
================== ==================
@ -90,7 +90,7 @@ one of ``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``; and
against. The following keywords are defined: against. The following keywords are defined:
``src-ip``/``dst-ip <cmp> <address-list>`` ``src-ip``/``dst-ip <cmp> <address-list>``
Source and destination address, repectively. Addresses can be Source and destination address, respectively. Addresses can be
given as IP addresses or CIDR masks. given as IP addresses or CIDR masks.
``src-port``/``dst-port`` ``<int-list>`` ``src-port``/``dst-port`` ``<int-list>``
@ -126,7 +126,7 @@ CIDR notation for netmasks and is translated into a corresponding
bitmask applied to the packet's value prior to the comparison (similar bitmask applied to the packet's value prior to the comparison (similar
to the optional ``& integer``). to the optional ``& integer``).
Putting all together, this is an example conditiation that is Putting all together, this is an example condition that is
equivalent to ``dst- ip == 1.2.3.4/16, 5.6.7.8/24``: equivalent to ``dst- ip == 1.2.3.4/16, 5.6.7.8/24``:
.. code:: bro-sig .. code:: bro-sig
@ -134,7 +134,7 @@ equivalent to ``dst- ip == 1.2.3.4/16, 5.6.7.8/24``:
header ip[16:4] == 1.2.3.4/16, 5.6.7.8/24 header ip[16:4] == 1.2.3.4/16, 5.6.7.8/24
Internally, the predefined header conditions are in fact just Internally, the predefined header conditions are in fact just
short-cuts and mappend into a generic condition. short-cuts and mapped into a generic condition.
Content Conditions Content Conditions
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
@ -265,7 +265,7 @@ Actions define what to do if a signature matches. Currently, there are
two actions defined: two actions defined:
``event <string>`` ``event <string>``
Raises a ``signature_match`` event. The event handler has the Raises a :bro:id:`signature_match` event. The event handler has the
following type: following type:
.. code:: bro .. code:: bro
@ -339,10 +339,10 @@ Things to keep in mind when writing signatures
respectively. Generally, Bro follows `flex's regular expression respectively. Generally, Bro follows `flex's regular expression
syntax syntax
<http://www.gnu.org/software/flex/manual/html_chapter/flex_7.html>`_. <http://www.gnu.org/software/flex/manual/html_chapter/flex_7.html>`_.
See the DPD signatures in ``policy/sigs/dpd.bro`` for some examples See the DPD signatures in ``base/frameworks/dpd/dpd.sig`` for some examples
of fairly complex payload patterns. of fairly complex payload patterns.
* The data argument of the ``signature_match`` handler might not carry * The data argument of the :bro:id:`signature_match` handler might not carry
the full text matched by the regular expression. Bro performs the the full text matched by the regular expression. Bro performs the
matching incrementally as packets come in; when the signature matching incrementally as packets come in; when the signature
eventually fires, it can only pass on the most recent chunk of data. eventually fires, it can only pass on the most recent chunk of data.

View file

@ -9,10 +9,10 @@ redef peer_description = Cluster::node;
# Add a cluster prefix. # Add a cluster prefix.
@prefixes += cluster @prefixes += cluster
## If this script isn't found anywhere, the cluster bombs out. # If this script isn't found anywhere, the cluster bombs out.
## Loading the cluster framework requires that a script by this name exists # Loading the cluster framework requires that a script by this name exists
## somewhere in the BROPATH. The only thing in the file should be the # somewhere in the BROPATH. The only thing in the file should be the
## cluster definition in the :bro:id:`Cluster::nodes` variable. # cluster definition in the :bro:id:`Cluster::nodes` variable.
@load cluster-layout @load cluster-layout
@if ( Cluster::node in Cluster::nodes ) @if ( Cluster::node in Cluster::nodes )

View file

@ -1,21 +1,45 @@
##! A framework for establishing and controlling a cluster of Bro instances.
##! In order to use the cluster framework, a script named
##! ``cluster-layout.bro`` must exist somewhere in Bro's script search path
##! which has a cluster definition of the :bro:id:`Cluster::nodes` variable.
##! The ``CLUSTER_NODE`` environment variable or :bro:id:`Cluster::node`
##! must also be sent and the cluster framework loaded as a package like
##! ``@load base/frameworks/cluster``.
@load base/frameworks/control @load base/frameworks/control
module Cluster; module Cluster;
export { export {
## The cluster logging stream identifier.
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
## The record type which contains the column fields of the cluster log.
type Info: record { type Info: record {
## The time at which a cluster message was generated.
ts: time; ts: time;
## A message indicating information about the cluster's operation.
message: string; message: string;
} &log; } &log;
## Types of nodes that are allowed to participate in the cluster
## configuration.
type NodeType: enum { type NodeType: enum {
## A dummy node type indicating the local node is not operating
## within a cluster.
NONE, NONE,
## A node type which is allowed to view/manipulate the configuration
## of other nodes in the cluster.
CONTROL, CONTROL,
## A node type responsible for log and policy management.
MANAGER, MANAGER,
## A node type for relaying worker node communication and synchronizing
## worker node state.
PROXY, PROXY,
## The node type doing all the actual traffic analysis.
WORKER, WORKER,
## A node acting as a traffic recorder using the
## `Time Machine <http://tracker.bro-ids.org/time-machine>`_ software.
TIME_MACHINE, TIME_MACHINE,
}; };
@ -49,30 +73,38 @@ export {
## Record type to indicate a node in a cluster. ## Record type to indicate a node in a cluster.
type Node: record { type Node: record {
## Identifies the type of cluster node in this node's configuration.
node_type: NodeType; node_type: NodeType;
## The IP address of the cluster node.
ip: addr; ip: addr;
## The port to which the this local node can connect when
## establishing communication.
p: port; p: port;
## Identifier for the interface a worker is sniffing. ## Identifier for the interface a worker is sniffing.
interface: string &optional; interface: string &optional;
## Name of the manager node this node uses. For workers and proxies.
## Manager node this node uses. For workers and proxies.
manager: string &optional; manager: string &optional;
## Proxy node this node uses. For workers and managers. ## Name of the proxy node this node uses. For workers and managers.
proxy: string &optional; proxy: string &optional;
## Worker nodes that this node connects with. For managers and proxies. ## Names of worker nodes that this node connects with.
## For managers and proxies.
workers: set[string] &optional; workers: set[string] &optional;
## Name of a time machine node with which this node connects.
time_machine: string &optional; time_machine: string &optional;
}; };
## This function can be called at any time to determine if the cluster ## This function can be called at any time to determine if the cluster
## framework is being enabled for this run. ## framework is being enabled for this run.
##
## Returns: True if :bro:id:`Cluster::node` has been set.
global is_enabled: function(): bool; global is_enabled: function(): bool;
## This function can be called at any time to determine what type of ## This function can be called at any time to determine what type of
## cluster node the current Bro instance is going to be acting as. ## cluster node the current Bro instance is going to be acting as.
## If :bro:id:`Cluster::is_enabled` returns false, then ## If :bro:id:`Cluster::is_enabled` returns false, then
## :bro:enum:`Cluster::NONE` is returned. ## :bro:enum:`Cluster::NONE` is returned.
##
## Returns: The :bro:type:`Cluster::NodeType` the calling node acts as.
global local_node_type: function(): NodeType; global local_node_type: function(): NodeType;
## This gives the value for the number of workers currently connected to, ## This gives the value for the number of workers currently connected to,

View file

@ -1,3 +1,7 @@
##! Redefines the options common to all proxy nodes within a Bro cluster.
##! In particular, proxies are not meant to produce logs locally and they
##! do not forward events anywhere, they mainly synchronize state between
##! worker nodes.
@prefixes += cluster-proxy @prefixes += cluster-proxy

View file

@ -1,3 +1,7 @@
##! Redefines some options common to all worker nodes within a Bro cluster.
##! In particular, worker nodes do not produce logs locally, instead they
##! send them off to a manager node for processing.
@prefixes += cluster-worker @prefixes += cluster-worker
## Don't do any local logging. ## Don't do any local logging.

View file

@ -1,3 +1,6 @@
##! This script establishes communication among all nodes in a cluster
##! as defined by :bro:id:`Cluster::nodes`.
@load ./main @load ./main
@load base/frameworks/communication @load base/frameworks/communication

View file

@ -1,11 +1,13 @@
##! Connect to remote Bro or Broccoli instances to share state and/or transfer ##! Facilitates connecting to remote Bro or Broccoli instances to share state
##! events. ##! and/or transfer events.
@load base/frameworks/packet-filter @load base/frameworks/packet-filter
module Communication; module Communication;
export { export {
## The communication logging stream identifier.
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
## Which interface to listen on (0.0.0.0 for any interface). ## Which interface to listen on (0.0.0.0 for any interface).
@ -21,14 +23,25 @@ export {
## compression. ## compression.
global compression_level = 0 &redef; global compression_level = 0 &redef;
## A record type containing the column fields of the communication log.
type Info: record { type Info: record {
## The network time at which a communication event occurred.
ts: time &log; ts: time &log;
## The peer name (if any) for which a communication event is concerned.
peer: string &log &optional; peer: string &log &optional;
## Where the communication event message originated from, that is,
## either from the scripting layer or inside the Bro process.
src_name: string &log &optional; src_name: string &log &optional;
## .. todo:: currently unused.
connected_peer_desc: string &log &optional; connected_peer_desc: string &log &optional;
## .. todo:: currently unused.
connected_peer_addr: addr &log &optional; connected_peer_addr: addr &log &optional;
## .. todo:: currently unused.
connected_peer_port: port &log &optional; connected_peer_port: port &log &optional;
## The severity of the communication event message.
level: string &log &optional; level: string &log &optional;
## A message describing the communication event between Bro or
## Broccoli instances.
message: string &log; message: string &log;
}; };
@ -77,7 +90,7 @@ export {
auth: bool &default = F; auth: bool &default = F;
## If not set, no capture filter is sent. ## If not set, no capture filter is sent.
## If set to "", the default cature filter is sent. ## If set to "", the default capture filter is sent.
capture_filter: string &optional; capture_filter: string &optional;
## Whether to use SSL-based communication. ## Whether to use SSL-based communication.
@ -97,10 +110,24 @@ export {
## to or respond to connections from. ## to or respond to connections from.
global nodes: table[string] of Node &redef; global nodes: table[string] of Node &redef;
## A table of peer nodes for which this node issued a
## :bro:id:`Communication::connect_peer` call but with which a connection
## has not yet been established or with which a connection has been
## closed and is currently in the process of retrying to establish.
## When a connection is successfully established, the peer is removed
## from the table.
global pending_peers: table[peer_id] of Node; global pending_peers: table[peer_id] of Node;
## A table of peer nodes for which this node has an established connection.
## Peers are automatically removed if their connection is closed and
## automatically added back if a connection is re-established later.
global connected_peers: table[peer_id] of Node; global connected_peers: table[peer_id] of Node;
## Connect to nodes[node], independent of its "connect" flag. ## Connect to a node in :bro:id:`Communication::nodes` independent
## of its "connect" flag.
##
## peer: the string used to index a particular node within the
## :bro:id:`Communication::nodes` table.
global connect_peer: function(peer: string); global connect_peer: function(peer: string);
} }

View file

@ -7,14 +7,16 @@ module DPD;
redef signature_files += "base/frameworks/dpd/dpd.sig"; redef signature_files += "base/frameworks/dpd/dpd.sig";
export { export {
## Add the DPD logging stream identifier.
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
## The record type defining the columns to log in the DPD logging stream.
type Info: record { type Info: record {
## Timestamp for when protocol analysis failed. ## Timestamp for when protocol analysis failed.
ts: time &log; ts: time &log;
## Connection unique ID. ## Connection unique ID.
uid: string &log; uid: string &log;
## Connection ID. ## Connection ID containing the 4-tuple which identifies endpoints.
id: conn_id &log; id: conn_id &log;
## Transport protocol for the violation. ## Transport protocol for the violation.
proto: transport_proto &log; proto: transport_proto &log;

View file

@ -1,16 +1,16 @@
##! The Bro logging interface. ##! The Bro logging interface.
##! ##!
##! See XXX for a introduction to Bro's logging framework. ##! See :doc:`/logging` for a introduction to Bro's logging framework.
module Log; module Log;
# Log::ID and Log::Writer are defined in bro.init due to circular dependencies. # Log::ID and Log::Writer are defined in types.bif due to circular dependencies.
export { export {
## If true, is local logging is by default enabled for all filters. ## If true, local logging is by default enabled for all filters.
const enable_local_logging = T &redef; const enable_local_logging = T &redef;
## If true, is remote logging is by default enabled for all filters. ## If true, remote logging is by default enabled for all filters.
const enable_remote_logging = T &redef; const enable_remote_logging = T &redef;
## Default writer to use if a filter does not specify ## Default writer to use if a filter does not specify
@ -23,21 +23,24 @@ export {
columns: any; columns: any;
## Event that will be raised once for each log entry. ## Event that will be raised once for each log entry.
## The event receives a single same parameter, an instance of type ``columns``. ## The event receives a single same parameter, an instance of type
## ``columns``.
ev: any &optional; ev: any &optional;
}; };
## Default function for building the path values for log filters if not ## Builds the default path values for log filters if not otherwise
## speficied otherwise by a filter. The default implementation uses ``id`` ## specified by a filter. The default implementation uses *id*
## to derive a name. ## to derive a name.
## ##
## id: The log stream. ## id: The ID associated with the log stream.
##
## path: A suggested path value, which may be either the filter's ## path: A suggested path value, which may be either the filter's
## ``path`` if defined, else a previous result from the function. ## ``path`` if defined, else a previous result from the function.
## If no ``path`` is defined for the filter, then the first call ## If no ``path`` is defined for the filter, then the first call
## to the function will contain an empty string. ## to the function will contain an empty string.
##
## rec: An instance of the streams's ``columns`` type with its ## rec: An instance of the streams's ``columns`` type with its
## fields set to the values to logged. ## fields set to the values to be logged.
## ##
## Returns: The path to be used for the filter. ## Returns: The path to be used for the filter.
global default_path_func: function(id: ID, path: string, rec: any) : string &redef; global default_path_func: function(id: ID, path: string, rec: any) : string &redef;
@ -46,7 +49,7 @@ export {
## Information passed into rotation callback functions. ## Information passed into rotation callback functions.
type RotationInfo: record { type RotationInfo: record {
writer: Writer; ##< Writer. writer: Writer; ##< The :bro:type:`Log::Writer` being used.
fname: string; ##< Full name of the rotated file. fname: string; ##< Full name of the rotated file.
path: string; ##< Original path value. path: string; ##< Original path value.
open: time; ##< Time when opened. open: time; ##< Time when opened.
@ -57,25 +60,26 @@ export {
## Default rotation interval. Zero disables rotation. ## Default rotation interval. Zero disables rotation.
const default_rotation_interval = 0secs &redef; const default_rotation_interval = 0secs &redef;
## Default naming format for timestamps embedded into filenames. Uses a strftime() style. ## Default naming format for timestamps embedded into filenames.
## Uses a ``strftime()`` style.
const default_rotation_date_format = "%Y-%m-%d-%H-%M-%S" &redef; const default_rotation_date_format = "%Y-%m-%d-%H-%M-%S" &redef;
## Default shell command to run on rotated files. Empty for none. ## Default shell command to run on rotated files. Empty for none.
const default_rotation_postprocessor_cmd = "" &redef; const default_rotation_postprocessor_cmd = "" &redef;
## Specifies the default postprocessor function per writer type. Entries in this ## Specifies the default postprocessor function per writer type.
## table are initialized by each writer type. ## Entries in this table are initialized by each writer type.
const default_rotation_postprocessors: table[Writer] of function(info: RotationInfo) : bool &redef; const default_rotation_postprocessors: table[Writer] of function(info: RotationInfo) : bool &redef;
## Filter customizing logging. ## A filter type describes how to customize logging streams.
type Filter: record { type Filter: record {
## Descriptive name to reference this filter. ## Descriptive name to reference this filter.
name: string; name: string;
## The writer to use. ## The logging writer implementation to use.
writer: Writer &default=default_writer; writer: Writer &default=default_writer;
## Predicate indicating whether a log entry should be recorded. ## Indicates whether a log entry should be recorded.
## If not given, all entries are recorded. ## If not given, all entries are recorded.
## ##
## rec: An instance of the streams's ``columns`` type with its ## rec: An instance of the streams's ``columns`` type with its
@ -101,13 +105,15 @@ export {
## easy to flood the disk by returning a new string for each ## easy to flood the disk by returning a new string for each
## connection ... ## connection ...
## ##
## id: The log stream. ## id: The ID associated with the log stream.
##
## path: A suggested path value, which may be either the filter's ## path: A suggested path value, which may be either the filter's
## ``path`` if defined, else a previous result from the function. ## ``path`` if defined, else a previous result from the function.
## If no ``path`` is defined for the filter, then the first call ## If no ``path`` is defined for the filter, then the first call
## to the function will contain an empty string. ## to the function will contain an empty string.
##
## rec: An instance of the streams's ``columns`` type with its ## rec: An instance of the streams's ``columns`` type with its
## fields set to the values to logged. ## fields set to the values to be logged.
## ##
## Returns: The path to be used for the filter. ## Returns: The path to be used for the filter.
path_func: function(id: ID, path: string, rec: any): string &optional; path_func: function(id: ID, path: string, rec: any): string &optional;
@ -129,27 +135,183 @@ export {
## Rotation interval. ## Rotation interval.
interv: interval &default=default_rotation_interval; interv: interval &default=default_rotation_interval;
## Callback function to trigger for rotated files. If not set, ## Callback function to trigger for rotated files. If not set, the
## the default comes out of default_rotation_postprocessors. ## default comes out of :bro:id:`Log::default_rotation_postprocessors`.
postprocessor: function(info: RotationInfo) : bool &optional; postprocessor: function(info: RotationInfo) : bool &optional;
}; };
## Sentinel value for indicating that a filter was not found when looked up. ## Sentinel value for indicating that a filter was not found when looked up.
const no_filter: Filter = [$name="<not found>"]; # Sentinel. const no_filter: Filter = [$name="<not found>"];
# TODO: Document. ## Creates a new logging stream with the default filter.
##
## id: The ID enum to be associated with the new logging stream.
##
## stream: A record defining the content that the new stream will log.
##
## Returns: True if a new logging stream was successfully created and
## a default filter added to it.
##
## .. bro:see:: Log::add_default_filter Log::remove_default_filter
global create_stream: function(id: ID, stream: Stream) : bool; global create_stream: function(id: ID, stream: Stream) : bool;
## Enables a previously disabled logging stream. Disabled streams
## will not be written to until they are enabled again. New streams
## are enabled by default.
##
## id: The ID associated with the logging stream to enable.
##
## Returns: True if the stream is re-enabled or was not previously disabled.
##
## .. bro:see:: Log::disable_stream
global enable_stream: function(id: ID) : bool; global enable_stream: function(id: ID) : bool;
## Disables a currently enabled logging stream. Disabled streams
## will not be written to until they are enabled again. New streams
## are enabled by default.
##
## id: The ID associated with the logging stream to disable.
##
## Returns: True if the stream is now disabled or was already disabled.
##
## .. bro:see:: Log::enable_stream
global disable_stream: function(id: ID) : bool; global disable_stream: function(id: ID) : bool;
## Adds a custom filter to an existing logging stream. If a filter
## with a matching ``name`` field already exists for the stream, it
## is removed when the new filter is successfully added.
##
## id: The ID associated with the logging stream to filter.
##
## filter: A record describing the desired logging parameters.
##
## Returns: True if the filter was sucessfully added, false if
## the filter was not added or the *filter* argument was not
## the correct type.
##
## .. bro:see:: Log::remove_filter Log::add_default_filter
## Log::remove_default_filter
global add_filter: function(id: ID, filter: Filter) : bool; global add_filter: function(id: ID, filter: Filter) : bool;
## Removes a filter from an existing logging stream.
##
## id: The ID associated with the logging stream from which to
## remove a filter.
##
## name: A string to match against the ``name`` field of a
## :bro:type:`Log::Filter` for identification purposes.
##
## Returns: True if the logging stream's filter was removed or
## if no filter associated with *name* was found.
##
## .. bro:see:: Log::remove_filter Log::add_default_filter
## Log::remove_default_filter
global remove_filter: function(id: ID, name: string) : bool; global remove_filter: function(id: ID, name: string) : bool;
global get_filter: function(id: ID, name: string) : Filter; # Returns no_filter if not found.
## Gets a filter associated with an existing logging stream.
##
## id: The ID associated with a logging stream from which to
## obtain one of its filters.
##
## name: A string to match against the ``name`` field of a
## :bro:type:`Log::Filter` for identification purposes.
##
## Returns: A filter attached to the logging stream *id* matching
## *name* or, if no matches are found returns the
## :bro:id:`Log::no_filter` sentinel value.
##
## .. bro:see:: Log::add_filter Log::remove_filter Log::add_default_filter
## Log::remove_default_filter
global get_filter: function(id: ID, name: string) : Filter;
## Writes a new log line/entry to a logging stream.
##
## id: The ID associated with a logging stream to be written to.
##
## columns: A record value describing the values of each field/column
## to write to the log stream.
##
## Returns: True if the stream was found and no error occurred in writing
## to it or if the stream was disabled and nothing was written.
## False if the stream was was not found, or the *columns*
## argument did not match what the stream was initially defined
## to handle, or one of the stream's filters has an invalid
## ``path_func``.
##
## .. bro:see: Log::enable_stream Log::disable_stream
global write: function(id: ID, columns: any) : bool; global write: function(id: ID, columns: any) : bool;
## Sets the buffering status for all the writers of a given logging stream.
## A given writer implementation may or may not support buffering and if it
## doesn't then toggling buffering with this function has no effect.
##
## id: The ID associated with a logging stream for which to
## enable/disable buffering.
##
## buffered: Whether to enable or disable log buffering.
##
## Returns: True if buffering status was set, false if the logging stream
## does not exist.
##
## .. bro:see:: Log::flush
global set_buf: function(id: ID, buffered: bool): bool; global set_buf: function(id: ID, buffered: bool): bool;
## Flushes any currently buffered output for all the writers of a given
## logging stream.
##
## id: The ID associated with a logging stream for which to flush buffered
## data.
##
## Returns: True if all writers of a log stream were signalled to flush
## buffered data or if the logging stream is disabled,
## false if the logging stream does not exist.
##
## .. bro:see:: Log::set_buf Log::enable_stream Log::disable_stream
global flush: function(id: ID): bool; global flush: function(id: ID): bool;
## Adds a default :bro:type:`Log::Filter` record with ``name`` field
## set as "default" to a given logging stream.
##
## id: The ID associated with a logging stream for which to add a default
## filter.
##
## Returns: The status of a call to :bro:id:`Log::add_filter` using a
## default :bro:type:`Log::Filter` argument with ``name`` field
## set to "default".
##
## .. bro:see:: Log::add_filter Log::remove_filter
## Log::remove_default_filter
global add_default_filter: function(id: ID) : bool; global add_default_filter: function(id: ID) : bool;
## Removes the :bro:type:`Log::Filter` with ``name`` field equal to
## "default".
##
## id: The ID associated with a logging stream from which to remove the
## default filter.
##
## Returns: The status of a call to :bro:id:`Log::remove_filter` using
## "default" as the argument.
##
## .. bro:see:: Log::add_filter Log::remove_filter Log::add_default_filter
global remove_default_filter: function(id: ID) : bool; global remove_default_filter: function(id: ID) : bool;
## Runs a command given by :bro:id:`Log::default_rotation_postprocessor_cmd`
## on a rotated file. Meant to be called from postprocessor functions
## that are added to :bro:id:`Log::default_rotation_postprocessors`.
##
## info: A record holding meta-information about the log being rotated.
##
## npath: The new path of the file (after already being rotated/processed
## by writer-specific postprocessor as defined in
## :bro:id:`Log::default_rotation_postprocessors`.
##
## Returns: True when :bro:id:`Log::default_rotation_postprocessor_cmd`
## is empty or the system command given by it has been invoked
## to postprocess a rotated log file.
##
## .. bro:see:: Log::default_rotation_date_format
## Log::default_rotation_postprocessor_cmd
## Log::default_rotation_postprocessors
global run_rotation_postprocessor_cmd: function(info: RotationInfo, npath: string) : bool; global run_rotation_postprocessor_cmd: function(info: RotationInfo, npath: string) : bool;
} }

View file

@ -1,29 +1,51 @@
##! This script defines a postprocessing function that can be applied ##! This script defines a postprocessing function that can be applied
##! to a logging filter in order to automatically SCP (secure copy) ##! to a logging filter in order to automatically SCP (secure copy)
##! a log stream (or a subset of it) to a remote host at configurable ##! a log stream (or a subset of it) to a remote host at configurable
##! rotation time intervals. ##! rotation time intervals. Generally, to use this functionality
##! you must handle the :bro:id:`bro_init` event and do the following
##! in your handler:
##!
##! 1) Create a new :bro:type:`Log::Filter` record that defines a name/path,
##! rotation interval, and set the ``postprocessor`` to
##! :bro:id:`Log::scp_postprocessor`.
##! 2) Add the filter to a logging stream using :bro:id:`Log::add_filter`.
##! 3) Add a table entry to :bro:id:`Log::scp_destinations` for the filter's
##! writer/path pair which defines a set of :bro:type:`Log::SCPDestination`
##! records.
module Log; module Log;
export { export {
## This postprocessor SCP's the rotated-log to all the remote hosts ## Secure-copies the rotated-log to all the remote hosts
## defined in :bro:id:`Log::scp_destinations` and then deletes ## defined in :bro:id:`Log::scp_destinations` and then deletes
## the local copy of the rotated-log. It's not active when ## the local copy of the rotated-log. It's not active when
## reading from trace files. ## reading from trace files.
##
## info: A record holding meta-information about the log file to be
## postprocessed.
##
## Returns: True if secure-copy system command was initiated or
## if no destination was configured for the log as described
## by *info*.
global scp_postprocessor: function(info: Log::RotationInfo): bool; global scp_postprocessor: function(info: Log::RotationInfo): bool;
## A container that describes the remote destination for the SCP command ## A container that describes the remote destination for the SCP command
## argument as ``user@host:path``. ## argument as ``user@host:path``.
type SCPDestination: record { type SCPDestination: record {
## The remote user to log in as. A trust mechanism should be
## pre-established.
user: string; user: string;
## The remote host to which to transfer logs.
host: string; host: string;
## The path/directory on the remote host to send logs.
path: string; path: string;
}; };
## A table indexed by a particular log writer and filter path, that yields ## A table indexed by a particular log writer and filter path, that yields
## a set remote destinations. The :bro:id:`Log::scp_postprocessor` ## a set remote destinations. The :bro:id:`Log::scp_postprocessor`
## function queries this table upon log rotation and performs a secure ## function queries this table upon log rotation and performs a secure
## copy of the rotated-log to each destination in the set. ## copy of the rotated-log to each destination in the set. This
## table can be modified at run-time.
global scp_destinations: table[Writer, string] of set[SCPDestination]; global scp_destinations: table[Writer, string] of set[SCPDestination];
} }

View file

@ -1,4 +1,5 @@
##! Interface for the ascii log writer. ##! Interface for the ASCII log writer. Redefinable options are available
##! to tweak the output format of ASCII logs.
module LogAscii; module LogAscii;
@ -7,7 +8,8 @@ export {
## into files. This is primarily for debugging purposes. ## into files. This is primarily for debugging purposes.
const output_to_stdout = F &redef; const output_to_stdout = F &redef;
## If true, include a header line with column names. ## If true, include a header line with column names and description
## of the other ASCII logging options that were used.
const include_header = T &redef; const include_header = T &redef;
## Prefix for the header line if included. ## Prefix for the header line if included.

View file

@ -1,3 +1,8 @@
##! Adds a new notice action type which can be used to email notices
##! to the administrators of a particular address space as set by
##! :bro:id:`Site::local_admins` if the notice contains a source
##! or destination address that lies within their space.
@load ../main @load ../main
@load base/utils/site @load base/utils/site

View file

@ -1,3 +1,5 @@
##! Allows configuration of a pager email address to which notices can be sent.
@load ../main @load ../main
module Notice; module Notice;

View file

@ -1,6 +1,6 @@
#! Notice extension that mails out a pretty-printed version of alarm.log ##! Notice extension that mails out a pretty-printed version of alarm.log
#! in regular intervals, formatted for better human readability. If activated, ##! in regular intervals, formatted for better human readability. If activated,
#! that replaces the default summary mail having the raw log output. ##! that replaces the default summary mail having the raw log output.
@load base/frameworks/cluster @load base/frameworks/cluster
@load ../main @load ../main
@ -16,7 +16,7 @@ export {
const mail_dest_pretty_printed = "" &redef; const mail_dest_pretty_printed = "" &redef;
## If an address from one of these networks is reported, we mark ## If an address from one of these networks is reported, we mark
## the entry with an addition quote symbol (i.e., ">"). Many MUAs ## the entry with an addition quote symbol (that is, ">"). Many MUAs
## then highlight such lines differently. ## then highlight such lines differently.
global flag_nets: set[subnet] &redef; global flag_nets: set[subnet] &redef;

View file

@ -1,4 +1,6 @@
##! Implements notice functionality across clusters. ##! Implements notice functionality across clusters. Worker nodes
##! will disable notice/alarm logging streams and forward notice
##! events to the manager node for logging/processing.
@load ./main @load ./main
@load base/frameworks/cluster @load base/frameworks/cluster
@ -7,10 +9,15 @@ module Notice;
export { export {
## This is the event used to transport notices on the cluster. ## This is the event used to transport notices on the cluster.
##
## n: The notice information to be sent to the cluster manager for
## further processing.
global cluster_notice: event(n: Notice::Info); global cluster_notice: event(n: Notice::Info);
} }
## Manager can communicate notice suppression to workers.
redef Cluster::manager2worker_events += /Notice::begin_suppression/; redef Cluster::manager2worker_events += /Notice::begin_suppression/;
## Workers needs need ability to forward notices to manager.
redef Cluster::worker2manager_events += /Notice::cluster_notice/; redef Cluster::worker2manager_events += /Notice::cluster_notice/;
@if ( Cluster::local_node_type() != Cluster::MANAGER ) @if ( Cluster::local_node_type() != Cluster::MANAGER )

View file

@ -2,8 +2,7 @@
##! are odd or potentially bad. Decisions of the meaning of various notices ##! are odd or potentially bad. Decisions of the meaning of various notices
##! need to be done per site because Bro does not ship with assumptions about ##! need to be done per site because Bro does not ship with assumptions about
##! what is bad activity for sites. More extensive documetation about using ##! what is bad activity for sites. More extensive documetation about using
##! the notice framework can be found in the documentation section of the ##! the notice framework can be found in :doc:`/notice`.
##! http://www.bro-ids.org/ website.
module Notice; module Notice;
@ -21,10 +20,10 @@ export {
## Scripts creating new notices need to redef this enum to add their own ## Scripts creating new notices need to redef this enum to add their own
## specific notice types which would then get used when they call the ## specific notice types which would then get used when they call the
## :bro:id:`NOTICE` function. The convention is to give a general category ## :bro:id:`NOTICE` function. The convention is to give a general category
## along with the specific notice separating words with underscores and using ## along with the specific notice separating words with underscores and
## leading capitals on each word except for abbreviations which are kept in ## using leading capitals on each word except for abbreviations which are
## all capitals. For example, SSH::Login is for heuristically guessed ## kept in all capitals. For example, SSH::Login is for heuristically
## successful SSH logins. ## guessed successful SSH logins.
type Type: enum { type Type: enum {
## Notice reporting a count of how often a notice occurred. ## Notice reporting a count of how often a notice occurred.
Tally, Tally,
@ -49,22 +48,33 @@ export {
}; };
## The notice framework is able to do automatic notice supression by ## The notice framework is able to do automatic notice supression by
## utilizing the $identifier field in :bro:type:`Info` records. ## utilizing the $identifier field in :bro:type:`Notice::Info` records.
## Set this to "0secs" to completely disable automated notice suppression. ## Set this to "0secs" to completely disable automated notice suppression.
const default_suppression_interval = 1hrs &redef; const default_suppression_interval = 1hrs &redef;
type Info: record { type Info: record {
## An absolute time indicating when the notice occurred, defaults
## to the current network time.
ts: time &log &optional; ts: time &log &optional;
## A connection UID which uniquely identifies the endpoints
## concerned with the notice.
uid: string &log &optional; uid: string &log &optional;
## A connection 4-tuple identifying the endpoints concerned with the
## notice.
id: conn_id &log &optional; id: conn_id &log &optional;
## These are shorthand ways of giving the uid and id to a notice. The ## A shorthand way of giving the uid and id to a notice. The
## reference to the actual connection will be deleted after applying ## reference to the actual connection will be deleted after applying
## the notice policy. ## the notice policy.
conn: connection &optional; conn: connection &optional;
## A shorthand way of giving the uid and id to a notice. The
## reference to the actual connection will be deleted after applying
## the notice policy.
iconn: icmp_conn &optional; iconn: icmp_conn &optional;
## The :bro:enum:`Notice::Type` of the notice. ## The type of the notice.
note: Type &log; note: Type &log;
## The human readable message for the notice. ## The human readable message for the notice.
msg: string &log &optional; msg: string &log &optional;
@ -141,8 +151,9 @@ export {
## This is the record that defines the items that make up the notice policy. ## This is the record that defines the items that make up the notice policy.
type PolicyItem: record { type PolicyItem: record {
## This is the exact positional order in which the :bro:type:`PolicyItem` ## This is the exact positional order in which the
## records are checked. This is set internally by the notice framework. ## :bro:type:`Notice::PolicyItem` records are checked.
## This is set internally by the notice framework.
position: count &log &optional; position: count &log &optional;
## Define the priority for this check. Items are checked in ordered ## Define the priority for this check. Items are checked in ordered
## from highest value (10) to lowest value (0). ## from highest value (10) to lowest value (0).
@ -163,8 +174,8 @@ export {
suppress_for: interval &log &optional; suppress_for: interval &log &optional;
}; };
## This is the where the :bro:id:`Notice::policy` is defined. All notice ## Defines a notice policy that is extensible on a per-site basis.
## processing is done through this variable. ## All notice processing is done through this variable.
const policy: set[PolicyItem] = { const policy: set[PolicyItem] = {
[$pred(n: Notice::Info) = { return (n$note in Notice::ignored_types); }, [$pred(n: Notice::Info) = { return (n$note in Notice::ignored_types); },
$halt=T, $priority = 9], $halt=T, $priority = 9],
@ -193,8 +204,9 @@ export {
## Local system sendmail program. ## Local system sendmail program.
const sendmail = "/usr/sbin/sendmail" &redef; const sendmail = "/usr/sbin/sendmail" &redef;
## Email address to send notices with the :bro:enum:`ACTION_EMAIL` action ## Email address to send notices with the :bro:enum:`Notice::ACTION_EMAIL`
## or to send bulk alarm logs on rotation with :bro:enum:`ACTION_ALARM`. ## action or to send bulk alarm logs on rotation with
## :bro:enum:`Notice::ACTION_ALARM`.
const mail_dest = "" &redef; const mail_dest = "" &redef;
## Address that emails will be from. ## Address that emails will be from.
@ -207,14 +219,20 @@ export {
## A log postprocessing function that implements emailing the contents ## A log postprocessing function that implements emailing the contents
## of a log upon rotation to any configured :bro:id:`Notice::mail_dest`. ## of a log upon rotation to any configured :bro:id:`Notice::mail_dest`.
## The rotated log is removed upon being sent. ## The rotated log is removed upon being sent.
##
## info: A record containing the rotated log file information.
##
## Returns: True.
global log_mailing_postprocessor: function(info: Log::RotationInfo): bool; global log_mailing_postprocessor: function(info: Log::RotationInfo): bool;
## This is the event that is called as the entry point to the ## This is the event that is called as the entry point to the
## notice framework by the global :bro:id:`NOTICE` function. By the time ## notice framework by the global :bro:id:`NOTICE` function. By the time
## this event is generated, default values have already been filled out in ## this event is generated, default values have already been filled out in
## the :bro:type:`Notice::Info` record and synchronous functions in the ## the :bro:type:`Notice::Info` record and synchronous functions in the
## :bro:id:`Notice:sync_functions` have already been called. The notice ## :bro:id:`Notice::sync_functions` have already been called. The notice
## policy has also been applied. ## policy has also been applied.
##
## n: The record containing notice data.
global notice: event(n: Info); global notice: event(n: Info);
## This is a set of functions that provide a synchronous way for scripts ## This is a set of functions that provide a synchronous way for scripts
@ -231,30 +249,55 @@ export {
const sync_functions: set[function(n: Notice::Info)] = set() &redef; const sync_functions: set[function(n: Notice::Info)] = set() &redef;
## This event is generated when a notice begins to be suppressed. ## This event is generated when a notice begins to be suppressed.
##
## n: The record containing notice data regarding the notice type
## about to be suppressed.
global begin_suppression: event(n: Notice::Info); global begin_suppression: event(n: Notice::Info);
## This event is generated on each occurence of an event being suppressed. ## This event is generated on each occurence of an event being suppressed.
##
## n: The record containing notice data regarding the notice type
## being suppressed.
global suppressed: event(n: Notice::Info); global suppressed: event(n: Notice::Info);
## This event is generated when a notice stops being suppressed. ## This event is generated when a notice stops being suppressed.
##
## n: The record containing notice data regarding the notice type
## that was being suppressed.
global end_suppression: event(n: Notice::Info); global end_suppression: event(n: Notice::Info);
## Call this function to send a notice in an email. It is already used ## Call this function to send a notice in an email. It is already used
## by default with the built in :bro:enum:`ACTION_EMAIL` and ## by default with the built in :bro:enum:`Notice::ACTION_EMAIL` and
## :bro:enum:`ACTION_PAGE` actions. ## :bro:enum:`Notice::ACTION_PAGE` actions.
##
## n: The record of notice data to email.
##
## dest: The intended recipient of the notice email.
##
## extend: Whether to extend the email using the ``email_body_sections``
## field of *n*.
global email_notice_to: function(n: Info, dest: string, extend: bool); global email_notice_to: function(n: Info, dest: string, extend: bool);
## Constructs mail headers to which an email body can be appended for ## Constructs mail headers to which an email body can be appended for
## sending with sendmail. ## sending with sendmail.
##
## subject_desc: a subject string to use for the mail ## subject_desc: a subject string to use for the mail
##
## dest: recipient string to use for the mail ## dest: recipient string to use for the mail
##
## Returns: a string of mail headers to which an email body can be appended ## Returns: a string of mail headers to which an email body can be appended
global email_headers: function(subject_desc: string, dest: string): string; global email_headers: function(subject_desc: string, dest: string): string;
## This event can be handled to access the :bro:type:`Info` ## This event can be handled to access the :bro:type:`Notice::Info`
## record as it is sent on to the logging framework. ## record as it is sent on to the logging framework.
##
## rec: The record containing notice data before it is logged.
global log_notice: event(rec: Info); global log_notice: event(rec: Info);
## This is an internal wrapper for the global NOTICE function. Please ## This is an internal wrapper for the global :bro:id:`NOTICE` function;
## disregard. ## disregard.
##
## n: The record of notice data.
global internal_NOTICE: function(n: Notice::Info); global internal_NOTICE: function(n: Notice::Info);
} }
@ -410,7 +453,8 @@ event notice(n: Notice::Info) &priority=-5
} }
## This determines if a notice is being suppressed. It is only used ## This determines if a notice is being suppressed. It is only used
## internally as part of the mechanics for the global NOTICE function. ## internally as part of the mechanics for the global :bro:id:`NOTICE`
## function.
function is_being_suppressed(n: Notice::Info): bool function is_being_suppressed(n: Notice::Info): bool
{ {
if ( n?$identifier && [n$note, n$identifier] in suppressing ) if ( n?$identifier && [n$note, n$identifier] in suppressing )

View file

@ -1,3 +1,12 @@
##! This script provides a default set of actions to take for "weird activity"
##! events generated from Bro's event engine. Weird activity is defined as
##! unusual or exceptional activity that can indicate malformed connections,
##! traffic that doesn't conform to a particular protocol, malfunctioning
##! or misconfigured hardware, or even an attacker attempting to avoid/confuse
##! a sensor. Without context, it's hard to judge whether a particular
##! category of weird activity is interesting, but this script provides
##! a starting point for the user.
@load base/utils/conn-ids @load base/utils/conn-ids
@load base/utils/site @load base/utils/site
@load ./main @load ./main
@ -5,6 +14,7 @@
module Weird; module Weird;
export { export {
## The weird logging stream identifier.
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
redef enum Notice::Type += { redef enum Notice::Type += {
@ -12,6 +22,7 @@ export {
Activity, Activity,
}; };
## The record type which contains the column fields of the weird log.
type Info: record { type Info: record {
## The time when the weird occurred. ## The time when the weird occurred.
ts: time &log; ts: time &log;
@ -32,19 +43,32 @@ export {
peer: string &log &optional; peer: string &log &optional;
}; };
## Types of actions that may be taken when handling weird activity events.
type Action: enum { type Action: enum {
## A dummy action indicating the user does not care what internal
## decision is made regarding a given type of weird.
ACTION_UNSPECIFIED, ACTION_UNSPECIFIED,
## No action is to be taken.
ACTION_IGNORE, ACTION_IGNORE,
## Log the weird event every time it occurs.
ACTION_LOG, ACTION_LOG,
## Log the weird event only once.
ACTION_LOG_ONCE, ACTION_LOG_ONCE,
## Log the weird event once per connection.
ACTION_LOG_PER_CONN, ACTION_LOG_PER_CONN,
## Log the weird event once per originator host.
ACTION_LOG_PER_ORIG, ACTION_LOG_PER_ORIG,
## Always generate a notice associated with the weird event.
ACTION_NOTICE, ACTION_NOTICE,
## Generate a notice associated with the weird event only once.
ACTION_NOTICE_ONCE, ACTION_NOTICE_ONCE,
## Generate a notice for the weird event once per connection.
ACTION_NOTICE_PER_CONN, ACTION_NOTICE_PER_CONN,
## Generate a notice for the weird event once per originator host.
ACTION_NOTICE_PER_ORIG, ACTION_NOTICE_PER_ORIG,
}; };
## A table specifying default/recommended actions per weird type.
const actions: table[string] of Action = { const actions: table[string] of Action = {
["unsolicited_SYN_response"] = ACTION_IGNORE, ["unsolicited_SYN_response"] = ACTION_IGNORE,
["above_hole_data_without_any_acks"] = ACTION_LOG, ["above_hole_data_without_any_acks"] = ACTION_LOG,
@ -201,7 +225,7 @@ export {
["fragment_overlap"] = ACTION_LOG_PER_ORIG, ["fragment_overlap"] = ACTION_LOG_PER_ORIG,
["fragment_protocol_inconsistency"] = ACTION_LOG, ["fragment_protocol_inconsistency"] = ACTION_LOG,
["fragment_size_inconsistency"] = ACTION_LOG_PER_ORIG, ["fragment_size_inconsistency"] = ACTION_LOG_PER_ORIG,
## These do indeed happen! # These do indeed happen!
["fragment_with_DF"] = ACTION_LOG, ["fragment_with_DF"] = ACTION_LOG,
["incompletely_captured_fragment"] = ACTION_LOG, ["incompletely_captured_fragment"] = ACTION_LOG,
["bad_IP_checksum"] = ACTION_LOG_PER_ORIG, ["bad_IP_checksum"] = ACTION_LOG_PER_ORIG,
@ -215,8 +239,8 @@ export {
## and weird name into this set. ## and weird name into this set.
const ignore_hosts: set[addr, string] &redef; const ignore_hosts: set[addr, string] &redef;
# But don't ignore these (for the weird file), it's handy keeping ## Don't ignore repeats for weirds in this set. For example,
# track of clustered checksum errors. ## it's handy keeping track of clustered checksum errors.
const weird_do_not_ignore_repeats = { const weird_do_not_ignore_repeats = {
"bad_IP_checksum", "bad_TCP_checksum", "bad_UDP_checksum", "bad_IP_checksum", "bad_TCP_checksum", "bad_UDP_checksum",
"bad_ICMP_checksum", "bad_ICMP_checksum",
@ -237,6 +261,10 @@ export {
## duplicate notices from being raised. ## duplicate notices from being raised.
global did_notice: set[string, string] &create_expire=1day &redef; global did_notice: set[string, string] &create_expire=1day &redef;
## Handlers of this event are invoked one per write to the weird
## logging stream before the data is actually written.
##
## rec: The weird columns about to be logged to the weird stream.
global log_weird: event(rec: Info); global log_weird: event(rec: Info);
} }

View file

@ -9,17 +9,22 @@
module PacketFilter; module PacketFilter;
export { export {
## Add the packet filter logging stream.
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
## Add notice types related to packet filter errors.
redef enum Notice::Type += { redef enum Notice::Type += {
## This notice is generated if a packet filter is unable to be compiled. ## This notice is generated if a packet filter is unable to be compiled.
Compile_Failure, Compile_Failure,
## This notice is generated if a packet filter is unable to be installed. ## This notice is generated if a packet filter is fails to install.
Install_Failure, Install_Failure,
}; };
## The record type defining columns to be logged in the packet filter
## logging stream.
type Info: record { type Info: record {
## The time at which the packet filter installation attempt was made.
ts: time &log; ts: time &log;
## This is a string representation of the node that applied this ## This is a string representation of the node that applied this
@ -40,7 +45,7 @@ export {
## By default, Bro will examine all packets. If this is set to false, ## By default, Bro will examine all packets. If this is set to false,
## it will dynamically build a BPF filter that only select protocols ## it will dynamically build a BPF filter that only select protocols
## for which the user has loaded a corresponding analysis script. ## for which the user has loaded a corresponding analysis script.
## The latter used to be default for Bro versions < 1.6. That has now ## The latter used to be default for Bro versions < 2.0. That has now
## changed however to enable port-independent protocol analysis. ## changed however to enable port-independent protocol analysis.
const all_packets = T &redef; const all_packets = T &redef;

View file

@ -1,4 +1,6 @@
##! This script reports on packet loss from the various packet sources. ##! This script reports on packet loss from the various packet sources.
##! When Bro is reading input from trace files, this script will not
##! report any packet loss statistics.
@load base/frameworks/notice @load base/frameworks/notice
@ -6,7 +8,7 @@ module PacketFilter;
export { export {
redef enum Notice::Type += { redef enum Notice::Type += {
## Bro reported packets dropped by the packet filter. ## Indicates packets were dropped by the packet filter.
Dropped_Packets, Dropped_Packets,
}; };

View file

@ -1,21 +1,36 @@
##! This framework is intended to create an output and filtering path for ##! This framework is intended to create an output and filtering path for
##! internal messages/warnings/errors. It should typically be loaded to ##! internal messages/warnings/errors. It should typically be loaded to
##! avoid Bro spewing internal messages to standard error. ##! avoid Bro spewing internal messages to standard error and instead log
##! them to a file in a standard way. Note that this framework deals with
##! the handling of internally-generated reporter messages, for the
##! interface into actually creating reporter messages from the scripting
##! layer, use the built-in functions in :doc:`/scripts/base/reporter.bif`.
module Reporter; module Reporter;
export { export {
## The reporter logging stream identifier.
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
## An indicator of reporter message severity.
type Level: enum { type Level: enum {
## Informational, not needing specific attention.
INFO, INFO,
## Warning of a potential problem.
WARNING, WARNING,
## A non-fatal error that should be addressed, but doesn't
## terminate program execution.
ERROR ERROR
}; };
## The record type which contains the column fields of the reporter log.
type Info: record { type Info: record {
## The network time at which the reporter event was generated.
ts: time &log; ts: time &log;
## The severity of the reporter message.
level: Level &log; level: Level &log;
## An info/warning/error message that could have either been
## generated from the internal Bro core or at the scripting-layer.
message: string &log; message: string &log;
## This is the location in a Bro script where the message originated. ## This is the location in a Bro script where the message originated.
## Not all reporter messages will have locations in them though. ## Not all reporter messages will have locations in them though.

View file

@ -1,30 +1,36 @@
##! Script level signature support. ##! Script level signature support. See the
##! :doc:`signature documentation </signatures>` for more information about
##! Bro's signature engine.
@load base/frameworks/notice @load base/frameworks/notice
module Signatures; module Signatures;
export { export {
## Add various signature-related notice types.
redef enum Notice::Type += { redef enum Notice::Type += {
## Generic for alarm-worthy ## Generic notice type for notice-worthy signature matches.
Sensitive_Signature, Sensitive_Signature,
## Host has triggered many signatures on the same host. The number of ## Host has triggered many signatures on the same host. The number of
## signatures is defined by the :bro:id:`vert_scan_thresholds` variable. ## signatures is defined by the
## :bro:id:`Signatures::vert_scan_thresholds` variable.
Multiple_Signatures, Multiple_Signatures,
## Host has triggered the same signature on multiple hosts as defined by the ## Host has triggered the same signature on multiple hosts as defined
## :bro:id:`horiz_scan_thresholds` variable. ## by the :bro:id:`Signatures::horiz_scan_thresholds` variable.
Multiple_Sig_Responders, Multiple_Sig_Responders,
## The same signature has triggered multiple times for a host. The number ## The same signature has triggered multiple times for a host. The
## of times the signature has be trigger is defined by the ## number of times the signature has been triggered is defined by the
## :bro:id:`count_thresholds` variable. To generate this notice, the ## :bro:id:`Signatures::count_thresholds` variable. To generate this
## :bro:enum:`SIG_COUNT_PER_RESP` action must be set for the signature. ## notice, the :bro:enum:`Signatures::SIG_COUNT_PER_RESP` action must
## bet set for the signature.
Count_Signature, Count_Signature,
## Summarize the number of times a host triggered a signature. The ## Summarize the number of times a host triggered a signature. The
## interval between summaries is defined by the :bro:id:`summary_interval` ## interval between summaries is defined by the
## variable. ## :bro:id:`Signatures::summary_interval` variable.
Signature_Summary, Signature_Summary,
}; };
## The signature logging stream identifier.
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
## These are the default actions you can apply to signature matches. ## These are the default actions you can apply to signature matches.
@ -39,8 +45,8 @@ export {
SIG_QUIET, SIG_QUIET,
## Generate a notice. ## Generate a notice.
SIG_LOG, SIG_LOG,
## The same as :bro:enum:`SIG_FILE`, but ignore for aggregate/scan ## The same as :bro:enum:`Signatures::SIG_LOG`, but ignore for
## processing. ## aggregate/scan processing.
SIG_FILE_BUT_NO_SCAN, SIG_FILE_BUT_NO_SCAN,
## Generate a notice and set it to be alarmed upon. ## Generate a notice and set it to be alarmed upon.
SIG_ALARM, SIG_ALARM,
@ -49,22 +55,33 @@ export {
## Alarm once and then never again. ## Alarm once and then never again.
SIG_ALARM_ONCE, SIG_ALARM_ONCE,
## Count signatures per responder host and alarm with the ## Count signatures per responder host and alarm with the
## :bro:enum:`Count_Signature` notice if a threshold defined by ## :bro:enum:`Signatures::Count_Signature` notice if a threshold
## :bro:id:`count_thresholds` is reached. ## defined by :bro:id:`Signatures::count_thresholds` is reached.
SIG_COUNT_PER_RESP, SIG_COUNT_PER_RESP,
## Don't alarm, but generate per-orig summary. ## Don't alarm, but generate per-orig summary.
SIG_SUMMARY, SIG_SUMMARY,
}; };
## The record type which contains the column fields of the signature log.
type Info: record { type Info: record {
## The network time at which a signature matching type of event to
## be logged has occurred.
ts: time &log; ts: time &log;
## The host which triggered the signature match event.
src_addr: addr &log &optional; src_addr: addr &log &optional;
## The host port on which the signature-matching activity occurred.
src_port: port &log &optional; src_port: port &log &optional;
## The destination host which was sent the payload that triggered the
## signature match.
dst_addr: addr &log &optional; dst_addr: addr &log &optional;
## The destination host port which was sent the payload that triggered
## the signature match.
dst_port: port &log &optional; dst_port: port &log &optional;
## Notice associated with signature event ## Notice associated with signature event
note: Notice::Type &log; note: Notice::Type &log;
## The name of the signature that matched.
sig_id: string &log &optional; sig_id: string &log &optional;
## A more descriptive message of the signature-matching event.
event_msg: string &log &optional; event_msg: string &log &optional;
## Extracted payload data or extra message. ## Extracted payload data or extra message.
sub_msg: string &log &optional; sub_msg: string &log &optional;
@ -82,22 +99,26 @@ export {
## Signature IDs that should always be ignored. ## Signature IDs that should always be ignored.
const ignored_ids = /NO_DEFAULT_MATCHES/ &redef; const ignored_ids = /NO_DEFAULT_MATCHES/ &redef;
## Alarm if, for a pair [orig, signature], the number of different ## Generate a notice if, for a pair [orig, signature], the number of
## responders has reached one of the thresholds. ## different responders has reached one of the thresholds.
const horiz_scan_thresholds = { 5, 10, 50, 100, 500, 1000 } &redef; const horiz_scan_thresholds = { 5, 10, 50, 100, 500, 1000 } &redef;
## Alarm if, for a pair [orig, resp], the number of different signature ## Generate a notice if, for a pair [orig, resp], the number of different
## matches has reached one of the thresholds. ## signature matches has reached one of the thresholds.
const vert_scan_thresholds = { 5, 10, 50, 100, 500, 1000 } &redef; const vert_scan_thresholds = { 5, 10, 50, 100, 500, 1000 } &redef;
## Alarm if a :bro:enum:`SIG_COUNT_PER_RESP` signature is triggered as ## Generate a notice if a :bro:enum:`Signatures::SIG_COUNT_PER_RESP`
## often as given by one of these thresholds. ## signature is triggered as often as given by one of these thresholds.
const count_thresholds = { 5, 10, 50, 100, 500, 1000, 10000, 1000000, } &redef; const count_thresholds = { 5, 10, 50, 100, 500, 1000, 10000, 1000000, } &redef;
## The interval between when :bro:id:`Signature_Summary` notices are ## The interval between when :bro:enum:`Signatures::Signature_Summary`
## generated. ## notice are generated.
const summary_interval = 1 day &redef; const summary_interval = 1 day &redef;
## This event can be handled to access/alter data about to be logged
## to the signature logging stream.
##
## rec: The record of signature data about to be logged.
global log_signature: event(rec: Info); global log_signature: event(rec: Info);
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
# Internal functions and types used by the logging framework. ##! Internal functions and types used by the logging framework.
module Log; module Log;

View file

@ -1,3 +1,11 @@
##! The reporter built-in functions allow for the scripting layer to
##! generate messages of varying severity. If no event handlers
##! exist for reporter messages, the messages are output to stderr.
##! If event handlers do exist, it's assumed they take care of determining
##! how/where to output the messages.
##!
##! See :doc:`/scripts/base/frameworks/reporter/main` for a convenient
##! reporter message logging framework.
module Reporter; module Reporter;
@ -5,6 +13,13 @@ module Reporter;
#include "NetVar.h" #include "NetVar.h"
%%} %%}
## Generates an informational message.
##
## msg: The informational message to report.
##
## Returns: Always true.
##
## .. bro:see:: reporter_info
function Reporter::info%(msg: string%): bool function Reporter::info%(msg: string%): bool
%{ %{
reporter->PushLocation(frame->GetCall()->GetLocationInfo()); reporter->PushLocation(frame->GetCall()->GetLocationInfo());
@ -13,6 +28,13 @@ function Reporter::info%(msg: string%): bool
return new Val(1, TYPE_BOOL); return new Val(1, TYPE_BOOL);
%} %}
## Generates a message that warns of a potential problem.
##
## msg: The warning message to report.
##
## Returns: Always true.
##
## .. bro:see:: reporter_warning
function Reporter::warning%(msg: string%): bool function Reporter::warning%(msg: string%): bool
%{ %{
reporter->PushLocation(frame->GetCall()->GetLocationInfo()); reporter->PushLocation(frame->GetCall()->GetLocationInfo());
@ -21,6 +43,14 @@ function Reporter::warning%(msg: string%): bool
return new Val(1, TYPE_BOOL); return new Val(1, TYPE_BOOL);
%} %}
## Generates a non-fatal error indicative of a definite problem that should
## be addressed. Program execution does not terminate.
##
## msg: The error message to report.
##
## Returns: Always true.
##
## .. bro:see:: reporter_error
function Reporter::error%(msg: string%): bool function Reporter::error%(msg: string%): bool
%{ %{
reporter->PushLocation(frame->GetCall()->GetLocationInfo()); reporter->PushLocation(frame->GetCall()->GetLocationInfo());
@ -29,6 +59,11 @@ function Reporter::error%(msg: string%): bool
return new Val(1, TYPE_BOOL); return new Val(1, TYPE_BOOL);
%} %}
## Generates a fatal error on stderr and terminates program execution.
##
## msg: The error message to report.
##
## Returns: Always true.
function Reporter::fatal%(msg: string%): bool function Reporter::fatal%(msg: string%): bool
%{ %{
reporter->PushLocation(frame->GetCall()->GetLocationInfo()); reporter->PushLocation(frame->GetCall()->GetLocationInfo());

View file

@ -10,6 +10,14 @@ using namespace std;
%%} %%}
## Concates all arguments into a single string. The function takes a variable
## number of arguments of type string and stiches them together.
##
## Returns: The concatenation of all (string) arguments.
##
## .. bro:see:: cat cat_sep cat_string_array cat_string_array_n
## fmt
## join_string_vec join_string_array
function string_cat%(...%): string function string_cat%(...%): string
%{ %{
int n = 0; int n = 0;
@ -73,18 +81,53 @@ BroString* cat_string_array_n(TableVal* tbl, int start, int end)
} }
%%} %%}
## Concatenates all elements in an array of strings.
##
## a: The :bro:id:`string_array` (``table[count] of string``).
##
## Returns: The concatenation of all elements in *a*.
##
## .. bro:see:: cat cat_sep string_cat cat_string_array_n
## fmt
## join_string_vec join_string_array
function cat_string_array%(a: string_array%): string function cat_string_array%(a: string_array%): string
%{ %{
TableVal* tbl = a->AsTableVal(); TableVal* tbl = a->AsTableVal();
return new StringVal(cat_string_array_n(tbl, 1, a->AsTable()->Length())); return new StringVal(cat_string_array_n(tbl, 1, a->AsTable()->Length()));
%} %}
## Concatenates a specific range of elements in an array of strings.
##
## a: The :bro:id:`string_array` (``table[count] of string``).
##
## start: The array index of the first element of the range.
##
## end: The array index of the last element of the range.
##
## Returns: The concatenation of the range *[start, end]* in *a*.
##
## .. bro:see:: cat string_cat cat_string_array
## fmt
## join_string_vec join_string_array
function cat_string_array_n%(a: string_array, start: count, end: count%): string function cat_string_array_n%(a: string_array, start: count, end: count%): string
%{ %{
TableVal* tbl = a->AsTableVal(); TableVal* tbl = a->AsTableVal();
return new StringVal(cat_string_array_n(tbl, start, end)); return new StringVal(cat_string_array_n(tbl, start, end));
%} %}
## Joins all values in the given array of strings with a separator placed
## between each element.
##
## sep: The separator to place between each element.
##
## a: The :bro:id:`string_array` (``table[count] of string``).
##
## Returns: The concatenation of all elements in *a*, with *sep* placed
## between each element.
##
## .. bro:see:: cat cat_sep string_cat cat_string_array cat_string_array_n
## fmt
## join_string_vec
function join_string_array%(sep: string, a: string_array%): string function join_string_array%(sep: string, a: string_array%): string
%{ %{
vector<const BroString*> vs; vector<const BroString*> vs;
@ -108,6 +151,45 @@ function join_string_array%(sep: string, a: string_array%): string
return new StringVal(concatenate(vs)); return new StringVal(concatenate(vs));
%} %}
## Joins all values in the given vector of strings with a separator placed
## between each element.
##
## sep: The separator to place between each element.
##
## a: The :bro:id:`string_vec` (``vector of string``).
##
## Returns: The concatenation of all elements in *a*, with *sep* placed
## between each element.
##
## .. bro:see:: cat cat_sep string_cat cat_string_array cat_string_array_n
## fmt
## join_string_array
function join_string_vec%(vec: string_vec, sep: string%): string
%{
ODesc d;
VectorVal *v = vec->AsVectorVal();
for ( unsigned i = 0; i < v->Size(); ++i )
{
if ( i > 0 )
d.Add(sep->CheckString(), 0);
v->Lookup(i+1)->Describe(&d);
}
BroString* s = new BroString(1, d.TakeBytes(), d.Len());
s->SetUseFreeToDelete(true);
return new StringVal(s);
%}
## Sorts an array of strings.
##
## a: The :bro:id:`string_array` (``table[count] of string``).
##
## Returns: A sorted copy of *a*.
##
## .. bro:see:: sort
function sort_string_array%(a: string_array%): string_array function sort_string_array%(a: string_array%): string_array
%{ %{
TableVal* tbl = a->AsTableVal(); TableVal* tbl = a->AsTableVal();
@ -134,26 +216,25 @@ function sort_string_array%(a: string_array%): string_array
return b; return b;
%} %}
function join_string_vec%(vec: string_vec, sep: string%): string
%{
ODesc d;
VectorVal *v = vec->AsVectorVal();
for ( unsigned i = 0; i < v->Size(); ++i )
{
if ( i > 0 )
d.Add(sep->CheckString(), 0);
v->Lookup(i+1)->Describe(&d);
}
BroString* s = new BroString(1, d.TakeBytes(), d.Len());
s->SetUseFreeToDelete(true);
return new StringVal(s);
%}
## Returns an edited version of a string that applies a special
## "backspace character" (usually ``\x08`` for backspace or ``\x7f`` for DEL).
## For ## example, ``edit("hello there", "e")`` returns ``"llo t"``.
##
## arg_s: The string to edit.
##
## arg_edit_char: A string of exactly one character that represents the
## "backspace character". If it is longer than one character Bro
## generates a run-time error and uses the first character in
## the string.
##
## Returns: An edited version of *arg_s* where *arg_edit_char* triggers the
## deletetion of the last character.
##
## .. bro:see:: clean
## to_string_literal
## escape_string
## strip
function edit%(arg_s: string, arg_edit_char: string%): string function edit%(arg_s: string, arg_edit_char: string%): string
%{ %{
if ( arg_edit_char->Len() != 1 ) if ( arg_edit_char->Len() != 1 )
@ -184,11 +265,28 @@ function edit%(arg_s: string, arg_edit_char: string%): string
return new StringVal(new BroString(1, byte_vec(new_s), ind)); return new StringVal(new BroString(1, byte_vec(new_s), ind));
%} %}
## Returns the number of characters (bytes) in the given string. The
## length computation includes any embedded NULs, and also a trailing NUL,
## if any (which is why the function isn't called ``strlen``; to remind
## the user that Bro strings can include NULs).
##
## s: The string to compute the length for.
##
## Returns: The number of characters in *s*.
function byte_len%(s: string%): count function byte_len%(s: string%): count
%{ %{
return new Val(s->Len(), TYPE_COUNT); return new Val(s->Len(), TYPE_COUNT);
%} %}
## Get a substring of from a string, given a starting position length.
##
## s: The string to obtain a substring from.
##
## start: The starting position of the substring in *s*
##
## n: The number of characters to extract, beginning at *start*.
##
## Returns: A substring of *s* of length *n* from position *start*.
function sub_bytes%(s: string, start: count, n: int%): string function sub_bytes%(s: string, start: count, n: int%): string
%{ %{
if ( start > 0 ) if ( start > 0 )
@ -368,42 +466,94 @@ Val* do_sub(StringVal* str_val, RE_Matcher* re, StringVal* repl, int do_all)
} }
%%} %%}
# Similar to split in awk. ## Splits a string into an array of strings according to a pattern.
##
## str: The string to split.
##
## re: The pattern describing the element separator in *str*.
##
## Returns: An array of strings where each element corresponds to a substring
## in *str* separated by *re*.
##
## .. bro:see:: split1 split_all split_n str_split
##
## .. note:: The returned table starts at index 1. Note that conceptually the
## return value is meant to be a vector and this might change in the
## future.
##
function split%(str: string, re: pattern%): string_array function split%(str: string, re: pattern%): string_array
%{ %{
return do_split(str, re, 0, 0, 0); return do_split(str, re, 0, 0, 0);
%} %}
# split1(str, pattern, include_separator): table[count] of string ## Splits a string *once* into a a two-element array of strings according to a
# ## pattern. This function is the same as :bro:id:`split`, but * is only split
# Same as split, except that str is only split (if possible) at the ## once (if possible) at the earliest position and an array of two strings is
# earliest position and an array of two strings is returned. ## returned.
# An array of one string is returned when str cannot be splitted. ##
## str: The string to split.
##
## re: The pattern describing the separator to split *str* in two pieces.
##
## Returns: An array of strings with two elements in which the first represents
## the substring in *str* up to the first occurence of *re*, and the
## second everything after *re*. An array of one string is returned
## when *s* cannot be split.
##
## .. bro:see:: split split_all split_n str_split
function split1%(str: string, re: pattern%): string_array function split1%(str: string, re: pattern%): string_array
%{ %{
return do_split(str, re, 0, 0, 1); return do_split(str, re, 0, 0, 1);
%} %}
# Same as split, except that the array returned by split_all also ## Splits a string into an array of strings according to a pattern. This
# includes parts of string that match the pattern in the array. ## function is the same as :bro:id:`split`, except that the separators are
## returned as well. For example, ``split_all("a-b--cd", /(\-)+/)`` returns
# For example, split_all("a-b--cd", /(\-)+/) returns {"a", "-", "b", ## ``{"a", "-", "b", "--", "cd"}``: odd-indexed elements do not match the
# "--", "cd"}: odd-indexed elements do not match the pattern ## pattern and even-indexed ones do.
# and even-indexed ones do. ##
## str: The string to split.
##
## re: The pattern describing the element separator in *str*.
##
## Returns: An array of strings where each two successive elements correspond
## to a substring in *str* of the part not matching *re* (odd-indexed)
## and thei part that matches *re* (even-indexed).
##
## .. bro:see:: split split1 split_n str_split
function split_all%(str: string, re: pattern%): string_array function split_all%(str: string, re: pattern%): string_array
%{ %{
return do_split(str, re, 0, 1, 0); return do_split(str, re, 0, 1, 0);
%} %}
## Splits a string a given number of times into an array of strings according
## to a pattern. This function is similar to :bro:id:`split1` and
## :bro:id:`split_all`, but with customizable behavior with respect to
## including separators in the result and the number of times to split.
##
## str: The string to split.
##
## re: The pattern describing the element separator in *str*.
##
## incl_sep: A flag indicating whether to include the separator matches in the
## result (as in :bro:id:`split_all`).
##
## max_num_sep: The number of times to split *str*.
##
## Returns: An array of strings where, if *incl_sep* is true, each two
## successive elements correspond to a substring in *str* of the part
## not matching *re* (odd-indexed) and the part that matches *re*
## (even-indexed).
##
## .. bro:see:: split split1 split_all str_split
function split_n%(str: string, re: pattern, function split_n%(str: string, re: pattern,
incl_sep: bool, max_num_sep: count%): string_array incl_sep: bool, max_num_sep: count%): string_array
%{ %{
return do_split(str, re, 0, incl_sep, max_num_sep); return do_split(str, re, 0, incl_sep, max_num_sep);
%} %}
## Deprecated. Will be removed.
# Reason: the parameter ``other`` does nothing.
function split_complete%(str: string, function split_complete%(str: string,
re: pattern, other: string_set, re: pattern, other: string_set,
incl_sep: bool, max_num_sep: count%): string_array incl_sep: bool, max_num_sep: count%): string_array
@ -411,22 +561,65 @@ function split_complete%(str: string,
return do_split(str, re, other->AsTableVal(), incl_sep, max_num_sep); return do_split(str, re, other->AsTableVal(), incl_sep, max_num_sep);
%} %}
## Substitutes a given replacement string for the first occurrence of a pattern
## in a given string.
##
## str: The string to perform the substitution in.
##
## re: The pattern being replaced with *repl*.
##
## repl: The string that replacs *re*.
##
## Returns: A copy of *str* with the first occurence of *re* replaced with
## *repl*.
##
## .. bro:see:: gsub subst_string
function sub%(str: string, re: pattern, repl: string%): string function sub%(str: string, re: pattern, repl: string%): string
%{ %{
return do_sub(str, re, repl, 0); return do_sub(str, re, repl, 0);
%} %}
## Substitutes a given replacement string for the all occurrences of a pattern
## in a given string.
##
## str: The string to perform the substitution in.
##
## re: The pattern being replaced with *repl*.
##
## repl: The string that replacs *re*.
##
## Returns: A copy of *str* with all occurences of *re* replaced with *repl*.
##
## .. bro:see:: sub subst_string
function gsub%(str: string, re: pattern, repl: string%): string function gsub%(str: string, re: pattern, repl: string%): string
%{ %{
return do_sub(str, re, repl, 1); return do_sub(str, re, repl, 1);
%} %}
## Lexicographically compares two string.
##
## s1: The first string.
##
## s2: The second string.
##
## Returns: An integer greater than, equal to, or less than 0 according as
## *s1* is greater than, equal to, or less than *s2*.
function strcmp%(s1: string, s2: string%): int function strcmp%(s1: string, s2: string%): int
%{ %{
return new Val(Bstr_cmp(s1->AsString(), s2->AsString()), TYPE_INT); return new Val(Bstr_cmp(s1->AsString(), s2->AsString()), TYPE_INT);
%} %}
# Returns 0 if $little is not found in $big. ## Locates the first occurrence of one string in another.
##
## big: The string to look in.
##
## little: The (smaller) string to find inside *big*.
##
## Returns: The location of *little* in *big* or 0 if *little* is not found in
## *big*.
##
## .. bro:see:: find_all find_last
function strstr%(big: string, little: string%): count function strstr%(big: string, little: string%): count
%{ %{
return new Val( return new Val(
@ -434,8 +627,17 @@ function strstr%(big: string, little: string%): count
TYPE_COUNT); TYPE_COUNT);
%} %}
# Substitute each (non-overlapping) appearance of $from in $s to $to, ## Substitutes each (non-overlapping) appearance of a string in another.
# and return the resulting string. ##
## s: The string in which to perform the substitution.
##
## from: The string to look for which is replaced with *to*.
##
## to: The string that replaces all occurrences of *from* in *s*.
##
## Returns: A copy of *s* where each occurrence of *from* is replaced with *to*.
##
## .. bro:see:: sub gsub
function subst_string%(s: string, from: string, to: string%): string function subst_string%(s: string, from: string, to: string%): string
%{ %{
const int little_len = from->Len(); const int little_len = from->Len();
@ -478,6 +680,15 @@ function subst_string%(s: string, from: string, to: string%): string
return new StringVal(concatenate(vs)); return new StringVal(concatenate(vs));
%} %}
## Replaces all uppercase letters in a string with their lowercase counterpart.
##
## str: The string to convert to lowercase letters.
##
## Returns: A copy of the given string with the uppercase letters (as indicated
## by ``isascii`` and \verb|isupper|``) folded to lowercase
## (via ``tolower``).
##
## .. bro:see:: to_upper is_ascii
function to_lower%(str: string%): string function to_lower%(str: string%): string
%{ %{
const u_char* s = str->Bytes(); const u_char* s = str->Bytes();
@ -498,6 +709,15 @@ function to_lower%(str: string%): string
return new StringVal(new BroString(1, lower_s, n)); return new StringVal(new BroString(1, lower_s, n));
%} %}
## Replaces all lowercase letters in a string with their uppercase counterpart.
##
## str: The string to convert to uppercase letters.
##
## Returns: A copy of the given string with the lowercase letters (as indicated
## by ``isascii`` and \verb|islower|``) folded to uppercase
## (via ``toupper``).
##
## .. bro:see:: to_lower is_ascii
function to_upper%(str: string%): string function to_upper%(str: string%): string
%{ %{
const u_char* s = str->Bytes(); const u_char* s = str->Bytes();
@ -518,18 +738,54 @@ function to_upper%(str: string%): string
return new StringVal(new BroString(1, upper_s, n)); return new StringVal(new BroString(1, upper_s, n));
%} %}
## Replaces non-printable characters in a string with escaped sequences. The
## mappings are:
##
## - ``NUL`` to ``\0``
## - ``DEL`` to ``^?``
## - values <= 26 to ``^[A-Z]``
## - values not in *[32, 126]** to ``%XX``
##
## If the string does not yet have a trailing NUL, one is added.
##
## str: The string to escape.
##
## Returns: The escaped string.
##
## .. bro:see:: to_string_literal escape_string
function clean%(str: string%): string function clean%(str: string%): string
%{ %{
char* s = str->AsString()->Render(); char* s = str->AsString()->Render();
return new StringVal(new BroString(1, byte_vec(s), strlen(s))); return new StringVal(new BroString(1, byte_vec(s), strlen(s)));
%} %}
## Replaces non-printable characters in a string with escaped sequences. The
## mappings are:
##
## - ``NUL`` to ``\0``
## - ``DEL`` to ``^?``
## - values <= 26 to ``^[A-Z]``
## - values not in *[32, 126]** to ``%XX``
##
## str: The string to escape.
##
## Returns: The escaped string.
##
## .. bro:see:: clean escape_string
function to_string_literal%(str: string%): string function to_string_literal%(str: string%): string
%{ %{
char* s = str->AsString()->Render(BroString::BRO_STRING_LITERAL); char* s = str->AsString()->Render(BroString::BRO_STRING_LITERAL);
return new StringVal(new BroString(1, byte_vec(s), strlen(s))); return new StringVal(new BroString(1, byte_vec(s), strlen(s)));
%} %}
## Determines whether a given string contains only ASCII characters.
##
## str: The string to examine.
##
## Returns: False if any byte value of *str* is greater than 127, and true
## otherwise.
##
## .. bro:see:: to_upper to_lower
function is_ascii%(str: string%): bool function is_ascii%(str: string%): bool
%{ %{
int n = str->Len(); int n = str->Len();
@ -542,7 +798,14 @@ function is_ascii%(str: string%): bool
return new Val(1, TYPE_BOOL); return new Val(1, TYPE_BOOL);
%} %}
# Make printable version of string. ## Creates a printable version of a string. This function is the same as
## :bro:id:`clean` except that non-printable characters are removed.
##
## s: The string to escape.
##
## Returns: The escaped string.
##
## .. bro:see:: clean to_string_literal
function escape_string%(s: string%): string function escape_string%(s: string%): string
%{ %{
char* escstr = s->AsString()->Render(); char* escstr = s->AsString()->Render();
@ -551,7 +814,12 @@ function escape_string%(s: string%): string
return val; return val;
%} %}
# Returns an ASCII hexadecimal representation of a string. ## Returns an ASCII hexadecimal representation of a string.
##
## s: The string to convert to hex.
##
## Returns: A copy of *s* where each byte is replaced with the corresponding
## hex nibble.
function string_to_ascii_hex%(s: string%): string function string_to_ascii_hex%(s: string%): string
%{ %{
char* x = new char[s->Len() * 2 + 1]; char* x = new char[s->Len() * 2 + 1];
@ -563,8 +831,15 @@ function string_to_ascii_hex%(s: string%): string
return new StringVal(new BroString(1, (u_char*) x, s->Len() * 2)); return new StringVal(new BroString(1, (u_char*) x, s->Len() * 2));
%} %}
function str_smith_waterman%(s1: string, s2: string, params: sw_params%) ## Uses the Smith Waterman algorithm to find similar/overlapping substrings.
: sw_substring_vec ## See `Wikipedia <http://en.wikipedia.org/wiki/Smith%E2%80%93Waterman_algorithm>`_.
##
## s1: The first string.
##
## s2: The second string.
##
## Returns: The result of the Smit Waterman algorithm calculation.
function str_smith_waterman%(s1: string, s2: string, params: sw_params%) : sw_substring_vec
%{ %{
SWParams sw_params(params->AsRecordVal()->Lookup(0)->AsCount(), SWParams sw_params(params->AsRecordVal()->Lookup(0)->AsCount(),
SWVariant(params->AsRecordVal()->Lookup(1)->AsCount())); SWVariant(params->AsRecordVal()->Lookup(1)->AsCount()));
@ -578,6 +853,16 @@ function str_smith_waterman%(s1: string, s2: string, params: sw_params%)
return result; return result;
%} %}
## Splits a string into substrings with the help of an index vector of cutting
## points.
##
## s: The string to split.
##
## idx: The index vector (``vector of count``) with the cutting points.
##
## Returns: A vector of strings.
##
## .. bro:see:: split split1 split_all split_n
function str_split%(s: string, idx: index_vec%): string_vec function str_split%(s: string, idx: index_vec%): string_vec
%{ %{
vector<Val*>* idx_v = idx->AsVector(); vector<Val*>* idx_v = idx->AsVector();
@ -606,6 +891,13 @@ function str_split%(s: string, idx: index_vec%): string_vec
return result_v; return result_v;
%} %}
## Strips whitespace at both ends of a string.
##
## str: The string to strip the whitespace from.
##
## Returns: A copy of *str* with leading and trailing whitespace removed.
##
## .. bro:see:: sub gsub
function strip%(str: string%): string function strip%(str: string%): string
%{ %{
const u_char* s = str->Bytes(); const u_char* s = str->Bytes();
@ -629,6 +921,14 @@ function strip%(str: string%): string
return new StringVal(new BroString(sp, (e - sp + 1), 1)); return new StringVal(new BroString(sp, (e - sp + 1), 1));
%} %}
## Generates a string of a given size and fills it with repetitions of a source
## string.
##
## len: The length of the output string.
##
## source: The string to concatenate repeatedly until *len* has been reached.
##
## Returns: A string of length *len* filled with *source*.
function string_fill%(len: int, source: string%): string function string_fill%(len: int, source: string%): string
%{ %{
const u_char* src = source->Bytes(); const u_char* src = source->Bytes();
@ -643,10 +943,15 @@ function string_fill%(len: int, source: string%): string
return new StringVal(new BroString(1, byte_vec(dst), len)); return new StringVal(new BroString(1, byte_vec(dst), len));
%} %}
# Takes a string and escapes characters that would allow execution of commands ## Takes a string and escapes characters that would allow execution of
# at the shell level. Must be used before including strings in system() or ## commands at the shell level. Must be used before including strings in
# similar calls. ## :bro:id:`system` or similar calls.
# ##
## source: The string to escape.
##
## Returns: A shell-escaped version of *source*.
##
## .. bro:see:: system
function str_shell_escape%(source: string%): string function str_shell_escape%(source: string%): string
%{ %{
unsigned j = 0; unsigned j = 0;
@ -675,8 +980,15 @@ function str_shell_escape%(source: string%): string
return new StringVal(new BroString(1, dst, j)); return new StringVal(new BroString(1, dst, j));
%} %}
# Returns all occurrences of the given pattern in the given string (an empty ## Finds all occurrences of a pattern in a string.
# empty set if none). ##
## str: The string to inspect.
##
## re: The pattern to look for in *str*.
##
## Returns: The set of strings in *str* that match *re*, or the empty set.
##
## .. bro:see: find_last strstr
function find_all%(str: string, re: pattern%) : string_set function find_all%(str: string, re: pattern%) : string_set
%{ %{
TableVal* a = new TableVal(internal_type("string_set")->AsTableType()); TableVal* a = new TableVal(internal_type("string_set")->AsTableType());
@ -697,11 +1009,18 @@ function find_all%(str: string, re: pattern%) : string_set
return a; return a;
%} %}
# Returns the last occurrence of the given pattern in the given string. ## Finds the last occurrence of a pattern in a string. This function returns
# If not found, returns an empty string. Note that this function returns ## the match that starts at the largest index in the string, which is not
# the match that starts at the largest index in the string, which is ## necessarily the longest match. For example, a pattern of ``/.*/`` will
# not necessarily the longest match. For example, a pattern of /.*/ ## return the final character in the string.
# will return the final character in the string. ##
## str: The string to inspect.
##
## re: The pattern to look for in *str*.
##
## Returns: The last string in *str* that matches *re*, or the empty string.
##
## .. bro:see: find_all strstr
function find_last%(str: string, re: pattern%) : string function find_last%(str: string, re: pattern%) : string
%{ %{
const u_char* s = str->Bytes(); const u_char* s = str->Bytes();
@ -717,10 +1036,16 @@ function find_last%(str: string, re: pattern%) : string
return new StringVal(""); return new StringVal("");
%} %}
# Returns a hex dump for given input data. The hex dump renders ## Returns a hex dump for given input data. The hex dump renders 16 bytes per
# 16 bytes per line, with hex on the left and ASCII (where printable) ## line, with hex on the left and ASCII (where printable)
# on the right. Based on Netdude's hex editor code. ## on the right.
# ##
## data_str: The string to dump in hex format.
##
## .. bro:see:: string_to_ascii_hex bytestring_to_hexstr
##
## .. note:: Based on Netdude's hex editor code.
##
function hexdump%(data_str: string%) : string function hexdump%(data_str: string%) : string
%{ %{