Merge remote-tracking branch 'origin/master' into topic/seth/faf-updates

Conflicts:
	scripts/base/frameworks/files/main.bro
	scripts/base/init-bare.bro
	scripts/base/protocols/ftp/file-analysis.bro
	scripts/base/protocols/http/file-analysis.bro
	scripts/base/protocols/irc/file-analysis.bro
	scripts/base/protocols/smtp/file-analysis.bro
	src/const.bif
	src/event.bif
	src/file_analysis/Analyzer.h
	src/file_analysis/file_analysis.bif
This commit is contained in:
Seth Hall 2013-07-05 02:13:27 -04:00
commit 58d133e764
555 changed files with 16982 additions and 13190 deletions

120
CHANGES
View file

@ -1,4 +1,124 @@
2.1-784 | 2013-07-04 22:28:48 -0400
* Add a call to lookup_connection in SSH scripts to update connval. (Seth Hall)
* Updating submodule(s). (Robin Sommer)
2.1-782 | 2013-07-03 17:00:39 -0700
* Remove the SSL log queueing mechanism that was included with the
log delay mechanism. (Seth Hall)
2.1-780 | 2013-07-03 16:46:26 -0700
* Rewrite of the RAW input reader for improved robustness and new
features. (Bernhard Amann) This includes:
- Send "end_of_data" event for all kind of streams.
- Send "process_finished" event with exit code of child
process at process termination.
- Expose name of input stream to readers.
- Better error handling.
- New "force_kill" option which SIGKILLs processes on reader termination.
- Supports reading from stdout and stderr simultaneously.
- Support sending data to stdin of child process.
- Streaming reads from external commands work without blocking.
2.1-762 | 2013-07-03 16:33:22 -0700
* Fix to correct support for TLS 1.2. Addresses #1020. (Seth Hall,
with help from Rafal Lesniak).
2.1-760 | 2013-07-03 16:31:36 -0700
* Teach broxygen to generate protocol analyzer plugin reference.
(Jon Siwek)
* Adding 'const' to a number of C++ methods. (Jon Siwek)
2.1-757 | 2013-07-03 16:28:10 -0700
* Fix redef of table index from clearing table.
`redef foo["x"] = 1` now acts like `redef foo += { ["x"] = 1 }`
instead of `redef foo = { ["x"] = 1 }`.
Addresses #1013. (Jon Siwek)
2.1-755 | 2013-07-03 16:22:43 -0700
* Add a general file analysis overview/how-to document. (Jon Siwek)
* Improve file analysis doxygen comments. (Jon Siwek)
* Improve tracking of HTTP file extraction. http.log now has files
taken from request and response bodies in different fields for
each, and can now track multiple files per body. That is, the
"extraction_file" field is now "extracted_request_files" and
"extracted_response_files". Addresses #988. (Jon Siwek)
* Fix HTTP multipart body file analysis. Each part now gets assigned
a different file handle/id. (Jon Siwek)
* Remove logging of analyzers field of FileAnalysis::Info. (Jon
Siwek)
* Remove extraction counter in default file extraction scripts. (Jon
Siwek)
* Remove FileAnalysis::postpone_timeout.
FileAnalysis::set_timeout_interval can now perform same function.
(Jon Siwek)
* Make default get_file_handle handlers &priority=5 so they're
easier to override. (Jon Siwek)
* Add input interface to forward data for file analysis. The new
Input::add_analysis function is used to automatically forward
input data on to the file analysis framework. (Jon Siwek)
* File analysis framework interface simplifications. (Jon Siwek)
- Remove script-layer data input interface (will be managed directly
by input framework later).
- Only track files internally by file id hash. Chance of collision
too small to justify also tracking unique file string.
2.1-741 | 2013-06-07 17:28:50 -0700
* Fixing typo that could cause an assertion to falsely trigger.
(Robin Sommer)
2.1-740 | 2013-06-07 16:37:32 -0700
* Fix for CMake 2.6.x. (Robin Sommer)
2.1-738 | 2013-06-07 08:38:13 -0700
* Remove invalid free on non-allocated pointer in hash function
object. Addresses #1018. (Matthias Vallentin)
2.1-736 | 2013-06-06 10:05:20 -0700
* New "magic constants" @DIR and @FILENAME that expand to the
directory path of the current script and just the script file name
without path, respectively. (Jon Siwek)
2.1-731 | 2013-06-04 21:19:08 -0700
* Reorginization of internal protocol analyzer code. We're moving
them to a modularized structure, based on a plugin model. Along
with this change comes generic plugin infrastructure that we'll
later extend to other Bro component as well. For now all plugins
are compiled in statically, but in the future we plan to also
enable dynamic loading at run time. (Robin Sommer)
* Ignoring file ids in external tests. (Robin Sommer)
2.1-675 | 2013-06-02 20:03:19 -0700
* Fix a compiler warning. (Robin Sommer)

14
NEWS
View file

@ -68,11 +68,17 @@ New Functionality
global foo: function(s: string, t: string &default="abc", u: count &default=0);
- Scripts can now use two new "magic constants" @DIR and @FILENAME
that expand to the directory path of the current script and just the
script file name without path, respectively. (Jon Siwek)
- The new file analysis framework moves most of the processing of file
content from script-land into the core, where it belongs. Much of
this is an internal change, the framework comes with the following
user-visibible functionality (some of that was already available
before, but done differently):
content from script-land into the core, where it belongs. See
doc/file-analysis.rst for more information.
Much of this is an internal change, but the framework also comes
with the following user-visibible functionality (some of that was
already available before, but done differently):
[TODO: This will probably change with further script updates.]

View file

@ -1 +1 @@
2.1-675
2.1-784

@ -1 +1 @@
Subproject commit f86a3169b8d49189d264cbc1a7507260cd9ff51d
Subproject commit c39bd478b9d0ecd05b1b83aa9d09a7887893977c

@ -1 +1 @@
Subproject commit cfaf4eea788bdac4ebfe9e46e3de2cd74b0bc068
Subproject commit a9942558c7d3dfd80148b8aaded64c82ade3d117

@ -1 +1 @@
Subproject commit 8955807b0f4151f5f6aca2e68d353b9b341d9f86
Subproject commit 889f9c65944ceac20ad9230efc39d33e6e1221c3

@ -1 +1 @@
Subproject commit 0eca32b35d16a4d387f41976ab46360ee6ecaed8
Subproject commit 017e7732446b36af935c26834394b51829335e7c

View file

@ -12,7 +12,7 @@
broPolicies=${BRO_SCRIPT_SOURCE_PATH}:${BRO_SCRIPT_SOURCE_PATH}/policy:${BRO_SCRIPT_SOURCE_PATH}/site
broGenPolicies=${CMAKE_BINARY_DIR}/src
broGenPolicies=${CMAKE_BINARY_DIR}/scripts
installedPolicies=${BRO_SCRIPT_INSTALL_PATH}:${BRO_SCRIPT_INSTALL_PATH}/site

2
cmake

@ -1 +1 @@
Subproject commit e1a7fd00a0a66d6831a239fe84f5fcfaa54e2c35
Subproject commit 0187b33a29d5ec824f940feff60dc5d8c2fe314f

View file

@ -82,7 +82,8 @@ class BroGeneric(ObjectDescription):
objects = self.env.domaindata['bro']['objects']
key = (self.objtype, name)
if key in objects:
if ( key in objects and self.objtype != "id" and
self.objtype != "type" ):
self.env.warn(self.env.docname,
'duplicate description of %s %s, ' %
(self.objtype, name) +
@ -150,6 +151,12 @@ class BroEnum(BroGeneric):
#self.indexnode['entries'].append(('single', indextext,
# targetname, targetname))
m = sig.split()
if len(m) < 2:
self.env.warn(self.env.docname,
"bro:enum directive missing argument(s)")
return
if m[1] == "Notice::Type":
if 'notices' not in self.env.domaindata['bro']:
self.env.domaindata['bro']['notices'] = []

View file

@ -10,7 +10,7 @@ File Analysis
script-layer depending on which network protocol was involved in the
file transfer. Scripts written to analyze files over one protocol
would have to be copied and modified to fit other protocols. The
file analysis framework (FAF) is an attempt to provide a generalized
file analysis framework (FAF) instead provides a generalized
presentation of file-related information. The information regarding
the protocol involved in transporting a file over the network is
still available, but it no longer has to dictate how one organizes

View file

@ -46,7 +46,7 @@ Script Reference
scripts/packages
scripts/index
scripts/builtins
scripts/bifs
scripts/proto-analyzers
Other Bro Components
--------------------

View file

@ -15,11 +15,11 @@ endif ()
#
# srcDir: the directory which contains broInput
# broInput: the file name of a bro policy script, any path prefix of this
# argument will be used to derive what path under policy/ the generated
# argument will be used to derive what path under scripts/ the generated
# documentation will be placed.
# group: optional name of group that the script documentation will belong to.
# If this is not given, .bif files automatically get their own group or
# the group is automatically by any path portion of the broInput argument.
# If this is not given, the group is automatically set to any path portion
# of the broInput argument.
#
# In addition to adding the makefile target, several CMake variables are set:
#
@ -45,12 +45,6 @@ macro(REST_TARGET srcDir broInput)
set(sumTextSrc ${absSrcPath})
set(ogSourceFile ${absSrcPath})
if (${extension} STREQUAL ".bif.bro")
set(ogSourceFile ${BIF_SRC_DIR}/${basename})
# the summary text is taken at configure time, but .bif.bro files
# may not have been generated yet, so read .bif file instead
set(sumTextSrc ${ogSourceFile})
endif ()
if (NOT relDstDir)
set(docName "${basename}")
@ -70,8 +64,6 @@ macro(REST_TARGET srcDir broInput)
if (NOT "${ARGN}" STREQUAL "")
set(group ${ARGN})
elseif (${extension} STREQUAL ".bif.bro")
set(group bifs)
elseif (relDstDir)
set(group ${relDstDir}/index)
# add package index to master package list if not already in it
@ -132,6 +124,29 @@ endmacro(REST_TARGET)
# Schedule Bro scripts for which to generate documentation.
include(DocSourcesList.cmake)
# This reST target is independent of a particular Bro script...
add_custom_command(OUTPUT proto-analyzers.rst
# delete any leftover state from previous bro runs
COMMAND "${CMAKE_COMMAND}"
ARGS -E remove_directory .state
# generate the reST documentation using bro
COMMAND BROPATH=${BROPATH}:${srcDir} BROMAGIC=${CMAKE_SOURCE_DIR}/magic ${CMAKE_BINARY_DIR}/src/bro
ARGS -b -Z base/init-bare.bro || (rm -rf .state *.log *.rst && exit 1)
# move generated doc into a new directory tree that
# defines the final structure of documents
COMMAND "${CMAKE_COMMAND}"
ARGS -E make_directory ${dstDir}
COMMAND "${CMAKE_COMMAND}"
ARGS -E copy proto-analyzers.rst ${dstDir}
# clean up the build directory
COMMAND rm
ARGS -rf .state *.log *.rst
DEPENDS bro
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "[Bro] Generating reST docs for proto-analyzers.rst"
)
list(APPEND ALL_REST_OUTPUTS proto-analyzers.rst)
# create temporary list of all docs to include in the master policy/index file
file(WRITE ${MASTER_POLICY_INDEX} "${MASTER_POLICY_INDEX_TEXT}")

View file

@ -16,15 +16,64 @@ rest_target(${CMAKE_CURRENT_SOURCE_DIR} example.bro internal)
rest_target(${psd} base/init-default.bro internal)
rest_target(${psd} base/init-bare.bro internal)
rest_target(${CMAKE_BINARY_DIR}/src base/bro.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/src base/const.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/src base/event.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/src base/file_analysis.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/src base/input.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/src base/logging.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/src base/reporter.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/src base/strings.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/src base/types.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/analyzer.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/bro.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/const.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/event.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/file_analysis.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/input.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/logging.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_ARP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_AYIYA.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_BackDoor.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_BitTorrent.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_ConnSize.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_DCE_RPC.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_DHCP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_DNS.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_FTP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_FTP.functions.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_File.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_FileHash.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_Finger.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_GTPv1.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_Gnutella.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_HTTP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_HTTP.functions.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_ICMP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_IRC.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_Ident.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_InterConn.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_Login.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_Login.functions.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_MIME.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_Modbus.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_NCP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_NTP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_NetBIOS.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_NetBIOS.functions.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_NetFlow.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_PIA.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_POP3.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_RPC.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_SMB.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_SMTP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_SMTP.functions.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_SOCKS.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_SSH.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_SSL.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_SSL.functions.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_SteppingStone.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_Syslog.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_TCP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_TCP.functions.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_Teredo.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_UDP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/plugins/Bro_ZIP.events.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/reporter.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/strings.bif.bro)
rest_target(${CMAKE_BINARY_DIR}/scripts base/bif/types.bif.bro)
rest_target(${psd} base/frameworks/analyzer/main.bro)
rest_target(${psd} base/frameworks/cluster/main.bro)
rest_target(${psd} base/frameworks/cluster/nodes/manager.bro)
rest_target(${psd} base/frameworks/cluster/nodes/proxy.bro)
@ -146,7 +195,6 @@ rest_target(${psd} policy/frameworks/software/vulnerable.bro)
rest_target(${psd} policy/integration/barnyard2/main.bro)
rest_target(${psd} policy/integration/barnyard2/types.bro)
rest_target(${psd} policy/integration/collective-intel/main.bro)
rest_target(${psd} policy/misc/analysis-groups.bro)
rest_target(${psd} policy/misc/app-metrics.bro)
rest_target(${psd} policy/misc/capture-loss.bro)
rest_target(${psd} policy/misc/detect-traceroute/main.bro)

View file

@ -1,5 +0,0 @@
.. This is a stub doc to which broxygen appends during the build process
Built-In Functions (BIFs)
=========================

View file

@ -54,11 +54,11 @@ global example_ports = {
443/tcp, 562/tcp,
} &redef;
# redefinitions of "dpd_config" are self-documenting and
# go into the generated doc's "Port Analysis" section
redef dpd_config += {
[ANALYZER_SSL] = [$ports = example_ports]
};
event bro_init()
{
Analyzer::register_for_ports(Analyzer::ANALYZER_SSL, example_ports);
}
# redefinitions of "Notice::Type" are self-documenting, but
# more information can be supplied in two different ways

View file

@ -67,12 +67,12 @@ sourcedir=${thisdir}/../..
echo "$statictext" > $outfile
bifs=`( cd ${sourcedir}/src && find . -name \*\.bif | sort )`
bifs=`( cd ${sourcedir}/build/scripts/base && find . -name \*\.bif.bro | sort )`
for file in $bifs
do
f=${file:2}.bro
echo "rest_target(\${CMAKE_BINARY_DIR}/src base/$f)" >> $outfile
f=${file:2}
echo "rest_target(\${CMAKE_BINARY_DIR}/scripts base/$f)" >> $outfile
done
scriptfiles=`( cd ${sourcedir}/scripts && find . -name \*\.bro | sort )`

View file

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

View file

@ -0,0 +1,179 @@
##! Framework for managing Bro's protocol analyzers.
##!
##! The analyzer framework allows to dynamically enable or disable analyzers, as
##! well as to manage the well-known ports which automatically activate a
##! particular analyzer for new connections.
##!
##! Protocol analyzers are identified by unique tags of type
##! :bro:type:`Analyzer::Tag`, such as :bro:enum:`Analyzer::ANALYZER_HTTP` and
##! :bro:enum:`Analyzer::ANALYZER_HTTP`. These tags are defined internally by
##! the analyzers themselves, and documented in their analyzer-specific
##! description along with the events that they generate.
module Analyzer;
export {
## If true, all available analyzers are initially disabled at startup. One
## can then selectively enable them with
## :bro:id:`Analyzer::enable_analyzer`.
global disable_all = F &redef;
## Enables an analyzer. Once enabled, the analyzer may be used for analysis
## of future connections as decided by Bro's dynamic protocol detection.
##
## tag: The tag of the analyzer to enable.
##
## Returns: True if the analyzer was successfully enabled.
global enable_analyzer: function(tag: Analyzer::Tag) : bool;
## Disables an analyzer. Once disabled, the analyzer will not be used
## further for analysis of future connections.
##
## tag: The tag of the analyzer to disable.
##
## Returns: True if the analyzer was successfully disabled.
global disable_analyzer: function(tag: Analyzer::Tag) : bool;
## Registers a set of well-known ports for an analyzer. If a future
## connection on one of these ports is seen, the analyzer will be
## automatically assigned to parsing it. The function *adds* to all ports
## already registered, it doesn't replace them.
##
## tag: The tag of the analyzer.
##
## ports: The set of well-known ports to associate with the analyzer.
##
## Returns: True if the ports were sucessfully registered.
global register_for_ports: function(tag: Analyzer::Tag, ports: set[port]) : bool;
## Registers an individual well-known port for an analyzer. If a future
## connection on this port is seen, the analyzer will be automatically
## assigned to parsing it. The function *adds* to all ports already
## registered, it doesn't replace them.
##
## tag: The tag of the analyzer.
##
## p: The well-known port to associate with the analyzer.
##
## Returns: True if the port was sucessfully registered.
global register_for_port: function(tag: Analyzer::Tag, p: port) : bool;
## Returns a set of all well-known ports currently registered for a
## specific analyzer.
##
## tag: The tag of the analyzer.
##
## Returns: The set of ports.
global registered_ports: function(tag: Analyzer::Tag) : set[port];
## Returns a table of all ports-to-analyzer mappings currently registered.
##
## Returns: A table mapping each analyzer to the set of ports
## registered for it.
global all_registered_ports: function() : table[Analyzer::Tag] of set[port];
## Translates an analyzer type to a string with the analyzer's name.
##
## tag: The analyzer tag.
##
## Returns: The analyzer name corresponding to the tag.
global name: function(tag: Analyzer::Tag) : string;
## Schedules an analyzer for a future connection originating from a given IP
## address and port.
##
## orig: The IP address originating a connection in the future.
## 0.0.0.0 can be used as a wildcard to match any originator address.
##
## resp: The IP address responding to a connection from *orig*.
##
## resp_p: The destination port at *resp*.
##
## analyzer: The analyzer ID.
##
## tout: A timeout interval after which the scheduling request will be
## discarded if the connection has not yet been seen.
##
## Returns: True if succesful.
global schedule_analyzer: function(orig: addr, resp: addr, resp_p: port,
analyzer: Analyzer::Tag, tout: interval) : bool;
## A set of analyzers to disable by default at startup. The default set
## contains legacy analyzers that are no longer supported.
global disabled_analyzers: set[Analyzer::Tag] = {
ANALYZER_INTERCONN,
ANALYZER_STEPPINGSTONE,
ANALYZER_BACKDOOR,
ANALYZER_TCPSTATS,
} &redef;
}
@load base/bif/analyzer.bif
global ports: table[Analyzer::Tag] of set[port];
event bro_init() &priority=5
{
if ( disable_all )
__disable_all_analyzers();
for ( a in disabled_analyzers )
disable_analyzer(a);
}
function enable_analyzer(tag: Analyzer::Tag) : bool
{
return __enable_analyzer(tag);
}
function disable_analyzer(tag: Analyzer::Tag) : bool
{
return __disable_analyzer(tag);
}
function register_for_ports(tag: Analyzer::Tag, ports: set[port]) : bool
{
local rc = T;
for ( p in ports )
{
if ( ! register_for_port(tag, p) )
rc = F;
}
return rc;
}
function register_for_port(tag: Analyzer::Tag, p: port) : bool
{
if ( ! __register_for_port(tag, p) )
return F;
if ( tag !in ports )
ports[tag] = set();
add ports[tag][p];
return T;
}
function registered_ports(tag: Analyzer::Tag) : set[port]
{
return tag in ports ? ports[tag] : set();
}
function all_registered_ports(): table[Analyzer::Tag] of set[port]
{
return ports;
}
function name(atype: Analyzer::Tag) : string
{
return __name(atype);
}
function schedule_analyzer(orig: addr, resp: addr, resp_p: port,
analyzer: Analyzer::Tag, tout: interval) : bool
{
return __schedule_analyzer(orig, resp, resp_p, analyzer, tout);
}

View file

@ -41,22 +41,11 @@ redef record connection += {
event bro_init() &priority=5
{
Log::create_stream(DPD::LOG, [$columns=Info]);
# Populate the internal DPD analysis variable.
for ( a in dpd_config )
{
for ( p in dpd_config[a]$ports )
{
if ( p !in dpd_analyzer_ports )
dpd_analyzer_ports[p] = set();
add dpd_analyzer_ports[p][a];
}
}
}
event protocol_confirmation(c: connection, atype: count, aid: count) &priority=10
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=10
{
local analyzer = analyzer_name(atype);
local analyzer = Analyzer::name(atype);
if ( fmt("-%s",analyzer) in c$service )
delete c$service[fmt("-%s", analyzer)];
@ -64,10 +53,10 @@ event protocol_confirmation(c: connection, atype: count, aid: count) &priority=1
add c$service[analyzer];
}
event protocol_violation(c: connection, atype: count, aid: count,
event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count,
reason: string) &priority=10
{
local analyzer = analyzer_name(atype);
local analyzer = Analyzer::name(atype);
# If the service hasn't been confirmed yet, don't generate a log message
# for the protocol violation.
if ( analyzer !in c$service )
@ -86,7 +75,7 @@ event protocol_violation(c: connection, atype: count, aid: count,
c$dpd = info;
}
event protocol_violation(c: connection, atype: count, aid: count, reason: string) &priority=5
event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count, reason: string) &priority=5
{
if ( !c?$dpd || aid in c$dpd$disabled_aids )
return;
@ -100,7 +89,7 @@ event protocol_violation(c: connection, atype: count, aid: count, reason: string
add c$dpd$disabled_aids[aid];
}
event protocol_violation(c: connection, atype: count, aid: count,
event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count,
reason: string) &priority=-5
{
if ( c?$dpd )

View file

@ -1,7 +1,7 @@
##! An interface for driving the analysis of files, possibly independent of
##! any network protocol over which they're transported.
@load base/file_analysis.bif
@load base/bif/file_analysis.bif
@load base/frameworks/logging
@load base/utils/site
@ -105,7 +105,7 @@ export {
## A table that can be used to disable file analysis completely for
## any files transferred over given network protocol analyzers.
const disable: table[AnalyzerTag] of bool = table() &redef;
const disable: table[Analyzer::Tag] of bool = table() &redef;
## The salt concatenated to unique file handle strings generated by
## :bro:see:`get_file_handle` before hashing them in to a file id

View file

@ -125,7 +125,6 @@ export {
## A file analyis input stream type used to forward input data to the
## file analysis framework.
type AnalysisDescription: record {
## String that allows the reader to find the source.
## For `READER_ASCII`, this is the filename.
source: string;
@ -186,7 +185,7 @@ export {
global end_of_data: event(name: string, source:string);
}
@load base/input.bif
@load base/bif/input.bif
module Input;

View file

@ -6,4 +6,12 @@ export {
## Separator between input records.
## Please note that the separator has to be exactly one character long
const record_separator = "\n" &redef;
## Event that is called when a process created by the raw reader exits.
##
## name: name of the input stream
## source: source of the input stream
## exit_code: exit code of the program, or number of the signal that forced the program to exit
## signal_exit: false when program exitted normally, true when program was forced to exit by a signal
global process_finished: event(name: string, source:string, exit_code:count, signal_exit:bool);
}

View file

@ -366,7 +366,7 @@ export {
# We keep a script-level copy of all filters so that we can manipulate them.
global filters: table[ID, string] of Filter;
@load base/logging.bif # Needs Filter and Stream defined.
@load base/bif/logging.bif # Needs Filter and Stream defined.
module Log;

View file

@ -9,7 +9,7 @@
##! Note that this framework deals with the handling of internally generated
##! reporter messages, for the interface in to actually creating interface
##! into actually creating reporter messages from the scripting layer, use
##! the built-in functions in :doc:`/scripts/base/reporter.bif`.
##! the built-in functions in :doc:`/scripts/base/bif/reporter.bif`.
module Reporter;

View file

@ -83,19 +83,17 @@ export {
}
const ayiya_ports = { 5072/udp };
redef dpd_config += { [ANALYZER_AYIYA] = [$ports = ayiya_ports] };
const teredo_ports = { 3544/udp };
redef dpd_config += { [ANALYZER_TEREDO] = [$ports = teredo_ports] };
const gtpv1_ports = { 2152/udp, 2123/udp };
redef dpd_config += { [ANALYZER_GTPV1] = [$ports = gtpv1_ports] };
redef likely_server_ports += { ayiya_ports, teredo_ports, gtpv1_ports };
event bro_init() &priority=5
{
Log::create_stream(Tunnel::LOG, [$columns=Info]);
Analyzer::register_for_ports(Analyzer::ANALYZER_AYIYA, ayiya_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_TEREDO, teredo_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_GTPV1, gtpv1_ports);
}
function register_all(ecv: EncapsulatingConnVector)

View file

@ -1,5 +1,5 @@
@load base/const.bif
@load base/types.bif
@load base/bif/const.bif.bro
@load base/bif/types.bif
# Type declarations
@ -222,17 +222,6 @@ type endpoint_stats: record {
endian_type: count;
};
## A unique analyzer instance ID. Each time instantiates a protocol analyzers
## for a connection, it assigns it a unique ID that can be used to reference
## that instance.
##
## .. bro:see:: analyzer_name disable_analyzer protocol_confirmation
## protocol_violation
##
## .. todo::While we declare an alias for the type here, the events/functions still
## use ``count``. That should be changed.
type AnalyzerID: count;
module Tunnel;
export {
## Records the identity of an encapsulating parent of a tunneled connection.
@ -713,9 +702,9 @@ type entropy_test_result: record {
};
# Prototypes of Bro built-in functions.
@load base/strings.bif
@load base/bro.bif
@load base/reporter.bif
@load base/bif/strings.bif
@load base/bif/bro.bif
@load base/bif/reporter.bif
## Deprecated. This is superseded by the new logging framework.
global log_file_name: function(tag: string): string &redef;
@ -2723,7 +2712,7 @@ export {
}
module GLOBAL;
@load base/event.bif
@load base/bif/event.bif
## BPF filter the user has set via the -f command line options. Empty if none.
const cmd_line_bpf_filter = "" &redef;
@ -2913,34 +2902,11 @@ const remote_trace_sync_peers = 0 &redef;
## consistency check.
const remote_check_sync_consistency = F &redef;
## Analyzer tags. The core automatically defines constants
## ``ANALYZER_<analyzer-name>*``, e.g., ``ANALYZER_HTTP``.
##
## .. bro:see:: dpd_config
##
## .. todo::We should autodoc these automaticallty generated constants.
type AnalyzerTag: count;
## Set of ports activating a particular protocol analysis.
##
## .. bro:see:: dpd_config
type dpd_protocol_config: record {
ports: set[port] &optional; ##< Set of ports.
};
## Port configuration for Bro's "dynamic protocol detection". Protocol
## analyzers can be activated via either well-known ports or content analysis.
## This table defines the ports.
##
## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size
## dpd_match_only_beginning dpd_ignore_ports
const dpd_config: table[AnalyzerTag] of dpd_protocol_config = {} &redef;
## Reassemble the beginning of all TCP connections before doing
## signature-matching. Enabling this provides more accurate matching at the
## expensive of CPU cycles.
##
## .. bro:see:: dpd_config dpd_buffer_size
## .. bro:see:: dpd_buffer_size
## dpd_match_only_beginning dpd_ignore_ports
##
## .. note:: Despite the name, this option affects *all* signature matching, not
@ -2955,24 +2921,24 @@ const dpd_reassemble_first_packets = T &redef;
## activated afterwards. Then only analyzers that can deal with partial
## connections will be able to analyze the session.
##
## .. bro:see:: dpd_reassemble_first_packets dpd_config dpd_match_only_beginning
## .. bro:see:: dpd_reassemble_first_packets dpd_match_only_beginning
## dpd_ignore_ports
const dpd_buffer_size = 1024 &redef;
## If true, stops signature matching if dpd_buffer_size has been reached.
##
## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size
## dpd_config dpd_ignore_ports
## dpd_ignore_ports
##
## .. note:: Despite the name, this option affects *all* signature matching, not
## only signatures used for dynamic protocol detection.
const dpd_match_only_beginning = T &redef;
## If true, don't consider any ports for deciding which protocol analyzer to
## use. If so, the value of :bro:see:`dpd_config` is ignored.
## use.
##
## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size
## dpd_match_only_beginning dpd_config
## dpd_match_only_beginning
const dpd_ignore_ports = F &redef;
## Ports which the core considers being likely used by servers. For ports in
@ -2980,13 +2946,6 @@ const dpd_ignore_ports = F &redef;
## connection if it misses the initial handshake.
const likely_server_ports: set[port] &redef;
## Deprated. Set of all ports for which we know an analyzer, built by
## :doc:`/scripts/base/frameworks/dpd/main`.
##
## .. todo::This should be defined by :doc:`/scripts/base/frameworks/dpd/main`
## itself we still need it.
global dpd_analyzer_ports: table[port] of set[AnalyzerTag];
## Per-incident timer managers are drained after this amount of inactivity.
const timer_mgr_inactivity_timeout = 1 min &redef;
@ -3095,10 +3054,12 @@ module GLOBAL;
## Number of bytes per packet to capture from live interfaces.
const snaplen = 8192 &redef;
# Load the logging framework here because it uses fairly deep integration with
# Load BiFs defined by plugins.
@load base/bif/plugins
# Load these frameworks here because they use fairly deep integration with
# BiFs and script-land defined types.
@load base/frameworks/logging
@load base/frameworks/input
@load base/frameworks/analyzer
@load base/frameworks/files

View file

@ -22,6 +22,7 @@
# loaded in base/init-bare.bro
#@load base/frameworks/logging
@load base/frameworks/notice
@load base/frameworks/analyzer
@load base/frameworks/dpd
@load base/frameworks/signatures
@load base/frameworks/packet-filter

View file

@ -6,9 +6,9 @@ module Conn;
export {
## Define inactivity timeouts by the service detected being used over
## the connection.
const analyzer_inactivity_timeouts: table[AnalyzerTag] of interval = {
const analyzer_inactivity_timeouts: table[Analyzer::Tag] of interval = {
# For interactive services, allow longer periods of inactivity.
[[ANALYZER_SSH, ANALYZER_FTP]] = 1 hrs,
[[Analyzer::ANALYZER_SSH, Analyzer::ANALYZER_FTP]] = 1 hrs,
} &redef;
## Define inactivity timeouts based on common protocol ports.
@ -18,7 +18,7 @@ export {
}
event protocol_confirmation(c: connection, atype: count, aid: count)
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count)
{
if ( atype in analyzer_inactivity_timeouts )
set_inactivity_timeout(c$id, analyzer_inactivity_timeouts[atype]);

View file

@ -130,19 +130,13 @@ redef capture_filters += {
["netbios-ns"] = "udp port 137",
};
const dns_ports = { 53/udp, 53/tcp, 137/udp, 5353/udp, 5355/udp };
redef dpd_config += { [ANALYZER_DNS] = [$ports = dns_ports] };
const dns_udp_ports = { 53/udp, 137/udp, 5353/udp, 5355/udp };
const dns_tcp_ports = { 53/tcp };
redef dpd_config += { [ANALYZER_DNS_UDP_BINPAC] = [$ports = dns_udp_ports] };
redef dpd_config += { [ANALYZER_DNS_TCP_BINPAC] = [$ports = dns_tcp_ports] };
redef likely_server_ports += { 53/udp, 53/tcp, 137/udp, 5353/udp, 5355/udp };
const ports = { 53/udp, 53/tcp, 137/udp, 5353/udp, 5355/udp };
redef likely_server_ports += { ports };
event bro_init() &priority=5
{
Log::create_stream(DNS::LOG, [$columns=Info, $ev=log_dns]);
Analyzer::register_for_ports(Analyzer::ANALYZER_DNS, ports);
}
function new_session(c: connection, trans_id: count): Info

View file

@ -111,11 +111,10 @@ redef record connection += {
};
# Configure DPD
const ports = { 21/tcp, 2811/tcp } &redef; # 2811/tcp is GridFTP.
redef capture_filters += { ["ftp"] = "port 21 and port 2811" };
redef dpd_config += { [ANALYZER_FTP] = [$ports = ports] };
redef likely_server_ports += { 21/tcp, 2811/tcp };
const ports = { 21/tcp, 2811/tcp };
redef likely_server_ports += { ports };
# Establish the variable for tracking expected connections.
global ftp_data_expected: table[addr, port] of Info &read_expire=5mins;
@ -123,6 +122,7 @@ global ftp_data_expected: table[addr, port] of Info &read_expire=5mins;
event bro_init() &priority=5
{
Log::create_stream(FTP::LOG, [$columns=Info, $ev=log_ftp]);
Analyzer::register_for_ports(Analyzer::ANALYZER_FTP, ports);
}
## A set of commands where the argument can be expected to refer
@ -221,7 +221,7 @@ function add_expected_data_channel(s: Info, chan: ExpectedDataChannel)
s$passive = chan$passive;
s$data_channel = chan;
ftp_data_expected[chan$resp_h, chan$resp_p] = s;
expect_connection(chan$orig_h, chan$resp_h, chan$resp_p, ANALYZER_FTP_DATA,
Analyzer::schedule_analyzer(chan$orig_h, chan$resp_h, chan$resp_p, Analyzer::ANALYZER_FTP_DATA,
5mins);
}
@ -338,7 +338,7 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) &prior
}
}
event expected_connection_seen(c: connection, a: count) &priority=10
event scheduled_analyzer_applied(c: connection, a: Analyzer::Tag) &priority=10
{
local id = c$id;
if ( [id$resp_h, id$resp_p] in ftp_data_expected )

View file

@ -127,29 +127,26 @@ redef record connection += {
http_state: State &optional;
};
# Initialize the HTTP logging stream.
event bro_init() &priority=5
{
Log::create_stream(HTTP::LOG, [$columns=Info, $ev=log_http]);
}
# DPD configuration.
const ports = {
80/tcp, 81/tcp, 631/tcp, 1080/tcp, 3128/tcp,
8000/tcp, 8080/tcp, 8888/tcp,
};
redef dpd_config += {
[[ANALYZER_HTTP, ANALYZER_HTTP_BINPAC]] = [$ports = ports],
};
redef capture_filters += {
["http"] = "tcp and port (80 or 81 or 631 or 1080 or 3138 or 8000 or 8080 or 8888)"
};
redef likely_server_ports += {
80/tcp, 81/tcp, 631/tcp, 1080/tcp, 3138/tcp,
const ports = {
80/tcp, 81/tcp, 631/tcp, 1080/tcp, 3128/tcp,
8000/tcp, 8080/tcp, 8888/tcp,
};
redef likely_server_ports += { ports };
# Initialize the HTTP logging stream and ports.
event bro_init() &priority=5
{
Log::create_stream(HTTP::LOG, [$columns=Info, $ev=log_http]);
Analyzer::register_for_ports(Analyzer::ANALYZER_HTTP, ports);
}
function code_in_range(c: count, min: count, max: count) : bool
{
return c >= min && c <= max;

View file

@ -70,11 +70,11 @@ event irc_dcc_message(c: connection, is_orig: bool,
c$irc$dcc_file_name = argument;
c$irc$dcc_file_size = size;
local p = count_to_port(dest_port, tcp);
expect_connection(to_addr("0.0.0.0"), address, p, ANALYZER_IRC_DATA, 5 min);
Analyzer::schedule_analyzer(0.0.0.0, address, p, Analyzer::ANALYZER_IRC_DATA, 5 min);
dcc_expected_transfers[address, p] = c$irc;
}
event expected_connection_seen(c: connection, a: count) &priority=10
event expected_connection_seen(c: connection, a: Analyzer::Tag) &priority=10
{
local id = c$id;
if ( [id$resp_h, id$resp_p] in dcc_expected_transfers )

View file

@ -45,14 +45,13 @@ redef capture_filters += { ["irc-6668"] = "port 6668" };
redef capture_filters += { ["irc-6669"] = "port 6669" };
# DPD configuration.
const irc_ports = { 6666/tcp, 6667/tcp, 6668/tcp, 6669/tcp };
redef dpd_config += { [ANALYZER_IRC] = [$ports = irc_ports] };
redef likely_server_ports += { 6666/tcp, 6667/tcp, 6668/tcp, 6669/tcp };
const ports = { 6666/tcp, 6667/tcp, 6668/tcp, 6669/tcp };
redef likely_server_ports += { ports };
event bro_init() &priority=5
{
Log::create_stream(IRC::LOG, [$columns=Info, $ev=irc_log]);
Analyzer::register_for_ports(Analyzer::ANALYZER_IRC, ports);
}
function new_session(c: connection): Info

View file

@ -31,12 +31,14 @@ redef record connection += {
# Configure DPD and the packet filter.
redef capture_filters += { ["modbus"] = "tcp port 502" };
redef dpd_config += { [ANALYZER_MODBUS] = [$ports = set(502/tcp)] };
redef likely_server_ports += { 502/tcp };
const ports = { 502/tcp };
redef likely_server_ports += { ports };
event bro_init() &priority=5
{
Log::create_stream(Modbus::LOG, [$columns=Info, $ev=log_modbus]);
Analyzer::register_for_ports(Analyzer::ANALYZER_MODBUS, ports);
}
event modbus_message(c: connection, headers: ModbusHeaders, is_orig: bool) &priority=5

View file

@ -74,9 +74,6 @@ export {
const mail_path_capture = ALL_HOSTS &redef;
global log_smtp: event(rec: Info);
## Configure the default ports for SMTP analysis.
const ports = { 25/tcp, 587/tcp } &redef;
}
redef record connection += {
@ -86,13 +83,14 @@ redef record connection += {
# Configure DPD
redef capture_filters += { ["smtp"] = "tcp port 25 or tcp port 587" };
redef dpd_config += { [ANALYZER_SMTP] = [$ports = ports] };
redef likely_server_ports += { 25/tcp, 587/tcp };
const ports = { 25/tcp, 587/tcp };
redef likely_server_ports += { ports };
event bro_init() &priority=5
{
Log::create_stream(SMTP::LOG, [$columns=SMTP::Info, $ev=log_smtp]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SMTP, ports);
}
function find_address_in_smtp_header(header: string): string

View file

@ -34,9 +34,13 @@ export {
global log_socks: event(rec: Info);
}
const ports = { 1080/tcp };
redef likely_server_ports += { ports };
event bro_init() &priority=5
{
Log::create_stream(SOCKS::LOG, [$columns=Info, $ev=log_socks]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SOCKS, ports);
}
redef record connection += {
@ -45,7 +49,6 @@ redef record connection += {
# Configure DPD
redef capture_filters += { ["socks"] = "tcp port 1080" };
redef dpd_config += { [ANALYZER_SOCKS] = [$ports = set(1080/tcp)] };
redef likely_server_ports += { 1080/tcp };
function set_session(c: connection, version: count)

View file

@ -71,10 +71,11 @@ export {
}
# Configure DPD and the packet filter
redef capture_filters += { ["ssh"] = "tcp port 22" };
redef dpd_config += { [ANALYZER_SSH] = [$ports = set(22/tcp)] };
redef likely_server_ports += { 22/tcp };
const ports = { 22/tcp };
redef capture_filters += { ["ssh"] = "tcp port 22" };
redef likely_server_ports += { ports };
redef record connection += {
ssh: Info &optional;
@ -83,6 +84,7 @@ redef record connection += {
event bro_init() &priority=5
{
Log::create_stream(SSH::LOG, [$columns=Info, $ev=log_ssh]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SSH, ports);
}
function set_session(c: connection)
@ -176,6 +178,7 @@ event ssh_watcher(c: connection)
if ( ! connection_exists(id) )
return;
lookup_connection(c$id);
check_ssh_connection(c, F);
if ( ! c$ssh$done )
schedule +15secs { ssh_watcher(c) };

View file

@ -94,11 +94,6 @@ redef record Info += {
delay_tokens: set[string] &optional;
};
event bro_init() &priority=5
{
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl]);
}
redef capture_filters += {
["ssl"] = "tcp port 443",
["nntps"] = "tcp port 563",
@ -117,23 +112,15 @@ redef capture_filters += {
const ports = {
443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp,
989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp
};
} &redef;
redef dpd_config += {
[[ANALYZER_SSL]] = [$ports = ports]
};
redef likely_server_ports += { ports };
redef likely_server_ports += {
443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp,
989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp
};
# A queue that buffers log records.
global log_delay_queue: table[count] of Info;
# The top queue index where records are added.
global log_delay_queue_head = 0;
# The bottom queue index that points to the next record to be flushed.
global log_delay_queue_tail = 0;
event bro_init() &priority=5
{
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SSL, ports);
}
function set_session(c: connection)
{
@ -144,26 +131,17 @@ function set_session(c: connection)
function delay_log(info: Info, token: string)
{
if ( ! info?$delay_tokens )
info$delay_tokens = set();
add info$delay_tokens[token];
log_delay_queue[log_delay_queue_head] = info;
++log_delay_queue_head;
}
function undelay_log(info: Info, token: string)
{
if ( token in info$delay_tokens )
if ( info?$delay_tokens && token in info$delay_tokens )
delete info$delay_tokens[token];
}
global log_record: function(info: Info);
event delay_logging(info: Info)
{
log_record(info);
}
function log_record(info: Info)
{
if ( ! info?$delay_tokens || |info$delay_tokens| == 0 )
@ -172,26 +150,14 @@ function log_record(info: Info)
}
else
{
for ( unused_index in log_delay_queue )
when ( |info$delay_tokens| == 0 )
{
if ( log_delay_queue_head == log_delay_queue_tail )
return;
if ( |log_delay_queue[log_delay_queue_tail]$delay_tokens| > 0 )
{
if ( info$ts + max_log_delay > network_time() )
{
schedule 1sec { delay_logging(info) };
return;
log_record(info);
}
else
timeout max_log_delay
{
Reporter::info(fmt("SSL delay tokens not released in time (%s)",
info$delay_tokens));
}
}
Log::write(SSL::LOG, log_delay_queue[log_delay_queue_tail]);
delete log_delay_queue[log_delay_queue_tail];
++log_delay_queue_tail;
Reporter::info(fmt("SSL delay tokens not released in time (%s tokens remaining)",
|info$delay_tokens|));
}
}
}
@ -288,28 +254,16 @@ event ssl_established(c: connection) &priority=-5
finish(c);
}
event protocol_confirmation(c: connection, atype: count, aid: count) &priority=5
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=5
{
# Check by checking for existence of c$ssl record.
if ( c?$ssl && analyzer_name(atype) == "SSL" )
if ( c?$ssl && atype == Analyzer::ANALYZER_SSL )
c$ssl$analyzer_id = aid;
}
event protocol_violation(c: connection, atype: count, aid: count,
event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count,
reason: string) &priority=5
{
if ( c?$ssl )
finish(c);
}
event bro_done()
{
if ( |log_delay_queue| == 0 )
return;
for ( unused_index in log_delay_queue )
{
Log::write(SSL::LOG, log_delay_queue[log_delay_queue_tail]);
delete log_delay_queue[log_delay_queue_tail];
++log_delay_queue_tail;
}
}

View file

@ -27,10 +27,9 @@ export {
}
redef capture_filters += { ["syslog"] = "port 514" };
const ports = { 514/udp } &redef;
redef dpd_config += { [ANALYZER_SYSLOG_BINPAC] = [$ports = ports] };
redef likely_server_ports += { 514/udp };
const ports = { 514/udp };
redef likely_server_ports += { ports };
redef record connection += {
syslog: Info &optional;
@ -39,6 +38,7 @@ redef record connection += {
event bro_init() &priority=5
{
Log::create_stream(Syslog::LOG, [$columns=Info]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SYSLOG, ports);
}
event syslog_message(c: connection, facility: count, severity: count, msg: string) &priority=5

View file

@ -21,22 +21,22 @@ export {
type dir: enum { NONE, INCOMING, OUTGOING, BOTH };
const valids: table[count, addr, port] of dir = {
const valids: table[Analyzer::Tag, addr, port] of dir = {
# A couple of ports commonly used for benign HTTP servers.
# For now we want to see everything.
# [ANALYZER_HTTP, 0.0.0.0, 81/tcp] = OUTGOING,
# [ANALYZER_HTTP, 0.0.0.0, 82/tcp] = OUTGOING,
# [ANALYZER_HTTP, 0.0.0.0, 83/tcp] = OUTGOING,
# [ANALYZER_HTTP, 0.0.0.0, 88/tcp] = OUTGOING,
# [ANALYZER_HTTP, 0.0.0.0, 8001/tcp] = OUTGOING,
# [ANALYZER_HTTP, 0.0.0.0, 8090/tcp] = OUTGOING,
# [ANALYZER_HTTP, 0.0.0.0, 8081/tcp] = OUTGOING,
# [Analyzer::ANALYZER_HTTP, 0.0.0.0, 81/tcp] = OUTGOING,
# [Analyzer::ANALYZER_HTTP, 0.0.0.0, 82/tcp] = OUTGOING,
# [Analyzer::ANALYZER_HTTP, 0.0.0.0, 83/tcp] = OUTGOING,
# [Analyzer::ANALYZER_HTTP, 0.0.0.0, 88/tcp] = OUTGOING,
# [Analyzer::ANALYZER_HTTP, 0.0.0.0, 8001/tcp] = OUTGOING,
# [Analyzer::ANALYZER_HTTP, 0.0.0.0, 8090/tcp] = OUTGOING,
# [Analyzer::ANALYZER_HTTP, 0.0.0.0, 8081/tcp] = OUTGOING,
#
# [ANALYZER_HTTP, 0.0.0.0, 6346/tcp] = BOTH, # Gnutella
# [ANALYZER_HTTP, 0.0.0.0, 6347/tcp] = BOTH, # Gnutella
# [ANALYZER_HTTP, 0.0.0.0, 6348/tcp] = BOTH, # Gnutella
# [Analyzer::ANALYZER_HTTP, 0.0.0.0, 6346/tcp] = BOTH, # Gnutella
# [Analyzer::ANALYZER_HTTP, 0.0.0.0, 6347/tcp] = BOTH, # Gnutella
# [Analyzer::ANALYZER_HTTP, 0.0.0.0, 6348/tcp] = BOTH, # Gnutella
} &redef;
# Set of analyzers for which we suppress Server_Found notices
@ -44,8 +44,8 @@ export {
# log files, this also saves memory because for these we don't
# need to remember which servers we already have reported, which
# for some can be a lot.
const suppress_servers: set [count] = {
# ANALYZER_HTTP
const suppress_servers: set [Analyzer::Tag] = {
# Analyzer::ANALYZER_HTTP
} &redef;
# We consider a connection to use a protocol X if the analyzer for X
@ -60,7 +60,7 @@ export {
# Entry point for other analyzers to report that they recognized
# a certain (sub-)protocol.
global found_protocol: function(c: connection, analyzer: count,
global found_protocol: function(c: connection, analyzer: Analyzer::Tag,
protocol: string);
# Table keeping reported (server, port, analyzer) tuples (and their
@ -70,7 +70,7 @@ export {
}
# Table that tracks currently active dynamic analyzers per connection.
global conns: table[conn_id] of set[count];
global conns: table[conn_id] of set[Analyzer::Tag];
# Table of reports by other analyzers about the protocol used in a connection.
global protocols: table[conn_id] of set[string];
@ -80,7 +80,7 @@ type protocol : record {
sub: string; # "sub-protocols" reported by other sources
};
function get_protocol(c: connection, a: count) : protocol
function get_protocol(c: connection, a: Analyzer::Tag) : protocol
{
local str = "";
if ( c$id in protocols )
@ -89,7 +89,7 @@ function get_protocol(c: connection, a: count) : protocol
str = |str| > 0 ? fmt("%s/%s", str, p) : p;
}
return [$a=analyzer_name(a), $sub=str];
return [$a=Analyzer::name(a), $sub=str];
}
function fmt_protocol(p: protocol) : string
@ -97,7 +97,7 @@ function fmt_protocol(p: protocol) : string
return p$sub != "" ? fmt("%s (via %s)", p$sub, p$a) : p$a;
}
function do_notice(c: connection, a: count, d: dir)
function do_notice(c: connection, a: Analyzer::Tag, d: dir)
{
if ( d == BOTH )
return;
@ -113,7 +113,7 @@ function do_notice(c: connection, a: count, d: dir)
NOTICE([$note=Protocol_Found,
$msg=fmt("%s %s on port %s", id_string(c$id), s, c$id$resp_p),
$sub=s, $conn=c, $n=a]);
$sub=s, $conn=c]);
# We report multiple Server_Found's per host if we find a new
# sub-protocol.
@ -129,7 +129,7 @@ function do_notice(c: connection, a: count, d: dir)
NOTICE([$note=Server_Found,
$msg=fmt("%s: %s server on port %s%s", c$id$resp_h, s,
c$id$resp_p, (known ? " (update)" : "")),
$p=c$id$resp_p, $sub=s, $conn=c, $src=c$id$resp_h, $n=a]);
$p=c$id$resp_p, $sub=s, $conn=c, $src=c$id$resp_h]);
if ( ! known )
servers[c$id$resp_h, c$id$resp_p, p$a] = set();
@ -194,10 +194,10 @@ event connection_state_remove(c: connection)
report_protocols(c);
}
event protocol_confirmation(c: connection, atype: count, aid: count)
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count)
{
# Don't report anything running on a well-known port.
if ( atype in dpd_config && c$id$resp_p in dpd_config[atype]$ports )
if ( c$id$resp_p in Analyzer::registered_ports(atype) )
return;
if ( c$id in conns )
@ -214,11 +214,10 @@ event protocol_confirmation(c: connection, atype: count, aid: count)
}
}
function found_protocol(c: connection, analyzer: count, protocol: string)
function found_protocol(c: connection, atype: Analyzer::Tag, protocol: string)
{
# Don't report anything running on a well-known port.
if ( analyzer in dpd_config &&
c$id$resp_p in dpd_config[analyzer]$ports )
if ( c$id$resp_p in Analyzer::registered_ports(atype) )
return;
if ( c$id !in protocols )

View file

@ -20,7 +20,7 @@ export {
}
event protocol_violation(c: connection, atype: count, aid: count,
event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count,
reason: string) &priority=4
{
if ( ! c?$dpd ) return;

View file

@ -1,31 +0,0 @@
##! This script gives the capability to selectively enable and disable event
##! groups at runtime. No events will be raised for all members of a disabled
##! event group.
module AnalysisGroups;
export {
## By default, all event groups are enabled.
## We disable all groups in this table.
const disabled: set[string] &redef;
}
# Set to remember all groups which were disabled by the last update.
global currently_disabled: set[string];
# This is the event that the control framework uses when it needs to indicate
# that an update control action happened.
event Control::configuration_update()
{
# Reenable those which are not to be disabled anymore.
for ( g in currently_disabled )
if ( g !in disabled )
enable_event_group(g);
# Disable those which are not already disabled.
for ( g in disabled )
if ( g !in currently_disabled )
disable_event_group(g);
currently_disabled = copy(disabled);
}

View file

@ -87,7 +87,7 @@ function known_services_done(c: connection)
event log_it(network_time(), id$resp_h, id$resp_p, c$service);
}
event protocol_confirmation(c: connection, atype: count, aid: count) &priority=-5
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=-5
{
known_services_done(c);
}

View file

@ -31,7 +31,6 @@
@load integration/barnyard2/types.bro
@load integration/collective-intel/__load__.bro
@load integration/collective-intel/main.bro
@load misc/analysis-groups.bro
@load misc/app-metrics.bro
@load misc/capture-loss.bro
@load misc/detect-traceroute/__load__.bro

View file

@ -1,403 +0,0 @@
// Main analyzer interface.
#ifndef ANALYZER_H
#define ANALYZER_H
#include <list>
#include "AnalyzerTags.h"
#include "Conn.h"
#include "Obj.h"
class DPM;
class PIA;
class Analyzer;
typedef list<Analyzer*> analyzer_list;
typedef void (Analyzer::*analyzer_timer_func)(double t);
// FIXME: This is a copy of ConnectionTimer, which we may eventually be
// able to get rid of.
class AnalyzerTimer : public Timer {
public:
AnalyzerTimer(Analyzer* arg_analyzer, analyzer_timer_func arg_timer,
double arg_t, int arg_do_expire, TimerType arg_type)
: Timer(arg_t, arg_type)
{ Init(arg_analyzer, arg_timer, arg_do_expire); }
virtual ~AnalyzerTimer();
void Dispatch(double t, int is_expire);
protected:
AnalyzerTimer() {}
void Init(Analyzer* analyzer, analyzer_timer_func timer, int do_expire);
Analyzer* analyzer;
analyzer_timer_func timer;
int do_expire;
};
// Main analyzer interface.
//
// Each analyzer is part of a tree, having a parent analyzer and an
// arbitrary number of child analyzers. Each analyzer also has a list of
// *suppport analyzers*. All its input first passes through this list of
// support analyzers, which can perform arbitrary preprocessing. Support
// analyzers share the same interface as regular analyzers, except that
// they are unidirectional, i.e., they see only one side of a connection.
//
// When overiding any of these methods, always make sure to call the
// base-class version first.
class SupportAnalyzer;
class OutputHandler;
class Analyzer {
public:
Analyzer(AnalyzerTag::Tag tag, Connection* conn);
virtual ~Analyzer();
virtual void Init();
virtual void Done();
// Pass data to the analyzer (it's automatically passed through its
// support analyzers first). We have packet-wise and stream-wise
// interfaces. For the packet-interface, some analyzers may require
// more information than others, so IP/caplen and seq may or may
// not be set.
void NextPacket(int len, const u_char* data, bool orig,
int seq = -1, const IP_Hdr* ip = 0, int caplen = 0);
void NextStream(int len, const u_char* data, bool is_orig);
// Used for data that can't be delivered (e.g., due to a previous
// sequence hole/gap).
void NextUndelivered(int seq, int len, bool is_orig);
// Report message boundary. (See EndOfData() below.)
void NextEndOfData(bool orig);
// Pass data on to all child analyzer(s). For SupportAnalyzers (see
// below), this is overridden to pass it on to the next sibling (or
// finally to the parent, if it's the last support analyzer).
//
// If we have an associated OutputHandler (see below), the data is
// additionally passed to that, too. For SupportAnalyzers, it is *only*
// delivered to the OutputHandler.
virtual void ForwardPacket(int len, const u_char* data,
bool orig, int seq,
const IP_Hdr* ip, int caplen);
virtual void ForwardStream(int len, const u_char* data, bool orig);
virtual void ForwardUndelivered(int seq, int len, bool orig);
// Report a message boundary to all child analyzers
virtual void ForwardEndOfData(bool orig);
AnalyzerID GetID() const { return id; }
Connection* Conn() const { return conn; }
// An OutputHandler can be used to get access to data extracted by this
// analyzer (i.e., all data which is passed to
// Forward{Packet,Stream,Undelivered}). We take the ownership of
// the handler.
class OutputHandler {
public:
virtual ~OutputHandler() { }
virtual void DeliverPacket(int len, const u_char* data,
bool orig, int seq,
const IP_Hdr* ip, int caplen)
{ }
virtual void DeliverStream(int len, const u_char* data,
bool orig) { }
virtual void Undelivered(int seq, int len, bool orig) { }
};
OutputHandler* GetOutputHandler() const { return output_handler; }
void SetOutputHandler(OutputHandler* handler)
{ output_handler = handler; }
// If an analyzer was triggered by a signature match, this returns the
// name of the signature; nil if not.
const Rule* Signature() const { return signature; }
void SetSignature(const Rule* sig) { signature = sig; }
void SetSkip(bool do_skip) { skip = do_skip; }
bool Skipping() const { return skip; }
bool IsFinished() const { return finished; }
AnalyzerTag::Tag GetTag() const { return tag; }
const char* GetTagName() const;
static AnalyzerTag::Tag GetTag(const char* tag);
static const char* GetTagName(AnalyzerTag::Tag tag);
static bool IsAvailable(AnalyzerTag::Tag tag)
{ return analyzer_configs[tag].available(); }
// Management of the tree.
//
// We immediately discard an added analyzer if there's already a child
// of the same type.
void AddChildAnalyzer(Analyzer* analyzer)
{ AddChildAnalyzer(analyzer, true); }
Analyzer* AddChildAnalyzer(AnalyzerTag::Tag tag);
void RemoveChildAnalyzer(Analyzer* analyzer);
void RemoveChildAnalyzer(AnalyzerID id);
bool HasChildAnalyzer(AnalyzerTag::Tag tag);
// Recursive; returns nil if not found.
Analyzer* FindChild(AnalyzerID id);
// Recursive; returns first found, or nil.
Analyzer* FindChild(AnalyzerTag::Tag tag);
const analyzer_list& GetChildren() { return children; }
Analyzer* Parent() const { return parent; }
void SetParent(Analyzer* p) { parent = p; }
// Remove this child analyzer from the parent's list.
void Remove() { assert(parent); parent->RemoveChildAnalyzer(this); }
// Management of support analyzers. Support analyzers are associated
// with a direction, and will only see data in the corresponding flow.
//
// We immediately discard an added analyzer if there's already a child
// of the same type for the same direction.
// Adds to tail of list.
void AddSupportAnalyzer(SupportAnalyzer* analyzer);
void RemoveSupportAnalyzer(SupportAnalyzer* analyzer);
// These are the methods where the analyzer actually gets its input.
// Each analyzer has only to implement the schemes it supports.
// Packet-wise (or more generally chunk-wise) input. "data" points
// to the payload that the analyzer is supposed to examine. If it's
// part of a full packet, "ip" points to its IP header. An analyzer
// may or may not require to be given the full packet (and its caplen)
// as well.
virtual void DeliverPacket(int len, const u_char* data, bool orig,
int seq, const IP_Hdr* ip, int caplen);
// Stream-wise payload input.
virtual void DeliverStream(int len, const u_char* data, bool orig);
// If a parent analyzer can't turn a sequence of packets into a stream
// (e.g., due to holes), it can pass the remaining data through this
// method to the child.
virtual void Undelivered(int seq, int len, bool orig);
// Report a message boundary. This is a generic method that can be used
// by specific Analyzers if all data of a message has been delivered,
// e.g., to report that HTTP body has been delivered completely by the
// HTTP analyzer before it starts with the next body. EndOfData() is
// automatically generated by the analyzer's Done() method.
virtual void EndOfData(bool is_orig);
// Occasionally we may find during analysis that we got the direction
// of the connection wrong. In these cases, this method is called
// to swap state if necessary. This will not happen after payload
// has already been passed on, so most analyzers don't need to care.
virtual void FlipRoles();
// Feedback about protocol conformance, to be called by the
// analyzer's processing. The methods raise the correspondiong
// protocol_confirmation and protocol_violation events.
// Report that we believe we're parsing the right protocol. This
// should be called as early as possible during a connection's
// life-time. The protocol_confirmed event is only raised once per
// analyzer, even if the method is called multiple times.
virtual void ProtocolConfirmation();
// Return whether the analyzer previously called ProtocolConfirmation()
// at least once before.
bool ProtocolConfirmed() const
{ return protocol_confirmed; }
// Report that we found a significant protocol violation which might
// indicate that the analyzed data is in fact not the expected
// protocol. The protocol_violation event is raised once per call to
// this method so that the script-level may build up some notion of
// how "severely" protocol semantics are violated.
virtual void ProtocolViolation(const char* reason,
const char* data = 0, int len = 0);
virtual unsigned int MemoryAllocation() const;
// Called whenever the connection value needs to be updated. Per
// default, this method will be called for each analyzer in the tree.
// Analyzers can use this method to attach additional data to the
// connections. A call to BuildConnVal will in turn trigger a call to
// UpdateConnVal.
virtual void UpdateConnVal(RecordVal *conn_val);
// The following methods are proxies: calls are directly forwarded
// to the connection instance. These are for convenience only,
// allowing us to reuse more of the old analyzer code unchanged.
RecordVal* BuildConnVal()
{ return conn->BuildConnVal(); }
void Event(EventHandlerPtr f, const char* name = 0)
{ conn->Event(f, this, name); }
void Event(EventHandlerPtr f, Val* v1, Val* v2 = 0)
{ conn->Event(f, this, v1, v2); }
void ConnectionEvent(EventHandlerPtr f, val_list* vl)
{ conn->ConnectionEvent(f, this, vl); }
void Weird(const char* name, const char* addl = "")
{ conn->Weird(name, addl); }
// Factory function to instantiate new analyzers.
static Analyzer* InstantiateAnalyzer(AnalyzerTag::Tag tag, Connection* c);
protected:
friend class DPM;
friend class Connection;
friend class AnalyzerTimer;
friend class TCP_ApplicationAnalyzer;
Analyzer() { }
// Associates a connection with this analyzer. Must be called if
// we're using the default ctor.
void SetConnection(Connection* c) { conn = c; }
// Creates the given timer to expire at time t. If do_expire
// is true, then the timer is also evaluated when Bro terminates,
// otherwise not.
void AddTimer(analyzer_timer_func timer, double t, int do_expire,
TimerType type);
void RemoveTimer(Timer* t);
void CancelTimers();
bool HasSupportAnalyzer(AnalyzerTag::Tag tag, bool orig);
void AddChildAnalyzer(Analyzer* analyzer, bool init);
void InitChildren();
void AppendNewChildren();
private:
// Internal method to eventually delete a child analyzer that's
// already Done().
void DeleteChild(analyzer_list::iterator i);
AnalyzerTag::Tag tag;
AnalyzerID id;
Connection* conn;
Analyzer* parent;
const Rule* signature;
OutputHandler* output_handler;
analyzer_list children;
SupportAnalyzer* orig_supporters;
SupportAnalyzer* resp_supporters;
analyzer_list new_children;
bool protocol_confirmed;
timer_list timers;
bool timers_canceled;
bool skip;
bool finished;
bool removing;
static AnalyzerID id_counter;
typedef bool (*available_callback)();
typedef Analyzer* (*factory_callback)(Connection* conn);
typedef bool (*match_callback)(Connection*);
struct Config {
AnalyzerTag::Tag tag;
const char* name;
factory_callback factory;
available_callback available;
match_callback match;
bool partial;
};
// Table of analyzers.
static const Config analyzer_configs[];
};
#define ADD_ANALYZER_TIMER(timer, t, do_expire, type) \
AddTimer(analyzer_timer_func(timer), (t), (do_expire), (type))
#define LOOP_OVER_CHILDREN(var) \
for ( analyzer_list::iterator var = children.begin(); \
var != children.end(); var++ )
#define LOOP_OVER_CONST_CHILDREN(var) \
for ( analyzer_list::const_iterator var = children.begin(); \
var != children.end(); var++ )
#define LOOP_OVER_GIVEN_CHILDREN(var, the_kids) \
for ( analyzer_list::iterator var = the_kids.begin(); \
var != the_kids.end(); var++ )
#define LOOP_OVER_GIVEN_CONST_CHILDREN(var, the_kids) \
for ( analyzer_list::const_iterator var = the_kids.begin(); \
var != the_kids.end(); var++ )
class SupportAnalyzer : public Analyzer {
public:
SupportAnalyzer(AnalyzerTag::Tag tag, Connection* conn, bool arg_orig)
: Analyzer(tag, conn) { orig = arg_orig; sibling = 0; }
virtual ~SupportAnalyzer() {}
bool IsOrig() const { return orig; }
virtual void ForwardPacket(int len, const u_char* data, bool orig,
int seq, const IP_Hdr* ip, int caplen);
virtual void ForwardStream(int len, const u_char* data, bool orig);
virtual void ForwardUndelivered(int seq, int len, bool orig);
SupportAnalyzer* Sibling() const { return sibling; }
protected:
friend class Analyzer;
SupportAnalyzer() { }
private:
bool orig;
// Points to next support analyzer in chain. The list is managed by
// parent analyzer.
SupportAnalyzer* sibling;
};
class TransportLayerAnalyzer : public Analyzer {
public:
TransportLayerAnalyzer(AnalyzerTag::Tag tag, Connection* conn)
: Analyzer(tag, conn) { pia = 0; }
virtual void Done();
virtual bool IsReuse(double t, const u_char* pkt) = 0;
virtual void SetContentsFile(unsigned int direction, BroFile* f);
virtual BroFile* GetContentsFile(unsigned int direction) const;
void SetPIA(PIA* arg_PIA) { pia = arg_PIA; }
PIA* GetPIA() const { return pia; }
// Raises packet_contents event.
void PacketContents(const u_char* data, int len);
protected:
TransportLayerAnalyzer() { }
private:
PIA* pia;
};
#endif

View file

@ -1,57 +0,0 @@
#ifndef ANALYZERTAGS_H
#define ANALYZERTAGS_H
// Each kind of analyzer gets a tag. When adding an analyzer here, also adapt
// the table of analyzers in Analyzer.cc.
//
// Using a namespace here is kind of a hack: ideally this would be in "class
// Analyzer {...}". But then we'd have circular dependencies across the header
// files.
#include "util.h"
typedef uint32 AnalyzerID;
namespace AnalyzerTag {
enum Tag {
Error = 0, // used as error code
// Analyzer in charge of protocol detection.
PIA_TCP, PIA_UDP,
// Transport-layer analyzers.
ICMP, TCP, UDP,
// Application-layer analyzers (hand-written).
BitTorrent, BitTorrentTracker,
DCE_RPC, DNS, Finger, FTP, Gnutella, HTTP, Ident, IRC,
Login, NCP, NetbiosSSN, NFS, NTP, POP3, Portmapper, Rlogin,
RPC, Rsh, SMB, SMTP, SSH,
Telnet,
// Application-layer analyzers, binpac-generated.
DHCP_BINPAC, DNS_TCP_BINPAC, DNS_UDP_BINPAC,
HTTP_BINPAC, SSL, SYSLOG_BINPAC,
Modbus,
// Decapsulation analyzers.
AYIYA,
SOCKS,
Teredo,
GTPv1,
// Other
File, IRC_Data, FTP_Data, Backdoor, InterConn, SteppingStone, TCPStats,
ConnSize,
// Support-analyzers
Contents, ContentLine, NVT, Zip, Contents_DNS, Contents_NCP,
Contents_NetbiosSSN, Contents_Rlogin, Contents_Rsh,
Contents_DCE_RPC, Contents_SMB, Contents_RPC, Contents_NFS,
FTP_ADAT,
// End-marker.
LastAnalyzer
};
};
#endif

View file

@ -82,9 +82,7 @@ int* Base64Converter::InitBase64Table(const string& alphabet)
return base64_table;
}
Base64Converter::Base64Converter(Analyzer* arg_analyzer, const string& arg_alphabet)
Base64Converter::Base64Converter(analyzer::Analyzer* arg_analyzer, const string& arg_alphabet)
{
if ( arg_alphabet.size() > 0 )
{

View file

@ -7,7 +7,8 @@
#include "util.h"
#include "BroString.h"
#include "Analyzer.h"
#include "Reporter.h"
#include "analyzer/Analyzer.h"
// Maybe we should have a base class for generic decoders?
class Base64Converter {
@ -15,7 +16,7 @@ public:
// <analyzer> is used for error reporting, and it should be zero when
// the decoder is called by the built-in function decode_base64() or encode_base64().
// Empty alphabet indicates the default base64 alphabet.
Base64Converter(Analyzer* analyzer, const string& alphabet = "");
Base64Converter(analyzer::Analyzer* analyzer, const string& alphabet = "");
~Base64Converter();
// A note on Decode():
@ -62,7 +63,7 @@ protected:
int base64_after_padding;
int* base64_table;
int errored; // if true, we encountered an error - skip further processing
Analyzer* analyzer;
analyzer::Analyzer* analyzer;
};

View file

@ -8,6 +8,9 @@
#include "BroDoc.h"
#include "BroDocObj.h"
#include "util.h"
#include "plugin/Manager.h"
#include "analyzer/Manager.h"
#include "analyzer/Component.h"
BroDoc::BroDoc(const std::string& rel, const std::string& abs)
{
@ -35,12 +38,14 @@ BroDoc::BroDoc(const std::string& rel, const std::string& abs)
downloadable_filename = source_filename;
#if 0
size_t ext_pos = downloadable_filename.find(".bif.bro");
if ( std::string::npos != ext_pos )
downloadable_filename.erase(ext_pos + 4);
#endif
reST_filename = doc_title;
ext_pos = reST_filename.find(".bro");
size_t ext_pos = reST_filename.find(".bro");
if ( std::string::npos == ext_pos )
reST_filename += ".rst";
@ -162,84 +167,77 @@ void BroDoc::SetPacketFilter(const std::string& s)
packet_filter.clear();
}
void BroDoc::AddPortAnalysis(const std::string& analyzer,
const std::string& ports)
{
std::string reST_string = analyzer + "::\n" + ports + "\n\n";
port_analysis.push_back(reST_string);
}
void BroDoc::WriteDocFile() const
{
WriteToDoc(".. Automatically generated. Do not edit.\n\n");
WriteToDoc(reST_file, ".. Automatically generated. Do not edit.\n\n");
WriteToDoc(":tocdepth: 3\n\n");
WriteToDoc(reST_file, ":tocdepth: 3\n\n");
WriteSectionHeading(doc_title.c_str(), '=');
WriteSectionHeading(reST_file, doc_title.c_str(), '=');
WriteStringList(".. bro:namespace:: %s\n", modules);
WriteStringList(reST_file, ".. bro:namespace:: %s\n", modules);
WriteToDoc("\n");
WriteToDoc(reST_file, "\n");
// WriteSectionHeading("Overview", '-');
WriteStringList("%s\n", summary);
// WriteSectionHeading(reST_file, "Overview", '-');
WriteStringList(reST_file, "%s\n", summary);
WriteToDoc("\n");
WriteToDoc(reST_file, "\n");
if ( ! modules.empty() )
{
WriteToDoc(":Namespace%s: ", (modules.size() > 1 ? "s" : ""));
// WriteStringList(":bro:namespace:`%s`", modules);
WriteStringList("``%s``, ", "``%s``", modules);
WriteToDoc("\n");
WriteToDoc(reST_file, ":Namespace%s: ", (modules.size() > 1 ? "s" : ""));
// WriteStringList(reST_file, ":bro:namespace:`%s`", modules);
WriteStringList(reST_file, "``%s``, ", "``%s``", modules);
WriteToDoc(reST_file, "\n");
}
if ( ! imports.empty() )
{
WriteToDoc(":Imports: ");
WriteToDoc(reST_file, ":Imports: ");
std::list<std::string>::const_iterator it;
for ( it = imports.begin(); it != imports.end(); ++it )
{
if ( it != imports.begin() )
WriteToDoc(", ");
WriteToDoc(reST_file, ", ");
string pretty(*it);
size_t pos = pretty.find("/index");
if ( pos != std::string::npos && pos + 6 == pretty.size() )
pretty = pretty.substr(0, pos);
WriteToDoc(":doc:`%s </scripts/%s>`", pretty.c_str(), it->c_str());
WriteToDoc(reST_file, ":doc:`%s </scripts/%s>`", pretty.c_str(), it->c_str());
}
WriteToDoc("\n");
WriteToDoc(reST_file, "\n");
}
WriteToDoc(":Source File: :download:`%s`\n",
WriteToDoc(reST_file, ":Source File: :download:`%s`\n",
downloadable_filename.c_str());
WriteToDoc("\n");
WriteToDoc(reST_file, "\n");
WriteInterface("Summary", '~', '#', true, true);
if ( ! notices.empty() )
WriteBroDocObjList(notices, "Notices", '#');
WriteBroDocObjList(reST_file, notices, "Notices", '#');
if ( port_analysis.size() || packet_filter.size() )
WriteSectionHeading("Configuration Changes", '#');
WriteSectionHeading(reST_file, "Configuration Changes", '#');
if ( ! port_analysis.empty() )
{
WriteSectionHeading("Port Analysis", '^');
WriteToDoc("Loading this script makes the following changes to "
WriteSectionHeading(reST_file, "Port Analysis", '^');
WriteToDoc(reST_file, "Loading this script makes the following changes to "
":bro:see:`dpd_config`.\n\n");
WriteStringList("%s, ", "%s", port_analysis);
WriteStringList(reST_file, "%s, ", "%s", port_analysis);
}
if ( ! packet_filter.empty() )
{
WriteSectionHeading("Packet Filter", '^');
WriteToDoc("Loading this script makes the following changes to "
WriteSectionHeading(reST_file, "Packet Filter", '^');
WriteToDoc(reST_file, "Loading this script makes the following changes to "
":bro:see:`capture_filters`.\n\n");
WriteToDoc("Filters added::\n\n");
WriteToDoc("%s\n", packet_filter.c_str());
WriteToDoc(reST_file, "Filters added::\n\n");
WriteToDoc(reST_file, "%s\n", packet_filter.c_str());
}
WriteInterface("Detailed Interface", '~', '#', true, false);
@ -265,23 +263,23 @@ void BroDoc::WriteDocFile() const
void BroDoc::WriteInterface(const char* heading, char underline,
char sub, bool isPublic, bool isShort) const
{
WriteSectionHeading(heading, underline);
WriteBroDocObjList(options, isPublic, "Options", sub, isShort);
WriteBroDocObjList(constants, isPublic, "Constants", sub, isShort);
WriteBroDocObjList(state_vars, isPublic, "State Variables", sub, isShort);
WriteBroDocObjList(types, isPublic, "Types", sub, isShort);
WriteBroDocObjList(events, isPublic, "Events", sub, isShort);
WriteBroDocObjList(hooks, isPublic, "Hooks", sub, isShort);
WriteBroDocObjList(functions, isPublic, "Functions", sub, isShort);
WriteBroDocObjList(redefs, isPublic, "Redefinitions", sub, isShort);
WriteSectionHeading(reST_file, heading, underline);
WriteBroDocObjList(reST_file, options, isPublic, "Options", sub, isShort);
WriteBroDocObjList(reST_file, constants, isPublic, "Constants", sub, isShort);
WriteBroDocObjList(reST_file, state_vars, isPublic, "State Variables", sub, isShort);
WriteBroDocObjList(reST_file, types, isPublic, "Types", sub, isShort);
WriteBroDocObjList(reST_file, events, isPublic, "Events", sub, isShort);
WriteBroDocObjList(reST_file, hooks, isPublic, "Hooks", sub, isShort);
WriteBroDocObjList(reST_file, functions, isPublic, "Functions", sub, isShort);
WriteBroDocObjList(reST_file, redefs, isPublic, "Redefinitions", sub, isShort);
}
void BroDoc::WriteStringList(const char* format, const char* last_format,
const std::list<std::string>& l) const
void BroDoc::WriteStringList(FILE* f, const char* format, const char* last_format,
const std::list<std::string>& l)
{
if ( l.empty() )
{
WriteToDoc("\n");
WriteToDoc(f, "\n");
return;
}
@ -290,12 +288,12 @@ void BroDoc::WriteStringList(const char* format, const char* last_format,
last--;
for ( it = l.begin(); it != last; ++it )
WriteToDoc(format, it->c_str());
WriteToDoc(f, format, it->c_str());
WriteToDoc(last_format, last->c_str());
WriteToDoc(f, last_format, last->c_str());
}
void BroDoc::WriteBroDocObjTable(const BroDocObjList& l) const
void BroDoc::WriteBroDocObjTable(FILE* f, const BroDocObjList& l)
{
int max_id_col = 0;
int max_com_col = 0;
@ -315,38 +313,38 @@ void BroDoc::WriteBroDocObjTable(const BroDocObjList& l) const
}
// Start table.
WriteRepeatedChar('=', max_id_col);
WriteToDoc(" ");
WriteRepeatedChar(f, '=', max_id_col);
WriteToDoc(f, " ");
if ( max_com_col == 0 )
WriteToDoc("=");
WriteToDoc(f, "=");
else
WriteRepeatedChar('=', max_com_col);
WriteRepeatedChar(f, '=', max_com_col);
WriteToDoc("\n");
WriteToDoc(f, "\n");
for ( it = l.begin(); it != l.end(); ++it )
{
if ( it != l.begin() )
WriteToDoc("\n\n");
(*it)->WriteReSTCompact(reST_file, max_id_col);
WriteToDoc(f, "\n\n");
(*it)->WriteReSTCompact(f, max_id_col);
}
// End table.
WriteToDoc("\n");
WriteRepeatedChar('=', max_id_col);
WriteToDoc(" ");
WriteToDoc(f, "\n");
WriteRepeatedChar(f, '=', max_id_col);
WriteToDoc(f, " ");
if ( max_com_col == 0 )
WriteToDoc("=");
WriteToDoc(f, "=");
else
WriteRepeatedChar('=', max_com_col);
WriteRepeatedChar(f, '=', max_com_col);
WriteToDoc("\n\n");
WriteToDoc(f, "\n\n");
}
void BroDoc::WriteBroDocObjList(const BroDocObjList& l, bool wantPublic,
const char* heading, char underline, bool isShort) const
void BroDoc::WriteBroDocObjList(FILE* f, const BroDocObjList& l, bool wantPublic,
const char* heading, char underline, bool isShort)
{
if ( l.empty() )
return;
@ -364,7 +362,7 @@ void BroDoc::WriteBroDocObjList(const BroDocObjList& l, bool wantPublic,
if ( it == l.end() )
return;
WriteSectionHeading(heading, underline);
WriteSectionHeading(f, heading, underline);
BroDocObjList filtered_list;
@ -375,13 +373,13 @@ void BroDoc::WriteBroDocObjList(const BroDocObjList& l, bool wantPublic,
}
if ( isShort )
WriteBroDocObjTable(filtered_list);
WriteBroDocObjTable(f, filtered_list);
else
WriteBroDocObjList(filtered_list);
WriteBroDocObjList(f, filtered_list);
}
void BroDoc::WriteBroDocObjList(const BroDocObjMap& m, bool wantPublic,
const char* heading, char underline, bool isShort) const
void BroDoc::WriteBroDocObjList(FILE* f, const BroDocObjMap& m, bool wantPublic,
const char* heading, char underline, bool isShort)
{
BroDocObjMap::const_iterator it;
BroDocObjList l;
@ -389,24 +387,24 @@ void BroDoc::WriteBroDocObjList(const BroDocObjMap& m, bool wantPublic,
for ( it = m.begin(); it != m.end(); ++it )
l.push_back(it->second);
WriteBroDocObjList(l, wantPublic, heading, underline, isShort);
WriteBroDocObjList(f, l, wantPublic, heading, underline, isShort);
}
void BroDoc::WriteBroDocObjList(const BroDocObjList& l, const char* heading,
char underline) const
void BroDoc::WriteBroDocObjList(FILE* f, const BroDocObjList& l, const char* heading,
char underline)
{
WriteSectionHeading(heading, underline);
WriteBroDocObjList(l);
WriteSectionHeading(f, heading, underline);
WriteBroDocObjList(f, l);
}
void BroDoc::WriteBroDocObjList(const BroDocObjList& l) const
void BroDoc::WriteBroDocObjList(FILE* f, const BroDocObjList& l)
{
for ( BroDocObjList::const_iterator it = l.begin(); it != l.end(); ++it )
(*it)->WriteReST(reST_file);
(*it)->WriteReST(f);
}
void BroDoc::WriteBroDocObjList(const BroDocObjMap& m, const char* heading,
char underline) const
void BroDoc::WriteBroDocObjList(FILE* f, const BroDocObjMap& m, const char* heading,
char underline)
{
BroDocObjMap::const_iterator it;
BroDocObjList l;
@ -414,28 +412,28 @@ void BroDoc::WriteBroDocObjList(const BroDocObjMap& m, const char* heading,
for ( it = m.begin(); it != m.end(); ++it )
l.push_back(it->second);
WriteBroDocObjList(l, heading, underline);
WriteBroDocObjList(f, l, heading, underline);
}
void BroDoc::WriteToDoc(const char* format, ...) const
void BroDoc::WriteToDoc(FILE* f, const char* format, ...)
{
va_list argp;
va_start(argp, format);
vfprintf(reST_file, format, argp);
vfprintf(f, format, argp);
va_end(argp);
}
void BroDoc::WriteSectionHeading(const char* heading, char underline) const
void BroDoc::WriteSectionHeading(FILE* f, const char* heading, char underline)
{
WriteToDoc("%s\n", heading);
WriteRepeatedChar(underline, strlen(heading));
WriteToDoc("\n");
WriteToDoc(f, "%s\n", heading);
WriteRepeatedChar(f, underline, strlen(heading));
WriteToDoc(f, "\n");
}
void BroDoc::WriteRepeatedChar(char c, size_t n) const
void BroDoc::WriteRepeatedChar(FILE* f, char c, size_t n)
{
for ( size_t i = 0; i < n; ++i )
WriteToDoc("%c", c);
WriteToDoc(f, "%c", c);
}
void BroDoc::FreeBroDocObjPtrList(BroDocObjList& l)
@ -457,3 +455,143 @@ void BroDoc::AddFunction(BroDocObj* o)
else
functions[o->Name()]->Combine(o);
}
static void WritePluginSectionHeading(FILE* f, const plugin::Plugin* p)
{
string name = p->Name();
fprintf(f, "%s\n", name.c_str());
for ( size_t i = 0; i < name.size(); ++i )
fprintf(f, "-");
fprintf(f, "\n\n");
fprintf(f, "%s\n\n", p->Description());
}
static void WriteAnalyzerComponent(FILE* f, const analyzer::Component* c)
{
EnumType* atag = analyzer_mgr->GetTagEnumType();
string tag = fmt("ANALYZER_%s", c->CanonicalName());
if ( atag->Lookup("Analyzer", tag.c_str()) < 0 )
reporter->InternalError("missing analyzer tag for %s", tag.c_str());
fprintf(f, ":bro:enum:`Analyzer::%s`\n\n", tag.c_str());
}
static void WritePluginComponents(FILE* f, const plugin::Plugin* p)
{
plugin::Plugin::component_list components = p->Components();
plugin::Plugin::component_list::const_iterator it;
fprintf(f, "Components\n");
fprintf(f, "++++++++++\n\n");
for ( it = components.begin(); it != components.end(); ++it )
{
switch ( (*it)->Type() ) {
case plugin::component::ANALYZER:
WriteAnalyzerComponent(f,
dynamic_cast<const analyzer::Component*>(*it));
break;
case plugin::component::READER:
reporter->InternalError("docs for READER component unimplemented");
case plugin::component::WRITER:
reporter->InternalError("docs for WRITER component unimplemented");
default:
reporter->InternalError("docs for unknown component unimplemented");
}
}
}
static void WritePluginBifItems(FILE* f, const plugin::Plugin* p,
plugin::BifItem::Type t, const string& heading)
{
plugin::Plugin::bif_item_list bifitems = p->BifItems();
plugin::Plugin::bif_item_list::iterator it = bifitems.begin();
while ( it != bifitems.end() )
{
if ( it->GetType() != t )
it = bifitems.erase(it);
else
++it;
}
if ( bifitems.empty() )
return;
fprintf(f, "%s\n", heading.c_str());
for ( size_t i = 0; i < heading.size(); ++i )
fprintf(f, "+");
fprintf(f, "\n\n");
for ( it = bifitems.begin(); it != bifitems.end(); ++it )
{
BroDocObj* o = doc_ids[it->GetID()];
if ( o )
o->WriteReST(f);
else
reporter->Warning("No docs for ID: %s\n", it->GetID());
}
}
static void WriteAnalyzerTagDefn(FILE* f, EnumType* e)
{
e = new CommentedEnumType(e);
e->SetTypeID(copy_string("Analyzer::Tag"));
ID* dummy_id = new ID(copy_string("Analyzer::Tag"), SCOPE_GLOBAL, true);
dummy_id->SetType(e);
dummy_id->MakeType();
list<string>* r = new list<string>();
r->push_back("Unique identifiers for protocol analyzers.");
BroDocObj bdo(dummy_id, r, true);
bdo.WriteReST(f);
}
static bool IsAnalyzerPlugin(const plugin::Plugin* p)
{
plugin::Plugin::component_list components = p->Components();
plugin::Plugin::component_list::const_iterator it;
for ( it = components.begin(); it != components.end(); ++it )
if ( (*it)->Type() != plugin::component::ANALYZER )
return false;
return true;
}
void CreateProtoAnalyzerDoc(const char* filename)
{
FILE* f = fopen(filename, "w");
fprintf(f, "Protocol Analyzer Reference\n");
fprintf(f, "===========================\n\n");
WriteAnalyzerTagDefn(f, analyzer_mgr->GetTagEnumType());
plugin::Manager::plugin_list plugins = plugin_mgr->Plugins();
plugin::Manager::plugin_list::const_iterator it;
for ( it = plugins.begin(); it != plugins.end(); ++it )
{
if ( ! IsAnalyzerPlugin(*it) )
continue;
WritePluginSectionHeading(f, *it);
WritePluginComponents(f, *it);
WritePluginBifItems(f, *it, plugin::BifItem::CONSTANT,
"Options/Constants");
WritePluginBifItems(f, *it, plugin::BifItem::GLOBAL, "Globals");
WritePluginBifItems(f, *it, plugin::BifItem::TYPE, "Types");
WritePluginBifItems(f, *it, plugin::BifItem::EVENT, "Events");
WritePluginBifItems(f, *it, plugin::BifItem::FUNCTION, "Functions");
}
fclose(f);
}

View file

@ -81,15 +81,6 @@ public:
*/
void SetPacketFilter(const std::string& s);
/**
* Schedules documentation of a given set of ports being associated
* with a particular analyzer as a result of the current script
* being loaded -- the way the "dpd_config" table is changed.
* @param analyzer An analyzer that changed the "dpd_config" table.
* @param ports The set of ports assigned to the analyzer in table.
*/
void AddPortAnalysis(const std::string& analyzer, const std::string& ports);
/**
* Schedules documentation of a script option. An option is
* defined as any variable in the script that is declared 'const'
@ -242,7 +233,115 @@ public:
return reST_filename.c_str();
}
protected:
typedef std::list<const BroDocObj*> BroDocObjList;
typedef std::map<std::string, BroDocObj*> BroDocObjMap;
/**
* Writes out a table of BroDocObj's to the reST document
* @param f The file to write to.
* @param l A list of BroDocObj pointers
*/
static void WriteBroDocObjTable(FILE* f, const BroDocObjList& l);
/**
* Writes out given number of characters to reST document
* @param f The file to write to.
* @param c the character to write
* @param n the number of characters to write
*/
static void WriteRepeatedChar(FILE* f, char c, size_t n);
/**
* A wrapper to fprintf() that always uses the reST document
* for the FILE* argument.
* @param f The file to write to.
* @param format A printf style format string.
*/
static void WriteToDoc(FILE* f, const char* format, ...);
/**
* Writes out a list of strings to the reST document.
* If the list is empty, prints a newline character.
* @param f The file to write to.
* @param format A printf style format string for elements of the list
* except for the last one in the list
* @param last_format A printf style format string to use for the last
* element of the list
* @param l A reference to a list of strings
*/
static void WriteStringList(FILE* f, const char* format, const char* last_format,
const std::list<std::string>& l);
/**
* @see WriteStringList(FILE* f, const char*, const char*,
* const std::list<std::string>&>)
*/
static void WriteStringList(FILE* f, const char* format,
const std::list<std::string>& l){
WriteStringList(f, format, format, l);
}
/**
* Writes out a list of BroDocObj objects to the reST document
* @param f The file to write to.
* @param l A list of BroDocObj pointers
* @param wantPublic If true, filter out objects that are not declared
* in the global scope. If false, filter out those that are in
* the global scope.
* @param heading The title of the section to create in the reST doc.
* @param underline The character to use to underline the reST
* section heading.
* @param isShort Whether to write the full documentation or a "short"
* version (a single sentence)
*/
static void WriteBroDocObjList(FILE* f, const BroDocObjList& l, bool wantPublic,
const char* heading, char underline,
bool isShort);
/**
* Wraps the BroDocObjMap into a BroDocObjList and the writes that list
* to the reST document
* @see WriteBroDocObjList(FILE* f, const BroDocObjList&, bool, const char*, char,
bool)
*/
static void WriteBroDocObjList(FILE* f, const BroDocObjMap& m, bool wantPublic,
const char* heading, char underline,
bool isShort);
/**
* Writes out a list of BroDocObj objects to the reST document
* @param l A list of BroDocObj pointers
* @param heading The title of the section to create in the reST doc.
* @param underline The character to use to underline the reST
* section heading.
*/
static void WriteBroDocObjList(FILE* f, const BroDocObjList& l, const char* heading,
char underline);
/**
* Writes out a list of BroDocObj objects to the reST document
* @param l A list of BroDocObj pointers
*/
static void WriteBroDocObjList(FILE* f, const BroDocObjList& l);
/**
* Wraps the BroDocObjMap into a BroDocObjList and the writes that list
* to the reST document
* @see WriteBroDocObjList(FILE* f, const BroDocObjList&, const char*, char)
*/
static void WriteBroDocObjList(FILE* f, const BroDocObjMap& m, const char* heading,
char underline);
/**
* Writes out a reST section heading
* @param f The file to write to.
* @param heading The title of the heading to create
* @param underline The character to use to underline the section title
* within the reST document
*/
static void WriteSectionHeading(FILE* f, const char* heading, char underline);
private:
FILE* reST_file;
std::string reST_filename;
std::string source_filename; // points to the basename of source file
@ -255,9 +354,6 @@ protected:
std::list<std::string> imports;
std::list<std::string> port_analysis;
typedef std::list<const BroDocObj*> BroDocObjList;
typedef std::map<std::string, BroDocObj*> BroDocObjMap;
BroDocObjList options;
BroDocObjList constants;
BroDocObjList state_vars;
@ -272,107 +368,6 @@ protected:
BroDocObjList all;
/**
* Writes out a list of strings to the reST document.
* If the list is empty, prints a newline character.
* @param format A printf style format string for elements of the list
* except for the last one in the list
* @param last_format A printf style format string to use for the last
* element of the list
* @param l A reference to a list of strings
*/
void WriteStringList(const char* format, const char* last_format,
const std::list<std::string>& l) const;
/**
* @see WriteStringList(const char*, const char*,
* const std::list<std::string>&>)
*/
void WriteStringList(const char* format,
const std::list<std::string>& l) const
{
WriteStringList(format, format, l);
}
/**
* Writes out a table of BroDocObj's to the reST document
* @param l A list of BroDocObj pointers
*/
void WriteBroDocObjTable(const BroDocObjList& l) const;
/**
* Writes out a list of BroDocObj objects to the reST document
* @param l A list of BroDocObj pointers
* @param wantPublic If true, filter out objects that are not declared
* in the global scope. If false, filter out those that are in
* the global scope.
* @param heading The title of the section to create in the reST doc.
* @param underline The character to use to underline the reST
* section heading.
* @param isShort Whether to write the full documentation or a "short"
* version (a single sentence)
*/
void WriteBroDocObjList(const BroDocObjList& l, bool wantPublic,
const char* heading, char underline,
bool isShort) const;
/**
* Wraps the BroDocObjMap into a BroDocObjList and the writes that list
* to the reST document
* @see WriteBroDocObjList(const BroDocObjList&, bool, const char*, char,
bool)
*/
void WriteBroDocObjList(const BroDocObjMap& m, bool wantPublic,
const char* heading, char underline,
bool isShort) const;
/**
* Writes out a list of BroDocObj objects to the reST document
* @param l A list of BroDocObj pointers
* @param heading The title of the section to create in the reST doc.
* @param underline The character to use to underline the reST
* section heading.
*/
void WriteBroDocObjList(const BroDocObjList& l, const char* heading,
char underline) const;
/**
* Writes out a list of BroDocObj objects to the reST document
* @param l A list of BroDocObj pointers
*/
void WriteBroDocObjList(const BroDocObjList& l) const;
/**
* Wraps the BroDocObjMap into a BroDocObjList and the writes that list
* to the reST document
* @see WriteBroDocObjList(const BroDocObjList&, const char*, char)
*/
void WriteBroDocObjList(const BroDocObjMap& m, const char* heading,
char underline) const;
/**
* A wrapper to fprintf() that always uses the reST document
* for the FILE* argument.
* @param format A printf style format string.
*/
void WriteToDoc(const char* format, ...) const;
/**
* Writes out a reST section heading
* @param heading The title of the heading to create
* @param underline The character to use to underline the section title
* within the reST document
*/
void WriteSectionHeading(const char* heading, char underline) const;
/**
* Writes out given number of characters to reST document
* @param c the character to write
* @param n the number of characters to write
*/
void WriteRepeatedChar(char c, size_t n) const;
/**
* Writes out the reST for either the script's public or private interface
* @param heading The title of the interfaces section heading
@ -387,7 +382,6 @@ protected:
*/
void WriteInterface(const char* heading, char underline, char subunderline,
bool isPublic, bool isShort) const;
private:
/**
* Frees memory allocated to BroDocObj's objects in a given list.
@ -413,4 +407,10 @@ private:
};
};
/**
* Writes out plugin index documentation for all analyzer plugins.
* @param filename the name of the file to write.
*/
void CreateProtoAnalyzerDoc(const char* filename);
#endif

View file

@ -4,6 +4,8 @@
#include "ID.h"
#include "BroDocObj.h"
map<string, BroDocObj*> doc_ids = map<string, BroDocObj*>();
BroDocObj* BroDocObj::last = 0;
BroDocObj::BroDocObj(const ID* id, std::list<std::string>*& reST,
@ -16,6 +18,7 @@ BroDocObj::BroDocObj(const ID* id, std::list<std::string>*& reST,
is_fake_id = is_fake;
use_role = 0;
FormulateShortDesc();
doc_ids[id->Name()] = this;
}
BroDocObj::~BroDocObj()

View file

@ -4,6 +4,7 @@
#include <cstdio>
#include <string>
#include <list>
#include <map>
#include "ID.h"
@ -134,4 +135,9 @@ protected:
private:
};
/**
* Map identifiers to their broxygen documentation objects.
*/
extern map<string, BroDocObj*> doc_ids;
#endif

View file

@ -3,6 +3,13 @@ include_directories(BEFORE
${CMAKE_CURRENT_BINARY_DIR}
)
# This collects generated bif and pac files from subdirectories.
set(bro_ALL_GENERATED_OUTPUTS CACHE INTERNAL "automatically generated files" FORCE)
# If TRUE, use CMake's object libraries for sub-directories instead of
# static libraries. This requires CMake >= 2.8.8.
set(bro_HAVE_OBJECT_LIBRARIES FALSE)
configure_file(version.c.in ${CMAKE_CURRENT_BINARY_DIR}/version.c)
configure_file(util-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/util-config.h)
@ -100,52 +107,13 @@ target_link_libraries(bifcl)
########################################################################
## bifcl-dependent targets
# A macro to define a command that uses the BIF compiler to produce
# C++ segments and Bro language declarations from .bif file
# The outputs are appended to list ALL_BIF_OUTPUTS
# Outputs that should be installed are appended to INSTALL_BIF_OUTPUTS
macro(BIF_TARGET bifInput)
get_bif_output_files(${bifInput} bifOutputs)
add_custom_command(OUTPUT ${bifOutputs}
COMMAND bifcl
ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${bifInput} || (rm -f ${bifOutputs} && exit 1)
# In order be able to run bro from the build directory,
# the generated bro script needs to be inside a
# a directory tree named the same way it will be
# referenced from an @load.
COMMAND "${CMAKE_COMMAND}"
ARGS -E copy ${bifInput}.bro base/${bifInput}.bro
COMMAND "${CMAKE_COMMAND}"
ARGS -E remove -f ${bifInput}.bro
DEPENDS ${bifInput}
DEPENDS bifcl
COMMENT "[BIFCL] Processing ${bifInput}"
)
list(APPEND ALL_BIF_OUTPUTS ${bifOutputs})
list(APPEND INSTALL_BIF_OUTPUTS
${CMAKE_CURRENT_BINARY_DIR}/base/${bifInput}.bro)
endmacro(BIF_TARGET)
# returns a list of output files that bifcl will produce
# for given input file in ${outputFileVar}
macro(GET_BIF_OUTPUT_FILES inputFile outputFileVar)
set(${outputFileVar}
base/${inputFile}.bro
${inputFile}.func_def
${inputFile}.func_h
${inputFile}.func_init
${inputFile}.netvar_def
${inputFile}.netvar_h
${inputFile}.netvar_init
)
endmacro(GET_BIF_OUTPUT_FILES)
include(BifCl)
set(BIF_SRCS
bro.bif
logging.bif
input.bif
event.bif
file_analysis.bif
const.bif
types.bif
strings.bif
@ -153,74 +121,54 @@ set(BIF_SRCS
)
foreach (bift ${BIF_SRCS})
bif_target(${bift})
bif_target(${bift} "standard")
endforeach ()
########################################################################
## BinPAC-dependent targets
set(BINPAC_AUXSRC
binpac.pac
bro.pac
binpac_bro.h
)
include(BinPAC)
# A macro to define a command that uses the BinPac compiler to
# produce C++ code that implements a protocol parser/analyzer
# The outputs of the command are appended to list ALL_BINPAC_OUTPUTS
# All arguments to this macro are appended to list ALL_BINPAC_INPUTS
macro(BINPAC_TARGET pacFile)
get_filename_component(basename ${pacFile} NAME_WE)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.h
${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.cc
COMMAND ${BinPAC_EXE}
ARGS -q -d ${CMAKE_CURRENT_BINARY_DIR}
-I ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/${pacFile}
DEPENDS ${BinPAC_EXE} ${pacFile}
${BINPAC_AUXSRC} ${ARGN}
COMMENT "[BINPAC] Processing ${pacFile}"
set(BINPAC_AUXSRC
${CMAKE_SOURCE_DIR}/src/binpac.pac
${CMAKE_SOURCE_DIR}/src/bro.pac
${CMAKE_SOURCE_DIR}/src/binpac_bro.h
)
list(APPEND ALL_BINPAC_INPUTS ${ARGV})
list(APPEND ALL_BINPAC_OUTPUTS
${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.h
${CMAKE_CURRENT_BINARY_DIR}/${basename}_pac.cc)
endmacro(BINPAC_TARGET)
binpac_target(binpac-lib.pac)
binpac_target(binpac_bro-lib.pac)
list(APPEND BINPAC_OUTPUTS "${BINPAC_OUTPUT_CC}")
binpac_target(ayiya.pac
ayiya-protocol.pac ayiya-analyzer.pac)
binpac_target(bittorrent.pac
bittorrent-protocol.pac bittorrent-analyzer.pac)
binpac_target(dce_rpc.pac
dce_rpc-protocol.pac dce_rpc-analyzer.pac epmapper.pac)
binpac_target(dce_rpc_simple.pac
dce_rpc-protocol.pac epmapper.pac)
binpac_target(dhcp.pac
dhcp-protocol.pac dhcp-analyzer.pac)
binpac_target(dns.pac
dns-protocol.pac dns-analyzer.pac)
binpac_target(dns_tcp.pac
dns.pac)
binpac_target(gtpv1.pac
gtpv1-protocol.pac gtpv1-analyzer.pac)
binpac_target(http.pac
http-protocol.pac http-analyzer.pac)
binpac_target(ncp.pac)
binpac_target(netflow.pac
netflow-protocol.pac netflow-analyzer.pac)
binpac_target(smb.pac
smb-protocol.pac smb-pipe.pac smb-mailslot.pac)
binpac_target(socks.pac
socks-protocol.pac socks-analyzer.pac)
binpac_target(ssl.pac
ssl-defs.pac ssl-protocol.pac ssl-analyzer.pac)
binpac_target(syslog.pac
syslog-protocol.pac syslog-analyzer.pac)
binpac_target(modbus.pac
modbus-protocol.pac modbus-analyzer.pac)
binpac_target(binpac_bro-lib.pac)
list(APPEND BINPAC_OUTPUTS "${BINPAC_OUTPUT_CC}")
########################################################################
## Including subdirectories.
########################################################################
set(bro_SUBDIR_LIBS CACHE INTERNAL "subdir libraries" FORCE)
set(bro_PLUGIN_LIBS CACHE INTERNAL "plugin libraries" FORCE)
add_subdirectory(analyzer)
add_subdirectory(file_analysis)
set(bro_SUBDIRS
${bro_SUBDIR_LIBS}
${bro_PLUGIN_LIBS}
)
if ( NOT bro_HAVE_OBJECT_LIBRARIES )
foreach (_plugin ${bro_PLUGIN_LIBS})
string(REGEX REPLACE "plugin-" "" _plugin "${_plugin}")
string(REGEX REPLACE "-" "_" _plugin "${_plugin}")
set(_decl "namespace plugin { namespace ${_plugin} { class Plugin; extern Plugin __plugin; } };")
set(_use "i += (size_t)(&(plugin::${_plugin}::__plugin));")
set(__BRO_DECL_PLUGINS "${__BRO_DECL_PLUGINS}${_decl}\n")
set(__BRO_USE_PLUGINS "${__BRO_USE_PLUGINS}${_use}\n")
endforeach()
configure_file(plugins.cc.in ${CMAKE_CURRENT_BINARY_DIR}/plugins.cc)
set(PLUGIN_INIT ${CMAKE_CURRENT_BINARY_DIR}/plugins.cc)
endif()
########################################################################
## bro target
@ -240,7 +188,7 @@ endif ()
macro(COLLECT_HEADERS _var)
foreach (src ${ARGN})
get_filename_component(ext ${src} EXT)
if (${ext} STREQUAL ".cc" OR ${ext} STREQUAL ".c")
if ("${ext}" STREQUAL ".cc" OR "${ext}" STREQUAL ".c")
get_filename_component(base ${src} NAME_WE)
get_filename_component(dir ${src} PATH)
if (NOT "${dir}")
@ -275,10 +223,8 @@ set_source_files_properties(nb_dns.c PROPERTIES COMPILE_FLAGS
set(bro_SRCS
${CMAKE_CURRENT_BINARY_DIR}/version.c
${BIF_SRCS}
${ALL_BIF_OUTPUTS}
${BINPAC_AUXSRC}
${ALL_BINPAC_INPUTS}
${ALL_BINPAC_OUTPUTS}
${BINPAC_OUTPUTS}
${TRANSFORMED_BISON_OUTPUTS}
${FLEX_RuleScanner_OUTPUTS}
${FLEX_RuleScanner_INPUT}
@ -290,19 +236,14 @@ set(bro_SRCS
${FLEX_Scanner_INPUT}
${BISON_Parser_INPUT}
${CMAKE_CURRENT_BINARY_DIR}/DebugCmdConstants.h
${PLUGIN_INIT}
main.cc
net_util.cc
util.cc
module_util.cc
Analyzer.cc
Anon.cc
ARP.cc
Attr.cc
AYIYA.cc
BackDoor.cc
Base64.cc
BitTorrent.cc
BitTorrentTracker.cc
BPF_Program.cc
BroDoc.cc
BroDocObj.cc
@ -312,14 +253,7 @@ set(bro_SRCS
ChunkedIO.cc
CompHash.cc
Conn.cc
ConnSizeAnalyzer.cc
ContentLine.cc
DCE_RPC.cc
DFA.cc
DHCP-binpac.cc
DNS.cc
DNS-binpac.cc
DNS_Mgr.cc
DbgBreakpoint.cc
DbgHelp.cc
DbgWatch.cc
@ -329,48 +263,29 @@ set(bro_SRCS
Desc.cc
Dict.cc
Discard.cc
DPM.cc
DNS_Mgr.cc
EquivClass.cc
Event.cc
EventHandler.cc
EventLauncher.cc
EventRegistry.cc
Expr.cc
FTP.cc
File.cc
FileAnalyzer.cc
Finger.cc
FlowSrc.cc
Frag.cc
Frame.cc
Func.cc
Gnutella.cc
GTPv1.cc
HTTP.cc
HTTP-binpac.cc
Hash.cc
ICMP.cc
ID.cc
Ident.cc
IntSet.cc
InterConn.cc
IOSource.cc
IP.cc
IPAddr.cc
IRC.cc
List.cc
Reporter.cc
Login.cc
MIME.cc
Modbus.cc
NCP.cc
NFA.cc
NFS.cc
NTP.cc
NVT.cc
Net.cc
NetVar.cc
NetbiosSSN.cc
Obj.cc
OpaqueVal.cc
OSFinger.cc
@ -378,31 +293,20 @@ set(bro_SRCS
PacketSort.cc
PersistenceSerializer.cc
PktSrc.cc
PIA.cc
PolicyFile.cc
POP3.cc
Portmap.cc
PrefixTable.cc
PriorityQueue.cc
Queue.cc
RandTest.cc
RE.cc
RPC.cc
Reassem.cc
RemoteSerializer.cc
Rlogin.cc
RSH.cc
Rule.cc
RuleAction.cc
RuleCondition.cc
RuleMatcher.cc
ScriptAnaly.cc
SmithWaterman.cc
SMB.cc
SMTP.cc
SOCKS.cc
SSH.cc
SSL.cc
Scope.cc
SerializationFormat.cc
SerialObj.cc
@ -410,24 +314,14 @@ set(bro_SRCS
Sessions.cc
StateAccess.cc
Stats.cc
SteppingStone.cc
Stmt.cc
Syslog-binpac.cc
TCP.cc
TCP_Endpoint.cc
TCP_Reassembler.cc
Telnet.cc
Teredo.cc
Timer.cc
Traverse.cc
Trigger.cc
TunnelEncapsulation.cc
Type.cc
UDP.cc
Val.cc
Var.cc
XDR.cc
ZIP.cc
bsd-getopt-long.c
bro_inet_ntop.c
cq.c
@ -461,29 +355,44 @@ set(bro_SRCS
input/readers/Binary.cc
input/readers/SQLite.cc
file_analysis/Manager.cc
file_analysis/File.cc
file_analysis/FileTimer.cc
file_analysis/Analyzer.h
file_analysis/AnalyzerSet.cc
file_analysis/Extract.cc
file_analysis/Hash.cc
file_analysis/DataEvent.cc
3rdparty/sqlite3.c
plugin/Component.cc
plugin/Manager.cc
plugin/Plugin.cc
plugin/Macros.h
nb_dns.c
digest.h
)
collect_headers(bro_HEADERS ${bro_SRCS})
add_executable(bro ${bro_SRCS} ${bro_HEADERS})
if ( bro_HAVE_OBJECT_LIBRARIES )
add_executable(bro ${bro_SRCS} ${bro_HEADERS} ${bro_SUBDIRS})
target_link_libraries(bro ${brodeps} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS})
else ()
add_executable(bro ${bro_SRCS} ${bro_HEADERS})
target_link_libraries(bro ${bro_SUBDIRS} ${brodeps} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS})
endif ()
install(TARGETS bro DESTINATION bin)
install(FILES ${INSTALL_BIF_OUTPUTS} DESTINATION ${BRO_SCRIPT_INSTALL_PATH}/base)
set(BRO_EXE bro
CACHE STRING "Bro executable binary" FORCE)
# Target to create all the autogenerated files.
add_custom_target(generate_outputs)
add_dependencies(generate_outputs ${bro_ALL_GENERATED_OUTPUTS})
# Build __load__.bro files for plugins/*.bif.bro.
bro_bif_create_loader(bif_loader_plugins ${CMAKE_BINARY_DIR}/scripts/base/bif/plugins)
add_dependencies(bif_loader_plugins ${bro_SUBDIRS})
add_dependencies(bro bif_loader_plugins)
# Install *.bif.bro.
install(DIRECTORY ${CMAKE_BINARY_DIR}/scripts/base/bif DESTINATION ${BRO_SCRIPT_INSTALL_PATH}/base)
# Make clean removes the bif directory.
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CMAKE_BINARY_DIR}/scripts/base/bif)

View file

@ -11,9 +11,10 @@
#include "Sessions.h"
#include "Reporter.h"
#include "Timer.h"
#include "PIA.h"
#include "analyzer/protocol/pia/PIA.h"
#include "binpac.h"
#include "TunnelEncapsulation.h"
#include "analyzer/Analyzer.h"
void ConnectionTimer::Init(Connection* arg_conn, timer_func arg_timer,
int arg_do_expire)
@ -402,16 +403,21 @@ RecordVal* Connection::BuildConnVal()
return conn_val;
}
Analyzer* Connection::FindAnalyzer(AnalyzerID id)
analyzer::Analyzer* Connection::FindAnalyzer(analyzer::ID id)
{
return root_analyzer ? root_analyzer->FindChild(id) : 0;
}
Analyzer* Connection::FindAnalyzer(AnalyzerTag::Tag tag)
analyzer::Analyzer* Connection::FindAnalyzer(analyzer::Tag tag)
{
return root_analyzer ? root_analyzer->FindChild(tag) : 0;
}
analyzer::Analyzer* Connection::FindAnalyzer(const char* name)
{
return root_analyzer->FindChild(name);
}
void Connection::AppendAddl(const char* str)
{
Unref(BuildConnVal());
@ -540,7 +546,7 @@ Val* Connection::BuildVersionVal(const char* s, int len)
}
int Connection::VersionFoundEvent(const IPAddr& addr, const char* s, int len,
Analyzer* analyzer)
analyzer::Analyzer* analyzer)
{
if ( ! software_version_found && ! software_parse_error )
return 1;
@ -578,7 +584,7 @@ int Connection::VersionFoundEvent(const IPAddr& addr, const char* s, int len,
}
int Connection::UnparsedVersionFoundEvent(const IPAddr& addr,
const char* full, int len, Analyzer* analyzer)
const char* full, int len, analyzer::Analyzer* analyzer)
{
// Skip leading white space.
while ( len && isspace(*full) )
@ -602,7 +608,7 @@ int Connection::UnparsedVersionFoundEvent(const IPAddr& addr,
return 1;
}
void Connection::Event(EventHandlerPtr f, Analyzer* analyzer, const char* name)
void Connection::Event(EventHandlerPtr f, analyzer::Analyzer* analyzer, const char* name)
{
if ( ! f )
return;
@ -615,7 +621,7 @@ void Connection::Event(EventHandlerPtr f, Analyzer* analyzer, const char* name)
ConnectionEvent(f, analyzer, vl);
}
void Connection::Event(EventHandlerPtr f, Analyzer* analyzer, Val* v1, Val* v2)
void Connection::Event(EventHandlerPtr f, analyzer::Analyzer* analyzer, Val* v1, Val* v2)
{
if ( ! f )
{
@ -634,7 +640,7 @@ void Connection::Event(EventHandlerPtr f, Analyzer* analyzer, Val* v1, Val* v2)
ConnectionEvent(f, analyzer, vl);
}
void Connection::ConnectionEvent(EventHandlerPtr f, Analyzer* a, val_list* vl)
void Connection::ConnectionEvent(EventHandlerPtr f, analyzer::Analyzer* a, val_list* vl)
{
if ( ! f )
{
@ -929,7 +935,7 @@ error:
return false;
}
void Connection::SetRootAnalyzer(TransportLayerAnalyzer* analyzer, PIA* pia)
void Connection::SetRootAnalyzer(analyzer::TransportLayerAnalyzer* analyzer, analyzer::pia::PIA* pia)
{
root_analyzer = analyzer;
primary_PIA = pia;

View file

@ -11,19 +11,22 @@
#include "Serializer.h"
#include "PersistenceSerializer.h"
#include "RuleMatcher.h"
#include "AnalyzerTags.h"
#include "IPAddr.h"
#include "TunnelEncapsulation.h"
#include "analyzer/Tag.h"
#include "analyzer/Analyzer.h"
class Connection;
class ConnectionTimer;
class NetSessions;
class LoginConn;
class RuleHdrTest;
class Specific_RE_Matcher;
class TransportLayerAnalyzer;
class RuleEndpointState;
namespace analyzer { class TransportLayerAnalyzer; }
typedef enum {
NUL_IN_LINE,
SINGULAR_CR,
@ -47,7 +50,7 @@ static inline int addr_port_canon_lt(const IPAddr& addr1, uint32 p1,
return addr1 < addr2 || (addr1 == addr2 && p1 < p2);
}
class Analyzer;
namespace analyzer { class Analyzer; }
class Connection : public BroObj {
public:
@ -102,8 +105,9 @@ public:
void FlipRoles();
Analyzer* FindAnalyzer(AnalyzerID id);
Analyzer* FindAnalyzer(AnalyzerTag::Tag tag); // find first in tree.
analyzer::Analyzer* FindAnalyzer(analyzer::ID id);
analyzer::Analyzer* FindAnalyzer(analyzer::Tag tag); // find first in tree.
analyzer::Analyzer* FindAnalyzer(const char* name); // find first in tree.
TransportProto ConnTransport() const { return proto; }
@ -161,15 +165,15 @@ public:
// Raises a software_version_found event based on the
// given string (returns false if it's not parseable).
int VersionFoundEvent(const IPAddr& addr, const char* s, int len,
Analyzer* analyzer = 0);
analyzer::Analyzer* analyzer = 0);
// Raises a software_unparsed_version_found event.
int UnparsedVersionFoundEvent(const IPAddr& addr,
const char* full_descr, int len, Analyzer* analyzer);
const char* full_descr, int len, analyzer::Analyzer* analyzer);
void Event(EventHandlerPtr f, Analyzer* analyzer, const char* name = 0);
void Event(EventHandlerPtr f, Analyzer* analyzer, Val* v1, Val* v2 = 0);
void ConnectionEvent(EventHandlerPtr f, Analyzer* analyzer,
void Event(EventHandlerPtr f, analyzer::Analyzer* analyzer, const char* name = 0);
void Event(EventHandlerPtr f, analyzer::Analyzer* analyzer, Val* v1, Val* v2 = 0);
void ConnectionEvent(EventHandlerPtr f, analyzer::Analyzer* analyzer,
val_list* vl);
void Weird(const char* name, const char* addl = "");
@ -241,9 +245,9 @@ public:
void DeleteTimer(double t);
// Sets the root of the analyzer tree as well as the primary PIA.
void SetRootAnalyzer(TransportLayerAnalyzer* analyzer, PIA* pia);
TransportLayerAnalyzer* GetRootAnalyzer() { return root_analyzer; }
PIA* GetPrimaryPIA() { return primary_PIA; }
void SetRootAnalyzer(analyzer::TransportLayerAnalyzer* analyzer, analyzer::pia::PIA* pia);
analyzer::TransportLayerAnalyzer* GetRootAnalyzer() { return root_analyzer; }
analyzer::pia::PIA* GetPrimaryPIA() { return primary_PIA; }
// Sets the transport protocol in use.
void SetTransport(TransportProto arg_proto) { proto = arg_proto; }
@ -314,8 +318,8 @@ protected:
string history;
uint32 hist_seen;
TransportLayerAnalyzer* root_analyzer;
PIA* primary_PIA;
analyzer::TransportLayerAnalyzer* root_analyzer;
analyzer::pia::PIA* primary_PIA;
uint64 uid; // Globally unique connection ID.
};

View file

@ -1,24 +0,0 @@
#include "DHCP-binpac.h"
DHCP_Analyzer_binpac::DHCP_Analyzer_binpac(Connection* conn)
: Analyzer(AnalyzerTag::DHCP_BINPAC, conn)
{
interp = new binpac::DHCP::DHCP_Conn(this);
}
DHCP_Analyzer_binpac::~DHCP_Analyzer_binpac()
{
delete interp;
}
void DHCP_Analyzer_binpac::Done()
{
Analyzer::Done();
}
void DHCP_Analyzer_binpac::DeliverPacket(int len, const u_char* data,
bool orig, int seq, const IP_Hdr* ip, int caplen)
{
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
interp->NewData(orig, data, data + len);
}

View file

@ -1,28 +0,0 @@
#ifndef dhcp_binpac_h
#define dhcp_binpac_h
#include "UDP.h"
#include "dhcp_pac.h"
class DHCP_Analyzer_binpac : public Analyzer {
public:
DHCP_Analyzer_binpac(Connection* conn);
virtual ~DHCP_Analyzer_binpac();
virtual void Done();
virtual void DeliverPacket(int len, const u_char* data, bool orig,
int seq, const IP_Hdr* ip, int caplen);
static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new DHCP_Analyzer_binpac(conn); }
static bool Available()
{ return dhcp_request && FLAGS_use_binpac; }
protected:
binpac::DHCP::DHCP_Conn* interp;
};
#endif

View file

@ -1,90 +0,0 @@
#include "DNS-binpac.h"
#include "TCP_Reassembler.h"
DNS_UDP_Analyzer_binpac::DNS_UDP_Analyzer_binpac(Connection* conn)
: Analyzer(AnalyzerTag::DNS_UDP_BINPAC, conn)
{
interp = new binpac::DNS::DNS_Conn(this);
did_session_done = 0;
ADD_ANALYZER_TIMER(&DNS_UDP_Analyzer_binpac::ExpireTimer,
network_time + dns_session_timeout, 1, TIMER_DNS_EXPIRE);
}
DNS_UDP_Analyzer_binpac::~DNS_UDP_Analyzer_binpac()
{
delete interp;
}
void DNS_UDP_Analyzer_binpac::Done()
{
Analyzer::Done();
if ( ! did_session_done )
Event(udp_session_done);
}
void DNS_UDP_Analyzer_binpac::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen)
{
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
interp->NewData(orig, data, data + len);
}
void DNS_UDP_Analyzer_binpac::ExpireTimer(double t)
{
// The - 1.0 in the following is to allow 1 second for the
// common case of a single request followed by a single reply,
// so we don't needlessly set the timer twice in that case.
if ( t - Conn()->LastTime() >= dns_session_timeout - 1.0 || terminating )
{
Event(connection_timeout);
sessions->Remove(Conn());
}
else
ADD_ANALYZER_TIMER(&DNS_UDP_Analyzer_binpac::ExpireTimer,
t + dns_session_timeout, 1, TIMER_DNS_EXPIRE);
}
DNS_TCP_Analyzer_binpac::DNS_TCP_Analyzer_binpac(Connection* conn)
: TCP_ApplicationAnalyzer(AnalyzerTag::DNS_TCP_BINPAC, conn)
{
interp = new binpac::DNS_on_TCP::DNS_TCP_Conn(this);
}
DNS_TCP_Analyzer_binpac::~DNS_TCP_Analyzer_binpac()
{
delete interp;
}
void DNS_TCP_Analyzer_binpac::Done()
{
TCP_ApplicationAnalyzer::Done();
interp->FlowEOF(true);
interp->FlowEOF(false);
}
void DNS_TCP_Analyzer_binpac::EndpointEOF(bool is_orig)
{
TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
interp->FlowEOF(is_orig);
}
void DNS_TCP_Analyzer_binpac::DeliverStream(int len, const u_char* data,
bool orig)
{
TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
assert(TCP());
if ( TCP()->IsPartial() || TCP()->HadGap(orig) )
// punt-on-partial or stop-on-gap.
return;
interp->NewData(orig, data, data + len);
}
void DNS_TCP_Analyzer_binpac::Undelivered(int seq, int len, bool orig)
{
TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
interp->NewGap(orig, len);
}

View file

@ -1,60 +0,0 @@
#ifndef dns_binpac_h
#define dns_binpac_h
#include "UDP.h"
#include "TCP.h"
#include "dns_pac.h"
// FIXME: As the binpac analyer for DNS-TCP and DNS-UDP are currently
// structured, we cannot directly combine them into one analyzer. Can we
// change that easily? (Ideally, the TCP preprocessing would become a
// support-analyzer as it is done for the traditional DNS analyzer.)
class DNS_UDP_Analyzer_binpac : public Analyzer {
public:
DNS_UDP_Analyzer_binpac(Connection* conn);
virtual ~DNS_UDP_Analyzer_binpac();
virtual void Done();
virtual void DeliverPacket(int len, const u_char* data, bool orig,
int seq, const IP_Hdr* ip, int caplen);
static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new DNS_UDP_Analyzer_binpac(conn); }
static bool Available()
{ return (dns_request || dns_full_request) && FLAGS_use_binpac; }
protected:
friend class AnalyzerTimer;
void ExpireTimer(double t);
int did_session_done;
binpac::DNS::DNS_Conn* interp;
};
#include "dns_tcp_pac.h"
class DNS_TCP_Analyzer_binpac : public TCP_ApplicationAnalyzer {
public:
DNS_TCP_Analyzer_binpac(Connection* conn);
virtual ~DNS_TCP_Analyzer_binpac();
virtual void Done();
virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual void Undelivered(int seq, int len, bool orig);
virtual void EndpointEOF(bool is_orig);
static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new DNS_TCP_Analyzer_binpac(conn); }
static bool Available()
{ return (dns_request || dns_full_request) && FLAGS_use_binpac; }
protected:
binpac::DNS_on_TCP::DNS_TCP_Conn* interp;
};
#endif

View file

@ -1,407 +0,0 @@
#include "DPM.h"
#include "PIA.h"
#include "Hash.h"
#include "ICMP.h"
#include "UDP.h"
#include "TCP.h"
#include "Val.h"
#include "BackDoor.h"
#include "InterConn.h"
#include "SteppingStone.h"
#include "ConnSizeAnalyzer.h"
ExpectedConn::ExpectedConn(const IPAddr& _orig, const IPAddr& _resp,
uint16 _resp_p, uint16 _proto)
{
if ( _orig == IPAddr(string("0.0.0.0")) )
// don't use the IPv4 mapping, use the literal unspecified address
// to indicate a wildcard
orig = IPAddr(string("::"));
else
orig = _orig;
resp = _resp;
resp_p = _resp_p;
proto = _proto;
}
ExpectedConn::ExpectedConn(const ExpectedConn& c)
{
orig = c.orig;
resp = c.resp;
resp_p = c.resp_p;
proto = c.proto;
}
DPM::DPM()
: active_analyzers(0), expected_conns_queue(AssignedAnalyzer::compare)
{
}
DPM::~DPM()
{
delete [] active_analyzers;
}
void DPM::PreScriptInit()
{
for ( int i = 1; i < int(AnalyzerTag::LastAnalyzer); i++ )
{
// Create IDs ANALYZER_*.
ID* id = install_ID(fmt("ANALYZER_%s",
Analyzer::analyzer_configs[i].name),
GLOBAL_MODULE_NAME, true, false);
assert(id);
id->SetVal(new Val(i, TYPE_COUNT));
id->SetType(id->ID_Val()->Type()->Ref());
}
}
void DPM::PostScriptInit()
{
active_analyzers = new bool[int(AnalyzerTag::LastAnalyzer)];
for ( int i = 1; i < int(AnalyzerTag::LastAnalyzer); i++ )
{
if ( ! Analyzer::analyzer_configs[i].available )
continue;
active_analyzers[i] = Analyzer::analyzer_configs[i].available();
if ( active_analyzers[i] )
AddConfig(Analyzer::analyzer_configs[i]);
}
}
void DPM::AddConfig(const Analyzer::Config& cfg)
{
#ifdef USE_PERFTOOLS_DEBUG
HeapLeakChecker::Disabler disabler;
#endif
Val* index = new Val(cfg.tag, TYPE_COUNT);
Val* v = dpd_config->Lookup(index);
#ifdef DEBUG
ODesc desc;
#endif
if ( v )
{
RecordVal* cfg_record = v->AsRecordVal();
Val* ports = cfg_record->Lookup(0);
if ( ports )
{
ListVal* plist = ports->AsTableVal()->ConvertToPureList();
for ( int i = 0; i< plist->Length(); ++i )
{
PortVal* port = plist->Index(i)->AsPortVal();
analyzer_map* ports =
port->IsTCP() ? &tcp_ports : &udp_ports;
analyzer_map::iterator j =
ports->find(port->Port());
if ( j == ports->end() )
{
tag_list* analyzers = new tag_list;
analyzers->push_back(cfg.tag);
ports->insert(analyzer_map::value_type(port->Port(), analyzers));
}
else
j->second->push_back(cfg.tag);
#ifdef DEBUG
port->Describe(&desc);
desc.SP();
#endif
}
}
}
DBG_LOG(DBG_DPD, "%s analyzer active on port(s) %s", cfg.name, desc.Description());
Unref(index);
}
AnalyzerTag::Tag DPM::GetExpected(int proto, const Connection* conn)
{
if ( ! expected_conns.Length() )
return AnalyzerTag::Error;
ExpectedConn c(conn->OrigAddr(), conn->RespAddr(),
ntohs(conn->RespPort()), proto);
HashKey* key = BuildExpectedConnHashKey(c);
AssignedAnalyzer* a = expected_conns.Lookup(key);
delete key;
if ( ! a )
{
// Wildcard for originator.
c.orig = IPAddr(string("::"));
HashKey* key = BuildExpectedConnHashKey(c);
a = expected_conns.Lookup(key);
delete key;
}
if ( ! a )
return AnalyzerTag::Error;
// We don't delete it here. It will be expired eventually.
return a->analyzer;
}
bool DPM::BuildInitialAnalyzerTree(TransportProto proto, Connection* conn,
const u_char* data)
{
TCP_Analyzer* tcp = 0;
UDP_Analyzer* udp = 0;
ICMP_Analyzer* icmp = 0;
TransportLayerAnalyzer* root = 0;
AnalyzerTag::Tag expected = AnalyzerTag::Error;
analyzer_map* ports = 0;
PIA* pia = 0;
bool analyzed = false;
switch ( proto ) {
case TRANSPORT_TCP:
root = tcp = new TCP_Analyzer(conn);
pia = new PIA_TCP(conn);
expected = GetExpected(proto, conn);
ports = &tcp_ports;
DBG_DPD(conn, "activated TCP analyzer");
break;
case TRANSPORT_UDP:
root = udp = new UDP_Analyzer(conn);
pia = new PIA_UDP(conn);
expected = GetExpected(proto, conn);
ports = &udp_ports;
DBG_DPD(conn, "activated UDP analyzer");
break;
case TRANSPORT_ICMP: {
root = icmp = new ICMP_Analyzer(conn);
DBG_DPD(conn, "activated ICMP analyzer");
analyzed = true;
break;
}
default:
reporter->InternalError("unknown protocol");
}
if ( ! root )
{
DBG_DPD(conn, "cannot build analyzer tree");
return false;
}
// Any scheduled analyzer?
if ( expected != AnalyzerTag::Error )
{
Analyzer* analyzer =
Analyzer::InstantiateAnalyzer(expected, conn);
root->AddChildAnalyzer(analyzer, false);
DBG_DPD_ARGS(conn, "activated %s analyzer as scheduled",
Analyzer::GetTagName(expected));
// Hmm... Do we want *just* the expected analyzer, or all
// other potential analyzers as well? For now we only take
// the scheduled one.
}
else
{ // Let's see if it's a port we know.
if ( ports && ! dpd_ignore_ports )
{
analyzer_map::const_iterator i =
ports->find(ntohs(conn->RespPort()));
if ( i != ports->end() )
{
tag_list* analyzers = i->second;
for ( tag_list::const_iterator j = analyzers->begin();
j != analyzers->end(); j++ )
{
Analyzer* analyzer =
Analyzer::InstantiateAnalyzer(*j, conn);
root->AddChildAnalyzer(analyzer, false);
DBG_DPD_ARGS(conn, "activated %s analyzer due to port %d", Analyzer::GetTagName(*j), conn->RespPort());
}
}
}
}
if ( tcp )
{
// We have to decide whether to reassamble the stream.
// We turn it on right away if we already have an app-layer
// analyzer, reassemble_first_packets is true, or the user
// asks us to do so. In all other cases, reassembly may
// be turned on later by the TCP PIA.
bool reass = root->GetChildren().size() ||
dpd_reassemble_first_packets ||
tcp_content_deliver_all_orig ||
tcp_content_deliver_all_resp;
if ( tcp_contents && ! reass )
{
PortVal dport(ntohs(conn->RespPort()), TRANSPORT_TCP);
Val* result;
if ( ! reass )
reass = tcp_content_delivery_ports_orig->Lookup(&dport);
if ( ! reass )
reass = tcp_content_delivery_ports_resp->Lookup(&dport);
}
if ( reass )
tcp->EnableReassembly();
// Add a BackDoor analyzer if requested. This analyzer
// can handle both reassembled and non-reassembled input.
if ( BackDoor_Analyzer::Available() )
{
BackDoor_Analyzer* bd = new BackDoor_Analyzer(conn);
tcp->AddChildAnalyzer(bd, false);
}
// Add a InterConn analyzer if requested. This analyzer
// can handle both reassembled and non-reassembled input.
if ( InterConn_Analyzer::Available() )
{
InterConn_Analyzer* bd = new InterConn_Analyzer(conn);
tcp->AddChildAnalyzer(bd, false);
}
// Add a SteppingStone analyzer if requested. The port
// should really not be hardcoded here, but as it can
// handle non-reassembled data, it doesn't really fit into
// our general framing ... Better would be to turn it
// on *after* we discover we have interactive traffic.
uint16 resp_port = ntohs(conn->RespPort());
if ( SteppingStone_Analyzer::Available() &&
(resp_port == 22 || resp_port == 23 || resp_port == 513) )
{
AddrVal src(conn->OrigAddr());
if ( ! stp_skip_src->Lookup(&src) )
{
SteppingStone_Analyzer* bd =
new SteppingStone_Analyzer(conn);
tcp->AddChildAnalyzer(bd, false);
}
}
// Add TCPStats analyzer. This needs to see packets so
// we cannot add it as a normal child.
if ( TCPStats_Analyzer::Available() )
tcp->AddChildPacketAnalyzer(new TCPStats_Analyzer(conn));
// Add ConnSize analyzer. Needs to see packets, not stream.
if ( ConnSize_Analyzer::Available() )
tcp->AddChildPacketAnalyzer(new ConnSize_Analyzer(conn));
}
else
{
if ( ConnSize_Analyzer::Available() )
root->AddChildAnalyzer(new ConnSize_Analyzer(conn), false);
}
if ( pia )
root->AddChildAnalyzer(pia->AsAnalyzer(), false);
if ( root->GetChildren().size() )
analyzed = true;
conn->SetRootAnalyzer(root, pia);
root->Init();
root->InitChildren();
if ( ! analyzed )
conn->SetLifetime(non_analyzed_lifetime);
if ( expected != AnalyzerTag::Error )
conn->Event(expected_connection_seen, 0,
new Val(expected, TYPE_COUNT));
return true;
}
void DPM::ExpectConnection(const IPAddr& orig, const IPAddr& resp,
uint16 resp_p,
TransportProto proto, AnalyzerTag::Tag analyzer,
double timeout, void* cookie)
{
// Use the chance to see if the oldest entry is already expired.
if ( expected_conns_queue.size() )
{
AssignedAnalyzer* a = expected_conns_queue.top();
if ( a->timeout < network_time )
{
if ( ! a->deleted )
{
HashKey* key = BuildExpectedConnHashKey(a->conn);
expected_conns.Remove(key);
delete key;
}
expected_conns_queue.pop();
DBG_LOG(DBG_DPD, "Expired expected %s analyzer for %s",
Analyzer::GetTagName(analyzer),
fmt_conn_id(a->conn.orig, 0,
a->conn.resp,
a->conn.resp_p));
delete a;
}
}
ExpectedConn c(orig, resp, resp_p, proto);
HashKey* key = BuildExpectedConnHashKey(c);
AssignedAnalyzer* a = expected_conns.Lookup(key);
if ( a )
a->deleted = true;
a = new AssignedAnalyzer(c);
a->analyzer = analyzer;
a->cookie = cookie;
a->timeout = network_time + timeout;
a->deleted = false;
expected_conns.Insert(key, a);
expected_conns_queue.push(a);
delete key;
}
void DPM::Done()
{
// Clean up expected-connection table.
while ( expected_conns_queue.size() )
{
AssignedAnalyzer* a = expected_conns_queue.top();
if ( ! a->deleted )
{
HashKey* key = BuildExpectedConnHashKey(a->conn);
expected_conns.Remove(key);
delete key;
}
expected_conns_queue.pop();
delete a;
}
}

131
src/DPM.h
View file

@ -1,131 +0,0 @@
// The central management unit for dynamic analyzer selection.
#ifndef DPM_H
#define DPM_H
#include <queue>
#include "Analyzer.h"
#include "Dict.h"
#include "net_util.h"
// DPM debug logging, which includes the connection id into the message.
#ifdef DEBUG
# define DBG_DPD(conn, txt) \
DBG_LOG(DBG_DPD, "%s " txt, \
fmt_conn_id(conn->OrigAddr(), ntohs(conn->OrigPort()), \
conn->RespAddr(), ntohs(conn->RespPort())));
# define DBG_DPD_ARGS(conn, fmt, args...) \
DBG_LOG(DBG_DPD, "%s " fmt, \
fmt_conn_id(conn->OrigAddr(), ntohs(conn->OrigPort()), \
conn->RespAddr(), ntohs(conn->RespPort())), ##args);
#else
# define DBG_DPD(conn, txt)
# define DBG_DPD_ARGS(conn, fmt, args...)
#endif
// Map to assign expected connections to analyzers.
class ExpectedConn {
public:
ExpectedConn(const IPAddr& _orig, const IPAddr& _resp,
uint16 _resp_p, uint16 _proto);
ExpectedConn(const ExpectedConn& c);
IPAddr orig;
IPAddr resp;
uint16 resp_p;
uint16 proto;
};
// Associates an analyzer for an expected future connection.
class AssignedAnalyzer {
public:
AssignedAnalyzer(const ExpectedConn& c)
: conn(c)
{
}
ExpectedConn conn;
AnalyzerTag::Tag analyzer;
double timeout;
void* cookie;
bool deleted;
static bool compare(const AssignedAnalyzer* a1, const AssignedAnalyzer* a2)
{ return a1->timeout > a2->timeout; }
};
declare(PDict, AssignedAnalyzer);
class DPM {
public:
DPM();
~DPM();
// Setup analyzer config.
void PreScriptInit(); // To be called before scripts are parsed ...
void PostScriptInit(); // ... and after.
// Given info about the first packet, build initial analyzer tree.
//
// It would be more flexible if we simply pass in the IP header
// and then extract the information we need. However, when this
// method is called from the session management, protocol and ports
// have already been extracted there and it would be a waste to do
// it again.
//
// Returns 0 if we can't build a tree (e.g., because the necessary
// analyzers have not been converted to the DPM framework yet...)
bool BuildInitialAnalyzerTree(TransportProto proto, Connection* conn,
const u_char* data);
// Schedules a particular analyzer for an upcoming connection.
// 0 acts as a wildcard for orig. (Cookie is currently unused.
// Eventually, we may pass it on to the analyzer).
void ExpectConnection(const IPAddr& orig, const IPAddr& resp, uint16 resp_p,
TransportProto proto, AnalyzerTag::Tag analyzer,
double timeout, void* cookie);
// Activates signature matching for protocol detection. (Called when an
// DPM signatures is found.)
void ActivateSigs() { sigs_activated = true; }
bool SigsActivated() const { return sigs_activated; }
void Done();
private:
// Convert script-level config into internal data structures.
void AddConfig(const Analyzer::Config& tag);
// Return analyzer if any has been scheduled with ExpectConnection()
// AnalyzerTag::::Error if none.
AnalyzerTag::Tag GetExpected(int proto, const Connection* conn);
// Mappings of destination port to analyzer.
typedef list<AnalyzerTag::Tag> tag_list;
typedef map<uint32, tag_list*> analyzer_map;
analyzer_map tcp_ports;
analyzer_map udp_ports;
// Array of bools indicating whether an analyzer is activated,
// indexed by AnalyzerTag::Tag.
bool* active_analyzers;
// True if signature-matching has been activated.
bool sigs_activated;
PDict(AssignedAnalyzer) expected_conns;
typedef priority_queue<
AssignedAnalyzer*,
vector<AssignedAnalyzer*>,
bool (*)(const AssignedAnalyzer*,
const AssignedAnalyzer*)> conn_queue;
conn_queue expected_conns_queue;
};
extern DPM* dpm;
#endif

View file

@ -21,7 +21,7 @@ enum DebugStream {
DBG_STRING, // String code
DBG_NOTIFIERS, // Notifiers (see StateAccess.h)
DBG_MAINLOOP, // Main IOSource loop
DBG_DPD, // Dynamic application detection framework
DBG_ANALYZER, // Analyzer framework
DBG_TM, // Time-machine packet input via Brocolli
DBG_LOGGING, // Logging streams
DBG_INPUT, // Input streams

View file

@ -13,7 +13,7 @@ int num_events_queued = 0;
int num_events_dispatched = 0;
Event::Event(EventHandlerPtr arg_handler, val_list* arg_args,
SourceID arg_src, AnalyzerID arg_aid, TimerMgr* arg_mgr,
SourceID arg_src, analyzer::ID arg_aid, TimerMgr* arg_mgr,
BroObj* arg_obj)
{
handler = arg_handler;

View file

@ -5,14 +5,16 @@
#include "EventRegistry.h"
#include "Serializer.h"
#include "AnalyzerTags.h"
#include "analyzer/Tag.h"
#include "analyzer/Analyzer.h"
class EventMgr;
class Event : public BroObj {
public:
Event(EventHandlerPtr handler, val_list* args,
SourceID src = SOURCE_LOCAL, AnalyzerID aid = 0,
SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0,
TimerMgr* mgr = 0, BroObj* obj = 0);
~Event();
@ -20,7 +22,7 @@ public:
Event* NextEvent() const { return next_event; }
SourceID Source() const { return src; }
AnalyzerID Analyzer() const { return aid; }
analyzer::ID Analyzer() const { return aid; }
TimerMgr* Mgr() const { return mgr; }
void Describe(ODesc* d) const;
@ -62,7 +64,7 @@ protected:
EventHandlerPtr handler;
val_list* args;
SourceID src;
AnalyzerID aid;
analyzer::ID aid;
TimerMgr* mgr;
BroObj* obj;
Event* next_event;
@ -77,7 +79,7 @@ public:
~EventMgr();
void QueueEvent(EventHandlerPtr h, val_list* vl,
SourceID src = SOURCE_LOCAL, AnalyzerID aid = 0,
SourceID src = SOURCE_LOCAL, analyzer::ID aid = 0,
TimerMgr* mgr = 0, BroObj* obj = 0)
{
if ( h )
@ -105,7 +107,7 @@ public:
// Returns the ID of the analyzer which raised the last event, or 0 if
// non-analyzer event.
AnalyzerID CurrentAnalyzer() const { return current_aid; }
analyzer::ID CurrentAnalyzer() const { return current_aid; }
// Returns the timer mgr associated with the last raised event.
TimerMgr* CurrentTimerMgr() const { return current_mgr; }
@ -124,7 +126,7 @@ protected:
Event* head;
Event* tail;
SourceID current_src;
AnalyzerID current_aid;
analyzer::ID current_aid;
TimerMgr* current_mgr;
RecordVal* src_val;
bool draining;

View file

@ -10,7 +10,6 @@ EventHandler::EventHandler(const char* arg_name)
used = false;
local = 0;
type = 0;
group = 0;
error_handler = false;
enabled = true;
}
@ -19,7 +18,6 @@ EventHandler::~EventHandler()
{
Unref(local);
delete [] name;
delete [] group;
}
EventHandler::operator bool() const

View file

@ -41,10 +41,6 @@ public:
void SetErrorHandler() { error_handler = true; }
bool ErrorHandler() { return error_handler; }
const char* Group() { return group; }
void SetGroup(const char* arg_group)
{ group = copy_string(arg_group); }
void SetEnable(bool arg_enable) { enabled = arg_enable; }
// We don't serialize the handler(s) itself here, but
@ -54,7 +50,6 @@ public:
private:
const char* name;
const char* group;
Func* local;
FuncType* type;
bool used; // this handler is indeed used somewhere

View file

@ -1,6 +1,8 @@
#include "Val.h"
#include "Analyzer.h"
#include "analyzer/Analyzer.h"
#include "EventLauncher.h"
#include "Event.h"
#include "NetVar.h"
#include "Conn.h"
#include "event.bif.func_def"

View file

@ -80,20 +80,13 @@ void EventRegistry::PrintDebug()
while ( (v = handlers.NextEntry(k, c)) )
{
delete k;
fprintf(stderr, "Registered event %s (%s handler)\n", v->Name(),
v->LocalHandler()? "local" : "no");
fprintf(stderr, "Registered event %s (%s handler / %s)\n", v->Name(),
v->LocalHandler()? "local" : "no",
*v ? "active" : "not active"
);
}
}
void EventRegistry::SetGroup(const char* name, const char* group)
{
EventHandler* eh = Lookup(name);
if ( ! eh )
reporter->InternalError("unknown event handler in SetGroup()");
eh->SetGroup(group);
}
void EventRegistry::SetErrorHandler(const char* name)
{
EventHandler* eh = Lookup(name);
@ -103,18 +96,3 @@ void EventRegistry::SetErrorHandler(const char* name)
eh->SetErrorHandler();
}
void EventRegistry::EnableGroup(const char* group, bool enable)
{
IterCookie* c = handlers.InitForIteration();
HashKey* k;
EventHandler* v;
while ( (v = handlers.NextEntry(k, c)) )
{
delete k;
if ( v->Group() && strcmp(v->Group(), group) == 0 )
v->SetEnable(enable);
}
}

View file

@ -26,17 +26,11 @@ public:
typedef PList(constchar) string_list;
string_list* Match(RE_Matcher* pattern);
// Associates a group with the given event.
void SetGroup(const char* name, const char* group);
// Marks a handler as handling errors. Error handler will not be called
// recursively to avoid infinite loops in case they trigger an error
// themselves.
void SetErrorHandler(const char* name);
// Enable/disable all members of the group.
void EnableGroup(const char* group, bool enable);
string_list* UnusedHandlers();
string_list* UsedHandlers();
void PrintDebug();

View file

@ -1,30 +0,0 @@
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef finger_h
#define finger_h
#include "TCP.h"
class ContentLine_Analyzer;
class Finger_Analyzer : public TCP_ApplicationAnalyzer {
public:
Finger_Analyzer(Connection* conn);
virtual ~Finger_Analyzer() {}
virtual void Done();
// Line-based input.
virtual void DeliverStream(int len, const u_char* data, bool orig);
static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new Finger_Analyzer(conn); }
static bool Available() { return finger_request || finger_reply; }
protected:
ContentLine_Analyzer* content_line_orig;
ContentLine_Analyzer* content_line_resp;
int did_deliver;
};
#endif

View file

@ -9,7 +9,7 @@
#include "FlowSrc.h"
#include "Net.h"
#include "netflow_pac.h"
#include "analyzer/protocol/netflow/netflow_pac.h"
#include <errno.h>
FlowSrc::FlowSrc()

View file

@ -38,7 +38,7 @@
#include "Func.h"
#include "Frame.h"
#include "Var.h"
#include "Login.h"
#include "analyzer/protocol/login/Login.h"
#include "Sessions.h"
#include "RE.h"
#include "Serializer.h"
@ -553,18 +553,15 @@ void builtin_error(const char* msg, BroObj* arg)
#include "input.bif.func_h"
#include "reporter.bif.func_h"
#include "strings.bif.func_h"
#include "file_analysis.bif.func_h"
#include "bro.bif.func_def"
#include "logging.bif.func_def"
#include "input.bif.func_def"
#include "reporter.bif.func_def"
#include "strings.bif.func_def"
#include "file_analysis.bif.func_def"
void init_builtin_funcs()
{
ftp_port = internal_type("ftp_port")->AsRecordType();
bro_resources = internal_type("bro_resources")->AsRecordType();
net_stats = internal_type("NetStats")->AsRecordType();
matcher_stats = internal_type("matcher_stats")->AsRecordType();
@ -576,7 +573,6 @@ void init_builtin_funcs()
#include "input.bif.func_init"
#include "reporter.bif.func_init"
#include "strings.bif.func_init"
#include "file_analysis.bif.func_init"
did_builtin_init = true;
}

View file

@ -66,7 +66,6 @@ template<class T, int N> class H3 {
T byte_lookup[N][H3_BYTE_RANGE];
public:
H3();
~H3() { free(byte_lookup); }
T operator()(const void* data, size_t size, size_t offset = 0) const
{
const unsigned char *p = static_cast<const unsigned char*>(data);

View file

@ -1,46 +0,0 @@
#include "HTTP-binpac.h"
#include "TCP_Reassembler.h"
HTTP_Analyzer_binpac::HTTP_Analyzer_binpac(Connection *c)
: TCP_ApplicationAnalyzer(AnalyzerTag::HTTP_BINPAC, c)
{
interp = new binpac::HTTP::HTTP_Conn(this);
}
HTTP_Analyzer_binpac::~HTTP_Analyzer_binpac()
{
delete interp;
}
void HTTP_Analyzer_binpac::Done()
{
TCP_ApplicationAnalyzer::Done();
interp->FlowEOF(true);
interp->FlowEOF(false);
}
void HTTP_Analyzer_binpac::EndpointEOF(bool is_orig)
{
TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
interp->FlowEOF(is_orig);
}
void HTTP_Analyzer_binpac::DeliverStream(int len, const u_char* data, bool orig)
{
TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
assert(TCP());
if ( TCP()->IsPartial() )
// punt on partial.
return;
interp->NewData(orig, data, data + len);
}
void HTTP_Analyzer_binpac::Undelivered(int seq, int len, bool orig)
{
TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
interp->NewGap(orig, len);
}

View file

@ -1,28 +0,0 @@
#ifndef http_binpac_h
#define http_binpac_h
#include "TCP.h"
#include "http_pac.h"
class HTTP_Analyzer_binpac : public TCP_ApplicationAnalyzer {
public:
HTTP_Analyzer_binpac(Connection* conn);
virtual ~HTTP_Analyzer_binpac();
virtual void Done();
virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual void Undelivered(int seq, int len, bool orig);
virtual void EndpointEOF(bool is_orig);
static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new HTTP_Analyzer_binpac(conn); }
static bool Available()
{ return (http_request || http_reply) && FLAGS_use_binpac; }
protected:
binpac::HTTP::HTTP_Conn* interp;
};
#endif

View file

@ -221,21 +221,7 @@ void ID::UpdateValAttrs()
if ( Type()->Tag() == TYPE_FUNC )
{
Attr* attr = attrs->FindAttr(ATTR_GROUP);
if ( attr )
{
Val* group = attr->AttrExpr()->ExprVal();
if ( group )
{
if ( group->Type()->Tag() == TYPE_STRING )
event_registry->SetGroup(Name(), group->AsString()->CheckString());
else
Error("&group attribute takes string");
}
}
attr = attrs->FindAttr(ATTR_ERROR_HANDLER);
Attr* attr = attrs->FindAttr(ATTR_ERROR_HANDLER);
if ( attr )
event_registry->SetErrorHandler(Name());

View file

@ -26,6 +26,7 @@ public:
bool IsGlobal() const { return scope != SCOPE_FUNCTION; }
bool IsExport() const { return is_export; }
void SetExport() { is_export = true; }
string ModuleName() const;

View file

@ -5,9 +5,10 @@
#include "IPAddr.h"
#include "Reporter.h"
#include "Conn.h"
#include "DPM.h"
#include "bro_inet_ntop.h"
#include "analyzer/Manager.h"
const uint8_t IPAddr::v4_mapped_prefix[12] = { 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0xff, 0xff };
@ -44,23 +45,6 @@ HashKey* BuildConnIDHashKey(const ConnID& id)
return new HashKey(&key, sizeof(key));
}
HashKey* BuildExpectedConnHashKey(const ExpectedConn& c)
{
struct {
in6_addr orig;
in6_addr resp;
uint16 resp_p;
uint16 proto;
} key;
key.orig = c.orig.in6;
key.resp = c.resp.in6;
key.resp_p = c.resp_p;
key.proto = c.proto;
return new HashKey(&key, sizeof(key));
}
void IPAddr::Mask(int top_bits_to_keep)
{
if ( top_bits_to_keep < 0 || top_bits_to_keep > 128 )

View file

@ -14,7 +14,7 @@
#include "threading/SerialTypes.h"
struct ConnID;
class ExpectedConn;
namespace analyzer { class ExpectedConn; }
typedef in_addr in4_addr;
@ -363,7 +363,6 @@ public:
void ConvertToThreadingValue(threading::Value::addr_t* v) const;
friend HashKey* BuildConnIDHashKey(const ConnID& id);
friend HashKey* BuildExpectedConnHashKey(const ExpectedConn& c);
unsigned int MemoryAllocation() const { return padded_sizeof(*this); }
@ -452,11 +451,6 @@ inline void IPAddr::ConvertToThreadingValue(threading::Value::addr_t* v) const
*/
HashKey* BuildConnIDHashKey(const ConnID& id);
/**
* Returns a hash key for a given ExpectedConn instance. Passes ownership to caller.
*/
HashKey* BuildExpectedConnHashKey(const ExpectedConn& c);
/**
* Class storing both IPv4 and IPv6 prefixes
* (i.e., \c 192.168.1.1/16 and \c FD00::/8.

View file

@ -1,58 +0,0 @@
#ifndef MODBUS_H
#define MODBUS_H
#include "TCP.h"
#include "modbus_pac.h"
class ModbusTCP_Analyzer : public TCP_ApplicationAnalyzer {
public:
ModbusTCP_Analyzer(Connection* conn);
virtual ~ModbusTCP_Analyzer();
virtual void Done();
virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual void Undelivered(int seq, int len, bool orig);
virtual void EndpointEOF(bool is_orig);
static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new ModbusTCP_Analyzer(conn); }
// Put event names in this function
static bool Available()
{
return modbus_message
| modbus_exception
| modbus_read_coils_request
| modbus_read_coils_response
| modbus_read_discrete_inputs_request
| modbus_read_discrete_inputs_response
| modbus_read_holding_registers_request
| modbus_read_holding_registers_response
| modbus_read_input_registers_request
| modbus_read_input_registers_response
| modbus_write_single_coil_request
| modbus_write_single_coil_response
| modbus_write_single_register_request
| modbus_write_single_register_response
| modbus_write_multiple_coils_request
| modbus_write_multiple_coils_response
| modbus_write_multiple_registers_request
| modbus_write_multiple_registers_response
| modbus_read_file_record_request
| modbus_read_file_record_response
| modbus_write_file_record_request
| modbus_write_file_record_response
| modbus_mask_write_register_request
| modbus_mask_write_register_response
| modbus_read_write_multiple_registers_request
| modbus_read_write_multiple_registers_response
| modbus_read_fifo_queue_request
| modbus_read_fifo_queue_response;
}
protected:
binpac::ModbusTCP::ModbusTCP_Conn* interp;
};
#endif

View file

@ -94,7 +94,6 @@ RecordType* http_stats_rec;
RecordType* http_message_stat;
int truncate_http_URI;
int pm_request;
RecordType* pm_mapping;
TableType* pm_mappings;
RecordType* pm_port_request;
@ -209,7 +208,6 @@ TableType* irc_join_list;
RecordType* irc_join_info;
TableVal* irc_servers;
TableVal* dpd_config;
int dpd_reassemble_first_packets;
int dpd_buffer_size;
int dpd_match_only_beginning;
@ -251,7 +249,6 @@ OpaqueType* entropy_type;
#include "logging.bif.netvar_def"
#include "input.bif.netvar_def"
#include "reporter.bif.netvar_def"
#include "file_analysis.bif.netvar_def"
void init_event_handlers()
{
@ -319,7 +316,6 @@ void init_net_var()
#include "logging.bif.netvar_init"
#include "input.bif.netvar_init"
#include "reporter.bif.netvar_init"
#include "file_analysis.bif.netvar_init"
conn_id = internal_type("conn_id")->AsRecordType();
endpoint = internal_type("endpoint")->AsRecordType();
@ -423,14 +419,6 @@ void init_net_var()
http_message_stat = internal_type("http_message_stat")->AsRecordType();
truncate_http_URI = opt_internal_int("truncate_http_URI");
pm_request = pm_request_null || pm_request_set ||
pm_request_unset || pm_request_getport ||
pm_request_dump || pm_request_callit ||
pm_attempt_null || pm_attempt_set ||
pm_attempt_unset || pm_attempt_getport ||
pm_attempt_dump || pm_attempt_callit ||
pm_bad_port;
pm_mapping = internal_type("pm_mapping")->AsRecordType();
pm_mappings = internal_type("pm_mappings")->AsTableType();
pm_port_request = internal_type("pm_port_request")->AsRecordType();
@ -526,7 +514,6 @@ void init_net_var()
opt_internal_double("remote_trace_sync_interval");
remote_trace_sync_peers = opt_internal_int("remote_trace_sync_peers");
dpd_config = internal_val("dpd_config")->AsTableVal();
dpd_reassemble_first_packets =
opt_internal_int("dpd_reassemble_first_packets");
dpd_buffer_size = opt_internal_int("dpd_buffer_size");

View file

@ -97,7 +97,6 @@ extern RecordType* http_stats_rec;
extern RecordType* http_message_stat;
extern int truncate_http_URI;
extern int pm_request;
extern RecordType* pm_mapping;
extern TableType* pm_mappings;
extern RecordType* pm_port_request;
@ -213,7 +212,6 @@ extern TableType* irc_join_list;
extern RecordType* irc_join_info;
extern TableVal* irc_servers;
extern TableVal* dpd_config;
extern int dpd_reassemble_first_packets;
extern int dpd_buffer_size;
extern int dpd_match_only_beginning;
@ -262,6 +260,5 @@ extern void init_net_var();
#include "logging.bif.netvar_h"
#include "input.bif.netvar_h"
#include "reporter.bif.netvar_h"
#include "file_analysis.bif.netvar_h"
#endif

View file

@ -8,8 +8,9 @@ using std::string;
#include "Conn.h"
#include "Event.h"
#include "NetVar.h"
#include "DPM.h"
#include "PIA.h"
#include "analyzer/protocol/pia/PIA.h"
#include "analyzer/Manager.h"
void RuleActionEvent::DoAction(const Rule* parent, RuleEndpointState* state,
const u_char* data, int len)
@ -34,42 +35,45 @@ void RuleActionEvent::PrintDebug()
fprintf(stderr, " RuleActionEvent: |%s|\n", msg);
}
RuleActionDPM::RuleActionDPM(const char* arg_analyzer)
RuleActionAnalyzer::RuleActionAnalyzer(const char* arg_analyzer)
{
string str(arg_analyzer);
string::size_type pos = str.find(':');
string arg = str.substr(0, pos);
analyzer = Analyzer::GetTag(arg.c_str());
analyzer = analyzer_mgr->GetAnalyzerTag(arg.c_str());
if ( ! analyzer )
reporter->Warning("unknown analyzer '%s' specified in rule", arg.c_str());
if ( pos != string::npos )
{
arg = str.substr(pos + 1);
child_analyzer = Analyzer::GetTag(arg.c_str());
child_analyzer = analyzer_mgr->GetAnalyzerTag(arg.c_str());
if ( ! child_analyzer )
reporter->Warning("unknown analyzer '%s' specified in rule", arg.c_str());
}
else
child_analyzer = AnalyzerTag::Error;
if ( analyzer != AnalyzerTag::Error )
dpm->ActivateSigs();
child_analyzer = analyzer::Tag();
}
void RuleActionDPM::PrintDebug()
void RuleActionAnalyzer::PrintDebug()
{
if ( child_analyzer == AnalyzerTag::Error )
fprintf(stderr, "|%s|\n", Analyzer::GetTagName(analyzer));
if ( ! child_analyzer )
fprintf(stderr, "|%s|\n", analyzer_mgr->GetAnalyzerName(analyzer));
else
fprintf(stderr, "|%s:%s|\n",
Analyzer::GetTagName(analyzer),
Analyzer::GetTagName(child_analyzer));
analyzer_mgr->GetAnalyzerName(analyzer),
analyzer_mgr->GetAnalyzerName(child_analyzer));
}
void RuleActionEnable::DoAction(const Rule* parent, RuleEndpointState* state,
const u_char* data, int len)
{
if ( ChildAnalyzer() == AnalyzerTag::Error )
if ( ! ChildAnalyzer() )
{
if ( ! Analyzer::IsAvailable(Analyzer()) )
if ( ! analyzer_mgr->IsEnabled(Analyzer()) )
return;
if ( state->PIA() )
@ -77,7 +81,7 @@ void RuleActionEnable::DoAction(const Rule* parent, RuleEndpointState* state,
}
else
{
if ( ! Analyzer::IsAvailable(ChildAnalyzer()) )
if ( ! analyzer_mgr->IsEnabled(ChildAnalyzer()) )
return;
// This is ugly and works only if there exists only one
@ -90,13 +94,13 @@ void RuleActionEnable::DoAction(const Rule* parent, RuleEndpointState* state,
void RuleActionEnable::PrintDebug()
{
fprintf(stderr, " RuleActionEnable: ");
RuleActionDPM::PrintDebug();
RuleActionAnalyzer::PrintDebug();
}
void RuleActionDisable::DoAction(const Rule* parent, RuleEndpointState* state,
const u_char* data, int len)
{
if ( ChildAnalyzer() == AnalyzerTag::Error )
if ( ! ChildAnalyzer() )
{
if ( state->PIA() )
state->PIA()->DeactivateAnalyzer(Analyzer());
@ -109,5 +113,5 @@ void RuleActionDisable::DoAction(const Rule* parent, RuleEndpointState* state,
void RuleActionDisable::PrintDebug()
{
fprintf(stderr, " RuleActionDisable: ");
RuleActionDPM::PrintDebug();
RuleActionAnalyzer::PrintDebug();
}

View file

@ -1,11 +1,12 @@
#ifndef ruleaction_h
#define ruleaction_h
#include "AnalyzerTags.h"
#include "BroString.h"
#include "List.h"
#include "util.h"
#include "analyzer/Tag.h"
class Rule;
class RuleEndpointState;
@ -35,29 +36,27 @@ private:
const char* msg;
};
// Base class for DPM enable/disable actions.
class RuleActionDPM : public RuleAction {
// Base class for enable/disable actions.
class RuleActionAnalyzer : public RuleAction {
public:
RuleActionDPM(const char* analyzer);
RuleActionAnalyzer(const char* analyzer);
virtual void DoAction(const Rule* parent, RuleEndpointState* state,
const u_char* data, int len) = 0;
virtual void PrintDebug();
AnalyzerTag::Tag Analyzer() const { return analyzer; }
AnalyzerTag::Tag ChildAnalyzer() const { return child_analyzer; }
analyzer::Tag Analyzer() const { return analyzer; }
analyzer::Tag ChildAnalyzer() const { return child_analyzer; }
private:
// FIXME: This is in fact an AnalyzerID but we can't include "Analyzer.h"
// at this point due to circular dependenides. Fix that!
AnalyzerTag::Tag analyzer;
AnalyzerTag::Tag child_analyzer;
analyzer::Tag analyzer;
analyzer::Tag child_analyzer;
};
class RuleActionEnable : public RuleActionDPM {
class RuleActionEnable : public RuleActionAnalyzer {
public:
RuleActionEnable(const char* analyzer) : RuleActionDPM(analyzer) {}
RuleActionEnable(const char* analyzer) : RuleActionAnalyzer(analyzer) {}
virtual void DoAction(const Rule* parent, RuleEndpointState* state,
const u_char* data, int len);
@ -65,9 +64,9 @@ public:
virtual void PrintDebug();
};
class RuleActionDisable : public RuleActionDPM {
class RuleActionDisable : public RuleActionAnalyzer {
public:
RuleActionDisable(const char* analyzer) : RuleActionDPM(analyzer) {}
RuleActionDisable(const char* analyzer) : RuleActionAnalyzer(analyzer) {}
virtual void DoAction(const Rule* parent, RuleEndpointState* state,
const u_char* data, int len);

View file

@ -1,29 +1,29 @@
#include "config.h"
#include "RuleCondition.h"
#include "TCP.h"
#include "analyzer/protocol/tcp/TCP.h"
#include "Scope.h"
static inline bool is_established(const TCP_Endpoint* e)
static inline bool is_established(const analyzer::tcp::TCP_Endpoint* e)
{
// We more or less follow Snort here: an established session
// is one for which the initial handshake has succeded (but we
// add partial connections). The connection tear-down is part
// of the connection.
return e->state != TCP_ENDPOINT_INACTIVE &&
e->state != TCP_ENDPOINT_SYN_SENT &&
e->state != TCP_ENDPOINT_SYN_ACK_SENT;
return e->state != analyzer::tcp::TCP_ENDPOINT_INACTIVE &&
e->state != analyzer::tcp::TCP_ENDPOINT_SYN_SENT &&
e->state != analyzer::tcp::TCP_ENDPOINT_SYN_ACK_SENT;
}
bool RuleConditionTCPState::DoMatch(Rule* rule, RuleEndpointState* state,
const u_char* data, int len)
{
Analyzer* root = state->GetAnalyzer()->Conn()->GetRootAnalyzer();
analyzer::Analyzer* root = state->GetAnalyzer()->Conn()->GetRootAnalyzer();
if ( ! root || root->GetTag() != AnalyzerTag::TCP )
if ( ! root || ! root->IsAnalyzer("TCP") )
return false;
TCP_Analyzer* ta = static_cast<TCP_Analyzer*>(root);
analyzer::tcp::TCP_Analyzer* ta = static_cast<analyzer::tcp::TCP_Analyzer*>(root);
if ( tcpstates & STATE_STATELESS )
return true;

View file

@ -3,7 +3,7 @@
#include "config.h"
#include "Analyzer.h"
#include "analyzer/Analyzer.h"
#include "RuleMatcher.h"
#include "DFA.h"
#include "NetVar.h"
@ -159,9 +159,9 @@ void RuleHdrTest::PrintDebug()
fprintf(stderr, "\n");
}
RuleEndpointState::RuleEndpointState(Analyzer* arg_analyzer, bool arg_is_orig,
RuleEndpointState::RuleEndpointState(analyzer::Analyzer* arg_analyzer, bool arg_is_orig,
RuleEndpointState* arg_opposite,
::PIA* arg_PIA)
analyzer::pia::PIA* arg_PIA)
{
payload_size = -1;
analyzer = arg_analyzer;
@ -562,10 +562,10 @@ static inline bool compare(const vector<IPPrefix>& prefixes, const IPAddr& a,
return false;
}
RuleEndpointState* RuleMatcher::InitEndpoint(Analyzer* analyzer,
RuleEndpointState* RuleMatcher::InitEndpoint(analyzer::Analyzer* analyzer,
const IP_Hdr* ip, int caplen,
RuleEndpointState* opposite,
bool from_orig, PIA* pia)
bool from_orig, analyzer::pia::PIA* pia)
{
RuleEndpointState* state =
new RuleEndpointState(analyzer, from_orig, opposite, pia);
@ -1300,8 +1300,8 @@ uint32 id_to_uint(const char* id)
return 0;
}
void RuleMatcherState::InitEndpointMatcher(Analyzer* analyzer, const IP_Hdr* ip,
int caplen, bool from_orig, PIA* pia)
void RuleMatcherState::InitEndpointMatcher(analyzer::Analyzer* analyzer, const IP_Hdr* ip,
int caplen, bool from_orig, analyzer::pia::PIA* pia)
{
if ( ! rule_matcher )
return;

View file

@ -35,8 +35,10 @@ extern const char* current_rule_file;
class RuleMatcher;
extern RuleMatcher* rule_matcher;
namespace analyzer {
namespace pia { class PIA; }
class Analyzer;
class PIA;
}
// RuleHdrTest and associated things:
@ -140,7 +142,7 @@ class RuleEndpointState {
public:
~RuleEndpointState();
Analyzer* GetAnalyzer() const { return analyzer; }
analyzer::Analyzer* GetAnalyzer() const { return analyzer; }
bool IsOrig() { return is_orig; }
// For flipping roles.
@ -152,15 +154,15 @@ public:
// Returns -1 if no chunk has been fed yet at all.
int PayloadSize() { return payload_size; }
::PIA* PIA() const { return pia; }
analyzer::pia::PIA* PIA() const { return pia; }
private:
friend class RuleMatcher;
// Constructor is private; use RuleMatcher::InitEndpoint()
// for creating an instance.
RuleEndpointState(Analyzer* arg_analyzer, bool arg_is_orig,
RuleEndpointState* arg_opposite, ::PIA* arg_PIA);
RuleEndpointState(analyzer::Analyzer* arg_analyzer, bool arg_is_orig,
RuleEndpointState* arg_opposite, analyzer::pia::PIA* arg_PIA);
struct Matcher {
RE_Match_State* state;
@ -171,9 +173,9 @@ private:
typedef PList(Matcher) matcher_list;
bool is_orig;
Analyzer* analyzer;
analyzer::Analyzer* analyzer;
RuleEndpointState* opposite;
::PIA* pia;
analyzer::pia::PIA* pia;
matcher_list matchers;
rule_hdr_test_list hdr_tests;
@ -207,8 +209,8 @@ public:
// the given packet (which should be the first packet encountered for
// this endpoint). If the matching is triggered by an PIA, a pointer to
// it needs to be given.
RuleEndpointState* InitEndpoint(Analyzer* analyzer, const IP_Hdr* ip,
int caplen, RuleEndpointState* opposite, bool is_orig, PIA* pia);
RuleEndpointState* InitEndpoint(analyzer::Analyzer* analyzer, const IP_Hdr* ip,
int caplen, RuleEndpointState* opposite, bool is_orig, analyzer::pia::PIA* pia);
// Finish matching for this stream.
void FinishEndpoint(RuleEndpointState* state);
@ -310,8 +312,8 @@ public:
{ delete orig_match_state; delete resp_match_state; }
// ip may be nil.
void InitEndpointMatcher(Analyzer* analyzer, const IP_Hdr* ip,
int caplen, bool from_orig, PIA* pia = 0);
void InitEndpointMatcher(analyzer::Analyzer* analyzer, const IP_Hdr* ip,
int caplen, bool from_orig, analyzer::pia::PIA* pia = 0);
// bol/eol should be set to false for type Rule::PAYLOAD; they're
// deduced automatically.

View file

@ -1,26 +0,0 @@
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef ssh_h
#define ssh_h
#include "TCP.h"
#include "ContentLine.h"
class SSH_Analyzer : public TCP_ApplicationAnalyzer {
public:
SSH_Analyzer(Connection* conn);
virtual void DeliverStream(int len, const u_char* data, bool orig);
static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new SSH_Analyzer(conn); }
static bool Available()
{ return ssh_client_version || ssh_server_version; }
private:
ContentLine_Analyzer* orig;
ContentLine_Analyzer* resp;
};
#endif

View file

@ -16,22 +16,25 @@
#include "Reporter.h"
#include "OSFinger.h"
#include "ICMP.h"
#include "UDP.h"
#include "analyzer/protocol/icmp/ICMP.h"
#include "analyzer/protocol/udp/UDP.h"
#include "DNS-binpac.h"
#include "HTTP-binpac.h"
#include "SteppingStone.h"
#include "BackDoor.h"
#include "InterConn.h"
#include "analyzer/protocol/stepping-stone/SteppingStone.h"
#include "analyzer/protocol/stepping-stone/events.bif.h"
#include "analyzer/protocol/backdoor/BackDoor.h"
#include "analyzer/protocol/backdoor/events.bif.h"
#include "analyzer/protocol/interconn/InterConn.h"
#include "analyzer/protocol/interconn/events.bif.h"
#include "analyzer/protocol/arp/ARP.h"
#include "analyzer/protocol/arp/events.bif.h"
#include "Discard.h"
#include "RuleMatcher.h"
#include "DPM.h"
#include "PacketSort.h"
#include "TunnelEncapsulation.h"
#include "analyzer/Manager.h"
// These represent NetBIOS services on ephemeral ports. They're numbered
// so that we can use a single int to hold either an actual TCP/UDP server
// port or one of these.
@ -104,7 +107,7 @@ NetSessions::NetSessions()
fragments.SetDeleteFunc(bro_obj_delete_func);
if ( stp_correlate_pair )
stp_manager = new SteppingStoneManager();
stp_manager = new analyzer::stepping_stone::SteppingStoneManager();
else
stp_manager = 0;
@ -143,7 +146,7 @@ NetSessions::NetSessions()
pkt_profiler = 0;
if ( arp_request || arp_reply || bad_arp )
arp_analyzer = new ARP_Analyzer();
arp_analyzer = new analyzer::arp::ARP_Analyzer();
else
arp_analyzer = 0;
}
@ -256,7 +259,7 @@ void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr,
DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size, 0);
}
else if ( ARP_Analyzer::IsARP(pkt, hdr_size) )
else if ( analyzer::arp::ARP_Analyzer::IsARP(pkt, hdr_size) )
{
if ( arp_analyzer )
arp_analyzer->NextPacket(t, hdr, pkt, hdr_size);
@ -523,7 +526,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
const struct icmp* icmpp = (const struct icmp *) data;
id.src_port = icmpp->icmp_type;
id.dst_port = ICMP4_counterpart(icmpp->icmp_type,
id.dst_port = analyzer::icmp::ICMP4_counterpart(icmpp->icmp_type,
icmpp->icmp_code,
id.is_one_way);
@ -539,7 +542,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
const struct icmp* icmpp = (const struct icmp *) data;
id.src_port = icmpp->icmp_type;
id.dst_port = ICMP6_counterpart(icmpp->icmp_type,
id.dst_port = analyzer::icmp::ICMP6_counterpart(icmpp->icmp_type,
icmpp->icmp_code,
id.is_one_way);
@ -964,12 +967,12 @@ void NetSessions::Remove(Connection* c)
{
c->CancelTimers();
TCP_Analyzer* ta = (TCP_Analyzer*) c->GetRootAnalyzer();
analyzer::tcp::TCP_Analyzer* ta = (analyzer::tcp::TCP_Analyzer*) c->GetRootAnalyzer();
if ( ta && c->ConnTransport() == TRANSPORT_TCP )
{
assert(ta->GetTag() == AnalyzerTag::TCP);
TCP_Endpoint* to = ta->Orig();
TCP_Endpoint* tr = ta->Resp();
assert(ta->IsAnalyzer("TCP"));
analyzer::tcp::TCP_Endpoint* to = ta->Orig();
analyzer::tcp::TCP_Endpoint* tr = ta->Resp();
tcp_stats.StateLeft(to->state, tr->state);
}
@ -1178,7 +1181,7 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id,
Connection* conn = new Connection(this, k, t, id, flow_label, encapsulation);
conn->SetTransport(tproto);
dpm->BuildInitialAnalyzerTree(tproto, conn, data);
analyzer_mgr->BuildInitialAnalyzerTree(conn);
bool external = conn->IsExternal();

View file

@ -6,12 +6,13 @@
#include "Dict.h"
#include "CompHash.h"
#include "IP.h"
#include "ARP.h"
#include "Frag.h"
#include "PacketFilter.h"
#include "Stats.h"
#include "NetVar.h"
#include "TunnelEncapsulation.h"
#include "analyzer/protocol/tcp/Stats.h"
#include <utility>
struct pcap_pkthdr;
@ -26,11 +27,12 @@ declare(PDict,Connection);
declare(PDict,FragReassembler);
class Discarder;
class SteppingStoneManager;
class PacketFilter;
class PacketSortElement;
namespace analyzer { namespace stepping_stone { class SteppingStoneManager; } }
namespace analyzer { namespace arp { class ARP_Analyzer; } }
struct SessionStats {
int num_TCP_conns;
int num_UDP_conns;
@ -127,7 +129,7 @@ public:
void ExpireTimerMgrs();
SteppingStoneManager* GetSTPManager() { return stp_manager; }
analyzer::stepping_stone::SteppingStoneManager* GetSTPManager() { return stp_manager; }
unsigned int CurrentConnections()
{
@ -183,7 +185,7 @@ public:
unsigned int ConnectionMemoryUsage();
unsigned int ConnectionMemoryUsageConnVals();
unsigned int MemoryAllocation();
TCPStateStats tcp_stats; // keeps statistics on TCP states
analyzer::tcp::TCPStateStats tcp_stats; // keeps statistics on TCP states
protected:
friend class RemoteSerializer;
@ -255,9 +257,9 @@ protected:
typedef std::map<IPPair, TunnelActivity> IPTunnelMap;
IPTunnelMap ip_tunnels;
ARP_Analyzer* arp_analyzer;
analyzer::arp::ARP_Analyzer* arp_analyzer;
SteppingStoneManager* stp_manager;
analyzer::stepping_stone::SteppingStoneManager* stp_manager;
Discarder* discarder;
PacketFilter* packet_filter;
OSFingerprint* SYN_OS_Fingerprinter;

View file

@ -389,84 +389,6 @@ void SegmentProfiler::Report()
reporter->SegmentProfile(name, loc, dtime, dmem);
}
TCPStateStats::TCPStateStats()
{
for ( int i = 0; i < TCP_ENDPOINT_RESET + 1; ++i )
for ( int j = 0; j < TCP_ENDPOINT_RESET + 1; ++j )
state_cnt[i][j] = 0;
}
void TCPStateStats::ChangeState(EndpointState o_prev, EndpointState o_now,
EndpointState r_prev, EndpointState r_now)
{
--state_cnt[o_prev][r_prev];
++state_cnt[o_now][r_now];
}
void TCPStateStats::FlipState(EndpointState orig, EndpointState resp)
{
--state_cnt[orig][resp];
++state_cnt[resp][orig];
}
unsigned int TCPStateStats::NumStatePartial() const
{
unsigned int sum = 0;
for ( int i = 0; i < TCP_ENDPOINT_RESET + 1; ++i )
{
sum += state_cnt[TCP_ENDPOINT_PARTIAL][i];
sum += state_cnt[i][TCP_ENDPOINT_PARTIAL];
}
return sum;
}
void TCPStateStats::PrintStats(BroFile* file, const char* prefix)
{
file->Write(prefix);
file->Write(" Inact. Syn. SA Part. Est. Fin. Rst.\n");
for ( int i = 0; i < TCP_ENDPOINT_RESET + 1; ++i )
{
file->Write(prefix);
switch ( i ) {
#define STATE_STRING(state, str) \
case state: \
file->Write(str); \
break;
STATE_STRING(TCP_ENDPOINT_INACTIVE, "Inact.");
STATE_STRING(TCP_ENDPOINT_SYN_SENT, "Syn. ");
STATE_STRING(TCP_ENDPOINT_SYN_ACK_SENT, "SA ");
STATE_STRING(TCP_ENDPOINT_PARTIAL, "Part. ");
STATE_STRING(TCP_ENDPOINT_ESTABLISHED, "Est. ");
STATE_STRING(TCP_ENDPOINT_CLOSED, "Fin. ");
STATE_STRING(TCP_ENDPOINT_RESET, "Rst. ");
}
file->Write(" ");
for ( int j = 0; j < TCP_ENDPOINT_RESET + 1; ++j )
{
unsigned int n = state_cnt[i][j];
if ( n > 0 )
{
char buf[32];
safe_snprintf(buf, sizeof(buf), "%-8d", state_cnt[i][j]);
file->Write(buf);
}
else
file->Write(" ");
}
file->Write("\n");
}
}
PacketProfiler::PacketProfiler(unsigned int mode, double freq,
BroFile* arg_file)
{

View file

@ -7,9 +7,6 @@
#include <sys/time.h>
#include <sys/resource.h>
#include "TCP_Endpoint.h"
// Object called by SegmentProfiler when it is done and reports its
// cumulative CPU/memory statistics.
class SegmentStatsReporter {
@ -121,67 +118,6 @@ extern uint64 tot_ack_bytes;
extern uint64 tot_gap_events;
extern uint64 tot_gap_bytes;
// A TCPStateStats object tracks the distribution of TCP states for
// the currently active connections.
class TCPStateStats {
public:
TCPStateStats();
~TCPStateStats() { }
void ChangeState(EndpointState o_prev, EndpointState o_now,
EndpointState r_prev, EndpointState r_now);
void FlipState(EndpointState orig, EndpointState resp);
void StateEntered (EndpointState o_state, EndpointState r_state)
{ ++state_cnt[o_state][r_state]; }
void StateLeft (EndpointState o_state, EndpointState r_state)
{ --state_cnt[o_state][r_state]; }
unsigned int Cnt(EndpointState state) const
{ return Cnt(state, state); }
unsigned int Cnt(EndpointState state1, EndpointState state2) const
{ return state_cnt[state1][state2]; }
unsigned int NumStateEstablished() const
{ return Cnt(TCP_ENDPOINT_ESTABLISHED); }
unsigned int NumStateHalfClose() const
{ // corresponds to S2,S3
return Cnt(TCP_ENDPOINT_ESTABLISHED, TCP_ENDPOINT_CLOSED) +
Cnt(TCP_ENDPOINT_CLOSED, TCP_ENDPOINT_ESTABLISHED);
}
unsigned int NumStateHalfRst() const
{
return Cnt(TCP_ENDPOINT_ESTABLISHED, TCP_ENDPOINT_RESET) +
Cnt(TCP_ENDPOINT_RESET, TCP_ENDPOINT_ESTABLISHED);
}
unsigned int NumStateClosed() const
{ return Cnt(TCP_ENDPOINT_CLOSED); }
unsigned int NumStateRequest() const
{
assert(Cnt(TCP_ENDPOINT_INACTIVE, TCP_ENDPOINT_SYN_SENT)==0);
return Cnt(TCP_ENDPOINT_SYN_SENT, TCP_ENDPOINT_INACTIVE);
}
unsigned int NumStateSuccRequest() const
{
return Cnt(TCP_ENDPOINT_SYN_SENT, TCP_ENDPOINT_SYN_ACK_SENT) +
Cnt(TCP_ENDPOINT_SYN_ACK_SENT, TCP_ENDPOINT_SYN_SENT);
}
unsigned int NumStateRstRequest() const
{
return Cnt(TCP_ENDPOINT_SYN_SENT, TCP_ENDPOINT_RESET) +
Cnt(TCP_ENDPOINT_RESET, TCP_ENDPOINT_SYN_SENT);
}
unsigned int NumStateInactive() const
{ return Cnt(TCP_ENDPOINT_INACTIVE); }
unsigned int NumStatePartial() const;
void PrintStats(BroFile* file, const char* prefix);
private:
unsigned int state_cnt[TCP_ENDPOINT_RESET+1][TCP_ENDPOINT_RESET+1];
};
class PacketProfiler {
public:
PacketProfiler(unsigned int mode, double freq, BroFile* arg_file);

View file

@ -1,55 +0,0 @@
#ifndef Syslog_binpac_h
#define Syslog_binpac_h
#include "UDP.h"
#include "TCP.h"
#include "syslog_pac.h"
class Syslog_Analyzer_binpac : public Analyzer {
public:
Syslog_Analyzer_binpac(Connection* conn);
virtual ~Syslog_Analyzer_binpac();
virtual void Done();
virtual void DeliverPacket(int len, const u_char* data, bool orig,
int seq, const IP_Hdr* ip, int caplen);
static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new Syslog_Analyzer_binpac(conn); }
static bool Available()
{ return syslog_message; }
protected:
friend class AnalyzerTimer;
void ExpireTimer(double t);
int did_session_done;
binpac::Syslog::Syslog_Conn* interp;
};
// #include "Syslog_tcp_pac.h"
//
//class Syslog_TCP_Analyzer_binpac : public TCP_ApplicationAnalyzer {
//public:
// Syslog_TCP_Analyzer_binpac(Connection* conn);
// virtual ~Syslog_TCP_Analyzer_binpac();
//
// virtual void Done();
// virtual void DeliverStream(int len, const u_char* data, bool orig);
// virtual void Undelivered(int seq, int len, bool orig);
// virtual void EndpointEOF(TCP_Reassembler* endp);
//
// static Analyzer* InstantiateAnalyzer(Connection* conn)
// { return new Syslog_TCP_Analyzer_binpac(conn); }
//
// static bool Available()
// { return (Syslog_request || Syslog_full_request) && FLAGS_use_binpac; }
//
//protected:
// binpac::Syslog_on_TCP::Syslog_TCP_Conn* interp;
//};
//
#endif

View file

@ -1334,6 +1334,16 @@ EnumType::EnumType(const string& arg_name)
counter = 0;
}
EnumType::EnumType(EnumType* e)
: BroType(TYPE_ENUM)
{
name = e->name;
counter = e->counter;
for ( NameMap::iterator it = e->names.begin(); it != e->names.end(); ++it )
names[copy_string(it->first)] = it->second;
}
EnumType::~EnumType()
{
for ( NameMap::iterator iter = names.begin(); iter != names.end(); ++iter )

View file

@ -523,6 +523,7 @@ protected:
class EnumType : public BroType {
public:
EnumType(const string& arg_name);
EnumType(EnumType* e);
~EnumType();
// The value of this name is next internal counter value, starting
@ -567,6 +568,7 @@ protected:
class CommentedEnumType: public EnumType {
public:
CommentedEnumType(const string& arg_name) : EnumType(arg_name) {}
CommentedEnumType(EnumType* e) : EnumType(e) {}
~CommentedEnumType();
void DescribeReST(ODesc* d) const;

View file

@ -1049,6 +1049,11 @@ StringVal::StringVal(const char* s) : Val(TYPE_STRING)
val.string_val = new BroString(s);
}
StringVal::StringVal(const string& s) : Val(TYPE_STRING)
{
val.string_val = new BroString(s.c_str());
}
StringVal* StringVal::ToUpper()
{
val.string_val->ToUpper();

View file

@ -608,6 +608,7 @@ class StringVal : public Val {
public:
StringVal(BroString* s);
StringVal(const char* s);
StringVal(const string& s);
StringVal(int length, const char* s);
Val* SizeVal() const

View file

@ -156,6 +156,12 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init,
if ( do_init )
{
if ( c == INIT_NONE && dt == VAR_REDEF && t->IsTable() &&
init && init->Tag() == EXPR_ASSIGN )
// e.g. 'redef foo["x"] = 1' is missing an init class, but the
// intention clearly isn't to overwrite entire existing table val.
c = INIT_EXTRA;
if ( (c == INIT_EXTRA && id->FindAttr(ATTR_ADD_FUNC)) ||
(c == INIT_REMOVE && id->FindAttr(ATTR_DEL_FUNC)) )
// Just apply the function.

View file

@ -1,191 +1,45 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include <algorithm>
#include "Analyzer.h"
#include "PIA.h"
#include "Event.h"
#include "Manager.h"
#include "AYIYA.h"
#include "BackDoor.h"
#include "BitTorrent.h"
#include "BitTorrentTracker.h"
#include "Finger.h"
#include "InterConn.h"
#include "NTP.h"
#include "HTTP.h"
#include "HTTP-binpac.h"
#include "ICMP.h"
#include "SteppingStone.h"
#include "IRC.h"
#include "SMTP.h"
#include "FTP.h"
#include "FileAnalyzer.h"
#include "DNS.h"
#include "DNS-binpac.h"
#include "DHCP-binpac.h"
#include "Telnet.h"
#include "Rlogin.h"
#include "RSH.h"
#include "DCE_RPC.h"
#include "Gnutella.h"
#include "Ident.h"
#include "Modbus.h"
#include "NCP.h"
#include "NetbiosSSN.h"
#include "SMB.h"
#include "NFS.h"
#include "Portmap.h"
#include "POP3.h"
#include "SOCKS.h"
#include "SSH.h"
#include "SSL.h"
#include "Syslog-binpac.h"
#include "Teredo.h"
#include "ConnSizeAnalyzer.h"
#include "GTPv1.h"
#include "analyzer/protocol/pia/PIA.h"
#include "../Event.h"
// Keep same order here as in AnalyzerTag definition!
const Analyzer::Config Analyzer::analyzer_configs[] = {
{ AnalyzerTag::Error, "<ERROR>", 0, 0, 0, false },
namespace analyzer {
{ AnalyzerTag::PIA_TCP, "PIA_TCP", PIA_TCP::InstantiateAnalyzer,
PIA_TCP::Available, 0, false },
{ AnalyzerTag::PIA_UDP, "PIA_UDP", PIA_UDP::InstantiateAnalyzer,
PIA_UDP::Available, 0, false },
class AnalyzerTimer : public Timer {
public:
AnalyzerTimer(Analyzer* arg_analyzer, analyzer_timer_func arg_timer,
double arg_t, int arg_do_expire, TimerType arg_type);
{ AnalyzerTag::ICMP, "ICMP", ICMP_Analyzer::InstantiateAnalyzer,
ICMP_Analyzer::Available, 0, false },
virtual ~AnalyzerTimer();
{ AnalyzerTag::TCP, "TCP", TCP_Analyzer::InstantiateAnalyzer,
TCP_Analyzer::Available, 0, false },
{ AnalyzerTag::UDP, "UDP", UDP_Analyzer::InstantiateAnalyzer,
UDP_Analyzer::Available, 0, false },
void Dispatch(double t, int is_expire);
{ AnalyzerTag::BitTorrent, "BITTORRENT",
BitTorrent_Analyzer::InstantiateAnalyzer,
BitTorrent_Analyzer::Available, 0, false },
{ AnalyzerTag::BitTorrentTracker, "BITTORRENTTRACKER",
BitTorrentTracker_Analyzer::InstantiateAnalyzer,
BitTorrentTracker_Analyzer::Available, 0, false },
{ AnalyzerTag::DCE_RPC, "DCE_RPC",
DCE_RPC_Analyzer::InstantiateAnalyzer,
DCE_RPC_Analyzer::Available, 0, false },
{ AnalyzerTag::DNS, "DNS", DNS_Analyzer::InstantiateAnalyzer,
DNS_Analyzer::Available, 0, false },
{ AnalyzerTag::Finger, "FINGER", Finger_Analyzer::InstantiateAnalyzer,
Finger_Analyzer::Available, 0, false },
{ AnalyzerTag::FTP, "FTP", FTP_Analyzer::InstantiateAnalyzer,
FTP_Analyzer::Available, 0, false },
{ AnalyzerTag::Gnutella, "GNUTELLA",
Gnutella_Analyzer::InstantiateAnalyzer,
Gnutella_Analyzer::Available, 0, false },
{ AnalyzerTag::HTTP, "HTTP", HTTP_Analyzer::InstantiateAnalyzer,
HTTP_Analyzer::Available, 0, false },
{ AnalyzerTag::Ident, "IDENT", Ident_Analyzer::InstantiateAnalyzer,
Ident_Analyzer::Available, 0, false },
{ AnalyzerTag::IRC, "IRC", IRC_Analyzer::InstantiateAnalyzer,
IRC_Analyzer::Available, 0, false },
{ AnalyzerTag::Login, "LOGIN", 0, 0, 0, false }, // just a base class
{ AnalyzerTag::NCP, "NCP", NCP_Analyzer::InstantiateAnalyzer,
NCP_Analyzer::Available, 0, false },
{ AnalyzerTag::NetbiosSSN, "NetbiosSSN",
NetbiosSSN_Analyzer::InstantiateAnalyzer,
NetbiosSSN_Analyzer::Available, 0, false },
{ AnalyzerTag::NFS, "NFS", NFS_Analyzer::InstantiateAnalyzer,
NFS_Analyzer::Available, 0, false },
{ AnalyzerTag::NTP, "NTP", NTP_Analyzer::InstantiateAnalyzer,
NTP_Analyzer::Available, 0, false },
{ AnalyzerTag::POP3, "POP3", POP3_Analyzer::InstantiateAnalyzer,
POP3_Analyzer::Available, 0, false },
{ AnalyzerTag::Portmapper, "PORTMAPPER",
Portmapper_Analyzer::InstantiateAnalyzer,
Portmapper_Analyzer::Available, 0, false },
{ AnalyzerTag::Rlogin, "RLOGIN", Rlogin_Analyzer::InstantiateAnalyzer,
Rlogin_Analyzer::Available, 0, false },
{ AnalyzerTag::RPC, "RPC", 0, 0, 0, false },
{ AnalyzerTag::Rsh, "RSH", Rsh_Analyzer::InstantiateAnalyzer,
Rsh_Analyzer::Available, 0, false },
{ AnalyzerTag::SMB, "SMB", SMB_Analyzer::InstantiateAnalyzer,
SMB_Analyzer::Available, 0, false },
{ AnalyzerTag::SMTP, "SMTP", SMTP_Analyzer::InstantiateAnalyzer,
SMTP_Analyzer::Available, 0, false },
{ AnalyzerTag::SSH, "SSH", SSH_Analyzer::InstantiateAnalyzer,
SSH_Analyzer::Available, 0, false },
{ AnalyzerTag::Telnet, "TELNET", Telnet_Analyzer::InstantiateAnalyzer,
Telnet_Analyzer::Available, 0, false },
protected:
AnalyzerTimer() {}
{ AnalyzerTag::DHCP_BINPAC, "DHCP_BINPAC",
DHCP_Analyzer_binpac::InstantiateAnalyzer,
DHCP_Analyzer_binpac::Available, 0, false },
{ AnalyzerTag::DNS_TCP_BINPAC, "DNS_TCP_BINPAC",
DNS_TCP_Analyzer_binpac::InstantiateAnalyzer,
DNS_TCP_Analyzer_binpac::Available, 0, false },
{ AnalyzerTag::DNS_UDP_BINPAC, "DNS_UDP_BINPAC",
DNS_UDP_Analyzer_binpac::InstantiateAnalyzer,
DNS_UDP_Analyzer_binpac::Available, 0, false },
{ AnalyzerTag::HTTP_BINPAC, "HTTP_BINPAC",
HTTP_Analyzer_binpac::InstantiateAnalyzer,
HTTP_Analyzer_binpac::Available, 0, false },
{ AnalyzerTag::SSL, "SSL",
SSL_Analyzer::InstantiateAnalyzer,
SSL_Analyzer::Available, 0, false },
{ AnalyzerTag::SYSLOG_BINPAC, "SYSLOG_BINPAC",
Syslog_Analyzer_binpac::InstantiateAnalyzer,
Syslog_Analyzer_binpac::Available, 0, false },
{ AnalyzerTag::Modbus, "MODBUS",
ModbusTCP_Analyzer::InstantiateAnalyzer,
ModbusTCP_Analyzer::Available, 0, false },
void Init(Analyzer* analyzer, analyzer_timer_func timer, int do_expire);
{ AnalyzerTag::AYIYA, "AYIYA",
AYIYA_Analyzer::InstantiateAnalyzer,
AYIYA_Analyzer::Available, 0, false },
{ AnalyzerTag::SOCKS, "SOCKS",
SOCKS_Analyzer::InstantiateAnalyzer,
SOCKS_Analyzer::Available, 0, false },
{ AnalyzerTag::Teredo, "TEREDO",
Teredo_Analyzer::InstantiateAnalyzer,
Teredo_Analyzer::Available, 0, false },
{ AnalyzerTag::GTPv1, "GTPV1",
GTPv1_Analyzer::InstantiateAnalyzer,
GTPv1_Analyzer::Available, 0, false },
{ AnalyzerTag::File, "FILE", File_Analyzer::InstantiateAnalyzer,
File_Analyzer::Available, 0, false },
{ AnalyzerTag::IRC_Data, "IRC_DATA", IRC_Data::InstantiateAnalyzer,
IRC_Data::Available, 0, false },
{ AnalyzerTag::FTP_Data, "FTP_DATA", FTP_Data::InstantiateAnalyzer,
FTP_Data::Available, 0, false },
{ AnalyzerTag::Backdoor, "BACKDOOR",
BackDoor_Analyzer::InstantiateAnalyzer,
BackDoor_Analyzer::Available, 0, false },
{ AnalyzerTag::InterConn, "INTERCONN",
InterConn_Analyzer::InstantiateAnalyzer,
InterConn_Analyzer::Available, 0, false },
{ AnalyzerTag::SteppingStone, "STEPPINGSTONE",
SteppingStone_Analyzer::InstantiateAnalyzer,
SteppingStone_Analyzer::Available, 0, false },
{ AnalyzerTag::TCPStats, "TCPSTATS",
TCPStats_Analyzer::InstantiateAnalyzer,
TCPStats_Analyzer::Available, 0, false },
{ AnalyzerTag::ConnSize, "CONNSIZE",
ConnSize_Analyzer::InstantiateAnalyzer,
ConnSize_Analyzer::Available, 0, false },
{ AnalyzerTag::Contents, "CONTENTS", 0, 0, 0, false },
{ AnalyzerTag::ContentLine, "CONTENTLINE", 0, 0, 0, false },
{ AnalyzerTag::NVT, "NVT", 0, 0, 0, false },
{ AnalyzerTag::Zip, "ZIP", 0, 0, 0, false },
{ AnalyzerTag::Contents_DNS, "CONTENTS_DNS", 0, 0, 0, false },
{ AnalyzerTag::Contents_NetbiosSSN, "CONTENTS_NETBIOSSSN", 0, 0, 0, false },
{ AnalyzerTag::Contents_NCP, "CONTENTS_NCP", 0, 0, 0, false },
{ AnalyzerTag::Contents_Rlogin, "CONTENTS_Rlogin", 0, 0, 0, false },
{ AnalyzerTag::Contents_Rsh, "CONTENTS_RSH", 0, 0, 0, false },
{ AnalyzerTag::Contents_DCE_RPC, "CONTENTS_DCE_RPC", 0, 0, 0, false },
{ AnalyzerTag::Contents_SMB, "CONTENTS_SMB", 0, 0, 0, false },
{ AnalyzerTag::Contents_RPC, "CONTENTS_RPC", 0, 0, 0, false },
{ AnalyzerTag::Contents_NFS, "CONTENTS_NFS", 0, 0, 0, false },
{ AnalyzerTag::FTP_ADAT, "FTP_ADAT", 0, 0, 0, false },
Analyzer* analyzer;
analyzer_timer_func timer;
int do_expire;
};
}
using namespace analyzer;
AnalyzerTimer::AnalyzerTimer(Analyzer* arg_analyzer, analyzer_timer_func arg_timer,
double arg_t, int arg_do_expire, TimerType arg_type)
: Timer(arg_t, arg_type)
{
Init(arg_analyzer, arg_timer, arg_do_expire);
}
AnalyzerTimer::~AnalyzerTimer()
{
analyzer->RemoveTimer(this);
@ -216,36 +70,53 @@ void AnalyzerTimer::Init(Analyzer* arg_analyzer, analyzer_timer_func arg_timer,
Ref(analyzer->Conn());
}
AnalyzerID Analyzer::id_counter = 0;;
analyzer::ID Analyzer::id_counter = 0;;
Analyzer* Analyzer::InstantiateAnalyzer(AnalyzerTag::Tag tag, Connection* c)
const char* Analyzer::GetAnalyzerName() const
{
Analyzer* a = analyzer_configs[tag].factory(c);
assert(a);
return a;
assert(tag);
return analyzer_mgr->GetAnalyzerName(tag);
}
const char* Analyzer::GetTagName(AnalyzerTag::Tag tag)
void Analyzer::SetAnalyzerTag(const Tag& arg_tag)
{
return analyzer_configs[tag].name;
assert(! tag || tag == arg_tag);
tag = arg_tag;
}
AnalyzerTag::Tag Analyzer::GetTag(const char* name)
bool Analyzer::IsAnalyzer(const char* name)
{
for ( int i = 1; i < int(AnalyzerTag::LastAnalyzer); i++ )
if ( strcasecmp(analyzer_configs[i].name, name) == 0 )
return analyzer_configs[i].tag;
return AnalyzerTag::Error;
assert(tag);
return strcmp(analyzer_mgr->GetAnalyzerName(tag), name) == 0;
}
// Used in debugging output.
static string fmt_analyzer(Analyzer* a)
{
return string(a->GetTagName()) + fmt("[%d]", a->GetID());
return string(a->GetAnalyzerName()) + fmt("[%d]", a->GetID());
}
Analyzer::Analyzer(AnalyzerTag::Tag arg_tag, Connection* arg_conn)
Analyzer::Analyzer(const char* name, Connection* conn)
{
Tag tag = analyzer_mgr->GetAnalyzerTag(name);
if ( ! tag )
reporter->InternalError("unknown analyzer name %s; mismatch with tag analyzer::Component?", name);
CtorInit(tag, conn);
}
Analyzer::Analyzer(const Tag& tag, Connection* conn)
{
CtorInit(tag, conn);
}
Analyzer::Analyzer(Connection* conn)
{
CtorInit(Tag(), conn);
}
void Analyzer::CtorInit(const Tag& arg_tag, Connection* arg_conn)
{
// Don't Ref conn here to avoid circular ref'ing. It can't be deleted
// before us.
@ -355,11 +226,6 @@ void Analyzer::NextPacket(int len, const u_char* data, bool is_orig, int seq,
}
}
const char* Analyzer::GetTagName() const
{
return GetTagName(tag);
}
void Analyzer::NextStream(int len, const u_char* data, bool is_orig)
{
if ( skip )
@ -514,7 +380,7 @@ void Analyzer::ForwardEndOfData(bool orig)
void Analyzer::AddChildAnalyzer(Analyzer* analyzer, bool init)
{
if ( HasChildAnalyzer(analyzer->GetTag()) )
if ( HasChildAnalyzer(analyzer->GetAnalyzerTag()) )
{
analyzer->Done();
delete analyzer;
@ -533,16 +399,19 @@ void Analyzer::AddChildAnalyzer(Analyzer* analyzer, bool init)
if ( init )
analyzer->Init();
DBG_LOG(DBG_DPD, "%s added child %s",
DBG_LOG(DBG_ANALYZER, "%s added child %s",
fmt_analyzer(this).c_str(), fmt_analyzer(analyzer).c_str());
}
Analyzer* Analyzer::AddChildAnalyzer(AnalyzerTag::Tag analyzer)
Analyzer* Analyzer::AddChildAnalyzer(Tag analyzer)
{
if ( ! HasChildAnalyzer(analyzer) )
{
Analyzer* a = InstantiateAnalyzer(analyzer, conn);
Analyzer* a = analyzer_mgr->InstantiateAnalyzer(analyzer, conn);
if ( a )
AddChildAnalyzer(a);
return a;
}
@ -554,7 +423,7 @@ void Analyzer::RemoveChildAnalyzer(Analyzer* analyzer)
LOOP_OVER_CHILDREN(i)
if ( *i == analyzer && ! (analyzer->finished || analyzer->removing) )
{
DBG_LOG(DBG_DPD, "%s disabling child %s",
DBG_LOG(DBG_ANALYZER, "%s disabling child %s",
fmt_analyzer(this).c_str(), fmt_analyzer(*i).c_str());
// We just flag it as being removed here but postpone
// actually doing that to later. Otherwise, we'd need
@ -567,12 +436,12 @@ void Analyzer::RemoveChildAnalyzer(Analyzer* analyzer)
}
}
void Analyzer::RemoveChildAnalyzer(AnalyzerID id)
void Analyzer::RemoveChildAnalyzer(ID id)
{
LOOP_OVER_CHILDREN(i)
if ( (*i)->id == id && ! ((*i)->finished || (*i)->removing) )
{
DBG_LOG(DBG_DPD, "%s disabling child %s", GetTagName(), id,
DBG_LOG(DBG_ANALYZER, "%s disabling child %s", GetAnalyzerName(), id,
fmt_analyzer(this).c_str(), fmt_analyzer(*i).c_str());
// See comment above.
(*i)->removing = true;
@ -580,7 +449,7 @@ void Analyzer::RemoveChildAnalyzer(AnalyzerID id)
}
}
bool Analyzer::HasChildAnalyzer(AnalyzerTag::Tag tag)
bool Analyzer::HasChildAnalyzer(Tag tag)
{
LOOP_OVER_CHILDREN(i)
if ( (*i)->tag == tag )
@ -593,7 +462,7 @@ bool Analyzer::HasChildAnalyzer(AnalyzerTag::Tag tag)
return false;
}
Analyzer* Analyzer::FindChild(AnalyzerID arg_id)
Analyzer* Analyzer::FindChild(ID arg_id)
{
if ( id == arg_id )
return this;
@ -608,7 +477,7 @@ Analyzer* Analyzer::FindChild(AnalyzerID arg_id)
return 0;
}
Analyzer* Analyzer::FindChild(AnalyzerTag::Tag arg_tag)
Analyzer* Analyzer::FindChild(Tag arg_tag)
{
if ( tag == arg_tag )
return this;
@ -623,6 +492,12 @@ Analyzer* Analyzer::FindChild(AnalyzerTag::Tag arg_tag)
return 0;
}
Analyzer* Analyzer::FindChild(const char* name)
{
Tag tag = analyzer_mgr->GetAnalyzerTag(name);
return tag ? FindChild(tag) : 0;
}
void Analyzer::DeleteChild(analyzer_list::iterator i)
{
Analyzer* child = *i;
@ -636,7 +511,7 @@ void Analyzer::DeleteChild(analyzer_list::iterator i)
child->removing = false;
}
DBG_LOG(DBG_DPD, "%s deleted child %s 3",
DBG_LOG(DBG_ANALYZER, "%s deleted child %s 3",
fmt_analyzer(this).c_str(), fmt_analyzer(child).c_str());
children.erase(i);
@ -645,9 +520,9 @@ void Analyzer::DeleteChild(analyzer_list::iterator i)
void Analyzer::AddSupportAnalyzer(SupportAnalyzer* analyzer)
{
if ( HasSupportAnalyzer(analyzer->GetTag(), analyzer->IsOrig()) )
if ( HasSupportAnalyzer(analyzer->GetAnalyzerTag(), analyzer->IsOrig()) )
{
DBG_LOG(DBG_DPD, "%s already has %s %s",
DBG_LOG(DBG_ANALYZER, "%s already has %s %s",
fmt_analyzer(this).c_str(),
analyzer->IsOrig() ? "originator" : "responder",
fmt_analyzer(analyzer).c_str());
@ -675,7 +550,7 @@ void Analyzer::AddSupportAnalyzer(SupportAnalyzer* analyzer)
analyzer->Init();
DBG_LOG(DBG_DPD, "%s added %s support %s",
DBG_LOG(DBG_ANALYZER, "%s added %s support %s",
fmt_analyzer(this).c_str(),
analyzer->IsOrig() ? "originator" : "responder",
fmt_analyzer(analyzer).c_str());
@ -699,7 +574,7 @@ void Analyzer::RemoveSupportAnalyzer(SupportAnalyzer* analyzer)
else
*head = s->sibling;
DBG_LOG(DBG_DPD, "%s removed support %s",
DBG_LOG(DBG_ANALYZER, "%s removed support %s",
fmt_analyzer(this).c_str(),
analyzer->IsOrig() ? "originator" : "responder",
fmt_analyzer(analyzer).c_str());
@ -711,7 +586,7 @@ void Analyzer::RemoveSupportAnalyzer(SupportAnalyzer* analyzer)
return;
}
bool Analyzer::HasSupportAnalyzer(AnalyzerTag::Tag tag, bool orig)
bool Analyzer::HasSupportAnalyzer(Tag tag, bool orig)
{
SupportAnalyzer* s = orig ? orig_supporters : resp_supporters;
for ( ; s; s = s->sibling )
@ -724,33 +599,33 @@ bool Analyzer::HasSupportAnalyzer(AnalyzerTag::Tag tag, bool orig)
void Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
int seq, const IP_Hdr* ip, int caplen)
{
DBG_LOG(DBG_DPD, "%s DeliverPacket(%d, %s, %d, %p, %d) [%s%s]",
DBG_LOG(DBG_ANALYZER, "%s DeliverPacket(%d, %s, %d, %p, %d) [%s%s]",
fmt_analyzer(this).c_str(), len, is_orig ? "T" : "F", seq, ip, caplen,
fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : "");
}
void Analyzer::DeliverStream(int len, const u_char* data, bool is_orig)
{
DBG_LOG(DBG_DPD, "%s DeliverStream(%d, %s) [%s%s]",
DBG_LOG(DBG_ANALYZER, "%s DeliverStream(%d, %s) [%s%s]",
fmt_analyzer(this).c_str(), len, is_orig ? "T" : "F",
fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : "");
}
void Analyzer::Undelivered(int seq, int len, bool is_orig)
{
DBG_LOG(DBG_DPD, "%s Undelivered(%d, %d, %s)",
DBG_LOG(DBG_ANALYZER, "%s Undelivered(%d, %d, %s)",
fmt_analyzer(this).c_str(), seq, len, is_orig ? "T" : "F");
}
void Analyzer::EndOfData(bool is_orig)
{
DBG_LOG(DBG_DPD, "%s EndOfData(%s)",
DBG_LOG(DBG_ANALYZER, "%s EndOfData(%s)",
fmt_analyzer(this).c_str(), is_orig ? "T" : "F");
}
void Analyzer::FlipRoles()
{
DBG_LOG(DBG_DPD, "%s FlipRoles()");
DBG_LOG(DBG_ANALYZER, "%s FlipRoles()");
LOOP_OVER_CHILDREN(i)
(*i)->FlipRoles();
@ -774,9 +649,12 @@ void Analyzer::ProtocolConfirmation()
if ( protocol_confirmed )
return;
EnumVal* tval = tag.AsEnumVal();
Ref(tval);
val_list* vl = new val_list;
vl->append(BuildConnVal());
vl->append(new Val(tag, TYPE_COUNT));
vl->append(tval);
vl->append(new Val(id, TYPE_COUNT));
// We immediately raise the event so that the analyzer can quickly
@ -802,9 +680,12 @@ void Analyzer::ProtocolViolation(const char* reason, const char* data, int len)
else
r = new StringVal(reason);
EnumVal* tval = tag.AsEnumVal();
Ref(tval);
val_list* vl = new val_list;
vl->append(BuildConnVal());
vl->append(new Val(tag, TYPE_COUNT));
vl->append(tval);
vl->append(new Val(id, TYPE_COUNT));
vl->append(r);
@ -876,6 +757,31 @@ void Analyzer::UpdateConnVal(RecordVal *conn_val)
(*i)->UpdateConnVal(conn_val);
}
RecordVal* Analyzer::BuildConnVal()
{
return conn->BuildConnVal();
}
void Analyzer::Event(EventHandlerPtr f, const char* name)
{
conn->Event(f, this, name);
}
void Analyzer::Event(EventHandlerPtr f, Val* v1, Val* v2)
{
conn->Event(f, this, v1, v2);
}
void Analyzer::ConnectionEvent(EventHandlerPtr f, val_list* vl)
{
conn->ConnectionEvent(f, this, vl);
}
void Analyzer::Weird(const char* name, const char* addl)
{
conn->Weird(name, addl);
}
void SupportAnalyzer::ForwardPacket(int len, const u_char* data, bool is_orig,
int seq, const IP_Hdr* ip, int caplen)
{

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