mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 15:48:19 +00:00
Merge remote-tracking branch 'origin/master' into topic/seth/smb
# Conflicts: # scripts/base/init-default.bro
This commit is contained in:
commit
7251b0f240
1182 changed files with 45819 additions and 13446 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -22,3 +22,6 @@
|
||||||
[submodule "aux/plugins"]
|
[submodule "aux/plugins"]
|
||||||
path = aux/plugins
|
path = aux/plugins
|
||||||
url = git://git.bro.org/bro-plugins
|
url = git://git.bro.org/bro-plugins
|
||||||
|
[submodule "aux/broker"]
|
||||||
|
path = aux/broker
|
||||||
|
url = git://git.bro.org/broker
|
||||||
|
|
|
@ -2,7 +2,7 @@ project(Bro C CXX)
|
||||||
|
|
||||||
# When changing the minimum version here, also adapt
|
# When changing the minimum version here, also adapt
|
||||||
# aux/bro-aux/plugin-support/skeleton/CMakeLists.txt
|
# aux/bro-aux/plugin-support/skeleton/CMakeLists.txt
|
||||||
cmake_minimum_required(VERSION 2.6.3 FATAL_ERROR)
|
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
|
||||||
|
|
||||||
include(cmake/CommonCMakeConfig.cmake)
|
include(cmake/CommonCMakeConfig.cmake)
|
||||||
|
|
||||||
|
@ -15,6 +15,11 @@ if (NOT BRO_SCRIPT_INSTALL_PATH)
|
||||||
set(BRO_SCRIPT_INSTALL_PATH ${BRO_ROOT_DIR}/share/bro)
|
set(BRO_SCRIPT_INSTALL_PATH ${BRO_ROOT_DIR}/share/bro)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (NOT BRO_MAN_INSTALL_PATH)
|
||||||
|
# set the default Bro man page installation path (user did not specify one)
|
||||||
|
set(BRO_MAN_INSTALL_PATH ${BRO_ROOT_DIR}/share/man)
|
||||||
|
endif ()
|
||||||
|
|
||||||
# sanitize the Bro script install directory into an absolute path
|
# sanitize the Bro script install directory into an absolute path
|
||||||
# (CMake is confused by ~ as a representation of home directory)
|
# (CMake is confused by ~ as a representation of home directory)
|
||||||
get_filename_component(BRO_SCRIPT_INSTALL_PATH ${BRO_SCRIPT_INSTALL_PATH}
|
get_filename_component(BRO_SCRIPT_INSTALL_PATH ${BRO_SCRIPT_INSTALL_PATH}
|
||||||
|
@ -26,12 +31,12 @@ configure_file(bro-path-dev.in ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev)
|
||||||
|
|
||||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.sh
|
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.sh
|
||||||
"export BROPATH=`${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n"
|
"export BROPATH=`${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n"
|
||||||
"export BRO_PLUGIN_PATH=\"${CMAKE_CURRENT_BINARY_DIR}/src:${BRO_PLUGIN_INSTALL_PATH}\"\n"
|
"export BRO_PLUGIN_PATH=\"${CMAKE_CURRENT_BINARY_DIR}/src\":${BRO_PLUGIN_PATH}\n"
|
||||||
"export PATH=\"${CMAKE_CURRENT_BINARY_DIR}/src\":$PATH\n")
|
"export PATH=\"${CMAKE_CURRENT_BINARY_DIR}/src\":$PATH\n")
|
||||||
|
|
||||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.csh
|
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.csh
|
||||||
"setenv BROPATH `${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n"
|
"setenv BROPATH `${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n"
|
||||||
"setenv BRO_PLUGIN_PATH \"${CMAKE_CURRENT_BINARY_DIR}/src:${BRO_PLUGIN_INSTALL_PATH}\"\n"
|
"setenv BRO_PLUGIN_PATH \"${CMAKE_CURRENT_BINARY_DIR}/src\":${BRO_PLUGIN_PATH}\n"
|
||||||
"setenv PATH \"${CMAKE_CURRENT_BINARY_DIR}/src\":$PATH\n")
|
"setenv PATH \"${CMAKE_CURRENT_BINARY_DIR}/src\":$PATH\n")
|
||||||
|
|
||||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1)
|
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1)
|
||||||
|
@ -56,7 +61,7 @@ if (NOT SED_EXE)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
FindRequiredPackage(Perl)
|
FindRequiredPackage(PythonInterp)
|
||||||
FindRequiredPackage(FLEX)
|
FindRequiredPackage(FLEX)
|
||||||
FindRequiredPackage(BISON)
|
FindRequiredPackage(BISON)
|
||||||
FindRequiredPackage(PCAP)
|
FindRequiredPackage(PCAP)
|
||||||
|
@ -108,7 +113,7 @@ if (NOT DISABLE_PERFTOOLS)
|
||||||
find_package(GooglePerftools)
|
find_package(GooglePerftools)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (GOOGLEPERFTOOLS_FOUND)
|
if (GOOGLEPERFTOOLS_FOUND OR TCMALLOC_FOUND)
|
||||||
set(HAVE_PERFTOOLS true)
|
set(HAVE_PERFTOOLS true)
|
||||||
# Non-Linux systems may not be well-supported by gperftools, so
|
# Non-Linux systems may not be well-supported by gperftools, so
|
||||||
# require explicit request from user to enable it in that case.
|
# require explicit request from user to enable it in that case.
|
||||||
|
@ -160,21 +165,30 @@ include(PCAPTests)
|
||||||
include(OpenSSLTests)
|
include(OpenSSLTests)
|
||||||
include(CheckNameserCompat)
|
include(CheckNameserCompat)
|
||||||
include(GetArchitecture)
|
include(GetArchitecture)
|
||||||
|
include(RequireCXX11)
|
||||||
|
|
||||||
# Tell the plugin code that we're building as part of the main tree.
|
# Tell the plugin code that we're building as part of the main tree.
|
||||||
set(BRO_PLUGIN_INTERNAL_BUILD true CACHE INTERNAL "" FORCE)
|
set(BRO_PLUGIN_INTERNAL_BUILD true CACHE INTERNAL "" FORCE)
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/bro-config.h.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
${CMAKE_CURRENT_BINARY_DIR}/bro-config.h)
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
## Recurse on sub-directories
|
## Recurse on sub-directories
|
||||||
|
|
||||||
|
if ( ENABLE_BROKER )
|
||||||
|
add_subdirectory(aux/broker)
|
||||||
|
set(brodeps ${brodeps} broker)
|
||||||
|
add_definitions(-DENABLE_BROKER)
|
||||||
|
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/aux/broker)
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(scripts)
|
add_subdirectory(scripts)
|
||||||
add_subdirectory(doc)
|
add_subdirectory(doc)
|
||||||
|
add_subdirectory(man)
|
||||||
|
|
||||||
include(CheckOptionalBuildSources)
|
include(CheckOptionalBuildSources)
|
||||||
|
|
||||||
|
@ -218,6 +232,8 @@ message(
|
||||||
"\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}"
|
"\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}"
|
||||||
"\nCPP: ${CMAKE_CXX_COMPILER}"
|
"\nCPP: ${CMAKE_CXX_COMPILER}"
|
||||||
"\n"
|
"\n"
|
||||||
|
"\nBroker: ${ENABLE_BROKER}"
|
||||||
|
"\nBroker Python: ${BROKER_PYTHON_BINDINGS}"
|
||||||
"\nBroccoli: ${INSTALL_BROCCOLI}"
|
"\nBroccoli: ${INSTALL_BROCCOLI}"
|
||||||
"\nBroctl: ${INSTALL_BROCTL}"
|
"\nBroctl: ${INSTALL_BROCTL}"
|
||||||
"\nAux. Tools: ${INSTALL_AUX_TOOLS}"
|
"\nAux. Tools: ${INSTALL_AUX_TOOLS}"
|
||||||
|
|
2
COPYING
2
COPYING
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 1995-2013, The Regents of the University of California
|
Copyright (c) 1995-2015, The Regents of the University of California
|
||||||
through the Lawrence Berkeley National Laboratory and the
|
through the Lawrence Berkeley National Laboratory and the
|
||||||
International Computer Science Institute. All rights reserved.
|
International Computer Science Institute. All rights reserved.
|
||||||
|
|
||||||
|
|
3
INSTALL
3
INSTALL
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
See doc/install/install.rst for installation instructions.
|
|
||||||
|
|
1
INSTALL
Symbolic link
1
INSTALL
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
doc/install/install.rst
|
15
Makefile
15
Makefile
|
@ -48,15 +48,18 @@ bindist:
|
||||||
|
|
||||||
distclean:
|
distclean:
|
||||||
rm -rf $(BUILD)
|
rm -rf $(BUILD)
|
||||||
|
$(MAKE) -C testing $@
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@( cd testing && make )
|
-@( cd testing && make )
|
||||||
|
|
||||||
test-all: test
|
test-aux:
|
||||||
test -d aux/broctl && ( cd aux/broctl && make test )
|
-test -d aux/broctl && ( cd aux/broctl && make test-all )
|
||||||
test -d aux/btest && ( cd aux/btest && make test )
|
-test -d aux/btest && ( cd aux/btest && make test )
|
||||||
test -d aux/bro-aux && ( cd aux/bro-aux && make test )
|
-test -d aux/bro-aux && ( cd aux/bro-aux && make test )
|
||||||
test -d aux/plugins && ( cd aux/plugins && make test-all )
|
-test -d aux/plugins && ( cd aux/plugins && make test-all )
|
||||||
|
|
||||||
|
test-all: test test-aux
|
||||||
|
|
||||||
configured:
|
configured:
|
||||||
@test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 )
|
@test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 )
|
||||||
|
|
312
NEWS
312
NEWS
|
@ -4,11 +4,70 @@ release. For an exhaustive list of changes, see the ``CHANGES`` file
|
||||||
(note that submodules, such as BroControl and Broccoli, come with
|
(note that submodules, such as BroControl and Broccoli, come with
|
||||||
their own ``CHANGES``.)
|
their own ``CHANGES``.)
|
||||||
|
|
||||||
Bro 2.4 (in progress)
|
Bro 2.5 (in progress)
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Dependencies
|
New Dependencies
|
||||||
------------
|
----------------
|
||||||
|
|
||||||
|
- Bro now requires a compiler with C++11 support for building the
|
||||||
|
source code.
|
||||||
|
|
||||||
|
- Bro now requires the C++ Actor Framework, CAF, which must be
|
||||||
|
installed first. See http://actor-framework.org.
|
||||||
|
|
||||||
|
- Bro now requires Python instead of Perl to compile the source code.
|
||||||
|
|
||||||
|
- The pcap buffer size can set through the new option Pcap::bufsize.
|
||||||
|
|
||||||
|
New Functionality
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
- Bro now tracks VLAN IDs. To record them inside the connection log,
|
||||||
|
load protocols/conn/vlan-logging.bro.
|
||||||
|
|
||||||
|
- A new per-packet event raw_packet() provides access to layer 2
|
||||||
|
information. Use with care, generating events per packet is
|
||||||
|
expensive.
|
||||||
|
|
||||||
|
- A new built-in function, decode_base64_conn() for Base64 decoding.
|
||||||
|
It works like decode_base64() but receives an additional connection
|
||||||
|
argument that will be used for decoding errors into weird.log
|
||||||
|
(instead of reporter.log).
|
||||||
|
|
||||||
|
- The IRC analyzer now recognizes StartTLS sessions and enable the SSL
|
||||||
|
analyzer for them.
|
||||||
|
|
||||||
|
- New Bro plugins in aux/plugins:
|
||||||
|
|
||||||
|
- af_packet: Native AF_PACKET support.
|
||||||
|
- myricom: Native Myricom SNF v3 support.
|
||||||
|
- pf_ring: Native PF_RING support.
|
||||||
|
- redis: An experimental log writer for Redis.
|
||||||
|
- tcprs: An TCP-level analyzer detecting retransmissions, reordering, and more.
|
||||||
|
|
||||||
|
Changed Functionality
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- Some script-level identifier have changed their names:
|
||||||
|
|
||||||
|
snaplen -> Pcap::snaplen
|
||||||
|
precompile_pcap_filter() -> Pcap::precompile_pcap_filter()
|
||||||
|
install_pcap_filter() -> Pcap::install_pcap_filter()
|
||||||
|
pcap_error() -> Pcap::pcap_error()
|
||||||
|
|
||||||
|
|
||||||
|
Deprecated Functionality
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
- The built-in functions decode_base64_custom() and
|
||||||
|
encode_base64_custom() are no longer needed and will be removed
|
||||||
|
in the future. Their functionality is now provided directly by
|
||||||
|
decode_base64() and encode_base64(), which take an optional
|
||||||
|
parameter to change the Base64 alphabet.
|
||||||
|
|
||||||
|
Bro 2.4
|
||||||
|
=======
|
||||||
|
|
||||||
New Functionality
|
New Functionality
|
||||||
-----------------
|
-----------------
|
||||||
|
@ -16,20 +75,257 @@ New Functionality
|
||||||
- Bro now has support for external plugins that can extend its core
|
- Bro now has support for external plugins that can extend its core
|
||||||
functionality, like protocol/file analysis, via shared libraries.
|
functionality, like protocol/file analysis, via shared libraries.
|
||||||
Plugins can be developed and distributed externally, and will be
|
Plugins can be developed and distributed externally, and will be
|
||||||
pulled in dynamically at startup. Currently, a plugin can provide
|
pulled in dynamically at startup (the environment variables
|
||||||
custom protocol analyzers, file analyzers, log writers[TODO], input
|
BRO_PLUGIN_PATH and BRO_PLUGIN_ACTIVATE can be used to specify the
|
||||||
readers[TODO], packet sources[TODO], and new built-in functions. A
|
locations and names of plugins to activate). Currently, a plugin
|
||||||
plugin can furthermore hook into Bro's processing a number of places
|
can provide custom protocol analyzers, file analyzers, log writers,
|
||||||
to add custom logic.
|
input readers, packet sources and dumpers, and new built-in functions.
|
||||||
|
A plugin can furthermore hook into Bro's processing at a number of
|
||||||
|
places to add custom logic.
|
||||||
|
|
||||||
See https://www.bro.org/sphinx-git/devel/plugins.html for more
|
See https://www.bro.org/sphinx-git/devel/plugins.html for more
|
||||||
information on writing plugins.
|
information on writing plugins.
|
||||||
|
|
||||||
|
- Bro now has support for the MySQL wire protocol. Activity gets
|
||||||
|
logged into mysql.log.
|
||||||
|
|
||||||
|
- Bro now parses DTLS traffic. Activity gets logged into ssl.log.
|
||||||
|
|
||||||
|
- Bro now has support for the Kerberos KRB5 protocol over TCP and
|
||||||
|
UDP. Activity gets logged into kerberos.log.
|
||||||
|
|
||||||
|
- Bro now has an RDP analyzer. Activity gets logged into rdp.log.
|
||||||
|
|
||||||
|
- Bro now has a file analyzer for Portable Executables. Activity gets
|
||||||
|
logged into pe.log.
|
||||||
|
|
||||||
|
- Bro now has support for the SIP protocol over UDP. Activity gets
|
||||||
|
logged into sip.log.
|
||||||
|
|
||||||
|
- Bro now features a completely rewritten, enhanced SSH analyzer. The
|
||||||
|
new analyzer is able to determine if logins failed or succeeded in
|
||||||
|
most circumstances, logs a lot more more information about SSH
|
||||||
|
sessions, supports v1, and introduces the intelligence type
|
||||||
|
``Intel::PUBKEY_HASH`` and location ``SSH::IN_SERVER_HOST_KEY``. The
|
||||||
|
analayzer also generates a set of additional events
|
||||||
|
(``ssh_auth_successful``, ``ssh_auth_failed``, ``ssh_capabilities``,
|
||||||
|
``ssh2_server_host_key``, ``ssh1_server_host_key``,
|
||||||
|
``ssh_encrypted_packet``, ``ssh2_dh_server_params``,
|
||||||
|
``ssh2_gss_error``, ``ssh2_ecc_key``). See next section for
|
||||||
|
incompatible SSH changes.
|
||||||
|
|
||||||
|
- Bro's file analysis now supports reassembly of files that are not
|
||||||
|
transferred/seen sequentially. The default file reassembly buffer
|
||||||
|
size is set with the ``Files::reassembly_buffer_size`` variable.
|
||||||
|
|
||||||
|
- Bro's file type identification has been greatly improved (new file types,
|
||||||
|
bug fixes, and performance improvements).
|
||||||
|
|
||||||
|
- Bro's scripting language now has a ``while`` statement::
|
||||||
|
|
||||||
|
while ( i < 5 )
|
||||||
|
print ++i;
|
||||||
|
|
||||||
|
``next`` and ``break`` can be used inside the loop's body just like
|
||||||
|
with ``for`` loops.
|
||||||
|
|
||||||
|
- Bro now integrates Broker, a new communication library. See
|
||||||
|
aux/broker/README for more information on Broker, and
|
||||||
|
doc/frameworks/broker.rst for the corresponding Bro script API.
|
||||||
|
|
||||||
|
With Broker, Bro has the similar capabilities of exchanging events and
|
||||||
|
logs with remote peers (either another Bro process or some other
|
||||||
|
application that uses Broker). It also includes a key-value store
|
||||||
|
API that can be used to share state between peers and optionally
|
||||||
|
allow data to persist on disk for longer-term storage.
|
||||||
|
|
||||||
|
Broker support is by default off for now; it can be enabled at
|
||||||
|
configure time with --enable-broker. It requires CAF version 0.13+
|
||||||
|
(https://github.com/actor-framework/actor-framework) as well as a
|
||||||
|
C++11 compiler (e.g. GCC 4.8+ or Clang 3.3+).
|
||||||
|
|
||||||
|
Broker will become a mandatory dependency in future Bro versions and
|
||||||
|
replace the current communication and serialization system.
|
||||||
|
|
||||||
|
- Add --enable-c++11 configure flag to compile Bro's source code in
|
||||||
|
C++11 mode with a corresponding compiler. Note that 2.4 will be the
|
||||||
|
last version of Bro that compiles without C++11 support.
|
||||||
|
|
||||||
|
- The SSL analysis now alerts when encountering SSL connections with
|
||||||
|
old protocol versions or unsafe cipher suites. It also gained
|
||||||
|
extended reporting of weak keys, caching of already validated
|
||||||
|
certificates, and full support for TLS record defragmentation. SSL generally
|
||||||
|
became much more robust and added several fields to ssl.log (while
|
||||||
|
removing some others).
|
||||||
|
|
||||||
|
- A new icmp_sent_payload event provides access to ICMP payload.
|
||||||
|
|
||||||
|
- The input framework's raw reader now supports seeking by adding an
|
||||||
|
option "offset" to the config map. Positive offsets are interpreted
|
||||||
|
to be from the beginning of the file, negative from the end of the
|
||||||
|
file (-1 is end of file).
|
||||||
|
|
||||||
|
- One can now raise events when a connection crosses a given size
|
||||||
|
threshold in terms of packets or bytes. The primary API for that
|
||||||
|
functionality is in base/protocols/conn/thresholds.bro.
|
||||||
|
|
||||||
|
- There is a new command-line option -Q/--time that prints Bro's execution
|
||||||
|
time and memory usage to stderr.
|
||||||
|
|
||||||
|
- BroControl now has a new command "deploy" which is equivalent to running
|
||||||
|
the "check", "install", "stop", and "start" commands (in that order).
|
||||||
|
|
||||||
|
- BroControl now has a new option "StatusCmdShowAll" that controls whether
|
||||||
|
or not the broctl "status" command gathers all of the status information.
|
||||||
|
This option can be used to make the "status" command run significantly
|
||||||
|
faster (in this case, the "Peers" column will not be shown in the output).
|
||||||
|
|
||||||
|
- BroControl now has a new option "StatsLogEnable" that controls whether
|
||||||
|
or not broctl will record information to the "stats.log" file. This option
|
||||||
|
can be used to make the "broctl cron" command run slightly faster (in this
|
||||||
|
case, "broctl cron" will also no longer send email about not seeing any
|
||||||
|
packets on the monitoring interfaces).
|
||||||
|
|
||||||
|
- BroControl now has a new option "MailHostUpDown" which controls whether or
|
||||||
|
not the "broctl cron" command will send email when it notices that a host
|
||||||
|
in the cluster is up or down.
|
||||||
|
|
||||||
|
- BroControl now has a new option "CommandTimeout" which specifies the number
|
||||||
|
of seconds to wait for a command that broctl ran to return results.
|
||||||
|
|
||||||
Changed Functionality
|
Changed Functionality
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
- bro-cut has been rewritten in C, and is hence much faster.
|
- bro-cut has been rewritten in C, and is hence much faster.
|
||||||
|
|
||||||
|
- File analysis
|
||||||
|
|
||||||
|
* Removed ``fa_file`` record's ``mime_type`` and ``mime_types``
|
||||||
|
fields. The event ``file_sniff`` has been added which provides
|
||||||
|
the same information. The ``mime_type`` field of ``Files::Info``
|
||||||
|
also still has this info.
|
||||||
|
|
||||||
|
* The earliest point that new mime type information is available is
|
||||||
|
in the ``file_sniff`` event which comes after the ``file_new`` and
|
||||||
|
``file_over_new_connection`` events. Scripts which inspected mime
|
||||||
|
type info within those events will need to be adapted. (Note: for
|
||||||
|
users that worked w/ versions of Bro from git, for a while there was
|
||||||
|
also an event called ``file_mime_type`` which is now replaced with
|
||||||
|
the ``file_sniff`` event).
|
||||||
|
|
||||||
|
* Removed ``Files::add_analyzers_for_mime_type`` function.
|
||||||
|
|
||||||
|
* Removed ``offset`` parameter of the ``file_extraction_limit``
|
||||||
|
event. Since file extraction now internally depends on file
|
||||||
|
reassembly for non-sequential files, "offset" can be obtained
|
||||||
|
with other information already available -- adding together
|
||||||
|
``seen_bytes`` and ``missed_bytes`` fields of the ``fa_file``
|
||||||
|
record gives how many bytes have been written so far (i.e.
|
||||||
|
the "offset").
|
||||||
|
|
||||||
|
- The SSH changes come with a few incompatibilities. The following
|
||||||
|
events have been renamed:
|
||||||
|
|
||||||
|
* ``SSH::heuristic_failed_login`` to ``ssh_auth_failed``
|
||||||
|
* ``SSH::heuristic_successful_login`` to ``ssh_auth_successful``
|
||||||
|
|
||||||
|
The ``SSH::Info`` status field has been removed and replaced with
|
||||||
|
the ``auth_success`` field. This field has been changed from a
|
||||||
|
string that was previously ``success``, ``failure`` or
|
||||||
|
``undetermined`` to a boolean. a boolean that is ``T``, ``F``, or
|
||||||
|
unset.
|
||||||
|
|
||||||
|
- The has_valid_octets function now uses a string_vec parameter instead of
|
||||||
|
string_array.
|
||||||
|
|
||||||
|
- conn.log gained a new field local_resp that works like local_orig,
|
||||||
|
just for the responder address of the connection.
|
||||||
|
|
||||||
|
- GRE tunnels are now identified as ``Tunnel::GRE`` instead of
|
||||||
|
``Tunnel::IP``.
|
||||||
|
|
||||||
|
- The default name for extracted files changed from extract-protocol-id
|
||||||
|
to extract-timestamp-protocol-id.
|
||||||
|
|
||||||
|
- The weird named "unmatched_HTTP_reply" has been removed since it can
|
||||||
|
be detected at the script-layer and is handled correctly by the
|
||||||
|
default HTTP scripts.
|
||||||
|
|
||||||
|
- When adding a logging filter to a stream, the filter can now inherit
|
||||||
|
a default ``path`` field from the associated ``Log::Stream`` record.
|
||||||
|
|
||||||
|
- When adding a logging filter to a stream, the
|
||||||
|
``Log::default_path_func`` is now only automatically added to the
|
||||||
|
filter if it has neither a ``path`` nor a ``path_func`` already
|
||||||
|
explicitly set. Before, the default path function would always be set
|
||||||
|
for all filters which didn't specify their own ``path_func``.
|
||||||
|
|
||||||
|
- BroControl now establishes only one ssh connection from the manager to
|
||||||
|
each remote host in a cluster configuration (previously, there would be
|
||||||
|
one ssh connection per remote Bro process).
|
||||||
|
|
||||||
|
- BroControl now uses SQLite to record state information instead of a
|
||||||
|
plain text file (the file "spool/broctl.dat" is no longer used).
|
||||||
|
On FreeBSD, this means that there is a new dependency on the package
|
||||||
|
"py27-sqlite3".
|
||||||
|
|
||||||
|
- BroControl now records the expected running state of each Bro node right
|
||||||
|
before each start or stop. The "broctl cron" command uses this info to
|
||||||
|
either start or stop Bro nodes as needed so that the actual state matches
|
||||||
|
the expected state (previously, "broctl cron" could only start nodes in
|
||||||
|
the "crashed" state, and could never stop a node).
|
||||||
|
|
||||||
|
- BroControl now sends all normal command output (i.e., not error messages)
|
||||||
|
to stdout. Error messages are still sent to stderr, however.
|
||||||
|
|
||||||
|
- The capability of processing NetFlow input has been removed for the
|
||||||
|
time being. Therefore, the -y/--flowfile and -Y/--netflow command-line
|
||||||
|
options have been removed, and the netflow_v5_header and netflow_v5_record
|
||||||
|
events have been removed.
|
||||||
|
|
||||||
|
- The -D/--dfa-size command-line option has been removed.
|
||||||
|
|
||||||
|
- The -L/--rule-benchmark command-line option has been removed.
|
||||||
|
|
||||||
|
- The -O/--optimize command-line option has been removed.
|
||||||
|
|
||||||
|
- The deprecated fields "hot" and "addl" have been removed from the
|
||||||
|
connection record. Likewise, the functions append_addl() and
|
||||||
|
append_addl_marker() have been removed.
|
||||||
|
|
||||||
|
- Log files now escape non-printable characters consistently as "\xXX'.
|
||||||
|
Furthermore, backslashes are escaped as "\\", making the
|
||||||
|
representation fully reversible.
|
||||||
|
|
||||||
|
Deprecated Functionality
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
- The split* family of functions are to be replaced with alternate
|
||||||
|
versions that return a vector of strings rather than a table of
|
||||||
|
strings. This also allows deprecation for some related string
|
||||||
|
concatenation/extraction functions. Note that the new functions use
|
||||||
|
0-based indexing, rather than 1-based.
|
||||||
|
|
||||||
|
The full list of now deprecated functions is:
|
||||||
|
|
||||||
|
* split: use split_string instead.
|
||||||
|
|
||||||
|
* split1: use split_string1 instead.
|
||||||
|
|
||||||
|
* split_all: use split_string_all instead.
|
||||||
|
|
||||||
|
* split_n: use split_string_n instead.
|
||||||
|
|
||||||
|
* cat_string_array: see join_string_vec instead.
|
||||||
|
|
||||||
|
* cat_string_array_n: see join_string_vec instead.
|
||||||
|
|
||||||
|
* join_string_array: see join_string_vec instead.
|
||||||
|
|
||||||
|
* sort_string_array: use sort instead.
|
||||||
|
|
||||||
|
* find_ip_addresses: use extract_ip_addresses instead.
|
||||||
|
|
||||||
Bro 2.3
|
Bro 2.3
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
|
1
README.rst
Symbolic link
1
README.rst
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
README
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2.3-183
|
2.4-228
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3a4684801aafa0558383199e9abd711650b53af9
|
Subproject commit 214294c502d377bb7bf511eac8c43608e54c875a
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9ea20c3905bd3fd5109849c474a2f2b4ed008357
|
Subproject commit 4e0d2bff4b2c287f66186c3654ef784bb0748d11
|
|
@ -1 +1 @@
|
||||||
Subproject commit 33d0ed4a54a6ecf08a0b5fe18831aa413b437066
|
Subproject commit 959cc0a8181e7f4b07559a6aecca2a0d7d3d445c
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2f808bc8541378b1a4953cca02c58c43945d154f
|
Subproject commit 1d0ca4753471cf822f612dc0d0e9bf9a439a994b
|
1
aux/broker
Submodule
1
aux/broker
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 9a2e8ec7b365bde282edc7301c7936eed6b4fbbb
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1efa4d10f943351efea96def68e598b053fd217a
|
Subproject commit 71a1e3efc437aa9f981be71affa1c4615e8d98a5
|
|
@ -1 +1 @@
|
||||||
Subproject commit 23055b473c689a79da12b2825d8388f71f28c709
|
Subproject commit 35007df0974b566f75d7c82af5b4d5a022333d87
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
||||||
Subproject commit 03de0cc467d2334dcb851eddd843d59fef217909
|
Subproject commit 843cdf6a91f06e5407bffbc79a343bff3cf4c81f
|
62
configure
vendored
62
configure
vendored
|
@ -24,6 +24,13 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
--prefix=PREFIX installation directory [/usr/local/bro]
|
--prefix=PREFIX installation directory [/usr/local/bro]
|
||||||
--scriptdir=PATH root installation directory for Bro scripts
|
--scriptdir=PATH root installation directory for Bro scripts
|
||||||
[PREFIX/share/bro]
|
[PREFIX/share/bro]
|
||||||
|
--localstatedir=PATH when using BroControl, path to store log files
|
||||||
|
and run-time data (within log/ and spool/ subdirs)
|
||||||
|
[PREFIX]
|
||||||
|
--spooldir=PATH when using BroControl, path to store run-time data
|
||||||
|
[PREFIX/spool]
|
||||||
|
--logdir=PATH when using BroControl, path to store log file
|
||||||
|
[PREFIX/logs]
|
||||||
--conf-files-dir=PATH config files installation directory [PREFIX/etc]
|
--conf-files-dir=PATH config files installation directory [PREFIX/etc]
|
||||||
|
|
||||||
Optional Features:
|
Optional Features:
|
||||||
|
@ -34,11 +41,13 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
--enable-perftools-debug use Google's perftools for debugging
|
--enable-perftools-debug use Google's perftools for debugging
|
||||||
--enable-jemalloc link against jemalloc
|
--enable-jemalloc link against jemalloc
|
||||||
--enable-ruby build ruby bindings for broccoli (deprecated)
|
--enable-ruby build ruby bindings for broccoli (deprecated)
|
||||||
|
--disable-broker disable use of the Broker communication library
|
||||||
--disable-broccoli don't build or install the Broccoli library
|
--disable-broccoli don't build or install the Broccoli library
|
||||||
--disable-broctl don't install Broctl
|
--disable-broctl don't install Broctl
|
||||||
--disable-auxtools don't build or install auxiliary tools
|
--disable-auxtools don't build or install auxiliary tools
|
||||||
--disable-perftools don't try to build with Google Perftools
|
--disable-perftools don't try to build with Google Perftools
|
||||||
--disable-python don't try to build python bindings for broccoli
|
--disable-python don't try to build python bindings for broccoli
|
||||||
|
--disable-pybroker don't try to build python bindings for broker
|
||||||
|
|
||||||
Required Packages in Non-Standard Locations:
|
Required Packages in Non-Standard Locations:
|
||||||
--with-openssl=PATH path to OpenSSL install root
|
--with-openssl=PATH path to OpenSSL install root
|
||||||
|
@ -47,19 +56,22 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
--with-binpac=PATH path to BinPAC install root
|
--with-binpac=PATH path to BinPAC install root
|
||||||
--with-flex=PATH path to flex executable
|
--with-flex=PATH path to flex executable
|
||||||
--with-bison=PATH path to bison executable
|
--with-bison=PATH path to bison executable
|
||||||
--with-perl=PATH path to perl executable
|
--with-python=PATH path to Python executable
|
||||||
|
--with-libcaf=PATH path to C++ Actor Framework installation
|
||||||
|
(a required Broker dependency)
|
||||||
|
|
||||||
Optional Packages in Non-Standard Locations:
|
Optional Packages in Non-Standard Locations:
|
||||||
--with-geoip=PATH path to the libGeoIP install root
|
--with-geoip=PATH path to the libGeoIP install root
|
||||||
--with-perftools=PATH path to Google Perftools install root
|
--with-perftools=PATH path to Google Perftools install root
|
||||||
--with-jemalloc=PATH path to jemalloc install root
|
--with-jemalloc=PATH path to jemalloc install root
|
||||||
--with-python=PATH path to Python interpreter
|
|
||||||
--with-python-lib=PATH path to libpython
|
--with-python-lib=PATH path to libpython
|
||||||
--with-python-inc=PATH path to Python headers
|
--with-python-inc=PATH path to Python headers
|
||||||
--with-ruby=PATH path to ruby interpreter
|
--with-ruby=PATH path to ruby interpreter
|
||||||
--with-ruby-lib=PATH path to ruby library
|
--with-ruby-lib=PATH path to ruby library
|
||||||
--with-ruby-inc=PATH path to ruby headers
|
--with-ruby-inc=PATH path to ruby headers
|
||||||
--with-swig=PATH path to SWIG executable
|
--with-swig=PATH path to SWIG executable
|
||||||
|
--with-rocksdb=PATH path to RocksDB installation
|
||||||
|
(an optional Broker dependency)
|
||||||
|
|
||||||
Packaging Options (for developers):
|
Packaging Options (for developers):
|
||||||
--binary-package toggle special logic for binary packaging
|
--binary-package toggle special logic for binary packaging
|
||||||
|
@ -81,7 +93,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
sourcedir="$( cd "$( dirname "$0" )" && pwd )"
|
sourcedir="$( cd "$( dirname "$0" )" && pwd )"
|
||||||
|
|
||||||
# Function to append a CMake cache entry definition to the
|
# Function to append a CMake cache entry definition to the
|
||||||
# CMakeCacheEntries variable
|
# CMakeCacheEntries variable.
|
||||||
# $1 is the cache entry variable name
|
# $1 is the cache entry variable name
|
||||||
# $2 is the cache entry variable type
|
# $2 is the cache entry variable type
|
||||||
# $3 is the cache entry variable value
|
# $3 is the cache entry variable value
|
||||||
|
@ -89,6 +101,17 @@ append_cache_entry () {
|
||||||
CMakeCacheEntries="$CMakeCacheEntries -D $1:$2=$3"
|
CMakeCacheEntries="$CMakeCacheEntries -D $1:$2=$3"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Function to remove a CMake cache entry definition from the
|
||||||
|
# CMakeCacheEntries variable
|
||||||
|
# $1 is the cache entry variable name
|
||||||
|
remove_cache_entry () {
|
||||||
|
CMakeCacheEntries="$CMakeCacheEntries -U $1"
|
||||||
|
|
||||||
|
# Even with -U, cmake still warns by default if
|
||||||
|
# added previously with -D.
|
||||||
|
CMakeCacheEntries="$CMakeCacheEntries --no-warn-unused-cli"
|
||||||
|
}
|
||||||
|
|
||||||
# set defaults
|
# set defaults
|
||||||
builddir=build
|
builddir=build
|
||||||
prefix=/usr/local/bro
|
prefix=/usr/local/bro
|
||||||
|
@ -98,10 +121,13 @@ append_cache_entry BRO_ROOT_DIR PATH $prefix
|
||||||
append_cache_entry PY_MOD_INSTALL_DIR PATH $prefix/lib/broctl
|
append_cache_entry PY_MOD_INSTALL_DIR PATH $prefix/lib/broctl
|
||||||
append_cache_entry BRO_SCRIPT_INSTALL_PATH STRING $prefix/share/bro
|
append_cache_entry BRO_SCRIPT_INSTALL_PATH STRING $prefix/share/bro
|
||||||
append_cache_entry BRO_ETC_INSTALL_DIR PATH $prefix/etc
|
append_cache_entry BRO_ETC_INSTALL_DIR PATH $prefix/etc
|
||||||
|
append_cache_entry BROKER_PYTHON_HOME PATH $prefix
|
||||||
|
append_cache_entry BROKER_PYTHON_BINDINGS BOOL false
|
||||||
append_cache_entry ENABLE_DEBUG BOOL false
|
append_cache_entry ENABLE_DEBUG BOOL false
|
||||||
append_cache_entry ENABLE_PERFTOOLS BOOL false
|
append_cache_entry ENABLE_PERFTOOLS BOOL false
|
||||||
append_cache_entry ENABLE_PERFTOOLS_DEBUG BOOL false
|
append_cache_entry ENABLE_PERFTOOLS_DEBUG BOOL false
|
||||||
append_cache_entry ENABLE_JEMALLOC BOOL false
|
append_cache_entry ENABLE_JEMALLOC BOOL false
|
||||||
|
append_cache_entry ENABLE_BROKER BOOL true
|
||||||
append_cache_entry BinPAC_SKIP_INSTALL BOOL true
|
append_cache_entry BinPAC_SKIP_INSTALL BOOL true
|
||||||
append_cache_entry BUILD_SHARED_LIBS BOOL true
|
append_cache_entry BUILD_SHARED_LIBS BOOL true
|
||||||
append_cache_entry INSTALL_AUX_TOOLS BOOL true
|
append_cache_entry INSTALL_AUX_TOOLS BOOL true
|
||||||
|
@ -135,6 +161,10 @@ while [ $# -ne 0 ]; do
|
||||||
append_cache_entry CMAKE_INSTALL_PREFIX PATH $optarg
|
append_cache_entry CMAKE_INSTALL_PREFIX PATH $optarg
|
||||||
append_cache_entry BRO_ROOT_DIR PATH $optarg
|
append_cache_entry BRO_ROOT_DIR PATH $optarg
|
||||||
append_cache_entry PY_MOD_INSTALL_DIR PATH $optarg/lib/broctl
|
append_cache_entry PY_MOD_INSTALL_DIR PATH $optarg/lib/broctl
|
||||||
|
|
||||||
|
if [ -z "$user_disabled_broker" ]; then
|
||||||
|
append_cache_entry BROKER_PYTHON_HOME PATH $optarg
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
--scriptdir=*)
|
--scriptdir=*)
|
||||||
append_cache_entry BRO_SCRIPT_INSTALL_PATH STRING $optarg
|
append_cache_entry BRO_SCRIPT_INSTALL_PATH STRING $optarg
|
||||||
|
@ -144,6 +174,15 @@ while [ $# -ne 0 ]; do
|
||||||
append_cache_entry BRO_ETC_INSTALL_DIR PATH $optarg
|
append_cache_entry BRO_ETC_INSTALL_DIR PATH $optarg
|
||||||
user_set_conffilesdir="true"
|
user_set_conffilesdir="true"
|
||||||
;;
|
;;
|
||||||
|
--localstatedir=*)
|
||||||
|
append_cache_entry BRO_LOCAL_STATE_DIR PATH $optarg
|
||||||
|
;;
|
||||||
|
--spooldir=*)
|
||||||
|
append_cache_entry BRO_SPOOL_DIR PATH $optarg
|
||||||
|
;;
|
||||||
|
--logdir=*)
|
||||||
|
append_cache_entry BRO_LOG_DIR PATH $optarg
|
||||||
|
;;
|
||||||
--enable-debug)
|
--enable-debug)
|
||||||
append_cache_entry ENABLE_DEBUG BOOL true
|
append_cache_entry ENABLE_DEBUG BOOL true
|
||||||
;;
|
;;
|
||||||
|
@ -160,6 +199,11 @@ while [ $# -ne 0 ]; do
|
||||||
--enable-jemalloc)
|
--enable-jemalloc)
|
||||||
append_cache_entry ENABLE_JEMALLOC BOOL true
|
append_cache_entry ENABLE_JEMALLOC BOOL true
|
||||||
;;
|
;;
|
||||||
|
--disable-broker)
|
||||||
|
append_cache_entry ENABLE_BROKER BOOL false
|
||||||
|
remove_cache_entry BROKER_PYTHON_HOME
|
||||||
|
user_disabled_broker="true"
|
||||||
|
;;
|
||||||
--disable-broccoli)
|
--disable-broccoli)
|
||||||
append_cache_entry INSTALL_BROCCOLI BOOL false
|
append_cache_entry INSTALL_BROCCOLI BOOL false
|
||||||
;;
|
;;
|
||||||
|
@ -175,6 +219,9 @@ while [ $# -ne 0 ]; do
|
||||||
--disable-python)
|
--disable-python)
|
||||||
append_cache_entry DISABLE_PYTHON_BINDINGS BOOL true
|
append_cache_entry DISABLE_PYTHON_BINDINGS BOOL true
|
||||||
;;
|
;;
|
||||||
|
--disable-pybroker)
|
||||||
|
append_cache_entry DISABLE_PYBROKER BOOL true
|
||||||
|
;;
|
||||||
--enable-ruby)
|
--enable-ruby)
|
||||||
append_cache_entry DISABLE_RUBY_BINDINGS BOOL false
|
append_cache_entry DISABLE_RUBY_BINDINGS BOOL false
|
||||||
;;
|
;;
|
||||||
|
@ -196,9 +243,6 @@ while [ $# -ne 0 ]; do
|
||||||
--with-bison=*)
|
--with-bison=*)
|
||||||
append_cache_entry BISON_EXECUTABLE PATH $optarg
|
append_cache_entry BISON_EXECUTABLE PATH $optarg
|
||||||
;;
|
;;
|
||||||
--with-perl=*)
|
|
||||||
append_cache_entry PERL_EXECUTABLE PATH $optarg
|
|
||||||
;;
|
|
||||||
--with-geoip=*)
|
--with-geoip=*)
|
||||||
append_cache_entry LibGeoIP_ROOT_DIR PATH $optarg
|
append_cache_entry LibGeoIP_ROOT_DIR PATH $optarg
|
||||||
;;
|
;;
|
||||||
|
@ -232,6 +276,12 @@ while [ $# -ne 0 ]; do
|
||||||
--with-swig=*)
|
--with-swig=*)
|
||||||
append_cache_entry SWIG_EXECUTABLE PATH $optarg
|
append_cache_entry SWIG_EXECUTABLE PATH $optarg
|
||||||
;;
|
;;
|
||||||
|
--with-libcaf=*)
|
||||||
|
append_cache_entry LIBCAF_ROOT_DIR PATH $optarg
|
||||||
|
;;
|
||||||
|
--with-rocksdb=*)
|
||||||
|
append_cache_entry ROCKSDB_ROOT_DIR PATH $optarg
|
||||||
|
;;
|
||||||
--binary-package)
|
--binary-package)
|
||||||
append_cache_entry BINARY_PACKAGING_MODE BOOL true
|
append_cache_entry BINARY_PACKAGING_MODE BOOL true
|
||||||
;;
|
;;
|
||||||
|
|
1
doc/components/bro-plugins/README.rst
Symbolic link
1
doc/components/bro-plugins/README.rst
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../aux/plugins/README
|
1
doc/components/bro-plugins/dataseries/README.rst
Symbolic link
1
doc/components/bro-plugins/dataseries/README.rst
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../../aux/plugins/dataseries/README
|
1
doc/components/bro-plugins/elasticsearch/README.rst
Symbolic link
1
doc/components/bro-plugins/elasticsearch/README.rst
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../../aux/plugins/elasticsearch/README
|
1
doc/components/bro-plugins/netmap/README.rst
Symbolic link
1
doc/components/bro-plugins/netmap/README.rst
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../../aux/plugins/netmap/README
|
1
doc/components/bro-plugins/pf_ring/README.rst
Symbolic link
1
doc/components/bro-plugins/pf_ring/README.rst
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../../aux/plugins/pf_ring/README
|
1
doc/components/bro-plugins/redis/README.rst
Symbolic link
1
doc/components/bro-plugins/redis/README.rst
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../../aux/plugins/redis/README
|
1
doc/components/broker/README.rst
Symbolic link
1
doc/components/broker/README.rst
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../aux/broker/README
|
1
doc/components/broker/broker-manual.rst
Symbolic link
1
doc/components/broker/broker-manual.rst
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../../aux/broker/broker-manual.rst
|
|
@ -17,8 +17,11 @@ current, independent component releases.
|
||||||
Broccoli - User Manual <broccoli/broccoli-manual>
|
Broccoli - User Manual <broccoli/broccoli-manual>
|
||||||
Broccoli Python Bindings <broccoli-python/README>
|
Broccoli Python Bindings <broccoli-python/README>
|
||||||
Broccoli Ruby Bindings <broccoli-ruby/README>
|
Broccoli Ruby Bindings <broccoli-ruby/README>
|
||||||
|
Broker - Bro's (New) Messaging Library (README) <broker/README>
|
||||||
|
Broker - User Manual <broker/broker-manual.rst>
|
||||||
BroControl - Interactive Bro management shell <broctl/README>
|
BroControl - Interactive Bro management shell <broctl/README>
|
||||||
Bro-Aux - Small auxiliary tools for Bro <bro-aux/README>
|
Bro-Aux - Small auxiliary tools for Bro <bro-aux/README>
|
||||||
|
Bro-Plugins - A collection of plugins for Bro <bro-plugins/README>
|
||||||
BTest - A unit testing framework <btest/README>
|
BTest - A unit testing framework <btest/README>
|
||||||
Capstats - Command-line packet statistic tool <capstats/README>
|
Capstats - Command-line packet statistic tool <capstats/README>
|
||||||
PySubnetTree - Python module for CIDR lookups<pysubnettree/README>
|
PySubnetTree - Python module for CIDR lookups<pysubnettree/README>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
Writing Bro Plugins
|
Writing Bro Plugins
|
||||||
===================
|
===================
|
||||||
|
|
||||||
Bro is internally moving to a plugin structure that enables extending
|
Bro internally provides a plugin API that enables extending
|
||||||
the system dynamically, without modifying the core code base. That way
|
the system dynamically, without modifying the core code base. That way
|
||||||
custom code remains self-contained and can be maintained, compiled,
|
custom code remains self-contained and can be maintained, compiled,
|
||||||
and installed independently. Currently, plugins can add the following
|
and installed independently. Currently, plugins can add the following
|
||||||
|
@ -17,11 +17,11 @@ functionality to Bro:
|
||||||
|
|
||||||
- File analyzers.
|
- File analyzers.
|
||||||
|
|
||||||
- Packet sources and packet dumpers. TODO: Not yet.
|
- Packet sources and packet dumpers.
|
||||||
|
|
||||||
- Logging framework backends. TODO: Not yet.
|
- Logging framework backends.
|
||||||
|
|
||||||
- Input framework readers. TODO: Not yet.
|
- Input framework readers.
|
||||||
|
|
||||||
A plugin's functionality is available to the user just as if Bro had
|
A plugin's functionality is available to the user just as if Bro had
|
||||||
the corresponding code built-in. Indeed, internally many of Bro's
|
the corresponding code built-in. Indeed, internally many of Bro's
|
||||||
|
@ -32,7 +32,7 @@ Quick Start
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Writing a basic plugin is quite straight-forward as long as one
|
Writing a basic plugin is quite straight-forward as long as one
|
||||||
follows a few conventions. In the following we walk a simple example
|
follows a few conventions. In the following we create a simple example
|
||||||
plugin that adds a new built-in function (bif) to Bro: we'll add
|
plugin that adds a new built-in function (bif) to Bro: we'll add
|
||||||
``rot13(s: string) : string``, a function that rotates every character
|
``rot13(s: string) : string``, a function that rotates every character
|
||||||
in a string by 13 places.
|
in a string by 13 places.
|
||||||
|
@ -42,18 +42,17 @@ certain structure. To get started, Bro's distribution provides a
|
||||||
helper script ``aux/bro-aux/plugin-support/init-plugin`` that creates
|
helper script ``aux/bro-aux/plugin-support/init-plugin`` that creates
|
||||||
a skeleton plugin that can then be customized. Let's use that::
|
a skeleton plugin that can then be customized. Let's use that::
|
||||||
|
|
||||||
# mkdir rot13-plugin
|
# init-plugin ./rot13-plugin Demo Rot13
|
||||||
# cd rot13-plugin
|
|
||||||
# init-plugin Demo Rot13
|
|
||||||
|
|
||||||
As you can see the script takes two arguments. The first is a
|
As you can see, the script takes three arguments. The first is a
|
||||||
namespace the plugin will live in, and the second a descriptive name
|
directory inside which the plugin skeleton will be created. The second
|
||||||
for the plugin itself. Bro uses the combination of the two to identify
|
is the namespace the plugin will live in, and the third is a descriptive
|
||||||
a plugin. The namespace serves to avoid naming conflicts between
|
name for the plugin itself relative to the namespace. Bro uses the
|
||||||
plugins written by independent developers; pick, e.g., the name of
|
combination of namespace and name to identify a plugin. The namespace
|
||||||
your organisation. The namespace ``Bro`` is reserved for functionality
|
serves to avoid naming conflicts between plugins written by independent
|
||||||
distributed by the Bro Project. In our example, the plugin will be
|
developers; pick, e.g., the name of your organisation. The namespace
|
||||||
called ``Demo::Rot13``.
|
``Bro`` is reserved for functionality distributed by the Bro Project. In
|
||||||
|
our example, the plugin will be called ``Demo::Rot13``.
|
||||||
|
|
||||||
The ``init-plugin`` script puts a number of files in place. The full
|
The ``init-plugin`` script puts a number of files in place. The full
|
||||||
layout is described later. For now, all we need is
|
layout is described later. For now, all we need is
|
||||||
|
@ -61,7 +60,7 @@ layout is described later. For now, all we need is
|
||||||
there as follows::
|
there as follows::
|
||||||
|
|
||||||
# cat src/rot13.bif
|
# cat src/rot13.bif
|
||||||
module CaesarCipher;
|
module Demo;
|
||||||
|
|
||||||
function rot13%(s: string%) : string
|
function rot13%(s: string%) : string
|
||||||
%{
|
%{
|
||||||
|
@ -82,21 +81,25 @@ The syntax of this file is just like any other ``*.bif`` file; we
|
||||||
won't go into it here.
|
won't go into it here.
|
||||||
|
|
||||||
Now we can already compile our plugin, we just need to tell the
|
Now we can already compile our plugin, we just need to tell the
|
||||||
configure script put in place by ``init-plugin`` where the Bro source
|
configure script (that ``init-plugin`` created) where the Bro
|
||||||
tree is located (Bro needs to have been built there first)::
|
source tree is located (Bro needs to have been built there first)::
|
||||||
|
|
||||||
|
# cd rot13-plugin
|
||||||
# ./configure --bro-dist=/path/to/bro/dist && make
|
# ./configure --bro-dist=/path/to/bro/dist && make
|
||||||
[... cmake output ...]
|
[... cmake output ...]
|
||||||
|
|
||||||
Now our ``rot13-plugin`` directory has everything that it needs
|
This builds the plugin in a subdirectory ``build/``. In fact, that
|
||||||
for Bro to recognize it as a dynamic plugin. Once we point Bro to it,
|
subdirectory *becomes* the plugin: when ``make`` finishes, ``build/``
|
||||||
it will pull it in automatically, as we can check with the ``-N``
|
has everything it needs for Bro to recognize it as a dynamic plugin.
|
||||||
|
|
||||||
|
Let's try that. Once we point Bro to the ``build/`` directory, it will
|
||||||
|
pull in our new plugin automatically, as we can check with the ``-N``
|
||||||
option::
|
option::
|
||||||
|
|
||||||
# export BRO_PLUGIN_PATH=/path/to/rot13-plugin
|
# export BRO_PLUGIN_PATH=/path/to/rot13-plugin/build
|
||||||
# bro -N
|
# bro -N
|
||||||
[...]
|
[...]
|
||||||
Plugin: Demo::Rot13 - <Insert brief description of plugin> (dynamic, version 1)
|
Demo::Rot13 - <Insert description> (dynamic, version 0.1)
|
||||||
[...]
|
[...]
|
||||||
|
|
||||||
That looks quite good, except for the dummy description that we should
|
That looks quite good, except for the dummy description that we should
|
||||||
|
@ -105,34 +108,36 @@ is about. We do this by editing the ``config.description`` line in
|
||||||
``src/Plugin.cc``, like this::
|
``src/Plugin.cc``, like this::
|
||||||
|
|
||||||
[...]
|
[...]
|
||||||
plugin::Configuration Configure()
|
plugin::Configuration Plugin::Configure()
|
||||||
{
|
{
|
||||||
plugin::Configuration config;
|
plugin::Configuration config;
|
||||||
config.name = "Demo::Rot13";
|
config.name = "Demo::Rot13";
|
||||||
config.description = "Caesar cipher rotating a string's characters by 13 places.";
|
config.description = "Caesar cipher rotating a string's characters by 13 places.";
|
||||||
config.version.major = 1;
|
config.version.major = 0;
|
||||||
config.version.minor = 0;
|
config.version.minor = 1;
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
[...]
|
[...]
|
||||||
|
|
||||||
|
Now rebuild and verify that the description is visible::
|
||||||
|
|
||||||
# make
|
# make
|
||||||
[...]
|
[...]
|
||||||
# bro -N | grep Rot13
|
# bro -N | grep Rot13
|
||||||
Plugin: Demo::Rot13 - Caesar cipher rotating a string's characters by 13 places. (dynamic, version 1)
|
Demo::Rot13 - Caesar cipher rotating a string's characters by 13 places. (dynamic, version 0.1)
|
||||||
|
|
||||||
Better. Bro can also show us what exactly the plugin provides with the
|
Bro can also show us what exactly the plugin provides with the
|
||||||
more verbose option ``-NN``::
|
more verbose option ``-NN``::
|
||||||
|
|
||||||
# bro -NN
|
# bro -NN
|
||||||
[...]
|
[...]
|
||||||
Plugin: Demo::Rot13 - Caesar cipher rotating a string's characters by 13 places. (dynamic, version 1)
|
Demo::Rot13 - Caesar cipher rotating a string's characters by 13 places. (dynamic, version 0.1)
|
||||||
[Function] CaesarCipher::rot13
|
[Function] Demo::rot13
|
||||||
[...]
|
[...]
|
||||||
|
|
||||||
There's our function. Now let's use it::
|
There's our function. Now let's use it::
|
||||||
|
|
||||||
# bro -e 'print CaesarCipher::rot13("Hello")'
|
# bro -e 'print Demo::rot13("Hello")'
|
||||||
Uryyb
|
Uryyb
|
||||||
|
|
||||||
It works. We next install the plugin along with Bro itself, so that it
|
It works. We next install the plugin along with Bro itself, so that it
|
||||||
|
@ -141,36 +146,42 @@ environment variable. If we first unset the variable, the function
|
||||||
will no longer be available::
|
will no longer be available::
|
||||||
|
|
||||||
# unset BRO_PLUGIN_PATH
|
# unset BRO_PLUGIN_PATH
|
||||||
# bro -e 'print CaesarCipher::rot13("Hello")'
|
# bro -e 'print Demo::rot13("Hello")'
|
||||||
error in <command line>, line 1: unknown identifier CaesarCipher::rot13, at or near "CaesarCipher::rot13"
|
error in <command line>, line 1: unknown identifier Demo::rot13, at or near "Demo::rot13"
|
||||||
|
|
||||||
Once we install it, it works again::
|
Once we install it, it works again::
|
||||||
|
|
||||||
# make install
|
# make install
|
||||||
# bro -e 'print CaesarCipher::rot13("Hello")'
|
# bro -e 'print Demo::rot13("Hello")'
|
||||||
Uryyb
|
Uryyb
|
||||||
|
|
||||||
The installed version went into
|
The installed version went into
|
||||||
``<bro-install-prefix>/lib/bro/plugins/Demo_Rot13``.
|
``<bro-install-prefix>/lib/bro/plugins/Demo_Rot13``.
|
||||||
|
|
||||||
We can distribute the plugin in either source or binary form by using
|
One can distribute the plugin independently of Bro for others to use.
|
||||||
the Makefile's ``sdist`` and ``bdist`` target, respectively. Both
|
To distribute in source form, just remove the ``build/`` directory
|
||||||
create corrsponding tarballs::
|
(``make distclean`` does that) and then tar up the whole ``rot13-plugin/``
|
||||||
|
directory. Others then follow the same process as above after
|
||||||
|
unpacking.
|
||||||
|
|
||||||
# make sdist
|
To distribute the plugin in binary form, the build process
|
||||||
[...]
|
conveniently creates a corresponding tarball in ``build/dist/``. In
|
||||||
Source distribution in build/sdist/Demo_Rot13.tar.gz
|
this case, it's called ``Demo_Rot13-0.1.tar.gz``, with the version
|
||||||
|
number coming out of the ``VERSION`` file that ``init-plugin`` put
|
||||||
|
into place. The binary tarball has everything needed to run the
|
||||||
|
plugin, but no further source files. Optionally, one can include
|
||||||
|
further files by specifying them in the plugin's ``CMakeLists.txt``
|
||||||
|
through the ``bro_plugin_dist_files`` macro; the skeleton does that
|
||||||
|
for ``README``, ``VERSION``, ``CHANGES``, and ``COPYING``. To use the
|
||||||
|
plugin through the binary tarball, just unpack it into
|
||||||
|
``<bro-install-prefix>/lib/bro/plugins/``. Alternatively, if you unpack
|
||||||
|
it in another location, then you need to point ``BRO_PLUGIN_PATH`` there.
|
||||||
|
|
||||||
# make bdist
|
Before distributing your plugin, you should edit some of the meta
|
||||||
[...]
|
files that ``init-plugin`` puts in place. Edit ``README`` and
|
||||||
Binary distribution in build/Demo_Rot13-darwin-x86_64.tar.gz
|
``VERSION``, and update ``CHANGES`` when you make changes. Also put a
|
||||||
|
license file in place as ``COPYING``; if BSD is fine, you will find a
|
||||||
The source archive will contain everything in the plugin directory
|
template in ``COPYING.edit-me``.
|
||||||
except any generated files. The binary archive will contain anything
|
|
||||||
needed to install and run the plugin, i.e., just what ``make install``
|
|
||||||
puts into place as well. As the binary distribution is
|
|
||||||
platform-dependent, its name includes the OS and architecture the
|
|
||||||
plugin was built on.
|
|
||||||
|
|
||||||
Plugin Directory Layout
|
Plugin Directory Layout
|
||||||
=======================
|
=======================
|
||||||
|
@ -179,14 +190,14 @@ A plugin's directory needs to follow a set of conventions so that Bro
|
||||||
(1) recognizes it as a plugin, and (2) knows what to load. While
|
(1) recognizes it as a plugin, and (2) knows what to load. While
|
||||||
``init-plugin`` takes care of most of this, the following is the full
|
``init-plugin`` takes care of most of this, the following is the full
|
||||||
story. We'll use ``<base>`` to represent a plugin's top-level
|
story. We'll use ``<base>`` to represent a plugin's top-level
|
||||||
directory.
|
directory. With the skeleton, ``<base>`` corresponds to ``build/``.
|
||||||
|
|
||||||
``<base>/__bro_plugin__``
|
``<base>/__bro_plugin__``
|
||||||
A file that marks a directory as containing a Bro plugin. The file
|
A file that marks a directory as containing a Bro plugin. The file
|
||||||
must exist, and its content must consist of a single line with the
|
must exist, and its content must consist of a single line with the
|
||||||
qualified name of the plugin (e.g., "Demo::Rot13").
|
qualified name of the plugin (e.g., "Demo::Rot13").
|
||||||
|
|
||||||
``<base>/lib/<plugin-name>-<os>-<arch>.so``
|
``<base>/lib/<plugin-name>.<os>-<arch>.so``
|
||||||
The shared library containing the plugin's compiled code. Bro will
|
The shared library containing the plugin's compiled code. Bro will
|
||||||
load this in dynamically at run-time if OS and architecture match
|
load this in dynamically at run-time if OS and architecture match
|
||||||
the current platform.
|
the current platform.
|
||||||
|
@ -198,16 +209,25 @@ directory.
|
||||||
"@load"ed.
|
"@load"ed.
|
||||||
|
|
||||||
``scripts``/__load__.bro
|
``scripts``/__load__.bro
|
||||||
A Bro script that will be loaded immediately when the plugin gets
|
A Bro script that will be loaded when the plugin gets activated.
|
||||||
activated. See below for more information on activating plugins.
|
When this script executes, any BiF elements that the plugin
|
||||||
|
defines will already be available. See below for more information
|
||||||
|
on activating plugins.
|
||||||
|
|
||||||
|
``scripts``/__preload__.bro
|
||||||
|
A Bro script that will be loaded when the plugin gets activated,
|
||||||
|
but before any BiF elements become available. See below for more
|
||||||
|
information on activating plugins.
|
||||||
|
|
||||||
``lib/bif/``
|
``lib/bif/``
|
||||||
Directory with auto-generated Bro scripts that declare the plugin's
|
Directory with auto-generated Bro scripts that declare the plugin's
|
||||||
bif elements. The files here are produced by ``bifcl``.
|
bif elements. The files here are produced by ``bifcl``.
|
||||||
|
|
||||||
|
Any other files in ``<base>`` are ignored by Bro.
|
||||||
|
|
||||||
By convention, a plugin should put its custom scripts into sub folders
|
By convention, a plugin should put its custom scripts into sub folders
|
||||||
of ``scripts/``, i.e., ``scripts/<script-namespace>/<script>.bro`` to
|
of ``scripts/``, i.e., ``scripts/<plugin-namespace>/<plugin-name>/<script>.bro``
|
||||||
avoid conflicts. As usual, you can then put a ``__load__.bro`` in
|
to avoid conflicts. As usual, you can then put a ``__load__.bro`` in
|
||||||
there as well so that, e.g., ``@load Demo/Rot13`` could load a whole
|
there as well so that, e.g., ``@load Demo/Rot13`` could load a whole
|
||||||
module in the form of multiple individual scripts.
|
module in the form of multiple individual scripts.
|
||||||
|
|
||||||
|
@ -229,15 +249,33 @@ their source directory (after ``make`` and setting Bro's
|
||||||
install``).
|
install``).
|
||||||
|
|
||||||
``make install`` copies over the ``lib`` and ``scripts`` directories,
|
``make install`` copies over the ``lib`` and ``scripts`` directories,
|
||||||
as well as the ``__bro_plugin__`` magic file and the ``README`` (which
|
as well as the ``__bro_plugin__`` magic file and any further
|
||||||
you should customize). One can add further CMake ``install`` rules to
|
distribution files specified in ``CMakeLists.txt`` (e.g., README,
|
||||||
install additional files if needed.
|
VERSION). You can find a full list of files installed in
|
||||||
|
``build/MANIFEST``. Behind the scenes, ``make install`` really just
|
||||||
|
unpacks the binary tarball from ``build/dist`` into the destination
|
||||||
|
directory.
|
||||||
|
|
||||||
``init-plugin`` will never overwrite existing files, so it's safe to
|
``init-plugin`` will never overwrite existing files. If its target
|
||||||
rerun in an existing plugin directory; it only put files in place that
|
directory already exists, it will by default decline to do anything.
|
||||||
don't exist yet. That also provides a convenient way to revert a file
|
You can run it with ``-u`` instead to update an existing plugin,
|
||||||
back to what ``init-plugin`` created originally: just delete it and
|
however it will never overwrite any existing files; it will only put
|
||||||
rerun.
|
in place files it doesn't find yet. To revert a file back to what
|
||||||
|
``init-plugin`` created originally, delete it first and then rerun
|
||||||
|
with ``-u``.
|
||||||
|
|
||||||
|
``init-plugin`` puts a ``configure`` script in place that wraps
|
||||||
|
``cmake`` with a more familiar configure-style configuration. By
|
||||||
|
default, the script provides two options for specifying paths to the
|
||||||
|
Bro source (``--bro-dist``) and to the plugin's installation directory
|
||||||
|
(``--install-root``). To extend ``configure`` with plugin-specific
|
||||||
|
options (such as search paths for its dependencies) don't edit the
|
||||||
|
script directly but instead extend ``configure.plugin``, which
|
||||||
|
``configure`` includes. That way you will be able to more easily
|
||||||
|
update ``configure`` in the future when the distribution version
|
||||||
|
changes. In ``configure.plugin`` you can use the predefined shell
|
||||||
|
function ``append_cache_entry`` to seed values into the CMake cache;
|
||||||
|
see the installed skeleton version and existing plugins for examples.
|
||||||
|
|
||||||
Activating a Plugin
|
Activating a Plugin
|
||||||
===================
|
===================
|
||||||
|
@ -248,7 +286,9 @@ Activating a plugin will:
|
||||||
1. Load the dynamic module
|
1. Load the dynamic module
|
||||||
2. Make any bif items available
|
2. Make any bif items available
|
||||||
3. Add the ``scripts/`` directory to ``BROPATH``
|
3. Add the ``scripts/`` directory to ``BROPATH``
|
||||||
4. Load ``scripts/__load__.bro``
|
4. Load ``scripts/__preload__.bro``
|
||||||
|
5. Make BiF elements available to scripts.
|
||||||
|
6. Load ``scripts/__load__.bro``
|
||||||
|
|
||||||
By default, Bro will automatically activate all dynamic plugins found
|
By default, Bro will automatically activate all dynamic plugins found
|
||||||
in its search path ``BRO_PLUGIN_PATH``. However, in bare mode (``bro
|
in its search path ``BRO_PLUGIN_PATH``. However, in bare mode (``bro
|
||||||
|
@ -265,23 +305,25 @@ plugins to unconditionally activate, even in bare mode.
|
||||||
activated plugins. Note that plugins compiled statically into Bro are
|
activated plugins. Note that plugins compiled statically into Bro are
|
||||||
always activated, and hence show up as such even in bare mode.
|
always activated, and hence show up as such even in bare mode.
|
||||||
|
|
||||||
Plugin Component
|
Plugin Components
|
||||||
================
|
=================
|
||||||
|
|
||||||
The following gives additional information about providing individual
|
The following subsections detail providing individual types of
|
||||||
types of functionality via plugins. Note that a single plugin can
|
functionality via plugins. Note that a single plugin can provide more
|
||||||
provide more than one type. For example, a plugin could provide
|
than one component type. For example, a plugin could provide multiple
|
||||||
multiple protocol analyzers at once; or both a logging backend and
|
protocol analyzers at once; or both a logging backend and input reader
|
||||||
input reader at the same time.
|
at the same time.
|
||||||
|
|
||||||
We now walk briefly through the specifics of providing a specific type
|
.. todo::
|
||||||
of functionality (a *component*) through a plugin. We'll focus on
|
|
||||||
their interfaces to the plugin system, rather than specifics on
|
These subsections are mostly missing right now, as much of their
|
||||||
writing the corresponding logic (usually the best way to get going on
|
content isn't actually plugin-specific, but concerns generally
|
||||||
that is to start with an existing plugin providing a corresponding
|
writing such functionality for Bro. The best way to get started
|
||||||
component and adapt that). We'll also point out how the CMake
|
right now is to look at existing code implementing similar
|
||||||
infrastructure put in place by the ``init-plugin`` helper script ties
|
functionality, either as a plugin or inside Bro proper. Also, for
|
||||||
the various pieces together.
|
each component type there's a unit test in
|
||||||
|
``testing/btest/plugins`` creating a basic plugin skeleton with a
|
||||||
|
corresponding component.
|
||||||
|
|
||||||
Bro Scripts
|
Bro Scripts
|
||||||
-----------
|
-----------
|
||||||
|
@ -315,22 +357,22 @@ TODO.
|
||||||
Logging Writer
|
Logging Writer
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Not yet available as plugins.
|
TODO.
|
||||||
|
|
||||||
Input Reader
|
Input Reader
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Not yet available as plugins.
|
TODO.
|
||||||
|
|
||||||
Packet Sources
|
Packet Sources
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Not yet available as plugins.
|
TODO.
|
||||||
|
|
||||||
Packet Dumpers
|
Packet Dumpers
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Not yet available as plugins.
|
TODO.
|
||||||
|
|
||||||
Hooks
|
Hooks
|
||||||
=====
|
=====
|
||||||
|
@ -341,19 +383,20 @@ Testing Plugins
|
||||||
===============
|
===============
|
||||||
|
|
||||||
A plugin should come with a test suite to exercise its functionality.
|
A plugin should come with a test suite to exercise its functionality.
|
||||||
The ``init-plugin`` script puts in place a basic </btest/README> setup
|
The ``init-plugin`` script puts in place a basic
|
||||||
|
:doc:`BTest <../../components/btest/README>` setup
|
||||||
to start with. Initially, it comes with a single test that just checks
|
to start with. Initially, it comes with a single test that just checks
|
||||||
that Bro loads the plugin correctly. It won't have a baseline yet, so
|
that Bro loads the plugin correctly. It won't have a baseline yet, so
|
||||||
let's get that in place::
|
let's get that in place::
|
||||||
|
|
||||||
# cd tests
|
# cd tests
|
||||||
# btest -d
|
# btest -d
|
||||||
[ 0%] plugin.loading ... failed
|
[ 0%] rot13.show-plugin ... failed
|
||||||
% 'btest-diff output' failed unexpectedly (exit code 100)
|
% 'btest-diff output' failed unexpectedly (exit code 100)
|
||||||
% cat .diag
|
% cat .diag
|
||||||
== File ===============================
|
== File ===============================
|
||||||
Demo::Rot13 - Caesar cipher rotating a string's characters by 13 places. (dynamic, version 1.0)
|
Demo::Rot13 - Caesar cipher rotating a string's characters by 13 places. (dynamic, version 0.1)
|
||||||
[Function] CaesarCipher::rot13
|
[Function] Demo::rot13
|
||||||
|
|
||||||
== Error ===============================
|
== Error ===============================
|
||||||
test-diff: no baseline found.
|
test-diff: no baseline found.
|
||||||
|
@ -373,20 +416,20 @@ Now let's add a custom test that ensures that our bif works
|
||||||
correctly::
|
correctly::
|
||||||
|
|
||||||
# cd tests
|
# cd tests
|
||||||
# cat >plugin/rot13.bro
|
# cat >rot13/bif-rot13.bro
|
||||||
|
|
||||||
# @TEST-EXEC: bro %INPUT >output
|
# @TEST-EXEC: bro %INPUT >output
|
||||||
# @TEST-EXEC: btest-diff output
|
# @TEST-EXEC: btest-diff output
|
||||||
|
|
||||||
event bro_init()
|
event bro_init()
|
||||||
{
|
{
|
||||||
print CaesarCipher::rot13("Hello");
|
print Demo::rot13("Hello");
|
||||||
}
|
}
|
||||||
|
|
||||||
Check the output::
|
Check the output::
|
||||||
|
|
||||||
# btest -d plugin/rot13.bro
|
# btest -d rot13/bif-rot13.bro
|
||||||
[ 0%] plugin.rot13 ... failed
|
[ 0%] rot13.bif-rot13 ... failed
|
||||||
% 'btest-diff output' failed unexpectedly (exit code 100)
|
% 'btest-diff output' failed unexpectedly (exit code 100)
|
||||||
% cat .diag
|
% cat .diag
|
||||||
== File ===============================
|
== File ===============================
|
||||||
|
@ -401,7 +444,7 @@ Check the output::
|
||||||
|
|
||||||
Install the baseline::
|
Install the baseline::
|
||||||
|
|
||||||
# btest -U plugin/rot13.bro
|
# btest -U rot13/bif-rot13.bro
|
||||||
all 1 tests successful
|
all 1 tests successful
|
||||||
|
|
||||||
Run the test-suite::
|
Run the test-suite::
|
||||||
|
@ -412,25 +455,31 @@ Run the test-suite::
|
||||||
Debugging Plugins
|
Debugging Plugins
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Plugins can use Bro's standard debug logger by using the
|
If your plugin isn't loading as expected, Bro's debugging facilities
|
||||||
``PLUGIN_DBG_LOG(<plugin>, <args>)`` macro (defined in
|
can help illuminate what's going on. To enable, recompile Bro
|
||||||
``DebugLogger.h``), where ``<plugin>`` is the ``Plugin`` instance and
|
with debugging support (``./configure --enable-debug``), and
|
||||||
``<args>`` are printf-style arguments, just as with Bro's standard
|
afterwards rebuild your plugin as well. If you then run Bro with ``-B
|
||||||
debuggging macros.
|
plugins``, it will produce a file ``debug.log`` that records details
|
||||||
|
about the process for searching, loading, and activating plugins.
|
||||||
At runtime, one then activates a plugin's debugging output with ``-B
|
|
||||||
plugin-<name>``, where ``<name>`` is the name of the plugin as
|
|
||||||
returned by its ``Configure()`` method, yet with the
|
|
||||||
namespace-separator ``::`` replaced with a simple dash. Example: If
|
|
||||||
the plugin is called ``Bro::Demo``, use ``-B plugin-Bro-Demo``. As
|
|
||||||
usual, the debugging output will be recorded to ``debug.log`` if Bro's
|
|
||||||
compiled in debug mode.
|
|
||||||
|
|
||||||
|
To generate your own debugging output from inside your plugin, you can
|
||||||
|
add a custom debug stream by using the ``PLUGIN_DBG_LOG(<plugin>,
|
||||||
|
<args>)`` macro (defined in ``DebugLogger.h``), where ``<plugin>`` is
|
||||||
|
the ``Plugin`` instance and ``<args>`` are printf-style arguments,
|
||||||
|
just as with Bro's standard debugging macros (grep for ``DBG_LOG`` in
|
||||||
|
Bro's ``src/`` to see examples). At runtime, you can then activate
|
||||||
|
your plugin's debugging output with ``-B plugin-<name>``, where
|
||||||
|
``<name>`` is the name of the plugin as returned by its
|
||||||
|
``Configure()`` method, yet with the namespace-separator ``::``
|
||||||
|
replaced with a simple dash. Example: If the plugin is called
|
||||||
|
``Demo::Rot13``, use ``-B plugin-Demo-Rot13``. As usual, the debugging
|
||||||
|
output will be recorded to ``debug.log`` if Bro's compiled in debug
|
||||||
|
mode.
|
||||||
|
|
||||||
Documenting Plugins
|
Documenting Plugins
|
||||||
===================
|
===================
|
||||||
|
|
||||||
..todo::
|
.. todo::
|
||||||
|
|
||||||
Integrate all this with Broxygen.
|
Integrate all this with Broxygen.
|
||||||
|
|
||||||
|
|
|
@ -176,6 +176,10 @@ class BroIdentifier(BroGeneric):
|
||||||
def get_index_text(self, objectname, name):
|
def get_index_text(self, objectname, name):
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
class BroKeyword(BroGeneric):
|
||||||
|
def get_index_text(self, objectname, name):
|
||||||
|
return name
|
||||||
|
|
||||||
class BroAttribute(BroGeneric):
|
class BroAttribute(BroGeneric):
|
||||||
def get_index_text(self, objectname, name):
|
def get_index_text(self, objectname, name):
|
||||||
return _('%s (attribute)') % (name)
|
return _('%s (attribute)') % (name)
|
||||||
|
@ -213,6 +217,7 @@ class BroDomain(Domain):
|
||||||
'type': ObjType(l_('type'), 'type'),
|
'type': ObjType(l_('type'), 'type'),
|
||||||
'namespace': ObjType(l_('namespace'), 'namespace'),
|
'namespace': ObjType(l_('namespace'), 'namespace'),
|
||||||
'id': ObjType(l_('id'), 'id'),
|
'id': ObjType(l_('id'), 'id'),
|
||||||
|
'keyword': ObjType(l_('keyword'), 'keyword'),
|
||||||
'enum': ObjType(l_('enum'), 'enum'),
|
'enum': ObjType(l_('enum'), 'enum'),
|
||||||
'attr': ObjType(l_('attr'), 'attr'),
|
'attr': ObjType(l_('attr'), 'attr'),
|
||||||
}
|
}
|
||||||
|
@ -221,6 +226,7 @@ class BroDomain(Domain):
|
||||||
'type': BroGeneric,
|
'type': BroGeneric,
|
||||||
'namespace': BroNamespace,
|
'namespace': BroNamespace,
|
||||||
'id': BroIdentifier,
|
'id': BroIdentifier,
|
||||||
|
'keyword': BroKeyword,
|
||||||
'enum': BroEnum,
|
'enum': BroEnum,
|
||||||
'attr': BroAttribute,
|
'attr': BroAttribute,
|
||||||
}
|
}
|
||||||
|
@ -229,6 +235,7 @@ class BroDomain(Domain):
|
||||||
'type': XRefRole(),
|
'type': XRefRole(),
|
||||||
'namespace': XRefRole(),
|
'namespace': XRefRole(),
|
||||||
'id': XRefRole(),
|
'id': XRefRole(),
|
||||||
|
'keyword': XRefRole(),
|
||||||
'enum': XRefRole(),
|
'enum': XRefRole(),
|
||||||
'attr': XRefRole(),
|
'attr': XRefRole(),
|
||||||
'see': XRefRole(),
|
'see': XRefRole(),
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -135,7 +135,10 @@ class Pygments(Directive):
|
||||||
# lexer not found, use default.
|
# lexer not found, use default.
|
||||||
lexer = TextLexer()
|
lexer = TextLexer()
|
||||||
else:
|
else:
|
||||||
|
try:
|
||||||
lexer = guess_lexer(content)
|
lexer = guess_lexer(content)
|
||||||
|
except:
|
||||||
|
lexer = TextLexer()
|
||||||
|
|
||||||
# import sys
|
# import sys
|
||||||
# print >>sys.stderr, self.arguments, lexer.__class__
|
# print >>sys.stderr, self.arguments, lexer.__class__
|
||||||
|
|
200
doc/frameworks/broker.rst
Normal file
200
doc/frameworks/broker.rst
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
|
||||||
|
.. _brokercomm-framework:
|
||||||
|
|
||||||
|
======================================
|
||||||
|
Broker-Enabled Communication Framework
|
||||||
|
======================================
|
||||||
|
|
||||||
|
.. rst-class:: opening
|
||||||
|
|
||||||
|
Bro can now use the `Broker Library
|
||||||
|
<../components/broker/README.html>`_ to exchange information with
|
||||||
|
other Bro processes.
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
|
||||||
|
Connecting to Peers
|
||||||
|
===================
|
||||||
|
|
||||||
|
Communication via Broker must first be turned on via
|
||||||
|
:bro:see:`BrokerComm::enable`.
|
||||||
|
|
||||||
|
Bro can accept incoming connections by calling :bro:see:`BrokerComm::listen`
|
||||||
|
and then monitor connection status updates via the
|
||||||
|
:bro:see:`BrokerComm::incoming_connection_established` and
|
||||||
|
:bro:see:`BrokerComm::incoming_connection_broken` events.
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/connecting-listener.bro
|
||||||
|
|
||||||
|
Bro can initiate outgoing connections by calling :bro:see:`BrokerComm::connect`
|
||||||
|
and then monitor connection status updates via the
|
||||||
|
:bro:see:`BrokerComm::outgoing_connection_established`,
|
||||||
|
:bro:see:`BrokerComm::outgoing_connection_broken`, and
|
||||||
|
:bro:see:`BrokerComm::outgoing_connection_incompatible` events.
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/connecting-connector.bro
|
||||||
|
|
||||||
|
Remote Printing
|
||||||
|
===============
|
||||||
|
|
||||||
|
To receive remote print messages, first use the
|
||||||
|
:bro:see:`BrokerComm::subscribe_to_prints` function to advertise to peers a
|
||||||
|
topic prefix of interest and then create an event handler for
|
||||||
|
:bro:see:`BrokerComm::print_handler` to handle any print messages that are
|
||||||
|
received.
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/printing-listener.bro
|
||||||
|
|
||||||
|
To send remote print messages, just call :bro:see:`BrokerComm::print`.
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/printing-connector.bro
|
||||||
|
|
||||||
|
Notice that the subscriber only used the prefix "bro/print/", but is
|
||||||
|
able to receive messages with full topics of "bro/print/hi",
|
||||||
|
"bro/print/stuff", and "bro/print/bye". The model here is that the
|
||||||
|
publisher of a message checks for all subscribers who advertised
|
||||||
|
interest in a prefix of that message's topic and sends it to them.
|
||||||
|
|
||||||
|
Message Format
|
||||||
|
--------------
|
||||||
|
|
||||||
|
For other applications that want to exchange print messages with Bro,
|
||||||
|
the Broker message format is simply:
|
||||||
|
|
||||||
|
.. code:: c++
|
||||||
|
|
||||||
|
broker::message{std::string{}};
|
||||||
|
|
||||||
|
Remote Events
|
||||||
|
=============
|
||||||
|
|
||||||
|
Receiving remote events is similar to remote prints. Just use the
|
||||||
|
:bro:see:`BrokerComm::subscribe_to_events` function and possibly define any
|
||||||
|
new events along with handlers that peers may want to send.
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/events-listener.bro
|
||||||
|
|
||||||
|
There are two different ways to send events. The first is to call the
|
||||||
|
:bro:see:`BrokerComm::event` function directly. The second option is to call
|
||||||
|
the :bro:see:`BrokerComm::auto_event` function where you specify a
|
||||||
|
particular event that will be automatically sent to peers whenever the
|
||||||
|
event is called locally via the normal event invocation syntax.
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/events-connector.bro
|
||||||
|
|
||||||
|
Again, the subscription model is prefix-based.
|
||||||
|
|
||||||
|
Message Format
|
||||||
|
--------------
|
||||||
|
|
||||||
|
For other applications that want to exchange event messages with Bro,
|
||||||
|
the Broker message format is:
|
||||||
|
|
||||||
|
.. code:: c++
|
||||||
|
|
||||||
|
broker::message{std::string{}, ...};
|
||||||
|
|
||||||
|
The first parameter is the name of the event and the remaining ``...``
|
||||||
|
are its arguments, which are any of the supported Broker data types as
|
||||||
|
they correspond to the Bro types for the event named in the first
|
||||||
|
parameter of the message.
|
||||||
|
|
||||||
|
Remote Logging
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/testlog.bro
|
||||||
|
|
||||||
|
Use the :bro:see:`BrokerComm::subscribe_to_logs` function to advertise interest
|
||||||
|
in logs written by peers. The topic names that Bro uses are implicitly of the
|
||||||
|
form "bro/log/<stream-name>".
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/logs-listener.bro
|
||||||
|
|
||||||
|
To send remote logs either redef :bro:see:`Log::enable_remote_logging` or
|
||||||
|
use the :bro:see:`BrokerComm::enable_remote_logs` function. The former
|
||||||
|
allows any log stream to be sent to peers while the latter enables remote
|
||||||
|
logging for particular streams.
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/logs-connector.bro
|
||||||
|
|
||||||
|
Message Format
|
||||||
|
--------------
|
||||||
|
|
||||||
|
For other applications that want to exchange log messages with Bro,
|
||||||
|
the Broker message format is:
|
||||||
|
|
||||||
|
.. code:: c++
|
||||||
|
|
||||||
|
broker::message{broker::enum_value{}, broker::record{}};
|
||||||
|
|
||||||
|
The enum value corresponds to the stream's :bro:see:`Log::ID` value, and
|
||||||
|
the record corresponds to a single entry of that log's columns record,
|
||||||
|
in this case a ``Test::Info`` value.
|
||||||
|
|
||||||
|
Tuning Access Control
|
||||||
|
=====================
|
||||||
|
|
||||||
|
By default, endpoints do not restrict the message topics that it sends
|
||||||
|
to peers and do not restrict what message topics and data store
|
||||||
|
identifiers get advertised to peers. These are the default
|
||||||
|
:bro:see:`BrokerComm::EndpointFlags` supplied to :bro:see:`BrokerComm::enable`.
|
||||||
|
|
||||||
|
If not using the ``auto_publish`` flag, one can use the
|
||||||
|
:bro:see:`BrokerComm::publish_topic` and :bro:see:`BrokerComm::unpublish_topic`
|
||||||
|
functions to manipulate the set of message topics (must match exactly)
|
||||||
|
that are allowed to be sent to peer endpoints. These settings take
|
||||||
|
precedence over the per-message ``peers`` flag supplied to functions
|
||||||
|
that take a :bro:see:`BrokerComm::SendFlags` such as :bro:see:`BrokerComm::print`,
|
||||||
|
:bro:see:`BrokerComm::event`, :bro:see:`BrokerComm::auto_event` or
|
||||||
|
:bro:see:`BrokerComm::enable_remote_logs`.
|
||||||
|
|
||||||
|
If not using the ``auto_advertise`` flag, one can use the
|
||||||
|
:bro:see:`BrokerComm::advertise_topic` and
|
||||||
|
:bro:see:`BrokerComm::unadvertise_topic` functions
|
||||||
|
to manipulate the set of topic prefixes that are allowed to be
|
||||||
|
advertised to peers. If an endpoint does not advertise a topic prefix, then
|
||||||
|
the only way peers can send messages to it is via the ``unsolicited``
|
||||||
|
flag of :bro:see:`BrokerComm::SendFlags` and choosing a topic with a matching
|
||||||
|
prefix (i.e. full topic may be longer than receivers prefix, just the
|
||||||
|
prefix needs to match).
|
||||||
|
|
||||||
|
Distributed Data Stores
|
||||||
|
=======================
|
||||||
|
|
||||||
|
There are three flavors of key-value data store interfaces: master,
|
||||||
|
clone, and frontend.
|
||||||
|
|
||||||
|
A frontend is the common interface to query and modify data stores.
|
||||||
|
That is, a clone is a specific type of frontend and a master is also a
|
||||||
|
specific type of frontend, but a standalone frontend can also exist to
|
||||||
|
e.g. query and modify the contents of a remote master store without
|
||||||
|
actually "owning" any of the contents itself.
|
||||||
|
|
||||||
|
A master data store can be cloned from remote peers which may then
|
||||||
|
perform lightweight, local queries against the clone, which
|
||||||
|
automatically stays synchronized with the master store. Clones cannot
|
||||||
|
modify their content directly, instead they send modifications to the
|
||||||
|
centralized master store which applies them and then broadcasts them to
|
||||||
|
all clones.
|
||||||
|
|
||||||
|
Master and clone stores get to choose what type of storage backend to
|
||||||
|
use. E.g. In-memory versus SQLite for persistence. Note that if clones
|
||||||
|
are used, then data store sizes must be able to fit within memory
|
||||||
|
regardless of the storage backend as a single snapshot of the master
|
||||||
|
store is sent in a single chunk to initialize the clone.
|
||||||
|
|
||||||
|
Data stores also support expiration on a per-key basis either using an
|
||||||
|
absolute point in time or a relative amount of time since the entry's
|
||||||
|
last modification time.
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/stores-listener.bro
|
||||||
|
|
||||||
|
.. btest-include:: ${DOC_ROOT}/frameworks/broker/stores-connector.bro
|
||||||
|
|
||||||
|
In the above example, if a local copy of the store contents isn't
|
||||||
|
needed, just replace the :bro:see:`BrokerStore::create_clone` call with
|
||||||
|
:bro:see:`BrokerStore::create_frontend`. Queries will then be made against
|
||||||
|
the remote master store instead of the local clone.
|
||||||
|
|
||||||
|
Note that all data store queries must be made within Bro's asynchronous
|
||||||
|
``when`` statements and must specify a timeout block.
|
18
doc/frameworks/broker/connecting-connector.bro
Normal file
18
doc/frameworks/broker/connecting-connector.bro
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const broker_port: port = 9999/tcp &redef;
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
redef BrokerComm::endpoint_name = "connector";
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
BrokerComm::connect("127.0.0.1", broker_port, 1sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::outgoing_connection_established(peer_address: string,
|
||||||
|
peer_port: port,
|
||||||
|
peer_name: string)
|
||||||
|
{
|
||||||
|
print "BrokerComm::outgoing_connection_established",
|
||||||
|
peer_address, peer_port, peer_name;
|
||||||
|
terminate();
|
||||||
|
}
|
20
doc/frameworks/broker/connecting-listener.bro
Normal file
20
doc/frameworks/broker/connecting-listener.bro
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
const broker_port: port = 9999/tcp &redef;
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
redef BrokerComm::endpoint_name = "listener";
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
BrokerComm::listen(broker_port, "127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::incoming_connection_established(peer_name: string)
|
||||||
|
{
|
||||||
|
print "BrokerComm::incoming_connection_established", peer_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::incoming_connection_broken(peer_name: string)
|
||||||
|
{
|
||||||
|
print "BrokerComm::incoming_connection_broken", peer_name;
|
||||||
|
terminate();
|
||||||
|
}
|
31
doc/frameworks/broker/events-connector.bro
Normal file
31
doc/frameworks/broker/events-connector.bro
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
const broker_port: port = 9999/tcp &redef;
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
redef BrokerComm::endpoint_name = "connector";
|
||||||
|
global my_event: event(msg: string, c: count);
|
||||||
|
global my_auto_event: event(msg: string, c: count);
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
BrokerComm::connect("127.0.0.1", broker_port, 1sec);
|
||||||
|
BrokerComm::auto_event("bro/event/my_auto_event", my_auto_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::outgoing_connection_established(peer_address: string,
|
||||||
|
peer_port: port,
|
||||||
|
peer_name: string)
|
||||||
|
{
|
||||||
|
print "BrokerComm::outgoing_connection_established",
|
||||||
|
peer_address, peer_port, peer_name;
|
||||||
|
BrokerComm::event("bro/event/my_event", BrokerComm::event_args(my_event, "hi", 0));
|
||||||
|
event my_auto_event("stuff", 88);
|
||||||
|
BrokerComm::event("bro/event/my_event", BrokerComm::event_args(my_event, "...", 1));
|
||||||
|
event my_auto_event("more stuff", 51);
|
||||||
|
BrokerComm::event("bro/event/my_event", BrokerComm::event_args(my_event, "bye", 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::outgoing_connection_broken(peer_address: string,
|
||||||
|
peer_port: port)
|
||||||
|
{
|
||||||
|
terminate();
|
||||||
|
}
|
36
doc/frameworks/broker/events-listener.bro
Normal file
36
doc/frameworks/broker/events-listener.bro
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
const broker_port: port = 9999/tcp &redef;
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
redef BrokerComm::endpoint_name = "listener";
|
||||||
|
global msg_count = 0;
|
||||||
|
global my_event: event(msg: string, c: count);
|
||||||
|
global my_auto_event: event(msg: string, c: count);
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
BrokerComm::subscribe_to_events("bro/event/");
|
||||||
|
BrokerComm::listen(broker_port, "127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::incoming_connection_established(peer_name: string)
|
||||||
|
{
|
||||||
|
print "BrokerComm::incoming_connection_established", peer_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
event my_event(msg: string, c: count)
|
||||||
|
{
|
||||||
|
++msg_count;
|
||||||
|
print "got my_event", msg, c;
|
||||||
|
|
||||||
|
if ( msg_count == 5 )
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
event my_auto_event(msg: string, c: count)
|
||||||
|
{
|
||||||
|
++msg_count;
|
||||||
|
print "got my_auto_event", msg, c;
|
||||||
|
|
||||||
|
if ( msg_count == 5 )
|
||||||
|
terminate();
|
||||||
|
}
|
40
doc/frameworks/broker/logs-connector.bro
Normal file
40
doc/frameworks/broker/logs-connector.bro
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
@load ./testlog
|
||||||
|
|
||||||
|
const broker_port: port = 9999/tcp &redef;
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
redef BrokerComm::endpoint_name = "connector";
|
||||||
|
redef Log::enable_local_logging = F;
|
||||||
|
redef Log::enable_remote_logging = F;
|
||||||
|
global n = 0;
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
BrokerComm::enable_remote_logs(Test::LOG);
|
||||||
|
BrokerComm::connect("127.0.0.1", broker_port, 1sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
event do_write()
|
||||||
|
{
|
||||||
|
if ( n == 6 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Log::write(Test::LOG, [$msg = "ping", $num = n]);
|
||||||
|
++n;
|
||||||
|
event do_write();
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::outgoing_connection_established(peer_address: string,
|
||||||
|
peer_port: port,
|
||||||
|
peer_name: string)
|
||||||
|
{
|
||||||
|
print "BrokerComm::outgoing_connection_established",
|
||||||
|
peer_address, peer_port, peer_name;
|
||||||
|
event do_write();
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::outgoing_connection_broken(peer_address: string,
|
||||||
|
peer_port: port)
|
||||||
|
{
|
||||||
|
terminate();
|
||||||
|
}
|
25
doc/frameworks/broker/logs-listener.bro
Normal file
25
doc/frameworks/broker/logs-listener.bro
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
@load ./testlog
|
||||||
|
|
||||||
|
const broker_port: port = 9999/tcp &redef;
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
redef BrokerComm::endpoint_name = "listener";
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
BrokerComm::subscribe_to_logs("bro/log/Test::LOG");
|
||||||
|
BrokerComm::listen(broker_port, "127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::incoming_connection_established(peer_name: string)
|
||||||
|
{
|
||||||
|
print "BrokerComm::incoming_connection_established", peer_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
event Test::log_test(rec: Test::Info)
|
||||||
|
{
|
||||||
|
print "wrote log", rec;
|
||||||
|
|
||||||
|
if ( rec$num == 5 )
|
||||||
|
terminate();
|
||||||
|
}
|
26
doc/frameworks/broker/printing-connector.bro
Normal file
26
doc/frameworks/broker/printing-connector.bro
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
const broker_port: port = 9999/tcp &redef;
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
redef BrokerComm::endpoint_name = "connector";
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
BrokerComm::connect("127.0.0.1", broker_port, 1sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::outgoing_connection_established(peer_address: string,
|
||||||
|
peer_port: port,
|
||||||
|
peer_name: string)
|
||||||
|
{
|
||||||
|
print "BrokerComm::outgoing_connection_established",
|
||||||
|
peer_address, peer_port, peer_name;
|
||||||
|
BrokerComm::print("bro/print/hi", "hello");
|
||||||
|
BrokerComm::print("bro/print/stuff", "...");
|
||||||
|
BrokerComm::print("bro/print/bye", "goodbye");
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::outgoing_connection_broken(peer_address: string,
|
||||||
|
peer_port: port)
|
||||||
|
{
|
||||||
|
terminate();
|
||||||
|
}
|
25
doc/frameworks/broker/printing-listener.bro
Normal file
25
doc/frameworks/broker/printing-listener.bro
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
const broker_port: port = 9999/tcp &redef;
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
redef BrokerComm::endpoint_name = "listener";
|
||||||
|
global msg_count = 0;
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
BrokerComm::subscribe_to_prints("bro/print/");
|
||||||
|
BrokerComm::listen(broker_port, "127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::incoming_connection_established(peer_name: string)
|
||||||
|
{
|
||||||
|
print "BrokerComm::incoming_connection_established", peer_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::print_handler(msg: string)
|
||||||
|
{
|
||||||
|
++msg_count;
|
||||||
|
print "got print message", msg;
|
||||||
|
|
||||||
|
if ( msg_count == 3 )
|
||||||
|
terminate();
|
||||||
|
}
|
53
doc/frameworks/broker/stores-connector.bro
Normal file
53
doc/frameworks/broker/stores-connector.bro
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
const broker_port: port = 9999/tcp &redef;
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
|
||||||
|
global h: opaque of BrokerStore::Handle;
|
||||||
|
|
||||||
|
function dv(d: BrokerComm::Data): BrokerComm::DataVector
|
||||||
|
{
|
||||||
|
local rval: BrokerComm::DataVector;
|
||||||
|
rval[0] = d;
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
global ready: event();
|
||||||
|
|
||||||
|
event BrokerComm::outgoing_connection_broken(peer_address: string,
|
||||||
|
peer_port: port)
|
||||||
|
{
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
event BrokerComm::outgoing_connection_established(peer_address: string,
|
||||||
|
peer_port: port,
|
||||||
|
peer_name: string)
|
||||||
|
{
|
||||||
|
local myset: set[string] = {"a", "b", "c"};
|
||||||
|
local myvec: vector of string = {"alpha", "beta", "gamma"};
|
||||||
|
h = BrokerStore::create_master("mystore");
|
||||||
|
BrokerStore::insert(h, BrokerComm::data("one"), BrokerComm::data(110));
|
||||||
|
BrokerStore::insert(h, BrokerComm::data("two"), BrokerComm::data(223));
|
||||||
|
BrokerStore::insert(h, BrokerComm::data("myset"), BrokerComm::data(myset));
|
||||||
|
BrokerStore::insert(h, BrokerComm::data("myvec"), BrokerComm::data(myvec));
|
||||||
|
BrokerStore::increment(h, BrokerComm::data("one"));
|
||||||
|
BrokerStore::decrement(h, BrokerComm::data("two"));
|
||||||
|
BrokerStore::add_to_set(h, BrokerComm::data("myset"), BrokerComm::data("d"));
|
||||||
|
BrokerStore::remove_from_set(h, BrokerComm::data("myset"), BrokerComm::data("b"));
|
||||||
|
BrokerStore::push_left(h, BrokerComm::data("myvec"), dv(BrokerComm::data("delta")));
|
||||||
|
BrokerStore::push_right(h, BrokerComm::data("myvec"), dv(BrokerComm::data("omega")));
|
||||||
|
|
||||||
|
when ( local res = BrokerStore::size(h) )
|
||||||
|
{
|
||||||
|
print "master size", res;
|
||||||
|
event ready();
|
||||||
|
}
|
||||||
|
timeout 10sec
|
||||||
|
{ print "timeout"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
BrokerComm::connect("127.0.0.1", broker_port, 1secs);
|
||||||
|
BrokerComm::auto_event("bro/event/ready", ready);
|
||||||
|
}
|
43
doc/frameworks/broker/stores-listener.bro
Normal file
43
doc/frameworks/broker/stores-listener.bro
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
const broker_port: port = 9999/tcp &redef;
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
|
||||||
|
global h: opaque of BrokerStore::Handle;
|
||||||
|
global expected_key_count = 4;
|
||||||
|
global key_count = 0;
|
||||||
|
|
||||||
|
function do_lookup(key: string)
|
||||||
|
{
|
||||||
|
when ( local res = BrokerStore::lookup(h, BrokerComm::data(key)) )
|
||||||
|
{
|
||||||
|
++key_count;
|
||||||
|
print "lookup", key, res;
|
||||||
|
|
||||||
|
if ( key_count == expected_key_count )
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
timeout 10sec
|
||||||
|
{ print "timeout", key; }
|
||||||
|
}
|
||||||
|
|
||||||
|
event ready()
|
||||||
|
{
|
||||||
|
h = BrokerStore::create_clone("mystore");
|
||||||
|
|
||||||
|
when ( local res = BrokerStore::keys(h) )
|
||||||
|
{
|
||||||
|
print "clone keys", res;
|
||||||
|
do_lookup(BrokerComm::refine_to_string(BrokerComm::vector_lookup(res$result, 0)));
|
||||||
|
do_lookup(BrokerComm::refine_to_string(BrokerComm::vector_lookup(res$result, 1)));
|
||||||
|
do_lookup(BrokerComm::refine_to_string(BrokerComm::vector_lookup(res$result, 2)));
|
||||||
|
do_lookup(BrokerComm::refine_to_string(BrokerComm::vector_lookup(res$result, 3)));
|
||||||
|
}
|
||||||
|
timeout 10sec
|
||||||
|
{ print "timeout"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
BrokerComm::subscribe_to_events("bro/event/ready");
|
||||||
|
BrokerComm::listen(broker_port, "127.0.0.1");
|
||||||
|
}
|
18
doc/frameworks/broker/testlog.bro
Normal file
18
doc/frameworks/broker/testlog.bro
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
module Test;
|
||||||
|
|
||||||
|
export {
|
||||||
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
|
type Info: record {
|
||||||
|
msg: string &log;
|
||||||
|
num: count &log;
|
||||||
|
};
|
||||||
|
|
||||||
|
global log_test: event(rec: Test::Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
event bro_init() &priority=5
|
||||||
|
{
|
||||||
|
BrokerComm::enable();
|
||||||
|
Log::create_stream(Test::LOG, [$columns=Test::Info, $ev=log_test, $path="test"]);
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
event file_new(f: fa_file)
|
event file_sniff(f: fa_file, meta: fa_metadata)
|
||||||
{
|
{
|
||||||
|
if ( ! meta?$mime_type ) return;
|
||||||
print "new file", f$id;
|
print "new file", f$id;
|
||||||
if ( f?$mime_type && f$mime_type == "text/plain" )
|
if ( meta$mime_type == "text/plain" )
|
||||||
Files::add_analyzer(f, Files::ANALYZER_MD5);
|
Files::add_analyzer(f, Files::ANALYZER_MD5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,13 @@ GeoLocation
|
||||||
Install libGeoIP
|
Install libGeoIP
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
Before building Bro, you need to install libGeoIP.
|
||||||
|
|
||||||
* FreeBSD:
|
* FreeBSD:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo pkg_add -r GeoIP
|
sudo pkg install GeoIP
|
||||||
|
|
||||||
* RPM/RedHat-based Linux:
|
* RPM/RedHat-based Linux:
|
||||||
|
|
||||||
|
@ -40,80 +42,99 @@ Install libGeoIP
|
||||||
|
|
||||||
* Mac OS X:
|
* Mac OS X:
|
||||||
|
|
||||||
Vanilla OS X installations don't ship with libGeoIP, but if
|
You need to install from your preferred package management system
|
||||||
installed from your preferred package management system (e.g.
|
(e.g. MacPorts, Fink, or Homebrew). The name of the package that you need
|
||||||
MacPorts, Fink, or Homebrew), they should be automatically detected
|
may be libgeoip, geoip, or geoip-dev, depending on which package management
|
||||||
and Bro will compile against them.
|
system you are using.
|
||||||
|
|
||||||
|
|
||||||
GeoIPLite Database Installation
|
GeoIPLite Database Installation
|
||||||
------------------------------------
|
-------------------------------
|
||||||
|
|
||||||
A country database for GeoIPLite is included when you do the C API
|
A country database for GeoIPLite is included when you do the C API
|
||||||
install, but for Bro, we are using the city database which includes
|
install, but for Bro, we are using the city database which includes
|
||||||
cities and regions in addition to countries.
|
cities and regions in addition to countries.
|
||||||
|
|
||||||
`Download <http://www.maxmind.com/app/geolitecity>`__ the GeoLite city
|
`Download <http://www.maxmind.com/app/geolitecity>`__ the GeoLite city
|
||||||
binary database.
|
binary database:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
|
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
|
||||||
gunzip GeoLiteCity.dat.gz
|
gunzip GeoLiteCity.dat.gz
|
||||||
|
|
||||||
Next, the file needs to be put in the database directory. This directory
|
Next, the file needs to be renamed and put in the GeoIP database directory.
|
||||||
should already exist and will vary depending on which platform and package
|
This directory should already exist and will vary depending on which platform
|
||||||
you are using. For FreeBSD, use ``/usr/local/share/GeoIP``. For Linux,
|
and package you are using. For FreeBSD, use ``/usr/local/share/GeoIP``. For
|
||||||
use ``/usr/share/GeoIP`` or ``/var/lib/GeoIP`` (choose whichever one
|
Linux, use ``/usr/share/GeoIP`` or ``/var/lib/GeoIP`` (choose whichever one
|
||||||
already exists).
|
already exists).
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
mv GeoLiteCity.dat <path_to_database_dir>/GeoIPCity.dat
|
mv GeoLiteCity.dat <path_to_database_dir>/GeoIPCity.dat
|
||||||
|
|
||||||
|
Note that there is a separate database for IPv6 addresses, which can also
|
||||||
|
be installed if you want GeoIP functionality for IPv6.
|
||||||
|
|
||||||
|
Testing
|
||||||
|
-------
|
||||||
|
|
||||||
|
Before using the GeoIP functionality, it is a good idea to verify that
|
||||||
|
everything is setup correctly. After installing libGeoIP and the GeoIP city
|
||||||
|
database, and building Bro, you can quickly check if the GeoIP functionality
|
||||||
|
works by running a command like this:
|
||||||
|
|
||||||
|
.. console::
|
||||||
|
|
||||||
|
bro -e "print lookup_location(8.8.8.8);"
|
||||||
|
|
||||||
|
If you see an error message similar to "Failed to open GeoIP City database",
|
||||||
|
then you may need to either rename or move your GeoIP city database file (the
|
||||||
|
error message should give you the full pathname of the database file that
|
||||||
|
Bro is looking for).
|
||||||
|
|
||||||
|
If you see an error message similar to "Bro was not configured for GeoIP
|
||||||
|
support", then you need to rebuild Bro and make sure it is linked against
|
||||||
|
libGeoIP. Normally, if libGeoIP is installed correctly then it should
|
||||||
|
automatically be found when building Bro. If this doesn't happen, then
|
||||||
|
you may need to specify the path to the libGeoIP installation
|
||||||
|
(e.g. ``./configure --with-geoip=<path>``).
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
There is a single built in function that provides the GeoIP
|
There is a built-in function that provides the GeoIP functionality:
|
||||||
functionality:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
function lookup_location(a:addr): geo_location
|
function lookup_location(a:addr): geo_location
|
||||||
|
|
||||||
There is also the :bro:see:`geo_location` data structure that is returned
|
The return value of the :bro:see:`lookup_location` function is a record
|
||||||
from the :bro:see:`lookup_location` function:
|
type called :bro:see:`geo_location`, and it consists of several fields
|
||||||
|
containing the country, region, city, latitude, and longitude of the specified
|
||||||
.. code:: bro
|
IP address. Since one or more fields in this record will be uninitialized
|
||||||
|
for some IP addresses (for example, the country and region of an IP address
|
||||||
type geo_location: record {
|
might be known, but the city could be unknown), a field should be checked
|
||||||
country_code: string;
|
if it has a value before trying to access the value.
|
||||||
region: string;
|
|
||||||
city: string;
|
|
||||||
latitude: double;
|
|
||||||
longitude: double;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
|
|
||||||
To write a line in a log file for every ftp connection from hosts in
|
To show every ftp connection from hosts in Ohio, this is now very easy:
|
||||||
Ohio, this is now very easy:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
global ftp_location_log: file = open_log_file("ftp-location");
|
|
||||||
|
|
||||||
event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool)
|
event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool)
|
||||||
{
|
{
|
||||||
local client = c$id$orig_h;
|
local client = c$id$orig_h;
|
||||||
local loc = lookup_location(client);
|
local loc = lookup_location(client);
|
||||||
if (loc$region == "OH" && loc$country_code == "US")
|
|
||||||
|
if (loc?$region && loc$region == "OH" && loc$country_code == "US")
|
||||||
{
|
{
|
||||||
print ftp_location_log, fmt("FTP Connection from:%s (%s,%s,%s)", client, loc$city, loc$region, loc$country_code);
|
local city = loc?$city ? loc$city : "<unknown>";
|
||||||
|
|
||||||
|
print fmt("FTP Connection from:%s (%s,%s,%s)", client, city,
|
||||||
|
loc$region, loc$country_code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,4 +14,4 @@ Frameworks
|
||||||
notice
|
notice
|
||||||
signatures
|
signatures
|
||||||
sumstats
|
sumstats
|
||||||
|
broker
|
||||||
|
|
|
@ -32,7 +32,8 @@ For this example we assume that we want to import data from a blacklist
|
||||||
that contains server IP addresses as well as the timestamp and the reason
|
that contains server IP addresses as well as the timestamp and the reason
|
||||||
for the block.
|
for the block.
|
||||||
|
|
||||||
An example input file could look like this:
|
An example input file could look like this (note that all fields must be
|
||||||
|
tab-separated):
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
@ -63,19 +64,23 @@ The two records are defined as:
|
||||||
reason: string;
|
reason: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
Note that the names of the fields in the record definitions have to correspond
|
Note that the names of the fields in the record definitions must correspond
|
||||||
to the column names listed in the '#fields' line of the log file, in this
|
to the column names listed in the '#fields' line of the log file, in this
|
||||||
case 'ip', 'timestamp', and 'reason'.
|
case 'ip', 'timestamp', and 'reason'. Also note that the ordering of the
|
||||||
|
columns does not matter, because each column is identified by name.
|
||||||
|
|
||||||
The log file is read into the table with a simple call of the ``add_table``
|
The log file is read into the table with a simple call of the
|
||||||
function:
|
:bro:id:`Input::add_table` function:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
global blacklist: table[addr] of Val = table();
|
global blacklist: table[addr] of Val = table();
|
||||||
|
|
||||||
Input::add_table([$source="blacklist.file", $name="blacklist", $idx=Idx, $val=Val, $destination=blacklist]);
|
event bro_init() {
|
||||||
|
Input::add_table([$source="blacklist.file", $name="blacklist",
|
||||||
|
$idx=Idx, $val=Val, $destination=blacklist]);
|
||||||
Input::remove("blacklist");
|
Input::remove("blacklist");
|
||||||
|
}
|
||||||
|
|
||||||
With these three lines we first create an empty table that should contain the
|
With these three lines we first create an empty table that should contain the
|
||||||
blacklist data and then instruct the input framework to open an input stream
|
blacklist data and then instruct the input framework to open an input stream
|
||||||
|
@ -92,7 +97,7 @@ Because of this, the data is not immediately accessible. Depending on the
|
||||||
size of the data source it might take from a few milliseconds up to a few
|
size of the data source it might take from a few milliseconds up to a few
|
||||||
seconds until all data is present in the table. Please note that this means
|
seconds until all data is present in the table. Please note that this means
|
||||||
that when Bro is running without an input source or on very short captured
|
that when Bro is running without an input source or on very short captured
|
||||||
files, it might terminate before the data is present in the system (because
|
files, it might terminate before the data is present in the table (because
|
||||||
Bro already handled all packets before the import thread finished).
|
Bro already handled all packets before the import thread finished).
|
||||||
|
|
||||||
Subsequent calls to an input source are queued until the previous action has
|
Subsequent calls to an input source are queued until the previous action has
|
||||||
|
@ -101,8 +106,8 @@ been completed. Because of this, it is, for example, possible to call
|
||||||
will remain queued until the first read has been completed.
|
will remain queued until the first read has been completed.
|
||||||
|
|
||||||
Once the input framework finishes reading from a data source, it fires
|
Once the input framework finishes reading from a data source, it fires
|
||||||
the ``end_of_data`` event. Once this event has been received all data
|
the :bro:id:`Input::end_of_data` event. Once this event has been received all
|
||||||
from the input file is available in the table.
|
data from the input file is available in the table.
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
|
@ -111,9 +116,9 @@ from the input file is available in the table.
|
||||||
print blacklist;
|
print blacklist;
|
||||||
}
|
}
|
||||||
|
|
||||||
The table can also already be used while the data is still being read - it
|
The table can be used while the data is still being read - it
|
||||||
just might not contain all lines in the input file when the event has not
|
just might not contain all lines from the input file before the event has
|
||||||
yet fired. After it has been populated it can be used like any other Bro
|
fired. After the table has been populated it can be used like any other Bro
|
||||||
table and blacklist entries can easily be tested:
|
table and blacklist entries can easily be tested:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
@ -130,10 +135,11 @@ changing. For these cases, the Bro input framework supports several ways to
|
||||||
deal with changing data files.
|
deal with changing data files.
|
||||||
|
|
||||||
The first, very basic method is an explicit refresh of an input stream. When
|
The first, very basic method is an explicit refresh of an input stream. When
|
||||||
an input stream is open, the function ``force_update`` can be called. This
|
an input stream is open (this means it has not yet been removed by a call to
|
||||||
will trigger a complete refresh of the table; any changed elements from the
|
:bro:id:`Input::remove`), the function :bro:id:`Input::force_update` can be
|
||||||
file will be updated. After the update is finished the ``end_of_data``
|
called. This will trigger a complete refresh of the table; any changed
|
||||||
event will be raised.
|
elements from the file will be updated. After the update is finished the
|
||||||
|
:bro:id:`Input::end_of_data` event will be raised.
|
||||||
|
|
||||||
In our example the call would look like:
|
In our example the call would look like:
|
||||||
|
|
||||||
|
@ -141,30 +147,35 @@ In our example the call would look like:
|
||||||
|
|
||||||
Input::force_update("blacklist");
|
Input::force_update("blacklist");
|
||||||
|
|
||||||
The input framework also supports two automatic refresh modes. The first mode
|
Alternatively, the input framework can automatically refresh the table
|
||||||
continually checks if a file has been changed. If the file has been changed, it
|
contents when it detects a change to the input file. To use this feature,
|
||||||
|
you need to specify a non-default read mode by setting the ``mode`` option
|
||||||
|
of the :bro:id:`Input::add_table` call. Valid values are ``Input::MANUAL``
|
||||||
|
(the default), ``Input::REREAD`` and ``Input::STREAM``. For example,
|
||||||
|
setting the value of the ``mode`` option in the previous example
|
||||||
|
would look like this:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
Input::add_table([$source="blacklist.file", $name="blacklist",
|
||||||
|
$idx=Idx, $val=Val, $destination=blacklist,
|
||||||
|
$mode=Input::REREAD]);
|
||||||
|
|
||||||
|
When using the reread mode (i.e., ``$mode=Input::REREAD``), Bro continually
|
||||||
|
checks if the input file has been changed. If the file has been changed, it
|
||||||
is re-read and the data in the Bro table is updated to reflect the current
|
is re-read and the data in the Bro table is updated to reflect the current
|
||||||
state. Each time a change has been detected and all the new data has been
|
state. Each time a change has been detected and all the new data has been
|
||||||
read into the table, the ``end_of_data`` event is raised.
|
read into the table, the ``end_of_data`` event is raised.
|
||||||
|
|
||||||
The second mode is a streaming mode. This mode assumes that the source data
|
When using the streaming mode (i.e., ``$mode=Input::STREAM``), Bro assumes
|
||||||
file is an append-only file to which new data is continually appended. Bro
|
that the source data file is an append-only file to which new data is
|
||||||
continually checks for new data at the end of the file and will add the new
|
continually appended. Bro continually checks for new data at the end of
|
||||||
data to the table. If newer lines in the file have the same index as previous
|
the file and will add the new data to the table. If newer lines in the
|
||||||
lines, they will overwrite the values in the output table. Because of the
|
file have the same index as previous lines, they will overwrite the
|
||||||
nature of streaming reads (data is continually added to the table),
|
values in the output table. Because of the nature of streaming reads
|
||||||
the ``end_of_data`` event is never raised when using streaming reads.
|
(data is continually added to the table), the ``end_of_data`` event
|
||||||
|
is never raised when using streaming reads.
|
||||||
|
|
||||||
The reading mode can be selected by setting the ``mode`` option of the
|
|
||||||
add_table call. Valid values are ``MANUAL`` (the default), ``REREAD``
|
|
||||||
and ``STREAM``.
|
|
||||||
|
|
||||||
Hence, when adding ``$mode=Input::REREAD`` to the previous example, the
|
|
||||||
blacklist table will always reflect the state of the blacklist input file.
|
|
||||||
|
|
||||||
.. code:: bro
|
|
||||||
|
|
||||||
Input::add_table([$source="blacklist.file", $name="blacklist", $idx=Idx, $val=Val, $destination=blacklist, $mode=Input::REREAD]);
|
|
||||||
|
|
||||||
Receiving change events
|
Receiving change events
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -173,34 +184,40 @@ When re-reading files, it might be interesting to know exactly which lines in
|
||||||
the source files have changed.
|
the source files have changed.
|
||||||
|
|
||||||
For this reason, the input framework can raise an event each time when a data
|
For this reason, the input framework can raise an event each time when a data
|
||||||
item is added to, removed from or changed in a table.
|
item is added to, removed from, or changed in a table.
|
||||||
|
|
||||||
The event definition looks like this:
|
The event definition looks like this (note that you can change the name of
|
||||||
|
this event in your own Bro script):
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
event entry(description: Input::TableDescription, tpe: Input::Event, left: Idx, right: Val) {
|
event entry(description: Input::TableDescription, tpe: Input::Event,
|
||||||
# act on values
|
left: Idx, right: Val) {
|
||||||
|
# do something here...
|
||||||
|
print fmt("%s = %s", left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
The event has to be specified in ``$ev`` in the ``add_table`` call:
|
The event must be specified in ``$ev`` in the ``add_table`` call:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
Input::add_table([$source="blacklist.file", $name="blacklist", $idx=Idx, $val=Val, $destination=blacklist, $mode=Input::REREAD, $ev=entry]);
|
Input::add_table([$source="blacklist.file", $name="blacklist",
|
||||||
|
$idx=Idx, $val=Val, $destination=blacklist,
|
||||||
|
$mode=Input::REREAD, $ev=entry]);
|
||||||
|
|
||||||
The ``description`` field of the event contains the arguments that were
|
The ``description`` argument of the event contains the arguments that were
|
||||||
originally supplied to the add_table call. Hence, the name of the stream can,
|
originally supplied to the add_table call. Hence, the name of the stream can,
|
||||||
for example, be accessed with ``description$name``. ``tpe`` is an enum
|
for example, be accessed with ``description$name``. The ``tpe`` argument of the
|
||||||
containing the type of the change that occurred.
|
event is an enum containing the type of the change that occurred.
|
||||||
|
|
||||||
If a line that was not previously present in the table has been added,
|
If a line that was not previously present in the table has been added,
|
||||||
then ``tpe`` will contain ``Input::EVENT_NEW``. In this case ``left`` contains
|
then the value of ``tpe`` will be ``Input::EVENT_NEW``. In this case ``left``
|
||||||
the index of the added table entry and ``right`` contains the values of the
|
contains the index of the added table entry and ``right`` contains the
|
||||||
added entry.
|
values of the added entry.
|
||||||
|
|
||||||
If a table entry that already was present is altered during the re-reading or
|
If a table entry that already was present is altered during the re-reading or
|
||||||
streaming read of a file, ``tpe`` will contain ``Input::EVENT_CHANGED``. In
|
streaming read of a file, then the value of ``tpe`` will be
|
||||||
|
``Input::EVENT_CHANGED``. In
|
||||||
this case ``left`` contains the index of the changed table entry and ``right``
|
this case ``left`` contains the index of the changed table entry and ``right``
|
||||||
contains the values of the entry before the change. The reason for this is
|
contains the values of the entry before the change. The reason for this is
|
||||||
that the table already has been updated when the event is raised. The current
|
that the table already has been updated when the event is raised. The current
|
||||||
|
@ -208,8 +225,9 @@ value in the table can be ascertained by looking up the current table value.
|
||||||
Hence it is possible to compare the new and the old values of the table.
|
Hence it is possible to compare the new and the old values of the table.
|
||||||
|
|
||||||
If a table element is removed because it was no longer present during a
|
If a table element is removed because it was no longer present during a
|
||||||
re-read, then ``tpe`` will contain ``Input::REMOVED``. In this case ``left``
|
re-read, then the value of ``tpe`` will be ``Input::EVENT_REMOVED``. In this
|
||||||
contains the index and ``right`` the values of the removed element.
|
case ``left`` contains the index and ``right`` the values of the removed
|
||||||
|
element.
|
||||||
|
|
||||||
|
|
||||||
Filtering data during import
|
Filtering data during import
|
||||||
|
@ -222,24 +240,26 @@ can either accept or veto the change by returning true for an accepted
|
||||||
change and false for a rejected change. Furthermore, it can alter the data
|
change and false for a rejected change. Furthermore, it can alter the data
|
||||||
before it is written to the table.
|
before it is written to the table.
|
||||||
|
|
||||||
The following example filter will reject to add entries to the table when
|
The following example filter will reject adding entries to the table when
|
||||||
they were generated over a month ago. It will accept all changes and all
|
they were generated over a month ago. It will accept all changes and all
|
||||||
removals of values that are already present in the table.
|
removals of values that are already present in the table.
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
Input::add_table([$source="blacklist.file", $name="blacklist", $idx=Idx, $val=Val, $destination=blacklist, $mode=Input::REREAD,
|
Input::add_table([$source="blacklist.file", $name="blacklist",
|
||||||
|
$idx=Idx, $val=Val, $destination=blacklist,
|
||||||
|
$mode=Input::REREAD,
|
||||||
$pred(typ: Input::Event, left: Idx, right: Val) = {
|
$pred(typ: Input::Event, left: Idx, right: Val) = {
|
||||||
if ( typ != Input::EVENT_NEW ) {
|
if ( typ != Input::EVENT_NEW ) {
|
||||||
return T;
|
return T;
|
||||||
}
|
}
|
||||||
return ( ( current_time() - right$timestamp ) < (30 day) );
|
return (current_time() - right$timestamp) < 30day;
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
To change elements while they are being imported, the predicate function can
|
To change elements while they are being imported, the predicate function can
|
||||||
manipulate ``left`` and ``right``. Note that predicate functions are called
|
manipulate ``left`` and ``right``. Note that predicate functions are called
|
||||||
before the change is committed to the table. Hence, when a table element is
|
before the change is committed to the table. Hence, when a table element is
|
||||||
changed (``tpe`` is ``INPUT::EVENT_CHANGED``), ``left`` and ``right``
|
changed (``typ`` is ``Input::EVENT_CHANGED``), ``left`` and ``right``
|
||||||
contain the new values, but the destination (``blacklist`` in our example)
|
contain the new values, but the destination (``blacklist`` in our example)
|
||||||
still contains the old values. This allows predicate functions to examine
|
still contains the old values. This allows predicate functions to examine
|
||||||
the changes between the old and the new version before deciding if they
|
the changes between the old and the new version before deciding if they
|
||||||
|
@ -250,14 +270,19 @@ Different readers
|
||||||
|
|
||||||
The input framework supports different kinds of readers for different kinds
|
The input framework supports different kinds of readers for different kinds
|
||||||
of source data files. At the moment, the default reader reads ASCII files
|
of source data files. At the moment, the default reader reads ASCII files
|
||||||
formatted in the Bro log file format (tab-separated values). At the moment,
|
formatted in the Bro log file format (tab-separated values with a "#fields"
|
||||||
Bro comes with two other readers. The ``RAW`` reader reads a file that is
|
header line). Several other readers are included in Bro.
|
||||||
split by a specified record separator (usually newline). The contents are
|
|
||||||
|
The raw reader reads a file that is
|
||||||
|
split by a specified record separator (newline by default). The contents are
|
||||||
returned line-by-line as strings; it can, for example, be used to read
|
returned line-by-line as strings; it can, for example, be used to read
|
||||||
configuration files and the like and is probably
|
configuration files and the like and is probably
|
||||||
only useful in the event mode and not for reading data to tables.
|
only useful in the event mode and not for reading data to tables.
|
||||||
|
|
||||||
Another included reader is the ``BENCHMARK`` reader, which is being used
|
The binary reader is intended to be used with file analysis input streams (and
|
||||||
|
is the default type of reader for those streams).
|
||||||
|
|
||||||
|
The benchmark reader is being used
|
||||||
to optimize the speed of the input framework. It can generate arbitrary
|
to optimize the speed of the input framework. It can generate arbitrary
|
||||||
amounts of semi-random data in all Bro data types supported by the input
|
amounts of semi-random data in all Bro data types supported by the input
|
||||||
framework.
|
framework.
|
||||||
|
@ -270,75 +295,17 @@ aforementioned ones:
|
||||||
|
|
||||||
logging-input-sqlite
|
logging-input-sqlite
|
||||||
|
|
||||||
Add_table options
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
This section lists all possible options that can be used for the add_table
|
|
||||||
function and gives a short explanation of their use. Most of the options
|
|
||||||
already have been discussed in the previous sections.
|
|
||||||
|
|
||||||
The possible fields that can be set for a table stream are:
|
|
||||||
|
|
||||||
``source``
|
|
||||||
A mandatory string identifying the source of the data.
|
|
||||||
For the ASCII reader this is the filename.
|
|
||||||
|
|
||||||
``name``
|
|
||||||
A mandatory name for the filter that can later be used
|
|
||||||
to manipulate it further.
|
|
||||||
|
|
||||||
``idx``
|
|
||||||
Record type that defines the index of the table.
|
|
||||||
|
|
||||||
``val``
|
|
||||||
Record type that defines the values of the table.
|
|
||||||
|
|
||||||
``reader``
|
|
||||||
The reader used for this stream. Default is ``READER_ASCII``.
|
|
||||||
|
|
||||||
``mode``
|
|
||||||
The mode in which the stream is opened. Possible values are
|
|
||||||
``MANUAL``, ``REREAD`` and ``STREAM``. Default is ``MANUAL``.
|
|
||||||
``MANUAL`` means that the file is not updated after it has
|
|
||||||
been read. Changes to the file will not be reflected in the
|
|
||||||
data Bro knows. ``REREAD`` means that the whole file is read
|
|
||||||
again each time a change is found. This should be used for
|
|
||||||
files that are mapped to a table where individual lines can
|
|
||||||
change. ``STREAM`` means that the data from the file is
|
|
||||||
streamed. Events / table entries will be generated as new
|
|
||||||
data is appended to the file.
|
|
||||||
|
|
||||||
``destination``
|
|
||||||
The destination table.
|
|
||||||
|
|
||||||
``ev``
|
|
||||||
Optional event that is raised, when values are added to,
|
|
||||||
changed in, or deleted from the table. Events are passed an
|
|
||||||
Input::Event description as the first argument, the index
|
|
||||||
record as the second argument and the values as the third
|
|
||||||
argument.
|
|
||||||
|
|
||||||
``pred``
|
|
||||||
Optional predicate, that can prevent entries from being added
|
|
||||||
to the table and events from being sent.
|
|
||||||
|
|
||||||
``want_record``
|
|
||||||
Boolean value, that defines if the event wants to receive the
|
|
||||||
fields inside of a single record value, or individually
|
|
||||||
(default). This can be used if ``val`` is a record
|
|
||||||
containing only one type. In this case, if ``want_record`` is
|
|
||||||
set to false, the table will contain elements of the type
|
|
||||||
contained in ``val``.
|
|
||||||
|
|
||||||
Reading Data to Events
|
Reading Data to Events
|
||||||
======================
|
======================
|
||||||
|
|
||||||
The second supported mode of the input framework is reading data to Bro
|
The second supported mode of the input framework is reading data to Bro
|
||||||
events instead of reading them to a table using event streams.
|
events instead of reading them to a table.
|
||||||
|
|
||||||
Event streams work very similarly to table streams that were already
|
Event streams work very similarly to table streams that were already
|
||||||
discussed in much detail. To read the blacklist of the previous example
|
discussed in much detail. To read the blacklist of the previous example
|
||||||
into an event stream, the following Bro code could be used:
|
into an event stream, the :bro:id:`Input::add_event` function is used.
|
||||||
|
For example:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
|
@ -348,12 +315,15 @@ into an event stream, the following Bro code could be used:
|
||||||
reason: string;
|
reason: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
event blacklistentry(description: Input::EventDescription, tpe: Input::Event, ip: addr, timestamp: time, reason: string) {
|
event blacklistentry(description: Input::EventDescription,
|
||||||
# work with event data
|
t: Input::Event, data: Val) {
|
||||||
|
# do something here...
|
||||||
|
print "data:", data;
|
||||||
}
|
}
|
||||||
|
|
||||||
event bro_init() {
|
event bro_init() {
|
||||||
Input::add_event([$source="blacklist.file", $name="blacklist", $fields=Val, $ev=blacklistentry]);
|
Input::add_event([$source="blacklist.file", $name="blacklist",
|
||||||
|
$fields=Val, $ev=blacklistentry]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -364,52 +334,3 @@ data types are provided in a single record definition.
|
||||||
Apart from this, event streams work exactly the same as table streams and
|
Apart from this, event streams work exactly the same as table streams and
|
||||||
support most of the options that are also supported for table streams.
|
support most of the options that are also supported for table streams.
|
||||||
|
|
||||||
The options that can be set when creating an event stream with
|
|
||||||
``add_event`` are:
|
|
||||||
|
|
||||||
``source``
|
|
||||||
A mandatory string identifying the source of the data.
|
|
||||||
For the ASCII reader this is the filename.
|
|
||||||
|
|
||||||
``name``
|
|
||||||
A mandatory name for the stream that can later be used
|
|
||||||
to remove it.
|
|
||||||
|
|
||||||
``fields``
|
|
||||||
Name of a record type containing the fields, which should be
|
|
||||||
retrieved from the input stream.
|
|
||||||
|
|
||||||
``ev``
|
|
||||||
The event which is fired, after a line has been read from the
|
|
||||||
input source. The first argument that is passed to the event
|
|
||||||
is an Input::Event structure, followed by the data, either
|
|
||||||
inside of a record (if ``want_record is set``) or as
|
|
||||||
individual fields. The Input::Event structure can contain
|
|
||||||
information, if the received line is ``NEW``, has been
|
|
||||||
``CHANGED`` or ``DELETED``. Since the ASCII reader cannot
|
|
||||||
track this information for event filters, the value is
|
|
||||||
always ``NEW`` at the moment.
|
|
||||||
|
|
||||||
``mode``
|
|
||||||
The mode in which the stream is opened. Possible values are
|
|
||||||
``MANUAL``, ``REREAD`` and ``STREAM``. Default is ``MANUAL``.
|
|
||||||
``MANUAL`` means that the file is not updated after it has
|
|
||||||
been read. Changes to the file will not be reflected in the
|
|
||||||
data Bro knows. ``REREAD`` means that the whole file is read
|
|
||||||
again each time a change is found. This should be used for
|
|
||||||
files that are mapped to a table where individual lines can
|
|
||||||
change. ``STREAM`` means that the data from the file is
|
|
||||||
streamed. Events / table entries will be generated as new
|
|
||||||
data is appended to the file.
|
|
||||||
|
|
||||||
``reader``
|
|
||||||
The reader used for this stream. Default is ``READER_ASCII``.
|
|
||||||
|
|
||||||
``want_record``
|
|
||||||
Boolean value, that defines if the event wants to receive the
|
|
||||||
fields inside of a single record value, or individually
|
|
||||||
(default). If this is set to true, the event will receive a
|
|
||||||
single record of the type provided in ``fields``.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,32 +14,35 @@ consume that data, make it available for matching, and provide
|
||||||
infrastructure around improving performance, memory utilization, and
|
infrastructure around improving performance, memory utilization, and
|
||||||
generally making all of this easier.
|
generally making all of this easier.
|
||||||
|
|
||||||
Data in the Intelligence Framework is the atomic piece of intelligence
|
Data in the Intelligence Framework is an atomic piece of intelligence
|
||||||
such as an IP address or an e-mail address along with a suite of
|
such as an IP address or an e-mail address along with a suite of
|
||||||
metadata about it such as a freeform source field, a freeform
|
metadata about it such as a freeform source field, a freeform
|
||||||
descriptive field and a URL which might lead to more information about
|
descriptive field and a URL which might lead to more information about
|
||||||
the specific item. The metadata in the default scripts has been
|
the specific item. The metadata in the default scripts has been
|
||||||
deliberately kept minimal so that the community can find the
|
deliberately kept minimal so that the community can find the
|
||||||
appropriate fields that need added by writing scripts which extend the
|
appropriate fields that need to be added by writing scripts which extend the
|
||||||
base record using the normal record extension mechanism.
|
base record using the normal record extension mechanism.
|
||||||
|
|
||||||
Quick Start
|
Quick Start
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
Load the package of scripts that sends data into the Intelligence
|
|
||||||
Framework to be checked by loading this script in local.bro::
|
|
||||||
|
|
||||||
@load policy/frameworks/intel/seen
|
|
||||||
|
|
||||||
Refer to the "Loading Intelligence" section below to see the format
|
Refer to the "Loading Intelligence" section below to see the format
|
||||||
for Intelligence Framework text files, then load those text files with
|
for Intelligence Framework text files, then load those text files with
|
||||||
this line in local.bro::
|
this line in local.bro::
|
||||||
|
|
||||||
redef Intel::read_files += { "/somewhere/yourdata.txt" };
|
redef Intel::read_files += { "/somewhere/yourdata.txt" };
|
||||||
|
|
||||||
The data itself only needs to reside on the manager if running in a
|
The text files need to reside only on the manager if running in a
|
||||||
cluster.
|
cluster.
|
||||||
|
|
||||||
|
Add the following line to local.bro in order to load the scripts
|
||||||
|
that send "seen" data into the Intelligence Framework to be checked against
|
||||||
|
the loaded intelligence data::
|
||||||
|
|
||||||
|
@load policy/frameworks/intel/seen
|
||||||
|
|
||||||
|
Intelligence data matches will be logged to the intel.log file.
|
||||||
|
|
||||||
Architecture
|
Architecture
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
@ -58,8 +61,10 @@ manager is the only node that needs the intelligence data. The
|
||||||
intelligence framework has distribution mechanisms which will push
|
intelligence framework has distribution mechanisms which will push
|
||||||
data out to all of the nodes that need it.
|
data out to all of the nodes that need it.
|
||||||
|
|
||||||
Here is an example of the intelligence data format. Note that all
|
Here is an example of the intelligence data format (note that there will be
|
||||||
whitespace field separators are literal tabs and fields containing only a
|
additional fields if you are using CIF intelligence data or if you are
|
||||||
|
using the policy/frameworks/intel/do_notice script). Note that all fields
|
||||||
|
must be separated by a single tab character and fields containing only a
|
||||||
hyphen are considered to be null values. ::
|
hyphen are considered to be null values. ::
|
||||||
|
|
||||||
#fields indicator indicator_type meta.source meta.desc meta.url
|
#fields indicator indicator_type meta.source meta.desc meta.url
|
||||||
|
@ -69,8 +74,21 @@ hyphen are considered to be null values. ::
|
||||||
For a list of all built-in `indicator_type` values, please refer to the
|
For a list of all built-in `indicator_type` values, please refer to the
|
||||||
documentation of :bro:see:`Intel::Type`.
|
documentation of :bro:see:`Intel::Type`.
|
||||||
|
|
||||||
To load the data once files are created, use the following example
|
Note that if you are using data from the Collective Intelligence Framework,
|
||||||
code to define files to load with your own file names of course::
|
then you will need to add the following line to your local.bro in order
|
||||||
|
to support additional metadata fields used by CIF::
|
||||||
|
|
||||||
|
@load policy/integration/collective-intel
|
||||||
|
|
||||||
|
There is a simple mechanism to raise a Bro notice (of type Intel::Notice)
|
||||||
|
for user-specified intelligence matches. To use this feature, add the
|
||||||
|
following line to local.bro in order to support additional metadata fields
|
||||||
|
(documented in the :bro:see:`Intel::MetaData` record)::
|
||||||
|
|
||||||
|
@load policy/frameworks/intel/do_notice
|
||||||
|
|
||||||
|
To load the data once the files are created, use the following example
|
||||||
|
to specify which files to load (with your own file names of course)::
|
||||||
|
|
||||||
redef Intel::read_files += {
|
redef Intel::read_files += {
|
||||||
"/somewhere/feed1.txt",
|
"/somewhere/feed1.txt",
|
||||||
|
@ -85,24 +103,23 @@ Seen Data
|
||||||
|
|
||||||
When some bit of data is extracted (such as an email address in the
|
When some bit of data is extracted (such as an email address in the
|
||||||
"From" header in a message over SMTP), the Intelligence Framework
|
"From" header in a message over SMTP), the Intelligence Framework
|
||||||
needs to be informed that this data was discovered and it's presence
|
needs to be informed that this data was discovered so that its presence
|
||||||
should be checked within the intelligence data set. This is
|
will be checked within the loaded intelligence data. This is
|
||||||
accomplished through the :bro:see:`Intel::seen` function.
|
accomplished through the :bro:see:`Intel::seen` function, however
|
||||||
|
typically users won't need to work with this function due to the
|
||||||
|
scripts included with Bro that will call this function.
|
||||||
|
|
||||||
Typically users won't need to work with this function due to built in
|
To load all of the scripts included with Bro for sending "seen" data to
|
||||||
hook scripts that Bro ships with that will "see" data and send it into
|
the intelligence framework, just add this line to local.bro::
|
||||||
the intelligence framework. A user may only need to load the entire
|
|
||||||
package of hook scripts as a module or pick and choose specific
|
@load policy/frameworks/intel/seen
|
||||||
scripts to load. Keep in mind that as more data is sent into the
|
|
||||||
|
Alternatively, specific scripts in that directory can be loaded.
|
||||||
|
Keep in mind that as more data is sent into the
|
||||||
intelligence framework, the CPU load consumed by Bro will increase
|
intelligence framework, the CPU load consumed by Bro will increase
|
||||||
depending on how many times the :bro:see:`Intel::seen` function is
|
depending on how many times the :bro:see:`Intel::seen` function is
|
||||||
being called which is heavily traffic dependent.
|
being called which is heavily traffic dependent.
|
||||||
|
|
||||||
The full package of hook scripts that Bro ships with for sending this
|
|
||||||
"seen" data into the intelligence framework can be loading by adding
|
|
||||||
this line to local.bro::
|
|
||||||
|
|
||||||
@load policy/frameworks/intel/seen
|
|
||||||
|
|
||||||
Intelligence Matches
|
Intelligence Matches
|
||||||
********************
|
********************
|
||||||
|
@ -111,6 +128,7 @@ Against all hopes, most networks will eventually have a hit on
|
||||||
intelligence data which could indicate a possible compromise or other
|
intelligence data which could indicate a possible compromise or other
|
||||||
unwanted activity. The Intelligence Framework provides an event that
|
unwanted activity. The Intelligence Framework provides an event that
|
||||||
is generated whenever a match is discovered named :bro:see:`Intel::match`.
|
is generated whenever a match is discovered named :bro:see:`Intel::match`.
|
||||||
|
|
||||||
Due to design restrictions placed upon
|
Due to design restrictions placed upon
|
||||||
the intelligence framework, there is no assurance as to where this
|
the intelligence framework, there is no assurance as to where this
|
||||||
event will be generated. It could be generated on the worker where
|
event will be generated. It could be generated on the worker where
|
||||||
|
@ -119,3 +137,7 @@ handled, only the data given as event arguments to the event can be
|
||||||
assured since the host where the data was seen may not be where
|
assured since the host where the data was seen may not be where
|
||||||
``Intel::match`` is handled.
|
``Intel::match`` is handled.
|
||||||
|
|
||||||
|
Intelligence matches are logged to the intel.log file. For a description of
|
||||||
|
each field in that file, see the documentation for the :bro:see:`Intel::Info`
|
||||||
|
record.
|
||||||
|
|
||||||
|
|
|
@ -23,17 +23,18 @@ In contrast to the ASCII reader and writer, the SQLite plugins have not yet
|
||||||
seen extensive use in production environments. While we are not aware
|
seen extensive use in production environments. While we are not aware
|
||||||
of any issues with them, we urge to caution when using them
|
of any issues with them, we urge to caution when using them
|
||||||
in production environments. There could be lingering issues which only occur
|
in production environments. There could be lingering issues which only occur
|
||||||
when the plugins are used with high amounts of data or in high-load environments.
|
when the plugins are used with high amounts of data or in high-load
|
||||||
|
environments.
|
||||||
|
|
||||||
Logging Data into SQLite Databases
|
Logging Data into SQLite Databases
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
Logging support for SQLite is available in all Bro installations starting with
|
Logging support for SQLite is available in all Bro installations starting with
|
||||||
version 2.2. There is no need to load any additional scripts or for any compile-time
|
version 2.2. There is no need to load any additional scripts or for any
|
||||||
configurations.
|
compile-time configurations.
|
||||||
|
|
||||||
Sending data from existing logging streams to SQLite is rather straightforward. You
|
Sending data from existing logging streams to SQLite is rather straightforward.
|
||||||
have to define a filter which specifies SQLite as the writer.
|
You have to define a filter which specifies SQLite as the writer.
|
||||||
|
|
||||||
The following example code adds SQLite as a filter for the connection log:
|
The following example code adds SQLite as a filter for the connection log:
|
||||||
|
|
||||||
|
@ -44,15 +45,15 @@ The following example code adds SQLite as a filter for the connection log:
|
||||||
# Make sure this parses correctly at least.
|
# Make sure this parses correctly at least.
|
||||||
@TEST-EXEC: bro ${DOC_ROOT}/frameworks/sqlite-conn-filter.bro
|
@TEST-EXEC: bro ${DOC_ROOT}/frameworks/sqlite-conn-filter.bro
|
||||||
|
|
||||||
Bro will create the database file ``/var/db/conn.sqlite``, if it does not already exist.
|
Bro will create the database file ``/var/db/conn.sqlite``, if it does not
|
||||||
It will also create a table with the name ``conn`` (if it does not exist) and start
|
already exist. It will also create a table with the name ``conn`` (if it
|
||||||
appending connection information to the table.
|
does not exist) and start appending connection information to the table.
|
||||||
|
|
||||||
At the moment, SQLite databases are not rotated the same way ASCII log-files are. You
|
At the moment, SQLite databases are not rotated the same way ASCII log-files
|
||||||
have to take care to create them in an adequate location.
|
are. You have to take care to create them in an adequate location.
|
||||||
|
|
||||||
If you examine the resulting SQLite database, the schema will contain the same fields
|
If you examine the resulting SQLite database, the schema will contain the
|
||||||
that are present in the ASCII log files::
|
same fields that are present in the ASCII log files::
|
||||||
|
|
||||||
# sqlite3 /var/db/conn.sqlite
|
# sqlite3 /var/db/conn.sqlite
|
||||||
|
|
||||||
|
@ -67,35 +68,39 @@ that are present in the ASCII log files::
|
||||||
'id.orig_p' integer,
|
'id.orig_p' integer,
|
||||||
...
|
...
|
||||||
|
|
||||||
Note that the ASCII ``conn.log`` will still be created. To disable the ASCII writer for a
|
Note that the ASCII ``conn.log`` will still be created. To prevent this file
|
||||||
log stream, you can remove the default filter:
|
from being created, you can remove the default filter:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
Log::remove_filter(Conn::LOG, "default");
|
Log::remove_filter(Conn::LOG, "default");
|
||||||
|
|
||||||
|
|
||||||
To create a custom SQLite log file, you have to create a new log stream that contains
|
To create a custom SQLite log file, you have to create a new log stream
|
||||||
just the information you want to commit to the database. Please refer to the
|
that contains just the information you want to commit to the database.
|
||||||
:ref:`framework-logging` documentation on how to create custom log streams.
|
Please refer to the :ref:`framework-logging` documentation on how to
|
||||||
|
create custom log streams.
|
||||||
|
|
||||||
Reading Data from SQLite Databases
|
Reading Data from SQLite Databases
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
Like logging support, support for reading data from SQLite databases is built into Bro starting
|
Like logging support, support for reading data from SQLite databases is
|
||||||
with version 2.2.
|
built into Bro starting with version 2.2.
|
||||||
|
|
||||||
Just as with the text-based input readers (please refer to the :ref:`framework-input`
|
Just as with the text-based input readers (please refer to the
|
||||||
documentation for them and for basic information on how to use the input-framework), the SQLite reader
|
:ref:`framework-input` documentation for them and for basic information
|
||||||
can be used to read data - in this case the result of SQL queries - into tables or into events.
|
on how to use the input framework), the SQLite reader can be used to
|
||||||
|
read data - in this case the result of SQL queries - into tables or into
|
||||||
|
events.
|
||||||
|
|
||||||
Reading Data into Tables
|
Reading Data into Tables
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
To read data from a SQLite database, we first have to provide Bro with the information, how
|
To read data from a SQLite database, we first have to provide Bro with
|
||||||
the resulting data will be structured. For this example, we expect that we have a SQLite database,
|
the information, how the resulting data will be structured. For this
|
||||||
which contains host IP addresses and the user accounts that are allowed to log into a specific
|
example, we expect that we have a SQLite database, which contains
|
||||||
machine.
|
host IP addresses and the user accounts that are allowed to log into
|
||||||
|
a specific machine.
|
||||||
|
|
||||||
The SQLite commands to create the schema are as follows::
|
The SQLite commands to create the schema are as follows::
|
||||||
|
|
||||||
|
@ -107,8 +112,8 @@ The SQLite commands to create the schema are as follows::
|
||||||
insert into machines_to_users values ('192.168.17.2', 'bernhard');
|
insert into machines_to_users values ('192.168.17.2', 'bernhard');
|
||||||
insert into machines_to_users values ('192.168.17.3', 'seth,matthias');
|
insert into machines_to_users values ('192.168.17.3', 'seth,matthias');
|
||||||
|
|
||||||
After creating a file called ``hosts.sqlite`` with this content, we can read the resulting table
|
After creating a file called ``hosts.sqlite`` with this content, we can
|
||||||
into Bro:
|
read the resulting table into Bro:
|
||||||
|
|
||||||
.. btest-include:: ${DOC_ROOT}/frameworks/sqlite-read-table.bro
|
.. btest-include:: ${DOC_ROOT}/frameworks/sqlite-read-table.bro
|
||||||
|
|
||||||
|
@ -117,22 +122,25 @@ into Bro:
|
||||||
# Make sure this parses correctly at least.
|
# Make sure this parses correctly at least.
|
||||||
@TEST-EXEC: bro ${DOC_ROOT}/frameworks/sqlite-read-table.bro
|
@TEST-EXEC: bro ${DOC_ROOT}/frameworks/sqlite-read-table.bro
|
||||||
|
|
||||||
Afterwards, that table can be used to check logins into hosts against the available
|
Afterwards, that table can be used to check logins into hosts against
|
||||||
userlist.
|
the available userlist.
|
||||||
|
|
||||||
Turning Data into Events
|
Turning Data into Events
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
The second mode is to use the SQLite reader to output the input data as events. Typically there
|
The second mode is to use the SQLite reader to output the input data as events.
|
||||||
are two reasons to do this. First, when the structure of the input data is too complicated
|
Typically there are two reasons to do this. First, when the structure of
|
||||||
for a direct table import. In this case, the data can be read into an event which can then
|
the input data is too complicated for a direct table import. In this case,
|
||||||
create the necessary data structures in Bro in scriptland.
|
the data can be read into an event which can then create the necessary
|
||||||
|
data structures in Bro in scriptland.
|
||||||
|
|
||||||
The second reason is, that the dataset is too big to hold it in memory. In this case, the checks
|
The second reason is, that the dataset is too big to hold it in memory. In
|
||||||
can be performed on-demand, when Bro encounters a situation where it needs additional information.
|
this case, the checks can be performed on-demand, when Bro encounters a
|
||||||
|
situation where it needs additional information.
|
||||||
|
|
||||||
An example for this would be an internal huge database with malware hashes. Live database queries
|
An example for this would be an internal huge database with malware
|
||||||
could be used to check the sporadically happening downloads against the database.
|
hashes. Live database queries could be used to check the sporadically
|
||||||
|
happening downloads against the database.
|
||||||
|
|
||||||
The SQLite commands to create the schema are as follows::
|
The SQLite commands to create the schema are as follows::
|
||||||
|
|
||||||
|
@ -151,9 +159,10 @@ The SQLite commands to create the schema are as follows::
|
||||||
insert into malware_hashes values ('73f45106968ff8dc51fba105fa91306af1ff6666', 'ftp-trace');
|
insert into malware_hashes values ('73f45106968ff8dc51fba105fa91306af1ff6666', 'ftp-trace');
|
||||||
|
|
||||||
|
|
||||||
The following code uses the file-analysis framework to get the sha1 hashes of files that are
|
The following code uses the file-analysis framework to get the sha1 hashes
|
||||||
transmitted over the network. For each hash, a SQL-query is run against SQLite. If the query
|
of files that are transmitted over the network. For each hash, a SQL-query
|
||||||
returns with a result, we had a hit against our malware-database and output the matching hash.
|
is run against SQLite. If the query returns with a result, we had a hit
|
||||||
|
against our malware-database and output the matching hash.
|
||||||
|
|
||||||
.. btest-include:: ${DOC_ROOT}/frameworks/sqlite-read-events.bro
|
.. btest-include:: ${DOC_ROOT}/frameworks/sqlite-read-events.bro
|
||||||
|
|
||||||
|
@ -162,5 +171,5 @@ returns with a result, we had a hit against our malware-database and output the
|
||||||
# Make sure this parses correctly at least.
|
# Make sure this parses correctly at least.
|
||||||
@TEST-EXEC: bro ${DOC_ROOT}/frameworks/sqlite-read-events.bro
|
@TEST-EXEC: bro ${DOC_ROOT}/frameworks/sqlite-read-events.bro
|
||||||
|
|
||||||
If you run this script against the trace in ``testing/btest/Traces/ftp/ipv4.trace``, you
|
If you run this script against the trace in
|
||||||
will get one hit.
|
``testing/btest/Traces/ftp/ipv4.trace``, you will get one hit.
|
||||||
|
|
|
@ -19,195 +19,144 @@ Terminology
|
||||||
|
|
||||||
Bro's logging interface is built around three main abstractions:
|
Bro's logging interface is built around three main abstractions:
|
||||||
|
|
||||||
Log streams
|
Streams
|
||||||
A stream corresponds to a single log. It defines the set of
|
A log stream corresponds to a single log. It defines the set of
|
||||||
fields that a log consists of with their names and fields.
|
fields that a log consists of with their names and types.
|
||||||
Examples are the ``conn`` for recording connection summaries,
|
Examples are the ``conn`` stream for recording connection summaries,
|
||||||
and the ``http`` stream for recording HTTP activity.
|
and the ``http`` stream for recording HTTP activity.
|
||||||
|
|
||||||
Filters
|
Filters
|
||||||
Each stream has a set of filters attached to it that determine
|
Each stream has a set of filters attached to it that determine
|
||||||
what information gets written out. By default, each stream has
|
what information gets written out. By default, each stream has
|
||||||
one default filter that just logs everything directly to disk
|
one default filter that just logs everything directly to disk.
|
||||||
with an automatically generated file name. However, further
|
However, additional filters can be added to record only a subset
|
||||||
filters can be added to record only a subset, split a stream
|
of the log records, write to different outputs, or set a custom
|
||||||
into different outputs, or to even duplicate the log to
|
rotation interval. If all filters are removed from a stream,
|
||||||
multiple outputs. If all filters are removed from a stream,
|
then output is disabled for that stream.
|
||||||
all output is disabled.
|
|
||||||
|
|
||||||
Writers
|
Writers
|
||||||
A writer defines the actual output format for the information
|
Each filter has a writer. A writer defines the actual output
|
||||||
being logged. At the moment, Bro comes with only one type of
|
format for the information being logged. The default writer is
|
||||||
writer, which produces tab separated ASCII files. In the
|
the ASCII writer, which produces tab-separated ASCII files. Other
|
||||||
future we will add further writers, like for binary output and
|
writers are available, like for binary output or direct logging
|
||||||
direct logging into a database.
|
into a database.
|
||||||
|
|
||||||
Basics
|
There are several different ways to customize Bro's logging: you can create
|
||||||
======
|
a new log stream, you can extend an existing log with new fields, you
|
||||||
|
can apply filters to an existing log stream, or you can customize the output
|
||||||
|
format by setting log writer options. All of these approaches are
|
||||||
|
described in this document.
|
||||||
|
|
||||||
The data fields that a stream records are defined by a record type
|
Streams
|
||||||
specified when it is created. Let's look at the script generating Bro's
|
=======
|
||||||
connection summaries as an example,
|
|
||||||
:doc:`/scripts/base/protocols/conn/main.bro`. It defines a record
|
|
||||||
:bro:type:`Conn::Info` that lists all the fields that go into
|
|
||||||
``conn.log``, each marked with a ``&log`` attribute indicating that it
|
|
||||||
is part of the information written out. To write a log record, the
|
|
||||||
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``
|
In order to log data to a new log stream, all of the following needs to be
|
||||||
that generates the normal output by recording all record fields into a
|
done:
|
||||||
single output file.
|
|
||||||
|
|
||||||
In the following, we summarize ways in which the logging can be
|
- A :bro:type:`record` type must be defined which consists of all the
|
||||||
customized. We continue using the connection summaries as our example
|
fields that will be logged (by convention, the name of this record type is
|
||||||
to work with.
|
usually "Info").
|
||||||
|
- A log stream ID (an :bro:type:`enum` with type name "Log::ID") must be
|
||||||
|
defined that uniquely identifies the new log stream.
|
||||||
|
- A log stream must be created using the :bro:id:`Log::create_stream` function.
|
||||||
|
- When the data to be logged becomes available, the :bro:id:`Log::write`
|
||||||
|
function must be called.
|
||||||
|
|
||||||
Filtering
|
In the following example, we create a new module "Foo" which creates
|
||||||
---------
|
a new log stream.
|
||||||
|
|
||||||
To create 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
|
|
||||||
logged:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
event bro_init()
|
module Foo;
|
||||||
{
|
|
||||||
# Add a new filter to the Conn::LOG stream that logs only
|
export {
|
||||||
# timestamp and originator address.
|
# Create an ID for our new stream. By convention, this is
|
||||||
local filter: Log::Filter = [$name="orig-only", $path="origs", $include=set("ts", "id.orig_h")];
|
# called "LOG".
|
||||||
Log::add_filter(Conn::LOG, filter);
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
|
# Define the record type that will contain the data to log.
|
||||||
|
type Info: record {
|
||||||
|
ts: time &log;
|
||||||
|
id: conn_id &log;
|
||||||
|
service: string &log &optional;
|
||||||
|
missed_bytes: count &log &default=0;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Note the fields that are set for the filter:
|
# Optionally, we can add a new field to the connection record so that
|
||||||
|
# the data we are logging (our "Info" record) will be easily
|
||||||
|
# accessible in a variety of event handlers.
|
||||||
|
redef record connection += {
|
||||||
|
# By convention, the name of this new field is the lowercase name
|
||||||
|
# of the module.
|
||||||
|
foo: Info &optional;
|
||||||
|
};
|
||||||
|
|
||||||
``name``
|
# This event is handled at a priority higher than zero so that if
|
||||||
A mandatory name for the filter that can later be used
|
# users modify this stream in another script, they can do so at the
|
||||||
to manipulate it further.
|
# default priority of zero.
|
||||||
|
event bro_init() &priority=5
|
||||||
|
{
|
||||||
|
# Create the stream. This adds a default filter automatically.
|
||||||
|
Log::create_stream(Foo::LOG, [$columns=Info, $path="foo"]);
|
||||||
|
}
|
||||||
|
|
||||||
``path``
|
In the definition of the "Info" record above, notice that each field has the
|
||||||
The filename for the output file, without any extension (which
|
:bro:attr:`&log` attribute. Without this attribute, a field will not appear in
|
||||||
may be automatically added by the writer). Default path values
|
the log output. Also notice one field has the :bro:attr:`&optional` attribute.
|
||||||
are generated by taking the stream's ID and munging it slightly.
|
This indicates that the field might not be assigned any value before the
|
||||||
:bro:enum:`Conn::LOG` is converted into ``conn``,
|
log record is written. Finally, a field with the :bro:attr:`&default`
|
||||||
:bro:enum:`PacketFilter::LOG` is converted into
|
attribute has a default value assigned to it automatically.
|
||||||
``packet_filter``, and :bro:enum:`Known::CERTS_LOG` is
|
|
||||||
converted into ``known_certs``.
|
|
||||||
|
|
||||||
``include``
|
At this point, the only thing missing is a call to the :bro:id:`Log::write`
|
||||||
A set limiting the fields to the ones given. The names
|
function to send data to the logging framework. The actual event handler
|
||||||
correspond to those in the :bro:type:`Conn::Info` record, with
|
where this should take place will depend on where your data becomes available.
|
||||||
sub-records unrolled by concatenating fields (separated with
|
In this example, the :bro:id:`connection_established` event provides our data,
|
||||||
dots).
|
and we also store a copy of the data being logged into the
|
||||||
|
:bro:type:`connection` record:
|
||||||
Using the code above, you will now get a new log file ``origs.log``
|
|
||||||
that looks like this::
|
|
||||||
|
|
||||||
#separator \x09
|
|
||||||
#path origs
|
|
||||||
#fields ts id.orig_h
|
|
||||||
#types time addr
|
|
||||||
1128727430.350788 141.42.64.125
|
|
||||||
1128727435.450898 141.42.64.125
|
|
||||||
|
|
||||||
If you want to make this the only log file for the stream, you can
|
|
||||||
remove the default filter (which, conveniently, has the name
|
|
||||||
``default``):
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
event bro_init()
|
event connection_established(c: connection)
|
||||||
{
|
{
|
||||||
# Remove the filter called "default".
|
local rec: Foo::Info = [$ts=network_time(), $id=c$id];
|
||||||
Log::remove_filter(Conn::LOG, "default");
|
|
||||||
|
# Store a copy of the data in the connection record so other
|
||||||
|
# event handlers can access it.
|
||||||
|
c$foo = rec;
|
||||||
|
|
||||||
|
Log::write(Foo::LOG, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
An alternate approach to "turning off" a log is to completely disable
|
If you run Bro with this script, a new log file ``foo.log`` will be created.
|
||||||
the stream:
|
Although we only specified four fields in the "Info" record above, the
|
||||||
|
log output will actually contain seven fields because one of the fields
|
||||||
|
(the one named "id") is itself a record type. Since a :bro:type:`conn_id`
|
||||||
|
record has four fields, then each of these fields is a separate column in
|
||||||
|
the log output. Note that the way that such fields are named in the log
|
||||||
|
output differs slightly from the way we would refer to the same field
|
||||||
|
in a Bro script (each dollar sign is replaced with a period). For example,
|
||||||
|
to access the first field of a ``conn_id`` in a Bro script we would use
|
||||||
|
the notation ``id$orig_h``, but that field is named ``id.orig_h``
|
||||||
|
in the log output.
|
||||||
|
|
||||||
.. code:: bro
|
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.
|
||||||
|
Normally data saved to the connection record will remain there for the
|
||||||
|
duration of the connection and from a practical perspective it's not
|
||||||
|
uncommon to need to delete that data before the end of the connection.
|
||||||
|
|
||||||
event bro_init()
|
|
||||||
{
|
|
||||||
Log::disable_stream(Conn::LOG);
|
|
||||||
}
|
|
||||||
|
|
||||||
If you want to skip only some fields but keep the rest, there is a
|
Add Fields to a Log
|
||||||
corresponding ``exclude`` filter attribute that you can use instead of
|
-------------------
|
||||||
``include`` to list only the ones you are not interested in.
|
|
||||||
|
|
||||||
A filter can also determine output paths *dynamically* based on the
|
You can add additional fields to a log by extending the record
|
||||||
record being logged. That allows, e.g., to record local and remote
|
type that defines its content, and setting a value for the new fields
|
||||||
connections into separate files. To do this, you define a function
|
before each log record is written.
|
||||||
that returns the desired path:
|
|
||||||
|
|
||||||
.. code:: bro
|
Let's say we want to add a boolean field ``is_private`` to
|
||||||
|
:bro:type:`Conn::Info` that indicates whether the originator IP address
|
||||||
function split_log(id: Log::ID, path: string, rec: Conn::Info) : string
|
is part of the :rfc:`1918` space:
|
||||||
{
|
|
||||||
# Return "conn-local" if originator is a local IP, otherwise "conn-remote".
|
|
||||||
local lr = Site::is_local_addr(rec$id$orig_h) ? "local" : "remote";
|
|
||||||
return fmt("%s-%s", path, lr);
|
|
||||||
}
|
|
||||||
|
|
||||||
event bro_init()
|
|
||||||
{
|
|
||||||
local filter: Log::Filter = [$name="conn-split", $path_func=split_log, $include=set("ts", "id.orig_h")];
|
|
||||||
Log::add_filter(Conn::LOG, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
Running this will now produce two files, ``local.log`` and
|
|
||||||
``remote.log``, with the corresponding entries. One could extend this
|
|
||||||
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
|
|
||||||
quickly ...
|
|
||||||
|
|
||||||
.. sidebar:: A More Generic Path Function
|
|
||||||
|
|
||||||
The ``split_log`` method has one draw-back: it can be used
|
|
||||||
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
|
|
||||||
variant:
|
|
||||||
|
|
||||||
.. code:: bro
|
|
||||||
|
|
||||||
function split_log(id: Log::ID, path: string, rec: record { id: conn_id; } ) : string
|
|
||||||
{
|
|
||||||
return Site::is_local_addr(rec$id$orig_h) ? "local" : "remote";
|
|
||||||
}
|
|
||||||
|
|
||||||
This function can be used with all log streams that have records
|
|
||||||
containing an ``id: conn_id`` field.
|
|
||||||
|
|
||||||
While so far we have seen how to customize the columns being logged,
|
|
||||||
you can also control which records are written out by providing a
|
|
||||||
predicate that will be called for each log record:
|
|
||||||
|
|
||||||
.. code:: bro
|
|
||||||
|
|
||||||
function http_only(rec: Conn::Info) : bool
|
|
||||||
{
|
|
||||||
# Record only connections with successfully analyzed HTTP traffic
|
|
||||||
return rec$service == "http";
|
|
||||||
}
|
|
||||||
|
|
||||||
event bro_init()
|
|
||||||
{
|
|
||||||
local filter: Log::Filter = [$name="http-only", $path="conn-http", $pred=http_only];
|
|
||||||
Log::add_filter(Conn::LOG, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
This will result in a log file ``conn-http.log`` that contains only
|
|
||||||
traffic detected and analyzed as HTTP traffic.
|
|
||||||
|
|
||||||
Extending
|
|
||||||
---------
|
|
||||||
|
|
||||||
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
|
|
||||||
field ``is_private`` to :bro:type:`Conn::Info` that indicates whether the
|
|
||||||
originator IP address is part of the :rfc:`1918` space:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
|
@ -218,9 +167,21 @@ originator IP address is part of the :rfc:`1918` space:
|
||||||
is_private: bool &default=F &log;
|
is_private: bool &default=F &log;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
As this example shows, when extending a log stream's "Info" record, each
|
||||||
|
new field must always be declared either with a ``&default`` value or
|
||||||
|
as ``&optional``. Furthermore, you need to add the ``&log`` attribute
|
||||||
|
or otherwise the field won't appear in the log file.
|
||||||
|
|
||||||
Now we need to set the field. A connection's summary is generated at
|
Now we need to set the field. Although the details vary depending on which
|
||||||
the time its state is removed from memory. We can add another handler
|
log is being extended, in general it is important to choose a suitable event
|
||||||
|
in which to set the additional fields because we need to make sure that
|
||||||
|
the fields are set before the log record is written. Sometimes the right
|
||||||
|
choice is the same event which writes the log record, but at a higher
|
||||||
|
priority (in order to ensure that the event handler that sets the additional
|
||||||
|
fields is executed before the event handler that writes the log record).
|
||||||
|
|
||||||
|
In this example, since a connection's summary is generated at
|
||||||
|
the time its state is removed from memory, we can add another handler
|
||||||
at that time that sets our field correctly:
|
at that time that sets our field correctly:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
@ -232,31 +193,58 @@ at that time that sets our field correctly:
|
||||||
}
|
}
|
||||||
|
|
||||||
Now ``conn.log`` will show a new field ``is_private`` of type
|
Now ``conn.log`` will show a new field ``is_private`` of type
|
||||||
``bool``.
|
``bool``. If you look at the Bro script which defines the connection
|
||||||
|
log stream :doc:`/scripts/base/protocols/conn/main.bro`, you will see
|
||||||
|
that ``Log::write`` gets called in an event handler for the
|
||||||
|
same event as used in this example to set the additional fields, but at a
|
||||||
|
lower priority than the one used in this example (i.e., the log record gets
|
||||||
|
written after we assign the ``is_private`` field).
|
||||||
|
|
||||||
Notes:
|
For extending logs this way, one needs a bit of knowledge about how
|
||||||
|
the script that creates the log stream is organizing its state
|
||||||
|
keeping. Most of the standard Bro scripts attach their log state to
|
||||||
|
the :bro:type:`connection` record where it can then be accessed, just
|
||||||
|
like ``c$conn`` above. For example, the HTTP analysis adds a field
|
||||||
|
``http`` of type :bro:type:`HTTP::Info` to the :bro:type:`connection`
|
||||||
|
record.
|
||||||
|
|
||||||
- For extending logs this way, one needs a bit of knowledge about how
|
|
||||||
the script that creates the log stream is organizing its state
|
|
||||||
keeping. Most of the standard Bro scripts attach their log state to
|
|
||||||
the :bro:type:`connection` record where it can then be accessed, just
|
|
||||||
as the ``c$conn`` above. For example, the HTTP analysis adds a field
|
|
||||||
``http`` of type :bro:type:`HTTP::Info` to the :bro:type:`connection`
|
|
||||||
record. See the script reference for more information.
|
|
||||||
|
|
||||||
- When extending records as shown above, the new fields must always be
|
Define a Logging Event
|
||||||
declared either with a ``&default`` value or as ``&optional``.
|
----------------------
|
||||||
Furthermore, you need to add the ``&log`` attribute or otherwise the
|
|
||||||
field won't appear in the output.
|
|
||||||
|
|
||||||
Hooking into the Logging
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
Sometimes it is helpful to do additional analysis of the information
|
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. To do this, we
|
||||||
default log streams define such an event. For example, the connection
|
need to modify the example module shown above to look something like this:
|
||||||
log stream raises the event :bro:id:`Conn::log_conn`. You
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
module Foo;
|
||||||
|
|
||||||
|
export {
|
||||||
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
|
type Info: record {
|
||||||
|
ts: time &log;
|
||||||
|
id: conn_id &log;
|
||||||
|
service: string &log &optional;
|
||||||
|
missed_bytes: count &log &default=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Define a logging event. By convention, this is called
|
||||||
|
# "log_<stream>".
|
||||||
|
global log_foo: event(rec: Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
event bro_init() &priority=5
|
||||||
|
{
|
||||||
|
# Specify the "log_foo" event here in order for Bro to raise it.
|
||||||
|
Log::create_stream(Foo::LOG, [$columns=Info, $ev=log_foo,
|
||||||
|
$path="foo"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
All of Bro's default log streams define such an event. For example, the
|
||||||
|
connection log stream raises the event :bro:id:`Conn::log_conn`. You
|
||||||
could use that for example for flagging when a connection to a
|
could use that for example for flagging when a connection to a
|
||||||
specific destination exceeds a certain duration:
|
specific destination exceeds a certain duration:
|
||||||
|
|
||||||
|
@ -270,7 +258,7 @@ specific destination exceeds a certain duration:
|
||||||
|
|
||||||
event Conn::log_conn(rec: Conn::Info)
|
event Conn::log_conn(rec: Conn::Info)
|
||||||
{
|
{
|
||||||
if ( rec$duration > 5mins )
|
if ( rec?$duration && rec$duration > 5mins )
|
||||||
NOTICE([$note=Long_Conn_Found,
|
NOTICE([$note=Long_Conn_Found,
|
||||||
$msg=fmt("unusually long conn to %s", rec$id$resp_h),
|
$msg=fmt("unusually long conn to %s", rec$id$resp_h),
|
||||||
$id=rec$id]);
|
$id=rec$id]);
|
||||||
|
@ -281,15 +269,196 @@ externally with Perl scripts. Much of what such an external script
|
||||||
would do later offline, one may instead do directly inside of Bro in
|
would do later offline, one may instead do directly inside of Bro in
|
||||||
real-time.
|
real-time.
|
||||||
|
|
||||||
Rotation
|
Disable a Stream
|
||||||
--------
|
----------------
|
||||||
|
|
||||||
By default, no log rotation occurs, but it's globally controllable for all
|
One way to "turn off" a log is to completely disable the stream. For
|
||||||
filters by redefining the :bro:id:`Log::default_rotation_interval` option:
|
example, the following example will prevent the conn.log from being written:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
redef Log::default_rotation_interval = 1 hr;
|
event bro_init()
|
||||||
|
{
|
||||||
|
Log::disable_stream(Conn::LOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
Note that this must run after the stream is created, so the priority
|
||||||
|
of this event handler must be lower than the priority of the event handler
|
||||||
|
where the stream was created.
|
||||||
|
|
||||||
|
|
||||||
|
Filters
|
||||||
|
=======
|
||||||
|
|
||||||
|
A stream has one or more filters attached to it (a stream without any filters
|
||||||
|
will not produce any log output). When a stream is created, it automatically
|
||||||
|
gets a default filter attached to it. This default filter can be removed
|
||||||
|
or replaced, or other filters can be added to the stream. This is accomplished
|
||||||
|
by using either the :bro:id:`Log::add_filter` or :bro:id:`Log::remove_filter`
|
||||||
|
function. This section shows how to use filters to do such tasks as
|
||||||
|
rename a log file, split the output into multiple files, control which
|
||||||
|
records are written, and set a custom rotation interval.
|
||||||
|
|
||||||
|
Rename Log File
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Normally, the log filename for a given log stream is determined when the
|
||||||
|
stream is created, unless you explicitly specify a different one by adding
|
||||||
|
a filter.
|
||||||
|
|
||||||
|
The easiest way to change a log filename is to simply replace the
|
||||||
|
default log filter with a new filter that specifies a value for the "path"
|
||||||
|
field. In this example, "conn.log" will be changed to "myconn.log":
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
# Replace default filter for the Conn::LOG stream in order to
|
||||||
|
# change the log filename.
|
||||||
|
|
||||||
|
local f = Log::get_filter(Conn::LOG, "default");
|
||||||
|
f$path = "myconn";
|
||||||
|
Log::add_filter(Conn::LOG, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
Keep in mind that the "path" field of a log filter never contains the
|
||||||
|
filename extension. The extension will be determined later by the log writer.
|
||||||
|
|
||||||
|
Add a New Log File
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Normally, a log stream writes to only one log file. However, you can
|
||||||
|
add filters so that the stream writes to multiple files. This is useful
|
||||||
|
if you want to restrict the set of fields being logged to the new file.
|
||||||
|
|
||||||
|
In this example, a new filter is added to the Conn::LOG stream that writes
|
||||||
|
two fields to a new log file:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
# Add a new filter to the Conn::LOG stream that logs only
|
||||||
|
# timestamp and originator address.
|
||||||
|
|
||||||
|
local filter: Log::Filter = [$name="orig-only", $path="origs",
|
||||||
|
$include=set("ts", "id.orig_h")];
|
||||||
|
Log::add_filter(Conn::LOG, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Notice how the "include" filter attribute specifies a set that limits the
|
||||||
|
fields to the ones given. The names correspond to those in the
|
||||||
|
:bro:type:`Conn::Info` record (however, because the "id" field is itself a
|
||||||
|
record, we can specify an individual field of "id" by the dot notation
|
||||||
|
shown in the example).
|
||||||
|
|
||||||
|
Using the code above, in addition to the regular ``conn.log``, you will
|
||||||
|
now also get a new log file ``origs.log`` that looks like the regular
|
||||||
|
``conn.log``, but will have only the fields specified in the "include"
|
||||||
|
filter attribute.
|
||||||
|
|
||||||
|
If you want to skip only some fields but keep the rest, there is a
|
||||||
|
corresponding ``exclude`` filter attribute that you can use instead of
|
||||||
|
``include`` to list only the ones you are not interested in.
|
||||||
|
|
||||||
|
If you want to make this the only log file for the stream, you can
|
||||||
|
remove the default filter:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
# Remove the filter called "default".
|
||||||
|
Log::remove_filter(Conn::LOG, "default");
|
||||||
|
}
|
||||||
|
|
||||||
|
Determine Log Path Dynamically
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Instead of using the "path" filter attribute, a filter can determine
|
||||||
|
output paths *dynamically* based on the record being logged. That
|
||||||
|
allows, e.g., to record local and remote connections into separate
|
||||||
|
files. To do this, you define a function that returns the desired path,
|
||||||
|
and use the "path_func" filter attribute:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
# Note: if using BroControl then you don't need to redef local_nets.
|
||||||
|
redef Site::local_nets = { 192.168.0.0/16 };
|
||||||
|
|
||||||
|
function myfunc(id: Log::ID, path: string, rec: Conn::Info) : string
|
||||||
|
{
|
||||||
|
# Return "conn-local" if originator is a local IP, otherwise
|
||||||
|
# return "conn-remote".
|
||||||
|
local r = Site::is_local_addr(rec$id$orig_h) ? "local" : "remote";
|
||||||
|
return fmt("%s-%s", path, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
local filter: Log::Filter = [$name="conn-split",
|
||||||
|
$path_func=myfunc, $include=set("ts", "id.orig_h")];
|
||||||
|
Log::add_filter(Conn::LOG, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
Running this will now produce two new files, ``conn-local.log`` and
|
||||||
|
``conn-remote.log``, with the corresponding entries (for this example to work,
|
||||||
|
the ``Site::local_nets`` must specify your local network). One could extend
|
||||||
|
this 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
|
||||||
|
quickly.
|
||||||
|
|
||||||
|
The ``myfunc`` function has one drawback: it can be used
|
||||||
|
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
|
||||||
|
variant:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
function myfunc(id: Log::ID, path: string,
|
||||||
|
rec: record { id: conn_id; } ) : string
|
||||||
|
{
|
||||||
|
local r = Site::is_local_addr(rec$id$orig_h) ? "local" : "remote";
|
||||||
|
return fmt("%s-%s", path, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
This function can be used with all log streams that have records
|
||||||
|
containing an ``id: conn_id`` field.
|
||||||
|
|
||||||
|
Filter Log Records
|
||||||
|
------------------
|
||||||
|
|
||||||
|
We have seen how to customize the columns being logged, but
|
||||||
|
you can also control which records are written out by providing a
|
||||||
|
predicate that will be called for each log record:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
function http_only(rec: Conn::Info) : bool
|
||||||
|
{
|
||||||
|
# Record only connections with successfully analyzed HTTP traffic
|
||||||
|
return rec?$service && rec$service == "http";
|
||||||
|
}
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
local filter: Log::Filter = [$name="http-only", $path="conn-http",
|
||||||
|
$pred=http_only];
|
||||||
|
Log::add_filter(Conn::LOG, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
This will result in a new log file ``conn-http.log`` that contains only
|
||||||
|
the log records from ``conn.log`` that are analyzed as HTTP traffic.
|
||||||
|
|
||||||
|
Rotation
|
||||||
|
--------
|
||||||
|
|
||||||
|
The log rotation interval is globally controllable for all
|
||||||
|
filters by redefining the :bro:id:`Log::default_rotation_interval` option
|
||||||
|
(note that when using BroControl, this option is set automatically via
|
||||||
|
the BroControl configuration).
|
||||||
|
|
||||||
Or specifically for certain :bro:type:`Log::Filter` instances by setting
|
Or specifically for certain :bro:type:`Log::Filter` instances by setting
|
||||||
their ``interv`` field. Here's an example of changing just the
|
their ``interv`` field. Here's an example of changing just the
|
||||||
|
@ -301,90 +470,73 @@ their ``interv`` field. Here's an example of changing just the
|
||||||
{
|
{
|
||||||
local f = Log::get_filter(Conn::LOG, "default");
|
local f = Log::get_filter(Conn::LOG, "default");
|
||||||
f$interv = 1 min;
|
f$interv = 1 min;
|
||||||
Log::remove_filter(Conn::LOG, "default");
|
|
||||||
Log::add_filter(Conn::LOG, f);
|
Log::add_filter(Conn::LOG, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASCII Writer Configuration
|
Writers
|
||||||
--------------------------
|
=======
|
||||||
|
|
||||||
The ASCII writer has a number of options for customizing the format of
|
Each filter has a writer. If you do not specify a writer when adding a
|
||||||
its output, see :doc:`/scripts/base/frameworks/logging/writers/ascii.bro`.
|
filter to a stream, then the ASCII writer is the default.
|
||||||
|
|
||||||
Adding Streams
|
There are two ways to specify a non-default writer. To change the default
|
||||||
==============
|
writer for all log filters, just redefine the :bro:id:`Log::default_writer`
|
||||||
|
option. Alternatively, you can specify the writer to use on a per-filter
|
||||||
|
basis by setting a value for the filter's "writer" field. Consult the
|
||||||
|
documentation of the writer to use to see if there are other options that are
|
||||||
|
needed.
|
||||||
|
|
||||||
It's easy to create a new log stream for custom scripts. Here's an
|
ASCII Writer
|
||||||
example for the ``Foo`` module:
|
------------
|
||||||
|
|
||||||
|
By default, the ASCII writer outputs log files that begin with several
|
||||||
|
lines of metadata, followed by the actual log output. The metadata
|
||||||
|
describes the format of the log file, the "path" of the log (i.e., the log
|
||||||
|
filename without file extension), and also specifies the time that the log
|
||||||
|
was created and the time when Bro finished writing to it.
|
||||||
|
The ASCII writer has a number of options for customizing the format of its
|
||||||
|
output, see :doc:`/scripts/base/frameworks/logging/writers/ascii.bro`.
|
||||||
|
If you change the output format options, then be careful to check whether
|
||||||
|
your postprocessing scripts can still recognize your log files.
|
||||||
|
|
||||||
|
Some writer options are global (i.e., they affect all log filters using
|
||||||
|
that log writer). For example, to change the output format of all ASCII
|
||||||
|
logs to JSON format:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
module Foo;
|
redef LogAscii::use_json = T;
|
||||||
|
|
||||||
export {
|
Some writer options are filter-specific (i.e., they affect only the filters
|
||||||
# Create an ID for our new stream. By convention, this is
|
that explicitly specify the option). For example, to change the output
|
||||||
# called "LOG".
|
format of the ``conn.log`` only:
|
||||||
redef enum Log::ID += { LOG };
|
|
||||||
|
|
||||||
# Define the fields. By convention, the type is called "Info".
|
.. code:: bro
|
||||||
type Info: record {
|
|
||||||
ts: time &log;
|
|
||||||
id: conn_id &log;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Define a hook event. By convention, this is called
|
event bro_init()
|
||||||
# "log_<stream>".
|
|
||||||
global log_foo: event(rec: Info);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# This event should be handled at a higher priority so that when
|
|
||||||
# users modify your stream later and they do it at priority 0,
|
|
||||||
# their code runs after this.
|
|
||||||
event bro_init() &priority=5
|
|
||||||
{
|
{
|
||||||
# Create the stream. This also adds a default filter automatically.
|
local f = Log::get_filter(Conn::LOG, "default");
|
||||||
Log::create_stream(Foo::LOG, [$columns=Info, $ev=log_foo]);
|
# Use tab-separated-value mode
|
||||||
|
f$config = table(["tsv"] = "T");
|
||||||
|
Log::add_filter(Conn::LOG, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
You can also add the state to the :bro:type:`connection` record to make
|
|
||||||
it easily accessible across event handlers:
|
|
||||||
|
|
||||||
.. code:: bro
|
|
||||||
|
|
||||||
redef record connection += {
|
|
||||||
foo: Info &optional;
|
|
||||||
}
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
.. code:: bro
|
|
||||||
|
|
||||||
event connection_established(c: connection)
|
|
||||||
{
|
|
||||||
local rec: Foo::Info = [$ts=network_time(), $id=c$id];
|
|
||||||
c$foo = rec;
|
|
||||||
Log::write(Foo::LOG, rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
See the existing scripts for how to work with such a new connection
|
|
||||||
field. A simple example is :doc:`/scripts/base/protocols/syslog/main.bro`.
|
|
||||||
|
|
||||||
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.
|
|
||||||
Normally data saved to the connection record will remain there for the
|
|
||||||
duration of the connection and from a practical perspective it's not
|
|
||||||
uncommon to need to delete that data before the end of the connection.
|
|
||||||
|
|
||||||
Other Writers
|
Other Writers
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Bro supports the following built-in output formats other than ASCII:
|
Bro supports the following additional built-in output formats:
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
logging-input-sqlite
|
logging-input-sqlite
|
||||||
|
|
||||||
Further formats are available as external plugins.
|
Additional writers are available as external plugins:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
../components/bro-plugins/dataseries/README
|
||||||
|
../components/bro-plugins/elasticsearch/README
|
||||||
|
|
||||||
|
|
|
@ -88,15 +88,15 @@ directly make modifications to the :bro:see:`Notice::Info` record
|
||||||
given as the argument to the hook.
|
given as the argument to the hook.
|
||||||
|
|
||||||
Here's a simple example which tells Bro to send an email for all notices of
|
Here's a simple example which tells Bro to send an email for all notices of
|
||||||
type :bro:see:`SSH::Password_Guessing` if the server is 10.0.0.1:
|
type :bro:see:`SSH::Password_Guessing` if the guesser attempted to log in to
|
||||||
|
the server at 192.168.56.103:
|
||||||
|
|
||||||
.. code:: bro
|
.. btest-include:: ${DOC_ROOT}/frameworks/notice_ssh_guesser.bro
|
||||||
|
|
||||||
hook Notice::policy(n: Notice::Info)
|
.. btest:: notice_ssh_guesser.bro
|
||||||
{
|
|
||||||
if ( n$note == SSH::Password_Guessing && n$id$resp_h == 10.0.0.1 )
|
@TEST-EXEC: btest-rst-cmd bro -C -r ${TRACES}/ssh/sshguess.pcap ${DOC_ROOT}/frameworks/notice_ssh_guesser.bro
|
||||||
add n$actions[Notice::ACTION_EMAIL];
|
@TEST-EXEC: btest-rst-cmd cat notice.log
|
||||||
}
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -112,8 +112,7 @@ a hook body to run before default hook bodies might look like this:
|
||||||
|
|
||||||
hook Notice::policy(n: Notice::Info) &priority=5
|
hook Notice::policy(n: Notice::Info) &priority=5
|
||||||
{
|
{
|
||||||
if ( n$note == SSH::Password_Guessing && n$id$resp_h == 10.0.0.1 )
|
# Insert your code here.
|
||||||
add n$actions[Notice::ACTION_EMAIL];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Hooks can also abort later hook bodies with the ``break`` keyword. This
|
Hooks can also abort later hook bodies with the ``break`` keyword. This
|
||||||
|
@ -271,7 +270,7 @@ script that is generating the notice has indicated to the notice framework how
|
||||||
to identify notices that are intrinsically the same. Identification of these
|
to identify notices that are intrinsically the same. Identification of these
|
||||||
"intrinsically duplicate" notices is implemented with an optional field in
|
"intrinsically duplicate" notices is implemented with an optional field in
|
||||||
:bro:see:`Notice::Info` records named ``$identifier`` which is a simple string.
|
:bro:see:`Notice::Info` records named ``$identifier`` which is a simple string.
|
||||||
If the ``$identifier`` and ``$type`` fields are the same for two notices, the
|
If the ``$identifier`` and ``$note`` fields are the same for two notices, the
|
||||||
notice framework actually considers them to be the same thing and can use that
|
notice framework actually considers them to be the same thing and can use that
|
||||||
information to suppress duplicates for a configurable period of time.
|
information to suppress duplicates for a configurable period of time.
|
||||||
|
|
||||||
|
|
10
doc/frameworks/notice_ssh_guesser.bro
Normal file
10
doc/frameworks/notice_ssh_guesser.bro
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
@load protocols/ssh/detect-bruteforcing
|
||||||
|
|
||||||
|
redef SSH::password_guesses_limit=10;
|
||||||
|
|
||||||
|
hook Notice::policy(n: Notice::Info)
|
||||||
|
{
|
||||||
|
if ( n$note == SSH::Password_Guessing && /192\.168\.56\.103/ in n$sub )
|
||||||
|
add n$actions[Notice::ACTION_EMAIL];
|
||||||
|
}
|
|
@ -7,18 +7,18 @@ global mime_to_ext: table[string] of string = {
|
||||||
["text/html"] = "html",
|
["text/html"] = "html",
|
||||||
};
|
};
|
||||||
|
|
||||||
event file_new(f: fa_file)
|
event file_sniff(f: fa_file, meta: fa_metadata)
|
||||||
{
|
{
|
||||||
if ( f$source != "HTTP" )
|
if ( f$source != "HTTP" )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( ! f?$mime_type )
|
if ( ! meta?$mime_type )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( f$mime_type !in mime_to_ext )
|
if ( meta$mime_type !in mime_to_ext )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
local fname = fmt("%s-%s.%s", f$source, f$id, mime_to_ext[f$mime_type]);
|
local fname = fmt("%s-%s.%s", f$source, f$id, mime_to_ext[meta$mime_type]);
|
||||||
print fmt("Extracting file %s", fname);
|
print fmt("Extracting file %s", fname);
|
||||||
Files::add_analyzer(f, Files::ANALYZER_EXTRACT, [$extract_filename=fname]);
|
Files::add_analyzer(f, Files::ANALYZER_EXTRACT, [$extract_filename=fname]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,13 @@ Reference Section
|
||||||
script-reference/index.rst
|
script-reference/index.rst
|
||||||
components/index.rst
|
components/index.rst
|
||||||
|
|
||||||
..
|
Development
|
||||||
|
===========
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
devel/plugins.rst
|
||||||
|
|
||||||
* :ref:`General Index <genindex>`
|
* :ref:`General Index <genindex>`
|
||||||
* :ref:`search`
|
* :ref:`search`
|
||||||
|
|
|
@ -8,10 +8,12 @@ How to Upgrade
|
||||||
If you're doing an upgrade install (rather than a fresh install),
|
If you're doing an upgrade install (rather than a fresh install),
|
||||||
there's two suggested approaches: either install Bro using the same
|
there's two suggested approaches: either install Bro using the same
|
||||||
installation prefix directory as before, or pick a new prefix and copy
|
installation prefix directory as before, or pick a new prefix and copy
|
||||||
local customizations over. Regardless of which approach you choose,
|
local customizations over.
|
||||||
if you are using BroControl, then after upgrading Bro you will need to
|
|
||||||
run "broctl check" (to verify that your new configuration is OK)
|
Regardless of which approach you choose, if you are using BroControl, then
|
||||||
and "broctl install" to complete the upgrade process.
|
before doing the upgrade you should stop all running Bro processes with the
|
||||||
|
"broctl stop" command. After the upgrade is complete then you will need
|
||||||
|
to run "broctl deploy".
|
||||||
|
|
||||||
In the following we summarize general guidelines for upgrading, see
|
In the following we summarize general guidelines for upgrading, see
|
||||||
the :ref:`release-notes` for version-specific information.
|
the :ref:`release-notes` for version-specific information.
|
||||||
|
@ -44,4 +46,4 @@ where Bro was originally installed). Review the files for differences
|
||||||
before copying and make adjustments as necessary (use the new version for
|
before copying and make adjustments as necessary (use the new version for
|
||||||
differences that aren't a result of a local change). Of particular note,
|
differences that aren't a result of a local change). Of particular note,
|
||||||
the copied version of ``$prefix/etc/broctl.cfg`` is likely to need changes
|
the copied version of ``$prefix/etc/broctl.cfg`` is likely to need changes
|
||||||
to the ``SpoolDir`` and ``LogDir`` settings.
|
to any settings that specify a pathname.
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
.. _MacPorts: http://www.macports.org
|
.. _MacPorts: http://www.macports.org
|
||||||
.. _Fink: http://www.finkproject.org
|
.. _Fink: http://www.finkproject.org
|
||||||
.. _Homebrew: http://brew.sh
|
.. _Homebrew: http://brew.sh
|
||||||
.. _bro downloads page: http://bro.org/download/index.html
|
.. _bro downloads page: https://www.bro.org/download/index.html
|
||||||
|
|
||||||
.. _installing-bro:
|
.. _installing-bro:
|
||||||
|
|
||||||
|
@ -32,22 +32,24 @@ before you begin:
|
||||||
* Libz
|
* Libz
|
||||||
* Bash (for BroControl)
|
* Bash (for BroControl)
|
||||||
* Python (for BroControl)
|
* Python (for BroControl)
|
||||||
|
* C++ Actor Framework (CAF) version 0.14 (http://actor-framework.org)
|
||||||
|
|
||||||
To build Bro from source, the following additional dependencies are required:
|
To build Bro from source, the following additional dependencies are required:
|
||||||
|
|
||||||
* CMake 2.6.3 or greater (http://www.cmake.org)
|
* CMake 2.8 or greater (http://www.cmake.org)
|
||||||
* Make
|
* Make
|
||||||
* C/C++ compiler
|
* C/C++ compiler with C++11 support (GCC 4.8+ or Clang 3.3+)
|
||||||
* SWIG (http://www.swig.org)
|
* SWIG (http://www.swig.org)
|
||||||
* Bison (GNU Parser Generator)
|
* Bison (GNU Parser Generator)
|
||||||
* Flex (Fast Lexical Analyzer)
|
* Flex (Fast Lexical Analyzer)
|
||||||
* Libpcap headers (http://www.tcpdump.org)
|
* Libpcap headers (http://www.tcpdump.org)
|
||||||
* OpenSSL headers (http://www.openssl.org)
|
* OpenSSL headers (http://www.openssl.org)
|
||||||
* zlib headers
|
* zlib headers
|
||||||
* Perl
|
* Python
|
||||||
|
|
||||||
To install the required dependencies, you can use (when done, make sure
|
To install CAF, first download the source code of the required version from: https://github.com/actor-framework/actor-framework/releases
|
||||||
that ``bash`` and ``python`` are in your ``PATH``):
|
|
||||||
|
To install the required dependencies, you can use:
|
||||||
|
|
||||||
* RPM/RedHat-based Linux:
|
* RPM/RedHat-based Linux:
|
||||||
|
|
||||||
|
@ -68,19 +70,26 @@ that ``bash`` and ``python`` are in your ``PATH``):
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo pkg_add -r bash cmake swig bison python perl
|
sudo pkg install bash cmake swig bison python py27-sqlite3
|
||||||
|
|
||||||
|
Note that in older versions of FreeBSD, you might have to use the
|
||||||
|
"pkg_add -r" command instead of "pkg install".
|
||||||
|
|
||||||
* Mac OS X:
|
* Mac OS X:
|
||||||
|
|
||||||
Compiling source code on Macs requires first downloading Xcode_,
|
Compiling source code on Macs requires first installing Xcode_ (in older
|
||||||
then going through its "Preferences..." -> "Downloads" menus to
|
versions of Xcode, you would then need to go through its
|
||||||
install the "Command Line Tools" component.
|
"Preferences..." -> "Downloads" menus to install the "Command Line Tools"
|
||||||
|
component).
|
||||||
|
|
||||||
OS X comes with all required dependencies except for CMake_ and SWIG_.
|
OS X comes with all required dependencies except for CMake_, SWIG_,
|
||||||
Distributions of these dependencies can likely be obtained from your
|
OpenSSL, and CAF. (OpenSSL used to be part of OS X versions 10.10
|
||||||
preferred Mac OS X package management system (e.g. MacPorts_, Fink_,
|
and older, for which it does not need to be installed manually. It
|
||||||
or Homebrew_). Specifically for MacPorts, the ``cmake``, ``swig``,
|
was removed in OS X 10.11). Distributions of these dependencies can
|
||||||
and ``swig-python`` packages provide the required dependencies.
|
likely be obtained from your preferred Mac OS X package management
|
||||||
|
system (e.g. Homebrew_, MacPorts_, or Fink_). Specifically for
|
||||||
|
Homebrew, the ``cmake``, ``swig``, ``openssl`` and ``caf`` packages
|
||||||
|
provide the required dependencies.
|
||||||
|
|
||||||
|
|
||||||
Optional Dependencies
|
Optional Dependencies
|
||||||
|
@ -93,8 +102,9 @@ build time:
|
||||||
* sendmail (enables Bro and BroControl to send mail)
|
* sendmail (enables Bro and BroControl to send mail)
|
||||||
* curl (used by a Bro script that implements active HTTP)
|
* curl (used by a Bro script that implements active HTTP)
|
||||||
* gperftools (tcmalloc is used to improve memory and CPU usage)
|
* gperftools (tcmalloc is used to improve memory and CPU usage)
|
||||||
|
* jemalloc (http://www.canonware.com/jemalloc/)
|
||||||
|
* PF_RING (Linux only, see :doc:`Cluster Configuration <../configuration/index>`)
|
||||||
* ipsumdump (for trace-summary; http://www.cs.ucla.edu/~kohler/ipsumdump)
|
* ipsumdump (for trace-summary; http://www.cs.ucla.edu/~kohler/ipsumdump)
|
||||||
* Ruby executable, library, and headers (for Broccoli Ruby bindings)
|
|
||||||
|
|
||||||
LibGeoIP is probably the most interesting and can be installed
|
LibGeoIP is probably the most interesting and can be installed
|
||||||
on most platforms by following the instructions for :ref:`installing
|
on most platforms by following the instructions for :ref:`installing
|
||||||
|
@ -110,40 +120,30 @@ code forms.
|
||||||
|
|
||||||
|
|
||||||
Using Pre-Built Binary Release Packages
|
Using Pre-Built Binary Release Packages
|
||||||
=======================================
|
---------------------------------------
|
||||||
|
|
||||||
See the `bro downloads page`_ for currently supported/targeted
|
See the `bro downloads page`_ for currently supported/targeted
|
||||||
platforms for binary releases.
|
platforms for binary releases and for installation instructions.
|
||||||
|
|
||||||
* RPM
|
* Linux Packages
|
||||||
|
|
||||||
.. console::
|
Linux based binary installations are usually performed by adding
|
||||||
|
information about the Bro packages to the respective system packaging
|
||||||
sudo yum localinstall Bro-*.rpm
|
tool. Then the usual system utilities such as ``apt``, ``dnf``, ``yum``,
|
||||||
|
or ``zypper`` are used to perform the installation.
|
||||||
* DEB
|
|
||||||
|
|
||||||
.. console::
|
|
||||||
|
|
||||||
sudo gdebi Bro-*.deb
|
|
||||||
|
|
||||||
* MacOS Disk Image with Installer
|
|
||||||
|
|
||||||
Just open the ``Bro-*.dmg`` and then run the ``.pkg`` installer.
|
|
||||||
Everything installed by the package will go into ``/opt/bro``.
|
|
||||||
|
|
||||||
The primary install prefix for binary packages is ``/opt/bro``.
|
The primary install prefix for binary packages is ``/opt/bro``.
|
||||||
Non-MacOS packages that include BroControl also put variable/runtime
|
|
||||||
data (e.g. Bro logs) in ``/var/opt/bro``.
|
|
||||||
|
|
||||||
Installing from Source
|
Installing from Source
|
||||||
==========================
|
----------------------
|
||||||
|
|
||||||
Bro releases are bundled into source packages for convenience and are
|
Bro releases are bundled into source packages for convenience and are
|
||||||
available on the `bro downloads page`_. Alternatively, the latest
|
available on the `bro downloads page`_.
|
||||||
Bro development version can be obtained through git repositories
|
|
||||||
|
Alternatively, the latest Bro development version
|
||||||
|
can be obtained through git repositories
|
||||||
hosted at ``git.bro.org``. See our `git development documentation
|
hosted at ``git.bro.org``. See our `git development documentation
|
||||||
<http://bro.org/development/howtos/process.html>`_ for comprehensive
|
<https://www.bro.org/development/howtos/process.html>`_ for comprehensive
|
||||||
information on Bro's use of git revision control, but the short story
|
information on Bro's use of git revision control, but the short story
|
||||||
for downloading the full source code experience for Bro via git is:
|
for downloading the full source code experience for Bro via git is:
|
||||||
|
|
||||||
|
@ -164,13 +164,23 @@ run ``./configure --help``):
|
||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
|
|
||||||
|
If the ``configure`` script fails, then it is most likely because it either
|
||||||
|
couldn't find a required dependency or it couldn't find a sufficiently new
|
||||||
|
version of a dependency. Assuming that you already installed all required
|
||||||
|
dependencies, then you may need to use one of the ``--with-*`` options
|
||||||
|
that can be given to the ``configure`` script to help it locate a dependency.
|
||||||
|
|
||||||
The default installation path is ``/usr/local/bro``, which would typically
|
The default installation path is ``/usr/local/bro``, which would typically
|
||||||
require root privileges when doing the ``make install``. A different
|
require root privileges when doing the ``make install``. A different
|
||||||
installation path can be chosen by specifying the ``--prefix`` option.
|
installation path can be chosen by specifying the ``configure`` script
|
||||||
Note that ``/usr`` and ``/opt/bro`` are the
|
``--prefix`` option. Note that ``/usr`` and ``/opt/bro`` are the
|
||||||
standard prefixes for binary Bro packages to be installed, so those are
|
standard prefixes for binary Bro packages to be installed, so those are
|
||||||
typically not good choices unless you are creating such a package.
|
typically not good choices unless you are creating such a package.
|
||||||
|
|
||||||
|
OpenBSD users, please see our `FAQ
|
||||||
|
<https://www.bro.org/documentation/faq.html>`_ if you are having
|
||||||
|
problems installing Bro.
|
||||||
|
|
||||||
Depending on the Bro package you downloaded, there may be auxiliary
|
Depending on the Bro package you downloaded, there may be auxiliary
|
||||||
tools and libraries available in the ``aux/`` directory. Some of them
|
tools and libraries available in the ``aux/`` directory. Some of them
|
||||||
will be automatically built and installed along with Bro. There are
|
will be automatically built and installed along with Bro. There are
|
||||||
|
@ -179,10 +189,6 @@ turn off unwanted auxiliary projects that would otherwise be installed
|
||||||
automatically. Finally, use ``make install-aux`` to install some of
|
automatically. Finally, use ``make install-aux`` to install some of
|
||||||
the other programs that are in the ``aux/bro-aux`` directory.
|
the other programs that are in the ``aux/bro-aux`` directory.
|
||||||
|
|
||||||
OpenBSD users, please see our `FAQ
|
|
||||||
<//www.bro.org/documentation/faq.html>`_ if you are having
|
|
||||||
problems installing Bro.
|
|
||||||
|
|
||||||
Finally, if you want to build the Bro documentation (not required, because
|
Finally, if you want to build the Bro documentation (not required, because
|
||||||
all of the documentation for the latest Bro release is available on the
|
all of the documentation for the latest Bro release is available on the
|
||||||
Bro web site), there are instructions in ``doc/README`` in the source
|
Bro web site), there are instructions in ``doc/README`` in the source
|
||||||
|
@ -191,7 +197,7 @@ distribution.
|
||||||
Configure the Run-Time Environment
|
Configure the Run-Time Environment
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
Just remember that you may need to adjust your ``PATH`` environment variable
|
You may want to adjust your ``PATH`` environment variable
|
||||||
according to the platform/shell/package you're using. For example:
|
according to the platform/shell/package you're using. For example:
|
||||||
|
|
||||||
Bourne-Shell Syntax:
|
Bourne-Shell Syntax:
|
||||||
|
|
|
@ -112,6 +112,8 @@ default, including:
|
||||||
|
|
||||||
As you can see, some log files are specific to a particular protocol,
|
As you can see, some log files are specific to a particular protocol,
|
||||||
while others aggregate information across different types of activity.
|
while others aggregate information across different types of activity.
|
||||||
|
For a complete list of log files and a description of its purpose,
|
||||||
|
see :doc:`Log Files <../script-reference/log-files>`.
|
||||||
|
|
||||||
.. _bro-cut:
|
.. _bro-cut:
|
||||||
|
|
||||||
|
@ -250,44 +252,3 @@ protocol, it can have multiple ``GET``/``POST``/etc requests in a
|
||||||
stream and Bro is able to extract and track that information for you,
|
stream and Bro is able to extract and track that information for you,
|
||||||
giving you an in-depth and structured view into HTTP traffic on your
|
giving you an in-depth and structured view into HTTP traffic on your
|
||||||
network.
|
network.
|
||||||
|
|
||||||
-----------------------
|
|
||||||
Common Log Files
|
|
||||||
-----------------------
|
|
||||||
As a monitoring tool, Bro records a detailed view of the traffic inspected
|
|
||||||
and the events generated in a series of relevant log files. These files can
|
|
||||||
later be reviewed for monitoring, auditing and troubleshooting purposes.
|
|
||||||
|
|
||||||
In this section we present a brief explanation of the most commonly used log
|
|
||||||
files generated by Bro including links to descriptions of some of the fields
|
|
||||||
for each log type.
|
|
||||||
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
| Log File | Description | Field Descriptions |
|
|
||||||
+=================+=======================================+==============================+
|
|
||||||
| http.log | Shows all HTTP requests and replies | :bro:type:`HTTP::Info` |
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
| ftp.log | Records FTP activity | :bro:type:`FTP::Info` |
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
| ssl.log | Records SSL sessions including | :bro:type:`SSL::Info` |
|
|
||||||
| | certificates used | |
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
| known_certs.log | Includes SSL certificates used | :bro:type:`Known::CertsInfo` |
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
| smtp.log | Summarizes SMTP traffic on a network | :bro:type:`SMTP::Info` |
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
| dns.log | Shows all DNS activity on a network | :bro:type:`DNS::Info` |
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
| conn.log | Records all connections seen by Bro | :bro:type:`Conn::Info` |
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
| dpd.log | Shows network activity on | :bro:type:`DPD::Info` |
|
|
||||||
| | non-standard ports | |
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
| files.log | Records information about all files | :bro:type:`Files::Info` |
|
|
||||||
| | transmitted over the network | |
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
| weird.log | Records unexpected protocol-level | :bro:type:`Weird::Info` |
|
|
||||||
| | activity | |
|
|
||||||
+-----------------+---------------------------------------+------------------------------+
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ export {
|
||||||
|
|
||||||
event bro_init() &priority=3
|
event bro_init() &priority=3
|
||||||
{
|
{
|
||||||
Log::create_stream(MimeMetrics::LOG, [$columns=Info]);
|
Log::create_stream(MimeMetrics::LOG, [$columns=Info, $path="mime_metrics"]);
|
||||||
local r1: SumStats::Reducer = [$stream="mime.bytes",
|
local r1: SumStats::Reducer = [$stream="mime.bytes",
|
||||||
$apply=set(SumStats::SUM)];
|
$apply=set(SumStats::SUM)];
|
||||||
local r2: SumStats::Reducer = [$stream="mime.hits",
|
local r2: SumStats::Reducer = [$stream="mime.hits",
|
||||||
|
|
24
doc/quickstart/conditional-notice.bro
Normal file
24
doc/quickstart/conditional-notice.bro
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
@load protocols/ssl/expiring-certs
|
||||||
|
|
||||||
|
const watched_servers: set[addr] = {
|
||||||
|
87.98.220.10,
|
||||||
|
} &redef;
|
||||||
|
|
||||||
|
# Site::local_nets usually isn't something you need to modify if
|
||||||
|
# BroControl automatically sets it up from networks.cfg. It's
|
||||||
|
# shown here for completeness.
|
||||||
|
redef Site::local_nets += {
|
||||||
|
87.98.0.0/16,
|
||||||
|
};
|
||||||
|
|
||||||
|
hook Notice::policy(n: Notice::Info)
|
||||||
|
{
|
||||||
|
if ( n$note != SSL::Certificate_Expired )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( n$id$resp_h !in watched_servers )
|
||||||
|
return;
|
||||||
|
|
||||||
|
add n$actions[Notice::ACTION_EMAIL];
|
||||||
|
}
|
||||||
|
|
|
@ -24,9 +24,10 @@ Managing Bro with BroControl
|
||||||
BroControl is an interactive shell for easily operating/managing Bro
|
BroControl is an interactive shell for easily operating/managing Bro
|
||||||
installations on a single system or even across multiple systems in a
|
installations on a single system or even across multiple systems in a
|
||||||
traffic-monitoring cluster. This section explains how to use BroControl
|
traffic-monitoring cluster. This section explains how to use BroControl
|
||||||
to manage a stand-alone Bro installation. For instructions on how to
|
to manage a stand-alone Bro installation. For a complete reference on
|
||||||
configure a Bro cluster, see the :doc:`Cluster Configuration
|
BroControl, see the :doc:`BroControl <../components/broctl/README>`
|
||||||
<../configuration/index>` documentation.
|
documentation. For instructions on how to configure a Bro cluster,
|
||||||
|
see the :doc:`Cluster Configuration <../configuration/index>` documentation.
|
||||||
|
|
||||||
A Minimal Starting Configuration
|
A Minimal Starting Configuration
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
@ -156,9 +157,11 @@ changes we want to make:
|
||||||
notice that means an SSL connection was established and the server's
|
notice that means an SSL connection was established and the server's
|
||||||
certificate couldn't be validated using Bro's default trust roots, but
|
certificate couldn't be validated using Bro's default trust roots, but
|
||||||
we want to ignore it.
|
we want to ignore it.
|
||||||
2) ``SSH::Login`` is a notice type that is triggered when an SSH connection
|
2) ``SSL::Certificate_Expired`` is a notice type that is triggered when
|
||||||
attempt looks like it may have been successful, and we want email when
|
an SSL connection was established using an expired certificate. We
|
||||||
that happens, but only for certain servers.
|
want email when that happens, but only for certain servers on the
|
||||||
|
local network (Bro can also proactively monitor for certs that will
|
||||||
|
soon expire, but this is just for demonstration purposes).
|
||||||
|
|
||||||
We've defined *what* we want to do, but need to know *where* to do it.
|
We've defined *what* we want to do, but need to know *where* to do it.
|
||||||
The answer is to use a script written in the Bro programming language, so
|
The answer is to use a script written in the Bro programming language, so
|
||||||
|
@ -203,7 +206,7 @@ the variable's value may not change at run-time, but whose initial value can be
|
||||||
modified via the ``redef`` operator at parse-time.
|
modified via the ``redef`` operator at parse-time.
|
||||||
|
|
||||||
Let's continue on our path to modify the behavior for the two SSL
|
Let's continue on our path to modify the behavior for the two SSL
|
||||||
and SSH notices. Looking at :doc:`/scripts/base/frameworks/notice/main.bro`,
|
notices. Looking at :doc:`/scripts/base/frameworks/notice/main.bro`,
|
||||||
we see that it advertises:
|
we see that it advertises:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
@ -216,7 +219,7 @@ we see that it advertises:
|
||||||
const ignored_types: set[Notice::Type] = {} &redef;
|
const ignored_types: set[Notice::Type] = {} &redef;
|
||||||
}
|
}
|
||||||
|
|
||||||
That's exactly what we want to do for the SSL notice. Add to ``local.bro``:
|
That's exactly what we want to do for the first notice. Add to ``local.bro``:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
|
@ -248,38 +251,30 @@ is valid before installing it and then restarting the Bro instance:
|
||||||
stopping bro ...
|
stopping bro ...
|
||||||
starting bro ...
|
starting bro ...
|
||||||
|
|
||||||
Now that the SSL notice is ignored, let's look at how to send an email on
|
Now that the SSL notice is ignored, let's look at how to send an email
|
||||||
the SSH notice. The notice framework has a similar option called
|
on the other notice. The notice framework has a similar option called
|
||||||
``emailed_types``, but using that would generate email for all SSH servers and
|
``emailed_types``, but using that would generate email for all SSL
|
||||||
we only want email for logins to certain ones. There is a ``policy`` hook
|
servers with expired certificates and we only want email for connections
|
||||||
that is actually what is used to implement the simple functionality of
|
to certain ones. There is a ``policy`` hook that is actually what is
|
||||||
``ignored_types`` and
|
used to implement the simple functionality of ``ignored_types`` and
|
||||||
``emailed_types``, but it's extensible such that the condition and action taken
|
``emailed_types``, but it's extensible such that the condition and
|
||||||
on notices can be user-defined.
|
action taken on notices can be user-defined.
|
||||||
|
|
||||||
In ``local.bro``, let's define a new ``policy`` hook handler body
|
In ``local.bro``, let's define a new ``policy`` hook handler body:
|
||||||
that takes the email action for SSH logins only for a defined set of servers:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. btest-include:: ${DOC_ROOT}/quickstart/conditional-notice.bro
|
||||||
|
|
||||||
const watched_servers: set[addr] = {
|
.. btest:: conditional-notice
|
||||||
192.168.1.100,
|
|
||||||
192.168.1.101,
|
|
||||||
192.168.1.102,
|
|
||||||
} &redef;
|
|
||||||
|
|
||||||
hook Notice::policy(n: Notice::Info)
|
@TEST-EXEC: btest-rst-cmd bro -r ${TRACES}/tls/tls-expired-cert.trace ${DOC_ROOT}/quickstart/conditional-notice.bro
|
||||||
{
|
@TEST-EXEC: btest-rst-cmd cat notice.log
|
||||||
if ( n$note == SSH::SUCCESSFUL_LOGIN && n$id$resp_h in watched_servers )
|
|
||||||
add n$actions[Notice::ACTION_EMAIL];
|
|
||||||
}
|
|
||||||
|
|
||||||
You'll just have to trust the syntax for now, but what we've done is
|
You'll just have to trust the syntax for now, but what we've done is
|
||||||
first declare our own variable to hold a set of watched addresses,
|
first declare our own variable to hold a set of watched addresses,
|
||||||
``watched_servers``; then added a hook handler body to the policy that will
|
``watched_servers``; then added a hook handler body to the policy that
|
||||||
generate an email whenever the notice type is an SSH login and the responding
|
will generate an email whenever the notice type is an SSL expired
|
||||||
host stored
|
certificate and the responding host stored inside the ``Info`` record's
|
||||||
inside the ``Info`` record's connection field is in the set of watched servers.
|
connection field is in the set of watched servers.
|
||||||
|
|
||||||
.. note:: Record field member access is done with the '$' character
|
.. note:: Record field member access is done with the '$' character
|
||||||
instead of a '.' as might be expected from other languages, in
|
instead of a '.' as might be expected from other languages, in
|
||||||
|
|
241
doc/script-reference/attributes.rst
Normal file
241
doc/script-reference/attributes.rst
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
Attributes
|
||||||
|
==========
|
||||||
|
|
||||||
|
The Bro scripting language supports the following attributes.
|
||||||
|
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| Name | Description |
|
||||||
|
+=============================+===============================================+
|
||||||
|
| :bro:attr:`&redef` |Redefine a global constant or extend a type. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&priority` |Specify priority for event handler or hook. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&log` |Mark a record field as to be written to a log. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&optional` |Allow a record field value to be missing. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&default` |Specify a default value. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&add_func` |Specify a function to call for each "redef +=".|
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&delete_func` |Same as "&add_func", except for "redef -=". |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&expire_func` |Specify a function to call when container |
|
||||||
|
| |element expires. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&read_expire` |Specify a read timeout interval. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&write_expire` |Specify a write timeout interval. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&create_expire` |Specify a creation timeout interval. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&synchronized` |Synchronize a variable across nodes. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&persistent` |Make a variable persistent (written to disk). |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&rotate_interval`|Rotate a file after specified interval. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&rotate_size` |Rotate a file after specified file size. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&encrypt` |Encrypt a file when writing to disk. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&raw_output` |Open file in raw mode (chars. are not escaped).|
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&mergeable` |Prefer set union for synchronized state. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&error_handler` |Used internally for reporter framework events. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&type_column` |Used by input framework for "port" type. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
| :bro:attr:`&deprecated` |Marks an identifier as deprecated. |
|
||||||
|
+-----------------------------+-----------------------------------------------+
|
||||||
|
|
||||||
|
Here is a more detailed explanation of each attribute:
|
||||||
|
|
||||||
|
.. bro:attr:: &redef
|
||||||
|
|
||||||
|
Allows use of a :bro:keyword:`redef` to redefine initial values of
|
||||||
|
global variables (i.e., variables declared either :bro:keyword:`global`
|
||||||
|
or :bro:keyword:`const`). Example::
|
||||||
|
|
||||||
|
const clever = T &redef;
|
||||||
|
global cache_size = 256 &redef;
|
||||||
|
|
||||||
|
Note that a variable declared "global" can also have its value changed
|
||||||
|
with assignment statements (doesn't matter if it has the "&redef"
|
||||||
|
attribute or not).
|
||||||
|
|
||||||
|
.. bro:attr:: &priority
|
||||||
|
|
||||||
|
Specifies the execution priority (as a signed integer) of a hook or
|
||||||
|
event handler. Higher values are executed before lower ones. The
|
||||||
|
default value is 0. Example::
|
||||||
|
|
||||||
|
event bro_init() &priority=10
|
||||||
|
{
|
||||||
|
print "high priority";
|
||||||
|
}
|
||||||
|
|
||||||
|
.. bro:attr:: &log
|
||||||
|
|
||||||
|
Writes a :bro:type:`record` field to the associated log stream.
|
||||||
|
|
||||||
|
.. bro:attr:: &optional
|
||||||
|
|
||||||
|
Allows a record field value to be missing (i.e., neither initialized nor
|
||||||
|
ever assigned a value).
|
||||||
|
|
||||||
|
In this example, the record could be instantiated with either
|
||||||
|
"myrec($a=127.0.0.1)" or "myrec($a=127.0.0.1, $b=80/tcp)"::
|
||||||
|
|
||||||
|
type myrec: record { a: addr; b: port &optional; };
|
||||||
|
|
||||||
|
The ``?$`` operator can be used to check if a record field has a value or
|
||||||
|
not (it returns a ``bool`` value of ``T`` if the field has a value,
|
||||||
|
and ``F`` if not).
|
||||||
|
|
||||||
|
.. bro:attr:: &default
|
||||||
|
|
||||||
|
Specifies a default value for a record field, container element, or a
|
||||||
|
function/hook/event parameter.
|
||||||
|
|
||||||
|
In this example, the record could be instantiated with either
|
||||||
|
"myrec($a=5, $c=3.14)" or "myrec($a=5, $b=53/udp, $c=3.14)"::
|
||||||
|
|
||||||
|
type myrec: record { a: count; b: port &default=80/tcp; c: double; };
|
||||||
|
|
||||||
|
In this example, the table will return the string ``"foo"`` for any
|
||||||
|
attempted access to a non-existing index::
|
||||||
|
|
||||||
|
global mytable: table[count] of string &default="foo";
|
||||||
|
|
||||||
|
When used with function/hook/event parameters, all of the parameters
|
||||||
|
with the "&default" attribute must come after all other parameters.
|
||||||
|
For example, the following function could be called either as "myfunc(5)"
|
||||||
|
or as "myfunc(5, 53/udp)"::
|
||||||
|
|
||||||
|
function myfunc(a: count, b: port &default=80/tcp)
|
||||||
|
{
|
||||||
|
print a, b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.. bro:attr:: &add_func
|
||||||
|
|
||||||
|
Can be applied to an identifier with &redef to specify a function to
|
||||||
|
be called any time a "redef <id> += ..." declaration is parsed. The
|
||||||
|
function takes two arguments of the same type as the identifier, the first
|
||||||
|
being the old value of the variable and the second being the new
|
||||||
|
value given after the "+=" operator in the "redef" declaration. The
|
||||||
|
return value of the function will be the actual new value of the
|
||||||
|
variable after the "redef" declaration is parsed.
|
||||||
|
|
||||||
|
.. bro:attr:: &delete_func
|
||||||
|
|
||||||
|
Same as :bro:attr:`&add_func`, except for :bro:keyword:`redef` declarations
|
||||||
|
that use the "-=" operator.
|
||||||
|
|
||||||
|
.. bro:attr:: &expire_func
|
||||||
|
|
||||||
|
Called right before a container element expires. The function's
|
||||||
|
first parameter is of the same type of the container and the second
|
||||||
|
parameter the same type of the container's index. The return
|
||||||
|
value is an :bro:type:`interval` indicating the amount of additional
|
||||||
|
time to wait before expiring the container element at the given
|
||||||
|
index (which will trigger another execution of this function).
|
||||||
|
|
||||||
|
.. 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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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:: &synchronized
|
||||||
|
|
||||||
|
Synchronizes variable accesses across nodes. The value of a
|
||||||
|
``&synchronized`` variable is automatically propagated to all peers
|
||||||
|
when it changes.
|
||||||
|
|
||||||
|
.. bro:attr:: &persistent
|
||||||
|
|
||||||
|
Makes a variable persistent, i.e., its value is written to disk (per
|
||||||
|
default at shutdown time).
|
||||||
|
|
||||||
|
.. bro:attr:: &rotate_interval
|
||||||
|
|
||||||
|
Rotates a file after a specified interval.
|
||||||
|
|
||||||
|
Note: This attribute is deprecated and will be removed in a future release.
|
||||||
|
|
||||||
|
.. bro:attr:: &rotate_size
|
||||||
|
|
||||||
|
Rotates a file after it has reached a given size in bytes.
|
||||||
|
|
||||||
|
Note: This attribute is deprecated and will be removed in a future release.
|
||||||
|
|
||||||
|
.. bro:attr:: &encrypt
|
||||||
|
|
||||||
|
Encrypts files right before writing them to disk.
|
||||||
|
|
||||||
|
Note: This attribute is deprecated and will be removed in a future release.
|
||||||
|
|
||||||
|
.. bro:attr:: &raw_output
|
||||||
|
|
||||||
|
Opens a file in raw mode, i.e., non-ASCII characters are not
|
||||||
|
escaped.
|
||||||
|
|
||||||
|
.. bro:attr:: &mergeable
|
||||||
|
|
||||||
|
Prefers merging sets on 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 values, 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:: &error_handler
|
||||||
|
|
||||||
|
Internally set on the events that are associated with the reporter
|
||||||
|
framework: :bro:id:`reporter_info`, :bro:id:`reporter_warning`, and
|
||||||
|
:bro:id:`reporter_error`. It prevents any handlers of those events
|
||||||
|
from being able to generate reporter messages that go through any of
|
||||||
|
those events (i.e., it prevents an infinite event recursion). Instead,
|
||||||
|
such nested reporter messages are output to stderr.
|
||||||
|
|
||||||
|
.. bro:attr:: &type_column
|
||||||
|
|
||||||
|
Used by the input framework. It can be used on columns of type
|
||||||
|
:bro:type:`port` (such a column only contains the port number) and
|
||||||
|
specifies the name of an additional column in
|
||||||
|
the input file which specifies the protocol of the port (tcp/udp/icmp).
|
||||||
|
|
||||||
|
In the following example, the input file would contain four columns
|
||||||
|
named "ip", "srcp", "proto", and "msg"::
|
||||||
|
|
||||||
|
type Idx: record {
|
||||||
|
ip: addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
type Val: record {
|
||||||
|
srcp: port &type_column = "proto";
|
||||||
|
msg: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
.. bro:attr:: &deprecated
|
||||||
|
|
||||||
|
The associated identifier is marked as deprecated and will be
|
||||||
|
removed in a future version of Bro. Look in the NEWS file for more
|
||||||
|
instructions to migrate code that uses deprecated functionality.
|
190
doc/script-reference/directives.rst
Normal file
190
doc/script-reference/directives.rst
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
Directives
|
||||||
|
==========
|
||||||
|
|
||||||
|
The Bro scripting language supports a number of directives that can
|
||||||
|
affect which scripts will be loaded or which lines in a script will be
|
||||||
|
executed. Directives are evaluated before script execution begins.
|
||||||
|
|
||||||
|
.. bro:keyword:: @DEBUG
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: @DIR
|
||||||
|
|
||||||
|
Expands to the directory pathname where the current script is located.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
print "Directory:", @DIR;
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: @FILENAME
|
||||||
|
|
||||||
|
Expands to the filename of the current script.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
print "File:", @FILENAME;
|
||||||
|
|
||||||
|
.. bro:keyword:: @load
|
||||||
|
|
||||||
|
Loads the specified Bro script, specified as the relative pathname
|
||||||
|
of the file (relative to one of the directories in Bro's file search path).
|
||||||
|
If the Bro script filename ends with ".bro", then you don't need to
|
||||||
|
specify the file extension. The filename cannot contain any whitespace.
|
||||||
|
|
||||||
|
In this example, Bro will try to load a script
|
||||||
|
"policy/misc/capture-loss.bro" by looking in each directory in the file
|
||||||
|
search path (the file search path can be changed by setting the BROPATH
|
||||||
|
environment variable)::
|
||||||
|
|
||||||
|
@load policy/misc/capture-loss
|
||||||
|
|
||||||
|
If you specify the name of a directory instead of a filename, then
|
||||||
|
Bro will try to load a file in that directory called "__load__.bro"
|
||||||
|
(presumably that file will contain additional "@load" directives).
|
||||||
|
|
||||||
|
In this example, Bro will try to load a file "tuning/defaults/__load__.bro"
|
||||||
|
by looking in each directory in the file search path::
|
||||||
|
|
||||||
|
@load tuning/defaults
|
||||||
|
|
||||||
|
The purpose of this directive is to ensure that all script dependencies
|
||||||
|
are satisfied, and to avoid having to list every needed Bro script
|
||||||
|
on the command-line. Bro keeps track of which scripts have been
|
||||||
|
loaded, so it is not an error to load a script more than once (once
|
||||||
|
a script has been loaded, any subsequent "@load" directives
|
||||||
|
for that script are ignored).
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: @load-plugin
|
||||||
|
|
||||||
|
Activate a dynamic plugin with the specified plugin name. The specified
|
||||||
|
plugin must be located in Bro's plugin search path. Example::
|
||||||
|
|
||||||
|
@load-plugin Demo::Rot13
|
||||||
|
|
||||||
|
By default, Bro will automatically activate all dynamic plugins found
|
||||||
|
in the plugin search path (the search path can be changed by setting
|
||||||
|
the environment variable BRO_PLUGIN_PATH to a colon-separated list of
|
||||||
|
directories). However, in bare mode ("bro -b"), dynamic plugins can be
|
||||||
|
activated only by using "@load-plugin", or by specifying the full
|
||||||
|
plugin name on the Bro command-line (e.g., "bro Demo::Rot13"), or by
|
||||||
|
setting the environment variable BRO_PLUGIN_ACTIVATE to a
|
||||||
|
comma-separated list of plugin names.
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: @load-sigs
|
||||||
|
|
||||||
|
This works similarly to "@load", except that in this case the filename
|
||||||
|
represents a signature file (not a Bro script). If the signature filename
|
||||||
|
ends with ".sig", then you don't need to specify the file extension
|
||||||
|
in the "@load-sigs" directive. The filename cannot contain any
|
||||||
|
whitespace.
|
||||||
|
|
||||||
|
In this example, Bro will try to load a signature file
|
||||||
|
"base/protocols/ssl/dpd.sig"::
|
||||||
|
|
||||||
|
@load-sigs base/protocols/ssl/dpd
|
||||||
|
|
||||||
|
The format for a signature file is explained in the documentation for the
|
||||||
|
`Signature Framework <../frameworks/signatures.html>`_.
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: @unload
|
||||||
|
|
||||||
|
This specifies a Bro script that we don't want to load (so a subsequent
|
||||||
|
attempt to load the specified script will be skipped). However,
|
||||||
|
if the specified script has already been loaded, then this directive
|
||||||
|
has no affect.
|
||||||
|
|
||||||
|
In the following example, if the "policy/misc/capture-loss.bro" script
|
||||||
|
has not been loaded yet, then Bro will not load it::
|
||||||
|
|
||||||
|
@unload policy/misc/capture-loss
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: @prefixes
|
||||||
|
|
||||||
|
Specifies a filename prefix to use when looking for script files
|
||||||
|
to load automatically. The prefix cannot contain any whitespace.
|
||||||
|
|
||||||
|
In the following example, the prefix "cluster" is used and all prefixes
|
||||||
|
that were previously specified are not used::
|
||||||
|
|
||||||
|
@prefixes = cluster
|
||||||
|
|
||||||
|
In the following example, the prefix "cluster-manager" is used in
|
||||||
|
addition to any previously-specified prefixes::
|
||||||
|
|
||||||
|
@prefixes += cluster-manager
|
||||||
|
|
||||||
|
The way this works is that after Bro parses all script files, then for each
|
||||||
|
loaded script Bro will take the absolute path of the script and then
|
||||||
|
it removes the portion of the directory path that is in Bro's file
|
||||||
|
search path. Then it replaces each "/" character with a period "."
|
||||||
|
and then prepends the prefix (specified in the "@prefixes" directive)
|
||||||
|
followed by a period. The resulting filename is searched for in each
|
||||||
|
directory in Bro's file search path. If a matching file is found, then
|
||||||
|
the file is automatically loaded.
|
||||||
|
|
||||||
|
For example, if a script called "local.bro" has been loaded, and a prefix
|
||||||
|
of "test" was specified, then Bro will look for a file named
|
||||||
|
"test.local.bro" in each directory of Bro's file search path.
|
||||||
|
|
||||||
|
An alternative way to specify prefixes is to use the "-p" Bro
|
||||||
|
command-line option.
|
||||||
|
|
||||||
|
.. bro:keyword:: @if
|
||||||
|
|
||||||
|
The specified expression must evaluate to type :bro:type:`bool`. If the
|
||||||
|
value is true, then the following script lines (up to the next "@else"
|
||||||
|
or "@endif") are available to be executed.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
@if ( ver == 2 )
|
||||||
|
print "version 2 detected";
|
||||||
|
@endif
|
||||||
|
|
||||||
|
.. bro:keyword:: @ifdef
|
||||||
|
|
||||||
|
This works like "@if", except that the result is true if the specified
|
||||||
|
identifier is defined.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
@ifdef ( pi )
|
||||||
|
print "pi is defined";
|
||||||
|
@endif
|
||||||
|
|
||||||
|
.. bro:keyword:: @ifndef
|
||||||
|
|
||||||
|
This works exactly like "@ifdef", except that the result is true if the
|
||||||
|
specified identifier is not defined.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
@ifndef ( pi )
|
||||||
|
print "pi is not defined";
|
||||||
|
@endif
|
||||||
|
|
||||||
|
.. bro:keyword:: @else
|
||||||
|
|
||||||
|
This directive is optional after an "@if", "@ifdef", or
|
||||||
|
"@ifndef". If present, it provides an else clause.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
@ifdef ( pi )
|
||||||
|
print "pi is defined";
|
||||||
|
@else
|
||||||
|
print "pi is not defined";
|
||||||
|
@endif
|
||||||
|
|
||||||
|
.. bro:keyword:: @endif
|
||||||
|
|
||||||
|
This directive is required to terminate each "@if", "@ifdef", or
|
||||||
|
"@ifndef".
|
||||||
|
|
|
@ -5,10 +5,17 @@ Script Reference
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
|
operators
|
||||||
|
types
|
||||||
|
attributes
|
||||||
|
statements
|
||||||
|
directives
|
||||||
|
log-files
|
||||||
notices
|
notices
|
||||||
proto-analyzers
|
proto-analyzers
|
||||||
file-analyzers
|
file-analyzers
|
||||||
builtins
|
|
||||||
packages
|
packages
|
||||||
scripts
|
scripts
|
||||||
Broxygen Example Script </scripts/broxygen/example.bro>
|
Broxygen Example Script </scripts/broxygen/example.bro>
|
||||||
|
|
||||||
|
|
||||||
|
|
158
doc/script-reference/log-files.rst
Normal file
158
doc/script-reference/log-files.rst
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
=========
|
||||||
|
Log Files
|
||||||
|
=========
|
||||||
|
|
||||||
|
Listed below are the log files generated by Bro, including a brief description
|
||||||
|
of the log file and links to descriptions of the fields for each log
|
||||||
|
type.
|
||||||
|
|
||||||
|
Network Protocols
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| Log File | Description | Field Descriptions |
|
||||||
|
+============================+=======================================+=================================+
|
||||||
|
| conn.log | TCP/UDP/ICMP connections | :bro:type:`Conn::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| dhcp.log | DHCP leases | :bro:type:`DHCP::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| dnp3.log | DNP3 requests and replies | :bro:type:`DNP3::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| dns.log | DNS activity | :bro:type:`DNS::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| ftp.log | FTP activity | :bro:type:`FTP::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| http.log | HTTP requests and replies | :bro:type:`HTTP::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| irc.log | IRC commands and responses | :bro:type:`IRC::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| kerberos.log | Kerberos | :bro:type:`KRB::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| modbus.log | Modbus commands and responses | :bro:type:`Modbus::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| modbus_register_change.log | Tracks changes to Modbus holding | :bro:type:`Modbus::MemmapInfo` |
|
||||||
|
| | registers | |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| mysql.log | MySQL | :bro:type:`MySQL::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| radius.log | RADIUS authentication attempts | :bro:type:`RADIUS::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| rdp.log | RDP | :bro:type:`RDP::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| sip.log | SIP | :bro:type:`SIP::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| smtp.log | SMTP transactions | :bro:type:`SMTP::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| snmp.log | SNMP messages | :bro:type:`SNMP::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| socks.log | SOCKS proxy requests | :bro:type:`SOCKS::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| ssh.log | SSH connections | :bro:type:`SSH::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| ssl.log | SSL/TLS handshake info | :bro:type:`SSL::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| syslog.log | Syslog messages | :bro:type:`Syslog::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| tunnel.log | Tunneling protocol events | :bro:type:`Tunnel::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
|
||||||
|
Files
|
||||||
|
-----
|
||||||
|
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| Log File | Description | Field Descriptions |
|
||||||
|
+============================+=======================================+=================================+
|
||||||
|
| files.log | File analysis results | :bro:type:`Files::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| pe.log | Portable Executable (PE) | :bro:type:`PE::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| x509.log | X.509 certificate info | :bro:type:`X509::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
|
||||||
|
Detection
|
||||||
|
---------
|
||||||
|
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| Log File | Description | Field Descriptions |
|
||||||
|
+============================+=======================================+=================================+
|
||||||
|
| intel.log | Intelligence data matches | :bro:type:`Intel::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| notice.log | Bro notices | :bro:type:`Notice::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| notice_alarm.log | The alarm stream | :bro:enum:`Notice::ACTION_ALARM`|
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| signatures.log | Signature matches | :bro:type:`Signatures::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| traceroute.log | Traceroute detection | :bro:type:`Traceroute::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
Network Observations
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| Log File | Description | Field Descriptions |
|
||||||
|
+============================+=======================================+=================================+
|
||||||
|
| app_stats.log | Web app usage statistics | :bro:type:`AppStats::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| known_certs.log | SSL certificates | :bro:type:`Known::CertsInfo` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| known_devices.log | MAC addresses of devices on the | :bro:type:`Known::DevicesInfo` |
|
||||||
|
| | network | |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| known_hosts.log | Hosts that have completed TCP | :bro:type:`Known::HostsInfo` |
|
||||||
|
| | handshakes | |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| known_modbus.log | Modbus masters and slaves | :bro:type:`Known::ModbusInfo` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| known_services.log | Services running on hosts | :bro:type:`Known::ServicesInfo` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| software.log | Software being used on the network | :bro:type:`Software::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
|
||||||
|
Miscellaneous
|
||||||
|
-------------
|
||||||
|
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| Log File | Description | Field Descriptions |
|
||||||
|
+============================+=======================================+=================================+
|
||||||
|
| barnyard2.log | Alerts received from Barnyard2 | :bro:type:`Barnyard2::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| dpd.log | Dynamic protocol detection failures | :bro:type:`DPD::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| unified2.log | Interprets Snort's unified output | :bro:type:`Unified2::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| weird.log | Unexpected network-level activity | :bro:type:`Weird::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
|
||||||
|
Bro Diagnostics
|
||||||
|
---------------
|
||||||
|
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| Log File | Description | Field Descriptions |
|
||||||
|
+============================+=======================================+=================================+
|
||||||
|
| capture_loss.log | Packet loss rate | :bro:type:`CaptureLoss::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| cluster.log | Bro cluster messages | :bro:type:`Cluster::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| communication.log | Communication events between Bro or | :bro:type:`Communication::Info` |
|
||||||
|
| | Broccoli instances | |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| loaded_scripts.log | Shows all scripts loaded by Bro | :bro:type:`LoadedScripts::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| packet_filter.log | List packet filters that were applied | :bro:type:`PacketFilter::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| prof.log | Profiling statistics (to create this | N/A |
|
||||||
|
| | log, load policy/misc/profiling.bro) | |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| reporter.log | Internal error/warning/info messages | :bro:type:`Reporter::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| stats.log | Memory/event/packet/lag statistics | :bro:type:`Stats::Info` |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| stderr.log | Captures standard error when Bro is | N/A |
|
||||||
|
| | started from BroControl | |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
| stdout.log | Captures standard output when Bro is | N/A |
|
||||||
|
| | started from BroControl | |
|
||||||
|
+----------------------------+---------------------------------------+---------------------------------+
|
||||||
|
|
191
doc/script-reference/operators.rst
Normal file
191
doc/script-reference/operators.rst
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
Operators
|
||||||
|
=========
|
||||||
|
|
||||||
|
The Bro scripting language supports the following operators. Note that
|
||||||
|
each data type only supports a subset of these operators. For more
|
||||||
|
details, see the documentation about the `data types <types.html>`_.
|
||||||
|
|
||||||
|
Relational operators
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The relational operators evaluate to type :bro:type:`bool`.
|
||||||
|
|
||||||
|
+------------------------------+--------------+
|
||||||
|
| Name | Syntax |
|
||||||
|
+==============================+==============+
|
||||||
|
| Equality | *a* == *b* |
|
||||||
|
+------------------------------+--------------+
|
||||||
|
| Inequality | *a* != *b* |
|
||||||
|
+------------------------------+--------------+
|
||||||
|
| Less than | *a* < *b* |
|
||||||
|
+------------------------------+--------------+
|
||||||
|
| Less than or equal | *a* <= *b* |
|
||||||
|
+------------------------------+--------------+
|
||||||
|
| Greater than | *a* > *b* |
|
||||||
|
+------------------------------+--------------+
|
||||||
|
| Greater than or equal | *a* >= *b* |
|
||||||
|
+------------------------------+--------------+
|
||||||
|
|
||||||
|
|
||||||
|
Logical operators
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The logical operators require operands of type :bro:type:`bool`, and
|
||||||
|
evaluate to type :bro:type:`bool`.
|
||||||
|
|
||||||
|
+------------------------------+--------------+
|
||||||
|
| Name | Syntax |
|
||||||
|
+==============================+==============+
|
||||||
|
| Logical AND | *a* && *b* |
|
||||||
|
+------------------------------+--------------+
|
||||||
|
| Logical OR | *a* \|\| *b* |
|
||||||
|
+------------------------------+--------------+
|
||||||
|
| Logical NOT | ! *a* |
|
||||||
|
+------------------------------+--------------+
|
||||||
|
|
||||||
|
|
||||||
|
Arithmetic operators
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Name | Syntax | Notes |
|
||||||
|
+==============================+=============+===============================+
|
||||||
|
| Addition | *a* + *b* | For :bro:type:`string` |
|
||||||
|
| | | operands, this performs |
|
||||||
|
| | | string concatenation. |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Subtraction | *a* - *b* | |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Multiplication | *a* \* *b* | |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Division | *a* / *b* | For :bro:type:`int` or |
|
||||||
|
| | | :bro:type:`count` operands, |
|
||||||
|
| | | the fractional part of the |
|
||||||
|
| | | result is dropped. |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Modulo | *a* % *b* | Operand types cannot be |
|
||||||
|
| | | "double". |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Unary plus | \+ *a* | |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Unary minus | \- *a* | |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Pre-increment | ++ *a* | Operand type cannot be |
|
||||||
|
| | | "double". |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Pre-decrement | ``--`` *a* | Operand type cannot be |
|
||||||
|
| | | "double". |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Absolute value | \| *a* \| | If operand is |
|
||||||
|
| | | :bro:type:`string`, |
|
||||||
|
| | | :bro:type:`set`, |
|
||||||
|
| | | :bro:type:`table`, or |
|
||||||
|
| | | :bro:type:`vector`, this |
|
||||||
|
| | | evaluates to number |
|
||||||
|
| | | of elements. |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
Assignment operators
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The assignment operators evaluate to the result of the assignment.
|
||||||
|
|
||||||
|
+------------------------------+-------------+
|
||||||
|
| Name | Syntax |
|
||||||
|
+==============================+=============+
|
||||||
|
| Assignment | *a* = *b* |
|
||||||
|
+------------------------------+-------------+
|
||||||
|
| Addition assignment | *a* += *b* |
|
||||||
|
+------------------------------+-------------+
|
||||||
|
| Subtraction assignment | *a* -= *b* |
|
||||||
|
+------------------------------+-------------+
|
||||||
|
|
||||||
|
|
||||||
|
Record field operators
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The record field operators take a :bro:type:`record` as the first operand,
|
||||||
|
and a field name as the second operand. For both operators, the specified
|
||||||
|
field name must be in the declaration of the record type.
|
||||||
|
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Name | Syntax | Notes |
|
||||||
|
+==============================+=============+===============================+
|
||||||
|
| Field access | *a* $ *b* | |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
| Field value existence test | *a* ?$ *b* | Evaluates to type |
|
||||||
|
| | | :bro:type:`bool`. |
|
||||||
|
| | | True if the specified field |
|
||||||
|
| | | has been assigned a value, or |
|
||||||
|
| | | false if not. |
|
||||||
|
+------------------------------+-------------+-------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
Other operators
|
||||||
|
---------------
|
||||||
|
|
||||||
|
+--------------------------------+-------------------+------------------------+
|
||||||
|
| Name | Syntax | Notes |
|
||||||
|
+================================+===================+========================+
|
||||||
|
| Membership test | *a* in *b* |Evaluates to type |
|
||||||
|
| | |:bro:type:`bool`. Do not|
|
||||||
|
| | |confuse this use of "in"|
|
||||||
|
| | |with that used in a |
|
||||||
|
| | |:bro:keyword:`for` |
|
||||||
|
| | |statement. |
|
||||||
|
+--------------------------------+-------------------+------------------------+
|
||||||
|
| Non-membership test | *a* !in *b* |This is the logical NOT |
|
||||||
|
| | |of the "in" operator. |
|
||||||
|
| | |For example: "a !in b" |
|
||||||
|
| | |is equivalent to |
|
||||||
|
| | |"!(a in b)". |
|
||||||
|
+--------------------------------+-------------------+------------------------+
|
||||||
|
| Table or vector element access | *a* [ *b* ] |This operator can also |
|
||||||
|
| | |be used with a |
|
||||||
|
| | |:bro:type:`set`, but |
|
||||||
|
| | |only with the |
|
||||||
|
| | |:bro:keyword:`add` or |
|
||||||
|
| | |:bro:keyword:`delete` |
|
||||||
|
| | |statement. |
|
||||||
|
+--------------------------------+-------------------+------------------------+
|
||||||
|
| Substring extraction | *a* [ *b* : *c* ] |See the |
|
||||||
|
| | |:bro:type:`string` type |
|
||||||
|
| | |for more details. |
|
||||||
|
+--------------------------------+-------------------+------------------------+
|
||||||
|
| Create a deep copy | copy ( *a* ) |This is relevant only |
|
||||||
|
| | |for data types that are |
|
||||||
|
| | |assigned by reference, |
|
||||||
|
| | |such as |
|
||||||
|
| | |:bro:type:`vector`, |
|
||||||
|
| | |:bro:type:`set`, |
|
||||||
|
| | |:bro:type:`table`, |
|
||||||
|
| | |and :bro:type:`record`. |
|
||||||
|
+--------------------------------+-------------------+------------------------+
|
||||||
|
| Module namespace access | *a* \:\: *b* |The first operand is the|
|
||||||
|
| | |module name, and the |
|
||||||
|
| | |second operand is an |
|
||||||
|
| | |identifier that refers |
|
||||||
|
| | |to a global variable, |
|
||||||
|
| | |enumeration constant, or|
|
||||||
|
| | |user-defined type that |
|
||||||
|
| | |was exported from the |
|
||||||
|
| | |module. |
|
||||||
|
+--------------------------------+-------------------+------------------------+
|
||||||
|
| Conditional | *a* ? *b* : *c* |The first operand must |
|
||||||
|
| | |evaluate to type |
|
||||||
|
| | |:bro:type:`bool`. |
|
||||||
|
| | |If true, then the |
|
||||||
|
| | |second expression is |
|
||||||
|
| | |evaluated and is the |
|
||||||
|
| | |result of the entire |
|
||||||
|
| | |expression. Otherwise, |
|
||||||
|
| | |the third expression is |
|
||||||
|
| | |evaluated and is the |
|
||||||
|
| | |result of the entire |
|
||||||
|
| | |expression. The types of|
|
||||||
|
| | |the second and third |
|
||||||
|
| | |operands must be |
|
||||||
|
| | |compatible. |
|
||||||
|
+--------------------------------+-------------------+------------------------+
|
||||||
|
|
650
doc/script-reference/statements.rst
Normal file
650
doc/script-reference/statements.rst
Normal file
|
@ -0,0 +1,650 @@
|
||||||
|
Declarations and Statements
|
||||||
|
===========================
|
||||||
|
|
||||||
|
The Bro scripting language supports the following declarations and
|
||||||
|
statements.
|
||||||
|
|
||||||
|
|
||||||
|
Declarations
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
+----------------------------+-----------------------------+
|
||||||
|
| Name | Description |
|
||||||
|
+============================+=============================+
|
||||||
|
| :bro:keyword:`module` | Change the current module |
|
||||||
|
+----------------------------+-----------------------------+
|
||||||
|
| :bro:keyword:`export` | Export identifiers from the |
|
||||||
|
| | current module |
|
||||||
|
+----------------------------+-----------------------------+
|
||||||
|
| :bro:keyword:`global` | Declare a global variable |
|
||||||
|
+----------------------------+-----------------------------+
|
||||||
|
| :bro:keyword:`const` | Declare a constant |
|
||||||
|
+----------------------------+-----------------------------+
|
||||||
|
| :bro:keyword:`type` | Declare a user-defined type |
|
||||||
|
+----------------------------+-----------------------------+
|
||||||
|
| :bro:keyword:`redef` | Redefine a global value or |
|
||||||
|
| | extend a user-defined type |
|
||||||
|
+----------------------------+-----------------------------+
|
||||||
|
| `function/event/hook`_ | Declare a function, event |
|
||||||
|
| | handler, or hook |
|
||||||
|
+----------------------------+-----------------------------+
|
||||||
|
|
||||||
|
Statements
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
+----------------------------+------------------------+
|
||||||
|
| Name | Description |
|
||||||
|
+============================+========================+
|
||||||
|
| :bro:keyword:`local` | Declare a local |
|
||||||
|
| | variable |
|
||||||
|
+----------------------------+------------------------+
|
||||||
|
| :bro:keyword:`add`, | Add or delete |
|
||||||
|
| :bro:keyword:`delete` | elements |
|
||||||
|
+----------------------------+------------------------+
|
||||||
|
| :bro:keyword:`print` | Print to stdout or a |
|
||||||
|
| | file |
|
||||||
|
+----------------------------+------------------------+
|
||||||
|
| :bro:keyword:`for`, | Loop over each |
|
||||||
|
| :bro:keyword:`while`, | element in a container |
|
||||||
|
| :bro:keyword:`next`, | object (``for``), or |
|
||||||
|
| :bro:keyword:`break` | as long as a condition |
|
||||||
|
| | evaluates to true |
|
||||||
|
| | (``while``). |
|
||||||
|
+----------------------------+------------------------+
|
||||||
|
| :bro:keyword:`if` | Evaluate boolean |
|
||||||
|
| | expression and if true,|
|
||||||
|
| | execute a statement |
|
||||||
|
+----------------------------+------------------------+
|
||||||
|
| :bro:keyword:`switch`, | Evaluate expression |
|
||||||
|
| :bro:keyword:`break`, | and execute statement |
|
||||||
|
| :bro:keyword:`fallthrough` | with a matching value |
|
||||||
|
+----------------------------+------------------------+
|
||||||
|
| :bro:keyword:`when` | Asynchronous execution |
|
||||||
|
+----------------------------+------------------------+
|
||||||
|
| :bro:keyword:`event`, | Invoke or schedule |
|
||||||
|
| :bro:keyword:`schedule` | an event handler |
|
||||||
|
+----------------------------+------------------------+
|
||||||
|
| :bro:keyword:`return` | Return from function, |
|
||||||
|
| | hook, or event handler |
|
||||||
|
+----------------------------+------------------------+
|
||||||
|
|
||||||
|
Declarations
|
||||||
|
------------
|
||||||
|
|
||||||
|
Declarations cannot occur within a function, hook, or event handler.
|
||||||
|
|
||||||
|
Declarations must appear before any statements (except those statements
|
||||||
|
that are in a function, hook, or event handler) in the concatenation of
|
||||||
|
all loaded Bro scripts.
|
||||||
|
|
||||||
|
.. bro:keyword:: module
|
||||||
|
|
||||||
|
The "module" keyword is used to change the current module. This
|
||||||
|
affects the scope of any subsequently declared global identifiers.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
module mymodule;
|
||||||
|
|
||||||
|
If a global identifier is declared after a "module" declaration,
|
||||||
|
then its scope ends at the end of the current Bro script or at the
|
||||||
|
next "module" declaration, whichever comes first. However, if a
|
||||||
|
global identifier is declared after a "module" declaration, but inside
|
||||||
|
an :bro:keyword:`export` block, then its scope ends at the end of the
|
||||||
|
last loaded Bro script, but it must be referenced using the namespace
|
||||||
|
operator (``::``) in other modules.
|
||||||
|
|
||||||
|
There can be any number of "module" declarations in a Bro script.
|
||||||
|
The same "module" declaration can appear in any number of different
|
||||||
|
Bro scripts.
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: export
|
||||||
|
|
||||||
|
An "export" block contains one or more declarations
|
||||||
|
(no statements are allowed in an "export" block) that the current
|
||||||
|
module is exporting. This enables these global identifiers to be visible
|
||||||
|
in other modules (but not prior to their declaration) via the namespace
|
||||||
|
operator (``::``). See the :bro:keyword:`module` keyword for a more
|
||||||
|
detailed explanation.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
export {
|
||||||
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
|
type Info: record {
|
||||||
|
ts: time &log;
|
||||||
|
uid: string &log;
|
||||||
|
};
|
||||||
|
|
||||||
|
const conntime = 30sec &redef;
|
||||||
|
}
|
||||||
|
|
||||||
|
Note that the braces in an "export" block are always required
|
||||||
|
(they do not indicate a compound statement). Also, no semicolon is
|
||||||
|
needed to terminate an "export" block.
|
||||||
|
|
||||||
|
.. bro:keyword:: global
|
||||||
|
|
||||||
|
Variables declared with the "global" keyword will be global.
|
||||||
|
|
||||||
|
If a type is not specified, then an initializer is required so that
|
||||||
|
the type can be inferred. Likewise, if an initializer is not supplied,
|
||||||
|
then the type must be specified. In some cases, when the type cannot
|
||||||
|
be correctly inferred, the type must be specified even when an
|
||||||
|
initializer is present. Example::
|
||||||
|
|
||||||
|
global pi = 3.14;
|
||||||
|
global hosts: set[addr];
|
||||||
|
global ciphers: table[string] of string = table();
|
||||||
|
|
||||||
|
Variable declarations outside of any function, hook, or event handler are
|
||||||
|
required to use this keyword (unless they are declared with the
|
||||||
|
:bro:keyword:`const` keyword instead).
|
||||||
|
|
||||||
|
Definitions of functions, hooks, and event handlers are not allowed
|
||||||
|
to use the "global" keyword. However, function declarations (i.e., no
|
||||||
|
function body is provided) can use the "global" keyword.
|
||||||
|
|
||||||
|
The scope of a global variable begins where the declaration is located,
|
||||||
|
and extends through all remaining Bro scripts that are loaded (however,
|
||||||
|
see the :bro:keyword:`module` keyword for an explanation of how modules
|
||||||
|
change the visibility of global identifiers).
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: const
|
||||||
|
|
||||||
|
A variable declared with the "const" keyword will be constant.
|
||||||
|
|
||||||
|
Variables declared as constant are required to be initialized at the
|
||||||
|
time of declaration. Normally, the type is inferred from the initializer,
|
||||||
|
but the type can be explicitly specified. Example::
|
||||||
|
|
||||||
|
const pi = 3.14;
|
||||||
|
const ssh_port: port = 22/tcp;
|
||||||
|
|
||||||
|
The value of a constant cannot be changed. The only exception is if the
|
||||||
|
variable is a global constant and has the :bro:attr:`&redef`
|
||||||
|
attribute, but even then its value can be changed only with a
|
||||||
|
:bro:keyword:`redef`.
|
||||||
|
|
||||||
|
The scope of a constant is local if the declaration is in a
|
||||||
|
function, hook, or event handler, and global otherwise.
|
||||||
|
|
||||||
|
Note that the "const" keyword cannot be used with either the "local"
|
||||||
|
or "global" keywords (i.e., "const" replaces "local" and "global").
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: type
|
||||||
|
|
||||||
|
The "type" keyword is used to declare a user-defined type. The name
|
||||||
|
of this new type has global scope and can be used anywhere a built-in
|
||||||
|
type name can occur.
|
||||||
|
|
||||||
|
The "type" keyword is most commonly used when defining a
|
||||||
|
:bro:type:`record` or an :bro:type:`enum`, but is also useful when
|
||||||
|
dealing with more complex types.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
type mytype: table[count] of table[addr, port] of string;
|
||||||
|
global myvar: mytype;
|
||||||
|
|
||||||
|
.. bro:keyword:: redef
|
||||||
|
|
||||||
|
There are three ways that "redef" can be used: to change the value of
|
||||||
|
a global variable (but only if it has the :bro:attr:`&redef` attribute),
|
||||||
|
to extend a record type or enum type, or to specify
|
||||||
|
a new event handler body that replaces all those that were previously
|
||||||
|
defined.
|
||||||
|
|
||||||
|
If you're using "redef" to change a global variable (defined using either
|
||||||
|
:bro:keyword:`const` or :bro:keyword:`global`), then the variable that you
|
||||||
|
want to change must have the :bro:attr:`&redef` attribute. If the variable
|
||||||
|
you're changing is a table, set, or pattern, you can use ``+=`` to add
|
||||||
|
new elements, or you can use ``=`` to specify a new value (all previous
|
||||||
|
contents of the object are removed). If the variable you're changing is a
|
||||||
|
set or table, then you can use the ``-=`` operator to remove the
|
||||||
|
specified elements (nothing happens for specified elements that don't
|
||||||
|
exist). If the variable you are changing is not a table, set, or pattern,
|
||||||
|
then you must use the ``=`` operator.
|
||||||
|
|
||||||
|
Examples::
|
||||||
|
|
||||||
|
redef pi = 3.14;
|
||||||
|
|
||||||
|
If you're using "redef" to extend a record or enum, then you must
|
||||||
|
use the ``+=`` assignment operator.
|
||||||
|
For an enum, you can add more enumeration constants, and for a record
|
||||||
|
you can add more record fields (however, each record field in the "redef"
|
||||||
|
must have either the :bro:attr:`&optional` or :bro:attr:`&default`
|
||||||
|
attribute).
|
||||||
|
|
||||||
|
Examples::
|
||||||
|
|
||||||
|
redef enum color += { Blue, Red };
|
||||||
|
redef record MyRecord += { n2:int &optional; s2:string &optional; };
|
||||||
|
|
||||||
|
If you're using "redef" to specify a new event handler body that
|
||||||
|
replaces all those that were previously defined (i.e., any subsequently
|
||||||
|
defined event handler body will not be affected by this "redef"), then
|
||||||
|
the syntax is the same as a regular event handler definition except for
|
||||||
|
the presence of the "redef" keyword.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
redef event myevent(s:string) { print "Redefined", s; }
|
||||||
|
|
||||||
|
|
||||||
|
.. _function/event/hook:
|
||||||
|
|
||||||
|
**function/event/hook**
|
||||||
|
For details on how to declare a :bro:type:`function`,
|
||||||
|
:bro:type:`event` handler, or :bro:type:`hook`,
|
||||||
|
see the documentation for those types.
|
||||||
|
|
||||||
|
|
||||||
|
Statements
|
||||||
|
----------
|
||||||
|
|
||||||
|
Statements (except those contained within a function, hook, or event
|
||||||
|
handler) can appear only after all global declarations in the concatenation
|
||||||
|
of all loaded Bro scripts.
|
||||||
|
|
||||||
|
Each statement in a Bro script must be terminated with a semicolon (with a
|
||||||
|
few exceptions noted below). An individual statement can span multiple
|
||||||
|
lines.
|
||||||
|
|
||||||
|
Here are the statements that the Bro scripting language supports.
|
||||||
|
|
||||||
|
.. bro:keyword:: add
|
||||||
|
|
||||||
|
The "add" statement is used to add an element to a :bro:type:`set`.
|
||||||
|
Nothing happens if the specified element already exists in the set.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
local myset: set[string];
|
||||||
|
add myset["test"];
|
||||||
|
|
||||||
|
.. bro:keyword:: break
|
||||||
|
|
||||||
|
The "break" statement is used to break out of a :bro:keyword:`switch`,
|
||||||
|
:bro:keyword:`for`, or :bro:keyword:`while` statement.
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: delete
|
||||||
|
|
||||||
|
The "delete" statement is used to remove an element from a
|
||||||
|
:bro:type:`set` or :bro:type:`table`. Nothing happens if the
|
||||||
|
specified element does not exist in the set or table.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
local myset = set("this", "test");
|
||||||
|
local mytable = table(["key1"] = 80/tcp, ["key2"] = 53/udp);
|
||||||
|
delete myset["test"];
|
||||||
|
delete mytable["key1"];
|
||||||
|
|
||||||
|
.. bro:keyword:: event
|
||||||
|
|
||||||
|
The "event" statement immediately queues invocation of an event handler.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
event myevent("test", 5);
|
||||||
|
|
||||||
|
.. bro:keyword:: fallthrough
|
||||||
|
|
||||||
|
The "fallthrough" statement can be used as the last statement in a
|
||||||
|
"case" block to indicate that execution should continue into the
|
||||||
|
next "case" or "default" label.
|
||||||
|
|
||||||
|
For an example, see the :bro:keyword:`switch` statement.
|
||||||
|
|
||||||
|
.. bro:keyword:: for
|
||||||
|
|
||||||
|
A "for" loop iterates over each element in a string, set, vector, or
|
||||||
|
table and executes a statement for each iteration. Currently,
|
||||||
|
modifying a container's membership while iterating over it may
|
||||||
|
result in undefined behavior, so avoid adding or removing elements
|
||||||
|
inside the loop.
|
||||||
|
|
||||||
|
For each iteration of the loop, a loop variable will be assigned to an
|
||||||
|
element if the expression evaluates to a string or set, or an index if
|
||||||
|
the expression evaluates to a vector or table. Then the statement
|
||||||
|
is executed. However, the statement will not be executed if the expression
|
||||||
|
evaluates to an object with no elements.
|
||||||
|
|
||||||
|
If the expression is a table or a set with more than one index, then the
|
||||||
|
loop variable must be specified as a comma-separated list of different
|
||||||
|
loop variables (one for each index), enclosed in brackets.
|
||||||
|
|
||||||
|
A :bro:keyword:`break` statement can be used at any time to immediately
|
||||||
|
terminate the "for" loop, and a :bro:keyword:`next` statement can be
|
||||||
|
used to skip to the next loop iteration.
|
||||||
|
|
||||||
|
Note that the loop variable in a "for" statement is not allowed to be
|
||||||
|
a global variable, and it does not need to be declared prior to the "for"
|
||||||
|
statement. The type will be inferred from the elements of the
|
||||||
|
expression.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
local myset = set(80/tcp, 81/tcp);
|
||||||
|
local mytable = table([10.0.0.1, 80/tcp]="s1", [10.0.0.2, 81/tcp]="s2");
|
||||||
|
|
||||||
|
for (p in myset)
|
||||||
|
print p;
|
||||||
|
|
||||||
|
for ([i,j] in mytable) {
|
||||||
|
if (mytable[i,j] == "done")
|
||||||
|
break;
|
||||||
|
if (mytable[i,j] == "skip")
|
||||||
|
next;
|
||||||
|
print i,j;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: if
|
||||||
|
|
||||||
|
Evaluates a given expression, which must yield a :bro:type:`bool` value.
|
||||||
|
If true, then a specified statement is executed. If false, then
|
||||||
|
the statement is not executed. Example::
|
||||||
|
|
||||||
|
if ( x == 2 ) print "x is 2";
|
||||||
|
|
||||||
|
|
||||||
|
However, if the expression evaluates to false and if an "else" is
|
||||||
|
provided, then the statement following the "else" is executed. Example::
|
||||||
|
|
||||||
|
if ( x == 2 )
|
||||||
|
print "x is 2";
|
||||||
|
else
|
||||||
|
print "x is not 2";
|
||||||
|
|
||||||
|
.. bro:keyword:: local
|
||||||
|
|
||||||
|
A variable declared with the "local" keyword will be local. If a type
|
||||||
|
is not specified, then an initializer is required so that the type can
|
||||||
|
be inferred. Likewise, if an initializer is not supplied, then the
|
||||||
|
type must be specified.
|
||||||
|
|
||||||
|
Examples::
|
||||||
|
|
||||||
|
local x1 = 5.7;
|
||||||
|
local x2: double;
|
||||||
|
local x3: double = 5.7;
|
||||||
|
|
||||||
|
Variable declarations inside a function, hook, or event handler are
|
||||||
|
required to use this keyword (the only two exceptions are variables
|
||||||
|
declared with :bro:keyword:`const`, and variables implicitly declared in a
|
||||||
|
:bro:keyword:`for` statement).
|
||||||
|
|
||||||
|
The scope of a local variable starts at the location where it is declared
|
||||||
|
and persists to the end of the function, hook,
|
||||||
|
or event handler in which it is declared (this is true even if the
|
||||||
|
local variable was declared within a `compound statement`_ or is the loop
|
||||||
|
variable in a "for" statement).
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: next
|
||||||
|
|
||||||
|
The "next" statement can only appear within a :bro:keyword:`for` or
|
||||||
|
:bro:keyword:`while` loop. It causes execution to skip to the next
|
||||||
|
iteration.
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: print
|
||||||
|
|
||||||
|
The "print" statement takes a comma-separated list of one or more
|
||||||
|
expressions. Each expression in the list is evaluated and then converted
|
||||||
|
to a string. Then each string is printed, with each string separated by
|
||||||
|
a comma in the output.
|
||||||
|
|
||||||
|
Examples::
|
||||||
|
|
||||||
|
print 3.14;
|
||||||
|
print "Results", x, y;
|
||||||
|
|
||||||
|
By default, the "print" statement writes to the standard
|
||||||
|
output (stdout). However, if the first expression is of type
|
||||||
|
:bro:type:`file`, then "print" writes to that file.
|
||||||
|
|
||||||
|
If a string contains non-printable characters (i.e., byte values that are
|
||||||
|
not in the range 32 - 126), then the "print" statement converts each
|
||||||
|
non-printable character to an escape sequence before it is printed.
|
||||||
|
|
||||||
|
For more control over how the strings are formatted, see the :bro:id:`fmt`
|
||||||
|
function.
|
||||||
|
|
||||||
|
.. bro:keyword:: return
|
||||||
|
|
||||||
|
The "return" statement immediately exits the current function, hook, or
|
||||||
|
event handler. For a function, the specified expression (if any) is
|
||||||
|
evaluated and returned. A "return" statement in a hook or event handler
|
||||||
|
cannot return a value because event handlers and hooks do not have
|
||||||
|
return types.
|
||||||
|
|
||||||
|
Examples::
|
||||||
|
|
||||||
|
function my_func(): string
|
||||||
|
{
|
||||||
|
return "done";
|
||||||
|
}
|
||||||
|
|
||||||
|
event my_event(n: count)
|
||||||
|
{
|
||||||
|
if ( n == 0 ) return;
|
||||||
|
|
||||||
|
print n;
|
||||||
|
}
|
||||||
|
|
||||||
|
There is a special form of the "return" statement that is only allowed
|
||||||
|
in functions. Syntactically, it looks like a :bro:keyword:`when` statement
|
||||||
|
immediately preceded by the "return" keyword. This form of the "return"
|
||||||
|
statement is used to specify a function that delays its result (such a
|
||||||
|
function can only be called in the expression of a :bro:keyword:`when`
|
||||||
|
statement). The function returns at the time the "when"
|
||||||
|
statement's condition becomes true, and the function returns the value
|
||||||
|
that the "when" statement's body returns (or if the condition does
|
||||||
|
not become true within the specified timeout interval, then the function
|
||||||
|
returns the value that the "timeout" block returns).
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
global X: table[string] of count;
|
||||||
|
|
||||||
|
function a() : count
|
||||||
|
{
|
||||||
|
# This delays until condition becomes true.
|
||||||
|
return when ( "a" in X )
|
||||||
|
{
|
||||||
|
return X["a"];
|
||||||
|
}
|
||||||
|
timeout 30 sec
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
# Installs a trigger which fires if a() returns 42.
|
||||||
|
when ( a() == 42 )
|
||||||
|
print "expected result";
|
||||||
|
|
||||||
|
print "Waiting for a() to return...";
|
||||||
|
X["a"] = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: schedule
|
||||||
|
|
||||||
|
The "schedule" statement is used to raise a specified event with
|
||||||
|
specified parameters at a later time specified as an :bro:type:`interval`.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
schedule 30sec { myevent(x, y, z) };
|
||||||
|
|
||||||
|
Note that the braces are always required (they do not indicate a
|
||||||
|
`compound statement`_).
|
||||||
|
|
||||||
|
Note that "schedule" is actually an expression that returns a value
|
||||||
|
of type "timer", but in practice the return value is not used.
|
||||||
|
|
||||||
|
.. bro:keyword:: switch
|
||||||
|
|
||||||
|
A "switch" statement evaluates a given expression and jumps to
|
||||||
|
the first "case" label which contains a matching value (the result of the
|
||||||
|
expression must be type-compatible with all of the values in all of the
|
||||||
|
"case" labels). If there is no matching value, then execution jumps to
|
||||||
|
the "default" label instead, and if there is no "default" label then
|
||||||
|
execution jumps out of the "switch" block.
|
||||||
|
|
||||||
|
Here is an example (assuming that "get_day_of_week" is a
|
||||||
|
function that returns a string)::
|
||||||
|
|
||||||
|
switch get_day_of_week()
|
||||||
|
{
|
||||||
|
case "Sa", "Su":
|
||||||
|
print "weekend";
|
||||||
|
fallthrough;
|
||||||
|
case "Mo", "Tu", "We", "Th", "Fr":
|
||||||
|
print "valid result";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print "invalid result";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
A "switch" block can have any number of "case" labels, and one
|
||||||
|
optional "default" label.
|
||||||
|
|
||||||
|
A "case" label can have a comma-separated list of
|
||||||
|
more than one value. A value in a "case" label can be an expression,
|
||||||
|
but it must be a constant expression (i.e., the expression can consist
|
||||||
|
only of constants).
|
||||||
|
|
||||||
|
Each "case" and the "default" block must
|
||||||
|
end with either a :bro:keyword:`break`, :bro:keyword:`fallthrough`, or
|
||||||
|
:bro:keyword:`return` statement (although "return" is allowed only
|
||||||
|
if the "switch" statement is inside a function, hook, or event handler).
|
||||||
|
If a "case" (or "default") block contain more than one statement, then
|
||||||
|
there is no need to wrap them in braces.
|
||||||
|
|
||||||
|
Note that the braces in a "switch" statement are always required (these
|
||||||
|
do not indicate the presence of a `compound statement`_), and that no
|
||||||
|
semicolon is needed at the end of a "switch" statement.
|
||||||
|
|
||||||
|
|
||||||
|
.. bro:keyword:: when
|
||||||
|
|
||||||
|
Evaluates a given expression, which must result in a value of type
|
||||||
|
:bro:type:`bool`. When the value of the expression becomes available
|
||||||
|
and if the result is true, then a specified statement is executed.
|
||||||
|
|
||||||
|
In the following example, if the expression evaluates to true, then
|
||||||
|
the "print" statement is executed::
|
||||||
|
|
||||||
|
when ( (local x = foo()) && x == 42 )
|
||||||
|
print x;
|
||||||
|
|
||||||
|
However, if a timeout is specified, and if the expression does not
|
||||||
|
evaluate to true within the specified timeout interval, then the
|
||||||
|
statement following the "timeout" keyword is executed::
|
||||||
|
|
||||||
|
when ( (local x = foo()) && x == 42 )
|
||||||
|
print x;
|
||||||
|
timeout 5sec {
|
||||||
|
print "timeout";
|
||||||
|
}
|
||||||
|
|
||||||
|
Note that when a timeout is specified the braces are
|
||||||
|
always required (these do not indicate a `compound statement`_).
|
||||||
|
|
||||||
|
The expression in a "when" statement can contain a declaration of a local
|
||||||
|
variable but only if the declaration is written in the form
|
||||||
|
"local *var* = *init*" (example: "local x = myfunction()"). This form
|
||||||
|
of a local declaration is actually an expression, the result of which
|
||||||
|
is always a boolean true value.
|
||||||
|
|
||||||
|
The expression in a "when" statement can contain an asynchronous function
|
||||||
|
call such as :bro:id:`lookup_hostname` (in fact, this is the only place
|
||||||
|
such a function can be called), but it can also contain an ordinary
|
||||||
|
function call. When an asynchronous function call is in the expression,
|
||||||
|
then Bro will continue processing statements in the script following
|
||||||
|
the "when" statement, and when the result of the function call is available
|
||||||
|
Bro will finish evaluating the expression in the "when" statement.
|
||||||
|
See the :bro:keyword:`return` statement for an explanation of how to
|
||||||
|
create an asynchronous function in a Bro script.
|
||||||
|
|
||||||
|
.. bro:keyword:: while
|
||||||
|
|
||||||
|
A "while" loop iterates over a body statement as long as a given
|
||||||
|
condition remains true.
|
||||||
|
|
||||||
|
A :bro:keyword:`break` statement can be used at any time to immediately
|
||||||
|
terminate the "while" loop, and a :bro:keyword:`next` statement can be
|
||||||
|
used to skip to the next loop iteration.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
local i = 0;
|
||||||
|
|
||||||
|
while ( i < 5 )
|
||||||
|
print ++i;
|
||||||
|
|
||||||
|
while ( some_cond() )
|
||||||
|
{
|
||||||
|
local finish_up = F;
|
||||||
|
|
||||||
|
if ( skip_ahead() )
|
||||||
|
next;
|
||||||
|
|
||||||
|
[...]
|
||||||
|
|
||||||
|
if ( finish_up )
|
||||||
|
break;
|
||||||
|
|
||||||
|
[...]
|
||||||
|
}
|
||||||
|
|
||||||
|
.. _compound statement:
|
||||||
|
|
||||||
|
**compound statement**
|
||||||
|
A compound statement is created by wrapping zero or more statements in
|
||||||
|
braces ``{ }``. Individual statements inside the braces need to be
|
||||||
|
terminated by a semicolon, but a semicolon is not needed at the end
|
||||||
|
(outside of the braces) of a compound statement.
|
||||||
|
|
||||||
|
A compound statement is required in order to execute more than one
|
||||||
|
statement in the body of a :bro:keyword:`for`, :bro:keyword:`while`,
|
||||||
|
:bro:keyword:`if`, or :bro:keyword:`when` statement.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
if ( x == 2 ) {
|
||||||
|
print "x is 2";
|
||||||
|
++x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Note that there are other places in the Bro scripting language that use
|
||||||
|
braces, but that do not indicate the presence of a compound
|
||||||
|
statement (these are noted in the documentation).
|
||||||
|
|
||||||
|
.. _null:
|
||||||
|
|
||||||
|
**null statement**
|
||||||
|
The null statement (executing it has no effect) consists of just a
|
||||||
|
semicolon. This might be useful during testing or debugging a Bro script
|
||||||
|
in places where a statement is required, but it is probably not useful
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
if ( x == 2 )
|
||||||
|
;
|
||||||
|
|
|
@ -1,92 +1,114 @@
|
||||||
Types and Attributes
|
|
||||||
====================
|
|
||||||
|
|
||||||
Types
|
Types
|
||||||
-----
|
=====
|
||||||
|
|
||||||
Every value in a Bro script has a type (see below for a list of all built-in
|
The Bro scripting language supports the following built-in types:
|
||||||
types). Although Bro variables have static types (meaning that their type
|
|
||||||
is fixed), their type is inferred from the value to which they are
|
|
||||||
initially assigned when the variable is declared without an explicit type
|
|
||||||
name.
|
|
||||||
|
|
||||||
Automatic conversions happen when a binary operator has operands of
|
+-----------------------+--------------------+
|
||||||
different types. Automatic conversions are limited to converting between
|
| Name | Description |
|
||||||
numeric types. The numeric types are ``int``, ``count``, and ``double``
|
+=======================+====================+
|
||||||
(``bool`` is not a numeric type).
|
| :bro:type:`bool` | Boolean |
|
||||||
When an automatic conversion occurs, values are promoted to the "highest"
|
+-----------------------+--------------------+
|
||||||
type in the expression. In general, this promotion follows a simple
|
| :bro:type:`count`, | Numeric types |
|
||||||
hierarchy: ``double`` is highest, ``int`` comes next, and ``count`` is
|
| :bro:type:`int`, | |
|
||||||
lowest.
|
| :bro:type:`double` | |
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
| :bro:type:`time`, | Time types |
|
||||||
|
| :bro:type:`interval` | |
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
| :bro:type:`string` | String |
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
| :bro:type:`pattern` | Regular expression |
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
| :bro:type:`port`, | Network types |
|
||||||
|
| :bro:type:`addr`, | |
|
||||||
|
| :bro:type:`subnet` | |
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
| :bro:type:`enum` | Enumeration |
|
||||||
|
| | (user-defined type)|
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
| :bro:type:`table`, | Container types |
|
||||||
|
| :bro:type:`set`, | |
|
||||||
|
| :bro:type:`vector`, | |
|
||||||
|
| :bro:type:`record` | |
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
| :bro:type:`function`, | Executable types |
|
||||||
|
| :bro:type:`event`, | |
|
||||||
|
| :bro:type:`hook` | |
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
| :bro:type:`file` | File type (only |
|
||||||
|
| | for writing) |
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
| :bro:type:`opaque` | Opaque type (for |
|
||||||
|
| | some built-in |
|
||||||
|
| | functions) |
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
| :bro:type:`any` | Any type (for |
|
||||||
|
| | functions or |
|
||||||
|
| | containers) |
|
||||||
|
+-----------------------+--------------------+
|
||||||
|
|
||||||
The Bro scripting language supports the following built-in types.
|
Here is a more detailed description of each type:
|
||||||
|
|
||||||
.. bro:type:: void
|
|
||||||
|
|
||||||
An internal Bro type (i.e., "void" is not a reserved keyword in the Bro
|
|
||||||
scripting language) representing the absence of a return type for a
|
|
||||||
function.
|
|
||||||
|
|
||||||
.. bro:type:: bool
|
.. bro:type:: bool
|
||||||
|
|
||||||
Reflects a value with one of two meanings: true or false. The two
|
Reflects a value with one of two meanings: true or false. The two
|
||||||
``bool`` constants are ``T`` and ``F``.
|
"bool" constants are ``T`` and ``F``.
|
||||||
|
|
||||||
The ``bool`` type supports the following operators: equality/inequality
|
The "bool" type supports the following operators: equality/inequality
|
||||||
(``==``, ``!=``), logical and/or (``&&``, ``||``), logical
|
(``==``, ``!=``), logical and/or (``&&``, ``||``), logical
|
||||||
negation (``!``), and absolute value (where ``|T|`` is 1, and ``|F|`` is 0).
|
negation (``!``), and absolute value (where ``|T|`` is 1, and ``|F|`` is 0,
|
||||||
|
and in both cases the result type is :bro:type:`count`).
|
||||||
|
|
||||||
.. bro:type:: int
|
.. bro:type:: int
|
||||||
|
|
||||||
A numeric type representing a 64-bit signed integer. An ``int`` constant
|
A numeric type representing a 64-bit signed integer. An "int" constant
|
||||||
is a string of digits preceded by a ``+`` or ``-`` sign, e.g.
|
is a string of digits preceded by a "+" or "-" sign, e.g.
|
||||||
``-42`` or ``+5`` (the "+" sign is optional but see note about type
|
``-42`` or ``+5`` (the "+" sign is optional but see note about type
|
||||||
inferencing below). An ``int`` constant can also be written in
|
inferencing below). An "int" constant can also be written in
|
||||||
hexadecimal notation (in which case "0x" must be between the sign and
|
hexadecimal notation (in which case "0x" must be between the sign and
|
||||||
the hex digits), e.g. ``-0xFF`` or ``+0xabc123``.
|
the hex digits), e.g. ``-0xFF`` or ``+0xabc123``.
|
||||||
|
|
||||||
The ``int`` type supports the following operators: arithmetic
|
The "int" type supports the following operators: arithmetic
|
||||||
operators (``+``, ``-``, ``*``, ``/``, ``%``), comparison operators
|
operators (``+``, ``-``, ``*``, ``/``, ``%``), comparison operators
|
||||||
(``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), assignment operators
|
(``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), assignment operators
|
||||||
(``=``, ``+=``, ``-=``), pre-increment (``++``), pre-decrement
|
(``=``, ``+=``, ``-=``), pre-increment (``++``), pre-decrement
|
||||||
(``--``), and absolute value (e.g., ``|-3|`` is 3).
|
(``--``), unary plus and minus (``+``, ``-``), and absolute value
|
||||||
|
(e.g., ``|-3|`` is 3, but the result type is :bro:type:`count`).
|
||||||
|
|
||||||
When using type inferencing use care so that the
|
When using type inferencing use care so that the
|
||||||
intended type is inferred, e.g. ``local size_difference = 0`` will
|
intended type is inferred, e.g. "local size_difference = 0" will
|
||||||
infer :bro:type:`count`, while ``local size_difference = +0``
|
infer ":bro:type:`count`", while "local size_difference = +0"
|
||||||
will infer :bro:type:`int`.
|
will infer "int".
|
||||||
|
|
||||||
.. bro:type:: count
|
.. bro:type:: count
|
||||||
|
|
||||||
A numeric type representing a 64-bit unsigned integer. A ``count``
|
A numeric type representing a 64-bit unsigned integer. A "count"
|
||||||
constant is a string of digits, e.g. ``1234`` or ``0``. A ``count``
|
constant is a string of digits, e.g. ``1234`` or ``0``. A "count"
|
||||||
can also be written in hexadecimal notation (in which case "0x" must
|
can also be written in hexadecimal notation (in which case "0x" must
|
||||||
precede the hex digits), e.g. ``0xff`` or ``0xABC123``.
|
precede the hex digits), e.g. ``0xff`` or ``0xABC123``.
|
||||||
|
|
||||||
The ``count`` type supports the same operators as the :bro:type:`int`
|
The "count" type supports the same operators as the ":bro:type:`int`"
|
||||||
type. A unary plus or minus applied to a ``count`` results in an ``int``.
|
type, but a unary plus or minus applied to a "count" results in an
|
||||||
|
"int".
|
||||||
.. bro:type:: counter
|
|
||||||
|
|
||||||
An alias to :bro:type:`count`.
|
|
||||||
|
|
||||||
.. bro:type:: double
|
.. bro:type:: double
|
||||||
|
|
||||||
A numeric type representing a double-precision floating-point
|
A numeric type representing a double-precision floating-point
|
||||||
number. Floating-point constants are written as a string of digits
|
number. Floating-point constants are written as a string of digits
|
||||||
with an optional decimal point, optional scale-factor in scientific
|
with an optional decimal point, optional scale-factor in scientific
|
||||||
notation, and optional ``+`` or ``-`` sign. Examples are ``-1234``,
|
notation, and optional "+" or "-" sign. Examples are ``-1234``,
|
||||||
``-1234e0``, ``3.14159``, and ``.003E-23``.
|
``-1234e0``, ``3.14159``, and ``.003E-23``.
|
||||||
|
|
||||||
The ``double`` type supports the following operators: arithmetic
|
The "double" type supports the following operators: arithmetic
|
||||||
operators (``+``, ``-``, ``*``, ``/``), comparison operators
|
operators (``+``, ``-``, ``*``, ``/``), comparison operators
|
||||||
(``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), assignment operators
|
(``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), assignment operators
|
||||||
(``=``, ``+=``, ``-=``), and absolute value (e.g., ``|-3.14|`` is 3.14).
|
(``=``, ``+=``, ``-=``), unary plus and minus (``+``, ``-``), and
|
||||||
|
absolute value (e.g., ``|-3.14|`` is 3.14).
|
||||||
|
|
||||||
When using type inferencing use care so that the
|
When using type inferencing use care so that the
|
||||||
intended type is inferred, e.g. ``local size_difference = 5`` will
|
intended type is inferred, e.g. "local size_difference = 5" will
|
||||||
infer :bro:type:`count`, while ``local size_difference = 5.0``
|
infer ":bro:type:`count`", while "local size_difference = 5.0"
|
||||||
will infer :bro:type:`double`.
|
will infer "double".
|
||||||
|
|
||||||
.. bro:type:: time
|
.. bro:type:: time
|
||||||
|
|
||||||
|
@ -97,10 +119,10 @@ The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
Time values support the comparison operators (``==``, ``!=``, ``<``,
|
Time values support the comparison operators (``==``, ``!=``, ``<``,
|
||||||
``<=``, ``>``, ``>=``). A ``time`` value can be subtracted from
|
``<=``, ``>``, ``>=``). A ``time`` value can be subtracted from
|
||||||
another ``time`` value to produce an ``interval`` value. An ``interval``
|
another ``time`` value to produce an :bro:type:`interval` value. An
|
||||||
value can be added to, or subtracted from, a ``time`` value to produce a
|
``interval`` value can be added to, or subtracted from, a ``time`` value
|
||||||
``time`` value. The absolute value of a ``time`` value is a ``double``
|
to produce a ``time`` value. The absolute value of a ``time`` value is
|
||||||
with the same numeric value.
|
a :bro:type:`double` with the same numeric value.
|
||||||
|
|
||||||
.. bro:type:: interval
|
.. bro:type:: interval
|
||||||
|
|
||||||
|
@ -115,52 +137,58 @@ The Bro scripting language supports the following built-in types.
|
||||||
``3.5mins``. An ``interval`` can also be negated, for example
|
``3.5mins``. An ``interval`` can also be negated, for example
|
||||||
``-12 hr`` represents "twelve hours in the past".
|
``-12 hr`` represents "twelve hours in the past".
|
||||||
|
|
||||||
Intervals support addition and subtraction. Intervals also support
|
Intervals support addition and subtraction, the comparison operators
|
||||||
division (in which case the result is a ``double`` value), the
|
(``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), the assignment
|
||||||
comparison operators (``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``),
|
operators (``=``, ``+=``, ``-=``), and unary plus and minus (``+``, ``-``).
|
||||||
and the assignment operators (``=``, ``+=``, ``-=``). Also, an
|
|
||||||
``interval`` can be multiplied or divided by an arithmetic type
|
Intervals also support division (in which case the result is a
|
||||||
(``count``, ``int``, or ``double``) to produce an ``interval`` value.
|
:bro:type:`double` value). An ``interval`` can be multiplied or divided
|
||||||
The absolute value of an ``interval`` is a ``double`` value equal to the
|
by an arithmetic type (``count``, ``int``, or ``double``) to produce
|
||||||
number of seconds in the ``interval`` (e.g., ``|-1 min|`` is 60).
|
an ``interval`` value. The absolute value of an ``interval`` is a
|
||||||
|
``double`` value equal to the number of seconds in the ``interval``
|
||||||
|
(e.g., ``|-1 min|`` is 60.0).
|
||||||
|
|
||||||
.. bro:type:: string
|
.. bro:type:: string
|
||||||
|
|
||||||
A type used to hold character-string values which represent text.
|
A type used to hold character-string values which represent text, although
|
||||||
String constants are created by enclosing text in double quotes (")
|
strings in a Bro script can actually contain any arbitrary binary data.
|
||||||
and the backslash character (\\) introduces escape sequences (all of
|
|
||||||
the C-style escape sequences are supported).
|
String constants are created by enclosing text within a pair of double
|
||||||
|
quotes ("). A string constant cannot span multiple lines in a Bro script.
|
||||||
|
The backslash character (\\) introduces escape sequences. The
|
||||||
|
following escape sequences are recognized: ``\n``, ``\t``, ``\v``, ``\b``,
|
||||||
|
``\r``, ``\f``, ``\a``, ``\ooo`` (where each 'o' is an octal digit),
|
||||||
|
``\xhh`` (where each 'h' is a hexadecimal digit). For escape sequences
|
||||||
|
that don't match any of these, Bro will just remove the backslash (so
|
||||||
|
to represent a literal backslash in a string constant, you just use
|
||||||
|
two consecutive backslashes).
|
||||||
|
|
||||||
Strings support concatenation (``+``), and assignment (``=``, ``+=``).
|
Strings support concatenation (``+``), and assignment (``=``, ``+=``).
|
||||||
Strings also support the comparison operators (``==``, ``!=``, ``<``,
|
Strings also support the comparison operators (``==``, ``!=``, ``<``,
|
||||||
``<=``, ``>``, ``>=``). The number of characters in a string can be
|
``<=``, ``>``, ``>=``). The number of characters in a string can be
|
||||||
found by enclosing the string within pipe characters (e.g., ``|"abc"|``
|
found by enclosing the string within pipe characters (e.g., ``|"abc"|``
|
||||||
is 3).
|
is 3). Substring searching can be performed using the "in" or "!in"
|
||||||
|
|
||||||
The subscript operator can extract an individual character or a substring
|
|
||||||
of a string (string indexing is zero-based, but an index of
|
|
||||||
-1 refers to the last character in the string, and -2 refers to the
|
|
||||||
second-to-last character, etc.). When extracting a substring, the
|
|
||||||
starting and ending index values are separated by a colon. For example::
|
|
||||||
|
|
||||||
local orig = "0123456789";
|
|
||||||
local third_char = orig[2];
|
|
||||||
local last_char = orig[-1];
|
|
||||||
local first_three_chars = orig[0:2];
|
|
||||||
|
|
||||||
Substring searching can be performed using the "in" or "!in"
|
|
||||||
operators (e.g., "bar" in "foobar" yields true).
|
operators (e.g., "bar" in "foobar" yields true).
|
||||||
|
|
||||||
Note that Bro represents strings internally as a count and vector of
|
The subscript operator can extract a substring of a string. To do this,
|
||||||
bytes rather than a NUL-terminated byte string (although string
|
specify the starting index to extract (if the starting index is omitted,
|
||||||
constants are also automatically NUL-terminated). This is because
|
then zero is assumed), followed by a colon and index
|
||||||
network traffic can easily introduce NULs into strings either by
|
one past the last character to extract (if the last index is omitted,
|
||||||
nature of an application, inadvertently, or maliciously. And while
|
then the extracted substring will go to the end of the original string).
|
||||||
NULs are allowed in Bro strings, when present in strings passed as
|
However, if both the colon and last index are omitted, then a string of
|
||||||
arguments to many functions, a run-time error can occur as their
|
length one is extracted. String indexing is zero-based, but an index
|
||||||
presence likely indicates a sort of problem. In that case, the
|
of -1 refers to the last character in the string, and -2 refers to the
|
||||||
string will also only be represented to the user as the literal
|
second-to-last character, etc. Here are a few examples::
|
||||||
"<string-with-NUL>" string.
|
|
||||||
|
local orig = "0123456789";
|
||||||
|
local second_char = orig[1];
|
||||||
|
local last_char = orig[-1];
|
||||||
|
local first_two_chars = orig[:2];
|
||||||
|
local last_two_chars = orig[8:];
|
||||||
|
local no_first_and_last = orig[1:9];
|
||||||
|
|
||||||
|
Note that the subscript operator cannot be used to modify a string (i.e.,
|
||||||
|
it cannot be on the left side of an assignment operator).
|
||||||
|
|
||||||
.. bro:type:: pattern
|
.. bro:type:: pattern
|
||||||
|
|
||||||
|
@ -174,7 +202,7 @@ The Bro scripting language supports the following built-in types.
|
||||||
and embedded.
|
and embedded.
|
||||||
|
|
||||||
In exact matching the ``==`` equality relational operator is used
|
In exact matching the ``==`` equality relational operator is used
|
||||||
with one :bro:type:`pattern` operand and one :bro:type:`string`
|
with one "pattern" operand and one ":bro:type:`string`"
|
||||||
operand (order of operands does not matter) to check whether the full
|
operand (order of operands does not matter) to check whether the full
|
||||||
string exactly matches the pattern. In exact matching, the ``^``
|
string exactly matches the pattern. In exact matching, the ``^``
|
||||||
beginning-of-line and ``$`` end-of-line anchors are redundant since
|
beginning-of-line and ``$`` end-of-line anchors are redundant since
|
||||||
|
@ -190,8 +218,8 @@ The Bro scripting language supports the following built-in types.
|
||||||
yields false. The ``!=`` operator would yield the negation of ``==``.
|
yields false. The ``!=`` operator would yield the negation of ``==``.
|
||||||
|
|
||||||
In embedded matching the ``in`` operator is used with one
|
In embedded matching the ``in`` operator is used with one
|
||||||
:bro:type:`pattern` operand (which must be on the left-hand side) and
|
"pattern" operand (which must be on the left-hand side) and
|
||||||
one :bro:type:`string` operand, but tests whether the pattern
|
one ":bro:type:`string`" operand, but tests whether the pattern
|
||||||
appears anywhere within the given string. For example::
|
appears anywhere within the given string. For example::
|
||||||
|
|
||||||
/foo|bar/ in "foobar"
|
/foo|bar/ in "foobar"
|
||||||
|
@ -203,27 +231,12 @@ The Bro scripting language supports the following built-in types.
|
||||||
is false since "oob" does not appear at the start of "foobar". The
|
is false since "oob" does not appear at the start of "foobar". The
|
||||||
``!in`` operator would yield the negation of ``in``.
|
``!in`` operator would yield the negation of ``in``.
|
||||||
|
|
||||||
.. bro:type:: enum
|
|
||||||
|
|
||||||
A type allowing the specification of a set of related values that
|
|
||||||
have no further structure. An example declaration:
|
|
||||||
|
|
||||||
.. code:: bro
|
|
||||||
|
|
||||||
type color: enum { Red, White, Blue, };
|
|
||||||
|
|
||||||
The last comma after ``Blue`` is optional.
|
|
||||||
|
|
||||||
The only operations allowed on enumerations are equality comparisons
|
|
||||||
(``==``, ``!=``) and assignment (``=``).
|
|
||||||
Enumerations do not have associated values or ordering.
|
|
||||||
|
|
||||||
.. bro:type:: port
|
.. bro:type:: port
|
||||||
|
|
||||||
A type representing transport-level port numbers. Besides TCP and
|
A type representing transport-level port numbers (besides TCP and
|
||||||
UDP ports, there is a concept of an ICMP "port" where the source
|
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
|
port is the ICMP message type and the destination port the ICMP
|
||||||
message code. A ``port`` constant is written as an unsigned integer
|
message code). A ``port`` constant is written as an unsigned integer
|
||||||
followed by one of ``/tcp``, ``/udp``, ``/icmp``, or ``/unknown``.
|
followed by one of ``/tcp``, ``/udp``, ``/icmp``, or ``/unknown``.
|
||||||
|
|
||||||
Ports support the comparison operators (``==``, ``!=``, ``<``, ``<=``,
|
Ports support the comparison operators (``==``, ``!=``, ``<``, ``<=``,
|
||||||
|
@ -255,14 +268,6 @@ The Bro scripting language supports the following built-in types.
|
||||||
address) are treated internally as IPv4 addresses (for example,
|
address) are treated internally as IPv4 addresses (for example,
|
||||||
``[::ffff:192.168.1.100]`` is equal to ``192.168.1.100``).
|
``[::ffff:192.168.1.100]`` is equal to ``192.168.1.100``).
|
||||||
|
|
||||||
Hostname constants can also be used, but since a hostname can
|
|
||||||
correspond to multiple IP addresses, the type of such a 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 equality (``==``, ``!=``),
|
Addresses can be compared for equality (``==``, ``!=``),
|
||||||
and also for ordering (``<``, ``<=``, ``>``, ``>=``). The absolute value
|
and also for ordering (``<``, ``<=``, ``>``, ``>=``). The absolute value
|
||||||
of an address gives the size in bits (32 for IPv4, and 128 for IPv6).
|
of an address gives the size in bits (32 for IPv4, and 128 for IPv6).
|
||||||
|
@ -285,9 +290,17 @@ The Bro scripting language supports the following built-in types.
|
||||||
if ( a in s )
|
if ( a in s )
|
||||||
print "true";
|
print "true";
|
||||||
|
|
||||||
Note that you can check if a given ``addr`` is IPv4 or IPv6 using
|
You can check if a given ``addr`` is IPv4 or IPv6 using
|
||||||
the :bro:id:`is_v4_addr` and :bro:id:`is_v6_addr` built-in functions.
|
the :bro:id:`is_v4_addr` and :bro:id:`is_v6_addr` built-in functions.
|
||||||
|
|
||||||
|
Note that hostname constants can also be used, but since a hostname can
|
||||||
|
correspond to multiple IP addresses, the type of such a variable is
|
||||||
|
"set[addr]". For example:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
local a = www.google.com;
|
||||||
|
|
||||||
.. bro:type:: subnet
|
.. bro:type:: subnet
|
||||||
|
|
||||||
A type representing a block of IP addresses in CIDR notation. A
|
A type representing a block of IP addresses in CIDR notation. A
|
||||||
|
@ -296,13 +309,24 @@ The Bro scripting language supports the following built-in types.
|
||||||
number. For example, ``192.168.0.0/16`` or ``[fe80::]/64``.
|
number. For example, ``192.168.0.0/16`` or ``[fe80::]/64``.
|
||||||
|
|
||||||
Subnets can be compared for equality (``==``, ``!=``). An
|
Subnets can be compared for equality (``==``, ``!=``). An
|
||||||
:bro:type:`addr` can be checked for inclusion in a subnet using
|
"addr" can be checked for inclusion in a subnet using
|
||||||
the "in" or "!in" operators.
|
the ``in`` or ``!in`` operators.
|
||||||
|
|
||||||
.. bro:type:: any
|
.. bro:type:: enum
|
||||||
|
|
||||||
Used to bypass strong typing. For example, a function can take an
|
A type allowing the specification of a set of related values that
|
||||||
argument of type ``any`` when it may be of different types.
|
have no further structure. An example declaration:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
type color: enum { Red, White, Blue, };
|
||||||
|
|
||||||
|
The last comma after ``Blue`` is optional. Both the type name ``color``
|
||||||
|
and the individual values (``Red``, etc.) have global scope.
|
||||||
|
|
||||||
|
Enumerations do not have associated values or ordering.
|
||||||
|
The only operations allowed on enumerations are equality comparisons
|
||||||
|
(``==``, ``!=``) and assignment (``=``).
|
||||||
|
|
||||||
.. bro:type:: table
|
.. bro:type:: table
|
||||||
|
|
||||||
|
@ -316,24 +340,28 @@ The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
table [ type^+ ] of type
|
table [ type^+ ] of type
|
||||||
|
|
||||||
where *type^+* is one or more types, separated by commas. For example:
|
where *type^+* is one or more types, separated by commas. The
|
||||||
|
index type cannot be any of the following types: pattern, table, set,
|
||||||
|
vector, file, opaque, any.
|
||||||
|
|
||||||
|
Here is an example of declaring a table indexed by "count" values
|
||||||
|
and yielding "string" values:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
global a: table[count] of string;
|
global a: table[count] of string;
|
||||||
|
|
||||||
declares a table indexed by :bro:type:`count` values and yielding
|
The yield type can also be more complex:
|
||||||
:bro:type:`string` values. The yield type can also be more complex:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
global a: table[count] of table[addr, port] of string;
|
global a: table[count] of table[addr, port] of string;
|
||||||
|
|
||||||
which declares a table indexed by :bro:type:`count` and yielding
|
which declares a table indexed by "count" and yielding
|
||||||
another :bro:type:`table` which is indexed by an :bro:type:`addr`
|
another "table" which is indexed by an "addr"
|
||||||
and :bro:type:`port` to yield a :bro:type:`string`.
|
and "port" to yield a "string".
|
||||||
|
|
||||||
Initialization of tables occurs by enclosing a set of initializers within
|
One way to initialize a table is by enclosing a set of initializers within
|
||||||
braces, for example:
|
braces, for example:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
@ -343,18 +371,17 @@ The Bro scripting language supports the following built-in types.
|
||||||
[5] = "five",
|
[5] = "five",
|
||||||
};
|
};
|
||||||
|
|
||||||
A table constructor (equivalent to above example) can also be used
|
A table constructor can also be used to create a table:
|
||||||
to create a table:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
global t2: table[count] of string = table(
|
global t2 = table(
|
||||||
[11] = "eleven",
|
[192.168.0.2, 22/tcp] = "ssh",
|
||||||
[5] = "five"
|
[192.168.0.3, 80/tcp] = "http"
|
||||||
);
|
);
|
||||||
|
|
||||||
Table constructors can also be explicitly named by a type, which is
|
Table constructors can also be explicitly named by a type, which is
|
||||||
useful for when a more complex index type could otherwise be
|
useful when a more complex index type could otherwise be
|
||||||
ambiguous:
|
ambiguous:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
@ -381,17 +408,7 @@ The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
if ( 13 in t )
|
if ( 13 in t )
|
||||||
...
|
...
|
||||||
|
if ( [192.168.0.2, 22/tcp] in t2 )
|
||||||
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 )
|
|
||||||
...
|
...
|
||||||
|
|
||||||
Add or overwrite individual table elements by assignment:
|
Add or overwrite individual table elements by assignment:
|
||||||
|
@ -400,7 +417,7 @@ The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
t[13] = "thirteen";
|
t[13] = "thirteen";
|
||||||
|
|
||||||
Remove individual table elements with ``delete``:
|
Remove individual table elements with :bro:keyword:`delete`:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
|
@ -416,6 +433,9 @@ The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
|t|
|
|t|
|
||||||
|
|
||||||
|
See the :bro:keyword:`for` statement for info on how to iterate over
|
||||||
|
the elements in a table.
|
||||||
|
|
||||||
.. bro:type:: set
|
.. bro:type:: set
|
||||||
|
|
||||||
A set is like a :bro:type:`table`, but it is a collection of indices
|
A set is like a :bro:type:`table`, but it is a collection of indices
|
||||||
|
@ -424,27 +444,26 @@ The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
set [ type^+ ]
|
set [ type^+ ]
|
||||||
|
|
||||||
where *type^+* is one or more types separated by commas.
|
where *type^+* is one or more types separated by commas. The
|
||||||
|
index type cannot be any of the following types: pattern, table, set,
|
||||||
|
vector, file, opaque, any.
|
||||||
|
|
||||||
Sets are initialized by listing elements enclosed by curly braces:
|
Sets can be initialized by listing elements enclosed by curly braces:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
global s: set[port] = { 21/tcp, 23/tcp, 80/tcp, 443/tcp };
|
global s: set[port] = { 21/tcp, 23/tcp, 80/tcp, 443/tcp };
|
||||||
global s2: set[port, string] = { [21/tcp, "ftp"], [23/tcp, "telnet"] };
|
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.
|
|
||||||
|
|
||||||
A set constructor (equivalent to above example) can also be used to
|
A set constructor (equivalent to above example) can also be used to
|
||||||
create a set:
|
create a set:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
global s3: set[port] = set(21/tcp, 23/tcp, 80/tcp, 443/tcp);
|
global s3 = set(21/tcp, 23/tcp, 80/tcp, 443/tcp);
|
||||||
|
|
||||||
Set constructors can also be explicitly named by a type, which is
|
Set constructors can also be explicitly named by a type, which is
|
||||||
useful for when a more complex index type could otherwise be
|
useful when a more complex index type could otherwise be
|
||||||
ambiguous:
|
ambiguous:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
@ -465,18 +484,10 @@ The Bro scripting language supports the following built-in types.
|
||||||
if ( 21/tcp in s )
|
if ( 21/tcp in s )
|
||||||
...
|
...
|
||||||
|
|
||||||
if ( 21/tcp !in s )
|
if ( [21/tcp, "ftp"] !in s2 )
|
||||||
...
|
...
|
||||||
|
|
||||||
Iterate over a set with a ``for`` loop:
|
Elements are added with :bro:keyword:`add`:
|
||||||
|
|
||||||
.. code:: bro
|
|
||||||
|
|
||||||
local s: set[port];
|
|
||||||
for ( p in s )
|
|
||||||
...
|
|
||||||
|
|
||||||
Elements are added with ``add``:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
|
@ -485,7 +496,7 @@ The Bro scripting language supports the following built-in types.
|
||||||
Nothing happens if the element with value ``22/tcp`` was already present in
|
Nothing happens if the element with value ``22/tcp`` was already present in
|
||||||
the set.
|
the set.
|
||||||
|
|
||||||
And removed with ``delete``:
|
And removed with :bro:keyword:`delete`:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
|
@ -501,6 +512,9 @@ The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
|s|
|
|s|
|
||||||
|
|
||||||
|
See the :bro:keyword:`for` statement for info on how to iterate over
|
||||||
|
the elements in a set.
|
||||||
|
|
||||||
.. bro:type:: vector
|
.. bro:type:: vector
|
||||||
|
|
||||||
A vector is like a :bro:type:`table`, except it's always indexed by a
|
A vector is like a :bro:type:`table`, except it's always indexed by a
|
||||||
|
@ -515,7 +529,7 @@ The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
global v: vector of string = vector("one", "two", "three");
|
local v = vector("one", "two", "three");
|
||||||
|
|
||||||
Vector constructors can also be explicitly named by a type, which
|
Vector constructors can also be explicitly named by a type, which
|
||||||
is useful for when a more complex yield type could otherwise be
|
is useful for when a more complex yield type could otherwise be
|
||||||
|
@ -539,14 +553,6 @@ The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
print v[2];
|
print v[2];
|
||||||
|
|
||||||
Iterate over a vector with a ``for`` loop:
|
|
||||||
|
|
||||||
.. code:: bro
|
|
||||||
|
|
||||||
local v: vector of string;
|
|
||||||
for ( n in v )
|
|
||||||
...
|
|
||||||
|
|
||||||
An element can be added to a vector by assigning the value (a value
|
An element can be added to a vector by assigning the value (a value
|
||||||
that already exists at that index will be overwritten):
|
that already exists at that index will be overwritten):
|
||||||
|
|
||||||
|
@ -577,11 +583,17 @@ The Bro scripting language supports the following built-in types.
|
||||||
The resulting vector of bool is the logical "and" (or logical "or") of
|
The resulting vector of bool is the logical "and" (or logical "or") of
|
||||||
each element of the operand vectors.
|
each element of the operand vectors.
|
||||||
|
|
||||||
|
See the :bro:keyword:`for` statement for info on how to iterate over
|
||||||
|
the elements in a vector.
|
||||||
|
|
||||||
.. bro:type:: record
|
.. bro:type:: record
|
||||||
|
|
||||||
A ``record`` is a collection of values. Each value has a field name
|
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
|
and a type. Values do not need to have the same type and the types
|
||||||
have no restrictions. An example record type definition:
|
have no restrictions. Field names must follow the same syntax as
|
||||||
|
regular variable names (except that field names are allowed to be the
|
||||||
|
same as local or global variables). An example record type
|
||||||
|
definition:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
|
@ -590,85 +602,44 @@ The Bro scripting language supports the following built-in types.
|
||||||
s: string &optional;
|
s: string &optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
Access to a record field uses the dollar sign (``$``) operator:
|
Records can be initialized or assigned as a whole in three different ways.
|
||||||
|
|
||||||
.. 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
|
When assigning a whole record value, all fields that are not
|
||||||
:bro:attr:`&optional` or have a :bro:attr:`&default` attribute must
|
:bro:attr:`&optional` or have a :bro:attr:`&default` attribute must
|
||||||
be specified.
|
be specified. First, there's a constructor syntax:
|
||||||
|
|
||||||
To test for existence of a field that is :bro:attr:`&optional`, use the
|
|
||||||
``?$`` operator:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
if ( r?$s )
|
local r: MyRecordType = record($c = 7);
|
||||||
...
|
|
||||||
|
|
||||||
Records can also be created using a constructor syntax:
|
|
||||||
|
|
||||||
.. code:: bro
|
|
||||||
|
|
||||||
global r2: MyRecordType = record($c = 7);
|
|
||||||
|
|
||||||
And the constructor can be explicitly named by type, too, which
|
And the constructor can be explicitly named by type, too, which
|
||||||
is arguably more readable code:
|
is arguably more readable:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
global r3 = MyRecordType($c = 42);
|
local r = MyRecordType($c = 42);
|
||||||
|
|
||||||
.. bro:type:: opaque
|
And the third way is like this:
|
||||||
|
|
||||||
A data type whose actual representation/implementation is
|
|
||||||
intentionally hidden, but whose values may be passed to certain
|
|
||||||
functions that can actually access the internal/hidden resources.
|
|
||||||
Opaque types are differentiated from each other by qualifying them
|
|
||||||
like ``opaque of md5`` or ``opaque of sha1``. Any valid identifier
|
|
||||||
can be used as the type qualifier.
|
|
||||||
|
|
||||||
An example use of this type is the set of built-in functions which
|
|
||||||
perform hashing:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
local handle: opaque of md5 = md5_hash_init();
|
local r: MyRecordType = [$c = 13, $s = "thirteen"];
|
||||||
md5_hash_update(handle, "test");
|
|
||||||
md5_hash_update(handle, "testing");
|
|
||||||
print md5_hash_finish(handle);
|
|
||||||
|
|
||||||
Here the opaque type is used to provide a handle to a particular
|
Access to a record field uses the dollar sign (``$``) operator, and
|
||||||
resource which is calculating an MD5 checksum incrementally over
|
record fields can be assigned with this:
|
||||||
time, but the details of that resource aren't relevant, it's only
|
|
||||||
necessary to have a handle as a way of identifying it and
|
|
||||||
distinguishing it from other such resources.
|
|
||||||
|
|
||||||
.. bro:type:: file
|
|
||||||
|
|
||||||
Bro supports writing to files, but not reading from them. Files
|
|
||||||
can be opened using either the :bro:id:`open` or :bro:id:`open_for_append`
|
|
||||||
built-in functions, and closed using the :bro:id:`close` built-in
|
|
||||||
function. For example, declare, open, and write to a file
|
|
||||||
and finally close it like:
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
global f: file = open("myfile");
|
local r: MyRecordType;
|
||||||
print f, "hello, world";
|
r$c = 13;
|
||||||
close(f);
|
|
||||||
|
|
||||||
Writing to files like this for logging usually isn't recommended, for better
|
To test if a field that is :bro:attr:`&optional` has been assigned a
|
||||||
logging support see :doc:`/frameworks/logging`.
|
value, use the ``?$`` operator (it returns a :bro:type:`bool` value of
|
||||||
|
``T`` if the field has been assigned a value, or ``F`` if not):
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
if ( r ?$ s )
|
||||||
|
...
|
||||||
|
|
||||||
.. bro:type:: function
|
.. bro:type:: function
|
||||||
|
|
||||||
|
@ -700,6 +671,16 @@ The Bro scripting language supports the following built-in types.
|
||||||
type, but when it is, the return type and argument list (including the
|
type, but when it is, the return type and argument list (including the
|
||||||
name of each argument) must match exactly.
|
name of each argument) must match exactly.
|
||||||
|
|
||||||
|
Here is an example function that takes no parameters and does not
|
||||||
|
return a value:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
function my_func()
|
||||||
|
{
|
||||||
|
print "my_func";
|
||||||
|
}
|
||||||
|
|
||||||
Function types don't need to have a name and can be assigned anonymously:
|
Function types don't need to have a name and can be assigned anonymously:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
@ -742,9 +723,20 @@ The Bro scripting language supports the following built-in types.
|
||||||
Event handlers are nearly identical in both syntax and semantics to
|
Event handlers are nearly identical in both syntax and semantics to
|
||||||
a :bro:type:`function`, with the two differences being that event
|
a :bro:type:`function`, with the two differences being that event
|
||||||
handlers have no return type since they never return a value, and
|
handlers have no return type since they never return a value, and
|
||||||
you cannot call an event handler. Instead of directly calling an
|
you cannot call an event handler.
|
||||||
event handler from a script, event handler bodies are executed when
|
|
||||||
they are invoked by one of three different methods:
|
Example:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
event my_event(r: bool, s: string)
|
||||||
|
{
|
||||||
|
print "my_event", r, s;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
- From the event engine
|
||||||
|
|
||||||
|
@ -765,7 +757,7 @@ The Bro scripting language supports the following built-in types.
|
||||||
This assumes that ``password_exposed`` was previously declared
|
This assumes that ``password_exposed`` was previously declared
|
||||||
as an event handler type with compatible arguments.
|
as an event handler type with compatible arguments.
|
||||||
|
|
||||||
- Via the ``schedule`` expression in a script
|
- Via the :bro:keyword:`schedule` expression in a script
|
||||||
|
|
||||||
This delays the invocation of event handlers until some time in
|
This delays the invocation of event handlers until some time in
|
||||||
the future. For example:
|
the future. For example:
|
||||||
|
@ -789,8 +781,8 @@ The Bro scripting language supports the following built-in types.
|
||||||
immediate and they do not get scheduled through an event queue.
|
immediate and they do not get scheduled through an event queue.
|
||||||
Also, a unique feature of a hook is that a given hook handler body
|
Also, a unique feature of a hook is that a given hook handler body
|
||||||
can short-circuit the execution of remaining hook handlers simply by
|
can short-circuit the execution of remaining hook handlers simply by
|
||||||
exiting from the body as a result of a ``break`` statement (as
|
exiting from the body as a result of a :bro:keyword:`break` statement (as
|
||||||
opposed to a ``return`` or just reaching the end of the body).
|
opposed to a :bro:keyword:`return` or just reaching the end of the body).
|
||||||
|
|
||||||
A hook type is declared like::
|
A hook type is declared like::
|
||||||
|
|
||||||
|
@ -859,142 +851,60 @@ The Bro scripting language supports the following built-in types.
|
||||||
executed due to one handler body exiting as a result of a ``break``
|
executed due to one handler body exiting as a result of a ``break``
|
||||||
statement.
|
statement.
|
||||||
|
|
||||||
Attributes
|
.. bro:type:: file
|
||||||
----------
|
|
||||||
|
|
||||||
Attributes occur at the end of type/event declarations and change their
|
Bro supports writing to files, but not reading from them (to read from
|
||||||
behavior. The syntax is ``&key`` or ``&key=val``, e.g., ``type T:
|
files see the :doc:`/frameworks/input`). Files
|
||||||
set[count] &read_expire=5min`` or ``event foo() &priority=-3``. The Bro
|
can be opened using either the :bro:id:`open` or :bro:id:`open_for_append`
|
||||||
scripting language supports the following built-in attributes.
|
built-in functions, and closed using the :bro:id:`close` built-in
|
||||||
|
function. For example, declare, open, and write to a file and finally
|
||||||
|
close it like:
|
||||||
|
|
||||||
.. bro:attr:: &optional
|
.. code:: bro
|
||||||
|
|
||||||
Allows a record field to be missing. For example the type ``record {
|
local f = open("myfile");
|
||||||
a: addr; b: port &optional; }`` could be instantiated both as
|
print f, "hello, world";
|
||||||
singleton ``[$a=127.0.0.1]`` or pair ``[$a=127.0.0.1, $b=80/tcp]``.
|
close(f);
|
||||||
|
|
||||||
.. bro:attr:: &default
|
Writing to files like this for logging usually isn't recommended, for better
|
||||||
|
logging support see :doc:`/frameworks/logging`.
|
||||||
|
|
||||||
Uses a default value for a record field, a function/hook/event
|
.. bro:type:: opaque
|
||||||
parameter, or container elements. For example, ``table[int] of
|
|
||||||
string &default="foo"`` would create a table that returns the
|
|
||||||
:bro:type:`string` ``"foo"`` for any non-existing index.
|
|
||||||
|
|
||||||
.. bro:attr:: &redef
|
A data type whose actual representation/implementation is
|
||||||
|
intentionally hidden, but whose values may be passed to certain
|
||||||
|
built-in functions that can actually access the internal/hidden resources.
|
||||||
|
Opaque types are differentiated from each other by qualifying them
|
||||||
|
like "opaque of md5" or "opaque of sha1".
|
||||||
|
|
||||||
Allows for redefinition of initial object values. This is typically
|
An example use of this type is the set of built-in functions which
|
||||||
used with constants, for example, ``const clever = T &redef;`` would
|
perform hashing:
|
||||||
allow the constant to be redefined at some later point during script
|
|
||||||
execution.
|
|
||||||
|
|
||||||
.. bro:attr:: &rotate_interval
|
.. code:: bro
|
||||||
|
|
||||||
Rotates a file after a specified interval.
|
local handle = md5_hash_init();
|
||||||
|
md5_hash_update(handle, "test");
|
||||||
|
md5_hash_update(handle, "testing");
|
||||||
|
print md5_hash_finish(handle);
|
||||||
|
|
||||||
.. bro:attr:: &rotate_size
|
Here the opaque type is used to provide a handle to a particular
|
||||||
|
resource which is calculating an MD5 hash incrementally over
|
||||||
|
time, but the details of that resource aren't relevant, it's only
|
||||||
|
necessary to have a handle as a way of identifying it and
|
||||||
|
distinguishing it from other such resources.
|
||||||
|
|
||||||
Rotates a file after it has reached a given size in bytes.
|
.. bro:type:: any
|
||||||
|
|
||||||
.. bro:attr:: &add_func
|
Used to bypass strong typing. For example, a function can take an
|
||||||
|
argument of type ``any`` when it may be of different types.
|
||||||
|
The only operation allowed on a variable of type ``any`` is assignment.
|
||||||
|
|
||||||
Can be applied to an identifier with &redef to specify a function to
|
Note that users aren't expected to use this type. It's provided mainly
|
||||||
be called any time a "redef <id> += ..." declaration is parsed. The
|
for use by some built-in functions and scripts included with Bro.
|
||||||
function takes two arguments of the same type as the identifier, the first
|
|
||||||
being the old value of the variable and the second being the new
|
|
||||||
value given after the "+=" operator in the "redef" declaration. The
|
|
||||||
return value of the function will be the actual new value of the
|
|
||||||
variable after the "redef" declaration is parsed.
|
|
||||||
|
|
||||||
.. bro:attr:: &delete_func
|
.. bro:type:: void
|
||||||
|
|
||||||
Same as &add_func, except for "redef" declarations that use the "-="
|
An internal Bro type (i.e., "void" is not a reserved keyword in the Bro
|
||||||
operator.
|
scripting language) representing the absence of a return type for a
|
||||||
|
function.
|
||||||
|
|
||||||
.. bro:attr:: &expire_func
|
|
||||||
|
|
||||||
Called right before a container element expires. The function's
|
|
||||||
first parameter is of the same type of the container and the second
|
|
||||||
parameter the same type of the container's index. The return
|
|
||||||
value is an :bro:type:`interval` indicating the amount of additional
|
|
||||||
time to wait before expiring the container element at the given
|
|
||||||
index (which will trigger another execution of this function).
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
Makes a variable persistent, i.e., its value is written to disk (per
|
|
||||||
default at shutdown time).
|
|
||||||
|
|
||||||
.. 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:: &encrypt
|
|
||||||
|
|
||||||
Encrypts files right before writing them to disk.
|
|
||||||
|
|
||||||
.. TODO: needs to be documented in more detail.
|
|
||||||
|
|
||||||
.. bro:attr:: &raw_output
|
|
||||||
|
|
||||||
Opens a file in raw mode, i.e., non-ASCII characters are not
|
|
||||||
escaped.
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
|
|
||||||
Specifies the execution priority (as a signed integer) of a hook or
|
|
||||||
event handler. Higher values are executed before lower ones. The
|
|
||||||
default value is 0.
|
|
||||||
|
|
||||||
.. bro:attr:: &group
|
|
||||||
|
|
||||||
Groups event handlers such that those in the same group can be
|
|
||||||
jointly activated or deactivated.
|
|
||||||
|
|
||||||
.. bro:attr:: &log
|
|
||||||
|
|
||||||
Writes a record field to the associated log stream.
|
|
||||||
|
|
||||||
.. bro:attr:: &error_handler
|
|
||||||
|
|
||||||
Internally set on the events that are associated with the reporter
|
|
||||||
framework: :bro:id:`reporter_info`, :bro:id:`reporter_warning`, and
|
|
||||||
:bro:id:`reporter_error`. It prevents any handlers of those events
|
|
||||||
from being able to generate reporter messages that go through any of
|
|
||||||
those events (i.e., it prevents an infinite event recursion). Instead,
|
|
||||||
such nested reporter messages are output to stderr.
|
|
||||||
|
|
||||||
.. bro:attr:: &type_column
|
|
||||||
|
|
||||||
Used by the input framework. It can be used on columns of type
|
|
||||||
:bro:type:`port` and specifies the name of an additional column in
|
|
||||||
the input file which specifies the protocol of the port (tcp/udp/icmp).
|
|
|
@ -4,7 +4,7 @@ type Service: record {
|
||||||
rfc: count;
|
rfc: count;
|
||||||
};
|
};
|
||||||
|
|
||||||
function print_service(serv: Service): string
|
function print_service(serv: Service)
|
||||||
{
|
{
|
||||||
print fmt("Service: %s(RFC%d)",serv$name, serv$rfc);
|
print fmt("Service: %s(RFC%d)",serv$name, serv$rfc);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ type System: record {
|
||||||
services: set[Service];
|
services: set[Service];
|
||||||
};
|
};
|
||||||
|
|
||||||
function print_service(serv: Service): string
|
function print_service(serv: Service)
|
||||||
{
|
{
|
||||||
print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc);
|
print fmt(" Service: %s(RFC%d)",serv$name, serv$rfc);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ function print_service(serv: Service): string
|
||||||
print fmt(" port: %s", p);
|
print fmt(" port: %s", p);
|
||||||
}
|
}
|
||||||
|
|
||||||
function print_system(sys: System): string
|
function print_system(sys: System)
|
||||||
{
|
{
|
||||||
print fmt("System: %s", sys$name);
|
print fmt("System: %s", sys$name);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,6 @@ event bro_init()
|
||||||
|
|
||||||
print fmt("contents of v1: %s", v1);
|
print fmt("contents of v1: %s", v1);
|
||||||
print fmt("length of v1: %d", |v1|);
|
print fmt("length of v1: %d", |v1|);
|
||||||
print fmt("contents of v1: %s", v2);
|
print fmt("contents of v2: %s", v2);
|
||||||
print fmt("length of v2: %d", |v2|);
|
print fmt("length of v2: %d", |v2|);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
event bro_init()
|
event bro_init()
|
||||||
{
|
{
|
||||||
local test_string = "The quick brown fox jumped over the lazy dog.";
|
local test_string = "The quick brown fox jumps over the lazy dog.";
|
||||||
local test_pattern = /quick|lazy/;
|
local test_pattern = /quick|lazy/;
|
||||||
|
|
||||||
if ( test_pattern in test_string )
|
if ( test_pattern in test_string )
|
||||||
|
|
|
@ -23,7 +23,7 @@ function factorial(n: count): count
|
||||||
event bro_init()
|
event bro_init()
|
||||||
{
|
{
|
||||||
# Create the logging stream.
|
# Create the logging stream.
|
||||||
Log::create_stream(LOG, [$columns=Info]);
|
Log::create_stream(LOG, [$columns=Info, $path="factor"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
event bro_done()
|
event bro_done()
|
||||||
|
|
|
@ -37,7 +37,7 @@ function mod5(id: Log::ID, path: string, rec: Factor::Info) : string
|
||||||
|
|
||||||
event bro_init()
|
event bro_init()
|
||||||
{
|
{
|
||||||
Log::create_stream(LOG, [$columns=Info]);
|
Log::create_stream(LOG, [$columns=Info, $path="factor"]);
|
||||||
|
|
||||||
local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5];
|
local filter: Log::Filter = [$name="split-mod5s", $path_func=mod5];
|
||||||
Log::add_filter(Factor::LOG, filter);
|
Log::add_filter(Factor::LOG, filter);
|
||||||
|
|
|
@ -22,7 +22,7 @@ function factorial(n: count): count
|
||||||
|
|
||||||
event bro_init()
|
event bro_init()
|
||||||
{
|
{
|
||||||
Log::create_stream(LOG, [$columns=Info, $ev=log_factor]);
|
Log::create_stream(LOG, [$columns=Info, $ev=log_factor, $path="factor"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
event bro_done()
|
event bro_done()
|
||||||
|
|
|
@ -103,9 +103,9 @@ In the ``file_hash`` event handler, there is an ``if`` statement that is used
|
||||||
to check for the correct type of hash, in this case
|
to check for the correct type of hash, in this case
|
||||||
a SHA1 hash. It also checks for a mime type we've defined as
|
a SHA1 hash. It also checks for a mime type we've defined as
|
||||||
being of interest as defined in the constant ``match_file_types``.
|
being of interest as defined in the constant ``match_file_types``.
|
||||||
The comparison is made against the expression ``f$mime_type``, which uses
|
The comparison is made against the expression ``f$info$mime_type``, which uses
|
||||||
the ``$`` dereference operator to check the value ``mime_type``
|
the ``$`` dereference operator to check the value ``mime_type``
|
||||||
inside the variable ``f``. If the entire expression evaluates to true,
|
inside the variable ``f$info``. If the entire expression evaluates to true,
|
||||||
then a helper function is called to do the rest of the work. In that
|
then a helper function is called to do the rest of the work. In that
|
||||||
function, a local variable is defined to hold a string comprised of
|
function, a local variable is defined to hold a string comprised of
|
||||||
the SHA1 hash concatenated with ``.malware.hash.cymru.com``; this
|
the SHA1 hash concatenated with ``.malware.hash.cymru.com``; this
|
||||||
|
@ -260,7 +260,7 @@ originating host is referenced by ``c$id$orig_h`` which if given a
|
||||||
narrative relates to ``orig_h`` which is a member of ``id`` which is
|
narrative relates to ``orig_h`` which is a member of ``id`` which is
|
||||||
a member of the data structure referred to as ``c`` that was passed
|
a member of the data structure referred to as ``c`` that was passed
|
||||||
into the event handler. Given that the responder port
|
into the event handler. Given that the responder port
|
||||||
``c$id$resp_p`` is ``53/tcp``, it's likely that Bro's base HTTP scripts
|
``c$id$resp_p`` is ``80/tcp``, it's likely that Bro's base HTTP scripts
|
||||||
can further populate the connection record. Let's load the
|
can further populate the connection record. Let's load the
|
||||||
``base/protocols/http`` scripts and check the output of our script.
|
``base/protocols/http`` scripts and check the output of our script.
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ decrypted from HTTP streams is stored in
|
||||||
excerpt from :doc:`/scripts/base/protocols/http/main.bro` below.
|
excerpt from :doc:`/scripts/base/protocols/http/main.bro` below.
|
||||||
|
|
||||||
.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/http/main.bro
|
.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/http/main.bro
|
||||||
:lines: 9-11,20-22,121
|
:lines: 9-11,20-22,125
|
||||||
|
|
||||||
Because the constant was declared with the ``&redef`` attribute, if we
|
Because the constant was declared with the ``&redef`` attribute, if we
|
||||||
needed to turn this option on globally, we could do so by adding the
|
needed to turn this option on globally, we could do so by adding the
|
||||||
|
@ -826,7 +826,7 @@ example of the ``record`` data type in the earlier sections, the
|
||||||
``conn.log``, is shown by the excerpt below.
|
``conn.log``, is shown by the excerpt below.
|
||||||
|
|
||||||
.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/conn/main.bro
|
.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/conn/main.bro
|
||||||
:lines: 10-12,16-17,19,21,23,25,28,31,35,38,57,63,69,92,95,99,102,106,110-111,116
|
:lines: 10-12,16-17,19,21,23,25,28,31,35,38,57,63,69,75,98,101,105,108,112,116-117,122
|
||||||
|
|
||||||
Looking at the structure of the definition, a new collection of data
|
Looking at the structure of the definition, a new collection of data
|
||||||
types is being defined as a type called ``Info``. Since this type
|
types is being defined as a type called ``Info``. Since this type
|
||||||
|
|
5
man/CMakeLists.txt
Normal file
5
man/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
install(DIRECTORY . DESTINATION ${BRO_MAN_INSTALL_PATH}/man8 FILES_MATCHING
|
||||||
|
PATTERN "*.8"
|
||||||
|
)
|
||||||
|
|
165
man/bro.8
Normal file
165
man/bro.8
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
.TH BRO "8" "November 2014" "bro" "System Administration Utilities"
|
||||||
|
.SH NAME
|
||||||
|
bro \- passive network traffic analyzer
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B bro
|
||||||
|
\/\fP [\fIoptions\fR] [\fIfile\fR ...]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
Bro is primarily a security monitor that inspects all traffic on a link in
|
||||||
|
depth for signs of suspicious activity. More generally, however, Bro
|
||||||
|
supports a wide range of traffic analysis tasks even outside of the
|
||||||
|
security domain, including performance measurements and helping with
|
||||||
|
trouble-shooting.
|
||||||
|
|
||||||
|
Bro comes with built-in functionality for a range of analysis and detection
|
||||||
|
tasks, including detecting malware by interfacing to external registries,
|
||||||
|
reporting vulnerable versions of software seen on the network, identifying
|
||||||
|
popular web applications, detecting SSH brute-forcing, validating SSL
|
||||||
|
certificate chains, among others.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B <file>
|
||||||
|
policy file, or read stdin
|
||||||
|
.TP
|
||||||
|
\fB\-a\fR,\ \-\-parse\-only
|
||||||
|
exit immediately after parsing scripts
|
||||||
|
.TP
|
||||||
|
\fB\-b\fR,\ \-\-bare\-mode
|
||||||
|
don't load scripts from the base/ directory
|
||||||
|
.TP
|
||||||
|
\fB\-d\fR,\ \-\-debug\-policy
|
||||||
|
activate policy file debugging
|
||||||
|
.TP
|
||||||
|
\fB\-e\fR,\ \-\-exec <bro code>
|
||||||
|
augment loaded policies by given code
|
||||||
|
.TP
|
||||||
|
\fB\-f\fR,\ \-\-filter <filter>
|
||||||
|
tcpdump filter
|
||||||
|
.TP
|
||||||
|
\fB\-g\fR,\ \-\-dump\-config
|
||||||
|
dump current config into .state dir
|
||||||
|
.TP
|
||||||
|
\fB\-h\fR,\ \-\-help|\-?
|
||||||
|
command line help
|
||||||
|
.TP
|
||||||
|
\fB\-i\fR,\ \-\-iface <interface>
|
||||||
|
read from given interface
|
||||||
|
.TP
|
||||||
|
\fB\-p\fR,\ \-\-prefix <prefix>
|
||||||
|
add given prefix to policy file resolution
|
||||||
|
.TP
|
||||||
|
\fB\-r\fR,\ \-\-readfile <readfile>
|
||||||
|
read from given tcpdump file
|
||||||
|
.TP
|
||||||
|
\fB\-s\fR,\ \-\-rulefile <rulefile>
|
||||||
|
read rules from given file
|
||||||
|
.TP
|
||||||
|
\fB\-t\fR,\ \-\-tracefile <tracefile>
|
||||||
|
activate execution tracing
|
||||||
|
.TP
|
||||||
|
\fB\-w\fR,\ \-\-writefile <writefile>
|
||||||
|
write to given tcpdump file
|
||||||
|
.TP
|
||||||
|
\fB\-v\fR,\ \-\-version
|
||||||
|
print version and exit
|
||||||
|
.TP
|
||||||
|
\fB\-x\fR,\ \-\-print\-state <file.bst>
|
||||||
|
print contents of state file
|
||||||
|
.TP
|
||||||
|
\fB\-z\fR,\ \-\-analyze <analysis>
|
||||||
|
run the specified policy file analysis
|
||||||
|
.TP
|
||||||
|
\fB\-C\fR,\ \-\-no\-checksums
|
||||||
|
ignore checksums
|
||||||
|
.TP
|
||||||
|
\fB\-F\fR,\ \-\-force\-dns
|
||||||
|
force DNS
|
||||||
|
.TP
|
||||||
|
\fB\-I\fR,\ \-\-print\-id <ID name>
|
||||||
|
print out given ID
|
||||||
|
.TP
|
||||||
|
\fB\-J\fR,\ \-\-set\-seed <seed>
|
||||||
|
set the random number seed
|
||||||
|
.TP
|
||||||
|
\fB\-K\fR,\ \-\-md5\-hashkey <hashkey>
|
||||||
|
set key for MD5\-keyed hashing
|
||||||
|
.TP
|
||||||
|
\fB\-N\fR,\ \-\-print\-plugins
|
||||||
|
print available plugins and exit (\fB\-NN\fR for verbose)
|
||||||
|
.TP
|
||||||
|
\fB\-P\fR,\ \-\-prime\-dns
|
||||||
|
prime DNS
|
||||||
|
.TP
|
||||||
|
\fB\-Q\fR,\ \-\-time
|
||||||
|
print execution time summary to stderr
|
||||||
|
.TP
|
||||||
|
\fB\-R\fR,\ \-\-replay <events.bst>
|
||||||
|
replay events
|
||||||
|
.TP
|
||||||
|
\fB\-S\fR,\ \-\-debug\-rules
|
||||||
|
enable rule debugging
|
||||||
|
.TP
|
||||||
|
\fB\-T\fR,\ \-\-re\-level <level>
|
||||||
|
set 'RE_level' for rules
|
||||||
|
.TP
|
||||||
|
\fB\-U\fR,\ \-\-status\-file <file>
|
||||||
|
Record process status in file
|
||||||
|
.TP
|
||||||
|
\fB\-W\fR,\ \-\-watchdog
|
||||||
|
activate watchdog timer
|
||||||
|
.TP
|
||||||
|
\fB\-X\fR,\ \-\-broxygen <cfgfile>
|
||||||
|
generate documentation based on config file
|
||||||
|
.TP
|
||||||
|
\fB\-\-pseudo\-realtime[=\fR<speedup>]
|
||||||
|
enable pseudo\-realtime for performance evaluation (default 1)
|
||||||
|
.TP
|
||||||
|
\fB\-\-load\-seeds\fR <file>
|
||||||
|
load seeds from given file
|
||||||
|
.TP
|
||||||
|
\fB\-\-save\-seeds\fR <file>
|
||||||
|
save seeds to given file
|
||||||
|
.TP
|
||||||
|
The following option is available only when Bro is built with the \-\-enable\-debug configure option:
|
||||||
|
.TP
|
||||||
|
\fB\-B\fR,\ \-\-debug <dbgstreams>
|
||||||
|
Enable debugging output for selected streams ('-B help' for help)
|
||||||
|
.TP
|
||||||
|
The following options are available only when Bro is built with gperftools support (use the \-\-enable\-perftools and \-\-enable\-perftools\-debug configure options):
|
||||||
|
.TP
|
||||||
|
\fB\-m\fR,\ \-\-mem-leaks
|
||||||
|
show leaks
|
||||||
|
.TP
|
||||||
|
\fB\-M\fR,\ \-\-mem-profile
|
||||||
|
record heap
|
||||||
|
.SH ENVIRONMENT
|
||||||
|
.TP
|
||||||
|
.B BROPATH
|
||||||
|
file search path
|
||||||
|
.TP
|
||||||
|
.B BRO_PLUGIN_PATH
|
||||||
|
plugin search path
|
||||||
|
.TP
|
||||||
|
.B BRO_PLUGIN_ACTIVATE
|
||||||
|
plugins to always activate
|
||||||
|
.TP
|
||||||
|
.B BRO_PREFIXES
|
||||||
|
prefix list
|
||||||
|
.TP
|
||||||
|
.B BRO_DNS_FAKE
|
||||||
|
disable DNS lookups
|
||||||
|
.TP
|
||||||
|
.B BRO_SEED_FILE
|
||||||
|
file to load seeds from
|
||||||
|
.TP
|
||||||
|
.B BRO_LOG_SUFFIX
|
||||||
|
ASCII log file extension
|
||||||
|
.TP
|
||||||
|
.B BRO_PROFILER_FILE
|
||||||
|
Output file for script execution statistics
|
||||||
|
.TP
|
||||||
|
.B BRO_DISABLE_BROXYGEN
|
||||||
|
Disable Broxygen documentation support
|
||||||
|
.SH AUTHOR
|
||||||
|
.B bro
|
||||||
|
was written by The Bro Project <info@bro.org>.
|
|
@ -1,14 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# CMake/CPack versions before 2.8.3 have bugs that can create bad packages
|
|
||||||
# Since packages will be built on several different systems, a single
|
|
||||||
# version of CMake is required to obtain consistency, but can be increased
|
|
||||||
# as new versions of CMake come out that also produce working packages.
|
|
||||||
|
|
||||||
CMAKE_PACK_REQ="cmake version 2.8.6"
|
|
||||||
CMAKE_VER=`cmake -version`
|
|
||||||
|
|
||||||
if [ "${CMAKE_VER}" != "${CMAKE_PACK_REQ}" ]; then
|
|
||||||
echo "Package creation requires ${CMAKE_PACK_REQ}" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
|
@ -3,8 +3,6 @@
|
||||||
# This script generates binary DEB packages.
|
# This script generates binary DEB packages.
|
||||||
# They can be found in ../build/ after running.
|
# They can be found in ../build/ after running.
|
||||||
|
|
||||||
./check-cmake || { exit 1; }
|
|
||||||
|
|
||||||
# The DEB CPack generator depends on `dpkg-shlibdeps` to automatically
|
# The DEB CPack generator depends on `dpkg-shlibdeps` to automatically
|
||||||
# determine what dependencies to set for the packages
|
# determine what dependencies to set for the packages
|
||||||
type dpkg-shlibdeps > /dev/null 2>&1 || {
|
type dpkg-shlibdeps > /dev/null 2>&1 || {
|
||||||
|
@ -16,6 +14,7 @@ the 'dpkg-dev' package, please install it first.
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix=/opt/bro
|
prefix=/opt/bro
|
||||||
|
localstatedir=/var/opt/bro
|
||||||
|
|
||||||
# During the packaging process, `dpkg-shlibs` will fail if used on a library
|
# During the packaging process, `dpkg-shlibs` will fail if used on a library
|
||||||
# that links to other internal/project libraries unless an RPATH is used or
|
# that links to other internal/project libraries unless an RPATH is used or
|
||||||
|
@ -31,7 +30,7 @@ cd ..
|
||||||
( cd build && make package )
|
( cd build && make package )
|
||||||
|
|
||||||
# Full Bro package
|
# Full Bro package
|
||||||
./configure --prefix=${prefix} --pkg-name-prefix=Bro --binary-package
|
./configure --prefix=${prefix} --localstatedir=${localstatedir} --pkg-name-prefix=Bro --binary-package
|
||||||
( cd build && make package )
|
( cd build && make package )
|
||||||
|
|
||||||
# Broccoli
|
# Broccoli
|
||||||
|
@ -42,6 +41,6 @@ cd ../..
|
||||||
|
|
||||||
# Broctl
|
# Broctl
|
||||||
cd aux/broctl
|
cd aux/broctl
|
||||||
./configure --prefix=${prefix} --binary-package
|
./configure --prefix=${prefix} --localstatedir=${localstatedir} --binary-package
|
||||||
( cd build && make package && mv *.deb ../../../build/ )
|
( cd build && make package && mv *.deb ../../../build/ )
|
||||||
cd ../..
|
cd ../..
|
||||||
|
|
|
@ -3,14 +3,6 @@
|
||||||
# This script creates binary packages for Mac OS X.
|
# This script creates binary packages for Mac OS X.
|
||||||
# They can be found in ../build/ after running.
|
# They can be found in ../build/ after running.
|
||||||
|
|
||||||
cmake -P /dev/stdin << "EOF"
|
|
||||||
if ( ${CMAKE_VERSION} VERSION_LESS 2.8.9 )
|
|
||||||
message(FATAL_ERROR "CMake >= 2.8.9 required to build package")
|
|
||||||
endif ()
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ $? -ne 0 ] && exit 1;
|
|
||||||
|
|
||||||
type sw_vers > /dev/null 2>&1 || {
|
type sw_vers > /dev/null 2>&1 || {
|
||||||
echo "Unable to get Mac OS X version" >&2;
|
echo "Unable to get Mac OS X version" >&2;
|
||||||
exit 1;
|
exit 1;
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
# This script generates binary RPM packages.
|
# This script generates binary RPM packages.
|
||||||
# They can be found in ../build/ after running.
|
# They can be found in ../build/ after running.
|
||||||
|
|
||||||
./check-cmake || { exit 1; }
|
|
||||||
|
|
||||||
# The RPM CPack generator depends on `rpmbuild` to create packages
|
# The RPM CPack generator depends on `rpmbuild` to create packages
|
||||||
type rpmbuild > /dev/null 2>&1 || {
|
type rpmbuild > /dev/null 2>&1 || {
|
||||||
echo "\
|
echo "\
|
||||||
|
@ -15,6 +13,7 @@ the 'rpm-build' package, please install it first.
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix=/opt/bro
|
prefix=/opt/bro
|
||||||
|
localstatedir=/var/opt/bro
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
|
@ -24,7 +23,7 @@ cd ..
|
||||||
( cd build && make package )
|
( cd build && make package )
|
||||||
|
|
||||||
# Full Bro package
|
# Full Bro package
|
||||||
./configure --prefix=${prefix} --pkg-name-prefix=Bro --binary-package
|
./configure --prefix=${prefix} --localstatedir=${localstatedir} --pkg-name-prefix=Bro --binary-package
|
||||||
( cd build && make package )
|
( cd build && make package )
|
||||||
|
|
||||||
# Broccoli
|
# Broccoli
|
||||||
|
@ -35,6 +34,6 @@ cd ../..
|
||||||
|
|
||||||
# Broctl
|
# Broctl
|
||||||
cd aux/broctl
|
cd aux/broctl
|
||||||
./configure --prefix=${prefix} --binary-package
|
./configure --prefix=${prefix} --localstatedir=${localstatedir} --binary-package
|
||||||
( cd build && make package && mv *.rpm ../../../build/ )
|
( cd build && make package && mv *.rpm ../../../build/ )
|
||||||
cd ../..
|
cd ../..
|
||||||
|
|
|
@ -53,7 +53,8 @@ function set_limit(f: fa_file, args: Files::AnalyzerArgs, n: count): bool
|
||||||
function on_add(f: fa_file, args: Files::AnalyzerArgs)
|
function on_add(f: fa_file, args: Files::AnalyzerArgs)
|
||||||
{
|
{
|
||||||
if ( ! args?$extract_filename )
|
if ( ! args?$extract_filename )
|
||||||
args$extract_filename = cat("extract-", f$source, "-", f$id);
|
args$extract_filename = cat("extract-", f$last_active, "-", f$source,
|
||||||
|
"-", f$id);
|
||||||
|
|
||||||
f$info$extracted = args$extract_filename;
|
f$info$extracted = args$extract_filename;
|
||||||
args$extract_filename = build_path_compressed(prefix, args$extract_filename);
|
args$extract_filename = build_path_compressed(prefix, args$extract_filename);
|
||||||
|
|
1
scripts/base/files/pe/README
Normal file
1
scripts/base/files/pe/README
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Support for Portable Executable (PE) file analysis.
|
2
scripts/base/files/pe/__load__.bro
Normal file
2
scripts/base/files/pe/__load__.bro
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
@load ./consts
|
||||||
|
@load ./main
|
184
scripts/base/files/pe/consts.bro
Normal file
184
scripts/base/files/pe/consts.bro
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
|
||||||
|
module PE;
|
||||||
|
|
||||||
|
export {
|
||||||
|
const machine_types: table[count] of string = {
|
||||||
|
[0x00] = "UNKNOWN",
|
||||||
|
[0x1d3] = "AM33",
|
||||||
|
[0x8664] = "AMD64",
|
||||||
|
[0x1c0] = "ARM",
|
||||||
|
[0x1c4] = "ARMNT",
|
||||||
|
[0xaa64] = "ARM64",
|
||||||
|
[0xebc] = "EBC",
|
||||||
|
[0x14c] = "I386",
|
||||||
|
[0x200] = "IA64",
|
||||||
|
[0x9041] = "M32R",
|
||||||
|
[0x266] = "MIPS16",
|
||||||
|
[0x366] = "MIPSFPU",
|
||||||
|
[0x466] = "MIPSFPU16",
|
||||||
|
[0x1f0] = "POWERPC",
|
||||||
|
[0x1f1] = "POWERPCFP",
|
||||||
|
[0x166] = "R4000",
|
||||||
|
[0x1a2] = "SH3",
|
||||||
|
[0x1a3] = "SH3DSP",
|
||||||
|
[0x1a6] = "SH4",
|
||||||
|
[0x1a8] = "SH5",
|
||||||
|
[0x1c2] = "THUMB",
|
||||||
|
[0x169] = "WCEMIPSV2"
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const file_characteristics: table[count] of string = {
|
||||||
|
[0x1] = "RELOCS_STRIPPED",
|
||||||
|
[0x2] = "EXECUTABLE_IMAGE",
|
||||||
|
[0x4] = "LINE_NUMS_STRIPPED",
|
||||||
|
[0x8] = "LOCAL_SYMS_STRIPPED",
|
||||||
|
[0x10] = "AGGRESSIVE_WS_TRIM",
|
||||||
|
[0x20] = "LARGE_ADDRESS_AWARE",
|
||||||
|
[0x80] = "BYTES_REVERSED_LO",
|
||||||
|
[0x100] = "32BIT_MACHINE",
|
||||||
|
[0x200] = "DEBUG_STRIPPED",
|
||||||
|
[0x400] = "REMOVABLE_RUN_FROM_SWAP",
|
||||||
|
[0x800] = "NET_RUN_FROM_SWAP",
|
||||||
|
[0x1000] = "SYSTEM",
|
||||||
|
[0x2000] = "DLL",
|
||||||
|
[0x4000] = "UP_SYSTEM_ONLY",
|
||||||
|
[0x8000] = "BYTES_REVERSED_HI"
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const dll_characteristics: table[count] of string = {
|
||||||
|
[0x40] = "DYNAMIC_BASE",
|
||||||
|
[0x80] = "FORCE_INTEGRITY",
|
||||||
|
[0x100] = "NX_COMPAT",
|
||||||
|
[0x200] = "NO_ISOLATION",
|
||||||
|
[0x400] = "NO_SEH",
|
||||||
|
[0x800] = "NO_BIND",
|
||||||
|
[0x2000] = "WDM_DRIVER",
|
||||||
|
[0x8000] = "TERMINAL_SERVER_AWARE"
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const windows_subsystems: table[count] of string = {
|
||||||
|
[0] = "UNKNOWN",
|
||||||
|
[1] = "NATIVE",
|
||||||
|
[2] = "WINDOWS_GUI",
|
||||||
|
[3] = "WINDOWS_CUI",
|
||||||
|
[7] = "POSIX_CUI",
|
||||||
|
[9] = "WINDOWS_CE_GUI",
|
||||||
|
[10] = "EFI_APPLICATION",
|
||||||
|
[11] = "EFI_BOOT_SERVICE_DRIVER",
|
||||||
|
[12] = "EFI_RUNTIME_
DRIVER",
|
||||||
|
[13] = "EFI_ROM",
|
||||||
|
[14] = "XBOX"
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const directories: table[count] of string = {
|
||||||
|
[0] = "Export Table",
|
||||||
|
[1] = "Import Table",
|
||||||
|
[2] = "Resource Table",
|
||||||
|
[3] = "Exception Table",
|
||||||
|
[4] = "Certificate Table",
|
||||||
|
[5] = "Base Relocation Table",
|
||||||
|
[6] = "Debug",
|
||||||
|
[7] = "Architecture",
|
||||||
|
[8] = "Global Ptr",
|
||||||
|
[9] = "TLS Table",
|
||||||
|
[10] = "Load Config Table",
|
||||||
|
[11] = "Bound Import",
|
||||||
|
[12] = "IAT",
|
||||||
|
[13] = "Delay Import Descriptor",
|
||||||
|
[14] = "CLR Runtime Header",
|
||||||
|
[15] = "Reserved"
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const section_characteristics: table[count] of string = {
|
||||||
|
[0x8] = "TYPE_NO_PAD",
|
||||||
|
[0x20] = "CNT_CODE",
|
||||||
|
[0x40] = "CNT_INITIALIZED_DATA",
|
||||||
|
[0x80] = "CNT_UNINITIALIZED_DATA",
|
||||||
|
[0x100] = "LNK_OTHER",
|
||||||
|
[0x200] = "LNK_INFO",
|
||||||
|
[0x800] = "LNK_REMOVE",
|
||||||
|
[0x1000] = "LNK_COMDAT",
|
||||||
|
[0x8000] = "GPREL",
|
||||||
|
[0x20000] = "MEM_16BIT",
|
||||||
|
[0x40000] = "MEM_LOCKED",
|
||||||
|
[0x80000] = "MEM_PRELOAD",
|
||||||
|
[0x100000] = "ALIGN_1BYTES",
|
||||||
|
[0x200000] = "ALIGN_2BYTES",
|
||||||
|
[0x300000] = "ALIGN_4BYTES",
|
||||||
|
[0x400000] = "ALIGN_8BYTES",
|
||||||
|
[0x500000] = "ALIGN_16BYTES",
|
||||||
|
[0x600000] = "ALIGN_32BYTES",
|
||||||
|
[0x700000] = "ALIGN_64BYTES",
|
||||||
|
[0x800000] = "ALIGN_128BYTES",
|
||||||
|
[0x900000] = "ALIGN_256BYTES",
|
||||||
|
[0xa00000] = "ALIGN_512BYTES",
|
||||||
|
[0xb00000] = "ALIGN_1024BYTES",
|
||||||
|
[0xc00000] = "ALIGN_2048BYTES",
|
||||||
|
[0xd00000] = "ALIGN_4096BYTES",
|
||||||
|
[0xe00000] = "ALIGN_8192BYTES",
|
||||||
|
[0x1000000] = "LNK_NRELOC_OVFL",
|
||||||
|
[0x2000000] = "MEM_DISCARDABLE",
|
||||||
|
[0x4000000] = "MEM_NOT_CACHED",
|
||||||
|
[0x8000000] = "MEM_NOT_PAGED",
|
||||||
|
[0x10000000] = "MEM_SHARED",
|
||||||
|
[0x20000000] = "MEM_EXECUTE",
|
||||||
|
[0x40000000] = "MEM_READ",
|
||||||
|
[0x80000000] = "MEM_WRITE"
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const os_versions: table[count, count] of string = {
|
||||||
|
[10,0] = "Windows 10",
|
||||||
|
[6,4] = "Windows 10 Technical Preview",
|
||||||
|
[6,3] = "Windows 8.1 or Server 2012 R2",
|
||||||
|
[6,2] = "Windows 8 or Server 2012",
|
||||||
|
[6,1] = "Windows 7 or Server 2008 R2",
|
||||||
|
[6,0] = "Windows Vista or Server 2008",
|
||||||
|
[5,2] = "Windows XP x64 or Server 2003",
|
||||||
|
[5,1] = "Windows XP",
|
||||||
|
[5,0] = "Windows 2000",
|
||||||
|
[4,90] = "Windows Me",
|
||||||
|
[4,10] = "Windows 98",
|
||||||
|
[4,0] = "Windows 95 or NT 4.0",
|
||||||
|
[3,51] = "Windows NT 3.51",
|
||||||
|
[3,50] = "Windows NT 3.5",
|
||||||
|
[3,2] = "Windows 3.2",
|
||||||
|
[3,11] = "Windows for Workgroups 3.11",
|
||||||
|
[3,10] = "Windows 3.1 or NT 3.1",
|
||||||
|
[3,0] = "Windows 3.0",
|
||||||
|
[2,11] = "Windows 2.11",
|
||||||
|
[2,10] = "Windows 2.10",
|
||||||
|
[2,0] = "Windows 2.0",
|
||||||
|
[1,4] = "Windows 1.04",
|
||||||
|
[1,3] = "Windows 1.03",
|
||||||
|
[1,1] = "Windows 1.01",
|
||||||
|
[1,0] = "Windows 1.0",
|
||||||
|
} &default=function(i: count, j: count):string { return fmt("unknown-%d.%d", i, j); };
|
||||||
|
|
||||||
|
const section_descs: table[string] of string = {
|
||||||
|
[".bss"] = "Uninitialized data",
|
||||||
|
[".cormeta"] = "CLR metadata that indicates that the object file contains managed code",
|
||||||
|
[".data"] = "Initialized data",
|
||||||
|
[".debug$F"] = "Generated FPO debug information",
|
||||||
|
[".debug$P"] = "Precompiled debug types",
|
||||||
|
[".debug$S"] = "Debug symbols",
|
||||||
|
[".debug$T"] = "Debug types",
|
||||||
|
[".drective"] = "Linker options",
|
||||||
|
[".edata"] = "Export tables",
|
||||||
|
[".idata"] = "Import tables",
|
||||||
|
[".idlsym"] = "Includes registered SEH to support IDL attributes",
|
||||||
|
[".pdata"] = "Exception information",
|
||||||
|
[".rdata"] = "Read-only initialized data",
|
||||||
|
[".reloc"] = "Image relocations",
|
||||||
|
[".rsrc"] = "Resource directory",
|
||||||
|
[".sbss"] = "GP-relative uninitialized data",
|
||||||
|
[".sdata"] = "GP-relative initialized data",
|
||||||
|
[".srdata"] = "GP-relative read-only data",
|
||||||
|
[".sxdata"] = "Registered exception handler data",
|
||||||
|
[".text"] = "Executable code",
|
||||||
|
[".tls"] = "Thread-local storage",
|
||||||
|
[".tls$"] = "Thread-local storage",
|
||||||
|
[".vsdata"] = "GP-relative initialized data",
|
||||||
|
[".xdata"] = "Exception information",
|
||||||
|
} &default=function(i: string):string { return fmt("unknown-%s", i); };
|
||||||
|
|
||||||
|
}
|
137
scripts/base/files/pe/main.bro
Normal file
137
scripts/base/files/pe/main.bro
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
module PE;
|
||||||
|
|
||||||
|
@load ./consts.bro
|
||||||
|
|
||||||
|
export {
|
||||||
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
|
type Info: record {
|
||||||
|
## Current timestamp.
|
||||||
|
ts: time &log;
|
||||||
|
## File id of this portable executable file.
|
||||||
|
id: string &log;
|
||||||
|
## The target machine that the file was compiled for.
|
||||||
|
machine: string &log &optional;
|
||||||
|
## The time that the file was created at.
|
||||||
|
compile_ts: time &log &optional;
|
||||||
|
## The required operating system.
|
||||||
|
os: string &log &optional;
|
||||||
|
## The subsystem that is required to run this file.
|
||||||
|
subsystem: string &log &optional;
|
||||||
|
## Is the file an executable, or just an object file?
|
||||||
|
is_exe: bool &log &default=T;
|
||||||
|
## Is the file a 64-bit executable?
|
||||||
|
is_64bit: bool &log &default=T;
|
||||||
|
## Does the file support Address Space Layout Randomization?
|
||||||
|
uses_aslr: bool &log &default=F;
|
||||||
|
## Does the file support Data Execution Prevention?
|
||||||
|
uses_dep: bool &log &default=F;
|
||||||
|
## Does the file enforce code integrity checks?
|
||||||
|
uses_code_integrity: bool &log &default=F;
|
||||||
|
## Does the file use structured exception handing?
|
||||||
|
uses_seh: bool &log &default=T;
|
||||||
|
## Does the file have an import table?
|
||||||
|
has_import_table: bool &log &optional;
|
||||||
|
## Does the file have an export table?
|
||||||
|
has_export_table: bool &log &optional;
|
||||||
|
## Does the file have an attribute certificate table?
|
||||||
|
has_cert_table: bool &log &optional;
|
||||||
|
## Does the file have a debug table?
|
||||||
|
has_debug_data: bool &log &optional;
|
||||||
|
## The names of the sections, in order.
|
||||||
|
section_names: vector of string &log &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
## Event for accessing logged records.
|
||||||
|
global log_pe: event(rec: Info);
|
||||||
|
|
||||||
|
## A hook that gets called when we first see a PE file.
|
||||||
|
global set_file: hook(f: fa_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
redef record fa_file += {
|
||||||
|
pe: Info &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pe_mime_types = { "application/x-dosexec" };
|
||||||
|
|
||||||
|
event bro_init() &priority=5
|
||||||
|
{
|
||||||
|
Files::register_for_mime_types(Files::ANALYZER_PE, pe_mime_types);
|
||||||
|
Log::create_stream(LOG, [$columns=Info, $ev=log_pe, $path="pe"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
hook set_file(f: fa_file) &priority=5
|
||||||
|
{
|
||||||
|
if ( ! f?$pe )
|
||||||
|
f$pe = [$ts=network_time(), $id=f$id];
|
||||||
|
}
|
||||||
|
|
||||||
|
event pe_dos_header(f: fa_file, h: PE::DOSHeader) &priority=5
|
||||||
|
{
|
||||||
|
hook set_file(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
event pe_file_header(f: fa_file, h: PE::FileHeader) &priority=5
|
||||||
|
{
|
||||||
|
hook set_file(f);
|
||||||
|
|
||||||
|
f$pe$machine = machine_types[h$machine];
|
||||||
|
f$pe$compile_ts = h$ts;
|
||||||
|
f$pe$is_exe = ( h$optional_header_size > 0 );
|
||||||
|
|
||||||
|
for ( c in h$characteristics )
|
||||||
|
{
|
||||||
|
if ( file_characteristics[c] == "32BIT_MACHINE" )
|
||||||
|
f$pe$is_64bit = F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event pe_optional_header(f: fa_file, h: PE::OptionalHeader) &priority=5
|
||||||
|
{
|
||||||
|
hook set_file(f);
|
||||||
|
|
||||||
|
# Only EXEs have optional headers
|
||||||
|
if ( ! f$pe$is_exe )
|
||||||
|
return;
|
||||||
|
|
||||||
|
f$pe$os = os_versions[h$os_version_major, h$os_version_minor];
|
||||||
|
f$pe$subsystem = windows_subsystems[h$subsystem];
|
||||||
|
|
||||||
|
for ( c in h$dll_characteristics )
|
||||||
|
{
|
||||||
|
if ( dll_characteristics[c] == "DYNAMIC_BASE" )
|
||||||
|
f$pe$uses_aslr = T;
|
||||||
|
if ( dll_characteristics[c] == "FORCE_INTEGRITY" )
|
||||||
|
f$pe$uses_code_integrity = T;
|
||||||
|
if ( dll_characteristics[c] == "NX_COMPAT" )
|
||||||
|
f$pe$uses_dep = T;
|
||||||
|
if ( dll_characteristics[c] == "NO_SEH" )
|
||||||
|
f$pe$uses_seh = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
f$pe$has_export_table = (|h$table_sizes| > 0 && h$table_sizes[0] > 0);
|
||||||
|
f$pe$has_import_table = (|h$table_sizes| > 1 && h$table_sizes[1] > 0);
|
||||||
|
f$pe$has_cert_table = (|h$table_sizes| > 4 && h$table_sizes[4] > 0);
|
||||||
|
f$pe$has_debug_data = (|h$table_sizes| > 6 && h$table_sizes[6] > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
event pe_section_header(f: fa_file, h: PE::SectionHeader) &priority=5
|
||||||
|
{
|
||||||
|
hook set_file(f);
|
||||||
|
|
||||||
|
# Only EXEs have section headers
|
||||||
|
if ( ! f$pe$is_exe )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( ! f$pe?$section_names )
|
||||||
|
f$pe$section_names = vector();
|
||||||
|
f$pe$section_names[|f$pe$section_names|] = h$name;
|
||||||
|
}
|
||||||
|
|
||||||
|
event file_state_remove(f: fa_file) &priority=-5
|
||||||
|
{
|
||||||
|
if ( f?$pe && f$pe?$machine )
|
||||||
|
Log::write(LOG, f$pe);
|
||||||
|
}
|
||||||
|
|
|
@ -71,11 +71,50 @@ global classification_map: table[count] of string;
|
||||||
global sid_map: table[count] of string;
|
global sid_map: table[count] of string;
|
||||||
global gen_map: table[count] of string;
|
global gen_map: table[count] of string;
|
||||||
|
|
||||||
|
global num_classification_map_reads = 0;
|
||||||
|
global num_sid_map_reads = 0;
|
||||||
|
global num_gen_map_reads = 0;
|
||||||
|
global watching = F;
|
||||||
|
|
||||||
# For reading in config files.
|
# For reading in config files.
|
||||||
type OneLine: record {
|
type OneLine: record {
|
||||||
line: string;
|
line: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function mappings_initialized(): bool
|
||||||
|
{
|
||||||
|
return num_classification_map_reads > 0 &&
|
||||||
|
num_sid_map_reads > 0 &&
|
||||||
|
num_gen_map_reads > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function start_watching()
|
||||||
|
{
|
||||||
|
if ( watching )
|
||||||
|
return;
|
||||||
|
|
||||||
|
watching = T;
|
||||||
|
|
||||||
|
if ( watch_dir != "" )
|
||||||
|
{
|
||||||
|
Dir::monitor(watch_dir, function(fname: string)
|
||||||
|
{
|
||||||
|
Input::add_analysis([$source=fname,
|
||||||
|
$reader=Input::READER_BINARY,
|
||||||
|
$mode=Input::STREAM,
|
||||||
|
$name=fname]);
|
||||||
|
}, 10secs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( watch_file != "" )
|
||||||
|
{
|
||||||
|
Input::add_analysis([$source=watch_file,
|
||||||
|
$reader=Input::READER_BINARY,
|
||||||
|
$mode=Input::STREAM,
|
||||||
|
$name=watch_file]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function create_info(ev: IDSEvent): Info
|
function create_info(ev: IDSEvent): Info
|
||||||
{
|
{
|
||||||
local info = Info($ts=ev$ts,
|
local info = Info($ts=ev$ts,
|
||||||
|
@ -113,34 +152,56 @@ redef record fa_file += {
|
||||||
|
|
||||||
event Unified2::read_sid_msg_line(desc: Input::EventDescription, tpe: Input::Event, line: string)
|
event Unified2::read_sid_msg_line(desc: Input::EventDescription, tpe: Input::Event, line: string)
|
||||||
{
|
{
|
||||||
local parts = split_n(line, / \|\| /, F, 100);
|
local parts = split_string_n(line, / \|\| /, F, 100);
|
||||||
if ( |parts| >= 2 && /^[0-9]+$/ in parts[1] )
|
if ( |parts| >= 2 && /^[0-9]+$/ in parts[0] )
|
||||||
sid_map[to_count(parts[1])] = parts[2];
|
sid_map[to_count(parts[0])] = parts[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
event Unified2::read_gen_msg_line(desc: Input::EventDescription, tpe: Input::Event, line: string)
|
event Unified2::read_gen_msg_line(desc: Input::EventDescription, tpe: Input::Event, line: string)
|
||||||
{
|
{
|
||||||
local parts = split_n(line, / \|\| /, F, 3);
|
local parts = split_string_n(line, / \|\| /, F, 3);
|
||||||
if ( |parts| >= 2 && /^[0-9]+$/ in parts[1] )
|
if ( |parts| >= 2 && /^[0-9]+$/ in parts[0] )
|
||||||
gen_map[to_count(parts[1])] = parts[3];
|
gen_map[to_count(parts[0])] = parts[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
event Unified2::read_classification_line(desc: Input::EventDescription, tpe: Input::Event, line: string)
|
event Unified2::read_classification_line(desc: Input::EventDescription, tpe: Input::Event, line: string)
|
||||||
{
|
{
|
||||||
local parts = split_n(line, /: /, F, 2);
|
local parts = split_string_n(line, /: /, F, 2);
|
||||||
if ( |parts| == 2 )
|
if ( |parts| == 2 )
|
||||||
{
|
{
|
||||||
local parts2 = split_n(parts[2], /,/, F, 4);
|
local parts2 = split_string_n(parts[1], /,/, F, 4);
|
||||||
if ( |parts2| > 1 )
|
if ( |parts2| > 1 )
|
||||||
classification_map[|classification_map|+1] = parts2[1];
|
classification_map[|classification_map|+1] = parts2[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event Input::end_of_data(name: string, source: string)
|
||||||
|
{
|
||||||
|
if ( name == classification_config )
|
||||||
|
++num_classification_map_reads;
|
||||||
|
else if ( name == sid_msg )
|
||||||
|
++num_sid_map_reads;
|
||||||
|
else if ( name == gen_msg )
|
||||||
|
++num_gen_map_reads;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( watching )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( mappings_initialized() )
|
||||||
|
start_watching();
|
||||||
|
}
|
||||||
|
|
||||||
event bro_init() &priority=5
|
event bro_init() &priority=5
|
||||||
{
|
{
|
||||||
Log::create_stream(Unified2::LOG, [$columns=Info, $ev=log_unified2]);
|
Log::create_stream(Unified2::LOG, [$columns=Info, $ev=log_unified2, $path="unified2"]);
|
||||||
|
|
||||||
if ( sid_msg != "" )
|
if ( sid_msg == "" )
|
||||||
|
{
|
||||||
|
num_sid_map_reads = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Input::add_event([$source=sid_msg,
|
Input::add_event([$source=sid_msg,
|
||||||
$reader=Input::READER_RAW,
|
$reader=Input::READER_RAW,
|
||||||
|
@ -151,7 +212,11 @@ event bro_init() &priority=5
|
||||||
$ev=Unified2::read_sid_msg_line]);
|
$ev=Unified2::read_sid_msg_line]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( gen_msg != "" )
|
if ( gen_msg == "" )
|
||||||
|
{
|
||||||
|
num_gen_map_reads = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Input::add_event([$source=gen_msg,
|
Input::add_event([$source=gen_msg,
|
||||||
$name=gen_msg,
|
$name=gen_msg,
|
||||||
|
@ -162,7 +227,11 @@ event bro_init() &priority=5
|
||||||
$ev=Unified2::read_gen_msg_line]);
|
$ev=Unified2::read_gen_msg_line]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( classification_config != "" )
|
if ( classification_config == "" )
|
||||||
|
{
|
||||||
|
num_classification_map_reads = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Input::add_event([$source=classification_config,
|
Input::add_event([$source=classification_config,
|
||||||
$name=classification_config,
|
$name=classification_config,
|
||||||
|
@ -173,32 +242,16 @@ event bro_init() &priority=5
|
||||||
$ev=Unified2::read_classification_line]);
|
$ev=Unified2::read_classification_line]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( watch_dir != "" )
|
if ( mappings_initialized() )
|
||||||
{
|
start_watching();
|
||||||
Dir::monitor(watch_dir, function(fname: string)
|
|
||||||
{
|
|
||||||
Input::add_analysis([$source=fname,
|
|
||||||
$reader=Input::READER_BINARY,
|
|
||||||
$mode=Input::STREAM,
|
|
||||||
$name=fname]);
|
|
||||||
}, 10secs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( watch_file != "" )
|
|
||||||
{
|
|
||||||
Input::add_analysis([$source=watch_file,
|
|
||||||
$reader=Input::READER_BINARY,
|
|
||||||
$mode=Input::STREAM,
|
|
||||||
$name=watch_file]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
event file_new(f: fa_file)
|
event file_new(f: fa_file)
|
||||||
{
|
{
|
||||||
local file_dir = "";
|
local file_dir = "";
|
||||||
local parts = split_all(f$source, /\/[^\/]*$/);
|
local parts = split_string_all(f$source, /\/[^\/]*$/);
|
||||||
if ( |parts| == 3 )
|
if ( |parts| == 3 )
|
||||||
file_dir = parts[1];
|
file_dir = parts[0];
|
||||||
|
|
||||||
if ( (watch_file != "" && f$source == watch_file) ||
|
if ( (watch_file != "" && f$source == watch_file) ||
|
||||||
(watch_dir != "" && compress_path(watch_dir) == file_dir) )
|
(watch_dir != "" && compress_path(watch_dir) == file_dir) )
|
||||||
|
|
|
@ -36,7 +36,7 @@ export {
|
||||||
|
|
||||||
event bro_init() &priority=5
|
event bro_init() &priority=5
|
||||||
{
|
{
|
||||||
Log::create_stream(X509::LOG, [$columns=Info, $ev=log_x509]);
|
Log::create_stream(X509::LOG, [$columns=Info, $ev=log_x509, $path="x509"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
redef record Files::Info += {
|
redef record Files::Info += {
|
||||||
|
@ -47,6 +47,9 @@ redef record Files::Info += {
|
||||||
|
|
||||||
event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) &priority=5
|
event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) &priority=5
|
||||||
{
|
{
|
||||||
|
if ( ! f$info?$mime_type )
|
||||||
|
f$info$mime_type = "application/pkix-cert";
|
||||||
|
|
||||||
f$info$x509 = [$ts=f$info$ts, $id=f$id, $certificate=cert, $handle=cert_ref];
|
f$info$x509 = [$ts=f$info$ts, $id=f$id, $certificate=cert, $handle=cert_ref];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
scripts/base/frameworks/broker/README
Normal file
2
scripts/base/frameworks/broker/README
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
The Broker communication framework facilitates connecting to remote Bro
|
||||||
|
instances to share state and transfer events.
|
1
scripts/base/frameworks/broker/__load__.bro
Normal file
1
scripts/base/frameworks/broker/__load__.bro
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@load ./main
|
103
scripts/base/frameworks/broker/main.bro
Normal file
103
scripts/base/frameworks/broker/main.bro
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
##! Various data structure definitions for use with Bro's communication system.
|
||||||
|
|
||||||
|
module BrokerComm;
|
||||||
|
|
||||||
|
export {
|
||||||
|
|
||||||
|
## A name used to identify this endpoint to peers.
|
||||||
|
## .. bro:see:: BrokerComm::connect BrokerComm::listen
|
||||||
|
const endpoint_name = "" &redef;
|
||||||
|
|
||||||
|
## Change communication behavior.
|
||||||
|
type EndpointFlags: record {
|
||||||
|
## Whether to restrict message topics that can be published to peers.
|
||||||
|
auto_publish: bool &default = T;
|
||||||
|
## Whether to restrict what message topics or data store identifiers
|
||||||
|
## the local endpoint advertises to peers (e.g. subscribing to
|
||||||
|
## events or making a master data store available).
|
||||||
|
auto_advertise: bool &default = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
## Fine-grained tuning of communication behavior for a particular message.
|
||||||
|
type SendFlags: record {
|
||||||
|
## Send the message to the local endpoint.
|
||||||
|
self: bool &default = F;
|
||||||
|
## Send the message to peer endpoints that advertise interest in
|
||||||
|
## the topic associated with the message.
|
||||||
|
peers: bool &default = T;
|
||||||
|
## Send the message to peer endpoints even if they don't advertise
|
||||||
|
## interest in the topic associated with the message.
|
||||||
|
unsolicited: bool &default = F;
|
||||||
|
};
|
||||||
|
|
||||||
|
## Opaque communication data.
|
||||||
|
type Data: record {
|
||||||
|
d: opaque of BrokerComm::Data &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
## Opaque communication data.
|
||||||
|
type DataVector: vector of BrokerComm::Data;
|
||||||
|
|
||||||
|
## Opaque event communication data.
|
||||||
|
type EventArgs: record {
|
||||||
|
## The name of the event. Not set if invalid event or arguments.
|
||||||
|
name: string &optional;
|
||||||
|
## The arguments to the event.
|
||||||
|
args: DataVector;
|
||||||
|
};
|
||||||
|
|
||||||
|
## Opaque communication data used as a convenient way to wrap key-value
|
||||||
|
## pairs that comprise table entries.
|
||||||
|
type TableItem : record {
|
||||||
|
key: BrokerComm::Data;
|
||||||
|
val: BrokerComm::Data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module BrokerStore;
|
||||||
|
|
||||||
|
export {
|
||||||
|
|
||||||
|
## Whether a data store query could be completed or not.
|
||||||
|
type QueryStatus: enum {
|
||||||
|
SUCCESS,
|
||||||
|
FAILURE,
|
||||||
|
};
|
||||||
|
|
||||||
|
## An expiry time for a key-value pair inserted in to a data store.
|
||||||
|
type ExpiryTime: record {
|
||||||
|
## Absolute point in time at which to expire the entry.
|
||||||
|
absolute: time &optional;
|
||||||
|
## A point in time relative to the last modification time at which
|
||||||
|
## to expire the entry. New modifications will delay the expiration.
|
||||||
|
since_last_modification: interval &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
## The result of a data store query.
|
||||||
|
type QueryResult: record {
|
||||||
|
## Whether the query completed or not.
|
||||||
|
status: BrokerStore::QueryStatus;
|
||||||
|
## The result of the query. Certain queries may use a particular
|
||||||
|
## data type (e.g. querying store size always returns a count, but
|
||||||
|
## a lookup may return various data types).
|
||||||
|
result: BrokerComm::Data;
|
||||||
|
};
|
||||||
|
|
||||||
|
## Options to tune the SQLite storage backend.
|
||||||
|
type SQLiteOptions: record {
|
||||||
|
## File system path of the database.
|
||||||
|
path: string &default = "store.sqlite";
|
||||||
|
};
|
||||||
|
|
||||||
|
## Options to tune the RocksDB storage backend.
|
||||||
|
type RocksDBOptions: record {
|
||||||
|
## File system path of the database.
|
||||||
|
path: string &default = "store.rocksdb";
|
||||||
|
};
|
||||||
|
|
||||||
|
## Options to tune the particular storage backends.
|
||||||
|
type BackendOptions: record {
|
||||||
|
sqlite: SQLiteOptions &default = SQLiteOptions();
|
||||||
|
rocksdb: RocksDBOptions &default = RocksDBOptions();
|
||||||
|
};
|
||||||
|
}
|
|
@ -126,6 +126,9 @@ export {
|
||||||
## This is usually supplied on the command line for each instance
|
## This is usually supplied on the command line for each instance
|
||||||
## of the cluster that is started up.
|
## of the cluster that is started up.
|
||||||
const node = getenv("CLUSTER_NODE") &redef;
|
const node = getenv("CLUSTER_NODE") &redef;
|
||||||
|
|
||||||
|
## Interval for retrying failed connections between cluster nodes.
|
||||||
|
const retry_interval = 1min &redef;
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_enabled(): bool
|
function is_enabled(): bool
|
||||||
|
@ -159,5 +162,5 @@ event bro_init() &priority=5
|
||||||
terminate();
|
terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::create_stream(Cluster::LOG, [$columns=Info]);
|
Log::create_stream(Cluster::LOG, [$columns=Info, $path="cluster"]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ event bro_init() &priority=9
|
||||||
Communication::nodes["time-machine"] = [$host=nodes[i]$ip,
|
Communication::nodes["time-machine"] = [$host=nodes[i]$ip,
|
||||||
$zone_id=nodes[i]$zone_id,
|
$zone_id=nodes[i]$zone_id,
|
||||||
$p=nodes[i]$p,
|
$p=nodes[i]$p,
|
||||||
$connect=T, $retry=1min,
|
$connect=T, $retry=retry_interval,
|
||||||
$events=tm2manager_events];
|
$events=tm2manager_events];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ event bro_init() &priority=9
|
||||||
if ( n?$proxy )
|
if ( n?$proxy )
|
||||||
Communication::nodes[i]
|
Communication::nodes[i]
|
||||||
= [$host=n$ip, $zone_id=n$zone_id, $p=n$p,
|
= [$host=n$ip, $zone_id=n$zone_id, $p=n$p,
|
||||||
$connect=T, $auth=F, $sync=T, $retry=1mins];
|
$connect=T, $auth=F, $sync=T, $retry=retry_interval];
|
||||||
else if ( me?$proxy && me$proxy == i )
|
else if ( me?$proxy && me$proxy == i )
|
||||||
Communication::nodes[me$proxy]
|
Communication::nodes[me$proxy]
|
||||||
= [$host=nodes[i]$ip, $zone_id=nodes[i]$zone_id,
|
= [$host=nodes[i]$ip, $zone_id=nodes[i]$zone_id,
|
||||||
|
@ -70,7 +70,7 @@ event bro_init() &priority=9
|
||||||
Communication::nodes["manager"] = [$host=nodes[i]$ip,
|
Communication::nodes["manager"] = [$host=nodes[i]$ip,
|
||||||
$zone_id=nodes[i]$zone_id,
|
$zone_id=nodes[i]$zone_id,
|
||||||
$p=nodes[i]$p,
|
$p=nodes[i]$p,
|
||||||
$connect=T, $retry=1mins,
|
$connect=T, $retry=retry_interval,
|
||||||
$class=node,
|
$class=node,
|
||||||
$events=manager2proxy_events];
|
$events=manager2proxy_events];
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ event bro_init() &priority=9
|
||||||
Communication::nodes["manager"] = [$host=nodes[i]$ip,
|
Communication::nodes["manager"] = [$host=nodes[i]$ip,
|
||||||
$zone_id=nodes[i]$zone_id,
|
$zone_id=nodes[i]$zone_id,
|
||||||
$p=nodes[i]$p,
|
$p=nodes[i]$p,
|
||||||
$connect=T, $retry=1mins,
|
$connect=T, $retry=retry_interval,
|
||||||
$class=node,
|
$class=node,
|
||||||
$events=manager2worker_events];
|
$events=manager2worker_events];
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ event bro_init() &priority=9
|
||||||
Communication::nodes["proxy"] = [$host=nodes[i]$ip,
|
Communication::nodes["proxy"] = [$host=nodes[i]$ip,
|
||||||
$zone_id=nodes[i]$zone_id,
|
$zone_id=nodes[i]$zone_id,
|
||||||
$p=nodes[i]$p,
|
$p=nodes[i]$p,
|
||||||
$connect=T, $retry=1mins,
|
$connect=T, $retry=retry_interval,
|
||||||
$sync=T, $class=node,
|
$sync=T, $class=node,
|
||||||
$events=proxy2worker_events];
|
$events=proxy2worker_events];
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ event bro_init() &priority=9
|
||||||
$zone_id=nodes[i]$zone_id,
|
$zone_id=nodes[i]$zone_id,
|
||||||
$p=nodes[i]$p,
|
$p=nodes[i]$p,
|
||||||
$connect=T,
|
$connect=T,
|
||||||
$retry=1min,
|
$retry=retry_interval,
|
||||||
$events=tm2worker_events];
|
$events=tm2worker_events];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ const src_names = {
|
||||||
|
|
||||||
event bro_init() &priority=5
|
event bro_init() &priority=5
|
||||||
{
|
{
|
||||||
Log::create_stream(Communication::LOG, [$columns=Info]);
|
Log::create_stream(Communication::LOG, [$columns=Info, $path="communication"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function do_script_log_common(level: count, src: count, msg: string)
|
function do_script_log_common(level: count, src: count, msg: string)
|
||||||
|
|
|
@ -38,7 +38,7 @@ redef record connection += {
|
||||||
|
|
||||||
event bro_init() &priority=5
|
event bro_init() &priority=5
|
||||||
{
|
{
|
||||||
Log::create_stream(DPD::LOG, [$columns=Info]);
|
Log::create_stream(DPD::LOG, [$columns=Info, $path="dpd"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=10
|
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=10
|
||||||
|
|
|
@ -1,2 +1,9 @@
|
||||||
|
@load-sigs ./archive
|
||||||
|
@load-sigs ./audio
|
||||||
|
@load-sigs ./font
|
||||||
@load-sigs ./general
|
@load-sigs ./general
|
||||||
|
@load-sigs ./image
|
||||||
|
@load-sigs ./msoffice
|
||||||
|
@load-sigs ./video
|
||||||
|
|
||||||
@load-sigs ./libmagic
|
@load-sigs ./libmagic
|
176
scripts/base/frameworks/files/magic/archive.sig
Normal file
176
scripts/base/frameworks/files/magic/archive.sig
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
|
||||||
|
signature file-tar {
|
||||||
|
file-magic /^[[:print:]\x00]{100}([[:digit:]\x20]{7}\x00){3}([[:digit:]\x20]{11}\x00){2}([[:digit:]\x00\x20]{7}[\x20\x00])[0-7\x00]/
|
||||||
|
file-mime "application/x-tar", 100
|
||||||
|
}
|
||||||
|
|
||||||
|
# This is low priority so that files using zip as a
|
||||||
|
# container will be identified correctly.
|
||||||
|
signature file-zip {
|
||||||
|
file-mime "application/zip", 10
|
||||||
|
file-magic /^PK\x03\x04.{2}/
|
||||||
|
}
|
||||||
|
|
||||||
|
# Multivolume Zip archive
|
||||||
|
signature file-multi-zip {
|
||||||
|
file-mime "application/zip", 10
|
||||||
|
file-magic /^PK\x07\x08PK\x03\x04/
|
||||||
|
}
|
||||||
|
|
||||||
|
# RAR
|
||||||
|
signature file-rar {
|
||||||
|
file-mime "application/x-rar", 70
|
||||||
|
file-magic /^Rar!/
|
||||||
|
}
|
||||||
|
|
||||||
|
# GZIP
|
||||||
|
signature file-gzip {
|
||||||
|
file-mime "application/x-gzip", 100
|
||||||
|
file-magic /\x1f\x8b/
|
||||||
|
}
|
||||||
|
|
||||||
|
# Microsoft Cabinet
|
||||||
|
signature file-ms-cab {
|
||||||
|
file-mime "application/vnd.ms-cab-compressed", 110
|
||||||
|
file-magic /^MSCF\x00\x00\x00\x00/
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mac OS X DMG files
|
||||||
|
signature file-dmg {
|
||||||
|
file-magic /^(\x78\x01\x73\x0D\x62\x62\x60|\x78\xDA\x63\x60\x18\x05|\x78\x01\x63\x60\x18\x05|\x78\xDA\x73\x0D|\x78[\x01\xDA]\xED[\xD0-\xD9])/
|
||||||
|
file-mime "application/x-dmg", 100
|
||||||
|
}
|
||||||
|
|
||||||
|
# XAR (eXtensible ARchive) format.
|
||||||
|
# Mac OS X uses this for the .pkg format.
|
||||||
|
signature file-xar {
|
||||||
|
file-magic /^xar\!/
|
||||||
|
file-mime "application/x-xar", 100
|
||||||
|
}
|
||||||
|
|
||||||
|
# RPM
|
||||||
|
signature file-magic-auto352 {
|
||||||
|
file-mime "application/x-rpm", 70
|
||||||
|
file-magic /^(drpm|\xed\xab\xee\xdb)/
|
||||||
|
}
|
||||||
|
|
||||||
|
# StuffIt
|
||||||
|
signature file-stuffit {
|
||||||
|
file-mime "application/x-stuffit", 70
|
||||||
|
file-magic /^(SIT\x21|StuffIt)/
|
||||||
|
}
|
||||||
|
|
||||||
|
# Archived data
|
||||||
|
signature file-x-archive {
|
||||||
|
file-mime "application/x-archive", 70
|
||||||
|
file-magic /^!?<ar(ch)?>/
|
||||||
|
}
|
||||||
|
|
||||||
|
# ARC archive data
|
||||||
|
signature file-arc {
|
||||||
|
file-mime "application/x-arc", 70
|
||||||
|
file-magic /^[\x00-\x7f]{2}[\x02-\x0a\x14\x48]\x1a/
|
||||||
|
}
|
||||||
|
|
||||||
|
# EET archive
|
||||||
|
signature file-eet {
|
||||||
|
file-mime "application/x-eet", 70
|
||||||
|
file-magic /^\x1e\xe7\xff\x00/
|
||||||
|
}
|
||||||
|
|
||||||
|
# Zoo archive
|
||||||
|
signature file-zoo {
|
||||||
|
file-mime "application/x-zoo", 70
|
||||||
|
file-magic /^.{20}\xdc\xa7\xc4\xfd/
|
||||||
|
}
|
||||||
|
|
||||||
|
# LZ4 compressed data (legacy format)
|
||||||
|
signature file-lz4-legacy {
|
||||||
|
file-mime "application/x-lz4", 70
|
||||||
|
file-magic /(\x02\x21\x4c\x18)/
|
||||||
|
}
|
||||||
|
|
||||||
|
# LZ4 compressed data
|
||||||
|
signature file-lz4 {
|
||||||
|
file-mime "application/x-lz4", 70
|
||||||
|
file-magic /^\x04\x22\x4d\x18/
|
||||||
|
}
|
||||||
|
|
||||||
|
# LRZIP compressed data
|
||||||
|
signature file-lrzip {
|
||||||
|
file-mime "application/x-lrzip", 1
|
||||||
|
file-magic /^LRZI/
|
||||||
|
}
|
||||||
|
|
||||||
|
# LZIP compressed data
|
||||||
|
signature file-lzip {
|
||||||
|
file-mime "application/x-lzip", 70
|
||||||
|
file-magic /^LZIP/
|
||||||
|
}
|
||||||
|
|
||||||
|
# Self-extracting PKZIP archive
|
||||||
|
signature file-magic-auto434 {
|
||||||
|
file-mime "application/zip", 340
|
||||||
|
file-magic /^MZ.{28}(Copyright 1989\x2d1990 PKWARE Inc|PKLITE Copr)\x2e/
|
||||||
|
}
|
||||||
|
|
||||||
|
# LHA archive (LZH)
|
||||||
|
signature file-lzh {
|
||||||
|
file-mime "application/x-lzh", 80
|
||||||
|
file-magic /^.{2}-(lh[ abcdex0-9]|lz[s2-8]|lz[s2-8]|pm[s012]|pc1)-/
|
||||||
|
}
|
||||||
|
|
||||||
|
# WARC Archive
|
||||||
|
signature file-warc {
|
||||||
|
file-mime "application/warc", 50
|
||||||
|
file-magic /^WARC\x2f/
|
||||||
|
}
|
||||||
|
|
||||||
|
# 7-zip archive data
|
||||||
|
signature file-7zip {
|
||||||
|
file-mime "application/x-7z-compressed", 50
|
||||||
|
file-magic /^7z\xbc\xaf\x27\x1c/
|
||||||
|
}
|
||||||
|
|
||||||
|
# XZ compressed data
|
||||||
|
signature file-xz {
|
||||||
|
file-mime "application/x-xz", 90
|
||||||
|
file-magic /^\xfd7zXZ\x00/
|
||||||
|
}
|
||||||
|
|
||||||
|
# LHa self-extracting archive
|
||||||
|
signature file-magic-auto436 {
|
||||||
|
file-mime "application/x-lha", 120
|
||||||
|
file-magic /^MZ.{34}LH[aA]\x27s SFX/
|
||||||
|
}
|
||||||
|
|
||||||
|
# ARJ archive data
|
||||||
|
signature file-arj {
|
||||||
|
file-mime "application/x-arj", 50
|
||||||
|
file-magic /^\x60\xea/
|
||||||
|
}
|
||||||
|
|
||||||
|
# Byte-swapped cpio archive
|
||||||
|
signature file-bs-cpio {
|
||||||
|
file-mime "application/x-cpio", 50
|
||||||
|
file-magic /(\x71\xc7|\xc7\x71)/
|
||||||
|
}
|
||||||
|
|
||||||
|
# CPIO archive
|
||||||
|
signature file-cpio {
|
||||||
|
file-mime "application/x-cpio", 50
|
||||||
|
file-magic /^(\xc7\x71|\x71\xc7)/
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compress'd data
|
||||||
|
signature file-compress {
|
||||||
|
file-mime "application/x-compress", 50
|
||||||
|
file-magic /^\x1f\x9d/
|
||||||
|
}
|
||||||
|
|
||||||
|
# LZMA compressed data
|
||||||
|
signature file-lzma {
|
||||||
|
file-mime "application/x-lzma", 71
|
||||||
|
file-magic /^\x5d\x00\x00/
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue