diff --git a/CHANGES b/CHANGES index 144eb9fd1b..92f0a3b9ee 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,49 @@ +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) + + * Allow named vector/set/table/record constructors. Addresses #983. + (Jon Siwek) + + * Adding Makefile target test-all that also runs the BroControl test + suite. (Robin Sommer) + +2.1-664 | 2013-05-28 21:37:46 -0700 + + * Dangling pointer fix. Addresses #1004. (Jon Siwek) + 2.1-659 | 2013-05-24 17:24:18 -0700 * Fix broken/missing documentation. (Jon Siwek) diff --git a/Makefile b/Makefile index 455fa6ed88..adf45f84f4 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,10 @@ distclean: rm -rf $(BUILD) test: - @(cd testing && make ) + @( cd testing && make ) + +test-all: test + test -d aux/broctl && ( cd aux/broctl && make test ) configured: @test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 ) diff --git a/NEWS b/NEWS index 77f899005d..f0d302156b 100644 --- a/NEWS +++ b/NEWS @@ -46,6 +46,19 @@ New Functionality have changed their signatures to work with opaques types rather than global state as it was before. +- The scripting language now supports a constructing sets, tables, + vectors, and records by name: + + type MyRecordType: record { + c: count; + s: string &optional; + }; + + global r: MyRecordType = record($c = 7); + + type MySet: set[MyRec]; + global s = MySet([$c=1], [$c=2]); + - Strings now support the subscript operator to extract individual characters and substrings (e.g., s[4], s[1,5]). The index expression can take up to two indices for the start and end index of the @@ -55,6 +68,10 @@ 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 diff --git a/VERSION b/VERSION index 494bc9cb81..0559f5c3b4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-659 +2.1-741 diff --git a/aux/binpac b/aux/binpac index f86a3169b8..c39bd478b9 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit f86a3169b8d49189d264cbc1a7507260cd9ff51d +Subproject commit c39bd478b9d0ecd05b1b83aa9d09a7887893977c diff --git a/aux/bro-aux b/aux/bro-aux index cfaf4eea78..a9942558c7 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit cfaf4eea788bdac4ebfe9e46e3de2cd74b0bc068 +Subproject commit a9942558c7d3dfd80148b8aaded64c82ade3d117 diff --git a/aux/broccoli b/aux/broccoli index 8955807b0f..889f9c6594 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 8955807b0f4151f5f6aca2e68d353b9b341d9f86 +Subproject commit 889f9c65944ceac20ad9230efc39d33e6e1221c3 diff --git a/aux/broctl b/aux/broctl index 4d0b75afad..cf7a1ca56f 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 4d0b75afadd6a3c6507e8ca18cb1913faa93a3b0 +Subproject commit cf7a1ca56f2b20f777542d912de0a9c8fdb0655d diff --git a/bro-path-dev.in b/bro-path-dev.in index 81d4f111fc..2c17d057c9 100755 --- a/bro-path-dev.in +++ b/bro-path-dev.in @@ -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 diff --git a/cmake b/cmake index e1a7fd00a0..0187b33a29 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit e1a7fd00a0a66d6831a239fe84f5fcfaa54e2c35 +Subproject commit 0187b33a29d5ec824f940feff60dc5d8c2fe314f diff --git a/doc/scripts/CMakeLists.txt b/doc/scripts/CMakeLists.txt index 315f751cd1..64c3de92eb 100644 --- a/doc/scripts/CMakeLists.txt +++ b/doc/scripts/CMakeLists.txt @@ -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,7 +64,7 @@ macro(REST_TARGET srcDir broInput) if (NOT "${ARGN}" STREQUAL "") set(group ${ARGN}) - elseif (${extension} STREQUAL ".bif.bro") + elseif (${broInput} MATCHES "\\.bif\\.bro$") set(group bifs) elseif (relDstDir) set(group ${relDstDir}/index) diff --git a/doc/scripts/DocSourcesList.cmake b/doc/scripts/DocSourcesList.cmake index e4c92a0777..0b077c2c50 100644 --- a/doc/scripts/DocSourcesList.cmake +++ b/doc/scripts/DocSourcesList.cmake @@ -16,15 +16,63 @@ 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_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 +194,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) diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst index 369f38c9eb..2f5c220458 100644 --- a/doc/scripts/builtins.rst +++ b/doc/scripts/builtins.rst @@ -246,6 +246,31 @@ The Bro scripting language supports the following built-in types. [5] = "five", }; + A table constructor (equivalent to above example) can also be used + to create a table: + + .. code:: bro + + global t2: table[count] of string = table( + [11] = "eleven", + [5] = "five" + ); + + Table constructors can also be explicitly named by a type, which is + useful for when a more complex index type could otherwise be + ambiguous: + + .. code:: bro + + type MyRec: record { + a: count &optional; + b: count; + }; + + type MyTable: table[MyRec] of string; + + global t3 = MyTable([[$b=5]] = "b5", [[$b=7]] = "b7"); + Accessing table elements if provided by enclosing values within square brackets (``[]``), for example: @@ -308,6 +333,28 @@ The Bro scripting language supports the following built-in types. The types are explicitly shown in the example above, but they could have been left to type inference. + A set constructor (equivalent to above example) can also be used to + create a set: + + .. code:: bro + + global s3: set[port] = set(21/tcp, 23/tcp, 80/tcp, 443/tcp); + + Set constructors can also be explicitly named by a type, which is + useful for when a more complex index type could otherwise be + ambiguous: + + .. code:: bro + + type MyRec: record { + a: count &optional; + b: count; + }; + + type MySet: set[MyRec]; + + global s4 = MySet([$b=1], [$b=2]); + Set membership is tested with ``in``: .. code:: bro @@ -349,6 +396,21 @@ The Bro scripting language supports the following built-in types. global v: vector of string = vector("one", "two", "three"); + Vector constructors can also be explicitly named by a type, which + is useful for when a more complex yield type could otherwise be + ambiguous. + + .. code:: bro + + type MyRec: record { + a: count &optional; + b: count; + }; + + type MyVec: vector of MyRec; + + global v2 = MyVec([$b=1], [$b=2], [$b=3]); + Adding an element to a vector involves accessing/assigning it: .. code:: bro @@ -402,6 +464,19 @@ The Bro scripting language supports the following built-in types. if ( r?$s ) ... + Records can also be created using a constructor syntax: + + .. code:: bro + + global r2: MyRecordType = record($c = 7); + + And the constructor can be explicitly named by type, too, which + is arguably more readable code: + + .. code:: bro + + global r3 = MyRecordType($c = 42); + .. bro:type:: opaque A data type whose actual representation/implementation is diff --git a/doc/scripts/example.bro b/doc/scripts/example.bro index 9f6f656ee1..2ff12bfa27 100644 --- a/doc/scripts/example.bro +++ b/doc/scripts/example.bro @@ -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 diff --git a/doc/scripts/genDocSourcesList.sh b/doc/scripts/genDocSourcesList.sh index a10121221a..31905c68db 100755 --- a/doc/scripts/genDocSourcesList.sh +++ b/doc/scripts/genDocSourcesList.sh @@ -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 )` diff --git a/scripts/base/frameworks/analyzer/__load__.bro b/scripts/base/frameworks/analyzer/__load__.bro new file mode 100644 index 0000000000..a10fe855df --- /dev/null +++ b/scripts/base/frameworks/analyzer/__load__.bro @@ -0,0 +1 @@ +@load ./main diff --git a/scripts/base/frameworks/analyzer/main.bro b/scripts/base/frameworks/analyzer/main.bro new file mode 100644 index 0000000000..e2dcf151c7 --- /dev/null +++ b/scripts/base/frameworks/analyzer/main.bro @@ -0,0 +1,181 @@ +##! 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. +##! +##! .. todo: ``The ANALYZER_*`` are in fact not yet documented, we need to +##! add that to Broxygen. +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); + } + diff --git a/scripts/base/frameworks/dpd/main.bro b/scripts/base/frameworks/dpd/main.bro index a5349b6cfb..c3282a1da4 100644 --- a/scripts/base/frameworks/dpd/main.bro +++ b/scripts/base/frameworks/dpd/main.bro @@ -23,12 +23,12 @@ export { analyzer: string &log; ## The textual reason for the analysis failure. failure_reason: string &log; - - ## Disabled analyzer IDs. This is only for internal tracking + + ## Disabled analyzer IDs. This is only for internal tracking ## so as to not attempt to disable analyzers multiple times. disabled_aids: set[count]; }; - + ## Ignore violations which go this many bytes into the connection. ## Set to 0 to never ignore protocol violations. const ignore_violations_after = 10 * 1024 &redef; @@ -41,41 +41,30 @@ 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)]; 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 ) return; - + delete c$service[analyzer]; add c$service[fmt("-%s", analyzer)]; - + local info: Info; info$ts=network_time(); info$uid=c$uid; @@ -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; @@ -94,13 +83,13 @@ event protocol_violation(c: connection, atype: count, aid: count, reason: string local size = c$orig$size + c$resp$size; if ( ignore_violations_after > 0 && size > ignore_violations_after ) return; - + # Disable the analyzer that raised the last core-generated event. disable_analyzer(c$id, aid); 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 ) diff --git a/scripts/base/frameworks/file-analysis/main.bro b/scripts/base/frameworks/file-analysis/main.bro index 142709dcc4..0ed66464fe 100644 --- a/scripts/base/frameworks/file-analysis/main.bro +++ b/scripts/base/frameworks/file-analysis/main.bro @@ -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 module FileAnalysis; @@ -104,7 +104,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; ## Event that can be handled to access the Info record as it is sent on ## to the logging framework. diff --git a/scripts/base/frameworks/input/main.bro b/scripts/base/frameworks/input/main.bro index 1a05abce71..4de98ea0f2 100644 --- a/scripts/base/frameworks/input/main.bro +++ b/scripts/base/frameworks/input/main.bro @@ -149,7 +149,7 @@ export { global end_of_data: event(name: string, source:string); } -@load base/input.bif +@load base/bif/input.bif module Input; diff --git a/scripts/base/frameworks/logging/main.bro b/scripts/base/frameworks/logging/main.bro index b1d76cfb62..30cc9c0d73 100644 --- a/scripts/base/frameworks/logging/main.bro +++ b/scripts/base/frameworks/logging/main.bro @@ -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; diff --git a/scripts/base/frameworks/reporter/main.bro b/scripts/base/frameworks/reporter/main.bro index 249ecdac98..891aebf6b2 100644 --- a/scripts/base/frameworks/reporter/main.bro +++ b/scripts/base/frameworks/reporter/main.bro @@ -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; diff --git a/scripts/base/frameworks/tunnels/main.bro b/scripts/base/frameworks/tunnels/main.bro index a8fc6c8236..faa725b3f6 100644 --- a/scripts/base/frameworks/tunnels/main.bro +++ b/scripts/base/frameworks/tunnels/main.bro @@ -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) diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index c4245d9052..2110110a40 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -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 @@ -226,7 +226,7 @@ type endpoint_stats: record { ## 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 +## .. bro:see:: Analyzer::name Analyzer::disable_analyzer protocol_confirmation ## protocol_violation ## ## .. todo::While we declare an alias for the type here, the events/functions still @@ -713,9 +713,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 +2723,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 +2913,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_*``, 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 +2932,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 +2957,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 +3065,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 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/file-analysis + +# Load BiFs defined by plugins. +@load base/bif/plugins diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index 829a1b9982..9c3995673c 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -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 diff --git a/scripts/base/protocols/conn/inactivity.bro b/scripts/base/protocols/conn/inactivity.bro index 28df192de3..b383f1ad7c 100644 --- a/scripts/base/protocols/conn/inactivity.bro +++ b/scripts/base/protocols/conn/inactivity.bro @@ -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]); diff --git a/scripts/base/protocols/dns/main.bro b/scripts/base/protocols/dns/main.bro index fd524b49cf..15da9aa7b7 100644 --- a/scripts/base/protocols/dns/main.bro +++ b/scripts/base/protocols/dns/main.bro @@ -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 diff --git a/scripts/base/protocols/ftp/file-analysis.bro b/scripts/base/protocols/ftp/file-analysis.bro index b26d8a942b..2096af9a75 100644 --- a/scripts/base/protocols/ftp/file-analysis.bro +++ b/scripts/base/protocols/ftp/file-analysis.bro @@ -11,7 +11,7 @@ export { function get_handle_string(c: connection): string { - return cat(ANALYZER_FTP_DATA, " ", c$start_time, " ", id_string(c$id)); + return cat(Analyzer::ANALYZER_FTP_DATA, " ", c$start_time, " ", id_string(c$id)); } function get_file_handle(c: connection, is_orig: bool): string @@ -40,8 +40,8 @@ function get_file_handle(c: connection, is_orig: bool): string module GLOBAL; -event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) +event get_file_handle(tag: Analyzer::Tag, c: connection, is_orig: bool) { - if ( tag != ANALYZER_FTP_DATA ) return; + if ( tag != Analyzer::ANALYZER_FTP_DATA ) return; set_file_handle(FTP::get_file_handle(c, is_orig)); } diff --git a/scripts/base/protocols/ftp/main.bro b/scripts/base/protocols/ftp/main.bro index 7e2a1200cc..88e1fbeeb8 100644 --- a/scripts/base/protocols/ftp/main.bro +++ b/scripts/base/protocols/ftp/main.bro @@ -1,6 +1,6 @@ ##! The logging this script does is primarily focused on logging FTP commands ##! along with metadata. For example, if files are transferred, the argument -##! will take on the full path that the client is at along with the requested +##! will take on the full path that the client is at along with the requested ##! file name. @load ./utils-commands @@ -13,16 +13,16 @@ module FTP; export { ## The FTP protocol logging stream identifier. redef enum Log::ID += { LOG }; - + ## List of commands that should have their command/response pairs logged. const logged_commands = { "APPE", "DELE", "RETR", "STOR", "STOU", "ACCT", "PORT", "PASV", "EPRT", "EPSV" } &redef; - + ## This setting changes if passwords used in FTP sessions are captured or not. const default_capture_password = F &redef; - + ## User IDs that can be considered "anonymous". const guest_ids = { "anonymous", "ftp", "ftpuser", "guest" } &redef; @@ -37,7 +37,7 @@ export { ## The port at which the acceptor is listening for the data connection. resp_p: port &log; }; - + type Info: record { ## Time when the command was sent. ts: time &log; @@ -53,12 +53,12 @@ export { command: string &log &optional; ## Argument for the command if one is given. arg: string &log &optional; - + ## Libmagic "sniffed" file type if the command indicates a file transfer. mime_type: string &log &optional; ## Size of the file if the command indicates a file transfer. file_size: count &log &optional; - + ## Reply code from the server in response to the command. reply_code: count &log &optional; ## Reply message from the server in response to the command. @@ -74,31 +74,31 @@ export { ## more concrete is discovered that the existing but unknown ## directory is ok to use. cwd: string &default="."; - + ## Command that is currently waiting for a response. cmdarg: CmdArg &optional; - ## Queue for commands that have been sent but not yet responded to + ## Queue for commands that have been sent but not yet responded to ## are tracked here. pending_commands: PendingCmds; - + ## Indicates if the session is in active or passive mode. passive: bool &default=F; - + ## Determines if the password will be captured for this request. capture_password: bool &default=default_capture_password; }; - ## This record is to hold a parsed FTP reply code. For example, for the + ## This record is to hold a parsed FTP reply code. For example, for the ## 201 status code, the digits would be parsed as: x->2, y->0, z=>1. type ReplyCode: record { x: count; y: count; z: count; }; - + ## Parse FTP reply codes into the three constituent single digit values. global parse_ftp_reply_code: function(code: count): ReplyCode; - + ## Event that can be handled to access the :bro:type:`FTP::Info` ## record as it is sent on to the logging framework. global log_ftp: event(rec: Info); @@ -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 @@ -166,7 +166,7 @@ function set_ftp_session(c: connection) s$uid=c$uid; s$id=c$id; c$ftp=s; - + # Add a shim command so the server can respond with some init response. add_pending_cmd(c$ftp$pending_commands, "", ""); } @@ -178,13 +178,13 @@ function ftp_message(s: Info) # or it's a deliberately logged command. if ( |s$tags| > 0 || (s?$cmdarg && s$cmdarg$cmd in logged_commands) ) { - if ( s?$password && - ! s$capture_password && + if ( s?$password && + ! s$capture_password && to_lower(s$user) !in guest_ids ) { s$password = ""; } - + local arg = s$cmdarg$arg; if ( s$cmdarg$cmd in file_cmds ) { @@ -194,7 +194,7 @@ function ftp_message(s: Info) arg = fmt("ftp://%s%s", addr_to_uri(s$id$resp_h), comp_path); } - + s$ts=s$cmdarg$ts; s$command=s$cmdarg$cmd; if ( arg == "" ) @@ -204,9 +204,9 @@ function ftp_message(s: Info) Log::write(FTP::LOG, s); } - - # The MIME and file_size fields are specific to file transfer commands - # and may not be used in all commands so they need reset to "blank" + + # The MIME and file_size fields are specific to file transfer commands + # and may not be used in all commands so they need reset to "blank" # values after logging. delete s$mime_type; delete s$file_size; @@ -221,8 +221,8 @@ 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, - 5mins); + Analyzer::schedule_analyzer(chan$orig_h, chan$resp_h, chan$resp_p, Analyzer::ANALYZER_FTP_DATA, + 5mins); } event ftp_request(c: connection, command: string, arg: string) &priority=5 @@ -237,19 +237,19 @@ event ftp_request(c: connection, command: string, arg: string) &priority=5 remove_pending_cmd(c$ftp$pending_commands, c$ftp$cmdarg); ftp_message(c$ftp); } - + local id = c$id; set_ftp_session(c); - + # Queue up the new command and argument add_pending_cmd(c$ftp$pending_commands, command, arg); - + if ( command == "USER" ) c$ftp$user = arg; - + else if ( command == "PASS" ) c$ftp$password = arg; - + else if ( command == "PORT" || command == "EPRT" ) { local data = (command == "PORT") ? @@ -277,7 +277,7 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) &prior # TODO: figure out what to do with continued FTP response (not used much) if ( cont_resp ) return; - + # TODO: do some sort of generic clear text login processing here. local response_xyz = parse_ftp_reply_code(code); #if ( response_xyz$x == 2 && # successful @@ -293,17 +293,17 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) &prior # if that's given as well which would be more correct. c$ftp$file_size = extract_count(msg); } - + # PASV and EPSV processing else if ( (code == 227 || code == 229) && (c$ftp$cmdarg$cmd == "PASV" || c$ftp$cmdarg$cmd == "EPSV") ) { local data = (code == 227) ? parse_ftp_pasv(msg) : parse_ftp_epsv(msg); - + if ( data$valid ) { c$ftp$passive=T; - + if ( code == 229 && data$h == [::] ) data$h = c$id$resp_h; @@ -327,9 +327,9 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) &prior else if ( c$ftp$cmdarg$cmd == "PWD" || c$ftp$cmdarg$cmd == "XPWD" ) c$ftp$cwd = extract_path(msg); } - + # In case there are multiple commands queued, go ahead and remove the - # command here and log because we can't do the normal processing pipeline + # command here and log because we can't do the normal processing pipeline # to wait for a new command before logging the command/response pair. if ( |c$ftp$pending_commands| > 1 ) { @@ -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 ) @@ -361,7 +361,7 @@ event connection_reused(c: connection) &priority=5 if ( "ftp-data" in c$service ) c$ftp_data_reuse = T; } - + event connection_state_remove(c: connection) &priority=-5 { if ( c$ftp_data_reuse ) return; diff --git a/scripts/base/protocols/http/file-analysis.bro b/scripts/base/protocols/http/file-analysis.bro index fc537f3477..51b3ea8dd5 100644 --- a/scripts/base/protocols/http/file-analysis.bro +++ b/scripts/base/protocols/http/file-analysis.bro @@ -15,17 +15,17 @@ function get_file_handle(c: connection, is_orig: bool): string if ( ! c?$http ) return ""; if ( c$http$range_request ) - return cat(ANALYZER_HTTP, " ", is_orig, " ", c$id$orig_h, " ", + return cat(Analyzer::ANALYZER_HTTP, " ", is_orig, " ", c$id$orig_h, " ", build_url(c$http)); - return cat(ANALYZER_HTTP, " ", c$start_time, " ", is_orig, " ", + return cat(Analyzer::ANALYZER_HTTP, " ", c$start_time, " ", is_orig, " ", c$http$trans_depth, " ", id_string(c$id)); } module GLOBAL; -event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) +event get_file_handle(tag: Analyzer::Tag, c: connection, is_orig: bool) { - if ( tag != ANALYZER_HTTP ) return; + if ( tag != Analyzer::ANALYZER_HTTP ) return; set_file_handle(HTTP::get_file_handle(c, is_orig)); } diff --git a/scripts/base/protocols/http/main.bro b/scripts/base/protocols/http/main.bro index a1771c8e77..1c9c1cad2d 100644 --- a/scripts/base/protocols/http/main.bro +++ b/scripts/base/protocols/http/main.bro @@ -123,29 +123,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; diff --git a/scripts/base/protocols/irc/dcc-send.bro b/scripts/base/protocols/irc/dcc-send.bro index 8f3de2ac09..0e1d52af59 100644 --- a/scripts/base/protocols/irc/dcc-send.bro +++ b/scripts/base/protocols/irc/dcc-send.bro @@ -175,11 +175,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 ) diff --git a/scripts/base/protocols/irc/file-analysis.bro b/scripts/base/protocols/irc/file-analysis.bro index 94d9f95d73..e1fdc9c484 100644 --- a/scripts/base/protocols/irc/file-analysis.bro +++ b/scripts/base/protocols/irc/file-analysis.bro @@ -12,13 +12,13 @@ export { function get_file_handle(c: connection, is_orig: bool): string { if ( is_orig ) return ""; - return cat(ANALYZER_IRC_DATA, " ", c$start_time, " ", id_string(c$id)); + return cat(Analyzer::ANALYZER_IRC_DATA, " ", c$start_time, " ", id_string(c$id)); } module GLOBAL; -event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) +event get_file_handle(tag: Analyzer::Tag, c: connection, is_orig: bool) { - if ( tag != ANALYZER_IRC_DATA ) return; + if ( tag != Analyzer::ANALYZER_IRC_DATA ) return; set_file_handle(IRC::get_file_handle(c, is_orig)); } diff --git a/scripts/base/protocols/irc/main.bro b/scripts/base/protocols/irc/main.bro index 1cf542b8ea..490c39f54f 100644 --- a/scripts/base/protocols/irc/main.bro +++ b/scripts/base/protocols/irc/main.bro @@ -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 diff --git a/scripts/base/protocols/modbus/main.bro b/scripts/base/protocols/modbus/main.bro index aa11c5ce07..a418873306 100644 --- a/scripts/base/protocols/modbus/main.bro +++ b/scripts/base/protocols/modbus/main.bro @@ -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 diff --git a/scripts/base/protocols/smtp/file-analysis.bro b/scripts/base/protocols/smtp/file-analysis.bro index cbe109eff3..17f9a32498 100644 --- a/scripts/base/protocols/smtp/file-analysis.bro +++ b/scripts/base/protocols/smtp/file-analysis.bro @@ -13,14 +13,14 @@ export { function get_file_handle(c: connection, is_orig: bool): string { if ( ! c?$smtp ) return ""; - return cat(ANALYZER_SMTP, " ", c$start_time, " ", c$smtp$trans_depth, " ", + return cat(Analyzer::ANALYZER_SMTP, " ", c$start_time, " ", c$smtp$trans_depth, " ", c$smtp_state$mime_level); } module GLOBAL; -event get_file_handle(tag: AnalyzerTag, c: connection, is_orig: bool) +event get_file_handle(tag: Analyzer::Tag, c: connection, is_orig: bool) { - if ( tag != ANALYZER_SMTP ) return; + if ( tag != Analyzer::ANALYZER_SMTP ) return; set_file_handle(SMTP::get_file_handle(c, is_orig)); } diff --git a/scripts/base/protocols/smtp/main.bro b/scripts/base/protocols/smtp/main.bro index 03b3d36a24..c7b3a452d2 100644 --- a/scripts/base/protocols/smtp/main.bro +++ b/scripts/base/protocols/smtp/main.bro @@ -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 diff --git a/scripts/base/protocols/socks/main.bro b/scripts/base/protocols/socks/main.bro index df5ee69f16..a188646515 100644 --- a/scripts/base/protocols/socks/main.bro +++ b/scripts/base/protocols/socks/main.bro @@ -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) diff --git a/scripts/base/protocols/ssh/main.bro b/scripts/base/protocols/ssh/main.bro index d069486e67..8e1c5515b5 100644 --- a/scripts/base/protocols/ssh/main.bro +++ b/scripts/base/protocols/ssh/main.bro @@ -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) diff --git a/scripts/base/protocols/ssl/main.bro b/scripts/base/protocols/ssl/main.bro index c6c4091a87..36d0c3f54d 100644 --- a/scripts/base/protocols/ssl/main.bro +++ b/scripts/base/protocols/ssl/main.bro @@ -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,16 +112,9 @@ 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 += { - 443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp, - 989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp -}; +redef likely_server_ports += { ports }; # A queue that buffers log records. global log_delay_queue: table[count] of Info; @@ -135,6 +123,12 @@ 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) { if ( ! c?$ssl ) @@ -288,14 +282,14 @@ 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 ) diff --git a/scripts/base/protocols/syslog/main.bro b/scripts/base/protocols/syslog/main.bro index 61334e3f2b..7c15fb4fae 100644 --- a/scripts/base/protocols/syslog/main.bro +++ b/scripts/base/protocols/syslog/main.bro @@ -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 diff --git a/scripts/policy/frameworks/dpd/detect-protocols.bro b/scripts/policy/frameworks/dpd/detect-protocols.bro index 8f4e892ce4..d50e4599ed 100644 --- a/scripts/policy/frameworks/dpd/detect-protocols.bro +++ b/scripts/policy/frameworks/dpd/detect-protocols.bro @@ -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 ) diff --git a/scripts/policy/frameworks/dpd/packet-segment-logging.bro b/scripts/policy/frameworks/dpd/packet-segment-logging.bro index 3883cd1207..a605d84a74 100644 --- a/scripts/policy/frameworks/dpd/packet-segment-logging.bro +++ b/scripts/policy/frameworks/dpd/packet-segment-logging.bro @@ -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; diff --git a/scripts/policy/misc/analysis-groups.bro b/scripts/policy/misc/analysis-groups.bro deleted file mode 100644 index 17f5bab845..0000000000 --- a/scripts/policy/misc/analysis-groups.bro +++ /dev/null @@ -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); - } \ No newline at end of file diff --git a/scripts/policy/protocols/conn/known-services.bro b/scripts/policy/protocols/conn/known-services.bro index f494a30f82..4e474f76a0 100644 --- a/scripts/policy/protocols/conn/known-services.bro +++ b/scripts/policy/protocols/conn/known-services.bro @@ -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); } diff --git a/scripts/test-all-policy.bro b/scripts/test-all-policy.bro index 7b349b64a3..daad03d9b6 100644 --- a/scripts/test-all-policy.bro +++ b/scripts/test-all-policy.bro @@ -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 diff --git a/src/Analyzer.h b/src/Analyzer.h deleted file mode 100644 index 6ccd7648d3..0000000000 --- a/src/Analyzer.h +++ /dev/null @@ -1,403 +0,0 @@ -// Main analyzer interface. - -#ifndef ANALYZER_H -#define ANALYZER_H - -#include - -#include "AnalyzerTags.h" -#include "Conn.h" -#include "Obj.h" - -class DPM; -class PIA; -class Analyzer; -typedef list 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 diff --git a/src/AnalyzerTags.h b/src/AnalyzerTags.h deleted file mode 100644 index 8429dec335..0000000000 --- a/src/AnalyzerTags.h +++ /dev/null @@ -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 diff --git a/src/Base64.cc b/src/Base64.cc index d3abd9b563..50732534ab 100644 --- a/src/Base64.cc +++ b/src/Base64.cc @@ -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 ) { diff --git a/src/Base64.h b/src/Base64.h index 8cfeffde74..d7e4384ac5 100644 --- a/src/Base64.h +++ b/src/Base64.h @@ -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: // 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; }; diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 23b1f56aaa..984bdc90a4 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -35,12 +35,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"; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 447b7d9ec7..5e74b3d8b0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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,45 +107,7 @@ 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 @@ -153,74 +122,53 @@ set(BIF_SRCS ) foreach (bift ${BIF_SRCS}) - bif_target(${bift}) + bif_target(${bift} "standard") endforeach () ######################################################################## ## BinPAC-dependent targets +include(BinPAC) + set(BINPAC_AUXSRC - binpac.pac - bro.pac - binpac_bro.h + ${CMAKE_SOURCE_DIR}/src/binpac.pac + ${CMAKE_SOURCE_DIR}/src/bro.pac + ${CMAKE_SOURCE_DIR}/src/binpac_bro.h ) -# 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}" - ) - 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) + +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 @@ -473,18 +367,41 @@ set(bro_SRCS 3rdparty/sqlite3.c + plugin/Component.cc + plugin/Manager.cc + plugin/Plugin.cc + nb_dns.c digest.h ) collect_headers(bro_HEADERS ${bro_SRCS}) -add_executable(bro ${bro_SRCS} ${bro_HEADERS}) - -target_link_libraries(bro ${brodeps} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) +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) + diff --git a/src/Conn.cc b/src/Conn.cc index bc2e7fb5cf..fb6ca3d810 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -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; diff --git a/src/Conn.h b/src/Conn.h index 782d41a801..95c521d875 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -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. }; diff --git a/src/DHCP-binpac.cc b/src/DHCP-binpac.cc deleted file mode 100644 index 2aec6e6e9f..0000000000 --- a/src/DHCP-binpac.cc +++ /dev/null @@ -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); - } diff --git a/src/DHCP-binpac.h b/src/DHCP-binpac.h deleted file mode 100644 index 06ddff3bb6..0000000000 --- a/src/DHCP-binpac.h +++ /dev/null @@ -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 diff --git a/src/DNS-binpac.cc b/src/DNS-binpac.cc deleted file mode 100644 index 999f6015c0..0000000000 --- a/src/DNS-binpac.cc +++ /dev/null @@ -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); - } diff --git a/src/DNS-binpac.h b/src/DNS-binpac.h deleted file mode 100644 index 0bbacf9192..0000000000 --- a/src/DNS-binpac.h +++ /dev/null @@ -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 diff --git a/src/DPM.cc b/src/DPM.cc deleted file mode 100644 index 611cf65c89..0000000000 --- a/src/DPM.cc +++ /dev/null @@ -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; - } - } - diff --git a/src/DPM.h b/src/DPM.h deleted file mode 100644 index f59d21dbfc..0000000000 --- a/src/DPM.h +++ /dev/null @@ -1,131 +0,0 @@ -// The central management unit for dynamic analyzer selection. - -#ifndef DPM_H -#define DPM_H - -#include - -#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 tag_list; - typedef map 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, - bool (*)(const AssignedAnalyzer*, - const AssignedAnalyzer*)> conn_queue; - conn_queue expected_conns_queue; -}; - -extern DPM* dpm; - -#endif diff --git a/src/DebugLogger.h b/src/DebugLogger.h index 5ce7230066..e293b326a8 100644 --- a/src/DebugLogger.h +++ b/src/DebugLogger.h @@ -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 diff --git a/src/Event.cc b/src/Event.cc index 9dd3415eaf..d6bb0d8e58 100644 --- a/src/Event.cc +++ b/src/Event.cc @@ -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; diff --git a/src/Event.h b/src/Event.h index e0ce7bf555..9d0a707cda 100644 --- a/src/Event.h +++ b/src/Event.h @@ -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; diff --git a/src/EventHandler.cc b/src/EventHandler.cc index 5598f93f98..4a74d68a08 100644 --- a/src/EventHandler.cc +++ b/src/EventHandler.cc @@ -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 diff --git a/src/EventHandler.h b/src/EventHandler.h index a86b8a285c..786d9f94ba 100644 --- a/src/EventHandler.h +++ b/src/EventHandler.h @@ -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 diff --git a/src/EventLauncher.cc b/src/EventLauncher.cc index 246c9dc8aa..cc32efe59e 100644 --- a/src/EventLauncher.cc +++ b/src/EventLauncher.cc @@ -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" diff --git a/src/EventRegistry.cc b/src/EventRegistry.cc index 4d29c5d95f..2da16de51d 100644 --- a/src/EventRegistry.cc +++ b/src/EventRegistry.cc @@ -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); - } - } - diff --git a/src/EventRegistry.h b/src/EventRegistry.h index 6ee5e3bcbd..3b4c8df918 100644 --- a/src/EventRegistry.h +++ b/src/EventRegistry.h @@ -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(); diff --git a/src/Expr.cc b/src/Expr.cc index 12d3d72304..221f6545ac 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3320,12 +3320,20 @@ bool HasFieldExpr::DoUnserialize(UnserialInfo* info) return UNSERIALIZE(¬_used) && UNSERIALIZE_STR(&field_name, 0) && UNSERIALIZE(&field); } -RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list) +RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list, + BroType* arg_type) : UnaryExpr(EXPR_RECORD_CONSTRUCTOR, constructor_list) { if ( IsError() ) return; + if ( arg_type && arg_type->Tag() != TYPE_RECORD ) + { + Error("bad record constructor type", arg_type); + SetError(); + return; + } + // Spin through the list, which should be comprised of // either record's or record-field-assign, and build up a // record type to associate with this constructor. @@ -3365,7 +3373,17 @@ RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list) } } - SetType(new RecordType(record_types)); + ctor_type = new RecordType(record_types); + + if ( arg_type ) + SetType(arg_type->Ref()); + else + SetType(ctor_type->Ref()); + } + +RecordConstructorExpr::~RecordConstructorExpr() + { + Unref(ctor_type); } Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const @@ -3391,7 +3409,7 @@ Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const Val* RecordConstructorExpr::Fold(Val* v) const { ListVal* lv = v->AsListVal(); - RecordType* rt = type->AsRecordType(); + RecordType* rt = ctor_type->AsRecordType(); if ( lv->Length() != rt->NumFields() ) Internal("inconsistency evaluating record constructor"); @@ -3401,6 +3419,19 @@ Val* RecordConstructorExpr::Fold(Val* v) const for ( int i = 0; i < lv->Length(); ++i ) rv->Assign(i, lv->Index(i)->Ref()); + if ( ! same_type(rt, type) ) + { + RecordVal* new_val = rv->CoerceTo(type->AsRecordType()); + + if ( new_val ) + { + Unref(rv); + rv = new_val; + } + else + Internal("record constructor coercion failed"); + } + return rv; } @@ -3416,37 +3447,89 @@ IMPLEMENT_SERIAL(RecordConstructorExpr, SER_RECORD_CONSTRUCTOR_EXPR); bool RecordConstructorExpr::DoSerialize(SerialInfo* info) const { DO_SERIALIZE(SER_RECORD_CONSTRUCTOR_EXPR, UnaryExpr); + SERIALIZE_OPTIONAL(ctor_type); return true; } bool RecordConstructorExpr::DoUnserialize(UnserialInfo* info) { DO_UNSERIALIZE(UnaryExpr); + BroType* t = 0; + UNSERIALIZE_OPTIONAL(t, RecordType::Unserialize(info)); + ctor_type = t->AsRecordType(); return true; } TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list, - attr_list* arg_attrs) + attr_list* arg_attrs, BroType* arg_type) : UnaryExpr(EXPR_TABLE_CONSTRUCTOR, constructor_list) { if ( IsError() ) return; - if ( constructor_list->Exprs().length() == 0 ) - SetType(new TableType(new TypeList(base_type(TYPE_ANY)), 0)); + if ( arg_type ) + { + if ( ! arg_type->IsTable() ) + { + Error("bad table constructor type", arg_type); + SetError(); + return; + } + + SetType(arg_type->Ref()); + } else { - SetType(init_type(constructor_list)); + if ( constructor_list->Exprs().length() == 0 ) + SetType(new TableType(new TypeList(base_type(TYPE_ANY)), 0)); + else + { + SetType(init_type(constructor_list)); - if ( ! type ) - SetError(); + if ( ! type ) + SetError(); - else if ( type->Tag() != TYPE_TABLE || - type->AsTableType()->IsSet() ) - SetError("values in table(...) constructor do not specify a table"); + else if ( type->Tag() != TYPE_TABLE || + type->AsTableType()->IsSet() ) + SetError("values in table(...) constructor do not specify a table"); + } } attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0; + + type_list* indices = type->AsTableType()->Indices()->Types(); + const expr_list& cle = constructor_list->Exprs(); + + // check and promote all index expressions in ctor list + loop_over_list(cle, i) + { + if ( cle[i]->Tag() != EXPR_ASSIGN ) + continue; + + Expr* idx_expr = cle[i]->AsAssignExpr()->Op1(); + + if ( idx_expr->Tag() != EXPR_LIST ) + continue; + + expr_list& idx_exprs = idx_expr->AsListExpr()->Exprs(); + + if ( idx_exprs.length() != indices->length() ) + continue; + + loop_over_list(idx_exprs, j) + { + Expr* idx = idx_exprs[j]; + + if ( check_and_promote_expr(idx, (*indices)[j]) ) + { + if ( idx != idx_exprs[j] ) + idx_exprs.replace(j, idx); + continue; + } + + ExprError("inconsistent types in table constructor"); + } + } } Val* TableConstructorExpr::Eval(Frame* f) const @@ -3502,16 +3585,30 @@ bool TableConstructorExpr::DoUnserialize(UnserialInfo* info) } SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list, - attr_list* arg_attrs) + attr_list* arg_attrs, BroType* arg_type) : UnaryExpr(EXPR_SET_CONSTRUCTOR, constructor_list) { if ( IsError() ) return; - if ( constructor_list->Exprs().length() == 0 ) - SetType(new ::SetType(new TypeList(base_type(TYPE_ANY)), 0)); + if ( arg_type ) + { + if ( ! arg_type->IsSet() ) + { + Error("bad set constructor type", arg_type); + SetError(); + return; + } + + SetType(arg_type->Ref()); + } else - SetType(init_type(constructor_list)); + { + if ( constructor_list->Exprs().length() == 0 ) + SetType(new ::SetType(new TypeList(base_type(TYPE_ANY)), 0)); + else + SetType(init_type(constructor_list)); + } if ( ! type ) SetError(); @@ -3520,6 +3617,37 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list, SetError("values in set(...) constructor do not specify a set"); attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0; + + type_list* indices = type->AsTableType()->Indices()->Types(); + expr_list& cle = constructor_list->Exprs(); + + if ( indices->length() == 1 ) + { + if ( ! check_and_promote_exprs_to_type(constructor_list, + (*indices)[0]) ) + ExprError("inconsistent type in set constructor"); + } + + else if ( indices->length() > 1 ) + { + // Check/promote each expression in composite index. + loop_over_list(cle, i) + { + Expr* ce = cle[i]; + ListExpr* le = ce->AsListExpr(); + + if ( ce->Tag() == EXPR_LIST && + check_and_promote_exprs(le, type->AsTableType()->Indices()) ) + { + if ( le != cle[i] ) + cle.replace(i, le); + + continue; + } + + ExprError("inconsistent types in set constructor"); + } + } } Val* SetConstructorExpr::Eval(Frame* f) const @@ -3590,31 +3718,50 @@ bool SetConstructorExpr::DoUnserialize(UnserialInfo* info) return true; } -VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list) +VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list, + BroType* arg_type) : UnaryExpr(EXPR_VECTOR_CONSTRUCTOR, constructor_list) { if ( IsError() ) return; - if ( constructor_list->Exprs().length() == 0 ) + if ( arg_type ) { - // vector(). - SetType(new ::VectorType(base_type(TYPE_ANY))); - return; - } + if ( arg_type->Tag() != TYPE_VECTOR ) + { + Error("bad vector constructor type", arg_type); + SetError(); + return; + } - BroType* t = merge_type_list(constructor_list); - if ( t ) - { - SetType(new VectorType(t->Ref())); - - if ( ! check_and_promote_exprs_to_type(constructor_list, t) ) - ExprError("inconsistent types in vector constructor"); - - Unref(t); + SetType(arg_type->Ref()); } else - SetError(); + { + if ( constructor_list->Exprs().length() == 0 ) + { + // vector(). + SetType(new ::VectorType(base_type(TYPE_ANY))); + return; + } + + BroType* t = merge_type_list(constructor_list); + + if ( t ) + { + SetType(new VectorType(t->Ref())); + Unref(t); + } + else + { + SetError(); + return; + } + } + + if ( ! check_and_promote_exprs_to_type(constructor_list, + type->AsVectorType()->YieldType()) ) + ExprError("inconsistent types in vector constructor"); } Val* VectorConstructorExpr::Eval(Frame* f) const diff --git a/src/Expr.h b/src/Expr.h index bb7526d502..ba173feae0 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -57,6 +57,8 @@ extern const char* expr_name(BroExprTag t); class Stmt; class Frame; class ListExpr; +class NameExpr; +class AssignExpr; class CallExpr; class EventExpr; @@ -159,12 +161,37 @@ public: CHECK_TAG(tag, EXPR_LIST, "ExprVal::AsListExpr", expr_name) return (const ListExpr*) this; } + ListExpr* AsListExpr() { CHECK_TAG(tag, EXPR_LIST, "ExprVal::AsListExpr", expr_name) return (ListExpr*) this; } + const NameExpr* AsNameExpr() const + { + CHECK_TAG(tag, EXPR_NAME, "ExprVal::AsNameExpr", expr_name) + return (const NameExpr*) this; + } + + NameExpr* AsNameExpr() + { + CHECK_TAG(tag, EXPR_NAME, "ExprVal::AsNameExpr", expr_name) + return (NameExpr*) this; + } + + const AssignExpr* AsAssignExpr() const + { + CHECK_TAG(tag, EXPR_ASSIGN, "ExprVal::AsAssignExpr", expr_name) + return (const AssignExpr*) this; + } + + AssignExpr* AsAssignExpr() + { + CHECK_TAG(tag, EXPR_ASSIGN, "ExprVal::AsAssignExpr", expr_name) + return (AssignExpr*) this; + } + void Describe(ODesc* d) const; bool Serialize(SerialInfo* info) const; @@ -729,7 +756,8 @@ protected: class RecordConstructorExpr : public UnaryExpr { public: - RecordConstructorExpr(ListExpr* constructor_list); + RecordConstructorExpr(ListExpr* constructor_list, BroType* arg_type = 0); + ~RecordConstructorExpr(); protected: friend class Expr; @@ -741,11 +769,14 @@ protected: void ExprDescribe(ODesc* d) const; DECLARE_SERIAL(RecordConstructorExpr); + + RecordType* ctor_type; // type inferred from the ctor expression list args }; class TableConstructorExpr : public UnaryExpr { public: - TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs); + TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs, + BroType* arg_type = 0); ~TableConstructorExpr() { Unref(attrs); } Attributes* Attrs() { return attrs; } @@ -767,7 +798,8 @@ protected: class SetConstructorExpr : public UnaryExpr { public: - SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs); + SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs, + BroType* arg_type = 0); ~SetConstructorExpr() { Unref(attrs); } Attributes* Attrs() { return attrs; } @@ -789,7 +821,7 @@ protected: class VectorConstructorExpr : public UnaryExpr { public: - VectorConstructorExpr(ListExpr* constructor_list); + VectorConstructorExpr(ListExpr* constructor_list, BroType* arg_type = 0); Val* Eval(Frame* f) const; diff --git a/src/Finger.h b/src/Finger.h deleted file mode 100644 index 3c61c4ad2a..0000000000 --- a/src/Finger.h +++ /dev/null @@ -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 diff --git a/src/FlowSrc.cc b/src/FlowSrc.cc index 59ce3fd6a4..f5fb0bd1e6 100644 --- a/src/FlowSrc.cc +++ b/src/FlowSrc.cc @@ -9,7 +9,7 @@ #include "FlowSrc.h" #include "Net.h" -#include "netflow_pac.h" +#include "analyzer/protocol/netflow/netflow_pac.h" #include FlowSrc::FlowSrc() diff --git a/src/Func.cc b/src/Func.cc index 30db27fc71..97d84013e6 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -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" @@ -564,7 +564,6 @@ void builtin_error(const char* msg, BroObj* arg) 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(); diff --git a/src/H3.h b/src/H3.h index 9e6f1c5c35..72d81d519f 100644 --- a/src/H3.h +++ b/src/H3.h @@ -66,7 +66,6 @@ template 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(data); diff --git a/src/HTTP-binpac.cc b/src/HTTP-binpac.cc deleted file mode 100644 index 47b2c479ec..0000000000 --- a/src/HTTP-binpac.cc +++ /dev/null @@ -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); - } diff --git a/src/HTTP-binpac.h b/src/HTTP-binpac.h deleted file mode 100644 index ef7cc7dd7d..0000000000 --- a/src/HTTP-binpac.h +++ /dev/null @@ -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 diff --git a/src/ID.cc b/src/ID.cc index 959ad9b07d..a6e592146b 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -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()); diff --git a/src/ID.h b/src/ID.h index 9c1f56e80f..57e1222511 100644 --- a/src/ID.h +++ b/src/ID.h @@ -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; diff --git a/src/IPAddr.cc b/src/IPAddr.cc index 51fb37c4d5..7fd3755042 100644 --- a/src/IPAddr.cc +++ b/src/IPAddr.cc @@ -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 ) diff --git a/src/IPAddr.h b/src/IPAddr.h index 5ddee70fb8..cc7b2baa6e 100644 --- a/src/IPAddr.h +++ b/src/IPAddr.h @@ -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. diff --git a/src/Modbus.h b/src/Modbus.h deleted file mode 100644 index 5e3294d91c..0000000000 --- a/src/Modbus.h +++ /dev/null @@ -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 diff --git a/src/NetVar.cc b/src/NetVar.cc index 3a23e4c9fa..74cd6d08d0 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -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; @@ -423,14 +421,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 +516,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"); diff --git a/src/NetVar.h b/src/NetVar.h index 1a20adcaf2..0ecceb9f92 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -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; diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index 66f8def489..8cd34aa8fc 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -351,10 +351,12 @@ public: } char Type() { return buffer[0]; } + RemoteSerializer::PeerID Peer() { - // Wow, is this ugly... - return ntohl(*(uint32*)(buffer + 4)); + uint32 tmp; + memcpy(&tmp, buffer + 4, sizeof(tmp)); + return ntohl(tmp); } const char* Raw() { return buffer; } diff --git a/src/RuleAction.cc b/src/RuleAction.cc index bf90c0681e..a13392ee40 100644 --- a/src/RuleAction.cc +++ b/src/RuleAction.cc @@ -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(); } diff --git a/src/RuleAction.h b/src/RuleAction.h index a9feb0c314..67ceadc6f1 100644 --- a/src/RuleAction.h +++ b/src/RuleAction.h @@ -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); diff --git a/src/RuleCondition.cc b/src/RuleCondition.cc index 410f6a1b3e..36d8cba39d 100644 --- a/src/RuleCondition.cc +++ b/src/RuleCondition.cc @@ -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(root); + analyzer::tcp::TCP_Analyzer* ta = static_cast(root); if ( tcpstates & STATE_STATELESS ) return true; diff --git a/src/RuleMatcher.cc b/src/RuleMatcher.cc index c71f86108a..5b6f673a8a 100644 --- a/src/RuleMatcher.cc +++ b/src/RuleMatcher.cc @@ -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& 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; diff --git a/src/RuleMatcher.h b/src/RuleMatcher.h index b8895513b4..351c3c30bf 100644 --- a/src/RuleMatcher.h +++ b/src/RuleMatcher.h @@ -35,8 +35,10 @@ extern const char* current_rule_file; class RuleMatcher; extern RuleMatcher* rule_matcher; -class Analyzer; -class PIA; +namespace analyzer { + namespace pia { class PIA; } + class Analyzer; +} // 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. diff --git a/src/SSH.h b/src/SSH.h deleted file mode 100644 index ccdcd76929..0000000000 --- a/src/SSH.h +++ /dev/null @@ -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 diff --git a/src/Sessions.cc b/src/Sessions.cc index 2e5a6ded30..b844dc614e 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -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,9 +526,9 @@ 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, - icmpp->icmp_code, - id.is_one_way); + id.dst_port = analyzer::icmp::ICMP4_counterpart(icmpp->icmp_type, + icmpp->icmp_code, + id.is_one_way); id.src_port = htons(id.src_port); id.dst_port = htons(id.dst_port); @@ -539,9 +542,9 @@ 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, - icmpp->icmp_code, - id.is_one_way); + id.dst_port = analyzer::icmp::ICMP6_counterpart(icmpp->icmp_type, + icmpp->icmp_code, + id.is_one_way); id.src_port = htons(id.src_port); id.dst_port = htons(id.dst_port); @@ -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); } @@ -1159,12 +1162,12 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id, if ( ! WantConnection(src_h, dst_h, tproto, flags, flip) ) return 0; + ConnID flip_id = *id; + if ( flip ) { // Make a guess that we're seeing the tail half of // an analyzable connection. - ConnID flip_id = *id; - const IPAddr ta = flip_id.src_addr; flip_id.src_addr = flip_id.dst_addr; flip_id.dst_addr = ta; @@ -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(); diff --git a/src/Sessions.h b/src/Sessions.h index abaa8b49d0..27b052ba2d 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -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 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 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; diff --git a/src/Stats.cc b/src/Stats.cc index 1bccb8f9be..9b839ec672 100644 --- a/src/Stats.cc +++ b/src/Stats.cc @@ -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) { diff --git a/src/Stats.h b/src/Stats.h index a11d66828a..8137ad16cf 100644 --- a/src/Stats.h +++ b/src/Stats.h @@ -7,9 +7,6 @@ #include #include -#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); diff --git a/src/Syslog-binpac.h b/src/Syslog-binpac.h deleted file mode 100644 index fcd75edf0e..0000000000 --- a/src/Syslog-binpac.h +++ /dev/null @@ -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 diff --git a/src/Type.h b/src/Type.h index 0b7620cd68..bad51776d9 100644 --- a/src/Type.h +++ b/src/Type.h @@ -217,6 +217,11 @@ public: return tag == TYPE_TABLE && (YieldType() == 0); } + int IsTable() const + { + return tag == TYPE_TABLE && (YieldType() != 0); + } + BroType* Ref() { ::Ref(this); return this; } virtual void Describe(ODesc* d) const; diff --git a/src/Val.cc b/src/Val.cc index 33b2d0eacd..3e69401918 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -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(); diff --git a/src/Val.h b/src/Val.h index 4b2705c5b4..019c390699 100644 --- a/src/Val.h +++ b/src/Val.h @@ -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 diff --git a/src/Analyzer.cc b/src/analyzer/Analyzer.cc similarity index 62% rename from src/Analyzer.cc rename to src/analyzer/Analyzer.cc index 8bb05429c1..ecd3c9f686 100644 --- a/src/Analyzer.cc +++ b/src/analyzer/Analyzer.cc @@ -1,191 +1,45 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include #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, "", 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); - AddChildAnalyzer(a); + 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) { diff --git a/src/analyzer/Analyzer.h b/src/analyzer/Analyzer.h new file mode 100644 index 0000000000..396d45d60e --- /dev/null +++ b/src/analyzer/Analyzer.h @@ -0,0 +1,852 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef ANALYZER_ANALYZER_H +#define ANALYZER_ANALYZER_H + +#include + +#include "Tag.h" + +#include "../Obj.h" +#include "../EventHandler.h" +#include "../Timer.h" + +class Rule; +class Connection; +class IP_Hdr; + +namespace analyzer { + +namespace tcp { class TCP_ApplicationAnalyzer; } +namespace pia { class PIA; } + +class Analyzer; +class AnalyzerTimer; +class SupportAnalyzer; +class OutputHandler; + +typedef list analyzer_list; +typedef uint32 ID; +typedef void (Analyzer::*analyzer_timer_func)(double t); + +/** + * Class to receive processed output from an anlyzer. + */ +class OutputHandler { +public: + /** + * Destructor. + */ + virtual ~OutputHandler() { } + + /** + * Hook for receiving packet data. Parameters are the same as for + * Analyzer::DeliverPacket(). + */ + virtual void DeliverPacket(int len, const u_char* data, + bool orig, int seq, + const IP_Hdr* ip, int caplen) + { } + + /** + * Hook for receiving stream data. Parameters are the same as for + * Analyzer::DeliverStream(). + */ + virtual void DeliverStream(int len, const u_char* data, + bool orig) { } + + /** + * Hook for receiving notification of stream gaps. Parameters are the + * same as for Analyzer::Undelivered(). + */ + virtual void Undelivered(int seq, int len, bool orig) { } +}; + +/** + * 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 + * SupportAnalyzer. All analyzer input first passes through this list of + * support analyzers, which can perform arbitrary preprocessing. + * + * When overiding any of the class' methods, always make sure to call the + * base-class version first. + */ +class Analyzer { +public: + /** + * Constructor. + * + * @param name The name for the type of analyzer. The name must match + * the one the corresponding Component registers. + * + * @param conn The connection the analyzer is associated with. + */ + Analyzer(const char* name, Connection* conn); + + /** + * Constructor. + * + * @param tag The tag for the type of analyzer. The tag must map to + * the name the corresponding Component registers. + * + * @param conn The connection the analyzer is associated with. + */ + Analyzer(const Tag& tag, Connection* conn); + + /** + * Constructor. As this version of the constructor does not receive a + * name or tag, setTag() must be called before the instance can be + * used. + * + * @param conn The connection the analyzer is associated with. + */ + Analyzer(Connection* conn); + + /** + * Destructor. + */ + virtual ~Analyzer(); + + /** + * Initializes the analyzer before input processing starts. + */ + virtual void Init(); + + /** + * Finishes the analyzer's operation after all input has been parsed. + */ + virtual void Done(); + + /** + * Passes packet input to the analyzer for processing. The analyzer + * will process the input with any support analyzers first and then + * forward the data to DeliverStream(), which derived classes can + * override. + * + * Note that there is a separate method for stream input, + * NextStream(). + * + * @param len The number of bytes passed in. + * + * @param data Pointer the input to process. + * + * @param is_orig True if this is originator-side input. + * + * @param seq Current sequence number, if available (only supported + * if the data is coming from the TCP analyzer. + * + * @param ip An IP packet header associated with the data, if + * available. + * + * @param caplen The packet's capture length, if available. + */ + void NextPacket(int len, const u_char* data, bool is_orig, + int seq = -1, const IP_Hdr* ip = 0, int caplen = 0); + + /** + * Passes stream input to the analyzer for processing. The analyzer + * will process the input with any support analyzers first and then + * forward the data to DeliverStream(), which derived classes can + * override. + * + * Note that there is a separate method for packet input, + * NextPacket(). + * + * @param len The number of bytes passed in. + * + * @param data Pointer the input to process. + * + * @param is_orig True if this is originator-side input. + */ + void NextStream(int len, const u_char* data, bool is_orig); + + /** + * Informs the analyzer about a gap in the TCP stream, i.e., data + * that can't be delivered. This method triggers Undelivered(), which + * derived classes can override. + * + * @param seq The sequence number of the first byte of gap. + * + * @param len The length of the gap. + * + * @param is_orig True if this is about originator-side input. + */ + void NextUndelivered(int seq, int len, bool is_orig); + + /** + * Reports a message boundary. This is a generic method that can be + * used by an Analyzer if all data of a PDU 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. A final EndOfData() + * is automatically generated by the analyzer's Done() method. This + * method triggers EndOfData(), which derived classes can override. + * + * @param is_orig True if this is about originator-side input. + */ + void NextEndOfData(bool is_orig); + + /** + * Forwards packet input on to all child analyzers. If the analyzer + * has an associated OutputHandlers, that one receives the input as + * well. + * + * Parameters are the same as for NextPacket(). + */ + virtual void ForwardPacket(int len, const u_char* data, + bool orig, int seq, + const IP_Hdr* ip, int caplen); + + /** + * Forwards stream input on to all child analyzers. If the analyzer + * has an associated OutputHandlers, that one receives the input as + * well. + * + * Parameters are the same as for NextStream(). + */ + virtual void ForwardStream(int len, const u_char* data, bool orig); + + /** + * Forwards a sequence gap on to all child analyzers. + * + * Parameters are the same as for NextUndelivered(). + */ + virtual void ForwardUndelivered(int seq, int len, bool orig); + + /** + * Forwards an end-of-data notification on to all child analyzers. + * + * Parameters are the same as for NextPacket(). + */ + virtual void ForwardEndOfData(bool orig); + + /** + * Hook for accessing packet input for parsing. This is called by + * NextDeliverPacket() and can be overridden by derived classes. + * Parameters are the same. + */ + virtual void DeliverPacket(int len, const u_char* data, bool orig, + int seq, const IP_Hdr* ip, int caplen); + + /** + * Hook for accessing stream input for parsing. This is called by + * NextDeliverStream() and can be overridden by derived classes. + * Parameters are the same. + */ + virtual void DeliverStream(int len, const u_char* data, bool orig); + + /** + * Hook for accessing input gap during parsing. This is called by + * NextUndelivered() and can be overridden by derived classes. + * Parameters are the same. + */ + virtual void Undelivered(int seq, int len, bool orig); + + /** + * Hook for accessing end-of-data notifications. This is called by + * NextEndOfData() and can be overridden by derived classes. + * Parameters are the same. + */ + virtual void EndOfData(bool is_orig); + + /** + * Signals the analyzer that its associated connection had its + * endpoint flipped. This can happen if during analysis it turns out + * 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(); + + /** + * Returns the analyzer instance's internal ID. These IDs are unique + * across all analyzer instantiated and can thus be used to indentify + * a specific instance. + */ + ID GetID() const { return id; } + + /** + * Returns the connection that the analyzer is associated with. + */ + Connection* Conn() const { return conn; } + + /** + * Returns the OutputHandler associated with the connection, or null + * if none. + */ + OutputHandler* GetOutputHandler() const { return output_handler; } + + /** + * Associates an OutputHandler with the connnection. + * + * @param handler The handler. + */ + void SetOutputHandler(OutputHandler* handler) + { output_handler = handler; } + + /** + * If this analyzer was activated by a signature match, this returns + * the signature that did so. Returns null otherwise. + */ + const Rule* Signature() const { return signature; } + + /** + * Sets the signature that activated this analyzer, if any. + * + * @param sig The signature. + */ + void SetSignature(const Rule* sig) { signature = sig; } + + /** + * Signals the analyzer to skip all further input processsing. The \a + * Next*() methods check this flag and discard the input if its set. + * + * @param do_skipe If true, further processing will be skipped. + */ + void SetSkip(bool do_skip) { skip = do_skip; } + + /** + * Returns true if the analyzer has been told to skip processing all + * further input. + */ + bool Skipping() const { return skip; } + + /** + * Returns true if Done() has been called. + */ + bool IsFinished() const { return finished; } + + /** + * Returns the tag associated with the analyzer's type. + */ + Tag GetAnalyzerTag() const { assert(tag); return tag; } + + /** + * Sets the tag associated with the analyzer's type. Note that this + * can be called only right after construction, if the constructor + * did not receive a name or tag. The method cannot be used to change + * an existing tag. + */ + void SetAnalyzerTag(const Tag& tag); + + /** + * Returns a textual description of the analyzer's type. This is + * what's passed to the constructor and usally corresponds to the + * protocol name, e.g., "HTTP". + */ + const char* GetAnalyzerName() const; + + /** + * Returns true if this analyzer's type matches the name passes in. + * This is shortcut for comparing GetAnalyzerName() with the given + * name. + * + * @param name The name to check. + */ + bool IsAnalyzer(const char* name); + + /** + * Adds a new child analyzer to the analyzer tree. If an analyzer of + * the same type already exists, the one passes in is silenty + * discarded. + * + * @param analyzer The ananlyzer to add. Takes ownership. + */ + void AddChildAnalyzer(Analyzer* analyzer) + { AddChildAnalyzer(analyzer, true); } + + /** + * Adds a new child analyzer to the analyzer tree. If an analyzer of + * the same type already exists, the one passes in is silenty + * discarded. + * + * @param tag The type of analyzer to add. + */ + Analyzer* AddChildAnalyzer(Tag tag); + + /** + * Removes a child analyzer. It's ok for the analyzer to not to be a + * child, in which case the method does nothing. + * + * @param analyzer The analyzer to remove. + */ + void RemoveChildAnalyzer(Analyzer* analyzer); + + /** + * Removes a child analyzer. It's ok for the analyzer to not to be a + * child, in which case the method does nothing. + * + * @param tag The type of analyzer to remove. + */ + void RemoveChildAnalyzer(ID id); + + /** + * Returns true if analyzer has a direct child of a given type. + * + * @param tag The type of analyzer to check for. + */ + bool HasChildAnalyzer(Tag tag); + + /** + * Recursively searches all (direct or indirect) childs of the + * analyzer for an analyzer with a specific ID. + * + * @param id The analyzer id to search. This is the ID that GetID() + * returns. + * + * @return The analyzer, or null if not found. + */ + Analyzer* FindChild(ID id); + + /** + * Recursively searches all (direct or indirect) childs of the + * analyzer for an analyzer of a given type. + * + * @param tag The analyzer type to search. + * + * @return The first analyzer of the given type found, or null if + * none. + */ + Analyzer* FindChild(Tag tag); + + /** + * Recursively searches all (direct or indirect) childs of the + * analyzer for an analyzer of a given type. + * + * @param name The naem of the analyzer type to search (e.g., + * "HTTP"). + * + * @return The first analyzer of the given type found, or null if + * none. + */ + Analyzer* FindChild(const char* name); + + /** + * Returns a list of all direct child analyzers. + */ + const analyzer_list& GetChildren() { return children; } + + /** + * Returns a pointer to the parent analyzer, or null if this instance + * has not yet been added to an analyzer tree. + */ + Analyzer* Parent() const { return parent; } + + /** + * Sets the parent analyzer. + * + * @param p The new parent. + */ + void SetParent(Analyzer* p) { parent = p; } + + /** + * Remove the analyzer form its parent. The analyzer must have a + * parent associated with it. + */ + void Remove() { assert(parent); parent->RemoveChildAnalyzer(this); } + + /** + * Appends a support analyzer to the current list. + * + * @param analyzer The support analyzer to add. + */ + void AddSupportAnalyzer(SupportAnalyzer* analyzer); + + /** + * Remove a support analyzer. + * + * @param analyzer The analyzer to remove. The function is a no-op if + * that analyzer is not part of the list of support analyzer. + */ + void RemoveSupportAnalyzer(SupportAnalyzer* analyzer); + + /** + * Signals Bro's protocol detection that the analyzer has recognized + * the input to indeed conform to the expected protocol. This should + * be called as early as possible during a connection's life-time. It + * may turn into \c protocol_confirmed event at the script-layer (but + * only once per analyzer for each connection, even if the method is + * called multiple times). + */ + virtual void ProtocolConfirmation(); + + /** + * Signals Bro's protocol detection that the analyzer has found a + * severe protocol violation that could indicate that it's not + * parsing the expected protocol. This turns into \c + * protocol_violation events at the script-layer (one such event is + * raised for each call to this method so that the script-layer can + * built up a notion of how prevalent protocol violations are; the + * more, the less likely it's the right protocol). + * + * @param reason A textual description of the error encountered. + * + * @param data An optional pointer to the malformed data. + * + * @param len If \a data is given, the length of it. + */ + virtual void ProtocolViolation(const char* reason, + const char* data = 0, int len = 0); + + /** + * Returns true if ProtocolConfirmation() has been called at least + * once. + */ + bool ProtocolConfirmed() const + { return protocol_confirmed; } + + /** + * Called whenever the connection value is 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(). + * + * @param conn_val The connenction value being updated. + */ + virtual void UpdateConnVal(RecordVal *conn_val); + + /** + * Convenience function that forwards directly to + * Connection::BuildConnVal(). + */ + RecordVal* BuildConnVal(); + + /** + * Convenience function that forwards directly to the corresponding + * Connection::Event(). + */ + void Event(EventHandlerPtr f, const char* name = 0); + + /** + * Convenience function that forwards directly to the corresponding + * Connection::Event(). + */ + void Event(EventHandlerPtr f, Val* v1, Val* v2 = 0); + + /** + * Convenience function that forwards directly to + * Connection::ConnectionEvent(). + */ + void ConnectionEvent(EventHandlerPtr f, val_list* vl); + + /** + * Convenience function that forwards directly to the corresponding + * Connection::Weird(). + */ + void Weird(const char* name, const char* addl = ""); + + /** + * Internal method. + */ + virtual unsigned int MemoryAllocation() const; + +protected: + friend class AnalyzerTimer; + friend class Manager; + friend class ::Connection; + friend class tcp::TCP_ApplicationAnalyzer; + + /** + * Associates a connection with this analyzer. Must be called if + * using the default ctor. + * + * @param c The connection. + */ + void SetConnection(Connection* c) { conn = c; } + + /** + * Instantiates a new timer associated with the analyzer. + * + * @param timer The callback function to execute when the timer + * fires. + * + * @param t The absolute time when the timer will fire. + * + * @param do_expire If true, the timer will also fire when Bro + * terminates even if \a t has not been reache yet. + * + * @param type The timer's type. + */ + void AddTimer(analyzer_timer_func timer, double t, int do_expire, + TimerType type); + + /** + * Cancels all timers added previously via AddTimer(). + */ + void CancelTimers(); + + /** + * Removes a given timer. This is an internal method and shouldn't be + * used by derived class. It does not cancel the timer. + */ + void RemoveTimer(Timer* t); + + /** + * Returnsn true if the analyzer has associated an SupportAnalyzer of a given type. + * + * @param tag The type to check for. + * + * @param orig True if asking about the originator side. + */ + bool HasSupportAnalyzer(Tag tag, bool orig); + + /** + * Adds a a new child analyzer with the option whether to intialize + * it. This is an internal method. + * + * @param analyzer The analyzer to add. Takes ownership. + * + * @param init If true, Init() will be calle.d + */ + void AddChildAnalyzer(Analyzer* analyzer, bool init); + + /** + * Inits all child analyzers. This is an internal method. + */ + void InitChildren(); + + /** + * Reorganizes the child data structure. This is an internal method. + */ + void AppendNewChildren(); + +private: + // Internal method to eventually delete a child analyzer that's + // already Done(). + void DeleteChild(analyzer_list::iterator i); + + // Helper for the ctors. + void CtorInit(const Tag& tag, Connection* conn); + + Tag tag; + ID 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 ID id_counter; +}; + +/** + * Convenience macro to add a new timer. + */ +#define ADD_ANALYZER_TIMER(timer, t, do_expire, type) \ + AddTimer(analyzer::analyzer_timer_func(timer), (t), (do_expire), (type)) + +/** + * Internal convenience macro to iterate over the list of child analyzers. + */ +#define LOOP_OVER_CHILDREN(var) \ + for ( analyzer::analyzer_list::iterator var = children.begin(); \ + var != children.end(); var++ ) + +/** + * Internal convenience macro to iterate over the constant list of child + * analyzers. + */ +#define LOOP_OVER_CONST_CHILDREN(var) \ + for ( analyzer::analyzer_list::const_iterator var = children.begin(); \ + var != children.end(); var++ ) + +/** + * Convenience macro to iterate over a given list of child analyzers. + */ +#define LOOP_OVER_GIVEN_CHILDREN(var, the_kids) \ + for ( analyzer::analyzer_list::iterator var = the_kids.begin(); \ + var != the_kids.end(); var++ ) + +/** + * Convenience macro to iterate over a given constant list of child + * analyzers. + */ +#define LOOP_OVER_GIVEN_CONST_CHILDREN(var, the_kids) \ + for ( analyzer::analyzer_list::const_iterator var = the_kids.begin(); \ + var != the_kids.end(); var++ ) + +/** + * Support analyzer preprocess input before it reaches an analyzer's main + * processing. They share the input interface with of an Analyzer but they + * are uni-directional: they receive data only from one side of a connection. + * + */ +class SupportAnalyzer : public Analyzer { +public: + /** + * Constructor. + * + * @param name A name for the protocol the analyzer is parsing. The + * name must match the one the corresponding Component registers. + * + * @param conn The connection the analyzer is associated with. + * + * @param arg_orig: If true, this is a support analyzer for the + * connection originator side, and otherwise for the responder side. + */ + SupportAnalyzer(const char* name, Connection* conn, bool arg_orig) + : Analyzer(name, conn) { orig = arg_orig; sibling = 0; } + + /** + * Destructor. + */ + virtual ~SupportAnalyzer() {} + + /** + * Returns true if this is a support analyzer for the connection's + * originator side. + */ + bool IsOrig() const { return orig; } + + /** + * Passes packet input to the next sibling SupportAnalyzer if any, or + * on to the associated main analyzer if none. If however there's an + * output handler associated with this support analyzer, the data is + * passed only to there. + * + * Parameters same as for Analyzer::ForwardPacket. + */ + virtual void ForwardPacket(int len, const u_char* data, bool orig, + int seq, const IP_Hdr* ip, int caplen); + + /** + * Passes stream input to the next sibling SupportAnalyzer if any, or + * on to the associated main analyzer if none. If however there's an + * output handler associated with this support analyzer, the data is + * passed only to there. + * + * Parameters same as for Analyzer::ForwardStream. + */ + virtual void ForwardStream(int len, const u_char* data, bool orig); + + /** + * Passes gap information to the next sibling SupportAnalyzer if any, + * or on to the associated main analyzer if none. If however there's + * an output handler associated with this support analyzer, the gap is + * passed only to there. + * + * Parameters same as for Analyzer::ForwardPacket. + */ + virtual void ForwardUndelivered(int seq, int len, bool orig); + + /** + * Returns the analyzer next sibling, or null if none. + */ + SupportAnalyzer* Sibling() const { return sibling; } + +protected: + friend class Analyzer; + +private: + bool orig; + + // Points to next support analyzer in chain. The list is managed by + // parent analyzer. + SupportAnalyzer* sibling; +}; + +// The following need to be consistent with bro.init. +#define CONTENTS_NONE 0 +#define CONTENTS_ORIG 1 +#define CONTENTS_RESP 2 +#define CONTENTS_BOTH 3 + +/** + * Base class for analyzers parsing transport-layer protocols. + */ +class TransportLayerAnalyzer : public Analyzer { +public: + /** + * Constructor. + * + * @param name A name for the protocol the analyzer is parsing. The + * name must match the one the corresponding Component registers. + * + * @param conn The connection the analyzer is associated with. + */ + TransportLayerAnalyzer(const char* name, Connection* conn) + : Analyzer(name, conn) { pia = 0; } + + /** + * Overridden from parent class. + */ + virtual void Done(); + + /** + * Returns true if the analyzer determines that in fact a new + * connection has started without the connection statement having + * terminated the previous one, i.e., the new data is arriving at + * what's the analyzer for the previous instance. This is used only + * for TCP. + */ + virtual bool IsReuse(double t, const u_char* pkt) = 0; + + /** + * Associates a file with the analyzer in which to record all + * analyzed input. This must only be called with derived classes that + * overide the method; the default implementation will abort. + * + * @param direction One of the CONTENTS_* constants indicating which + * direction of the input stream is to be recorded. + * + * @param f The file to record to. + * + */ + virtual void SetContentsFile(unsigned int direction, BroFile* f); + + /** + * Returns an associated contents file, if any. This must only be + * called with derived classes that overide the method; the default + * implementation will abort. + * + * @param direction One of the CONTENTS_* constants indicating which + * direction the query is for. + */ + virtual BroFile* GetContentsFile(unsigned int direction) const; + + /** + * Associates a PIA with this analyzer. A PIA takes the + * transport-layer input and determine which protocol analyzer(s) to + * use for parsing it. + */ + void SetPIA(pia::PIA* arg_PIA) { pia = arg_PIA; } + + /** + * Returns the associated PIA, or null of none. Does not take + * ownership. + */ + pia::PIA* GetPIA() const { return pia; } + + /** + * Helper to raise a \c packet_contents event. + * + * @param data The dass to pass to the event. + * + * @param len The length of \a data. + */ + void PacketContents(const u_char* data, int len); + +private: + pia::PIA* pia; +}; + +} + +#endif diff --git a/src/analyzer/CMakeLists.txt b/src/analyzer/CMakeLists.txt new file mode 100644 index 0000000000..20b53d7ca8 --- /dev/null +++ b/src/analyzer/CMakeLists.txt @@ -0,0 +1,22 @@ + +include(BroSubdir) + +include_directories(BEFORE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +add_subdirectory(protocol) + +set(analyzer_SRCS + Analyzer.cc + Manager.cc + Component.cc + Tag.cc +) + +bif_target(analyzer.bif) + +bro_add_subdir_library(analyzer ${analyzer_SRCS} ${BIF_OUTPUT_CC}) +add_dependencies(bro_analyzer generate_outputs) + diff --git a/src/analyzer/Component.cc b/src/analyzer/Component.cc new file mode 100644 index 0000000000..5844da848f --- /dev/null +++ b/src/analyzer/Component.cc @@ -0,0 +1,90 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Component.h" +#include "Manager.h" + +#include "../Desc.h" + +using namespace analyzer; + +Tag::type_t Component::type_counter = 0; + +static const char* canonify_name(const char* name) + { + unsigned int len = strlen(name); + char* nname = new char[len + 1]; + + for ( unsigned int i = 0; i < len; i++ ) + { + char c = isalnum(name[i]) ? name[i] : '_'; + nname[i] = toupper(c); + } + + nname[len] = '\0'; + return nname; + } + +Component::Component(const char* arg_name, factory_callback arg_factory, Tag::subtype_t arg_subtype, bool arg_enabled, bool arg_partial) + : plugin::Component(plugin::component::ANALYZER) + { + name = copy_string(arg_name); + canon_name = canonify_name(arg_name); + factory = arg_factory; + enabled = arg_enabled; + partial = arg_partial; + + tag = analyzer::Tag(++type_counter, arg_subtype); + } + +Component::Component(const Component& other) + : plugin::Component(Type()) + { + name = copy_string(other.name); + canon_name = copy_string(other.canon_name); + factory = other.factory; + enabled = other.enabled; + partial = other.partial; + tag = other.tag; + } + +Component::~Component() + { + delete [] name; + delete [] canon_name; + } + +analyzer::Tag Component::Tag() const + { + return tag; + } + +void Component::Describe(ODesc* d) + { + plugin::Component::Describe(d); + d->Add(name); + d->Add(" ("); + + if ( factory ) + { + d->Add("ANALYZER_"); + d->Add(canon_name); + d->Add(", "); + } + + d->Add(enabled ? "enabled" : "disabled"); + d->Add(")"); + } + +Component& Component::operator=(const Component& other) + { + if ( &other != this ) + { + name = copy_string(other.name); + factory = other.factory; + enabled = other.enabled; + partial = other.partial; + tag = other.tag; + } + + return *this; + } diff --git a/src/analyzer/Component.h b/src/analyzer/Component.h new file mode 100644 index 0000000000..b766c2fe82 --- /dev/null +++ b/src/analyzer/Component.h @@ -0,0 +1,141 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef ANALYZER_PLUGIN_COMPONENT_H +#define ANALYZER_PLUGIN_COMPONENT_H + +#include "Tag.h" +#include "plugin/Component.h" + +#include "../config.h" +#include "../util.h" + +class Connection; + +namespace analyzer { + +class Analyzer; + +/** + * Component description for plugins providing analyzers. + * + * A plugin can provide a specific protocol analyzer by registering this + * analyzer component, describing the analyzer. + */ +class Component : public plugin::Component { +public: + typedef bool (*available_callback)(); + typedef Analyzer* (*factory_callback)(Connection* conn); + + /** + * Constructor. + * + * @param name The name of the provided analyzer. This name is used + * across the system to identify the analyzer, e.g., when calling + * analyzer::Manager::InstantiateAnalyzer with a name. + * + * @param factory A factory function to instantiate instances of the + * analyzer's class, which must be derived directly or indirectly + * from analyzer::Analyzer. This is typically a static \c + * Instatiate() method inside the class that just allocates and + * returns a new instance. + * + * @param subtype A subtype associated with this component that + * further distinguishes it. The subtype will be integrated into + * the analyzer::Tag that the manager associates with this analyzer, + * and analyzer instances can accordingly access it via analyzer::Tag(). + * If not used, leave at zero. + * + * @param enabled If false the analyzer starts out as disabled and + * hence won't be used. It can still be enabled later via the + * manager, including from script-land. + * + * @param partial If true, the analyzer can deal with payload from + * partial connections, i.e., when Bro enters the stream mid-way + * after not seeing the beginning. Note that handling of partial + * connections has generally not seen much testing yet as virtually + * no existing analyzer supports it. + */ + Component(const char* name, factory_callback factory, Tag::subtype_t subtype = 0, bool enabled = true, bool partial = false); + + /** + * Copy constructor. + */ + Component(const Component& other); + + /** + * Destructor. + */ + ~Component(); + + /** + * Returns the name of the analyzer. This name is unique across all + * analyzers and used to identify it. The returned name is derived + * from what's passed to the constructor but upper-cased and + * canonified to allow being part of a script-level ID. + */ + const char* Name() const { return name; } + + /** + * Returns a canonocalized version of the analyzer's name. The + * returned name is derived from what's passed to the constructor but + * upper-cased and transformed to allow being part of a script-level + * ID. + */ + const char* CanonicalName() const { return canon_name; } + + /** + * Returns the analyzer's factory function. + */ + factory_callback Factory() const { return factory; } + + /** + * Returns whether the analyzer supports partial connections. Partial + * connections are those where Bro starts processing payload + * mid-stream, after missing the beginning. + */ + bool Partial() const { return partial; } + + /** + * Returns true if the analyzer is currently enabled and hence + * available for use. + */ + bool Enabled() const { return enabled; } + + /** + * Returns the analyzer's tag. Note that this is automatically + * generated for each new Components, and hence unique across all of + * them. + */ + analyzer::Tag Tag() const; + + /** + * Enables or disables this analyzer. + * + * @param arg_enabled True to enabled, false to disable. + * + */ + void SetEnabled(bool arg_enabled) { enabled = arg_enabled; } + + /** + * Generates a human-readable description of the component's main + * parameters. This goes into the output of \c "bro -NN". + */ + virtual void Describe(ODesc* d); + + Component& operator=(const Component& other); + +private: + const char* name; // The analyzer's name. + const char* canon_name; // The analyzer's canonical name. + factory_callback factory; // The analyzer's factory callback. + bool partial; // True if the analyzer supports partial connections. + analyzer::Tag tag; // The automatically assigned analyzer tag. + bool enabled; // True if the analyzer is enabled. + + // Global counter used to generate unique tags. + static analyzer::Tag::type_t type_counter; +}; + +} + +#endif diff --git a/src/analyzer/Manager.cc b/src/analyzer/Manager.cc new file mode 100644 index 0000000000..5695dec625 --- /dev/null +++ b/src/analyzer/Manager.cc @@ -0,0 +1,697 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Manager.h" + +#include "Hash.h" +#include "Val.h" + +#include "protocol/backdoor/BackDoor.h" +#include "protocol/conn-size/ConnSize.h" +#include "protocol/icmp/ICMP.h" +#include "protocol/interconn/InterConn.h" +#include "protocol/pia/PIA.h" +#include "protocol/stepping-stone/SteppingStone.h" +#include "protocol/tcp/TCP.h" +#include "protocol/udp/UDP.h" + +#include "plugin/Manager.h" + +#include "protocol/tcp/events.bif.h" + +using namespace analyzer; + +Manager::ConnIndex::ConnIndex(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; + } + +Manager::ConnIndex::ConnIndex() + { + orig = resp = IPAddr("0.0.0.0"); + resp_p = 0; + proto = 0; + } + +bool Manager::ConnIndex::operator<(const ConnIndex& other) const + { + if ( orig != other.orig ) + return orig < other.orig; + + if ( resp != other.resp ) + return resp < other.resp; + + if ( proto != other.proto ) + return proto < other.proto; + + if ( resp_p != other.resp_p ) + return resp_p < other.resp_p; + + return false; + } + +Manager::Manager() + { + tag_enum_type = new EnumType("Analyzer::Tag"); + ::ID* id = install_ID("Tag", "Analyzer", true, true); + add_type(id, tag_enum_type, 0, 0); + } + +Manager::~Manager() + { + for ( analyzer_map_by_port::const_iterator i = analyzers_by_port_tcp.begin(); i != analyzers_by_port_tcp.end(); i++ ) + delete i->second; + + for ( analyzer_map_by_port::const_iterator i = analyzers_by_port_udp.begin(); i != analyzers_by_port_udp.end(); i++ ) + delete i->second; + + analyzers_by_port_udp.clear(); + analyzers_by_port_tcp.clear(); + + // Clean up expected-connection table. + while ( conns_by_timeout.size() ) + { + ScheduledAnalyzer* a = conns_by_timeout.top(); + conns_by_timeout.pop(); + delete a; + } + } + +void Manager::InitPreScript() + { + std::list analyzers = plugin_mgr->Components(); + + for ( std::list::const_iterator i = analyzers.begin(); i != analyzers.end(); i++ ) + RegisterAnalyzerComponent(*i); + + // Cache these tags. + analyzer_backdoor = GetAnalyzerTag("BACKDOOR"); + analyzer_connsize = GetAnalyzerTag("CONNSIZE"); + analyzer_interconn = GetAnalyzerTag("INTERCONN"); + analyzer_stepping = GetAnalyzerTag("STEPPINGSTONE"); + analyzer_tcpstats = GetAnalyzerTag("TCPSTATS"); + } + +void Manager::InitPostScript() + { + #include "analyzer.bif.init.cc" + } + +void Manager::DumpDebug() + { +#ifdef DEBUG + DBG_LOG(DBG_ANALYZER, "Available analyzers after bro_init():"); + for ( analyzer_map_by_name::const_iterator i = analyzers_by_name.begin(); i != analyzers_by_name.end(); i++ ) + DBG_LOG(DBG_ANALYZER, " %s (%s)", i->second->Name(), IsEnabled(i->second->Tag()) ? "enabled" : "disabled"); + + DBG_LOG(DBG_ANALYZER, ""); + DBG_LOG(DBG_ANALYZER, "Analyzers by port:"); + + for ( analyzer_map_by_port::const_iterator i = analyzers_by_port_tcp.begin(); i != analyzers_by_port_tcp.end(); i++ ) + { + string s; + + for ( tag_set::const_iterator j = i->second->begin(); j != i->second->end(); j++ ) + s += string(GetAnalyzerName(*j)) + " "; + + DBG_LOG(DBG_ANALYZER, " %d/tcp: %s", i->first, s.c_str()); + } + + for ( analyzer_map_by_port::const_iterator i = analyzers_by_port_udp.begin(); i != analyzers_by_port_udp.end(); i++ ) + { + string s; + + for ( tag_set::const_iterator j = i->second->begin(); j != i->second->end(); j++ ) + s += string(GetAnalyzerName(*j)) + " "; + + DBG_LOG(DBG_ANALYZER, " %d/udp: %s", i->first, s.c_str()); + } + +#endif + } + +void Manager::Done() + { + } + +void Manager::RegisterAnalyzerComponent(Component* component) + { + const char* cname = component->CanonicalName(); + + if ( Lookup(cname) ) + reporter->FatalError("Analyzer %s defined more than once", cname); + + DBG_LOG(DBG_ANALYZER, "Registering analyzer %s (tag %s)", + component->Name(), component->Tag().AsString().c_str()); + + analyzers_by_name.insert(std::make_pair(cname, component)); + analyzers_by_tag.insert(std::make_pair(component->Tag(), component)); + analyzers_by_val.insert(std::make_pair(component->Tag().AsEnumVal()->InternalInt(), component)); + + // Install enum "Analyzer::ANALYZER_*" + string id = fmt("ANALYZER_%s", cname); + tag_enum_type->AddName("Analyzer", id.c_str(), component->Tag().AsEnumVal()->InternalInt(), true); + } + +bool Manager::EnableAnalyzer(Tag tag) + { + Component* p = Lookup(tag); + + if ( ! p ) + return false; + + DBG_LOG(DBG_ANALYZER, "Enabling analyzer %s", p->Name()); + p->SetEnabled(true); + + return true; + } + +bool Manager::EnableAnalyzer(EnumVal* val) + { + Component* p = Lookup(val); + + if ( ! p ) + return false; + + DBG_LOG(DBG_ANALYZER, "Enabling analyzer %s", p->Name()); + p->SetEnabled(true); + + return true; + } + +bool Manager::DisableAnalyzer(Tag tag) + { + Component* p = Lookup(tag); + + if ( ! p ) + return false; + + DBG_LOG(DBG_ANALYZER, "Disabling analyzer %s", p->Name()); + p->SetEnabled(false); + + return true; + } + +bool Manager::DisableAnalyzer(EnumVal* val) + { + Component* p = Lookup(val); + + if ( ! p ) + return false; + + DBG_LOG(DBG_ANALYZER, "Disabling analyzer %s", p->Name()); + p->SetEnabled(false); + + return true; + } + +void Manager::DisableAllAnalyzers() + { + DBG_LOG(DBG_ANALYZER, "Disabling all analyzers"); + + for ( analyzer_map_by_tag::const_iterator i = analyzers_by_tag.begin(); i != analyzers_by_tag.end(); i++ ) + i->second->SetEnabled(false); + } + +bool Manager::IsEnabled(Tag tag) + { + if ( ! tag ) + return false; + + Component* p = Lookup(tag); + + if ( ! p ) + return false; + + return p->Enabled(); + } + +bool Manager::IsEnabled(EnumVal* val) + { + Component* p = Lookup(val); + + if ( ! p ) + return false; + + return p->Enabled(); + } + + +bool Manager::RegisterAnalyzerForPort(EnumVal* val, PortVal* port) + { + Component* p = Lookup(val); + + if ( ! p ) + return false; + + return RegisterAnalyzerForPort(p->Tag(), port->PortType(), port->Port()); + } + +bool Manager::UnregisterAnalyzerForPort(EnumVal* val, PortVal* port) + { + Component* p = Lookup(val); + + if ( ! p ) + return false; + + return UnregisterAnalyzerForPort(p->Tag(), port->PortType(), port->Port()); + } + +bool Manager::RegisterAnalyzerForPort(Tag tag, TransportProto proto, uint32 port) + { + tag_set* l = LookupPort(proto, port, true); + +#ifdef DEBUG + const char* name = GetAnalyzerName(tag); + DBG_LOG(DBG_ANALYZER, "Registering analyzer %s for port %" PRIu32 "/%d", name, port, proto); +#endif + + l->insert(tag); + return true; + } + +bool Manager::UnregisterAnalyzerForPort(Tag tag, TransportProto proto, uint32 port) + { + tag_set* l = LookupPort(proto, port, true); + +#ifdef DEBUG + const char* name = GetAnalyzerName(tag); + DBG_LOG(DBG_ANALYZER, "Unregistering analyzer %s for port %" PRIu32 "/%d", name, port, proto); +#endif + + l->erase(tag); + return true; + } + +Analyzer* Manager::InstantiateAnalyzer(Tag tag, Connection* conn) + { + Component* c = Lookup(tag); + + if ( ! c ) + reporter->InternalError("request to instantiate unknown analyzer"); + + if ( ! c->Enabled() ) + return 0; + + if ( ! c->Factory() ) + reporter->InternalError("analyzer %s cannot be instantiated dynamically", GetAnalyzerName(tag)); + + Analyzer* a = c->Factory()(conn); + + if ( ! a ) + reporter->InternalError("analyzer instantiation failed"); + + a->SetAnalyzerTag(tag); + + return a; + } + +Analyzer* Manager::InstantiateAnalyzer(const char* name, Connection* conn) + { + Tag tag = GetAnalyzerTag(name); + return tag ? InstantiateAnalyzer(tag, conn) : 0; + } + +const char* Manager::GetAnalyzerName(Tag tag) + { + static const char* error = ""; + + if ( ! tag ) + return error; + + Component* c = Lookup(tag); + + if ( ! c ) + reporter->InternalError("request for name of unknown analyzer tag %s", tag.AsString().c_str()); + + return c->CanonicalName(); + } + +const char* Manager::GetAnalyzerName(Val* val) + { + return GetAnalyzerName(Tag(val->AsEnumVal())); + } + +Tag Manager::GetAnalyzerTag(const char* name) + { + Component* c = Lookup(name); + return c ? c->Tag() : Tag(); + } + +EnumType* Manager::GetTagEnumType() + { + return tag_enum_type; + } + +Component* Manager::Lookup(const char* name) + { + analyzer_map_by_name::const_iterator i = analyzers_by_name.find(to_upper(name)); + return i != analyzers_by_name.end() ? i->second : 0; + } + +Component* Manager::Lookup(const Tag& tag) + { + analyzer_map_by_tag::const_iterator i = analyzers_by_tag.find(tag); + return i != analyzers_by_tag.end() ? i->second : 0; + } + +Component* Manager::Lookup(EnumVal* val) + { + analyzer_map_by_val::const_iterator i = analyzers_by_val.find(val->InternalInt()); + return i != analyzers_by_val.end() ? i->second : 0; + } + +Manager::tag_set* Manager::LookupPort(TransportProto proto, uint32 port, bool add_if_not_found) + { + analyzer_map_by_port* m = 0; + + switch ( proto ) { + case TRANSPORT_TCP: + m = &analyzers_by_port_tcp; + break; + + case TRANSPORT_UDP: + m = &analyzers_by_port_udp; + break; + + default: + reporter->InternalError("unsupport transport protocol in analyzer::Manager::LookupPort"); + } + + analyzer_map_by_port::const_iterator i = m->find(port); + + if ( i != m->end() ) + return i->second; + + if ( ! add_if_not_found ) + return 0; + + tag_set* l = new tag_set; + m->insert(std::make_pair(port, l)); + return l; + } + +Manager::tag_set* Manager::LookupPort(PortVal* val, bool add_if_not_found) + { + return LookupPort(val->PortType(), val->Port(), add_if_not_found); + } + +bool Manager::BuildInitialAnalyzerTree(Connection* conn) + { + Analyzer* analyzer = 0; + tcp::TCP_Analyzer* tcp = 0; + udp::UDP_Analyzer* udp = 0; + icmp::ICMP_Analyzer* icmp = 0; + TransportLayerAnalyzer* root = 0; + tag_set expected; + pia::PIA* pia = 0; + bool analyzed = false; + bool check_port = false; + + switch ( conn->ConnTransport() ) { + + case TRANSPORT_TCP: + root = tcp = new tcp::TCP_Analyzer(conn); + pia = new pia::PIA_TCP(conn); + expected = GetScheduled(conn); + check_port = true; + DBG_ANALYZER(conn, "activated TCP analyzer"); + break; + + case TRANSPORT_UDP: + root = udp = new udp::UDP_Analyzer(conn); + pia = new pia::PIA_UDP(conn); + expected = GetScheduled(conn); + check_port = true; + DBG_ANALYZER(conn, "activated UDP analyzer"); + break; + + case TRANSPORT_ICMP: { + root = icmp = new icmp::ICMP_Analyzer(conn); + DBG_ANALYZER(conn, "activated ICMP analyzer"); + analyzed = true; + break; + } + + default: + reporter->InternalError("unknown protocol"); + } + + if ( ! root ) + { + DBG_ANALYZER(conn, "cannot build analyzer tree"); + return false; + } + + // Any scheduled analyzer? + for ( tag_set::iterator i = expected.begin(); i != expected.end(); i++ ) + { + Analyzer* analyzer = analyzer_mgr->InstantiateAnalyzer(*i, conn); + + if ( analyzer ) + { + root->AddChildAnalyzer(analyzer, false); + + DBG_ANALYZER_ARGS(conn, "activated %s analyzer as scheduled", + analyzer_mgr->GetAnalyzerName(*i)); + } + + } + + // Hmm... Do we want *just* the expected analyzer, or all + // other potential analyzers as well? For now we only take + // the scheduled ones. + if ( expected.size() == 0 ) + { // Let's see if it's a port we know. + if ( check_port && ! dpd_ignore_ports ) + { + int resp_port = ntohs(conn->RespPort()); + tag_set* ports = LookupPort(conn->ConnTransport(), resp_port, false); + + if ( ports ) + { + for ( tag_set::const_iterator j = ports->begin(); j != ports->end(); ++j ) + { + Analyzer* analyzer = analyzer_mgr->InstantiateAnalyzer(*j, conn); + + if ( ! analyzer ) + continue; + + root->AddChildAnalyzer(analyzer, false); + DBG_ANALYZER_ARGS(conn, "activated %s analyzer due to port %d", + analyzer_mgr->GetAnalyzerName(*j), resp_port); + } + } + } + } + + 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(); + + if ( IsEnabled(analyzer_backdoor) ) + // Add a BackDoor analyzer if requested. This analyzer + // can handle both reassembled and non-reassembled input. + tcp->AddChildAnalyzer(new backdoor::BackDoor_Analyzer(conn), false); + + if ( IsEnabled(analyzer_interconn) ) + // Add a InterConn analyzer if requested. This analyzer + // can handle both reassembled and non-reassembled input. + tcp->AddChildAnalyzer(new interconn::InterConn_Analyzer(conn), false); + + if ( IsEnabled(analyzer_stepping) ) + { + // 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 ( resp_port == 22 || resp_port == 23 || resp_port == 513 ) + { + AddrVal src(conn->OrigAddr()); + if ( ! stp_skip_src->Lookup(&src) ) + tcp->AddChildAnalyzer(new stepping_stone::SteppingStone_Analyzer(conn), false); + } + } + + if ( IsEnabled(analyzer_tcpstats) ) + // Add TCPStats analyzer. This needs to see packets so + // we cannot add it as a normal child. + tcp->AddChildPacketAnalyzer(new tcp::TCPStats_Analyzer(conn)); + + if ( IsEnabled(analyzer_connsize) ) + // Add ConnSize analyzer. Needs to see packets, not stream. + tcp->AddChildPacketAnalyzer(new conn_size::ConnSize_Analyzer(conn)); + } + + else + { + if ( IsEnabled(analyzer_connsize) ) + // Add ConnSize analyzer. Needs to see packets, not stream. + root->AddChildAnalyzer(new conn_size::ConnSize_Analyzer(conn)); + } + + if ( pia ) + root->AddChildAnalyzer(pia->AsAnalyzer()); + + if ( root->GetChildren().size() ) + analyzed = true; + + conn->SetRootAnalyzer(root, pia); + root->Init(); + root->InitChildren(); + + if ( ! analyzed ) + conn->SetLifetime(non_analyzed_lifetime); + + for ( tag_set::iterator i = expected.begin(); i != expected.end(); i++ ) + { + EnumVal* tag = i->AsEnumVal(); + Ref(tag); + conn->Event(scheduled_analyzer_applied, 0, tag); + } + + return true; + } + +void Manager::ExpireScheduledAnalyzers() + { + if ( ! network_time ) + return; + + while ( conns_by_timeout.size() ) + { + ScheduledAnalyzer* a = conns_by_timeout.top(); + + if ( a->timeout > network_time ) + return; + + conns_by_timeout.pop(); + + std::pair all = conns.equal_range(a->conn); + + bool found = false; + + for ( conns_map::iterator i = all.first; i != all.second; i++ ) + { + if ( i->second != a ) + continue; + + conns.erase(i); + + DBG_LOG(DBG_ANALYZER, "Expiring expected analyzer %s for connection %s", + analyzer_mgr->GetAnalyzerName(a->analyzer), + fmt_conn_id(a->conn.orig, 0, a->conn.resp, a->conn.resp_p)); + + delete a; + found = true; + break; + } + + assert(found); + } + } + +void Manager::ScheduleAnalyzer(const IPAddr& orig, const IPAddr& resp, + uint16 resp_p, + TransportProto proto, Tag analyzer, + double timeout) + { + if ( ! network_time ) + { + reporter->Warning("cannot schedule analyzers before processing begins; ignored"); + return; + } + + assert(timeout); + + // Use the chance to see if the oldest entry is already expired. + ExpireScheduledAnalyzers(); + + ScheduledAnalyzer* a = new ScheduledAnalyzer; + a->conn = ConnIndex(orig, resp, resp_p, proto); + a->analyzer = analyzer; + a->timeout = network_time + timeout; + + conns.insert(std::make_pair(a->conn, a)); + conns_by_timeout.push(a); + } + +void Manager::ScheduleAnalyzer(const IPAddr& orig, const IPAddr& resp, + uint16 resp_p, + TransportProto proto, const char* analyzer, + double timeout) + { + Tag tag = GetAnalyzerTag(analyzer); + + if ( tag != Tag() ) + ScheduleAnalyzer(orig, resp, resp_p, proto, tag, timeout); + } + +void Manager::ScheduleAnalyzer(const IPAddr& orig, const IPAddr& resp, PortVal* resp_p, + Val* analyzer, double timeout) + { + EnumVal* ev = analyzer->AsEnumVal(); + return ScheduleAnalyzer(orig, resp, resp_p->Port(), resp_p->PortType(), Tag(ev), timeout); + } + +Manager::tag_set Manager::GetScheduled(const Connection* conn) + { + ConnIndex c(conn->OrigAddr(), conn->RespAddr(), + ntohs(conn->RespPort()), conn->ConnTransport()); + + std::pair all = conns.equal_range(c); + + tag_set result; + + for ( conns_map::iterator i = all.first; i != all.second; i++ ) + result.insert(i->second->analyzer); + + // Try wildcard for originator. + c.orig = IPAddr(string("::")); + all = conns.equal_range(c); + + for ( conns_map::iterator i = all.first; i != all.second; i++ ) + { + if ( i->second->timeout > network_time ) + result.insert(i->second->analyzer); + } + + // We don't delete scheduled analyzers here. They will be expired + // eventually. + return result; + } diff --git a/src/analyzer/Manager.h b/src/analyzer/Manager.h new file mode 100644 index 0000000000..efae629971 --- /dev/null +++ b/src/analyzer/Manager.h @@ -0,0 +1,443 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +/** + * The central management unit for registering and instantiating analyzers. + * + * For each protocol that Bro supports, there's one class derived from + * analyzer::Analyzer. Once we have decided that a connection's payload is to + * be parsed as a given protocol, we instantiate the corresponding + * analyzer-derived class and add the new instance as a child node into the + * connection's analyzer tree. + * + * In addition to the analyzer-derived class itself, for each protocol + * there's also "meta-class" derived from analyzer::Component that describes + * the analyzer, including status information on if that particular protocol + * analysis is currently enabled. + * + * To identify an analyzer (or to be precise: a component), the manager + * maintains mappings of (1) analyzer::Tag to component, and (2) + * human-readable analyzer name to component. + */ +#ifndef ANALYZER_MANAGER_H +#define ANALYZER_MANAGER_H + +#include + +#include "Analyzer.h" +#include "Component.h" +#include "Tag.h" + +#include "../Dict.h" +#include "../net_util.h" +#include "../IP.h" + +#include "analyzer/analyzer.bif.h" + +namespace analyzer { + +/** + * Class maintaining and scheduling available protocol analyzers. + * + * The manager maintains a registry of all available protocol analyzers, + * including a mapping between their textual names and analyzer::Tag. It + * instantantiates new analyzers on demand. For new connections, the manager + * sets up their initial analyzer tree, including adding the right \c PIA, + * respecting well-known ports, and tracking any analyzers specifically + * scheduled for individidual connections. + * + * Note that we keep the public interface of this class free of std::* + * classes. This allows to external analyzer code to potentially use a + * different C++ standard library. + */ +class Manager { +public: + /** + * Constructor. + */ + Manager(); + + /** + * Destructor. + */ + ~Manager(); + + /** + * First-stage initializion of the manager. This is called early on + * during Bro's initialization, before any scripts are processed. + */ + void InitPreScript(); + + /** + * Second-stage initialization of the manager. This is called late + * during Bro's initialization after any scripts are processed. + */ + void InitPostScript(); + + /** + * Finished the manager's operations. + */ + void Done(); + + /** + * Dumps out the state of all registered analyzers to the \c analyzer + * debug stream. Should be called only after any \c bro_init events + * have executed to ensure that any of their changes are applied. + */ + void DumpDebug(); // Called after bro_init() events. + + /** + * Enables an analyzer type. Only enabled analyzers will be + * instantiated for new connections. + * + * @param tag The analyzer's tag. + * + * @return True if successful. + */ + bool EnableAnalyzer(Tag tag); + + /** + * Enables an analyzer type. Only enabled analyzers will be + * instantiated for new connections. + * + * @param tag The analyzer's tag as an enum of script type \c + * Analyzer::Tag. + * + * @return True if successful. + */ + bool EnableAnalyzer(EnumVal* tag); + + /** + * Enables an analyzer type. Disabled analyzers will not be + * instantiated for new connections. + * + * @param tag The analyzer's tag. + * + * @return True if successful. + */ + bool DisableAnalyzer(Tag tag); + + /** + * Enables an analyzer type. Disabled analyzers will not be + * instantiated for new connections. + * + * @param tag The analyzer's tag as an enum of script type \c + * Analyzer::Tag. + * + * @return True if successful. + */ + bool DisableAnalyzer(EnumVal* tag); + + /** + * Disables all currently registered analyzers. + */ + void DisableAllAnalyzers(); + + /** + * Returns true if an analyzer is enabled. + * + * @param tag The analyzer's tag. + */ + bool IsEnabled(Tag tag); + + /** + * Returns true if an analyzer is enabled. + * + * @param tag The analyzer's tag as an enum of script type \c + * Analyzer::Tag. + */ + bool IsEnabled(EnumVal* tag); + + /** + * Registers a well-known port for an analyzer. Once registered, + * connection on that port will start with a corresponding analyzer + * assigned. + * + * @param tag The analyzer's tag as an enum of script type \c + * Analyzer::Tag. + * + * @param port The well-known port. + * + * @return True if successful. + */ + bool RegisterAnalyzerForPort(EnumVal* tag, PortVal* port); + + /** + * Registers a well-known port for an analyzer. Once registered, + * connection on that port will start with a corresponding analyzer + * assigned. + * + * @param tag The analyzer's tag. + * + * @param proto The port's protocol. + * + * @param port The port's number. + * + * @return True if successful. + */ + bool RegisterAnalyzerForPort(Tag tag, TransportProto proto, uint32 port); + + /** + * Unregisters a well-known port for an anlyzers. + * + * @param tag The analyzer's tag as an enum of script type \c + * Analyzer::Tag. + * + * @param port The well-known port. + * + * @return True if successful (incl. when the port wasn't actually + * registered for the analyzer). + * + */ + bool UnregisterAnalyzerForPort(EnumVal* tag, PortVal* port); + + /** + * Unregisters a well-known port for an anlyzers. + * + * @param tag The analyzer's tag. + * + * @param proto The port's protocol. + * + * @param port The port's number. + * + * @param tag The analyzer's tag as an enum of script type \c + * Analyzer::Tag. + */ + bool UnregisterAnalyzerForPort(Tag tag, TransportProto proto, uint32 port); + + /** + * Instantiates a new analyzer instance for a connection. + * + * @param tag The analyzer's tag. + * + * @param conn The connection the analyzer is to be associated with. + * + * @return The new analyzer instance. Note that the analyzer will not + * have been added to the connection's analyzer tree yet. Returns + * null if tag is invalid or the requested analyzer is disabled. + */ + Analyzer* InstantiateAnalyzer(Tag tag, Connection* c); + + /** + * Instantiates a new analyzer instance for a connection. + * + * @param name The name of the analyzer. + * + * @param conn The connection the analyzer is to be associated with. + * + * @return The new analyzer instance. Note that the analyzer will not + * have been added to the connection's analyzer tree yet. Returns + * null if the name is not known or if the requested analyzer that is + * disabled. + */ + Analyzer* InstantiateAnalyzer(const char* name, Connection* c); + + /** + * Translates an analyzer tag into corresponding analyzer name. + * + * @param tag The analyzer tag. + * + * @return The name, or an empty string if the tag is invalid. + */ + const char* GetAnalyzerName(Tag tag); + + /** + * Translates an script-level analyzer tag into corresponding + * analyzer name. + * + * @param val The analyzer tag as an script-level enum value of type + * \c Analyzer::Tag. + * + * @return The name, or an empty string if the tag is invalid. + */ + const char* GetAnalyzerName(Val* val); + + /** + * Translates an analyzer name into the corresponding tag. + * + * @param name The name. + * + * @return The tag. If the name does not correspond to a valid + * analyzer, the returned tag will evaluate to false. + */ + Tag GetAnalyzerTag(const char* name); + + /** + * Returns the enum type that corresponds to the script-level type \c + * Analyzer::Tag. + */ + EnumType* GetTagEnumType(); + + /** + * Given the first packet of a connection, builds its initial + * analyzer tree. + * + * @param conn The connection to add the initial set of analyzers to. + * + * @return False if the tree cannot be build; that's usually an + * internally error. + */ + bool BuildInitialAnalyzerTree(Connection* conn); + + /** + * Schedules a particular analyzer for an upcoming connection. Once + * the connection is seen, BuildInitAnalyzerTree() will add the + * specified analyzer to its tree. + * + * @param orig The connection's anticipated originator address. + * 0.0.0.0 can be used as a wildcard matching any originator. + * + * @param resp The connection's anticipated responder address (no + * wilcard). + * + * @param resp_p The connection's anticipated responder port. + * + * @param proto The connection's anticipated transport protocol. + * + * @param analyzer The analyzer to use once the connection is seen. + * + * @param timeout An interval after which to timeout the request to + * schedule this analyzer. Must be non-zero. + */ + void ScheduleAnalyzer(const IPAddr& orig, const IPAddr& resp, uint16 resp_p, + TransportProto proto, Tag analyzer, double timeout); + + /** + * Schedules a particular analyzer for an upcoming connection. Once + * the connection is seen, BuildInitAnalyzerTree() will add the + * specified analyzer to its tree. + * + * @param orig The connection's anticipated originator address. 0 can + * be used as a wildcard matching any originator. + * + * @param resp The The connection's anticipated responder address (no + * wilcard). + * + * @param resp_p The connection's anticipated responder port. + * + * @param proto The connection's anticipated transport protocol. + * + * @param analyzer The name of the analyzer to use once the + * connection is seen. + * + * @param timeout An interval after which to timeout the request to + * schedule this analyzer. Must be non-zero. + */ + void ScheduleAnalyzer(const IPAddr& orig, const IPAddr& resp, uint16 resp_p, + TransportProto proto, const char* analyzer, + double timeout); + + /** + * Schedules a particular analyzer for an upcoming connection. Once + * the connection is seen, BuildInitAnalyzerTree() will add the + * specified analyzer to its tree. + * + * @param orig The connection's anticipated originator address. 0 can + * be used as a wildcard matching any originator. + * + * @param resp The connection's anticipated responder address (no + * wilcard). + * + * @param resp_p The connection's anticipated responder port. + * + * @param analyzer The analyzer to use once the connection is seen as + * an enum value of script-type \c Analyzer::Tag. + * + * @param timeout An interval after which to timeout the request to + * schedule this analyzer. Must be non-zero. + */ + void ScheduleAnalyzer(const IPAddr& orig, const IPAddr& resp, PortVal* resp_p, + Val* analyzer, double timeout); + +private: + typedef set tag_set; + typedef map analyzer_map_by_name; + typedef map analyzer_map_by_tag; + typedef map analyzer_map_by_val; + typedef map analyzer_map_by_port; + + void RegisterAnalyzerComponent(Component* component); // Takes ownership. + + Component* Lookup(const string& name); + Component* Lookup(const char* name); + Component* Lookup(const Tag& tag); + Component* Lookup(EnumVal* val); + + tag_set* LookupPort(PortVal* val, bool add_if_not_found); + tag_set* LookupPort(TransportProto proto, uint32 port, bool add_if_not_found); + + tag_set GetScheduled(const Connection* conn); + void ExpireScheduledAnalyzers(); + + analyzer_map_by_port analyzers_by_port_tcp; + analyzer_map_by_port analyzers_by_port_udp; + analyzer_map_by_name analyzers_by_name; + analyzer_map_by_tag analyzers_by_tag; + analyzer_map_by_val analyzers_by_val; + + Tag analyzer_backdoor; + Tag analyzer_connsize; + Tag analyzer_interconn; + Tag analyzer_stepping; + Tag analyzer_tcpstats; + + EnumType* tag_enum_type; + + //// Data structures to track analyzed scheduled for future connections. + + // The index for a scheduled connection. + struct ConnIndex { + IPAddr orig; + IPAddr resp; + uint16 resp_p; + uint16 proto; + + ConnIndex(const IPAddr& _orig, const IPAddr& _resp, + uint16 _resp_p, uint16 _proto); + ConnIndex(); + + bool operator<(const ConnIndex& other) const; + }; + + // Information associated with a scheduled connection. + struct ScheduledAnalyzer { + ConnIndex conn; + Tag analyzer; + double timeout; + + struct Comparator { + bool operator() (ScheduledAnalyzer* a, ScheduledAnalyzer* b) { + return a->timeout > b->timeout; + } + }; + }; + + typedef std::multimap conns_map; + typedef std::priority_queue, + ScheduledAnalyzer::Comparator> conns_queue; + + conns_map conns; + conns_queue conns_by_timeout; +}; + +} + +extern analyzer::Manager* analyzer_mgr; + +// Macros for anayzer debug logging which include the connection id into the +// message. +#ifdef DEBUG +# define DBG_ANALYZER(conn, txt) \ + DBG_LOG(DBG_ANALYZER, "%s " txt, \ + fmt_conn_id(conn->OrigAddr(), ntohs(conn->OrigPort()), \ + conn->RespAddr(), ntohs(conn->RespPort()))); +# define DBG_ANALYZER_ARGS(conn, fmt, args...) \ + DBG_LOG(DBG_ANALYZER, "%s " fmt, \ + fmt_conn_id(conn->OrigAddr(), ntohs(conn->OrigPort()), \ + conn->RespAddr(), ntohs(conn->RespPort())), ##args); +#else +# define DBG_ANALYZER(conn, txt) +# define DBG_ANALYZER_ARGS(conn, fmt, args...) +#endif + +#endif diff --git a/src/analyzer/Tag.cc b/src/analyzer/Tag.cc new file mode 100644 index 0000000000..2f04ff17da --- /dev/null +++ b/src/analyzer/Tag.cc @@ -0,0 +1,92 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Tag.h" +#include "Manager.h" + +#include "../NetVar.h" + +using namespace analyzer; + +Tag Tag::Error; + +Tag::Tag(type_t arg_type, subtype_t arg_subtype) + { + assert(arg_type > 0); + + type = arg_type; + subtype = arg_subtype; + int64_t i = (int64)(type) | ((int64)subtype << 31); + + EnumType* etype = analyzer_mgr->GetTagEnumType(); + Ref(etype); + val = new EnumVal(i, etype); + } + +Tag::Tag(EnumVal* arg_val) + { + assert(arg_val); + + val = arg_val; + Ref(val); + + int64 i = val->InternalInt(); + type = i & 0xffffffff; + subtype = (i >> 31) & 0xffffffff; + } + +Tag::Tag(const Tag& other) + { + type = other.type; + subtype = other.subtype; + val = other.val; + + if ( val ) + Ref(val); + } + +Tag::Tag() + { + type = 0; + subtype = 0; + val = 0; + } + +Tag::~Tag() + { + Unref(val); + val = 0; + } + +Tag& Tag::operator=(const Tag& other) + { + if ( this != &other ) + { + type = other.type; + subtype = other.subtype; + val = other.val; + + if ( val ) + Ref(val); + } + + return *this; + } + +EnumVal* Tag::AsEnumVal() const + { + if ( ! val ) + { + assert(analyzer_mgr); + assert(type == 0 && subtype == 0); + EnumType* etype = analyzer_mgr->GetTagEnumType(); + Ref(etype); + val = new EnumVal(0, etype); + } + + return val; + } + +std::string Tag::AsString() const + { + return fmt("%" PRIu32 "/%" PRIu32, type, subtype); + } diff --git a/src/analyzer/Tag.h b/src/analyzer/Tag.h new file mode 100644 index 0000000000..cf33dca41c --- /dev/null +++ b/src/analyzer/Tag.h @@ -0,0 +1,152 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef ANALYZER_TAG_H +#define ANALYZER_TAG_H + +#include "config.h" +#include "util.h" + +class EnumVal; + +namespace analyzer { + +class Manager; +class Component; + +/** + * Class to identify an analyzer type. + * + * Each analyzer type gets a tag consisting of a main type and subtype. The + * former is an identifier that's unique all analyzer classes. The latter is + * passed through to the analyzer instances for their use, yet not further + * interpreted by the analyzer infrastructure; it allows an analyzer to + * branch out into a set of sub-analyzers internally. Jointly, main type and + * subtype form an analyzer "tag". Each unique tag corresponds to a single + * "analyzer" from the user's perspective. At the script layer, these tags + * are mapped into enums of type \c Analyzer::Tag. Internally, the + * analyzer::Mangager maintains the mapping of tag to analyzer (and it also + * assigns them their main types), and analyzer::Component creates new + * tags. + * + * The Tag class supports all operations necessary to act as an index in a + * \c std::map. + */ +class Tag { +public: + /** + * Type for the analyzer's main type. + */ + typedef uint32 type_t; + + /** + * Type for the analyzer's subtype. + */ + typedef uint32 subtype_t; + + /* + * Copy constructor. + */ + Tag(const Tag& other); + + /** + * Default constructor. This initializes the tag with an error value + * that will make \c operator \c bool return false. + */ + Tag(); + + /** + * Destructor. + */ + ~Tag(); + + /** + * Returns the tag's main type. + */ + type_t Type() const { return type; } + + /** + * Returns the tag's subtype. + */ + subtype_t Subtype() const { return subtype; } + + /** + * Returns the \c Analyzer::Tag enum that corresponds to this tag. + * The returned value is \a does not have its ref-count increased. + */ + EnumVal* AsEnumVal() const; + + /** + * Returns the numerical values for main and subtype inside a string + * suitable for printing. This is primarily for debugging. + */ + std::string AsString() const; + + /** + * Returns false if the tag represents an error value rather than a + * legal analyzer type. + */ + operator bool() const { return *this != Tag(); } + + /** + * Assignment operator. + */ + Tag& operator=(const Tag& other); + + /** + * Compares two tags for equality. + */ + bool operator==(const Tag& other) const + { + return type == other.type && subtype == other.subtype; + } + + /** + * Compares two tags for inequality. + */ + bool operator!=(const Tag& other) const + { + return type != other.type || subtype != other.subtype; + } + + /** + * Compares two tags for less-than relationship. + */ + bool operator<(const Tag& other) const + { + return type != other.type ? type < other.type : (subtype < other.subtype); + } + + static Tag Error; + +protected: + friend class analyzer::Manager; + friend class analyzer::Component; + + /** + * Constructor. Note + * + * @param type The main type. Note that the \a analyzer::Manager + * manages the value space internally, so noone else should assign + * any main tyoes. + * + * @param subtype The sub type, which is left to an analyzer for + * interpretation. By default it's set to zero. + */ + Tag(type_t type, subtype_t subtype = 0); + + /** + * Constructor. + * + * @param val An enuam value of script type \c Analyzer::Tag. + */ + Tag(EnumVal* val); + +private: + type_t type; // Main type. + subtype_t subtype; // Subtype. + mutable EnumVal* val; // Analyzer::Tag value. +}; + +} + +#endif diff --git a/src/analyzer/analyzer.bif b/src/analyzer/analyzer.bif new file mode 100644 index 0000000000..7f3cc6ed94 --- /dev/null +++ b/src/analyzer/analyzer.bif @@ -0,0 +1,45 @@ +##! Internal functions and types used by the analyzer framework. + +module Analyzer; + +%%{ +#include "NetVar.h" + +#include "analyzer/Manager.h" +%%} + +function Analyzer::__enable_analyzer%(id: Analyzer::Tag%) : bool + %{ + bool result = analyzer_mgr->EnableAnalyzer(id->AsEnumVal()); + return new Val(result, TYPE_BOOL); + %} + +function Analyzer::__disable_analyzer%(id: Analyzer::Tag%) : bool + %{ + bool result = analyzer_mgr->DisableAnalyzer(id->AsEnumVal()); + return new Val(result, TYPE_BOOL); + %} + +function Analyzer::__disable_all_analyzers%(%) : any + %{ + analyzer_mgr->DisableAllAnalyzers(); + return 0; + %} + +function Analyzer::__register_for_port%(id: Analyzer::Tag, p: port%) : bool + %{ + bool result = analyzer_mgr->RegisterAnalyzerForPort(id->AsEnumVal(), p); + return new Val(result, TYPE_BOOL); + %} + +function Analyzer::__schedule_analyzer%(orig: addr, resp: addr, resp_p: port, + analyzer: Analyzer::Tag, tout: interval%) : bool + %{ + analyzer_mgr->ScheduleAnalyzer(orig->AsAddr(), resp->AsAddr(), resp_p, analyzer->AsEnumVal(), tout); + return new Val(true, TYPE_BOOL); + %} + +function __name%(atype: Analyzer::Tag%) : string + %{ + return new StringVal(analyzer_mgr->GetAnalyzerName(atype)); + %} diff --git a/src/analyzer/protocol/CMakeLists.txt b/src/analyzer/protocol/CMakeLists.txt new file mode 100644 index 0000000000..a4e170f52b --- /dev/null +++ b/src/analyzer/protocol/CMakeLists.txt @@ -0,0 +1,40 @@ + +add_subdirectory(arp) +add_subdirectory(ayiya) +add_subdirectory(backdoor) +add_subdirectory(bittorrent) +add_subdirectory(conn-size) +add_subdirectory(dce-rpc) +add_subdirectory(dhcp) +add_subdirectory(dns) +add_subdirectory(file) +add_subdirectory(finger) +add_subdirectory(ftp) +add_subdirectory(gnutella) +add_subdirectory(gtpv1) +add_subdirectory(http) +add_subdirectory(icmp) +add_subdirectory(ident) +add_subdirectory(interconn) +add_subdirectory(irc) +add_subdirectory(login) +add_subdirectory(modbus) +add_subdirectory(mime) +add_subdirectory(ncp) +add_subdirectory(netflow) +add_subdirectory(netbios) +add_subdirectory(ntp) +add_subdirectory(pia) +add_subdirectory(pop3) +add_subdirectory(rpc) +add_subdirectory(smb) +add_subdirectory(smtp) +add_subdirectory(socks) +add_subdirectory(ssh) +add_subdirectory(ssl) +add_subdirectory(stepping-stone) +add_subdirectory(syslog) +add_subdirectory(tcp) +add_subdirectory(teredo) +add_subdirectory(udp) +add_subdirectory(zip) diff --git a/src/ARP.cc b/src/analyzer/protocol/arp/ARP.cc similarity index 99% rename from src/ARP.cc rename to src/analyzer/protocol/arp/ARP.cc index 7ffd82764c..b3ef5383ce 100644 --- a/src/ARP.cc +++ b/src/analyzer/protocol/arp/ARP.cc @@ -1,10 +1,12 @@ // See the file "COPYING" in the main distribution directory for copyright. - #include "ARP.h" #include "Event.h" #include "Reporter.h" +#include "events.bif.h" + +using namespace analyzer::arp; ARP_Analyzer::ARP_Analyzer() { diff --git a/src/ARP.h b/src/analyzer/protocol/arp/ARP.h similarity index 89% rename from src/ARP.h rename to src/analyzer/protocol/arp/ARP.h index f4b623c513..f09dc6c398 100644 --- a/src/ARP.h +++ b/src/analyzer/protocol/arp/ARP.h @@ -1,7 +1,7 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef arp_h -#define arp_h +#ifndef ANALYZER_PROTOCOL_ARP_ARP_H +#define ANALYZER_PROTOCOL_ARP_ARP_H #include "config.h" #include @@ -24,7 +24,9 @@ #endif #include "NetVar.h" +#include "PacketSort.h" +namespace analyzer { namespace arp { class ARP_Analyzer : public BroObj { public: @@ -53,4 +55,6 @@ protected: EventHandlerPtr arp_reply; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/arp/CMakeLists.txt b/src/analyzer/protocol/arp/CMakeLists.txt new file mode 100644 index 0000000000..eec6755a18 --- /dev/null +++ b/src/analyzer/protocol/arp/CMakeLists.txt @@ -0,0 +1,15 @@ + +# This is not an actual analyzer, but used by the core. We still +# maintain it here along with the other analyzers because conceptually +# it's also parsing a protocol just like them. The current structure +# is merely a left-over from when this code was written. + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro ARP) +bro_plugin_cc(ARP.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() + diff --git a/src/analyzer/protocol/arp/Plugin.cc b/src/analyzer/protocol/arp/Plugin.cc new file mode 100644 index 0000000000..9045ef412f --- /dev/null +++ b/src/analyzer/protocol/arp/Plugin.cc @@ -0,0 +1,7 @@ + +#include "plugin/Plugin.h" + +BRO_PLUGIN_BEGIN(Bro, ARP) + BRO_PLUGIN_DESCRIPTION("ARP Parsing Code"); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/arp/events.bif b/src/analyzer/protocol/arp/events.bif new file mode 100644 index 0000000000..efee33d7f4 --- /dev/null +++ b/src/analyzer/protocol/arp/events.bif @@ -0,0 +1,63 @@ +## Generated for ARP requests. +## +## See `Wikipedia `__ +## for more information about the ARP protocol. +## +## mac_src: The request's source MAC address. +## +## mac_dst: The request's destination MAC address. +## +## SPA: The sender protocol address. +## +## SHA: The sender hardware address. +## +## TPA: The target protocol address. +## +## THA: The target hardware address. +## +## .. bro:see:: arp_reply bad_arp +event arp_request%(mac_src: string, mac_dst: string, SPA: addr, SHA: string, + TPA: addr, THA: string%); + +## Generated for ARP replies. +## +## See `Wikipedia `__ +## for more information about the ARP protocol. +## +## mac_src: The reply's source MAC address. +## +## mac_dst: The reply's destination MAC address. +## +## SPA: The sender protocol address. +## +## SHA: The sender hardware address. +## +## TPA: The target protocol address. +## +## THA: The target hardware address. +## +## .. bro:see:: arp_request bad_arp +event arp_reply%(mac_src: string, mac_dst: string, SPA: addr, SHA: string, + TPA: addr, THA: string%); + +## Generated for ARP packets that Bro cannot interpret. Examples are packets +## with non-standard hardware address formats or hardware addresses that do not +## match the originator of the packet. +## +## SPA: The sender protocol address. +## +## SHA: The sender hardware address. +## +## TPA: The target protocol address. +## +## THA: The target hardware address. +## +## explanation: A short description of why the ARP packet is considered "bad". +## +## .. bro:see:: arp_reply arp_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event bad_arp%(SPA: addr, SHA: string, TPA: addr, THA: string, explanation: string%); diff --git a/src/AYIYA.cc b/src/analyzer/protocol/ayiya/AYIYA.cc similarity index 85% rename from src/AYIYA.cc rename to src/analyzer/protocol/ayiya/AYIYA.cc index 79fa44e743..070a3ef3e1 100644 --- a/src/AYIYA.cc +++ b/src/analyzer/protocol/ayiya/AYIYA.cc @@ -1,7 +1,12 @@ + #include "AYIYA.h" +#include "Func.h" +#include "events.bif.h" + +using namespace analyzer::ayiya; AYIYA_Analyzer::AYIYA_Analyzer(Connection* conn) -: Analyzer(AnalyzerTag::AYIYA, conn) +: Analyzer("AYIYA", conn) { interp = new binpac::AYIYA::AYIYA_Conn(this); } diff --git a/src/AYIYA.h b/src/analyzer/protocol/ayiya/AYIYA.h similarity index 56% rename from src/AYIYA.h rename to src/analyzer/protocol/ayiya/AYIYA.h index 79b41553c7..f5bb379cf4 100644 --- a/src/AYIYA.h +++ b/src/analyzer/protocol/ayiya/AYIYA.h @@ -1,9 +1,11 @@ -#ifndef AYIYA_h -#define AYIYA_h +#ifndef ANALYZER_PROTOCOL_AYIYA_AYIYA_H +#define ANALYZER_PROTOCOL_AYIYA_AYIYA_H #include "ayiya_pac.h" -class AYIYA_Analyzer : public Analyzer { +namespace analyzer { namespace ayiya { + +class AYIYA_Analyzer : public analyzer::Analyzer { public: AYIYA_Analyzer(Connection* conn); virtual ~AYIYA_Analyzer(); @@ -12,18 +14,15 @@ public: virtual void DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new AYIYA_Analyzer(conn); } - static bool Available() - { return BifConst::Tunnel::enable_ayiya && - BifConst::Tunnel::max_depth > 0; } - protected: - friend class AnalyzerTimer; void ExpireTimer(double t); binpac::AYIYA::AYIYA_Conn* interp; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/ayiya/CMakeLists.txt b/src/analyzer/protocol/ayiya/CMakeLists.txt new file mode 100644 index 0000000000..ae23c25e2d --- /dev/null +++ b/src/analyzer/protocol/ayiya/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro AYIYA) +bro_plugin_cc(AYIYA.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(ayiya.pac ayiya-protocol.pac ayiya-analyzer.pac) +bro_plugin_end() diff --git a/src/analyzer/protocol/ayiya/Plugin.cc b/src/analyzer/protocol/ayiya/Plugin.cc new file mode 100644 index 0000000000..0fc96eff3c --- /dev/null +++ b/src/analyzer/protocol/ayiya/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "AYIYA.h" + +BRO_PLUGIN_BEGIN(Bro, AYIYA) + BRO_PLUGIN_DESCRIPTION("AYIYA Analyzer"); + BRO_PLUGIN_ANALYZER("AYIYA", ayiya::AYIYA_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/ayiya-analyzer.pac b/src/analyzer/protocol/ayiya/ayiya-analyzer.pac similarity index 100% rename from src/ayiya-analyzer.pac rename to src/analyzer/protocol/ayiya/ayiya-analyzer.pac diff --git a/src/ayiya-protocol.pac b/src/analyzer/protocol/ayiya/ayiya-protocol.pac similarity index 100% rename from src/ayiya-protocol.pac rename to src/analyzer/protocol/ayiya/ayiya-protocol.pac diff --git a/src/ayiya.pac b/src/analyzer/protocol/ayiya/ayiya.pac similarity index 81% rename from src/ayiya.pac rename to src/analyzer/protocol/ayiya/ayiya.pac index 58fa196c15..b1f3a6ef77 100644 --- a/src/ayiya.pac +++ b/src/analyzer/protocol/ayiya/ayiya.pac @@ -1,6 +1,11 @@ + %include binpac.pac %include bro.pac +%extern{ +#include "events.bif.h" +%} + analyzer AYIYA withcontext { connection: AYIYA_Conn; flow: AYIYA_Flow; diff --git a/src/analyzer/protocol/ayiya/events.bif b/src/analyzer/protocol/ayiya/events.bif new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/BackDoor.cc b/src/analyzer/protocol/backdoor/BackDoor.cc similarity index 98% rename from src/BackDoor.cc rename to src/analyzer/protocol/backdoor/BackDoor.cc index c218a98ce2..a466938ff6 100644 --- a/src/BackDoor.cc +++ b/src/analyzer/protocol/backdoor/BackDoor.cc @@ -5,9 +5,13 @@ #include "BackDoor.h" #include "Event.h" #include "Net.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" -BackDoorEndpoint::BackDoorEndpoint(TCP_Endpoint* e) +#include "events.bif.h" + +using namespace analyzer::backdoor; + +BackDoorEndpoint::BackDoorEndpoint(tcp::TCP_Endpoint* e) { endp = e; is_partial = 0; @@ -53,7 +57,7 @@ int BackDoorEndpoint::DataSent(double /* t */, int seq, if ( len <= 0 ) return 0; - if ( endp->state == TCP_ENDPOINT_PARTIAL ) + if ( endp->state == tcp::TCP_ENDPOINT_PARTIAL ) is_partial = 1; int ack = endp->AckSeq() - endp->StartSeq(); @@ -681,7 +685,7 @@ int BackDoorEndpoint::CheckForString(const char* str, BackDoor_Analyzer::BackDoor_Analyzer(Connection* c) -: TCP_ApplicationAnalyzer(AnalyzerTag::Backdoor, c) +: tcp::TCP_ApplicationAnalyzer("BACKDOOR", c) { orig_endp = resp_endp = 0; @@ -701,7 +705,7 @@ BackDoor_Analyzer::~BackDoor_Analyzer() void BackDoor_Analyzer::Init() { - TCP_ApplicationAnalyzer::Init(); + tcp::TCP_ApplicationAnalyzer::Init(); assert(TCP()); orig_endp = new BackDoorEndpoint(TCP()->Orig()); @@ -740,7 +744,7 @@ void BackDoor_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) void BackDoor_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); if ( ! IsFinished() ) { diff --git a/src/BackDoor.h b/src/analyzer/protocol/backdoor/BackDoor.h similarity index 82% rename from src/BackDoor.h rename to src/analyzer/protocol/backdoor/BackDoor.h index 40ea3bbaa3..5bc8a67381 100644 --- a/src/BackDoor.h +++ b/src/analyzer/protocol/backdoor/BackDoor.h @@ -1,16 +1,18 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef backdoor_h -#define backdoor_h +#ifndef ANALYZER_PROTOCOL_BACKDOOR_BACKDOOR_H +#define ANALYZER_PROTOCOL_BACKDOOR_BACKDOOR_H -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #include "Timer.h" #include "NetVar.h" -#include "Login.h" +#include "analyzer/protocol/login/Login.h" + +namespace analyzer { namespace backdoor { class BackDoorEndpoint { public: - BackDoorEndpoint(TCP_Endpoint* e); + BackDoorEndpoint(tcp::TCP_Endpoint* e); int DataSent(double t, int seq, int len, int caplen, const u_char* data, const IP_Hdr* ip, const struct tcphdr* tp); @@ -44,7 +46,7 @@ protected: int CheckForFullString(const char* str, const u_char* data, int len); int CheckForString(const char* str, const u_char* data, int len); - TCP_Endpoint* endp; + tcp::TCP_Endpoint* endp; int is_partial; int max_top_seq; @@ -62,7 +64,7 @@ protected: uint32 num_7bit_ascii; }; -class BackDoor_Analyzer : public TCP_ApplicationAnalyzer { +class BackDoor_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: BackDoor_Analyzer(Connection* c); ~BackDoor_Analyzer(); @@ -71,18 +73,9 @@ public: virtual void Done(); void StatTimer(double t, int is_expire); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new BackDoor_Analyzer(conn); } - static bool Available() - { - return backdoor_stats || rlogin_signature_found || - telnet_signature_found || ssh_signature_found || - root_backdoor_signature_found || ftp_signature_found || - napster_signature_found || kazaa_signature_found || - http_signature_found || http_proxy_signature_found; - } - protected: // We support both packet and stream input, and can be instantiated // even if the TCP analyzer is not yet reassembling. @@ -114,4 +107,6 @@ protected: BackDoor_Analyzer* analyzer; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/backdoor/CMakeLists.txt b/src/analyzer/protocol/backdoor/CMakeLists.txt new file mode 100644 index 0000000000..5df04769f6 --- /dev/null +++ b/src/analyzer/protocol/backdoor/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro BackDoor) +bro_plugin_cc(BackDoor.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/analyzer/protocol/backdoor/Plugin.cc b/src/analyzer/protocol/backdoor/Plugin.cc new file mode 100644 index 0000000000..0983aaf5d3 --- /dev/null +++ b/src/analyzer/protocol/backdoor/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "BackDoor.h" + +BRO_PLUGIN_BEGIN(Bro, BackDoor) + BRO_PLUGIN_DESCRIPTION("Backdoor Analyzer (deprecated)"); + BRO_PLUGIN_ANALYZER("BackDoor", backdoor::BackDoor_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/backdoor/events.bif b/src/analyzer/protocol/backdoor/events.bif new file mode 100644 index 0000000000..81676ee43b --- /dev/null +++ b/src/analyzer/protocol/backdoor/events.bif @@ -0,0 +1,32 @@ +## Deprecated. Will be removed. +event backdoor_stats%(c: connection, os: backdoor_endp_stats, rs: backdoor_endp_stats%); + +## Deprecated. Will be removed. +event backdoor_remove_conn%(c: connection%); + +## Deprecated. Will be removed. +event ftp_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event gnutella_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event http_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event irc_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event telnet_signature_found%(c: connection, is_orig: bool, len: count%); + +## Deprecated. Will be removed. +event ssh_signature_found%(c: connection, is_orig: bool%); + +## Deprecated. Will be removed. +event rlogin_signature_found%(c: connection, is_orig: bool, num_null: count, len: count%); + +## Deprecated. Will be removed. +event smtp_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event http_proxy_signature_found%(c: connection%); diff --git a/src/BitTorrent.cc b/src/analyzer/protocol/bittorrent/BitTorrent.cc similarity index 89% rename from src/BitTorrent.cc rename to src/analyzer/protocol/bittorrent/BitTorrent.cc index fa8fb09e43..99fd9dc132 100644 --- a/src/BitTorrent.cc +++ b/src/analyzer/protocol/bittorrent/BitTorrent.cc @@ -1,10 +1,14 @@ // This code contributed by Nadi Sarrar. #include "BitTorrent.h" -#include "TCP_Reassembler.h" +#include "analyzer/protocol/tcp/TCP_Reassembler.h" + +#include "events.bif.h" + +using namespace analyzer::bittorrent; BitTorrent_Analyzer::BitTorrent_Analyzer(Connection* c) -: TCP_ApplicationAnalyzer(AnalyzerTag::BitTorrent, c) +: tcp::TCP_ApplicationAnalyzer("BITTORRENT", c) { interp = new binpac::BitTorrent::BitTorrent_Conn(this); stop_orig = stop_resp = false; @@ -18,7 +22,7 @@ BitTorrent_Analyzer::~BitTorrent_Analyzer() void BitTorrent_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); interp->FlowEOF(true); interp->FlowEOF(false); @@ -29,7 +33,7 @@ void BitTorrent_Analyzer::DeliverStream(int len, const u_char* data, bool orig) uint64& this_stream_len = orig ? stream_len_orig : stream_len_resp; bool& this_stop = orig ? stop_orig : stop_resp; - TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); assert(TCP()); @@ -66,7 +70,7 @@ void BitTorrent_Analyzer::DeliverStream(int len, const u_char* data, bool orig) void BitTorrent_Analyzer::Undelivered(int seq, int len, bool orig) { - TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); + tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); // TODO: Code commented out for now. I think that shoving data that // is definitely wrong into the parser seems like a really bad idea. @@ -108,7 +112,7 @@ void BitTorrent_Analyzer::Undelivered(int seq, int len, bool orig) void BitTorrent_Analyzer::EndpointEOF(bool is_orig) { - TCP_ApplicationAnalyzer::EndpointEOF(is_orig); + tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig); interp->FlowEOF(is_orig); } diff --git a/src/BitTorrent.h b/src/analyzer/protocol/bittorrent/BitTorrent.h similarity index 62% rename from src/BitTorrent.h rename to src/analyzer/protocol/bittorrent/BitTorrent.h index f083cf4fc7..7739463052 100644 --- a/src/BitTorrent.h +++ b/src/analyzer/protocol/bittorrent/BitTorrent.h @@ -1,13 +1,15 @@ // This code contributed by Nadi Sarrar. -#ifndef bittorrent_h -#define bittorrent_h +#ifndef ANALYZER_PROTOCOL_BITTORRENT_BITTORRENT_H +#define ANALYZER_PROTOCOL_BITTORRENT_BITTORRENT_H -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #include "bittorrent_pac.h" -class BitTorrent_Analyzer : public TCP_ApplicationAnalyzer { +namespace analyzer { namespace bittorrent { + +class BitTorrent_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: BitTorrent_Analyzer(Connection* conn); virtual ~BitTorrent_Analyzer(); @@ -17,12 +19,9 @@ public: virtual void Undelivered(int seq, int len, bool orig); virtual void EndpointEOF(bool is_orig); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new BitTorrent_Analyzer(conn); } - static bool Available() - { return bittorrent_peer_handshake || bittorrent_peer_piece; } - protected: void DeliverWeird(const char* msg, bool orig); @@ -31,4 +30,6 @@ protected: uint64 stream_len_orig, stream_len_resp; }; +} } // namespace analyzer::* + #endif diff --git a/src/BitTorrentTracker.cc b/src/analyzer/protocol/bittorrent/BitTorrentTracker.cc similarity index 97% rename from src/BitTorrentTracker.cc rename to src/analyzer/protocol/bittorrent/BitTorrentTracker.cc index 12c5a199de..b32db9a8bd 100644 --- a/src/BitTorrentTracker.cc +++ b/src/analyzer/protocol/bittorrent/BitTorrentTracker.cc @@ -1,7 +1,9 @@ // This code contributed by Nadi Sarrar. #include "BitTorrentTracker.h" -#include "TCP_Reassembler.h" +#include "analyzer/protocol/tcp/TCP_Reassembler.h" + +#include "events.bif.h" #include #include @@ -11,6 +13,8 @@ # define FMT_INT "%" PRId64 # define FMT_UINT "%" PRIu64 +using namespace analyzer::bittorrent; + static TableType* bt_tracker_headers = 0; static RecordType* bittorrent_peer; static TableType* bittorrent_peer_set; @@ -18,7 +22,7 @@ static RecordType* bittorrent_benc_value; static TableType* bittorrent_benc_dir; BitTorrentTracker_Analyzer::BitTorrentTracker_Analyzer(Connection* c) -: TCP_ApplicationAnalyzer(AnalyzerTag::BitTorrentTracker, c) +: tcp::TCP_ApplicationAnalyzer("BITTORRENT", c) { if ( ! bt_tracker_headers ) { @@ -74,13 +78,13 @@ BitTorrentTracker_Analyzer::~BitTorrentTracker_Analyzer() void BitTorrentTracker_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); } void BitTorrentTracker_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { - TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); assert(TCP()); @@ -205,7 +209,7 @@ void BitTorrentTracker_Analyzer::ServerReply(int len, const u_char* data) void BitTorrentTracker_Analyzer::Undelivered(int seq, int len, bool orig) { - TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); + tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); ProtocolViolation("BitTorrentTracker: cannot recover from content gap"); @@ -217,7 +221,7 @@ void BitTorrentTracker_Analyzer::Undelivered(int seq, int len, bool orig) void BitTorrentTracker_Analyzer::EndpointEOF(bool is_orig) { - TCP_ApplicationAnalyzer::EndpointEOF(is_orig); + tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig); } void BitTorrentTracker_Analyzer::InitBencParser(void) diff --git a/src/BitTorrentTracker.h b/src/analyzer/protocol/bittorrent/BitTorrentTracker.h similarity index 88% rename from src/BitTorrentTracker.h rename to src/analyzer/protocol/bittorrent/BitTorrentTracker.h index 3b9efe0430..b041e556b7 100644 --- a/src/BitTorrentTracker.h +++ b/src/analyzer/protocol/bittorrent/BitTorrentTracker.h @@ -1,12 +1,14 @@ // This code contributed by Nadi Sarrar. -#ifndef bittorrenttracker_h -#define bittorrenttracker_h +#ifndef ANALYZER_PROTOCOL_BITTORRENT_BITTORRENTTRACKER_H +#define ANALYZER_PROTOCOL_BITTORRENT_BITTORRENTTRACKER_H -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #define BTTRACKER_BUF 2048 +namespace analyzer { namespace bittorrent { + // If the following is defined, then the analyzer will store all of // the headers seen in tracker messages. //#define BTTRACKER_STORE_HEADERS 1 @@ -40,7 +42,7 @@ enum btt_benc_states { BENC_STATE_STR2, }; -class BitTorrentTracker_Analyzer : public TCP_ApplicationAnalyzer { +class BitTorrentTracker_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: BitTorrentTracker_Analyzer(Connection* conn); virtual ~BitTorrentTracker_Analyzer(); @@ -50,12 +52,9 @@ public: virtual void Undelivered(int seq, int len, bool orig); virtual void EndpointEOF(bool is_orig); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new BitTorrentTracker_Analyzer(conn); } - static bool Available() - { return bt_tracker_request || bt_tracker_response; } - protected: void ClientRequest(int len, const u_char* data); void ServerReply(int len, const u_char* data); @@ -129,4 +128,6 @@ protected: bool stop_orig, stop_resp; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/bittorrent/CMakeLists.txt b/src/analyzer/protocol/bittorrent/CMakeLists.txt new file mode 100644 index 0000000000..630ea03498 --- /dev/null +++ b/src/analyzer/protocol/bittorrent/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro BitTorrent) +bro_plugin_cc(BitTorrent.cc BitTorrentTracker.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(bittorrent.pac bittorrent-analyzer.pac bittorrent-protocol.pac) +bro_plugin_end() diff --git a/src/analyzer/protocol/bittorrent/Plugin.cc b/src/analyzer/protocol/bittorrent/Plugin.cc new file mode 100644 index 0000000000..2da9972d0d --- /dev/null +++ b/src/analyzer/protocol/bittorrent/Plugin.cc @@ -0,0 +1,12 @@ + +#include "plugin/Plugin.h" + +#include "BitTorrent.h" +#include "BitTorrentTracker.h" + +BRO_PLUGIN_BEGIN(Bro, BitTorrent) + BRO_PLUGIN_DESCRIPTION("BitTorrent Analyzer"); + BRO_PLUGIN_ANALYZER("BitTorrent", bittorrent::BitTorrent_Analyzer); + BRO_PLUGIN_ANALYZER("BitTorrentTracker", bittorrent::BitTorrent_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/bittorrent-analyzer.pac b/src/analyzer/protocol/bittorrent/bittorrent-analyzer.pac similarity index 100% rename from src/bittorrent-analyzer.pac rename to src/analyzer/protocol/bittorrent/bittorrent-analyzer.pac diff --git a/src/bittorrent-protocol.pac b/src/analyzer/protocol/bittorrent/bittorrent-protocol.pac similarity index 100% rename from src/bittorrent-protocol.pac rename to src/analyzer/protocol/bittorrent/bittorrent-protocol.pac diff --git a/src/bittorrent.pac b/src/analyzer/protocol/bittorrent/bittorrent.pac similarity index 92% rename from src/bittorrent.pac rename to src/analyzer/protocol/bittorrent/bittorrent.pac index f6255902dd..39e53596dd 100644 --- a/src/bittorrent.pac +++ b/src/analyzer/protocol/bittorrent/bittorrent.pac @@ -5,6 +5,8 @@ %extern{ #define MSGLEN_LIMIT 0x40000 + +#include "events.bif.h" %} analyzer BitTorrent withcontext { diff --git a/src/analyzer/protocol/bittorrent/events.bif b/src/analyzer/protocol/bittorrent/events.bif new file mode 100644 index 0000000000..8c4ddc146f --- /dev/null +++ b/src/analyzer/protocol/bittorrent/events.bif @@ -0,0 +1,226 @@ +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_have bittorrent_peer_interested bittorrent_peer_keep_alive +## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird +event bittorrent_peer_handshake%(c: connection, is_orig: bool, + reserved: string, info_hash: string, peer_id: string%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird +event bittorrent_peer_keep_alive%(c: connection, is_orig: bool%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird +event bittorrent_peer_choke%(c: connection, is_orig: bool%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request +## bittorrent_peer_unknown bittorrent_peer_weird +event bittorrent_peer_unchoke%(c: connection, is_orig: bool%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_keep_alive +## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird +event bittorrent_peer_interested%(c: connection, is_orig: bool%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird +event bittorrent_peer_not_interested%(c: connection, is_orig: bool%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_interested bittorrent_peer_keep_alive +## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird +event bittorrent_peer_have%(c: connection, is_orig: bool, piece_index: count%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_cancel bittorrent_peer_choke bittorrent_peer_handshake +## bittorrent_peer_have bittorrent_peer_interested bittorrent_peer_keep_alive +## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird +event bittorrent_peer_bitfield%(c: connection, is_orig: bool, bitfield: string%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird +event bittorrent_peer_request%(c: connection, is_orig: bool, index: count, + begin: count, length: count%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird +event bittorrent_peer_piece%(c: connection, is_orig: bool, index: count, + begin: count, piece_length: count%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird +event bittorrent_peer_cancel%(c: connection, is_orig: bool, index: count, + begin: count, length: count%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird +event bittorrent_peer_port%(c: connection, is_orig: bool, listen_port: port%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_weird +event bittorrent_peer_unknown%(c: connection, is_orig: bool, message_id: count, + data: string%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown +event bittorrent_peer_weird%(c: connection, is_orig: bool, msg: string%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird +event bt_tracker_request%(c: connection, uri: string, + headers: bt_tracker_headers%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird +event bt_tracker_response%(c: connection, status: count, + headers: bt_tracker_headers, + peers: bittorrent_peer_set, + benc: bittorrent_benc_dir%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird +event bt_tracker_response_not_ok%(c: connection, status: count, + headers: bt_tracker_headers%); + +## TODO. +## +## See `Wikipedia `__ for +## more information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird +event bt_tracker_weird%(c: connection, is_orig: bool, msg: string%); + diff --git a/src/analyzer/protocol/conn-size/CMakeLists.txt b/src/analyzer/protocol/conn-size/CMakeLists.txt new file mode 100644 index 0000000000..efaadef401 --- /dev/null +++ b/src/analyzer/protocol/conn-size/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro ConnSize) +bro_plugin_cc(ConnSize.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/ConnSizeAnalyzer.cc b/src/analyzer/protocol/conn-size/ConnSize.cc similarity index 92% rename from src/ConnSizeAnalyzer.cc rename to src/analyzer/protocol/conn-size/ConnSize.cc index a1b892f4db..b912fe3d2d 100644 --- a/src/ConnSizeAnalyzer.cc +++ b/src/analyzer/protocol/conn-size/ConnSize.cc @@ -3,13 +3,15 @@ // See ConnSize.h for more extensive comments. -#include "ConnSizeAnalyzer.h" -#include "TCP.h" +#include "ConnSize.h" +#include "analyzer/protocol/tcp/TCP.h" +#include "events.bif.h" +using namespace analyzer::conn_size; ConnSize_Analyzer::ConnSize_Analyzer(Connection* c) -: Analyzer(AnalyzerTag::ConnSize, c) +: Analyzer("CONNSIZE", c) { } diff --git a/src/ConnSizeAnalyzer.h b/src/analyzer/protocol/conn-size/ConnSize.h similarity index 65% rename from src/ConnSizeAnalyzer.h rename to src/analyzer/protocol/conn-size/ConnSize.h index 1fdd57bb15..25f096dd32 100644 --- a/src/ConnSizeAnalyzer.h +++ b/src/analyzer/protocol/conn-size/ConnSize.h @@ -1,14 +1,15 @@ // See the file "COPYING" in the main distribution directory for copyright. // -#ifndef CONNSTATS_H -#define CONNSTATS_H +#ifndef ANALYZER_PROTOCOL_CONN_SIZE_CONNSIZE_H +#define ANALYZER_PROTOCOL_CONN_SIZE_CONNSIZE_H -#include "Analyzer.h" +#include "analyzer/Analyzer.h" #include "NetVar.h" +namespace analyzer { namespace conn_size { -class ConnSize_Analyzer : public Analyzer { +class ConnSize_Analyzer : public analyzer::Analyzer { public: ConnSize_Analyzer(Connection* c); virtual ~ConnSize_Analyzer(); @@ -20,11 +21,9 @@ public: virtual void UpdateConnVal(RecordVal *conn_val); virtual void FlipRoles(); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new ConnSize_Analyzer(conn); } - static bool Available() { return BifConst::use_conn_size_analyzer ; } - protected: virtual void DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen); @@ -36,4 +35,6 @@ protected: uint64_t resp_pkts; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/conn-size/Plugin.cc b/src/analyzer/protocol/conn-size/Plugin.cc new file mode 100644 index 0000000000..6993e15ff8 --- /dev/null +++ b/src/analyzer/protocol/conn-size/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "ConnSize.h" + +BRO_PLUGIN_BEGIN(Bro, ConnSize) + BRO_PLUGIN_DESCRIPTION("Connection size analyzer"); + BRO_PLUGIN_ANALYZER("ConnSize", conn_size::ConnSize_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/conn-size/events.bif b/src/analyzer/protocol/conn-size/events.bif new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/analyzer/protocol/dce-rpc/CMakeLists.txt b/src/analyzer/protocol/dce-rpc/CMakeLists.txt new file mode 100644 index 0000000000..d9baa08acf --- /dev/null +++ b/src/analyzer/protocol/dce-rpc/CMakeLists.txt @@ -0,0 +1,12 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro DCE_RPC) +bro_plugin_cc(DCE_RPC.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(dce_rpc.pac dce_rpc-protocol.pac dce_rpc-analyzer.pac) +bro_plugin_pac(dce_rpc_simple.pac dce_rpc-protocol.pac epmapper.pac) +bro_plugin_end() + diff --git a/src/DCE_RPC.cc b/src/analyzer/protocol/dce-rpc/DCE_RPC.cc similarity index 95% rename from src/DCE_RPC.cc rename to src/analyzer/protocol/dce-rpc/DCE_RPC.cc index 21cb3be9a0..dd31cfa8a7 100644 --- a/src/DCE_RPC.cc +++ b/src/analyzer/protocol/dce-rpc/DCE_RPC.cc @@ -10,7 +10,12 @@ using namespace std; #include "DCE_RPC.h" #include "Sessions.h" -#include "DPM.h" + +#include "analyzer/Manager.h" + +#include "events.bif.h" + +using namespace analyzer::dce_rpc; #define xbyte(b, n) (((const u_char*) (b))[n]) @@ -26,7 +31,7 @@ static int uuid_index[] = { 12, 13, 14, 15 }; -const char* uuid_to_string(const u_char* uuid_data) +const char* analyzer::dce_rpc::uuid_to_string(const u_char* uuid_data) { static char s[1024]; char* sp = s; @@ -160,11 +165,11 @@ static void add_dce_rpc_endpoint(const dce_rpc_endpoint_addr& addr, // of the dce_rpc_endpoints table. // FIXME: Don't hard-code the timeout. - dpm->ExpectConnection(IPAddr(), addr.addr, addr.port, addr.proto, - AnalyzerTag::DCE_RPC, 5 * 60, 0); + analyzer_mgr->ScheduleAnalyzer(IPAddr(), addr.addr, addr.port, addr.proto, + "DCE_RPC", 5 * 60); } -DCE_RPC_Header::DCE_RPC_Header(Analyzer* a, const u_char* b) +DCE_RPC_Header::DCE_RPC_Header(analyzer::Analyzer* a, const u_char* b) { analyzer = a; bytes = b; @@ -183,7 +188,7 @@ DCE_RPC_Header::DCE_RPC_Header(Analyzer* a, const u_char* b) frag_len = extract_uint16(LittleEndian(), bytes + 8); } -DCE_RPC_Session::DCE_RPC_Session(Analyzer* a) +DCE_RPC_Session::DCE_RPC_Session(analyzer::Analyzer* a) : analyzer(a), if_uuid("00000000-0000-0000-0000-000000000000"), if_id(BifEnum::DCE_RPC_unknown_if) @@ -442,7 +447,7 @@ void DCE_RPC_Session::DeliverEpmapperMapResponse( Contents_DCE_RPC_Analyzer::Contents_DCE_RPC_Analyzer(Connection* conn, bool orig, DCE_RPC_Session* arg_session, bool speculative) -: TCP_SupportAnalyzer(AnalyzerTag::Contents_DCE_RPC, conn, orig) +: tcp::TCP_SupportAnalyzer("CONTENTS_DCE_RPC", conn, orig) { session = arg_session; msg_buf = 0; @@ -474,10 +479,10 @@ Contents_DCE_RPC_Analyzer::~Contents_DCE_RPC_Analyzer() void Contents_DCE_RPC_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { - TCP_SupportAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_SupportAnalyzer::DeliverStream(len, data, orig); - TCP_Analyzer* tcp = - static_cast(Parent())->TCP(); + tcp::TCP_Analyzer* tcp = + static_cast(Parent())->TCP(); if ( tcp->HadGap(orig) || tcp->IsPartial() ) return; @@ -566,7 +571,7 @@ bool Contents_DCE_RPC_Analyzer::ParseHeader() } DCE_RPC_Analyzer::DCE_RPC_Analyzer(Connection* conn, bool arg_speculative) -: TCP_ApplicationAnalyzer(AnalyzerTag::DCE_RPC, conn) +: tcp::TCP_ApplicationAnalyzer("DCE_RPC", conn) { session = new DCE_RPC_Session(this); speculative = arg_speculative; diff --git a/src/DCE_RPC.h b/src/analyzer/protocol/dce-rpc/DCE_RPC.h similarity index 87% rename from src/DCE_RPC.h rename to src/analyzer/protocol/dce-rpc/DCE_RPC.h index acdbf1637d..2abfb584b5 100644 --- a/src/DCE_RPC.h +++ b/src/analyzer/protocol/dce-rpc/DCE_RPC.h @@ -1,17 +1,21 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef dce_rpc_h -#define dce_rpc_h +#ifndef ANALYZER_PROTOCOL_DCE_RPC_DCE_RPC_H +#define ANALYZER_PROTOCOL_DCE_RPC_DCE_RPC_H // NOTE: This is a somewhat crude analyzer for DCE/RPC (used on Microsoft // Windows systems) and shouldn't be considered as stable. #include "NetVar.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/dce-rpc/events.bif.h" #include "IPAddr.h" #include "dce_rpc_simple_pac.h" + +namespace analyzer { namespace dce_rpc { + class UUID { public: UUID(); @@ -88,7 +92,7 @@ enum DCE_RPC_PTYPE { class DCE_RPC_Header { public: - DCE_RPC_Header(Analyzer* a, const u_char* bytes); + DCE_RPC_Header(analyzer::Analyzer* a, const u_char* bytes); BifEnum::dce_rpc_ptype PTYPE() const { return ptype; } int FragLen() const { return frag_len; } @@ -99,7 +103,7 @@ public: void SetBytes(const u_char* b) { bytes = b; } protected: - Analyzer* analyzer; + analyzer::Analyzer* analyzer; const u_char* bytes; BifEnum::dce_rpc_ptype ptype; int frag_len; @@ -112,7 +116,7 @@ protected: class DCE_RPC_Session { public: - DCE_RPC_Session(Analyzer* a); + DCE_RPC_Session(analyzer::Analyzer* a); virtual ~DCE_RPC_Session() {} virtual void DeliverPDU(int is_orig, int len, const u_char* data); @@ -135,7 +139,7 @@ protected: const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu, const binpac::DCE_RPC_Simple::DCE_RPC_Response* resp); - Analyzer* analyzer; + analyzer::Analyzer* analyzer; UUID if_uuid; BifEnum::dce_rpc_if_id if_id; int opnum; @@ -145,7 +149,7 @@ protected: } mapped; }; -class Contents_DCE_RPC_Analyzer : public TCP_SupportAnalyzer { +class Contents_DCE_RPC_Analyzer : public tcp::TCP_SupportAnalyzer { public: Contents_DCE_RPC_Analyzer(Connection* conn, bool orig, DCE_RPC_Session* session, bool speculative); @@ -169,20 +173,19 @@ protected: DCE_RPC_Session* session; }; -class DCE_RPC_Analyzer : public TCP_ApplicationAnalyzer { +class DCE_RPC_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: DCE_RPC_Analyzer(Connection* conn, bool speculative = false); ~DCE_RPC_Analyzer(); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new DCE_RPC_Analyzer(conn); } - static bool Available() - { return DCE_RPC_Session::any_dce_rpc_event(); } - protected: DCE_RPC_Session* session; bool speculative; }; +} } // namespace analyzer::* + #endif /* dce_rpc_h */ diff --git a/src/analyzer/protocol/dce-rpc/Plugin.cc b/src/analyzer/protocol/dce-rpc/Plugin.cc new file mode 100644 index 0000000000..d9f3ce16c8 --- /dev/null +++ b/src/analyzer/protocol/dce-rpc/Plugin.cc @@ -0,0 +1,11 @@ + +#include "plugin/Plugin.h" + +#include "DCE_RPC.h" + +BRO_PLUGIN_BEGIN(Bro, DCE_RPC) + BRO_PLUGIN_DESCRIPTION("DCE-RPC analyzer"); + BRO_PLUGIN_ANALYZER("DCE_RPC", dce_rpc::DCE_RPC_Analyzer); + BRO_PLUGIN_SUPPORT_ANALYZER("Contents_DCE_RPC"); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/dce_rpc-analyzer.pac b/src/analyzer/protocol/dce-rpc/dce_rpc-analyzer.pac similarity index 100% rename from src/dce_rpc-analyzer.pac rename to src/analyzer/protocol/dce-rpc/dce_rpc-analyzer.pac diff --git a/src/dce_rpc-protocol.pac b/src/analyzer/protocol/dce-rpc/dce_rpc-protocol.pac similarity index 100% rename from src/dce_rpc-protocol.pac rename to src/analyzer/protocol/dce-rpc/dce_rpc-protocol.pac diff --git a/src/dce_rpc.pac b/src/analyzer/protocol/dce-rpc/dce_rpc.pac similarity index 83% rename from src/dce_rpc.pac rename to src/analyzer/protocol/dce-rpc/dce_rpc.pac index cbcd0cbdc4..632d2304a1 100644 --- a/src/dce_rpc.pac +++ b/src/analyzer/protocol/dce-rpc/dce_rpc.pac @@ -1,6 +1,10 @@ %include binpac.pac %include bro.pac +%extern{ +#include "events.bif.h" +%} + analyzer DCE_RPC withcontext { connection: DCE_RPC_Conn; flow: DCE_RPC_Flow; diff --git a/src/dce_rpc_simple.pac b/src/analyzer/protocol/dce-rpc/dce_rpc_simple.pac similarity index 92% rename from src/dce_rpc_simple.pac rename to src/analyzer/protocol/dce-rpc/dce_rpc_simple.pac index f31c2a078b..1bf0387b1d 100644 --- a/src/dce_rpc_simple.pac +++ b/src/analyzer/protocol/dce-rpc/dce_rpc_simple.pac @@ -1,5 +1,9 @@ %include bro.pac +%extern{ +#include "events.bif.h" +%} + analyzer DCE_RPC_Simple withcontext {}; %include dce_rpc-protocol.pac diff --git a/src/epmapper.pac b/src/analyzer/protocol/dce-rpc/epmapper.pac similarity index 100% rename from src/epmapper.pac rename to src/analyzer/protocol/dce-rpc/epmapper.pac diff --git a/src/analyzer/protocol/dce-rpc/events.bif b/src/analyzer/protocol/dce-rpc/events.bif new file mode 100644 index 0000000000..bdabb674fa --- /dev/null +++ b/src/analyzer/protocol/dce-rpc/events.bif @@ -0,0 +1,55 @@ +## TODO. +## +## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_request +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dce_rpc_message%(c: connection, is_orig: bool, ptype: dce_rpc_ptype, msg: string%); + +## TODO. +## +## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_message dce_rpc_request +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dce_rpc_bind%(c: connection, uuid: string%); + +## TODO. +## +## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dce_rpc_request%(c: connection, opnum: count, stub: string%); + +## TODO. +## +## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message +## dce_rpc_request rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dce_rpc_response%(c: connection, opnum: count, stub: string%); + +## TODO. +## +## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message +## dce_rpc_request dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event epm_map_response%(c: connection, uuid: string, p: port, h: addr%); + diff --git a/src/analyzer/protocol/dhcp/CMakeLists.txt b/src/analyzer/protocol/dhcp/CMakeLists.txt new file mode 100644 index 0000000000..646a11f9ab --- /dev/null +++ b/src/analyzer/protocol/dhcp/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro DHCP) +bro_plugin_cc(DHCP.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(dhcp.pac dhcp-protocol.pac dhcp-analyzer.pac) +bro_plugin_end() diff --git a/src/analyzer/protocol/dhcp/DHCP.cc b/src/analyzer/protocol/dhcp/DHCP.cc new file mode 100644 index 0000000000..8d05aef37d --- /dev/null +++ b/src/analyzer/protocol/dhcp/DHCP.cc @@ -0,0 +1,29 @@ + +#include "DHCP.h" + +#include "events.bif.h" + +using namespace analyzer::dhcp; + +DHCP_Analyzer::DHCP_Analyzer(Connection* conn) +: Analyzer("DHCP", conn) + { + interp = new binpac::DHCP::DHCP_Conn(this); + } + +DHCP_Analyzer::~DHCP_Analyzer() + { + delete interp; + } + +void DHCP_Analyzer::Done() + { + Analyzer::Done(); + } + +void DHCP_Analyzer::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); + } diff --git a/src/analyzer/protocol/dhcp/DHCP.h b/src/analyzer/protocol/dhcp/DHCP.h new file mode 100644 index 0000000000..a1c06e8b85 --- /dev/null +++ b/src/analyzer/protocol/dhcp/DHCP.h @@ -0,0 +1,28 @@ +#ifndef ANALYZER_PROTOCOL_DHCP_DHCP_H +#define ANALYZER_PROTOCOL_DHCP_DHCP_H + +#include "analyzer/protocol/udp/UDP.h" + +#include "dhcp_pac.h" + +namespace analyzer { namespace dhcp { + +class DHCP_Analyzer : public analyzer::Analyzer { +public: + DHCP_Analyzer(Connection* conn); + virtual ~DHCP_Analyzer(); + + virtual void Done(); + virtual void DeliverPacket(int len, const u_char* data, bool orig, + int seq, const IP_Hdr* ip, int caplen); + + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) + { return new DHCP_Analyzer(conn); } + +protected: + binpac::DHCP::DHCP_Conn* interp; +}; + +} } // namespace analyzer::* + +#endif diff --git a/src/analyzer/protocol/dhcp/Plugin.cc b/src/analyzer/protocol/dhcp/Plugin.cc new file mode 100644 index 0000000000..73603f8cb1 --- /dev/null +++ b/src/analyzer/protocol/dhcp/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "DHCP.h" + +BRO_PLUGIN_BEGIN(Bro, DHCP) + BRO_PLUGIN_DESCRIPTION("DHCP analyzer"); + BRO_PLUGIN_ANALYZER("DHCP", dhcp::DHCP_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/dhcp-analyzer.pac b/src/analyzer/protocol/dhcp/dhcp-analyzer.pac similarity index 100% rename from src/dhcp-analyzer.pac rename to src/analyzer/protocol/dhcp/dhcp-analyzer.pac diff --git a/src/dhcp-protocol.pac b/src/analyzer/protocol/dhcp/dhcp-protocol.pac similarity index 100% rename from src/dhcp-protocol.pac rename to src/analyzer/protocol/dhcp/dhcp-protocol.pac diff --git a/src/dhcp.pac b/src/analyzer/protocol/dhcp/dhcp.pac similarity index 79% rename from src/dhcp.pac rename to src/analyzer/protocol/dhcp/dhcp.pac index 9e9d7755a4..c4a684badc 100644 --- a/src/dhcp.pac +++ b/src/analyzer/protocol/dhcp/dhcp.pac @@ -1,5 +1,9 @@ %include bro.pac +%extern{ +#include "events.bif.h" +%} + analyzer DHCP withcontext { connection: DHCP_Conn; flow: DHCP_Flow; diff --git a/src/analyzer/protocol/dhcp/events.bif b/src/analyzer/protocol/dhcp/events.bif new file mode 100644 index 0000000000..741504185e --- /dev/null +++ b/src/analyzer/protocol/dhcp/events.bif @@ -0,0 +1,239 @@ +## Generated for DHCP messages of type *discover*. +## +## See `Wikipedia +## `__ for +## more information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow. +## +## msg: The parsed type-independent part of the DHCP message. +## +## req_addr: The specific address requested by the client. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +## +## .. note:: Bro does not support broadcast packets (as used by the DHCP +## protocol). It treats broadcast addresses just like any other and +## associates packets into transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dhcp_discover%(c: connection, msg: dhcp_msg, req_addr: addr%); + +## Generated for DHCP messages of type *offer*. +## +## See `Wikipedia +## `__ for +## more information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow. +## +## msg: TODO. +## +## mask: The subnet mask specified by the message. +## +## router: The list of routers specified by the message. +## +## lease: The least interval specified by the message. +## +## serv_addr: The server address specified by the message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note:: Bro does not support broadcast packets (as used by the DHCP +## protocol). It treats broadcast addresses just like any other and +## associates packets into transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dhcp_offer%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr%); + +## Generated for DHCP messages of type *request*. +## +## See `Wikipedia +## `__ for +## more information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow. +## +## msg: The parsed type-independent part of the DHCP message. +## +## req_addr: The client address specified by the message. +## +## serv_addr: The server address specified by the message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note:: Bro does not support broadcast packets (as used by the DHCP +## protocol). It treats broadcast addresses just like any other and +## associates packets into transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dhcp_request%(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr%); + +## Generated for DHCP messages of type *decline*. +## +## See `Wikipedia +## `__ for +## more information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow. +## +## msg: The parsed type-independent part of the DHCP message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note:: Bro does not support broadcast packets (as used by the DHCP +## protocol). It treats broadcast addresses just like any other and +## associates packets into transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dhcp_decline%(c: connection, msg: dhcp_msg%); + +## Generated for DHCP messages of type *acknowledgment*. +## +## See `Wikipedia +## `__ for +## more information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow. +## +## msg: The parsed type-independent part of the DHCP message. +## +## mask: The subnet mask specified by the message. +## +## router: The list of routers specified by the message. +## +## lease: The least interval specified by the message. +## +## serv_addr: The server address specified by the message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note:: Bro does not support broadcast packets (as used by the DHCP +## protocol). It treats broadcast addresses just like any other and +## associates packets into transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dhcp_ack%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr%); + +## Generated for DHCP messages of type *negative acknowledgment*. +## +## See `Wikipedia +## `__ for +## more information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow. +## +## msg: The parsed type-independent part of the DHCP message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note:: Bro does not support broadcast packets (as used by the DHCP +## protocol). It treats broadcast addresses just like any other and +## associates packets into transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dhcp_nak%(c: connection, msg: dhcp_msg%); + +## Generated for DHCP messages of type *release*. +## +## See `Wikipedia +## `__ for +## more information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow. +## +## msg: The parsed type-independent part of the DHCP message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note:: Bro does not support broadcast packets (as used by the DHCP +## protocol). It treats broadcast addresses just like any other and +## associates packets into transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dhcp_release%(c: connection, msg: dhcp_msg%); + +## Generated for DHCP messages of type *inform*. +## +## See `Wikipedia +## `__ for +## more information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow. +## +## msg: The parsed type-independent part of the DHCP message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note:: Bro does not support broadcast packets (as used by the DHCP +## protocol). It treats broadcast addresses just like any other and +## associates packets into transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event dhcp_inform%(c: connection, msg: dhcp_msg%); + diff --git a/src/analyzer/protocol/dns/CMakeLists.txt b/src/analyzer/protocol/dns/CMakeLists.txt new file mode 100644 index 0000000000..c63b2dc690 --- /dev/null +++ b/src/analyzer/protocol/dns/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro DNS) +bro_plugin_cc(DNS.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/DNS.cc b/src/analyzer/protocol/dns/DNS.cc similarity index 98% rename from src/DNS.cc rename to src/analyzer/protocol/dns/DNS.cc index a3b0b62ef3..4901df4417 100644 --- a/src/DNS.cc +++ b/src/analyzer/protocol/dns/DNS.cc @@ -12,7 +12,11 @@ #include "Sessions.h" #include "Event.h" -DNS_Interpreter::DNS_Interpreter(Analyzer* arg_analyzer) +#include "events.bif.h" + +using namespace analyzer::dns; + +DNS_Interpreter::DNS_Interpreter(analyzer::Analyzer* arg_analyzer) { analyzer = arg_analyzer; } @@ -993,7 +997,7 @@ Val* DNS_MsgInfo::BuildTSIG_Val() Contents_DNS::Contents_DNS(Connection* conn, bool orig, DNS_Interpreter* arg_interp) -: TCP_SupportAnalyzer(AnalyzerTag::Contents_DNS, conn, orig) +: tcp::TCP_SupportAnalyzer("CONTENTS_DNS", conn, orig) { interp = arg_interp; @@ -1080,7 +1084,7 @@ void Contents_DNS::DeliverStream(int len, const u_char* data, bool orig) } DNS_Analyzer::DNS_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::DNS, conn) +: tcp::TCP_ApplicationAnalyzer("DNS", conn) { interp = new DNS_Interpreter(this); contents_dns_orig = contents_dns_resp = 0; @@ -1112,7 +1116,7 @@ void DNS_Analyzer::Init() void DNS_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); if ( Conn()->ConnTransport() == TRANSPORT_UDP && ! did_session_done ) Event(udp_session_done); @@ -1123,7 +1127,7 @@ void DNS_Analyzer::Done() void DNS_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) { - TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); + tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); if ( orig ) { @@ -1141,10 +1145,10 @@ void DNS_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, } -void DNS_Analyzer::ConnectionClosed(TCP_Endpoint* endpoint, TCP_Endpoint* peer, +void DNS_Analyzer::ConnectionClosed(tcp::TCP_Endpoint* endpoint, tcp::TCP_Endpoint* peer, int gen_event) { - TCP_ApplicationAnalyzer::ConnectionClosed(endpoint, peer, gen_event); + tcp::TCP_ApplicationAnalyzer::ConnectionClosed(endpoint, peer, gen_event); assert(contents_dns_orig && contents_dns_resp); contents_dns_orig->Flush(); diff --git a/src/DNS.h b/src/analyzer/protocol/dns/DNS.h similarity index 93% rename from src/DNS.h rename to src/analyzer/protocol/dns/DNS.h index 83ca80911e..373250e8f4 100644 --- a/src/DNS.h +++ b/src/analyzer/protocol/dns/DNS.h @@ -1,11 +1,13 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef dns_h -#define dns_h +#ifndef ANALYZER_PROTOCOL_DNS_DNS_H +#define ANALYZER_PROTOCOL_DNS_DNS_H -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #include "binpac_bro.h" +namespace analyzer { namespace dns { + typedef enum { DNS_OP_QUERY = 0, ///< standard query DNS_OP_IQUERY = 1, ///< reverse query @@ -149,7 +151,7 @@ public: class DNS_Interpreter { public: - DNS_Interpreter(Analyzer* analyzer); + DNS_Interpreter(analyzer::Analyzer* analyzer); int ParseMessage(const u_char* data, int len, int is_query); @@ -217,7 +219,7 @@ protected: const u_char*& data, int& len, BroString* question_name); - Analyzer* analyzer; + analyzer::Analyzer* analyzer; }; @@ -229,7 +231,7 @@ typedef enum { // Support analyzer which chunks the TCP stream into "packets". // ### This should be merged with TCP_Contents_RPC. -class Contents_DNS : public TCP_SupportAnalyzer { +class Contents_DNS : public tcp::TCP_SupportAnalyzer { public: Contents_DNS(Connection* c, bool orig, DNS_Interpreter* interp); ~Contents_DNS(); @@ -251,7 +253,7 @@ protected: }; // Works for both TCP and UDP. -class DNS_Analyzer : public TCP_ApplicationAnalyzer { +class DNS_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: DNS_Analyzer(Connection* conn); ~DNS_Analyzer(); @@ -261,20 +263,14 @@ public: virtual void Init(); virtual void Done(); - virtual void ConnectionClosed(TCP_Endpoint* endpoint, - TCP_Endpoint* peer, int gen_event); + virtual void ConnectionClosed(tcp::TCP_Endpoint* endpoint, + tcp::TCP_Endpoint* peer, int gen_event); void ExpireTimer(double t); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new DNS_Analyzer(conn); } - static bool Available() - { - return (dns_request || dns_full_request) && - ! FLAGS_use_binpac; - } - protected: DNS_Interpreter* interp; Contents_DNS* contents_dns_orig; @@ -285,4 +281,6 @@ protected: // FIXME: Doesn't really fit into new analyzer structure. What to do? int IsReuse(double t, const u_char* pkt); +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/dns/Plugin.cc b/src/analyzer/protocol/dns/Plugin.cc new file mode 100644 index 0000000000..bb96692cd0 --- /dev/null +++ b/src/analyzer/protocol/dns/Plugin.cc @@ -0,0 +1,11 @@ + +#include "plugin/Plugin.h" + +#include "DNS.h" + +BRO_PLUGIN_BEGIN(Bro, DNS) + BRO_PLUGIN_DESCRIPTION("DNS analyzer"); + BRO_PLUGIN_ANALYZER("DNS", dns::DNS_Analyzer); + BRO_PLUGIN_SUPPORT_ANALYZER("Contents_DNS"); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/dns/events.bif b/src/analyzer/protocol/dns/events.bif new file mode 100644 index 0000000000..95c604a8b8 --- /dev/null +++ b/src/analyzer/protocol/dns/events.bif @@ -0,0 +1,482 @@ +## Generated for all DNS messages. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## msg: The parsed DNS message header. +## +## len: The length of the message's raw representation (i.e., the DNS payload). +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_query_reply dns_rejected +## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_message%(c: connection, is_orig: bool, msg: dns_msg, len: count%); + +## Generated for DNS requests. For requests with multiple queries, this event +## is raised once for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## query: The queried name. +## +## qtype: The queried resource record type. +## +## qclass: The queried resource record class. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_request%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%); + +## Generated for DNS replies that reject a query. This event is raised if a DNS +## reply either indicates failure via its status code or does not pass on any +## answers to a query. Note that all of the event's parameters are parsed out of +## the reply; there's no stateful correlation with the query. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## query: The queried name. +## +## qtype: The queried resource record type. +## +## qclass: The queried resource record class. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_rejected%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%); + +## Generated for DNS replies with an *ok* status code but no question section. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## query: The queried name. +## +## qtype: The queried resource record type. +## +## qclass: The queried resource record class. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_rejected +## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_query_reply%(c: connection, msg: dns_msg, query: string, + qtype: count, qclass: count%); + +## Generated for DNS replies of type *A*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## a: The address returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A6_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply +## dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_A_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%); + +## Generated for DNS replies of type *AAAA*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## a: The address returned by the reply. +## +## .. bro:see:: dns_A_reply dns_A6_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply +## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl +## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request +## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_AAAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%); + +## Generated for DNS replies of type *A6*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## a: The address returned by the reply. +## +## .. bro:see:: dns_A_reply dns_AAAA_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply +## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl +## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request +## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_A6_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%); + +## Generated for DNS replies of type *NS*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## name: The name returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_NS_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%); + +## Generated for DNS replies of type *CNAME*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## name: The name returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply +## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl +## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request +## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_CNAME_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%); + +## Generated for DNS replies of type *PTR*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## name: The name returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_SOA_reply dns_SRV_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_PTR_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%); + +## Generated for DNS replies of type *CNAME*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## soa: The parsed SOA value. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SRV_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_SOA_reply%(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa%); + +## Generated for DNS replies of type *WKS*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_WKS_reply%(c: connection, msg: dns_msg, ans: dns_answer%); + +## Generated for DNS replies of type *HINFO*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl dns_MX_reply +## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl +## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request +## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_HINFO_reply%(c: connection, msg: dns_msg, ans: dns_answer%); + +## Generated for DNS replies of type *MX*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## name: The name returned by the reply. +## +## preference: The preference for *name* specified by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_MX_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string, preference: count%); + +## Generated for DNS replies of type *TXT*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## str: The textual information returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, str: string%); + +## Generated for DNS replies of type *SRV*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_SRV_reply%(c: connection, msg: dns_msg, ans: dns_answer%); + +## Generated for DNS replies of type *EDNS*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The parsed EDNS reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_HINFO_reply dns_MX_reply +## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl +## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request +## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_EDNS_addl%(c: connection, msg: dns_msg, ans: dns_edns_additional%); + +## Generated for DNS replies of type *TSIG*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The parsed TSIG reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_TSIG_addl%(c: connection, msg: dns_msg, ans: dns_tsig_additional%); + +## Generated at the end of processing a DNS packet. This event is the last +## ``dns_*`` event that will be raised for a DNS query/reply and signals that +## all resource records have been passed on. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_end%(c: connection, msg: dns_msg%); + +## Deprecated. Will be removed. +## +## .. todo:: Unclear what this event is for; it's never raised. We should just +## remove it. +event dns_full_request%(%); + +## msg: The raw DNS payload. +## +## .. note:: This event is deprecated and superseded by Bro's dynamic protocol +## detection framework. +event non_dns_request%(c: connection, msg: string%); diff --git a/src/analyzer/protocol/file/CMakeLists.txt b/src/analyzer/protocol/file/CMakeLists.txt new file mode 100644 index 0000000000..978c28c9c4 --- /dev/null +++ b/src/analyzer/protocol/file/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro File) +bro_plugin_cc(File.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/FileAnalyzer.cc b/src/analyzer/protocol/file/File.cc similarity index 71% rename from src/FileAnalyzer.cc rename to src/analyzer/protocol/file/File.cc index a43bba2246..d05e85df5d 100644 --- a/src/FileAnalyzer.cc +++ b/src/analyzer/protocol/file/File.cc @@ -1,19 +1,24 @@ #include +#include "File.h" + #include "file_analysis/Manager.h" -#include "FileAnalyzer.h" #include "Reporter.h" #include "util.h" -File_Analyzer::File_Analyzer(AnalyzerTag::Tag tag, Connection* conn) -: TCP_ApplicationAnalyzer(tag, conn) +#include "events.bif.h" + +using namespace analyzer::file; + +File_Analyzer::File_Analyzer(const char* name, Connection* conn) + : TCP_ApplicationAnalyzer(name, conn) { buffer_len = 0; } void File_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { - TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); int n = min(len, BUFFER_SIZE - buffer_len); @@ -35,7 +40,7 @@ void File_Analyzer::Undelivered(int seq, int len, bool orig) void File_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); if ( buffer_len && buffer_len != BUFFER_SIZE ) Identify(); @@ -55,47 +60,47 @@ void File_Analyzer::Identify() } IRC_Data::IRC_Data(Connection* conn) - : File_Analyzer(AnalyzerTag::IRC_Data, conn) + : File_Analyzer("IRC_Data", conn) { } void IRC_Data::Done() { File_Analyzer::Done(); - file_mgr->EndOfFile(GetTag(), Conn()); + file_mgr->EndOfFile(GetAnalyzerTag(), Conn()); } void IRC_Data::DeliverStream(int len, const u_char* data, bool orig) { File_Analyzer::DeliverStream(len, data, orig); - file_mgr->DataIn(data, len, GetTag(), Conn(), orig); + file_mgr->DataIn(data, len, GetAnalyzerTag(), Conn(), orig); } void IRC_Data::Undelivered(int seq, int len, bool orig) { File_Analyzer::Undelivered(seq, len, orig); - file_mgr->Gap(seq, len, GetTag(), Conn(), orig); + file_mgr->Gap(seq, len, GetAnalyzerTag(), Conn(), orig); } FTP_Data::FTP_Data(Connection* conn) - : File_Analyzer(AnalyzerTag::FTP_Data, conn) + : File_Analyzer("FTP_Data", conn) { } void FTP_Data::Done() { File_Analyzer::Done(); - file_mgr->EndOfFile(GetTag(), Conn()); + file_mgr->EndOfFile(GetAnalyzerTag(), Conn()); } void FTP_Data::DeliverStream(int len, const u_char* data, bool orig) { File_Analyzer::DeliverStream(len, data, orig); - file_mgr->DataIn(data, len, GetTag(), Conn(), orig); + file_mgr->DataIn(data, len, GetAnalyzerTag(), Conn(), orig); } void FTP_Data::Undelivered(int seq, int len, bool orig) { File_Analyzer::Undelivered(seq, len, orig); - file_mgr->Gap(seq, len, GetTag(), Conn(), orig); + file_mgr->Gap(seq, len, GetAnalyzerTag(), Conn(), orig); } diff --git a/src/FileAnalyzer.h b/src/analyzer/protocol/file/File.h similarity index 61% rename from src/FileAnalyzer.h rename to src/analyzer/protocol/file/File.h index 59ec5cdb37..7afbd569c4 100644 --- a/src/FileAnalyzer.h +++ b/src/analyzer/protocol/file/File.h @@ -1,15 +1,17 @@ // Analyzer for connections that transfer binary data. -#ifndef FILEANALYZER_H -#define FILEANALYZER_H +#ifndef ANALYZER_PROTOCOL_FILE_FILE_H +#define ANALYZER_PROTOCOL_FILE_FILE_H -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #include -class File_Analyzer : public TCP_ApplicationAnalyzer { +namespace analyzer { namespace file { + +class File_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: - File_Analyzer(AnalyzerTag::Tag tag, Connection* conn); + File_Analyzer(const char* name, Connection* conn); virtual void Done(); @@ -17,14 +19,10 @@ public: void Undelivered(int seq, int len, bool orig); - static Analyzer* InstantiateAnalyzer(Connection* conn) - { return new File_Analyzer(AnalyzerTag::File, conn); } - - static bool Available() { return file_transferred; } +// static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) +// { return new File_Analyzer(conn); } protected: - File_Analyzer() {} - void Identify(); static const int BUFFER_SIZE = 1024; @@ -34,36 +32,32 @@ protected: class IRC_Data : public File_Analyzer { public: - IRC_Data(Connection* conn); virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(int seq, int len, bool orig); static Analyzer* InstantiateAnalyzer(Connection* conn) { return new IRC_Data(conn); } - - static bool Available() { return true; } }; class FTP_Data : public File_Analyzer { public: - FTP_Data(Connection* conn); virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - void Undelivered(int seq, int len, bool orig); + virtual void Undelivered(int seq, int len, bool orig); static Analyzer* InstantiateAnalyzer(Connection* conn) { return new FTP_Data(conn); } - - static bool Available() { return true; } }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/file/Plugin.cc b/src/analyzer/protocol/file/Plugin.cc new file mode 100644 index 0000000000..6e6adae90c --- /dev/null +++ b/src/analyzer/protocol/file/Plugin.cc @@ -0,0 +1,11 @@ + +#include "plugin/Plugin.h" + +#include "./File.h" + +BRO_PLUGIN_BEGIN(Bro, File) + BRO_PLUGIN_DESCRIPTION("Generic file analyzer"); + BRO_PLUGIN_ANALYZER("FTP_Data", file::FTP_Data); + BRO_PLUGIN_ANALYZER("IRC_Data", file::IRC_Data); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/file/events.bif b/src/analyzer/protocol/file/events.bif new file mode 100644 index 0000000000..4277f1975f --- /dev/null +++ b/src/analyzer/protocol/file/events.bif @@ -0,0 +1,3 @@ +## TODO. +## +event file_transferred%(c: connection, prefix: string, descr: string, mime_type: string%); diff --git a/src/analyzer/protocol/finger/CMakeLists.txt b/src/analyzer/protocol/finger/CMakeLists.txt new file mode 100644 index 0000000000..52dd3816f9 --- /dev/null +++ b/src/analyzer/protocol/finger/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro Finger) +bro_plugin_cc(Finger.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/Finger.cc b/src/analyzer/protocol/finger/Finger.cc similarity index 80% rename from src/Finger.cc rename to src/analyzer/protocol/finger/Finger.cc index be0f3754b5..bf9bdcc68a 100644 --- a/src/Finger.cc +++ b/src/analyzer/protocol/finger/Finger.cc @@ -7,27 +7,31 @@ #include "NetVar.h" #include "Finger.h" #include "Event.h" -#include "ContentLine.h" +#include "analyzer/protocol/tcp/ContentLine.h" + +#include "events.bif.h" + +using namespace analyzer::finger; Finger_Analyzer::Finger_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::Finger, conn) +: tcp::TCP_ApplicationAnalyzer("FINGER", conn) { did_deliver = 0; - content_line_orig = new ContentLine_Analyzer(conn, true); + content_line_orig = new tcp::ContentLine_Analyzer(conn, true); content_line_orig->SetIsNULSensitive(true); - content_line_resp = new ContentLine_Analyzer(conn, false); + content_line_resp = new tcp::ContentLine_Analyzer(conn, false); AddSupportAnalyzer(content_line_orig); AddSupportAnalyzer(content_line_resp); } void Finger_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); if ( TCP() ) if ( (! did_deliver || content_line_orig->HasPartialLine()) && - (TCP()->OrigState() == TCP_ENDPOINT_CLOSED || - TCP()->OrigPrevState() == TCP_ENDPOINT_CLOSED) ) + (TCP()->OrigState() == tcp::TCP_ENDPOINT_CLOSED || + TCP()->OrigPrevState() == tcp::TCP_ENDPOINT_CLOSED) ) // ### should include the partial text Weird("partial_finger_request"); } diff --git a/src/analyzer/protocol/finger/Finger.h b/src/analyzer/protocol/finger/Finger.h new file mode 100644 index 0000000000..efea0fae6b --- /dev/null +++ b/src/analyzer/protocol/finger/Finger.h @@ -0,0 +1,31 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef ANALYZER_PROTOCOL_FINGER_FINGER_H +#define ANALYZER_PROTOCOL_FINGER_FINGER_H + +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/tcp/ContentLine.h" + +namespace analyzer { namespace finger { + +class Finger_Analyzer : public tcp::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::Analyzer* InstantiateAnalyzer(Connection* conn) + { return new Finger_Analyzer(conn); } + +protected: + tcp::ContentLine_Analyzer* content_line_orig; + tcp::ContentLine_Analyzer* content_line_resp; + int did_deliver; +}; + +} } // namespace analyzer::* + +#endif diff --git a/src/analyzer/protocol/finger/Plugin.cc b/src/analyzer/protocol/finger/Plugin.cc new file mode 100644 index 0000000000..6cf909ca54 --- /dev/null +++ b/src/analyzer/protocol/finger/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "Finger.h" + +BRO_PLUGIN_BEGIN(Bro, Finger) + BRO_PLUGIN_DESCRIPTION("Finger analyzer"); + BRO_PLUGIN_ANALYZER("Finger", finger::Finger_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/finger/events.bif b/src/analyzer/protocol/finger/events.bif new file mode 100644 index 0000000000..e495263b12 --- /dev/null +++ b/src/analyzer/protocol/finger/events.bif @@ -0,0 +1,38 @@ +## Generated for Finger requests. +## +## See `Wikipedia `__ for more +## information about the Finger protocol. +## +## c: The connection. +## +## full: True if verbose information is requested (``/W`` switch). +## +## username: The request's user name. +## +## hostname: The request's host name. +## +## .. bro:see:: finger_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event finger_request%(c: connection, full: bool, username: string, hostname: string%); + +## Generated for Finger replies. +## +## See `Wikipedia `__ for more +## information about the Finger protocol. +## +## c: The connection. +## +## reply_line: The reply as returned by the server +## +## .. bro:see:: finger_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event finger_reply%(c: connection, reply_line: string%); + diff --git a/src/analyzer/protocol/ftp/CMakeLists.txt b/src/analyzer/protocol/ftp/CMakeLists.txt new file mode 100644 index 0000000000..ab657f9260 --- /dev/null +++ b/src/analyzer/protocol/ftp/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro FTP) +bro_plugin_cc(FTP.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_bif(functions.bif) +bro_plugin_end() diff --git a/src/FTP.cc b/src/analyzer/protocol/ftp/FTP.cc similarity index 89% rename from src/FTP.cc rename to src/analyzer/protocol/ftp/FTP.cc index 5e7a66e304..91afe6f8a4 100644 --- a/src/FTP.cc +++ b/src/analyzer/protocol/ftp/FTP.cc @@ -6,23 +6,27 @@ #include "NetVar.h" #include "FTP.h" -#include "NVT.h" #include "Event.h" -#include "SSL.h" #include "Base64.h" +#include "analyzer/Manager.h" +#include "analyzer/protocol/login/NVT.h" + +#include "events.bif.h" + +using namespace analyzer::ftp; FTP_Analyzer::FTP_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::FTP, conn) +: tcp::TCP_ApplicationAnalyzer("FTP", conn) { pending_reply = 0; - nvt_orig = new NVT_Analyzer(conn, true); + nvt_orig = new login::NVT_Analyzer(conn, true); nvt_orig->SetIsNULSensitive(true); nvt_orig->SetIsNULSensitive(true); nvt_orig->SetCRLFAsEOL(LF_as_EOL); nvt_orig->SetIsNULSensitive(LF_as_EOL); - nvt_resp = new NVT_Analyzer(conn, false); + nvt_resp = new login::NVT_Analyzer(conn, false); nvt_resp->SetIsNULSensitive(true); nvt_resp->SetIsNULSensitive(true); nvt_resp->SetCRLFAsEOL(LF_as_EOL); @@ -37,11 +41,11 @@ FTP_Analyzer::FTP_Analyzer(Connection* conn) void FTP_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); if ( nvt_orig->HasPartialLine() && - (TCP()->OrigState() == TCP_ENDPOINT_CLOSED || - TCP()->OrigPrevState() == TCP_ENDPOINT_CLOSED) ) + (TCP()->OrigState() == tcp::TCP_ENDPOINT_CLOSED || + TCP()->OrigPrevState() == tcp::TCP_ENDPOINT_CLOSED) ) // ### should include the partial text Weird("partial_ftp_request"); } @@ -56,7 +60,7 @@ static uint32 get_reply_code(int len, const char* line) void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig) { - TCP_ApplicationAnalyzer::DeliverStream(length, data, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(length, data, orig); if ( (orig && ! ftp_request) || (! orig && ! ftp_reply) ) return; @@ -154,10 +158,13 @@ void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig) // Server wants to proceed with an ADAT exchange and we // know how to analyze the GSI mechanism, so attach analyzer // to look for that. - SSL_Analyzer* ssl = new SSL_Analyzer(Conn()); - ssl->AddSupportAnalyzer(new FTP_ADAT_Analyzer(Conn(), true)); - ssl->AddSupportAnalyzer(new FTP_ADAT_Analyzer(Conn(), false)); - AddChildAnalyzer(ssl); + Analyzer* ssl = analyzer_mgr->InstantiateAnalyzer("SSL", Conn()); + if ( ssl ) + { + ssl->AddSupportAnalyzer(new FTP_ADAT_Analyzer(Conn(), true)); + ssl->AddSupportAnalyzer(new FTP_ADAT_Analyzer(Conn(), false)); + AddChildAnalyzer(ssl); + } } vl->append(new Val(reply_code, TYPE_COUNT)); @@ -176,7 +183,7 @@ void FTP_ADAT_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { // Don't know how to parse anything but the ADAT exchanges of GSI GSSAPI, // which is basically just TLS/SSL. - if ( ! Parent()->GetTag() == AnalyzerTag::SSL ) + if ( ! Parent()->IsAnalyzer("SSL") ) { Parent()->Remove(); return; diff --git a/src/FTP.h b/src/analyzer/protocol/ftp/FTP.h similarity index 68% rename from src/FTP.h rename to src/analyzer/protocol/ftp/FTP.h index f8d7644808..1cffa19b1d 100644 --- a/src/FTP.h +++ b/src/analyzer/protocol/ftp/FTP.h @@ -1,31 +1,28 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef ftp_h -#define ftp_h +#ifndef ANALYZER_PROTOCOL_FTP_FTP_H +#define ANALYZER_PROTOCOL_FTP_FTP_H -#include "NVT.h" -#include "TCP.h" +#include "analyzer/protocol/login/NVT.h" +#include "analyzer/protocol/tcp/TCP.h" -class FTP_Analyzer : public TCP_ApplicationAnalyzer { +namespace analyzer { namespace ftp { + +class FTP_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: FTP_Analyzer(Connection* conn); virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new FTP_Analyzer(conn); } - static bool Available() { return ftp_request || ftp_reply; } - - protected: - FTP_Analyzer() {} - - NVT_Analyzer* nvt_orig; - NVT_Analyzer* nvt_resp; + login::NVT_Analyzer* nvt_orig; + login::NVT_Analyzer* nvt_resp; uint32 pending_reply; // code associated with multi-line reply, or 0 string auth_requested; // AUTH method requested }; @@ -37,10 +34,10 @@ protected: * analyzer just decodes the tokens and passes them on to the parent, which must * be an SSL analyzer instance. */ -class FTP_ADAT_Analyzer : public SupportAnalyzer { +class FTP_ADAT_Analyzer : public analyzer::SupportAnalyzer { public: FTP_ADAT_Analyzer(Connection* conn, bool arg_orig) - : SupportAnalyzer(AnalyzerTag::FTP_ADAT, conn, arg_orig), + : SupportAnalyzer("FTP_ADAT", conn, arg_orig), first_token(true) { } void DeliverStream(int len, const u_char* data, bool orig); @@ -52,4 +49,6 @@ protected: bool first_token; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/ftp/Plugin.cc b/src/analyzer/protocol/ftp/Plugin.cc new file mode 100644 index 0000000000..db8e20e7ed --- /dev/null +++ b/src/analyzer/protocol/ftp/Plugin.cc @@ -0,0 +1,12 @@ + +#include "plugin/Plugin.h" + +#include "FTP.h" + +BRO_PLUGIN_BEGIN(Bro, FTP) + BRO_PLUGIN_DESCRIPTION("FTP analyzer"); + BRO_PLUGIN_ANALYZER("FTP", ftp::FTP_Analyzer); + BRO_PLUGIN_SUPPORT_ANALYZER("FTP_ADAT"); + BRO_PLUGIN_BIF_FILE(events); + BRO_PLUGIN_BIF_FILE(functions); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/ftp/events.bif b/src/analyzer/protocol/ftp/events.bif new file mode 100644 index 0000000000..16faa417d3 --- /dev/null +++ b/src/analyzer/protocol/ftp/events.bif @@ -0,0 +1,35 @@ +## Generated for client-side FTP commands. +## +## See `Wikipedia `__ for +## more information about the FTP protocol. +## +## c: The connection. +## +## command: The FTP command issued by the client (without any arguments). +## +## arg: The arguments going with the command. +## +## .. bro:see:: ftp_reply fmt_ftp_port parse_eftp_port +## parse_ftp_epsv parse_ftp_pasv parse_ftp_port +event ftp_request%(c: connection, command: string, arg: string%); + +## Generated for server-side FTP replies. +## +## See `Wikipedia `__ for +## more information about the FTP protocol. +## +## c: The connection. +## +## code: The numerical response code the server responded with. +## +## msg: The textual message of the response. +## +## cont_resp: True if the reply line is tagged as being continued to the next +## line. If so, further events will be raised and a handler may want +## to reassemble the pieces before processing the response any +## further. +## +## .. bro:see:: ftp_request fmt_ftp_port parse_eftp_port +## parse_ftp_epsv parse_ftp_pasv parse_ftp_port +event ftp_reply%(c: connection, code: count, msg: string, cont_resp: bool%); + diff --git a/src/analyzer/protocol/ftp/functions.bif b/src/analyzer/protocol/ftp/functions.bif new file mode 100644 index 0000000000..a667d8ca88 --- /dev/null +++ b/src/analyzer/protocol/ftp/functions.bif @@ -0,0 +1,220 @@ + +type ftp_port: record; + +%%{ + +static Val* parse_port(const char* line) + { + RecordVal* r = new RecordVal(BifType::Record::ftp_port); + + int bytes[6]; + if ( line && sscanf(line, "%d,%d,%d,%d,%d,%d", + &bytes[0], &bytes[1], &bytes[2], + &bytes[3], &bytes[4], &bytes[5]) == 6 ) + { + int good = 1; + + for ( int i = 0; i < 6; ++i ) + if ( bytes[i] < 0 || bytes[i] > 255 ) + { + good = 0; + break; + } + + uint32 addr = (bytes[0] << 24) | (bytes[1] << 16) | + (bytes[2] << 8) | bytes[3]; + uint32 port = (bytes[4] << 8) | bytes[5]; + + // Since port is unsigned, no need to check for < 0. + if ( port > 65535 ) + { + port = 0; + good = 0; + } + + r->Assign(0, new AddrVal(htonl(addr))); + r->Assign(1, new PortVal(port, TRANSPORT_TCP)); + r->Assign(2, new Val(good, TYPE_BOOL)); + } + else + { + r->Assign(0, new AddrVal(uint32(0))); + r->Assign(1, new PortVal(0, TRANSPORT_TCP)); + r->Assign(2, new Val(0, TYPE_BOOL)); + } + + return r; + } + +static Val* parse_eftp(const char* line) + { + RecordVal* r = new RecordVal(BifType::Record::ftp_port); + + int net_proto = 0; // currently not used + IPAddr addr; // unspecified IPv6 address (all 128 bits zero) + int port = 0; + int good = 0; + + if ( line ) + { + while ( isspace(*line) ) // skip whitespace + ++line; + + char delimiter = *line; + char* next_delim; + + if ( *line ) + { + good = 1; + ++line; // skip delimiter + + net_proto = strtol(line, &next_delim, 10); + if ( *next_delim != delimiter ) + good = 0; + + line = next_delim; + if ( *line ) + ++line; + + if ( *line && *line != delimiter ) + { + const char* nptr = strchr(line, delimiter); + if ( nptr == NULL ) + { + nptr = line + strlen(line); + good = 0; + } + + string s(line, nptr-line); // extract IP address + IPAddr tmp(s); + // on error, "tmp" will have all 128 bits zero + if ( tmp == addr ) + good = 0; + + addr = tmp; + } + + line = strchr(line, delimiter); + + if ( line != NULL ) + { + ++line; // now the port + port = strtol(line, &next_delim, 10); + if ( *next_delim != delimiter ) + good = 0; + } + + } + + } + + r->Assign(0, new AddrVal(addr)); + r->Assign(1, new PortVal(port, TRANSPORT_TCP)); + r->Assign(2, new Val(good, TYPE_BOOL)); + + return r; + } +%%} + +## Converts a string representation of the FTP PORT command to an ``ftp_port``. +## +## s: The string of the FTP PORT command, e.g., ``"10,0,0,1,4,31"``. +## +## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` +## +## .. bro:see:: parse_eftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port +function parse_ftp_port%(s: string%): ftp_port + %{ + return parse_port(s->CheckString()); + %} + +## Converts a string representation of the FTP EPRT command to an ``ftp_port``. +## See `RFC 2428 `_. +## The format is ``EPRT``, +## where ```` is a delimiter in the ASCII range 33-126 (usually ``|``). +## +## s: The string of the FTP EPRT command, e.g., ``"|1|10.0.0.1|1055|"``. +## +## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` +## +## .. bro:see:: parse_ftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port +function parse_eftp_port%(s: string%): ftp_port + %{ + return parse_eftp(s->CheckString()); + %} + +## Converts the result of the FTP PASV command to an ``ftp_port``. +## +## str: The string containing the result of the FTP PASV command. +## +## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` +## +## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_epsv fmt_ftp_port +function parse_ftp_pasv%(str: string%): ftp_port + %{ + const char* s = str->CheckString(); + const char* line = strchr(s, '('); + if ( line ) + ++line; // move past '(' + else if ( (line = strstr(s, "PORT")) ) + line += 5; // Skip over + else if ( (line = strchr(s, ',')) ) + { // Look for comma-separated list. + while ( --line >= s && isdigit(*line) ) + ; // Back up over preceding digits. + ++line; // now points to first digit, or beginning of s + } + + return parse_port(line); + %} + +## Converts the result of the FTP EPSV command to an ``ftp_port``. +## See `RFC 2428 `_. +## The format is `` ()``, where ```` is a +## delimiter in the ASCII range 33-126 (usually ``|``). +## +## str: The string containing the result of the FTP EPSV command. +## +## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` +## +## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv fmt_ftp_port +function parse_ftp_epsv%(str: string%): ftp_port + %{ + const char* s = str->CheckString(); + const char* line = strchr(s, '('); + if ( line ) + ++line; // move past '(' + return parse_eftp(line); + %} + +## Formats an IP address and TCP port as an FTP PORT command. For example, +## ``10.0.0.1`` and ``1055/tcp`` yields ``"10,0,0,1,4,31"``. +## +## a: The IP address. +## +## p: The TCP port. +## +## Returns: The FTP PORT string. +## +## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv parse_ftp_epsv +function fmt_ftp_port%(a: addr, p: port%): string + %{ + const uint32* addr; + int len = a->AsAddr().GetBytes(&addr); + if ( len == 1 ) + { + uint32 a = ntohl(addr[0]); + uint32 pn = p->Port(); + return new StringVal(fmt("%d,%d,%d,%d,%d,%d", + a >> 24, (a >> 16) & 0xff, + (a >> 8) & 0xff, a & 0xff, + pn >> 8, pn & 0xff)); + } + else + { + builtin_error("conversion of non-IPv4 address in fmt_ftp_port", + @ARG@[0]); + return new StringVal(""); + } + %} + diff --git a/src/analyzer/protocol/gnutella/CMakeLists.txt b/src/analyzer/protocol/gnutella/CMakeLists.txt new file mode 100644 index 0000000000..ee5415b924 --- /dev/null +++ b/src/analyzer/protocol/gnutella/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro Gnutella) +bro_plugin_cc(Gnutella.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/Gnutella.cc b/src/analyzer/protocol/gnutella/Gnutella.cc similarity index 92% rename from src/Gnutella.cc rename to src/analyzer/protocol/gnutella/Gnutella.cc index 6b5e901bc5..c0bab92007 100644 --- a/src/Gnutella.cc +++ b/src/analyzer/protocol/gnutella/Gnutella.cc @@ -7,10 +7,14 @@ #include #include "NetVar.h" -#include "HTTP.h" #include "Gnutella.h" #include "Event.h" -#include "PIA.h" +#include "analyzer/protocol/pia/PIA.h" +#include "analyzer/Manager.h" + +#include "events.bif.h" + +using namespace analyzer::gnutella; GnutellaMsgState::GnutellaMsgState() { @@ -30,7 +34,7 @@ GnutellaMsgState::GnutellaMsgState() Gnutella_Analyzer::Gnutella_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::Gnutella, conn) +: tcp::TCP_ApplicationAnalyzer("GNUTELLA", conn) { state = 0; new_state = 0; @@ -50,7 +54,7 @@ Gnutella_Analyzer::~Gnutella_Analyzer() void Gnutella_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); if ( ! sent_establish && (gnutella_establish || gnutella_not_establish) ) { @@ -129,17 +133,18 @@ int Gnutella_Analyzer::IsHTTP(string header) ConnectionEvent(gnutella_http_notify, vl); } - if ( HTTP_Analyzer::Available() ) + analyzer::Analyzer* a = analyzer_mgr->InstantiateAnalyzer("HTTP", Conn()); + + if ( a ) { - Analyzer* a = new HTTP_Analyzer(Conn()); Parent()->AddChildAnalyzer(a); - if ( Parent()->GetTag() == AnalyzerTag::TCP ) + if ( Parent()->IsAnalyzer("TCP") ) { // Replay buffered data. - PIA* pia = static_cast(Parent())->GetPIA(); + pia::PIA* pia = static_cast(Parent())->GetPIA(); if ( pia ) - static_cast(pia)->ReplayStreamBuffer(a); + static_cast(pia)->ReplayStreamBuffer(a); } Parent()->RemoveChildAnalyzer(this); @@ -327,7 +332,7 @@ void Gnutella_Analyzer::DeliverMessages(int len, const u_char* data, bool orig) void Gnutella_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { - TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); ms = orig ? orig_msg_state : resp_msg_state; ms->current_offset = 0; diff --git a/src/Gnutella.h b/src/analyzer/protocol/gnutella/Gnutella.h similarity index 78% rename from src/Gnutella.h rename to src/analyzer/protocol/gnutella/Gnutella.h index 455876462d..11d51cf276 100644 --- a/src/Gnutella.h +++ b/src/analyzer/protocol/gnutella/Gnutella.h @@ -1,9 +1,9 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef gnutella_h -#define gnutella_h +#ifndef ANALYZER_PROTOCOL_GNUTELLA_GNUTELLA_H +#define ANALYZER_PROTOCOL_GNUTELLA_GNUTELLA_H -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #define ORIG_OK 0x1 #define RESP_OK 0x2 @@ -11,6 +11,8 @@ #define GNUTELLA_MSG_SIZE 23 #define GNUTELLA_MAX_PAYLOAD 1024 +namespace analyzer { namespace gnutella { + class GnutellaMsgState { public: GnutellaMsgState (); @@ -32,7 +34,7 @@ public: }; -class Gnutella_Analyzer : public TCP_ApplicationAnalyzer { +class Gnutella_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: Gnutella_Analyzer(Connection* conn); ~Gnutella_Analyzer(); @@ -40,16 +42,9 @@ public: virtual void Done (); virtual void DeliverStream(int len, const u_char* data, bool orig); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new Gnutella_Analyzer(conn); } - static bool Available() - { - return gnutella_text_msg || gnutella_binary_msg || - gnutella_partial_binary_msg || gnutella_establish || - gnutella_not_establish || gnutella_http_notify; - } - private: int NextLine(const u_char* data, int len); @@ -74,4 +69,6 @@ private: GnutellaMsgState* ms; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/gnutella/Plugin.cc b/src/analyzer/protocol/gnutella/Plugin.cc new file mode 100644 index 0000000000..73b91af002 --- /dev/null +++ b/src/analyzer/protocol/gnutella/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "Gnutella.h" + +BRO_PLUGIN_BEGIN(Bro, Gnutella) + BRO_PLUGIN_DESCRIPTION("Gnutella analyzer"); + BRO_PLUGIN_ANALYZER("Gnutella", gnutella::Gnutella_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/gnutella/events.bif b/src/analyzer/protocol/gnutella/events.bif new file mode 100644 index 0000000000..9384f34e88 --- /dev/null +++ b/src/analyzer/protocol/gnutella/events.bif @@ -0,0 +1,88 @@ +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify +## gnutella_not_establish gnutella_partial_binary_msg gnutella_signature_found +## +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event gnutella_text_msg%(c: connection, orig: bool, headers: string%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_establish gnutella_http_notify gnutella_not_establish +## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event gnutella_binary_msg%(c: connection, orig: bool, msg_type: count, + ttl: count, hops: count, msg_len: count, + payload: string, payload_len: count, + trunc: bool, complete: bool%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify +## gnutella_not_establish gnutella_signature_found gnutella_text_msg +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event gnutella_partial_binary_msg%(c: connection, orig: bool, + msg: string, len: count%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_binary_msg gnutella_http_notify gnutella_not_establish +## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event gnutella_establish%(c: connection%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify +## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event gnutella_not_establish%(c: connection%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_not_establish +## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event gnutella_http_notify%(c: connection%); diff --git a/src/analyzer/protocol/gtpv1/CMakeLists.txt b/src/analyzer/protocol/gtpv1/CMakeLists.txt new file mode 100644 index 0000000000..b45f32e883 --- /dev/null +++ b/src/analyzer/protocol/gtpv1/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro GTPv1) +bro_plugin_cc(GTPv1.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(gtpv1.pac gtpv1-protocol.pac gtpv1-analyzer.pac) +bro_plugin_end() diff --git a/src/GTPv1.cc b/src/analyzer/protocol/gtpv1/GTPv1.cc similarity index 78% rename from src/GTPv1.cc rename to src/analyzer/protocol/gtpv1/GTPv1.cc index 68b6f30a0c..0a94a28554 100644 --- a/src/GTPv1.cc +++ b/src/analyzer/protocol/gtpv1/GTPv1.cc @@ -1,7 +1,13 @@ +// See the file "COPYING" in the main distribution directory for copyright. + #include "GTPv1.h" +#include "events.bif.h" + +using namespace analyzer::gtpv1; + GTPv1_Analyzer::GTPv1_Analyzer(Connection* conn) -: Analyzer(AnalyzerTag::GTPv1, conn) +: Analyzer("GTPV1", conn) { interp = new binpac::GTPv1::GTPv1_Conn(this); } diff --git a/src/GTPv1.h b/src/analyzer/protocol/gtpv1/GTPv1.h similarity index 56% rename from src/GTPv1.h rename to src/analyzer/protocol/gtpv1/GTPv1.h index e111158833..b58405ea7f 100644 --- a/src/GTPv1.h +++ b/src/analyzer/protocol/gtpv1/GTPv1.h @@ -1,9 +1,11 @@ -#ifndef GTPv1_h -#define GTPv1_h +#ifndef ANALYZER_PROTOCOL_GTPV1_GTPV1_H +#define ANALYZER_PROTOCOL_GTPV1_GTPV1_H #include "gtpv1_pac.h" -class GTPv1_Analyzer : public Analyzer { +namespace analyzer { namespace gtpv1 { + +class GTPv1_Analyzer : public analyzer::Analyzer { public: GTPv1_Analyzer(Connection* conn); virtual ~GTPv1_Analyzer(); @@ -12,18 +14,15 @@ public: virtual void DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new GTPv1_Analyzer(conn); } - static bool Available() - { return BifConst::Tunnel::enable_gtpv1 && - BifConst::Tunnel::max_depth > 0; } - protected: - friend class AnalyzerTimer; void ExpireTimer(double t); binpac::GTPv1::GTPv1_Conn* interp; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/gtpv1/Plugin.cc b/src/analyzer/protocol/gtpv1/Plugin.cc new file mode 100644 index 0000000000..83d1557e4d --- /dev/null +++ b/src/analyzer/protocol/gtpv1/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "GTPv1.h" + +BRO_PLUGIN_BEGIN(Bro, GTPv1) + BRO_PLUGIN_DESCRIPTION("GTPv1 analyzer"); + BRO_PLUGIN_ANALYZER("GTPv1", gtpv1::GTPv1_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/gtpv1/events.bif b/src/analyzer/protocol/gtpv1/events.bif new file mode 100644 index 0000000000..b3bac93a2e --- /dev/null +++ b/src/analyzer/protocol/gtpv1/events.bif @@ -0,0 +1,74 @@ +## Generated for any GTP message with a GTPv1 header. +## +## c: The connection over which the message is sent. +## +## hdr: The GTPv1 header. +event gtpv1_message%(c: connection, hdr: gtpv1_hdr%); + +## Generated for GTPv1 G-PDU packets. That is, packets with a UDP payload +## that includes a GTP header followed by an IPv4 or IPv6 packet. +## +## outer: The GTP outer tunnel connection. +## +## inner_gtp: The GTP header. +## +## inner_ip: The inner IP and transport layer packet headers. +## +## .. note:: Since this event may be raised on a per-packet basis, handling +## it may become particularly expensive for real-time analysis. +event gtpv1_g_pdu_packet%(outer: connection, inner_gtp: gtpv1_hdr, inner_ip: pkt_hdr%); + +## Generated for GTPv1-C Create PDP Context Request messages. +## +## c: The connection over which the message is sent. +## +## hdr: The GTPv1 header. +## +## elements: The set of Information Elements comprising the message. +event gtpv1_create_pdp_ctx_request%(c: connection, hdr: gtpv1_hdr, elements: gtp_create_pdp_ctx_request_elements%); + +## Generated for GTPv1-C Create PDP Context Response messages. +## +## c: The connection over which the message is sent. +## +## hdr: The GTPv1 header. +## +## elements: The set of Information Elements comprising the message. +event gtpv1_create_pdp_ctx_response%(c: connection, hdr: gtpv1_hdr, elements: gtp_create_pdp_ctx_response_elements%); + +## Generated for GTPv1-C Update PDP Context Request messages. +## +## c: The connection over which the message is sent. +## +## hdr: The GTPv1 header. +## +## elements: The set of Information Elements comprising the message. +event gtpv1_update_pdp_ctx_request%(c: connection, hdr: gtpv1_hdr, elements: gtp_update_pdp_ctx_request_elements%); + +## Generated for GTPv1-C Update PDP Context Response messages. +## +## c: The connection over which the message is sent. +## +## hdr: The GTPv1 header. +## +## elements: The set of Information Elements comprising the message. +event gtpv1_update_pdp_ctx_response%(c: connection, hdr: gtpv1_hdr, elements: gtp_update_pdp_ctx_response_elements%); + +## Generated for GTPv1-C Delete PDP Context Request messages. +## +## c: The connection over which the message is sent. +## +## hdr: The GTPv1 header. +## +## elements: The set of Information Elements comprising the message. +event gtpv1_delete_pdp_ctx_request%(c: connection, hdr: gtpv1_hdr, elements: gtp_delete_pdp_ctx_request_elements%); + +## Generated for GTPv1-C Delete PDP Context Response messages. +## +## c: The connection over which the message is sent. +## +## hdr: The GTPv1 header. +## +## elements: The set of Information Elements comprising the message. +event gtpv1_delete_pdp_ctx_response%(c: connection, hdr: gtpv1_hdr, elements: gtp_delete_pdp_ctx_response_elements%); + diff --git a/src/gtpv1-analyzer.pac b/src/analyzer/protocol/gtpv1/gtpv1-analyzer.pac similarity index 100% rename from src/gtpv1-analyzer.pac rename to src/analyzer/protocol/gtpv1/gtpv1-analyzer.pac diff --git a/src/gtpv1-protocol.pac b/src/analyzer/protocol/gtpv1/gtpv1-protocol.pac similarity index 100% rename from src/gtpv1-protocol.pac rename to src/analyzer/protocol/gtpv1/gtpv1-protocol.pac diff --git a/src/gtpv1.pac b/src/analyzer/protocol/gtpv1/gtpv1.pac similarity index 82% rename from src/gtpv1.pac rename to src/analyzer/protocol/gtpv1/gtpv1.pac index d155ecfd67..0305951cc5 100644 --- a/src/gtpv1.pac +++ b/src/analyzer/protocol/gtpv1/gtpv1.pac @@ -1,6 +1,10 @@ %include binpac.pac %include bro.pac +%extern{ +#include "events.bif.h" +%} + analyzer GTPv1 withcontext { connection: GTPv1_Conn; flow: GTPv1_Flow; diff --git a/src/analyzer/protocol/http/CMakeLists.txt b/src/analyzer/protocol/http/CMakeLists.txt new file mode 100644 index 0000000000..d1fbed07f0 --- /dev/null +++ b/src/analyzer/protocol/http/CMakeLists.txt @@ -0,0 +1,11 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro HTTP) +bro_plugin_cc(HTTP.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_bif(functions.bif) +bro_plugin_end() + diff --git a/src/HTTP.cc b/src/analyzer/protocol/http/HTTP.cc similarity index 90% rename from src/HTTP.cc rename to src/analyzer/protocol/http/HTTP.cc index 07868555e1..71c0052b4b 100644 --- a/src/HTTP.cc +++ b/src/analyzer/protocol/http/HTTP.cc @@ -11,9 +11,13 @@ #include "NetVar.h" #include "HTTP.h" #include "Event.h" -#include "MIME.h" +#include "analyzer/protocol/mime/MIME.h" #include "file_analysis/Manager.h" +#include "events.bif.h" + +using namespace analyzer::http; + const bool DEBUG_http = false; // The EXPECT_*_NOTHING states are used to prevent further parsing. Used if a @@ -82,7 +86,7 @@ void HTTP_Entity::Deliver(int len, const char* data, int trailing_CRLF) if ( end_of_data ) { // Multipart entities may have trailers - if ( content_type != CONTENT_TYPE_MULTIPART ) + if ( content_type != mime::CONTENT_TYPE_MULTIPART ) IllegalFormat("data trailing the end of entity"); return; } @@ -98,8 +102,8 @@ void HTTP_Entity::Deliver(int len, const char* data, int trailing_CRLF) } // Entity body. - if ( content_type == CONTENT_TYPE_MULTIPART || - content_type == CONTENT_TYPE_MESSAGE ) + if ( content_type == mime::CONTENT_TYPE_MULTIPART || + content_type == mime::CONTENT_TYPE_MESSAGE ) DeliverBody(len, data, trailing_CRLF); else if ( chunked_transfer_state != NON_CHUNKED_TRANSFER ) @@ -166,7 +170,7 @@ void HTTP_Entity::Deliver(int len, const char* data, int trailing_CRLF) DeliverBody(len, data, trailing_CRLF); } -class HTTP_Entity::UncompressedOutput : public Analyzer::OutputHandler { +class HTTP_Entity::UncompressedOutput : public analyzer::OutputHandler { public: UncompressedOutput(HTTP_Entity* e) { entity = e; } virtual ~UncompressedOutput() { } @@ -182,14 +186,14 @@ void HTTP_Entity::DeliverBody(int len, const char* data, int trailing_CRLF) { if ( encoding == GZIP || encoding == DEFLATE ) { - ZIP_Analyzer::Method method = + zip::ZIP_Analyzer::Method method = encoding == GZIP ? - ZIP_Analyzer::GZIP : ZIP_Analyzer::DEFLATE; + zip::ZIP_Analyzer::GZIP : zip::ZIP_Analyzer::DEFLATE; if ( ! zip ) { // We don't care about the direction here. - zip = new ZIP_Analyzer( + zip = new zip::ZIP_Analyzer( http_message->MyHTTP_Analyzer()->Conn(), false, method); zip->SetOutputHandler(new UncompressedOutput(this)); @@ -239,7 +243,7 @@ int HTTP_Entity::Undelivered(int64_t len) return 0; file_mgr->Gap(body_length, len, - http_message->MyHTTP_Analyzer()->GetTag(), + http_message->MyHTTP_Analyzer()->GetAnalyzerTag(), http_message->MyHTTP_Analyzer()->Conn(), http_message->IsOrig()); @@ -296,12 +300,12 @@ void HTTP_Entity::SubmitData(int len, const char* buf) { if ( send_size && instance_length > 0 ) file_mgr->SetSize(instance_length, - http_message->MyHTTP_Analyzer()->GetTag(), + http_message->MyHTTP_Analyzer()->GetAnalyzerTag(), http_message->MyHTTP_Analyzer()->Conn(), http_message->IsOrig()); file_mgr->DataIn(reinterpret_cast(buf), len, offset, - http_message->MyHTTP_Analyzer()->GetTag(), + http_message->MyHTTP_Analyzer()->GetAnalyzerTag(), http_message->MyHTTP_Analyzer()->Conn(), http_message->IsOrig()); @@ -311,12 +315,12 @@ void HTTP_Entity::SubmitData(int len, const char* buf) { if ( send_size && content_length > 0 ) file_mgr->SetSize(content_length, - http_message->MyHTTP_Analyzer()->GetTag(), + http_message->MyHTTP_Analyzer()->GetAnalyzerTag(), http_message->MyHTTP_Analyzer()->Conn(), http_message->IsOrig()); file_mgr->DataIn(reinterpret_cast(buf), len, - http_message->MyHTTP_Analyzer()->GetTag(), + http_message->MyHTTP_Analyzer()->GetAnalyzerTag(), http_message->MyHTTP_Analyzer()->Conn(), http_message->IsOrig()); } @@ -336,12 +340,12 @@ void HTTP_Entity::SetPlainDelivery(int64_t length) // expect_data_length. } -void HTTP_Entity::SubmitHeader(MIME_Header* h) +void HTTP_Entity::SubmitHeader(mime::MIME_Header* h) { - if ( strcasecmp_n(h->get_name(), "content-length") == 0 ) + if ( mime::strcasecmp_n(h->get_name(), "content-length") == 0 ) { data_chunk_t vt = h->get_value_token(); - if ( ! is_null_data_chunk(vt) ) + if ( ! mime::is_null_data_chunk(vt) ) { int64_t n; if ( atoi_n(vt.length, vt.data, 0, 10, n) ) @@ -352,7 +356,7 @@ void HTTP_Entity::SubmitHeader(MIME_Header* h) } // Figure out content-length for HTTP 206 Partial Content response - else if ( strcasecmp_n(h->get_name(), "content-range") == 0 && + else if ( mime::strcasecmp_n(h->get_name(), "content-range") == 0 && http_message->MyHTTP_Analyzer()->HTTP_ReplyCode() == 206 ) { data_chunk_t vt = h->get_value_token(); @@ -422,19 +426,19 @@ void HTTP_Entity::SubmitHeader(MIME_Header* h) } } - else if ( strcasecmp_n(h->get_name(), "transfer-encoding") == 0 ) + else if ( mime::strcasecmp_n(h->get_name(), "transfer-encoding") == 0 ) { data_chunk_t vt = h->get_value_token(); - if ( strcasecmp_n(vt, "chunked") == 0 ) + if ( mime::strcasecmp_n(vt, "chunked") == 0 ) chunked_transfer_state = BEFORE_CHUNK; } - else if ( strcasecmp_n(h->get_name(), "content-encoding") == 0 ) + else if ( mime::strcasecmp_n(h->get_name(), "content-encoding") == 0 ) { data_chunk_t vt = h->get_value_token(); - if ( strcasecmp_n(vt, "gzip") == 0 ) + if ( mime::strcasecmp_n(vt, "gzip") == 0 ) encoding = GZIP; - if ( strcasecmp_n(vt, "deflate") == 0 ) + if ( mime::strcasecmp_n(vt, "deflate") == 0 ) encoding = DEFLATE; } @@ -468,8 +472,8 @@ void HTTP_Entity::SubmitAllHeaders() return; } - if ( content_type == CONTENT_TYPE_MULTIPART || - content_type == CONTENT_TYPE_MESSAGE ) + if ( content_type == mime::CONTENT_TYPE_MULTIPART || + content_type == mime::CONTENT_TYPE_MESSAGE ) { // Do nothing. // Make sure that we check for multiple/message contents first, @@ -518,7 +522,7 @@ void HTTP_Entity::SubmitAllHeaders() } HTTP_Message::HTTP_Message(HTTP_Analyzer* arg_analyzer, - ContentLine_Analyzer* arg_cl, bool arg_is_orig, + tcp::ContentLine_Analyzer* arg_cl, bool arg_is_orig, int expect_body, int64_t init_header_length) : MIME_Message (arg_analyzer) { @@ -569,7 +573,7 @@ void HTTP_Message::Done(const int interrupted, const char* detail) if ( is_orig || MyHTTP_Analyzer()->HTTP_ReplyCode() != 206 ) // multipart/byteranges may span multiple connections - file_mgr->EndOfFile(MyHTTP_Analyzer()->GetTag(), + file_mgr->EndOfFile(MyHTTP_Analyzer()->GetAnalyzerTag(), MyHTTP_Analyzer()->Conn(), is_orig); if ( http_message_done ) @@ -606,7 +610,7 @@ int HTTP_Message::Undelivered(int64_t len) return 0; } -void HTTP_Message::BeginEntity(MIME_Entity* entity) +void HTTP_Message::BeginEntity(mime::MIME_Entity* entity) { if ( DEBUG_http ) DEBUG_MSG("%.6f: begin entity (%d)\n", network_time, is_orig); @@ -622,7 +626,7 @@ void HTTP_Message::BeginEntity(MIME_Entity* entity) } } -void HTTP_Message::EndEntity(MIME_Entity* entity) +void HTTP_Message::EndEntity(mime::MIME_Entity* entity) { if ( DEBUG_http ) DEBUG_MSG("%.6f: end entity (%d)\n", network_time, is_orig); @@ -648,16 +652,16 @@ void HTTP_Message::EndEntity(MIME_Entity* entity) Done(); else if ( is_orig || MyHTTP_Analyzer()->HTTP_ReplyCode() != 206 ) - file_mgr->EndOfFile(MyHTTP_Analyzer()->GetTag(), + file_mgr->EndOfFile(MyHTTP_Analyzer()->GetAnalyzerTag(), MyHTTP_Analyzer()->Conn(), is_orig); } -void HTTP_Message::SubmitHeader(MIME_Header* h) +void HTTP_Message::SubmitHeader(mime::MIME_Header* h) { MyHTTP_Analyzer()->HTTP_Header(is_orig, h); } -void HTTP_Message::SubmitAllHeaders(MIME_HeaderList& hlist) +void HTTP_Message::SubmitAllHeaders(mime::MIME_HeaderList& hlist) { if ( http_all_headers ) { @@ -684,7 +688,7 @@ void HTTP_Message::SubmitAllHeaders(MIME_HeaderList& hlist) } } -void HTTP_Message::SubmitTrailingHeaders(MIME_HeaderList& /* hlist */) +void HTTP_Message::SubmitTrailingHeaders(mime::MIME_HeaderList& /* hlist */) { // Do nothing for now. } @@ -725,15 +729,15 @@ void HTTP_Message::SubmitEvent(int event_type, const char* detail) const char* category = ""; switch ( event_type ) { - case MIME_EVENT_ILLEGAL_FORMAT: + case mime::MIME_EVENT_ILLEGAL_FORMAT: category = "illegal format"; break; - case MIME_EVENT_ILLEGAL_ENCODING: + case mime::MIME_EVENT_ILLEGAL_ENCODING: category = "illegal encoding"; break; - case MIME_EVENT_CONTENT_GAP: + case mime::MIME_EVENT_CONTENT_GAP: category = "content gap"; break; @@ -848,7 +852,7 @@ void HTTP_Message::Weird(const char* msg) } HTTP_Analyzer::HTTP_Analyzer(Connection* conn) - : TCP_ApplicationAnalyzer(AnalyzerTag::HTTP, conn) +: tcp::TCP_ApplicationAnalyzer("HTTP", conn) { num_requests = num_replies = 0; num_request_lines = num_reply_lines = 0; @@ -868,10 +872,10 @@ HTTP_Analyzer::HTTP_Analyzer(Connection* conn) reply_code = 0; reply_reason_phrase = 0; - content_line_orig = new ContentLine_Analyzer(conn, true); + content_line_orig = new tcp::ContentLine_Analyzer(conn, true); AddSupportAnalyzer(content_line_orig); - content_line_resp = new ContentLine_Analyzer(conn, false); + content_line_resp = new tcp::ContentLine_Analyzer(conn, false); content_line_resp->SetSkipPartial(true); AddSupportAnalyzer(content_line_resp); } @@ -889,7 +893,7 @@ void HTTP_Analyzer::Done() if ( IsFinished() ) return; - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); RequestMade(1, "message interrupted when connection done"); ReplyMade(1, "message interrupted when connection done"); @@ -908,18 +912,18 @@ void HTTP_Analyzer::Done() unanswered_requests.pop(); } - file_mgr->EndOfFile(GetTag(), Conn(), true); + file_mgr->EndOfFile(GetAnalyzerTag(), Conn(), true); /* TODO: this might be nice to have, but reply code is cleared by now. if ( HTTP_ReplyCode() != 206 ) // multipart/byteranges may span multiple connections - file_mgr->EndOfFile(GetTag(), Conn(), false); + file_mgr->EndOfFile(GetAnalyzerTag(), Conn(), false); */ } void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) { - TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig); if ( TCP() && TCP()->IsPartial() ) return; @@ -927,7 +931,7 @@ void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) const char* line = reinterpret_cast(data); const char* end_of_line = line + len; - ContentLine_Analyzer* content_line = + tcp::ContentLine_Analyzer* content_line = is_orig ? content_line_orig : content_line_resp; if ( content_line->IsPlainDelivery() ) @@ -976,7 +980,7 @@ void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) { if ( ! RequestExpected() ) HTTP_Event("crud_trailing_HTTP_request", - new_string_val(line, end_of_line)); + mime::new_string_val(line, end_of_line)); else { // We do see HTTP requests with a @@ -1055,20 +1059,20 @@ void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) void HTTP_Analyzer::Undelivered(int seq, int len, bool is_orig) { - TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig); + tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig); // DEBUG_MSG("Undelivered from %d: %d bytes\n", seq, length); HTTP_Message* msg = is_orig ? request_message : reply_message; - ContentLine_Analyzer* content_line = + tcp::ContentLine_Analyzer* content_line = is_orig ? content_line_orig : content_line_resp; if ( ! content_line->IsSkippedContents(seq, len) ) { if ( msg ) - msg->SubmitEvent(MIME_EVENT_CONTENT_GAP, + msg->SubmitEvent(mime::MIME_EVENT_CONTENT_GAP, fmt("seq=%d, len=%d", seq, len)); } @@ -1099,7 +1103,7 @@ void HTTP_Analyzer::Undelivered(int seq, int len, bool is_orig) void HTTP_Analyzer::EndpointEOF(bool is_orig) { - TCP_ApplicationAnalyzer::EndpointEOF(is_orig); + tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig); // DEBUG_MSG("%.6f eof\n", network_time); @@ -1111,7 +1115,7 @@ void HTTP_Analyzer::EndpointEOF(bool is_orig) void HTTP_Analyzer::ConnectionFinished(int half_finished) { - TCP_ApplicationAnalyzer::ConnectionFinished(half_finished); + tcp::TCP_ApplicationAnalyzer::ConnectionFinished(half_finished); // DEBUG_MSG("%.6f connection finished\n", network_time); RequestMade(1, "message ends as connection is finished"); @@ -1120,7 +1124,7 @@ void HTTP_Analyzer::ConnectionFinished(int half_finished) void HTTP_Analyzer::ConnectionReset() { - TCP_ApplicationAnalyzer::ConnectionReset(); + tcp::TCP_ApplicationAnalyzer::ConnectionReset(); RequestMade(1, "message interrupted by RST"); ReplyMade(1, "message interrupted by RST"); @@ -1128,7 +1132,7 @@ void HTTP_Analyzer::ConnectionReset() void HTTP_Analyzer::PacketWithRST() { - TCP_ApplicationAnalyzer::PacketWithRST(); + tcp::TCP_ApplicationAnalyzer::PacketWithRST(); RequestMade(1, "message interrupted by RST"); ReplyMade(1, "message interrupted by RST"); @@ -1272,10 +1276,10 @@ int HTTP_Analyzer::ParseRequest(const char* line, const char* end_of_line) version_end = version_start + 3; if ( skip_whitespace(version_end, end_of_line) != end_of_line ) HTTP_Event("crud after HTTP version is ignored", - new_string_val(line, end_of_line)); + mime::new_string_val(line, end_of_line)); } else - HTTP_Event("bad_HTTP_version", new_string_val(line, end_of_line)); + HTTP_Event("bad_HTTP_version", mime::new_string_val(line, end_of_line)); } // NormalizeURI(line, end_of_uri); @@ -1299,7 +1303,7 @@ double HTTP_Analyzer::HTTP_Version(int len, const char* data) } else { - HTTP_Event("bad_HTTP_version", new_string_val(len, data)); + HTTP_Event("bad_HTTP_version", mime::new_string_val(len, data)); return 0; } } @@ -1478,20 +1482,20 @@ int HTTP_Analyzer::HTTP_ReplyLine(const char* line, const char* end_of_line) // ##TODO: some server replies with an HTML document // without a status line and a MIME header, when the // request is malformed. - HTTP_Event("bad_HTTP_reply", new_string_val(line, end_of_line)); + HTTP_Event("bad_HTTP_reply", mime::new_string_val(line, end_of_line)); return 0; } SetVersion(reply_version, HTTP_Version(end_of_line - rest, rest)); for ( ; rest < end_of_line; ++rest ) - if ( is_lws(*rest) ) + if ( mime::is_lws(*rest) ) break; if ( rest >= end_of_line ) { HTTP_Event("HTTP_reply_code_missing", - new_string_val(line, end_of_line)); + mime::new_string_val(line, end_of_line)); return 0; } @@ -1500,20 +1504,20 @@ int HTTP_Analyzer::HTTP_ReplyLine(const char* line, const char* end_of_line) if ( rest + 3 > end_of_line ) { HTTP_Event("HTTP_reply_code_missing", - new_string_val(line, end_of_line)); + mime::new_string_val(line, end_of_line)); return 0; } reply_code = HTTP_ReplyCode(rest); for ( rest += 3; rest < end_of_line; ++rest ) - if ( is_lws(*rest) ) + if ( mime::is_lws(*rest) ) break; if ( rest >= end_of_line ) { HTTP_Event("HTTP_reply_reason_phrase_missing", - new_string_val(line, end_of_line)); + mime::new_string_val(line, end_of_line)); // Tolerate missing reason phrase? return 1; } @@ -1560,7 +1564,7 @@ int HTTP_Analyzer::ExpectReplyMessageBody() return HTTP_BODY_EXPECTED; } -void HTTP_Analyzer::HTTP_Header(int is_orig, MIME_Header* h) +void HTTP_Analyzer::HTTP_Header(int is_orig, mime::MIME_Header* h) { #if 0 // ### Only call ParseVersion if we're tracking versions: @@ -1577,16 +1581,16 @@ void HTTP_Analyzer::HTTP_Header(int is_orig, MIME_Header* h) // side, and if seen assume the connection to be persistent. // This seems fairly safe - at worst, the client does indeed // send additional requests, and the server ignores them. - if ( is_orig && strcasecmp_n(h->get_name(), "connection") == 0 ) + if ( is_orig && mime::strcasecmp_n(h->get_name(), "connection") == 0 ) { - if ( strcasecmp_n(h->get_value_token(), "keep-alive") == 0 ) + if ( mime::strcasecmp_n(h->get_value_token(), "keep-alive") == 0 ) keep_alive = 1; } if ( ! is_orig && - strcasecmp_n(h->get_name(), "connection") == 0 ) + mime::strcasecmp_n(h->get_name(), "connection") == 0 ) { - if ( strcasecmp_n(h->get_value_token(), "close") == 0 ) + if ( mime::strcasecmp_n(h->get_value_token(), "close") == 0 ) connection_close = 1; } @@ -1609,8 +1613,8 @@ void HTTP_Analyzer::HTTP_Header(int is_orig, MIME_Header* h) val_list* vl = new val_list(); vl->append(BuildConnVal()); vl->append(new Val(is_orig, TYPE_BOOL)); - vl->append(new_string_val(h->get_name())->ToUpper()); - vl->append(new_string_val(h->get_value())); + vl->append(mime::new_string_val(h->get_name())->ToUpper()); + vl->append(mime::new_string_val(h->get_value())); if ( DEBUG_http ) DEBUG_MSG("%.6f http_header\n", network_time); ConnectionEvent(http_header, vl); @@ -1639,7 +1643,7 @@ void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const IPAddr& host, while ( len > 0 ) { // Skip white space. - while ( len && is_lws(*data) ) + while ( len && mime::is_lws(*data) ) { ++data; --len; @@ -1652,7 +1656,7 @@ void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const IPAddr& host, // Find end of comment. const char* data_start = data; const char* eoc = - data + MIME_skip_lws_comments(len, data); + data + mime::MIME_skip_lws_comments(len, data); // Split into parts. // (This may get confused by nested comments, @@ -1662,7 +1666,7 @@ void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const IPAddr& host, while ( 1 ) { // Eat spaces. - while ( data < eoc && is_lws(*data) ) + while ( data < eoc && mime::is_lws(*data) ) ++data; // Find end of token. @@ -1675,7 +1679,7 @@ void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const IPAddr& host, break; // Delete spaces at end of token. - for ( ; eot > data && is_lws(*(eot-1)); --eot ) + for ( ; eot > data && mime::is_lws(*(eot-1)); --eot ) ; if ( data != eot && software_version_found ) @@ -1688,7 +1692,7 @@ void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const IPAddr& host, continue; } - offset = MIME_get_slash_token_pair(len, data, + offset = mime::MIME_get_slash_token_pair(len, data, &product, &product_version); if ( offset < 0 ) { @@ -1696,10 +1700,10 @@ void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const IPAddr& host, // so we do not complain in the final version if ( num_version == 0 ) HTTP_Event("bad_HTTP_version", - new_string_val(len, data)); + mime::new_string_val(len, data)); // Try to simply skip next token. - offset = MIME_get_token(len, data, &product); + offset = mime::MIME_get_token(len, data, &product); if ( offset < 0 ) break; @@ -1763,7 +1767,7 @@ void HTTP_Analyzer::HTTP_MessageDone(int is_orig, HTTP_Message* /* message */) ReplyMade(0, "message ends normally"); } -void HTTP_Analyzer::InitHTTPMessage(ContentLine_Analyzer* cl, HTTP_Message*& message, +void HTTP_Analyzer::InitHTTPMessage(tcp::ContentLine_Analyzer* cl, HTTP_Message*& message, bool is_orig, int expect_body, int64_t init_header_length) { if ( message ) @@ -1787,25 +1791,25 @@ void HTTP_Analyzer::SkipEntityData(int is_orig) msg->SkipEntityData(); } -int is_reserved_URI_char(unsigned char ch) +int analyzer::http::is_reserved_URI_char(unsigned char ch) { // see RFC 2396 (definition of URI) return strchr(";/?:@&=+$,", ch) != 0; } -int is_unreserved_URI_char(unsigned char ch) +int analyzer::http::is_unreserved_URI_char(unsigned char ch) { // see RFC 2396 (definition of URI) return isalnum(ch) || strchr("-_.!~*\'()", ch) != 0; } -void escape_URI_char(unsigned char ch, unsigned char*& p) +void analyzer::http::escape_URI_char(unsigned char ch, unsigned char*& p) { *p++ = '%'; *p++ = encode_hex((ch >> 4) & 0xf); *p++ = encode_hex(ch & 0xf); } -BroString* unescape_URI(const u_char* line, const u_char* line_end, - Analyzer* analyzer) +BroString* analyzer::http::unescape_URI(const u_char* line, const u_char* line_end, + analyzer::Analyzer* analyzer) { byte_vec decoded_URI = new u_char[line_end - line + 1]; byte_vec URI_p = decoded_URI; diff --git a/src/HTTP.h b/src/analyzer/protocol/http/HTTP.h similarity index 81% rename from src/HTTP.h rename to src/analyzer/protocol/http/HTTP.h index 81c7385825..8339e48e3b 100644 --- a/src/HTTP.h +++ b/src/analyzer/protocol/http/HTTP.h @@ -1,14 +1,19 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef http_h -#define http_h +#ifndef ANALYZER_PROTOCOL_HTTP_HTTP_H +#define ANALYZER_PROTOCOL_HTTP_HTTP_H -#include "TCP.h" -#include "ContentLine.h" -#include "MIME.h" +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/tcp/ContentLine.h" +#include "analyzer/protocol/zip/ZIP.h" +#include "analyzer/protocol/mime/MIME.h" #include "binpac_bro.h" -#include "ZIP.h" #include "IPAddr.h" +#include "events.bif.h" + +#include "HTTP.h" + +namespace analyzer { namespace http { enum CHUNKED_TRANSFER_STATE { NON_CHUNKED_TRANSFER, @@ -24,7 +29,7 @@ class HTTP_Entity; class HTTP_Message; class HTTP_Analyzer; -class HTTP_Entity : public MIME_Entity { +class HTTP_Entity : public mime::MIME_Entity { public: HTTP_Entity(HTTP_Message* msg, MIME_Entity* parent_entity, int expect_body); @@ -54,7 +59,7 @@ protected: int64_t header_length; int deliver_body; enum { IDENTITY, GZIP, COMPRESS, DEFLATE } encoding; - ZIP_Analyzer* zip; + zip::ZIP_Analyzer* zip; bool is_partial_content; uint64_t offset; int64_t instance_length; // total length indicated by content-range @@ -69,7 +74,7 @@ protected: void SetPlainDelivery(int64_t length); - void SubmitHeader(MIME_Header* h); + void SubmitHeader(mime::MIME_Header* h); void SubmitAllHeaders(); }; @@ -90,9 +95,9 @@ enum { // HTTP_Message::EndEntity -> Message::Done // HTTP_MessageDone -> {Request,Reply}Made -class HTTP_Message : public MIME_Message { +class HTTP_Message : public mime::MIME_Message { public: - HTTP_Message(HTTP_Analyzer* analyzer, ContentLine_Analyzer* cl, + HTTP_Message(HTTP_Analyzer* analyzer, tcp::ContentLine_Analyzer* cl, bool is_orig, int expect_body, int64_t init_header_length); ~HTTP_Message(); void Done(const int interrupted, const char* msg); @@ -100,16 +105,16 @@ public: int Undelivered(int64_t len); - void BeginEntity(MIME_Entity* /* entity */); - void EndEntity(MIME_Entity* entity); - void SubmitHeader(MIME_Header* h); - void SubmitAllHeaders(MIME_HeaderList& /* hlist */); + void BeginEntity(mime::MIME_Entity* /* entity */); + void EndEntity(mime::MIME_Entity* entity); + void SubmitHeader(mime::MIME_Header* h); + void SubmitAllHeaders(mime::MIME_HeaderList& /* hlist */); void SubmitData(int len, const char* buf); int RequestBuffer(int* plen, char** pbuf); void SubmitAllData(); void SubmitEvent(int event_type, const char* detail); - void SubmitTrailingHeaders(MIME_HeaderList& /* hlist */); + void SubmitTrailingHeaders(mime::MIME_HeaderList& /* hlist */); void SetPlainDelivery(int64_t length); void SkipEntityData(); @@ -121,7 +126,7 @@ public: protected: HTTP_Analyzer* analyzer; - ContentLine_Analyzer* content_line; + tcp::ContentLine_Analyzer* content_line; bool is_orig; vector buffers; @@ -149,14 +154,14 @@ protected: Val* BuildMessageStat(const int interrupted, const char* msg); }; -class HTTP_Analyzer : public TCP_ApplicationAnalyzer { +class HTTP_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: HTTP_Analyzer(Connection* conn); ~HTTP_Analyzer(); - void Undelivered(TCP_Endpoint* sender, int seq, int len); + void Undelivered(tcp::TCP_Endpoint* sender, int seq, int len); - void HTTP_Header(int is_orig, MIME_Header* h); + void HTTP_Header(int is_orig, mime::MIME_Header* h); void HTTP_EntityData(int is_orig, const BroString* entity_data); void HTTP_MessageDone(int is_orig, HTTP_Message* message); void HTTP_Event(const char* category, const char* detail); @@ -172,20 +177,20 @@ public: virtual void DeliverStream(int len, const u_char* data, bool orig); virtual void Undelivered(int seq, int len, bool orig); - // Overriden from TCP_ApplicationAnalyzer + // Overriden from tcp::TCP_ApplicationAnalyzer virtual void EndpointEOF(bool is_orig); virtual void ConnectionFinished(int half_finished); virtual void ConnectionReset(); virtual void PacketWithRST(); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new HTTP_Analyzer(conn); } static bool Available() { return (http_request || http_reply || http_header || http_all_headers || http_begin_entity || http_end_entity || http_content_type || http_entity_data || http_message_done || - http_event || http_stats) && !FLAGS_use_binpac; } + http_event || http_stats); } protected: void GenStats(); @@ -193,7 +198,7 @@ protected: int HTTP_RequestLine(const char* line, const char* end_of_line); int HTTP_ReplyLine(const char* line, const char* end_of_line); - void InitHTTPMessage(ContentLine_Analyzer* cl, HTTP_Message*& message, bool is_orig, + void InitHTTPMessage(tcp::ContentLine_Analyzer* cl, HTTP_Message*& message, bool is_orig, int expect_body, int64_t init_header_length); const char* PrefixMatch(const char* line, const char* end_of_line, @@ -245,8 +250,8 @@ protected: int reply_code; Val* reply_reason_phrase; - ContentLine_Analyzer* content_line_orig; - ContentLine_Analyzer* content_line_resp; + tcp::ContentLine_Analyzer* content_line_orig; + tcp::ContentLine_Analyzer* content_line_resp; HTTP_Message* request_message; HTTP_Message* reply_message; @@ -256,6 +261,8 @@ extern int is_reserved_URI_char(unsigned char ch); extern int is_unreserved_URI_char(unsigned char ch); extern void escape_URI_char(unsigned char ch, unsigned char*& p); extern BroString* unescape_URI(const u_char* line, const u_char* line_end, - Analyzer* analyzer); + analyzer::Analyzer* analyzer); + +} } // namespace analyzer::* #endif diff --git a/src/analyzer/protocol/http/Plugin.cc b/src/analyzer/protocol/http/Plugin.cc new file mode 100644 index 0000000000..1a2a05cbed --- /dev/null +++ b/src/analyzer/protocol/http/Plugin.cc @@ -0,0 +1,11 @@ + +#include "plugin/Plugin.h" + +#include "HTTP.h" + +BRO_PLUGIN_BEGIN(Bro, HTTP) + BRO_PLUGIN_DESCRIPTION("HTTP analyzer"); + BRO_PLUGIN_ANALYZER("HTTP", http::HTTP_Analyzer); + BRO_PLUGIN_BIF_FILE(events); + BRO_PLUGIN_BIF_FILE(functions); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/http/events.bif b/src/analyzer/protocol/http/events.bif new file mode 100644 index 0000000000..7a509c6d54 --- /dev/null +++ b/src/analyzer/protocol/http/events.bif @@ -0,0 +1,232 @@ + +## Generated for HTTP requests. Bro supports persistent and pipelined HTTP +## sessions and raises corresponding events as it parses client/server +## dialogues. This event is generated as soon as a request's initial line has +## been parsed, and before any :bro:id:`http_header` events are raised. +## +## See `Wikipedia `__ +## for more information about the HTTP protocol. +## +## c: The connection. +## +## method: The HTTP method extracted from the request (e.g., ``GET``, ``POST``). +## +## original_URI: The unprocessed URI as specified in the request. +## +## unescaped_URI: The URI with all percent-encodings decoded. +## +## version: The version number specified in the request (e.g., ``1.1``). +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_event http_header http_message_done http_reply http_stats +## truncate_http_URI +event http_request%(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string%); + +## Generated for HTTP replies. Bro supports persistent and pipelined HTTP +## sessions and raises corresponding events as it parses client/server +## dialogues. This event is generated as soon as a reply's initial line has +## been parsed, and before any :bro:id:`http_header` events are raised. +## +## See `Wikipedia `__ +## for more information about the HTTP protocol. +## +## c: The connection. +## +## version: The version number specified in the reply (e.g., ``1.1``). +## +## code: The numerical response code returned by the server. +## +## reason: The textual description returned by the server along with *code*. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_event http_header http_message_done http_request +## http_stats +event http_reply%(c: connection, version: string, code: count, reason: string%); + +## Generated for HTTP headers. Bro supports persistent and pipelined HTTP +## sessions and raises corresponding events as it parses client/server +## dialogues. +## +## See `Wikipedia `__ +## for more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the header was sent by the originator of the TCP connection. +## +## name: The name of the header. +## +## value: The value of the header. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_event http_message_done http_reply http_request +## http_stats +## +## .. note:: This event is also raised for headers found in nested body +## entities. +event http_header%(c: connection, is_orig: bool, name: string, value: string%); + +## Generated for HTTP headers, passing on all headers of an HTTP message at +## once. Bro supports persistent and pipelined HTTP sessions and raises +## corresponding events as it parses client/server dialogues. +## +## See `Wikipedia `__ +## for more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the header was sent by the originator of the TCP connection. +## +## hlist: A *table* containing all headers extracted from the current entity. +## The table is indexed by the position of the header (1 for the first, +## 2 for the second, etc.). +## +## .. bro:see:: http_begin_entity http_content_type http_end_entity http_entity_data +## http_event http_header http_message_done http_reply http_request http_stats +## +## .. note:: This event is also raised for headers found in nested body +## entities. +event http_all_headers%(c: connection, is_orig: bool, hlist: mime_header_list%); + +## Generated when starting to parse an HTTP body entity. This event is generated +## at least once for each non-empty (client or server) HTTP body; and +## potentially more than once if the body contains further nested MIME +## entities. Bro raises this event just before it starts parsing each entity's +## content. +## +## See `Wikipedia `__ +## for more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the entity was sent by the originator of the TCP +## connection. +## +## .. bro:see:: http_all_headers http_content_type http_end_entity http_entity_data +## http_event http_header http_message_done http_reply http_request http_stats +## mime_begin_entity +event http_begin_entity%(c: connection, is_orig: bool%); + +## Generated when finishing parsing an HTTP body entity. This event is generated +## at least once for each non-empty (client or server) HTTP body; and +## potentially more than once if the body contains further nested MIME +## entities. Bro raises this event at the point when it has finished parsing an +## entity's content. +## +## See `Wikipedia `__ +## for more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the entity was sent by the originator of the TCP +## connection. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_entity_data +## http_event http_header http_message_done http_reply http_request +## http_stats mime_end_entity +event http_end_entity%(c: connection, is_orig: bool%); + +## Generated when parsing an HTTP body entity, passing on the data. This event +## can potentially be raised many times for each entity, each time passing a +## chunk of the data of not further defined size. +## +## A common idiom for using this event is to first *reassemble* the data +## at the scripting layer by concatenating it to a successively growing +## string; and only perform further content analysis once the corresponding +## :bro:id:`http_end_entity` event has been raised. Note, however, that doing so +## can be quite expensive for HTTP tranders. At the very least, one should +## impose an upper size limit on how much data is being buffered. +## +## See `Wikipedia `__ +## for more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the entity was sent by the originator of the TCP +## connection. +## +## length: The length of *data*. +## +## data: One chunk of raw entity data. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_event http_header http_message_done http_reply http_request http_stats +## mime_entity_data http_entity_data_delivery_size skip_http_data +event http_entity_data%(c: connection, is_orig: bool, length: count, data: string%); + +## Generated for reporting an HTTP body's content type. This event is +## generated at the end of parsing an HTTP header, passing on the MIME +## type as specified by the ``Content-Type`` header. If that header is +## missing, this event is still raised with a default value of ``text/plain``. +## +## See `Wikipedia `__ +## for more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the entity was sent by the originator of the TCP +## connection. +## +## ty: The main type. +## +## subty: The subtype. +## +## .. bro:see:: http_all_headers http_begin_entity http_end_entity http_entity_data +## http_event http_header http_message_done http_reply http_request http_stats +## +## .. note:: This event is also raised for headers found in nested body +## entities. +event http_content_type%(c: connection, is_orig: bool, ty: string, subty: string%); + +## Generated once at the end of parsing an HTTP message. Bro supports persistent +## and pipelined HTTP sessions and raises corresponding events as it parses +## client/server dialogues. A "message" is one top-level HTTP entity, such as a +## complete request or reply. Each message can have further nested sub-entities +## inside. This event is raised once all sub-entities belonging to a top-level +## message have been processed (and their corresponding ``http_entity_*`` events +## generated). +## +## See `Wikipedia `__ +## for more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the entity was sent by the originator of the TCP +## connection. +## +## stat: Further meta information about the message. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_event http_header http_reply http_request http_stats +event http_message_done%(c: connection, is_orig: bool, stat: http_message_stat%); + +## Generated for errors found when decoding HTTP requests or replies. +## +## See `Wikipedia `__ +## for more information about the HTTP protocol. +## +## c: The connection. +## +## event_type: A string describing the general category of the problem found +## (e.g., ``illegal format``). +## +## detail: Further more detailed description of the error. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_header http_message_done http_reply http_request +## http_stats mime_event +event http_event%(c: connection, event_type: string, detail: string%); + +## Generated at the end of an HTTP session to report statistics about it. This +## event is raised after all of an HTTP session's requests and replies have been +## fully processed. +## +## c: The connection. +## +## stats: Statistics summarizing HTTP-level properties of the finished +## connection. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_event http_header http_message_done http_reply +## http_request +event http_stats%(c: connection, stats: http_stats_rec%); diff --git a/src/analyzer/protocol/http/functions.bif b/src/analyzer/protocol/http/functions.bif new file mode 100644 index 0000000000..c4e5df80d5 --- /dev/null +++ b/src/analyzer/protocol/http/functions.bif @@ -0,0 +1,56 @@ + +%%{ +#include "protocol/http/HTTP.h" +%%} + +## Skips the data of the HTTP entity. +## +## c: The HTTP connection. +## +## is_orig: If true, the client data is skipped, and the server data otherwise. +## +## .. bro:see:: skip_smtp_data +function skip_http_entity_data%(c: connection, is_orig: bool%): any + %{ + analyzer::ID id = mgr.CurrentAnalyzer(); + if ( id ) + { + analyzer::Analyzer* ha = c->FindAnalyzer(id); + + if ( ha ) + { + if ( ha->IsAnalyzer("HTTP") ) + static_cast(ha)->SkipEntityData(is_orig); + else + reporter->Error("non-HTTP analyzer associated with connection record"); + } + else + reporter->Error("could not find analyzer for skip_http_entity_data"); + + } + else + reporter->Error("no analyzer associated with connection record"); + + return 0; + %} + +## Unescapes all characters in a URI (decode every ``%xx`` group). +## +## URI: The URI to unescape. +## +## Returns: The unescaped URI with all ``%xx`` groups decoded. +## +## .. note:: +## +## Unescaping reserved characters may cause loss of information. RFC 2396: +## A URI is always in an "escaped" form, since escaping or unescaping a +## completed URI might change its semantics. Normally, the only time +## escape encodings can safely be made is when the URI is being created +## from its component parts. +function unescape_URI%(URI: string%): string + %{ + const u_char* line = URI->Bytes(); + const u_char* const line_end = line + URI->Len(); + + return new StringVal(analyzer::http::unescape_URI(line, line_end, 0)); + %} diff --git a/src/analyzer/protocol/icmp/CMakeLists.txt b/src/analyzer/protocol/icmp/CMakeLists.txt new file mode 100644 index 0000000000..7b8bd9c7fe --- /dev/null +++ b/src/analyzer/protocol/icmp/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro ICMP) +bro_plugin_cc(ICMP.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/ICMP.cc b/src/analyzer/protocol/icmp/ICMP.cc similarity index 98% rename from src/ICMP.cc rename to src/analyzer/protocol/icmp/ICMP.cc index 5634e3885f..732727d709 100644 --- a/src/ICMP.cc +++ b/src/analyzer/protocol/icmp/ICMP.cc @@ -8,19 +8,16 @@ #include "NetVar.h" #include "Event.h" #include "ICMP.h" +#include "Conn.h" + +#include "events.bif.h" #include -ICMP_Analyzer::ICMP_Analyzer(Connection* c) -: TransportLayerAnalyzer(AnalyzerTag::ICMP, c) - { - icmp_conn_val = 0; - c->SetInactivityTimeout(icmp_inactivity_timeout); - request_len = reply_len = -1; - } +using namespace analyzer::icmp; -ICMP_Analyzer::ICMP_Analyzer(AnalyzerTag::Tag tag, Connection* c) -: TransportLayerAnalyzer(tag, c) +ICMP_Analyzer::ICMP_Analyzer(Connection* c) +: TransportLayerAnalyzer("ICMP", c) { icmp_conn_val = 0; c->SetInactivityTimeout(icmp_inactivity_timeout); @@ -835,7 +832,7 @@ VectorVal* ICMP_Analyzer::BuildNDOptionsVal(int caplen, const u_char* data) return vv; } -int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way) +int analyzer::icmp::ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way) { is_one_way = false; @@ -862,7 +859,7 @@ int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way) } } -int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way) +int analyzer::icmp::ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way) { is_one_way = false; diff --git a/src/ICMP.h b/src/analyzer/protocol/icmp/ICMP.h similarity index 88% rename from src/ICMP.h rename to src/analyzer/protocol/icmp/ICMP.h index 1e30b7ff54..e371f53889 100644 --- a/src/ICMP.h +++ b/src/analyzer/protocol/icmp/ICMP.h @@ -1,9 +1,12 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef icmp_h -#define icmp_h +#ifndef ANALYZER_PROTOCOL_ICMP_ICMP_H +#define ANALYZER_PROTOCOL_ICMP_ICMP_H -#include "Analyzer.h" +#include "RuleMatcher.h" +#include "analyzer/Analyzer.h" + +namespace analyzer { namespace icmp { typedef enum { ICMP_INACTIVE, // no packet seen @@ -12,20 +15,17 @@ typedef enum { // We do not have an PIA for ICMP (yet) and therefore derive from // RuleMatcherState to perform our own matching. -class ICMP_Analyzer : public TransportLayerAnalyzer { +class ICMP_Analyzer : public analyzer::TransportLayerAnalyzer { public: ICMP_Analyzer(Connection* conn); virtual void UpdateConnVal(RecordVal *conn_val); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new ICMP_Analyzer(conn); } - static bool Available() { return true; } - protected: - ICMP_Analyzer() { } - ICMP_Analyzer(AnalyzerTag::Tag tag, Connection* conn); + ICMP_Analyzer(analyzer::Tag tag, Connection* conn); virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, @@ -94,4 +94,6 @@ private: extern int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way); extern int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way); +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/icmp/Plugin.cc b/src/analyzer/protocol/icmp/Plugin.cc new file mode 100644 index 0000000000..f313842c2a --- /dev/null +++ b/src/analyzer/protocol/icmp/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "ICMP.h" + +BRO_PLUGIN_BEGIN(Bro, ICMP) + BRO_PLUGIN_DESCRIPTION("ICMP analyzer"); + BRO_PLUGIN_ANALYZER("ICMP", icmp::ICMP_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/icmp/events.bif b/src/analyzer/protocol/icmp/events.bif new file mode 100644 index 0000000000..c471ca0ee6 --- /dev/null +++ b/src/analyzer/protocol/icmp/events.bif @@ -0,0 +1,300 @@ +## Generated for all ICMP messages that are not handled separately with +## dedicated ICMP events. Bro's ICMP analyzer handles a number of ICMP messages +## directly with dedicated events. This event acts as a fallback for those it +## doesn't. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard +## connection record *c*. +## +## .. bro:see:: icmp_error_message +event icmp_sent%(c: connection, icmp: icmp_conn%); + +## Generated for ICMP *echo request* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard +## connection record *c*. +## +## id: The *echo request* identifier. +## +## seq: The *echo request* sequence number. +## +## payload: The message-specific data of the packet payload, i.e., everything +## after the first 8 bytes of the ICMP header. +## +## .. bro:see:: icmp_echo_reply +event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); + +## Generated for ICMP *echo reply* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## id: The *echo reply* identifier. +## +## seq: The *echo reply* sequence number. +## +## payload: The message-specific data of the packet payload, i.e., everything +## after the first 8 bytes of the ICMP header. +## +## .. bro:see:: icmp_echo_request +event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); + +## Generated for all ICMPv6 error messages that are not handled +## separately with dedicated events. Bro's ICMP analyzer handles a number +## of ICMP error messages directly with dedicated events. This event acts +## as a fallback for those it doesn't. +## +## See `Wikipedia +## `__ for more +## information about the ICMPv6 protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard +## connection record *c*. +## +## code: The ICMP code of the error message. +## +## context: A record with specifics of the original packet that the message +## refers to. +## +## .. bro:see:: icmp_unreachable icmp_packet_too_big +## icmp_time_exceeded icmp_parameter_problem +event icmp_error_message%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMP *destination unreachable* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *unreachable* message. +## +## context: A record with specifics of the original packet that the message +## refers to. *Unreachable* messages should include the original IP +## header from the packet that triggered them, and Bro parses that +## into the *context* structure. Note that if the *unreachable* +## includes only a partial IP header for some reason, no +## fields of *context* will be filled out. +## +## .. bro:see:: icmp_error_message icmp_packet_too_big +## icmp_time_exceeded icmp_parameter_problem +event icmp_unreachable%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMPv6 *packet too big* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMPv6 protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *too big* message. +## +## context: A record with specifics of the original packet that the message +## refers to. *Too big* messages should include the original IP header +## from the packet that triggered them, and Bro parses that into +## the *context* structure. Note that if the *too big* includes only +## a partial IP header for some reason, no fields of *context* will +## be filled out. +## +## .. bro:see:: icmp_error_message icmp_unreachable +## icmp_time_exceeded icmp_parameter_problem +event icmp_packet_too_big%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMP *time exceeded* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *exceeded* message. +## +## context: A record with specifics of the original packet that the message +## refers to. *Unreachable* messages should include the original IP +## header from the packet that triggered them, and Bro parses that +## into the *context* structure. Note that if the *exceeded* includes +## only a partial IP header for some reason, no fields of *context* +## will be filled out. +## +## .. bro:see:: icmp_error_message icmp_unreachable icmp_packet_too_big +## icmp_parameter_problem +event icmp_time_exceeded%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMPv6 *parameter problem* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMPv6 protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *parameter problem* message. +## +## context: A record with specifics of the original packet that the message +## refers to. *Parameter problem* messages should include the original +## IP header from the packet that triggered them, and Bro parses that +## into the *context* structure. Note that if the *parameter problem* +## includes only a partial IP header for some reason, no fields +## of *context* will be filled out. +## +## .. bro:see:: icmp_error_message icmp_unreachable icmp_packet_too_big +## icmp_time_exceeded +event icmp_parameter_problem%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMP *router solicitation* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## options: Any Neighbor Discovery options included with message (:rfc:`4861`). +## +## .. bro:see:: icmp_router_advertisement +## icmp_neighbor_solicitation icmp_neighbor_advertisement icmp_redirect +event icmp_router_solicitation%(c: connection, icmp: icmp_conn, options: icmp6_nd_options%); + +## Generated for ICMP *router advertisement* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## cur_hop_limit: The default value that should be placed in Hop Count field +## for outgoing IP packets. +## +## managed: Managed address configuration flag, :rfc:`4861`. +## +## other: Other stateful configuration flag, :rfc:`4861`. +## +## home_agent: Mobile IPv6 home agent flag, :rfc:`3775`. +## +## pref: Router selection preferences, :rfc:`4191`. +## +## proxy: Neighbor discovery proxy flag, :rfc:`4389`. +## +## rsv: Remaining two reserved bits of router advertisement flags. +## +## router_lifetime: How long this router should be used as a default router. +## +## reachable_time: How long a neighbor should be considered reachable. +## +## retrans_timer: How long a host should wait before retransmitting. +## +## options: Any Neighbor Discovery options included with message (:rfc:`4861`). +## +## .. bro:see:: icmp_router_solicitation +## icmp_neighbor_solicitation icmp_neighbor_advertisement icmp_redirect +event icmp_router_advertisement%(c: connection, icmp: icmp_conn, cur_hop_limit: count, managed: bool, other: bool, home_agent: bool, pref: count, proxy: bool, rsv: count, router_lifetime: interval, reachable_time: interval, retrans_timer: interval, options: icmp6_nd_options%); + +## Generated for ICMP *neighbor solicitation* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## tgt: The IP address of the target of the solicitation. +## +## options: Any Neighbor Discovery options included with message (:rfc:`4861`). +## +## .. bro:see:: icmp_router_solicitation icmp_router_advertisement +## icmp_neighbor_advertisement icmp_redirect +event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn, tgt: addr, options: icmp6_nd_options%); + +## Generated for ICMP *neighbor advertisement* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## router: Flag indicating the sender is a router. +## +## solicited: Flag indicating advertisement is in response to a solicitation. +## +## override: Flag indicating advertisement should override existing caches. +## +## tgt: the Target Address in the soliciting message or the address whose +## link-layer address has changed for unsolicited adverts. +## +## options: Any Neighbor Discovery options included with message (:rfc:`4861`). +## +## .. bro:see:: icmp_router_solicitation icmp_router_advertisement +## icmp_neighbor_solicitation icmp_redirect +event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn, router: bool, solicited: bool, override: bool, tgt: addr, options: icmp6_nd_options%); + +## Generated for ICMP *redirect* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## tgt: The address that is supposed to be a better first hop to use for +## ICMP Destination Address. +## +## dest: The address of the destination which is redirected to the target. +## +## options: Any Neighbor Discovery options included with message (:rfc:`4861`). +## +## .. bro:see:: icmp_router_solicitation icmp_router_advertisement +## icmp_neighbor_solicitation icmp_neighbor_advertisement +event icmp_redirect%(c: connection, icmp: icmp_conn, tgt: addr, dest: addr, options: icmp6_nd_options%); + diff --git a/src/analyzer/protocol/ident/CMakeLists.txt b/src/analyzer/protocol/ident/CMakeLists.txt new file mode 100644 index 0000000000..658dff141e --- /dev/null +++ b/src/analyzer/protocol/ident/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro Ident) +bro_plugin_cc(Ident.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/Ident.cc b/src/analyzer/protocol/ident/Ident.cc similarity index 81% rename from src/Ident.cc rename to src/analyzer/protocol/ident/Ident.cc index b2e82e5f12..8e25775af8 100644 --- a/src/Ident.cc +++ b/src/analyzer/protocol/ident/Ident.cc @@ -8,13 +8,17 @@ #include "Ident.h" #include "Event.h" +#include "events.bif.h" + +using namespace analyzer::ident; + Ident_Analyzer::Ident_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::Ident, conn) +: tcp::TCP_ApplicationAnalyzer("IDENT", conn) { did_bad_reply = did_deliver = 0; - orig_ident = new ContentLine_Analyzer(conn, true); - resp_ident = new ContentLine_Analyzer(conn, false); + orig_ident = new tcp::ContentLine_Analyzer(conn, true); + resp_ident = new tcp::ContentLine_Analyzer(conn, false); orig_ident->SetIsNULSensitive(true); resp_ident->SetIsNULSensitive(true); @@ -25,29 +29,29 @@ Ident_Analyzer::Ident_Analyzer(Connection* conn) void Ident_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); if ( TCP() ) if ( (! did_deliver || orig_ident->HasPartialLine()) && - (TCP()->OrigState() == TCP_ENDPOINT_CLOSED || - TCP()->OrigPrevState() == TCP_ENDPOINT_CLOSED) && - TCP()->OrigPrevState() != TCP_ENDPOINT_PARTIAL && - TCP()->RespPrevState() != TCP_ENDPOINT_PARTIAL && - TCP()->OrigPrevState() != TCP_ENDPOINT_INACTIVE && - TCP()->RespPrevState() != TCP_ENDPOINT_INACTIVE ) + (TCP()->OrigState() == tcp::TCP_ENDPOINT_CLOSED || + TCP()->OrigPrevState() == tcp::TCP_ENDPOINT_CLOSED) && + TCP()->OrigPrevState() != tcp::TCP_ENDPOINT_PARTIAL && + TCP()->RespPrevState() != tcp::TCP_ENDPOINT_PARTIAL && + TCP()->OrigPrevState() != tcp::TCP_ENDPOINT_INACTIVE && + TCP()->RespPrevState() != tcp::TCP_ENDPOINT_INACTIVE ) Weird("partial_ident_request"); } void Ident_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig) { - TCP_ApplicationAnalyzer::DeliverStream(length, data, is_orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(length, data, is_orig); int remote_port, local_port; const char* line = (const char*) data; const char* orig_line = line; const char* end_of_line = line + length; - TCP_Endpoint* s = 0; + tcp::TCP_Endpoint* s = 0; if ( TCP() ) s = is_orig ? TCP()->Orig() : TCP()->Resp(); @@ -60,9 +64,9 @@ void Ident_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig) line = ParsePair(line, end_of_line, remote_port, local_port); if ( ! line ) { - if ( s && s->state == TCP_ENDPOINT_CLOSED && - (s->prev_state == TCP_ENDPOINT_INACTIVE || - s->prev_state == TCP_ENDPOINT_PARTIAL) ) + if ( s && s->state == tcp::TCP_ENDPOINT_CLOSED && + (s->prev_state == tcp::TCP_ENDPOINT_INACTIVE || + s->prev_state == tcp::TCP_ENDPOINT_PARTIAL) ) // not surprising the request is mangled. return; @@ -95,9 +99,9 @@ void Ident_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig) if ( ! line || line == end_of_line || line[0] != ':' ) { - if ( s && s->state == TCP_ENDPOINT_CLOSED && - (s->prev_state == TCP_ENDPOINT_INACTIVE || - s->prev_state == TCP_ENDPOINT_PARTIAL) ) + if ( s && s->state == tcp::TCP_ENDPOINT_CLOSED && + (s->prev_state == tcp::TCP_ENDPOINT_INACTIVE || + s->prev_state == tcp::TCP_ENDPOINT_PARTIAL) ) // not surprising the request is mangled. return; diff --git a/src/Ident.h b/src/analyzer/protocol/ident/Ident.h similarity index 57% rename from src/Ident.h rename to src/analyzer/protocol/ident/Ident.h index a848d233e1..31df1dcdc6 100644 --- a/src/Ident.h +++ b/src/analyzer/protocol/ident/Ident.h @@ -1,24 +1,23 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef ident_h -#define ident_h +#ifndef ANALYZER_PROTOCOL_IDENT_IDENT_H +#define ANALYZER_PROTOCOL_IDENT_IDENT_H -#include "TCP.h" -#include "ContentLine.h" +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/tcp/ContentLine.h" -class Ident_Analyzer : public TCP_ApplicationAnalyzer { +namespace analyzer { namespace ident { + +class Ident_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: Ident_Analyzer(Connection* conn); virtual void Done(); virtual void DeliverStream(int length, const u_char* data, bool is_orig); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new Ident_Analyzer(conn); } - static bool Available() - { return ident_request || ident_reply || ident_error; } - protected: const char* ParsePair(const char* line, const char* end_of_line, int& p1, int &p2); @@ -28,11 +27,13 @@ protected: void BadRequest(int length, const char* line); void BadReply(int length, const char* line); - ContentLine_Analyzer* orig_ident; - ContentLine_Analyzer* resp_ident; + tcp::ContentLine_Analyzer* orig_ident; + tcp::ContentLine_Analyzer* resp_ident; unsigned int did_deliver:1; unsigned int did_bad_reply:1; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/ident/Plugin.cc b/src/analyzer/protocol/ident/Plugin.cc new file mode 100644 index 0000000000..c053689b8f --- /dev/null +++ b/src/analyzer/protocol/ident/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "Ident.h" + +BRO_PLUGIN_BEGIN(Bro, Ident) + BRO_PLUGIN_DESCRIPTION("Ident analyzer"); + BRO_PLUGIN_ANALYZER("Ident", ident::Ident_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/ident/events.bif b/src/analyzer/protocol/ident/events.bif new file mode 100644 index 0000000000..96a7f37a31 --- /dev/null +++ b/src/analyzer/protocol/ident/events.bif @@ -0,0 +1,63 @@ +## Generated for Ident requests. +## +## See `Wikipedia `__ for more +## information about the Ident protocol. +## +## c: The connection. +## +## lport: The request's local port. +## +## rport: The request's remote port. +## +## .. bro:see:: ident_error ident_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event ident_request%(c: connection, lport: port, rport: port%); + +## Generated for Ident replies. +## +## See `Wikipedia `__ for more +## information about the Ident protocol. +## +## c: The connection. +## +## lport: The corresponding request's local port. +## +## rport: The corresponding request's remote port. +## +## user_id: The user id returned by the reply. +## +## system: The operating system returned by the reply. +## +## .. bro:see:: ident_error ident_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event ident_reply%(c: connection, lport: port, rport: port, user_id: string, system: string%); + +## Generated for Ident error replies. +## +## See `Wikipedia `__ for more +## information about the Ident protocol. +## +## c: The connection. +## +## lport: The corresponding request's local port. +## +## rport: The corresponding request's remote port. +## +## line: The error description returned by the reply. +## +## .. bro:see:: ident_reply ident_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event ident_error%(c: connection, lport: port, rport: port, line: string%); + diff --git a/src/analyzer/protocol/interconn/CMakeLists.txt b/src/analyzer/protocol/interconn/CMakeLists.txt new file mode 100644 index 0000000000..ef5ca13a9a --- /dev/null +++ b/src/analyzer/protocol/interconn/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro InterConn) +bro_plugin_cc(InterConn.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/InterConn.cc b/src/analyzer/protocol/interconn/InterConn.cc similarity index 92% rename from src/InterConn.cc rename to src/analyzer/protocol/interconn/InterConn.cc index 403081181a..4b298eaa52 100644 --- a/src/InterConn.cc +++ b/src/analyzer/protocol/interconn/InterConn.cc @@ -5,9 +5,13 @@ #include "InterConn.h" #include "Event.h" #include "Net.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" -InterConnEndpoint::InterConnEndpoint(TCP_Endpoint* e) +#include "events.bif.h" + +using namespace analyzer::interconn; + +InterConnEndpoint::InterConnEndpoint(tcp::TCP_Endpoint* e) { endp = e; max_top_seq = 0; @@ -30,7 +34,7 @@ int InterConnEndpoint::DataSent(double t, int seq, int len, int caplen, if ( len <= 0 ) return 0; - if ( endp->state == TCP_ENDPOINT_PARTIAL ) + if ( endp->state == tcp::TCP_ENDPOINT_PARTIAL ) is_partial = 1; int ack = endp->AckSeq() - endp->StartSeq(); @@ -153,7 +157,7 @@ int InterConnEndpoint::IsNormalKeystrokeInterarrival(double t) const } InterConn_Analyzer::InterConn_Analyzer(Connection* c) -: TCP_ApplicationAnalyzer(AnalyzerTag::InterConn, c) +: tcp::TCP_ApplicationAnalyzer("INTERCONN", c) { orig_endp = resp_endp = 0; orig_stream_pos = resp_stream_pos = 1; @@ -172,7 +176,7 @@ InterConn_Analyzer::~InterConn_Analyzer() void InterConn_Analyzer::Init() { - TCP_ApplicationAnalyzer::Init(); + tcp::TCP_ApplicationAnalyzer::Init(); assert(TCP()); orig_endp = new InterConnEndpoint(TCP()->Orig()); @@ -182,7 +186,7 @@ void InterConn_Analyzer::Init() void InterConn_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen) { - TCP_ApplicationAnalyzer::DeliverPacket(len, data, is_orig, + tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); if ( is_orig ) @@ -193,7 +197,7 @@ void InterConn_Analyzer::DeliverPacket(int len, const u_char* data, void InterConn_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) { - TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig); if ( is_orig ) { @@ -218,7 +222,7 @@ void InterConn_Analyzer::Done() RemoveEvent(); } - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); } void InterConn_Analyzer::StatTimer(double t, int is_expire) diff --git a/src/InterConn.h b/src/analyzer/protocol/interconn/InterConn.h similarity index 80% rename from src/InterConn.h rename to src/analyzer/protocol/interconn/InterConn.h index d9cd10de27..b13abecab1 100644 --- a/src/InterConn.h +++ b/src/analyzer/protocol/interconn/InterConn.h @@ -1,15 +1,17 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef interconn_h -#define interconn_h +#ifndef ANALYZER_PROTOCOL_INTERCONN_INTERCONN_H +#define ANALYZER_PROTOCOL_INTERCONN_INTERCONN_H -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #include "Timer.h" #include "NetVar.h" +namespace analyzer { namespace interconn { + class InterConnEndpoint : public BroObj { public: - InterConnEndpoint(TCP_Endpoint* e); + InterConnEndpoint(tcp::TCP_Endpoint* e); int DataSent(double t, int seq, int len, int caplen, const u_char* data, const IP_Hdr* ip, const struct tcphdr* tp); @@ -21,7 +23,7 @@ protected: int IsPotentialKeystrokePacket(int len) const; int IsNormalKeystrokeInterarrival(double t) const; - TCP_Endpoint* endp; + tcp::TCP_Endpoint* endp; double last_keystroke_time; int max_top_seq; uint32 num_pkts; @@ -38,7 +40,7 @@ protected: }; -class InterConn_Analyzer : public TCP_ApplicationAnalyzer { +class InterConn_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: InterConn_Analyzer(Connection* c); ~InterConn_Analyzer(); @@ -47,11 +49,9 @@ public: virtual void Done(); void StatTimer(double t, int is_expire); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new InterConn_Analyzer(conn); } - static bool Available() { return interconn_stats; } - protected: // We support both packet and stream input and can be put in place even // if the TCP analyzer is not yet reassembling. @@ -83,4 +83,6 @@ protected: InterConn_Analyzer* analyzer; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/interconn/Plugin.cc b/src/analyzer/protocol/interconn/Plugin.cc new file mode 100644 index 0000000000..c135d0fb07 --- /dev/null +++ b/src/analyzer/protocol/interconn/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "InterConn.h" + +BRO_PLUGIN_BEGIN(Bro, InterConn) + BRO_PLUGIN_DESCRIPTION("InterConn analyzer (deprecated)"); + BRO_PLUGIN_ANALYZER("InterConn", interconn::InterConn_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/interconn/events.bif b/src/analyzer/protocol/interconn/events.bif new file mode 100644 index 0000000000..6e859da668 --- /dev/null +++ b/src/analyzer/protocol/interconn/events.bif @@ -0,0 +1,8 @@ +# ##### Deprecated events. Proposed for removal. + +## Deprecated. Will be removed. +event interconn_stats%(c: connection, os: interconn_endp_stats, rs: interconn_endp_stats%); + +## Deprecated. Will be removed. +event interconn_remove_conn%(c: connection%); + diff --git a/src/analyzer/protocol/irc/CMakeLists.txt b/src/analyzer/protocol/irc/CMakeLists.txt new file mode 100644 index 0000000000..5f97482365 --- /dev/null +++ b/src/analyzer/protocol/irc/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro IRC) +bro_plugin_cc(IRC.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/IRC.cc b/src/analyzer/protocol/irc/IRC.cc similarity index 95% rename from src/IRC.cc rename to src/analyzer/protocol/irc/IRC.cc index 1918300ba2..71f591635f 100644 --- a/src/IRC.cc +++ b/src/analyzer/protocol/irc/IRC.cc @@ -2,15 +2,18 @@ #include #include "IRC.h" -#include "DPM.h" -#include "ContentLine.h" +#include "analyzer/protocol/tcp/ContentLine.h" #include "NetVar.h" #include "Event.h" -#include "ZIP.h" +#include "analyzer/protocol/zip/ZIP.h" +#include "analyzer/Manager.h" +#include "events.bif.h" + +using namespace analyzer::irc; IRC_Analyzer::IRC_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::IRC, conn) +: tcp::TCP_ApplicationAnalyzer("IRC", conn) { invalid_msg_count = 0; invalid_msg_max_count = 20; @@ -18,50 +21,18 @@ IRC_Analyzer::IRC_Analyzer(Connection* conn) resp_status = WAIT_FOR_REGISTRATION; orig_zip_status = NO_ZIP; resp_zip_status = NO_ZIP; - AddSupportAnalyzer(new ContentLine_Analyzer(conn, true)); - AddSupportAnalyzer(new ContentLine_Analyzer(conn, false)); - } - -bool IRC_Analyzer::Available() - { - static bool did_avail = false; - static bool avail = false; - - if ( ! did_avail ) - { - // It's a lot of events, but for consistency with other - // analyzers we need to check for all of them. - avail = irc_request || irc_reply || - irc_message || irc_quit_message || - irc_privmsg_message || irc_notice_message || - irc_squery_message || irc_join_message || - irc_part_message || irc_nick_message || - irc_invalid_nick || irc_network_info || - irc_server_info || irc_channel_info || irc_who_line || - irc_who_message || irc_whois_message || - irc_whois_user_line || irc_whois_operator_line || - irc_whois_channel_line || irc_oper_message || - irc_oper_response || irc_kick_message || - irc_error_message || irc_invite_message || - irc_mode_message || irc_squit_message || - irc_names_info || irc_dcc_message || - irc_global_users || irc_user_message || - irc_channel_topic || irc_password_message; - - did_avail = true; - } - - return avail; + AddSupportAnalyzer(new tcp::ContentLine_Analyzer(conn, true)); + AddSupportAnalyzer(new tcp::ContentLine_Analyzer(conn, false)); } void IRC_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); } void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { - TCP_ApplicationAnalyzer::DeliverStream(length, line, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(length, line, orig); // check line size if ( length > 512 ) @@ -1190,8 +1161,8 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { orig_zip_status = ZIP_LOADED; resp_zip_status = ZIP_LOADED; - AddSupportAnalyzer(new ZIP_Analyzer(Conn(), true)); - AddSupportAnalyzer(new ZIP_Analyzer(Conn(), false)); + AddSupportAnalyzer(new zip::ZIP_Analyzer(Conn(), true)); + AddSupportAnalyzer(new zip::ZIP_Analyzer(Conn(), false)); } return; diff --git a/src/IRC.h b/src/analyzer/protocol/irc/IRC.h similarity index 80% rename from src/IRC.h rename to src/analyzer/protocol/irc/IRC.h index 0fe36957de..a4112ccb12 100644 --- a/src/IRC.h +++ b/src/analyzer/protocol/irc/IRC.h @@ -1,13 +1,15 @@ // An IRC analyzer contributed by Roland Gruber. -#ifndef irc_h -#define irc_h -#include "TCP.h" +#ifndef ANALYZER_PROTOCOL_IRC_IRC_H +#define ANALYZER_PROTOCOL_IRC_IRC_H +#include "analyzer/protocol/tcp/TCP.h" + +namespace analyzer { namespace irc { /** * \brief Main class for analyzing IRC traffic. */ -class IRC_Analyzer : public TCP_ApplicationAnalyzer { +class IRC_Analyzer : public tcp::TCP_ApplicationAnalyzer { enum { WAIT_FOR_REGISTRATION, REGISTERED, }; enum { NO_ZIP, ACCEPT_ZIP, ZIP_LOADED, }; public: @@ -30,13 +32,11 @@ public: */ virtual void DeliverStream(int len, const u_char* data, bool orig); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new IRC_Analyzer(conn); } - static bool Available(); - protected: int orig_status; int orig_zip_status; @@ -62,4 +62,6 @@ private: }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/irc/Plugin.cc b/src/analyzer/protocol/irc/Plugin.cc new file mode 100644 index 0000000000..fc7de1bd6d --- /dev/null +++ b/src/analyzer/protocol/irc/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "IRC.h" + +BRO_PLUGIN_BEGIN(Bro, IRC) + BRO_PLUGIN_DESCRIPTION("IRC analyzer"); + BRO_PLUGIN_ANALYZER("IRC", irc::IRC_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/irc/events.bif b/src/analyzer/protocol/irc/events.bif new file mode 100644 index 0000000000..4e69b9ad33 --- /dev/null +++ b/src/analyzer/protocol/irc/events.bif @@ -0,0 +1,799 @@ + +## Generated for all client-side IRC commands. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: Always true. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## command: The command. +## +## arguments: The arguments for the command. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +## +## .. note:: This event is generated only for messages that originate +## at the client-side. Commands coming in from remote trigger +## the :bro:id:`irc_message` event instead. +event irc_request%(c: connection, is_orig: bool, prefix: string, + command: string, arguments: string%); + +## Generated for all IRC replies. IRC replies are sent in response to a +## request and come with a reply code. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## prefix: The optional prefix coming with the reply. IRC uses the prefix to +## indicate the true origin of a message. +## +## code: The reply code, as specified by the protocol. +## +## params: The reply's parameters. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_reply%(c: connection, is_orig: bool, prefix: string, + code: count, params: string%); + +## Generated for IRC commands forwarded from the server to the client. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: Always false. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## command: The command. +## +## message: TODO. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +## +## .. note:: +## +## This event is generated only for messages that are forwarded by the server +## to the client. Commands coming from client trigger the +## :bro:id:`irc_request` event instead. +event irc_message%(c: connection, is_orig: bool, prefix: string, + command: string, message: string%); + +## Generated for IRC messages of type *quit*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## nick: The nickname coming with the message. +## +## message: The text included with the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_quit_message%(c: connection, is_orig: bool, nick: string, message: string%); + +## Generated for IRC messages of type *privmsg*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## source: The source of the private communication. +## +## target: The target of the private communication. +## +## message: The text of communication. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_privmsg_message%(c: connection, is_orig: bool, source: string, + target: string, message: string%); + +## Generated for IRC messages of type *notice*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## source: The source of the private communication. +## +## target: The target of the private communication. +## +## message: The text of communication. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_notice_message%(c: connection, is_orig: bool, source: string, + target: string, message: string%); + +## Generated for IRC messages of type *squery*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## source: The source of the private communication. +## +## target: The target of the private communication. +## +## message: The text of communication. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_squery_message%(c: connection, is_orig: bool, source: string, + target: string, message: string%); + +## Generated for IRC messages of type *join*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## info_list: The user information coming with the command. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_join_message%(c: connection, is_orig: bool, info_list: irc_join_list%); + +## Generated for IRC messages of type *part*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## nick: The nickname coming with the message. +## +## chans: The set of channels affected. +## +## message: The text coming with the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_password_message +event irc_part_message%(c: connection, is_orig: bool, nick: string, + chans: string_set, message: string%); + +## Generated for IRC messages of type *nick*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## who: The user changing its nickname. +## +## newnick: The new nickname. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_nick_message%(c: connection, is_orig: bool, who: string, newnick: string%); + +## Generated when a server rejects an IRC nickname. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_invalid_nick%(c: connection, is_orig: bool%); + +## Generated for an IRC reply of type *luserclient*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## users: The number of users as returned in the reply. +## +## services: The number of services as returned in the reply. +## +## servers: The number of servers as returned in the reply. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_network_info%(c: connection, is_orig: bool, users: count, + services: count, servers: count%); + +## Generated for an IRC reply of type *luserme*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## users: The number of users as returned in the reply. +## +## services: The number of services as returned in the reply. +## +## servers: The number of servers as returned in the reply. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_server_info%(c: connection, is_orig: bool, users: count, + services: count, servers: count%); + +## Generated for an IRC reply of type *luserchannels*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## chans: The number of channels as returned in the reply. +## +## .. bro:see:: irc_channel_topic irc_dcc_message irc_error_message irc_global_users +## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_channel_info%(c: connection, is_orig: bool, chans: count%); + +## Generated for an IRC reply of type *whoreply*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## target_nick: The target nickname. +## +## channel: The channel. +## +## user: The user. +## +## host: The host. +## +## server: The server. +## +## nick: The nickname. +## +## params: The parameters. +## +## hops: The hop count. +## +## real_name: The real name. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_who_line%(c: connection, is_orig: bool, target_nick: string, + channel: string, user: string, host: string, + server: string, nick: string, params: string, + hops: count, real_name: string%); + + +## Generated for an IRC reply of type *namereply*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## c_type: The channel type. +## +## channel: The channel. +## +## users: The set of users. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_names_info%(c: connection, is_orig: bool, c_type: string, + channel: string, users: string_set%); + +## Generated for an IRC reply of type *whoisoperator*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## nick: The nickname specified in the reply. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_whois_operator_line%(c: connection, is_orig: bool, nick: string%); + +## Generated for an IRC reply of type *whoischannels*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## nick: The nickname specified in the reply. +## +## chans: The set of channels returned. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_whois_channel_line%(c: connection, is_orig: bool, nick: string, + chans: string_set%); + +## Generated for an IRC reply of type *whoisuser*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## nick: The nickname specified in the reply. +## +## user: The user name specified in the reply. +## +## host: The host name specified in the reply. +## +## real_name: The real name specified in the reply. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_whois_user_line%(c: connection, is_orig: bool, nick: string, + user: string, host: string, real_name: string%); + +## Generated for IRC replies of type *youreoper* and *nooperhost*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## got_oper: True if the *oper* command was executed successfully +## (*youreport*) and false otherwise (*nooperhost*). +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_part_message +## irc_password_message +event irc_oper_response%(c: connection, is_orig: bool, got_oper: bool%); + +## Generated for an IRC reply of type *globalusers*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## msg: The message coming with the reply. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_global_users%(c: connection, is_orig: bool, prefix: string, msg: string%); + +## Generated for an IRC reply of type *topic*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## channel: The channel name specified in the reply. +## +## topic: The topic specified in the reply. +## +## .. bro:see:: irc_channel_info irc_dcc_message irc_error_message irc_global_users +## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_channel_topic%(c: connection, is_orig: bool, channel: string, topic: string%); + +## Generated for IRC messages of type *who*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## mask: The mask specified in the message. +## +## oper: True if the operator flag was set. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_who_message%(c: connection, is_orig: bool, mask: string, oper: bool%); + +## Generated for IRC messages of type *whois*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## server: TODO. +## +## users: TODO. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_whois_message%(c: connection, is_orig: bool, server: string, users: string%); + +## Generated for IRC messages of type *oper*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## user: The user specified in the message. +## +## password: The password specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_response irc_part_message +## irc_password_message +event irc_oper_message%(c: connection, is_orig: bool, user: string, password: string%); + +## Generated for IRC messages of type *kick*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## chans: The channels specified in the message. +## +## users: The users specified in the message. +## +## comment: The comment specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_kick_message%(c: connection, is_orig: bool, prefix: string, + chans: string, users: string, comment: string%); + +## Generated for IRC messages of type *error*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## message: The textual description specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_global_users +## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_error_message%(c: connection, is_orig: bool, prefix: string, message: string%); + +## Generated for IRC messages of type *invite*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## nickname: The nickname specified in the message. +## +## channel: The channel specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_invite_message%(c: connection, is_orig: bool, prefix: string, + nickname: string, channel: string%); + +## Generated for IRC messages of type *mode*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## params: The parameters coming with the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_mode_message%(c: connection, is_orig: bool, prefix: string, params: string%); + +## Generated for IRC messages of type *squit*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## server: The server specified in the message. +## +## message: The textual description specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_squit_message%(c: connection, is_orig: bool, prefix: string, + server: string, message: string%); + +## Generated for IRC messages of type *dcc*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## target: The target specified in the message. +## +## dcc_type: The DCC type specified in the message. +## +## argument: The argument specified in the message. +## +## address: The address specified in the message. +## +## dest_port: The destination port specified in the message. +## +## size: The size specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_error_message irc_global_users +## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_dcc_message%(c: connection, is_orig: bool, + prefix: string, target: string, + dcc_type: string, argument: string, + address: addr, dest_port: count, size: count%); + +## Generated for IRC messages of type *user*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## user: The user specified in the message. +## +## host: The host name specified in the message. +## +## server: The server name specified in the message. +## +## real_name: The real name specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_user_message%(c: connection, is_orig: bool, user: string, host: string, server: string, real_name: string%); + +## Generated for IRC messages of type *password*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## password: The password specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message +event irc_password_message%(c: connection, is_orig: bool, password: string%); diff --git a/src/analyzer/protocol/login/CMakeLists.txt b/src/analyzer/protocol/login/CMakeLists.txt new file mode 100644 index 0000000000..66f8eb1568 --- /dev/null +++ b/src/analyzer/protocol/login/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro Login) +bro_plugin_cc(Login.cc RSH.cc Telnet.cc Rlogin.cc NVT.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_bif(functions.bif) +bro_plugin_end() diff --git a/src/Login.cc b/src/analyzer/protocol/login/Login.cc similarity index 97% rename from src/Login.cc rename to src/analyzer/protocol/login/Login.cc index e626fb3a0a..335b855f1d 100644 --- a/src/Login.cc +++ b/src/analyzer/protocol/login/Login.cc @@ -10,6 +10,10 @@ #include "RE.h" #include "Event.h" +#include "events.bif.h" + +using namespace analyzer::login; + static RE_Matcher* re_skip_authentication = 0; static RE_Matcher* re_direct_login_prompts; static RE_Matcher* re_login_prompts; @@ -20,8 +24,8 @@ static RE_Matcher* re_login_timeouts; static RE_Matcher* init_RE(ListVal* l); -Login_Analyzer::Login_Analyzer(AnalyzerTag::Tag tag, Connection* conn) -: TCP_ApplicationAnalyzer(tag, conn) +Login_Analyzer::Login_Analyzer(const char* name, Connection* conn) +: tcp::TCP_ApplicationAnalyzer(name, conn) { state = LOGIN_STATE_AUTHENTICATE; num_user_lines_seen = lines_scanned = 0; @@ -65,7 +69,7 @@ Login_Analyzer::~Login_Analyzer() void Login_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { - TCP_ApplicationAnalyzer::DeliverStream(length, line, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(length, line, orig); char* str = new char[length+1]; @@ -102,8 +106,8 @@ void Login_Analyzer::NewLine(bool orig, char* line) if ( state == LOGIN_STATE_AUTHENTICATE ) { - if ( TCP()->OrigState() == TCP_ENDPOINT_PARTIAL || - TCP()->RespState() == TCP_ENDPOINT_PARTIAL ) + if ( TCP()->OrigState() == tcp::TCP_ENDPOINT_PARTIAL || + TCP()->RespState() == tcp::TCP_ENDPOINT_PARTIAL ) state = LOGIN_STATE_CONFUSED; // unknown login state else { @@ -361,7 +365,7 @@ void Login_Analyzer::SetEnv(bool orig, char* name, char* val) void Login_Analyzer::EndpointEOF(bool orig) { - TCP_ApplicationAnalyzer::EndpointEOF(orig); + tcp::TCP_ApplicationAnalyzer::EndpointEOF(orig); if ( state == LOGIN_STATE_AUTHENTICATE && HaveTypeahead() ) { diff --git a/src/Login.h b/src/analyzer/protocol/login/Login.h similarity index 88% rename from src/Login.h rename to src/analyzer/protocol/login/Login.h index b186cc52d2..2178bdff1a 100644 --- a/src/Login.h +++ b/src/analyzer/protocol/login/Login.h @@ -1,9 +1,11 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef login_h -#define login_h +#ifndef ANALYZER_PROTOCOL_LOGIN_LOGIN_H +#define ANALYZER_PROTOCOL_LOGIN_LOGIN_H -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" + +namespace analyzer { namespace login { typedef enum { LOGIN_STATE_AUTHENTICATE, // trying to authenticate @@ -19,9 +21,9 @@ typedef enum { // Maximum # lines look after login for failure. #define MAX_LOGIN_LOOKAHEAD 10 -class Login_Analyzer : public TCP_ApplicationAnalyzer { +class Login_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: - Login_Analyzer(AnalyzerTag::Tag tag, Connection* conn); + Login_Analyzer(const char* name, Connection* conn); ~Login_Analyzer(); virtual void DeliverStream(int len, const u_char* data, bool orig); @@ -82,4 +84,6 @@ protected: int saw_ploy; }; +} } // namespace analyzer::* + #endif diff --git a/src/NVT.cc b/src/analyzer/protocol/login/NVT.cc similarity index 98% rename from src/NVT.cc rename to src/analyzer/protocol/login/NVT.cc index 5ba12ac32a..62e4d0c050 100644 --- a/src/NVT.cc +++ b/src/analyzer/protocol/login/NVT.cc @@ -7,7 +7,9 @@ #include "NVT.h" #include "NetVar.h" #include "Event.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" + +#include "events.bif.h" #define IS_3_BYTE_OPTION(c) (c >= 251 && c <= 254) @@ -24,6 +26,8 @@ #define TELNET_IAC 255 +using namespace analyzer::login; + TelnetOption::TelnetOption(NVT_Analyzer* arg_endp, unsigned int arg_code) { endp = arg_endp; @@ -287,7 +291,7 @@ void TelnetEnvironmentOption::RecvSubOption(u_char* data, int len) break; } - static_cast + static_cast (endp->Parent())->SetEnv(endp->IsOrig(), var_name, var_val); } @@ -360,7 +364,7 @@ void TelnetBinaryOption::InconsistentOption(unsigned int /* type */) NVT_Analyzer::NVT_Analyzer(Connection* conn, bool orig) -: ContentLine_Analyzer(AnalyzerTag::NVT, conn, orig) +: tcp::ContentLine_Analyzer("NVT", conn, orig) { peer = 0; is_suboption = last_was_IAC = pending_IAC = 0; diff --git a/src/NVT.h b/src/analyzer/protocol/login/NVT.h similarity index 94% rename from src/NVT.h rename to src/analyzer/protocol/login/NVT.h index 61aa1ef740..3bcadcdc8e 100644 --- a/src/NVT.h +++ b/src/analyzer/protocol/login/NVT.h @@ -1,10 +1,9 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef nvt_h -#define nvt_h - -#include "ContentLine.h" +#ifndef ANALYZER_PROTOCOL_LOGIN_NVT_H +#define ANALYZER_PROTOCOL_LOGIN_NVT_H +#include "analyzer/protocol/tcp/ContentLine.h" #define TELNET_OPTION_BINARY 0 #define TELNET_OPTION_TERMINAL 24 @@ -13,8 +12,9 @@ #define TELNET_OPTION_ENVIRON 39 #define NUM_TELNET_OPTIONS 5 -class NVT_Analyzer; +namespace analyzer { namespace login { +class NVT_Analyzer; class TelnetOption { public: @@ -123,7 +123,7 @@ protected: void InconsistentOption(unsigned int type); }; -class NVT_Analyzer : public ContentLine_Analyzer { +class NVT_Analyzer : public tcp::ContentLine_Analyzer { public: NVT_Analyzer(Connection* conn, bool orig); ~NVT_Analyzer(); @@ -170,4 +170,6 @@ protected: int num_options; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/login/Plugin.cc b/src/analyzer/protocol/login/Plugin.cc new file mode 100644 index 0000000000..6b8d1a8fed --- /dev/null +++ b/src/analyzer/protocol/login/Plugin.cc @@ -0,0 +1,20 @@ + +#include "plugin/Plugin.h" + +#include "Login.h" +#include "Telnet.h" +#include "RSH.h" +#include "Rlogin.h" + +BRO_PLUGIN_BEGIN(Bro, Login) + BRO_PLUGIN_DESCRIPTION("Telnet/Rsh/Rlogin analyzers"); + BRO_PLUGIN_ANALYZER("Telnet", login::Telnet_Analyzer); + BRO_PLUGIN_ANALYZER("Rsh", login::Rsh_Analyzer); + BRO_PLUGIN_ANALYZER("Rlogin", login::Rlogin_Analyzer); + BRO_PLUGIN_ANALYZER_BARE("NVT"); + BRO_PLUGIN_ANALYZER_BARE("Login"); + BRO_PLUGIN_SUPPORT_ANALYZER("Contents_Rsh"); + BRO_PLUGIN_SUPPORT_ANALYZER("Contents_Rlogin"); + BRO_PLUGIN_BIF_FILE(events); + BRO_PLUGIN_BIF_FILE(functions); +BRO_PLUGIN_END diff --git a/src/RSH.cc b/src/analyzer/protocol/login/RSH.cc similarity index 92% rename from src/RSH.cc rename to src/analyzer/protocol/login/RSH.cc index ceef3ba7a4..1890fc3098 100644 --- a/src/RSH.cc +++ b/src/analyzer/protocol/login/RSH.cc @@ -6,12 +6,15 @@ #include "Event.h" #include "RSH.h" +#include "events.bif.h" + +using namespace analyzer::login; // FIXME: this code should probably be merged with Rlogin.cc. Contents_Rsh_Analyzer::Contents_Rsh_Analyzer(Connection* conn, bool orig, Rsh_Analyzer* arg_analyzer) -: ContentLine_Analyzer(AnalyzerTag::Contents_Rsh, conn, orig) +: tcp::ContentLine_Analyzer("CONTENTS_RSH", conn, orig) { num_bytes_to_scan = 0; analyzer = arg_analyzer; @@ -28,7 +31,7 @@ Contents_Rsh_Analyzer::~Contents_Rsh_Analyzer() void Contents_Rsh_Analyzer::DoDeliver(int len, const u_char* data) { - TCP_Analyzer* tcp = static_cast(Parent())->TCP(); + tcp::TCP_Analyzer* tcp = static_cast(Parent())->TCP(); assert(tcp); int endp_state = IsOrig() ? tcp->OrigState() : tcp->RespState(); @@ -42,10 +45,10 @@ void Contents_Rsh_Analyzer::DoDeliver(int len, const u_char* data) switch ( state ) { case RSH_FIRST_NULL: - if ( endp_state == TCP_ENDPOINT_PARTIAL || + if ( endp_state == tcp::TCP_ENDPOINT_PARTIAL || // We can be in closed if the data's due to // a dataful FIN being the first thing we see. - endp_state == TCP_ENDPOINT_CLOSED ) + endp_state == tcp::TCP_ENDPOINT_CLOSED ) { state = RSH_UNKNOWN; ++len, --data; // put back c and reprocess @@ -138,7 +141,7 @@ void Contents_Rsh_Analyzer::BadProlog() } Rsh_Analyzer::Rsh_Analyzer(Connection* conn) -: Login_Analyzer(AnalyzerTag::Rsh, conn) +: Login_Analyzer("RSH", conn) { contents_orig = new Contents_Rsh_Analyzer(conn, true, this); contents_resp = new Contents_Rsh_Analyzer(conn, false, this); diff --git a/src/RSH.h b/src/analyzer/protocol/login/RSH.h similarity index 79% rename from src/RSH.h rename to src/analyzer/protocol/login/RSH.h index 136d0b07f1..2036ea966a 100644 --- a/src/RSH.h +++ b/src/analyzer/protocol/login/RSH.h @@ -1,10 +1,12 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef rsh_h -#define rsh_h +#ifndef ANALYZER_PROTOCOL_LOGIN_RSH_H +#define ANALYZER_PROTOCOL_LOGIN_RSH_H #include "Login.h" -#include "ContentLine.h" +#include "analyzer/protocol/tcp/ContentLine.h" + +namespace analyzer { namespace login { typedef enum { RSH_FIRST_NULL, // waiting to see first NUL @@ -21,7 +23,7 @@ typedef enum { class Rsh_Analyzer; -class Contents_Rsh_Analyzer : public ContentLine_Analyzer { +class Contents_Rsh_Analyzer : public tcp::ContentLine_Analyzer { public: Contents_Rsh_Analyzer(Connection* conn, bool orig, Rsh_Analyzer* analyzer); ~Contents_Rsh_Analyzer(); @@ -47,14 +49,13 @@ public: void ClientUserName(const char* s); void ServerUserName(const char* s); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new Rsh_Analyzer(conn); } - static bool Available() - { return login_failure || login_success || login_input_line || login_output_line; } - Contents_Rsh_Analyzer* contents_orig; Contents_Rsh_Analyzer* contents_resp; }; +} } // namespace analyzer::* + #endif diff --git a/src/Rlogin.cc b/src/analyzer/protocol/login/Rlogin.cc similarity index 91% rename from src/Rlogin.cc rename to src/analyzer/protocol/login/Rlogin.cc index 1ad3f16d7e..9a31a47aa1 100644 --- a/src/Rlogin.cc +++ b/src/analyzer/protocol/login/Rlogin.cc @@ -6,9 +6,12 @@ #include "Event.h" #include "Rlogin.h" +#include "events.bif.h" + +using namespace analyzer::login; Contents_Rlogin_Analyzer::Contents_Rlogin_Analyzer(Connection* conn, bool orig, Rlogin_Analyzer* arg_analyzer) -: ContentLine_Analyzer(AnalyzerTag::Contents_Rlogin, conn, orig) +: tcp::ContentLine_Analyzer("CONTENTLINE", conn, orig) { num_bytes_to_scan = 0; analyzer = arg_analyzer; @@ -26,7 +29,7 @@ Contents_Rlogin_Analyzer::~Contents_Rlogin_Analyzer() void Contents_Rlogin_Analyzer::DoDeliver(int len, const u_char* data) { - TCP_Analyzer* tcp = static_cast(Parent())->TCP(); + tcp::TCP_Analyzer* tcp = static_cast(Parent())->TCP(); assert(tcp); int endp_state = IsOrig() ? tcp->OrigState() : tcp->RespState(); @@ -40,10 +43,10 @@ void Contents_Rlogin_Analyzer::DoDeliver(int len, const u_char* data) switch ( state ) { case RLOGIN_FIRST_NULL: - if ( endp_state == TCP_ENDPOINT_PARTIAL || + if ( endp_state == tcp::TCP_ENDPOINT_PARTIAL || // We can be in closed if the data's due to // a dataful FIN being the first thing we see. - endp_state == TCP_ENDPOINT_CLOSED ) + endp_state == tcp::TCP_ENDPOINT_CLOSED ) { state = RLOGIN_UNKNOWN; ++len, --data; // put back c and reprocess @@ -85,10 +88,10 @@ void Contents_Rlogin_Analyzer::DoDeliver(int len, const u_char* data) break; case RLOGIN_SERVER_ACK: - if ( endp_state == TCP_ENDPOINT_PARTIAL || + if ( endp_state == tcp::TCP_ENDPOINT_PARTIAL || // We can be in closed if the data's due to // a dataful FIN being the first thing we see. - endp_state == TCP_ENDPOINT_CLOSED ) + endp_state == tcp::TCP_ENDPOINT_CLOSED ) { state = RLOGIN_UNKNOWN; ++len, --data; // put back c and reprocess @@ -204,7 +207,7 @@ void Contents_Rlogin_Analyzer::BadProlog() Rlogin_Analyzer::Rlogin_Analyzer(Connection* conn) -: Login_Analyzer(AnalyzerTag::Rlogin, conn) +: Login_Analyzer("RLOGIN", conn) { Contents_Rlogin_Analyzer* orig = new Contents_Rlogin_Analyzer(conn, true, this); diff --git a/src/Rlogin.h b/src/analyzer/protocol/login/Rlogin.h similarity index 82% rename from src/Rlogin.h rename to src/analyzer/protocol/login/Rlogin.h index f8ad480630..79de3b8952 100644 --- a/src/Rlogin.h +++ b/src/analyzer/protocol/login/Rlogin.h @@ -1,10 +1,12 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef rlogin_h -#define rlogin_h +#ifndef ANALYZER_PROTOCOL_LOGIN_RLOGIN_H +#define ANALYZER_PROTOCOL_LOGIN_RLOGIN_H #include "Login.h" -#include "ContentLine.h" +#include "analyzer/protocol/tcp/ContentLine.h" + +namespace analyzer { namespace login { typedef enum { RLOGIN_FIRST_NULL, // waiting to see first NUL @@ -29,7 +31,7 @@ typedef enum { class Rlogin_Analyzer; -class Contents_Rlogin_Analyzer : public ContentLine_Analyzer { +class Contents_Rlogin_Analyzer : public tcp::ContentLine_Analyzer { public: Contents_Rlogin_Analyzer(Connection* conn, bool orig, Rlogin_Analyzer* analyzer); @@ -60,14 +62,10 @@ public: void ServerUserName(const char* s); void TerminalType(const char* s); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new Rlogin_Analyzer(conn); } - - static bool Available() - { - return login_failure || login_success || - login_input_line || login_output_line; - } }; +} } // namespace analyzer::* + #endif diff --git a/src/Telnet.cc b/src/analyzer/protocol/login/Telnet.cc similarity index 82% rename from src/Telnet.cc rename to src/analyzer/protocol/login/Telnet.cc index 62c7d7b500..c22b2afc5e 100644 --- a/src/Telnet.cc +++ b/src/analyzer/protocol/login/Telnet.cc @@ -5,8 +5,12 @@ #include "Telnet.h" #include "NVT.h" +#include "events.bif.h" + +using namespace analyzer::login; + Telnet_Analyzer::Telnet_Analyzer(Connection* conn) -: Login_Analyzer(AnalyzerTag::Telnet, conn) +: Login_Analyzer("TELNET", conn) { NVT_Analyzer* nvt_orig = new NVT_Analyzer(conn, true); NVT_Analyzer* nvt_resp = new NVT_Analyzer(conn, false); diff --git a/src/Telnet.h b/src/analyzer/protocol/login/Telnet.h similarity index 55% rename from src/Telnet.h rename to src/analyzer/protocol/login/Telnet.h index 5675775789..332281013c 100644 --- a/src/Telnet.h +++ b/src/analyzer/protocol/login/Telnet.h @@ -1,23 +1,21 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef telnet_h -#define telnet_h +#ifndef ANALYZER_PROTOCOL_LOGIN_TELNET_H +#define ANALYZER_PROTOCOL_LOGIN_TELNET_H #include "Login.h" +namespace analyzer { namespace login { + class Telnet_Analyzer : public Login_Analyzer { public: Telnet_Analyzer(Connection* conn); virtual ~Telnet_Analyzer() {} - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new Telnet_Analyzer(conn); } - - static bool Available() - { - return login_failure || login_success || - login_input_line || login_output_line; - } }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/login/events.bif b/src/analyzer/protocol/login/events.bif new file mode 100644 index 0000000000..68f1c3cf11 --- /dev/null +++ b/src/analyzer/protocol/login/events.bif @@ -0,0 +1,409 @@ +## Generated for client side commands on an RSH connection. +## +## See `RFC 1258 `__ for more information +## about the Rlogin/Rsh protocol. +## +## c: The connection. +## +## client_user: The client-side user name as sent in the initial protocol +## handshake. +## +## server_user: The server-side user name as sent in the initial protocol +## handshake. +## +## line: The command line sent in the request. +## +## new_session: True if this is the first command of the Rsh session. +## +## .. bro:see:: rsh_reply login_confused login_confused_text login_display +## login_failure login_input_line login_output_line login_prompt login_success +## login_terminal +## +## .. note:: For historical reasons, these events are separate from the +## ``login_`` events. Ideally, they would all be handled uniquely. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event rsh_request%(c: connection, client_user: string, server_user: string, line: string, new_session: bool%); + +## Generated for client side commands on an RSH connection. +## +## See `RFC 1258 `__ for more information +## about the Rlogin/Rsh protocol. +## +## c: The connection. +## +## client_user: The client-side user name as sent in the initial protocol +## handshake. +## +## server_user: The server-side user name as sent in the initial protocol +## handshake. +## +## line: The command line sent in the request. +## +## .. bro:see:: rsh_request login_confused login_confused_text login_display +## login_failure login_input_line login_output_line login_prompt login_success +## login_terminal +## +## .. note:: For historical reasons, these events are separate from the +## ``login_`` events. Ideally, they would all be handled uniquely. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event rsh_reply%(c: connection, client_user: string, server_user: string, line: string%); + +## Generated for Telnet/Rlogin login failures. The *login* analyzer inspects +## Telnet/Rlogin sessions to heuristically extract username and password +## information as well as the text returned by the login server. This event is +## raised if a login attempt appears to have been unsuccessful. +## +## c: The connection. +## +## user: The user name tried. +## +## client_user: For Telnet connections, this is an empty string, but for Rlogin +## connections, it is the client name passed in the initial authentication +## information (to check against .rhosts). +## +## password: The password tried. +## +## line: The line of text that led the analyzer to conclude that the +## authentication had failed. +## +## .. bro:see:: login_confused login_confused_text login_display login_input_line +## login_output_line login_prompt login_success login_terminal direct_login_prompts +## get_login_state login_failure_msgs login_non_failure_msgs login_prompts login_success_msgs +## login_timeouts set_login_state +## +## .. note:: The login analyzer depends on a set of script-level variables that +## need to be configured with patterns identifying login attempts. This +## configuration has not yet been ported over from Bro 1.5 to Bro 2.x, and +## the analyzer is therefore not directly usable at the moment. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event login_failure%(c: connection, user: string, client_user: string, password: string, line: string%); + +## Generated for successful Telnet/Rlogin logins. The *login* analyzer inspects +## Telnet/Rlogin sessions to heuristically extract username and password +## information as well as the text returned by the login server. This event is +## raised if a login attempt appears to have been successful. +## +## c: The connection. +## +## user: The user name used. +## +## client_user: For Telnet connections, this is an empty string, but for Rlogin +## connections, it is the client name passed in the initial authentication +## information (to check against .rhosts). +## +## password: The password used. +## +## line: The line of text that led the analyzer to conclude that the +## authentication had succeeded. +## +## .. bro:see:: login_confused login_confused_text login_display login_failure +## login_input_line login_output_line login_prompt login_terminal +## direct_login_prompts get_login_state login_failure_msgs login_non_failure_msgs +## login_prompts login_success_msgs login_timeouts set_login_state +## +## .. note:: The login analyzer depends on a set of script-level variables that +## need to be configured with patterns identifying login attempts. This +## configuration has not yet been ported over from Bro 1.5 to Bro 2.x, and +## the analyzer is therefore not directly usable at the moment. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event login_success%(c: connection, user: string, client_user: string, password: string, line: string%); + +## Generated for lines of input on Telnet/Rlogin sessions. The line will have +## control characters (such as in-band Telnet options) removed. +## +## c: The connection. +## +## line: The input line. +## +## .. bro:see:: login_confused login_confused_text login_display login_failure +## login_output_line login_prompt login_success login_terminal rsh_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event login_input_line%(c: connection, line: string%); + +## Generated for lines of output on Telnet/Rlogin sessions. The line will have +## control characters (such as in-band Telnet options) removed. +## +## c: The connection. +## +## line: The ouput line. +## +## .. bro:see:: login_confused login_confused_text login_display login_failure +## login_input_line login_prompt login_success login_terminal rsh_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event login_output_line%(c: connection, line: string%); + +## Generated when tracking of Telnet/Rlogin authentication failed. As Bro's +## *login* analyzer uses a number of heuristics to extract authentication +## information, it may become confused. If it can no longer correctly track +## the authentication dialog, it raises this event. +## +## c: The connection. +## +## msg: Gives the particular problem the heuristics detected (for example, +## ``multiple_login_prompts`` means that the engine saw several login +## prompts in a row, without the type-ahead from the client side presumed +## necessary to cause them) +## +## line: The line of text that caused the heuristics to conclude they were +## confused. +## +## .. bro:see:: login_confused_text login_display login_failure login_input_line login_output_line +## login_prompt login_success login_terminal direct_login_prompts get_login_state +## login_failure_msgs login_non_failure_msgs login_prompts login_success_msgs +## login_timeouts set_login_state +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event login_confused%(c: connection, msg: string, line: string%); + +## Generated after getting confused while tracking a Telnet/Rlogin +## authentication dialog. The *login* analyzer generates this even for every +## line of user input after it has reported :bro:id:`login_confused` for a +## connection. +## +## c: The connection. +## +## line: The line the user typed. +## +## .. bro:see:: login_confused login_display login_failure login_input_line +## login_output_line login_prompt login_success login_terminal direct_login_prompts +## get_login_state login_failure_msgs login_non_failure_msgs login_prompts +## login_success_msgs login_timeouts set_login_state +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event login_confused_text%(c: connection, line: string%); + +## Generated for clients transmitting a terminal type in a Telnet session. This +## information is extracted out of environment variables sent as Telnet options. +## +## c: The connection. +## +## terminal: The TERM value transmitted. +## +## .. bro:see:: login_confused login_confused_text login_display login_failure +## login_input_line login_output_line login_prompt login_success +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event login_terminal%(c: connection, terminal: string%); + +## Generated for clients transmitting an X11 DISPLAY in a Telnet session. This +## information is extracted out of environment variables sent as Telnet options. +## +## c: The connection. +## +## display: The DISPLAY transmitted. +## +## .. bro:see:: login_confused login_confused_text login_failure login_input_line +## login_output_line login_prompt login_success login_terminal +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event login_display%(c: connection, display: string%); + +## Generated when a Telnet authentication has been successful. The Telnet +## protocol includes options for negotiating authentication. When such an +## option is sent from client to server and the server replies that it accepts +## the authentication, then the event engine generates this event. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## name: The authenticated name. +## +## c: The connection. +## +## .. bro:see:: authentication_rejected authentication_skipped login_success +## +## .. note:: This event inspects the corresponding Telnet option +## while :bro:id:`login_success` heuristically determines success by watching +## session data. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event authentication_accepted%(name: string, c: connection%); + +## Generated when a Telnet authentication has been unsuccessful. The Telnet +## protocol includes options for negotiating authentication. When such an option +## is sent from client to server and the server replies that it did not accept +## the authentication, then the event engine generates this event. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## name: The attempted authentication name. +## +## c: The connection. +## +## .. bro:see:: authentication_accepted authentication_skipped login_failure +## +## .. note:: This event inspects the corresponding Telnet option +## while :bro:id:`login_success` heuristically determines failure by watching +## session data. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event authentication_rejected%(name: string, c: connection%); + +## Generated for Telnet/Rlogin sessions when a pattern match indicates +## that no authentication is performed. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## .. bro:see:: authentication_accepted authentication_rejected direct_login_prompts +## get_login_state login_failure_msgs login_non_failure_msgs login_prompts +## login_success_msgs login_timeouts set_login_state +## +## .. note:: The login analyzer depends on a set of script-level variables that +## need to be configured with patterns identifying activity. This +## configuration has not yet been ported over from Bro 1.5 to Bro 2.x, and +## the analyzer is therefore not directly usable at the moment. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event authentication_skipped%(c: connection%); + +## Generated for clients transmitting a terminal prompt in a Telnet session. +## This information is extracted out of environment variables sent as Telnet +## options. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## prompt: The TTYPROMPT transmitted. +## +## .. bro:see:: login_confused login_confused_text login_display login_failure +## login_input_line login_output_line login_success login_terminal +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event login_prompt%(c: connection, prompt: string%); + +## Generated for Telnet sessions when encryption is activated. The Telnet +## protocol includes options for negotiating encryption. When such a series of +## options is successfully negotiated, the event engine generates this event. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## .. bro:see:: authentication_accepted authentication_rejected authentication_skipped +## login_confused login_confused_text login_display login_failure login_input_line +## login_output_line login_prompt login_success login_terminal +event activating_encryption%(c: connection%); + +## Generated for an inconsistent Telnet option. Telnet options are specified +## by the client and server stating which options they are willing to +## support vs. which they are not, and then instructing one another which in +## fact they should or should not use for the current connection. If the event +## engine sees a peer violate either what the other peer has instructed it to +## do, or what it itself offered in terms of options in the past, then the +## engine generates this event. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## .. bro:see:: bad_option bad_option_termination authentication_accepted +## authentication_rejected authentication_skipped login_confused +## login_confused_text login_display login_failure login_input_line +## login_output_line login_prompt login_success login_terminal +event inconsistent_option%(c: connection%); + +## Generated for an ill-formed or unrecognized Telnet option. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## .. bro:see:: inconsistent_option bad_option_termination authentication_accepted +## authentication_rejected authentication_skipped login_confused +## login_confused_text login_display login_failure login_input_line +## login_output_line login_prompt login_success login_terminal +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event bad_option%(c: connection%); + +## Generated for a Telnet option that's incorrectly terminated. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## .. bro:see:: inconsistent_option bad_option authentication_accepted +## authentication_rejected authentication_skipped login_confused +## login_confused_text login_display login_failure login_input_line +## login_output_line login_prompt login_success login_terminal +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event bad_option_termination%(c: connection%); diff --git a/src/analyzer/protocol/login/functions.bif b/src/analyzer/protocol/login/functions.bif new file mode 100644 index 0000000000..c3d7cbf82b --- /dev/null +++ b/src/analyzer/protocol/login/functions.bif @@ -0,0 +1,62 @@ + +%%{ +#include "Login.h" +%%} + +## Returns the state of the given login (Telnet or Rlogin) connection. +## +## cid: The connection ID. +## +## Returns: False if the connection is not active or is not tagged as a +## login analyzer. Otherwise the function returns the state, which can +## be one of: +## +## - ``LOGIN_STATE_AUTHENTICATE``: The connection is in its +## initial authentication dialog. +## - ``LOGIN_STATE_LOGGED_IN``: The analyzer believes the user has +## successfully authenticated. +## - ``LOGIN_STATE_SKIP``: The analyzer has skipped any further +## processing of the connection. +## - ``LOGIN_STATE_CONFUSED``: The analyzer has concluded that it +## does not correctly know the state of the connection, and/or +## the username associated with it. +## +## .. bro:see:: set_login_state +function get_login_state%(cid: conn_id%): count + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_BOOL); + + analyzer::Analyzer* la = c->FindAnalyzer("Login"); + if ( ! la ) + return new Val(0, TYPE_BOOL); + + return new Val(int(static_cast(la)->LoginState()), + TYPE_COUNT); + %} + +## Sets the login state of a connection with a login analyzer. +## +## cid: The connection ID. +## +## new_state: The new state of the login analyzer. See +## :bro:id:`get_login_state` for possible values. +## +## Returns: Returns false if *cid* is not an active connection +## or is not tagged as a login analyzer, and true otherwise. +## +## .. bro:see:: get_login_state +function set_login_state%(cid: conn_id, new_state: count%): bool + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_BOOL); + + analyzer::Analyzer* la = c->FindAnalyzer("Login"); + if ( ! la ) + return new Val(0, TYPE_BOOL); + + static_cast(la)->SetLoginState(analyzer::login::login_state(new_state)); + return new Val(1, TYPE_BOOL); + %} diff --git a/src/analyzer/protocol/mime/CMakeLists.txt b/src/analyzer/protocol/mime/CMakeLists.txt new file mode 100644 index 0000000000..0a038625f8 --- /dev/null +++ b/src/analyzer/protocol/mime/CMakeLists.txt @@ -0,0 +1,15 @@ + +# This is not an actual analyzer, but used by others. We still +# maintain it here along with the other analyzers because conceptually +# it's also parsing a protocol just like them. The current structure +# is merely a left-over from when this code was written. + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro MIME) +bro_plugin_cc(MIME.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() + diff --git a/src/MIME.cc b/src/analyzer/protocol/mime/MIME.cc similarity index 98% rename from src/MIME.cc rename to src/analyzer/protocol/mime/MIME.cc index 3104ed2e8e..039f26b905 100644 --- a/src/MIME.cc +++ b/src/analyzer/protocol/mime/MIME.cc @@ -7,6 +7,8 @@ #include "digest.h" #include "file_analysis/Manager.h" +#include "events.bif.h" + // Here are a few things to do: // // 1. Add a Bro internal function 'stop_deliver_data_of_entity' so @@ -17,44 +19,10 @@ // headers of form: =; =; // =; ... (so that +namespace analyzer { namespace mime { + static const data_chunk_t null_data_chunk = { 0, 0 }; -int is_null_data_chunk(data_chunk_t b) - { - return b.data == 0; - } - -int fputs(data_chunk_t b, FILE* fp) - { - for ( int i = 0; i < b.length; ++i ) - if ( fputc(b.data[i], fp) == EOF ) - return EOF; - return 0; - } - -StringVal* new_string_val(int length, const char* data) - { - return new StringVal(length, data); - } - -StringVal* new_string_val(const char* data, const char* end_of_data) - { - return new StringVal(end_of_data - data, data); - } - -StringVal* new_string_val(const data_chunk_t buf) - { - return new_string_val(buf.length, buf.data); - } - -data_chunk_t get_data_chunk(BroString* s) - { - data_chunk_t b; - b.length = s->Len(); - b.data = (const char*) s->Bytes(); - return b; - } - int mime_header_only = 0; int mime_decode_data = 1; int mime_submit_data = 1; @@ -130,6 +98,326 @@ static const char* MIMEContentEncodingName[] = { 0, }; +int is_null_data_chunk(data_chunk_t b) + { + return b.data == 0; + } + +int is_lws(char ch) + { + return ch == 9 || ch == 32; + } + +StringVal* new_string_val(int length, const char* data) + { + return new StringVal(length, data); + } + +StringVal* new_string_val(const char* data, const char* end_of_data) + { + return new StringVal(end_of_data - data, data); + } + +StringVal* new_string_val(const data_chunk_t buf) + { + return new_string_val(buf.length, buf.data); + } + +static data_chunk_t get_data_chunk(BroString* s) + { + data_chunk_t b; + b.length = s->Len(); + b.data = (const char*) s->Bytes(); + return b; + } + +int fputs(data_chunk_t b, FILE* fp) + { + for ( int i = 0; i < b.length; ++i ) + if ( fputc(b.data[i], fp) == EOF ) + return EOF; + return 0; + } + +void MIME_Mail::Undelivered(int len) + { + // is_orig param not available, doesn't matter as long as it's consistent + file_mgr->Gap(cur_entity_len, len, analyzer->GetAnalyzerTag(), analyzer->Conn(), + false); + } + +int strcasecmp_n(data_chunk_t s, const char* t) + { + return ::strcasecmp_n(s.length, s.data, t); + } + +int MIME_count_leading_lws(int len, const char* data) + { + int i; + for ( i = 0; i < len; ++i ) + if ( ! is_lws(data[i]) ) + break; + return i; + } + +int MIME_count_trailing_lws(int len, const char* data) + { + int i; + for ( i = 0; i < len; ++i ) + if ( ! is_lws(data[len - 1 - i]) ) + break; + return i; + } + +// See RFC 2822, page 11 +int MIME_skip_comments(int len, const char* data) + { + if ( len == 0 || data[0] != '(' ) + return 0; + + int par = 0; + for ( int i = 0; i < len; ++i ) + { + switch ( data[i] ) { + case '(': + ++par; + break; + + case ')': + --par; + if ( par == 0 ) + return i + 1; + break; + + case '\\': + ++i; + break; + } + } + + return len; + } + +// Skip over lws and comments, but not tspecials. Do not use this +// function in quoted-string or comments. +int MIME_skip_lws_comments(int len, const char* data) + { + int i = 0; + while ( i < len ) + { + if ( is_lws(data[i]) ) + ++i; + else + { + if ( data[i] == '(' ) + i += MIME_skip_comments(len - i, data + i); + else + return i; + } + } + + return len; + } + +int MIME_get_field_name(int len, const char* data, data_chunk_t* name) + { + int i = MIME_skip_lws_comments(len, data); + while ( i < len ) + { + int j; + if ( MIME_is_field_name_char(data[i]) ) + { + name->data = data + i; + + for ( j = i; j < len; ++j ) + if ( ! MIME_is_field_name_char(data[j]) ) + break; + + name->length = j - i; + return j; + } + + j = MIME_skip_lws_comments(len - i, data + i); + i += (j > 0) ? j : 1; + } + + return -1; + } + +// See RFC 2045, page 12. +int MIME_is_tspecial (char ch) + { + return ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '@' || + ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"' || + ch == '/' || ch == '[' || ch == ']' || ch == '?' || ch == '='; + } + +int MIME_is_field_name_char (char ch) + { + return ch >= 33 && ch <= 126 && ch != ':'; + } + +int MIME_is_token_char (char ch) + { + return ch >= 33 && ch <= 126 && ! MIME_is_tspecial(ch); + } + +// See RFC 2045, page 12. +// A token is composed of characters that are not SPACE, CTLs or tspecials +int MIME_get_token(int len, const char* data, data_chunk_t* token) + { + int i = MIME_skip_lws_comments(len, data); + while ( i < len ) + { + int j; + + if ( MIME_is_token_char(data[i]) ) + { + token->data = (data + i); + for ( j = i; j < len; ++j ) + { + if ( ! MIME_is_token_char(data[j]) ) + break; + } + + token->length = j - i; + return j; + } + + j = MIME_skip_lws_comments(len - i, data + i); + i += (j > 0) ? j : 1; + } + + return -1; + } + +int MIME_get_slash_token_pair(int len, const char* data, data_chunk_t* first, data_chunk_t* second) + { + int offset; + const char* data_start = data; + + offset = MIME_get_token(len, data, first); + if ( offset < 0 ) + { + // DEBUG_MSG("first token missing in slash token pair"); + return -1; + } + + data += offset; + len -= offset; + + offset = MIME_skip_lws_comments(len, data); + if ( offset < 0 || offset >= len || data[offset] != '/' ) + { + // DEBUG_MSG("/ not found in slash token pair"); + return -1; + } + + ++offset; + data += offset; + len -= offset; + + offset = MIME_get_token(len, data, second); + if ( offset < 0 ) + { + // DEBUG_MSG("second token missing in slash token pair"); + return -1; + } + + data += offset; + len -= offset; + + return data - data_start; + } + +// See RFC 2822, page 13. +int MIME_get_quoted_string(int len, const char* data, data_chunk_t* str) + { + int offset = MIME_skip_lws_comments(len, data); + + len -= offset; + data += offset; + + if ( len <= 0 || *data != '"' ) + return -1; + + for ( int i = 1; i < len; ++i ) + { + switch ( data[i] ) { + case '"': + str->data = data + 1; + str->length = i - 1; + return offset + i + 1; + + case '\\': + ++i; + break; + } + } + + return -1; + } + +int MIME_get_value(int len, const char* data, BroString*& buf) + { + int offset = MIME_skip_lws_comments(len, data); + + len -= offset; + data += offset; + + if ( len > 0 && *data == '"' ) + { + data_chunk_t str; + int end = MIME_get_quoted_string(len, data, &str); + if ( end < 0 ) + return -1; + + buf = MIME_decode_quoted_pairs(str); + return offset + end; + } + + else + { + data_chunk_t str; + int end = MIME_get_token(len, data, &str); + if ( end < 0 ) + return -1; + + buf = new BroString((const u_char*)str.data, str.length, 1); + return offset + end; + } + } + +// Decode each quoted-pair: a '\' followed by a character by the +// quoted character. The decoded string is returned. + +BroString* MIME_decode_quoted_pairs(data_chunk_t buf) + { + const char* data = buf.data; + char* dest = new char[buf.length+1]; + int j = 0; + for ( int i = 0; i < buf.length; ++i ) + if ( data[i] == '\\' ) + { + if ( ++i < buf.length ) + dest[j++] = data[i]; + else + { + // a trailing '\' -- don't know what + // to do with it -- ignore it. + } + } + else + dest[j++] = data[i]; + dest[j] = 0; + + return new BroString(1, (byte_vec) dest, j); + } + + +} } // namespace analyzer::* + +using namespace analyzer::mime; MIME_Multiline::MIME_Multiline() { @@ -967,7 +1255,7 @@ TableVal* MIME_Message::BuildHeaderTable(MIME_HeaderList& hlist) return t; } -MIME_Mail::MIME_Mail(Analyzer* mail_analyzer, int buf_size) +MIME_Mail::MIME_Mail(analyzer::Analyzer* mail_analyzer, int buf_size) : MIME_Message(mail_analyzer) { analyzer = mail_analyzer; @@ -1021,7 +1309,7 @@ void MIME_Mail::Done() MIME_Message::Done(); - file_mgr->EndOfFile(analyzer->GetTag(), analyzer->Conn()); + file_mgr->EndOfFile(analyzer->GetAnalyzerTag(), analyzer->Conn()); } MIME_Mail::~MIME_Mail() @@ -1072,7 +1360,7 @@ void MIME_Mail::EndEntity(MIME_Entity* /* entity */) analyzer->ConnectionEvent(mime_end_entity, vl); } - file_mgr->EndOfFile(analyzer->GetTag(), analyzer->Conn()); + file_mgr->EndOfFile(analyzer->GetAnalyzerTag(), analyzer->Conn()); } void MIME_Mail::SubmitHeader(MIME_Header* h) @@ -1132,7 +1420,7 @@ void MIME_Mail::SubmitData(int len, const char* buf) // is_orig param not available, doesn't matter as long as it's consistent file_mgr->DataIn(reinterpret_cast(buf), len, - analyzer->GetTag(), analyzer->Conn(), false); + analyzer->GetAnalyzerTag(), analyzer->Conn(), false); cur_entity_len += len; buffer_start = (buf + len) - (char*)data_buffer->Bytes(); @@ -1205,283 +1493,3 @@ void MIME_Mail::SubmitEvent(int event_type, const char* detail) analyzer->ConnectionEvent(mime_event, vl); } } - -void MIME_Mail::Undelivered(int len) - { - // is_orig param not available, doesn't matter as long as it's consistent - file_mgr->Gap(cur_entity_len, len, analyzer->GetTag(), analyzer->Conn(), - false); - } - -int strcasecmp_n(data_chunk_t s, const char* t) - { - return strcasecmp_n(s.length, s.data, t); - } - -int is_lws(char ch) - { - return ch == 9 || ch == 32; - } - -int MIME_count_leading_lws(int len, const char* data) - { - int i; - for ( i = 0; i < len; ++i ) - if ( ! is_lws(data[i]) ) - break; - return i; - } - -int MIME_count_trailing_lws(int len, const char* data) - { - int i; - for ( i = 0; i < len; ++i ) - if ( ! is_lws(data[len - 1 - i]) ) - break; - return i; - } - -// See RFC 2822, page 11 -int MIME_skip_comments(int len, const char* data) - { - if ( len == 0 || data[0] != '(' ) - return 0; - - int par = 0; - for ( int i = 0; i < len; ++i ) - { - switch ( data[i] ) { - case '(': - ++par; - break; - - case ')': - --par; - if ( par == 0 ) - return i + 1; - break; - - case '\\': - ++i; - break; - } - } - - return len; - } - -// Skip over lws and comments, but not tspecials. Do not use this -// function in quoted-string or comments. -int MIME_skip_lws_comments(int len, const char* data) - { - int i = 0; - while ( i < len ) - { - if ( is_lws(data[i]) ) - ++i; - else - { - if ( data[i] == '(' ) - i += MIME_skip_comments(len - i, data + i); - else - return i; - } - } - - return len; - } - -int MIME_get_field_name(int len, const char* data, data_chunk_t* name) - { - int i = MIME_skip_lws_comments(len, data); - while ( i < len ) - { - int j; - if ( MIME_is_field_name_char(data[i]) ) - { - name->data = data + i; - - for ( j = i; j < len; ++j ) - if ( ! MIME_is_field_name_char(data[j]) ) - break; - - name->length = j - i; - return j; - } - - j = MIME_skip_lws_comments(len - i, data + i); - i += (j > 0) ? j : 1; - } - - return -1; - } - -// See RFC 2045, page 12. -int MIME_is_tspecial (char ch) - { - return ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '@' || - ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"' || - ch == '/' || ch == '[' || ch == ']' || ch == '?' || ch == '='; - } - -int MIME_is_field_name_char (char ch) - { - return ch >= 33 && ch <= 126 && ch != ':'; - } - -int MIME_is_token_char (char ch) - { - return ch >= 33 && ch <= 126 && ! MIME_is_tspecial(ch); - } - -// See RFC 2045, page 12. -// A token is composed of characters that are not SPACE, CTLs or tspecials -int MIME_get_token(int len, const char* data, data_chunk_t* token) - { - int i = MIME_skip_lws_comments(len, data); - while ( i < len ) - { - int j; - - if ( MIME_is_token_char(data[i]) ) - { - token->data = (data + i); - for ( j = i; j < len; ++j ) - { - if ( ! MIME_is_token_char(data[j]) ) - break; - } - - token->length = j - i; - return j; - } - - j = MIME_skip_lws_comments(len - i, data + i); - i += (j > 0) ? j : 1; - } - - return -1; - } - -int MIME_get_slash_token_pair(int len, const char* data, data_chunk_t* first, data_chunk_t* second) - { - int offset; - const char* data_start = data; - - offset = MIME_get_token(len, data, first); - if ( offset < 0 ) - { - // DEBUG_MSG("first token missing in slash token pair"); - return -1; - } - - data += offset; - len -= offset; - - offset = MIME_skip_lws_comments(len, data); - if ( offset < 0 || offset >= len || data[offset] != '/' ) - { - // DEBUG_MSG("/ not found in slash token pair"); - return -1; - } - - ++offset; - data += offset; - len -= offset; - - offset = MIME_get_token(len, data, second); - if ( offset < 0 ) - { - // DEBUG_MSG("second token missing in slash token pair"); - return -1; - } - - data += offset; - len -= offset; - - return data - data_start; - } - -// See RFC 2822, page 13. -int MIME_get_quoted_string(int len, const char* data, data_chunk_t* str) - { - int offset = MIME_skip_lws_comments(len, data); - - len -= offset; - data += offset; - - if ( len <= 0 || *data != '"' ) - return -1; - - for ( int i = 1; i < len; ++i ) - { - switch ( data[i] ) { - case '"': - str->data = data + 1; - str->length = i - 1; - return offset + i + 1; - - case '\\': - ++i; - break; - } - } - - return -1; - } - -int MIME_get_value(int len, const char* data, BroString*& buf) - { - int offset = MIME_skip_lws_comments(len, data); - - len -= offset; - data += offset; - - if ( len > 0 && *data == '"' ) - { - data_chunk_t str; - int end = MIME_get_quoted_string(len, data, &str); - if ( end < 0 ) - return -1; - - buf = MIME_decode_quoted_pairs(str); - return offset + end; - } - - else - { - data_chunk_t str; - int end = MIME_get_token(len, data, &str); - if ( end < 0 ) - return -1; - - buf = new BroString((const u_char*)str.data, str.length, 1); - return offset + end; - } - } - -// Decode each quoted-pair: a '\' followed by a character by the -// quoted character. The decoded string is returned. - -BroString* MIME_decode_quoted_pairs(data_chunk_t buf) - { - const char* data = buf.data; - char* dest = new char[buf.length+1]; - int j = 0; - for ( int i = 0; i < buf.length; ++i ) - if ( data[i] == '\\' ) - { - if ( ++i < buf.length ) - dest[j++] = data[i]; - else - { - // a trailing '\' -- don't know what - // to do with it -- ignore it. - } - } - else - dest[j++] = data[i]; - dest[j] = 0; - - return new BroString(1, (byte_vec) dest, j); - } diff --git a/src/MIME.h b/src/analyzer/protocol/mime/MIME.h similarity index 95% rename from src/MIME.h rename to src/analyzer/protocol/mime/MIME.h index eb30a43bd3..4d7a89f37a 100644 --- a/src/MIME.h +++ b/src/analyzer/protocol/mime/MIME.h @@ -1,5 +1,5 @@ -#ifndef mime_h -#define mime_h +#ifndef ANALYZER_PROTOCOL_MIME_MIME_H +#define ANALYZER_PROTOCOL_MIME_MIME_H #include #include @@ -10,7 +10,9 @@ using namespace std; #include "Base64.h" #include "BroString.h" -#include "Analyzer.h" +#include "analyzer/Analyzer.h" + +namespace analyzer { namespace mime { // MIME: Multipurpose Internet Mail Extensions // Follows RFC 822 & 2822 (Internet Mail), 2045-2049 (MIME) @@ -178,7 +180,7 @@ protected: class MIME_Message { public: - MIME_Message(Analyzer* arg_analyzer) + MIME_Message(analyzer::Analyzer* arg_analyzer) { // Cannot initialize top_level entity because we do // not know its type yet (MIME_Entity / MIME_Mail / @@ -203,7 +205,7 @@ public: top_level->Deliver(len, data, trailing_CRLF); } - Analyzer* GetAnalyzer() const { return analyzer; } + analyzer::Analyzer* GetAnalyzer() const { return analyzer; } // Events generated by MIME_Entity virtual void BeginEntity(MIME_Entity*) = 0; @@ -215,7 +217,7 @@ public: virtual void SubmitEvent(int event_type, const char* detail) = 0; protected: - Analyzer* analyzer; + analyzer::Analyzer* analyzer; MIME_Entity* top_level; int finished; @@ -226,7 +228,7 @@ protected: class MIME_Mail : public MIME_Message { public: - MIME_Mail(Analyzer* mail_conn, int buf_size = 0); + MIME_Mail(analyzer::Analyzer* mail_conn, int buf_size = 0); ~MIME_Mail(); void Done(); @@ -276,4 +278,6 @@ extern int MIME_get_value(int len, const char* data, BroString*& buf); extern int MIME_get_field_name(int len, const char* data, data_chunk_t* name); extern BroString* MIME_decode_quoted_pairs(data_chunk_t buf); +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/mime/Plugin.cc b/src/analyzer/protocol/mime/Plugin.cc new file mode 100644 index 0000000000..d519a8f84e --- /dev/null +++ b/src/analyzer/protocol/mime/Plugin.cc @@ -0,0 +1,7 @@ + +#include "plugin/Plugin.h" + +BRO_PLUGIN_BEGIN(Bro, MIME) + BRO_PLUGIN_DESCRIPTION("MIME parsing code"); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/mime/events.bif b/src/analyzer/protocol/mime/events.bif new file mode 100644 index 0000000000..e9e5f66fda --- /dev/null +++ b/src/analyzer/protocol/mime/events.bif @@ -0,0 +1,196 @@ +## Generated when starting to parse an email MIME entity. MIME is a +## protocol-independent data format for encoding text and files, along with +## corresponding metadata, for transmission. Bro raises this event when it +## begins parsing a MIME entity extracted from an email protocol. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See +## `Wikipedia `__ for more information +## about MIME. +## +## c: The connection. +## +## .. bro:see:: mime_all_data mime_all_headers mime_content_hash mime_end_entity +## mime_entity_data mime_event mime_one_header mime_segment_data smtp_data +## http_begin_entity +## +## .. note:: Bro also extracts MIME entities from HTTP sessions. For those, +## however, it raises :bro:id:`http_begin_entity` instead. +event mime_begin_entity%(c: connection%); + +## Generated when finishing parsing an email MIME entity. MIME is a +## protocol-independent data format for encoding text and files, along with +## corresponding metadata, for transmission. Bro raises this event when it +## finished parsing a MIME entity extracted from an email protocol. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See +## `Wikipedia `__ for more information +## about MIME. +## +## c: The connection. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_entity_data mime_event mime_one_header mime_segment_data smtp_data +## http_end_entity +## +## .. note:: Bro also extracts MIME entities from HTTP sessions. For those, +## however, it raises :bro:id:`http_end_entity` instead. +event mime_end_entity%(c: connection%); + +## Generated for individual MIME headers extracted from email MIME +## entities. MIME is a protocol-independent data format for encoding text and +## files, along with corresponding metadata, for transmission. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See +## `Wikipedia `__ for more information +## about MIME. +## +## c: The connection. +## +## h: The parsed MIME header. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_event mime_segment_data +## http_header http_all_headers +## +## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, +## however, it raises :bro:id:`http_header` instead. +event mime_one_header%(c: connection, h: mime_header_rec%); + +## Generated for MIME headers extracted from email MIME entities, passing all +## headers at once. MIME is a protocol-independent data format for encoding +## text and files, along with corresponding metadata, for transmission. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See +## `Wikipedia `__ for more information +## about MIME. +## +## c: The connection. +## +## hlist: A *table* containing all headers extracted from the current entity. +## The table is indexed by the position of the header (1 for the first, +## 2 for the second, etc.). +## +## .. bro:see:: mime_all_data mime_begin_entity mime_content_hash mime_end_entity +## mime_entity_data mime_event mime_one_header mime_segment_data +## http_header http_all_headers +## +## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, +## however, it raises :bro:id:`http_header` instead. +event mime_all_headers%(c: connection, hlist: mime_header_list%); + +## Generated for chunks of decoded MIME data from email MIME entities. MIME +## is a protocol-independent data format for encoding text and files, along with +## corresponding metadata, for transmission. As Bro parses the data of an +## entity, it raises a sequence of these events, each coming as soon as a new +## chunk of data is available. In contrast, there is also +## :bro:id:`mime_entity_data`, which passes all of an entities data at once +## in a single block. While the latter is more convenient to handle, +## ``mime_segment_data`` is more efficient as Bro does not need to buffer +## the data. Thus, if possible, this event should be preferred. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See +## `Wikipedia `__ for more information +## about MIME. +## +## c: The connection. +## +## length: The length of *data*. +## +## data: The raw data of one segment of the current entity. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_event mime_one_header http_entity_data +## mime_segment_length mime_segment_overlap_length +## +## .. note:: Bro also extracts MIME data from HTTP sessions. For those, +## however, it raises :bro:id:`http_entity_data` (sic!) instead. +event mime_segment_data%(c: connection, length: count, data: string%); + +## Generated for data decoded from an email MIME entity. This event delivers +## the complete content of a single MIME entity. In contrast, there is also +## :bro:id:`mime_segment_data`, which passes on a sequence of data chunks as +## they come in. While ``mime_entity_data`` is more convenient to handle, +## ``mime_segment_data`` is more efficient as Bro does not need to buffer the +## data. Thus, if possible, the latter should be preferred. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See +## `Wikipedia `__ for more information +## about MIME. +## +## c: The connection. +## +## length: The length of *data*. +## +## data: The raw data of the complete entity. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_event mime_one_header mime_segment_data +## +## .. note:: While Bro also decodes MIME entities extracted from HTTP +## sessions, there's no corresponding event for that currently. +event mime_entity_data%(c: connection, length: count, data: string%); + +## Generated for passing on all data decoded from a single email MIME +## message. If an email message has more than one MIME entity, this event +## combines all their data into a single value for analysis. Note that because +## of the potentially significant buffering necessary, using this event can be +## expensive. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See +## `Wikipedia `__ for more information +## about MIME. +## +## c: The connection. +## +## length: The length of *data*. +## +## data: The raw data of all MIME entities concatenated. +## +## .. bro:see:: mime_all_headers mime_begin_entity mime_content_hash mime_end_entity +## mime_entity_data mime_event mime_one_header mime_segment_data +## +## .. note:: While Bro also decodes MIME entities extracted from HTTP +## sessions, there's no corresponding event for that currently. +event mime_all_data%(c: connection, length: count, data: string%); + +## Generated for errors found when decoding email MIME entities. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See +## `Wikipedia `__ for more information +## about MIME. +## +## c: The connection. +## +## event_type: A string describing the general category of the problem found +## (e.g., ``illegal format``). +## +## detail: Further more detailed description of the error. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_one_header mime_segment_data http_event +## +## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, +## however, it raises :bro:id:`http_event` instead. +event mime_event%(c: connection, event_type: string, detail: string%); + +## Generated for decoded MIME entities extracted from email messages, passing on +## their MD5 checksums. Bro computes the MD5 over the complete decoded data of +## each MIME entity. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See +## `Wikipedia `__ for more information +## about MIME. +## +## c: The connection. +## +## content_len: The length of the entity being hashed. +## +## hash_value: The MD5 hash. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_end_entity +## mime_entity_data mime_event mime_one_header mime_segment_data +## +## .. note:: While Bro also decodes MIME entities extracted from HTTP +## sessions, there's no corresponding event for that currently. +event mime_content_hash%(c: connection, content_len: count, hash_value: string%); + diff --git a/src/analyzer/protocol/modbus/CMakeLists.txt b/src/analyzer/protocol/modbus/CMakeLists.txt new file mode 100644 index 0000000000..e6705cdd22 --- /dev/null +++ b/src/analyzer/protocol/modbus/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro Modbus) +bro_plugin_cc(Modbus.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(modbus.pac modbus-analyzer.pac modbus-protocol.pac) +bro_plugin_end() diff --git a/src/Modbus.cc b/src/analyzer/protocol/modbus/Modbus.cc similarity index 84% rename from src/Modbus.cc rename to src/analyzer/protocol/modbus/Modbus.cc index 278eb91e57..9d216d356b 100644 --- a/src/Modbus.cc +++ b/src/analyzer/protocol/modbus/Modbus.cc @@ -1,9 +1,13 @@ #include "Modbus.h" -#include "TCP_Reassembler.h" +#include "analyzer/protocol/tcp/TCP_Reassembler.h" + +#include "events.bif.h" + +using namespace analyzer::modbus; ModbusTCP_Analyzer::ModbusTCP_Analyzer(Connection* c) - : TCP_ApplicationAnalyzer(AnalyzerTag::Modbus, c) + : TCP_ApplicationAnalyzer("MODBUS", c) { interp = new binpac::ModbusTCP::ModbusTCP_Conn(this); } diff --git a/src/analyzer/protocol/modbus/Modbus.h b/src/analyzer/protocol/modbus/Modbus.h new file mode 100644 index 0000000000..6f566be828 --- /dev/null +++ b/src/analyzer/protocol/modbus/Modbus.h @@ -0,0 +1,29 @@ +#ifndef ANALYZER_PROTOCOL_MODBUS_MODBUS_H +#define ANALYZER_PROTOCOL_MODBUS_MODBUS_H + +#include "analyzer/protocol/tcp/TCP.h" +#include "modbus_pac.h" + +namespace analyzer { namespace modbus { + +class ModbusTCP_Analyzer : public tcp::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::Analyzer* InstantiateAnalyzer(Connection* conn) + { return new ModbusTCP_Analyzer(conn); } + +protected: + binpac::ModbusTCP::ModbusTCP_Conn* interp; +}; + +} } // namespace analyzer::* + +#endif diff --git a/src/analyzer/protocol/modbus/Plugin.cc b/src/analyzer/protocol/modbus/Plugin.cc new file mode 100644 index 0000000000..c84992cbae --- /dev/null +++ b/src/analyzer/protocol/modbus/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "Modbus.h" + +BRO_PLUGIN_BEGIN(Bro, Modbus) + BRO_PLUGIN_DESCRIPTION("Modbus analyzer"); + BRO_PLUGIN_ANALYZER("MODBUS", modbus::ModbusTCP_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/modbus/events.bif b/src/analyzer/protocol/modbus/events.bif new file mode 100644 index 0000000000..1cd17381ee --- /dev/null +++ b/src/analyzer/protocol/modbus/events.bif @@ -0,0 +1,295 @@ +## Generated for any modbus message regardless if the particular function +## is further supported or not. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## is_orig: True if the event is raised for the originator side. +event modbus_message%(c: connection, headers: ModbusHeaders, is_orig: bool%); + +## Generated for any modbus exception message. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## code: The exception code. +event modbus_exception%(c: connection, headers: ModbusHeaders, code: count%); + +## Generated for a Modbus read coils request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## start_address: The memory address where of the first coil to be read. +## +## quantity: The number of coils to be read. +event modbus_read_coils_request%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); + +## Generated for a Modbus read coils response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## coils: The coil values returned from the device. +event modbus_read_coils_response%(c: connection, headers: ModbusHeaders, coils: ModbusCoils%); + +## Generated for a Modbus read discrete inputs request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## start_address: The memory address of the first coil to be read. +## +## quantity: The number of coils to be read. +event modbus_read_discrete_inputs_request%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); + +## Generated for a Modbus read discrete inputs response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## coils: The coil values returned from the device. +event modbus_read_discrete_inputs_response%(c: connection, headers: ModbusHeaders, coils: ModbusCoils%); + +## Generated for a Modbus read holding registers request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## start_address: The memory address of the first register to be read. +## +## quantity: The number of registers to be read. +event modbus_read_holding_registers_request%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); + +## Generated for a Modbus read holding registers response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## registers: The register values returned from the device. +event modbus_read_holding_registers_response%(c: connection, headers: ModbusHeaders, registers: ModbusRegisters%); + +## Generated for a Modbus read input registers request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## start_address: The memory address of the first register to be read. +## +## quantity: The number of registers to be read. +event modbus_read_input_registers_request%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); + +## Generated for a Modbus read input registers response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## registers: The register values returned from the device. +event modbus_read_input_registers_response%(c: connection, headers: ModbusHeaders, registers: ModbusRegisters%); + +## Generated for a Modbus write single coil request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## address: The memory address of the coil to be written. +## +## value: The value to be written to the coil. +event modbus_write_single_coil_request%(c: connection, headers: ModbusHeaders, address: count, value: bool%); + +## Generated for a Modbus write single coil response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## address: The memory address of the coil that was written. +## +## value: The value that was written to the coil. +event modbus_write_single_coil_response%(c: connection, headers: ModbusHeaders, address: count, value: bool%); + +## Generated for a Modbus write single register request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## address: The memory address of the register to be written. +## +## value: The value to be written to the register. +event modbus_write_single_register_request%(c: connection, headers: ModbusHeaders, address: count, value: count%); + +## Generated for a Modbus write single register response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## address: The memory address of the register that was written. +## +## value: The value that was written to the register. +event modbus_write_single_register_response%(c: connection, headers: ModbusHeaders, address: count, value: count%); + +## Generated for a Modbus write multiple coils request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## start_address: The memory address of the first coil to be written. +## +## value: The values to be written to the coils. +event modbus_write_multiple_coils_request%(c: connection, headers: ModbusHeaders, start_address: count, coils: ModbusCoils%); + +## Generated for a Modbus write multiple coils response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## start_address: The memory address of the first coil that was written. +## +## quantity: The quantity of coils that were written. +event modbus_write_multiple_coils_response%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); + +## Generated for a Modbus write multiple registers request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## start_address: The memory address of the first register to be written. +## +## registers: The values to be written to the registers. +event modbus_write_multiple_registers_request%(c: connection, headers: ModbusHeaders, start_address: count, registers: ModbusRegisters%); + +## Generated for a Modbus write multiple registers response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## start_address: The memory address of the first register that was written. +## +## quantity: The quantity of registers that were written. +event modbus_write_multiple_registers_response%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); + +## Generated for a Modbus read file record request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## .. note: This event is incomplete. The information from the data structure is not +## yet passed through to the event. +event modbus_read_file_record_request%(c: connection, headers: ModbusHeaders%); + +## Generated for a Modbus read file record response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## .. note: This event is incomplete. The information from the data structure is not +## yet passed through to the event. +event modbus_read_file_record_response%(c: connection, headers: ModbusHeaders%); + +## Generated for a Modbus write file record request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## .. note: This event is incomplete. The information from the data structure is not +## yet passed through to the event. +event modbus_write_file_record_request%(c: connection, headers: ModbusHeaders%); + +## Generated for a Modbus write file record response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## .. note: This event is incomplete. The information from the data structure is not +## yet passed through to the event. +event modbus_write_file_record_response%(c: connection, headers: ModbusHeaders%); + +## Generated for a Modbus mask write register request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## address: The memory address of the register where the masks should be applied. +## +## and_mask: The value of the logical AND mask to apply to the register. +## +## or_mask: The value of the logical OR mask to apply to the register. +event modbus_mask_write_register_request%(c: connection, headers: ModbusHeaders, address: count, and_mask: count, or_mask: count%); + +## Generated for a Modbus mask write register request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## address: The memory address of the register where the masks were applied. +## +## and_mask: The value of the logical AND mask applied register. +## +## or_mask: The value of the logical OR mask applied to the register. +event modbus_mask_write_register_response%(c: connection, headers: ModbusHeaders, address: count, and_mask: count, or_mask: count%); + +## Generated for a Modbus read/write multiple registers request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## read_start_address: The memory address of the first register to be read. +## +## read_quantity: The number of registers to read. +## +## write_start_address: The memory address of the first register to be written. +## +## write_registers: The values to be written to the registers. +event modbus_read_write_multiple_registers_request%(c: connection, headers: ModbusHeaders, read_start_address: count, read_quantity: count, write_start_address: count, write_registers: ModbusRegisters%); + +## Generated for a Modbus read/write multiple registers response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## written_registers: The register values read from the registers specified in the request. +event modbus_read_write_multiple_registers_response%(c: connection, headers: ModbusHeaders, written_registers: ModbusRegisters%); + +## Generated for a Modbus read FIFO queue request. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## start_address: The address of the FIFO queue to read. +event modbus_read_fifo_queue_request%(c: connection, headers: ModbusHeaders, start_address: count%); + +## Generated for a Modbus read FIFO queue response. +## +## c: The connection. +## +## headers: The headers for the modbus function. +## +## fifos: The register values read from the FIFO queue on the device. +event modbus_read_fifo_queue_response%(c: connection, headers: ModbusHeaders, fifos: ModbusRegisters%); + diff --git a/src/modbus-analyzer.pac b/src/analyzer/protocol/modbus/modbus-analyzer.pac similarity index 100% rename from src/modbus-analyzer.pac rename to src/analyzer/protocol/modbus/modbus-analyzer.pac diff --git a/src/modbus-protocol.pac b/src/analyzer/protocol/modbus/modbus-protocol.pac similarity index 100% rename from src/modbus-protocol.pac rename to src/analyzer/protocol/modbus/modbus-protocol.pac diff --git a/src/modbus.pac b/src/analyzer/protocol/modbus/modbus.pac similarity index 95% rename from src/modbus.pac rename to src/analyzer/protocol/modbus/modbus.pac index 9148997295..28b657abc5 100644 --- a/src/modbus.pac +++ b/src/analyzer/protocol/modbus/modbus.pac @@ -9,6 +9,10 @@ %include binpac.pac %include bro.pac +%extern{ +#include "events.bif.h" +%} + analyzer ModbusTCP withcontext { connection: ModbusTCP_Conn; flow: ModbusTCP_Flow; diff --git a/src/analyzer/protocol/ncp/CMakeLists.txt b/src/analyzer/protocol/ncp/CMakeLists.txt new file mode 100644 index 0000000000..bd06d4e426 --- /dev/null +++ b/src/analyzer/protocol/ncp/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro NCP) +bro_plugin_cc(NCP.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(ncp.pac) +bro_plugin_end() diff --git a/src/NCP.cc b/src/analyzer/protocol/ncp/NCP.cc similarity index 89% rename from src/NCP.cc rename to src/analyzer/protocol/ncp/NCP.cc index edd882747c..75b6c9f4be 100644 --- a/src/NCP.cc +++ b/src/analyzer/protocol/ncp/NCP.cc @@ -6,7 +6,12 @@ #include #include +#include "NCP.h" + +#include "events.bif.h" + using namespace std; +using namespace analyzer::ncp; #include "NCP.h" #include "Sessions.h" @@ -17,7 +22,7 @@ using namespace std; uint16(xbyte(bytes, 0)) | ((uint16(xbyte(bytes, 1))) << 8) : \ uint16(xbyte(bytes, 1)) | ((uint16(xbyte(bytes, 0))) << 8)) -NCP_Session::NCP_Session(Analyzer* a) +NCP_Session::NCP_Session(analyzer::Analyzer* a) : analyzer(a) { req_frame_type = 0; @@ -150,15 +155,15 @@ void NCP_FrameBuffer::compute_msg_length() } Contents_NCP_Analyzer::Contents_NCP_Analyzer(Connection* conn, bool orig, NCP_Session* arg_session) -: TCP_SupportAnalyzer(AnalyzerTag::Contents_NCP, conn, orig) +: tcp::TCP_SupportAnalyzer("CONTENTS_NCP", conn, orig) { session = arg_session; resync = true; - TCP_Analyzer* tcp = static_cast(Parent())->TCP(); + tcp::TCP_Analyzer* tcp = static_cast(Parent())->TCP(); if ( tcp ) resync = (orig ? tcp->OrigState() : tcp->RespState()) != - TCP_ENDPOINT_ESTABLISHED; + tcp::TCP_ENDPOINT_ESTABLISHED; } Contents_NCP_Analyzer::~Contents_NCP_Analyzer() @@ -167,9 +172,9 @@ Contents_NCP_Analyzer::~Contents_NCP_Analyzer() void Contents_NCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { - TCP_SupportAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_SupportAnalyzer::DeliverStream(len, data, orig); - TCP_Analyzer* tcp = static_cast(Parent())->TCP(); + tcp::TCP_Analyzer* tcp = static_cast(Parent())->TCP(); if ( tcp && tcp->HadGap(orig) ) return; @@ -208,14 +213,14 @@ void Contents_NCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig void Contents_NCP_Analyzer::Undelivered(int seq, int len, bool orig) { - TCP_SupportAnalyzer::Undelivered(seq, len, orig); + tcp::TCP_SupportAnalyzer::Undelivered(seq, len, orig); buffer.Reset(); resync = true; } NCP_Analyzer::NCP_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::NCP, conn) +: tcp::TCP_ApplicationAnalyzer("NCP", conn) { session = new NCP_Session(this); o_ncp = new Contents_NCP_Analyzer(conn, true, session); diff --git a/src/NCP.h b/src/analyzer/protocol/ncp/NCP.h similarity index 84% rename from src/NCP.h rename to src/analyzer/protocol/ncp/NCP.h index 1e783ee3ab..34174df74e 100644 --- a/src/NCP.h +++ b/src/analyzer/protocol/ncp/NCP.h @@ -1,7 +1,7 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef ncp_h -#define ncp_h +#ifndef ANALYZER_PROTOCOL_NCP_NCP_H +#define ANALYZER_PROTOCOL_NCP_NCP_H // A very crude analyzer for NCP (Netware Core Protocol) // @@ -19,17 +19,19 @@ // http://faydoc.tripod.com/structures/21/2149.htm #include "NetVar.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #include "ncp_pac.h" +namespace analyzer { namespace ncp { + // Create a general NCP_Session class so that it can be used in // case the RPC conversation is tunneled through other connections, // e.g., through an SMB session. class NCP_Session { public: - NCP_Session(Analyzer* analyzer); + NCP_Session(analyzer::Analyzer* analyzer); virtual ~NCP_Session() {} virtual void Deliver(int is_orig, int len, const u_char* data); @@ -42,7 +44,7 @@ public: protected: void DeliverFrame(const binpac::NCP::ncp_frame* frame); - Analyzer* analyzer; + analyzer::Analyzer* analyzer; int req_frame_type; int req_func; }; @@ -81,7 +83,7 @@ protected: void compute_msg_length(); }; -class Contents_NCP_Analyzer : public TCP_SupportAnalyzer { +class Contents_NCP_Analyzer : public tcp::TCP_SupportAnalyzer { public: Contents_NCP_Analyzer(Connection* conn, bool orig, NCP_Session* session); ~Contents_NCP_Analyzer(); @@ -97,16 +99,14 @@ protected: bool resync; }; -class NCP_Analyzer : public TCP_ApplicationAnalyzer { +class NCP_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: NCP_Analyzer(Connection* conn); virtual ~NCP_Analyzer(); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new NCP_Analyzer(conn); } - static bool Available() { return NCP_Session::any_ncp_event(); } - protected: NCP_Session* session; @@ -114,4 +114,6 @@ protected: Contents_NCP_Analyzer * r_ncp; }; +} } // namespace analyzer::* + #endif /* ncp_h */ diff --git a/src/NCP_func.def b/src/analyzer/protocol/ncp/NCP_func.def similarity index 100% rename from src/NCP_func.def rename to src/analyzer/protocol/ncp/NCP_func.def diff --git a/src/analyzer/protocol/ncp/Plugin.cc b/src/analyzer/protocol/ncp/Plugin.cc new file mode 100644 index 0000000000..85cd318fe0 --- /dev/null +++ b/src/analyzer/protocol/ncp/Plugin.cc @@ -0,0 +1,11 @@ + +#include "plugin/Plugin.h" + +#include "NCP.h" + +BRO_PLUGIN_BEGIN(Bro, NCP) + BRO_PLUGIN_DESCRIPTION("NCP analyzer"); + BRO_PLUGIN_ANALYZER("NCP", ncp::NCP_Analyzer); + BRO_PLUGIN_SUPPORT_ANALYZER("Contents_NCP"); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/ncp/events.bif b/src/analyzer/protocol/ncp/events.bif new file mode 100644 index 0000000000..9b5b7d77a7 --- /dev/null +++ b/src/analyzer/protocol/ncp/events.bif @@ -0,0 +1,46 @@ +## Generated for NCP requests (Netware Core Protocol). +## +## See `Wikipedia `__ for +## more information about the NCP protocol. +## +## c: The connection. +## +## frame_type: The frame type, as specified by the protocol. +## +## length: The length of the request body, excluding the frame header. +## +## func: The requested function, as specified by the protocol. +## +## .. bro:see:: ncp_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event ncp_request%(c: connection, frame_type: count, length: count, func: count%); + +## Generated for NCP replies (Netware Core Protocol). +## +## See `Wikipedia `__ for +## more information about the NCP protocol. +## +## c: The connection. +## +## frame_type: The frame type, as specified by the protocol. +## +## length: The length of the request body, excluding the frame header. +## +## req_frame: The frame type from the corresponding request. +## +## req_func: The function code from the corresponding request. +## +## completion_code: The reply's completion code, as specified by the protocol. +## +## .. bro:see:: ncp_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event ncp_reply%(c: connection, frame_type: count, length: count, req_frame: count, req_func: count, completion_code: count%); + diff --git a/src/ncp.pac b/src/analyzer/protocol/ncp/ncp.pac similarity index 97% rename from src/ncp.pac rename to src/analyzer/protocol/ncp/ncp.pac index 86b8bca5da..d4d5734a54 100644 --- a/src/ncp.pac +++ b/src/analyzer/protocol/ncp/ncp.pac @@ -2,6 +2,10 @@ %include bro.pac +%extern{ +#include "events.bif.h" +%} + analyzer NCP withcontext {}; type ncp_request(length: uint32) = record { diff --git a/src/analyzer/protocol/netbios/CMakeLists.txt b/src/analyzer/protocol/netbios/CMakeLists.txt new file mode 100644 index 0000000000..ad6009d171 --- /dev/null +++ b/src/analyzer/protocol/netbios/CMakeLists.txt @@ -0,0 +1,13 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) +include_directories(AFTER ${CMAKE_CURRENT_BINARY_DIR}/../dce-rpc) +include_directories(AFTER ${CMAKE_CURRENT_BINARY_DIR}/../smb) + +bro_plugin_begin(Bro NetBIOS) +bro_plugin_cc(NetbiosSSN.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_bif(functions.bif) +bro_plugin_end() + diff --git a/src/NetbiosSSN.cc b/src/analyzer/protocol/netbios/NetbiosSSN.cc similarity index 93% rename from src/NetbiosSSN.cc rename to src/analyzer/protocol/netbios/NetbiosSSN.cc index 362d974956..01544c4b2c 100644 --- a/src/NetbiosSSN.cc +++ b/src/analyzer/protocol/netbios/NetbiosSSN.cc @@ -9,6 +9,10 @@ #include "Sessions.h" #include "Event.h" +#include "events.bif.h" + +using namespace analyzer::netbios_ssn; + double netbios_ssn_session_timeout = 15.0; #define MAKE_INT16(dest, src) dest = *src; dest <<=8; src++; dest |= *src; src++; @@ -43,8 +47,8 @@ NetbiosDGM_RawMsgHdr::NetbiosDGM_RawMsgHdr(const u_char*& data, int& len) } -NetbiosSSN_Interpreter::NetbiosSSN_Interpreter(Analyzer* arg_analyzer, - SMB_Session* arg_smb_session) +NetbiosSSN_Interpreter::NetbiosSSN_Interpreter(analyzer::Analyzer* arg_analyzer, + smb::SMB_Session* arg_smb_session) { analyzer = arg_analyzer; smb_session = arg_smb_session; @@ -340,7 +344,7 @@ void NetbiosSSN_Interpreter::Event(EventHandlerPtr event, const u_char* data, Contents_NetbiosSSN::Contents_NetbiosSSN(Connection* conn, bool orig, NetbiosSSN_Interpreter* arg_interp) -: TCP_SupportAnalyzer(AnalyzerTag::Contents_NetbiosSSN, conn, orig) +: tcp::TCP_SupportAnalyzer("CONTENTS_NETBIOSSSN", conn, orig) { interp = arg_interp; type = flags = msg_size = 0; @@ -365,7 +369,7 @@ void Contents_NetbiosSSN::Flush() void Contents_NetbiosSSN::DeliverStream(int len, const u_char* data, bool orig) { - TCP_SupportAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_SupportAnalyzer::DeliverStream(len, data, orig); if ( state == NETBIOS_SSN_TYPE ) { @@ -455,9 +459,9 @@ void Contents_NetbiosSSN::DeliverStream(int len, const u_char* data, bool orig) } NetbiosSSN_Analyzer::NetbiosSSN_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::NetbiosSSN, conn) +: tcp::TCP_ApplicationAnalyzer("NETBIOS", conn) { - smb_session = new SMB_Session(this); + smb_session = new smb::SMB_Session(this); interp = new NetbiosSSN_Interpreter(this, smb_session); orig_netbios = resp_netbios = 0; did_session_done = 0; @@ -485,7 +489,7 @@ NetbiosSSN_Analyzer::~NetbiosSSN_Analyzer() void NetbiosSSN_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); interp->Timeout(); if ( Conn()->ConnTransport() == TRANSPORT_UDP && ! did_session_done ) @@ -496,15 +500,15 @@ void NetbiosSSN_Analyzer::Done() void NetbiosSSN_Analyzer::EndpointEOF(bool orig) { - TCP_ApplicationAnalyzer::EndpointEOF(orig); + tcp::TCP_ApplicationAnalyzer::EndpointEOF(orig); (orig ? orig_netbios : resp_netbios)->Flush(); } -void NetbiosSSN_Analyzer::ConnectionClosed(TCP_Endpoint* endpoint, - TCP_Endpoint* peer, int gen_event) +void NetbiosSSN_Analyzer::ConnectionClosed(tcp::TCP_Endpoint* endpoint, + tcp::TCP_Endpoint* peer, int gen_event) { - TCP_ApplicationAnalyzer::ConnectionClosed(endpoint, peer, gen_event); + tcp::TCP_ApplicationAnalyzer::ConnectionClosed(endpoint, peer, gen_event); // Question: Why do we flush *both* endpoints upon connection close? // orig_netbios->Flush(); @@ -514,7 +518,7 @@ void NetbiosSSN_Analyzer::ConnectionClosed(TCP_Endpoint* endpoint, void NetbiosSSN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) { - TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); + tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); if ( orig ) interp->ParseMessageUDP(data, len, 1); diff --git a/src/NetbiosSSN.h b/src/analyzer/protocol/netbios/NetbiosSSN.h similarity index 83% rename from src/NetbiosSSN.h rename to src/analyzer/protocol/netbios/NetbiosSSN.h index 7c4dd91b90..7c2728ef9a 100644 --- a/src/NetbiosSSN.h +++ b/src/analyzer/protocol/netbios/NetbiosSSN.h @@ -1,11 +1,13 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef netbios_ssn_h -#define netbios_ssn_h +#ifndef ANALYZER_PROTOCOL_NETBIOS_SSN_NETBIOSSSN_H +#define ANALYZER_PROTOCOL_NETBIOS_SSN_NETBIOSSSN_H -#include "UDP.h" -#include "TCP.h" -#include "SMB.h" +#include "analyzer/protocol/udp/UDP.h" +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/smb/SMB.h" + +namespace analyzer { namespace netbios_ssn { typedef enum { NETBIOS_SSN_MSG = 0x0, @@ -62,7 +64,7 @@ struct NetbiosDGM_RawMsgHdr { class NetbiosSSN_Interpreter { public: - NetbiosSSN_Interpreter(Analyzer* analyzer, SMB_Session* smb_session); + NetbiosSSN_Interpreter(analyzer::Analyzer* analyzer, smb::SMB_Session* smb_session); int ParseMessage(unsigned int type, unsigned int flags, const u_char* data, int len, int is_query); @@ -73,17 +75,6 @@ public: void Timeout() { } - static bool any_netbios_ssn_event() - { - return netbios_session_message || - netbios_session_request || - netbios_session_accepted || - netbios_session_rejected || - netbios_session_raw_message || - netbios_session_ret_arg_resp || - netbios_session_keepalive; - } - protected: int ParseSessionMsg(const u_char* data, int len, int is_query); int ParseSessionReq(const u_char* data, int len, int is_query); @@ -108,8 +99,8 @@ protected: u_char*& xname, int& xlen); protected: - Analyzer* analyzer; - SMB_Session* smb_session; + analyzer::Analyzer* analyzer; + smb::SMB_Session* smb_session; }; @@ -122,7 +113,7 @@ typedef enum { } NetbiosSSN_State; // ### This should be merged with TCP_Contents_RPC, TCP_Contents_DNS. -class Contents_NetbiosSSN : public TCP_SupportAnalyzer { +class Contents_NetbiosSSN : public tcp::TCP_SupportAnalyzer { public: Contents_NetbiosSSN(Connection* conn, bool orig, NetbiosSSN_Interpreter* interp); @@ -148,7 +139,7 @@ protected: NetbiosSSN_State state; }; -class NetbiosSSN_Analyzer : public TCP_ApplicationAnalyzer { +class NetbiosSSN_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: NetbiosSSN_Analyzer(Connection* conn); ~NetbiosSSN_Analyzer(); @@ -157,25 +148,18 @@ public: virtual void DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new NetbiosSSN_Analyzer(conn); } - static bool Available() - { - return NetbiosSSN_Interpreter::any_netbios_ssn_event() || - SMB_Session::any_smb_event() || - DCE_RPC_Session::any_dce_rpc_event(); - } - protected: - virtual void ConnectionClosed(TCP_Endpoint* endpoint, - TCP_Endpoint* peer, int gen_event); + virtual void ConnectionClosed(tcp::TCP_Endpoint* endpoint, + tcp::TCP_Endpoint* peer, int gen_event); virtual void EndpointEOF(bool is_orig); void ExpireTimer(double t); NetbiosSSN_Interpreter* interp; - SMB_Session* smb_session; + smb::SMB_Session* smb_session; Contents_NetbiosSSN* orig_netbios; Contents_NetbiosSSN* resp_netbios; int did_session_done; @@ -184,4 +168,6 @@ protected: // FIXME: Doesn't really fit into new analyzer structure. What to do? int IsReuse(double t, const u_char* pkt); +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/netbios/Plugin.cc b/src/analyzer/protocol/netbios/Plugin.cc new file mode 100644 index 0000000000..15daeb1ab5 --- /dev/null +++ b/src/analyzer/protocol/netbios/Plugin.cc @@ -0,0 +1,12 @@ + +#include "plugin/Plugin.h" + +#include "NetbiosSSN.h" + +BRO_PLUGIN_BEGIN(Bro, NetBIOS) + BRO_PLUGIN_DESCRIPTION("NetBIOS analyzer (support only SSN currently)"); + BRO_PLUGIN_ANALYZER("NetbiosSSN", netbios_ssn::NetbiosSSN_Analyzer); + BRO_PLUGIN_SUPPORT_ANALYZER("Contents_NetbiosSSN"); + BRO_PLUGIN_BIF_FILE(events); + BRO_PLUGIN_BIF_FILE(functions); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/netbios/events.bif b/src/analyzer/protocol/netbios/events.bif new file mode 100644 index 0000000000..bf382e1663 --- /dev/null +++ b/src/analyzer/protocol/netbios/events.bif @@ -0,0 +1,209 @@ +## Generated for all NetBIOS SSN and DGM messages. Bro's NetBIOS analyzer +## processes the NetBIOS session service running on TCP port 139, and (despite +## its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be TCP or UDP, depending on the type of the +## NetBIOS session. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## msg_type: The general type of message, as defined in Section 4.3.1 of +## `RFC 1002 `__. +## +## data_len: The length of the message's payload. +## +## .. bro:see:: netbios_session_accepted netbios_session_keepalive +## netbios_session_raw_message netbios_session_rejected netbios_session_request +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's +## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event netbios_session_message%(c: connection, is_orig: bool, msg_type: count, data_len: count%); + +## Generated for NetBIOS messages of type *session request*. Bro's NetBIOS +## analyzer processes the NetBIOS session service running on TCP port 139, and +## (despite its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be TCP or UDP, depending on the type of the +## NetBIOS session. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS +## header. +## +## .. bro:see:: netbios_session_accepted netbios_session_keepalive +## netbios_session_message netbios_session_raw_message netbios_session_rejected +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's +## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event netbios_session_request%(c: connection, msg: string%); + +## Generated for NetBIOS messages of type *positive session response*. Bro's +## NetBIOS analyzer processes the NetBIOS session service running on TCP port +## 139, and (despite its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be TCP or UDP, depending on the type of the +## NetBIOS session. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS +## header. +## +## .. bro:see:: netbios_session_keepalive netbios_session_message +## netbios_session_raw_message netbios_session_rejected netbios_session_request +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's +## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event netbios_session_accepted%(c: connection, msg: string%); + +## Generated for NetBIOS messages of type *negative session response*. Bro's +## NetBIOS analyzer processes the NetBIOS session service running on TCP port +## 139, and (despite its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be TCP or UDP, depending on the type of the +## NetBIOS session. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS +## header. +## +## .. bro:see:: netbios_session_accepted netbios_session_keepalive +## netbios_session_message netbios_session_raw_message netbios_session_request +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's +## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event netbios_session_rejected%(c: connection, msg: string%); + +## Generated for NetBIOS messages of type *session message* that are not +## carrying an SMB payload. +## +## NetBIOS analyzer processes the NetBIOS session service running on TCP port +## 139, and (despite its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be TCP or UDP, depending on the type of the +## NetBIOS session. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS +## header (i.e., the ``user_data``). +## +## .. bro:see:: netbios_session_accepted netbios_session_keepalive +## netbios_session_message netbios_session_rejected netbios_session_request +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's +## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: This is an oddly named event. In fact, it's probably an odd event +## to have to begin with. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event netbios_session_raw_message%(c: connection, is_orig: bool, msg: string%); + +## Generated for NetBIOS messages of type *retarget response*. Bro's NetBIOS +## analyzer processes the NetBIOS session service running on TCP port 139, and +## (despite its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be TCP or UDP, depending on the type of the +## NetBIOS session. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS +## header. +## +## .. bro:see:: netbios_session_accepted netbios_session_keepalive +## netbios_session_message netbios_session_raw_message netbios_session_rejected +## netbios_session_request decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's +## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: This is an oddly named event. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event netbios_session_ret_arg_resp%(c: connection, msg: string%); + +## Generated for NetBIOS messages of type *keep-alive*. Bro's NetBIOS analyzer +## processes the NetBIOS session service running on TCP port 139, and (despite +## its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be TCP or UDP, depending on the type of the +## NetBIOS session. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS +## header. +## +## .. bro:see:: netbios_session_accepted netbios_session_message +## netbios_session_raw_message netbios_session_rejected netbios_session_request +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's +## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event netbios_session_keepalive%(c: connection, msg: string%); + diff --git a/src/analyzer/protocol/netbios/functions.bif b/src/analyzer/protocol/netbios/functions.bif new file mode 100644 index 0000000000..d4316d0c66 --- /dev/null +++ b/src/analyzer/protocol/netbios/functions.bif @@ -0,0 +1,50 @@ + +## Decode a NetBIOS name. See http://support.microsoft.com/kb/194203. +## +## name: The encoded NetBIOS name, e.g., ``"FEEIEFCAEOEFFEECEJEPFDCAEOEBENEF"``. +## +## Returns: The decoded NetBIOS name, e.g., ``"THE NETBIOS NAME"``. +## +## .. bro:see:: decode_netbios_name_type +function decode_netbios_name%(name: string%): string + %{ + char buf[16]; + char result[16]; + const u_char* s = name->Bytes(); + int i, j; + + for ( i = 0, j = 0; i < 16; ++i ) + { + char c0 = (j < name->Len()) ? toupper(s[j++]) : 'A'; + char c1 = (j < name->Len()) ? toupper(s[j++]) : 'A'; + buf[i] = ((c0 - 'A') << 4) + (c1 - 'A'); + } + + for ( i = 0; i < 15; ++i ) + { + if ( isalnum(buf[i]) || ispunct(buf[i]) || + // \x01\x02 is seen in at least one case as the first two bytes. + // I think that any \x01 and \x02 should always be passed through. + buf[i] < 3 ) + result[i] = buf[i]; + else + break; + } + + return new StringVal(i, result); + %} + +## Converts a NetBIOS name type to its corresponding numeric value. +## See http://support.microsoft.com/kb/163409. +## +## name: The NetBIOS name type. +## +## Returns: The numeric value of *name*. +## +## .. bro:see:: decode_netbios_name +function decode_netbios_name_type%(name: string%): count + %{ + const u_char* s = name->Bytes(); + char return_val = ((toupper(s[30]) - 'A') << 4) + (toupper(s[31]) - 'A'); + return new Val(return_val, TYPE_COUNT); + %} diff --git a/src/analyzer/protocol/netflow/CMakeLists.txt b/src/analyzer/protocol/netflow/CMakeLists.txt new file mode 100644 index 0000000000..3afc9fd66a --- /dev/null +++ b/src/analyzer/protocol/netflow/CMakeLists.txt @@ -0,0 +1,16 @@ + +# This is not an actual analyzer, but used by the core. We still +# maintain it here along with the other analyzers because conceptually +# it's also parsing a protocol just like them. The current structure +# is merely a left-over from when this code was written. + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro NetFlow) +bro_plugin_cc(Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(netflow.pac netflow-protocol.pac netflow-analyzer.pac) +bro_plugin_end() + diff --git a/src/analyzer/protocol/netflow/Plugin.cc b/src/analyzer/protocol/netflow/Plugin.cc new file mode 100644 index 0000000000..b994caa5d8 --- /dev/null +++ b/src/analyzer/protocol/netflow/Plugin.cc @@ -0,0 +1,7 @@ + +#include "plugin/Plugin.h" + +BRO_PLUGIN_BEGIN(Bro, NetFlow) + BRO_PLUGIN_DESCRIPTION("NetFlow parsing code"); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/netflow/events.bif b/src/analyzer/protocol/netflow/events.bif new file mode 100644 index 0000000000..69c196de9e --- /dev/null +++ b/src/analyzer/protocol/netflow/events.bif @@ -0,0 +1,18 @@ +## Generated for a received NetFlow v5 header. Bro's NetFlow processor raises +## this event whenever it either receives a NetFlow header on the port it's +## listening on, or reads one from a trace file. +## +## h: The parsed NetFlow header. +## +## .. bro:see:: netflow_v5_record +event netflow_v5_header%(h: nf_v5_header%); + +## Generated for a received NetFlow v5 record. Bro's NetFlow processor raises +## this event whenever it either receives a NetFlow record on the port it's +## listening on, or reads one from a trace file. +## +## r: The parsed NetFlow record. +## +## .. bro:see:: netflow_v5_record +event netflow_v5_record%(r: nf_v5_record%); + diff --git a/src/netflow-analyzer.pac b/src/analyzer/protocol/netflow/netflow-analyzer.pac similarity index 100% rename from src/netflow-analyzer.pac rename to src/analyzer/protocol/netflow/netflow-analyzer.pac diff --git a/src/netflow-protocol.pac b/src/analyzer/protocol/netflow/netflow-protocol.pac similarity index 100% rename from src/netflow-protocol.pac rename to src/analyzer/protocol/netflow/netflow-protocol.pac diff --git a/src/netflow.pac b/src/analyzer/protocol/netflow/netflow.pac similarity index 88% rename from src/netflow.pac rename to src/analyzer/protocol/netflow/netflow.pac index 91040aadeb..57e1b71a76 100644 --- a/src/netflow.pac +++ b/src/analyzer/protocol/netflow/netflow.pac @@ -4,6 +4,8 @@ #include "net_util.h" #include "Event.h" extern RecordType* conn_id; + +#include "events.bif.h" %} %include bro.pac diff --git a/src/analyzer/protocol/ntp/CMakeLists.txt b/src/analyzer/protocol/ntp/CMakeLists.txt new file mode 100644 index 0000000000..a8b8bb1872 --- /dev/null +++ b/src/analyzer/protocol/ntp/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro NTP) +bro_plugin_cc(NTP.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/NTP.cc b/src/analyzer/protocol/ntp/NTP.cc similarity index 97% rename from src/NTP.cc rename to src/analyzer/protocol/ntp/NTP.cc index 60b7e6202d..b4b63d5634 100644 --- a/src/NTP.cc +++ b/src/analyzer/protocol/ntp/NTP.cc @@ -7,9 +7,12 @@ #include "Sessions.h" #include "Event.h" +#include "events.bif.h" + +using namespace analyzer::ntp; NTP_Analyzer::NTP_Analyzer(Connection* conn) - : Analyzer(AnalyzerTag::NTP, conn) + : Analyzer("NTP", conn) { ADD_ANALYZER_TIMER(&NTP_Analyzer::ExpireTimer, network_time + ntp_session_timeout, 1, diff --git a/src/NTP.h b/src/analyzer/protocol/ntp/NTP.h similarity index 83% rename from src/NTP.h rename to src/analyzer/protocol/ntp/NTP.h index a22a7b231b..201c5a8774 100644 --- a/src/NTP.h +++ b/src/analyzer/protocol/ntp/NTP.h @@ -1,16 +1,17 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef ntp_h -#define ntp_h - -#include "UDP.h" +#ifndef ANALYZER_PROTOCOL_NTP_NTP_H +#define ANALYZER_PROTOCOL_NTP_NTP_H +#include "analyzer/protocol/udp/UDP.h" // The following are from the tcpdump distribution, credited there // to the U of MD implementation. #define JAN_1970 2208988800.0 /* 1970 - 1900 in seconds */ +namespace analyzer { namespace ntp { + struct l_fixedpt { unsigned int int_part; unsigned int fraction; @@ -35,15 +36,13 @@ struct ntpdata { struct l_fixedpt xmt; }; -class NTP_Analyzer : public Analyzer { +class NTP_Analyzer : public analyzer::Analyzer { public: NTP_Analyzer(Connection* conn); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new NTP_Analyzer(conn); } - static bool Available() { return ntp_message; } - protected: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, @@ -65,4 +64,6 @@ protected: void ExpireTimer(double t); }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/ntp/Plugin.cc b/src/analyzer/protocol/ntp/Plugin.cc new file mode 100644 index 0000000000..ce4ce5680f --- /dev/null +++ b/src/analyzer/protocol/ntp/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "NTP.h" + +BRO_PLUGIN_BEGIN(Bro, NTP) + BRO_PLUGIN_DESCRIPTION("NTP analyzer"); + BRO_PLUGIN_ANALYZER("NTP", ntp::NTP_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/ntp/events.bif b/src/analyzer/protocol/ntp/events.bif new file mode 100644 index 0000000000..bba2dfbbe5 --- /dev/null +++ b/src/analyzer/protocol/ntp/events.bif @@ -0,0 +1,21 @@ +## Generated for all NTP messages. Different from many other of Bro's events, +## this one is generated for both client-side and server-side messages. +## +## See `Wikipedia `__ for +## more information about the NTP protocol. +## +## u: The connection record describing the corresponding UDP flow. +## +## msg: The parsed NTP message. +## +## excess: The raw bytes of any optional parts of the NTP packet. Bro does not +## further parse any optional fields. +## +## .. bro:see:: ntp_session_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event ntp_message%(u: connection, msg: ntp_msg, excess: string%); + diff --git a/src/analyzer/protocol/pia/CMakeLists.txt b/src/analyzer/protocol/pia/CMakeLists.txt new file mode 100644 index 0000000000..ff55bcf0aa --- /dev/null +++ b/src/analyzer/protocol/pia/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro PIA) +bro_plugin_cc(PIA.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/PIA.cc b/src/analyzer/protocol/pia/PIA.cc similarity index 80% rename from src/PIA.cc rename to src/analyzer/protocol/pia/PIA.cc index 9adb4ccab3..cc1dd7ea0e 100644 --- a/src/PIA.cc +++ b/src/analyzer/protocol/pia/PIA.cc @@ -1,8 +1,12 @@ #include "PIA.h" #include "RuleMatcher.h" -#include "TCP_Reassembler.h" +#include "analyzer/protocol/tcp/TCP_Reassembler.h" -PIA::PIA(Analyzer* arg_as_analyzer) +#include "events.bif.h" + +using namespace analyzer::pia; + +PIA::PIA(analyzer::Analyzer* arg_as_analyzer) { current_packet.data = 0; as_analyzer = arg_as_analyzer; @@ -61,9 +65,9 @@ void PIA::AddToBuffer(Buffer* buffer, int len, const u_char* data, bool is_orig) AddToBuffer(buffer, -1, len, data, is_orig); } -void PIA::ReplayPacketBuffer(Analyzer* analyzer) +void PIA::ReplayPacketBuffer(analyzer::Analyzer* analyzer) { - DBG_LOG(DBG_DPD, "PIA replaying %d total packet bytes", pkt_buffer.size); + DBG_LOG(DBG_ANALYZER, "PIA replaying %d total packet bytes", pkt_buffer.size); for ( DataBlock* b = pkt_buffer.head; b; b = b->next ) analyzer->DeliverPacket(b->len, b->data, b->is_orig, -1, 0, 0); @@ -129,11 +133,11 @@ void PIA::DoMatch(const u_char* data, int len, bool is_orig, bool bol, bool eol, bol, eol, clear_state); } -void PIA_UDP::ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule) +void PIA_UDP::ActivateAnalyzer(analyzer::Tag tag, const Rule* rule) { if ( pkt_buffer.state == MATCHING_ONLY ) { - DBG_LOG(DBG_DPD, "analyzer found but buffer already exceeded"); + DBG_LOG(DBG_ANALYZER, "analyzer found but buffer already exceeded"); // FIXME: This is where to check whether an analyzer // supports partial connections once we get such. return; @@ -142,14 +146,14 @@ void PIA_UDP::ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule) if ( Parent()->HasChildAnalyzer(tag) ) return; - Analyzer* a = Parent()->AddChildAnalyzer(tag); + analyzer::Analyzer* a = Parent()->AddChildAnalyzer(tag); a->SetSignature(rule); if ( a ) ReplayPacketBuffer(a); } -void PIA_UDP::DeactivateAnalyzer(AnalyzerTag::Tag tag) +void PIA_UDP::DeactivateAnalyzer(analyzer::Tag tag) { reporter->InternalError("PIA_UDP::Deact not implemented yet"); } @@ -163,11 +167,11 @@ PIA_TCP::~PIA_TCP() void PIA_TCP::Init() { - TCP_ApplicationAnalyzer::Init(); + tcp::TCP_ApplicationAnalyzer::Init(); - if ( Parent()->GetTag() == AnalyzerTag::TCP ) + if ( Parent()->IsAnalyzer("TCP") ) { - TCP_Analyzer* tcp = static_cast(Parent()); + tcp::TCP_Analyzer* tcp = static_cast(Parent()); SetTCP(tcp); tcp->SetPIA(this); } @@ -180,7 +184,7 @@ void PIA_TCP::FirstPacket(bool is_orig, const IP_Hdr* ip) static struct tcphdr* tcp4 = 0; static IP_Hdr* ip4_hdr = 0; - DBG_LOG(DBG_DPD, "PIA_TCP[%d] FirstPacket(%s)", GetID(), (is_orig ? "T" : "F")); + DBG_LOG(DBG_ANALYZER, "PIA_TCP[%d] FirstPacket(%s)", GetID(), (is_orig ? "T" : "F")); if ( ! ip ) { @@ -223,7 +227,7 @@ void PIA_TCP::FirstPacket(bool is_orig, const IP_Hdr* ip) void PIA_TCP::DeliverStream(int len, const u_char* data, bool is_orig) { - TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig); if ( stream_buffer.state == SKIPPING ) return; @@ -253,7 +257,7 @@ void PIA_TCP::DeliverStream(int len, const u_char* data, bool is_orig) void PIA_TCP::Undelivered(int seq, int len, bool is_orig) { - TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig); + tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig); if ( stream_buffer.state == BUFFERING ) // We use data=nil to mark an undelivered. @@ -262,11 +266,11 @@ void PIA_TCP::Undelivered(int seq, int len, bool is_orig) // No check for buffer overrun here. I think that's ok. } -void PIA_TCP::ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule) +void PIA_TCP::ActivateAnalyzer(analyzer::Tag tag, const Rule* rule) { if ( stream_buffer.state == MATCHING_ONLY ) { - DBG_LOG(DBG_DPD, "analyzer found but buffer already exceeded"); + DBG_LOG(DBG_ANALYZER, "analyzer found but buffer already exceeded"); // FIXME: This is where to check whether an analyzer supports // partial connections once we get such. return; @@ -275,7 +279,7 @@ void PIA_TCP::ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule) if ( Parent()->HasChildAnalyzer(tag) ) return; - Analyzer* a = Parent()->AddChildAnalyzer(tag); + analyzer::Analyzer* a = Parent()->AddChildAnalyzer(tag); a->SetSignature(rule); // We have two cases here: @@ -294,7 +298,7 @@ void PIA_TCP::ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule) // // Here's what we do: // - // (1) We create new TCP_Reassemblers and feed them the buffered + // (1) We create new tcp::TCP_Reassemblers and feed them the buffered // packets. // // (2) The reassembler will give us their results via the @@ -305,13 +309,13 @@ void PIA_TCP::ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule) // (4) We hand the two reassemblers to the TCP Analyzer (our parent), // turning reassembly now on for all subsequent data. - DBG_LOG(DBG_DPD, "DPM_TCP switching from packet-mode to stream-mode"); + DBG_LOG(DBG_ANALYZER, "PIA_TCP switching from packet-mode to stream-mode"); stream_mode = true; // FIXME: The reassembler will query the endpoint for state. Not sure // if this is works in all cases... - if ( Parent()->GetTag() != AnalyzerTag::TCP ) + if ( ! Parent()->IsAnalyzer("TCP") ) { // Our parent is not the TCP analyzer, which can only mean // we have been inserted somewhere further down in the @@ -322,14 +326,14 @@ void PIA_TCP::ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule) return; } - TCP_Analyzer* tcp = (TCP_Analyzer*) Parent(); + tcp::TCP_Analyzer* tcp = (tcp::TCP_Analyzer*) Parent(); - TCP_Reassembler* reass_orig = - new TCP_Reassembler(this, tcp, TCP_Reassembler::Direct, + tcp::TCP_Reassembler* reass_orig = + new tcp::TCP_Reassembler(this, tcp, tcp::TCP_Reassembler::Direct, true, tcp->Orig()); - TCP_Reassembler* reass_resp = - new TCP_Reassembler(this, tcp, TCP_Reassembler::Direct, + tcp::TCP_Reassembler* reass_resp = + new tcp::TCP_Reassembler(this, tcp, tcp::TCP_Reassembler::Direct, false, tcp->Resp()); int orig_seq = 0; @@ -365,20 +369,20 @@ void PIA_TCP::ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule) reass_orig->AckReceived(orig_seq); reass_resp->AckReceived(resp_seq); - reass_orig->SetType(TCP_Reassembler::Forward); - reass_resp->SetType(TCP_Reassembler::Forward); + reass_orig->SetType(tcp::TCP_Reassembler::Forward); + reass_resp->SetType(tcp::TCP_Reassembler::Forward); tcp->SetReassembler(reass_orig, reass_resp); } -void PIA_TCP::DeactivateAnalyzer(AnalyzerTag::Tag tag) +void PIA_TCP::DeactivateAnalyzer(analyzer::Tag tag) { reporter->InternalError("PIA_TCP::Deact not implemented yet"); } -void PIA_TCP::ReplayStreamBuffer(Analyzer* analyzer) +void PIA_TCP::ReplayStreamBuffer(analyzer::Analyzer* analyzer) { - DBG_LOG(DBG_DPD, "PIA_TCP replaying %d total stream bytes", stream_buffer.size); + DBG_LOG(DBG_ANALYZER, "PIA_TCP replaying %d total stream bytes", stream_buffer.size); for ( DataBlock* b = stream_buffer.head; b; b = b->next ) { diff --git a/src/PIA.h b/src/analyzer/protocol/pia/PIA.h similarity index 77% rename from src/PIA.h rename to src/analyzer/protocol/pia/PIA.h index 907350bbdf..d8c272d219 100644 --- a/src/PIA.h +++ b/src/analyzer/protocol/pia/PIA.h @@ -1,13 +1,15 @@ // An analyzer for application-layer protocol-detection. -#ifndef PIA_H -#define PIA_H +#ifndef ANALYZER_PROTOCOL_PIA_PIA_H +#define ANALYZER_PROTOCOL_PIA_PIA_H -#include "Analyzer.h" -#include "TCP.h" +#include "analyzer/Analyzer.h" +#include "analyzer/protocol/tcp/TCP.h" class RuleEndpointState; +namespace analyzer { namespace pia { + // Abstract PIA class providing common functionality for both TCP and UDP. // Accepts only packet input. // @@ -17,27 +19,25 @@ class RuleEndpointState; // PIAs and then each needs its own matching-state. class PIA : public RuleMatcherState { public: - PIA(Analyzer* as_analyzer); + PIA(analyzer::Analyzer* as_analyzer); virtual ~PIA(); // Called when PIA wants to put an Analyzer in charge. rule is the // signature that triggered the activitation, if any. - virtual void ActivateAnalyzer(AnalyzerTag::Tag tag, + virtual void ActivateAnalyzer(analyzer::Tag tag, const Rule* rule = 0) = 0; // Called when PIA wants to remove an Analyzer. - virtual void DeactivateAnalyzer(AnalyzerTag::Tag tag) = 0; + virtual void DeactivateAnalyzer(analyzer::Tag tag) = 0; void Match(Rule::PatternType type, const u_char* data, int len, bool is_orig, bool bol, bool eol, bool clear_state); - void ReplayPacketBuffer(Analyzer* analyzer); + void ReplayPacketBuffer(analyzer::Analyzer* analyzer); // Children are also derived from Analyzer. Return this object // as pointer to an Analyzer. - Analyzer* AsAnalyzer() { return as_analyzer; } - - static bool Available() { return true; } + analyzer::Analyzer* AsAnalyzer() { return as_analyzer; } protected: void PIA_Done(); @@ -81,20 +81,20 @@ protected: Buffer pkt_buffer; private: - Analyzer* as_analyzer; + analyzer::Analyzer* as_analyzer; Connection* conn; DataBlock current_packet; }; // PIA for UDP. -class PIA_UDP : public PIA, public Analyzer { +class PIA_UDP : public PIA, public analyzer::Analyzer { public: PIA_UDP(Connection* conn) - : PIA(this), Analyzer(AnalyzerTag::PIA_UDP, conn) + : PIA(this), Analyzer("PIA_UDP", conn) { SetConn(conn); } virtual ~PIA_UDP() { } - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new PIA_UDP(conn); } protected: @@ -111,16 +111,16 @@ protected: PIA_DeliverPacket(len, data, is_orig, seq, ip, caplen); } - virtual void ActivateAnalyzer(AnalyzerTag::Tag tag, const Rule* rule); - virtual void DeactivateAnalyzer(AnalyzerTag::Tag tag); + virtual void ActivateAnalyzer(analyzer::Tag tag, const Rule* rule); + virtual void DeactivateAnalyzer(analyzer::Tag tag); }; // PIA for TCP. Accepts both packet and stream input (and reassembles // packets before passing payload on to children). -class PIA_TCP : public PIA, public TCP_ApplicationAnalyzer { +class PIA_TCP : public PIA, public tcp::TCP_ApplicationAnalyzer { public: PIA_TCP(Connection* conn) - : PIA(this), TCP_ApplicationAnalyzer(AnalyzerTag::PIA_TCP, conn) + : PIA(this), tcp::TCP_ApplicationAnalyzer("PIA_TCP", conn) { stream_mode = false; SetConn(conn); } virtual ~PIA_TCP(); @@ -137,9 +137,9 @@ public: // to be unnecessary overhead.) void FirstPacket(bool is_orig, const IP_Hdr* ip); - void ReplayStreamBuffer(Analyzer* analyzer); + void ReplayStreamBuffer(analyzer::Analyzer* analyzer); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new PIA_TCP(conn); } protected: @@ -159,9 +159,9 @@ protected: virtual void DeliverStream(int len, const u_char* data, bool is_orig); virtual void Undelivered(int seq, int len, bool is_orig); - virtual void ActivateAnalyzer(AnalyzerTag::Tag tag, + virtual void ActivateAnalyzer(analyzer::Tag tag, const Rule* rule = 0); - virtual void DeactivateAnalyzer(AnalyzerTag::Tag tag); + virtual void DeactivateAnalyzer(analyzer::Tag tag); private: // FIXME: Not sure yet whether we need both pkt_buffer and stream_buffer. @@ -171,4 +171,6 @@ private: bool stream_mode; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/pia/Plugin.cc b/src/analyzer/protocol/pia/Plugin.cc new file mode 100644 index 0000000000..7d52801475 --- /dev/null +++ b/src/analyzer/protocol/pia/Plugin.cc @@ -0,0 +1,11 @@ + +#include "plugin/Plugin.h" + +#include "PIA.h" + +BRO_PLUGIN_BEGIN(Bro, PIA) + BRO_PLUGIN_DESCRIPTION("Analyzers implementing Dynamic Protocol Detection"); + BRO_PLUGIN_ANALYZER("PIA_TCP", pia::PIA_TCP); + BRO_PLUGIN_ANALYZER("PIA_UDP", pia::PIA_UDP); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/pia/events.bif b/src/analyzer/protocol/pia/events.bif new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/analyzer/protocol/pop3/CMakeLists.txt b/src/analyzer/protocol/pop3/CMakeLists.txt new file mode 100644 index 0000000000..8071d6a74d --- /dev/null +++ b/src/analyzer/protocol/pop3/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro POP3) +bro_plugin_cc(POP3.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/POP3.cc b/src/analyzer/protocol/pop3/POP3.cc similarity index 97% rename from src/POP3.cc rename to src/analyzer/protocol/pop3/POP3.cc index 3075e76507..652fd20e32 100644 --- a/src/POP3.cc +++ b/src/analyzer/protocol/pop3/POP3.cc @@ -12,8 +12,12 @@ #include "NetVar.h" #include "POP3.h" #include "Event.h" -#include "NVT.h" #include "Reporter.h" +#include "analyzer/protocol/login/NVT.h" + +#include "events.bif.h" + +using namespace analyzer::pop3; #undef POP3_CMD_DEF #define POP3_CMD_DEF(cmd) #cmd, @@ -26,7 +30,7 @@ static const char* pop3_cmd_word[] = { POP3_Analyzer::POP3_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::POP3, conn) +: tcp::TCP_ApplicationAnalyzer("POP3", conn) { masterState = POP3_START; subState = POP3_WOK; @@ -41,8 +45,8 @@ POP3_Analyzer::POP3_Analyzer(Connection* conn) mail = 0; - AddSupportAnalyzer(new ContentLine_Analyzer(conn, true)); - AddSupportAnalyzer(new ContentLine_Analyzer(conn, false)); + AddSupportAnalyzer(new tcp::ContentLine_Analyzer(conn, true)); + AddSupportAnalyzer(new tcp::ContentLine_Analyzer(conn, false)); } POP3_Analyzer::~POP3_Analyzer() @@ -51,7 +55,7 @@ POP3_Analyzer::~POP3_Analyzer() void POP3_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); if ( mail ) EndData(); @@ -60,7 +64,7 @@ void POP3_Analyzer::Done() void POP3_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { - TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); if ( (TCP() && TCP()->IsPartial()) || backOff ) return; @@ -802,7 +806,7 @@ void POP3_Analyzer::AuthSuccessfull() void POP3_Analyzer::BeginData() { delete mail; - mail = new MIME_Mail(this); + mail = new mime::MIME_Mail(this); } void POP3_Analyzer::EndData() diff --git a/src/POP3.h b/src/analyzer/protocol/pop3/POP3.h similarity index 80% rename from src/POP3.h rename to src/analyzer/protocol/pop3/POP3.h index 8d09d5e686..ab535420e5 100644 --- a/src/POP3.h +++ b/src/analyzer/protocol/pop3/POP3.h @@ -2,21 +2,22 @@ // // An analyser for the POP3 protocol. -#ifndef pop3_h -#define pop3_h +#ifndef ANALYZER_PROTOCOL_POP3_POP3_H +#define ANALYZER_PROTOCOL_POP3_POP3_H #include #include #include -#include "NVT.h" -#include "TCP.h" -#include "MIME.h" - +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/login/NVT.h" +#include "analyzer/protocol/mime/MIME.h" #undef POP3_CMD_DEF #define POP3_CMD_DEF(cmd) POP3_CMD_##cmd, +namespace analyzer { namespace pop3 { + typedef enum { #include "POP3_cmd.def" } POP3_Cmd; @@ -60,7 +61,7 @@ typedef enum { POP3_WOK, } POP3_SubState; -class POP3_Analyzer : public TCP_ApplicationAnalyzer { +class POP3_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: POP3_Analyzer(Connection* conn); ~POP3_Analyzer(); @@ -68,16 +69,11 @@ public: virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new POP3_Analyzer(conn); } - static bool Available() - { - return pop3_request || pop3_reply || pop3_data || pop3_unexpected; - } - protected: int masterState; int subState; @@ -108,11 +104,13 @@ protected: void POP3Event(EventHandlerPtr event, bool is_orig, const char* arg1 = 0, const char* arg2 = 0); - MIME_Mail* mail; + mime::MIME_Mail* mail; list cmds; private: bool backOff; }; +} } // namespace analyzer::* + #endif diff --git a/src/POP3_cmd.def b/src/analyzer/protocol/pop3/POP3_cmd.def similarity index 100% rename from src/POP3_cmd.def rename to src/analyzer/protocol/pop3/POP3_cmd.def diff --git a/src/analyzer/protocol/pop3/Plugin.cc b/src/analyzer/protocol/pop3/Plugin.cc new file mode 100644 index 0000000000..edd99e2617 --- /dev/null +++ b/src/analyzer/protocol/pop3/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "POP3.h" + +BRO_PLUGIN_BEGIN(Bro, POP3) + BRO_PLUGIN_DESCRIPTION("POP3 analyzer"); + BRO_PLUGIN_ANALYZER("POP3", pop3::POP3_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/pop3/events.bif b/src/analyzer/protocol/pop3/events.bif new file mode 100644 index 0000000000..7692c61f6b --- /dev/null +++ b/src/analyzer/protocol/pop3/events.bif @@ -0,0 +1,172 @@ +## Generated for client-side commands on POP3 connections. +## +## See `Wikipedia `__ for more information +## about the POP3 protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## command: The command sent. +## +## arg: The argument to the command. +## +## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_reply +## pop3_terminate pop3_unexpected +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pop3_request%(c: connection, is_orig: bool, + command: string, arg: string%); + +## Generated for server-side replies to commands on POP3 connections. +## +## See `Wikipedia `__ for more information +## about the POP3 protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP +## connection. +## +## cmd: The success indicator sent by the server. This corresponds to the +## first token on the line sent, and should be either ``OK`` or ``ERR``. +## +## msg: The textual description the server sent along with *cmd*. +## +## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_request +## pop3_terminate pop3_unexpected +## +## .. todo:: This event is receiving odd parameters, should unify. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pop3_reply%(c: connection, is_orig: bool, cmd: string, msg: string%); + +## Generated for server-side multi-line responses on POP3 connections. POP3 +## connections use multi-line responses to send bulk data, such as the actual +## mails. This event is generated once for each line that's part of such a +## response. +## +## See `Wikipedia `__ for more information +## about the POP3 protocol. +## +## c: The connection. +## +## is_orig: True if the data was sent by the originator of the TCP connection. +## +## data: The data sent. +## +## .. bro:see:: pop3_login_failure pop3_login_success pop3_reply pop3_request +## pop3_terminate pop3_unexpected +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pop3_data%(c: connection, is_orig: bool, data: string%); + +## Generated for errors encountered on POP3 sessions. If the POP3 analyzer +## finds state transitions that do not conform to the protocol specification, +## or other situations it can't handle, it raises this event. +## +## See `Wikipedia `__ for more information +## about the POP3 protocol. +## +## c: The connection. +## +## is_orig: True if the data was sent by the originator of the TCP connection. +## +## msg: A textual description of the situation. +## +## detail: The input that triggered the event. +## +## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_reply pop3_request +## pop3_terminate +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pop3_unexpected%(c: connection, is_orig: bool, + msg: string, detail: string%); + +## Generated when a POP3 connection goes encrypted. While POP3 is by default a +## clear-text protocol, extensions exist to switch to encryption. This event is +## generated if that happens and the analyzer then stops processing the +## connection. +## +## See `Wikipedia `__ for more information +## about the POP3 protocol. +## +## c: The connection. +## +## is_orig: Always false. +## +## msg: A descriptive message why processing was stopped. +## +## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_reply pop3_request +## pop3_unexpected +## +## .. note:: Currently, only the ``STARTLS`` command is recognized and +## triggers this. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pop3_terminate%(c: connection, is_orig: bool, msg: string%); + +## Generated for successful authentications on POP3 connections. +## +## See `Wikipedia `__ for more information +## about the POP3 protocol. +## +## c: The connection. +## +## is_orig: Always false. +## +## user: The user name used for authentication. The event is only generated if +## a non-empty user name was used. +## +## password: The password used for authentication. +## +## .. bro:see:: pop3_data pop3_login_failure pop3_reply pop3_request pop3_terminate +## pop3_unexpected +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pop3_login_success%(c: connection, is_orig: bool, + user: string, password: string%); + +## Generated for unsuccessful authentications on POP3 connections. +## +## See `Wikipedia `__ for more information +## about the POP3 protocol. +## +## c: The connection. +## +## is_orig: Always false. +## +## user: The user name attempted for authentication. The event is only +## generated if a non-empty user name was used. +## +## password: The password attempted for authentication. +## +## .. bro:see:: pop3_data pop3_login_success pop3_reply pop3_request pop3_terminate +## pop3_unexpected +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pop3_login_failure%(c: connection, is_orig: bool, + user: string, password: string%); + diff --git a/src/analyzer/protocol/rpc/CMakeLists.txt b/src/analyzer/protocol/rpc/CMakeLists.txt new file mode 100644 index 0000000000..5696a74cd6 --- /dev/null +++ b/src/analyzer/protocol/rpc/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro RPC) +bro_plugin_cc(RPC.cc NFS.cc Portmap.cc XDR.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/NFS.cc b/src/analyzer/protocol/rpc/NFS.cc similarity index 99% rename from src/NFS.cc rename to src/analyzer/protocol/rpc/NFS.cc index d64f7755a3..51d1b90691 100644 --- a/src/NFS.cc +++ b/src/analyzer/protocol/rpc/NFS.cc @@ -9,6 +9,10 @@ #include "NFS.h" #include "Event.h" +#include "events.bif.h" + +using namespace analyzer::rpc; + int NFS_Interp::RPC_BuildCall(RPC_CallInfo* c, const u_char*& buf, int& n) { if ( c->Program() != 100003 ) @@ -641,7 +645,7 @@ Val* NFS_Interp::ExtractBool(const u_char*& buf, int& n) NFS_Analyzer::NFS_Analyzer(Connection* conn) - : RPC_Analyzer(AnalyzerTag::NFS, conn, new NFS_Interp(this)) + : RPC_Analyzer("RPC", conn, new NFS_Interp(this)) { orig_rpc = resp_rpc = 0; } diff --git a/src/NFS.h b/src/analyzer/protocol/rpc/NFS.h similarity index 86% rename from src/NFS.h rename to src/analyzer/protocol/rpc/NFS.h index 6a65143808..7656450d94 100644 --- a/src/NFS.h +++ b/src/analyzer/protocol/rpc/NFS.h @@ -1,15 +1,17 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef nfs_h -#define nfs_h +#ifndef ANALYZER_PROTOCOL_RPC_NFS_H +#define ANALYZER_PROTOCOL_RPC_NFS_H #include "RPC.h" #include "XDR.h" #include "Event.h" +namespace analyzer { namespace rpc { + class NFS_Interp : public RPC_Interpreter { public: - NFS_Interp(Analyzer* arg_analyzer) : RPC_Interpreter(arg_analyzer) { } + NFS_Interp(analyzer::Analyzer* arg_analyzer) : RPC_Interpreter(arg_analyzer) { } protected: int RPC_BuildCall(RPC_CallInfo* c, const u_char*& buf, int& n); @@ -75,19 +77,11 @@ public: NFS_Analyzer(Connection* conn); virtual void Init(); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new NFS_Analyzer(conn); } - - static bool Available() - { - return ( nfs_proc_null || nfs_proc_not_implemented || nfs_proc_getattr || - nfs_proc_lookup || nfs_proc_read || nfs_proc_readlink || - nfs_proc_write || nfs_proc_create || nfs_proc_mkdir || - nfs_proc_remove || nfs_proc_rmdir || nfs_proc_readdir || - nfs_reply_status || - rpc_dialogue || rpc_call || rpc_reply ); - } }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/rpc/Plugin.cc b/src/analyzer/protocol/rpc/Plugin.cc new file mode 100644 index 0000000000..9760df0623 --- /dev/null +++ b/src/analyzer/protocol/rpc/Plugin.cc @@ -0,0 +1,15 @@ + +#include "plugin/Plugin.h" + +#include "RPC.h" +#include "NFS.h" +#include "Portmap.h" + +BRO_PLUGIN_BEGIN(Bro, RPC) + BRO_PLUGIN_DESCRIPTION("Analyzers for RPC-based protocols"); + BRO_PLUGIN_ANALYZER("NFS", rpc::NFS_Analyzer); + BRO_PLUGIN_ANALYZER("Portmapper", rpc::Portmapper_Analyzer); + BRO_PLUGIN_SUPPORT_ANALYZER("Contents_RPC"); + BRO_PLUGIN_SUPPORT_ANALYZER("Contents_NFS"); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/Portmap.cc b/src/analyzer/protocol/rpc/Portmap.cc similarity index 98% rename from src/Portmap.cc rename to src/analyzer/protocol/rpc/Portmap.cc index dd1049a361..f57d9a915c 100644 --- a/src/Portmap.cc +++ b/src/analyzer/protocol/rpc/Portmap.cc @@ -7,6 +7,10 @@ #include "Portmap.h" #include "Event.h" +#include "events.bif.h" + +using namespace analyzer::rpc; + #define PMAPPROC_NULL 0 #define PMAPPROC_SET 1 #define PMAPPROC_UNSET 2 @@ -300,7 +304,7 @@ void PortmapperInterp::Event(EventHandlerPtr f, Val* request, BifEnum::rpc_statu } Portmapper_Analyzer::Portmapper_Analyzer(Connection* conn) -: RPC_Analyzer(AnalyzerTag::Portmapper, conn, new PortmapperInterp(this)) +: RPC_Analyzer("PORTMAPPER", conn, new PortmapperInterp(this)) { orig_rpc = resp_rpc = 0; } diff --git a/src/Portmap.h b/src/analyzer/protocol/rpc/Portmap.h similarity index 74% rename from src/Portmap.h rename to src/analyzer/protocol/rpc/Portmap.h index 62e954bc80..52d0c21a04 100644 --- a/src/Portmap.h +++ b/src/analyzer/protocol/rpc/Portmap.h @@ -1,13 +1,15 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef portmap_h -#define portmap_h +#ifndef ANALYZER_PROTOCOL_RPC_PORTMAP_H +#define ANALYZER_PROTOCOL_RPC_PORTMAP_H #include "RPC.h" +namespace analyzer { namespace rpc { + class PortmapperInterp : public RPC_Interpreter { public: - PortmapperInterp(Analyzer* arg_analyzer) : RPC_Interpreter(arg_analyzer) { } + PortmapperInterp(analyzer::Analyzer* arg_analyzer) : RPC_Interpreter(arg_analyzer) { } protected: int RPC_BuildCall(RPC_CallInfo* c, const u_char*& buf, int& n); @@ -29,11 +31,10 @@ public: virtual ~Portmapper_Analyzer(); virtual void Init(); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new Portmapper_Analyzer(conn); } - - static bool Available() - { return pm_request || rpc_call; } }; +} } // namespace analyzer::* + #endif diff --git a/src/RPC.cc b/src/analyzer/protocol/rpc/RPC.cc similarity index 95% rename from src/RPC.cc rename to src/analyzer/protocol/rpc/RPC.cc index 81fd6709b1..ea037c227f 100644 --- a/src/RPC.cc +++ b/src/analyzer/protocol/rpc/RPC.cc @@ -11,6 +11,10 @@ #include "RPC.h" #include "Sessions.h" +#include "events.bif.h" + +using namespace analyzer::rpc; + namespace { // local namespace const bool DEBUG_rpc_resync = false; } @@ -66,7 +70,7 @@ void rpc_callinfo_delete_func(void* v) delete (RPC_CallInfo*) v; } -RPC_Interpreter::RPC_Interpreter(Analyzer* arg_analyzer) +RPC_Interpreter::RPC_Interpreter(analyzer::Analyzer* arg_analyzer) { analyzer = arg_analyzer; calls.SetDeleteFunc(rpc_callinfo_delete_func); @@ -373,7 +377,7 @@ bool RPC_Reasm_Buffer::ConsumeChunk(const u_char*& data, int& len) Contents_RPC::Contents_RPC(Connection* conn, bool orig, RPC_Interpreter* arg_interp) - : TCP_SupportAnalyzer(AnalyzerTag::Contents_RPC, conn, orig) + : tcp::TCP_SupportAnalyzer("CONTENTS_RPC", conn, orig) { interp = arg_interp; state = WAIT_FOR_MESSAGE; @@ -385,7 +389,7 @@ Contents_RPC::Contents_RPC(Connection* conn, bool orig, void Contents_RPC::Init() { - TCP_SupportAnalyzer::Init(); + tcp::TCP_SupportAnalyzer::Init(); } Contents_RPC::~Contents_RPC() @@ -394,7 +398,7 @@ Contents_RPC::~Contents_RPC() void Contents_RPC::Undelivered(int seq, int len, bool orig) { - TCP_SupportAnalyzer::Undelivered(seq, len, orig); + tcp::TCP_SupportAnalyzer::Undelivered(seq, len, orig); NeedResync(); } @@ -413,12 +417,12 @@ bool Contents_RPC::CheckResync(int& len, const u_char*& data, bool orig) // is fully established we are in sync (since it's the first chunk // of data after the SYN if its not established we need to // resync. - TCP_Analyzer* tcp = - static_cast(Parent())->TCP(); + tcp::TCP_Analyzer* tcp = + static_cast(Parent())->TCP(); assert(tcp); if ( (IsOrig() ? tcp->OrigState() : tcp->RespState()) != - TCP_ENDPOINT_ESTABLISHED ) + tcp::TCP_ENDPOINT_ESTABLISHED ) { NeedResync(); } @@ -578,7 +582,7 @@ bool Contents_RPC::CheckResync(int& len, const u_char*& data, bool orig) void Contents_RPC::DeliverStream(int len, const u_char* data, bool orig) { - TCP_SupportAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_SupportAnalyzer::DeliverStream(len, data, orig); uint32 marker; bool last_frag; @@ -673,9 +677,9 @@ void Contents_RPC::DeliverStream(int len, const u_char* data, bool orig) } // end while } -RPC_Analyzer::RPC_Analyzer(AnalyzerTag::Tag tag, Connection* conn, +RPC_Analyzer::RPC_Analyzer(const char* name, Connection* conn, RPC_Interpreter* arg_interp) -: TCP_ApplicationAnalyzer(tag, conn) +: tcp::TCP_ApplicationAnalyzer(name, conn) { interp = arg_interp; @@ -692,7 +696,7 @@ RPC_Analyzer::~RPC_Analyzer() void RPC_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) { - TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); + tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen); len = min(len, caplen); if ( orig ) @@ -709,7 +713,7 @@ void RPC_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, void RPC_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); interp->Timeout(); } diff --git a/src/RPC.h b/src/analyzer/protocol/rpc/RPC.h similarity index 93% rename from src/RPC.h rename to src/analyzer/protocol/rpc/RPC.h index 0eee423460..a705d272f6 100644 --- a/src/RPC.h +++ b/src/analyzer/protocol/rpc/RPC.h @@ -1,10 +1,12 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef rpc_h -#define rpc_h +#ifndef ANALYZER_PROTOCOL_RPC_RPC_H +#define ANALYZER_PROTOCOL_RPC_RPC_H -#include "TCP.h" -#include "UDP.h" +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/udp/UDP.h" + +namespace analyzer { namespace rpc { enum { RPC_CALL = 0, @@ -92,7 +94,7 @@ declare(PDict,RPC_CallInfo); class RPC_Interpreter { public: - RPC_Interpreter(Analyzer* analyzer); + RPC_Interpreter(analyzer::Analyzer* analyzer); virtual ~RPC_Interpreter(); // Delivers the given RPC. Returns true if "len" bytes were @@ -115,7 +117,7 @@ protected: void Weird(const char* name); PDict(RPC_CallInfo) calls; - Analyzer* analyzer; + analyzer::Analyzer* analyzer; }; @@ -176,7 +178,7 @@ protected: }; /* Support Analyzer for reassembling RPC-over-TCP messages */ -class Contents_RPC : public TCP_SupportAnalyzer { +class Contents_RPC : public tcp::TCP_SupportAnalyzer { public: Contents_RPC(Connection* conn, bool orig, RPC_Interpreter* interp); virtual ~Contents_RPC(); @@ -222,9 +224,9 @@ protected: int resync_toskip; }; -class RPC_Analyzer : public TCP_ApplicationAnalyzer { +class RPC_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: - RPC_Analyzer(AnalyzerTag::Tag tag, Connection* conn, + RPC_Analyzer(const char* name, Connection* conn, RPC_Interpreter* arg_interp); virtual ~RPC_Analyzer(); @@ -242,4 +244,6 @@ protected: Contents_RPC* resp_rpc; }; +} } // namespace analyzer::* + #endif diff --git a/src/XDR.cc b/src/analyzer/protocol/rpc/XDR.cc similarity index 73% rename from src/XDR.cc rename to src/analyzer/protocol/rpc/XDR.cc index 96d855ddbd..981a982716 100644 --- a/src/XDR.cc +++ b/src/analyzer/protocol/rpc/XDR.cc @@ -6,7 +6,11 @@ #include "XDR.h" -uint32 extract_XDR_uint32(const u_char*& buf, int& len) +#include "events.bif.h" + +using namespace analyzer::rpc; + +uint32 analyzer::rpc::extract_XDR_uint32(const u_char*& buf, int& len) { if ( ! buf ) return 0; @@ -26,7 +30,7 @@ uint32 extract_XDR_uint32(const u_char*& buf, int& len) return bits32; } -uint64 extract_XDR_uint64(const u_char*& buf, int& len) +uint64 analyzer::rpc::extract_XDR_uint64(const u_char*& buf, int& len) { if ( ! buf || len < 8 ) { @@ -40,7 +44,7 @@ uint64 extract_XDR_uint64(const u_char*& buf, int& len) return (uhi << 32) + ulo; } -double extract_XDR_time(const u_char*& buf, int& len) +double analyzer::rpc::extract_XDR_time(const u_char*& buf, int& len) { if ( ! buf || len < 8 ) { @@ -54,7 +58,7 @@ double extract_XDR_time(const u_char*& buf, int& len) return double(uhi) + double(ulo) / 1e9; } -const u_char* extract_XDR_opaque(const u_char*& buf, int& len, int& n, int max_len, bool short_buf_ok) +const u_char* analyzer::rpc::extract_XDR_opaque(const u_char*& buf, int& len, int& n, int max_len, bool short_buf_ok) { n = int(extract_XDR_uint32(buf, len)); if ( ! buf ) @@ -78,7 +82,7 @@ const u_char* extract_XDR_opaque(const u_char*& buf, int& len, int& n, int max_l return opaque; } -const u_char* extract_XDR_opaque_fixed(const u_char*& buf, int& len, int n) +const u_char* analyzer::rpc::extract_XDR_opaque_fixed(const u_char*& buf, int& len, int n) { if ( ! buf ) return 0; @@ -97,7 +101,7 @@ const u_char* extract_XDR_opaque_fixed(const u_char*& buf, int& len, int n) } -uint32 skip_XDR_opaque_auth(const u_char*& buf, int& len) +uint32 analyzer::rpc::skip_XDR_opaque_auth(const u_char*& buf, int& len) { uint32 auth_flavor = extract_XDR_uint32(buf, len); if ( ! buf ) diff --git a/src/XDR.h b/src/analyzer/protocol/rpc/XDR.h similarity index 81% rename from src/XDR.h rename to src/analyzer/protocol/rpc/XDR.h index 65192d6067..a1be0a1e05 100644 --- a/src/XDR.h +++ b/src/analyzer/protocol/rpc/XDR.h @@ -1,13 +1,15 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef xdr_h -#define xdr_h +#ifndef ANALYZER_PROTOCOL_RPC_XDR_H +#define ANALYZER_PROTOCOL_RPC_XDR_H #include #include #include "util.h" +namespace analyzer { namespace rpc { + extern uint32 extract_XDR_uint32(const u_char*& buf, int& len); extern uint64 extract_XDR_uint64(const u_char*& buf, int& len); extern double extract_XDR_time(const u_char*& buf, int& len); @@ -16,4 +18,6 @@ extern const u_char* extract_XDR_opaque(const u_char*& buf, int& len, extern const u_char* extract_XDR_opaque_fixed(const u_char*& buf, int& len, int n); extern uint32 skip_XDR_opaque_auth(const u_char*& buf, int& len); +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/rpc/events.bif b/src/analyzer/protocol/rpc/events.bif new file mode 100644 index 0000000000..72c57aff74 --- /dev/null +++ b/src/analyzer/protocol/rpc/events.bif @@ -0,0 +1,731 @@ +## Generated for NFSv3 request/reply dialogues of type *null*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_read nfs_proc_readdir nfs_proc_readlink +## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_null%(c: connection, info: NFS3::info_t%); + +## Generated for NFSv3 request/reply dialogues of type *getattr*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## fh: TODO. +## +## attrs: The attributes returned in the reply. The values may not be valid if +## the request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status +## rpc_call rpc_dialogue rpc_reply file_mode +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_getattr%(c: connection, info: NFS3::info_t, fh: string, attrs: NFS3::fattr_t%); + +## Generated for NFSv3 request/reply dialogues of type *lookup*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: The arguments passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status +## rpc_call rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_lookup%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::lookup_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *read*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: The arguments passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_remove nfs_proc_rmdir +## nfs_proc_write nfs_reply_status rpc_call rpc_dialogue rpc_reply +## NFS3::return_data NFS3::return_data_first_only NFS3::return_data_max +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_read%(c: connection, info: NFS3::info_t, req: NFS3::readargs_t, rep: NFS3::read_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *readlink*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## fh: The file handle passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_readlink%(c: connection, info: NFS3::info_t, fh: string, rep: NFS3::readlink_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *write*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: TODO. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_reply_status rpc_call +## rpc_dialogue rpc_reply NFS3::return_data NFS3::return_data_first_only +## NFS3::return_data_max +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_write%(c: connection, info: NFS3::info_t, req: NFS3::writeargs_t, rep: NFS3::write_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *create*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: TODO. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status +## rpc_call rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_create%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::newobj_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *mkdir*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: TODO. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status +## rpc_call rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_mkdir%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::newobj_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *remove*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: TODO. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_remove%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::delobj_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *rmdir*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: TODO. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_write nfs_reply_status rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_rmdir%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::delobj_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *readdir*. The event is +## generated once we have either seen both the request and its corresponding +## reply, or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: TODO. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readlink +## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_readdir%(c: connection, info: NFS3::info_t, req: NFS3::readdirargs_t, rep: NFS3::readdir_reply_t%); + +## Generated for NFSv3 request/reply dialogues of a type that Bro's NFSv3 +## analyzer does not implement. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## proc: The procedure called that Bro does not implement. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_null nfs_proc_read nfs_proc_readdir nfs_proc_readlink nfs_proc_remove +## nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_proc_not_implemented%(c: connection, info: NFS3::info_t, proc: NFS3::proc_t%); + +## Generated for each NFSv3 reply message received, reporting just the +## status included. +## +## n: The connection. +## +## info: Reports the status included in the reply. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event nfs_reply_status%(n: connection, info: NFS3::info_t%); + +## Generated for Portmapper requests of type *null*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit +## pm_request_dump pm_request_getport pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_request_null%(r: connection%); + +## Generated for Portmapper request/reply dialogues of type *set*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## m: The argument to the request. +## +## success: True if the request was successful, according to the corresponding +## reply. If no reply was seen, this will be false once the request +## times out. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit +## pm_request_dump pm_request_getport pm_request_null pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_request_set%(r: connection, m: pm_mapping, success: bool%); + +## Generated for Portmapper request/reply dialogues of type *unset*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## m: The argument to the request. +## +## success: True if the request was successful, according to the corresponding +## reply. If no reply was seen, this will be false once the request +## times out. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit +## pm_request_dump pm_request_getport pm_request_null pm_request_set rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_request_unset%(r: connection, m: pm_mapping, success: bool%); + +## Generated for Portmapper request/reply dialogues of type *getport*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## pr: The argument to the request. +## +## p: The port returned by the server. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit +## pm_request_dump pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_request_getport%(r: connection, pr: pm_port_request, p: port%); + +## Generated for Portmapper request/reply dialogues of type *dump*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## m: The mappings returned by the server. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_request_dump%(r: connection, m: pm_mappings%); + +## Generated for Portmapper request/reply dialogues of type *callit*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## call: The argument to the request. +## +## p: The port value returned by the call. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_request_callit%(r: connection, call: pm_callit_request, p: port%); + +## Generated for failed Portmapper requests of type *null*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_attempt_null%(r: connection, status: rpc_status%); + +## Generated for failed Portmapper requests of type *set*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## m: The argument to the original request. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_attempt_set%(r: connection, status: rpc_status, m: pm_mapping%); + +## Generated for failed Portmapper requests of type *unset*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## m: The argument to the original request. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_attempt_unset%(r: connection, status: rpc_status, m: pm_mapping%); + +## Generated for failed Portmapper requests of type *getport*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## pr: The argument to the original request. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_null +## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_attempt_getport%(r: connection, status: rpc_status, pr: pm_port_request%); + +## Generated for failed Portmapper requests of type *dump*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_getport pm_attempt_null +## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_attempt_dump%(r: connection, status: rpc_status%); + +## Generated for failed Portmapper requests of type *callit*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## call: The argument to the original request. +## +## .. bro:see:: epm_map_response pm_attempt_dump pm_attempt_getport pm_attempt_null +## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_attempt_callit%(r: connection, status: rpc_status, call: pm_callit_request%); + +## Generated for Portmapper requests or replies that include an invalid port +## number. Since ports are represented by unsigned 4-byte integers, they can +## stray outside the allowed range of 0--65535 by being >= 65536. If so, this +## event is generated. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## bad_p: The invalid port value. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_request_callit +## pm_request_dump pm_request_getport pm_request_null pm_request_set +## pm_request_unset rpc_call rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event pm_bad_port%(r: connection, bad_p: count%); + +## Generated for RPC request/reply *pairs*. The RPC analyzer associates request +## and reply by their transaction identifiers and raises this event once both +## have been seen. If there's not a reply, this event will still be generated +## eventually on timeout. In that case, *status* will be set to +## :bro:enum:`RPC_TIMEOUT`. +## +## See `Wikipedia `__ for more information +## about the ONC RPC protocol. +## +## c: The connection. +## +## prog: The remote program to call. +## +## ver: The version of the remote program to call. +## +## proc: The procedure of the remote program to call. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## start_time: The time when the *call* was seen. +## +## call_len: The size of the *call_body* PDU. +## +## reply_len: The size of the *reply_body* PDU. +## +## .. bro:see:: rpc_call rpc_reply dce_rpc_bind dce_rpc_message dce_rpc_request +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event rpc_dialogue%(c: connection, prog: count, ver: count, proc: count, status: rpc_status, start_time: time, call_len: count, reply_len: count%); + +## Generated for RPC *call* messages. +## +## See `Wikipedia `__ for more information +## about the ONC RPC protocol. +## +## c: The connection. +## +## xid: The transaction identifier allowing to match requests with replies. +## +## prog: The remote program to call. +## +## ver: The version of the remote program to call. +## +## proc: The procedure of the remote program to call. +## +## call_len: The size of the *call_body* PDU. +## +## .. bro:see:: rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message dce_rpc_request +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event rpc_call%(c: connection, xid: count, prog: count, ver: count, proc: count, call_len: count%); + +## Generated for RPC *reply* messages. +## +## See `Wikipedia `__ for more information +## about the ONC RPC protocol. +## +## c: The connection. +## +## xid: The transaction identifier allowing to match requests with replies. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## reply_len: The size of the *reply_body* PDU. +## +## .. bro:see:: rpc_call rpc_dialogue dce_rpc_bind dce_rpc_message dce_rpc_request +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## call to :bro:see:`Analyzer::register_for_ports` or a DPD payload +## signature. +event rpc_reply%(c: connection, xid: count, status: rpc_status, reply_len: count%); diff --git a/src/analyzer/protocol/smb/CMakeLists.txt b/src/analyzer/protocol/smb/CMakeLists.txt new file mode 100644 index 0000000000..feec283197 --- /dev/null +++ b/src/analyzer/protocol/smb/CMakeLists.txt @@ -0,0 +1,11 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) +include_directories(AFTER ${CMAKE_CURRENT_BINARY_DIR}/../dce-rpc) + +bro_plugin_begin(Bro SMB) +bro_plugin_cc(SMB.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(smb.pac smb-protocol.pac smb-pipe.pac smb-mailslot.pac) +bro_plugin_end() diff --git a/src/analyzer/protocol/smb/Plugin.cc b/src/analyzer/protocol/smb/Plugin.cc new file mode 100644 index 0000000000..af564c067c --- /dev/null +++ b/src/analyzer/protocol/smb/Plugin.cc @@ -0,0 +1,11 @@ + +#include "plugin/Plugin.h" + +#include "SMB.h" + +BRO_PLUGIN_BEGIN(Bro, SMB) + BRO_PLUGIN_DESCRIPTION("SMB analyzer"); + BRO_PLUGIN_ANALYZER("SMB", smb::SMB_Analyzer); + BRO_PLUGIN_SUPPORT_ANALYZER("Contents_SMB"); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/SMB.cc b/src/analyzer/protocol/smb/SMB.cc similarity index 98% rename from src/SMB.cc rename to src/analyzer/protocol/smb/SMB.cc index a06707328a..798e2bfd1f 100644 --- a/src/SMB.cc +++ b/src/analyzer/protocol/smb/SMB.cc @@ -6,6 +6,10 @@ #include "Val.h" #include "Reporter.h" +#include "events.bif.h" + +using namespace analyzer::smb; + namespace { const bool DEBUG_smb_ipc = true; } @@ -93,7 +97,7 @@ static int lookup_IPC_name(BroString* name) return IPC_NONE; } -SMB_Session::SMB_Session(Analyzer* arg_analyzer) +SMB_Session::SMB_Session(analyzer::Analyzer* arg_analyzer) { analyzer = arg_analyzer; dce_rpc_session = 0; @@ -1093,7 +1097,7 @@ bool SMB_Session::CheckRPC(int is_orig, int data_count, const u_char *data) if ( LooksLikeRPC(data_count, data) ) { if ( ! dce_rpc_session ) - dce_rpc_session = new DCE_RPC_Session(analyzer); + dce_rpc_session = new dce_rpc::DCE_RPC_Session(analyzer); dce_rpc_session->DeliverPDU(is_orig, data_count, data); @@ -1104,7 +1108,7 @@ bool SMB_Session::CheckRPC(int is_orig, int data_count, const u_char *data) } Contents_SMB::Contents_SMB(Connection* conn, bool orig, SMB_Session* s) -: TCP_SupportAnalyzer(AnalyzerTag::Contents_SMB, conn, orig) +: tcp::TCP_SupportAnalyzer("CONTENTS_SMB", conn, orig) { smb_session = s; msg_buf = 0; @@ -1145,7 +1149,7 @@ void Contents_SMB::DeliverSMB(int len, const u_char* data) void Contents_SMB::DeliverStream(int len, const u_char* data, bool orig) { - TCP_SupportAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_SupportAnalyzer::DeliverStream(len, data, orig); while ( len > 0 ) { @@ -1221,7 +1225,7 @@ void Contents_SMB::DeliverStream(int len, const u_char* data, bool orig) } SMB_Analyzer::SMB_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::SMB, conn) +: tcp::TCP_ApplicationAnalyzer("SMB", conn) { smb_session = new SMB_Session(this); o_smb = new Contents_SMB(conn, true, smb_session); diff --git a/src/SMB.h b/src/analyzer/protocol/smb/SMB.h similarity index 88% rename from src/SMB.h rename to src/analyzer/protocol/smb/SMB.h index f7287efb79..b54852e5b7 100644 --- a/src/SMB.h +++ b/src/analyzer/protocol/smb/SMB.h @@ -1,15 +1,17 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef smb_h -#define smb_h +#ifndef ANALYZER_PROTOCOL_SMB_SMB_H +#define ANALYZER_PROTOCOL_SMB_SMB_H // SMB (CIFS) analyzer. // Reference: http://www.snia.org/tech_activities/CIFS/CIFS-TR-1p00_FINAL.pdf -#include "TCP.h" -#include "DCE_RPC.h" +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/dce-rpc/DCE_RPC.h" #include "smb_pac.h" +namespace analyzer { namespace smb { + enum IPC_named_pipe { IPC_NONE, IPC_LOCATOR, @@ -39,20 +41,11 @@ protected: class SMB_Session { public: - SMB_Session(Analyzer* analyzer); + SMB_Session(analyzer::Analyzer* analyzer); ~SMB_Session(); void Deliver(int is_orig, int len, const u_char* msg); - static bool any_smb_event() - { - return smb_message || - smb_com_tree_connect_andx || - smb_com_nt_create_andx || smb_com_transaction || - smb_com_transaction2 || smb_com_read_andx || - smb_com_write_andx; - } - protected: void ParseMessage(int is_orig, int cmd, binpac::SMB::SMB_header const &hdr, @@ -158,8 +151,8 @@ protected: Val* BuildTransactionVal(binpac::SMB::SMB_transaction_response const &trans); Val* BuildTransactionDataVal(binpac::SMB::SMB_transaction_data* data); - Analyzer* analyzer; - DCE_RPC_Session* dce_rpc_session; + analyzer::Analyzer* analyzer; + dce_rpc::DCE_RPC_Session* dce_rpc_session; enum IPC_named_pipe IPC_pipe; int is_IPC; int req_cmd; @@ -170,7 +163,7 @@ protected: binpac::SMB::SMB_andx* andx_[2]; }; -class Contents_SMB : public TCP_SupportAnalyzer { +class Contents_SMB : public tcp::TCP_SupportAnalyzer { public: Contents_SMB(Connection* conn, bool orig, SMB_Session* smb_session); ~Contents_SMB(); @@ -190,24 +183,20 @@ protected: int buf_len; // size off msg_buf }; -class SMB_Analyzer : public TCP_ApplicationAnalyzer { +class SMB_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: SMB_Analyzer(Connection* conn); ~SMB_Analyzer(); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new SMB_Analyzer(conn); } - static bool Available() - { - return SMB_Session::any_smb_event() || - DCE_RPC_Session::any_dce_rpc_event(); - } - protected: SMB_Session* smb_session; Contents_SMB* o_smb; Contents_SMB* r_smb; }; +} } // namespace analyzer::* + #endif diff --git a/src/SMB_COM.def b/src/analyzer/protocol/smb/SMB_COM.def similarity index 100% rename from src/SMB_COM.def rename to src/analyzer/protocol/smb/SMB_COM.def diff --git a/src/analyzer/protocol/smb/events.bif b/src/analyzer/protocol/smb/events.bif new file mode 100644 index 0000000000..74cb1feb77 --- /dev/null +++ b/src/analyzer/protocol/smb/events.bif @@ -0,0 +1,495 @@ +## Generated for all SMB/CIFS messages. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## is_orig: True if the message was sent by the originator of the underlying +## transport-level connection. +## +## cmd: A string mnemonic of the SMB command code. +## +## body_length: The length of the SMB message body, i.e. the data starting after +## the SMB header. +## +## body: The raw SMB message body, i.e., the data starting after the SMB header. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error +## smb_get_dfs_referral +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_message%(c: connection, hdr: smb_hdr, is_orig: bool, cmd: string, body_length: count, body: string%); + +## Generated for SMB/CIFS messages of type *tree connect andx*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## path: The ``path`` attribute specified in the message. +## +## service: The ``service`` attribute specified in the message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_tree_connect_andx%(c: connection, hdr: smb_hdr, path: string, service: string%); + +## Generated for SMB/CIFS messages of type *tree disconnect*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_tree_disconnect%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages of type *nt create andx*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## name: The ``name`` attribute specified in the message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_read_andx +## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_nt_create_andx%(c: connection, hdr: smb_hdr, name: string%); + +## Generated for SMB/CIFS messages of type *nt transaction*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## trans: The parsed transaction header. +## +## data: The raw transaction data. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe +## smb_com_trans_rap smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_transaction%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); + +## Generated for SMB/CIFS messages of type *nt transaction 2*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## trans: The parsed transaction header. +## +## data: The raw transaction data. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe +## smb_com_trans_rap smb_com_transaction smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_transaction2%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); + +## Generated for SMB/CIFS messages of type *transaction mailslot*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## trans: The parsed transaction header. +## +## data: The raw transaction data. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_trans_mailslot%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); + +## Generated for SMB/CIFS messages of type *transaction rap*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## trans: The parsed transaction header. +## +## data: The raw transaction data. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error +## smb_get_dfs_referral smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_trans_rap%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); + +## Generated for SMB/CIFS messages of type *transaction pipe*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## trans: The parsed transaction header. +## +## data: The raw transaction data. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_trans_pipe%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); + +## Generated for SMB/CIFS messages of type *read andx*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## data: Always empty. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_read_andx%(c: connection, hdr: smb_hdr, data: string%); + +## Generated for SMB/CIFS messages of type *read andx*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## data: Always empty. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_tree_disconnect smb_error +## smb_get_dfs_referral smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_write_andx%(c: connection, hdr: smb_hdr, data: string%); + +## Generated for SMB/CIFS messages of type *get dfs referral*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## max_referral_level: The ``max_referral_level`` attribute specified in the +## message. +## +## file_name: The ``filene_name`` attribute specified in the message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_get_dfs_referral%(c: connection, hdr: smb_hdr, max_referral_level: count, file_name: string%); + +## Generated for SMB/CIFS messages of type *negotiate*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx smb_com_setup_andx +## smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap smb_com_transaction +## smb_com_transaction2 smb_com_tree_connect_andx smb_com_tree_disconnect +## smb_com_write_andx smb_error smb_get_dfs_referral smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_negotiate%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages of type *negotiate response*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## dialect_index: The ``dialect`` indicated in the message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_nt_create_andx smb_com_read_andx smb_com_setup_andx +## smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap smb_com_transaction +## smb_com_transaction2 smb_com_tree_connect_andx smb_com_tree_disconnect +## smb_com_write_andx smb_error smb_get_dfs_referral smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_negotiate_response%(c: connection, hdr: smb_hdr, dialect_index: count%); + +## Generated for SMB/CIFS messages of type *setup andx*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_setup_andx%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages of type *generic andx*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_close smb_com_logoff_andx smb_com_negotiate +## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx +## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_generic_andx%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages of type *close*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_generic_andx smb_com_logoff_andx smb_com_negotiate +## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx +## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_close%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages of type *logoff andx*. +## +## See `Wikipedia `__ for +## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses +## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_negotiate +## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx +## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_com_logoff_andx%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages that indicate an error. This event is +## triggered by an SMB header including a status that signals an error. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## cmd: The SMB command code. +## +## cmd_str: A string mnemonic of the SMB command code. +## +## data: The raw SMB message body, i.e., the data starting after the SMB header. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx +## smb_get_dfs_referral smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to +## register a port for it or add a DPD payload signature. +event smb_error%(c: connection, hdr: smb_hdr, cmd: count, cmd_str: string, data: string%); + diff --git a/src/smb-mailslot.pac b/src/analyzer/protocol/smb/smb-mailslot.pac similarity index 100% rename from src/smb-mailslot.pac rename to src/analyzer/protocol/smb/smb-mailslot.pac diff --git a/src/smb-pipe.pac b/src/analyzer/protocol/smb/smb-pipe.pac similarity index 100% rename from src/smb-pipe.pac rename to src/analyzer/protocol/smb/smb-pipe.pac diff --git a/src/smb-protocol.pac b/src/analyzer/protocol/smb/smb-protocol.pac similarity index 100% rename from src/smb-protocol.pac rename to src/analyzer/protocol/smb/smb-protocol.pac diff --git a/src/smb.pac b/src/analyzer/protocol/smb/smb.pac similarity index 79% rename from src/smb.pac rename to src/analyzer/protocol/smb/smb.pac index 740ad47991..1fdab27d90 100644 --- a/src/smb.pac +++ b/src/analyzer/protocol/smb/smb.pac @@ -1,6 +1,10 @@ %include binpac.pac %include bro.pac +%extern{ +#include "events.bif.h" +%} + analyzer SMB withcontext { }; %include smb-protocol.pac diff --git a/src/analyzer/protocol/smtp/CMakeLists.txt b/src/analyzer/protocol/smtp/CMakeLists.txt new file mode 100644 index 0000000000..82918656a0 --- /dev/null +++ b/src/analyzer/protocol/smtp/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro SMTP) +bro_plugin_cc(SMTP.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_bif(functions.bif) +bro_plugin_end() diff --git a/src/analyzer/protocol/smtp/Plugin.cc b/src/analyzer/protocol/smtp/Plugin.cc new file mode 100644 index 0000000000..e089d7ffb1 --- /dev/null +++ b/src/analyzer/protocol/smtp/Plugin.cc @@ -0,0 +1,11 @@ + +#include "plugin/Plugin.h" + +#include "SMTP.h" + +BRO_PLUGIN_BEGIN(Bro, SMTP) + BRO_PLUGIN_DESCRIPTION("SMTP analyzer"); + BRO_PLUGIN_ANALYZER("SMTP", smtp::SMTP_Analyzer); + BRO_PLUGIN_BIF_FILE(events); + BRO_PLUGIN_BIF_FILE(functions); +BRO_PLUGIN_END diff --git a/src/SMTP.cc b/src/analyzer/protocol/smtp/SMTP.cc similarity index 96% rename from src/SMTP.cc rename to src/analyzer/protocol/smtp/SMTP.cc index 33f65ed743..b496e97c69 100644 --- a/src/SMTP.cc +++ b/src/analyzer/protocol/smtp/SMTP.cc @@ -7,8 +7,12 @@ #include "NetVar.h" #include "SMTP.h" #include "Event.h" -#include "ContentLine.h" #include "Reporter.h" +#include "analyzer/protocol/tcp/ContentLine.h" + +#include "events.bif.h" + +using namespace analyzer::smtp; #undef SMTP_CMD_DEF #define SMTP_CMD_DEF(cmd) #cmd, @@ -21,7 +25,7 @@ static const char* smtp_cmd_word[] = { SMTP_Analyzer::SMTP_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::SMTP, conn) +: tcp::TCP_ApplicationAnalyzer("SMTP", conn) { expect_sender = 0; expect_recver = 1; @@ -40,12 +44,12 @@ SMTP_Analyzer::SMTP_Analyzer(Connection* conn) line_after_gap = 0; mail = 0; UpdateState(first_cmd, 0); - ContentLine_Analyzer* cl_orig = new ContentLine_Analyzer(conn, true); + tcp::ContentLine_Analyzer* cl_orig = new tcp::ContentLine_Analyzer(conn, true); cl_orig->SetIsNULSensitive(true); cl_orig->SetSkipPartial(true); AddSupportAnalyzer(cl_orig); - ContentLine_Analyzer* cl_resp = new ContentLine_Analyzer(conn, false); + tcp::ContentLine_Analyzer* cl_resp = new tcp::ContentLine_Analyzer(conn, false); cl_resp->SetIsNULSensitive(true); cl_resp->SetSkipPartial(true); AddSupportAnalyzer(cl_resp); @@ -53,7 +57,7 @@ SMTP_Analyzer::SMTP_Analyzer(Connection* conn) void SMTP_Analyzer::ConnectionFinished(int half_finished) { - TCP_ApplicationAnalyzer::ConnectionFinished(half_finished); + tcp::TCP_ApplicationAnalyzer::ConnectionFinished(half_finished); if ( ! half_finished && mail ) EndData(); @@ -66,7 +70,7 @@ SMTP_Analyzer::~SMTP_Analyzer() void SMTP_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); if ( mail ) EndData(); @@ -74,7 +78,7 @@ void SMTP_Analyzer::Done() void SMTP_Analyzer::Undelivered(int seq, int len, bool is_orig) { - TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig); + tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig); if ( len <= 0 ) return; @@ -112,7 +116,7 @@ void SMTP_Analyzer::Undelivered(int seq, int len, bool is_orig) void SMTP_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { - TCP_ApplicationAnalyzer::DeliverStream(length, line, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(length, line, orig); // NOTE: do not use IsOrig() here, because of TURN command. int is_sender = orig_is_sender ? orig : ! orig; @@ -873,7 +877,7 @@ void SMTP_Analyzer::BeginData() delete mail; } - mail = new MIME_Mail(this); + mail = new mime::MIME_Mail(this); } void SMTP_Analyzer::EndData() diff --git a/src/SMTP.h b/src/analyzer/protocol/smtp/SMTP.h similarity index 87% rename from src/SMTP.h rename to src/analyzer/protocol/smtp/SMTP.h index 5b15dc44c0..cc12167d30 100644 --- a/src/SMTP.h +++ b/src/analyzer/protocol/smtp/SMTP.h @@ -1,18 +1,19 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef smtp_h -#define smtp_h +#ifndef ANALYZER_PROTOCOL_SMTP_SMTP_H +#define ANALYZER_PROTOCOL_SMTP_SMTP_H #include using namespace std; -#include "TCP.h" -#include "MIME.h" - +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/mime/MIME.h" #undef SMTP_CMD_DEF #define SMTP_CMD_DEF(cmd) SMTP_CMD_##cmd, +namespace analyzer { namespace smtp { + typedef enum { #include "SMTP_cmd.def" } SMTP_Cmd; @@ -35,7 +36,7 @@ typedef enum { } SMTP_State; -class SMTP_Analyzer : public TCP_ApplicationAnalyzer { +class SMTP_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: SMTP_Analyzer(Connection* conn); ~SMTP_Analyzer(); @@ -47,17 +48,11 @@ public: void SkipData() { skip_data = 1; } // skip delivery of data lines - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new SMTP_Analyzer(conn); } - static bool Available() - { - return smtp_request || smtp_reply || - smtp_data || smtp_unexpected; - } - protected: void ProcessLine(int length, const char* line, bool orig); @@ -93,7 +88,9 @@ protected: BroString* line_after_gap; // last line before the first reply // after a gap - MIME_Mail* mail; + mime::MIME_Mail* mail; }; +} } // namespace analyzer::* + #endif diff --git a/src/SMTP_cmd.def b/src/analyzer/protocol/smtp/SMTP_cmd.def similarity index 100% rename from src/SMTP_cmd.def rename to src/analyzer/protocol/smtp/SMTP_cmd.def diff --git a/src/analyzer/protocol/smtp/events.bif b/src/analyzer/protocol/smtp/events.bif new file mode 100644 index 0000000000..4a376bcbf8 --- /dev/null +++ b/src/analyzer/protocol/smtp/events.bif @@ -0,0 +1,100 @@ +## Generated for client-side SMTP commands. +## +## See `Wikipedia `__ +## for more information about the SMTP protocol. +## +## c: The connection. +## +## is_orig: True if the sender of the command is the originator of the TCP +## connection. Note that this is not redundant: the SMTP ``TURN`` command +## allows client and server to flip roles on established SMTP sessions, +## and hence a "request" might still come from the TCP-level responder. +## In practice, however, that will rarely happen as TURN is considered +## insecure and rarely used. +## +## command: The request's command, without any arguments. +## +## arg: The request command's arguments. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data +## smtp_data smtp_reply +## +## .. note:: Bro does not support the newer ETRN extension yet. +event smtp_request%(c: connection, is_orig: bool, command: string, arg: string%); + +## Generated for server-side SMTP commands. +## +## See `Wikipedia `__ +## for more information about the SMTP protocol. +## +## c: The connection. +## +## is_orig: True if the sender of the command is the originator of the TCP +## connection. Note that this is not redundant: the SMTP ``TURN`` command +## allows client and server to flip roles on established SMTP sessions, +## and hence a "reply" might still come from the TCP-level originator. In +## practice, however, that will rarely happen as TURN is considered +## insecure and rarely used. +## +## code: The reply's numerical code. +## +## cmd: TODO. +## +## msg: The reply's textual description. +## +## cont_resp: True if the reply line is tagged as being continued to the next +## line. If so, further events will be raised and a handler may want to +## reassemble the pieces before processing the response any further. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data +## smtp_data smtp_request +## +## .. note:: Bro doesn't support the newer ETRN extension yet. +event smtp_reply%(c: connection, is_orig: bool, code: count, cmd: string, msg: string, cont_resp: bool%); + +## Generated for DATA transmitted on SMTP sessions. This event is raised for +## subsequent chunks of raw data following the ``DATA`` SMTP command until the +## corresponding end marker ``.`` is seen. A handler may want to reassemble +## the pieces as they come in if stream-analysis is required. +## +## See `Wikipedia `__ +## for more information about the SMTP protocol. +## +## c: The connection. +## +## is_orig: True if the sender of the data is the originator of the TCP +## connection. +## +## data: The raw data. Note that the size of each chunk is undefined and +## depends on specifics of the underlying TCP connection. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data +## smtp_reply smtp_request skip_smtp_data +## +## .. note:: This event receives the unprocessed raw data. There is a separate +## set of ``mime_*`` events that strip out the outer MIME-layer of emails and +## provide structured access to their content. +event smtp_data%(c: connection, is_orig: bool, data: string%); + +## Generated for unexpected activity on SMTP sessions. The SMTP analyzer tracks +## the state of SMTP sessions and reports commands and other activity with this +## event that it sees even though it would not expect so at the current point +## of the communication. +## +## See `Wikipedia `__ +## for more information about the SMTP protocol. +## +## c: The connection. +## +## is_orig: True if the sender of the unexpected activity is the originator of +## the TCP connection. +## +## msg: A descriptive message of what was unexpected. +## +## detail: The actual SMTP line triggering the event. +## +## .. bro:see:: smtp_data smtp_request smtp_reply +event smtp_unexpected%(c: connection, is_orig: bool, msg: string, detail: string%); diff --git a/src/analyzer/protocol/smtp/functions.bif b/src/analyzer/protocol/smtp/functions.bif new file mode 100644 index 0000000000..8630685096 --- /dev/null +++ b/src/analyzer/protocol/smtp/functions.bif @@ -0,0 +1,17 @@ + +%%{ +#include "analyzer/protocol/smtp/SMTP.h" +%%} + +## Skips SMTP data until the next email in a connection. +## +## c: The SMTP connection. +## +## .. bro:see:: skip_http_entity_data +function skip_smtp_data%(c: connection%): any + %{ + analyzer::Analyzer* sa = c->FindAnalyzer("SMTP"); + if ( sa ) + static_cast(sa)->SkipData(); + return 0; + %} diff --git a/src/analyzer/protocol/socks/CMakeLists.txt b/src/analyzer/protocol/socks/CMakeLists.txt new file mode 100644 index 0000000000..5157c8d368 --- /dev/null +++ b/src/analyzer/protocol/socks/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro SOCKS) +bro_plugin_cc(SOCKS.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(socks.pac socks-protocol.pac socks-analyzer.pac) +bro_plugin_end() diff --git a/src/analyzer/protocol/socks/Plugin.cc b/src/analyzer/protocol/socks/Plugin.cc new file mode 100644 index 0000000000..d01f4520b7 --- /dev/null +++ b/src/analyzer/protocol/socks/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "SOCKS.h" + +BRO_PLUGIN_BEGIN(Bro, SOCKS) + BRO_PLUGIN_DESCRIPTION("SOCKS analyzer"); + BRO_PLUGIN_ANALYZER("SOCKS", socks::SOCKS_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/SOCKS.cc b/src/analyzer/protocol/socks/SOCKS.cc similarity index 77% rename from src/SOCKS.cc rename to src/analyzer/protocol/socks/SOCKS.cc index 4a6eda7043..f9d81b8a16 100644 --- a/src/SOCKS.cc +++ b/src/analyzer/protocol/socks/SOCKS.cc @@ -1,9 +1,13 @@ #include "SOCKS.h" #include "socks_pac.h" -#include "TCP_Reassembler.h" +#include "analyzer/protocol/tcp/TCP_Reassembler.h" + +#include "events.bif.h" + +using namespace analyzer::socks; SOCKS_Analyzer::SOCKS_Analyzer(Connection* conn) -: TCP_ApplicationAnalyzer(AnalyzerTag::SOCKS, conn) +: tcp::TCP_ApplicationAnalyzer("SOCKS", conn) { interp = new binpac::SOCKS::SOCKS_Conn(this); orig_done = resp_done = false; @@ -25,7 +29,7 @@ void SOCKS_Analyzer::EndpointDone(bool orig) void SOCKS_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); interp->FlowEOF(true); interp->FlowEOF(false); @@ -33,13 +37,13 @@ void SOCKS_Analyzer::Done() void SOCKS_Analyzer::EndpointEOF(bool is_orig) { - TCP_ApplicationAnalyzer::EndpointEOF(is_orig); + tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig); interp->FlowEOF(is_orig); } void SOCKS_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { - TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); assert(TCP()); @@ -57,7 +61,7 @@ void SOCKS_Analyzer::DeliverStream(int len, const u_char* data, bool orig) if ( ! pia ) { - pia = new PIA_TCP(Conn()); + pia = new pia::PIA_TCP(Conn()); AddChildAnalyzer(pia); pia->FirstPacket(true, 0); pia->FirstPacket(false, 0); @@ -80,7 +84,7 @@ void SOCKS_Analyzer::DeliverStream(int len, const u_char* data, bool orig) void SOCKS_Analyzer::Undelivered(int seq, int len, bool orig) { - TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); + tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); interp->NewGap(orig, len); } diff --git a/src/SOCKS.h b/src/analyzer/protocol/socks/SOCKS.h similarity index 58% rename from src/SOCKS.h rename to src/analyzer/protocol/socks/SOCKS.h index 9753abb660..f005967fd8 100644 --- a/src/SOCKS.h +++ b/src/analyzer/protocol/socks/SOCKS.h @@ -1,10 +1,10 @@ -#ifndef socks_h -#define socks_h +#ifndef ANALYZER_PROTOCOL_SOCKS_SOCKS_H +#define ANALYZER_PROTOCOL_SOCKS_SOCKS_H // SOCKS v4 analyzer. -#include "TCP.h" -#include "PIA.h" +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/pia/PIA.h" namespace binpac { namespace SOCKS { @@ -12,8 +12,9 @@ namespace binpac { } } +namespace analyzer { namespace socks { -class SOCKS_Analyzer : public TCP_ApplicationAnalyzer { +class SOCKS_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: SOCKS_Analyzer(Connection* conn); ~SOCKS_Analyzer(); @@ -25,21 +26,18 @@ public: virtual void Undelivered(int seq, int len, bool orig); virtual void EndpointEOF(bool is_orig); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new SOCKS_Analyzer(conn); } - static bool Available() - { - return socks_request || socks_reply; - } - protected: bool orig_done; bool resp_done; - PIA_TCP *pia; + pia::PIA_TCP *pia; binpac::SOCKS::SOCKS_Conn* interp; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/socks/events.bif b/src/analyzer/protocol/socks/events.bif new file mode 100644 index 0000000000..4f1f8ad1cd --- /dev/null +++ b/src/analyzer/protocol/socks/events.bif @@ -0,0 +1,29 @@ +## Generated when a SOCKS request is analyzed. +## +## c: The parent connection of the proxy. +## +## version: The version of SOCKS this message used. +## +## request_type: The type of the request. +## +## sa: Address that the tunneled traffic should be sent to. +## +## p: The destination port for the proxied traffic. +## +## user: Username given for the SOCKS connection. This is not yet implemented +## for SOCKSv5. +event socks_request%(c: connection, version: count, request_type: count, sa: SOCKS::Address, p: port, user: string%); + +## Generated when a SOCKS reply is analyzed. +## +## c: The parent connection of the proxy. +## +## version: The version of SOCKS this message used. +## +## reply: The status reply from the server. +## +## sa: The address that the server sent the traffic to. +## +## p: The destination port for the proxied traffic. +event socks_reply%(c: connection, version: count, reply: count, sa: SOCKS::Address, p: port%); + diff --git a/src/socks-analyzer.pac b/src/analyzer/protocol/socks/socks-analyzer.pac similarity index 93% rename from src/socks-analyzer.pac rename to src/analyzer/protocol/socks/socks-analyzer.pac index 7ce364670b..80051f0b27 100644 --- a/src/socks-analyzer.pac +++ b/src/analyzer/protocol/socks/socks-analyzer.pac @@ -35,7 +35,7 @@ refine connection SOCKS_Conn += { new PortVal(${request.port} | TCP_PORT_MASK), array_to_string(${request.user})); - static_cast(bro_analyzer())->EndpointDone(true); + static_cast(bro_analyzer())->EndpointDone(true); return true; %} @@ -53,7 +53,7 @@ refine connection SOCKS_Conn += { new PortVal(${reply.port} | TCP_PORT_MASK)); bro_analyzer()->ProtocolConfirmation(); - static_cast(bro_analyzer())->EndpointDone(false); + static_cast(bro_analyzer())->EndpointDone(false); return true; %} @@ -97,7 +97,7 @@ refine connection SOCKS_Conn += { new PortVal(${request.port} | TCP_PORT_MASK), new StringVal("")); - static_cast(bro_analyzer())->EndpointDone(true); + static_cast(bro_analyzer())->EndpointDone(true); return true; %} @@ -136,7 +136,7 @@ refine connection SOCKS_Conn += { new PortVal(${reply.port} | TCP_PORT_MASK)); bro_analyzer()->ProtocolConfirmation(); - static_cast(bro_analyzer())->EndpointDone(false); + static_cast(bro_analyzer())->EndpointDone(false); return true; %} diff --git a/src/socks-protocol.pac b/src/analyzer/protocol/socks/socks-protocol.pac similarity index 100% rename from src/socks-protocol.pac rename to src/analyzer/protocol/socks/socks-protocol.pac diff --git a/src/socks.pac b/src/analyzer/protocol/socks/socks.pac similarity index 88% rename from src/socks.pac rename to src/analyzer/protocol/socks/socks.pac index 15d3580674..a9c4099508 100644 --- a/src/socks.pac +++ b/src/analyzer/protocol/socks/socks.pac @@ -3,6 +3,8 @@ %extern{ #include "SOCKS.h" + +#include "events.bif.h" %} analyzer SOCKS withcontext { @@ -21,4 +23,4 @@ flow SOCKS_Flow(is_orig: bool) { datagram = SOCKS_Version(is_orig) withcontext(connection, this); }; -%include socks-analyzer.pac \ No newline at end of file +%include socks-analyzer.pac diff --git a/src/analyzer/protocol/ssh/CMakeLists.txt b/src/analyzer/protocol/ssh/CMakeLists.txt new file mode 100644 index 0000000000..505c89332e --- /dev/null +++ b/src/analyzer/protocol/ssh/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro SSH) +bro_plugin_cc(SSH.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/analyzer/protocol/ssh/Plugin.cc b/src/analyzer/protocol/ssh/Plugin.cc new file mode 100644 index 0000000000..53a0294a88 --- /dev/null +++ b/src/analyzer/protocol/ssh/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "SSH.h" + +BRO_PLUGIN_BEGIN(Bro, SSH) + BRO_PLUGIN_DESCRIPTION("SSH analyzer"); + BRO_PLUGIN_ANALYZER("SSH", ssh::SSH_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/SSH.cc b/src/analyzer/protocol/ssh/SSH.cc similarity index 84% rename from src/SSH.cc rename to src/analyzer/protocol/ssh/SSH.cc index 3a8f468ae4..ab3f6a5e5b 100644 --- a/src/SSH.cc +++ b/src/analyzer/protocol/ssh/SSH.cc @@ -7,17 +7,21 @@ #include "NetVar.h" #include "SSH.h" #include "Event.h" -#include "ContentLine.h" +#include "analyzer/protocol/tcp/ContentLine.h" + +#include "events.bif.h" + +using namespace analyzer::ssh; SSH_Analyzer::SSH_Analyzer(Connection* c) -: TCP_ApplicationAnalyzer(AnalyzerTag::SSH, c) +: tcp::TCP_ApplicationAnalyzer("SSH", c) { - orig = new ContentLine_Analyzer(c, true); + orig = new tcp::ContentLine_Analyzer(c, true); orig->SetSkipPartial(true); orig->SetCRLFAsEOL(LF_as_EOL); AddSupportAnalyzer(orig); - resp = new ContentLine_Analyzer(c, false); + resp = new tcp::ContentLine_Analyzer(c, false); resp->SetSkipPartial(true); resp->SetCRLFAsEOL(LF_as_EOL); AddSupportAnalyzer(resp); @@ -25,7 +29,7 @@ SSH_Analyzer::SSH_Analyzer(Connection* c) void SSH_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig) { - TCP_ApplicationAnalyzer::DeliverStream(length, data, is_orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(length, data, is_orig); // We're all done processing this endpoint - flag it as such, // before we even determine whether we have any event generation @@ -38,7 +42,7 @@ void SSH_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig) if ( TCP() ) { // Don't try to parse version if there has already been a gap. - TCP_Endpoint* endp = is_orig ? TCP()->Orig() : TCP()->Resp(); + tcp::TCP_Endpoint* endp = is_orig ? TCP()->Orig() : TCP()->Resp(); if ( endp->HadGap() ) return; } diff --git a/src/analyzer/protocol/ssh/SSH.h b/src/analyzer/protocol/ssh/SSH.h new file mode 100644 index 0000000000..3878881693 --- /dev/null +++ b/src/analyzer/protocol/ssh/SSH.h @@ -0,0 +1,27 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef ANALYZER_PROTOCOL_SSH_SSH_H +#define ANALYZER_PROTOCOL_SSH_SSH_H + +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/tcp/ContentLine.h" + +namespace analyzer { namespace ssh { + +class SSH_Analyzer : public tcp::TCP_ApplicationAnalyzer { +public: + SSH_Analyzer(Connection* conn); + + virtual void DeliverStream(int len, const u_char* data, bool orig); + + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) + { return new SSH_Analyzer(conn); } + +private: + tcp::ContentLine_Analyzer* orig; + tcp::ContentLine_Analyzer* resp; +}; + +} } // namespace analyzer::* + +#endif diff --git a/src/analyzer/protocol/ssh/events.bif b/src/analyzer/protocol/ssh/events.bif new file mode 100644 index 0000000000..9d73f5e483 --- /dev/null +++ b/src/analyzer/protocol/ssh/events.bif @@ -0,0 +1,38 @@ +## Generated when seeing an SSH client's version identification. The SSH +## protocol starts with a clear-text handshake message that reports client and +## server protocol/software versions. This event provides access to what the +## client sent. +## +## +## See `Wikipedia `__ for more +## information about the SSH protocol. +## +## c: The connection. +## +## version: The version string the client sent (e.g., `SSH-2.0-libssh-0.11`). +## +## .. bro:see:: ssh_server_version +## +## .. note:: As everything after the initial version handshake proceeds +## encrypted, Bro cannot further analyze SSH sessions. +event ssh_client_version%(c: connection, version: string%); + +## Generated when seeing an SSH server's version identification. The SSH +## protocol starts with a clear-text handshake message that reports client and +## server protocol/software versions. This event provides access to what the +## server sent. +## +## See `Wikipedia `__ for more +## information about the SSH protocol. +## +## c: The connection. +## +## version: The version string the server sent (e.g., +## ``SSH-1.99-OpenSSH_3.9p1``). +## +## .. bro:see:: ssh_client_version +## +## .. note:: As everything coming after the initial version handshake proceeds +## encrypted, Bro cannot further analyze SSH sessions. +event ssh_server_version%(c: connection, version: string%); + diff --git a/src/analyzer/protocol/ssl/CMakeLists.txt b/src/analyzer/protocol/ssl/CMakeLists.txt new file mode 100644 index 0000000000..f1838e5f3b --- /dev/null +++ b/src/analyzer/protocol/ssl/CMakeLists.txt @@ -0,0 +1,11 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro SSL) +bro_plugin_cc(SSL.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_bif(functions.bif) +bro_plugin_pac(ssl.pac ssl-analyzer.pac ssl-protocol.pac ssl-defs.pac) +bro_plugin_end() diff --git a/src/analyzer/protocol/ssl/Plugin.cc b/src/analyzer/protocol/ssl/Plugin.cc new file mode 100644 index 0000000000..c63be864f8 --- /dev/null +++ b/src/analyzer/protocol/ssl/Plugin.cc @@ -0,0 +1,11 @@ + +#include "plugin/Plugin.h" + +#include "SSL.h" + +BRO_PLUGIN_BEGIN(Bro, SSL) + BRO_PLUGIN_DESCRIPTION("SSL analyzer"); + BRO_PLUGIN_ANALYZER("SSL", ssl::SSL_Analyzer); + BRO_PLUGIN_BIF_FILE(events); + BRO_PLUGIN_BIF_FILE(functions); +BRO_PLUGIN_END diff --git a/src/SSL.cc b/src/analyzer/protocol/ssl/SSL.cc similarity index 72% rename from src/SSL.cc rename to src/analyzer/protocol/ssl/SSL.cc index 4658bbbc16..6cd2fa59f8 100644 --- a/src/SSL.cc +++ b/src/analyzer/protocol/ssl/SSL.cc @@ -1,10 +1,15 @@ + #include "SSL.h" -#include "TCP_Reassembler.h" +#include "analyzer/protocol/tcp/TCP_Reassembler.h" #include "Reporter.h" #include "util.h" +#include "events.bif.h" + +using namespace analyzer::ssl; + SSL_Analyzer::SSL_Analyzer(Connection* c) -: TCP_ApplicationAnalyzer(AnalyzerTag::SSL, c) +: tcp::TCP_ApplicationAnalyzer("SSL", c) { interp = new binpac::SSL::SSL_Conn(this); had_gap = false; @@ -17,7 +22,7 @@ SSL_Analyzer::~SSL_Analyzer() void SSL_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); interp->FlowEOF(true); interp->FlowEOF(false); @@ -25,13 +30,13 @@ void SSL_Analyzer::Done() void SSL_Analyzer::EndpointEOF(bool is_orig) { - TCP_ApplicationAnalyzer::EndpointEOF(is_orig); + tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig); interp->FlowEOF(is_orig); } void SSL_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { - TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); assert(TCP()); if ( TCP()->IsPartial() ) @@ -54,7 +59,7 @@ void SSL_Analyzer::DeliverStream(int len, const u_char* data, bool orig) void SSL_Analyzer::Undelivered(int seq, int len, bool orig) { - TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); + tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); had_gap = true; interp->NewGap(orig, len); } diff --git a/src/SSL.h b/src/analyzer/protocol/ssl/SSL.h similarity index 61% rename from src/SSL.h rename to src/analyzer/protocol/ssl/SSL.h index d0ef164877..6423d1b155 100644 --- a/src/SSL.h +++ b/src/analyzer/protocol/ssl/SSL.h @@ -1,10 +1,14 @@ -#ifndef ssl_h -#define ssl_h +#ifndef ANALYZER_PROTOCOL_SSL_SSL_H +#define ANALYZER_PROTOCOL_SSL_SSL_H -#include "TCP.h" +#include "events.bif.h" + +#include "analyzer/protocol/tcp/TCP.h" #include "ssl_pac.h" -class SSL_Analyzer : public TCP_ApplicationAnalyzer { +namespace analyzer { namespace ssl { + +class SSL_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: SSL_Analyzer(Connection* conn); virtual ~SSL_Analyzer(); @@ -14,10 +18,10 @@ public: virtual void DeliverStream(int len, const u_char* data, bool orig); virtual void Undelivered(int seq, int len, bool orig); - // Overriden from TCP_ApplicationAnalyzer. + // Overriden from tcp::TCP_ApplicationAnalyzer. virtual void EndpointEOF(bool is_orig); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new SSL_Analyzer(conn); } static bool Available() @@ -33,4 +37,6 @@ protected: }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/ssl/events.bif b/src/analyzer/protocol/ssl/events.bif new file mode 100644 index 0000000000..3d0c7e9d6a --- /dev/null +++ b/src/analyzer/protocol/ssl/events.bif @@ -0,0 +1,195 @@ +## Generated for an SSL/TLS client's initial *hello* message. SSL/TLS sessions +## start with an unencrypted handshake, and Bro extracts as much information out +## of that as it can. This event provides access to the initial information +## sent by the client. +## +## See `Wikipedia `__ for +## more information about the SSL/TLS protocol. +## +## c: The connection. +## +## version: The protocol version as extracted from the client's message. The +## values are standardized as part of the SSL/TLS protocol. The +## :bro:id:`SSL::version_strings` table maps them to descriptive names. +## +## possible_ts: The current time as sent by the client. Note that SSL/TLS does +## not require clocks to be set correctly, so treat with care. +## +## session_id: The session ID sent by the client (if any). +## +## ciphers: The list of ciphers the client offered to use. The values are +## standardized as part of the SSL/TLS protocol. The +## :bro:id:`SSL::cipher_desc` table maps them to descriptive names. +## +## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello +## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%); + +## Generated for an SSL/TLS server's initial *hello* message. SSL/TLS sessions +## start with an unencrypted handshake, and Bro extracts as much information out +## of that as it can. This event provides access to the initial information +## sent by the client. +## +## See `Wikipedia `__ for +## more information about the SSL/TLS protocol. +## +## c: The connection. +## +## version: The protocol version as extracted from the server's message. +## The values are standardized as part of the SSL/TLS protocol. The +## :bro:id:`SSL::version_strings` table maps them to descriptive names. +## +## possible_ts: The current time as sent by the server. Note that SSL/TLS does +## not require clocks to be set correctly, so treat with care. +## +## session_id: The session ID as sent back by the server (if any). +## +## cipher: The cipher chosen by the server. The values are standardized as part +## of the SSL/TLS protocol. The :bro:id:`SSL::cipher_desc` table maps +## them to descriptive names. +## +## comp_method: The compression method chosen by the client. The values are +## standardized as part of the SSL/TLS protocol. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension +## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%); + +## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS +## sessions start with an unencrypted handshake, and Bro extracts as much +## information out of that as it can. This event provides access to any +## extensions either side sends as part of an extended *hello* message. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## code: The numerical code of the extension. The values are standardized as +## part of the SSL/TLS protocol. The :bro:id:`SSL::extensions` table maps +## them to descriptive names. +## +## val: The raw extension value that was sent in the message. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello +## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%); + +## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with +## an unencrypted handshake, and Bro extracts as much information out of that +## as it can. This event signals the time when an SSL/TLS has finished the +## handshake and its endpoints consider it as fully established. Typically, +## everything from now on will be encrypted. +## +## See `Wikipedia `__ for +## more information about the SSL/TLS protocol. +## +## c: The connection. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello +## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +event ssl_established%(c: connection%); + +## Generated for SSL/TLS alert records. SSL/TLS sessions start with an +## unencrypted handshake, and Bro extracts as much information out of that as +## it can. If during that handshake, an endpoint encounters a fatal error, it +## sends an *alert* record, that in turn triggers this event. After an *alert*, +## any endpoint may close the connection immediately. +## +## See `Wikipedia `__ for +## more information about the SSL/TLS protocol. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## level: The severity level, as sent in the *alert*. The values are defined as +## part of the SSL/TLS protocol. +## +## desc: A numerical value identifying the cause of the *alert*. The values are +## defined as part of the SSL/TLS protocol. +## +## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello +## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%); + +## Generated for SSL/TLS handshake messages that are a part of the +## stateless-server session resumption mechanism. SSL/TLS sessions start with +## an unencrypted handshake, and Bro extracts as much information out of that +## as it can. This event is raised when an SSL/TLS server passes a session +## ticket to the client that can later be used for resuming the session. The +## mechanism is described in :rfc:`4507` +## +## See `Wikipedia `__ for +## more information about the SSL/TLS protocol. +## +## c: The connection. +## +## ticket_lifetime_hint: A hint from the server about how long the ticket +## should be stored by the client. +## +## ticket: The raw ticket data. +## +## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello +## x509_certificate x509_error x509_extension ssl_alert +event ssl_session_ticket_handshake%(c: connection, ticket_lifetime_hint: count, ticket: string%); + +## Generated for X509 certificates seen in SSL/TLS connections. During the +## initial SSL/TLS handshake, certificates are exchanged in the clear. Bro +## raises this event for each certificate seen (including both a site's primary +## cert, and further certs sent as part of the validation chain). +## +## See `Wikipedia `__ for more information +## about the X.509 format. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## cert: The parsed certificate. +## +## chain_idx: The index in the validation chain that this cert has. Index zero +## indicates an endpoint's primary cert, while higher indices +## indicate the place in the validation chain (which has length +## *chain_len*). +## +## chain_len: The total length of the validation chain that this cert is part +## of. +## +## der_cert: The complete cert encoded in `DER +## `__ +## format. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension +## ssl_server_hello x509_error x509_extension x509_verify +event x509_certificate%(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string%); + +## Generated for X509 extensions seen in a certificate. +## +## See `Wikipedia `__ for more information +## about the X.509 format. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## data: The raw data associated with the extension. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension +## ssl_server_hello x509_certificate x509_error x509_verify +event x509_extension%(c: connection, is_orig: bool, data: string%); + +## Generated when errors occur during parsing an X509 certificate. +## +## See `Wikipedia `__ for more information +## about the X.509 format. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## err: An error code describing what went wrong. :bro:id:`SSL::x509_errors` +## maps error codes to a textual description. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension +## ssl_server_hello x509_certificate x509_extension x509_err2str x509_verify +event x509_error%(c: connection, is_orig: bool, err: count%); diff --git a/src/analyzer/protocol/ssl/functions.bif b/src/analyzer/protocol/ssl/functions.bif new file mode 100644 index 0000000000..f2d4861007 --- /dev/null +++ b/src/analyzer/protocol/ssl/functions.bif @@ -0,0 +1,132 @@ + +%%{ +#include +#include +#include + +// This is the indexed map of X509 certificate stores. +static map x509_stores; + +// ### NOTE: while d2i_X509 does not take a const u_char** pointer, +// here we assume d2i_X509 does not write to , so it is safe to +// convert data to a non-const pointer. Could some X509 guru verify +// this? + +X509* d2i_X509_(X509** px, const u_char** in, int len) + { +#ifdef OPENSSL_D2I_X509_USES_CONST_CHAR + return d2i_X509(px, in, len); +#else + return d2i_X509(px, (u_char**)in, len); +#endif + } + +%%} + + +## Verifies a certificate. +## +## der_cert: The X.509 certificate in DER format. +## +## cert_stack: Specifies a certificate chain to validate against, with index 0 +## typically being the root CA. Bro uses the Mozilla root CA list +## by default. +## +## root_certs: A list of additional root certificates that extends +## *cert_stack*. +## +## Returns: A status code of the verification which can be converted into an +## ASCII string via :bro:id:`x509_err2str`. +## +## .. bro:see:: x509_err2str +function x509_verify%(der_cert: string, cert_stack: string_vec, root_certs: table_string_of_string%): count + %{ + X509_STORE* ctx = 0; + int i = 0; + + // If this certificate store was built previously, just reuse the old one. + if ( x509_stores.count(root_certs) > 0 ) + ctx = x509_stores[root_certs]; + + if ( ! ctx ) // lookup to see if we have this one built already! + { + ctx = X509_STORE_new(); + TableVal* root_certs2 = root_certs->AsTableVal(); + ListVal* idxs = root_certs2->ConvertToPureList(); + + // Build the validation store + for ( i = 0; i < idxs->Length(); ++i ) + { + Val* key = idxs->Index(i); + StringVal *sv = root_certs2->Lookup(key)->AsStringVal(); + const uint8* data = sv->Bytes(); + X509* x = d2i_X509_(NULL, &data, sv->Len()); + if ( ! x ) + { + builtin_error(fmt("Root CA error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); + return new Val((uint64) ERR_get_error(), TYPE_COUNT); + } + X509_STORE_add_cert(ctx, x); + } + delete idxs; + + // Save the newly constructed certificate store into the cacheing map. + x509_stores[root_certs] = ctx; + } + + const uint8 *cert_data = der_cert->Bytes(); + X509* cert = d2i_X509_(NULL, &cert_data, der_cert->Len()); + if ( ! cert ) + { + builtin_error(fmt("Certificate error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); + return new Val((uint64) ERR_get_error(), TYPE_COUNT); + } + + STACK_OF(X509)* untrusted_certs = sk_X509_new_null(); + if ( ! untrusted_certs ) + { + builtin_error(fmt("Untrusted certificate stack initialization error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); + return new Val((uint64) ERR_get_error(), TYPE_COUNT); + } + + VectorVal *cert_stack_vec = cert_stack->AsVectorVal(); + for ( i = 0; i < (int) cert_stack_vec->Size(); ++i ) + { + StringVal *sv = cert_stack_vec->Lookup(i)->AsStringVal(); + const uint8 *data = sv->Bytes(); + X509* x = d2i_X509_(NULL, &data, sv->Len()); + if ( ! x ) + { + X509_free(cert); + sk_X509_pop_free(untrusted_certs, X509_free); + builtin_error(fmt("Untrusted certificate stack creation error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); + return new Val((uint64) ERR_get_error(), TYPE_COUNT); + } + sk_X509_push(untrusted_certs, x); + } + + X509_STORE_CTX csc; + X509_STORE_CTX_init(&csc, ctx, cert, untrusted_certs); + X509_STORE_CTX_set_time(&csc, 0, (time_t) network_time); + + int result = X509_verify_cert(&csc); + X509_STORE_CTX_cleanup(&csc); + + if ( untrusted_certs ) + sk_X509_pop_free(untrusted_certs, X509_free); + X509_free(cert); + + return new Val((uint64) csc.error, TYPE_COUNT); + %} + +## Converts a certificate verification error code into an ASCII string. +## +## err_num: The error code. +## +## Returns: A string representation of *err_num*. +## +## .. bro:see:: x509_verify +function x509_err2str%(err_num: count%): string + %{ + return new StringVal(X509_verify_cert_error_string(err_num)); + %} diff --git a/src/ssl-analyzer.pac b/src/analyzer/protocol/ssl/ssl-analyzer.pac similarity index 100% rename from src/ssl-analyzer.pac rename to src/analyzer/protocol/ssl/ssl-analyzer.pac diff --git a/src/ssl-defs.pac b/src/analyzer/protocol/ssl/ssl-defs.pac similarity index 95% rename from src/ssl-defs.pac rename to src/analyzer/protocol/ssl/ssl-defs.pac index 4f715bbddd..c35fc56e85 100644 --- a/src/ssl-defs.pac +++ b/src/analyzer/protocol/ssl/ssl-defs.pac @@ -3,6 +3,8 @@ %extern{ #include using std::string; + +#include "events.bif.h" %} enum ContentType { diff --git a/src/ssl-protocol.pac b/src/analyzer/protocol/ssl/ssl-protocol.pac similarity index 100% rename from src/ssl-protocol.pac rename to src/analyzer/protocol/ssl/ssl-protocol.pac diff --git a/src/ssl.pac b/src/analyzer/protocol/ssl/ssl.pac similarity index 94% rename from src/ssl.pac rename to src/analyzer/protocol/ssl/ssl.pac index 25aed7a66f..4a32227088 100644 --- a/src/ssl.pac +++ b/src/analyzer/protocol/ssl/ssl.pac @@ -8,6 +8,10 @@ %include binpac.pac %include bro.pac +%extern{ +#include "events.bif.h" +%} + analyzer SSL withcontext { connection: SSL_Conn; flow: SSL_Flow; diff --git a/src/analyzer/protocol/stepping-stone/CMakeLists.txt b/src/analyzer/protocol/stepping-stone/CMakeLists.txt new file mode 100644 index 0000000000..042f5bc858 --- /dev/null +++ b/src/analyzer/protocol/stepping-stone/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro SteppingStone) +bro_plugin_cc(SteppingStone.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/analyzer/protocol/stepping-stone/Plugin.cc b/src/analyzer/protocol/stepping-stone/Plugin.cc new file mode 100644 index 0000000000..129b95fb25 --- /dev/null +++ b/src/analyzer/protocol/stepping-stone/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "SteppingStone.h" + +BRO_PLUGIN_BEGIN(Bro, SteppingStone) + BRO_PLUGIN_DESCRIPTION("Stepping stone analyzer (deprecated)"); + BRO_PLUGIN_ANALYZER("SteppingStone", stepping_stone::SteppingStone_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/SteppingStone.cc b/src/analyzer/protocol/stepping-stone/SteppingStone.cc similarity index 90% rename from src/SteppingStone.cc rename to src/analyzer/protocol/stepping-stone/SteppingStone.cc index 32850d82c6..09a7444213 100644 --- a/src/SteppingStone.cc +++ b/src/analyzer/protocol/stepping-stone/SteppingStone.cc @@ -7,11 +7,15 @@ #include "Event.h" #include "Net.h" #include "NetVar.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #include "SteppingStone.h" #include "util.h" -SteppingStoneEndpoint::SteppingStoneEndpoint(TCP_Endpoint* e, SteppingStoneManager* m) +#include "events.bif.h" + +using namespace analyzer::stepping_stone; + +SteppingStoneEndpoint::SteppingStoneEndpoint(tcp::TCP_Endpoint* e, SteppingStoneManager* m) { endp = e; stp_max_top_seq = 0; @@ -157,7 +161,7 @@ void SteppingStoneEndpoint::CreateEndpEvent(int is_orig) } SteppingStone_Analyzer::SteppingStone_Analyzer(Connection* c) -: TCP_ApplicationAnalyzer(AnalyzerTag::SteppingStone, c) +: tcp::TCP_ApplicationAnalyzer("STEPPINGSTONE", c) { stp_manager = sessions->GetSTPManager(); @@ -167,7 +171,7 @@ SteppingStone_Analyzer::SteppingStone_Analyzer(Connection* c) void SteppingStone_Analyzer::Init() { - TCP_ApplicationAnalyzer::Init(); + tcp::TCP_ApplicationAnalyzer::Init(); assert(TCP()); orig_endp = new SteppingStoneEndpoint(TCP()->Orig(), stp_manager); @@ -178,7 +182,7 @@ void SteppingStone_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen) { - TCP_ApplicationAnalyzer::DeliverPacket(len, data, is_orig, seq, + tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); if ( is_orig ) @@ -190,7 +194,7 @@ void SteppingStone_Analyzer::DeliverPacket(int len, const u_char* data, void SteppingStone_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig) { - TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig); + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, is_orig); if ( is_orig ) { @@ -209,7 +213,7 @@ void SteppingStone_Analyzer::DeliverStream(int len, const u_char* data, void SteppingStone_Analyzer::Done() { - TCP_ApplicationAnalyzer::Done(); + tcp::TCP_ApplicationAnalyzer::Done(); orig_endp->Done(); resp_endp->Done(); diff --git a/src/SteppingStone.h b/src/analyzer/protocol/stepping-stone/SteppingStone.h similarity index 82% rename from src/SteppingStone.h rename to src/analyzer/protocol/stepping-stone/SteppingStone.h index a47b268c83..1471c08a3b 100644 --- a/src/SteppingStone.h +++ b/src/analyzer/protocol/stepping-stone/SteppingStone.h @@ -1,13 +1,15 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef steppingstone_h -#define steppingstone_h +#ifndef ANALYZER_PROTOCOL_STEPPING_STONE_STEPPINGSTONE_H +#define ANALYZER_PROTOCOL_STEPPING_STONE_STEPPINGSTONE_H #include "Queue.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" class NetSessions; +namespace analyzer { namespace stepping_stone { + class SteppingStoneEndpoint; class SteppingStoneManager; @@ -16,7 +18,7 @@ declare(PDict,SteppingStoneEndpoint); class SteppingStoneEndpoint : public BroObj { public: - SteppingStoneEndpoint(TCP_Endpoint* e, SteppingStoneManager* m); + SteppingStoneEndpoint(tcp::TCP_Endpoint* e, SteppingStoneManager* m); ~SteppingStoneEndpoint(); void Done(); @@ -27,7 +29,7 @@ protected: void Event(EventHandlerPtr f, int id1, int id2 = -1); void CreateEndpEvent(int is_orig); - TCP_Endpoint* endp; + tcp::TCP_Endpoint* endp; int stp_max_top_seq; double stp_last_time; double stp_resume_time; @@ -43,7 +45,7 @@ protected: PDict(SteppingStoneEndpoint) stp_outbound_endps; }; -class SteppingStone_Analyzer : public TCP_ApplicationAnalyzer { +class SteppingStone_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: SteppingStone_Analyzer(Connection* c); virtual ~SteppingStone_Analyzer() {}; @@ -51,11 +53,9 @@ public: virtual void Init(); virtual void Done(); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new SteppingStone_Analyzer(conn); } - static bool Available() { return stp_correlate_pair; } - protected: // We support both packet and stream input and can be put in place even // if the TCP analyzer is not yet reassebmling. @@ -87,4 +87,6 @@ protected: int endp_cnt; }; +} } // namespace analyzer::* + #endif /* steppingstone_h */ diff --git a/src/analyzer/protocol/stepping-stone/events.bif b/src/analyzer/protocol/stepping-stone/events.bif new file mode 100644 index 0000000000..8d578eba64 --- /dev/null +++ b/src/analyzer/protocol/stepping-stone/events.bif @@ -0,0 +1,17 @@ +## Deprecated. Will be removed. +event stp_create_endp%(c: connection, e: int, is_orig: bool%); + +# ##### Internal events. Not further documented. + +## Event internal to the stepping stone detector. +event stp_resume_endp%(e: int%); + +## Event internal to the stepping stone detector. +event stp_correlate_pair%(e1: int, e2: int%); + +## Event internal to the stepping stone detector. +event stp_remove_pair%(e1: int, e2: int%); + +## Event internal to the stepping stone detector. +event stp_remove_endp%(e: int%); + diff --git a/src/analyzer/protocol/syslog/CMakeLists.txt b/src/analyzer/protocol/syslog/CMakeLists.txt new file mode 100644 index 0000000000..5366f94642 --- /dev/null +++ b/src/analyzer/protocol/syslog/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro Syslog) +bro_plugin_cc(Syslog.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_pac(syslog.pac syslog-analyzer.pac syslog-protocol.pac) +bro_plugin_end() diff --git a/src/analyzer/protocol/syslog/Plugin.cc b/src/analyzer/protocol/syslog/Plugin.cc new file mode 100644 index 0000000000..67abaaf970 --- /dev/null +++ b/src/analyzer/protocol/syslog/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "Syslog.h" + +BRO_PLUGIN_BEGIN(Bro, Syslog) + BRO_PLUGIN_DESCRIPTION("Syslog analyzer (UDP-only currently)"); + BRO_PLUGIN_ANALYZER("Syslog", syslog::Syslog_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/Syslog-binpac.cc b/src/analyzer/protocol/syslog/Syslog.cc similarity index 50% rename from src/Syslog-binpac.cc rename to src/analyzer/protocol/syslog/Syslog.cc index c8697d0f3f..2b783afc64 100644 --- a/src/Syslog-binpac.cc +++ b/src/analyzer/protocol/syslog/Syslog.cc @@ -1,21 +1,26 @@ -#include "Syslog-binpac.h" -#include "TCP_Reassembler.h" -Syslog_Analyzer_binpac::Syslog_Analyzer_binpac(Connection* conn) -: Analyzer(AnalyzerTag::SYSLOG_BINPAC, conn) +#include "Syslog.h" +#include "analyzer/protocol/tcp/TCP_Reassembler.h" + +#include "events.bif.h" + +using namespace analyzer::syslog; + +Syslog_Analyzer::Syslog_Analyzer(Connection* conn) +: Analyzer("SYSLOG", conn) { interp = new binpac::Syslog::Syslog_Conn(this); did_session_done = 0; - //ADD_ANALYZER_TIMER(&Syslog_Analyzer_binpac::ExpireTimer, + //ADD_ANALYZER_TIMER(&Syslog_Analyzer::ExpireTimer, // network_time + Syslog_session_timeout, 1, TIMER_Syslog_EXPIRE); } -Syslog_Analyzer_binpac::~Syslog_Analyzer_binpac() +Syslog_Analyzer::~Syslog_Analyzer() { delete interp; } -void Syslog_Analyzer_binpac::Done() +void Syslog_Analyzer::Done() { Analyzer::Done(); @@ -23,13 +28,13 @@ void Syslog_Analyzer_binpac::Done() Event(udp_session_done); } -void Syslog_Analyzer_binpac::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen) +void Syslog_Analyzer::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 Syslog_Analyzer_binpac::ExpireTimer(double t) +//void Syslog_Analyzer::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, @@ -40,39 +45,39 @@ void Syslog_Analyzer_binpac::DeliverPacket(int len, const u_char* data, bool ori // sessions->Remove(Conn()); // } // else -// ADD_ANALYZER_TIMER(&Syslog_Analyzer_binpac::ExpireTimer, +// ADD_ANALYZER_TIMER(&Syslog_Analyzer::ExpireTimer, // t + Syslog_session_timeout, 1, TIMER_Syslog_EXPIRE); // } -//Syslog_TCP_Analyzer_binpac::Syslog_TCP_Analyzer_binpac(Connection* conn) -//: TCP_ApplicationAnalyzer(AnalyzerTag::Syslog_TCP_BINPAC, conn) +//Syslog_tcp::TCP_Analyzer::Syslog_tcp::TCP_Analyzer(Connection* conn) +//: tcp::TCP_ApplicationAnalyzer(conn) // { // interp = new binpac::Syslog_on_TCP::Syslog_TCP_Conn(this); // } -//Syslog_TCP_Analyzer_binpac::~Syslog_TCP_Analyzer_binpac() +//Syslog_tcp::TCP_Analyzer::~Syslog_tcp::TCP_Analyzer() // { // delete interp; // } -//void Syslog_TCP_Analyzer_binpac::Done() +//void Syslog_tcp::TCP_Analyzer::Done() // { -// TCP_ApplicationAnalyzer::Done(); +// tcp::TCP_ApplicationAnalyzer::Done(); // // interp->FlowEOF(true); // interp->FlowEOF(false); // } -//void Syslog_TCP_Analyzer_binpac::EndpointEOF(TCP_Reassembler* endp) +//void Syslog_tcp::TCP_Analyzer::EndpointEOF(tcp::TCP_Reassembler* endp) // { -// TCP_ApplicationAnalyzer::EndpointEOF(endp); +// tcp::TCP_ApplicationAnalyzer::EndpointEOF(endp); // interp->FlowEOF(endp->IsOrig()); // } -//void Syslog_TCP_Analyzer_binpac::DeliverStream(int len, const u_char* data, +//void Syslog_tcp::TCP_Analyzer::DeliverStream(int len, const u_char* data, // bool orig) // { -// TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); +// tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); // // assert(TCP()); // @@ -83,8 +88,8 @@ void Syslog_Analyzer_binpac::DeliverPacket(int len, const u_char* data, bool ori // interp->NewData(orig, data, data + len); // } -//void Syslog_TCP_Analyzer_binpac::Undelivered(int seq, int len, bool orig) +//void Syslog_tcp::TCP_Analyzer::Undelivered(int seq, int len, bool orig) // { -// TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); +// tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); // interp->NewGap(orig, len); // } diff --git a/src/analyzer/protocol/syslog/Syslog.h b/src/analyzer/protocol/syslog/Syslog.h new file mode 100644 index 0000000000..355863e36e --- /dev/null +++ b/src/analyzer/protocol/syslog/Syslog.h @@ -0,0 +1,53 @@ + +#ifndef ANALYZER_PROTOCOL_SYSLOG_SYSLOG_H +#define ANALYZER_PROTOCOL_SYSLOG_SYSLOG_H + +#include "analyzer/protocol/udp/UDP.h" +#include "analyzer/protocol/tcp/TCP.h" + +#include "syslog_pac.h" + +namespace analyzer { namespace syslog { + +class Syslog_Analyzer : public analyzer::Analyzer { +public: + Syslog_Analyzer(Connection* conn); + virtual ~Syslog_Analyzer(); + + virtual void Done(); + virtual void DeliverPacket(int len, const u_char* data, bool orig, + int seq, const IP_Hdr* ip, int caplen); + + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) + { return new Syslog_Analyzer(conn); } + +protected: + void ExpireTimer(double t); + + int did_session_done; + + binpac::Syslog::Syslog_Conn* interp; +}; + +// #include "Syslog_tcp_pac.h" +// +//class Syslog_tcp::TCP_Analyzer : public tcp::TCP_ApplicationAnalyzer { +//public: +// Syslog_tcp::TCP_Analyzer(Connection* conn); +// virtual ~Syslog_tcp::TCP_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(tcp::TCP_Reassembler* endp); +// +// static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) +// { return new Syslog_tcp::TCP_Analyzer(conn); } +// +//protected: +// binpac::Syslog_on_TCP::Syslog_TCP_Conn* interp; +//}; +// +} } // namespace analyzer::* + +#endif diff --git a/src/analyzer/protocol/syslog/events.bif b/src/analyzer/protocol/syslog/events.bif new file mode 100644 index 0000000000..f82adc7e69 --- /dev/null +++ b/src/analyzer/protocol/syslog/events.bif @@ -0,0 +1,17 @@ + +## Generated for monitored Syslog messages. +## +## See `Wikipedia `__ for more +## information about the Syslog protocol. +## +## c: The connection record for the underlying transport-layer session/flow. +## +## facility: The "facility" included in the message. +## +## severity: The "severity" included in the message. +## +## msg: The message logged. +## +## .. note:: Bro currently parses only UDP syslog traffic. Support for TCP +## syslog will be added soon. +event syslog_message%(c: connection, facility: count, severity: count, msg: string%); diff --git a/src/syslog-analyzer.pac b/src/analyzer/protocol/syslog/syslog-analyzer.pac similarity index 100% rename from src/syslog-analyzer.pac rename to src/analyzer/protocol/syslog/syslog-analyzer.pac diff --git a/src/syslog-protocol.pac b/src/analyzer/protocol/syslog/syslog-protocol.pac similarity index 100% rename from src/syslog-protocol.pac rename to src/analyzer/protocol/syslog/syslog-protocol.pac diff --git a/src/syslog.pac b/src/analyzer/protocol/syslog/syslog.pac similarity index 82% rename from src/syslog.pac rename to src/analyzer/protocol/syslog/syslog.pac index 3c0ecfb10d..2c1fdd10d0 100644 --- a/src/syslog.pac +++ b/src/analyzer/protocol/syslog/syslog.pac @@ -1,6 +1,11 @@ + %include binpac.pac %include bro.pac +%extern{ +#include "events.bif.h" +%} + analyzer Syslog withcontext { connection: Syslog_Conn; flow: Syslog_Flow; diff --git a/src/analyzer/protocol/tcp/CMakeLists.txt b/src/analyzer/protocol/tcp/CMakeLists.txt new file mode 100644 index 0000000000..d4b2dc3eab --- /dev/null +++ b/src/analyzer/protocol/tcp/CMakeLists.txt @@ -0,0 +1,10 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro TCP) +bro_plugin_cc(TCP.cc TCP_Endpoint.cc TCP_Reassembler.cc ContentLine.cc Stats.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_bif(functions.bif) +bro_plugin_end() diff --git a/src/ContentLine.cc b/src/analyzer/protocol/tcp/ContentLine.cc similarity index 96% rename from src/ContentLine.cc rename to src/analyzer/protocol/tcp/ContentLine.cc index 5601694e1d..2a810c5dd1 100644 --- a/src/ContentLine.cc +++ b/src/analyzer/protocol/tcp/ContentLine.cc @@ -1,17 +1,20 @@ #include #include "ContentLine.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" + +#include "events.bif.h" + +using namespace analyzer::tcp; ContentLine_Analyzer::ContentLine_Analyzer(Connection* conn, bool orig) -: TCP_SupportAnalyzer(AnalyzerTag::ContentLine, conn, orig) +: TCP_SupportAnalyzer("CONTENTLINE", conn, orig) { InitState(); } -ContentLine_Analyzer::ContentLine_Analyzer(AnalyzerTag::Tag tag, - Connection* conn, bool orig) -: TCP_SupportAnalyzer(tag, conn, orig) +ContentLine_Analyzer::ContentLine_Analyzer(const char* name, Connection* conn, bool orig) +: TCP_SupportAnalyzer(name, conn, orig) { InitState(); } diff --git a/src/ContentLine.h b/src/analyzer/protocol/tcp/ContentLine.h similarity index 91% rename from src/ContentLine.h rename to src/analyzer/protocol/tcp/ContentLine.h index 5e9f01945f..ecc1347984 100644 --- a/src/ContentLine.h +++ b/src/analyzer/protocol/tcp/ContentLine.h @@ -1,9 +1,11 @@ // Support-analyzer to split a reassembled stream into lines. -#ifndef CONTENTLINE_H -#define CONTENTLINE_H +#ifndef ANALYZER_PROTOCOL_TCP_CONTENTLINE_H +#define ANALYZER_PROTOCOL_TCP_CONTENTLINE_H -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" + +namespace analyzer { namespace tcp { #define CR_as_EOL 1 #define LF_as_EOL 2 @@ -55,7 +57,7 @@ public: { return seq + length <= seq_to_skip; } protected: - ContentLine_Analyzer(AnalyzerTag::Tag tag, Connection* conn, bool orig); + ContentLine_Analyzer(const char* name, Connection* conn, bool orig); virtual void DeliverStream(int len, const u_char* data, bool is_orig); virtual void Undelivered(int seq, int len, bool orig); @@ -104,4 +106,6 @@ protected: unsigned int skip_partial:1; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/tcp/Plugin.cc b/src/analyzer/protocol/tcp/Plugin.cc new file mode 100644 index 0000000000..6132b6f386 --- /dev/null +++ b/src/analyzer/protocol/tcp/Plugin.cc @@ -0,0 +1,14 @@ + +#include "plugin/Plugin.h" + +#include "TCP.h" + +BRO_PLUGIN_BEGIN(Bro, TCP) + BRO_PLUGIN_DESCRIPTION("TCP analyzer"); + BRO_PLUGIN_ANALYZER("TCP", tcp::TCP_Analyzer); + BRO_PLUGIN_ANALYZER("TCPStats", tcp::TCPStats_Analyzer); + BRO_PLUGIN_SUPPORT_ANALYZER("ContentLine"); + BRO_PLUGIN_SUPPORT_ANALYZER("Contents"); + BRO_PLUGIN_BIF_FILE(events); + BRO_PLUGIN_BIF_FILE(functions); +BRO_PLUGIN_END diff --git a/src/analyzer/protocol/tcp/Stats.cc b/src/analyzer/protocol/tcp/Stats.cc new file mode 100644 index 0000000000..b5337fa2db --- /dev/null +++ b/src/analyzer/protocol/tcp/Stats.cc @@ -0,0 +1,83 @@ + +#include "Stats.h" +#include "File.h" + +#include "events.bif.h" + +using namespace analyzer::tcp; + +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"); + } + } diff --git a/src/analyzer/protocol/tcp/Stats.h b/src/analyzer/protocol/tcp/Stats.h new file mode 100644 index 0000000000..721d898d95 --- /dev/null +++ b/src/analyzer/protocol/tcp/Stats.h @@ -0,0 +1,71 @@ + +#ifndef ANALYZER_PROTOCOL_TCP_STATS_H +#define ANALYZER_PROTOCOL_TCP_STATS_H + +#include "TCP_Endpoint.h" + +namespace analyzer { namespace tcp { + +// 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]; +}; + +} } // namespace analyzer::* + +#endif diff --git a/src/TCP.cc b/src/analyzer/protocol/tcp/TCP.cc similarity index 97% rename from src/TCP.cc rename to src/analyzer/protocol/tcp/TCP.cc index c291f8e76c..8f42e0f2b1 100644 --- a/src/TCP.cc +++ b/src/analyzer/protocol/tcp/TCP.cc @@ -3,13 +3,18 @@ #include #include "NetVar.h" -#include "PIA.h" #include "File.h" -#include "TCP.h" -#include "TCP_Reassembler.h" #include "OSFinger.h" #include "Event.h" +#include "analyzer/protocol/pia/PIA.h" +#include "analyzer/protocol/tcp/TCP.h" +#include "analyzer/protocol/tcp/TCP_Reassembler.h" + +#include "events.bif.h" + +using namespace analyzer::tcp; + namespace { // local namespace const bool DEBUG_tcp_data_sent = false; const bool DEBUG_tcp_connection_close = false; @@ -32,7 +37,7 @@ static const int ORIG = 1; static const int RESP = 2; TCP_Analyzer::TCP_Analyzer(Connection* conn) -: TransportLayerAnalyzer(AnalyzerTag::TCP, conn) +: TransportLayerAnalyzer("TCP", conn) { // Set a timer to eventually time out this connection. ADD_ANALYZER_TIMER(&TCP_Analyzer::ExpireTimer, @@ -953,7 +958,7 @@ void TCP_Analyzer::CheckPIA_FirstPacket(int is_orig, const IP_Hdr* ip) { if ( is_orig && ! (first_packet_seen & ORIG) ) { - PIA_TCP* pia = static_cast(Conn()->GetPrimaryPIA()); + pia::PIA_TCP* pia = static_cast(Conn()->GetPrimaryPIA()); if ( pia ) pia->FirstPacket(is_orig, ip); first_packet_seen |= ORIG; @@ -961,7 +966,7 @@ void TCP_Analyzer::CheckPIA_FirstPacket(int is_orig, const IP_Hdr* ip) if ( ! is_orig && ! (first_packet_seen & RESP) ) { - PIA_TCP* pia = static_cast(Conn()->GetPrimaryPIA()); + pia::PIA_TCP* pia = static_cast(Conn()->GetPrimaryPIA()); if ( pia ) pia->FirstPacket(is_orig, ip); first_packet_seen |= RESP; @@ -1534,12 +1539,10 @@ void TCP_Analyzer::DeleteTimer(double /* t */) sessions->Remove(Conn()); } - -// The following need to be consistent with bro.init. -#define CONTENTS_NONE 0 -#define CONTENTS_ORIG 1 -#define CONTENTS_RESP 2 -#define CONTENTS_BOTH 3 +void TCP_Analyzer::ConnDeleteTimer(double t) + { + Conn()->DeleteTimer(t); + } void TCP_Analyzer::SetContentsFile(unsigned int direction, BroFile* f) { @@ -1830,7 +1833,7 @@ void TCP_ApplicationAnalyzer::Init() { Analyzer::Init(); - if ( Parent()->GetTag() == AnalyzerTag::TCP ) + if ( Parent()->IsAnalyzer("TCP") ) SetTCP(static_cast(Parent())); } @@ -1853,7 +1856,7 @@ void TCP_ApplicationAnalyzer::DeliverPacket(int len, const u_char* data, const IP_Hdr* ip, int caplen) { Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen); - DBG_LOG(DBG_DPD, "TCP_ApplicationAnalyzer ignoring DeliverPacket(%d, %s, %d, %p, %d) [%s%s]", + DBG_LOG(DBG_ANALYZER, "TCP_ApplicationAnalyzer ignoring DeliverPacket(%d, %s, %d, %p, %d) [%s%s]", len, is_orig ? "T" : "F", seq, ip, caplen, fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : ""); } @@ -1866,7 +1869,7 @@ void TCP_ApplicationAnalyzer::SetEnv(bool /* is_orig */, char* name, char* val) void TCP_ApplicationAnalyzer::EndpointEOF(bool is_orig) { - SupportAnalyzer* sa = is_orig ? orig_supporters : resp_supporters; + analyzer::SupportAnalyzer* sa = is_orig ? orig_supporters : resp_supporters; for ( ; sa; sa = sa->Sibling() ) static_cast(sa)->EndpointEOF(is_orig); } @@ -1874,7 +1877,7 @@ void TCP_ApplicationAnalyzer::EndpointEOF(bool is_orig) void TCP_ApplicationAnalyzer::ConnectionClosed(TCP_Endpoint* endpoint, TCP_Endpoint* peer, int gen_event) { - SupportAnalyzer* sa = + analyzer::SupportAnalyzer* sa = endpoint->IsOrig() ? orig_supporters : resp_supporters; for ( ; sa; sa = sa->Sibling() ) @@ -1884,30 +1887,30 @@ void TCP_ApplicationAnalyzer::ConnectionClosed(TCP_Endpoint* endpoint, void TCP_ApplicationAnalyzer::ConnectionFinished(int half_finished) { - for ( SupportAnalyzer* sa = orig_supporters; sa; sa = sa->Sibling() ) + for ( analyzer::SupportAnalyzer* sa = orig_supporters; sa; sa = sa->Sibling() ) static_cast(sa) ->ConnectionFinished(half_finished); - for ( SupportAnalyzer* sa = resp_supporters; sa; sa = sa->Sibling() ) + for ( analyzer::SupportAnalyzer* sa = resp_supporters; sa; sa = sa->Sibling() ) static_cast(sa) ->ConnectionFinished(half_finished); } void TCP_ApplicationAnalyzer::ConnectionReset() { - for ( SupportAnalyzer* sa = orig_supporters; sa; sa = sa->Sibling() ) + for ( analyzer::SupportAnalyzer* sa = orig_supporters; sa; sa = sa->Sibling() ) static_cast(sa)->ConnectionReset(); - for ( SupportAnalyzer* sa = resp_supporters; sa; sa = sa->Sibling() ) + for ( analyzer::SupportAnalyzer* sa = resp_supporters; sa; sa = sa->Sibling() ) static_cast(sa)->ConnectionReset(); } void TCP_ApplicationAnalyzer::PacketWithRST() { - for ( SupportAnalyzer* sa = orig_supporters; sa; sa = sa->Sibling() ) + for ( analyzer::SupportAnalyzer* sa = orig_supporters; sa; sa = sa->Sibling() ) static_cast(sa)->PacketWithRST(); - for ( SupportAnalyzer* sa = resp_supporters; sa; sa = sa->Sibling() ) + for ( analyzer::SupportAnalyzer* sa = resp_supporters; sa; sa = sa->Sibling() ) static_cast(sa)->PacketWithRST(); } @@ -2043,7 +2046,7 @@ RecordVal* TCPStats_Endpoint::BuildStats() } TCPStats_Analyzer::TCPStats_Analyzer(Connection* c) -: TCP_ApplicationAnalyzer(AnalyzerTag::TCPStats, c) +: TCP_ApplicationAnalyzer("TCPSTATS", c) { } diff --git a/src/TCP.h b/src/analyzer/protocol/tcp/TCP.h similarity index 89% rename from src/TCP.h rename to src/analyzer/protocol/tcp/TCP.h index 635fda7960..b2649b4ab8 100644 --- a/src/TCP.h +++ b/src/analyzer/protocol/tcp/TCP.h @@ -1,19 +1,25 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef TCP_H -#define TCP_H +#ifndef ANALYZER_PROTOCOL_TCP_TCP_H +#define ANALYZER_PROTOCOL_TCP_TCP_H -#include "Analyzer.h" -#include "TCP.h" +#include "analyzer/Analyzer.h" +#include "analyzer/protocol/tcp/TCP.h" #include "PacketDumper.h" #include "IPAddr.h" +#include "TCP_Endpoint.h" +#include "Conn.h" // We define two classes here: // - TCP_Analyzer is the analyzer for the TCP protocol itself. // - TCP_ApplicationAnalyzer is an abstract base class for analyzers for a // protocol running on top of TCP. +// +namespace analyzer { namespace pia { class PIA_TCP; } }; -class PIA_TCP; +namespace analyzer { namespace tcp { + +class TCP_Endpoint; class TCP_ApplicationAnalyzer; class TCP_Reassembler; @@ -32,7 +38,7 @@ protected: u_char flags; }; -class TCP_Analyzer : public TransportLayerAnalyzer { +class TCP_Analyzer : public analyzer::TransportLayerAnalyzer { public: TCP_Analyzer(Connection* conn); virtual ~TCP_Analyzer(); @@ -41,7 +47,7 @@ public: // Add a child analyzer that will always get the packets, // independently of whether we do any reassembly. - void AddChildPacketAnalyzer(Analyzer* a) + void AddChildPacketAnalyzer(analyzer::Analyzer* a) { packet_children.push_back(a); a->SetParent(this); } // True if the connection has closed in some sense, false otherwise. @@ -85,15 +91,13 @@ public: proc_tcp_option_t proc, TCP_Analyzer* analyzer, bool is_orig, void* cookie); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new TCP_Analyzer(conn); } - static bool Available() { return true; } - protected: friend class TCP_ApplicationAnalyzer; friend class TCP_Reassembler; - friend class PIA_TCP; + friend class analyzer::pia::PIA_TCP; // Analyzer interface. virtual void Init(); @@ -213,7 +217,7 @@ protected: void ExpireTimer(double t); void ResetTimer(double t); void DeleteTimer(double t); - void ConnDeleteTimer(double t) { Conn()->DeleteTimer(t); } + void ConnDeleteTimer(double t); void EndpointEOF(TCP_Reassembler* endp); void ConnectionClosed(TCP_Endpoint* endpoint, @@ -222,7 +226,7 @@ protected: void ConnectionReset(); void PacketWithRST(); - void SetReassembler(TCP_Reassembler* rorig, TCP_Reassembler* rresp); + void SetReassembler(tcp::TCP_Reassembler* rorig, tcp::TCP_Reassembler* rresp); Val* BuildSYNPacketVal(int is_orig, const IP_Hdr* ip, const struct tcphdr* tcp); @@ -240,6 +244,7 @@ private: TCP_Endpoint* orig; TCP_Endpoint* resp; + typedef list analyzer_list; analyzer_list packet_children; unsigned int first_packet_seen: 2; @@ -259,10 +264,14 @@ private: unsigned int seen_first_ACK: 1; }; -class TCP_ApplicationAnalyzer : public Analyzer { +class TCP_ApplicationAnalyzer : public analyzer::Analyzer { public: - TCP_ApplicationAnalyzer(AnalyzerTag::Tag tag, Connection* conn) - : Analyzer(tag, conn) + TCP_ApplicationAnalyzer(const char* name, Connection* conn) + : Analyzer(name, conn) + { tcp = 0; } + + TCP_ApplicationAnalyzer(Connection* conn) + : Analyzer(conn) { tcp = 0; } virtual ~TCP_ApplicationAnalyzer() { } @@ -273,8 +282,7 @@ public: { return tcp ? tcp : - static_cast( - Conn()->FindAnalyzer(AnalyzerTag::TCP)); + static_cast(Conn()->FindAnalyzer("TCP")); } void SetTCP(TCP_Analyzer* arg_tcp) { tcp = arg_tcp; } @@ -308,17 +316,14 @@ public: // delete them when done with them. virtual void SetEnv(bool orig, char* name, char* val); -protected: - TCP_ApplicationAnalyzer() { }; - private: TCP_Analyzer* tcp; }; -class TCP_SupportAnalyzer : public SupportAnalyzer { +class TCP_SupportAnalyzer : public analyzer::SupportAnalyzer { public: - TCP_SupportAnalyzer(AnalyzerTag::Tag tag, Connection* conn, bool arg_orig) - : SupportAnalyzer(tag, conn, arg_orig) { } + TCP_SupportAnalyzer(const char* name, Connection* conn, bool arg_orig) + : analyzer::SupportAnalyzer(name, conn, arg_orig) { } virtual ~TCP_SupportAnalyzer() {} @@ -354,7 +359,7 @@ protected: int endian_type; }; -class TCPStats_Analyzer : public TCP_ApplicationAnalyzer { +class TCPStats_Analyzer : public tcp::TCP_ApplicationAnalyzer { public: TCPStats_Analyzer(Connection* c); ~TCPStats_Analyzer(); @@ -362,11 +367,9 @@ public: virtual void Init(); virtual void Done(); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new TCPStats_Analyzer(conn); } - static bool Available() { return conn_stats || tcp_rexmit; } - protected: virtual void DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen); @@ -375,4 +378,6 @@ protected: TCPStats_Endpoint* resp_stats; }; +} } // namespace analyzer::* + #endif diff --git a/src/TCP_Endpoint.cc b/src/analyzer/protocol/tcp/TCP_Endpoint.cc similarity index 98% rename from src/TCP_Endpoint.cc rename to src/analyzer/protocol/tcp/TCP_Endpoint.cc index 69c08870d9..3beafdeb8a 100644 --- a/src/TCP_Endpoint.cc +++ b/src/analyzer/protocol/tcp/TCP_Endpoint.cc @@ -2,13 +2,17 @@ #include "Net.h" #include "NetVar.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #include "TCP_Reassembler.h" #include "Sessions.h" #include "Event.h" #include "File.h" #include "Val.h" +#include "events.bif.h" + +using namespace analyzer::tcp; + TCP_Endpoint::TCP_Endpoint(TCP_Analyzer* arg_analyzer, int arg_is_orig) { contents_processor = 0; diff --git a/src/TCP_Endpoint.h b/src/analyzer/protocol/tcp/TCP_Endpoint.h similarity index 96% rename from src/TCP_Endpoint.h rename to src/analyzer/protocol/tcp/TCP_Endpoint.h index 52a757b256..31e239225b 100644 --- a/src/TCP_Endpoint.h +++ b/src/analyzer/protocol/tcp/TCP_Endpoint.h @@ -1,10 +1,18 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef tcpendpoint_h -#define tcpendpoint_h +#ifndef ANALYZER_PROTOCOL_TCP_TCP_ENDPOINT_H +#define ANALYZER_PROTOCOL_TCP_TCP_ENDPOINT_H #include "IPAddr.h" +class Connection; +class IP_Hdr; + +namespace analyzer { namespace tcp { + +class TCP_Analyzer; +class TCP_Reassembler; + typedef enum { TCP_ENDPOINT_INACTIVE, // no SYN (or other packets) seen for this side TCP_ENDPOINT_SYN_SENT, // SYN seen, but no ack @@ -16,11 +24,6 @@ typedef enum { TCP_ENDPOINT_RESET // RST seen } EndpointState; -class Connection; -class TCP_Reassembler; -class IP_Hdr; -class TCP_Analyzer; - // One endpoint of a TCP connection. class TCP_Endpoint { public: @@ -157,4 +160,6 @@ protected: #define ENDIAN_BIG 2 #define ENDIAN_CONFUSED 3 +} } // namespace analyzer::* + #endif diff --git a/src/TCP_Reassembler.cc b/src/analyzer/protocol/tcp/TCP_Reassembler.cc similarity index 98% rename from src/TCP_Reassembler.cc rename to src/analyzer/protocol/tcp/TCP_Reassembler.cc index eb2709373c..949be9f599 100644 --- a/src/TCP_Reassembler.cc +++ b/src/analyzer/protocol/tcp/TCP_Reassembler.cc @@ -1,13 +1,17 @@ #include -#include "Analyzer.h" +#include "analyzer/Analyzer.h" #include "TCP_Reassembler.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" #include "TCP_Endpoint.h" // Only needed for gap_report events. #include "Event.h" +#include "events.bif.h" + +using namespace analyzer::tcp; + // Note, sequence numbers are relative. I.e., they start with 1. // TODO: The Reassembler should start using 64 bit ints for keeping track of @@ -25,7 +29,7 @@ static uint64 last_ack_bytes = 0; static uint64 last_gap_events = 0; static uint64 last_gap_bytes = 0; -TCP_Reassembler::TCP_Reassembler(Analyzer* arg_dst_analyzer, +TCP_Reassembler::TCP_Reassembler(analyzer::Analyzer* arg_dst_analyzer, TCP_Analyzer* arg_tcp_analyzer, TCP_Reassembler::Type arg_type, bool arg_is_orig, TCP_Endpoint* arg_endp) diff --git a/src/TCP_Reassembler.h b/src/analyzer/protocol/tcp/TCP_Reassembler.h similarity index 94% rename from src/TCP_Reassembler.h rename to src/analyzer/protocol/tcp/TCP_Reassembler.h index cb1750e2a2..8bb80a0570 100644 --- a/src/TCP_Reassembler.h +++ b/src/analyzer/protocol/tcp/TCP_Reassembler.h @@ -1,5 +1,5 @@ -#ifndef TCP_REASSEMBLER_H -#define TCP_REASSEMBLER_H +#ifndef ANALYZER_PROTOCOL_TCP_TCP_REASSEMBLER_H +#define ANALYZER_PROTOCOL_TCP_TCP_REASSEMBLER_H #include "Reassem.h" #include "TCP_Endpoint.h" @@ -13,8 +13,10 @@ class BroFile; class Connection; + +namespace analyzer { namespace tcp { + class TCP_Analyzer; -class Analyzer; const int STOP_ON_GAP = 1; const int PUNT_ON_PARTIAL = 1; @@ -69,6 +71,8 @@ public: // Skip up to seq, as if there's a content gap. // Can be used to skip HTTP data for performance considerations. void SkipToSeq(int seq); +} } // namespace analyzer::* + #endif int DataSent(double t, int seq, int len, const u_char* data, @@ -95,6 +99,8 @@ public: #ifdef ENABLE_SEQ_TO_SKIP bool IsSkippedContents(int seq, int length) const { return seq + length <= seq_to_skip; } +} } // namespace analyzer::* + #endif private: @@ -132,4 +138,6 @@ private: bool is_orig; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/tcp/events.bif b/src/analyzer/protocol/tcp/events.bif new file mode 100644 index 0000000000..af61783ac4 --- /dev/null +++ b/src/analyzer/protocol/tcp/events.bif @@ -0,0 +1,289 @@ + +## Generated when reassembly starts for a TCP connection. This event is raised +## at the moment when Bro's TCP analyzer enables stream reassembly for a +## connection. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reset connection_reused +## connection_state_remove connection_status_update connection_timeout +## scheduled_analyzer_applied new_connection partial_connection +event new_connection_contents%(c: connection%); + +## Generated for an unsuccessful connection attempt. This event is raised when +## an originator unsuccessfully attempted to establish a connection. +## "Unsuccessful" is defined as at least :bro:id:`tcp_attempt_delay` seconds +## having elapsed since the originator first sent a connection establishment +## packet to the destination without seeing a reply. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_established +## connection_external connection_finished connection_first_ACK +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout scheduled_analyzer_applied +## new_connection new_connection_contents partial_connection +event connection_attempt%(c: connection%); + +## Generated when a SYN-ACK packet is seen in response to a SYN packet during +## a TCP handshake. The final ACK of the handshake in response to SYN-ACK may +## or may not occur later, one way to tell is to check the *history* field of +## :bro:type:`connection` to see if the originator sent an ACK, indicated by +## 'A' in the history string. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_external connection_finished connection_first_ACK +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout scheduled_analyzer_applied +## new_connection new_connection_contents partial_connection +event connection_established%(c: connection%); + +## Generated for a new active TCP connection if Bro did not see the initial +## handshake. This event is raised when Bro has observed traffic from each +## endpoint, but the activity did not begin with the usual connection +## establishment. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reset connection_reused +## connection_state_remove connection_status_update connection_timeout +## scheduled_analyzer_applied new_connection new_connection_contents +## +event partial_connection%(c: connection%); + +## Generated when a previously inactive endpoint attempts to close a TCP +## connection via a normal FIN handshake or an abort RST sequence. When the +## endpoint sent one of these packets, Bro waits +## :bro:id:`tcp_partial_close_delay` prior to generating the event, to give +## the other endpoint a chance to close the connection normally. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout scheduled_analyzer_applied +## new_connection new_connection_contents partial_connection +event connection_partial_close%(c: connection%); + +## Generated for a TCP connection that finished normally. The event is raised +## when a regular FIN handshake from both endpoints was observed. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_first_ACK +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout scheduled_analyzer_applied +## new_connection new_connection_contents partial_connection +event connection_finished%(c: connection%); + +## Generated when one endpoint of a TCP connection attempted to gracefully close +## the connection, but the other endpoint is in the TCP_INACTIVE state. This can +## happen due to split routing, in which Bro only sees one side of a connection. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout scheduled_analyzer_applied +## new_connection new_connection_contents partial_connection +event connection_half_finished%(c: connection%); + +## Generated for a rejected TCP connection. This event is raised when an +## originator attempted to setup a TCP connection but the responder replied +## with a RST packet denying it. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout scheduled_analyzer_applied +## new_connection new_connection_contents partial_connection +## +## c: The connection. +## +## .. note:: +## +## If the responder does not respond at all, :bro:id:`connection_attempt` is +## raised instead. If the responder initially accepts the connection but +## aborts it later, Bro first generates :bro:id:`connection_established` +## and then :bro:id:`connection_reset`. +event connection_rejected%(c: connection%); + +## Generated when an endpoint aborted a TCP connection. The event is raised +## when one endpoint of an established TCP connection aborted by sending a RST +## packet. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reused +## connection_state_remove connection_status_update connection_timeout +## scheduled_analyzer_applied new_connection new_connection_contents +## partial_connection +event connection_reset%(c: connection%); + +## Generated for each still-open TCP connection when Bro terminates. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout scheduled_analyzer_applied +## new_connection new_connection_contents partial_connection bro_done +event connection_pending%(c: connection%); + +## Generated for a SYN packet. Bro raises this event for every SYN packet seen +## by its TCP analyzer. +## +## c: The connection. +## +## pkt: Information extracted from the SYN packet. +## +## .. bro:see:: connection_EOF connection_attempt connection_established +## connection_external connection_finished connection_first_ACK +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout scheduled_analyzer_applied +## new_connection new_connection_contents partial_connection +## +## .. note:: +## +## This event has quite low-level semantics and can potentially be expensive +## to generate. It should only be used if one really needs the specific +## information passed into the handler via the ``pkt`` argument. If not, +## handling one of the other ``connection_*`` events is typically the +## better approach. +event connection_SYN_packet%(c: connection, pkt: SYN_packet%); + +## Generated for the first ACK packet seen for a TCP connection from +## its *originator*. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout scheduled_analyzer_applied +## new_connection new_connection_contents partial_connection +## +## .. note:: +## +## This event has quite low-level semantics and should be used only rarely. +event connection_first_ACK%(c: connection%); + +## Generated at the end of reassembled TCP connections. The TCP reassembler +## raised the event once for each endpoint of a connection when it finished +## reassembling the corresponding side of the communication. +## +## c: The connection. +## +## is_orig: True if the event is raised for the originator side. +## +## .. bro:see:: connection_SYN_packet connection_attempt connection_established +## connection_external connection_finished connection_first_ACK +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout scheduled_analyzer_applied +## new_connection new_connection_contents partial_connection +event connection_EOF%(c: connection, is_orig: bool%); + +## Generated for every TCP packet. This is a very low-level and expensive event +## that should be avoided when at all possible. It's usually infeasible to +## handle when processing even medium volumes of traffic in real-time. It's +## slightly better than :bro:id:`new_packet` because it affects only TCP, but +## not much. That said, if you work from a trace and want to do some +## packet-level analysis, it may come in handy. +## +## c: The connection the packet is part of. +## +## is_orig: True if the packet was sent by the connection's originator. +## +## flags: A string with the packet's TCP flags. In the string, each character +## corresponds to one set flag, as follows: ``S`` -> SYN; ``F`` -> FIN; +## ``R`` -> RST; ``A`` -> ACK; ``P`` -> PUSH. +## +## seq: The packet's TCP sequence number. +## +## ack: The packet's ACK number. +## +## len: The length of the TCP payload, as specified in the packet header. +## +## payload: The raw TCP payload. Note that this may be shorter than *len* if +## the packet was not fully captured. +## +## .. bro:see:: new_packet packet_contents tcp_option tcp_contents tcp_rexmit +event tcp_packet%(c: connection, is_orig: bool, flags: string, seq: count, ack: count, len: count, payload: string%); + +## Generated for each option found in a TCP header. Like many of the ``tcp_*`` +## events, this is a very low-level event and potentially expensive as it may +## be raised very often. +## +## c: The connection the packet is part of. +## +## is_orig: True if the packet was sent by the connection's originator. +## +## opt: The numerical option number, as found in the TCP header. +## +## optlen: The length of the options value. +## +## .. bro:see:: tcp_packet tcp_contents tcp_rexmit +## +## .. note:: There is currently no way to get the actual option value, if any. +event tcp_option%(c: connection, is_orig: bool, opt: count, optlen: count%); + +## Generated for each chunk of reassembled TCP payload. When content delivery is +## enabled for a TCP connection (via :bro:id:`tcp_content_delivery_ports_orig`, +## :bro:id:`tcp_content_delivery_ports_resp`, +## :bro:id:`tcp_content_deliver_all_orig`, +## :bro:id:`tcp_content_deliver_all_resp`), this event is raised for each chunk +## of in-order payload reconstructed from the packet stream. Note that this +## event is potentially expensive if many connections carry significant amounts +## of data as then all that data needs to be passed on to the scripting layer. +## +## c: The connection the payload is part of. +## +## is_orig: True if the packet was sent by the connection's originator. +## +## seq: The sequence number corresponding to the first byte of the payload +## chunk. +## +## contents: The raw payload, which will be non-empty. +## +## .. bro:see:: tcp_packet tcp_option tcp_rexmit +## tcp_content_delivery_ports_orig tcp_content_delivery_ports_resp +## tcp_content_deliver_all_resp tcp_content_deliver_all_orig +## +## .. note:: +## +## The payload received by this event is the same that is also passed into +## application-layer protocol analyzers internally. Subsequent invocations of +## this event for the same connection receive non-overlapping in-order chunks +## of its TCP payload stream. It is however undefined what size each chunk +## has; while Bro passes the data on as soon as possible, specifics depend on +## network-level effects such as latency, acknowledgements, reordering, etc. +event tcp_contents%(c: connection, is_orig: bool, seq: count, contents: string%); + +## TODO. +event tcp_rexmit%(c: connection, is_orig: bool, seq: count, len: count, data_in_flight: count, window: count%); + diff --git a/src/analyzer/protocol/tcp/functions.bif b/src/analyzer/protocol/tcp/functions.bif new file mode 100644 index 0000000000..ff812b80ee --- /dev/null +++ b/src/analyzer/protocol/tcp/functions.bif @@ -0,0 +1,159 @@ + +%%{ +#include "analyzer/protocol/tcp/TCP.h" +%%} + +## Get the originator sequence number of a TCP connection. Sequence numbers +## are absolute (i.e., they reflect the values seen directly in packet headers; +## they are not relative to the beginning of the connection). +## +## cid: The connection ID. +## +## Returns: The highest sequence number sent by a connection's originator, or 0 +## if *cid* does not point to an active TCP connection. +## +## .. bro:see:: get_resp_seq +function get_orig_seq%(cid: conn_id%): count + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_COUNT); + + if ( c->ConnTransport() != TRANSPORT_TCP ) + return new Val(0, TYPE_COUNT); + + analyzer::Analyzer* tc = c->FindAnalyzer("TCP"); + if ( tc ) + return new Val(static_cast(tc)->OrigSeq(), + TYPE_COUNT); + else + { + reporter->Error("connection does not have TCP analyzer"); + return new Val(0, TYPE_COUNT); + } + %} + +## Get the responder sequence number of a TCP connection. Sequence numbers +## are absolute (i.e., they reflect the values seen directly in packet headers; +## they are not relative to the beginning of the connection). +## +## cid: The connection ID. +## +## Returns: The highest sequence number sent by a connection's responder, or 0 +## if *cid* does not point to an active TCP connection. +## +## .. bro:see:: get_orig_seq +function get_resp_seq%(cid: conn_id%): count + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_COUNT); + + if ( c->ConnTransport() != TRANSPORT_TCP ) + return new Val(0, TYPE_COUNT); + + analyzer::Analyzer* tc = c->FindAnalyzer("TCP"); + if ( tc ) + return new Val(static_cast(tc)->RespSeq(), + TYPE_COUNT); + else + { + reporter->Error("connection does not have TCP analyzer"); + return new Val(0, TYPE_COUNT); + } + %} + +## Returns statistics about TCP gaps. +## +## Returns: A record with TCP gap statistics. +## +## .. bro:see:: do_profiling +## net_stats +## resource_usage +## dump_rule_stats +## get_matcher_stats +function get_gap_summary%(%): gap_info + %{ + RecordVal* r = new RecordVal(gap_info); + r->Assign(0, new Val(tot_ack_events, TYPE_COUNT)); + r->Assign(1, new Val(tot_ack_bytes, TYPE_COUNT)); + r->Assign(2, new Val(tot_gap_events, TYPE_COUNT)); + r->Assign(3, new Val(tot_gap_bytes, TYPE_COUNT)); + + return r; + %} + +## Associates a file handle with a connection for writing TCP byte stream +## contents. +## +## cid: The connection ID. +## +## direction: Controls what sides of the connection to record. The argument can +## take one of the four values: +## +## - ``CONTENTS_NONE``: Stop recording the connection's content. +## - ``CONTENTS_ORIG``: Record the data sent by the connection +## originator (often the client). +## - ``CONTENTS_RESP``: Record the data sent by the connection +## responder (often the server). +## - ``CONTENTS_BOTH``: Record the data sent in both directions. +## Results in the two directions being +## intermixed in the file, in the order the +## data was seen by Bro. +## +## f: The file handle of the file to write the contents to. +## +## Returns: Returns false if *cid* does not point to an active connection, and +## true otherwise. +## +## .. note:: +## +## The data recorded to the file reflects the byte stream, not the +## contents of individual packets. Reordering and duplicates are +## removed. If any data is missing, the recording stops at the +## missing data; this can happen, e.g., due to an +## :bro:id:`ack_above_hole` event. +## +## .. bro:see:: get_contents_file set_record_packets +function set_contents_file%(cid: conn_id, direction: count, f: file%): bool + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_BOOL); + + c->GetRootAnalyzer()->SetContentsFile(direction, f); + return new Val(1, TYPE_BOOL); + %} + +## Returns the file handle of the contents file of a connection. +## +## cid: The connection ID. +## +## direction: Controls what sides of the connection to record. See +## :bro:id:`set_contents_file` for possible values. +## +## Returns: The :bro:type:`file` handle for the contents file of the +## connection identified by *cid*. If the connection exists +## but there is no contents file for *direction*, then the function +## generates an error and returns a file handle to ``stderr``. +## +## .. bro:see:: set_contents_file set_record_packets +function get_contents_file%(cid: conn_id, direction: count%): file + %{ + Connection* c = sessions->FindConnection(cid); + BroFile* f = c ? c->GetRootAnalyzer()->GetContentsFile(direction) : 0; + + if ( f ) + { + Ref(f); + return new Val(f); + } + + // Return some sort of error value. + if ( ! c ) + builtin_error("unknown connection id in get_contents_file()", cid); + else + builtin_error("no contents file for given direction"); + + return new Val(new BroFile(stderr, "-", "w")); + %} diff --git a/src/analyzer/protocol/teredo/CMakeLists.txt b/src/analyzer/protocol/teredo/CMakeLists.txt new file mode 100644 index 0000000000..c9c4a84db6 --- /dev/null +++ b/src/analyzer/protocol/teredo/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro Teredo) +bro_plugin_cc(Teredo.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/analyzer/protocol/teredo/Plugin.cc b/src/analyzer/protocol/teredo/Plugin.cc new file mode 100644 index 0000000000..91de23b318 --- /dev/null +++ b/src/analyzer/protocol/teredo/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "Teredo.h" + +BRO_PLUGIN_BEGIN(Bro, Teredo) + BRO_PLUGIN_DESCRIPTION("Teredo analyzer"); + BRO_PLUGIN_ANALYZER("Teredo", teredo::Teredo_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/Teredo.cc b/src/analyzer/protocol/teredo/Teredo.cc similarity index 98% rename from src/Teredo.cc rename to src/analyzer/protocol/teredo/Teredo.cc index 7794d1cb3b..d81f90d840 100644 --- a/src/Teredo.cc +++ b/src/analyzer/protocol/teredo/Teredo.cc @@ -1,8 +1,14 @@ #include "Teredo.h" +#include "TunnelEncapsulation.h" +#include "Conn.h" #include "IP.h" #include "Reporter.h" +#include "events.bif.h" + +using namespace analyzer::teredo; + void Teredo_Analyzer::Done() { Analyzer::Done(); diff --git a/src/Teredo.h b/src/analyzer/protocol/teredo/Teredo.h similarity index 84% rename from src/Teredo.h rename to src/analyzer/protocol/teredo/Teredo.h index e720d3f37c..0da007187d 100644 --- a/src/Teredo.h +++ b/src/analyzer/protocol/teredo/Teredo.h @@ -1,12 +1,15 @@ -#ifndef Teredo_h -#define Teredo_h +#ifndef ANALYZER_PROTOCOL_TEREDO_TEREDO_H +#define ANALYZER_PROTOCOL_TEREDO_TEREDO_H -#include "Analyzer.h" +#include "analyzer/Analyzer.h" #include "NetVar.h" +#include "Reporter.h" -class Teredo_Analyzer : public Analyzer { +namespace analyzer { namespace teredo { + +class Teredo_Analyzer : public analyzer::Analyzer { public: - Teredo_Analyzer(Connection* conn) : Analyzer(AnalyzerTag::Teredo, conn), + Teredo_Analyzer(Connection* conn) : Analyzer("TEREDO", conn), valid_orig(false), valid_resp(false) {} @@ -18,13 +21,9 @@ public: virtual void DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new Teredo_Analyzer(conn); } - static bool Available() - { return BifConst::Tunnel::enable_teredo && - BifConst::Tunnel::max_depth > 0; } - /** * Emits a weird only if the analyzer has previously been able to * decapsulate a Teredo packet in both directions or if *force* param is @@ -50,7 +49,6 @@ public: } protected: - friend class AnalyzerTimer; void ExpireTimer(double t); bool valid_orig; @@ -93,4 +91,6 @@ protected: const Teredo_Analyzer* analyzer; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/teredo/events.bif b/src/analyzer/protocol/teredo/events.bif new file mode 100644 index 0000000000..62bc7d06cd --- /dev/null +++ b/src/analyzer/protocol/teredo/events.bif @@ -0,0 +1,55 @@ +## Generated for any IPv6 packet encapsulated in a Teredo tunnel. +## See :rfc:`4380` for more information about the Teredo protocol. +## +## outer: The Teredo tunnel connection. +## +## inner: The Teredo-encapsulated IPv6 packet header and transport header. +## +## .. bro:see:: teredo_authentication teredo_origin_indication teredo_bubble +## +## .. note:: Since this event may be raised on a per-packet basis, handling +## it may become particularly expensive for real-time analysis. +event teredo_packet%(outer: connection, inner: teredo_hdr%); + +## Generated for IPv6 packets encapsulated in a Teredo tunnel that +## use the Teredo authentication encapsulation method. +## See :rfc:`4380` for more information about the Teredo protocol. +## +## outer: The Teredo tunnel connection. +## +## inner: The Teredo-encapsulated IPv6 packet header and transport header. +## +## .. bro:see:: teredo_packet teredo_origin_indication teredo_bubble +## +## .. note:: Since this event may be raised on a per-packet basis, handling +## it may become particularly expensive for real-time analysis. +event teredo_authentication%(outer: connection, inner: teredo_hdr%); + +## Generated for IPv6 packets encapsulated in a Teredo tunnel that +## use the Teredo origin indication encapsulation method. +## See :rfc:`4380` for more information about the Teredo protocol. +## +## outer: The Teredo tunnel connection. +## +## inner: The Teredo-encapsulated IPv6 packet header and transport header. +## +## .. bro:see:: teredo_packet teredo_authentication teredo_bubble +## +## .. note:: Since this event may be raised on a per-packet basis, handling +## it may become particularly expensive for real-time analysis. +event teredo_origin_indication%(outer: connection, inner: teredo_hdr%); + +## Generated for Teredo bubble packets. That is, IPv6 packets encapsulated +## in a Teredo tunnel that have a Next Header value of :bro:id:`IPPROTO_NONE`. +## See :rfc:`4380` for more information about the Teredo protocol. +## +## outer: The Teredo tunnel connection. +## +## inner: The Teredo-encapsulated IPv6 packet header and transport header. +## +## .. bro:see:: teredo_packet teredo_authentication teredo_origin_indication +## +## .. note:: Since this event may be raised on a per-packet basis, handling +## it may become particularly expensive for real-time analysis. +event teredo_bubble%(outer: connection, inner: teredo_hdr%); + diff --git a/src/analyzer/protocol/udp/CMakeLists.txt b/src/analyzer/protocol/udp/CMakeLists.txt new file mode 100644 index 0000000000..0c92be60a3 --- /dev/null +++ b/src/analyzer/protocol/udp/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro UDP) +bro_plugin_cc(UDP.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/analyzer/protocol/udp/Plugin.cc b/src/analyzer/protocol/udp/Plugin.cc new file mode 100644 index 0000000000..0dbf0f80ca --- /dev/null +++ b/src/analyzer/protocol/udp/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "analyzer/protocol/udp/UDP.h" + +BRO_PLUGIN_BEGIN(Bro, UDP) + BRO_PLUGIN_DESCRIPTION("UDP Analyzer"); + BRO_PLUGIN_ANALYZER("UDP", udp::UDP_Analyzer); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/UDP.cc b/src/analyzer/protocol/udp/UDP.cc similarity index 97% rename from src/UDP.cc rename to src/analyzer/protocol/udp/UDP.cc index d85cb39edd..3050ea5648 100644 --- a/src/UDP.cc +++ b/src/analyzer/protocol/udp/UDP.cc @@ -6,11 +6,16 @@ #include "Net.h" #include "NetVar.h" -#include "UDP.h" +#include "analyzer/protocol/udp/UDP.h" #include "Reporter.h" +#include "Conn.h" + +#include "events.bif.h" + +using namespace analyzer::udp; UDP_Analyzer::UDP_Analyzer(Connection* conn) -: TransportLayerAnalyzer(AnalyzerTag::UDP, conn) +: TransportLayerAnalyzer("UDP", conn) { conn->EnableStatusUpdateTimer(); conn->SetInactivityTimeout(udp_inactivity_timeout); diff --git a/src/UDP.h b/src/analyzer/protocol/udp/UDP.h similarity index 77% rename from src/UDP.h rename to src/analyzer/protocol/udp/UDP.h index b93d4da97f..bcfee401b0 100644 --- a/src/UDP.h +++ b/src/analyzer/protocol/udp/UDP.h @@ -1,17 +1,19 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef udp_h -#define udp_h +#ifndef ANALYZER_PROTOCOL_UDP_UDP_H +#define ANALYZER_PROTOCOL_UDP_UDP_H -#include "Analyzer.h" +#include "analyzer/Analyzer.h" #include +namespace analyzer { namespace udp { + typedef enum { UDP_INACTIVE, // no packet seen UDP_ACTIVE, // packets seen } UDP_EndpointState; -class UDP_Analyzer : public TransportLayerAnalyzer { +class UDP_Analyzer : public analyzer::TransportLayerAnalyzer { public: UDP_Analyzer(Connection* conn); virtual ~UDP_Analyzer(); @@ -20,11 +22,9 @@ public: virtual void UpdateConnVal(RecordVal *conn_val); - static Analyzer* InstantiateAnalyzer(Connection* conn) + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) { return new UDP_Analyzer(conn); } - static bool Available() { return true; } - protected: virtual void Done(); virtual void DeliverPacket(int len, const u_char* data, bool orig, @@ -47,4 +47,6 @@ private: #define HIST_RESP_CORRUPT_PKT 0x8 }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/udp/events.bif b/src/analyzer/protocol/udp/events.bif new file mode 100644 index 0000000000..394181cf5d --- /dev/null +++ b/src/analyzer/protocol/udp/events.bif @@ -0,0 +1,38 @@ +## Generated for each packet sent by a UDP flow's originator. This a potentially +## expensive event due to the volume of UDP traffic and should be used with +## care. +## +## u: The connection record for the corresponding UDP flow. +## +## .. bro:see:: udp_contents udp_reply udp_session_done +event udp_request%(u: connection%); + +## Generated for each packet sent by a UDP flow's responder. This a potentially +## expensive event due to the volume of UDP traffic and should be used with +## care. +## +## u: The connection record for the corresponding UDP flow. +## +## .. bro:see:: udp_contents udp_request udp_session_done +event udp_reply%(u: connection%); + +## Generated for UDP packets to pass on their payload. As the number of UDP +## packets can be very large, this event is normally raised only for those on +## ports configured in :bro:id:`udp_content_delivery_ports_orig` (for packets +## sent by the flow's originator) or :bro:id:`udp_content_delivery_ports_resp` +## (for packets sent by the flow's responder). However, delivery can be enabled +## for all UDP request and reply packets by setting +## :bro:id:`udp_content_deliver_all_orig` or +## :bro:id:`udp_content_deliver_all_resp`, respectively. Note that this +## event is also raised for all matching UDP packets, including empty ones. +## +## u: The connection record for the corresponding UDP flow. +## +## is_orig: True if the event is raised for the originator side. +## +## contents: TODO. +## +## .. bro:see:: udp_reply udp_request udp_session_done +## udp_content_deliver_all_orig udp_content_deliver_all_resp +## udp_content_delivery_ports_orig udp_content_delivery_ports_resp +event udp_contents%(u: connection, is_orig: bool, contents: string%); diff --git a/src/analyzer/protocol/zip/CMakeLists.txt b/src/analyzer/protocol/zip/CMakeLists.txt new file mode 100644 index 0000000000..814119f9f7 --- /dev/null +++ b/src/analyzer/protocol/zip/CMakeLists.txt @@ -0,0 +1,9 @@ + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro ZIP) +bro_plugin_cc(ZIP.cc Plugin.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/analyzer/protocol/zip/Plugin.cc b/src/analyzer/protocol/zip/Plugin.cc new file mode 100644 index 0000000000..b55accccb3 --- /dev/null +++ b/src/analyzer/protocol/zip/Plugin.cc @@ -0,0 +1,10 @@ + +#include "plugin/Plugin.h" + +#include "ZIP.h" + +BRO_PLUGIN_BEGIN(Bro, ZIP) + BRO_PLUGIN_DESCRIPTION("Generic ZIP support analyzer"); + BRO_PLUGIN_ANALYZER_BARE("ZIP"); + BRO_PLUGIN_BIF_FILE(events); +BRO_PLUGIN_END diff --git a/src/ZIP.cc b/src/analyzer/protocol/zip/ZIP.cc similarity index 90% rename from src/ZIP.cc rename to src/analyzer/protocol/zip/ZIP.cc index 0ebe93abe6..132515f29a 100644 --- a/src/ZIP.cc +++ b/src/analyzer/protocol/zip/ZIP.cc @@ -2,8 +2,12 @@ #include "ZIP.h" +#include "events.bif.h" + +using namespace analyzer::zip; + ZIP_Analyzer::ZIP_Analyzer(Connection* conn, bool orig, Method arg_method) -: TCP_SupportAnalyzer(AnalyzerTag::Zip, conn, orig) +: tcp::TCP_SupportAnalyzer("ZIP", conn, orig) { zip = 0; zip_status = Z_OK; @@ -44,7 +48,7 @@ void ZIP_Analyzer::Done() void ZIP_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { - TCP_SupportAnalyzer::DeliverStream(len, data, orig); + tcp::TCP_SupportAnalyzer::DeliverStream(len, data, orig); if ( ! len || zip_status != Z_OK ) return; diff --git a/src/ZIP.h b/src/analyzer/protocol/zip/ZIP.h similarity index 65% rename from src/ZIP.h rename to src/analyzer/protocol/zip/ZIP.h index 6a8a180d1a..b284529d86 100644 --- a/src/ZIP.h +++ b/src/analyzer/protocol/zip/ZIP.h @@ -1,14 +1,16 @@ // See the file "COPYING" in the main distribution directory for copyright. -#ifndef zip_h -#define zip_h +#ifndef ANALYZER_PROTOCOL_ZIP_ZIP_H +#define ANALYZER_PROTOCOL_ZIP_ZIP_H #include "config.h" #include "zlib.h" -#include "TCP.h" +#include "analyzer/protocol/tcp/TCP.h" -class ZIP_Analyzer : public TCP_SupportAnalyzer { +namespace analyzer { namespace zip { + +class ZIP_Analyzer : public tcp::TCP_SupportAnalyzer { public: enum Method { GZIP, DEFLATE }; @@ -26,4 +28,6 @@ protected: Method method; }; +} } // namespace analyzer::* + #endif diff --git a/src/analyzer/protocol/zip/events.bif b/src/analyzer/protocol/zip/events.bif new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/binpac_bro.h b/src/binpac_bro.h index dcdbe94f57..5902c52113 100644 --- a/src/binpac_bro.h +++ b/src/binpac_bro.h @@ -1,20 +1,24 @@ #ifndef binpac_bro_h #define binpac_bro_h -class Analyzer; +class Connection; class Val; class PortVal; +namespace analyzer { class Analyzer; } + #include "util.h" -#include "Analyzer.h" #include "Val.h" #include "event.bif.func_h" +#include "TunnelEncapsulation.h" +#include "analyzer/Analyzer.h" +#include "Conn.h" #include "binpac.h" namespace binpac { -typedef Analyzer* BroAnalyzer; +typedef analyzer::Analyzer* BroAnalyzer; typedef Val* BroVal; typedef PortVal* BroPortVal; typedef StringVal* BroStringVal; @@ -31,6 +35,4 @@ inline StringVal* bytestring_to_val(const_bytestring const &str) } // namespace binpac -extern int FLAGS_use_binpac; - #endif diff --git a/src/bro-bif.h b/src/bro-bif.h new file mode 100644 index 0000000000..24312e4753 --- /dev/null +++ b/src/bro-bif.h @@ -0,0 +1,11 @@ + +#ifndef BRO_BIF_H +#define BRO_BIF_H + +// Headers to include by generated BiF code. +#include "analyzer/Analyzer.h" +#include "Conn.h" +#include "NetVar.h" +#include "Event.h" + +#endif diff --git a/src/bro.bif b/src/bro.bif index 26fe16d821..efb913bbf7 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -21,7 +21,6 @@ using namespace std; -RecordType* ftp_port; RecordType* net_stats; RecordType* bro_resources; RecordType* matcher_stats; @@ -1783,26 +1782,6 @@ function get_matcher_stats%(%): matcher_stats return r; %} -## Returns statistics about TCP gaps. -## -## Returns: A record with TCP gap statistics. -## -## .. bro:see:: do_profiling -## net_stats -## resource_usage -## dump_rule_stats -## get_matcher_stats -function get_gap_summary%(%): gap_info - %{ - RecordVal* r = new RecordVal(gap_info); - r->Assign(0, new Val(tot_ack_events, TYPE_COUNT)); - r->Assign(1, new Val(tot_ack_bytes, TYPE_COUNT)); - r->Assign(2, new Val(tot_gap_events, TYPE_COUNT)); - r->Assign(3, new Val(tot_gap_bytes, TYPE_COUNT)); - - return r; - %} - ## Generates a table of the size of all global variables. The table index is ## the variable name and the value is the variable size in bytes. ## @@ -2629,273 +2608,6 @@ function addr_to_ptr_name%(a: addr%): string return new StringVal(a->AsAddr().PtrName().c_str()); %} - -%%{ -static Val* parse_port(const char* line) - { - RecordVal* r = new RecordVal(ftp_port); - - int bytes[6]; - if ( line && sscanf(line, "%d,%d,%d,%d,%d,%d", - &bytes[0], &bytes[1], &bytes[2], - &bytes[3], &bytes[4], &bytes[5]) == 6 ) - { - int good = 1; - - for ( int i = 0; i < 6; ++i ) - if ( bytes[i] < 0 || bytes[i] > 255 ) - { - good = 0; - break; - } - - uint32 addr = (bytes[0] << 24) | (bytes[1] << 16) | - (bytes[2] << 8) | bytes[3]; - uint32 port = (bytes[4] << 8) | bytes[5]; - - // Since port is unsigned, no need to check for < 0. - if ( port > 65535 ) - { - port = 0; - good = 0; - } - - r->Assign(0, new AddrVal(htonl(addr))); - r->Assign(1, new PortVal(port, TRANSPORT_TCP)); - r->Assign(2, new Val(good, TYPE_BOOL)); - } - else - { - r->Assign(0, new AddrVal(uint32(0))); - r->Assign(1, new PortVal(0, TRANSPORT_TCP)); - r->Assign(2, new Val(0, TYPE_BOOL)); - } - - return r; - } - -static Val* parse_eftp(const char* line) - { - RecordVal* r = new RecordVal(ftp_port); - - int net_proto = 0; // currently not used - IPAddr addr; // unspecified IPv6 address (all 128 bits zero) - int port = 0; - int good = 0; - - if ( line ) - { - while ( isspace(*line) ) // skip whitespace - ++line; - - char delimiter = *line; - char* next_delim; - - if ( *line ) - { - good = 1; - ++line; // skip delimiter - - net_proto = strtol(line, &next_delim, 10); - if ( *next_delim != delimiter ) - good = 0; - - line = next_delim; - if ( *line ) - ++line; - - if ( *line && *line != delimiter ) - { - const char* nptr = strchr(line, delimiter); - if ( nptr == NULL ) - { - nptr = line + strlen(line); - good = 0; - } - - string s(line, nptr-line); // extract IP address - IPAddr tmp(s); - // on error, "tmp" will have all 128 bits zero - if ( tmp == addr ) - good = 0; - - addr = tmp; - } - - line = strchr(line, delimiter); - - if ( line != NULL ) - { - ++line; // now the port - port = strtol(line, &next_delim, 10); - if ( *next_delim != delimiter ) - good = 0; - } - - } - - } - - r->Assign(0, new AddrVal(addr)); - r->Assign(1, new PortVal(port, TRANSPORT_TCP)); - r->Assign(2, new Val(good, TYPE_BOOL)); - - return r; - } -%%} - -## Converts a string representation of the FTP PORT command to an ``ftp_port``. -## -## s: The string of the FTP PORT command, e.g., ``"10,0,0,1,4,31"``. -## -## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` -## -## .. bro:see:: parse_eftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port -function parse_ftp_port%(s: string%): ftp_port - %{ - return parse_port(s->CheckString()); - %} - -## Converts a string representation of the FTP EPRT command to an ``ftp_port``. -## See `RFC 2428 `_. -## The format is ``EPRT``, -## where ```` is a delimiter in the ASCII range 33-126 (usually ``|``). -## -## s: The string of the FTP EPRT command, e.g., ``"|1|10.0.0.1|1055|"``. -## -## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` -## -## .. bro:see:: parse_ftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port -function parse_eftp_port%(s: string%): ftp_port - %{ - return parse_eftp(s->CheckString()); - %} - -## Converts the result of the FTP PASV command to an ``ftp_port``. -## -## str: The string containing the result of the FTP PASV command. -## -## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` -## -## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_epsv fmt_ftp_port -function parse_ftp_pasv%(str: string%): ftp_port - %{ - const char* s = str->CheckString(); - const char* line = strchr(s, '('); - if ( line ) - ++line; // move past '(' - else if ( (line = strstr(s, "PORT")) ) - line += 5; // Skip over - else if ( (line = strchr(s, ',')) ) - { // Look for comma-separated list. - while ( --line >= s && isdigit(*line) ) - ; // Back up over preceding digits. - ++line; // now points to first digit, or beginning of s - } - - return parse_port(line); - %} - -## Converts the result of the FTP EPSV command to an ``ftp_port``. -## See `RFC 2428 `_. -## The format is `` ()``, where ```` is a -## delimiter in the ASCII range 33-126 (usually ``|``). -## -## str: The string containing the result of the FTP EPSV command. -## -## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` -## -## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv fmt_ftp_port -function parse_ftp_epsv%(str: string%): ftp_port - %{ - const char* s = str->CheckString(); - const char* line = strchr(s, '('); - if ( line ) - ++line; // move past '(' - return parse_eftp(line); - %} - -## Formats an IP address and TCP port as an FTP PORT command. For example, -## ``10.0.0.1`` and ``1055/tcp`` yields ``"10,0,0,1,4,31"``. -## -## a: The IP address. -## -## p: The TCP port. -## -## Returns: The FTP PORT string. -## -## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv parse_ftp_epsv -function fmt_ftp_port%(a: addr, p: port%): string - %{ - const uint32* addr; - int len = a->AsAddr().GetBytes(&addr); - if ( len == 1 ) - { - uint32 a = ntohl(addr[0]); - uint32 pn = p->Port(); - return new StringVal(fmt("%d,%d,%d,%d,%d,%d", - a >> 24, (a >> 16) & 0xff, - (a >> 8) & 0xff, a & 0xff, - pn >> 8, pn & 0xff)); - } - else - { - builtin_error("conversion of non-IPv4 address in fmt_ftp_port", - @ARG@[0]); - return new StringVal(""); - } - %} - -## Decode a NetBIOS name. See http://support.microsoft.com/kb/194203. -## -## name: The encoded NetBIOS name, e.g., ``"FEEIEFCAEOEFFEECEJEPFDCAEOEBENEF"``. -## -## Returns: The decoded NetBIOS name, e.g., ``"THE NETBIOS NAME"``. -## -## .. bro:see:: decode_netbios_name_type -function decode_netbios_name%(name: string%): string - %{ - char buf[16]; - char result[16]; - const u_char* s = name->Bytes(); - int i, j; - - for ( i = 0, j = 0; i < 16; ++i ) - { - char c0 = (j < name->Len()) ? toupper(s[j++]) : 'A'; - char c1 = (j < name->Len()) ? toupper(s[j++]) : 'A'; - buf[i] = ((c0 - 'A') << 4) + (c1 - 'A'); - } - - for ( i = 0; i < 15; ++i ) - { - if ( isalnum(buf[i]) || ispunct(buf[i]) || - // \x01\x02 is seen in at least one case as the first two bytes. - // I think that any \x01 and \x02 should always be passed through. - buf[i] < 3 ) - result[i] = buf[i]; - else - break; - } - - return new StringVal(i, result); - %} - -## Converts a NetBIOS name type to its corresponding numeric value. -## See http://support.microsoft.com/kb/163409. -## -## name: The NetBIOS name type. -## -## Returns: The numeric value of *name*. -## -## .. bro:see:: decode_netbios_name -function decode_netbios_name_type%(name: string%): count - %{ - const u_char* s = name->Bytes(); - char return_val = ((toupper(s[30]) - 'A') << 4) + (toupper(s[31]) - 'A'); - return new Val(return_val, TYPE_COUNT); - %} - ## Converts a string of bytes into its hexadecimal representation. ## For example, ``"04"`` would be converted to ``"3034"``. ## @@ -3002,8 +2714,6 @@ function decode_base64_custom%(s: string, a: string%): string %} %%{ -#include "DCE_RPC.h" - typedef struct { uint32 time_low; uint16 time_mid; @@ -3415,8 +3125,6 @@ function lookup_connection%(cid: conn_id%): connection %} %%{ -#include "HTTP.h" - const char* conn_id_string(Val* c) { Val* id = (*(c->AsRecord()))[0]; @@ -3432,58 +3140,6 @@ const char* conn_id_string(Val* c) } %%} -## Skips the data of the HTTP entity. -## -## c: The HTTP connection. -## -## is_orig: If true, the client data is skipped, and the server data otherwise. -## -## .. bro:see:: skip_smtp_data -function skip_http_entity_data%(c: connection, is_orig: bool%): any - %{ - AnalyzerID id = mgr.CurrentAnalyzer(); - if ( id ) - { - Analyzer* ha = c->FindAnalyzer(id); - - if ( ha ) - { - if ( ha->GetTag() == AnalyzerTag::HTTP ) - static_cast(ha)->SkipEntityData(is_orig); - else - reporter->Error("non-HTTP analyzer associated with connection record"); - } - else - reporter->Error("could not find analyzer for skip_http_entity_data"); - - } - else - reporter->Error("no analyzer associated with connection record"); - - return 0; - %} - -## Unescapes all characters in a URI (decode every ``%xx`` group). -## -## URI: The URI to unescape. -## -## Returns: The unescaped URI with all ``%xx`` groups decoded. -## -## .. note:: -## -## Unescaping reserved characters may cause loss of information. RFC 2396: -## A URI is always in an "escaped" form, since escaping or unescaping a -## completed URI might change its semantics. Normally, the only time -## escape encodings can safely be made is when the URI is being created -## from its component parts. -function unescape_URI%(URI: string%): string - %{ - const u_char* line = URI->Bytes(); - const u_char* const line_end = line + URI->Len(); - - return new StringVal(unescape_URI(line, line_end, 0)); - %} - ## Writes the current packet to a file. ## ## file_name: The name of the file to write the packet to. @@ -3931,138 +3587,6 @@ function lookup_asn%(a: addr%) : count return new Val(0, TYPE_COUNT); %} -%%{ -#include -#include -#include - -// This is the indexed map of X509 certificate stores. -static map x509_stores; - -// ### NOTE: while d2i_X509 does not take a const u_char** pointer, -// here we assume d2i_X509 does not write to , so it is safe to -// convert data to a non-const pointer. Could some X509 guru verify -// this? - -X509* d2i_X509_(X509** px, const u_char** in, int len) - { -#ifdef OPENSSL_D2I_X509_USES_CONST_CHAR - return d2i_X509(px, in, len); -#else - return d2i_X509(px, (u_char**)in, len); -#endif - } - -%%} - - -## Verifies a certificate. -## -## der_cert: The X.509 certificate in DER format. -## -## cert_stack: Specifies a certificate chain to validate against, with index 0 -## typically being the root CA. Bro uses the Mozilla root CA list -## by default. -## -## root_certs: A list of additional root certificates that extends -## *cert_stack*. -## -## Returns: A status code of the verification which can be converted into an -## ASCII string via :bro:id:`x509_err2str`. -## -## .. bro:see:: x509_err2str -function x509_verify%(der_cert: string, cert_stack: string_vec, root_certs: table_string_of_string%): count - %{ - X509_STORE* ctx = 0; - int i = 0; - - // If this certificate store was built previously, just reuse the old one. - if ( x509_stores.count(root_certs) > 0 ) - ctx = x509_stores[root_certs]; - - if ( ! ctx ) // lookup to see if we have this one built already! - { - ctx = X509_STORE_new(); - TableVal* root_certs2 = root_certs->AsTableVal(); - ListVal* idxs = root_certs2->ConvertToPureList(); - - // Build the validation store - for ( i = 0; i < idxs->Length(); ++i ) - { - Val* key = idxs->Index(i); - StringVal *sv = root_certs2->Lookup(key)->AsStringVal(); - const uint8* data = sv->Bytes(); - X509* x = d2i_X509_(NULL, &data, sv->Len()); - if ( ! x ) - { - builtin_error(fmt("Root CA error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); - return new Val((uint64) ERR_get_error(), TYPE_COUNT); - } - X509_STORE_add_cert(ctx, x); - } - delete idxs; - - // Save the newly constructed certificate store into the cacheing map. - x509_stores[root_certs] = ctx; - } - - const uint8 *cert_data = der_cert->Bytes(); - X509* cert = d2i_X509_(NULL, &cert_data, der_cert->Len()); - if ( ! cert ) - { - builtin_error(fmt("Certificate error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); - return new Val((uint64) ERR_get_error(), TYPE_COUNT); - } - - STACK_OF(X509)* untrusted_certs = sk_X509_new_null(); - if ( ! untrusted_certs ) - { - builtin_error(fmt("Untrusted certificate stack initialization error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); - return new Val((uint64) ERR_get_error(), TYPE_COUNT); - } - - VectorVal *cert_stack_vec = cert_stack->AsVectorVal(); - for ( i = 0; i < (int) cert_stack_vec->Size(); ++i ) - { - StringVal *sv = cert_stack_vec->Lookup(i)->AsStringVal(); - const uint8 *data = sv->Bytes(); - X509* x = d2i_X509_(NULL, &data, sv->Len()); - if ( ! x ) - { - X509_free(cert); - sk_X509_pop_free(untrusted_certs, X509_free); - builtin_error(fmt("Untrusted certificate stack creation error: %s", ERR_error_string(ERR_peek_last_error(),NULL))); - return new Val((uint64) ERR_get_error(), TYPE_COUNT); - } - sk_X509_push(untrusted_certs, x); - } - - X509_STORE_CTX csc; - X509_STORE_CTX_init(&csc, ctx, cert, untrusted_certs); - X509_STORE_CTX_set_time(&csc, 0, (time_t) network_time); - - int result = X509_verify_cert(&csc); - X509_STORE_CTX_cleanup(&csc); - - if ( untrusted_certs ) - sk_X509_pop_free(untrusted_certs, X509_free); - X509_free(cert); - - return new Val((uint64) csc.error, TYPE_COUNT); - %} - -## Converts a certificate verification error code into an ASCII string. -## -## err_num: The error code. -## -## Returns: A string representation of *err_num*. -## -## .. bro:see:: x509_verify -function x509_err2str%(err_num: count%): string - %{ - return new StringVal(X509_verify_cert_error_string(err_num)); - %} - ## Converts UNIX file permissions given by a mode to an ASCII string. ## ## mode: The permissions (an octal number like 0644 converted to decimal). @@ -4162,36 +3686,9 @@ function file_mode%(mode: count%): string # =========================================================================== %%{ -#include "DPM.h" +#include "analyzer/Manager.h" %%} -## Schedules an analyzer for a future connection from a given IP address and -## port. The function ignores the scheduling request if the connection did -## not occur within the specified time interval. -## -## orig: The IP address originating a connection in the future. -## -## resp: The IP address responding to a connection from *orig*. -## -## resp_p: The destination port at *resp*. -## -## analyzer: The analyzer ID. -## -## tout: The timeout interval after which to ignore the scheduling request. -## -## Returns: True (unconditionally). -## -## .. bro:see:: disable_analyzer analyzer_name -## -## .. todo:: The return value should be changed to any. -function expect_connection%(orig: addr, resp: addr, resp_p: port, - analyzer: count, tout: interval%) : any - %{ - dpm->ExpectConnection(orig->AsAddr(), resp->AsAddr(), resp_p->Port(), - resp_p->PortType(), (AnalyzerTag::Tag) analyzer, tout, 0); - return new Val(1, TYPE_BOOL); - %} - ## Disables the analyzer which raised the current event (if the analyzer ## belongs to the given connection). ## @@ -4202,7 +3699,7 @@ function expect_connection%(orig: addr, resp: addr, resp_p: port, ## Returns: True if the connection identified by *cid* exists and has analyzer ## *aid*. ## -## .. bro:see:: expect_connection analyzer_name +## .. bro:see:: Analyzer::schedule_analyzer Analyzer::name function disable_analyzer%(cid: conn_id, aid: count%) : bool %{ Connection* c = sessions->FindConnection(cid); @@ -4212,7 +3709,7 @@ function disable_analyzer%(cid: conn_id, aid: count%) : bool return new Val(0, TYPE_BOOL); } - Analyzer* a = c->FindAnalyzer(aid); + analyzer::Analyzer* a = c->FindAnalyzer(aid); if ( ! a ) { reporter->Error("connection does not have analyzer specified to disable"); @@ -4223,18 +3720,6 @@ function disable_analyzer%(cid: conn_id, aid: count%) : bool return new Val(1, TYPE_BOOL); %} -## Translate an analyzer type to an ASCII string. -## -## aid: The analyzer ID. -## -## Returns: The analyzer *aid* as string. -## -## .. bro:see:: expect_connection disable_analyzer current_analyzer -function analyzer_name%(aid: count%) : string - %{ - return new StringVal(Analyzer::GetTagName((AnalyzerTag::Tag) aid)); - %} - ## Informs Bro that it should skip any further processing of the contents of ## a given connection. In particular, Bro will refrain from reassembling the ## TCP byte stream and from generating events relating to any analyzers that @@ -4289,81 +3774,6 @@ function set_record_packets%(cid: conn_id, do_record: bool%): bool return new Val(1, TYPE_BOOL); %} -## Associates a file handle with a connection for writing TCP byte stream -## contents. -## -## cid: The connection ID. -## -## direction: Controls what sides of the connection to record. The argument can -## take one of the four values: -## -## - ``CONTENTS_NONE``: Stop recording the connection's content. -## - ``CONTENTS_ORIG``: Record the data sent by the connection -## originator (often the client). -## - ``CONTENTS_RESP``: Record the data sent by the connection -## responder (often the server). -## - ``CONTENTS_BOTH``: Record the data sent in both directions. -## Results in the two directions being -## intermixed in the file, in the order the -## data was seen by Bro. -## -## f: The file handle of the file to write the contents to. -## -## Returns: Returns false if *cid* does not point to an active connection, and -## true otherwise. -## -## .. note:: -## -## The data recorded to the file reflects the byte stream, not the -## contents of individual packets. Reordering and duplicates are -## removed. If any data is missing, the recording stops at the -## missing data; this can happen, e.g., due to an -## :bro:id:`ack_above_hole` event. -## -## .. bro:see:: get_contents_file set_record_packets -function set_contents_file%(cid: conn_id, direction: count, f: file%): bool - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_BOOL); - - c->GetRootAnalyzer()->SetContentsFile(direction, f); - return new Val(1, TYPE_BOOL); - %} - -## Returns the file handle of the contents file of a connection. -## -## cid: The connection ID. -## -## direction: Controls what sides of the connection to record. See -## :bro:id:`set_contents_file` for possible values. -## -## Returns: The :bro:type:`file` handle for the contents file of the -## connection identified by *cid*. If the connection exists -## but there is no contents file for *direction*, then the function -## generates an error and returns a file handle to ``stderr``. -## -## .. bro:see:: set_contents_file set_record_packets -function get_contents_file%(cid: conn_id, direction: count%): file - %{ - Connection* c = sessions->FindConnection(cid); - BroFile* f = c ? c->GetRootAnalyzer()->GetContentsFile(direction) : 0; - - if ( f ) - { - Ref(f); - return new Val(f); - } - - // Return some sort of error value. - if ( ! c ) - builtin_error("unknown connection id in get_contents_file()", cid); - else - builtin_error("no contents file for given direction"); - - return new Val(new BroFile(stderr, "-", "w")); - %} - ## Sets an individual inactivity timeout for a connection and thus ## overrides the global inactivity timeout. ## @@ -4384,170 +3794,6 @@ function set_inactivity_timeout%(cid: conn_id, t: interval%): interval return new Val(old_timeout, TYPE_INTERVAL); %} -## Returns the state of the given login (Telnet or Rlogin) connection. -## -## cid: The connection ID. -## -## Returns: False if the connection is not active or is not tagged as a -## login analyzer. Otherwise the function returns the state, which can -## be one of: -## -## - ``LOGIN_STATE_AUTHENTICATE``: The connection is in its -## initial authentication dialog. -## - ``LOGIN_STATE_LOGGED_IN``: The analyzer believes the user has -## successfully authenticated. -## - ``LOGIN_STATE_SKIP``: The analyzer has skipped any further -## processing of the connection. -## - ``LOGIN_STATE_CONFUSED``: The analyzer has concluded that it -## does not correctly know the state of the connection, and/or -## the username associated with it. -## -## .. bro:see:: set_login_state -function get_login_state%(cid: conn_id%): count - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_BOOL); - - Analyzer* la = c->FindAnalyzer(AnalyzerTag::Login); - if ( ! la ) - return new Val(0, TYPE_BOOL); - - return new Val(int(static_cast(la)->LoginState()), - TYPE_COUNT); - %} - -## Sets the login state of a connection with a login analyzer. -## -## cid: The connection ID. -## -## new_state: The new state of the login analyzer. See -## :bro:id:`get_login_state` for possible values. -## -## Returns: Returns false if *cid* is not an active connection -## or is not tagged as a login analyzer, and true otherwise. -## -## .. bro:see:: get_login_state -function set_login_state%(cid: conn_id, new_state: count%): bool - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_BOOL); - - Analyzer* la = c->FindAnalyzer(AnalyzerTag::Login); - if ( ! la ) - return new Val(0, TYPE_BOOL); - - static_cast(la)->SetLoginState(login_state(new_state)); - return new Val(1, TYPE_BOOL); - %} - -%%{ -#include "TCP.h" -%%} - -## Get the originator sequence number of a TCP connection. Sequence numbers -## are absolute (i.e., they reflect the values seen directly in packet headers; -## they are not relative to the beginning of the connection). -## -## cid: The connection ID. -## -## Returns: The highest sequence number sent by a connection's originator, or 0 -## if *cid* does not point to an active TCP connection. -## -## .. bro:see:: get_resp_seq -function get_orig_seq%(cid: conn_id%): count - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_COUNT); - - if ( c->ConnTransport() != TRANSPORT_TCP ) - return new Val(0, TYPE_COUNT); - - Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP); - if ( tc ) - return new Val(static_cast(tc)->OrigSeq(), - TYPE_COUNT); - else - { - reporter->Error("connection does not have TCP analyzer"); - return new Val(0, TYPE_COUNT); - } - %} - -## Get the responder sequence number of a TCP connection. Sequence numbers -## are absolute (i.e., they reflect the values seen directly in packet headers; -## they are not relative to the beginning of the connection). -## -## cid: The connection ID. -## -## Returns: The highest sequence number sent by a connection's responder, or 0 -## if *cid* does not point to an active TCP connection. -## -## .. bro:see:: get_orig_seq -function get_resp_seq%(cid: conn_id%): count - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_COUNT); - - if ( c->ConnTransport() != TRANSPORT_TCP ) - return new Val(0, TYPE_COUNT); - - Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP); - if ( tc ) - return new Val(static_cast(tc)->RespSeq(), - TYPE_COUNT); - else - { - reporter->Error("connection does not have TCP analyzer"); - return new Val(0, TYPE_COUNT); - } - %} - -%%{ -#include "SMTP.h" -%%} - -## Skips SMTP data until the next email in a connection. -## -## c: The SMTP connection. -## -## .. bro:see:: skip_http_entity_data -function skip_smtp_data%(c: connection%): any - %{ - Analyzer* sa = c->FindAnalyzer(AnalyzerTag::SMTP); - if ( sa ) - static_cast(sa)->SkipData(); - return 0; - %} - -## Enables all event handlers in a given group. One can tag event handlers with -## the :bro:attr:`&group` attribute to logically group them together, e.g, -## ``event foo() &group="bar"``. This function enables all event handlers that -## belong to such a group. -## -## group: The group. -## -## .. bro:see:: disable_event_group -function enable_event_group%(group: string%) : any - %{ - event_registry->EnableGroup(group->CheckString(), true); - return 0; - %} - -## Disables all event handlers in a given group. -## -## group: The group. -## -## .. bro:see:: enable_event_group -function disable_event_group%(group: string%) : any - %{ - event_registry->EnableGroup(group->CheckString(), false); - return 0; - %} - # =========================================================================== # # Files and Directories diff --git a/src/builtin-func.l b/src/builtin-func.l index fa9915077f..5d053c555d 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -28,7 +28,7 @@ int check_c_mode(int t) WS [ \t]+ OWS [ \t]* /* Note, bifcl only accepts a single "::" in IDs while the policy - layer acceptes multiple. (But the policy layer doesn't have + layer acceptes multiple. (But the policy layer doesn't have a hierachy. */ IDCOMPONENT [A-Za-z_][A-Za-z_0-9]* ID {IDCOMPONENT}(::{IDCOMPONENT})? @@ -144,6 +144,9 @@ int yywrap() extern int yyparse(); char* input_filename = 0; +char* input_filename_with_path = 0; +char* plugin = 0; +int alternative_mode = 0; FILE* fp_bro_init = 0; FILE* fp_func_def = 0; @@ -175,15 +178,124 @@ FILE* open_output_file(const char* surfix) return fp; } +void usage() + { + fprintf(stderr, "usage: bifcl [-p] *.bif\n"); + exit(1); + } + +void init_alternative_mode() + { + fp_bro_init = open_output_file("bro"); + fp_func_h = open_output_file("h"); + fp_func_def = open_output_file("cc"); + fp_func_init = open_output_file("init.cc"); + + fp_netvar_h = fp_func_h; + fp_netvar_def = fp_func_def; + fp_netvar_init = fp_func_init; + + int n = 1024 + strlen(input_filename); + char auto_gen_comment[n]; + + snprintf(auto_gen_comment, n, + "This file was automatically generated by bifcl from %s (%s mode).", + input_filename_with_path, plugin ? "plugin" : "alternative"); + + fprintf(fp_bro_init, "# %s\n\n", auto_gen_comment); + fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); + fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); + fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); + + static char guard[1024]; + getcwd(guard, sizeof(guard)); + strncat(guard, "/", sizeof(guard)); + strncat(guard, input_filename, sizeof(guard)); + + for ( char* p = guard; *p; p++ ) + { + if ( strchr("/.-", *p) ) + *p = '_'; + } + + fprintf(fp_func_h, "#if defined(BRO_IN_NETVAR) || ! defined(%s)\n", guard); + + fprintf(fp_func_h, "#ifndef BRO_IN_NETVAR\n"); + fprintf(fp_func_h, "#ifndef %s\n", guard); + fprintf(fp_func_h, "#define %s\n", guard); + fprintf(fp_func_h, "#include \"bro-bif.h\"\n"); + fprintf(fp_func_h, "#endif\n"); + fprintf(fp_func_h, "#endif\n"); + fprintf(fp_func_h, "\n"); + + fprintf(fp_func_def, "\n"); + fprintf(fp_func_def, "#include \"%s.h\"\n", input_filename); + fprintf(fp_func_def, "\n"); + + static char name[1024]; + strncpy(name, input_filename, sizeof(name)); + char* dot = strchr(name, '.'); + if ( dot ) + *dot = '\0'; + + if ( plugin ) + { + fprintf(fp_func_init, "\n"); + fprintf(fp_func_init, "#include \n"); + fprintf(fp_func_init, "#include \n"); + fprintf(fp_func_init, "#include \"%s.h\"\n", input_filename); + fprintf(fp_func_init, "\n"); + fprintf(fp_func_init, "namespace plugin { namespace %s {\n", plugin); + fprintf(fp_func_init, "\n"); + fprintf(fp_func_init, "std::list > __bif_%s_init()\n", name); + fprintf(fp_func_init, "\t{\n"); + fprintf(fp_func_init, "\tstd::list > bifs;\n"); + fprintf(fp_func_init, "\n"); + } + } + +void finish_alternative_mode() + { + fprintf(fp_func_h, "\n"); + fprintf(fp_func_h, "#endif\n"); + + if ( plugin ) + { + fprintf(fp_func_init, "\n"); + fprintf(fp_func_init, "\treturn bifs;\n"); + fprintf(fp_func_init, "\t}\n"); + fprintf(fp_func_init, "} }\n"); + fprintf(fp_func_init, "\n"); + } + } int main(int argc, char* argv[]) { - for ( int i = 1; i < argc; i++ ) + char opt; + + while ( (opt = getopt(argc, argv, "p:s")) != -1 ) + { + switch ( opt ) { + case 'p': + alternative_mode = 1; + plugin = optarg; + break; + + case 's': + alternative_mode = 1; + break; + + default: + usage(); + } + } + + for ( int i = optind; i < argc; i++ ) { FILE* fp_input; char* slash; - input_filename = argv[i]; + input_filename = input_filename_with_path = argv[i]; slash = strrchr(input_filename, '/'); if ( (fp_input = fopen(input_filename, "r")) == NULL ) @@ -196,17 +308,41 @@ int main(int argc, char* argv[]) if ( slash ) input_filename = slash + 1; - fp_bro_init = open_output_file("bro"); - fp_func_h = open_output_file("func_h"); - fp_func_def = open_output_file("func_def"); - fp_func_init = open_output_file("func_init"); - fp_netvar_h = open_output_file("netvar_h"); - fp_netvar_def = open_output_file("netvar_def"); - fp_netvar_init = open_output_file("netvar_init"); + if ( ! alternative_mode ) + { + fp_bro_init = open_output_file("bro"); + fp_func_h = open_output_file("func_h"); + fp_func_def = open_output_file("func_def"); + fp_func_init = open_output_file("func_init"); + fp_netvar_h = open_output_file("netvar_h"); + fp_netvar_def = open_output_file("netvar_def"); + fp_netvar_init = open_output_file("netvar_init"); + + int n = 1024 + strlen(input_filename); + char auto_gen_comment[n]; + + snprintf(auto_gen_comment, n, + "This file was automatically generated by bifcl from %s.", + input_filename); + + fprintf(fp_bro_init, "# %s\n\n", auto_gen_comment); + fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); + fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); + fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); + fprintf(fp_netvar_def, "// %s\n\n", auto_gen_comment); + fprintf(fp_netvar_h, "// %s\n\n", auto_gen_comment); + fprintf(fp_netvar_init, "// %s\n\n", auto_gen_comment); + } + + else + init_alternative_mode(); yy_switch_to_buffer(yy_create_buffer(fp_input, YY_BUF_SIZE)); yyparse(); + if ( alternative_mode ) + finish_alternative_mode(); + fclose(fp_input); close_all_output_files(); @@ -226,9 +362,13 @@ void close_all_output_files(void) close_if_open(&fp_func_h); close_if_open(&fp_func_def); close_if_open(&fp_func_init); - close_if_open(&fp_netvar_h); - close_if_open(&fp_netvar_def); - close_if_open(&fp_netvar_init); + + if ( ! alternative_mode ) + { + close_if_open(&fp_netvar_h); + close_if_open(&fp_netvar_def); + close_if_open(&fp_netvar_init); + } } void remove_file(const char *surfix) @@ -239,7 +379,7 @@ void remove_file(const char *surfix) unlink(fn); } -void err_exit(void) +void err_exit(void) { close_all_output_files(); /* clean up. remove all output files we've generated so far */ diff --git a/src/builtin-func.y b/src/builtin-func.y index 54ec5a29f6..662256b8d6 100644 --- a/src/builtin-func.y +++ b/src/builtin-func.y @@ -15,6 +15,7 @@ using namespace std; extern int line_number; extern char* input_filename; +extern char* plugin; #define print_line_directive(fp) fprintf(fp, "\n#line %d \"%s\"\n", line_number, input_filename) @@ -197,11 +198,11 @@ char* concat(const char* str1, const char* str2) void print_event_c_prototype(FILE *fp, bool is_header) { if ( is_header ) - fprintf(fp, "%s void %s(Analyzer* analyzer%s", + fprintf(fp, "%s void %s(analyzer::Analyzer* analyzer%s", decl.generate_c_namespace_start.c_str(), decl.generate_bare_name.c_str(), args.size() ? ", " : "" ); else - fprintf(fp, "void %s(Analyzer* analyzer%s", + fprintf(fp, "void %s(analyzer::Analyzer* analyzer%s", decl.generate_c_fullname.c_str(), args.size() ? ", " : "" ); for ( int i = 0; i < (int) args.size(); ++i ) @@ -265,6 +266,15 @@ void print_event_c_body(FILE *fp) fprintf(fp, "\t} // event generation\n"); //fprintf(fp, "%s // end namespace\n", decl.generate_c_namespace_end.c_str()); } + +void record_bif_item(const char* id, int type) + { + if ( ! plugin ) + return; + + fprintf(fp_func_init, "\tbifs.push_back(std::make_pair(\"%s\", %d));\n", id, type); + } + %} %token TOK_LPP TOK_RPP TOK_LPB TOK_RPB TOK_LPPB TOK_RPPB TOK_VAR_ARG @@ -304,21 +314,6 @@ definitions: definitions definition opt_ws } | opt_ws { - int n = 1024 + strlen(input_filename); - char auto_gen_comment[n]; - - snprintf(auto_gen_comment, n, - "This file was automatically generated by bifcl from %s.", - input_filename); - - fprintf(fp_bro_init, "# %s\n\n", auto_gen_comment); - fprintf(fp_func_def, "// %s\n\n", auto_gen_comment); - fprintf(fp_func_h, "// %s\n\n", auto_gen_comment); - fprintf(fp_func_init, "// %s\n\n", auto_gen_comment); - fprintf(fp_netvar_def, "// %s\n\n", auto_gen_comment); - fprintf(fp_netvar_h, "// %s\n\n", auto_gen_comment); - fprintf(fp_netvar_init, "// %s\n\n", auto_gen_comment); - fprintf(fp_bro_init, "%s", $1); fprintf(fp_bro_init, "export {\n"); } @@ -362,6 +357,8 @@ type_def: TOK_TYPE opt_ws TOK_ID opt_ws ':' opt_ws type_def_types opt_ws ';' "\t%s = internal_type(\"%s\")->As%sType();\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str(), type_name.c_str()); + + record_bif_item(decl.bro_fullname.c_str(), 5); } ; @@ -403,6 +400,8 @@ enum_def: enum_def_1 enum_list TOK_RPB fprintf(fp_netvar_init, "\t%s = internal_type(\"%s\")->AsEnumType();\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + + record_bif_item(decl.bro_fullname.c_str(), 5); } ; @@ -457,6 +456,8 @@ const_def: TOK_CONST opt_ws TOK_ID opt_ws ':' opt_ws TOK_ID opt_ws ';' fprintf(fp_netvar_init, "\t%s = internal_const_val(\"%s\")%s;\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str(), accessor); + + record_bif_item(decl.bro_fullname.c_str(), 3); } attr_list: @@ -543,6 +544,8 @@ head_1: TOK_ID opt_ws arg_begin fprintf(fp_func_def, "Val* %s(Frame* frame, val_list* %s)", decl.c_fullname.c_str(), arg_list_name); + + record_bif_item(decl.bro_fullname.c_str(), 1); } else if ( definition_type == EVENT_DEF ) { @@ -559,6 +562,8 @@ head_1: TOK_ID opt_ws arg_begin "\t%s = internal_handler(\"%s\");\n", decl.c_fullname.c_str(), decl.bro_fullname.c_str()); + record_bif_item(decl.bro_fullname.c_str(), 2); + // C++ prototypes of bro_event_* functions will // be generated later. } diff --git a/src/dns-analyzer.pac b/src/dns-analyzer.pac deleted file mode 100644 index e92b6ef709..0000000000 --- a/src/dns-analyzer.pac +++ /dev/null @@ -1,343 +0,0 @@ -%extern{ -#include -%} - -%code{ -int add_to_name_buffer(DNS_name* name, char* buf, const int buf_n, int buf_i) - { - for ( int i = 0; i < int(name->labels()->size()); ++i ) - { - DNS_label* label = (*name->labels())[i]; - if ( label->label_type() == 0 ) - { - bytestring const &label_str = label->label(); - if ( buf_i > 0 && buf_i < buf_n ) - buf[buf_i++] = '.'; - BINPAC_ASSERT(buf_i + label_str.length() <= buf_n); - memcpy(buf + buf_i, label_str.begin(), - label_str.length()); - buf_i += label_str.length(); - } - else if ( label->label_type() == 3 ) - { - return add_to_name_buffer(label->ptr(), buf, - buf_n, buf_i); - } - } - - return buf_i; - } - -StringVal* name_to_val(DNS_name* name) - { - char name_buf[520]; - int n = add_to_name_buffer(name, name_buf, sizeof(name_buf), 0); - if ( n > 0 ) - --n; // remove the trailing '.' - - BINPAC_ASSERT(n < int(sizeof(name_buf))); - - name_buf[n] = 0; - for ( int i = 0; i < n; ++i ) - if ( isupper(name_buf[i]) ) - name_buf[i] = tolower(name_buf[i]); - - return new StringVal(name_buf); - } -%} - -connection DNS_Conn(bro_analyzer: BroAnalyzer) -{ - upflow = DNS_Flow; - downflow = DNS_Flow; -}; - -flow DNS_Flow -{ - datagram = DNS_message withcontext(connection, this); - - %member{ - set pointer_set; - BroVal dns_msg_val_; - %} - - %init{ - dns_msg_val_ = 0; - %} - - %cleanup{ - Unref(dns_msg_val_); - dns_msg_val_ = 0; - %} - - # Return a byte segment starting at in the original message. - function get_pointer(msgdata: const_bytestring, - offset: int): const_bytestring - %{ - if ( offset < 0 || offset >= msgdata.length() ) - return const_bytestring(0, 0); - - if ( pointer_set.find(offset) != pointer_set.end() ) - throw Exception("DNS pointer loop!"); - - pointer_set.insert(offset); - return const_bytestring(msgdata.begin() + offset, msgdata.end()); - %} - - function reset_pointer_set(): bool - %{ - pointer_set.clear(); - return true; - %} - - function process_dns_header(hdr: DNS_header): bool - %{ - Unref(dns_msg_val_); - - RecordVal* r = new RecordVal(dns_msg); - - r->Assign(0, new Val(${hdr.id}, TYPE_COUNT)); - r->Assign(1, new Val(${hdr.opcode}, TYPE_COUNT)); - r->Assign(2, new Val(${hdr.rcode}, TYPE_COUNT)); - r->Assign(3, new Val(${hdr.qr}, TYPE_BOOL)); - r->Assign(4, new Val(${hdr.aa}, TYPE_BOOL)); - r->Assign(5, new Val(${hdr.tc}, TYPE_BOOL)); - r->Assign(6, new Val(${hdr.rd}, TYPE_BOOL)); - r->Assign(7, new Val(${hdr.ra}, TYPE_BOOL)); - r->Assign(8, new Val(${hdr.z}, TYPE_COUNT)); - - r->Assign(9, new Val(${hdr.qdcount}, TYPE_COUNT)); - r->Assign(10, new Val(${hdr.ancount}, TYPE_COUNT)); - r->Assign(11, new Val(${hdr.nscount}, TYPE_COUNT)); - r->Assign(12, new Val(${hdr.arcount}, TYPE_COUNT)); - - dns_msg_val_ = r; - - return true; - %} - - function process_dns_question(question: DNS_question): bool - %{ - DNS_message* msg = question->msg(); - - if ( msg->header()->qr() == 0 ) - { - BifEvent::generate_dns_request( - connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), - name_to_val(question->qname()), - question->qtype(), - question->qclass()); - } - - else if ( msg->header()->ancount() == 0 && - msg->header()->nscount() == 0 && - msg->header()->arcount() == 0 ) - { - BifEvent::generate_dns_rejected( - connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), - name_to_val(question->qname()), - question->qtype(), - question->qclass()); - } - - return true; - %} - - function build_dns_answer(rr: DNS_rr): BroVal - %{ - RecordVal* r = new RecordVal(dns_answer); - - r->Assign(0, new Val(rr->answer_type(), TYPE_COUNT)); - r->Assign(1, name_to_val(rr->rr_name())); - r->Assign(2, new Val(rr->rr_type(), TYPE_COUNT)); - r->Assign(3, new Val(rr->rr_class(), TYPE_COUNT)); - r->Assign(4, new IntervalVal(double(rr->rr_ttl()), Seconds)); - - return r; - %} - - function build_dns_soa(soa: DNS_rdata_SOA): BroVal - %{ - RecordVal* r = new RecordVal(dns_soa); - - r->Assign(0, name_to_val(soa->mname())); - r->Assign(1, name_to_val(soa->rname())); - r->Assign(2, new Val(soa->serial(), TYPE_COUNT)); - r->Assign(3, new IntervalVal(double(soa->refresh()), Seconds)); - r->Assign(4, new IntervalVal(double(soa->retry()), Seconds)); - r->Assign(5, new IntervalVal(double(soa->expire()), Seconds)); - r->Assign(6, new IntervalVal(double(soa->minimum()), Seconds)); - - return r; - %} - - function build_edns_additional(rr: DNS_rr): BroVal - %{ - // We have to treat the additional record type in EDNS - // differently than a regular resource record. - RecordVal* r = new RecordVal(dns_edns_additional); - - r->Assign(0, new Val(int(rr->answer_type()), TYPE_COUNT)); - r->Assign(1, name_to_val(rr->rr_name())); - - // Type = 0x29 or 41 = EDNS - r->Assign(2, new Val(rr->rr_type(), TYPE_COUNT)); - - // Sender's UDP payload size, per RFC 2671 4.3 - r->Assign(3, new Val(rr->rr_class(), TYPE_COUNT)); - - // Need to break the TTL field into three components: - // initial: [------------- ttl (32) ---------------------] - // after: [DO][ ext rcode (7)][ver # (8)][ Z field (16)] - - unsigned int ercode = (rr->rr_ttl() & 0xff000000) >> 24; - unsigned int version = (rr->rr_ttl() & 0x00ff0000) >> 16; - unsigned int z = (rr->rr_ttl() & 0x0000ffff); - - int rcode = rr->msg()->header()->rcode(); - unsigned int return_error = (ercode << 8) | rcode; - - r->Assign(4, new Val(return_error, TYPE_COUNT)); - r->Assign(5, new Val(version, TYPE_COUNT)); - r->Assign(6, new Val(z, TYPE_COUNT)); - r->Assign(7, new IntervalVal(double(rr->rr_ttl()), Seconds)); - r->Assign(8, new Val(rr->msg()->header()->qr() == 0, TYPE_COUNT)); - - return r; - %} - - function process_dns_rr(rr: DNS_rr): bool - %{ - const DNS_rdata* rd = rr->rr_rdata(); - - switch ( rr->rr_type() ) { - case TYPE_A: - if ( dns_A_reply ) - { - ::uint32 addr = rd->type_a(); - BifEvent::generate_dns_A_reply(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), build_dns_answer(rr), - new AddrVal(htonl(addr))); - } - break; - - case TYPE_A6: - if ( dns_A6_reply ) - { - ::uint32 addr[4]; - for ( unsigned int i = 0; i < 4; ++i ) - addr[i] = htonl((*rd->type_aaaa())[i]); - - BifEvent::generate_dns_A6_reply(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), build_dns_answer(rr), - new AddrVal(addr)); - } - break; - - case TYPE_AAAA: - if ( dns_AAAA_reply ) - { - ::uint32 addr[4]; - for ( unsigned int i = 0; i < 4; ++i ) - addr[i] = htonl((*rd->type_aaaa())[i]); - - BifEvent::generate_dns_AAAA_reply(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), build_dns_answer(rr), - new AddrVal(addr)); - } - break; - - case TYPE_NS: - if ( dns_NS_reply ) - { - BifEvent::generate_dns_NS_reply(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), - build_dns_answer(rr), - name_to_val(rr->rr_rdata()->type_ns())); - } - break; - - case TYPE_CNAME: - if ( dns_CNAME_reply ) - { - BifEvent::generate_dns_CNAME_reply( - connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), - build_dns_answer(rr), - name_to_val(rr->rr_rdata()->type_cname())); - } - break; - - case TYPE_SOA: - if ( dns_SOA_reply ) - { - BifEvent::generate_dns_SOA_reply( - connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), - build_dns_answer(rr), - build_dns_soa(rr->rr_rdata()->type_soa())); - } - break; - - case TYPE_PTR: - if ( dns_PTR_reply ) - { - BifEvent::generate_dns_PTR_reply( - connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), - build_dns_answer(rr), - name_to_val(rr->rr_rdata()->type_ptr())); - } - break; - - case TYPE_MX: - if ( dns_MX_reply ) - { - BifEvent::generate_dns_MX_reply( - connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), - build_dns_answer(rr), - name_to_val(rr->rr_rdata()->type_mx()->name()), - rr->rr_rdata()->type_mx()->preference()); - } - break; - - case TYPE_EDNS: - if ( dns_EDNS_addl ) - { - BifEvent::generate_dns_EDNS_addl( - connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), - build_edns_additional(rr)); - } - break; - } - - return true; - %} -}; - -refine typeattr DNS_header += &let { - proc_dns_header = $context.flow.process_dns_header(this); -}; - -refine typeattr DNS_question += &let { - proc_dns_question = $context.flow.process_dns_question(this); -}; - -refine typeattr DNS_rr += &let { - proc_dns_rr = $context.flow.process_dns_rr(this); -}; diff --git a/src/dns-protocol.pac b/src/dns-protocol.pac deleted file mode 100644 index fbeb9d0fa3..0000000000 --- a/src/dns-protocol.pac +++ /dev/null @@ -1,215 +0,0 @@ -enum DNS_answer_type { - DNS_QUESTION, - DNS_ANSWER, - DNS_AUTHORITY, - DNS_ADDITIONAL, -}; - -enum DNS_rdata_type { - TYPE_A = 1, - TYPE_NS = 2, - TYPE_MD = 3, - TYPE_MF = 4, - TYPE_CNAME = 5, - TYPE_SOA = 6, - TYPE_MB = 7, - TYPE_MG = 8, - TYPE_MR = 9, - TYPE_NULL = 10, - TYPE_WKS = 11, - TYPE_PTR = 12, - TYPE_HINFO = 13, - TYPE_MINFO = 14, - TYPE_MX = 15, - TYPE_TXT = 16, - TYPE_AAAA = 28, # IPv6 (RFC 1886) - TYPE_NBS = 32, # Netbios name (RFC 1002) - TYPE_A6 = 38, # IPv6 with indirection (RFC 2874) - TYPE_EDNS = 41, # < OPT pseudo-RR (RFC 2671) -}; - -# 1 1 1 1 1 1 -# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | ID | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# |QR| Opcode |AA|TC|RD|RA| Z | RCODE | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | QDCOUNT | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | ANCOUNT | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | NSCOUNT | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | ARCOUNT | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - -type DNS_header = record { - id : uint16; - qrop : uint16; - qdcount : uint16; - ancount : uint16; - nscount : uint16; - arcount : uint16; -} &let { - qr: bool = qrop >> 15; - opcode: uint8 = (qrop >> 11) & 0xf; - aa: bool = (qrop >> 10) & 0x1; - tc: bool = (qrop >> 9) & 0x1; - rd: bool = (qrop >> 8) & 0x1; - ra: bool = (qrop >> 7) & 0x1; - z: uint8 = (qrop >> 4) & 0x7; - rcode: uint8 = qrop & 0xf; -}; - -type DNS_label(msg: DNS_message) = record { - length: uint8; - data: case label_type of { - 0 -> label: bytestring &length = length; - 3 -> ptr_lo: uint8; - }; -} &let { - label_type: uint8 = length >> 6; - last: bool = (length == 0) || (label_type == 3); - - # A name pointer. - ptr: DNS_name(msg) - withinput $context.flow.get_pointer(msg.sourcedata, - ((length & 0x3f) << 8) | ptr_lo) - &if(label_type == 3); - - clear_pointer_set: bool = $context.flow.reset_pointer_set() - &if(last); -}; - -type DNS_name(msg: DNS_message) = record { - labels: DNS_label(msg)[] &until($element.last); -}; - -type DNS_char_string = record { - length: uint8; - data: bytestring &length = length; -}; - -# 1 1 1 1 1 1 -# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | | -# / QNAME / -# / / -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | QTYPE | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | QCLASS | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - -type DNS_question(msg: DNS_message) = record { - qname: DNS_name(msg); - qtype: uint16; - qclass: uint16; -}; - -type DNS_rdata_MX(msg: DNS_message) = record { - preference: uint16; - name: DNS_name(msg); -}; - -type DNS_rdata_SOA(msg: DNS_message) = record { - mname: DNS_name(msg); - rname: DNS_name(msg); - serial: uint32; - refresh: uint32; - retry: uint32; - expire: uint32; - minimum: uint32; -}; - -type DNS_rdata_WKS = record { - address: uint32; - protocol: uint8; - bitmap: bytestring &restofdata; -}; - -type DNS_rdata_HINFO = record { - cpu: DNS_char_string; - os: DNS_char_string; -}; - -type DNS_rdata(msg: DNS_message, - rr_type: uint16, - rr_class: uint16) = case rr_type of { - - TYPE_A -> type_a: uint32 &check(rr_class == CLASS_IN); - TYPE_NS -> type_ns: DNS_name(msg); - TYPE_CNAME -> type_cname: DNS_name(msg); - TYPE_SOA -> type_soa: DNS_rdata_SOA(msg); - TYPE_PTR -> type_ptr: DNS_name(msg); - TYPE_MX -> type_mx: DNS_rdata_MX(msg); - TYPE_AAAA, TYPE_A6 - -> type_aaaa: uint32[4]; - - # TYPE_WKS -> type_wks: DNS_rdata_WKS; - # TYPE_HINFO -> type_hinfo: DNS_rdata_HINFO; - # TYPE_TXT -> type_txt: bytestring &restofdata; - - # 3 -> type_md: DNS_rdata_MD; - # 4 -> type_mf: DNS_rdata_MF; - # 7 -> type_mb: DNS_rdata_MB; - # 8 -> type_mg: DNS_rdata_MG; - # 9 -> type_mr: DNS_rdata_MR; - # 10 -> type_null: DNS_rdata_NULL; - # 14 -> type_minfo: DNS_rdata_MINFO; - # 32 -> type_nbs: DNS_rdata_NBS; - - default -> unknown: bytestring &restofdata; -}; - -# 1 1 1 1 1 1 -# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | | -# / / -# / NAME / -# | | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | TYPE | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | CLASS | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | TTL | -# | | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | RDLENGTH | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| -# / RDATA / -# / / -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - -type DNS_rr(msg: DNS_message, answer_type: DNS_answer_type) = record { - rr_name: DNS_name(msg); - rr_type: uint16; - rr_class: uint16; - rr_ttl: uint32; - rr_rdlength: uint16; - rr_rdata: DNS_rdata(msg, rr_type, rr_class) &length = rr_rdlength; -}; - -# +---------------------+ -# | Header | -# +---------------------+ -# | Question | the question for the name server -# +---------------------+ -# | Answer | RRs answering the question -# +---------------------+ -# | Authority | RRs pointing toward an authority -# +---------------------+ -# | Additional | RRs holding additional information -# +---------------------+ - -type DNS_message = record { - header: DNS_header; - question: DNS_question(this)[header.qdcount]; - answer: DNS_rr(this, DNS_ANSWER)[header.ancount]; - authority: DNS_rr(this, DNS_AUTHORITY)[header.nscount]; - additional: DNS_rr(this, DNS_ADDITIONAL)[header.arcount]; -} &byteorder = bigendian, &exportsourcedata; diff --git a/src/dns.pac b/src/dns.pac deleted file mode 100644 index aeffdf0bc7..0000000000 --- a/src/dns.pac +++ /dev/null @@ -1,9 +0,0 @@ -%include bro.pac - -analyzer DNS withcontext { - connection: DNS_Conn; - flow: DNS_Flow; -}; - -%include dns-protocol.pac -%include dns-analyzer.pac diff --git a/src/dns_tcp.pac b/src/dns_tcp.pac deleted file mode 100644 index d31ff58c6e..0000000000 --- a/src/dns_tcp.pac +++ /dev/null @@ -1,45 +0,0 @@ -%extern{ -#include "dns_pac.h" // for DNS_Conn -%} - -%include bro.pac - -analyzer DNS_on_TCP withcontext { - connection: DNS_TCP_Conn; - flow: DNS_TCP_Flow; -}; - -type DNS_TCP_PDU(is_orig: bool) = record { - msglen: uint16; - msg: bytestring &length = msglen; -} &byteorder = bigendian, &length = 2 + msglen, &let { - deliver: bool = $context.connection.deliver_dns_message(is_orig, msg); -}; - -connection DNS_TCP_Conn(bro_analyzer: BroAnalyzer) { - upflow = DNS_TCP_Flow(true); - downflow = DNS_TCP_Flow(false); - - %member{ - DNS::DNS_Conn *abstract_dns_connection_; - %} - - %init{ - abstract_dns_connection_ = new DNS::DNS_Conn(bro_analyzer); - %} - - %cleanup{ - delete abstract_dns_connection_; - abstract_dns_connection_ = 0; - %} - - function deliver_dns_message(is_orig: bool, msg: const_bytestring): bool - %{ - abstract_dns_connection_->NewData(is_orig, msg.begin(), msg.end()); - return true; - %} -}; - -flow DNS_TCP_Flow(is_orig: bool) { - flowunit = DNS_TCP_PDU(is_orig) withcontext(connection, this); -}; diff --git a/src/event.bif b/src/event.bif index 2263412699..f7fd9b4147 100644 --- a/src/event.bif +++ b/src/event.bif @@ -1,7 +1,9 @@ -##! The events that the C/C++ core of Bro can generate. This is mostly -##! consisting of high-level network events that protocol analyzers detect, -##! but there are also several general-utility events generated by internal -##! Bro frameworks. +##! The protocol-independent events that the C/C++ core of Bro can generate. +##! +##! This is mostly events not related to a specific transport- or +##! application-layer protocol, but also includes a few that may be generated +##! by more than one protocols analyzer (like events generated by both UDP and +##! TCP analysis.) # # Documentation conventions: @@ -59,69 +61,6 @@ event bro_init%(%); ## is not generated. event bro_done%(%); -## Generated when an internal DNS lookup produces the same result as last time. -## Bro keeps an internal DNS cache for host names and IP addresses it has -## already resolved. This event is generated when a subsequent lookup returns -## the same result as stored in the cache. -## -## dm: A record describing the new resolver result (which matches the old one). -## -## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified -event dns_mapping_valid%(dm: dns_mapping%); - -## Generated when an internal DNS lookup got no answer even though it had -## succeeded in the past. Bro keeps an internal DNS cache for host names and IP -## addresses it has already resolved. This event is generated when a -## subsequent lookup does not produce an answer even though we have -## already stored a result in the cache. -## -## dm: A record describing the old resolver result. -## -## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_valid -event dns_mapping_unverified%(dm: dns_mapping%); - -## Generated when an internal DNS lookup succeeded but an earlier attempt -## did not. Bro keeps an internal DNS cache for host names and IP -## addresses it has already resolved. This event is generated when a subsequent -## lookup produces an answer for a query that was marked as failed in the cache. -## -## dm: A record describing the new resolver result. -## -## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_unverified -## dns_mapping_valid -event dns_mapping_new_name%(dm: dns_mapping%); - -## Generated when an internal DNS lookup returned zero answers even though it -## had succeeded in the past. Bro keeps an internal DNS cache for host names -## and IP addresses it has already resolved. This event is generated when -## on a subsequent lookup we receive an answer that is empty even -## though we have already stored a result in the cache. -## -## dm: A record describing the old resolver result. -## -## .. bro:see:: dns_mapping_altered dns_mapping_new_name dns_mapping_unverified -## dns_mapping_valid -event dns_mapping_lost_name%(dm: dns_mapping%); - -## Generated when an internal DNS lookup produced a different result than in -## the past. Bro keeps an internal DNS cache for host names and IP addresses -## it has already resolved. This event is generated when a subsequent lookup -## returns a different answer than we have stored in the cache. -## -## dm: A record describing the new resolver result. -## -## old_addrs: Addresses that used to be part of the returned set for the query -## described by *dm*, but are not anymore. -## -## new_addrs: Addresses that were not part of the returned set for the query -## described by *dm*, but now are. -## -## .. bro:see:: dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified -## dns_mapping_valid -event dns_mapping_altered%(dm: dns_mapping, old_addrs: addr_set, new_addrs: addr_set%); - ## Generated for every new connection. This event is raised with the first ## packet of a previously unknown connection. Bro uses a flow-based definition ## of "connection" here that includes not only TCP sessions but also UDP and @@ -134,7 +73,7 @@ event dns_mapping_altered%(dm: dns_mapping, old_addrs: addr_set, new_addrs: addr ## connection_first_ACK connection_half_finished connection_partial_close ## connection_pending connection_rejected connection_reset connection_reused ## connection_state_remove connection_status_update connection_timeout -## expected_connection_seen new_connection_contents partial_connection +## scheduled_analyzer_applied new_connection_contents partial_connection ## ## .. note:: ## @@ -157,9 +96,10 @@ event new_connection%(c: connection%); ## e: The new encapsulation. event tunnel_changed%(c: connection, e: EncapsulatingConnVector%); -## Generated when reassembly starts for a TCP connection. This event is raised -## at the moment when Bro's TCP analyzer enables stream reassembly for a -## connection. +## Generated when a TCP connection timed out. This event is raised when +## no activity was seen for an interval of at least +## :bro:id:`tcp_connection_linger`, and either one endpoint has already +## closed the connection or one side never became active. ## ## c: The connection. ## @@ -167,148 +107,19 @@ event tunnel_changed%(c: connection, e: EncapsulatingConnVector%); ## connection_established connection_external connection_finished ## connection_first_ACK connection_half_finished connection_partial_close ## connection_pending connection_rejected connection_reset connection_reused -## connection_state_remove connection_status_update connection_timeout -## expected_connection_seen new_connection partial_connection -event new_connection_contents%(c: connection%); - -## Generated for an unsuccessful connection attempt. This event is raised when -## an originator unsuccessfully attempted to establish a connection. -## "Unsuccessful" is defined as at least :bro:id:`tcp_attempt_delay` seconds -## having elapsed since the originator first sent a connection establishment -## packet to the destination without seeing a reply. -## -## c: The connection. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_established -## connection_external connection_finished connection_first_ACK -## connection_half_finished connection_partial_close connection_pending -## connection_rejected connection_reset connection_reused connection_state_remove -## connection_status_update connection_timeout expected_connection_seen -## new_connection new_connection_contents partial_connection -event connection_attempt%(c: connection%); - -## Generated when a SYN-ACK packet is seen in response to a SYN packet during -## a TCP handshake. The final ACK of the handshake in response to SYN-ACK may -## or may not occur later, one way to tell is to check the *history* field of -## :bro:type:`connection` to see if the originator sent an ACK, indicated by -## 'A' in the history string. -## -## c: The connection. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt -## connection_external connection_finished connection_first_ACK -## connection_half_finished connection_partial_close connection_pending -## connection_rejected connection_reset connection_reused connection_state_remove -## connection_status_update connection_timeout expected_connection_seen -## new_connection new_connection_contents partial_connection -event connection_established%(c: connection%); - -## Generated for a new active TCP connection if Bro did not see the initial -## handshake. This event is raised when Bro has observed traffic from each -## endpoint, but the activity did not begin with the usual connection -## establishment. -## -## c: The connection. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt -## connection_established connection_external connection_finished -## connection_first_ACK connection_half_finished connection_partial_close -## connection_pending connection_rejected connection_reset connection_reused -## connection_state_remove connection_status_update connection_timeout -## expected_connection_seen new_connection new_connection_contents -## -event partial_connection%(c: connection%); - -## Generated when a previously inactive endpoint attempts to close a TCP -## connection via a normal FIN handshake or an abort RST sequence. When the -## endpoint sent one of these packets, Bro waits -## :bro:id:`tcp_partial_close_delay` prior to generating the event, to give -## the other endpoint a chance to close the connection normally. -## -## c: The connection. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt -## connection_established connection_external connection_finished -## connection_first_ACK connection_half_finished connection_pending -## connection_rejected connection_reset connection_reused connection_state_remove -## connection_status_update connection_timeout expected_connection_seen -## new_connection new_connection_contents partial_connection -event connection_partial_close%(c: connection%); - -## Generated for a TCP connection that finished normally. The event is raised -## when a regular FIN handshake from both endpoints was observed. -## -## c: The connection. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt -## connection_established connection_external connection_first_ACK -## connection_half_finished connection_partial_close connection_pending -## connection_rejected connection_reset connection_reused connection_state_remove -## connection_status_update connection_timeout expected_connection_seen -## new_connection new_connection_contents partial_connection -event connection_finished%(c: connection%); - -## Generated when one endpoint of a TCP connection attempted to gracefully close -## the connection, but the other endpoint is in the TCP_INACTIVE state. This can -## happen due to split routing, in which Bro only sees one side of a connection. -## -## c: The connection. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt -## connection_established connection_external connection_finished -## connection_first_ACK connection_partial_close connection_pending -## connection_rejected connection_reset connection_reused connection_state_remove -## connection_status_update connection_timeout expected_connection_seen -## new_connection new_connection_contents partial_connection -event connection_half_finished%(c: connection%); - -## Generated for a rejected TCP connection. This event is raised when an -## originator attempted to setup a TCP connection but the responder replied -## with a RST packet denying it. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt -## connection_established connection_external connection_finished -## connection_first_ACK connection_half_finished connection_partial_close -## connection_pending connection_reset connection_reused connection_state_remove -## connection_status_update connection_timeout expected_connection_seen -## new_connection new_connection_contents partial_connection -## -## c: The connection. +## connection_state_remove connection_status_update +## scheduled_analyzer_applied new_connection new_connection_contents +## partial_connection ## ## .. note:: ## -## If the responder does not respond at all, :bro:id:`connection_attempt` is -## raised instead. If the responder initially accepts the connection but -## aborts it later, Bro first generates :bro:id:`connection_established` -## and then :bro:id:`connection_reset`. -event connection_rejected%(c: connection%); - -## Generated when an endpoint aborted a TCP connection. The event is raised -## when one endpoint of an established TCP connection aborted by sending a RST -## packet. -## -## c: The connection. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt -## connection_established connection_external connection_finished -## connection_first_ACK connection_half_finished connection_partial_close -## connection_pending connection_rejected connection_reused -## connection_state_remove connection_status_update connection_timeout -## expected_connection_seen new_connection new_connection_contents -## partial_connection -event connection_reset%(c: connection%); - -## Generated for each still-open connection when Bro terminates. -## -## c: The connection. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt -## connection_established connection_external connection_finished -## connection_first_ACK connection_half_finished connection_partial_close -## connection_rejected connection_reset connection_reused connection_state_remove -## connection_status_update connection_timeout expected_connection_seen -## new_connection new_connection_contents partial_connection bro_done -event connection_pending%(c: connection%); +## The precise semantics of this event can be unintuitive as it only +## covers a subset of cases where a connection times out. Often, handling +## :bro:id:`connection_state_remove` is the better option. That one will be +## generated reliably when an interval of ``tcp_inactivity_timeout`` has +## passed without any activity seen (but also for all other ways a +## connection may terminate). +event connection_timeout%(c: connection%); ## Generated when a connection's internal state is about to be removed from ## memory. Bro generates this event reliably once for every connection when it @@ -323,75 +134,11 @@ event connection_pending%(c: connection%); ## connection_established connection_external connection_finished ## connection_first_ACK connection_half_finished connection_partial_close ## connection_pending connection_rejected connection_reset connection_reused -## connection_status_update connection_timeout expected_connection_seen +## connection_status_update connection_timeout scheduled_analyzer_applied ## new_connection new_connection_contents partial_connection udp_inactivity_timeout ## tcp_inactivity_timeout icmp_inactivity_timeout conn_stats event connection_state_remove%(c: connection%); -## Generated for a SYN packet. Bro raises this event for every SYN packet seen -## by its TCP analyzer. -## -## c: The connection. -## -## pkt: Information extracted from the SYN packet. -## -## .. bro:see:: connection_EOF connection_attempt connection_established -## connection_external connection_finished connection_first_ACK -## connection_half_finished connection_partial_close connection_pending -## connection_rejected connection_reset connection_reused connection_state_remove -## connection_status_update connection_timeout expected_connection_seen -## new_connection new_connection_contents partial_connection -## -## .. note:: -## -## This event has quite low-level semantics and can potentially be expensive -## to generate. It should only be used if one really needs the specific -## information passed into the handler via the ``pkt`` argument. If not, -## handling one of the other ``connection_*`` events is typically the -## better approach. -event connection_SYN_packet%(c: connection, pkt: SYN_packet%); - -## Generated for the first ACK packet seen for a TCP connection from -## its *originator*. -## -## c: The connection. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt -## connection_established connection_external connection_finished -## connection_half_finished connection_partial_close connection_pending -## connection_rejected connection_reset connection_reused connection_state_remove -## connection_status_update connection_timeout expected_connection_seen -## new_connection new_connection_contents partial_connection -## -## .. note:: -## -## This event has quite low-level semantics and should be used only rarely. -event connection_first_ACK%(c: connection%); - -## Generated when a TCP connection timed out. This event is raised when -## no activity was seen for an interval of at least -## :bro:id:`tcp_connection_linger`, and either one endpoint has already -## closed the connection or one side never became active. -## -## c: The connection. -## -## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt -## connection_established connection_external connection_finished -## connection_first_ACK connection_half_finished connection_partial_close -## connection_pending connection_rejected connection_reset connection_reused -## connection_state_remove connection_status_update expected_connection_seen -## new_connection new_connection_contents partial_connection -## -## .. note:: -## -## The precise semantics of this event can be unintuitive as it only -## covers a subset of cases where a connection times out. Often, handling -## :bro:id:`connection_state_remove` is the better option. That one will be -## generated reliably when an interval of ``tcp_inactivity_timeout`` has -## passed without any activity seen (but also for all other ways a -## connection may terminate). -event connection_timeout%(c: connection%); - ## Generated when a connection 4-tuple is reused. This event is raised when Bro ## sees a new TCP session or UDP flow using a 4-tuple matching that of an ## earlier connection it still considers active. @@ -402,7 +149,7 @@ event connection_timeout%(c: connection%); ## connection_established connection_external connection_finished ## connection_first_ACK connection_half_finished connection_partial_close ## connection_pending connection_rejected connection_reset connection_state_remove -## connection_status_update connection_timeout expected_connection_seen +## connection_status_update connection_timeout scheduled_analyzer_applied ## new_connection new_connection_contents partial_connection event connection_reused%(c: connection%); @@ -416,7 +163,7 @@ event connection_reused%(c: connection%); ## connection_established connection_external connection_finished ## connection_first_ACK connection_half_finished connection_partial_close ## connection_pending connection_rejected connection_reset connection_reused -## connection_state_remove connection_timeout expected_connection_seen +## connection_state_remove connection_timeout scheduled_analyzer_applied ## new_connection new_connection_contents partial_connection event connection_status_update%(c: connection%); @@ -434,22 +181,6 @@ event connection_status_update%(c: connection%); ## .. bro:see:: connection_established new_connection event connection_flow_label_changed%(c: connection, is_orig: bool, old_label: count, new_label: count%); -## Generated at the end of reassembled TCP connections. The TCP reassembler -## raised the event once for each endpoint of a connection when it finished -## reassembling the corresponding side of the communication. -## -## c: The connection. -## -## is_orig: True if the event is raised for the originator side. -## -## .. bro:see:: connection_SYN_packet connection_attempt connection_established -## connection_external connection_finished connection_first_ACK -## connection_half_finished connection_partial_close connection_pending -## connection_rejected connection_reset connection_reused connection_state_remove -## connection_status_update connection_timeout expected_connection_seen -## new_connection new_connection_contents partial_connection -event connection_EOF%(c: connection, is_orig: bool%); - ## Generated for a new connection received from the communication subsystem. ## Remote peers can inject packets into Bro's packet loop, for example via ## :doc:`Broccoli `. The communication system @@ -460,15 +191,26 @@ event connection_EOF%(c: connection, is_orig: bool%); ## tag: TODO. event connection_external%(c: connection, tag: string%); +## Generated when a UDP session for a supported protocol has finished. Some of +## Bro's application-layer UDP analyzers flag the end of a session by raising +## this event. Currently, the analyzers for DNS, NTP, Netbios, Syslog, AYIYA, +## Teredo, and GTPv1 support this. +## +## u: The connection record for the corresponding UDP flow. +## +## .. bro:see:: udp_contents udp_reply udp_request +event udp_session_done%(u: connection%); + ## Generated when a connection is seen that is marked as being expected. -## The function :bro:id:`expect_connection` tells Bro to expect a particular -## connection to come up, and which analyzer to associate with it. Once the -## first packet of such a connection is indeed seen, this event is raised. +## The function :bro:id:`Analyzer::schedule_analyzer` tells Bro to expect a +## particular connection to come up, and which analyzer to associate with it. +## Once the first packet of such a connection is indeed seen, this event is +## raised. ## ## c: The connection. ## ## a: The analyzer that was scheduled for the connection with the -## :bro:id:`expect_connection` call. When the event is raised, that +## :bro:id:`Analyzer::schedule_analyzer` call. When the event is raised, that ## analyzer will already have been activated to process the connection. The ## ``count`` is one of the ``ANALYZER_*`` constants, e.g., ``ANALYZER_HTTP``. ## @@ -481,7 +223,7 @@ event connection_external%(c: connection, tag: string%); ## ## .. todo:: We don't have a good way to document the automatically generated ## ``ANALYZER_*`` constants right now. -event expected_connection_seen%(c: connection, a: count%); +event scheduled_analyzer_applied%(c: connection, a: Analyzer::Tag%); ## Generated for every packet Bro sees. This is a very low-level and expensive ## event that should be avoided when at all possible. It's usually infeasible to @@ -522,135 +264,6 @@ event esp_packet%(p: pkt_hdr%); ## .. bro:see:: new_packet tcp_packet ipv6_ext_headers event mobile_ipv6_message%(p: pkt_hdr%); -## Generated for any IPv6 packet encapsulated in a Teredo tunnel. -## See :rfc:`4380` for more information about the Teredo protocol. -## -## outer: The Teredo tunnel connection. -## -## inner: The Teredo-encapsulated IPv6 packet header and transport header. -## -## .. bro:see:: teredo_authentication teredo_origin_indication teredo_bubble -## -## .. note:: Since this event may be raised on a per-packet basis, handling -## it may become particularly expensive for real-time analysis. -event teredo_packet%(outer: connection, inner: teredo_hdr%); - -## Generated for IPv6 packets encapsulated in a Teredo tunnel that -## use the Teredo authentication encapsulation method. -## See :rfc:`4380` for more information about the Teredo protocol. -## -## outer: The Teredo tunnel connection. -## -## inner: The Teredo-encapsulated IPv6 packet header and transport header. -## -## .. bro:see:: teredo_packet teredo_origin_indication teredo_bubble -## -## .. note:: Since this event may be raised on a per-packet basis, handling -## it may become particularly expensive for real-time analysis. -event teredo_authentication%(outer: connection, inner: teredo_hdr%); - -## Generated for IPv6 packets encapsulated in a Teredo tunnel that -## use the Teredo origin indication encapsulation method. -## See :rfc:`4380` for more information about the Teredo protocol. -## -## outer: The Teredo tunnel connection. -## -## inner: The Teredo-encapsulated IPv6 packet header and transport header. -## -## .. bro:see:: teredo_packet teredo_authentication teredo_bubble -## -## .. note:: Since this event may be raised on a per-packet basis, handling -## it may become particularly expensive for real-time analysis. -event teredo_origin_indication%(outer: connection, inner: teredo_hdr%); - -## Generated for Teredo bubble packets. That is, IPv6 packets encapsulated -## in a Teredo tunnel that have a Next Header value of :bro:id:`IPPROTO_NONE`. -## See :rfc:`4380` for more information about the Teredo protocol. -## -## outer: The Teredo tunnel connection. -## -## inner: The Teredo-encapsulated IPv6 packet header and transport header. -## -## .. bro:see:: teredo_packet teredo_authentication teredo_origin_indication -## -## .. note:: Since this event may be raised on a per-packet basis, handling -## it may become particularly expensive for real-time analysis. -event teredo_bubble%(outer: connection, inner: teredo_hdr%); - -## Generated for any GTP message with a GTPv1 header. -## -## c: The connection over which the message is sent. -## -## hdr: The GTPv1 header. -event gtpv1_message%(c: connection, hdr: gtpv1_hdr%); - -## Generated for GTPv1 G-PDU packets. That is, packets with a UDP payload -## that includes a GTP header followed by an IPv4 or IPv6 packet. -## -## outer: The GTP outer tunnel connection. -## -## inner_gtp: The GTP header. -## -## inner_ip: The inner IP and transport layer packet headers. -## -## .. note:: Since this event may be raised on a per-packet basis, handling -## it may become particularly expensive for real-time analysis. -event gtpv1_g_pdu_packet%(outer: connection, inner_gtp: gtpv1_hdr, inner_ip: pkt_hdr%); - -## Generated for GTPv1-C Create PDP Context Request messages. -## -## c: The connection over which the message is sent. -## -## hdr: The GTPv1 header. -## -## elements: The set of Information Elements comprising the message. -event gtpv1_create_pdp_ctx_request%(c: connection, hdr: gtpv1_hdr, elements: gtp_create_pdp_ctx_request_elements%); - -## Generated for GTPv1-C Create PDP Context Response messages. -## -## c: The connection over which the message is sent. -## -## hdr: The GTPv1 header. -## -## elements: The set of Information Elements comprising the message. -event gtpv1_create_pdp_ctx_response%(c: connection, hdr: gtpv1_hdr, elements: gtp_create_pdp_ctx_response_elements%); - -## Generated for GTPv1-C Update PDP Context Request messages. -## -## c: The connection over which the message is sent. -## -## hdr: The GTPv1 header. -## -## elements: The set of Information Elements comprising the message. -event gtpv1_update_pdp_ctx_request%(c: connection, hdr: gtpv1_hdr, elements: gtp_update_pdp_ctx_request_elements%); - -## Generated for GTPv1-C Update PDP Context Response messages. -## -## c: The connection over which the message is sent. -## -## hdr: The GTPv1 header. -## -## elements: The set of Information Elements comprising the message. -event gtpv1_update_pdp_ctx_response%(c: connection, hdr: gtpv1_hdr, elements: gtp_update_pdp_ctx_response_elements%); - -## Generated for GTPv1-C Delete PDP Context Request messages. -## -## c: The connection over which the message is sent. -## -## hdr: The GTPv1 header. -## -## elements: The set of Information Elements comprising the message. -event gtpv1_delete_pdp_ctx_request%(c: connection, hdr: gtpv1_hdr, elements: gtp_delete_pdp_ctx_request_elements%); - -## Generated for GTPv1-C Delete PDP Context Response messages. -## -## c: The connection over which the message is sent. -## -## hdr: The GTPv1 header. -## -## elements: The set of Information Elements comprising the message. -event gtpv1_delete_pdp_ctx_response%(c: connection, hdr: gtpv1_hdr, elements: gtp_delete_pdp_ctx_response_elements%); - ## Generated for every packet that has a non-empty transport-layer payload. ## This is a very low-level and expensive event that should be avoided when ## at all possible. It's usually infeasible to handle when processing even @@ -665,85 +278,6 @@ event gtpv1_delete_pdp_ctx_response%(c: connection, hdr: gtpv1_hdr, elements: gt ## .. bro:see:: new_packet tcp_packet event packet_contents%(c: connection, contents: string%); -## Generated for every TCP packet. This is a very low-level and expensive event -## that should be avoided when at all possible. It's usually infeasible to -## handle when processing even medium volumes of traffic in real-time. It's -## slightly better than :bro:id:`new_packet` because it affects only TCP, but -## not much. That said, if you work from a trace and want to do some -## packet-level analysis, it may come in handy. -## -## c: The connection the packet is part of. -## -## is_orig: True if the packet was sent by the connection's originator. -## -## flags: A string with the packet's TCP flags. In the string, each character -## corresponds to one set flag, as follows: ``S`` -> SYN; ``F`` -> FIN; -## ``R`` -> RST; ``A`` -> ACK; ``P`` -> PUSH. -## -## seq: The packet's TCP sequence number. -## -## ack: The packet's ACK number. -## -## len: The length of the TCP payload, as specified in the packet header. -## -## payload: The raw TCP payload. Note that this may be shorter than *len* if -## the packet was not fully captured. -## -## .. bro:see:: new_packet packet_contents tcp_option tcp_contents tcp_rexmit -event tcp_packet%(c: connection, is_orig: bool, flags: string, seq: count, ack: count, len: count, payload: string%); - -## Generated for each option found in a TCP header. Like many of the ``tcp_*`` -## events, this is a very low-level event and potentially expensive as it may -## be raised very often. -## -## c: The connection the packet is part of. -## -## is_orig: True if the packet was sent by the connection's originator. -## -## opt: The numerical option number, as found in the TCP header. -## -## optlen: The length of the options value. -## -## .. bro:see:: tcp_packet tcp_contents tcp_rexmit -## -## .. note:: There is currently no way to get the actual option value, if any. -event tcp_option%(c: connection, is_orig: bool, opt: count, optlen: count%); - -## Generated for each chunk of reassembled TCP payload. When content delivery is -## enabled for a TCP connection (via :bro:id:`tcp_content_delivery_ports_orig`, -## :bro:id:`tcp_content_delivery_ports_resp`, -## :bro:id:`tcp_content_deliver_all_orig`, -## :bro:id:`tcp_content_deliver_all_resp`), this event is raised for each chunk -## of in-order payload reconstructed from the packet stream. Note that this -## event is potentially expensive if many connections carry significant amounts -## of data as then all that data needs to be passed on to the scripting layer. -## -## c: The connection the payload is part of. -## -## is_orig: True if the packet was sent by the connection's originator. -## -## seq: The sequence number corresponding to the first byte of the payload -## chunk. -## -## contents: The raw payload, which will be non-empty. -## -## .. bro:see:: tcp_packet tcp_option tcp_rexmit -## tcp_content_delivery_ports_orig tcp_content_delivery_ports_resp -## tcp_content_deliver_all_resp tcp_content_deliver_all_orig -## -## .. note:: -## -## The payload received by this event is the same that is also passed into -## application-layer protocol analyzers internally. Subsequent invocations of -## this event for the same connection receive non-overlapping in-order chunks -## of its TCP payload stream. It is however undefined what size each chunk -## has; while Bro passes the data on as soon as possible, specifics depend on -## network-level effects such as latency, acknowledgements, reordering, etc. -event tcp_contents%(c: connection, is_orig: bool, seq: count, contents: string%); - -## TODO. -event tcp_rexmit%(c: connection, is_orig: bool, seq: count, len: count, data_in_flight: count, window: count%); - ## Generated when Bro detects a TCP retransmission inconsistency. When ## reassembling a TCP stream, Bro buffers all payload until it sees the ## responder acking it. If during that time, the sender resends a chunk of @@ -831,7 +365,6 @@ event content_gap%(c: connection, is_orig: bool, seq: count, length: count%); ## is exceeded. event gap_report%(dt: interval, info: gap_info%); - ## Generated when a protocol analyzer confirms that a connection is indeed ## using that protocol. Bro's dynamic protocol detection heuristically activates ## analyzers as soon as it believes a connection *could* be using a particular @@ -841,8 +374,8 @@ event gap_report%(dt: interval, info: gap_info%); ## c: The connection. ## ## atype: The type of the analyzer confirming that its protocol is in -## use. The value is one of the ``ANALYZER_*`` constants. For example, -## ``ANALYZER_HTTP`` means the HTTP analyzers determined that it's indeed +## use. The value is one of the ``Analyzer::ANALYZER_*`` constants. For example, +## ``Analyzer::ANALYZER_HTTP`` means the HTTP analyzer determined that it's indeed ## parsing an HTTP connection. ## ## aid: A unique integer ID identifying the specific *instance* of the @@ -857,7 +390,7 @@ event gap_report%(dt: interval, info: gap_info%); ## Bro's default scripts use this event to determine the ``service`` column ## of :bro:type:`Conn::Info`: once confirmed, the protocol will be listed ## there (and thus in ``conn.log``). -event protocol_confirmation%(c: connection, atype: count, aid: count%); +event protocol_confirmation%(c: connection, atype: Analyzer::Tag, aid: count%); ## Generated when a protocol analyzer determines that a connection it is parsing ## is not conforming to the protocol it expects. Bro's dynamic protocol @@ -869,8 +402,8 @@ event protocol_confirmation%(c: connection, atype: count, aid: count%); ## c: The connection. ## ## atype: The type of the analyzer confirming that its protocol is in -## use. The value is one of the ``ANALYZER_*`` constants. For example, -## ``ANALYZER_HTTP`` means the HTTP analyzers determined that it's indeed +## use. The value is one of the ``Analyzer::ANALYZER_*`` constants. For example, +## ``Analyzer::ANALYZER_HTTP`` means the HTTP analyzer determined that it's indeed ## parsing an HTTP connection. ## ## aid: A unique integer ID identifying the specific *instance* of the @@ -888,356 +421,7 @@ event protocol_confirmation%(c: connection, atype: count, aid: count%); ## :bro:id:`disable_analyzer` if it's parsing the wrong protocol. That's ## however a script-level decision and not done automatically by the event ## engine. -event protocol_violation%(c: connection, atype: count, aid: count, reason: string%); - -## Generated for each packet sent by a UDP flow's originator. This a potentially -## expensive event due to the volume of UDP traffic and should be used with -## care. -## -## u: The connection record for the corresponding UDP flow. -## -## .. bro:see:: udp_contents udp_reply udp_session_done -event udp_request%(u: connection%); - -## Generated for each packet sent by a UDP flow's responder. This a potentially -## expensive event due to the volume of UDP traffic and should be used with -## care. -## -## u: The connection record for the corresponding UDP flow. -## -## .. bro:see:: udp_contents udp_request udp_session_done -event udp_reply%(u: connection%); - -## Generated for UDP packets to pass on their payload. As the number of UDP -## packets can be very large, this event is normally raised only for those on -## ports configured in :bro:id:`udp_content_delivery_ports_orig` (for packets -## sent by the flow's originator) or :bro:id:`udp_content_delivery_ports_resp` -## (for packets sent by the flow's responder). However, delivery can be enabled -## for all UDP request and reply packets by setting -## :bro:id:`udp_content_deliver_all_orig` or -## :bro:id:`udp_content_deliver_all_resp`, respectively. Note that this -## event is also raised for all matching UDP packets, including empty ones. -## -## u: The connection record for the corresponding UDP flow. -## -## is_orig: True if the event is raised for the originator side. -## -## contents: TODO. -## -## .. bro:see:: udp_reply udp_request udp_session_done -## udp_content_deliver_all_orig udp_content_deliver_all_resp -## udp_content_delivery_ports_orig udp_content_delivery_ports_resp -event udp_contents%(u: connection, is_orig: bool, contents: string%); - -## Generated when a UDP session for a supported protocol has finished. Some of -## Bro's application-layer UDP analyzers flag the end of a session by raising -## this event. Currently, the analyzers for DNS, NTP, Netbios, Syslog, AYIYA, -## Teredo, and GTPv1 support this. -## -## u: The connection record for the corresponding UDP flow. -## -## .. bro:see:: udp_contents udp_reply udp_request -event udp_session_done%(u: connection%); - -## Generated for all ICMP messages that are not handled separately with -## dedicated ICMP events. Bro's ICMP analyzer handles a number of ICMP messages -## directly with dedicated events. This event acts as a fallback for those it -## doesn't. -## -## See `Wikipedia -## `__ for more -## information about the ICMP protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard -## connection record *c*. -## -## .. bro:see:: icmp_error_message -event icmp_sent%(c: connection, icmp: icmp_conn%); - -## Generated for ICMP *echo request* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMP protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard -## connection record *c*. -## -## id: The *echo request* identifier. -## -## seq: The *echo request* sequence number. -## -## payload: The message-specific data of the packet payload, i.e., everything -## after the first 8 bytes of the ICMP header. -## -## .. bro:see:: icmp_echo_reply -event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); - -## Generated for ICMP *echo reply* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMP protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard connection -## record *c*. -## -## id: The *echo reply* identifier. -## -## seq: The *echo reply* sequence number. -## -## payload: The message-specific data of the packet payload, i.e., everything -## after the first 8 bytes of the ICMP header. -## -## .. bro:see:: icmp_echo_request -event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); - -## Generated for all ICMPv6 error messages that are not handled -## separately with dedicated events. Bro's ICMP analyzer handles a number -## of ICMP error messages directly with dedicated events. This event acts -## as a fallback for those it doesn't. -## -## See `Wikipedia -## `__ for more -## information about the ICMPv6 protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard -## connection record *c*. -## -## code: The ICMP code of the error message. -## -## context: A record with specifics of the original packet that the message -## refers to. -## -## .. bro:see:: icmp_unreachable icmp_packet_too_big -## icmp_time_exceeded icmp_parameter_problem -event icmp_error_message%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); - -## Generated for ICMP *destination unreachable* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMP protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard connection -## record *c*. -## -## code: The ICMP code of the *unreachable* message. -## -## context: A record with specifics of the original packet that the message -## refers to. *Unreachable* messages should include the original IP -## header from the packet that triggered them, and Bro parses that -## into the *context* structure. Note that if the *unreachable* -## includes only a partial IP header for some reason, no -## fields of *context* will be filled out. -## -## .. bro:see:: icmp_error_message icmp_packet_too_big -## icmp_time_exceeded icmp_parameter_problem -event icmp_unreachable%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); - -## Generated for ICMPv6 *packet too big* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMPv6 protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard connection -## record *c*. -## -## code: The ICMP code of the *too big* message. -## -## context: A record with specifics of the original packet that the message -## refers to. *Too big* messages should include the original IP header -## from the packet that triggered them, and Bro parses that into -## the *context* structure. Note that if the *too big* includes only -## a partial IP header for some reason, no fields of *context* will -## be filled out. -## -## .. bro:see:: icmp_error_message icmp_unreachable -## icmp_time_exceeded icmp_parameter_problem -event icmp_packet_too_big%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); - -## Generated for ICMP *time exceeded* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMP protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard connection -## record *c*. -## -## code: The ICMP code of the *exceeded* message. -## -## context: A record with specifics of the original packet that the message -## refers to. *Unreachable* messages should include the original IP -## header from the packet that triggered them, and Bro parses that -## into the *context* structure. Note that if the *exceeded* includes -## only a partial IP header for some reason, no fields of *context* -## will be filled out. -## -## .. bro:see:: icmp_error_message icmp_unreachable icmp_packet_too_big -## icmp_parameter_problem -event icmp_time_exceeded%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); - -## Generated for ICMPv6 *parameter problem* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMPv6 protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard connection -## record *c*. -## -## code: The ICMP code of the *parameter problem* message. -## -## context: A record with specifics of the original packet that the message -## refers to. *Parameter problem* messages should include the original -## IP header from the packet that triggered them, and Bro parses that -## into the *context* structure. Note that if the *parameter problem* -## includes only a partial IP header for some reason, no fields -## of *context* will be filled out. -## -## .. bro:see:: icmp_error_message icmp_unreachable icmp_packet_too_big -## icmp_time_exceeded -event icmp_parameter_problem%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); - -## Generated for ICMP *router solicitation* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMP protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard connection -## record *c*. -## -## options: Any Neighbor Discovery options included with message (:rfc:`4861`). -## -## .. bro:see:: icmp_router_advertisement -## icmp_neighbor_solicitation icmp_neighbor_advertisement icmp_redirect -event icmp_router_solicitation%(c: connection, icmp: icmp_conn, options: icmp6_nd_options%); - -## Generated for ICMP *router advertisement* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMP protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard connection -## record *c*. -## -## cur_hop_limit: The default value that should be placed in Hop Count field -## for outgoing IP packets. -## -## managed: Managed address configuration flag, :rfc:`4861`. -## -## other: Other stateful configuration flag, :rfc:`4861`. -## -## home_agent: Mobile IPv6 home agent flag, :rfc:`3775`. -## -## pref: Router selection preferences, :rfc:`4191`. -## -## proxy: Neighbor discovery proxy flag, :rfc:`4389`. -## -## rsv: Remaining two reserved bits of router advertisement flags. -## -## router_lifetime: How long this router should be used as a default router. -## -## reachable_time: How long a neighbor should be considered reachable. -## -## retrans_timer: How long a host should wait before retransmitting. -## -## options: Any Neighbor Discovery options included with message (:rfc:`4861`). -## -## .. bro:see:: icmp_router_solicitation -## icmp_neighbor_solicitation icmp_neighbor_advertisement icmp_redirect -event icmp_router_advertisement%(c: connection, icmp: icmp_conn, cur_hop_limit: count, managed: bool, other: bool, home_agent: bool, pref: count, proxy: bool, rsv: count, router_lifetime: interval, reachable_time: interval, retrans_timer: interval, options: icmp6_nd_options%); - -## Generated for ICMP *neighbor solicitation* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMP protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard connection -## record *c*. -## -## tgt: The IP address of the target of the solicitation. -## -## options: Any Neighbor Discovery options included with message (:rfc:`4861`). -## -## .. bro:see:: icmp_router_solicitation icmp_router_advertisement -## icmp_neighbor_advertisement icmp_redirect -event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn, tgt: addr, options: icmp6_nd_options%); - -## Generated for ICMP *neighbor advertisement* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMP protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard connection -## record *c*. -## -## router: Flag indicating the sender is a router. -## -## solicited: Flag indicating advertisement is in response to a solicitation. -## -## override: Flag indicating advertisement should override existing caches. -## -## tgt: the Target Address in the soliciting message or the address whose -## link-layer address has changed for unsolicited adverts. -## -## options: Any Neighbor Discovery options included with message (:rfc:`4861`). -## -## .. bro:see:: icmp_router_solicitation icmp_router_advertisement -## icmp_neighbor_solicitation icmp_redirect -event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn, router: bool, solicited: bool, override: bool, tgt: addr, options: icmp6_nd_options%); - -## Generated for ICMP *redirect* messages. -## -## See `Wikipedia -## `__ for more -## information about the ICMP protocol. -## -## c: The connection record for the corresponding ICMP flow. -## -## icmp: Additional ICMP-specific information augmenting the standard connection -## record *c*. -## -## tgt: The address that is supposed to be a better first hop to use for -## ICMP Destination Address. -## -## dest: The address of the destination which is redirected to the target. -## -## options: Any Neighbor Discovery options included with message (:rfc:`4861`). -## -## .. bro:see:: icmp_router_solicitation icmp_router_advertisement -## icmp_neighbor_solicitation icmp_neighbor_advertisement -event icmp_redirect%(c: connection, icmp: icmp_conn, tgt: addr, dest: addr, options: icmp6_nd_options%); +event protocol_violation%(c: connection, atype: Analyzer::Tag, aid: count, reason: string%); ## Generated when a TCP connection terminated, passing on statistics about the ## two endpoints. This event is always generated when Bro flushes the internal @@ -1329,4950 +513,6 @@ event net_weird%(name: string%); ## dmem: The difference in memory usage caused by processing the sampled packet. event load_sample%(samples: load_sample_info, CPU: interval, dmem: int%); -## Generated for ARP requests. -## -## See `Wikipedia `__ -## for more information about the ARP protocol. -## -## mac_src: The request's source MAC address. -## -## mac_dst: The request's destination MAC address. -## -## SPA: The sender protocol address. -## -## SHA: The sender hardware address. -## -## TPA: The target protocol address. -## -## THA: The target hardware address. -## -## .. bro:see:: arp_reply bad_arp -event arp_request%(mac_src: string, mac_dst: string, SPA: addr, SHA: string, - TPA: addr, THA: string%); - -## Generated for ARP replies. -## -## See `Wikipedia `__ -## for more information about the ARP protocol. -## -## mac_src: The reply's source MAC address. -## -## mac_dst: The reply's destination MAC address. -## -## SPA: The sender protocol address. -## -## SHA: The sender hardware address. -## -## TPA: The target protocol address. -## -## THA: The target hardware address. -## -## .. bro:see:: arp_request bad_arp -event arp_reply%(mac_src: string, mac_dst: string, SPA: addr, SHA: string, - TPA: addr, THA: string%); - -## Generated for ARP packets that Bro cannot interpret. Examples are packets -## with non-standard hardware address formats or hardware addresses that do not -## match the originator of the packet. -## -## SPA: The sender protocol address. -## -## SHA: The sender hardware address. -## -## TPA: The target protocol address. -## -## THA: The target hardware address. -## -## explanation: A short description of why the ARP packet is considered "bad". -## -## .. bro:see:: arp_reply arp_request -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event bad_arp%(SPA: addr, SHA: string, TPA: addr, THA: string, explanation: string%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_have bittorrent_peer_interested bittorrent_peer_keep_alive -## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port -## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown -## bittorrent_peer_weird -event bittorrent_peer_handshake%(c: connection, is_orig: bool, - reserved: string, info_hash: string, peer_id: string%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port -## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown -## bittorrent_peer_weird -event bittorrent_peer_keep_alive%(c: connection, is_orig: bool%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke -## bittorrent_peer_unknown bittorrent_peer_weird -event bittorrent_peer_choke%(c: connection, is_orig: bool%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_port bittorrent_peer_request -## bittorrent_peer_unknown bittorrent_peer_weird -event bittorrent_peer_unchoke%(c: connection, is_orig: bool%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_keep_alive -## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port -## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown -## bittorrent_peer_weird -event bittorrent_peer_interested%(c: connection, is_orig: bool%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_piece bittorrent_peer_port -## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown -## bittorrent_peer_weird -event bittorrent_peer_not_interested%(c: connection, is_orig: bool%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_interested bittorrent_peer_keep_alive -## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port -## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown -## bittorrent_peer_weird -event bittorrent_peer_have%(c: connection, is_orig: bool, piece_index: count%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_cancel bittorrent_peer_choke bittorrent_peer_handshake -## bittorrent_peer_have bittorrent_peer_interested bittorrent_peer_keep_alive -## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port -## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown -## bittorrent_peer_weird -event bittorrent_peer_bitfield%(c: connection, is_orig: bool, bitfield: string%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_port bittorrent_peer_unchoke bittorrent_peer_unknown -## bittorrent_peer_weird -event bittorrent_peer_request%(c: connection, is_orig: bool, index: count, - begin: count, length: count%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_port -## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown -## bittorrent_peer_weird -event bittorrent_peer_piece%(c: connection, is_orig: bool, index: count, - begin: count, piece_length: count%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke -## bittorrent_peer_unknown bittorrent_peer_weird -event bittorrent_peer_cancel%(c: connection, is_orig: bool, index: count, - begin: count, length: count%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown -## bittorrent_peer_weird -event bittorrent_peer_port%(c: connection, is_orig: bool, listen_port: port%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke -## bittorrent_peer_weird -event bittorrent_peer_unknown%(c: connection, is_orig: bool, message_id: count, - data: string%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke -## bittorrent_peer_unknown -event bittorrent_peer_weird%(c: connection, is_orig: bool, msg: string%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke -## bittorrent_peer_unknown bittorrent_peer_weird -event bt_tracker_request%(c: connection, uri: string, - headers: bt_tracker_headers%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke -## bittorrent_peer_unknown bittorrent_peer_weird -event bt_tracker_response%(c: connection, status: count, - headers: bt_tracker_headers, - peers: bittorrent_peer_set, - benc: bittorrent_benc_dir%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke -## bittorrent_peer_unknown bittorrent_peer_weird -event bt_tracker_response_not_ok%(c: connection, status: count, - headers: bt_tracker_headers%); - -## TODO. -## -## See `Wikipedia `__ for -## more information about the BitTorrent protocol. -## -## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke -## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested -## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece -## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke -## bittorrent_peer_unknown bittorrent_peer_weird -event bt_tracker_weird%(c: connection, is_orig: bool, msg: string%); - -## Generated for Finger requests. -## -## See `Wikipedia `__ for more -## information about the Finger protocol. -## -## c: The connection. -## -## full: True if verbose information is requested (``/W`` switch). -## -## username: The request's user name. -## -## hostname: The request's host name. -## -## .. bro:see:: finger_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event finger_request%(c: connection, full: bool, username: string, hostname: string%); - -## Generated for Finger replies. -## -## See `Wikipedia `__ for more -## information about the Finger protocol. -## -## c: The connection. -## -## reply_line: The reply as returned by the server -## -## .. bro:see:: finger_request -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event finger_reply%(c: connection, reply_line: string%); - - -## TODO. -## -## See `Wikipedia `__ for more -## information about the Gnutella protocol. -## -## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify -## gnutella_not_establish gnutella_partial_binary_msg gnutella_signature_found -## -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event gnutella_text_msg%(c: connection, orig: bool, headers: string%); - -## TODO. -## -## See `Wikipedia `__ for more -## information about the Gnutella protocol. -## -## .. bro:see:: gnutella_establish gnutella_http_notify gnutella_not_establish -## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event gnutella_binary_msg%(c: connection, orig: bool, msg_type: count, - ttl: count, hops: count, msg_len: count, - payload: string, payload_len: count, - trunc: bool, complete: bool%); - -## TODO. -## -## See `Wikipedia `__ for more -## information about the Gnutella protocol. -## -## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify -## gnutella_not_establish gnutella_signature_found gnutella_text_msg -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event gnutella_partial_binary_msg%(c: connection, orig: bool, - msg: string, len: count%); - -## TODO. -## -## See `Wikipedia `__ for more -## information about the Gnutella protocol. -## -## .. bro:see:: gnutella_binary_msg gnutella_http_notify gnutella_not_establish -## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event gnutella_establish%(c: connection%); - -## TODO. -## -## See `Wikipedia `__ for more -## information about the Gnutella protocol. -## -## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify -## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event gnutella_not_establish%(c: connection%); - -## TODO. -## -## See `Wikipedia `__ for more -## information about the Gnutella protocol. -## -## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_not_establish -## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event gnutella_http_notify%(c: connection%); - -## Generated for Ident requests. -## -## See `Wikipedia `__ for more -## information about the Ident protocol. -## -## c: The connection. -## -## lport: The request's local port. -## -## rport: The request's remote port. -## -## .. bro:see:: ident_error ident_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event ident_request%(c: connection, lport: port, rport: port%); - -## Generated for Ident replies. -## -## See `Wikipedia `__ for more -## information about the Ident protocol. -## -## c: The connection. -## -## lport: The corresponding request's local port. -## -## rport: The corresponding request's remote port. -## -## user_id: The user id returned by the reply. -## -## system: The operating system returned by the reply. -## -## .. bro:see:: ident_error ident_request -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event ident_reply%(c: connection, lport: port, rport: port, user_id: string, system: string%); - -## Generated for Ident error replies. -## -## See `Wikipedia `__ for more -## information about the Ident protocol. -## -## c: The connection. -## -## lport: The corresponding request's local port. -## -## rport: The corresponding request's remote port. -## -## line: The error description returned by the reply. -## -## .. bro:see:: ident_reply ident_request -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event ident_error%(c: connection, lport: port, rport: port, line: string%); - -## Generated for Telnet/Rlogin login failures. The *login* analyzer inspects -## Telnet/Rlogin sessions to heuristically extract username and password -## information as well as the text returned by the login server. This event is -## raised if a login attempt appears to have been unsuccessful. -## -## c: The connection. -## -## user: The user name tried. -## -## client_user: For Telnet connections, this is an empty string, but for Rlogin -## connections, it is the client name passed in the initial authentication -## information (to check against .rhosts). -## -## password: The password tried. -## -## line: The line of text that led the analyzer to conclude that the -## authentication had failed. -## -## .. bro:see:: login_confused login_confused_text login_display login_input_line -## login_output_line login_prompt login_success login_terminal direct_login_prompts -## get_login_state login_failure_msgs login_non_failure_msgs login_prompts login_success_msgs -## login_timeouts set_login_state -## -## .. note:: The login analyzer depends on a set of script-level variables that -## need to be configured with patterns identifying login attempts. This -## configuration has not yet been ported over from Bro 1.5 to Bro 2.x, and -## the analyzer is therefore not directly usable at the moment. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event login_failure%(c: connection, user: string, client_user: string, password: string, line: string%); - -## Generated for successful Telnet/Rlogin logins. The *login* analyzer inspects -## Telnet/Rlogin sessions to heuristically extract username and password -## information as well as the text returned by the login server. This event is -## raised if a login attempt appears to have been successful. -## -## c: The connection. -## -## user: The user name used. -## -## client_user: For Telnet connections, this is an empty string, but for Rlogin -## connections, it is the client name passed in the initial authentication -## information (to check against .rhosts). -## -## password: The password used. -## -## line: The line of text that led the analyzer to conclude that the -## authentication had succeeded. -## -## .. bro:see:: login_confused login_confused_text login_display login_failure -## login_input_line login_output_line login_prompt login_terminal -## direct_login_prompts get_login_state login_failure_msgs login_non_failure_msgs -## login_prompts login_success_msgs login_timeouts set_login_state -## -## .. note:: The login analyzer depends on a set of script-level variables that -## need to be configured with patterns identifying login attempts. This -## configuration has not yet been ported over from Bro 1.5 to Bro 2.x, and -## the analyzer is therefore not directly usable at the moment. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event login_success%(c: connection, user: string, client_user: string, password: string, line: string%); - -## Generated for lines of input on Telnet/Rlogin sessions. The line will have -## control characters (such as in-band Telnet options) removed. -## -## c: The connection. -## -## line: The input line. -## -## .. bro:see:: login_confused login_confused_text login_display login_failure -## login_output_line login_prompt login_success login_terminal rsh_request -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event login_input_line%(c: connection, line: string%); - -## Generated for lines of output on Telnet/Rlogin sessions. The line will have -## control characters (such as in-band Telnet options) removed. -## -## c: The connection. -## -## line: The ouput line. -## -## .. bro:see:: login_confused login_confused_text login_display login_failure -## login_input_line login_prompt login_success login_terminal rsh_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event login_output_line%(c: connection, line: string%); - -## Generated when tracking of Telnet/Rlogin authentication failed. As Bro's -## *login* analyzer uses a number of heuristics to extract authentication -## information, it may become confused. If it can no longer correctly track -## the authentication dialog, it raises this event. -## -## c: The connection. -## -## msg: Gives the particular problem the heuristics detected (for example, -## ``multiple_login_prompts`` means that the engine saw several login -## prompts in a row, without the type-ahead from the client side presumed -## necessary to cause them) -## -## line: The line of text that caused the heuristics to conclude they were -## confused. -## -## .. bro:see:: login_confused_text login_display login_failure login_input_line login_output_line -## login_prompt login_success login_terminal direct_login_prompts get_login_state -## login_failure_msgs login_non_failure_msgs login_prompts login_success_msgs -## login_timeouts set_login_state -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event login_confused%(c: connection, msg: string, line: string%); - -## Generated after getting confused while tracking a Telnet/Rlogin -## authentication dialog. The *login* analyzer generates this even for every -## line of user input after it has reported :bro:id:`login_confused` for a -## connection. -## -## c: The connection. -## -## line: The line the user typed. -## -## .. bro:see:: login_confused login_display login_failure login_input_line -## login_output_line login_prompt login_success login_terminal direct_login_prompts -## get_login_state login_failure_msgs login_non_failure_msgs login_prompts -## login_success_msgs login_timeouts set_login_state -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event login_confused_text%(c: connection, line: string%); - -## Generated for clients transmitting a terminal type in a Telnet session. This -## information is extracted out of environment variables sent as Telnet options. -## -## c: The connection. -## -## terminal: The TERM value transmitted. -## -## .. bro:see:: login_confused login_confused_text login_display login_failure -## login_input_line login_output_line login_prompt login_success -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event login_terminal%(c: connection, terminal: string%); - -## Generated for clients transmitting an X11 DISPLAY in a Telnet session. This -## information is extracted out of environment variables sent as Telnet options. -## -## c: The connection. -## -## display: The DISPLAY transmitted. -## -## .. bro:see:: login_confused login_confused_text login_failure login_input_line -## login_output_line login_prompt login_success login_terminal -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event login_display%(c: connection, display: string%); - -## Generated when a Telnet authentication has been successful. The Telnet -## protocol includes options for negotiating authentication. When such an -## option is sent from client to server and the server replies that it accepts -## the authentication, then the event engine generates this event. -## -## See `Wikipedia `__ for more information -## about the Telnet protocol. -## -## name: The authenticated name. -## -## c: The connection. -## -## .. bro:see:: authentication_rejected authentication_skipped login_success -## -## .. note:: This event inspects the corresponding Telnet option -## while :bro:id:`login_success` heuristically determines success by watching -## session data. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event authentication_accepted%(name: string, c: connection%); - -## Generated when a Telnet authentication has been unsuccessful. The Telnet -## protocol includes options for negotiating authentication. When such an option -## is sent from client to server and the server replies that it did not accept -## the authentication, then the event engine generates this event. -## -## See `Wikipedia `__ for more information -## about the Telnet protocol. -## -## name: The attempted authentication name. -## -## c: The connection. -## -## .. bro:see:: authentication_accepted authentication_skipped login_failure -## -## .. note:: This event inspects the corresponding Telnet option -## while :bro:id:`login_success` heuristically determines failure by watching -## session data. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event authentication_rejected%(name: string, c: connection%); - -## Generated for Telnet/Rlogin sessions when a pattern match indicates -## that no authentication is performed. -## -## See `Wikipedia `__ for more information -## about the Telnet protocol. -## -## c: The connection. -## -## .. bro:see:: authentication_accepted authentication_rejected direct_login_prompts -## get_login_state login_failure_msgs login_non_failure_msgs login_prompts -## login_success_msgs login_timeouts set_login_state -## -## .. note:: The login analyzer depends on a set of script-level variables that -## need to be configured with patterns identifying activity. This -## configuration has not yet been ported over from Bro 1.5 to Bro 2.x, and -## the analyzer is therefore not directly usable at the moment. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event authentication_skipped%(c: connection%); - -## Generated for clients transmitting a terminal prompt in a Telnet session. -## This information is extracted out of environment variables sent as Telnet -## options. -## -## See `Wikipedia `__ for more information -## about the Telnet protocol. -## -## c: The connection. -## -## prompt: The TTYPROMPT transmitted. -## -## .. bro:see:: login_confused login_confused_text login_display login_failure -## login_input_line login_output_line login_success login_terminal -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event login_prompt%(c: connection, prompt: string%); - -## Generated for Telnet sessions when encryption is activated. The Telnet -## protocol includes options for negotiating encryption. When such a series of -## options is successfully negotiated, the event engine generates this event. -## -## See `Wikipedia `__ for more information -## about the Telnet protocol. -## -## c: The connection. -## -## .. bro:see:: authentication_accepted authentication_rejected authentication_skipped -## login_confused login_confused_text login_display login_failure login_input_line -## login_output_line login_prompt login_success login_terminal -event activating_encryption%(c: connection%); - -## Generated for an inconsistent Telnet option. Telnet options are specified -## by the client and server stating which options they are willing to -## support vs. which they are not, and then instructing one another which in -## fact they should or should not use for the current connection. If the event -## engine sees a peer violate either what the other peer has instructed it to -## do, or what it itself offered in terms of options in the past, then the -## engine generates this event. -## -## See `Wikipedia `__ for more information -## about the Telnet protocol. -## -## c: The connection. -## -## .. bro:see:: bad_option bad_option_termination authentication_accepted -## authentication_rejected authentication_skipped login_confused -## login_confused_text login_display login_failure login_input_line -## login_output_line login_prompt login_success login_terminal -event inconsistent_option%(c: connection%); - -## Generated for an ill-formed or unrecognized Telnet option. -## -## See `Wikipedia `__ for more information -## about the Telnet protocol. -## -## c: The connection. -## -## .. bro:see:: inconsistent_option bad_option_termination authentication_accepted -## authentication_rejected authentication_skipped login_confused -## login_confused_text login_display login_failure login_input_line -## login_output_line login_prompt login_success login_terminal -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event bad_option%(c: connection%); - -## Generated for a Telnet option that's incorrectly terminated. -## -## See `Wikipedia `__ for more information -## about the Telnet protocol. -## -## c: The connection. -## -## .. bro:see:: inconsistent_option bad_option authentication_accepted -## authentication_rejected authentication_skipped login_confused -## login_confused_text login_display login_failure login_input_line -## login_output_line login_prompt login_success login_terminal -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event bad_option_termination%(c: connection%); - -## Generated for client side commands on an RSH connection. -## -## See `RFC 1258 `__ for more information -## about the Rlogin/Rsh protocol. -## -## c: The connection. -## -## client_user: The client-side user name as sent in the initial protocol -## handshake. -## -## server_user: The server-side user name as sent in the initial protocol -## handshake. -## -## line: The command line sent in the request. -## -## new_session: True if this is the first command of the Rsh session. -## -## .. bro:see:: rsh_reply login_confused login_confused_text login_display -## login_failure login_input_line login_output_line login_prompt login_success -## login_terminal -## -## .. note:: For historical reasons, these events are separate from the -## ``login_`` events. Ideally, they would all be handled uniquely. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event rsh_request%(c: connection, client_user: string, server_user: string, line: string, new_session: bool%); - -## Generated for client side commands on an RSH connection. -## -## See `RFC 1258 `__ for more information -## about the Rlogin/Rsh protocol. -## -## c: The connection. -## -## client_user: The client-side user name as sent in the initial protocol -## handshake. -## -## server_user: The server-side user name as sent in the initial protocol -## handshake. -## -## line: The command line sent in the request. -## -## .. bro:see:: rsh_request login_confused login_confused_text login_display -## login_failure login_input_line login_output_line login_prompt login_success -## login_terminal -## -## .. note:: For historical reasons, these events are separate from the -## ``login_`` events. Ideally, they would all be handled uniquely. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event rsh_reply%(c: connection, client_user: string, server_user: string, line: string%); - -## Generated for client-side FTP commands. -## -## See `Wikipedia `__ for -## more information about the FTP protocol. -## -## c: The connection. -## -## command: The FTP command issued by the client (without any arguments). -## -## arg: The arguments going with the command. -## -## .. bro:see:: ftp_reply fmt_ftp_port parse_eftp_port -## parse_ftp_epsv parse_ftp_pasv parse_ftp_port -event ftp_request%(c: connection, command: string, arg: string%) &group="ftp"; - -## Generated for server-side FTP replies. -## -## See `Wikipedia `__ for -## more information about the FTP protocol. -## -## c: The connection. -## -## code: The numerical response code the server responded with. -## -## msg: The textual message of the response. -## -## cont_resp: True if the reply line is tagged as being continued to the next -## line. If so, further events will be raised and a handler may want -## to reassemble the pieces before processing the response any -## further. -## -## .. bro:see:: ftp_request fmt_ftp_port parse_eftp_port -## parse_ftp_epsv parse_ftp_pasv parse_ftp_port -event ftp_reply%(c: connection, code: count, msg: string, cont_resp: bool%) &group="ftp"; - -## Generated for client-side SMTP commands. -## -## See `Wikipedia `__ -## for more information about the SMTP protocol. -## -## c: The connection. -## -## is_orig: True if the sender of the command is the originator of the TCP -## connection. Note that this is not redundant: the SMTP ``TURN`` command -## allows client and server to flip roles on established SMTP sessions, -## and hence a "request" might still come from the TCP-level responder. -## In practice, however, that will rarely happen as TURN is considered -## insecure and rarely used. -## -## command: The request's command, without any arguments. -## -## arg: The request command's arguments. -## -## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash -## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data -## smtp_data smtp_reply -## -## .. note:: Bro does not support the newer ETRN extension yet. -event smtp_request%(c: connection, is_orig: bool, command: string, arg: string%) &group="smtp"; - -## Generated for server-side SMTP commands. -## -## See `Wikipedia `__ -## for more information about the SMTP protocol. -## -## c: The connection. -## -## is_orig: True if the sender of the command is the originator of the TCP -## connection. Note that this is not redundant: the SMTP ``TURN`` command -## allows client and server to flip roles on established SMTP sessions, -## and hence a "reply" might still come from the TCP-level originator. In -## practice, however, that will rarely happen as TURN is considered -## insecure and rarely used. -## -## code: The reply's numerical code. -## -## cmd: TODO. -## -## msg: The reply's textual description. -## -## cont_resp: True if the reply line is tagged as being continued to the next -## line. If so, further events will be raised and a handler may want to -## reassemble the pieces before processing the response any further. -## -## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash -## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data -## smtp_data smtp_request -## -## .. note:: Bro doesn't support the newer ETRN extension yet. -event smtp_reply%(c: connection, is_orig: bool, code: count, cmd: string, msg: string, cont_resp: bool%) &group="smtp"; - -## Generated for DATA transmitted on SMTP sessions. This event is raised for -## subsequent chunks of raw data following the ``DATA`` SMTP command until the -## corresponding end marker ``.`` is seen. A handler may want to reassemble -## the pieces as they come in if stream-analysis is required. -## -## See `Wikipedia `__ -## for more information about the SMTP protocol. -## -## c: The connection. -## -## is_orig: True if the sender of the data is the originator of the TCP -## connection. -## -## data: The raw data. Note that the size of each chunk is undefined and -## depends on specifics of the underlying TCP connection. -## -## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash -## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data -## smtp_reply smtp_request skip_smtp_data -## -## .. note:: This event receives the unprocessed raw data. There is a separate -## set of ``mime_*`` events that strip out the outer MIME-layer of emails and -## provide structured access to their content. -event smtp_data%(c: connection, is_orig: bool, data: string%) &group="smtp"; - -## Generated for unexpected activity on SMTP sessions. The SMTP analyzer tracks -## the state of SMTP sessions and reports commands and other activity with this -## event that it sees even though it would not expect so at the current point -## of the communication. -## -## See `Wikipedia `__ -## for more information about the SMTP protocol. -## -## c: The connection. -## -## is_orig: True if the sender of the unexpected activity is the originator of -## the TCP connection. -## -## msg: A descriptive message of what was unexpected. -## -## detail: The actual SMTP line triggering the event. -## -## .. bro:see:: smtp_data smtp_request smtp_reply -event smtp_unexpected%(c: connection, is_orig: bool, msg: string, detail: string%) &group="smtp"; - -## Generated when starting to parse an email MIME entity. MIME is a -## protocol-independent data format for encoding text and files, along with -## corresponding metadata, for transmission. Bro raises this event when it -## begins parsing a MIME entity extracted from an email protocol. -## -## Bro's MIME analyzer for emails currently supports SMTP and POP3. See -## `Wikipedia `__ for more information -## about MIME. -## -## c: The connection. -## -## .. bro:see:: mime_all_data mime_all_headers mime_content_hash mime_end_entity -## mime_entity_data mime_event mime_one_header mime_segment_data smtp_data -## http_begin_entity -## -## .. note:: Bro also extracts MIME entities from HTTP sessions. For those, -## however, it raises :bro:id:`http_begin_entity` instead. -event mime_begin_entity%(c: connection%); - -## Generated when finishing parsing an email MIME entity. MIME is a -## protocol-independent data format for encoding text and files, along with -## corresponding metadata, for transmission. Bro raises this event when it -## finished parsing a MIME entity extracted from an email protocol. -## -## Bro's MIME analyzer for emails currently supports SMTP and POP3. See -## `Wikipedia `__ for more information -## about MIME. -## -## c: The connection. -## -## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash -## mime_entity_data mime_event mime_one_header mime_segment_data smtp_data -## http_end_entity -## -## .. note:: Bro also extracts MIME entities from HTTP sessions. For those, -## however, it raises :bro:id:`http_end_entity` instead. -event mime_end_entity%(c: connection%); - -## Generated for individual MIME headers extracted from email MIME -## entities. MIME is a protocol-independent data format for encoding text and -## files, along with corresponding metadata, for transmission. -## -## Bro's MIME analyzer for emails currently supports SMTP and POP3. See -## `Wikipedia `__ for more information -## about MIME. -## -## c: The connection. -## -## h: The parsed MIME header. -## -## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash -## mime_end_entity mime_entity_data mime_event mime_segment_data -## http_header http_all_headers -## -## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, -## however, it raises :bro:id:`http_header` instead. -event mime_one_header%(c: connection, h: mime_header_rec%); - -## Generated for MIME headers extracted from email MIME entities, passing all -## headers at once. MIME is a protocol-independent data format for encoding -## text and files, along with corresponding metadata, for transmission. -## -## Bro's MIME analyzer for emails currently supports SMTP and POP3. See -## `Wikipedia `__ for more information -## about MIME. -## -## c: The connection. -## -## hlist: A *table* containing all headers extracted from the current entity. -## The table is indexed by the position of the header (1 for the first, -## 2 for the second, etc.). -## -## .. bro:see:: mime_all_data mime_begin_entity mime_content_hash mime_end_entity -## mime_entity_data mime_event mime_one_header mime_segment_data -## http_header http_all_headers -## -## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, -## however, it raises :bro:id:`http_header` instead. -event mime_all_headers%(c: connection, hlist: mime_header_list%); - -## Generated for chunks of decoded MIME data from email MIME entities. MIME -## is a protocol-independent data format for encoding text and files, along with -## corresponding metadata, for transmission. As Bro parses the data of an -## entity, it raises a sequence of these events, each coming as soon as a new -## chunk of data is available. In contrast, there is also -## :bro:id:`mime_entity_data`, which passes all of an entities data at once -## in a single block. While the latter is more convenient to handle, -## ``mime_segment_data`` is more efficient as Bro does not need to buffer -## the data. Thus, if possible, this event should be preferred. -## -## Bro's MIME analyzer for emails currently supports SMTP and POP3. See -## `Wikipedia `__ for more information -## about MIME. -## -## c: The connection. -## -## length: The length of *data*. -## -## data: The raw data of one segment of the current entity. -## -## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash -## mime_end_entity mime_entity_data mime_event mime_one_header http_entity_data -## mime_segment_length mime_segment_overlap_length -## -## .. note:: Bro also extracts MIME data from HTTP sessions. For those, -## however, it raises :bro:id:`http_entity_data` (sic!) instead. -event mime_segment_data%(c: connection, length: count, data: string%); - -## Generated for data decoded from an email MIME entity. This event delivers -## the complete content of a single MIME entity. In contrast, there is also -## :bro:id:`mime_segment_data`, which passes on a sequence of data chunks as -## they come in. While ``mime_entity_data`` is more convenient to handle, -## ``mime_segment_data`` is more efficient as Bro does not need to buffer the -## data. Thus, if possible, the latter should be preferred. -## -## Bro's MIME analyzer for emails currently supports SMTP and POP3. See -## `Wikipedia `__ for more information -## about MIME. -## -## c: The connection. -## -## length: The length of *data*. -## -## data: The raw data of the complete entity. -## -## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash -## mime_end_entity mime_event mime_one_header mime_segment_data -## -## .. note:: While Bro also decodes MIME entities extracted from HTTP -## sessions, there's no corresponding event for that currently. -event mime_entity_data%(c: connection, length: count, data: string%); - -## Generated for passing on all data decoded from a single email MIME -## message. If an email message has more than one MIME entity, this event -## combines all their data into a single value for analysis. Note that because -## of the potentially significant buffering necessary, using this event can be -## expensive. -## -## Bro's MIME analyzer for emails currently supports SMTP and POP3. See -## `Wikipedia `__ for more information -## about MIME. -## -## c: The connection. -## -## length: The length of *data*. -## -## data: The raw data of all MIME entities concatenated. -## -## .. bro:see:: mime_all_headers mime_begin_entity mime_content_hash mime_end_entity -## mime_entity_data mime_event mime_one_header mime_segment_data -## -## .. note:: While Bro also decodes MIME entities extracted from HTTP -## sessions, there's no corresponding event for that currently. -event mime_all_data%(c: connection, length: count, data: string%); - -## Generated for errors found when decoding email MIME entities. -## -## Bro's MIME analyzer for emails currently supports SMTP and POP3. See -## `Wikipedia `__ for more information -## about MIME. -## -## c: The connection. -## -## event_type: A string describing the general category of the problem found -## (e.g., ``illegal format``). -## -## detail: Further more detailed description of the error. -## -## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash -## mime_end_entity mime_entity_data mime_one_header mime_segment_data http_event -## -## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, -## however, it raises :bro:id:`http_event` instead. -event mime_event%(c: connection, event_type: string, detail: string%); - -## Generated for decoded MIME entities extracted from email messages, passing on -## their MD5 checksums. Bro computes the MD5 over the complete decoded data of -## each MIME entity. -## -## Bro's MIME analyzer for emails currently supports SMTP and POP3. See -## `Wikipedia `__ for more information -## about MIME. -## -## c: The connection. -## -## content_len: The length of the entity being hashed. -## -## hash_value: The MD5 hash. -## -## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_end_entity -## mime_entity_data mime_event mime_one_header mime_segment_data -## -## .. note:: While Bro also decodes MIME entities extracted from HTTP -## sessions, there's no corresponding event for that currently. -event mime_content_hash%(c: connection, content_len: count, hash_value: string%); - -## Generated for RPC request/reply *pairs*. The RPC analyzer associates request -## and reply by their transaction identifiers and raises this event once both -## have been seen. If there's not a reply, this event will still be generated -## eventually on timeout. In that case, *status* will be set to -## :bro:enum:`RPC_TIMEOUT`. -## -## See `Wikipedia `__ for more information -## about the ONC RPC protocol. -## -## c: The connection. -## -## prog: The remote program to call. -## -## ver: The version of the remote program to call. -## -## proc: The procedure of the remote program to call. -## -## status: The status of the reply, which should be one of the index values of -## :bro:id:`RPC_status`. -## -## start_time: The time when the *call* was seen. -## -## call_len: The size of the *call_body* PDU. -## -## reply_len: The size of the *reply_body* PDU. -## -## .. bro:see:: rpc_call rpc_reply dce_rpc_bind dce_rpc_message dce_rpc_request -## dce_rpc_response rpc_timeout -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event rpc_dialogue%(c: connection, prog: count, ver: count, proc: count, status: rpc_status, start_time: time, call_len: count, reply_len: count%); - -## Generated for RPC *call* messages. -## -## See `Wikipedia `__ for more information -## about the ONC RPC protocol. -## -## c: The connection. -## -## xid: The transaction identifier allowing to match requests with replies. -## -## prog: The remote program to call. -## -## ver: The version of the remote program to call. -## -## proc: The procedure of the remote program to call. -## -## call_len: The size of the *call_body* PDU. -## -## .. bro:see:: rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message dce_rpc_request -## dce_rpc_response rpc_timeout -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event rpc_call%(c: connection, xid: count, prog: count, ver: count, proc: count, call_len: count%); - -## Generated for RPC *reply* messages. -## -## See `Wikipedia `__ for more information -## about the ONC RPC protocol. -## -## c: The connection. -## -## xid: The transaction identifier allowing to match requests with replies. -## -## status: The status of the reply, which should be one of the index values of -## :bro:id:`RPC_status`. -## -## reply_len: The size of the *reply_body* PDU. -## -## .. bro:see:: rpc_call rpc_dialogue dce_rpc_bind dce_rpc_message dce_rpc_request -## dce_rpc_response rpc_timeout -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event rpc_reply%(c: connection, xid: count, status: rpc_status, reply_len: count%); - -## Generated for Portmapper requests of type *null*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport -## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit -## pm_request_dump pm_request_getport pm_request_set pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_request_null%(r: connection%); - -## Generated for Portmapper request/reply dialogues of type *set*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## m: The argument to the request. -## -## success: True if the request was successful, according to the corresponding -## reply. If no reply was seen, this will be false once the request -## times out. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport -## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit -## pm_request_dump pm_request_getport pm_request_null pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_request_set%(r: connection, m: pm_mapping, success: bool%); - -## Generated for Portmapper request/reply dialogues of type *unset*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## m: The argument to the request. -## -## success: True if the request was successful, according to the corresponding -## reply. If no reply was seen, this will be false once the request -## times out. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport -## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit -## pm_request_dump pm_request_getport pm_request_null pm_request_set rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_request_unset%(r: connection, m: pm_mapping, success: bool%); - -## Generated for Portmapper request/reply dialogues of type *getport*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## pr: The argument to the request. -## -## p: The port returned by the server. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport -## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit -## pm_request_dump pm_request_null pm_request_set pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_request_getport%(r: connection, pr: pm_port_request, p: port%); - -## Generated for Portmapper request/reply dialogues of type *dump*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## m: The mappings returned by the server. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport -## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit -## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_request_dump%(r: connection, m: pm_mappings%); - -## Generated for Portmapper request/reply dialogues of type *callit*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## call: The argument to the request. -## -## p: The port value returned by the call. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport -## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_dump -## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_request_callit%(r: connection, call: pm_callit_request, p: port%); - -## Generated for failed Portmapper requests of type *null*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## status: The status of the reply, which should be one of the index values of -## :bro:id:`RPC_status`. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport -## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump -## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_attempt_null%(r: connection, status: rpc_status%); - -## Generated for failed Portmapper requests of type *set*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## status: The status of the reply, which should be one of the index values of -## :bro:id:`RPC_status`. -## -## m: The argument to the original request. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport -## pm_attempt_null pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump -## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_attempt_set%(r: connection, status: rpc_status, m: pm_mapping%); - -## Generated for failed Portmapper requests of type *unset*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## status: The status of the reply, which should be one of the index values of -## :bro:id:`RPC_status`. -## -## m: The argument to the original request. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport -## pm_attempt_null pm_attempt_set pm_bad_port pm_request_callit pm_request_dump -## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_attempt_unset%(r: connection, status: rpc_status, m: pm_mapping%); - -## Generated for failed Portmapper requests of type *getport*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## status: The status of the reply, which should be one of the index values of -## :bro:id:`RPC_status`. -## -## pr: The argument to the original request. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_null -## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump -## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_attempt_getport%(r: connection, status: rpc_status, pr: pm_port_request%); - -## Generated for failed Portmapper requests of type *dump*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## status: The status of the reply, which should be one of the index values of -## :bro:id:`RPC_status`. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_getport pm_attempt_null -## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump -## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_attempt_dump%(r: connection, status: rpc_status%); - -## Generated for failed Portmapper requests of type *callit*. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## status: The status of the reply, which should be one of the index values of -## :bro:id:`RPC_status`. -## -## call: The argument to the original request. -## -## .. bro:see:: epm_map_response pm_attempt_dump pm_attempt_getport pm_attempt_null -## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump -## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_attempt_callit%(r: connection, status: rpc_status, call: pm_callit_request%); - -## Generated for Portmapper requests or replies that include an invalid port -## number. Since ports are represented by unsigned 4-byte integers, they can -## stray outside the allowed range of 0--65535 by being >= 65536. If so, this -## event is generated. -## -## Portmapper is a service running on top of RPC. See `Wikipedia -## `__ for more information about the -## service. -## -## r: The RPC connection. -## -## bad_p: The invalid port value. -## -## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport -## pm_attempt_null pm_attempt_set pm_attempt_unset pm_request_callit -## pm_request_dump pm_request_getport pm_request_null pm_request_set -## pm_request_unset rpc_call rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pm_bad_port%(r: connection, bad_p: count%); - -## Generated for NFSv3 request/reply dialogues of type *null*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_read nfs_proc_readdir nfs_proc_readlink -## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_null%(c: connection, info: NFS3::info_t%); - -## Generated for NFSv3 request/reply dialogues of type *getattr*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## fh: TODO. -## -## attrs: The attributes returned in the reply. The values may not be valid if -## the request was unsuccessful. -## -## .. bro:see:: nfs_proc_create nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir -## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status -## rpc_call rpc_dialogue rpc_reply file_mode -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_getattr%(c: connection, info: NFS3::info_t, fh: string, attrs: NFS3::fattr_t%); - -## Generated for NFSv3 request/reply dialogues of type *lookup*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## req: The arguments passed in the request. -## -## rep: The response returned in the reply. The values may not be valid if the -## request was unsuccessful. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir -## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status -## rpc_call rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_lookup%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::lookup_reply_t%); - -## Generated for NFSv3 request/reply dialogues of type *read*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## req: The arguments passed in the request. -## -## rep: The response returned in the reply. The values may not be valid if the -## request was unsuccessful. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_null nfs_proc_remove nfs_proc_rmdir -## nfs_proc_write nfs_reply_status rpc_call rpc_dialogue rpc_reply -## NFS3::return_data NFS3::return_data_first_only NFS3::return_data_max -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_read%(c: connection, info: NFS3::info_t, req: NFS3::readargs_t, rep: NFS3::read_reply_t%); - -## Generated for NFSv3 request/reply dialogues of type *readlink*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## fh: The file handle passed in the request. -## -## rep: The response returned in the reply. The values may not be valid if the -## request was unsuccessful. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir -## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_readlink%(c: connection, info: NFS3::info_t, fh: string, rep: NFS3::readlink_reply_t%); - -## Generated for NFSv3 request/reply dialogues of type *write*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## req: TODO. -## -## rep: The response returned in the reply. The values may not be valid if the -## request was unsuccessful. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir -## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_reply_status rpc_call -## rpc_dialogue rpc_reply NFS3::return_data NFS3::return_data_first_only -## NFS3::return_data_max -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_write%(c: connection, info: NFS3::info_t, req: NFS3::writeargs_t, rep: NFS3::write_reply_t%); - -## Generated for NFSv3 request/reply dialogues of type *create*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## req: TODO. -## -## rep: The response returned in the reply. The values may not be valid if the -## request was unsuccessful. -## -## .. bro:see:: nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir -## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status -## rpc_call rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_create%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::newobj_reply_t%); - -## Generated for NFSv3 request/reply dialogues of type *mkdir*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## req: TODO. -## -## rep: The response returned in the reply. The values may not be valid if the -## request was unsuccessful. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup -## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir -## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status -## rpc_call rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_mkdir%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::newobj_reply_t%); - -## Generated for NFSv3 request/reply dialogues of type *remove*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## req: TODO. -## -## rep: The response returned in the reply. The values may not be valid if the -## request was unsuccessful. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir -## nfs_proc_readlink nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_remove%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::delobj_reply_t%); - -## Generated for NFSv3 request/reply dialogues of type *rmdir*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## req: TODO. -## -## rep: The response returned in the reply. The values may not be valid if the -## request was unsuccessful. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir -## nfs_proc_readlink nfs_proc_remove nfs_proc_write nfs_reply_status rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_rmdir%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::delobj_reply_t%); - -## Generated for NFSv3 request/reply dialogues of type *readdir*. The event is -## generated once we have either seen both the request and its corresponding -## reply, or an unanswered request has timed out. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## req: TODO. -## -## rep: The response returned in the reply. The values may not be valid if the -## request was unsuccessful. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readlink -## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_readdir%(c: connection, info: NFS3::info_t, req: NFS3::readdirargs_t, rep: NFS3::readdir_reply_t%); - -## Generated for NFSv3 request/reply dialogues of a type that Bro's NFSv3 -## analyzer does not implement. -## -## NFS is a service running on top of RPC. See `Wikipedia -## `__ for more -## information about the service. -## -## c: The RPC connection. -## -## info: Reports the status of the dialogue, along with some meta information. -## -## proc: The procedure called that Bro does not implement. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_null nfs_proc_read nfs_proc_readdir nfs_proc_readlink nfs_proc_remove -## nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_proc_not_implemented%(c: connection, info: NFS3::info_t, proc: NFS3::proc_t%); - -## Generated for each NFSv3 reply message received, reporting just the -## status included. -## -## n: The connection. -## -## info: Reports the status included in the reply. -## -## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir -## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir -## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write rpc_call -## rpc_dialogue rpc_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event nfs_reply_status%(n: connection, info: NFS3::info_t%); - -## Generated for all NTP messages. Different from many other of Bro's events, -## this one is generated for both client-side and server-side messages. -## -## See `Wikipedia `__ for -## more information about the NTP protocol. -## -## u: The connection record describing the corresponding UDP flow. -## -## msg: The parsed NTP message. -## -## excess: The raw bytes of any optional parts of the NTP packet. Bro does not -## further parse any optional fields. -## -## .. bro:see:: ntp_session_timeout -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event ntp_message%(u: connection, msg: ntp_msg, excess: string%); - -## Generated for all NetBIOS SSN and DGM messages. Bro's NetBIOS analyzer -## processes the NetBIOS session service running on TCP port 139, and (despite -## its name!) the NetBIOS datagram service on UDP port 138. -## -## See `Wikipedia `__ for more information -## about NetBIOS. `RFC 1002 `__ describes -## the packet format for NetBIOS over TCP/IP, which Bro parses. -## -## c: The connection, which may be TCP or UDP, depending on the type of the -## NetBIOS session. -## -## is_orig: True if the message was sent by the originator of the connection. -## -## msg_type: The general type of message, as defined in Section 4.3.1 of -## `RFC 1002 `__. -## -## data_len: The length of the message's payload. -## -## .. bro:see:: netbios_session_accepted netbios_session_keepalive -## netbios_session_raw_message netbios_session_rejected netbios_session_request -## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type -## -## .. note:: These days, NetBIOS is primarily used as a transport mechanism for -## `SMB/CIFS `__. Bro's -## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event netbios_session_message%(c: connection, is_orig: bool, msg_type: count, data_len: count%); - -## Generated for NetBIOS messages of type *session request*. Bro's NetBIOS -## analyzer processes the NetBIOS session service running on TCP port 139, and -## (despite its name!) the NetBIOS datagram service on UDP port 138. -## -## See `Wikipedia `__ for more information -## about NetBIOS. `RFC 1002 `__ describes -## the packet format for NetBIOS over TCP/IP, which Bro parses. -## -## c: The connection, which may be TCP or UDP, depending on the type of the -## NetBIOS session. -## -## msg: The raw payload of the message sent, excluding the common NetBIOS -## header. -## -## .. bro:see:: netbios_session_accepted netbios_session_keepalive -## netbios_session_message netbios_session_raw_message netbios_session_rejected -## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type -## -## .. note:: These days, NetBIOS is primarily used as a transport mechanism for -## `SMB/CIFS `__. Bro's -## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event netbios_session_request%(c: connection, msg: string%); - -## Generated for NetBIOS messages of type *positive session response*. Bro's -## NetBIOS analyzer processes the NetBIOS session service running on TCP port -## 139, and (despite its name!) the NetBIOS datagram service on UDP port 138. -## -## See `Wikipedia `__ for more information -## about NetBIOS. `RFC 1002 `__ describes -## the packet format for NetBIOS over TCP/IP, which Bro parses. -## -## c: The connection, which may be TCP or UDP, depending on the type of the -## NetBIOS session. -## -## msg: The raw payload of the message sent, excluding the common NetBIOS -## header. -## -## .. bro:see:: netbios_session_keepalive netbios_session_message -## netbios_session_raw_message netbios_session_rejected netbios_session_request -## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type -## -## .. note:: These days, NetBIOS is primarily used as a transport mechanism for -## `SMB/CIFS `__. Bro's -## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event netbios_session_accepted%(c: connection, msg: string%); - -## Generated for NetBIOS messages of type *negative session response*. Bro's -## NetBIOS analyzer processes the NetBIOS session service running on TCP port -## 139, and (despite its name!) the NetBIOS datagram service on UDP port 138. -## -## See `Wikipedia `__ for more information -## about NetBIOS. `RFC 1002 `__ describes -## the packet format for NetBIOS over TCP/IP, which Bro parses. -## -## c: The connection, which may be TCP or UDP, depending on the type of the -## NetBIOS session. -## -## msg: The raw payload of the message sent, excluding the common NetBIOS -## header. -## -## .. bro:see:: netbios_session_accepted netbios_session_keepalive -## netbios_session_message netbios_session_raw_message netbios_session_request -## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type -## -## .. note:: These days, NetBIOS is primarily used as a transport mechanism for -## `SMB/CIFS `__. Bro's -## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event netbios_session_rejected%(c: connection, msg: string%); - -## Generated for NetBIOS messages of type *session message* that are not -## carrying an SMB payload. -## -## NetBIOS analyzer processes the NetBIOS session service running on TCP port -## 139, and (despite its name!) the NetBIOS datagram service on UDP port 138. -## -## See `Wikipedia `__ for more information -## about NetBIOS. `RFC 1002 `__ describes -## the packet format for NetBIOS over TCP/IP, which Bro parses. -## -## c: The connection, which may be TCP or UDP, depending on the type of the -## NetBIOS session. -## -## is_orig: True if the message was sent by the originator of the connection. -## -## msg: The raw payload of the message sent, excluding the common NetBIOS -## header (i.e., the ``user_data``). -## -## .. bro:see:: netbios_session_accepted netbios_session_keepalive -## netbios_session_message netbios_session_rejected netbios_session_request -## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type -## -## .. note:: These days, NetBIOS is primarily used as a transport mechanism for -## `SMB/CIFS `__. Bro's -## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. -## -## .. todo:: This is an oddly named event. In fact, it's probably an odd event -## to have to begin with. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event netbios_session_raw_message%(c: connection, is_orig: bool, msg: string%); - -## Generated for NetBIOS messages of type *retarget response*. Bro's NetBIOS -## analyzer processes the NetBIOS session service running on TCP port 139, and -## (despite its name!) the NetBIOS datagram service on UDP port 138. -## -## See `Wikipedia `__ for more information -## about NetBIOS. `RFC 1002 `__ describes -## the packet format for NetBIOS over TCP/IP, which Bro parses. -## -## c: The connection, which may be TCP or UDP, depending on the type of the -## NetBIOS session. -## -## msg: The raw payload of the message sent, excluding the common NetBIOS -## header. -## -## .. bro:see:: netbios_session_accepted netbios_session_keepalive -## netbios_session_message netbios_session_raw_message netbios_session_rejected -## netbios_session_request decode_netbios_name decode_netbios_name_type -## -## .. note:: These days, NetBIOS is primarily used as a transport mechanism for -## `SMB/CIFS `__. Bro's -## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. -## -## .. todo:: This is an oddly named event. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event netbios_session_ret_arg_resp%(c: connection, msg: string%); - -## Generated for NetBIOS messages of type *keep-alive*. Bro's NetBIOS analyzer -## processes the NetBIOS session service running on TCP port 139, and (despite -## its name!) the NetBIOS datagram service on UDP port 138. -## -## See `Wikipedia `__ for more information -## about NetBIOS. `RFC 1002 `__ describes -## the packet format for NetBIOS over TCP/IP, which Bro parses. -## -## c: The connection, which may be TCP or UDP, depending on the type of the -## NetBIOS session. -## -## msg: The raw payload of the message sent, excluding the common NetBIOS -## header. -## -## .. bro:see:: netbios_session_accepted netbios_session_message -## netbios_session_raw_message netbios_session_rejected netbios_session_request -## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type -## -## .. note:: These days, NetBIOS is primarily used as a transport mechanism for -## `SMB/CIFS `__. Bro's -## SMB analyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event netbios_session_keepalive%(c: connection, msg: string%); - -## Generated for all SMB/CIFS messages. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## is_orig: True if the message was sent by the originator of the underlying -## transport-level connection. -## -## cmd: A string mnemonic of the SMB command code. -## -## body_length: The length of the SMB message body, i.e. the data starting after -## the SMB header. -## -## body: The raw SMB message body, i.e., the data starting after the SMB header. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot -## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 -## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error -## smb_get_dfs_referral -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_message%(c: connection, hdr: smb_hdr, is_orig: bool, cmd: string, body_length: count, body: string%); - -## Generated for SMB/CIFS messages of type *tree connect andx*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## path: The ``path`` attribute specified in the message. -## -## service: The ``service`` attribute specified in the message. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot -## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_tree_connect_andx%(c: connection, hdr: smb_hdr, path: string, service: string%); - -## Generated for SMB/CIFS messages of type *tree disconnect*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot -## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 -## smb_com_tree_connect_andx smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_tree_disconnect%(c: connection, hdr: smb_hdr%); - -## Generated for SMB/CIFS messages of type *nt create andx*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## name: The ``name`` attribute specified in the message. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_read_andx -## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap -## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_nt_create_andx%(c: connection, hdr: smb_hdr, name: string%); - -## Generated for SMB/CIFS messages of type *nt transaction*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## trans: The parsed transaction header. -## -## data: The raw transaction data. -## -## is_orig: True if the message was sent by the originator of the connection. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe -## smb_com_trans_rap smb_com_transaction2 smb_com_tree_connect_andx -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_transaction%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); - -## Generated for SMB/CIFS messages of type *nt transaction 2*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## trans: The parsed transaction header. -## -## data: The raw transaction data. -## -## is_orig: True if the message was sent by the originator of the connection. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe -## smb_com_trans_rap smb_com_transaction smb_com_tree_connect_andx -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_transaction2%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); - -## Generated for SMB/CIFS messages of type *transaction mailslot*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## trans: The parsed transaction header. -## -## data: The raw transaction data. -## -## is_orig: True if the message was sent by the originator of the connection. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_pipe smb_com_trans_rap -## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_trans_mailslot%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); - -## Generated for SMB/CIFS messages of type *transaction rap*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## trans: The parsed transaction header. -## -## data: The raw transaction data. -## -## is_orig: True if the message was sent by the originator of the connection. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot -## smb_com_trans_pipe smb_com_transaction smb_com_transaction2 -## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error -## smb_get_dfs_referral smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_trans_rap%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); - -## Generated for SMB/CIFS messages of type *transaction pipe*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## trans: The parsed transaction header. -## -## data: The raw transaction data. -## -## is_orig: True if the message was sent by the originator of the connection. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_rap -## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_trans_pipe%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); - -## Generated for SMB/CIFS messages of type *read andx*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## data: Always empty. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap -## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_read_andx%(c: connection, hdr: smb_hdr, data: string%); - -## Generated for SMB/CIFS messages of type *read andx*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## data: Always empty. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot -## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 -## smb_com_tree_connect_andx smb_com_tree_disconnect smb_error -## smb_get_dfs_referral smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_write_andx%(c: connection, hdr: smb_hdr, data: string%); - -## Generated for SMB/CIFS messages of type *get dfs referral*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## max_referral_level: The ``max_referral_level`` attribute specified in the -## message. -## -## file_name: The ``filene_name`` attribute specified in the message. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot -## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 -## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_get_dfs_referral%(c: connection, hdr: smb_hdr, max_referral_level: count, file_name: string%); - -## Generated for SMB/CIFS messages of type *negotiate*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx smb_com_setup_andx -## smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap smb_com_transaction -## smb_com_transaction2 smb_com_tree_connect_andx smb_com_tree_disconnect -## smb_com_write_andx smb_error smb_get_dfs_referral smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_negotiate%(c: connection, hdr: smb_hdr%); - -## Generated for SMB/CIFS messages of type *negotiate response*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## dialect_index: The ``dialect`` indicated in the message. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_nt_create_andx smb_com_read_andx smb_com_setup_andx -## smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap smb_com_transaction -## smb_com_transaction2 smb_com_tree_connect_andx smb_com_tree_disconnect -## smb_com_write_andx smb_error smb_get_dfs_referral smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_negotiate_response%(c: connection, hdr: smb_hdr, dialect_index: count%); - -## Generated for SMB/CIFS messages of type *setup andx*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap -## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_setup_andx%(c: connection, hdr: smb_hdr%); - -## Generated for SMB/CIFS messages of type *generic andx*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## .. bro:see:: smb_com_close smb_com_logoff_andx smb_com_negotiate -## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx -## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap -## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_generic_andx%(c: connection, hdr: smb_hdr%); - -## Generated for SMB/CIFS messages of type *close*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## .. bro:see:: smb_com_generic_andx smb_com_logoff_andx smb_com_negotiate -## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx -## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap -## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_close%(c: connection, hdr: smb_hdr%); - -## Generated for SMB/CIFS messages of type *logoff andx*. -## -## See `Wikipedia `__ for -## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses -## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_negotiate -## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx -## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap -## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx -## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral -## smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_com_logoff_andx%(c: connection, hdr: smb_hdr%); - -## Generated for SMB/CIFS messages that indicate an error. This event is -## triggered by an SMB header including a status that signals an error. -## -## c: The connection. -## -## hdr: The parsed header of the SMB message. -## -## cmd: The SMB command code. -## -## cmd_str: A string mnemonic of the SMB command code. -## -## data: The raw SMB message body, i.e., the data starting after the SMB header. -## -## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx -## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx -## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot -## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 -## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx -## smb_get_dfs_referral smb_message -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event smb_error%(c: connection, hdr: smb_hdr, cmd: count, cmd_str: string, data: string%); - -## Generated for all DNS messages. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## is_orig: True if the message was sent by the originator of the connection. -## -## msg: The parsed DNS message header. -## -## len: The length of the message's raw representation (i.e., the DNS payload). -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_query_reply dns_rejected -## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl -## dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_message%(c: connection, is_orig: bool, msg: dns_msg, len: count%) &group="dns"; - -## Generated for DNS requests. For requests with multiple queries, this event -## is raised once for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## query: The queried name. -## -## qtype: The queried resource record type. -## -## qclass: The queried resource record class. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl -## dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_request%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%) &group="dns"; - -## Generated for DNS replies that reject a query. This event is raised if a DNS -## reply either indicates failure via its status code or does not pass on any -## answers to a query. Note that all of the event's parameters are parsed out of -## the reply; there's no stateful correlation with the query. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## query: The queried name. -## -## qtype: The queried resource record type. -## -## qclass: The queried resource record class. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl -## dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_rejected%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%) &group="dns"; - -## Generated for DNS replies with an *ok* status code but no question section. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## query: The queried name. -## -## qtype: The queried resource record type. -## -## qclass: The queried resource record class. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_rejected -## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl -## dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_query_reply%(c: connection, msg: dns_msg, query: string, - qtype: count, qclass: count%) &group="dns"; - -## Generated when the DNS analyzer processes what seems to be a non-DNS packet. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The raw DNS payload. -## -## .. note:: This event is deprecated and superseded by Bro's dynamic protocol -## detection framework. -event non_dns_request%(c: connection, msg: string%) &group="dns"; - -## Generated for DNS replies of type *A*. For replies with multiple answers, an -## individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## a: The address returned by the reply. -## -## .. bro:see:: dns_AAAA_reply dns_A6_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply -## dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request -## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_A_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns"; - -## Generated for DNS replies of type *AAAA*. For replies with multiple answers, -## an individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## a: The address returned by the reply. -## -## .. bro:see:: dns_A_reply dns_A6_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply -## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl -## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered -## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified -## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request -## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl -## dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_AAAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns"; - -## Generated for DNS replies of type *A6*. For replies with multiple answers, an -## individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## a: The address returned by the reply. -## -## .. bro:see:: dns_A_reply dns_AAAA_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply -## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl -## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered -## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified -## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request -## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl -## dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_A6_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns"; - -## Generated for DNS replies of type *NS*. For replies with multiple answers, an -## individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## name: The name returned by the reply. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request -## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_NS_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns"; - -## Generated for DNS replies of type *CNAME*. For replies with multiple answers, -## an individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## name: The name returned by the reply. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply -## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl -## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered -## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified -## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request -## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl -## dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_CNAME_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns"; - -## Generated for DNS replies of type *PTR*. For replies with multiple answers, -## an individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## name: The name returned by the reply. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_SOA_reply dns_SRV_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request -## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_PTR_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns"; - -## Generated for DNS replies of type *CNAME*. For replies with multiple answers, -## an individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## soa: The parsed SOA value. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SRV_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request -## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_SOA_reply%(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa%) &group="dns"; - -## Generated for DNS replies of type *WKS*. For replies with multiple answers, -## an individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_end dns_full_request -## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_WKS_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns"; - -## Generated for DNS replies of type *HINFO*. For replies with multiple answers, -## an individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl dns_MX_reply -## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl -## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered -## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified -## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request -## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl -## dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_HINFO_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns"; - -## Generated for DNS replies of type *MX*. For replies with multiple answers, an -## individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## name: The name returned by the reply. -## -## preference: The preference for *name* specified by the reply. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request -## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_MX_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string, preference: count%) &group="dns"; - -## Generated for DNS replies of type *TXT*. For replies with multiple answers, -## an individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## str: The textual information returned by the reply. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_WKS_reply dns_end dns_full_request -## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, str: string%) &group="dns"; - -## Generated for DNS replies of type *SRV*. For replies with multiple answers, -## an individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The type-independent part of the parsed answer record. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request -## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_SRV_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns"; - -## Generated for DNS replies of type *EDNS*. For replies with multiple answers, -## an individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The parsed EDNS reply. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_HINFO_reply dns_MX_reply -## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl -## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered -## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified -## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request -## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl -## dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_EDNS_addl%(c: connection, msg: dns_msg, ans: dns_edns_additional%) &group="dns"; - -## Generated for DNS replies of type *TSIG*. For replies with multiple answers, -## an individual event of the corresponding type is raised for each. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## ans: The parsed TSIG reply. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TXT_reply dns_WKS_reply dns_end dns_full_request -## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_TSIG_addl%(c: connection, msg: dns_msg, ans: dns_tsig_additional%) &group="dns"; - -## Generated at the end of processing a DNS packet. This event is the last -## ``dns_*`` event that will be raised for a DNS query/reply and signals that -## all resource records have been passed on. -## -## See `Wikipedia `__ for more -## information about the DNS protocol. Bro analyzes both UDP and TCP DNS -## sessions. -## -## c: The connection, which may be UDP or TCP depending on the type of the -## transport-layer session being analyzed. -## -## msg: The parsed DNS message header. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_full_request -## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -event dns_end%(c: connection, msg: dns_msg%) &group="dns"; - -## Generated for DHCP messages of type *discover*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. -## -## c: The connection record describing the underlying UDP flow. -## -## msg: The parsed type-independent part of the DHCP message. -## -## req_addr: The specific address requested by the client. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout -## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth -## -## .. note:: Bro does not support broadcast packets (as used by the DHCP -## protocol). It treats broadcast addresses just like any other and -## associates packets into transport-level flows in the same way as usual. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dhcp_discover%(c: connection, msg: dhcp_msg, req_addr: addr%); - -## Generated for DHCP messages of type *offer*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. -## -## c: The connection record describing the underlying UDP flow. -## -## msg: TODO. -## -## mask: The subnet mask specified by the message. -## -## router: The list of routers specified by the message. -## -## lease: The least interval specified by the message. -## -## serv_addr: The server address specified by the message. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request -## -## .. note:: Bro does not support broadcast packets (as used by the DHCP -## protocol). It treats broadcast addresses just like any other and -## associates packets into transport-level flows in the same way as usual. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dhcp_offer%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr%); - -## Generated for DHCP messages of type *request*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. -## -## c: The connection record describing the underlying UDP flow. -## -## msg: The parsed type-independent part of the DHCP message. -## -## req_addr: The client address specified by the message. -## -## serv_addr: The server address specified by the message. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request -## -## .. note:: Bro does not support broadcast packets (as used by the DHCP -## protocol). It treats broadcast addresses just like any other and -## associates packets into transport-level flows in the same way as usual. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dhcp_request%(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr%); - -## Generated for DHCP messages of type *decline*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. -## -## c: The connection record describing the underlying UDP flow. -## -## msg: The parsed type-independent part of the DHCP message. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request -## -## .. note:: Bro does not support broadcast packets (as used by the DHCP -## protocol). It treats broadcast addresses just like any other and -## associates packets into transport-level flows in the same way as usual. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dhcp_decline%(c: connection, msg: dhcp_msg%); - -## Generated for DHCP messages of type *acknowledgment*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. -## -## c: The connection record describing the underlying UDP flow. -## -## msg: The parsed type-independent part of the DHCP message. -## -## mask: The subnet mask specified by the message. -## -## router: The list of routers specified by the message. -## -## lease: The least interval specified by the message. -## -## serv_addr: The server address specified by the message. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request -## -## .. note:: Bro does not support broadcast packets (as used by the DHCP -## protocol). It treats broadcast addresses just like any other and -## associates packets into transport-level flows in the same way as usual. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dhcp_ack%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr%); - -## Generated for DHCP messages of type *negative acknowledgment*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. -## -## c: The connection record describing the underlying UDP flow. -## -## msg: The parsed type-independent part of the DHCP message. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request -## -## .. note:: Bro does not support broadcast packets (as used by the DHCP -## protocol). It treats broadcast addresses just like any other and -## associates packets into transport-level flows in the same way as usual. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dhcp_nak%(c: connection, msg: dhcp_msg%); - -## Generated for DHCP messages of type *release*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. -## -## c: The connection record describing the underlying UDP flow. -## -## msg: The parsed type-independent part of the DHCP message. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request -## -## .. note:: Bro does not support broadcast packets (as used by the DHCP -## protocol). It treats broadcast addresses just like any other and -## associates packets into transport-level flows in the same way as usual. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dhcp_release%(c: connection, msg: dhcp_msg%); - -## Generated for DHCP messages of type *inform*. -## -## See `Wikipedia -## `__ for -## more information about the DHCP protocol. -## -## c: The connection record describing the underlying UDP flow. -## -## msg: The parsed type-independent part of the DHCP message. -## -## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl -## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name -## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply -## dns_rejected dns_request non_dns_request -## -## .. note:: Bro does not support broadcast packets (as used by the DHCP -## protocol). It treats broadcast addresses just like any other and -## associates packets into transport-level flows in the same way as usual. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dhcp_inform%(c: connection, msg: dhcp_msg%); - -## Generated for HTTP requests. Bro supports persistent and pipelined HTTP -## sessions and raises corresponding events as it parses client/server -## dialogues. This event is generated as soon as a request's initial line has -## been parsed, and before any :bro:id:`http_header` events are raised. -## -## See `Wikipedia `__ -## for more information about the HTTP protocol. -## -## c: The connection. -## -## method: The HTTP method extracted from the request (e.g., ``GET``, ``POST``). -## -## original_URI: The unprocessed URI as specified in the request. -## -## unescaped_URI: The URI with all percent-encodings decoded. -## -## version: The version number specified in the request (e.g., ``1.1``). -## -## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity -## http_entity_data http_event http_header http_message_done http_reply http_stats -## truncate_http_URI -event http_request%(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string%) &group="http-request"; - -## Generated for HTTP replies. Bro supports persistent and pipelined HTTP -## sessions and raises corresponding events as it parses client/server -## dialogues. This event is generated as soon as a reply's initial line has -## been parsed, and before any :bro:id:`http_header` events are raised. -## -## See `Wikipedia `__ -## for more information about the HTTP protocol. -## -## c: The connection. -## -## version: The version number specified in the reply (e.g., ``1.1``). -## -## code: The numerical response code returned by the server. -## -## reason: The textual description returned by the server along with *code*. -## -## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity -## http_entity_data http_event http_header http_message_done http_request -## http_stats -event http_reply%(c: connection, version: string, code: count, reason: string%) &group="http-reply"; - -## Generated for HTTP headers. Bro supports persistent and pipelined HTTP -## sessions and raises corresponding events as it parses client/server -## dialogues. -## -## See `Wikipedia `__ -## for more information about the HTTP protocol. -## -## c: The connection. -## -## is_orig: True if the header was sent by the originator of the TCP connection. -## -## name: The name of the header. -## -## value: The value of the header. -## -## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity -## http_entity_data http_event http_message_done http_reply http_request -## http_stats -## -## .. note:: This event is also raised for headers found in nested body -## entities. -event http_header%(c: connection, is_orig: bool, name: string, value: string%) &group="http-header"; - -## Generated for HTTP headers, passing on all headers of an HTTP message at -## once. Bro supports persistent and pipelined HTTP sessions and raises -## corresponding events as it parses client/server dialogues. -## -## See `Wikipedia `__ -## for more information about the HTTP protocol. -## -## c: The connection. -## -## is_orig: True if the header was sent by the originator of the TCP connection. -## -## hlist: A *table* containing all headers extracted from the current entity. -## The table is indexed by the position of the header (1 for the first, -## 2 for the second, etc.). -## -## .. bro:see:: http_begin_entity http_content_type http_end_entity http_entity_data -## http_event http_header http_message_done http_reply http_request http_stats -## -## .. note:: This event is also raised for headers found in nested body -## entities. -event http_all_headers%(c: connection, is_orig: bool, hlist: mime_header_list%) &group="http-header"; - -## Generated when starting to parse an HTTP body entity. This event is generated -## at least once for each non-empty (client or server) HTTP body; and -## potentially more than once if the body contains further nested MIME -## entities. Bro raises this event just before it starts parsing each entity's -## content. -## -## See `Wikipedia `__ -## for more information about the HTTP protocol. -## -## c: The connection. -## -## is_orig: True if the entity was sent by the originator of the TCP -## connection. -## -## .. bro:see:: http_all_headers http_content_type http_end_entity http_entity_data -## http_event http_header http_message_done http_reply http_request http_stats -## mime_begin_entity -event http_begin_entity%(c: connection, is_orig: bool%) &group="http-body"; - -## Generated when finishing parsing an HTTP body entity. This event is generated -## at least once for each non-empty (client or server) HTTP body; and -## potentially more than once if the body contains further nested MIME -## entities. Bro raises this event at the point when it has finished parsing an -## entity's content. -## -## See `Wikipedia `__ -## for more information about the HTTP protocol. -## -## c: The connection. -## -## is_orig: True if the entity was sent by the originator of the TCP -## connection. -## -## .. bro:see:: http_all_headers http_begin_entity http_content_type http_entity_data -## http_event http_header http_message_done http_reply http_request -## http_stats mime_end_entity -event http_end_entity%(c: connection, is_orig: bool%) &group="http-body"; - -## Generated when parsing an HTTP body entity, passing on the data. This event -## can potentially be raised many times for each entity, each time passing a -## chunk of the data of not further defined size. -## -## A common idiom for using this event is to first *reassemble* the data -## at the scripting layer by concatenating it to a successively growing -## string; and only perform further content analysis once the corresponding -## :bro:id:`http_end_entity` event has been raised. Note, however, that doing so -## can be quite expensive for HTTP tranders. At the very least, one should -## impose an upper size limit on how much data is being buffered. -## -## See `Wikipedia `__ -## for more information about the HTTP protocol. -## -## c: The connection. -## -## is_orig: True if the entity was sent by the originator of the TCP -## connection. -## -## length: The length of *data*. -## -## data: One chunk of raw entity data. -## -## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity -## http_event http_header http_message_done http_reply http_request http_stats -## mime_entity_data http_entity_data_delivery_size skip_http_data -event http_entity_data%(c: connection, is_orig: bool, length: count, data: string%) &group="http-body"; - -## Generated for reporting an HTTP body's content type. This event is -## generated at the end of parsing an HTTP header, passing on the MIME -## type as specified by the ``Content-Type`` header. If that header is -## missing, this event is still raised with a default value of ``text/plain``. -## -## See `Wikipedia `__ -## for more information about the HTTP protocol. -## -## c: The connection. -## -## is_orig: True if the entity was sent by the originator of the TCP -## connection. -## -## ty: The main type. -## -## subty: The subtype. -## -## .. bro:see:: http_all_headers http_begin_entity http_end_entity http_entity_data -## http_event http_header http_message_done http_reply http_request http_stats -## -## .. note:: This event is also raised for headers found in nested body -## entities. -event http_content_type%(c: connection, is_orig: bool, ty: string, subty: string%) &group="http-body"; - -## Generated once at the end of parsing an HTTP message. Bro supports persistent -## and pipelined HTTP sessions and raises corresponding events as it parses -## client/server dialogues. A "message" is one top-level HTTP entity, such as a -## complete request or reply. Each message can have further nested sub-entities -## inside. This event is raised once all sub-entities belonging to a top-level -## message have been processed (and their corresponding ``http_entity_*`` events -## generated). -## -## See `Wikipedia `__ -## for more information about the HTTP protocol. -## -## c: The connection. -## -## is_orig: True if the entity was sent by the originator of the TCP -## connection. -## -## stat: Further meta information about the message. -## -## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity -## http_entity_data http_event http_header http_reply http_request http_stats -event http_message_done%(c: connection, is_orig: bool, stat: http_message_stat%) &group="http-body"; - -## Generated for errors found when decoding HTTP requests or replies. -## -## See `Wikipedia `__ -## for more information about the HTTP protocol. -## -## c: The connection. -## -## event_type: A string describing the general category of the problem found -## (e.g., ``illegal format``). -## -## detail: Further more detailed description of the error. -## -## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity -## http_entity_data http_header http_message_done http_reply http_request -## http_stats mime_event -event http_event%(c: connection, event_type: string, detail: string%); - -## Generated at the end of an HTTP session to report statistics about it. This -## event is raised after all of an HTTP session's requests and replies have been -## fully processed. -## -## c: The connection. -## -## stats: Statistics summarizing HTTP-level properties of the finished -## connection. -## -## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity -## http_entity_data http_event http_header http_message_done http_reply -## http_request -event http_stats%(c: connection, stats: http_stats_rec%); - -## Generated when seeing an SSH client's version identification. The SSH -## protocol starts with a clear-text handshake message that reports client and -## server protocol/software versions. This event provides access to what the -## client sent. -## -## -## See `Wikipedia `__ for more -## information about the SSH protocol. -## -## c: The connection. -## -## version: The version string the client sent (e.g., `SSH-2.0-libssh-0.11`). -## -## .. bro:see:: ssh_server_version -## -## .. note:: As everything after the initial version handshake proceeds -## encrypted, Bro cannot further analyze SSH sessions. -event ssh_client_version%(c: connection, version: string%); - -## Generated when seeing an SSH server's version identification. The SSH -## protocol starts with a clear-text handshake message that reports client and -## server protocol/software versions. This event provides access to what the -## server sent. -## -## See `Wikipedia `__ for more -## information about the SSH protocol. -## -## c: The connection. -## -## version: The version string the server sent (e.g., -## ``SSH-1.99-OpenSSH_3.9p1``). -## -## .. bro:see:: ssh_client_version -## -## .. note:: As everything coming after the initial version handshake proceeds -## encrypted, Bro cannot further analyze SSH sessions. -event ssh_server_version%(c: connection, version: string%); - -## Generated for an SSL/TLS client's initial *hello* message. SSL/TLS sessions -## start with an unencrypted handshake, and Bro extracts as much information out -## of that as it can. This event provides access to the initial information -## sent by the client. -## -## See `Wikipedia `__ for -## more information about the SSL/TLS protocol. -## -## c: The connection. -## -## version: The protocol version as extracted from the client's message. The -## values are standardized as part of the SSL/TLS protocol. The -## :bro:id:`SSL::version_strings` table maps them to descriptive names. -## -## possible_ts: The current time as sent by the client. Note that SSL/TLS does -## not require clocks to be set correctly, so treat with care. -## -## session_id: The session ID sent by the client (if any). -## -## ciphers: The list of ciphers the client offered to use. The values are -## standardized as part of the SSL/TLS protocol. The -## :bro:id:`SSL::cipher_desc` table maps them to descriptive names. -## -## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello -## ssl_session_ticket_handshake x509_certificate x509_error x509_extension -event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%); - -## Generated for an SSL/TLS server's initial *hello* message. SSL/TLS sessions -## start with an unencrypted handshake, and Bro extracts as much information out -## of that as it can. This event provides access to the initial information -## sent by the client. -## -## See `Wikipedia `__ for -## more information about the SSL/TLS protocol. -## -## c: The connection. -## -## version: The protocol version as extracted from the server's message. -## The values are standardized as part of the SSL/TLS protocol. The -## :bro:id:`SSL::version_strings` table maps them to descriptive names. -## -## possible_ts: The current time as sent by the server. Note that SSL/TLS does -## not require clocks to be set correctly, so treat with care. -## -## session_id: The session ID as sent back by the server (if any). -## -## cipher: The cipher chosen by the server. The values are standardized as part -## of the SSL/TLS protocol. The :bro:id:`SSL::cipher_desc` table maps -## them to descriptive names. -## -## comp_method: The compression method chosen by the client. The values are -## standardized as part of the SSL/TLS protocol. -## -## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension -## ssl_session_ticket_handshake x509_certificate x509_error x509_extension -event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%); - -## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS -## sessions start with an unencrypted handshake, and Bro extracts as much -## information out of that as it can. This event provides access to any -## extensions either side sends as part of an extended *hello* message. -## -## c: The connection. -## -## is_orig: True if event is raised for originator side of the connection. -## -## code: The numerical code of the extension. The values are standardized as -## part of the SSL/TLS protocol. The :bro:id:`SSL::extensions` table maps -## them to descriptive names. -## -## val: The raw extension value that was sent in the message. -## -## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello -## ssl_session_ticket_handshake x509_certificate x509_error x509_extension -event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%); - -## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with -## an unencrypted handshake, and Bro extracts as much information out of that -## as it can. This event signals the time when an SSL/TLS has finished the -## handshake and its endpoints consider it as fully established. Typically, -## everything from now on will be encrypted. -## -## See `Wikipedia `__ for -## more information about the SSL/TLS protocol. -## -## c: The connection. -## -## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello -## ssl_session_ticket_handshake x509_certificate x509_error x509_extension -event ssl_established%(c: connection%); - -## Generated for SSL/TLS alert records. SSL/TLS sessions start with an -## unencrypted handshake, and Bro extracts as much information out of that as -## it can. If during that handshake, an endpoint encounters a fatal error, it -## sends an *alert* record, that in turn triggers this event. After an *alert*, -## any endpoint may close the connection immediately. -## -## See `Wikipedia `__ for -## more information about the SSL/TLS protocol. -## -## c: The connection. -## -## is_orig: True if event is raised for originator side of the connection. -## -## level: The severity level, as sent in the *alert*. The values are defined as -## part of the SSL/TLS protocol. -## -## desc: A numerical value identifying the cause of the *alert*. The values are -## defined as part of the SSL/TLS protocol. -## -## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello -## ssl_session_ticket_handshake x509_certificate x509_error x509_extension -event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%); - -## Generated for SSL/TLS handshake messages that are a part of the -## stateless-server session resumption mechanism. SSL/TLS sessions start with -## an unencrypted handshake, and Bro extracts as much information out of that -## as it can. This event is raised when an SSL/TLS server passes a session -## ticket to the client that can later be used for resuming the session. The -## mechanism is described in :rfc:`4507` -## -## See `Wikipedia `__ for -## more information about the SSL/TLS protocol. -## -## c: The connection. -## -## ticket_lifetime_hint: A hint from the server about how long the ticket -## should be stored by the client. -## -## ticket: The raw ticket data. -## -## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello -## x509_certificate x509_error x509_extension ssl_alert -event ssl_session_ticket_handshake%(c: connection, ticket_lifetime_hint: count, ticket: string%); - -## Generated for X509 certificates seen in SSL/TLS connections. During the -## initial SSL/TLS handshake, certificates are exchanged in the clear. Bro -## raises this event for each certificate seen (including both a site's primary -## cert, and further certs sent as part of the validation chain). -## -## See `Wikipedia `__ for more information -## about the X.509 format. -## -## c: The connection. -## -## is_orig: True if event is raised for originator side of the connection. -## -## cert: The parsed certificate. -## -## chain_idx: The index in the validation chain that this cert has. Index zero -## indicates an endpoint's primary cert, while higher indices -## indicate the place in the validation chain (which has length -## *chain_len*). -## -## chain_len: The total length of the validation chain that this cert is part -## of. -## -## der_cert: The complete cert encoded in `DER -## `__ -## format. -## -## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension -## ssl_server_hello x509_error x509_extension x509_verify -event x509_certificate%(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string%); - -## Generated for X509 extensions seen in a certificate. -## -## See `Wikipedia `__ for more information -## about the X.509 format. -## -## c: The connection. -## -## is_orig: True if event is raised for originator side of the connection. -## -## data: The raw data associated with the extension. -## -## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension -## ssl_server_hello x509_certificate x509_error x509_verify -event x509_extension%(c: connection, is_orig: bool, data: string%); - -## Generated when errors occur during parsing an X509 certificate. -## -## See `Wikipedia `__ for more information -## about the X.509 format. -## -## c: The connection. -## -## is_orig: True if event is raised for originator side of the connection. -## -## err: An error code describing what went wrong. :bro:id:`SSL::x509_errors` -## maps error codes to a textual description. -## -## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension -## ssl_server_hello x509_certificate x509_extension x509_err2str x509_verify -event x509_error%(c: connection, is_orig: bool, err: count%); - -## TODO. -## -## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_request -## dce_rpc_response rpc_timeout -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dce_rpc_message%(c: connection, is_orig: bool, ptype: dce_rpc_ptype, msg: string%); - -## TODO. -## -## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_message dce_rpc_request -## dce_rpc_response rpc_timeout -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dce_rpc_bind%(c: connection, uuid: string%); - -## TODO. -## -## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message -## dce_rpc_response rpc_timeout -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dce_rpc_request%(c: connection, opnum: count, stub: string%); - -## TODO. -## -## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message -## dce_rpc_request rpc_timeout -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event dce_rpc_response%(c: connection, opnum: count, stub: string%); - -## TODO. -## -## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message -## dce_rpc_request dce_rpc_response rpc_timeout -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event epm_map_response%(c: connection, uuid: string, p: port, h: addr%); - -## Generated for NCP requests (Netware Core Protocol). -## -## See `Wikipedia `__ for -## more information about the NCP protocol. -## -## c: The connection. -## -## frame_type: The frame type, as specified by the protocol. -## -## length: The length of the request body, excluding the frame header. -## -## func: The requested function, as specified by the protocol. -## -## .. bro:see:: ncp_reply -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event ncp_request%(c: connection, frame_type: count, length: count, func: count%); - -## Generated for NCP replies (Netware Core Protocol). -## -## See `Wikipedia `__ for -## more information about the NCP protocol. -## -## c: The connection. -## -## frame_type: The frame type, as specified by the protocol. -## -## length: The length of the request body, excluding the frame header. -## -## req_frame: The frame type from the corresponding request. -## -## req_func: The function code from the corresponding request. -## -## completion_code: The reply's completion code, as specified by the protocol. -## -## .. bro:see:: ncp_request -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event ncp_reply%(c: connection, frame_type: count, length: count, req_frame: count, req_func: count, completion_code: count%); - -## Generated for client-side commands on POP3 connections. -## -## See `Wikipedia `__ for more information -## about the POP3 protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## command: The command sent. -## -## arg: The argument to the command. -## -## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_reply -## pop3_terminate pop3_unexpected -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pop3_request%(c: connection, is_orig: bool, - command: string, arg: string%); - -## Generated for server-side replies to commands on POP3 connections. -## -## See `Wikipedia `__ for more information -## about the POP3 protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## cmd: The success indicator sent by the server. This corresponds to the -## first token on the line sent, and should be either ``OK`` or ``ERR``. -## -## msg: The textual description the server sent along with *cmd*. -## -## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_request -## pop3_terminate pop3_unexpected -## -## .. todo:: This event is receiving odd parameters, should unify. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pop3_reply%(c: connection, is_orig: bool, cmd: string, msg: string%); - -## Generated for server-side multi-line responses on POP3 connections. POP3 -## connections use multi-line responses to send bulk data, such as the actual -## mails. This event is generated once for each line that's part of such a -## response. -## -## See `Wikipedia `__ for more information -## about the POP3 protocol. -## -## c: The connection. -## -## is_orig: True if the data was sent by the originator of the TCP connection. -## -## data: The data sent. -## -## .. bro:see:: pop3_login_failure pop3_login_success pop3_reply pop3_request -## pop3_terminate pop3_unexpected -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pop3_data%(c: connection, is_orig: bool, data: string%); - -## Generated for errors encountered on POP3 sessions. If the POP3 analyzer -## finds state transitions that do not conform to the protocol specification, -## or other situations it can't handle, it raises this event. -## -## See `Wikipedia `__ for more information -## about the POP3 protocol. -## -## c: The connection. -## -## is_orig: True if the data was sent by the originator of the TCP connection. -## -## msg: A textual description of the situation. -## -## detail: The input that triggered the event. -## -## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_reply pop3_request -## pop3_terminate -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pop3_unexpected%(c: connection, is_orig: bool, - msg: string, detail: string%); - -## Generated when a POP3 connection goes encrypted. While POP3 is by default a -## clear-text protocol, extensions exist to switch to encryption. This event is -## generated if that happens and the analyzer then stops processing the -## connection. -## -## See `Wikipedia `__ for more information -## about the POP3 protocol. -## -## c: The connection. -## -## is_orig: Always false. -## -## msg: A descriptive message why processing was stopped. -## -## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_reply pop3_request -## pop3_unexpected -## -## .. note:: Currently, only the ``STARTLS`` command is recognized and -## triggers this. -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pop3_terminate%(c: connection, is_orig: bool, msg: string%); - -## Generated for successful authentications on POP3 connections. -## -## See `Wikipedia `__ for more information -## about the POP3 protocol. -## -## c: The connection. -## -## is_orig: Always false. -## -## user: The user name used for authentication. The event is only generated if -## a non-empty user name was used. -## -## password: The password used for authentication. -## -## .. bro:see:: pop3_data pop3_login_failure pop3_reply pop3_request pop3_terminate -## pop3_unexpected -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pop3_login_success%(c: connection, is_orig: bool, - user: string, password: string%); - -## Generated for unsuccessful authentications on POP3 connections. -## -## See `Wikipedia `__ for more information -## about the POP3 protocol. -## -## c: The connection. -## -## is_orig: Always false. -## -## user: The user name attempted for authentication. The event is only -## generated if a non-empty user name was used. -## -## password: The password attempted for authentication. -## -## .. bro:see:: pop3_data pop3_login_success pop3_reply pop3_request pop3_terminate -## pop3_unexpected -## -## .. todo:: Bro's current default configuration does not activate the protocol -## analyzer that generates this event; the corresponding script has not yet -## been ported to Bro 2.x. To still enable this event, one needs to add a -## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. -event pop3_login_failure%(c: connection, is_orig: bool, - user: string, password: string%); - - -## Generated for all client-side IRC commands. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: Always true. -## -## prefix: The optional prefix coming with the command. IRC uses the prefix to -## indicate the true origin of a message. -## -## command: The command. -## -## arguments: The arguments for the command. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -## -## .. note:: This event is generated only for messages that originate -## at the client-side. Commands coming in from remote trigger -## the :bro:id:`irc_message` event instead. -event irc_request%(c: connection, is_orig: bool, prefix: string, - command: string, arguments: string%); - -## Generated for all IRC replies. IRC replies are sent in response to a -## request and come with a reply code. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## prefix: The optional prefix coming with the reply. IRC uses the prefix to -## indicate the true origin of a message. -## -## code: The reply code, as specified by the protocol. -## -## params: The reply's parameters. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_reply%(c: connection, is_orig: bool, prefix: string, - code: count, params: string%); - -## Generated for IRC commands forwarded from the server to the client. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: Always false. -## -## prefix: The optional prefix coming with the command. IRC uses the prefix to -## indicate the true origin of a message. -## -## command: The command. -## -## message: TODO. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -## -## .. note:: -## -## This event is generated only for messages that are forwarded by the server -## to the client. Commands coming from client trigger the -## :bro:id:`irc_request` event instead. -event irc_message%(c: connection, is_orig: bool, prefix: string, - command: string, message: string%); - -## Generated for IRC messages of type *quit*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## nick: The nickname coming with the message. -## -## message: The text included with the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_quit_message%(c: connection, is_orig: bool, nick: string, message: string%); - -## Generated for IRC messages of type *privmsg*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## source: The source of the private communication. -## -## target: The target of the private communication. -## -## message: The text of communication. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_privmsg_message%(c: connection, is_orig: bool, source: string, - target: string, message: string%); - -## Generated for IRC messages of type *notice*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## source: The source of the private communication. -## -## target: The target of the private communication. -## -## message: The text of communication. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_notice_message%(c: connection, is_orig: bool, source: string, - target: string, message: string%); - -## Generated for IRC messages of type *squery*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## source: The source of the private communication. -## -## target: The target of the private communication. -## -## message: The text of communication. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_squery_message%(c: connection, is_orig: bool, source: string, - target: string, message: string%); - -## Generated for IRC messages of type *join*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## info_list: The user information coming with the command. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_kick_message -## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_join_message%(c: connection, is_orig: bool, info_list: irc_join_list%); - -## Generated for IRC messages of type *part*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## nick: The nickname coming with the message. -## -## chans: The set of channels affected. -## -## message: The text coming with the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_password_message -event irc_part_message%(c: connection, is_orig: bool, nick: string, - chans: string_set, message: string%); - -## Generated for IRC messages of type *nick*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## who: The user changing its nickname. -## -## newnick: The new nickname. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_nick_message%(c: connection, is_orig: bool, who: string, newnick: string%); - -## Generated when a server rejects an IRC nickname. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invite_message irc_join_message irc_kick_message -## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_invalid_nick%(c: connection, is_orig: bool%); - -## Generated for an IRC reply of type *luserclient*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## users: The number of users as returned in the reply. -## -## services: The number of services as returned in the reply. -## -## servers: The number of servers as returned in the reply. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_network_info%(c: connection, is_orig: bool, users: count, - services: count, servers: count%); - -## Generated for an IRC reply of type *luserme*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## users: The number of users as returned in the reply. -## -## services: The number of services as returned in the reply. -## -## servers: The number of servers as returned in the reply. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_server_info%(c: connection, is_orig: bool, users: count, - services: count, servers: count%); - -## Generated for an IRC reply of type *luserchannels*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## chans: The number of channels as returned in the reply. -## -## .. bro:see:: irc_channel_topic irc_dcc_message irc_error_message irc_global_users -## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message -## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_channel_info%(c: connection, is_orig: bool, chans: count%); - -## Generated for an IRC reply of type *whoreply*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## target_nick: The target nickname. -## -## channel: The channel. -## -## user: The user. -## -## host: The host. -## -## server: The server. -## -## nick: The nickname. -## -## params: The parameters. -## -## hops: The hop count. -## -## real_name: The real name. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_who_line%(c: connection, is_orig: bool, target_nick: string, - channel: string, user: string, host: string, - server: string, nick: string, params: string, - hops: count, real_name: string%); - - -## Generated for an IRC reply of type *namereply*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## c_type: The channel type. -## -## channel: The channel. -## -## users: The set of users. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_names_info%(c: connection, is_orig: bool, c_type: string, - channel: string, users: string_set%); - -## Generated for an IRC reply of type *whoisoperator*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## nick: The nickname specified in the reply. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_whois_operator_line%(c: connection, is_orig: bool, nick: string%); - -## Generated for an IRC reply of type *whoischannels*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## nick: The nickname specified in the reply. -## -## chans: The set of channels returned. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_whois_channel_line%(c: connection, is_orig: bool, nick: string, - chans: string_set%); - -## Generated for an IRC reply of type *whoisuser*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## nick: The nickname specified in the reply. -## -## user: The user name specified in the reply. -## -## host: The host name specified in the reply. -## -## real_name: The real name specified in the reply. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_whois_user_line%(c: connection, is_orig: bool, nick: string, - user: string, host: string, real_name: string%); - -## Generated for IRC replies of type *youreoper* and *nooperhost*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## got_oper: True if the *oper* command was executed successfully -## (*youreport*) and false otherwise (*nooperhost*). -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_part_message -## irc_password_message -event irc_oper_response%(c: connection, is_orig: bool, got_oper: bool%); - -## Generated for an IRC reply of type *globalusers*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## prefix: The optional prefix coming with the command. IRC uses the prefix to -## indicate the true origin of a message. -## -## msg: The message coming with the reply. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message -## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_global_users%(c: connection, is_orig: bool, prefix: string, msg: string%); - -## Generated for an IRC reply of type *topic*. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## channel: The channel name specified in the reply. -## -## topic: The topic specified in the reply. -## -## .. bro:see:: irc_channel_info irc_dcc_message irc_error_message irc_global_users -## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message -## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_channel_topic%(c: connection, is_orig: bool, channel: string, topic: string%); - -## Generated for IRC messages of type *who*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## mask: The mask specified in the message. -## -## oper: True if the operator flag was set. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_who_message%(c: connection, is_orig: bool, mask: string, oper: bool%); - -## Generated for IRC messages of type *whois*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## server: TODO. -## -## users: TODO. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_whois_message%(c: connection, is_orig: bool, server: string, users: string%); - -## Generated for IRC messages of type *oper*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## user: The user specified in the message. -## -## password: The password specified in the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_response irc_part_message -## irc_password_message -event irc_oper_message%(c: connection, is_orig: bool, user: string, password: string%); - -## Generated for IRC messages of type *kick*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## prefix: The optional prefix coming with the command. IRC uses the prefix to -## indicate the true origin of a message. -## -## chans: The channels specified in the message. -## -## users: The users specified in the message. -## -## comment: The comment specified in the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_kick_message%(c: connection, is_orig: bool, prefix: string, - chans: string, users: string, comment: string%); - -## Generated for IRC messages of type *error*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## prefix: The optional prefix coming with the command. IRC uses the prefix to -## indicate the true origin of a message. -## -## message: The textual description specified in the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_global_users -## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message -## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_error_message%(c: connection, is_orig: bool, prefix: string, message: string%); - -## Generated for IRC messages of type *invite*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## prefix: The optional prefix coming with the command. IRC uses the prefix to -## indicate the true origin of a message. -## -## nickname: The nickname specified in the message. -## -## channel: The channel specified in the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_join_message irc_kick_message -## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_invite_message%(c: connection, is_orig: bool, prefix: string, - nickname: string, channel: string%); - -## Generated for IRC messages of type *mode*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## prefix: The optional prefix coming with the command. IRC uses the prefix to -## indicate the true origin of a message. -## -## params: The parameters coming with the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_names_info irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_mode_message%(c: connection, is_orig: bool, prefix: string, params: string%); - -## Generated for IRC messages of type *squit*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## prefix: The optional prefix coming with the command. IRC uses the prefix to -## indicate the true origin of a message. -## -## server: The server specified in the message. -## -## message: The textual description specified in the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_squit_message%(c: connection, is_orig: bool, prefix: string, - server: string, message: string%); - -## Generated for IRC messages of type *dcc*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## prefix: The optional prefix coming with the command. IRC uses the prefix to -## indicate the true origin of a message. -## -## target: The target specified in the message. -## -## dcc_type: The DCC type specified in the message. -## -## argument: The argument specified in the message. -## -## address: The address specified in the message. -## -## dest_port: The destination port specified in the message. -## -## size: The size specified in the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_error_message irc_global_users -## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message -## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message -## irc_notice_message irc_oper_message irc_oper_response irc_part_message -## irc_password_message -event irc_dcc_message%(c: connection, is_orig: bool, - prefix: string, target: string, - dcc_type: string, argument: string, - address: addr, dest_port: count, size: count%); - -## Generated for IRC messages of type *user*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## user: The user specified in the message. -## -## host: The host name specified in the message. -## -## server: The server name specified in the message. -## -## real_name: The real name specified in the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message irc_password_message -event irc_user_message%(c: connection, is_orig: bool, user: string, host: string, server: string, real_name: string%); - -## Generated for IRC messages of type *password*. This event is generated for -## messages coming from both the client and the server. -## -## See `Wikipedia `__ for more -## information about the IRC protocol. -## -## c: The connection. -## -## is_orig: True if the command was sent by the originator of the TCP -## connection. -## -## password: The password specified in the message. -## -## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message -## irc_global_users irc_invalid_nick irc_invite_message irc_join_message -## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info -## irc_nick_message irc_notice_message irc_oper_message irc_oper_response -## irc_part_message -event irc_password_message%(c: connection, is_orig: bool, password: string%); - -## TODO. -## -event file_transferred%(c: connection, prefix: string, descr: string, mime_type: string%); - -## Generated for monitored Syslog messages. -## -## See `Wikipedia `__ for more -## information about the Syslog protocol. -## -## c: The connection record for the underlying transport-layer session/flow. -## -## facility: The "facility" included in the message. -## -## severity: The "severity" included in the message. -## -## msg: The message logged. -## -## .. note:: Bro currently parses only UDP syslog traffic. Support for TCP -## syslog will be added soon. -event syslog_message%(c: connection, facility: count, severity: count, msg: string%); - ## Generated when a signature matches. Bro's signature engine provides ## high-performance pattern matching separately from the normal script ## processing. If a signature with an ``event`` action matches, this event is @@ -6292,35 +532,6 @@ event syslog_message%(c: connection, facility: count, severity: count, msg: stri ## triggering the match will be passed on to the event. event signature_match%(state: signature_state, msg: string, data: string%); -## Generated when a SOCKS request is analyzed. -## -## c: The parent connection of the proxy. -## -## version: The version of SOCKS this message used. -## -## request_type: The type of the request. -## -## sa: Address that the tunneled traffic should be sent to. -## -## p: The destination port for the proxied traffic. -## -## user: Username given for the SOCKS connection. This is not yet implemented -## for SOCKSv5. -event socks_request%(c: connection, version: count, request_type: count, sa: SOCKS::Address, p: port, user: string%); - -## Generated when a SOCKS reply is analyzed. -## -## c: The parent connection of the proxy. -## -## version: The version of SOCKS this message used. -## -## reply: The status reply from the server. -## -## sa: The address that the server sent the traffic to. -## -## p: The destination port for the proxied traffic. -event socks_reply%(c: connection, version: count, reply: count, sa: SOCKS::Address, p: port%); - ## Generated when a protocol analyzer finds an identification of a software ## used on a system. This is a protocol-independent event that is fed by ## different analyzers. For example, the HTTP analyzer reports user-agent and @@ -6338,7 +549,7 @@ event socks_reply%(c: connection, version: count, reply: count, sa: SOCKS::Addre ## ## .. bro:see:: software_parse_error software_unparsed_version_found OS_version_found event software_version_found%(c: connection, host: addr, - s: software, descr: string%); + s: software, descr: string%); ## Generated when a protocol analyzer finds an identification of a software ## used on a system but cannot parse it. This is a protocol-independent event @@ -6449,8 +660,6 @@ event remote_event_registered%(p: event_peer, name: string%); ## remote_state_inconsistency print_hook event remote_connection_error%(p: event_peer, reason: string%); - - ## Generated when a remote peer sent us a capture filter. While this event is ## intended primarily for use by Bro's communication framework, it can also ## trigger additional code if helpful. @@ -6569,7 +778,7 @@ event remote_log_peer%(p: event_peer, level: count, src: count, msg: string%); ## remote_event_registered remote_log remote_state_access_performed ## remote_state_inconsistency print_hook event remote_pong%(p: event_peer, seq: count, - d1: interval, d2: interval, d3: interval%); + d1: interval, d2: interval, d3: interval%); ## Generated each time a remote state access has been replayed locally. This ## event is primarily intended for debugging. @@ -6596,326 +805,6 @@ event remote_state_access_performed%(id: string, v: any%); ## .. bro:see:: profiling_interval expensive_profiling_multiple event profiling_update%(f: file, expensive: bool%); -## Generated each time Bro's script interpreter opens a file. This event is -## triggered only for files opened via :bro:id:`open`, and in particular not for -## normal log files as created by log writers. -## -## f: The opened file. -event file_opened%(f: file%); - -## Generated for a received NetFlow v5 header. Bro's NetFlow processor raises -## this event whenever it either receives a NetFlow header on the port it's -## listening on, or reads one from a trace file. -## -## h: The parsed NetFlow header. -## -## .. bro:see:: netflow_v5_record -event netflow_v5_header%(h: nf_v5_header%); - -## Generated for a received NetFlow v5 record. Bro's NetFlow processor raises -## this event whenever it either receives a NetFlow record on the port it's -## listening on, or reads one from a trace file. -## -## r: The parsed NetFlow record. -## -## .. bro:see:: netflow_v5_record -event netflow_v5_record%(r: nf_v5_record%); - -## Generated for any modbus message regardless if the particular function -## is further supported or not. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## is_orig: True if the event is raised for the originator side. -event modbus_message%(c: connection, headers: ModbusHeaders, is_orig: bool%); - -## Generated for any modbus exception message. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## code: The exception code. -event modbus_exception%(c: connection, headers: ModbusHeaders, code: count%); - -## Generated for a Modbus read coils request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## start_address: The memory address where of the first coil to be read. -## -## quantity: The number of coils to be read. -event modbus_read_coils_request%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); - -## Generated for a Modbus read coils response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## coils: The coil values returned from the device. -event modbus_read_coils_response%(c: connection, headers: ModbusHeaders, coils: ModbusCoils%); - -## Generated for a Modbus read discrete inputs request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## start_address: The memory address of the first coil to be read. -## -## quantity: The number of coils to be read. -event modbus_read_discrete_inputs_request%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); - -## Generated for a Modbus read discrete inputs response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## coils: The coil values returned from the device. -event modbus_read_discrete_inputs_response%(c: connection, headers: ModbusHeaders, coils: ModbusCoils%); - -## Generated for a Modbus read holding registers request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## start_address: The memory address of the first register to be read. -## -## quantity: The number of registers to be read. -event modbus_read_holding_registers_request%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); - -## Generated for a Modbus read holding registers response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## registers: The register values returned from the device. -event modbus_read_holding_registers_response%(c: connection, headers: ModbusHeaders, registers: ModbusRegisters%); - -## Generated for a Modbus read input registers request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## start_address: The memory address of the first register to be read. -## -## quantity: The number of registers to be read. -event modbus_read_input_registers_request%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); - -## Generated for a Modbus read input registers response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## registers: The register values returned from the device. -event modbus_read_input_registers_response%(c: connection, headers: ModbusHeaders, registers: ModbusRegisters%); - -## Generated for a Modbus write single coil request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## address: The memory address of the coil to be written. -## -## value: The value to be written to the coil. -event modbus_write_single_coil_request%(c: connection, headers: ModbusHeaders, address: count, value: bool%); - -## Generated for a Modbus write single coil response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## address: The memory address of the coil that was written. -## -## value: The value that was written to the coil. -event modbus_write_single_coil_response%(c: connection, headers: ModbusHeaders, address: count, value: bool%); - -## Generated for a Modbus write single register request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## address: The memory address of the register to be written. -## -## value: The value to be written to the register. -event modbus_write_single_register_request%(c: connection, headers: ModbusHeaders, address: count, value: count%); - -## Generated for a Modbus write single register response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## address: The memory address of the register that was written. -## -## value: The value that was written to the register. -event modbus_write_single_register_response%(c: connection, headers: ModbusHeaders, address: count, value: count%); - -## Generated for a Modbus write multiple coils request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## start_address: The memory address of the first coil to be written. -## -## value: The values to be written to the coils. -event modbus_write_multiple_coils_request%(c: connection, headers: ModbusHeaders, start_address: count, coils: ModbusCoils%); - -## Generated for a Modbus write multiple coils response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## start_address: The memory address of the first coil that was written. -## -## quantity: The quantity of coils that were written. -event modbus_write_multiple_coils_response%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); - -## Generated for a Modbus write multiple registers request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## start_address: The memory address of the first register to be written. -## -## registers: The values to be written to the registers. -event modbus_write_multiple_registers_request%(c: connection, headers: ModbusHeaders, start_address: count, registers: ModbusRegisters%); - -## Generated for a Modbus write multiple registers response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## start_address: The memory address of the first register that was written. -## -## quantity: The quantity of registers that were written. -event modbus_write_multiple_registers_response%(c: connection, headers: ModbusHeaders, start_address: count, quantity: count%); - -## Generated for a Modbus read file record request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## .. note: This event is incomplete. The information from the data structure is not -## yet passed through to the event. -event modbus_read_file_record_request%(c: connection, headers: ModbusHeaders%); - -## Generated for a Modbus read file record response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## .. note: This event is incomplete. The information from the data structure is not -## yet passed through to the event. -event modbus_read_file_record_response%(c: connection, headers: ModbusHeaders%); - -## Generated for a Modbus write file record request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## .. note: This event is incomplete. The information from the data structure is not -## yet passed through to the event. -event modbus_write_file_record_request%(c: connection, headers: ModbusHeaders%); - -## Generated for a Modbus write file record response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## .. note: This event is incomplete. The information from the data structure is not -## yet passed through to the event. -event modbus_write_file_record_response%(c: connection, headers: ModbusHeaders%); - -## Generated for a Modbus mask write register request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## address: The memory address of the register where the masks should be applied. -## -## and_mask: The value of the logical AND mask to apply to the register. -## -## or_mask: The value of the logical OR mask to apply to the register. -event modbus_mask_write_register_request%(c: connection, headers: ModbusHeaders, address: count, and_mask: count, or_mask: count%); - -## Generated for a Modbus mask write register request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## address: The memory address of the register where the masks were applied. -## -## and_mask: The value of the logical AND mask applied register. -## -## or_mask: The value of the logical OR mask applied to the register. -event modbus_mask_write_register_response%(c: connection, headers: ModbusHeaders, address: count, and_mask: count, or_mask: count%); - -## Generated for a Modbus read/write multiple registers request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## read_start_address: The memory address of the first register to be read. -## -## read_quantity: The number of registers to read. -## -## write_start_address: The memory address of the first register to be written. -## -## write_registers: The values to be written to the registers. -event modbus_read_write_multiple_registers_request%(c: connection, headers: ModbusHeaders, read_start_address: count, read_quantity: count, write_start_address: count, write_registers: ModbusRegisters%); - -## Generated for a Modbus read/write multiple registers response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## written_registers: The register values read from the registers specified in the request. -event modbus_read_write_multiple_registers_response%(c: connection, headers: ModbusHeaders, written_registers: ModbusRegisters%); - -## Generated for a Modbus read FIFO queue request. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## start_address: The address of the FIFO queue to read. -event modbus_read_fifo_queue_request%(c: connection, headers: ModbusHeaders, start_address: count%); - -## Generated for a Modbus read FIFO queue response. -## -## c: The connection. -## -## headers: The headers for the modbus function. -## -## fifos: The register values read from the FIFO queue on the device. -event modbus_read_fifo_queue_response%(c: connection, headers: ModbusHeaders, fifos: ModbusRegisters%); - ## Raised for informational messages reported via Bro's reporter framework. Such ## messages may be generated internally by the event engine and also by other ## scripts calling :bro:id:`Reporter::info`. @@ -6981,6 +870,13 @@ event reporter_error%(t: time, msg: string, location: string%) &error_handler; ## recursively for each ``@load``. event bro_script_loaded%(path: string, level: count%); +## Generated each time Bro's script interpreter opens a file. This event is +## triggered only for files opened via :bro:id:`open`, and in particular not for +## normal log files as created by log writers. +## +## f: The opened file. +event file_opened%(f: file%); + ## Marks a point in the event stream at which the event queue started flushing. event event_queue_flush_point%(%); @@ -6998,7 +894,7 @@ event event_queue_flush_point%(%); ## is_orig: The direction the file data is flowing over the connection. ## ## .. bro:see:: set_file_handle -event get_file_handle%(tag: count, c: connection, is_orig: bool%); +event get_file_handle%(tag: Analyzer::Tag, c: connection, is_orig: bool%); ## Indicates that an analysis of a new file has begun. The analysis can be ## augmented at this time via :bro:see:`FileAnalysis::add_analyzer`. @@ -7059,82 +955,81 @@ event file_state_remove%(f: fa_file%); ## FileAnalysis::ANALYZER_SHA1 FileAnalysis::ANALYZER_SHA256 event file_hash%(f: fa_file, kind: string, hash: string%); -## Deprecated. Will be removed. -event stp_create_endp%(c: connection, e: int, is_orig: bool%); +## Generated when an internal DNS lookup produces the same result as last time. +## Bro keeps an internal DNS cache for host names and IP addresses it has +## already resolved. This event is generated when a subsequent lookup returns +## the same result as stored in the cache. +## +## dm: A record describing the new resolver result (which matches the old one). +## +## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified +event dns_mapping_valid%(dm: dns_mapping%); -# ##### Internal events. Not further documented. +## Generated when an internal DNS lookup got no answer even though it had +## succeeded in the past. Bro keeps an internal DNS cache for host names and IP +## addresses it has already resolved. This event is generated when a +## subsequent lookup does not produce an answer even though we have +## already stored a result in the cache. +## +## dm: A record describing the old resolver result. +## +## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_valid +event dns_mapping_unverified%(dm: dns_mapping%); -## Event internal to the stepping stone detector. -event stp_resume_endp%(e: int%); +## Generated when an internal DNS lookup succeeded but an earlier attempt +## did not. Bro keeps an internal DNS cache for host names and IP +## addresses it has already resolved. This event is generated when a subsequent +## lookup produces an answer for a query that was marked as failed in the cache. +## +## dm: A record describing the new resolver result. +## +## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_unverified +## dns_mapping_valid +event dns_mapping_new_name%(dm: dns_mapping%); -## Event internal to the stepping stone detector. -event stp_correlate_pair%(e1: int, e2: int%); +## Generated when an internal DNS lookup returned zero answers even though it +## had succeeded in the past. Bro keeps an internal DNS cache for host names +## and IP addresses it has already resolved. This event is generated when +## on a subsequent lookup we receive an answer that is empty even +## though we have already stored a result in the cache. +## +## dm: A record describing the old resolver result. +## +## .. bro:see:: dns_mapping_altered dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid +event dns_mapping_lost_name%(dm: dns_mapping%); -## Event internal to the stepping stone detector. -event stp_remove_pair%(e1: int, e2: int%); - -## Event internal to the stepping stone detector. -event stp_remove_endp%(e: int%); - -# ##### Deprecated events. Proposed for removal. - -## Deprecated. Will be removed. -event interconn_stats%(c: connection, os: interconn_endp_stats, rs: interconn_endp_stats%); - -## Deprecated. Will be removed. -event interconn_remove_conn%(c: connection%); - -## Deprecated. Will be removed. -event backdoor_stats%(c: connection, os: backdoor_endp_stats, rs: backdoor_endp_stats%); - -## Deprecated. Will be removed. -event backdoor_remove_conn%(c: connection%); - -## Deprecated. Will be removed. -event ssh_signature_found%(c: connection, is_orig: bool%); - -## Deprecated. Will be removed. -event telnet_signature_found%(c: connection, is_orig: bool, len: count%); - -## Deprecated. Will be removed. -event rlogin_signature_found%(c: connection, is_orig: bool, num_null: count, len: count%); +## Generated when an internal DNS lookup produced a different result than in +## the past. Bro keeps an internal DNS cache for host names and IP addresses +## it has already resolved. This event is generated when a subsequent lookup +## returns a different answer than we have stored in the cache. +## +## dm: A record describing the new resolver result. +## +## old_addrs: Addresses that used to be part of the returned set for the query +## described by *dm*, but are not anymore. +## +## new_addrs: Addresses that were not part of the returned set for the query +## described by *dm*, but now are. +## +## .. bro:see:: dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid +event dns_mapping_altered%(dm: dns_mapping, old_addrs: addr_set, new_addrs: addr_set%); ## Deprecated. Will be removed. event root_backdoor_signature_found%(c: connection%); -## Deprecated. Will be removed. -event ftp_signature_found%(c: connection%); - ## Deprecated. Will be removed. event napster_signature_found%(c: connection%); -## Deprecated. Will be removed. -event gnutella_signature_found%(c: connection%); - ## Deprecated. Will be removed. event kazaa_signature_found%(c: connection%); -## Deprecated. Will be removed. -event http_signature_found%(c: connection%); - -## Deprecated. Will be removed. -event http_proxy_signature_found%(c: connection%); - -## Deprecated. Will be removed. -event smtp_signature_found%(c: connection%); - -## Deprecated. Will be removed. -event irc_signature_found%(c: connection%); - ## Deprecated. Will be removed. event gaobot_signature_found%(c: connection%); -## Deprecated. Will be removed. -## -## .. todo:: Unclear what this event is for; it's never raised. We should just -## remove it. -event dns_full_request%(%) &group="dns"; - ## Deprecated. Will be removed. event anonymization_mapping%(orig: addr, mapped: addr%); diff --git a/src/file_analysis/File.cc b/src/file_analysis/File.cc index 17b01f6b39..bc40eb058c 100644 --- a/src/file_analysis/File.cc +++ b/src/file_analysis/File.cc @@ -11,9 +11,11 @@ #include "Reporter.h" #include "Val.h" #include "Type.h" -#include "../Analyzer.h" #include "Event.h" +#include "analyzer/Analyzer.h" +#include "analyzer/Manager.h" + using namespace file_analysis; static Val* empty_connection_table() @@ -76,7 +78,7 @@ void File::StaticInit() salt = BifConst::FileAnalysis::salt->CheckString(); } -File::File(const string& unique, Connection* conn, AnalyzerTag::Tag tag, +File::File(const string& unique, Connection* conn, analyzer::Tag tag, bool is_orig) : id(""), unique(unique), val(0), postpone_timeout(false), first_chunk(true), missed_bof(false), need_reassembly(false), done(false), @@ -101,7 +103,7 @@ File::File(const string& unique, Connection* conn, AnalyzerTag::Tag tag, if ( conn ) { // add source, connection, is_orig fields - val->Assign(source_idx, new StringVal(::Analyzer::GetTagName(tag))); + val->Assign(source_idx, new StringVal(analyzer_mgr->GetAnalyzerName(tag))); val->Assign(is_orig_idx, new Val(is_orig, TYPE_BOOL)); UpdateConnectionFields(conn); } diff --git a/src/file_analysis/File.h b/src/file_analysis/File.h index a31f0bfa41..40446934e1 100644 --- a/src/file_analysis/File.h +++ b/src/file_analysis/File.h @@ -6,7 +6,6 @@ #include #include -#include "AnalyzerTags.h" #include "Conn.h" #include "Val.h" #include "AnalyzerSet.h" @@ -132,7 +131,7 @@ protected: * Constructor; only file_analysis::Manager should be creating these. */ File(const string& unique, Connection* conn = 0, - AnalyzerTag::Tag tag = AnalyzerTag::Error, bool is_orig = false); + analyzer::Tag tag = analyzer::Tag::Error, bool is_orig = false); /** * Updates the "conn_ids" and "conn_uids" fields in #val record with the diff --git a/src/file_analysis/Manager.cc b/src/file_analysis/Manager.cc index d6f00e1856..5ddfd085b3 100644 --- a/src/file_analysis/Manager.cc +++ b/src/file_analysis/Manager.cc @@ -38,7 +38,7 @@ void Manager::SetHandle(const string& handle) } void Manager::DataIn(const u_char* data, uint64 len, uint64 offset, - AnalyzerTag::Tag tag, Connection* conn, bool is_orig) + analyzer::Tag tag, Connection* conn, bool is_orig) { if ( IsDisabled(tag) ) return; @@ -65,7 +65,7 @@ void Manager::DataIn(const u_char* data, uint64 len, uint64 offset, RemoveFile(file->GetUnique()); } -void Manager::DataIn(const u_char* data, uint64 len, AnalyzerTag::Tag tag, +void Manager::DataIn(const u_char* data, uint64 len, analyzer::Tag tag, Connection* conn, bool is_orig) { if ( IsDisabled(tag) ) @@ -94,13 +94,13 @@ void Manager::DataIn(const u_char* data, uint64 len, File* file) RemoveFile(file->GetUnique()); } -void Manager::EndOfFile(AnalyzerTag::Tag tag, Connection* conn) +void Manager::EndOfFile(analyzer::Tag tag, Connection* conn) { EndOfFile(tag, conn, true); EndOfFile(tag, conn, false); } -void Manager::EndOfFile(AnalyzerTag::Tag tag, Connection* conn, bool is_orig) +void Manager::EndOfFile(analyzer::Tag tag, Connection* conn, bool is_orig) { if ( IsDisabled(tag) ) return; @@ -114,7 +114,7 @@ void Manager::EndOfFile(const string& unique) RemoveFile(unique); } -void Manager::Gap(uint64 offset, uint64 len, AnalyzerTag::Tag tag, +void Manager::Gap(uint64 offset, uint64 len, analyzer::Tag tag, Connection* conn, bool is_orig) { if ( IsDisabled(tag) ) @@ -137,7 +137,7 @@ void Manager::Gap(uint64 offset, uint64 len, File* file) file->Gap(offset, len); } -void Manager::SetSize(uint64 size, AnalyzerTag::Tag tag, Connection* conn, +void Manager::SetSize(uint64 size, analyzer::Tag tag, Connection* conn, bool is_orig) { if ( IsDisabled(tag) ) @@ -206,7 +206,7 @@ bool Manager::RemoveAnalyzer(const FileID& file_id, const RecordVal* args) const } File* Manager::GetFile(const string& unique, Connection* conn, - AnalyzerTag::Tag tag, bool is_orig, bool update_conn) + analyzer::Tag tag, bool is_orig, bool update_conn) { if ( unique.empty() ) return 0; @@ -321,15 +321,18 @@ bool Manager::IsIgnored(const string& unique) return ignored.find(unique) != ignored.end(); } -void Manager::GetFileHandle(AnalyzerTag::Tag tag, Connection* c, bool is_orig) +void Manager::GetFileHandle(analyzer::Tag tag, Connection* c, bool is_orig) { current_handle.clear(); if ( ! get_file_handle ) return; + EnumVal* tagval = tag.AsEnumVal(); + Ref(tagval); + val_list* vl = new val_list(); - vl->append(new Val(tag, TYPE_COUNT)); + vl->append(tagval); vl->append(c->BuildConnVal()); vl->append(new Val(is_orig, TYPE_BOOL)); @@ -337,7 +340,7 @@ void Manager::GetFileHandle(AnalyzerTag::Tag tag, Connection* c, bool is_orig) mgr.Drain(); // need file handle immediately so we don't have to buffer data } -bool Manager::IsDisabled(AnalyzerTag::Tag tag) +bool Manager::IsDisabled(analyzer::Tag tag) { if ( ! disabled ) disabled = internal_const_val("FileAnalysis::disable")->AsTableVal(); diff --git a/src/file_analysis/Manager.h b/src/file_analysis/Manager.h index d2f8f6f1bf..99121b8575 100644 --- a/src/file_analysis/Manager.h +++ b/src/file_analysis/Manager.h @@ -9,7 +9,6 @@ #include #include "Net.h" -#include "AnalyzerTags.h" #include "Conn.h" #include "Val.h" #include "Analyzer.h" @@ -20,6 +19,8 @@ #include "FileTimer.h" #include "FileID.h" +#include "analyzer/Tag.h" + namespace file_analysis { /** @@ -44,7 +45,7 @@ public: * Pass in non-sequential file data. */ void DataIn(const u_char* data, uint64 len, uint64 offset, - AnalyzerTag::Tag tag, Connection* conn, bool is_orig); + analyzer::Tag tag, Connection* conn, bool is_orig); void DataIn(const u_char* data, uint64 len, uint64 offset, const string& unique); void DataIn(const u_char* data, uint64 len, uint64 offset, @@ -53,7 +54,7 @@ public: /** * Pass in sequential file data. */ - void DataIn(const u_char* data, uint64 len, AnalyzerTag::Tag tag, + void DataIn(const u_char* data, uint64 len, analyzer::Tag tag, Connection* conn, bool is_orig); void DataIn(const u_char* data, uint64 len, const string& unique); void DataIn(const u_char* data, uint64 len, File* file); @@ -61,14 +62,14 @@ public: /** * Signal the end of file data. */ - void EndOfFile(AnalyzerTag::Tag tag, Connection* conn); - void EndOfFile(AnalyzerTag::Tag tag, Connection* conn, bool is_orig); + void EndOfFile(analyzer::Tag tag, Connection* conn); + void EndOfFile(analyzer::Tag tag, Connection* conn, bool is_orig); void EndOfFile(const string& unique); /** * Signal a gap in the file data stream. */ - void Gap(uint64 offset, uint64 len, AnalyzerTag::Tag tag, Connection* conn, + void Gap(uint64 offset, uint64 len, analyzer::Tag tag, Connection* conn, bool is_orig); void Gap(uint64 offset, uint64 len, const string& unique); void Gap(uint64 offset, uint64 len, File* file); @@ -76,7 +77,7 @@ public: /** * Provide the expected number of bytes that comprise a file. */ - void SetSize(uint64 size, AnalyzerTag::Tag tag, Connection* conn, + void SetSize(uint64 size, analyzer::Tag tag, Connection* conn, bool is_orig); void SetSize(uint64 size, const string& unique); void SetSize(uint64 size, File* file); @@ -133,7 +134,7 @@ protected: * fields. */ File* GetFile(const string& unique, Connection* conn = 0, - AnalyzerTag::Tag tag = AnalyzerTag::Error, + analyzer::Tag tag = analyzer::Tag::Error, bool is_orig = false, bool update_conn = true); /** @@ -159,12 +160,12 @@ protected: * \c get_file_handle event derives from the connection params. The * event queue is flushed so that we can get the handle value immediately. */ - void GetFileHandle(AnalyzerTag::Tag tag, Connection* c, bool is_orig); + void GetFileHandle(analyzer::Tag tag, Connection* c, bool is_orig); /** * @return whether file analysis is disabled for the given analyzer. */ - static bool IsDisabled(AnalyzerTag::Tag tag); + static bool IsDisabled(analyzer::Tag tag); private: StrMap str_map; /**< Map unique string to file_analysis::File. */ diff --git a/src/http-analyzer.pac b/src/http-analyzer.pac deleted file mode 100644 index e12be59438..0000000000 --- a/src/http-analyzer.pac +++ /dev/null @@ -1,430 +0,0 @@ -%extern{ -#include - -// Used by unescape_URI(). -extern int is_reserved_URI_char(unsigned char ch); -extern int is_unreserved_URI_char(unsigned char ch); -%} - -# Remember to call bytestring::free() on the result. -function to_upper(s: const_bytestring): bytestring - %{ - char* buf = new char[s.length() + 1]; - const char* sp = (const char*) s.begin(); - - for ( int i = 0; i < s.length(); ++i ) - if ( islower(sp[i]) ) - buf[i] = toupper(sp[i]); - else - buf[i] = sp[i]; - - buf[s.length()] = '\0'; - - return bytestring((uint8*) buf, s.length()); - %} - -connection HTTP_Conn(bro_analyzer: BroAnalyzer) { - upflow = HTTP_Flow(true); - downflow = HTTP_Flow(false); -}; - -flow HTTP_Flow(is_orig: bool) { - flowunit = HTTP_PDU(is_orig) withcontext (connection, this); - - # States. - %member{ - int content_length_; - DeliveryMode delivery_mode_; - bytestring end_of_multipart_; - - double msg_start_time_; - int msg_begin_seq_; - int msg_header_end_seq_; - - bool build_headers_; - vector headers_; - %} - - %init{ - content_length_ = 0; - delivery_mode_ = UNKNOWN_DELIVERY_MODE; - - msg_start_time_ = 0; - msg_begin_seq_ = 0; - msg_header_end_seq_ = -1; - - build_headers_ = (::http_all_headers != 0); - %} - - %cleanup{ - end_of_multipart_.free(); - %} - - function content_length(): int - %{ - return content_length_; - %} - - function delivery_mode(): DeliveryMode - %{ - return delivery_mode_; - %} - - function end_of_multipart(): const_bytestring - %{ - return end_of_multipart_; - %} - - # Methods. - function http_request(method: const_bytestring, uri: const_bytestring, - vers: HTTP_Version): bool - %{ - if ( ::http_request ) - { - bytestring unescaped_uri = unescape_uri(uri); - BifEvent::generate_http_request(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - bytestring_to_val(method), - bytestring_to_val(uri), - bytestring_to_val(unescaped_uri), - bytestring_to_val(${vers.vers_str})); - unescaped_uri.free(); - } - - http_message_begin(); - - return true; - %} - - function http_reply(vers: HTTP_Version, code: int, - reason: const_bytestring): bool - %{ - if ( ::http_reply ) - { - BifEvent::generate_http_reply(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - bytestring_to_val(${vers.vers_str}), code, - bytestring_to_val(reason)); - } - - http_message_begin(); - - return true; - %} - - function build_http_header_val(name: const_bytestring, - value: const_bytestring): BroVal - %{ - RecordVal* header_record = new RecordVal(mime_header_rec); - - StringVal* name_val = 0; - if ( name.length() > 0 ) - { - // Make it all uppercase. - name_val = new StringVal(name.length(), - (const char*) name.begin()); - name_val->ToUpper(); - } - else - name_val = new StringVal(""); - - header_record->Assign(0, name_val); - header_record->Assign(1, bytestring_to_val(value)); - - return header_record; - %} - - function extract_boundary(value: const_bytestring): bytestring - %{ - const char* boundary_prefix = "boundary="; - const char* boundary_begin = strcasestr( - (const char*) value.begin(), - boundary_prefix); - - if ( ! boundary_begin ) - return bytestring(); - - boundary_begin += 9; - - const char* boundary_end = strcasestr(boundary_begin, ";"); - if ( ! boundary_end ) - boundary_end = (const char*) value.end(); - - return bytestring((const uint8*) boundary_begin, - (const uint8*) boundary_end); - %} - - function is_end_of_multipart(line: const_bytestring): bool - %{ - if ( line.length() < 4 + end_of_multipart_.length() ) - return false; - - int len = end_of_multipart_.length(); - - // line =?= "--" end_of_multipart_ "--" - return ( line[0] == '-' && line[1] == '-' && - line[len + 2] == '-' && line[len + 3] == '-' && - strncmp((const char*) line.begin() + 2, - (const char*) end_of_multipart_.begin(), - len) == 0 ); - %} - - function http_header(name_colon: const_bytestring, - value: const_bytestring): bool - %{ - const_bytestring name( - name_colon.begin(), - name_colon.length() > 0 ? - name_colon.end() - 1 : - name_colon.end()); - - if ( bytestring_casecmp(name, "CONTENT-LENGTH") == 0 ) - { - content_length_ = bytestring_to_int(value, 10); - delivery_mode_ = CONTENT_LENGTH; - } - - else if ( bytestring_casecmp(name, "TRANSFER-ENCODING") == 0 ) - { - if ( bytestring_caseprefix(value, "CHUNKED") ) - delivery_mode_ = CHUNKED; - } - - else if ( bytestring_casecmp(name, "CONTENT-TYPE") == 0 ) - { - if ( bytestring_caseprefix(value, "MULTIPART") ) - { - end_of_multipart_.free(); - end_of_multipart_ = extract_boundary(value); - if ( end_of_multipart_.length() > 0 ) - delivery_mode_ = MULTIPART; - } - } - - if ( ::http_header ) - { - BifEvent::generate_http_header(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - is_orig(), - bytestring_to_val(name)->ToUpper(), - bytestring_to_val(value)); - } - - if ( build_headers_ ) - headers_.push_back(build_http_header_val(name, value)); - - return true; - %} - - function build_http_headers_val(): BroVal - %{ - TableVal* t = new TableVal(mime_header_list); - - for ( unsigned int i = 0; i < headers_.size(); ++i ) - { // index starting from 1 - Val* index = new Val(i + 1, TYPE_COUNT); - t->Assign(index, headers_[i]); - Unref(index); - } - - return t; - %} - - function gen_http_all_headers(): void - %{ - if ( ::http_all_headers ) - { - BifEvent::generate_http_all_headers(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - is_orig(), - build_http_headers_val()); - } - - headers_.clear(); - %} - - function http_end_of_headers(headers: HTTP_Headers): bool - %{ - if ( delivery_mode_ != CHUNKED && build_headers_ ) - gen_http_all_headers(); - - // Check if this is the first set of headers - // (i.e. not headers after chunks). - if ( msg_header_end_seq_ == -1 ) - msg_header_end_seq_ = flow_buffer_->data_seq(); - - return true; - %} - - function http_message_begin(): void - %{ - msg_start_time_ = network_time(); - if ( ::http_begin_entity ) - { - BifEvent::generate_http_begin_entity(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), is_orig()); - } - %} - - function build_http_message_stat(): BroVal - %{ - int msg_header_length = msg_header_end_seq_ - msg_begin_seq_; - int msg_body_length = - flow_buffer_->data_seq() - msg_header_end_seq_; - - bool msg_interrupted = false; - - RecordVal* stat = new RecordVal(http_message_stat); - int field = 0; - stat->Assign(field++, new Val(msg_start_time_, TYPE_TIME)); - stat->Assign(field++, new Val(msg_interrupted, TYPE_BOOL)); - stat->Assign(field++, new StringVal("")); - stat->Assign(field++, new Val(msg_body_length, TYPE_COUNT)); - stat->Assign(field++, new Val(0, TYPE_COUNT)); - stat->Assign(field++, new Val(msg_header_length, TYPE_COUNT)); - - return stat; - %} - - function http_message_done(pdu: HTTP_PDU): bool - %{ - if ( ! headers_.empty() ) - gen_http_all_headers(); - - if ( ::http_end_entity ) - { - BifEvent::generate_http_end_entity(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), is_orig()); - } - - if ( ::http_message_done ) - { - BifEvent::generate_http_message_done(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - is_orig(), build_http_message_stat()); - } - - end_of_multipart_.free(); - - // Initialize for next message. - msg_begin_seq_ = flow_buffer_->data_seq(); - msg_header_end_seq_ = -1; - - return true; - %} - - # Remember to call bytestring::free() on the result - function unescape_uri(uri: const_bytestring): bytestring - %{ - const u_char* line = uri.begin(); - const u_char* line_end = uri.end(); - BroAnalyzer a = connection()->bro_analyzer(); - - // ### Copied from HTTP.cc - byte_vec decoded_URI = new u_char[line_end - line + 1]; - byte_vec URI_p = decoded_URI; - - // An 'unescaped_special_char' here means a character that - // *should* be escaped, but isn't in the URI. A control - // character that appears directly in the URI would be an - // example. The RFC implies that if we do not unescape the - // URI that we see in the trace, every character should be a - // printable one -- either reserved or unreserved (or '%'). - // - // Counting the number of unescaped characters and generating - // a weird event on URI's with unescaped characters (which - // are rare) will let us locate strange-looking URI's in the - // trace -- those URI's are often interesting. - - int unescaped_special_char = 0; - - while ( line < line_end ) - { - if ( *line == '%' ) - { - ++line; - - if ( line == line_end ) - { - // How to deal with % at end of line? - // *URI_p++ = '%'; - if ( a ) - a->Weird("illegal_%_at_end_of_URI"); - break; - } - - else if ( *line == '%' ) - { - // Double '%' might be either due to - // software bug, or, more likely, an - // evasion (e.g., used by Nimda). - // *URI_p++ = '%'; - if ( a ) - a->Weird("double_%_in_URI"); - --line; // ignore the first '%' - } - - else if ( isxdigit(line[0]) && isxdigit(line[1]) ) - { - *URI_p++ = (decode_hex(line[0]) << 4) + - decode_hex(line[1]); - ++line; // place line at last hex digit - } - - else - { - if ( a ) - a->Weird("unescaped_%_in_URI"); - *URI_p++ = '%'; // put back initial '%' - // Take char. without interpretation.. - *URI_p++ = *line; - } - } - - else - { - if ( ! is_reserved_URI_char(*line) && - ! is_unreserved_URI_char(*line) ) - // Count these up as a way to compress - // the corresponding Weird event to a - // single instance. - ++unescaped_special_char; - *URI_p++ = *line; - } - - ++line; - } - - URI_p[0] = 0; - - if ( unescaped_special_char && a ) - a->Weird("unescaped_special_URI_char"); - - return bytestring(decoded_URI, URI_p - decoded_URI); - %} -}; - -refine typeattr HTTP_RequestLine += &let { - process_request: bool = - $context.flow.http_request(method, uri, version); -}; - -refine typeattr HTTP_ReplyLine += &let { - process_reply: bool = - $context.flow.http_reply(version, status.stat_num, reason); -}; - -refine typeattr HTTP_Header += &let { - process_header: bool = - $context.flow.http_header(name, value); -}; - -refine typeattr HTTP_Headers += &let { - process_end_of_headers: bool = - $context.flow.http_end_of_headers(this); -}; - -refine typeattr HTTP_PDU += &let { - process_message: bool = - $context.flow.http_message_done(this); -}; diff --git a/src/http-protocol.pac b/src/http-protocol.pac deleted file mode 100644 index e4487a75e3..0000000000 --- a/src/http-protocol.pac +++ /dev/null @@ -1,140 +0,0 @@ -enum ExpectBody { - BODY_EXPECTED, - BODY_NOT_EXPECTED, - BODY_MAYBE, -}; - -enum DeliveryMode { - UNKNOWN_DELIVERY_MODE, - CONTENT_LENGTH, - CHUNKED, - MULTIPART, -}; - -## token = 1* -## separators = "(" | ")" | "<" | ">" | "@" -## | "," | ";" | ":" | "\" | <"> -## | "/" | "[" | "]" | "?" | "=" -## | "{" | "}" | SP | HT -## reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | -## "$" | "," - -type HTTP_TOKEN = RE/[^()<>@,;:\\"\/\[\]?={} \t]+/; -type HTTP_WS = RE/[ \t]*/; -type HTTP_URI = RE/[[:alnum:][:punct:]]+/; - -type HTTP_PDU(is_orig: bool) = case is_orig of { - true -> request: HTTP_Request; - false -> reply: HTTP_Reply; -}; - -type HTTP_Request = record { - request: HTTP_RequestLine; - msg: HTTP_Message(BODY_MAYBE); -}; - -function expect_reply_body(reply_status: int): ExpectBody - %{ - // TODO: check if the request is "HEAD" - if ( (reply_status >= 100 && reply_status < 200) || - reply_status == 204 || reply_status == 304 ) - return BODY_NOT_EXPECTED; - return BODY_EXPECTED; - %} - -type HTTP_Reply = record { - reply: HTTP_ReplyLine; - msg: HTTP_Message(expect_reply_body(reply.status.stat_num)); -}; - -type HTTP_RequestLine = record { - method: HTTP_TOKEN; - : HTTP_WS; - uri: HTTP_URI; - : HTTP_WS; - version: HTTP_Version; -} &oneline; - -type HTTP_ReplyLine = record { - version: HTTP_Version; - : HTTP_WS; - status: HTTP_Status; - : HTTP_WS; - reason: bytestring &restofdata; -} &oneline; - -type HTTP_Status = record { - stat_str: RE/[0-9]{3}/; -} &let { - stat_num: int = bytestring_to_int(stat_str, 10); -}; - -type HTTP_Version = record { - : "HTTP/"; - vers_str: RE/[0-9]+\.[0-9]+/; -} &let { - vers_num: double = bytestring_to_double(vers_str); -}; - -type HTTP_Headers = HTTP_Header[] &until($input.length() == 0); - -type HTTP_Message(expect_body: ExpectBody) = record { - headers: HTTP_Headers; - body_or_not: case expect_body of { - BODY_NOT_EXPECTED -> none: empty; - default -> body: HTTP_Body(expect_body); - }; -}; - -# Multi-line headers are supported by allowing header names to be -# empty. -# -type HTTP_HEADER_NAME = RE/|([^: \t]+:)/; -type HTTP_Header = record { - name: HTTP_HEADER_NAME &transient; - : HTTP_WS; - value: bytestring &restofdata &transient; -} &oneline; - -type MIME_Line = record { - line: bytestring &restofdata &transient; -} &oneline; - -type MIME_Lines = MIME_Line[] - &until($context.flow.is_end_of_multipart($input)); - -# TODO: parse multipart message according to MIME -type HTTP_Body(expect_body: ExpectBody) = - case $context.flow.delivery_mode() of { - - CONTENT_LENGTH -> body: bytestring - &length = $context.flow.content_length(), - &chunked; - - CHUNKED -> chunks: HTTP_Chunks; - - MULTIPART -> multipart: MIME_Lines; - - default -> unknown: HTTP_UnknownBody(expect_body); -}; - -type HTTP_UnknownBody(expect_body: ExpectBody) = case expect_body of { - BODY_MAYBE, BODY_NOT_EXPECTED -> maybenot: empty; - BODY_EXPECTED -> rest: bytestring &restofflow &chunked; -}; - -type HTTP_Chunks = record { - chunks: HTTP_Chunk[] &until($element.chunk_length == 0); - headers: HTTP_Headers; -}; - -type HTTP_Chunk = record { - length_line: bytestring &oneline; - data: bytestring &length = chunk_length &chunked; - opt_crlf: case chunk_length of { - 0 -> none: empty; - default -> crlf: bytestring &oneline &check(trailing_crlf == ""); - }; -} &let { - chunk_length: int = bytestring_to_int(length_line, 16); -}; diff --git a/src/http.pac b/src/http.pac deleted file mode 100644 index 38e6ad0b5e..0000000000 --- a/src/http.pac +++ /dev/null @@ -1,10 +0,0 @@ -%include binpac.pac -%include bro.pac - -analyzer HTTP withcontext { - connection: HTTP_Conn; - flow: HTTP_Flow; -}; - -%include http-protocol.pac -%include http-analyzer.pac diff --git a/src/main.cc b/src/main.cc index b330f36509..491f8a732d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -50,7 +50,6 @@ extern "C" void OPENSSL_add_all_algorithms_conf(void); #include "PersistenceSerializer.h" #include "EventRegistry.h" #include "Stats.h" -#include "DPM.h" #include "BroDoc.h" #include "Brofiler.h" @@ -58,6 +57,9 @@ extern "C" void OPENSSL_add_all_algorithms_conf(void); #include "input/Manager.h" #include "logging/Manager.h" #include "logging/writers/Ascii.h" +#include "analyzer/Manager.h" +#include "analyzer/Tag.h" +#include "plugin/Manager.h" #include "file_analysis/Manager.h" @@ -94,6 +96,8 @@ TimerMgr* timer_mgr; logging::Manager* log_mgr = 0; threading::Manager* thread_mgr = 0; input::Manager* input_mgr = 0; +plugin::Manager* plugin_mgr = 0; +analyzer::Manager* analyzer_mgr = 0; file_analysis::Manager* file_mgr = 0; Stmt* stmts; EventHandlerPtr net_done = 0; @@ -108,7 +112,6 @@ ProfileLogger* profiling_logger = 0; ProfileLogger* segment_logger = 0; SampleLogger* sample_logger = 0; int signal_val = 0; -DPM* dpm = 0; int optimize = 0; int do_notice_analysis = 0; int rule_bench = 0; @@ -120,8 +123,6 @@ vector params; char* proc_status_file = 0; int snaplen = 0; // this gets set from the scripting-layer's value -int FLAGS_use_binpac = false; - extern std::list docs_generated; // Keep copy of command line @@ -185,6 +186,7 @@ void usage() fprintf(stderr, " -I|--print-id | print out given ID\n"); fprintf(stderr, " -K|--md5-hashkey | set key for MD5-keyed hashing\n"); fprintf(stderr, " -L|--rule-benchmark | benchmark for rules\n"); + fprintf(stderr, " -N|--print-plugins | print available plugins and exit (-NN for verbose)\n"); fprintf(stderr, " -O|--optimize | optimize policy script\n"); fprintf(stderr, " -P|--prime-dns | prime DNS\n"); fprintf(stderr, " -R|--replay | replay events\n"); @@ -209,8 +211,6 @@ void usage() fprintf(stderr, " -n|--idmef-dtd | specify path to IDMEF DTD file\n"); #endif - fprintf(stderr, " --use-binpac | use new-style BinPAC parsers when available\n"); - fprintf(stderr, " $BROPATH | file search path (%s)\n", bro_path()); fprintf(stderr, " $BROMAGIC | libmagic mime magic database search path (%s)\n", bro_magic_path()); fprintf(stderr, " $BRO_PREFIXES | prefix list (%s)\n", bro_prefixes()); @@ -243,6 +243,32 @@ void usage() exit(1); } +void show_plugins(int level) + { + plugin::Manager::plugin_list plugins = plugin_mgr->Plugins(); + + if ( ! plugins.size() ) + { + printf("No plugins registered, not even any built-ins. This is probably a bug.\n"); + return; + } + + ODesc d; + + if ( level == 1 ) + d.SetShort(); + + for ( plugin::Manager::plugin_list::const_iterator i = plugins.begin(); i != plugins.end(); i++ ) + { + (*i)->Describe(&d); + + if ( ! d.IsShort() ) + d.Add("\n"); + } + + printf("%s", d.Description()); + } + void done_with_network() { set_processing_status("TERMINATING", "done_with_network"); @@ -272,7 +298,7 @@ void done_with_network() terminating = true; - dpm->Done(); + analyzer_mgr->Done(); timer_mgr->Expire(); dns_mgr->Flush(); mgr.Drain(); @@ -335,6 +361,8 @@ void terminate_bro() mgr.Drain(); + plugin_mgr->FinishPlugins(); + delete timer_mgr; delete dns_mgr; delete persistence_serializer; @@ -344,8 +372,9 @@ void terminate_bro() delete event_registry; delete secondary_path; delete remote_serializer; - delete dpm; + delete analyzer_mgr; delete log_mgr; + delete plugin_mgr; delete thread_mgr; delete file_mgr; delete reporter; @@ -424,6 +453,7 @@ int main(int argc, char** argv) int override_ignore_checksums = 0; int rule_debug = 0; int RE_level = 4; + int print_plugins = 0; static struct option long_opts[] = { {"bare-mode", no_argument, 0, 'b'}, @@ -452,6 +482,7 @@ int main(int argc, char** argv) {"set-seed", required_argument, 0, 'J'}, {"md5-hashkey", required_argument, 0, 'K'}, {"rule-benchmark", no_argument, 0, 'L'}, + {"print-plugins", no_argument, 0, 'N'}, {"optimize", no_argument, 0, 'O'}, {"prime-dns", no_argument, 0, 'P'}, {"replay", required_argument, 0, 'R'}, @@ -474,8 +505,6 @@ int main(int argc, char** argv) {"pseudo-realtime", optional_argument, 0, 'E'}, - {"use-binpac", no_argument, &FLAGS_use_binpac, 1}, - {0, 0, 0, 0}, }; @@ -506,7 +535,7 @@ int main(int argc, char** argv) opterr = 0; char opts[256]; - safe_strncpy(opts, "B:D:e:f:I:i:K:l:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGLOPSWbdghvZ", + safe_strncpy(opts, "B:D:e:f:I:i:K:l:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGLNOPSWbdghvZ", sizeof(opts)); #ifdef USE_PERFTOOLS_DEBUG @@ -621,6 +650,10 @@ int main(int argc, char** argv) ++rule_bench; break; + case 'N': + ++print_plugins; + break; + case 'O': optimize = 1; break; @@ -767,7 +800,7 @@ int main(int argc, char** argv) if ( optind == argc && read_files.length() == 0 && flow_files.length() == 0 && interfaces.length() == 0 && - ! (id_name || bst_file) && ! command_line_policy ) + ! (id_name || bst_file) && ! command_line_policy && ! print_plugins ) add_input_file("-"); // Process remaining arguments. X=Y arguments indicate script @@ -781,6 +814,8 @@ int main(int argc, char** argv) add_input_file(argv[optind++]); } + push_scope(0); + dns_mgr = new DNS_Mgr(dns_type); // It would nice if this were configurable. This is similar to the @@ -791,20 +826,20 @@ int main(int argc, char** argv) persistence_serializer = new PersistenceSerializer(); remote_serializer = new RemoteSerializer(); event_registry = new EventRegistry(); + analyzer_mgr = new analyzer::Manager(); log_mgr = new logging::Manager(); input_mgr = new input::Manager(); + plugin_mgr = new plugin::Manager(); file_mgr = new file_analysis::Manager(); + plugin_mgr->InitPreScript(); + analyzer_mgr->InitPreScript(); + if ( events_file ) event_player = new EventPlayer(events_file); init_event_handlers(); - push_scope(0); - - dpm = new DPM; - dpm->PreScriptInit(); - // The leak-checker tends to produce some false // positives (memory which had already been // allocated before we start the checking is @@ -818,6 +853,15 @@ int main(int argc, char** argv) yyparse(); + plugin_mgr->InitPostScript(); + analyzer_mgr->InitPostScript(); + + if ( print_plugins ) + { + show_plugins(print_plugins); + exit(1); + } + #ifdef USE_PERFTOOLS_DEBUG } #endif @@ -1063,12 +1107,12 @@ int main(int argc, char** argv) mgr.QueueEvent(bro_script_loaded, vl); } - dpm->PostScriptInit(); - reporter->ReportViaEvents(true); mgr.Drain(); + analyzer_mgr->DumpDebug(); + have_pending_timers = ! reading_traces && timer_mgr->Size() > 0; io_sources.Register(thread_mgr, true); diff --git a/src/parse.y b/src/parse.y index 7ce1174595..98df0de2a3 100644 --- a/src/parse.y +++ b/src/parse.y @@ -2,7 +2,7 @@ // See the file "COPYING" in the main distribution directory for copyright. %} -%expect 88 +%expect 85 %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF @@ -23,7 +23,7 @@ %token TOK_ATTR_EXPIRE_CREATE TOK_ATTR_EXPIRE_READ TOK_ATTR_EXPIRE_WRITE %token TOK_ATTR_PERSISTENT TOK_ATTR_SYNCHRONIZED %token TOK_ATTR_RAW_OUTPUT TOK_ATTR_MERGEABLE -%token TOK_ATTR_PRIORITY TOK_ATTR_GROUP TOK_ATTR_LOG TOK_ATTR_ERROR_HANDLER +%token TOK_ATTR_PRIORITY TOK_ATTR_LOG TOK_ATTR_ERROR_HANDLER %token TOK_ATTR_TYPE_COLUMN %token TOK_DEBUG @@ -79,7 +79,7 @@ #include "Expr.h" #include "Stmt.h" #include "Var.h" -#include "DNS.h" +/* #include "analyzer/protocol/dns/DNS.h" */ #include "RE.h" #include "Scope.h" #include "Reporter.h" @@ -522,10 +522,52 @@ expr: $$ = new VectorConstructorExpr($3); } - | expr '(' opt_expr_list ')' + | expr '(' { - set_location(@1, @4); - $$ = new CallExpr($1, $3, in_hook > 0); + if ( $1->Tag() == EXPR_NAME && $1->Type()->IsTable() ) + ++in_init; + } + + opt_expr_list + { + if ( $1->Tag() == EXPR_NAME && $1->Type()->IsTable() ) + --in_init; + } + + ')' + { + set_location(@1, @6); + + BroType* ctor_type = 0; + + if ( $1->Tag() == EXPR_NAME && + (ctor_type = $1->AsNameExpr()->Id()->AsType()) ) + { + switch ( ctor_type->Tag() ) { + case TYPE_RECORD: + $$ = new RecordConstructorExpr($4, ctor_type); + break; + + case TYPE_TABLE: + if ( ctor_type->IsTable() ) + $$ = new TableConstructorExpr($4, 0, ctor_type); + else + $$ = new SetConstructorExpr($4, 0, ctor_type); + + break; + + case TYPE_VECTOR: + $$ = new VectorConstructorExpr($4, ctor_type); + break; + + default: + $1->Error("constructor type not implemented"); + YYERROR; + } + } + + else + $$ = new CallExpr($1, $4, in_hook > 0); } | TOK_HOOK { ++in_hook; } expr @@ -1081,8 +1123,7 @@ decl: add_global($2, $3, $4, $5, $6, VAR_REDEF); if ( generate_documentation && - ! streq("capture_filters", $2->Name()) && - ! streq("dpd_config", $2->Name()) ) + ! streq("capture_filters", $2->Name()) ) { ID* fake_id = create_dummy_id($2, $2->Type()); BroDocObj* o = new BroDocObj(fake_id, reST_doc_comments, true); @@ -1362,8 +1403,6 @@ attr: { $$ = new Attr(ATTR_MERGEABLE); } | TOK_ATTR_PRIORITY '=' expr { $$ = new Attr(ATTR_PRIORITY, $3); } - | TOK_ATTR_GROUP '=' expr - { $$ = new Attr(ATTR_GROUP, $3); } | TOK_ATTR_TYPE_COLUMN '=' expr { $$ = new Attr(ATTR_TYPE_COLUMN, $3); } | TOK_ATTR_LOG diff --git a/src/plugin/Component.cc b/src/plugin/Component.cc new file mode 100644 index 0000000000..7d2e69eb86 --- /dev/null +++ b/src/plugin/Component.cc @@ -0,0 +1,48 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Component.h" + +#include "../Desc.h" +#include "../Reporter.h" + +using namespace plugin; + +Component::Component(component::Type arg_type) + { + type = arg_type; + } + +Component::~Component() + { + } + +component::Type Component::Type() const + { + return type; + } + +void Component::Describe(ODesc* d) + { + d->Add(" "); + d->Add("["); + + switch ( type ) { + case component::READER: + d->Add("Reader"); + break; + + case component::WRITER: + d->Add("Writer"); + break; + + case component::ANALYZER: + d->Add("Analyzer"); + break; + + default: + reporter->InternalError("unknown component type in plugin::Component::Describe"); + } + + d->Add("]"); + d->Add(" "); + } diff --git a/src/plugin/Component.h b/src/plugin/Component.h new file mode 100644 index 0000000000..fbeb70ebed --- /dev/null +++ b/src/plugin/Component.h @@ -0,0 +1,68 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef PLUGIN_COMPONENT_H +#define PLUGIN_COMPONENT_H + +class ODesc; + +namespace plugin { + +namespace component { + +/** + * Component types. + */ +enum Type { + READER, /// An input reader (not currently used). + WRITER, /// An logging writer (not currenly used). + ANALYZER /// A protocol analyzer. + }; +} + +#if 0 +namespace input { class PluginComponent; } +namespace logging { class PluginComponent; } +namespace analyzer { class PluginComponent; } +#endif + +/** + * Base class for plugin components. A component is a specific piece of + * functionality that a plugin provides, such as a protocol analyzer or a log + * writer. + */ +class Component +{ +public: + /** + * Constructor. + * + * @param type The type of the compoment. + */ + Component(component::Type type); + + /** + * Destructor. + */ + virtual ~Component(); + + /** + * Returns the compoment's type. + */ + component::Type Type() const; + + /** + * Returns a textual representation of the component. The default + * version just output the type. Derived version should call the + * parent's implementation and that add further information. + * + * @param d The description object to use. + */ + virtual void Describe(ODesc* d); + +private: + component::Type type; +}; + +} + +#endif diff --git a/src/plugin/Macros.h b/src/plugin/Macros.h new file mode 100644 index 0000000000..f5c1a41cfa --- /dev/null +++ b/src/plugin/Macros.h @@ -0,0 +1,119 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +/** + * A set of macros wrapping internal logic for defining plugins and + * components. + */ + +#ifndef PLUGIN_MACROS_H +#define PLUGIN_MACROS_H + +#include "analyzer/Component.h" + +/** + * The current plugin API version. Plugins that won't match this version will + * be rejected. + */ +#define BRO_PLUGIN_API_VERSION 1 + +/** + * Starts the definition of a new plugin. + * + * @param _ns: A namespace for the plugin. All plugins compiled in statically + * must use the reserved "Bro" namespace. External plugins should define + * their own namespace to avoid collisions. + * + * @param _name: The plugin's name. The combiniation of namespace and name + * must be unique across all loaded plugins. + */ +#define BRO_PLUGIN_BEGIN(_ns, _name) \ + namespace plugin { namespace _ns ## _ ## _name {\ + class Plugin : public plugin::Plugin { \ + protected: \ + void InitPreScript() \ + { \ + SetName(#_ns "::" #_name); \ + SetVersion(-1);\ + SetAPIVersion(BRO_PLUGIN_API_VERSION);\ + SetDynamicPlugin(false); +// TODO: The SetDynamicPlugin() call is currently hardcoded to false. Change +// once we have dynamic plugins as well. + + +/** + * Ends the definition of a plugin. + */ +#define BRO_PLUGIN_END \ + } \ + }; \ + \ + Plugin __plugin; \ + } } + +/** + * Provides a textual description for a plugin. + * + * @param d A string with the description. + */ +#define BRO_PLUGIN_DESCRIPTION(d) SetDescription(d) + +/** + * Defines a version of the plugin. The version is mostly informational for + * the user; if a plugin's functionality changes, the version should be + * increased. + * + * @param v An integer version. + */ +#define BRO_PLUGIN_VERSION(v) SetVersion(v) + +/** + * Adds script-level items defined in a \c *.bif file to what the plugin + * provides. + * + * @param file A string with the name of \c *.bif file. When loaded, the + * plugin will make all items defined in the file available to Bro's script + * interpreter. + */ +#define BRO_PLUGIN_BIF_FILE(file) \ + extern std::list > __bif_##file##_init(); \ + AddBifInitFunction(&__bif_##file##_init); + +/** + * Defines a component implementing a protocol analyzer. + * + * @param tag A string with the analyzer's tag. This must be unique across + * all loaded analyzers and will translate into a corresponding \c ANALYZER_* + * constant at the script-layer. + * + * @param cls The class that implements the analyzer. It must be derived + * (directly or indirectly) from analyzer::Analyzer. + */ +#define BRO_PLUGIN_ANALYZER(tag, cls) \ + AddComponent(new ::analyzer::Component(tag, ::analyzer::cls::InstantiateAnalyzer)); + +/** + * Defines a component implementing a protocol analyzer class that will + * not be instantiated dynamically. This is for two use-cases: (1) abstract + * analyzer base classes that aren't instantiated directly; and (2) analyzers + * that are only instantiated explicitly by other Bro components, but not + * dynamically by the manager based on their tag (e.g., the ZIP analyzer is + * attached by the HTTP analyzer when corresponding content is found). + * + * @param tag A string with the analyzer's tag. This must be unique across + * all loaded analyzers and will translate into a corresponding \c ANALYZER_* + * constant at the script-layer. + */ +#define BRO_PLUGIN_ANALYZER_BARE(tag) \ + AddComponent(new ::analyzer::Component(tag, 0)); + +/** + * Defines a component implementating a support analyzer. + * + * @param tag A string with the analyzer's tag. This must be unique across + * all loaded analyzers and will translate into a corresponding \c ANALYZER_* + * constant at the script-layer. + */ +#define BRO_PLUGIN_SUPPORT_ANALYZER(tag) \ + AddComponent(new ::analyzer::Component(tag, 0)); + +#endif diff --git a/src/plugin/Manager.cc b/src/plugin/Manager.cc new file mode 100644 index 0000000000..93ed3f2b97 --- /dev/null +++ b/src/plugin/Manager.cc @@ -0,0 +1,85 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "Manager.h" + +#include "../Reporter.h" + +using namespace plugin; + +Manager::Manager() + { + init = false; + } + +Manager::~Manager() + { + assert(! init); + } + +bool Manager::LoadPlugin(const std::string& path) + { + assert(! init); + reporter->InternalError("plugin::Manager::LoadPlugin not yet implemented"); + return false; + } + +bool Manager::LoadPluginsFrom(const std::string& dir) + { + assert(! init); + reporter->InternalError("plugin::Manager::LoadPluginsFrom not yet implemented"); + return false; + } + +bool Manager::RegisterPlugin(Plugin *plugin) + { + Manager::PluginsInternal()->push_back(plugin); + return true; + } + +void Manager::InitPreScript() + { + assert(! init); + + for ( plugin_list::iterator i = Manager::PluginsInternal()->begin(); i != Manager::PluginsInternal()->end(); i++ ) + (*i)->InitPreScript(); + + init = true; + } + +void Manager::InitPostScript() + { + assert(init); + + for ( plugin_list::iterator i = Manager::PluginsInternal()->begin(); i != Manager::PluginsInternal()->end(); i++ ) + (*i)->InitPostScript(); + } + +void Manager::FinishPlugins() + { + assert(init); + + for ( plugin_list::iterator i = Manager::PluginsInternal()->begin(); i != Manager::PluginsInternal()->end(); i++ ) + { + (*i)->Done(); +// delete *i; + } + + Manager::PluginsInternal()->clear(); + + init = false; + } + +Manager::plugin_list Manager::Plugins() const + { + return *Manager::PluginsInternal(); + } + +Manager::plugin_list* Manager::PluginsInternal() + { + static plugin_list* plugins = 0; + + if ( ! plugins ) + plugins = new plugin_list; + + return plugins; + } diff --git a/src/plugin/Manager.h b/src/plugin/Manager.h new file mode 100644 index 0000000000..2bbcaeb0f1 --- /dev/null +++ b/src/plugin/Manager.h @@ -0,0 +1,130 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef PLUGIN_MANAGER_H +#define PLUGIN_MANAGER_H + +#include "Plugin.h" +#include "Component.h" + +#include "../Reporter.h" + +namespace plugin { + +/** + * A singleton object managing all plugins. + */ +class Manager +{ +public: + typedef std::list plugin_list; + typedef Plugin::component_list component_list; + + /** + * Constructor. + */ + Manager(); + + /** + * Destructor. + */ + ~Manager(); + + /** + * Loads a plugin dynamically from a file. This must be called only + * before InitPluginsPreScript() + * + * This is not currently implemented. + * + * @param file The path to the plugin to load. + */ + bool LoadPlugin(const std::string& file); + + /** + * Loads plugins dynamically found in a directory. This must be + * called only before InitPluginsPreScript(). + * + * This is not currently implemented. + * + * @param dir The directory to search for plugins. + */ + bool LoadPluginsFrom(const std::string& dir); + + /** + * First-stage initializion of the manager. This is called early on + * during Bro's initialization, before any scripts are processed, and + * forwards to the corresponding Plugin methods. + */ + void InitPreScript(); + + /** + * Second-stage initialization of the manager. This is called late + * during Bro's initialization after any scripts are processed, and + * forwards to the corresponding Plugin methods. + */ + void InitPostScript(); + + /** + * Finalizes all plugins at termination time. This forwards to the + * corresponding Plugin methods. + */ + void FinishPlugins(); + + /** + * Returns a list of all available plugins. This includes all that + * are compiled in statically, as well as those loaded dynamically so + * far. + */ + plugin_list Plugins() const; + + /** + * Returns a list of all available components, in any plugin, that + * are derived from a specific class. The class is given as the + * template parameter \c T. + */ + template std::list Components() const; + + /** + * Internal method that registers a freshly instantiated plugin with + * the manager. + * + * @param plugin The plugin to register. The method does not take + * ownership, yet assumes the pointer will stay valid at least until + * the Manager is destroyed. + */ + static bool RegisterPlugin(Plugin *plugin); + +private: + static plugin_list* PluginsInternal(); + + bool init; +}; + +template +std::list Manager::Components() const + { + std::list result; + + for ( plugin_list::const_iterator p = PluginsInternal()->begin(); p != PluginsInternal()->end(); p++ ) + { + component_list components = (*p)->Components(); + + for ( component_list::const_iterator c = components.begin(); c != components.end(); c++ ) + { + T* t = dynamic_cast(*c); + + if ( t ) + result.push_back(t); + } + } + + return result; + } + +} + +/** + * The global plugin manager singleton. + */ +extern plugin::Manager* plugin_mgr; + +#endif diff --git a/src/plugin/Plugin.cc b/src/plugin/Plugin.cc new file mode 100644 index 0000000000..352aff6aed --- /dev/null +++ b/src/plugin/Plugin.cc @@ -0,0 +1,246 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include + +#include "Plugin.h" +#include "Manager.h" +#include "Component.h" + +#include "../Desc.h" + +using namespace plugin; + +BifItem::BifItem(const std::string& arg_id, Type arg_type) + { + id = copy_string(arg_id.c_str()); + type = arg_type; + } + +BifItem::BifItem(const BifItem& other) + { + id = copy_string(other.id); + type = other.type; + } + +BifItem& BifItem::operator=(const BifItem& other) + { + if ( this != &other ) + { + id = copy_string(other.id); + type = other.type; + } + + return *this; + } + +BifItem::~BifItem() + { + delete [] id; + } + +Plugin::Plugin() + { + name = copy_string(""); + description = copy_string(""); + + // These will be reset by the BRO_PLUGIN_* macros. + version = -9999; + api_version = -9999; + dynamic = false; + + Manager::RegisterPlugin(this); + } + +Plugin::~Plugin() + { + Done(); + + delete [] name; + delete [] description; + } + +const char* Plugin::Name() + { + return name; + } + +void Plugin::SetName(const char* arg_name) + { + name = copy_string(arg_name); + } + +const char* Plugin::Description() + { + return description; + } + +void Plugin::SetDescription(const char* arg_description) + { + description = copy_string(arg_description); + } + +int Plugin::Version() + { + return dynamic ? version : 0; + } + +void Plugin::SetVersion(int arg_version) + { + version = arg_version; + } + +int Plugin::APIVersion() + { + return api_version; + } + +bool Plugin::DynamicPlugin() + { + return dynamic; + } + +void Plugin::SetAPIVersion(int arg_version) + { + api_version = arg_version; + } + +void Plugin::SetDynamicPlugin(bool arg_dynamic) + { + dynamic = arg_dynamic; + } + +void Plugin::InitPreScript() + { + } + +void Plugin::InitPostScript() + { + for ( bif_init_func_list::const_iterator f = bif_inits.begin(); f != bif_inits.end(); f++ ) + { + bif_init_func_result items = (**f)(); + + for ( bif_init_func_result::const_iterator i = items.begin(); i != items.end(); i++ ) + { + BifItem bi((*i).first, (BifItem::Type)(*i).second); + bif_items.push_back(bi); + } + } + } + +Plugin::bif_item_list Plugin::BifItems() + { + bif_item_list l1 = bif_items; + bif_item_list l2 = CustomBifItems(); + + for ( bif_item_list::const_iterator i = l2.begin(); i != l2.end(); i++ ) + l1.push_back(*i); + + return l1; + } + +Plugin::bif_item_list Plugin::CustomBifItems() + { + return bif_item_list(); + } + +void Plugin::Done() + { + for ( component_list::const_iterator i = components.begin(); i != components.end(); i++ ) + delete *i; + + components.clear(); + } + +Plugin::component_list Plugin::Components() + { + return components; + } + +void Plugin::AddComponent(Component* c) + { + components.push_back(c); + } + +void Plugin::AddBifInitFunction(bif_init_func c) + { + bif_inits.push_back(c); + } + +void Plugin::Describe(ODesc* d) + { + d->Add("Plugin: "); + d->Add(name); + + if ( description && *description ) + { + d->Add(" - "); + d->Add(description); + } + + if ( dynamic ) + { + if ( version > 0 ) + { + d->Add(" (version "); + d->Add(version); + d->Add(")"); + } + else + d->Add(" (version not set)"); + } + + else + d->Add(" (built-in)"); + + d->Add("\n"); + + if ( d->IsShort() ) + return; + + for ( component_list::const_iterator i = components.begin(); i != components.end(); i++ ) + { + (*i)->Describe(d); + d->Add("\n"); + } + + bif_item_list items = BifItems(); + + for ( bif_item_list::const_iterator i = items.begin(); i != items.end(); i++ ) + { + const char* type = 0; + + switch ( (*i).GetType() ) { + case BifItem::FUNCTION: + type = "Function"; + break; + + case BifItem::EVENT: + type = "Event"; + break; + + case BifItem::CONSTANT: + type = "Constant"; + break; + + case BifItem::GLOBAL: + type = "Global"; + break; + + case BifItem::TYPE: + type = "Type"; + break; + + default: + type = ""; + } + + d->Add(" "); + d->Add("["); + d->Add(type); + d->Add("] "); + d->Add((*i).GetID()); + d->Add("\n"); + } + } + + diff --git a/src/plugin/Plugin.h b/src/plugin/Plugin.h new file mode 100644 index 0000000000..6c6d89a4d1 --- /dev/null +++ b/src/plugin/Plugin.h @@ -0,0 +1,252 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef PLUGIN_PLUGIN_H +#define PLUGIN_PLUGIN_H + +#include +#include + +#include "Macros.h" + +class ODesc; + +namespace plugin { + +class Manager; +class Component; + +/** + * A class describing an item defined in \c *.bif file. + */ +class BifItem { +public: + /** + * Type of the item. + * + * The values here must match the integers that \c bifcl generated. + */ + enum Type { FUNCTION = 1, EVENT = 2, CONSTANT = 3, GLOBAL = 4, TYPE = 5 }; + + /** + * Constructor. + * + * @param id The script-level name of the item. This should be fully + * qualified. + * + * @param type The type of the item. + */ + BifItem(const std::string& id, Type type); + + /** + * Copy constructor. + */ + BifItem(const BifItem& other); + + /** + * Assigment operator. + */ + BifItem& operator=(const BifItem& other); + + /** + * Destructor. + */ + ~BifItem(); + + /** + * Returns the script-level ID as passed into the constructor. + */ + const char* GetID() const { return id; } + + /** + * Returns the type as passed into the constructor. + */ + Type GetType() const { return type; } + +private: + const char* id; + Type type; +}; + +/** + * Base class for all plugins. + * + * Plugins encapsulate functionality that extends one of Bro's major + * subsystems, such as analysis of a specific protocol, or logging output in + * a particular format. A plugin is a logical container that can provide one + * or more \a components implementing functionality. For example, a RPC + * plugin could provide analyzer for set of related protocols (RPC, NFS, + * etc.), each of which would be a separate component. Likewise, a SQLite + * plugin could provide both a writer and reader component. In addition to + * components, a plugin can also provide of script-level elements defined in + * *.bif files. + * + * Currently, all plugins are compiled statically into the final Bro binary. + * Later, we will extend the infrastructure to also support plugins loaded + * dynamically as shared libraries. + */ +class Plugin { +public: + typedef std::list component_list; + typedef std::list bif_item_list; + + /** + * Constructor. + */ + Plugin(); + + /** + * Destructor. + */ + virtual ~Plugin(); + + /** + * Returns the name of the plugin. + */ + const char* Name(); + + /** + * Returns a short textual description of the plugin, if provided. + */ + const char* Description(); + + /** + * Returns the version of the plugin. Version are only meaningful for + * dynamically compiled plugins; for statically compiled ones, this + * will always return 0. + */ + int Version(); + + /** + * Returns true if this is a dynamically linked in plugin. + */ + bool DynamicPlugin(); + + /** + * Returns the internal API version that this plugin relies on. Only + * plugins that match Bro's current API version may be used. For + * statically compiled plugins this is automatically the case, but + * dynamically loaded plugins may cause a mismatch if they were + * compiled for a different Bro version. + */ + int APIVersion(); + + /** + * Returns a list of all components the plugin provides. + */ + component_list Components(); + + /** + * Returns a list of all BiF items that the plugin provides. This + * must be called only after InitBif() has been executed. + */ + bif_item_list BifItems(); + + /** + * First-stage initialization of the plugin called early during Bro's + * startup, before scripts are parsed. This can be overridden by + * derived classes; they must however call the parent's + * implementation. + */ + virtual void InitPreScript(); + + /** + * Second-stage initialization of the plugin called late during Bro's + * startup, after scripts are parsed. This can be overridden by + * derived classes; they must however call the parent's + * implementation. + */ + virtual void InitPostScript(); + + /** + * Finalizer method that derived classes can override for performing + * custom tasks at shutdown. Implementation must call the parent's + * version. + */ + virtual void Done(); + + /** + * Returns a textual description of the plugin. + * + * @param d Description object to use for rendering. If "short mode" + * is disabled, the rendering will include a list of all components + * and BiF items. + */ + void Describe(ODesc* d); + +protected: + typedef std::list > bif_init_func_result; + typedef bif_init_func_result (*bif_init_func)(); + + /** + * Sets the plugins name. + * + * @param name The name. Makes a copy internally. + */ + void SetName(const char* name); + + /** + * Sets the plugin's textual description. + * + * @param name The description. Makes a copy internally. + */ + void SetDescription(const char* descr); + + /** + * Sets the plugin's version. + * + * @param version The version. + */ + void SetVersion(int version); + + /** + * Sets the API version the plugin requires. + * BRO_PLUGIN_VERSION_BUILTIN indicates that it's a plugin linked in + * statically. + */ + void SetAPIVersion(int version); + + /** + * Marks the plugin as statically or dynamically linked. + * + * @param dynamic True if this is a dynamically linked plugin. + */ + void SetDynamicPlugin(bool dynamic); + + /** + * Takes ownership. + */ + void AddComponent(Component* c); + + /** + * Virtual method that can be overriden by derived class to provide + * information about further script-level elements that the plugins + * provides on its own, i.e., outside of the standard mechanism + * processing *.bif files automatically. The returned information is + * for informational purpuses only and will show up in the result of + * BifItems() as well as in the Describe() output. + */ + virtual bif_item_list CustomBifItems() ; + + /** + * Internal function adding an entry point for registering + * auto-generated BiFs. + */ + void AddBifInitFunction(bif_init_func c); + +private: + typedef std::list bif_init_func_list; + + const char* name; + const char* description; + int version; + int api_version; + bool dynamic; + + component_list components; + bif_item_list bif_items; + bif_init_func_list bif_inits; +}; + +} + +#endif diff --git a/src/plugins.cc.in b/src/plugins.cc.in new file mode 100644 index 0000000000..4527d5d1a9 --- /dev/null +++ b/src/plugins.cc.in @@ -0,0 +1,22 @@ + +// A work-around the problem that for static libraries unused globals +// aren't linked into the final binary. CMake automatically inserts +// code here to reference the globals that initializes each of the +// statically compiled plugins. +// +// Note: This won't be necessary anymore once we can assume CMake >2.8.8 +// as a required depencendy. If so, switch bro_HAVE_OBJECT_LIBRARIES +// in src/CMakeLists.txt to TRUE and remove this. + +#include + +${__BRO_DECL_PLUGINS} + +size_t __make_sure_to_use_plugin_globals() +{ + // This function is never actually called. + + size_t i = 0; + ${__BRO_USE_PLUGINS} + return i; +} diff --git a/src/scan.l b/src/scan.l index ffbc125728..f23fa10f75 100644 --- a/src/scan.l +++ b/src/scan.l @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include "input.h" @@ -22,9 +24,11 @@ #include "PolicyFile.h" #include "broparse.h" #include "BroDoc.h" -#include "Analyzer.h" -#include "AnalyzerTags.h" #include "Reporter.h" +#include "RE.h" +#include "Net.h" + +#include "analyzer/Analyzer.h" extern YYLTYPE yylloc; // holds start line and column of token extern int print_loaded_scripts; @@ -67,9 +71,6 @@ void clear_reST_doc_comments(); // Adds changes to capture_filter to the current script's reST documentation. static void check_capture_filter_changes(); -// Adds changes to dpd_config to the current script's reST documentation. -static void check_dpd_config_changes(); - static const char* canon_doc_comment(const char* comment) { // "##Text" and "## Text" are treated the same in order to be able @@ -328,7 +329,6 @@ when return TOK_WHEN; &encrypt return TOK_ATTR_ENCRYPT; &error_handler return TOK_ATTR_ERROR_HANDLER; &expire_func return TOK_ATTR_EXPIRE_FUNC; -&group return TOK_ATTR_GROUP; &log return TOK_ATTR_LOG; &mergeable return TOK_ATTR_MERGEABLE; &optional return TOK_ATTR_OPTIONAL; @@ -344,6 +344,34 @@ when return TOK_WHEN; @DEBUG return TOK_DEBUG; // marks input for debugger +@DIR { + string rval = current_scanned_file_path; + + if ( ! rval.empty() && rval[0] == '.' ) + { + char path[MAXPATHLEN]; + + if ( ! getcwd(path, MAXPATHLEN) ) + reporter->InternalError("getcwd failed: %s", strerror(errno)); + else + rval = string(path) + "/" + rval; + } + + RET_CONST(new StringVal(rval.c_str())); + } + +@FILENAME { + char* filename_copy = copy_string(::filename); + const char* bname = basename(filename_copy); + + if ( ! bname ) + reporter->InternalError("basename failed: %s", strerror(errno)); + + StringVal* rval = new StringVal(bname); + delete [] filename_copy; + RET_CONST(rval); + } + @load{WS}{FILE} { const char* new_file = skip_whitespace(yytext + 5); // Skip "@load". if ( generate_documentation ) @@ -552,7 +580,7 @@ YYLTYPE GetCurrentLocation() static int load_files(const char* orig_file) { // Whether we pushed on a FileInfo that will restore the - // current module after the final file has been scanned. + // current module after the final file has been scanned. bool did_module_restore = false; const char* full_filename = ""; @@ -822,7 +850,6 @@ int yywrap() while ( input_files.length() > 0 ) { check_capture_filter_changes(); - check_dpd_config_changes(); if ( load_files(input_files[0]) ) { @@ -838,7 +865,6 @@ int yywrap() } check_capture_filter_changes(); - check_dpd_config_changes(); // For each file scanned so far, and for each @prefix, look for a // prefixed and flattened version of the loaded file in BROPATH. The @@ -1003,51 +1029,6 @@ static void check_capture_filter_changes() } } -static void check_dpd_config_changes() - { - if ( ! generate_documentation ) - return; - - // Lookup the "dpd_config" identifier, if it has any defined value, - // add it to the script's documentation, and clear the table so that - // it doesn't taint the documentation for subsequent scripts. - ID* dpd_config = global_scope()->Lookup("dpd_config"); - if ( ! dpd_config ) - return; - - TableVal* dpd_table = dpd_config->ID_Val()->AsTableVal(); - ListVal* dpd_list = dpd_table->ConvertToList(); - - for ( int i = 0; i < dpd_list->Length(); ++i ) - { - Val* key = dpd_list->Index(i); - if ( ! key ) - continue; - - Val* v = dpd_table->Lookup(key); - if ( ! v ) - continue; - - int tag = key->AsListVal()->Index(0)->AsCount(); - ODesc valdesc; - valdesc.SetIndentSpaces(4); - valdesc.PushIndent(); - v->Describe(&valdesc); - - if ( tag < AnalyzerTag::Error || tag > AnalyzerTag::LastAnalyzer ) - { - fprintf(stderr, "Warning: skipped bad analyzer tag: %i\n", tag); - continue; - } - - last_reST_doc->AddPortAnalysis( - Analyzer::GetTagName((AnalyzerTag::Tag)tag), - valdesc.Description()); - } - - dpd_table->RemoveAll(); - } - void print_current_reST_doc_comments() { if ( ! reST_doc_comments ) diff --git a/src/util-config.h.in b/src/util-config.h.in index 4c57495eb6..ff5e28537a 100644 --- a/src/util-config.h.in +++ b/src/util-config.h.in @@ -1,4 +1,5 @@ #define BRO_SCRIPT_INSTALL_PATH "@BRO_SCRIPT_INSTALL_PATH@" #define BRO_SCRIPT_SOURCE_PATH "@BRO_SCRIPT_SOURCE_PATH@" -#define BRO_BUILD_PATH "@CMAKE_CURRENT_BINARY_DIR@" +#define BRO_BUILD_SOURCE_PATH "@CMAKE_BINARY_DIR@/src" +#define BRO_BUILD_SCRIPTS_PATH "@CMAKE_BINARY_DIR@/scripts" #define BRO_MAGIC_INSTALL_PATH "@BRO_MAGIC_INSTALL_PATH@" diff --git a/src/util.cc b/src/util.cc index a031f41ffe..de9bd5b679 100644 --- a/src/util.cc +++ b/src/util.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -298,6 +299,13 @@ void to_upper(char* s) } } +string to_upper(const std::string& s) + { + string t = s; + std::transform(t.begin(), t.end(), t.begin(), ::toupper); + return t; + } + const char* strchr_n(const char* s, const char* end_of_s, char ch) { for ( ; s < end_of_s; ++s ) @@ -1026,8 +1034,10 @@ void get_script_subpath(const std::string& full_filename, const char** subpath) my_subpath.erase(0, strlen(BRO_SCRIPT_INSTALL_PATH)); else if ( (p = my_subpath.find(BRO_SCRIPT_SOURCE_PATH)) != std::string::npos ) my_subpath.erase(0, strlen(BRO_SCRIPT_SOURCE_PATH)); - else if ( (p = my_subpath.find(BRO_BUILD_PATH)) != std::string::npos ) - my_subpath.erase(0, strlen(BRO_BUILD_PATH)); + else if ( (p = my_subpath.find(BRO_BUILD_SOURCE_PATH)) != std::string::npos ) + my_subpath.erase(0, strlen(BRO_BUILD_SOURCE_PATH)); + else if ( (p = my_subpath.find(BRO_BUILD_SCRIPTS_PATH)) != std::string::npos ) + my_subpath.erase(0, strlen(BRO_BUILD_SCRIPTS_PATH)); // if root path found, remove path separators until next path component if ( p != std::string::npos ) diff --git a/src/util.h b/src/util.h index b0ac760117..49bcbf318b 100644 --- a/src/util.h +++ b/src/util.h @@ -5,8 +5,14 @@ // Expose C99 functionality from inttypes.h, which would otherwise not be // available in C++. +#ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS +#endif + +#ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS +#endif + #include #include @@ -114,6 +120,7 @@ extern char* skip_digits(char* s); extern char* get_word(char*& s); extern void get_word(int length, const char* s, int& pwlen, const char*& pw); extern void to_upper(char* s); +extern std::string to_upper(const std::string& s); extern const char* strchr_n(const char* s, const char* end_of_s, char ch); extern const char* strrchr_n(const char* s, const char* end_of_s, char ch); extern int decode_hex(char ch); diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index 840f555711..06652e37e7 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -3,19 +3,19 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2013-05-15-23-01-21 +#open 2013-05-17-03-57-47 #fields name #types string scripts/base/init-bare.bro - build/src/base/const.bif.bro - build/src/base/types.bif.bro - build/src/base/strings.bif.bro - build/src/base/bro.bif.bro - build/src/base/reporter.bif.bro - build/src/base/event.bif.bro + build/scripts/base/bif/const.bif.bro + build/scripts/base/bif/types.bif.bro + build/scripts/base/bif/strings.bif.bro + build/scripts/base/bif/bro.bif.bro + build/scripts/base/bif/reporter.bif.bro + build/scripts/base/bif/event.bif.bro scripts/base/frameworks/logging/__load__.bro scripts/base/frameworks/logging/main.bro - build/src/base/logging.bif.bro + build/scripts/base/bif/logging.bif.bro scripts/base/frameworks/logging/postprocessors/__load__.bro scripts/base/frameworks/logging/postprocessors/scp.bro scripts/base/frameworks/logging/postprocessors/sftp.bro @@ -26,15 +26,65 @@ scripts/base/init-bare.bro scripts/base/frameworks/logging/writers/none.bro scripts/base/frameworks/input/__load__.bro scripts/base/frameworks/input/main.bro - build/src/base/input.bif.bro + build/scripts/base/bif/input.bif.bro scripts/base/frameworks/input/readers/ascii.bro scripts/base/frameworks/input/readers/raw.bro scripts/base/frameworks/input/readers/benchmark.bro scripts/base/frameworks/input/readers/binary.bro scripts/base/frameworks/input/readers/sqlite.bro + scripts/base/frameworks/analyzer/__load__.bro + scripts/base/frameworks/analyzer/main.bro + build/scripts/base/bif/analyzer.bif.bro scripts/base/frameworks/file-analysis/__load__.bro scripts/base/frameworks/file-analysis/main.bro - build/src/base/file_analysis.bif.bro + build/scripts/base/bif/file_analysis.bif.bro + build/scripts/base/bif/plugins/__load__.bro + build/scripts/base/bif/plugins/Bro_ARP.events.bif.bro + build/scripts/base/bif/plugins/Bro_AYIYA.events.bif.bro + build/scripts/base/bif/plugins/Bro_BackDoor.events.bif.bro + build/scripts/base/bif/plugins/Bro_BitTorrent.events.bif.bro + build/scripts/base/bif/plugins/Bro_ConnSize.events.bif.bro + build/scripts/base/bif/plugins/Bro_DCE_RPC.events.bif.bro + build/scripts/base/bif/plugins/Bro_DHCP.events.bif.bro + build/scripts/base/bif/plugins/Bro_DNS.events.bif.bro + build/scripts/base/bif/plugins/Bro_FTP.events.bif.bro + build/scripts/base/bif/plugins/Bro_FTP.functions.bif.bro + build/scripts/base/bif/plugins/Bro_File.events.bif.bro + build/scripts/base/bif/plugins/Bro_Finger.events.bif.bro + build/scripts/base/bif/plugins/Bro_GTPv1.events.bif.bro + build/scripts/base/bif/plugins/Bro_Gnutella.events.bif.bro + build/scripts/base/bif/plugins/Bro_HTTP.events.bif.bro + build/scripts/base/bif/plugins/Bro_HTTP.functions.bif.bro + build/scripts/base/bif/plugins/Bro_ICMP.events.bif.bro + build/scripts/base/bif/plugins/Bro_IRC.events.bif.bro + build/scripts/base/bif/plugins/Bro_Ident.events.bif.bro + build/scripts/base/bif/plugins/Bro_InterConn.events.bif.bro + build/scripts/base/bif/plugins/Bro_Login.events.bif.bro + build/scripts/base/bif/plugins/Bro_Login.functions.bif.bro + build/scripts/base/bif/plugins/Bro_MIME.events.bif.bro + build/scripts/base/bif/plugins/Bro_Modbus.events.bif.bro + build/scripts/base/bif/plugins/Bro_NCP.events.bif.bro + build/scripts/base/bif/plugins/Bro_NTP.events.bif.bro + build/scripts/base/bif/plugins/Bro_NetBIOS.events.bif.bro + build/scripts/base/bif/plugins/Bro_NetBIOS.functions.bif.bro + build/scripts/base/bif/plugins/Bro_NetFlow.events.bif.bro + build/scripts/base/bif/plugins/Bro_PIA.events.bif.bro + build/scripts/base/bif/plugins/Bro_POP3.events.bif.bro + build/scripts/base/bif/plugins/Bro_RPC.events.bif.bro + build/scripts/base/bif/plugins/Bro_SMB.events.bif.bro + build/scripts/base/bif/plugins/Bro_SMTP.events.bif.bro + build/scripts/base/bif/plugins/Bro_SMTP.functions.bif.bro + build/scripts/base/bif/plugins/Bro_SOCKS.events.bif.bro + build/scripts/base/bif/plugins/Bro_SSH.events.bif.bro + build/scripts/base/bif/plugins/Bro_SSL.events.bif.bro + build/scripts/base/bif/plugins/Bro_SSL.functions.bif.bro + build/scripts/base/bif/plugins/Bro_SteppingStone.events.bif.bro + build/scripts/base/bif/plugins/Bro_Syslog.events.bif.bro + build/scripts/base/bif/plugins/Bro_TCP.events.bif.bro + build/scripts/base/bif/plugins/Bro_TCP.functions.bif.bro + build/scripts/base/bif/plugins/Bro_Teredo.events.bif.bro + build/scripts/base/bif/plugins/Bro_UDP.events.bif.bro + build/scripts/base/bif/plugins/Bro_ZIP.events.bif.bro scripts/policy/misc/loaded-scripts.bro scripts/base/utils/paths.bro -#close 2013-05-15-23-01-21 +#close 2013-05-17-03-57-47 diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index 3cfd9b58a7..cb92b663f0 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -3,19 +3,19 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2013-05-16-00-19-22 +#open 2013-05-17-03-58-48 #fields name #types string scripts/base/init-bare.bro - build/src/base/const.bif.bro - build/src/base/types.bif.bro - build/src/base/strings.bif.bro - build/src/base/bro.bif.bro - build/src/base/reporter.bif.bro - build/src/base/event.bif.bro + build/scripts/base/bif/const.bif.bro + build/scripts/base/bif/types.bif.bro + build/scripts/base/bif/strings.bif.bro + build/scripts/base/bif/bro.bif.bro + build/scripts/base/bif/reporter.bif.bro + build/scripts/base/bif/event.bif.bro scripts/base/frameworks/logging/__load__.bro scripts/base/frameworks/logging/main.bro - build/src/base/logging.bif.bro + build/scripts/base/bif/logging.bif.bro scripts/base/frameworks/logging/postprocessors/__load__.bro scripts/base/frameworks/logging/postprocessors/scp.bro scripts/base/frameworks/logging/postprocessors/sftp.bro @@ -26,15 +26,65 @@ scripts/base/init-bare.bro scripts/base/frameworks/logging/writers/none.bro scripts/base/frameworks/input/__load__.bro scripts/base/frameworks/input/main.bro - build/src/base/input.bif.bro + build/scripts/base/bif/input.bif.bro scripts/base/frameworks/input/readers/ascii.bro scripts/base/frameworks/input/readers/raw.bro scripts/base/frameworks/input/readers/benchmark.bro scripts/base/frameworks/input/readers/binary.bro scripts/base/frameworks/input/readers/sqlite.bro + scripts/base/frameworks/analyzer/__load__.bro + scripts/base/frameworks/analyzer/main.bro + build/scripts/base/bif/analyzer.bif.bro scripts/base/frameworks/file-analysis/__load__.bro scripts/base/frameworks/file-analysis/main.bro - build/src/base/file_analysis.bif.bro + build/scripts/base/bif/file_analysis.bif.bro + build/scripts/base/bif/plugins/__load__.bro + build/scripts/base/bif/plugins/Bro_ARP.events.bif.bro + build/scripts/base/bif/plugins/Bro_AYIYA.events.bif.bro + build/scripts/base/bif/plugins/Bro_BackDoor.events.bif.bro + build/scripts/base/bif/plugins/Bro_BitTorrent.events.bif.bro + build/scripts/base/bif/plugins/Bro_ConnSize.events.bif.bro + build/scripts/base/bif/plugins/Bro_DCE_RPC.events.bif.bro + build/scripts/base/bif/plugins/Bro_DHCP.events.bif.bro + build/scripts/base/bif/plugins/Bro_DNS.events.bif.bro + build/scripts/base/bif/plugins/Bro_FTP.events.bif.bro + build/scripts/base/bif/plugins/Bro_FTP.functions.bif.bro + build/scripts/base/bif/plugins/Bro_File.events.bif.bro + build/scripts/base/bif/plugins/Bro_Finger.events.bif.bro + build/scripts/base/bif/plugins/Bro_GTPv1.events.bif.bro + build/scripts/base/bif/plugins/Bro_Gnutella.events.bif.bro + build/scripts/base/bif/plugins/Bro_HTTP.events.bif.bro + build/scripts/base/bif/plugins/Bro_HTTP.functions.bif.bro + build/scripts/base/bif/plugins/Bro_ICMP.events.bif.bro + build/scripts/base/bif/plugins/Bro_IRC.events.bif.bro + build/scripts/base/bif/plugins/Bro_Ident.events.bif.bro + build/scripts/base/bif/plugins/Bro_InterConn.events.bif.bro + build/scripts/base/bif/plugins/Bro_Login.events.bif.bro + build/scripts/base/bif/plugins/Bro_Login.functions.bif.bro + build/scripts/base/bif/plugins/Bro_MIME.events.bif.bro + build/scripts/base/bif/plugins/Bro_Modbus.events.bif.bro + build/scripts/base/bif/plugins/Bro_NCP.events.bif.bro + build/scripts/base/bif/plugins/Bro_NTP.events.bif.bro + build/scripts/base/bif/plugins/Bro_NetBIOS.events.bif.bro + build/scripts/base/bif/plugins/Bro_NetBIOS.functions.bif.bro + build/scripts/base/bif/plugins/Bro_NetFlow.events.bif.bro + build/scripts/base/bif/plugins/Bro_PIA.events.bif.bro + build/scripts/base/bif/plugins/Bro_POP3.events.bif.bro + build/scripts/base/bif/plugins/Bro_RPC.events.bif.bro + build/scripts/base/bif/plugins/Bro_SMB.events.bif.bro + build/scripts/base/bif/plugins/Bro_SMTP.events.bif.bro + build/scripts/base/bif/plugins/Bro_SMTP.functions.bif.bro + build/scripts/base/bif/plugins/Bro_SOCKS.events.bif.bro + build/scripts/base/bif/plugins/Bro_SSH.events.bif.bro + build/scripts/base/bif/plugins/Bro_SSL.events.bif.bro + build/scripts/base/bif/plugins/Bro_SSL.functions.bif.bro + build/scripts/base/bif/plugins/Bro_SteppingStone.events.bif.bro + build/scripts/base/bif/plugins/Bro_Syslog.events.bif.bro + build/scripts/base/bif/plugins/Bro_TCP.events.bif.bro + build/scripts/base/bif/plugins/Bro_TCP.functions.bif.bro + build/scripts/base/bif/plugins/Bro_Teredo.events.bif.bro + build/scripts/base/bif/plugins/Bro_UDP.events.bif.bro + build/scripts/base/bif/plugins/Bro_ZIP.events.bif.bro scripts/base/init-default.bro scripts/base/utils/site.bro scripts/base/utils/patterns.bro @@ -141,4 +191,4 @@ scripts/base/init-default.bro scripts/base/protocols/syslog/main.bro scripts/base/misc/find-checksum-offloading.bro scripts/policy/misc/loaded-scripts.bro -#close 2013-05-16-00-19-22 +#close 2013-05-17-03-58-48 diff --git a/testing/btest/Baseline/doc.autogen-reST-example/example.rst b/testing/btest/Baseline/doc.autogen-reST-example/example.rst index 1f60efe70b..2cb75a6b9f 100644 --- a/testing/btest/Baseline/doc.autogen-reST-example/example.rst +++ b/testing/btest/Baseline/doc.autogen-reST-example/example.rst @@ -109,17 +109,6 @@ Notices Configuration Changes ##################### -Port Analysis -^^^^^^^^^^^^^ -Loading this script makes the following changes to :bro:see:`dpd_config`. - -SSL:: - - [ports={ - 443/tcp, - 562/tcp - }] - Packet Filter ^^^^^^^^^^^^^ Loading this script makes the following changes to :bro:see:`capture_filters`. diff --git a/testing/btest/Baseline/istate.events-ssl/events.rec.log b/testing/btest/Baseline/istate.events-ssl/events.rec.log index 04993fb84a..8c7f4f621c 100644 --- a/testing/btest/Baseline/istate.events-ssl/events.rec.log +++ b/testing/btest/Baseline/istate.events-ssl/events.rec.log @@ -8,7 +8,6 @@ http_all_headers http_content_type http_end_entity http_message_done -http_signature_found http_reply http_begin_entity http_header diff --git a/testing/btest/Baseline/istate.events-ssl/events.snd.log b/testing/btest/Baseline/istate.events-ssl/events.snd.log index 04993fb84a..8c7f4f621c 100644 --- a/testing/btest/Baseline/istate.events-ssl/events.snd.log +++ b/testing/btest/Baseline/istate.events-ssl/events.snd.log @@ -8,7 +8,6 @@ http_all_headers http_content_type http_end_entity http_message_done -http_signature_found http_reply http_begin_entity http_header diff --git a/testing/btest/Baseline/istate.events/events.rec.log b/testing/btest/Baseline/istate.events/events.rec.log index 04993fb84a..8c7f4f621c 100644 --- a/testing/btest/Baseline/istate.events/events.rec.log +++ b/testing/btest/Baseline/istate.events/events.rec.log @@ -8,7 +8,6 @@ http_all_headers http_content_type http_end_entity http_message_done -http_signature_found http_reply http_begin_entity http_header diff --git a/testing/btest/Baseline/istate.events/events.snd.log b/testing/btest/Baseline/istate.events/events.snd.log index 04993fb84a..8c7f4f621c 100644 --- a/testing/btest/Baseline/istate.events/events.snd.log +++ b/testing/btest/Baseline/istate.events/events.snd.log @@ -8,7 +8,6 @@ http_all_headers http_content_type http_end_entity http_message_done -http_signature_found http_reply http_begin_entity http_header diff --git a/testing/btest/Baseline/language.at-dir/out b/testing/btest/Baseline/language.at-dir/out new file mode 100644 index 0000000000..4cd8e27d6a --- /dev/null +++ b/testing/btest/Baseline/language.at-dir/out @@ -0,0 +1 @@ +/Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.at-dir diff --git a/testing/btest/Baseline/language.at-dir/out2 b/testing/btest/Baseline/language.at-dir/out2 new file mode 100644 index 0000000000..f8e3c550d3 --- /dev/null +++ b/testing/btest/Baseline/language.at-dir/out2 @@ -0,0 +1 @@ +/Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/language.at-path/. diff --git a/testing/btest/Baseline/language.at-filename/out b/testing/btest/Baseline/language.at-filename/out new file mode 100644 index 0000000000..12cfb152d9 --- /dev/null +++ b/testing/btest/Baseline/language.at-filename/out @@ -0,0 +1 @@ +at-filename.bro diff --git a/testing/btest/Baseline/language.named-record-ctors/out b/testing/btest/Baseline/language.named-record-ctors/out new file mode 100644 index 0000000000..39b2ed7c0b --- /dev/null +++ b/testing/btest/Baseline/language.named-record-ctors/out @@ -0,0 +1,2 @@ +[min=, max=2] +[min=7, max=42] diff --git a/testing/btest/Baseline/language.named-set-ctors/out b/testing/btest/Baseline/language.named-set-ctors/out new file mode 100644 index 0000000000..66b0baed7f --- /dev/null +++ b/testing/btest/Baseline/language.named-set-ctors/out @@ -0,0 +1,13 @@ +{ +1, +5, +3 +} +{ +[min=, max=5], +[min=, max=2] +} +{ +[test, 1] , +[cool, 2] +} diff --git a/testing/btest/Baseline/language.named-table-ctors/out b/testing/btest/Baseline/language.named-table-ctors/out new file mode 100644 index 0000000000..23554d10f6 --- /dev/null +++ b/testing/btest/Baseline/language.named-table-ctors/out @@ -0,0 +1,19 @@ +{ +[1] = one, +[5] = five, +[3] = three +} +{ +[[min=, max=5]] = max5, +[[min=, max=2]] = max2 +} +{ +[test, 1] = test1, +[cool, 2] = cool2 +} +{ +[two] = 2.0, +[one] = 1.0, +[three] = 3.0 +} +0 diff --git a/testing/btest/Baseline/language.named-vector-ctors/out b/testing/btest/Baseline/language.named-vector-ctors/out new file mode 100644 index 0000000000..53ed260c93 --- /dev/null +++ b/testing/btest/Baseline/language.named-vector-ctors/out @@ -0,0 +1,3 @@ +[one, two, three] +[1.0, 2.0, 3.0] +[[min=, max=1], [min=, max=2], [min=, max=3]] diff --git a/testing/btest/Baseline/scripts.base.frameworks.analyzer.schedule-analyzer/output b/testing/btest/Baseline/scripts.base.frameworks.analyzer.schedule-analyzer/output new file mode 100644 index 0000000000..600f353088 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.analyzer.schedule-analyzer/output @@ -0,0 +1,5 @@ +APPLIED:, 1299491995.0, [orig_h=10.0.0.2, orig_p=20/tcp, resp_h=10.0.0.3, resp_p=6/tcp], Analyzer::ANALYZER_DNS +APPLIED:, 1299491995.0, [orig_h=10.0.0.2, orig_p=20/tcp, resp_h=10.0.0.3, resp_p=6/tcp], Analyzer::ANALYZER_FTP +APPLIED:, 1299491995.0, [orig_h=10.0.0.2, orig_p=20/tcp, resp_h=10.0.0.3, resp_p=6/tcp], Analyzer::ANALYZER_HTTP +APPLIED:, 1299491995.0, [orig_h=10.0.0.2, orig_p=20/tcp, resp_h=10.0.0.3, resp_p=6/tcp], Analyzer::ANALYZER_SSH +APPLIED:, 1299499195.0, [orig_h=10.0.0.2, orig_p=20/tcp, resp_h=10.0.0.3, resp_p=8/tcp], Analyzer::ANALYZER_DNS diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.actions.data_event/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.actions.data_event/out index d0816d8a94..45756e5323 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.actions.data_event/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.actions.data_event/out @@ -1,23 +1,23 @@ FILE_NEW -Cx92a0ym5R8, 0, 0 +BYYd1GSNX5c, 0, 0 FILE_BOF_BUFFER ^J0.26 | 201 MIME_TYPE text/plain -file_stream, Cx92a0ym5R8, 1500, ^J0.26 | 2012-08-24 15:10:04 -0700^J^J * Fixing update-changes, which could pick the wrong control file. (Robin Sommer)^J^J * Fixing GPG signing script. (Robin Sommer)^J^J0.25 | 2012-08-01 13:55:46 -0500^J^J * Fix configure script to exit with non-zero status on error (Jon Siwek)^J^J0.24 | 2012-07-05 12:50:43 -0700^J^J * Raise minimum required CMake version to 2.6.3 (Jon Siwek)^J^J * Adding script to delete old fully-merged branches. (Robin Sommer)^J^J0.23-2 | 2012-01-25 13:24:01 -0800^J^J * Fix a bro-cut error message. (Daniel Thayer)^J^J0.23 | 2012-01-11 12:16:11 -0800^J^J * Tweaks to release scripts, plus a new one for signing files.^J (Robin Sommer)^J^J0.22 | 2012-01-10 16:45:19 -0800^J^J * Tweaks for OpenBSD support. (Jon Siwek)^J^J * bro-cut extensions and fixes. (Robin Sommer)^J ^J - If no field names are given on the command line, we now pass through^J all fields. Adresses #657.^J^J - Removing some GNUism from awk script. Addresses #653.^J^J - Added option for time output in UTC. Addresses #668.^J^J - Added output field separator option -F. Addresses #649.^J^J - Fixing option -c: only some header lines were passed through^J rather than all. (Robin Sommer)^J^J * Fix parallel make portability. (Jon Siwek)^J^J0.21-9 | 2011-11-07 05:44:14 -0800^J^J * Fixing compiler warnings. Addresses #388. (Jon Siwek)^J^J0.21-2 | 2011-11-02 18:12:13 -0700^J^J * Fix for misnaming temp file in update-changes script. (Robin Sommer)^J^J0.21-1 | 2011-11-02 18:10:39 -0700^J^J * Little fix for make-relea -file_chunk, Cx92a0ym5R8, 1500, 0, ^J0.26 | 2012-08-24 15:10:04 -0700^J^J * Fixing update-changes, which could pick the wrong control file. (Robin Sommer)^J^J * Fixing GPG signing script. (Robin Sommer)^J^J0.25 | 2012-08-01 13:55:46 -0500^J^J * Fix configure script to exit with non-zero status on error (Jon Siwek)^J^J0.24 | 2012-07-05 12:50:43 -0700^J^J * Raise minimum required CMake version to 2.6.3 (Jon Siwek)^J^J * Adding script to delete old fully-merged branches. (Robin Sommer)^J^J0.23-2 | 2012-01-25 13:24:01 -0800^J^J * Fix a bro-cut error message. (Daniel Thayer)^J^J0.23 | 2012-01-11 12:16:11 -0800^J^J * Tweaks to release scripts, plus a new one for signing files.^J (Robin Sommer)^J^J0.22 | 2012-01-10 16:45:19 -0800^J^J * Tweaks for OpenBSD support. (Jon Siwek)^J^J * bro-cut extensions and fixes. (Robin Sommer)^J ^J - If no field names are given on the command line, we now pass through^J all fields. Adresses #657.^J^J - Removing some GNUism from awk script. Addresses #653.^J^J - Added option for time output in UTC. Addresses #668.^J^J - Added output field separator option -F. Addresses #649.^J^J - Fixing option -c: only some header lines were passed through^J rather than all. (Robin Sommer)^J^J * Fix parallel make portability. (Jon Siwek)^J^J0.21-9 | 2011-11-07 05:44:14 -0800^J^J * Fixing compiler warnings. Addresses #388. (Jon Siwek)^J^J0.21-2 | 2011-11-02 18:12:13 -0700^J^J * Fix for misnaming temp file in update-changes script. (Robin Sommer)^J^J0.21-1 | 2011-11-02 18:10:39 -0700^J^J * Little fix for make-relea -file_stream, Cx92a0ym5R8, 1024, se script, which could pick out the wrong^J tag. (Robin Sommer)^J^J0.21 | 2011-10-27 17:40:45 -0700^J^J * Fixing bro-cut's usage message and argument error handling. (Robin Sommer)^J^J * Bugfix in update-changes script. (Robin Sommer)^J^J * update-changes now ignores commits it did itself. (Robin Sommer)^J^J * Fix a bug in the update-changes script. (Robin Sommer)^J^J * bro-cut now always installs to $prefix/bin by `make install`. (Jon Siwek)^J^J * Options to adjust time format for bro-cut. (Robin Sommer)^J^J The default with -d is now ISO format. The new option "-D "^J specifies a custom strftime()-style format string. Alternatively,^J the environment variable BRO_CUT_TIMEFMT can set the format as^J well.^J^J * bro-cut now understands the field separator header. (Robin Sommer)^J^J * Renaming options -h/-H -> -c/-C, and doing some general cleanup.^J^J0.2 | 2011-10-25 19:53:57 -0700^J^J * Adding support for replacing version string in a setup.py. (Robin^J Sommer)^J^J * Change generated root cert DN indices f -file_chunk, Cx92a0ym5R8, 1024, 1500, se script, which could pick out the wrong^J tag. (Robin Sommer)^J^J0.21 | 2011-10-27 17:40:45 -0700^J^J * Fixing bro-cut's usage message and argument error handling. (Robin Sommer)^J^J * Bugfix in update-changes script. (Robin Sommer)^J^J * update-changes now ignores commits it did itself. (Robin Sommer)^J^J * Fix a bug in the update-changes script. (Robin Sommer)^J^J * bro-cut now always installs to $prefix/bin by `make install`. (Jon Siwek)^J^J * Options to adjust time format for bro-cut. (Robin Sommer)^J^J The default with -d is now ISO format. The new option "-D "^J specifies a custom strftime()-style format string. Alternatively,^J the environment variable BRO_CUT_TIMEFMT can set the format as^J well.^J^J * bro-cut now understands the field separator header. (Robin Sommer)^J^J * Renaming options -h/-H -> -c/-C, and doing some general cleanup.^J^J0.2 | 2011-10-25 19:53:57 -0700^J^J * Adding support for replacing version string in a setup.py. (Robin^J Sommer)^J^J * Change generated root cert DN indices f -file_stream, Cx92a0ym5R8, 476, ormat for RFC2253^J compliance. (Jon Siwek)^J^J * New tool devel-tools/check-release to run before making releases.^J (Robin Sommer)^J^J * devel-tools/update-changes gets a new option -a to amend to^J previous commit if possible. Default is now not to (used to be the^J opposite). (Robin Sommer)^J^J * Change Mozilla trust root generation to index certs by subject DN. (Jon Siwek)^J^J * Change distclean to only remove build dir. (Jon Siwek)^J^J * Make dist now cleans the -file_chunk, Cx92a0ym5R8, 476, 2524, ormat for RFC2253^J compliance. (Jon Siwek)^J^J * New tool devel-tools/check-release to run before making releases.^J (Robin Sommer)^J^J * devel-tools/update-changes gets a new option -a to amend to^J previous commit if possible. Default is now not to (used to be the^J opposite). (Robin Sommer)^J^J * Change Mozilla trust root generation to index certs by subject DN. (Jon Siwek)^J^J * Change distclean to only remove build dir. (Jon Siwek)^J^J * Make dist now cleans the -file_stream, Cx92a0ym5R8, 1024, copied source (Jon Siwek)^J^J * Small tweak to make-release for forced git-clean. (Jon Siwek)^J^J * Fix to not let updates scripts loose their executable permissions.^J (Robin Sommer)^J^J * devel-tools/update-changes now looks for a 'release' tag to^J idenfify the stable version, and 'beta' for the beta versions.^J (Robin Sommer).^J^J * Distribution cleanup. (Robin Sommer)^J^J * New script devel-tools/make-release to create source tar balls.^J (Robin Sommer)^J^J * Removing bdcat. With the new log format, this isn't very useful^J anymore. (Robin Sommer)^J^J * Adding script that shows all pending git fastpath commits. (Robin^J Sommer)^J^J * Script to measure CPU time by loading an increasing set of^J scripts. (Robin Sommer)^J^J * extract-conn script now deals wit *.gz files. (Robin Sommer)^J^J * Tiny update to output a valid CA list file for SSL cert^J validation. (Seth Hall)^J^J * Adding "install-aux" target. Addresses #622. (Jon Siwek)^J^J * Distribution cleanup. (Jon Siwek and Robin Sommer)^J^J * FindPCAP -file_chunk, Cx92a0ym5R8, 1024, 3000, copied source (Jon Siwek)^J^J * Small tweak to make-release for forced git-clean. (Jon Siwek)^J^J * Fix to not let updates scripts loose their executable permissions.^J (Robin Sommer)^J^J * devel-tools/update-changes now looks for a 'release' tag to^J idenfify the stable version, and 'beta' for the beta versions.^J (Robin Sommer).^J^J * Distribution cleanup. (Robin Sommer)^J^J * New script devel-tools/make-release to create source tar balls.^J (Robin Sommer)^J^J * Removing bdcat. With the new log format, this isn't very useful^J anymore. (Robin Sommer)^J^J * Adding script that shows all pending git fastpath commits. (Robin^J Sommer)^J^J * Script to measure CPU time by loading an increasing set of^J scripts. (Robin Sommer)^J^J * extract-conn script now deals wit *.gz files. (Robin Sommer)^J^J * Tiny update to output a valid CA list file for SSL cert^J validation. (Seth Hall)^J^J * Adding "install-aux" target. Addresses #622. (Jon Siwek)^J^J * Distribution cleanup. (Jon Siwek and Robin Sommer)^J^J * FindPCAP -file_stream, Cx92a0ym5R8, 476, now links against thread library when necessary (e.g.^J PF_RING's libpcap) (Jon Siwek)^J^J * Install binaries with an RPATH (Jon Siwek)^J^J * Workaround for FreeBSD CMake port missing debug flags (Jon Siwek)^J^J * Rewrite of the update-changes script. (Robin Sommer)^J^J0.1-1 | 2011-06-14 21:12:41 -0700^J^J * Add a script for generating Mozilla's CA list for the SSL analyzer.^J (Seth Hall)^J^J0.1 | 2011-04-01 16:28:22 -0700^J^J * Converting build process to CMake. (Jon Siwek)^J -file_chunk, Cx92a0ym5R8, 476, 4024, now links against thread library when necessary (e.g.^J PF_RING's libpcap) (Jon Siwek)^J^J * Install binaries with an RPATH (Jon Siwek)^J^J * Workaround for FreeBSD CMake port missing debug flags (Jon Siwek)^J^J * Rewrite of the update-changes script. (Robin Sommer)^J^J0.1-1 | 2011-06-14 21:12:41 -0700^J^J * Add a script for generating Mozilla's CA list for the SSL analyzer.^J (Seth Hall)^J^J0.1 | 2011-04-01 16:28:22 -0700^J^J * Converting build process to CMake. (Jon Siwek)^J -file_stream, Cx92a0ym5R8, 205, ^J * Removing cf/hf/ca-* from distribution. The README has a note where^J to find them now. (Robin Sommer)^J^J * General cleanup. (Robin Sommer)^J^J * Initial import of bro/aux from SVN r7088. (Jon Siwek)^J -file_chunk, Cx92a0ym5R8, 205, 4500, ^J * Removing cf/hf/ca-* from distribution. The README has a note where^J to find them now. (Robin Sommer)^J^J * General cleanup. (Robin Sommer)^J^J * Initial import of bro/aux from SVN r7088. (Jon Siwek)^J +file_stream, BYYd1GSNX5c, 1500, ^J0.26 | 2012-08-24 15:10:04 -0700^J^J * Fixing update-changes, which could pick the wrong control file. (Robin Sommer)^J^J * Fixing GPG signing script. (Robin Sommer)^J^J0.25 | 2012-08-01 13:55:46 -0500^J^J * Fix configure script to exit with non-zero status on error (Jon Siwek)^J^J0.24 | 2012-07-05 12:50:43 -0700^J^J * Raise minimum required CMake version to 2.6.3 (Jon Siwek)^J^J * Adding script to delete old fully-merged branches. (Robin Sommer)^J^J0.23-2 | 2012-01-25 13:24:01 -0800^J^J * Fix a bro-cut error message. (Daniel Thayer)^J^J0.23 | 2012-01-11 12:16:11 -0800^J^J * Tweaks to release scripts, plus a new one for signing files.^J (Robin Sommer)^J^J0.22 | 2012-01-10 16:45:19 -0800^J^J * Tweaks for OpenBSD support. (Jon Siwek)^J^J * bro-cut extensions and fixes. (Robin Sommer)^J ^J - If no field names are given on the command line, we now pass through^J all fields. Adresses #657.^J^J - Removing some GNUism from awk script. Addresses #653.^J^J - Added option for time output in UTC. Addresses #668.^J^J - Added output field separator option -F. Addresses #649.^J^J - Fixing option -c: only some header lines were passed through^J rather than all. (Robin Sommer)^J^J * Fix parallel make portability. (Jon Siwek)^J^J0.21-9 | 2011-11-07 05:44:14 -0800^J^J * Fixing compiler warnings. Addresses #388. (Jon Siwek)^J^J0.21-2 | 2011-11-02 18:12:13 -0700^J^J * Fix for misnaming temp file in update-changes script. (Robin Sommer)^J^J0.21-1 | 2011-11-02 18:10:39 -0700^J^J * Little fix for make-relea +file_chunk, BYYd1GSNX5c, 1500, 0, ^J0.26 | 2012-08-24 15:10:04 -0700^J^J * Fixing update-changes, which could pick the wrong control file. (Robin Sommer)^J^J * Fixing GPG signing script. (Robin Sommer)^J^J0.25 | 2012-08-01 13:55:46 -0500^J^J * Fix configure script to exit with non-zero status on error (Jon Siwek)^J^J0.24 | 2012-07-05 12:50:43 -0700^J^J * Raise minimum required CMake version to 2.6.3 (Jon Siwek)^J^J * Adding script to delete old fully-merged branches. (Robin Sommer)^J^J0.23-2 | 2012-01-25 13:24:01 -0800^J^J * Fix a bro-cut error message. (Daniel Thayer)^J^J0.23 | 2012-01-11 12:16:11 -0800^J^J * Tweaks to release scripts, plus a new one for signing files.^J (Robin Sommer)^J^J0.22 | 2012-01-10 16:45:19 -0800^J^J * Tweaks for OpenBSD support. (Jon Siwek)^J^J * bro-cut extensions and fixes. (Robin Sommer)^J ^J - If no field names are given on the command line, we now pass through^J all fields. Adresses #657.^J^J - Removing some GNUism from awk script. Addresses #653.^J^J - Added option for time output in UTC. Addresses #668.^J^J - Added output field separator option -F. Addresses #649.^J^J - Fixing option -c: only some header lines were passed through^J rather than all. (Robin Sommer)^J^J * Fix parallel make portability. (Jon Siwek)^J^J0.21-9 | 2011-11-07 05:44:14 -0800^J^J * Fixing compiler warnings. Addresses #388. (Jon Siwek)^J^J0.21-2 | 2011-11-02 18:12:13 -0700^J^J * Fix for misnaming temp file in update-changes script. (Robin Sommer)^J^J0.21-1 | 2011-11-02 18:10:39 -0700^J^J * Little fix for make-relea +file_stream, BYYd1GSNX5c, 1024, se script, which could pick out the wrong^J tag. (Robin Sommer)^J^J0.21 | 2011-10-27 17:40:45 -0700^J^J * Fixing bro-cut's usage message and argument error handling. (Robin Sommer)^J^J * Bugfix in update-changes script. (Robin Sommer)^J^J * update-changes now ignores commits it did itself. (Robin Sommer)^J^J * Fix a bug in the update-changes script. (Robin Sommer)^J^J * bro-cut now always installs to $prefix/bin by `make install`. (Jon Siwek)^J^J * Options to adjust time format for bro-cut. (Robin Sommer)^J^J The default with -d is now ISO format. The new option "-D "^J specifies a custom strftime()-style format string. Alternatively,^J the environment variable BRO_CUT_TIMEFMT can set the format as^J well.^J^J * bro-cut now understands the field separator header. (Robin Sommer)^J^J * Renaming options -h/-H -> -c/-C, and doing some general cleanup.^J^J0.2 | 2011-10-25 19:53:57 -0700^J^J * Adding support for replacing version string in a setup.py. (Robin^J Sommer)^J^J * Change generated root cert DN indices f +file_chunk, BYYd1GSNX5c, 1024, 1500, se script, which could pick out the wrong^J tag. (Robin Sommer)^J^J0.21 | 2011-10-27 17:40:45 -0700^J^J * Fixing bro-cut's usage message and argument error handling. (Robin Sommer)^J^J * Bugfix in update-changes script. (Robin Sommer)^J^J * update-changes now ignores commits it did itself. (Robin Sommer)^J^J * Fix a bug in the update-changes script. (Robin Sommer)^J^J * bro-cut now always installs to $prefix/bin by `make install`. (Jon Siwek)^J^J * Options to adjust time format for bro-cut. (Robin Sommer)^J^J The default with -d is now ISO format. The new option "-D "^J specifies a custom strftime()-style format string. Alternatively,^J the environment variable BRO_CUT_TIMEFMT can set the format as^J well.^J^J * bro-cut now understands the field separator header. (Robin Sommer)^J^J * Renaming options -h/-H -> -c/-C, and doing some general cleanup.^J^J0.2 | 2011-10-25 19:53:57 -0700^J^J * Adding support for replacing version string in a setup.py. (Robin^J Sommer)^J^J * Change generated root cert DN indices f +file_stream, BYYd1GSNX5c, 476, ormat for RFC2253^J compliance. (Jon Siwek)^J^J * New tool devel-tools/check-release to run before making releases.^J (Robin Sommer)^J^J * devel-tools/update-changes gets a new option -a to amend to^J previous commit if possible. Default is now not to (used to be the^J opposite). (Robin Sommer)^J^J * Change Mozilla trust root generation to index certs by subject DN. (Jon Siwek)^J^J * Change distclean to only remove build dir. (Jon Siwek)^J^J * Make dist now cleans the +file_chunk, BYYd1GSNX5c, 476, 2524, ormat for RFC2253^J compliance. (Jon Siwek)^J^J * New tool devel-tools/check-release to run before making releases.^J (Robin Sommer)^J^J * devel-tools/update-changes gets a new option -a to amend to^J previous commit if possible. Default is now not to (used to be the^J opposite). (Robin Sommer)^J^J * Change Mozilla trust root generation to index certs by subject DN. (Jon Siwek)^J^J * Change distclean to only remove build dir. (Jon Siwek)^J^J * Make dist now cleans the +file_stream, BYYd1GSNX5c, 1024, copied source (Jon Siwek)^J^J * Small tweak to make-release for forced git-clean. (Jon Siwek)^J^J * Fix to not let updates scripts loose their executable permissions.^J (Robin Sommer)^J^J * devel-tools/update-changes now looks for a 'release' tag to^J idenfify the stable version, and 'beta' for the beta versions.^J (Robin Sommer).^J^J * Distribution cleanup. (Robin Sommer)^J^J * New script devel-tools/make-release to create source tar balls.^J (Robin Sommer)^J^J * Removing bdcat. With the new log format, this isn't very useful^J anymore. (Robin Sommer)^J^J * Adding script that shows all pending git fastpath commits. (Robin^J Sommer)^J^J * Script to measure CPU time by loading an increasing set of^J scripts. (Robin Sommer)^J^J * extract-conn script now deals wit *.gz files. (Robin Sommer)^J^J * Tiny update to output a valid CA list file for SSL cert^J validation. (Seth Hall)^J^J * Adding "install-aux" target. Addresses #622. (Jon Siwek)^J^J * Distribution cleanup. (Jon Siwek and Robin Sommer)^J^J * FindPCAP +file_chunk, BYYd1GSNX5c, 1024, 3000, copied source (Jon Siwek)^J^J * Small tweak to make-release for forced git-clean. (Jon Siwek)^J^J * Fix to not let updates scripts loose their executable permissions.^J (Robin Sommer)^J^J * devel-tools/update-changes now looks for a 'release' tag to^J idenfify the stable version, and 'beta' for the beta versions.^J (Robin Sommer).^J^J * Distribution cleanup. (Robin Sommer)^J^J * New script devel-tools/make-release to create source tar balls.^J (Robin Sommer)^J^J * Removing bdcat. With the new log format, this isn't very useful^J anymore. (Robin Sommer)^J^J * Adding script that shows all pending git fastpath commits. (Robin^J Sommer)^J^J * Script to measure CPU time by loading an increasing set of^J scripts. (Robin Sommer)^J^J * extract-conn script now deals wit *.gz files. (Robin Sommer)^J^J * Tiny update to output a valid CA list file for SSL cert^J validation. (Seth Hall)^J^J * Adding "install-aux" target. Addresses #622. (Jon Siwek)^J^J * Distribution cleanup. (Jon Siwek and Robin Sommer)^J^J * FindPCAP +file_stream, BYYd1GSNX5c, 476, now links against thread library when necessary (e.g.^J PF_RING's libpcap) (Jon Siwek)^J^J * Install binaries with an RPATH (Jon Siwek)^J^J * Workaround for FreeBSD CMake port missing debug flags (Jon Siwek)^J^J * Rewrite of the update-changes script. (Robin Sommer)^J^J0.1-1 | 2011-06-14 21:12:41 -0700^J^J * Add a script for generating Mozilla's CA list for the SSL analyzer.^J (Seth Hall)^J^J0.1 | 2011-04-01 16:28:22 -0700^J^J * Converting build process to CMake. (Jon Siwek)^J +file_chunk, BYYd1GSNX5c, 476, 4024, now links against thread library when necessary (e.g.^J PF_RING's libpcap) (Jon Siwek)^J^J * Install binaries with an RPATH (Jon Siwek)^J^J * Workaround for FreeBSD CMake port missing debug flags (Jon Siwek)^J^J * Rewrite of the update-changes script. (Robin Sommer)^J^J0.1-1 | 2011-06-14 21:12:41 -0700^J^J * Add a script for generating Mozilla's CA list for the SSL analyzer.^J (Seth Hall)^J^J0.1 | 2011-04-01 16:28:22 -0700^J^J * Converting build process to CMake. (Jon Siwek)^J +file_stream, BYYd1GSNX5c, 205, ^J * Removing cf/hf/ca-* from distribution. The README has a note where^J to find them now. (Robin Sommer)^J^J * General cleanup. (Robin Sommer)^J^J * Initial import of bro/aux from SVN r7088. (Jon Siwek)^J +file_chunk, BYYd1GSNX5c, 205, 4500, ^J * Removing cf/hf/ca-* from distribution. The README has a note where^J to find them now. (Robin Sommer)^J^J * General cleanup. (Robin Sommer)^J^J * Initial import of bro/aux from SVN r7088. (Jon Siwek)^J FILE_STATE_REMOVE -Cx92a0ym5R8, 4705, 0 +BYYd1GSNX5c, 4705, 0 [orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp] total bytes: 4705 source: HTTP diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.postpone_timeout/bro..stdout b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.postpone_timeout/bro..stdout index 9cb4b5cc68..5ee716da85 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.postpone_timeout/bro..stdout +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.postpone_timeout/bro..stdout @@ -1,20 +1,20 @@ FILE_NEW -oDwT1BbzjM1, 0, 0 +Cvu8OAp0WEd, 0, 0 MIME_TYPE application/x-dosexec FILE_STATE_REMOVE -oDwT1BbzjM1, 1022920, 0 +Cvu8OAp0WEd, 1022920, 0 [orig_h=192.168.72.14, orig_p=3254/tcp, resp_h=65.54.95.206, resp_p=80/tcp] total bytes: 1022920 source: HTTP FILE_NEW -oDwT1BbzjM1, 0, 0 +Cvu8OAp0WEd, 0, 0 MIME_TYPE application/octet-stream FILE_TIMEOUT FILE_TIMEOUT FILE_STATE_REMOVE -oDwT1BbzjM1, 206024, 0 +Cvu8OAp0WEd, 206024, 0 [orig_h=192.168.72.14, orig_p=3257/tcp, resp_h=65.54.95.14, resp_p=80/tcp] total bytes: 1022920 source: HTTP diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.remove_action/get.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.remove_action/get.out index 846363961e..ab736c80db 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.remove_action/get.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.remove_action/get.out @@ -1,11 +1,11 @@ FILE_NEW -Cx92a0ym5R8, 0, 0 +BYYd1GSNX5c, 0, 0 FILE_BOF_BUFFER ^J0.26 | 201 MIME_TYPE text/plain FILE_STATE_REMOVE -Cx92a0ym5R8, 4705, 0 +BYYd1GSNX5c, 4705, 0 [orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp] total bytes: 4705 source: HTTP diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.stop/get.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.stop/get.out index 6000f36f85..006c66ebe1 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.stop/get.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.stop/get.out @@ -1,5 +1,5 @@ FILE_NEW -Cx92a0ym5R8, 0, 0 +BYYd1GSNX5c, 0, 0 FILE_BOF_BUFFER ^J0.26 | 201 MIME_TYPE diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out index 2e1907c91c..a24c711b36 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.ftp/out @@ -1,11 +1,11 @@ FILE_NEW -sidhzrR4IT8, 0, 0 +5LcdtqrLA97, 0, 0 FILE_BOF_BUFFER The Nationa MIME_TYPE text/x-pascal FILE_STATE_REMOVE -sidhzrR4IT8, 16557, 0 +5LcdtqrLA97, 16557, 0 [orig_h=141.142.228.5, orig_p=50737/tcp, resp_h=141.142.192.162, resp_p=38141/tcp] source: FTP_DATA MD5: 7192a8075196267203adb3dfaa5c908d diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/Cx92a0ym5R8-file b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/1-file similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/Cx92a0ym5R8-file rename to testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/1-file diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/kg59rqyYxN-file b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/2-file similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/kg59rqyYxN-file rename to testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/2-file diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get-gzip.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get-gzip.out index c425a7301f..20474cab30 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get-gzip.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get-gzip.out @@ -1,11 +1,11 @@ FILE_NEW -kg59rqyYxN, 0, 0 +FBfDYB0kA49, 0, 0 FILE_BOF_BUFFER {^J "origin MIME_TYPE text/plain FILE_STATE_REMOVE -kg59rqyYxN, 197, 0 +FBfDYB0kA49, 197, 0 [orig_h=141.142.228.5, orig_p=50153/tcp, resp_h=54.243.118.187, resp_p=80/tcp] source: HTTP MD5: 5baba7eea57bc8a42a92c817ed566d72 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get.out index ebac8b624e..1668467841 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.get/get.out @@ -1,11 +1,11 @@ FILE_NEW -Cx92a0ym5R8, 0, 0 +BYYd1GSNX5c, 0, 0 FILE_BOF_BUFFER ^J0.26 | 201 MIME_TYPE text/plain FILE_STATE_REMOVE -Cx92a0ym5R8, 4705, 0 +BYYd1GSNX5c, 4705, 0 [orig_h=141.142.228.5, orig_p=59856/tcp, resp_h=192.150.187.43, resp_p=80/tcp] total bytes: 4705 source: HTTP diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.out index 02435aaca7..50bacac717 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.out @@ -1,10 +1,10 @@ FILE_NEW -7gZBKVUgy4l, 0, 0 +1QXxzNpRT3h, 0, 0 MIME_TYPE application/pdf FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE -7gZBKVUgy4l, 555523, 0 +1QXxzNpRT3h, 555523, 0 [orig_h=10.101.84.70, orig_p=10978/tcp, resp_h=129.174.93.161, resp_p=80/tcp] [orig_h=10.101.84.70, orig_p=10977/tcp, resp_h=129.174.93.161, resp_p=80/tcp] total bytes: 555523 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.size b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.size index 13d0c3c958..49f10feff1 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.size +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/a.size @@ -1 +1 @@ -555523 7gZBKVUgy4l-file0 +555523 file-0 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.out index 8ea01332c8..5b892c7e9a 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.out @@ -1,19 +1,19 @@ FILE_NEW -oDwT1BbzjM1, 0, 0 +Cvu8OAp0WEd, 0, 0 MIME_TYPE application/x-dosexec FILE_STATE_REMOVE -oDwT1BbzjM1, 1022920, 0 +Cvu8OAp0WEd, 1022920, 0 [orig_h=192.168.72.14, orig_p=3254/tcp, resp_h=65.54.95.206, resp_p=80/tcp] total bytes: 1022920 source: HTTP FILE_NEW -oDwT1BbzjM1, 0, 0 +Cvu8OAp0WEd, 0, 0 MIME_TYPE application/octet-stream FILE_TIMEOUT FILE_STATE_REMOVE -oDwT1BbzjM1, 206024, 0 +Cvu8OAp0WEd, 206024, 0 [orig_h=192.168.72.14, orig_p=3257/tcp, resp_h=65.54.95.14, resp_p=80/tcp] total bytes: 1022920 source: HTTP diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.size b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.size index c1c1d71db7..5066aeab6d 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.size +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/b.size @@ -1 +1 @@ -1022920 oDwT1BbzjM1-file0 +1022920 file-0 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.out index 1ad4f52f36..886abee0f2 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.out @@ -1,10 +1,10 @@ FILE_NEW -uHS14uhRKGe, 0, 0 +me4WAjZH0Ik, 0, 0 MIME_TYPE application/octet-stream FILE_OVER_NEW_CONNECTION FILE_STATE_REMOVE -uHS14uhRKGe, 498702, 0 +me4WAjZH0Ik, 498702, 0 [orig_h=10.45.179.94, orig_p=19950/tcp, resp_h=129.174.93.170, resp_p=80/tcp] [orig_h=10.45.179.94, orig_p=19953/tcp, resp_h=129.174.93.170, resp_p=80/tcp] total bytes: 498668 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.size b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.size index da0f4d480c..e38aaa1e25 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.size +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.partial-content/c.size @@ -1 +1 @@ -498668 uHS14uhRKGe-file0 +498668 file-0 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/aFQKI8SPOL2-file b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/1-file similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/aFQKI8SPOL2-file rename to testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/1-file diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/CCU3vUEr06l-file b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/2-file similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/CCU3vUEr06l-file rename to testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/2-file diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/HCzA0dVwDPj-file b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/3-file similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/HCzA0dVwDPj-file rename to testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/3-file diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/a1Zu1fteVEf-file b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/4-file similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/a1Zu1fteVEf-file rename to testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/4-file diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/xXlF7wFdsR-file b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/5-file similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/xXlF7wFdsR-file rename to testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/5-file diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/out index 67d7c5d555..fb045a346c 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.pipeline/out @@ -1,37 +1,37 @@ FILE_NEW -aFQKI8SPOL2, 0, 0 +FiqZGsUZjXk, 0, 0 FILE_BOF_BUFFER /*^J******** MIME_TYPE text/plain FILE_STATE_REMOVE -aFQKI8SPOL2, 2675, 0 +FiqZGsUZjXk, 2675, 0 [orig_h=192.168.1.104, orig_p=1673/tcp, resp_h=63.245.209.11, resp_p=80/tcp] source: HTTP MD5: b932c3310ce47e158d1a5a42e0b01279 SHA1: 0e42ae17eea9b074981bd3a34535ad3a22d02706 SHA256: 5b037a2c5e36f56e63a3012c73e46a04b27741d8ff8f8b62c832fb681fc60f42 FILE_NEW -CCU3vUEr06l, 0, 0 +GU8RrggV4f5, 0, 0 FILE_BOF_BUFFER //-- Google MIME_TYPE text/plain FILE_STATE_REMOVE -CCU3vUEr06l, 21421, 0 +GU8RrggV4f5, 21421, 0 [orig_h=192.168.1.104, orig_p=1673/tcp, resp_h=63.245.209.11, resp_p=80/tcp] source: HTTP MD5: e732f7bf1d7cb4eedcb1661697d7bc8c SHA1: 8f241117afaa8ca5f41dc059e66d75c283dcc983 SHA256: 6a509fd05aa7c8fa05080198894bb19e638554ffcee0e0b3d7bc8ff54afee1da FILE_NEW -HCzA0dVwDPj, 0, 0 +0afVj9ZG1J9, 0, 0 FILE_BOF_BUFFER GIF89a^D\0^D\0\xb3 MIME_TYPE image/gif FILE_STATE_REMOVE -HCzA0dVwDPj, 94, 0 +0afVj9ZG1J9, 94, 0 [orig_h=192.168.1.104, orig_p=1673/tcp, resp_h=63.245.209.11, resp_p=80/tcp] total bytes: 94 source: HTTP @@ -39,13 +39,13 @@ MD5: d903de7e30db1691d3130ba5eae6b9a7 SHA1: 81f5f056ce5e97d940854bb0c48017b45dd9f15e SHA256: 6fb22aa9d780ea63bd7a2e12b92b16fcbf1c4874f1d3e11309a5ba984433c315 FILE_NEW -a1Zu1fteVEf, 0, 0 +oMJlhgZt8Nh, 0, 0 FILE_BOF_BUFFER \x89PNG^M^J^Z^J\0\0\0 MIME_TYPE image/png FILE_STATE_REMOVE -a1Zu1fteVEf, 2349, 0 +oMJlhgZt8Nh, 2349, 0 [orig_h=192.168.1.104, orig_p=1673/tcp, resp_h=63.245.209.11, resp_p=80/tcp] total bytes: 2349 source: HTTP @@ -53,13 +53,13 @@ MD5: e0029eea80812e9a8e57b8d05d52938a SHA1: 560eab5a0177246827a94042dd103916d8765ac7 SHA256: e0b4500c1fd1d675da4137461cbe64d3c8489f4180d194e47683b20e7fb876f4 FILE_NEW -xXlF7wFdsR, 0, 0 +KajlXqmipId, 0, 0 FILE_BOF_BUFFER \x89PNG^M^J^Z^J\0\0\0 MIME_TYPE image/png FILE_STATE_REMOVE -xXlF7wFdsR, 27579, 0 +KajlXqmipId, 27579, 0 [orig_h=192.168.1.104, orig_p=1673/tcp, resp_h=63.245.209.11, resp_p=80/tcp] total bytes: 27579 source: HTTP diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/v5HLI7MxPQh-file b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/1-file similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/v5HLI7MxPQh-file rename to testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/1-file diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/PZS1XGHkIf1-file b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/2-file similarity index 100% rename from testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/PZS1XGHkIf1-file rename to testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/2-file diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/out index 0eecaf994a..72868299f6 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.http.post/out @@ -1,11 +1,11 @@ FILE_NEW -v5HLI7MxPQh, 0, 0 +1V1QkS1JR02, 0, 0 FILE_BOF_BUFFER hello world MIME_TYPE text/plain FILE_STATE_REMOVE -v5HLI7MxPQh, 11, 0 +1V1QkS1JR02, 11, 0 [orig_h=141.142.228.5, orig_p=53595/tcp, resp_h=54.243.55.129, resp_p=80/tcp] total bytes: 11 source: HTTP @@ -13,13 +13,13 @@ MD5: 5eb63bbbe01eeed093cb22bb8f5acdc3 SHA1: 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed SHA256: b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 FILE_NEW -PZS1XGHkIf1, 0, 0 +IYuq13QwRPh, 0, 0 FILE_BOF_BUFFER {^J "origin MIME_TYPE text/plain FILE_STATE_REMOVE -PZS1XGHkIf1, 366, 0 +IYuq13QwRPh, 366, 0 [orig_h=141.142.228.5, orig_p=53595/tcp, resp_h=54.243.55.129, resp_p=80/tcp] total bytes: 366 source: HTTP diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.irc/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.irc/out index 03b0c9e932..4d869319f7 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.irc/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.irc/out @@ -1,11 +1,11 @@ FILE_NEW -wqKMAamJVSb, 0, 0 +A3OSdqG9zvk, 0, 0 FILE_BOF_BUFFER PK^C^D^T\0\0\0^H\0\xae MIME_TYPE application/zip FILE_STATE_REMOVE -wqKMAamJVSb, 42208, 0 +A3OSdqG9zvk, 42208, 0 [orig_h=192.168.1.77, orig_p=57655/tcp, resp_h=209.197.168.151, resp_p=1024/tcp] source: IRC_DATA MD5: 8c0803242f549c2780cb88b9a9215c65 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/file_analysis.log b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/file_analysis.log index 86f132470b..3dc2106d85 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/file_analysis.log +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.logging/file_analysis.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path file_analysis -#open 2013-04-23-15-41-01 +#open 2013-05-17-00-55-16 #fields id parent_id source is_orig last_active seen_bytes total_bytes missing_bytes overflow_bytes timeout_interval bof_buffer_size mime_type timedout conn_uids analyzers extracted_files md5 sha1 sha256 #types string string string bool time count count count count interval count string bool table[string] table[enum] table[string] string string string -Cx92a0ym5R8 - HTTP F 1362692527.009775 4705 4705 0 0 120.000000 1024 text/plain F UWkUyAuUGXf FileAnalysis::ANALYZER_SHA1,FileAnalysis::ANALYZER_EXTRACT,FileAnalysis::ANALYZER_DATA_EVENT,FileAnalysis::ANALYZER_MD5,FileAnalysis::ANALYZER_SHA256 Cx92a0ym5R8-file 397168fd09991a0e712254df7bc639ac 1dd7ac0398df6cbc0696445a91ec681facf4dc47 4e7c7ef0984119447e743e3ec77e1de52713e345cde03fe7df753a35849bed18 -#close 2013-04-23-15-41-01 +BYYd1GSNX5c - HTTP F 1362692527.009775 4705 4705 0 0 120.000000 1024 text/plain F UWkUyAuUGXf FileAnalysis::ANALYZER_SHA1,FileAnalysis::ANALYZER_EXTRACT,FileAnalysis::ANALYZER_DATA_EVENT,FileAnalysis::ANALYZER_MD5,FileAnalysis::ANALYZER_SHA256 BYYd1GSNX5c-file 397168fd09991a0e712254df7bc639ac 1dd7ac0398df6cbc0696445a91ec681facf4dc47 4e7c7ef0984119447e743e3ec77e1de52713e345cde03fe7df753a35849bed18 +#close 2013-05-17-00-55-16 diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.smtp/out b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.smtp/out index 83dc60f18e..eeb138cba7 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.smtp/out +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.smtp/out @@ -1,37 +1,37 @@ FILE_NEW -cwR7l6Zctxb, 0, 0 +mR3f2AAKo11, 0, 0 FILE_BOF_BUFFER Hello^M^J^M^J ^M MIME_TYPE text/plain FILE_STATE_REMOVE -cwR7l6Zctxb, 79, 0 +mR3f2AAKo11, 79, 0 [orig_h=10.10.1.4, orig_p=1470/tcp, resp_h=74.53.140.153, resp_p=25/tcp] source: SMTP MD5: 92bca2e6cdcde73647125da7dccbdd07 SHA1: b7e497be8a9f5e2c4b6980fceb015360f98f4a13 SHA256: 785a8a044d1454ec88837108f443bbb30cc4f529393ffd57118261036bfe59f5 FILE_NEW -ZAOEQmRyxv1, 0, 0 +svBvmJEWan2, 0, 0 FILE_BOF_BUFFER - - - - - - - (empty) - - - - ftp-item-Rqjkzoroau4-0.dat -1329843193.984222 k6kgXLOoSKl 141.142.220.235 59378 199.233.217.249 56667 - - - - - - - (empty) - - - - ftp-item-BTsa70Ua9x7-1.dat +1329843193.984222 arKYeMETxOg 141.142.220.235 37604 199.233.217.249 56666 - - - - - - - (empty) - - - - ftp-item-pVhQhhFsB2b-0.dat +1329843193.984222 k6kgXLOoSKl 141.142.220.235 59378 199.233.217.249 56667 - - - - - - - (empty) - - - - ftp-item-fFCPkV1sEsc-1.dat 1329843179.926563 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. (empty) - - - - - 1329843194.040188 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,131,46 - - 200 PORT command successful. (empty) F 199.233.217.249 141.142.220.235 33582 - 1329843194.095782 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test LIST - - - 226 Transfer complete. (empty) - - - - - 1329843197.672179 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test PORT 141,142,220,235,147,203 - - 200 PORT command successful. (empty) F 199.233.217.249 141.142.220.235 37835 - -1329843199.968212 nQcgTWjvg4c 199.233.217.249 61920 141.142.220.235 33582 - - - - - - - (empty) - - - - ftp-item-VLQvJybrm38-2.dat +1329843199.968212 nQcgTWjvg4c 199.233.217.249 61920 141.142.220.235 33582 - - - - - - - (empty) - - - - ftp-item-g3zS3MuJFh-2.dat 1329843197.727769 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain 77 226 Transfer complete. (empty) - - - - - -1329843200.079930 j4u32Pc5bif 199.233.217.249 61918 141.142.220.235 37835 - - - - - - - (empty) - - - - ftp-item-zrfwSs9K1yk-3.dat -#close 2013-04-12-16-32-25 +1329843200.079930 j4u32Pc5bif 199.233.217.249 61918 141.142.220.235 37835 - - - - - - - (empty) - - - - ftp-item-lMf4UWRkEO5-3.dat +#close 2013-05-18-00-48-19 diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item-BFymS6bFgT3-0.dat b/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item.dat similarity index 100% rename from testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item-BFymS6bFgT3-0.dat rename to testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item.dat diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log index 789896072f..9c891f4c74 100644 --- a/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path http -#open 2013-03-22-14-38-28 +#open 2013-05-17-23-19-09 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file #types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string string -1128727435.634189 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - text/html - http-item-BFymS6bFgT3-0.dat -#close 2013-03-22-14-38-28 +1128727435.634189 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - text/html - http-item-54zlJFqn0x6-0.dat +#close 2013-05-17-23-19-09 diff --git a/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc-dcc-item-wqKMAamJVSb-0.dat b/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc-dcc-item.dat similarity index 100% rename from testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc-dcc-item-wqKMAamJVSb-0.dat rename to testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc-dcc-item.dat diff --git a/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log b/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log index 4e70587ff0..2d37e2626f 100644 --- a/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log +++ b/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log @@ -3,11 +3,11 @@ #empty_field (empty) #unset_field - #path irc -#open 2013-03-27-18-49-16 +#open 2013-05-17-23-19-21 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p nick user command value addl dcc_file_name dcc_file_size dcc_mime_type extraction_file #types time string addr port addr port string string string string string string count string string 1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 - - NICK bloed - - - - - 1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed - USER sdkfje sdkfje Montreal.QC.CA.Undernet.org dkdkrwq - - - - 1311189174.474127 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje JOIN #easymovies (empty) - - - - -1311189316.326025 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje DCC #easymovies (empty) ladyvampress-default(2011-07-07)-OS.zip 42208 FAKE_MIME irc-dcc-item-wqKMAamJVSb-0.dat -#close 2013-03-27-18-49-16 +1311189316.326025 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje DCC #easymovies (empty) ladyvampress-default(2011-07-07)-OS.zip 42208 FAKE_MIME irc-dcc-item-A3OSdqG9zvk-0.dat +#close 2013-05-17-23-19-21 diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity-cwR7l6Zctxb-0.dat b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity-0.dat similarity index 100% rename from testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity-cwR7l6Zctxb-0.dat rename to testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity-0.dat diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity-Ltd7QO7jEv3-1.dat b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity-1.dat similarity index 100% rename from testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity-Ltd7QO7jEv3-1.dat rename to testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity-1.dat diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log index 0051ddba61..039af42a2b 100644 --- a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log +++ b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log @@ -3,10 +3,10 @@ #empty_field (empty) #unset_field - #path smtp_entities -#open 2013-03-26-20-43-14 +#open 2013-05-17-23-19-41 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth filename content_len mime_type md5 extraction_file excerpt #types time string addr port addr port count string count string string string string -1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 79 text/plain - smtp-entity-cwR7l6Zctxb-0.dat (empty) +1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 79 text/plain - smtp-entity-mR3f2AAKo11-0.dat (empty) 1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 1918 text/html - - (empty) -1254722770.692804 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 NEWS.txt 10823 text/plain - smtp-entity-Ltd7QO7jEv3-1.dat (empty) -#close 2013-03-26-20-43-14 +1254722770.692804 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 NEWS.txt 10823 text/plain - smtp-entity-ZNp0KBSLByc-1.dat (empty) +#close 2013-05-17-23-19-41 diff --git a/testing/btest/Baseline/scripts.base.protocols.syslog.trace/syslog.log b/testing/btest/Baseline/scripts.base.protocols.syslog.trace/syslog.log new file mode 100644 index 0000000000..df53ef42f6 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.syslog.trace/syslog.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path syslog +#open 2013-04-05-20-06-27 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto facility severity message +#types time string addr port addr port enum string string string +1365191811.424495 UWkUyAuUGXf 127.0.0.1 57067 127.0.0.1 514 udp LOCAL0 NOTICE Apr 5 12:56:51 robin: Hello, syslog!\x00 +#close 2013-04-05-20-06-27 diff --git a/testing/btest/Baseline/signatures.dpd/dpd-ipv4.out b/testing/btest/Baseline/signatures.dpd/dpd-ipv4.out index abb41f330c..d9f5126aab 100644 --- a/testing/btest/Baseline/signatures.dpd/dpd-ipv4.out +++ b/testing/btest/Baseline/signatures.dpd/dpd-ipv4.out @@ -1,6 +1,4 @@ -dpd_config, { - -} +|Analyzer::all_registered_ports()|, 0 signature_match [orig_h=141.142.220.235, orig_p=50003/tcp, resp_h=199.233.217.249, resp_p=21/tcp] - matched my_ftp_client ftp_reply 199.233.217.249:21 - 220 ftp.NetBSD.org FTP server (NetBSD-ftpd 20100320) ready. ftp_request 141.142.220.235:50003 - USER anonymous diff --git a/testing/btest/Baseline/signatures.dpd/dpd-ipv6.out b/testing/btest/Baseline/signatures.dpd/dpd-ipv6.out index a2227ee890..f26ff25291 100644 --- a/testing/btest/Baseline/signatures.dpd/dpd-ipv6.out +++ b/testing/btest/Baseline/signatures.dpd/dpd-ipv6.out @@ -1,6 +1,4 @@ -dpd_config, { - -} +|Analyzer::all_registered_ports()|, 0 signature_match [orig_h=2001:470:1f11:81f:c999:d94:aa7c:2e3e, orig_p=49185/tcp, resp_h=2001:470:4867:99::21, resp_p=21/tcp] - matched my_ftp_client ftp_reply [2001:470:4867:99::21]:21 - 220 ftp.NetBSD.org FTP server (NetBSD-ftpd 20100320) ready. ftp_request [2001:470:1f11:81f:c999:d94:aa7c:2e3e]:49185 - USER anonymous diff --git a/testing/btest/Baseline/signatures.dpd/nosig-ipv4.out b/testing/btest/Baseline/signatures.dpd/nosig-ipv4.out index 55566505d8..1b3be8e060 100644 --- a/testing/btest/Baseline/signatures.dpd/nosig-ipv4.out +++ b/testing/btest/Baseline/signatures.dpd/nosig-ipv4.out @@ -1,3 +1 @@ -dpd_config, { - -} +|Analyzer::all_registered_ports()|, 0 diff --git a/testing/btest/Baseline/signatures.dpd/nosig-ipv6.out b/testing/btest/Baseline/signatures.dpd/nosig-ipv6.out index 55566505d8..1b3be8e060 100644 --- a/testing/btest/Baseline/signatures.dpd/nosig-ipv6.out +++ b/testing/btest/Baseline/signatures.dpd/nosig-ipv6.out @@ -1,3 +1 @@ -dpd_config, { - -} +|Analyzer::all_registered_ports()|, 0 diff --git a/testing/btest/Traces/ssh-on-port-80.trace b/testing/btest/Traces/ssh-on-port-80.trace new file mode 100644 index 0000000000..6c0ae22e30 Binary files /dev/null and b/testing/btest/Traces/ssh-on-port-80.trace differ diff --git a/testing/btest/Traces/syslog-single-udp.trace b/testing/btest/Traces/syslog-single-udp.trace new file mode 100644 index 0000000000..9e1505a38a Binary files /dev/null and b/testing/btest/Traces/syslog-single-udp.trace differ diff --git a/testing/btest/bifs/analyzer_name.bro b/testing/btest/bifs/analyzer_name.bro index 9297d2ca27..266d1c159f 100644 --- a/testing/btest/bifs/analyzer_name.bro +++ b/testing/btest/bifs/analyzer_name.bro @@ -4,6 +4,6 @@ event bro_init() { - local a = 1; - print analyzer_name(a); + local a = Analyzer::ANALYZER_PIA_TCP; + print Analyzer::name(a); } diff --git a/testing/btest/btest.cfg b/testing/btest/btest.cfg index 4f888f710b..4a13833094 100644 --- a/testing/btest/btest.cfg +++ b/testing/btest/btest.cfg @@ -12,7 +12,7 @@ BRO_SEED_FILE=%(testbase)s/random.seed TZ=UTC LC_ALL=C BTEST_PATH=%(testbase)s/../../aux/btest -PATH=%(testbase)s/../../build/src:%(testbase)s/../scripts:%(testbase)s/../../aux/btest:%(default_path)s +PATH=%(testbase)s/../../build/src:%(testbase)s/../scripts:%(testbase)s/../../aux/btest:%(testbase)s/../../aux/bro-aux/bro-cut:%(default_path)s TRACES=%(testbase)s/Traces SCRIPTS=%(testbase)s/../scripts DIST=%(testbase)s/../.. diff --git a/testing/btest/core/tunnels/gtp/non_recursive.test b/testing/btest/core/tunnels/gtp/non_recursive.test index d44bfce79d..0b03c0d6ae 100644 --- a/testing/btest/core/tunnels/gtp/non_recursive.test +++ b/testing/btest/core/tunnels/gtp/non_recursive.test @@ -5,7 +5,7 @@ # So if we find inside a GTP tunnel anohter IP/UDP packet with port 2152, # it is just a UDP packet, but not another GTP tunnel. -event protocol_violation(c: connection, atype: count, aid: count, reason: string) +event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count, reason: string) { print "protocol_violation", c$id, reason; } diff --git a/testing/btest/core/tunnels/teredo-known-services.test b/testing/btest/core/tunnels/teredo-known-services.test index 862930758f..d03ef2ab71 100644 --- a/testing/btest/core/tunnels/teredo-known-services.test +++ b/testing/btest/core/tunnels/teredo-known-services.test @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro -b -r $TRACES/tunnels/false-teredo.pcap base/frameworks/dpd protocols/conn/known-services Tunnel::delay_teredo_confirmation=T "Site::local_nets+={192.168.1.0/24}" +# @TEST-EXEC: bro -r $TRACES/tunnels/false-teredo.pcap base/frameworks/dpd protocols/conn/known-services Tunnel::delay_teredo_confirmation=T "Site::local_nets+={192.168.1.0/24}" # @TEST-EXEC: test ! -e known_services.log # @TEST-EXEC: bro -b -r $TRACES/tunnels/false-teredo.pcap base/frameworks/dpd protocols/conn/known-services Tunnel::delay_teredo_confirmation=F "Site::local_nets+={192.168.1.0/24}" # @TEST-EXEC: btest-diff known_services.log diff --git a/testing/btest/language/at-dir.bro b/testing/btest/language/at-dir.bro new file mode 100644 index 0000000000..b826e3a5da --- /dev/null +++ b/testing/btest/language/at-dir.bro @@ -0,0 +1,10 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out +# @TEST-EXEC: bro -b ./pathtest.bro >out2 +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out2 + +print @DIR; + +@TEST-START-FILE pathtest.bro +print @DIR; +@TEST-END-FILE diff --git a/testing/btest/language/at-filename.bro b/testing/btest/language/at-filename.bro new file mode 100644 index 0000000000..83e4e968f3 --- /dev/null +++ b/testing/btest/language/at-filename.bro @@ -0,0 +1,4 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +print @FILENAME; diff --git a/testing/btest/language/named-record-ctors.bro b/testing/btest/language/named-record-ctors.bro new file mode 100644 index 0000000000..7f04b9d4b0 --- /dev/null +++ b/testing/btest/language/named-record-ctors.bro @@ -0,0 +1,12 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +type MyRec: record { + min: count &optional; + max: count; +}; + +local myrec: MyRec = MyRec($max=2); +print myrec; +myrec = MyRec($min=7, $max=42); +print myrec; diff --git a/testing/btest/language/named-set-ctors.bro b/testing/btest/language/named-set-ctors.bro new file mode 100644 index 0000000000..083937c42e --- /dev/null +++ b/testing/btest/language/named-set-ctors.bro @@ -0,0 +1,19 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +type MyRec: record { + min: count &optional; + max: count; +}; + +type FooSet: set[count]; +type FooSetRec: set[MyRec]; +type FooSetComp: set[string, count]; + +global myset: FooSet = FooSet(1, 5, 3); +global mysetrec: FooSetRec = FooSetRec([$max=5], [$max=2]); +global mysetcomp: FooSetComp = FooSetComp(["test", 1], ["cool", 2]); + +print myset; +print mysetrec; +print mysetcomp; diff --git a/testing/btest/language/named-table-ctors.bro b/testing/btest/language/named-table-ctors.bro new file mode 100644 index 0000000000..83500488f1 --- /dev/null +++ b/testing/btest/language/named-table-ctors.bro @@ -0,0 +1,24 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +type MyRec: record { + min: count &optional; + max: count; +}; + +type FooTable: table[count] of string; +type FooTableRec: table[MyRec] of string; +type FooTableComp: table[string, count] of string; +type FooTableY: table[string] of double; + +global mytable: FooTable = FooTable([1] = "one", [5] = "five", [3] = "three"); +global mytablerec: FooTableRec = FooTableRec([[$max=5]] = "max5", [[$max=2]] = "max2"); +global mytablecomp: FooTableComp = FooTableComp(["test", 1] = "test1", ["cool", +2] = "cool2"); +global mytabley: FooTableY = FooTableY(["one"] = 1, ["two"] = 2, ["three"] = 3) &default=0; + +print mytable; +print mytablerec; +print mytablecomp; +print mytabley; +print mytabley["test"]; diff --git a/testing/btest/language/named-vector-ctors.bro b/testing/btest/language/named-vector-ctors.bro new file mode 100644 index 0000000000..1e0e1e9e55 --- /dev/null +++ b/testing/btest/language/named-vector-ctors.bro @@ -0,0 +1,19 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +type MyRec: record { + min: count &optional; + max: count; +}; + +type FooVector: vector of string; +type FooVectorD: vector of double; +type FooVectorRec: vector of MyRec; + +global myvec: FooVector = FooVector("one", "two", "three"); +global myvecd: FooVectorD = FooVectorD(1, 2, 3); +global myvecrec: FooVectorRec = FooVectorRec([$max=1], [$max=2], [$max=3]); + +print myvec; +print myvecd; +print myvecrec; diff --git a/testing/btest/scripts/base/frameworks/analyzer/disable-analyzer.bro b/testing/btest/scripts/base/frameworks/analyzer/disable-analyzer.bro new file mode 100644 index 0000000000..749236f6c6 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/analyzer/disable-analyzer.bro @@ -0,0 +1,14 @@ +# +# @TEST-EXEC: bro -r ${TRACES}/var-services-std-ports.trace %INPUT +# @TEST-EXEC: cat conn.log | bro-cut service | grep -vq dns +# @TEST-EXEC: cat conn.log | bro-cut service | grep -vq ssh +# + +redef Analyzer::disabled_analyzers += { Analyzer::ANALYZER_SSH }; + +event bro_init() + { + Analyzer::disable_analyzer(Analyzer::ANALYZER_DNS); + } + + diff --git a/testing/btest/scripts/base/frameworks/analyzer/enable-analyzer.bro b/testing/btest/scripts/base/frameworks/analyzer/enable-analyzer.bro new file mode 100644 index 0000000000..bcee794768 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/analyzer/enable-analyzer.bro @@ -0,0 +1,13 @@ +# +# @TEST-EXEC: bro -r ${TRACES}/var-services-std-ports.trace %INPUT +# @TEST-EXEC: cat conn.log | bro-cut service | grep -q dns +# + +redef Analyzer::disable_all = T; + +event bro_init() + { + Analyzer::enable_analyzer(Analyzer::ANALYZER_DNS); + } + + diff --git a/testing/btest/scripts/base/frameworks/analyzer/register-for-port.bro b/testing/btest/scripts/base/frameworks/analyzer/register-for-port.bro new file mode 100644 index 0000000000..f3b54177e2 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/analyzer/register-for-port.bro @@ -0,0 +1,13 @@ +# +# @TEST-EXEC: bro -r ${TRACES}/ssh-on-port-80.trace %INPUT dpd_buffer_size=0; +# @TEST-EXEC: cat conn.log | bro-cut service | grep -q ssh +# +# @TEST-EXEC: bro -r ${TRACES}/ssh-on-port-80.trace dpd_buffer_size=0; +# @TEST-EXEC: cat conn.log | bro-cut service | grep -vq ssh + +event bro_init() + { + Analyzer::register_for_port(Analyzer::ANALYZER_SSH, 80/tcp); + } + + diff --git a/testing/btest/scripts/base/frameworks/analyzer/schedule-analyzer.bro b/testing/btest/scripts/base/frameworks/analyzer/schedule-analyzer.bro new file mode 100644 index 0000000000..114ea73673 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/analyzer/schedule-analyzer.bro @@ -0,0 +1,36 @@ +# +# @TEST-EXEC: bro -b -r ${TRACES}/rotation.trace %INPUT | sort >output +# @TEST-EXEC: btest-diff output + +global x = 0; + +event new_connection(c: connection) + { + # Make sure expiration executes. + Analyzer::schedule_analyzer(1.2.3.4, 1.2.3.4, 8/tcp, Analyzer::ANALYZER_MODBUS, 100hrs); + + if ( x > 0 ) + return; + + x = 1; + + Analyzer::schedule_analyzer(10.0.0.2, 10.0.0.3, 6/tcp, Analyzer::ANALYZER_SSH, 100hrs); + Analyzer::schedule_analyzer(10.0.0.2, 10.0.0.3, 6/tcp, Analyzer::ANALYZER_HTTP, 100hrs); + Analyzer::schedule_analyzer(10.0.0.2, 10.0.0.3, 6/tcp, Analyzer::ANALYZER_DNS, 100hrs); + Analyzer::schedule_analyzer(0.0.0.0, 10.0.0.3, 6/tcp, Analyzer::ANALYZER_FTP, 100hrs); + + Analyzer::schedule_analyzer(10.0.0.2, 10.0.0.3, 7/tcp, Analyzer::ANALYZER_SSH, 1sec); + Analyzer::schedule_analyzer(10.0.0.2, 10.0.0.3, 8/tcp, Analyzer::ANALYZER_HTTP, 1sec); + Analyzer::schedule_analyzer(10.0.0.2, 10.0.0.3, 8/tcp, Analyzer::ANALYZER_DNS, 100hrs); + Analyzer::schedule_analyzer(10.0.0.2, 10.0.0.3, 9/tcp, Analyzer::ANALYZER_FTP, 1sec); + } + +event scheduled_analyzer_applied(c: connection, a: Analyzer::Tag) + { + print "APPLIED:", network_time(), c$id, a; + } + + + + + diff --git a/testing/btest/scripts/base/frameworks/file-analysis/http/get.bro b/testing/btest/scripts/base/frameworks/file-analysis/http/get.bro index 317a6276e6..f7f4a0395b 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/http/get.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/http/get.bro @@ -1,13 +1,15 @@ -# @TEST-EXEC: bro -r $TRACES/http/get.trace $SCRIPTS/file-analysis-test.bro %INPUT >get.out -# @TEST-EXEC: bro -r $TRACES/http/get-gzip.trace $SCRIPTS/file-analysis-test.bro %INPUT >get-gzip.out +# @TEST-EXEC: bro -r $TRACES/http/get.trace $SCRIPTS/file-analysis-test.bro %INPUT c=1 >get.out +# @TEST-EXEC: bro -r $TRACES/http/get-gzip.trace $SCRIPTS/file-analysis-test.bro %INPUT c=2 >get-gzip.out # @TEST-EXEC: btest-diff get.out # @TEST-EXEC: btest-diff get-gzip.out -# @TEST-EXEC: btest-diff Cx92a0ym5R8-file -# @TEST-EXEC: btest-diff kg59rqyYxN-file +# @TEST-EXEC: btest-diff 1-file +# @TEST-EXEC: btest-diff 2-file redef test_file_analysis_source = "HTTP"; +global c = 0 &redef; + redef test_get_file_name = function(f: fa_file): string { - return fmt("%s-file", f$id); + return fmt("%d-file", c); }; diff --git a/testing/btest/scripts/base/frameworks/file-analysis/http/partial-content.bro b/testing/btest/scripts/base/frameworks/file-analysis/http/partial-content.bro index 1f3d54daea..93443f0ca8 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/http/partial-content.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/http/partial-content.bro @@ -1,16 +1,16 @@ # @TEST-EXEC: bro -r $TRACES/http/206_example_a.pcap $SCRIPTS/file-analysis-test.bro %INPUT >a.out # @TEST-EXEC: btest-diff a.out -# @TEST-EXEC: wc -c 7gZBKVUgy4l-file0 | sed 's/^[ \t]* //g' >a.size +# @TEST-EXEC: wc -c file-0 | sed 's/^[ \t]* //g' >a.size # @TEST-EXEC: btest-diff a.size # @TEST-EXEC: bro -r $TRACES/http/206_example_b.pcap $SCRIPTS/file-analysis-test.bro %INPUT >b.out # @TEST-EXEC: btest-diff b.out -# @TEST-EXEC: wc -c oDwT1BbzjM1-file0 | sed 's/^[ \t]* //g' >b.size +# @TEST-EXEC: wc -c file-0 | sed 's/^[ \t]* //g' >b.size # @TEST-EXEC: btest-diff b.size # @TEST-EXEC: bro -r $TRACES/http/206_example_c.pcap $SCRIPTS/file-analysis-test.bro %INPUT >c.out # @TEST-EXEC: btest-diff c.out -# @TEST-EXEC: wc -c uHS14uhRKGe-file0 | sed 's/^[ \t]* //g' >c.size +# @TEST-EXEC: wc -c file-0 | sed 's/^[ \t]* //g' >c.size # @TEST-EXEC: btest-diff c.size global cnt: count = 0; @@ -19,7 +19,7 @@ redef test_file_analysis_source = "HTTP"; redef test_get_file_name = function(f: fa_file): string { - local rval: string = fmt("%s-file%d", f$id, cnt); + local rval: string = fmt("file-%d", cnt); ++cnt; return rval; }; diff --git a/testing/btest/scripts/base/frameworks/file-analysis/http/pipeline.bro b/testing/btest/scripts/base/frameworks/file-analysis/http/pipeline.bro index 5135b03786..36743a8bad 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/http/pipeline.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/http/pipeline.bro @@ -1,14 +1,16 @@ # @TEST-EXEC: bro -r $TRACES/http/pipelined-requests.trace $SCRIPTS/file-analysis-test.bro %INPUT >out # @TEST-EXEC: btest-diff out -# @TEST-EXEC: btest-diff aFQKI8SPOL2-file -# @TEST-EXEC: btest-diff CCU3vUEr06l-file -# @TEST-EXEC: btest-diff HCzA0dVwDPj-file -# @TEST-EXEC: btest-diff a1Zu1fteVEf-file -# @TEST-EXEC: btest-diff xXlF7wFdsR-file +# @TEST-EXEC: btest-diff 1-file +# @TEST-EXEC: btest-diff 2-file +# @TEST-EXEC: btest-diff 3-file +# @TEST-EXEC: btest-diff 4-file +# @TEST-EXEC: btest-diff 5-file redef test_file_analysis_source = "HTTP"; +global c = 0; + redef test_get_file_name = function(f: fa_file): string { - return fmt("%s-file", f$id); + return fmt("%d-file", ++c); }; diff --git a/testing/btest/scripts/base/frameworks/file-analysis/http/post.bro b/testing/btest/scripts/base/frameworks/file-analysis/http/post.bro index 5db64c9ff0..79ac1cb5c1 100644 --- a/testing/btest/scripts/base/frameworks/file-analysis/http/post.bro +++ b/testing/btest/scripts/base/frameworks/file-analysis/http/post.bro @@ -1,11 +1,13 @@ # @TEST-EXEC: bro -r $TRACES/http/post.trace $SCRIPTS/file-analysis-test.bro %INPUT >out # @TEST-EXEC: btest-diff out -# @TEST-EXEC: btest-diff v5HLI7MxPQh-file -# @TEST-EXEC: btest-diff PZS1XGHkIf1-file +# @TEST-EXEC: btest-diff 1-file +# @TEST-EXEC: btest-diff 2-file redef test_file_analysis_source = "HTTP"; +global c = 0; + redef test_get_file_name = function(f: fa_file): string { - return fmt("%s-file", f$id); + return fmt("%d-file", ++c); }; diff --git a/testing/btest/scripts/base/protocols/ftp/ftp-extract.bro b/testing/btest/scripts/base/protocols/ftp/ftp-extract.bro index 9ae5280757..de1025ed82 100644 --- a/testing/btest/scripts/base/protocols/ftp/ftp-extract.bro +++ b/testing/btest/scripts/base/protocols/ftp/ftp-extract.bro @@ -3,10 +3,14 @@ # @TEST-EXEC: bro -r $TRACES/ftp/ipv4.trace %INPUT # @TEST-EXEC: btest-diff conn.log # @TEST-EXEC: btest-diff ftp.log -# @TEST-EXEC: btest-diff ftp-item-Rqjkzoroau4-0.dat -# @TEST-EXEC: btest-diff ftp-item-BTsa70Ua9x7-1.dat -# @TEST-EXEC: btest-diff ftp-item-VLQvJybrm38-2.dat -# @TEST-EXEC: btest-diff ftp-item-zrfwSs9K1yk-3.dat +# @TEST-EXEC: mv ftp-item-*-0.dat ftp-item-0.dat +# @TEST-EXEC: mv ftp-item-*-1.dat ftp-item-1.dat +# @TEST-EXEC: mv ftp-item-*-2.dat ftp-item-2.dat +# @TEST-EXEC: mv ftp-item-*-3.dat ftp-item-3.dat +# @TEST-EXEC: btest-diff ftp-item-0.dat +# @TEST-EXEC: btest-diff ftp-item-1.dat +# @TEST-EXEC: btest-diff ftp-item-2.dat +# @TEST-EXEC: btest-diff ftp-item-3.dat redef FTP::logged_commands += {"LIST"}; redef FTP::extract_file_types=/.*/; diff --git a/testing/btest/scripts/base/protocols/http/http-extract-files.bro b/testing/btest/scripts/base/protocols/http/http-extract-files.bro index ce9d3e7e04..6156009821 100644 --- a/testing/btest/scripts/base/protocols/http/http-extract-files.bro +++ b/testing/btest/scripts/base/protocols/http/http-extract-files.bro @@ -1,5 +1,6 @@ # @TEST-EXEC: bro -C -r $TRACES/web.trace %INPUT # @TEST-EXEC: btest-diff http.log -# @TEST-EXEC: btest-diff http-item-BFymS6bFgT3-0.dat +# @TEST-EXEC: mv http-item-*.dat http-item.dat +# @TEST-EXEC: btest-diff http-item.dat redef HTTP::extract_file_types += /text\/html/; diff --git a/testing/btest/scripts/base/protocols/irc/dcc-extract.test b/testing/btest/scripts/base/protocols/irc/dcc-extract.test index 8a6680f99b..71ab1b0900 100644 --- a/testing/btest/scripts/base/protocols/irc/dcc-extract.test +++ b/testing/btest/scripts/base/protocols/irc/dcc-extract.test @@ -4,9 +4,10 @@ # @TEST-EXEC: bro -r $TRACES/irc-dcc-send.trace %INPUT # @TEST-EXEC: btest-diff irc.log -# @TEST-EXEC: btest-diff irc-dcc-item-wqKMAamJVSb-0.dat +# @TEST-EXEC: mv irc-dcc-item-*-0.dat irc-dcc-item.dat +# @TEST-EXEC: btest-diff irc-dcc-item.dat # @TEST-EXEC: bro -r $TRACES/irc-dcc-send.trace %INPUT IRC::extraction_prefix="test" -# @TEST-EXEC: test -e test-wqKMAamJVSb-0.dat +# @TEST-EXEC: test -e test-*-0.dat redef IRC::extract_file_types=/.*/; diff --git a/testing/btest/scripts/base/protocols/modbus/events.bro b/testing/btest/scripts/base/protocols/modbus/events.bro index 46d9c0ce7a..a5fe26be9c 100644 --- a/testing/btest/scripts/base/protocols/modbus/events.bro +++ b/testing/btest/scripts/base/protocols/modbus/events.bro @@ -2,7 +2,7 @@ # @TEST-EXEC: bro -r $TRACES/modbus/modbus.trace %INPUT | sort | uniq -c | sed 's/^ *//g' >output # @TEST-EXEC: btest-diff output # @TEST-EXEC: cat output | awk '{print $2}' | grep "^modbus_" | sort | uniq | wc -l >covered -# @TEST-EXEC: cat ${DIST}/src/event.bif | grep "^event modbus_" | wc -l >total +# @TEST-EXEC: cat ${DIST}/src/analyzer/protocol/modbus/events.bif | grep "^event modbus_" | wc -l >total # @TEST-EXEC: echo `cat covered` of `cat total` events triggered by trace >coverage # @TEST-EXEC: btest-diff coverage diff --git a/testing/btest/scripts/base/protocols/smtp/mime-extract.test b/testing/btest/scripts/base/protocols/smtp/mime-extract.test index 54e50d0459..149fcf67c3 100644 --- a/testing/btest/scripts/base/protocols/smtp/mime-extract.test +++ b/testing/btest/scripts/base/protocols/smtp/mime-extract.test @@ -1,10 +1,12 @@ # @TEST-EXEC: bro -r $TRACES/smtp.trace %INPUT # @TEST-EXEC: btest-diff smtp_entities.log -# @TEST-EXEC: btest-diff smtp-entity-cwR7l6Zctxb-0.dat -# @TEST-EXEC: btest-diff smtp-entity-Ltd7QO7jEv3-1.dat +# @TEST-EXEC: mv smtp-entity-*-0.dat smtp-entity-0.dat +# @TEST-EXEC: mv smtp-entity-*-1.dat smtp-entity-1.dat +# @TEST-EXEC: btest-diff smtp-entity-0.dat +# @TEST-EXEC: btest-diff smtp-entity-1.dat # @TEST-EXEC: bro -r $TRACES/smtp.trace %INPUT SMTP::extraction_prefix="test" -# @TEST-EXEC: test -e test-cwR7l6Zctxb-0.dat -# @TEST-EXEC: test -e test-Ltd7QO7jEv3-1.dat +# @TEST-EXEC: test -e test-*-0.dat +# @TEST-EXEC: test -e test-*-1.dat @load base/protocols/smtp diff --git a/testing/btest/scripts/base/protocols/syslog/trace.test b/testing/btest/scripts/base/protocols/syslog/trace.test new file mode 100644 index 0000000000..78b681a9d8 --- /dev/null +++ b/testing/btest/scripts/base/protocols/syslog/trace.test @@ -0,0 +1,4 @@ +# @TEST-EXEC: bro -r $TRACES/syslog-single-udp.trace %INPUT +# @TEST-EXEC: btest-diff syslog.log + +@load base/protocols/syslog diff --git a/testing/btest/signatures/dpd.bro b/testing/btest/signatures/dpd.bro index a302603bd2..39f1b01294 100644 --- a/testing/btest/signatures/dpd.bro +++ b/testing/btest/signatures/dpd.bro @@ -33,7 +33,7 @@ signature my_ftp_server { event bro_init() { # no analyzer attached to any port by default, depends entirely on sigs - print "dpd_config", dpd_config; + print "|Analyzer::all_registered_ports()|", |Analyzer::all_registered_ports()|; } event signature_match(state: signature_state, msg: string, data: string) diff --git a/testing/scripts/diff-canonifier-external b/testing/scripts/diff-canonifier-external index 04ef699538..f4356154e4 100755 --- a/testing/scripts/diff-canonifier-external +++ b/testing/scripts/diff-canonifier-external @@ -4,6 +4,7 @@ `dirname $0`/diff-remove-timestamps \ | `dirname $0`/diff-remove-uids \ + | `dirname $0`/diff-remove-file-ids \ | `dirname $0`/diff-remove-x509-names \ | `dirname $0`/diff-canon-notice-policy \ | `dirname $0`/diff-sort diff --git a/testing/scripts/diff-remove-file-ids b/testing/scripts/diff-remove-file-ids new file mode 100755 index 0000000000..f54177d8ba --- /dev/null +++ b/testing/scripts/diff-remove-file-ids @@ -0,0 +1,33 @@ +#! /usr/bin/awk -f +# +# A diff canonifier that removes all file IDs from file_analysis.log + +BEGIN { + FS="\t"; + OFS="\t"; + process = 0; + } + +$1 == "#path" && $2 == "file_analysis" { + process = 1; + } + +process && column1 > 0 && column2 > 0 { + $column1 = "XXXXXXXXXXX"; + $column2 = "XXXXXXXXXXX"; + } + +/^#/ { + for ( i = 0; i < NF; ++i ) { + if ( $i == "id" ) + column1 = i - 1; + + if ( $i == "parent_id" ) + column2 = i - 1; + } + } + +{ print } + + +