mirror of
https://github.com/zeek/zeek.git
synced 2025-10-10 10:38:20 +00:00
Merge remote-tracking branch 'origin/master' into topic/johanna/openflow
This commit is contained in:
commit
a51ee45e05
264 changed files with 7452 additions and 4927 deletions
212
CHANGES
212
CHANGES
|
@ -1,4 +1,216 @@
|
|||
|
||||
2.4-beta | 2015-05-07 21:55:31 -0700
|
||||
|
||||
* Release 2.4-beta.
|
||||
|
||||
* Update local-compat.test (Johanna Amann)
|
||||
|
||||
2.3-913 | 2015-05-06 09:58:00 -0700
|
||||
|
||||
* Add /sbin to PATH in btest.cfg and remove duplicate default_path.
|
||||
(Daniel Thayer)
|
||||
|
||||
2.3-911 | 2015-05-04 09:58:09 -0700
|
||||
|
||||
* Update usage output and list of command line options. (Daniel
|
||||
Thayer)
|
||||
|
||||
* Fix to ssh/geo-data.bro for unset directions. (Vlad Grigorescu)
|
||||
|
||||
* Improve SIP logging and remove reporter messages. (Seth Hall)
|
||||
|
||||
2.3-905 | 2015-04-29 17:01:30 -0700
|
||||
|
||||
* Improve SIP logging and remove reporter messages. (Seth Hall)
|
||||
|
||||
2.3-903 | 2015-04-27 17:27:59 -0700
|
||||
|
||||
* BIT-1350: Improve record coercion type checking. (Jon Siwek)
|
||||
|
||||
2.3-901 | 2015-04-27 17:25:27 -0700
|
||||
|
||||
* BIT-1384: Remove -O (optimize scripts) command-line option, which
|
||||
hadn't been working for a while already. (Jon Siwek)
|
||||
|
||||
2.3-899 | 2015-04-27 17:22:42 -0700
|
||||
|
||||
* Fix the -J/--set-seed cmd-line option. (Daniel Thayer)
|
||||
|
||||
* Remove unused -l, -L, and -Z cmd-line options. (Daniel Thayer)
|
||||
|
||||
2.3-892 | 2015-04-27 08:22:22 -0700
|
||||
|
||||
* Fix typos in the Broker BIF documentation. (Daniel Thayer)
|
||||
|
||||
* Update installation instructions and remove outdated references.
|
||||
(Johanna Amann)
|
||||
|
||||
* Easier support for systems with tcmalloc_minimal installed. (Seth
|
||||
Hall)
|
||||
|
||||
2.3-884 | 2015-04-23 12:30:15 -0500
|
||||
|
||||
* Fix some outdated documentation unit tests. (Jon Siwek)
|
||||
|
||||
2.3-883 | 2015-04-23 07:10:36 -0700
|
||||
|
||||
* Fix -N option to work with builtin plugins as well. (Robin Sommer)
|
||||
|
||||
2.3-882 | 2015-04-23 06:59:40 -0700
|
||||
|
||||
* Add missing .pac dependencies for some binpac analyzer targets.
|
||||
(Jon Siwek)
|
||||
|
||||
2.3-879 | 2015-04-22 10:38:07 -0500
|
||||
|
||||
* Fix compile errors. (Jon Siwek)
|
||||
|
||||
2.3-878 | 2015-04-22 08:21:23 -0700
|
||||
|
||||
* Fix another compiler warning in DTLS. (Johanna Amann)
|
||||
|
||||
2.3-877 | 2015-04-21 20:14:16 -0700
|
||||
|
||||
* Adding missing include. (Robin Sommer)
|
||||
|
||||
2.3-876 | 2015-04-21 16:40:10 -0700
|
||||
|
||||
* Attempt at fixing a potential std::length_error exception in RDP
|
||||
analyzer. Addresses BIT-1337. (Robin Sommer)
|
||||
|
||||
* Fixing compile problem caused by overeager factorization. (Robin
|
||||
Sommer)
|
||||
|
||||
2.3-874 | 2015-04-21 16:09:20 -0700
|
||||
|
||||
* Change details of escaping when logging/printing. (Seth Hall/Robin
|
||||
Sommer)
|
||||
|
||||
- Log files now escape non-printable characters consistently
|
||||
as "\xXX'. Furthermore, backslashes are escaped as "\\",
|
||||
making the representation fully reversible.
|
||||
|
||||
- When escaping via script-level functions (escape_string,
|
||||
clean), we likewise now escape consistently with "\xXX" and
|
||||
"\\".
|
||||
|
||||
- There's no "alternative" output style anymore, i.e., fmt()
|
||||
'%A' qualifier is gone.
|
||||
|
||||
Addresses BIT-1333.
|
||||
|
||||
* Remove several BroString escaping methods that are no longer
|
||||
useful. (Seth Hall)
|
||||
|
||||
2.3-864 | 2015-04-21 15:24:02 -0700
|
||||
|
||||
* A SIP protocol analyzer. (Vlad Grigorescu)
|
||||
|
||||
Activity gets logged into sip.log. It generates the following
|
||||
events:
|
||||
|
||||
event sip_request(c: connection, method: string, original_URI: string, version: string);
|
||||
event sip_reply(c: connection, version: string, code: count, reason: string);
|
||||
event sip_header(c: connection, is_orig: bool, name: string, value: string);
|
||||
event sip_all_headers(c: connection, is_orig: bool, hlist: mime_header_list);
|
||||
event sip_begin_entity(c: connection, is_orig: bool);
|
||||
event sip_end_entity(c: connection, is_orig: bool);
|
||||
|
||||
The analyzer support SIP over UDP currently.
|
||||
|
||||
* BIT-1343: Factor common ASN.1 code from RDP, SNMP, and Kerberos
|
||||
analyzers. (Jon Siwek/Robin Sommer)
|
||||
|
||||
2.3-838 | 2015-04-21 13:40:12 -0700
|
||||
|
||||
* BIT-1373: Fix vector index assignment reference count bug. (Jon Siwek)
|
||||
|
||||
2.3-836 | 2015-04-21 13:37:31 -0700
|
||||
|
||||
* Fix SSH direction field being unset. Addresses BIT-1365. (Vlad
|
||||
Grigorescu)
|
||||
|
||||
2.3-835 | 2015-04-21 16:36:00 -0500
|
||||
|
||||
* Clarify Broker examples. (Jon Siwek)
|
||||
|
||||
2.3-833 | 2015-04-21 12:38:32 -0700
|
||||
|
||||
* A Kerberos protocol analyzer. (Vlad Grigorescu)
|
||||
|
||||
Activity gets logged into kerberos.log. It generates the following
|
||||
events:
|
||||
|
||||
event krb_as_request(c: connection, msg: KRB::KDC_Request);
|
||||
event krb_as_response(c: connection, msg: KRB::KDC_Response);
|
||||
event krb_tgs_request(c: connection, msg: KRB::KDC_Request);
|
||||
event krb_tgs_response(c: connection, msg: KRB::KDC_Response);
|
||||
event krb_ap_request(c: connection, ticket: KRB::Ticket, opts: KRB::AP_Options);
|
||||
event krb_priv(c: connection, is_orig: bool);
|
||||
event krb_safe(c: connection, is_orig: bool, msg: KRB::SAFE_Msg);
|
||||
event krb_cred(c: connection, is_orig: bool, tickets: KRB::Ticket_Vector);
|
||||
event krb_error(c: connection, msg: KRB::Error_Msg);
|
||||
|
||||
2.3-793 | 2015-04-20 20:51:00 -0700
|
||||
|
||||
* Add decoding of PROXY-AUTHORIZATION header to HTTP analyze,
|
||||
treating it the same as AUTHORIZATION. (Josh Liburdi)
|
||||
|
||||
* Remove deprecated fields "hot" and "addl" from the connection
|
||||
record. Remove the functions append_addl() and
|
||||
append_addl_marker(). (Robin Sommer)
|
||||
|
||||
* Removing the NetFlow analyzer, which hasn't been used anymore
|
||||
since then corresponding command-line option went away. (Robin
|
||||
Sommer)
|
||||
|
||||
2.3-787 | 2015-04-20 19:15:23 -0700
|
||||
|
||||
* A file analyzer for Portable Executables. (Vlad Grigorescu/Seth
|
||||
Hall).
|
||||
|
||||
Activity gets logged into pe.log. It generates the following
|
||||
events:
|
||||
|
||||
event pe_dos_header(f: fa_file, h: PE::DOSHeader);
|
||||
event pe_dos_code(f: fa_file, code: string);
|
||||
event pe_file_header(f: fa_file, h: PE::FileHeader);
|
||||
event pe_optional_header(f: fa_file, h: PE::OptionalHeader);
|
||||
event pe_section_header(f: fa_file, h: PE::SectionHeader);
|
||||
|
||||
2.3-741 | 2015-04-20 13:12:39 -0700
|
||||
|
||||
* API changes to file analysis mime type detection. Removed
|
||||
"file_mime_type" and "file_mime_types" event, replacing them with
|
||||
a new event called "file_metadata_inferred". Addresses BIT-1368.
|
||||
(Jon Siwek)
|
||||
|
||||
* A large series of improvements for file type identification. This
|
||||
inludes a many signature updates (new types, cleanup, performance
|
||||
improvments) and splitting out signatures into subfiles. (Seth
|
||||
Hall)
|
||||
|
||||
* Fix an issue with files having gaps before the bof_buffer is
|
||||
filled, which could lead to file type identification not working
|
||||
correctly. (Seth Hall)
|
||||
|
||||
* Fix an issue with packet loss in HTTP file reporting for file type
|
||||
identification wasn't working correctly zero-length bodies. (Seth
|
||||
Hall)
|
||||
|
||||
* X.509 certificates are now populating files.log with the mime type
|
||||
application/pkix-cert. (Seth Hall)
|
||||
|
||||
* Normalized some FILE_ANALYSIS debug messages. (Seth Hall)
|
||||
|
||||
2.3-725 | 2015-04-20 12:54:54 -0700
|
||||
|
||||
* Updating submodule(s).
|
||||
|
||||
2.3-724 | 2015-04-20 14:11:02 -0500
|
||||
|
||||
* Fix uninitialized field in raw input reader. (Jon Siwek)
|
||||
|
||||
2.3-722 | 2015-04-20 12:59:03 -0500
|
||||
|
||||
* Remove unneeded documentation cross-referencing. (Jon Siwek)
|
||||
|
|
|
@ -113,7 +113,7 @@ if (NOT DISABLE_PERFTOOLS)
|
|||
find_package(GooglePerftools)
|
||||
endif ()
|
||||
|
||||
if (GOOGLEPERFTOOLS_FOUND)
|
||||
if (GOOGLEPERFTOOLS_FOUND OR TCMALLOC_FOUND)
|
||||
set(HAVE_PERFTOOLS true)
|
||||
# Non-Linux systems may not be well-supported by gperftools, so
|
||||
# require explicit request from user to enable it in that case.
|
||||
|
|
107
NEWS
107
NEWS
|
@ -13,10 +13,12 @@ New Functionality
|
|||
- Bro now has support for external plugins that can extend its core
|
||||
functionality, like protocol/file analysis, via shared libraries.
|
||||
Plugins can be developed and distributed externally, and will be
|
||||
pulled in dynamically at startup. Currently, a plugin can provide
|
||||
custom protocol analyzers, file analyzers, log writers, input
|
||||
readers, packet sources and dumpers, and new built-in functions. A
|
||||
plugin can furthermore hook into Bro's processing at a number of
|
||||
pulled in dynamically at startup (the environment variables
|
||||
BRO_PLUGIN_PATH and BRO_PLUGIN_ACTIVATE can be used to specify the
|
||||
locations and names of plugins to activate). Currently, a plugin
|
||||
can provide custom protocol analyzers, file analyzers, log writers,
|
||||
input readers, packet sources and dumpers, and new built-in functions.
|
||||
A plugin can furthermore hook into Bro's processing at a number of
|
||||
places to add custom logic.
|
||||
|
||||
See https://www.bro.org/sphinx-git/devel/plugins.html for more
|
||||
|
@ -25,17 +27,37 @@ New Functionality
|
|||
- Bro now has support for the MySQL wire protocol. Activity gets
|
||||
logged into mysql.log.
|
||||
|
||||
- Bro now parses DTLS traffic.
|
||||
- Bro now parses DTLS traffic. Activity gets logged into ssl.log.
|
||||
|
||||
- Bro now has an RDP analyzer.
|
||||
- Bro now has support for the Kerberos KRB5 protocol over TCP and
|
||||
UDP. Activity gets logged into kerberos.log.
|
||||
|
||||
- Bro now features a completely rewritten, enhanced SSH analyzer, with
|
||||
a set of addedd events being generated. A lot more information about
|
||||
SSH sessions is logged. The analyzer is able to determine if logins
|
||||
failed or succeeded in most circumstances.
|
||||
- Bro now has an RDP analyzer. Activity gets logged into rdp.log.
|
||||
|
||||
- Bro now has a file analyzer for Portable Executables. Activity gets
|
||||
logged into pe.log.
|
||||
|
||||
- Bro now has support for the SIP protocol over UDP. Activity gets
|
||||
logged into sip.log.
|
||||
|
||||
- Bro now features a completely rewritten, enhanced SSH analyzer. The
|
||||
new analyzer is able to determine if logins failed or succeeded in
|
||||
most circumstances, logs a lot more more information about SSH
|
||||
sessions, supports v1, and introduces the intelligence type
|
||||
``Intel::PUBKEY_HASH`` and location ``SSH::IN_SERVER_HOST_KEY``. The
|
||||
analayzer also generates a set of additional events
|
||||
(``ssh_auth_successful``, ``ssh_auth_failed``, ``ssh_capabilities``,
|
||||
``ssh2_server_host_key``, ``ssh1_server_host_key``,
|
||||
``ssh_encrypted_packet``, ``ssh2_dh_server_params``,
|
||||
``ssh2_gss_error``, ``ssh2_ecc_key``). See next section for
|
||||
incompatible SSH changes.
|
||||
|
||||
- Bro's file analysis now supports reassembly of files that are not
|
||||
transferred/seen sequentially.
|
||||
transferred/seen sequentially. The default file reassembly buffer
|
||||
size is set with the ``Files::reassembly_buffer_size`` variable.
|
||||
|
||||
- Bro's file type identification has been greatly improved (new file types,
|
||||
bug fixes, and performance improvements).
|
||||
|
||||
- Bro's scripting language now has a ``while`` statement::
|
||||
|
||||
|
@ -61,7 +83,7 @@ New Functionality
|
|||
C++11 compiler (e.g. GCC 4.8+ or Clang 3.3+).
|
||||
|
||||
Broker will become a mandatory dependency in future Bro versions and
|
||||
replace the current communcation and serialization system.
|
||||
replace the current communication and serialization system.
|
||||
|
||||
- Add --enable-c++11 configure flag to compile Bro's source code in
|
||||
C++11 mode with a corresponding compiler. Note that 2.4 will be the
|
||||
|
@ -69,10 +91,10 @@ New Functionality
|
|||
|
||||
- The SSL analysis now alerts when encountering SSL connections with
|
||||
old protocol versions or unsafe cipher suites. It also gained
|
||||
extended reporting of weak keys, caching of already valdidated
|
||||
certificates, full support TLS record defragmentation. SSL generally
|
||||
extended reporting of weak keys, caching of already validated
|
||||
certificates, and full support for TLS record defragmentation. SSL generally
|
||||
became much more robust and added several fields to ssl.log (while
|
||||
removing some other).
|
||||
removing some others).
|
||||
|
||||
- A new icmp_sent_payload event provides access to ICMP payload.
|
||||
|
||||
|
@ -85,6 +107,9 @@ New Functionality
|
|||
threshold in terms of packets or bytes. The primary API for that
|
||||
functionality is in base/protocols/conn/thresholds.bro.
|
||||
|
||||
- There is a new command-line option -Q/--time that prints Bro's execution
|
||||
time and memory usage to stderr.
|
||||
|
||||
- BroControl now has a new command "deploy" which is equivalent to running
|
||||
the "check", "install", "stop", and "start" commands (in that order).
|
||||
|
||||
|
@ -114,14 +139,17 @@ Changed Functionality
|
|||
- File analysis
|
||||
|
||||
* Removed ``fa_file`` record's ``mime_type`` and ``mime_types``
|
||||
fields. The events ``file_mime_type`` and ``file_mime_types``
|
||||
have been added which contain the same information. The
|
||||
``mime_type`` field of ``Files::Info`` also still has this info.
|
||||
fields. The event ``file_sniff`` has been added which provides
|
||||
the same information. The ``mime_type`` field of ``Files::Info``
|
||||
also still has this info.
|
||||
|
||||
* The earliest point that new mime type information is available is
|
||||
in the ``file_mime_type`` event which comes after the ``file_new``
|
||||
and ``file_over_new_connection`` events. Scripts which inspected
|
||||
mime type info within those events will need to be adapted.
|
||||
in the ``file_sniff`` event which comes after the ``file_new`` and
|
||||
``file_over_new_connection`` events. Scripts which inspected mime
|
||||
type info within those events will need to be adapted. (Note: for
|
||||
users that worked w/ versions of Bro from git, for a while there was
|
||||
also an event called ``file_mime_type`` which is now replaced with
|
||||
the ``file_sniff`` event).
|
||||
|
||||
* Removed ``Files::add_analyzers_for_mime_type`` function.
|
||||
|
||||
|
@ -130,10 +158,22 @@ Changed Functionality
|
|||
reassembly for non-sequential files, "offset" can be obtained
|
||||
with other information already available -- adding together
|
||||
``seen_bytes`` and ``missed_bytes`` fields of the ``fa_file``
|
||||
record gives the how many bytes have been written so far (i.e.
|
||||
record gives how many bytes have been written so far (i.e.
|
||||
the "offset").
|
||||
|
||||
- has_valid_octets: now uses a string_vec parameter instead of
|
||||
- The SSH changes come with a few incompatibilities. The following
|
||||
events have been renamed:
|
||||
|
||||
* ``SSH::heuristic_failed_login`` to ``SSH::ssh_auth_failed``
|
||||
* ``SSH::heuristic_successful_login`` to ``SSH::ssh_auth_successful``
|
||||
|
||||
The ``SSH::Info`` status field has been removed and replaced with
|
||||
the ``auth_success`` field. This field has been changed from a
|
||||
string that was previously ``success``, ``failure`` or
|
||||
``undetermined`` to a boolean. a boolean that is ``T``, ``F``, or
|
||||
unset.
|
||||
|
||||
- The has_valid_octets function now uses a string_vec parameter instead of
|
||||
string_array.
|
||||
|
||||
- conn.log gained a new field local_resp that works like local_orig,
|
||||
|
@ -176,6 +216,25 @@ Changed Functionality
|
|||
- BroControl now sends all normal command output (i.e., not error messages)
|
||||
to stdout. Error messages are still sent to stderr, however.
|
||||
|
||||
- The capability of processing NetFlow input has been removed for the
|
||||
time being. Therefore, the -y/--flowfile and -Y/--netflow command-line
|
||||
options have been removed, and the netflow_v5_header and netflow_v5_record
|
||||
events have been removed.
|
||||
|
||||
- The -D/--dfa-size command-line option has been removed.
|
||||
|
||||
- The -L/--rule-benchmark command-line option has been removed.
|
||||
|
||||
- The -O/--optimize command-line option has been removed.
|
||||
|
||||
- The deprecated fields "hot" and "addl" have been removed from the
|
||||
connection record. Likewise, the functions append_addl() and
|
||||
append_addl_marker() have been removed.
|
||||
|
||||
- Log files now escape non-printable characters consistently as "\xXX'.
|
||||
Furthermore, backslashes are escaped as "\\", making the
|
||||
representation fully reversible.
|
||||
|
||||
Deprecated Functionality
|
||||
------------------------
|
||||
|
||||
|
@ -185,7 +244,7 @@ Deprecated Functionality
|
|||
concatenation/extraction functions. Note that the new functions use
|
||||
0-based indexing, rather than 1-based.
|
||||
|
||||
The full list of now deprecation functions is:
|
||||
The full list of now deprecated functions is:
|
||||
|
||||
* split: use split_string instead.
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2.3-722
|
||||
2.4-beta
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 544330932e7cd4615d6d19f63907e8aa2acebb9e
|
||||
Subproject commit 4f33233aef5539ae4f12c6d0e4338247833c3900
|
|
@ -1 +1 @@
|
|||
Subproject commit 462e300bf9c37dcc39b70a4c2d89d19f7351c804
|
||||
Subproject commit a2d290a832c35ad11f3fabb19812bcae2ff089cd
|
|
@ -1 +1 @@
|
|||
Subproject commit 45276b39a946d70095c983753cd321ad07dcf285
|
||||
Subproject commit 74bb4bbd949e61e099178f8a97499d3f1355de8b
|
|
@ -1 +1 @@
|
|||
Subproject commit e864a0949e52a797f4000194b5c2980cf3618deb
|
||||
Subproject commit 97c17d21725e42b36f4b49579077ecdc28ddb86a
|
|
@ -1 +1 @@
|
|||
Subproject commit 0c25c1daa7dcf885dd16cc1b725295dc36decafe
|
||||
Subproject commit b02fefd5cf78c1576e59c106f5211ce5ae47cfdd
|
|
@ -1 +1 @@
|
|||
Subproject commit d69df586c91531db0c3abe838b10a429dda4fa87
|
||||
Subproject commit 80b42ee3e4503783b6720855b28e83ff1658c22b
|
|
@ -1 +1 @@
|
|||
Subproject commit 7a14085394e54a950e477eb4fafb3827ff8dbdc3
|
||||
Subproject commit e1ea9f67cfe3d6a81e0c1479ced0b9aa73e77c87
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
|||
Subproject commit 2fd35ab6a6245a005828c32f0aa87eb21698c054
|
||||
Subproject commit 6406fb79d30df8d7956110ce65a97d18e4bc8c3b
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
const broker_port: port &redef;
|
||||
const broker_port: port = 9999/tcp &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
redef BrokerComm::endpoint_name = "connector";
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
const broker_port: port &redef;
|
||||
const broker_port: port = 9999/tcp &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
redef BrokerComm::endpoint_name = "listener";
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const broker_port: port &redef;
|
||||
const broker_port: port = 9999/tcp &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
redef BrokerComm::endpoint_name = "connector";
|
||||
global my_event: event(msg: string, c: count);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
const broker_port: port &redef;
|
||||
const broker_port: port = 9999/tcp &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
redef BrokerComm::endpoint_name = "listener";
|
||||
global msg_count = 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@load ./testlog
|
||||
|
||||
const broker_port: port &redef;
|
||||
const broker_port: port = 9999/tcp &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
redef BrokerComm::endpoint_name = "connector";
|
||||
redef Log::enable_local_logging = F;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@load ./testlog
|
||||
|
||||
const broker_port: port &redef;
|
||||
const broker_port: port = 9999/tcp &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
redef BrokerComm::endpoint_name = "listener";
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const broker_port: port &redef;
|
||||
const broker_port: port = 9999/tcp &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
redef BrokerComm::endpoint_name = "connector";
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
const broker_port: port &redef;
|
||||
const broker_port: port = 9999/tcp &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
redef BrokerComm::endpoint_name = "listener";
|
||||
global msg_count = 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const broker_port: port &redef;
|
||||
const broker_port: port = 9999/tcp &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
|
||||
global h: opaque of BrokerStore::Handle;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const broker_port: port &redef;
|
||||
const broker_port: port = 9999/tcp &redef;
|
||||
redef exit_only_after_terminate = T;
|
||||
|
||||
global h: opaque of BrokerStore::Handle;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
event file_mime_type(f: fa_file, mime_type: string)
|
||||
event file_sniff(f: fa_file, meta: fa_metadata)
|
||||
{
|
||||
if ( ! meta?$mime_type ) return;
|
||||
print "new file", f$id;
|
||||
if ( mime_type == "text/plain" )
|
||||
if ( meta$mime_type == "text/plain" )
|
||||
Files::add_analyzer(f, Files::ANALYZER_MD5);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,15 +7,18 @@ global mime_to_ext: table[string] of string = {
|
|||
["text/html"] = "html",
|
||||
};
|
||||
|
||||
event file_mime_type(f: fa_file, mime_type: string)
|
||||
event file_sniff(f: fa_file, meta: fa_metadata)
|
||||
{
|
||||
if ( f$source != "HTTP" )
|
||||
return;
|
||||
|
||||
if ( mime_type !in mime_to_ext )
|
||||
if ( ! meta?$mime_type )
|
||||
return;
|
||||
|
||||
local fname = fmt("%s-%s.%s", f$source, f$id, mime_to_ext[mime_type]);
|
||||
if ( meta$mime_type !in mime_to_ext )
|
||||
return;
|
||||
|
||||
local fname = fmt("%s-%s.%s", f$source, f$id, mime_to_ext[meta$mime_type]);
|
||||
print fmt("Extracting file %s", fname);
|
||||
Files::add_analyzer(f, Files::ANALYZER_EXTRACT, [$extract_filename=fname]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ that ``bash`` and ``python`` are in your ``PATH``):
|
|||
|
||||
.. console::
|
||||
|
||||
sudo pkg_add -r bash cmake swig bison python perl
|
||||
sudo pkg_add -r bash cmake swig bison python perl py27-sqlite3
|
||||
|
||||
* Mac OS X:
|
||||
|
||||
|
@ -113,19 +113,15 @@ Using Pre-Built Binary Release Packages
|
|||
=======================================
|
||||
|
||||
See the `bro downloads page`_ for currently supported/targeted
|
||||
platforms for binary releases.
|
||||
platforms for binary releases and for installation instructions.
|
||||
|
||||
* RPM
|
||||
* Linux Packages
|
||||
|
||||
.. console::
|
||||
|
||||
sudo yum localinstall Bro-*.rpm
|
||||
|
||||
* DEB
|
||||
|
||||
.. console::
|
||||
|
||||
sudo gdebi Bro-*.deb
|
||||
Linux based binary installations are usually performed by adding
|
||||
information about the Bro packages to the respective system packaging
|
||||
tool. Theen the usual system utilities such as ``apt``, ``yum``
|
||||
or ``zyppper`` are used to perforn the installation. By default,
|
||||
installations of binary packages will go into ``/opt/bro``.
|
||||
|
||||
* MacOS Disk Image with Installer
|
||||
|
||||
|
@ -133,8 +129,6 @@ platforms for binary releases.
|
|||
Everything installed by the package will go into ``/opt/bro``.
|
||||
|
||||
The primary install prefix for binary packages is ``/opt/bro``.
|
||||
Non-MacOS packages that include BroControl also put variable/runtime
|
||||
data (e.g. Bro logs) in ``/var/opt/bro``.
|
||||
|
||||
Installing from Source
|
||||
==========================
|
||||
|
|
|
@ -363,7 +363,7 @@ decrypted from HTTP streams is stored in
|
|||
excerpt from :doc:`/scripts/base/protocols/http/main.bro` below.
|
||||
|
||||
.. btest-include:: ${BRO_SRC_ROOT}/scripts/base/protocols/http/main.bro
|
||||
:lines: 9-11,20-22,121
|
||||
:lines: 9-11,20-22,125
|
||||
|
||||
Because the constant was declared with the ``&redef`` attribute, if we
|
||||
needed to turn this option on globally, we could do so by adding the
|
||||
|
|
2
scripts/base/files/pe/__load__.bro
Normal file
2
scripts/base/files/pe/__load__.bro
Normal file
|
@ -0,0 +1,2 @@
|
|||
@load ./consts
|
||||
@load ./main
|
184
scripts/base/files/pe/consts.bro
Normal file
184
scripts/base/files/pe/consts.bro
Normal file
|
@ -0,0 +1,184 @@
|
|||
|
||||
module PE;
|
||||
|
||||
export {
|
||||
const machine_types: table[count] of string = {
|
||||
[0x00] = "UNKNOWN",
|
||||
[0x1d3] = "AM33",
|
||||
[0x8664] = "AMD64",
|
||||
[0x1c0] = "ARM",
|
||||
[0x1c4] = "ARMNT",
|
||||
[0xaa64] = "ARM64",
|
||||
[0xebc] = "EBC",
|
||||
[0x14c] = "I386",
|
||||
[0x200] = "IA64",
|
||||
[0x9041] = "M32R",
|
||||
[0x266] = "MIPS16",
|
||||
[0x366] = "MIPSFPU",
|
||||
[0x466] = "MIPSFPU16",
|
||||
[0x1f0] = "POWERPC",
|
||||
[0x1f1] = "POWERPCFP",
|
||||
[0x166] = "R4000",
|
||||
[0x1a2] = "SH3",
|
||||
[0x1a3] = "SH3DSP",
|
||||
[0x1a6] = "SH4",
|
||||
[0x1a8] = "SH5",
|
||||
[0x1c2] = "THUMB",
|
||||
[0x169] = "WCEMIPSV2"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const file_characteristics: table[count] of string = {
|
||||
[0x1] = "RELOCS_STRIPPED",
|
||||
[0x2] = "EXECUTABLE_IMAGE",
|
||||
[0x4] = "LINE_NUMS_STRIPPED",
|
||||
[0x8] = "LOCAL_SYMS_STRIPPED",
|
||||
[0x10] = "AGGRESSIVE_WS_TRIM",
|
||||
[0x20] = "LARGE_ADDRESS_AWARE",
|
||||
[0x80] = "BYTES_REVERSED_LO",
|
||||
[0x100] = "32BIT_MACHINE",
|
||||
[0x200] = "DEBUG_STRIPPED",
|
||||
[0x400] = "REMOVABLE_RUN_FROM_SWAP",
|
||||
[0x800] = "NET_RUN_FROM_SWAP",
|
||||
[0x1000] = "SYSTEM",
|
||||
[0x2000] = "DLL",
|
||||
[0x4000] = "UP_SYSTEM_ONLY",
|
||||
[0x8000] = "BYTES_REVERSED_HI"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const dll_characteristics: table[count] of string = {
|
||||
[0x40] = "DYNAMIC_BASE",
|
||||
[0x80] = "FORCE_INTEGRITY",
|
||||
[0x100] = "NX_COMPAT",
|
||||
[0x200] = "NO_ISOLATION",
|
||||
[0x400] = "NO_SEH",
|
||||
[0x800] = "NO_BIND",
|
||||
[0x2000] = "WDM_DRIVER",
|
||||
[0x8000] = "TERMINAL_SERVER_AWARE"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const windows_subsystems: table[count] of string = {
|
||||
[0] = "UNKNOWN",
|
||||
[1] = "NATIVE",
|
||||
[2] = "WINDOWS_GUI",
|
||||
[3] = "WINDOWS_CUI",
|
||||
[7] = "POSIX_CUI",
|
||||
[9] = "WINDOWS_CE_GUI",
|
||||
[10] = "EFI_APPLICATION",
|
||||
[11] = "EFI_BOOT_SERVICE_DRIVER",
|
||||
[12] = "EFI_RUNTIME_
DRIVER",
|
||||
[13] = "EFI_ROM",
|
||||
[14] = "XBOX"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const directories: table[count] of string = {
|
||||
[0] = "Export Table",
|
||||
[1] = "Import Table",
|
||||
[2] = "Resource Table",
|
||||
[3] = "Exception Table",
|
||||
[4] = "Certificate Table",
|
||||
[5] = "Base Relocation Table",
|
||||
[6] = "Debug",
|
||||
[7] = "Architecture",
|
||||
[8] = "Global Ptr",
|
||||
[9] = "TLS Table",
|
||||
[10] = "Load Config Table",
|
||||
[11] = "Bound Import",
|
||||
[12] = "IAT",
|
||||
[13] = "Delay Import Descriptor",
|
||||
[14] = "CLR Runtime Header",
|
||||
[15] = "Reserved"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const section_characteristics: table[count] of string = {
|
||||
[0x8] = "TYPE_NO_PAD",
|
||||
[0x20] = "CNT_CODE",
|
||||
[0x40] = "CNT_INITIALIZED_DATA",
|
||||
[0x80] = "CNT_UNINITIALIZED_DATA",
|
||||
[0x100] = "LNK_OTHER",
|
||||
[0x200] = "LNK_INFO",
|
||||
[0x800] = "LNK_REMOVE",
|
||||
[0x1000] = "LNK_COMDAT",
|
||||
[0x8000] = "GPREL",
|
||||
[0x20000] = "MEM_16BIT",
|
||||
[0x40000] = "MEM_LOCKED",
|
||||
[0x80000] = "MEM_PRELOAD",
|
||||
[0x100000] = "ALIGN_1BYTES",
|
||||
[0x200000] = "ALIGN_2BYTES",
|
||||
[0x300000] = "ALIGN_4BYTES",
|
||||
[0x400000] = "ALIGN_8BYTES",
|
||||
[0x500000] = "ALIGN_16BYTES",
|
||||
[0x600000] = "ALIGN_32BYTES",
|
||||
[0x700000] = "ALIGN_64BYTES",
|
||||
[0x800000] = "ALIGN_128BYTES",
|
||||
[0x900000] = "ALIGN_256BYTES",
|
||||
[0xa00000] = "ALIGN_512BYTES",
|
||||
[0xb00000] = "ALIGN_1024BYTES",
|
||||
[0xc00000] = "ALIGN_2048BYTES",
|
||||
[0xd00000] = "ALIGN_4096BYTES",
|
||||
[0xe00000] = "ALIGN_8192BYTES",
|
||||
[0x1000000] = "LNK_NRELOC_OVFL",
|
||||
[0x2000000] = "MEM_DISCARDABLE",
|
||||
[0x4000000] = "MEM_NOT_CACHED",
|
||||
[0x8000000] = "MEM_NOT_PAGED",
|
||||
[0x10000000] = "MEM_SHARED",
|
||||
[0x20000000] = "MEM_EXECUTE",
|
||||
[0x40000000] = "MEM_READ",
|
||||
[0x80000000] = "MEM_WRITE"
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const os_versions: table[count, count] of string = {
|
||||
[10,0] = "Windows 10",
|
||||
[6,4] = "Windows 10 Technical Preview",
|
||||
[6,3] = "Windows 8.1 or Server 2012 R2",
|
||||
[6,2] = "Windows 8 or Server 2012",
|
||||
[6,1] = "Windows 7 or Server 2008 R2",
|
||||
[6,0] = "Windows Vista or Server 2008",
|
||||
[5,2] = "Windows XP x64 or Server 2003",
|
||||
[5,1] = "Windows XP",
|
||||
[5,0] = "Windows 2000",
|
||||
[4,90] = "Windows Me",
|
||||
[4,10] = "Windows 98",
|
||||
[4,0] = "Windows 95 or NT 4.0",
|
||||
[3,51] = "Windows NT 3.51",
|
||||
[3,50] = "Windows NT 3.5",
|
||||
[3,2] = "Windows 3.2",
|
||||
[3,11] = "Windows for Workgroups 3.11",
|
||||
[3,10] = "Windows 3.1 or NT 3.1",
|
||||
[3,0] = "Windows 3.0",
|
||||
[2,11] = "Windows 2.11",
|
||||
[2,10] = "Windows 2.10",
|
||||
[2,0] = "Windows 2.0",
|
||||
[1,4] = "Windows 1.04",
|
||||
[1,3] = "Windows 1.03",
|
||||
[1,1] = "Windows 1.01",
|
||||
[1,0] = "Windows 1.0",
|
||||
} &default=function(i: count, j: count):string { return fmt("unknown-%d.%d", i, j); };
|
||||
|
||||
const section_descs: table[string] of string = {
|
||||
[".bss"] = "Uninitialized data",
|
||||
[".cormeta"] = "CLR metadata that indicates that the object file contains managed code",
|
||||
[".data"] = "Initialized data",
|
||||
[".debug$F"] = "Generated FPO debug information",
|
||||
[".debug$P"] = "Precompiled debug types",
|
||||
[".debug$S"] = "Debug symbols",
|
||||
[".debug$T"] = "Debug types",
|
||||
[".drective"] = "Linker options",
|
||||
[".edata"] = "Export tables",
|
||||
[".idata"] = "Import tables",
|
||||
[".idlsym"] = "Includes registered SEH to support IDL attributes",
|
||||
[".pdata"] = "Exception information",
|
||||
[".rdata"] = "Read-only initialized data",
|
||||
[".reloc"] = "Image relocations",
|
||||
[".rsrc"] = "Resource directory",
|
||||
[".sbss"] = "GP-relative uninitialized data",
|
||||
[".sdata"] = "GP-relative initialized data",
|
||||
[".srdata"] = "GP-relative read-only data",
|
||||
[".sxdata"] = "Registered exception handler data",
|
||||
[".text"] = "Executable code",
|
||||
[".tls"] = "Thread-local storage",
|
||||
[".tls$"] = "Thread-local storage",
|
||||
[".vsdata"] = "GP-relative initialized data",
|
||||
[".xdata"] = "Exception information",
|
||||
} &default=function(i: string):string { return fmt("unknown-%s", i); };
|
||||
|
||||
}
|
137
scripts/base/files/pe/main.bro
Normal file
137
scripts/base/files/pe/main.bro
Normal file
|
@ -0,0 +1,137 @@
|
|||
module PE;
|
||||
|
||||
@load ./consts.bro
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Current timestamp.
|
||||
ts: time &log;
|
||||
## File id of this portable executable file.
|
||||
id: string &log;
|
||||
## The target machine that the file was compiled for.
|
||||
machine: string &log &optional;
|
||||
## The time that the file was created at.
|
||||
compile_ts: time &log &optional;
|
||||
## The required operating system.
|
||||
os: string &log &optional;
|
||||
## The subsystem that is required to run this file.
|
||||
subsystem: string &log &optional;
|
||||
## Is the file an executable, or just an object file?
|
||||
is_exe: bool &log &default=T;
|
||||
## Is the file a 64-bit executable?
|
||||
is_64bit: bool &log &default=T;
|
||||
## Does the file support Address Space Layout Randomization?
|
||||
uses_aslr: bool &log &default=F;
|
||||
## Does the file support Data Execution Prevention?
|
||||
uses_dep: bool &log &default=F;
|
||||
## Does the file enforce code integrity checks?
|
||||
uses_code_integrity: bool &log &default=F;
|
||||
## Does the file use structured exception handing?
|
||||
uses_seh: bool &log &default=T;
|
||||
## Does the file have an import table?
|
||||
has_import_table: bool &log &optional;
|
||||
## Does the file have an export table?
|
||||
has_export_table: bool &log &optional;
|
||||
## Does the file have an attribute certificate table?
|
||||
has_cert_table: bool &log &optional;
|
||||
## Does the file have a debug table?
|
||||
has_debug_data: bool &log &optional;
|
||||
## The names of the sections, in order.
|
||||
section_names: vector of string &log &optional;
|
||||
};
|
||||
|
||||
## Event for accessing logged records.
|
||||
global log_pe: event(rec: Info);
|
||||
|
||||
## A hook that gets called when we first see a PE file.
|
||||
global set_file: hook(f: fa_file);
|
||||
}
|
||||
|
||||
redef record fa_file += {
|
||||
pe: Info &optional;
|
||||
};
|
||||
|
||||
const pe_mime_types = { "application/x-dosexec" };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Files::register_for_mime_types(Files::ANALYZER_PE, pe_mime_types);
|
||||
Log::create_stream(LOG, [$columns=Info, $ev=log_pe, $path="pe"]);
|
||||
}
|
||||
|
||||
hook set_file(f: fa_file) &priority=5
|
||||
{
|
||||
if ( ! f?$pe )
|
||||
f$pe = [$ts=network_time(), $id=f$id];
|
||||
}
|
||||
|
||||
event pe_dos_header(f: fa_file, h: PE::DOSHeader) &priority=5
|
||||
{
|
||||
hook set_file(f);
|
||||
}
|
||||
|
||||
event pe_file_header(f: fa_file, h: PE::FileHeader) &priority=5
|
||||
{
|
||||
hook set_file(f);
|
||||
|
||||
f$pe$machine = machine_types[h$machine];
|
||||
f$pe$compile_ts = h$ts;
|
||||
f$pe$is_exe = ( h$optional_header_size > 0 );
|
||||
|
||||
for ( c in h$characteristics )
|
||||
{
|
||||
if ( file_characteristics[c] == "32BIT_MACHINE" )
|
||||
f$pe$is_64bit = F;
|
||||
}
|
||||
}
|
||||
|
||||
event pe_optional_header(f: fa_file, h: PE::OptionalHeader) &priority=5
|
||||
{
|
||||
hook set_file(f);
|
||||
|
||||
# Only EXEs have optional headers
|
||||
if ( ! f$pe$is_exe )
|
||||
return;
|
||||
|
||||
f$pe$os = os_versions[h$os_version_major, h$os_version_minor];
|
||||
f$pe$subsystem = windows_subsystems[h$subsystem];
|
||||
|
||||
for ( c in h$dll_characteristics )
|
||||
{
|
||||
if ( dll_characteristics[c] == "DYNAMIC_BASE" )
|
||||
f$pe$uses_aslr = T;
|
||||
if ( dll_characteristics[c] == "FORCE_INTEGRITY" )
|
||||
f$pe$uses_code_integrity = T;
|
||||
if ( dll_characteristics[c] == "NX_COMPAT" )
|
||||
f$pe$uses_dep = T;
|
||||
if ( dll_characteristics[c] == "NO_SEH" )
|
||||
f$pe$uses_seh = F;
|
||||
}
|
||||
|
||||
f$pe$has_export_table = (|h$table_sizes| > 0 && h$table_sizes[0] > 0);
|
||||
f$pe$has_import_table = (|h$table_sizes| > 1 && h$table_sizes[1] > 0);
|
||||
f$pe$has_cert_table = (|h$table_sizes| > 4 && h$table_sizes[4] > 0);
|
||||
f$pe$has_debug_data = (|h$table_sizes| > 6 && h$table_sizes[6] > 0);
|
||||
}
|
||||
|
||||
event pe_section_header(f: fa_file, h: PE::SectionHeader) &priority=5
|
||||
{
|
||||
hook set_file(f);
|
||||
|
||||
# Only EXEs have section headers
|
||||
if ( ! f$pe$is_exe )
|
||||
return;
|
||||
|
||||
if ( ! f$pe?$section_names )
|
||||
f$pe$section_names = vector();
|
||||
f$pe$section_names[|f$pe$section_names|] = h$name;
|
||||
}
|
||||
|
||||
event file_state_remove(f: fa_file) &priority=-5
|
||||
{
|
||||
if ( f?$pe && f$pe?$machine )
|
||||
Log::write(LOG, f$pe);
|
||||
}
|
||||
|
|
@ -47,6 +47,9 @@ redef record Files::Info += {
|
|||
|
||||
event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) &priority=5
|
||||
{
|
||||
if ( ! f$info?$mime_type )
|
||||
f$info$mime_type = "application/pkix-cert";
|
||||
|
||||
f$info$x509 = [$ts=f$info$ts, $id=f$id, $certificate=cert, $handle=cert_ref];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
@load-sigs ./archive
|
||||
@load-sigs ./audio
|
||||
@load-sigs ./font
|
||||
@load-sigs ./general
|
||||
@load-sigs ./image
|
||||
@load-sigs ./msoffice
|
||||
@load-sigs ./libmagic
|
||||
@load-sigs ./video
|
||||
|
||||
@load-sigs ./libmagic
|
176
scripts/base/frameworks/files/magic/archive.sig
Normal file
176
scripts/base/frameworks/files/magic/archive.sig
Normal file
|
@ -0,0 +1,176 @@
|
|||
|
||||
signature file-tar {
|
||||
file-magic /^[[:print:]\x00]{100}([[:digit:]\x20]{7}\x00){3}([[:digit:]\x20]{11}\x00){2}([[:digit:]\x00\x20]{7}[\x20\x00])[0-7\x00]/
|
||||
file-mime "application/x-tar", 100
|
||||
}
|
||||
|
||||
# This is low priority so that files using zip as a
|
||||
# container will be identified correctly.
|
||||
signature file-zip {
|
||||
file-mime "application/zip", 10
|
||||
file-magic /^PK\x03\x04.{2}/
|
||||
}
|
||||
|
||||
# Multivolume Zip archive
|
||||
signature file-multi-zip {
|
||||
file-mime "application/zip", 10
|
||||
file-magic /^PK\x07\x08PK\x03\x04/
|
||||
}
|
||||
|
||||
# RAR
|
||||
signature file-rar {
|
||||
file-mime "application/x-rar", 70
|
||||
file-magic /^Rar!/
|
||||
}
|
||||
|
||||
# GZIP
|
||||
signature file-gzip {
|
||||
file-mime "application/x-gzip", 100
|
||||
file-magic /\x1f\x8b/
|
||||
}
|
||||
|
||||
# Microsoft Cabinet
|
||||
signature file-ms-cab {
|
||||
file-mime "application/vnd.ms-cab-compressed", 110
|
||||
file-magic /^MSCF\x00\x00\x00\x00/
|
||||
}
|
||||
|
||||
# Mac OS X DMG files
|
||||
signature file-dmg {
|
||||
file-magic /^(\x78\x01\x73\x0D\x62\x62\x60|\x78\xDA\x63\x60\x18\x05|\x78\x01\x63\x60\x18\x05|\x78\xDA\x73\x0D|\x78[\x01\xDA]\xED[\xD0-\xD9])/
|
||||
file-mime "application/x-dmg", 100
|
||||
}
|
||||
|
||||
# XAR (eXtensible ARchive) format.
|
||||
# Mac OS X uses this for the .pkg format.
|
||||
signature file-xar {
|
||||
file-magic /^xar\!/
|
||||
file-mime "application/x-xar", 100
|
||||
}
|
||||
|
||||
# RPM
|
||||
signature file-magic-auto352 {
|
||||
file-mime "application/x-rpm", 70
|
||||
file-magic /^(drpm|\xed\xab\xee\xdb)/
|
||||
}
|
||||
|
||||
# StuffIt
|
||||
signature file-stuffit {
|
||||
file-mime "application/x-stuffit", 70
|
||||
file-magic /^(SIT\x21|StuffIt)/
|
||||
}
|
||||
|
||||
# Archived data
|
||||
signature file-x-archive {
|
||||
file-mime "application/x-archive", 70
|
||||
file-magic /^!?<ar(ch)?>/
|
||||
}
|
||||
|
||||
# ARC archive data
|
||||
signature file-arc {
|
||||
file-mime "application/x-arc", 70
|
||||
file-magic /^[\x00-\x7f]{2}[\x02-\x0a\x14\x48]\x1a/
|
||||
}
|
||||
|
||||
# EET archive
|
||||
signature file-eet {
|
||||
file-mime "application/x-eet", 70
|
||||
file-magic /^\x1e\xe7\xff\x00/
|
||||
}
|
||||
|
||||
# Zoo archive
|
||||
signature file-zoo {
|
||||
file-mime "application/x-zoo", 70
|
||||
file-magic /^.{20}\xdc\xa7\xc4\xfd/
|
||||
}
|
||||
|
||||
# LZ4 compressed data (legacy format)
|
||||
signature file-lz4-legacy {
|
||||
file-mime "application/x-lz4", 70
|
||||
file-magic /(\x02\x21\x4c\x18)/
|
||||
}
|
||||
|
||||
# LZ4 compressed data
|
||||
signature file-lz4 {
|
||||
file-mime "application/x-lz4", 70
|
||||
file-magic /^\x04\x22\x4d\x18/
|
||||
}
|
||||
|
||||
# LRZIP compressed data
|
||||
signature file-lrzip {
|
||||
file-mime "application/x-lrzip", 1
|
||||
file-magic /^LRZI/
|
||||
}
|
||||
|
||||
# LZIP compressed data
|
||||
signature file-lzip {
|
||||
file-mime "application/x-lzip", 70
|
||||
file-magic /^LZIP/
|
||||
}
|
||||
|
||||
# Self-extracting PKZIP archive
|
||||
signature file-magic-auto434 {
|
||||
file-mime "application/zip", 340
|
||||
file-magic /^MZ.{28}(Copyright 1989\x2d1990 PKWARE Inc|PKLITE Copr)\x2e/
|
||||
}
|
||||
|
||||
# LHA archive (LZH)
|
||||
signature file-lzh {
|
||||
file-mime "application/x-lzh", 80
|
||||
file-magic /^.{2}-(lh[ abcdex0-9]|lz[s2-8]|lz[s2-8]|pm[s012]|pc1)-/
|
||||
}
|
||||
|
||||
# WARC Archive
|
||||
signature file-warc {
|
||||
file-mime "application/warc", 50
|
||||
file-magic /^WARC\x2f/
|
||||
}
|
||||
|
||||
# 7-zip archive data
|
||||
signature file-7zip {
|
||||
file-mime "application/x-7z-compressed", 50
|
||||
file-magic /^7z\xbc\xaf\x27\x1c/
|
||||
}
|
||||
|
||||
# XZ compressed data
|
||||
signature file-xz {
|
||||
file-mime "application/x-xz", 90
|
||||
file-magic /^\xfd7zXZ\x00/
|
||||
}
|
||||
|
||||
# LHa self-extracting archive
|
||||
signature file-magic-auto436 {
|
||||
file-mime "application/x-lha", 120
|
||||
file-magic /^MZ.{34}LH[aA]\x27s SFX/
|
||||
}
|
||||
|
||||
# ARJ archive data
|
||||
signature file-arj {
|
||||
file-mime "application/x-arj", 50
|
||||
file-magic /^\x60\xea/
|
||||
}
|
||||
|
||||
# Byte-swapped cpio archive
|
||||
signature file-bs-cpio {
|
||||
file-mime "application/x-cpio", 50
|
||||
file-magic /(\x71\xc7|\xc7\x71)/
|
||||
}
|
||||
|
||||
# CPIO archive
|
||||
signature file-cpio {
|
||||
file-mime "application/x-cpio", 50
|
||||
file-magic /^(\xc7\x71|\x71\xc7)/
|
||||
}
|
||||
|
||||
# Compress'd data
|
||||
signature file-compress {
|
||||
file-mime "application/x-compress", 50
|
||||
file-magic /^\x1f\x9d/
|
||||
}
|
||||
|
||||
# LZMA compressed data
|
||||
signature file-lzma {
|
||||
file-mime "application/x-lzma", 71
|
||||
file-magic /^\x5d\x00\x00/
|
||||
}
|
||||
|
13
scripts/base/frameworks/files/magic/audio.sig
Normal file
13
scripts/base/frameworks/files/magic/audio.sig
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
# MPEG v3 audio
|
||||
signature file-mpeg-audio {
|
||||
file-mime "audio/mpeg", 20
|
||||
file-magic /^\xff[\xe2\xe3\xf2\xf3\xf6\xf7\xfa\xfb\xfc\xfd]/
|
||||
}
|
||||
|
||||
# MPEG v4 audio
|
||||
signature file-m4a {
|
||||
file-mime "audio/m4a", 70
|
||||
file-magic /^....ftyp(m4a)/
|
||||
}
|
||||
|
41
scripts/base/frameworks/files/magic/font.sig
Normal file
41
scripts/base/frameworks/files/magic/font.sig
Normal file
|
@ -0,0 +1,41 @@
|
|||
|
||||
# Web Open Font Format
|
||||
signature file-woff {
|
||||
file-magic /^wOFF/
|
||||
file-mime "application/font-woff", 70
|
||||
}
|
||||
|
||||
# TrueType font
|
||||
signature file-ttf {
|
||||
file-mime "application/x-font-ttf", 80
|
||||
file-magic /^\x00\x01\x00\x00\x00/
|
||||
}
|
||||
|
||||
signature file-embedded-opentype {
|
||||
file-mime "application/vnd.ms-fontobject", 50
|
||||
file-magic /^.{34}LP/
|
||||
}
|
||||
|
||||
# X11 SNF font
|
||||
signature file-snf {
|
||||
file-mime "application/x-font-sfn", 70
|
||||
file-magic /^(\x04\x00\x00\x00|\x00\x00\x00\x04).{100}(\x04\x00\x00\x00|\x00\x00\x00\x04)/
|
||||
}
|
||||
|
||||
# OpenType font
|
||||
signature file-opentype {
|
||||
file-mime "application/vnd.ms-opentype", 70
|
||||
file-magic /^OTTO/
|
||||
}
|
||||
|
||||
# FrameMaker Font file
|
||||
signature file-maker-screen-font {
|
||||
file-mime "application/x-mif", 190
|
||||
file-magic /^\x3cMakerScreenFont/
|
||||
}
|
||||
|
||||
# >0 string,=SplineFontDB: (len=13), ["Spline Font Database "], swap_endian=0
|
||||
signature file-spline-font-db {
|
||||
file-mime "application/vnd.font-fontforge-sfd", 160
|
||||
file-magic /^SplineFontDB\x3a/
|
||||
}
|
|
@ -1,18 +1,87 @@
|
|||
# General purpose file magic signatures.
|
||||
|
||||
# Plaintext
|
||||
# (Including BOMs for UTF-8, 16, and 32)
|
||||
signature file-plaintext {
|
||||
file-magic /^([[:print:][:space:]]{10})/
|
||||
file-mime "text/plain", -20
|
||||
file-mime "text/plain", -20
|
||||
file-magic /^(\xef\xbb\xbf|(\x00\x00)?\xfe\xff|\xff\xfe(\x00\x00)?)?[[:space:]\x20-\x7E]{10}/
|
||||
}
|
||||
|
||||
signature file-tar {
|
||||
file-magic /^[[:print:]\x00]{100}([[:digit:]\x20]{7}\x00){3}([[:digit:]\x20]{11}\x00){2}([[:digit:]\x00\x20]{7}[\x20\x00])[0-7\x00]/
|
||||
file-mime "application/x-tar", 100
|
||||
signature file-json {
|
||||
file-mime "text/json", 1
|
||||
file-magic /^(\xef\xbb\xbf)?[\x0d\x0a[:blank:]]*\{[\x0d\x0a[:blank:]]*(["][^"]{1,}["]|[a-zA-Z][a-zA-Z0-9\\_]*)[\x0d\x0a[:blank:]]*:[\x0d\x0a[:blank:]]*(["]|\[|\{|[0-9]|true|false)/
|
||||
}
|
||||
|
||||
signature file-zip {
|
||||
file-mime "application/zip", 10
|
||||
file-magic /^PK\x03\x04.{2}/
|
||||
signature file-json2 {
|
||||
file-mime "text/json", 1
|
||||
file-magic /^(\xef\xbb\xbf)?[\x0d\x0a[:blank:]]*\[[\x0d\x0a[:blank:]]*(((["][^"]{1,}["]|[0-9]{1,}(\.[0-9]{1,})?|true|false)[\x0d\x0a[:blank:]]*,)|\{|\[)[\x0d\x0a[:blank:]]*/
|
||||
}
|
||||
|
||||
# Match empty JSON documents.
|
||||
signature file-json3 {
|
||||
file-mime "text/json", 0
|
||||
file-magic /^(\xef\xbb\xbf)?[\x0d\x0a[:blank:]]*(\[\]|\{\})[\x0d\x0a[:blank:]]*$/
|
||||
}
|
||||
|
||||
signature file-xml {
|
||||
file-mime "application/xml", 10
|
||||
file-magic /^(\xef\xbb\xbf)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*<\?xml /
|
||||
}
|
||||
|
||||
signature file-xhtml {
|
||||
file-mime "text/html", 100
|
||||
file-magic /^(\xef\xbb\xbf)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*(<\?xml .*\?>)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*<(![dD][oO][cC][tT][yY][pP][eE] {1,}[hH][tT][mM][lL]|[hH][tT][mM][lL]|[mM][eE][tT][aA] {1,}[hH][tT][tT][pP]-[eE][qQ][uU][iI][vV])/
|
||||
}
|
||||
|
||||
signature file-html {
|
||||
file-mime "text/html", 49
|
||||
file-magic /^(\xef\xbb\xbf)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*(<\?xml .*\?>)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*<![dD][oO][cC][tT][yY][pP][eE] {1,}[hH][tT][mM][lL]/
|
||||
}
|
||||
|
||||
signature file-html2 {
|
||||
file-mime "text/html", 20
|
||||
file-magic /^(\xef\xbb\xbf)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*(<\?xml .*\?>)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*<([hH][eE][aA][dD]|[hH][tT][mM][lL]|[tT][iI][tT][lL][eE]|[bB][oO][dD][yY])/
|
||||
}
|
||||
|
||||
signature file-rss {
|
||||
file-mime "text/rss", 90
|
||||
file-magic /^(\xef\xbb\xbf)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*(<\?xml .*\?>)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*<[rR][sS][sS]/
|
||||
}
|
||||
|
||||
signature file-atom {
|
||||
file-mime "text/atom", 100
|
||||
file-magic /^(\xef\xbb\xbf)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*(<\?xml .*\?>)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*<([rR][sS][sS][^>]*xmlns:atom|[fF][eE][eE][dD][^>]*xmlns=["']?http:\/\/www.w3.org\/2005\/Atom["']?)/
|
||||
}
|
||||
|
||||
signature file-soap {
|
||||
file-mime "application/soap+xml", 49
|
||||
file-magic /^(\xef\xbb\xbf)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*(<\?xml .*\?>)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*<[sS][oO][aA][pP](-[eE][nN][vV])?:[eE][nN][vV][eE][lL][oO][pP][eE]/
|
||||
}
|
||||
|
||||
signature file-cross-domain-policy {
|
||||
file-mime "text/x-cross-domain-policy", 49
|
||||
file-magic /^([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*(<\?xml .*\?>)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*<![dD][oO][cC][tT][yY][pP][eE] {1,}[cC][rR][oO][sS][sS]-[dD][oO][mM][aA][iI][nN]-[pP][oO][lL][iI][cC][yY]/
|
||||
}
|
||||
|
||||
signature file-cross-domain-policy2 {
|
||||
file-mime "text/x-cross-domain-policy", 49
|
||||
file-magic /^([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*(<\?xml .*\?>)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*<[cC][rR][oO][sS][sS]-[dD][oO][mM][aA][iI][nN]-[pP][oO][lL][iI][cC][yY]/
|
||||
}
|
||||
|
||||
signature file-xmlrpc {
|
||||
file-mime "application/xml-rpc", 49
|
||||
file-magic /^(\xef\xbb\xbf)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*(<\?xml .*\?>)?([\x0d\x0a[:blank:]]*(<!--.*-->)?[\x0d\x0a[:blank:]]*)*<[mM][eE][tT][hH][oO][dD][rR][eE][sS][pP][oO][nN][sS][eE]>/
|
||||
}
|
||||
|
||||
signature file-coldfusion {
|
||||
file-mime "magnus-internal/cold-fusion", 20
|
||||
file-magic /^([\x0d\x0a[:blank:]]*(<!--.*-->)?)*<(CFPARAM|CFSET|CFIF)/
|
||||
}
|
||||
|
||||
# Microsoft LNK files
|
||||
signature file-lnk {
|
||||
file-mime "application/x-ms-shortcut", 49
|
||||
file-magic /^\x4C\x00\x00\x00\x01\x14\x02\x00\x00\x00\x00\x00\xC0\x00\x00\x00\x00\x10\x00\x00\x00\x46/
|
||||
}
|
||||
|
||||
signature file-jar {
|
||||
|
@ -21,8 +90,20 @@ signature file-jar {
|
|||
}
|
||||
|
||||
signature file-java-applet {
|
||||
file-magic /^\xca\xfe\xba\xbe...[\x2e-\x34]/
|
||||
file-mime "application/x-java-applet", 71
|
||||
file-magic /^\xca\xfe\xba\xbe...[\x2d-\x34]/
|
||||
}
|
||||
|
||||
# OCSP requests over HTTP.
|
||||
signature file-ocsp-request {
|
||||
file-magic /^.{11,19}\x06\x05\x2b\x0e\x03\x02\x1a/
|
||||
file-mime "application/ocsp-request", 71
|
||||
}
|
||||
|
||||
# OCSP responses over HTTP.
|
||||
signature file-ocsp-response {
|
||||
file-magic /^.{11,19}\x06\x09\x2B\x06\x01\x05\x05\x07\x30\x01\x01/
|
||||
file-mime "application/ocsp-response", 71
|
||||
}
|
||||
|
||||
# Shockwave flash
|
||||
|
@ -37,12 +118,6 @@ signature file-tnef {
|
|||
file-mime "application/vnd.ms-tnef", 100
|
||||
}
|
||||
|
||||
# Mac OS X DMG files
|
||||
signature file-dmg {
|
||||
file-magic /^(\x78\x01\x73\x0D\x62\x62\x60|\x78\xDA\x63\x60\x18\x05|\x78\x01\x63\x60\x18\x05|\x78\xDA\x73\x0D|\x78[\x01\xDA]\xED[\xD0-\xD9])/
|
||||
file-mime "application/x-dmg", 100
|
||||
}
|
||||
|
||||
# Mac OS X Mach-O executable
|
||||
signature file-mach-o {
|
||||
file-magic /^[\xce\xcf]\xfa\xed\xfe/
|
||||
|
@ -55,13 +130,6 @@ signature file-mach-o-universal {
|
|||
file-mime "application/x-mach-o-executable", 100
|
||||
}
|
||||
|
||||
# XAR (eXtensible ARchive) format.
|
||||
# Mac OS X uses this for the .pkg format.
|
||||
signature file-xar {
|
||||
file-magic /^xar\!/
|
||||
file-mime "application/x-xar", 100
|
||||
}
|
||||
|
||||
signature file-pkcs7 {
|
||||
file-magic /^MIME-Version:.*protocol=\"application\/pkcs7-signature\"/
|
||||
file-mime "application/pkcs7-signature", 100
|
||||
|
@ -79,16 +147,6 @@ signature file-jnlp {
|
|||
file-mime "application/x-java-jnlp-file", 100
|
||||
}
|
||||
|
||||
signature file-ico {
|
||||
file-magic /^\x00\x00\x01\x00/
|
||||
file-mime "image/x-icon", 70
|
||||
}
|
||||
|
||||
signature file-cur {
|
||||
file-magic /^\x00\x00\x02\x00/
|
||||
file-mime "image/x-cursor", 70
|
||||
}
|
||||
|
||||
signature file-pcap {
|
||||
file-magic /^(\xa1\xb2\xc3\xd4|\xd4\xc3\xb2\xa1)/
|
||||
file-mime "application/vnd.tcpdump.pcap", 70
|
||||
|
@ -119,7 +177,58 @@ signature file-python {
|
|||
file-mime "text/x-python", 60
|
||||
}
|
||||
|
||||
signature file-awk {
|
||||
file-mime "text/x-awk", 60
|
||||
file-magic /^\x23\x21[^\n]{1,15}bin\/(env[[:space:]]+)?(g|n)?awk/
|
||||
}
|
||||
|
||||
signature file-tcl {
|
||||
file-mime "text/x-tcl", 60
|
||||
file-magic /^\x23\x21[^\n]{1,15}bin\/(env[[:space:]]+)?(wish|tcl)/
|
||||
}
|
||||
|
||||
signature file-lua {
|
||||
file-mime "text/x-lua", 49
|
||||
file-magic /^\x23\x21[^\n]{1,15}bin\/(env[[:space:]]+)?lua/
|
||||
}
|
||||
|
||||
signature file-javascript {
|
||||
file-mime "application/javascript", 60
|
||||
file-magic /^\x23\x21[^\n]{1,15}bin\/(env[[:space:]]+)?node(js)?/
|
||||
}
|
||||
|
||||
signature file-javascript2 {
|
||||
file-mime "application/javascript", 60
|
||||
file-magic /^[\x0d\x0a[:blank:]]*<[sS][cC][rR][iI][pP][tT][[:blank:]]+([tT][yY][pP][eE]|[lL][aA][nN][gG][uU][aA][gG][eE])=['"]?([tT][eE][xX][tT]\/)?[jJ][aA][vV][aA][sS][cC][rR][iI][pP][tT]/
|
||||
}
|
||||
|
||||
signature file-javascript3 {
|
||||
file-mime "application/javascript", 60
|
||||
# This seems to be a somewhat common idiom in javascript.
|
||||
file-magic /^[\x0d\x0a[:blank:]]*for \(;;\);/
|
||||
}
|
||||
|
||||
signature file-javascript4 {
|
||||
file-mime "application/javascript", 60
|
||||
file-magic /^[\x0d\x0a[:blank:]]*document\.write(ln)?[:blank:]?\(/
|
||||
}
|
||||
|
||||
signature file-javascript5 {
|
||||
file-mime "application/javascript", 60
|
||||
file-magic /^\(function\(\)[[:blank:]\n]*\{/
|
||||
}
|
||||
|
||||
signature file-javascript6 {
|
||||
file-mime "application/javascript", 60
|
||||
file-magic /^[\x0d\x0a[:blank:]]*<script>[\x0d\x0a[:blank:]]*(var|function) /
|
||||
}
|
||||
|
||||
signature file-php {
|
||||
file-mime "text/x-php", 60
|
||||
file-magic /^\x23\x21[^\n]{1,15}bin\/(env[[:space:]]+)?php/
|
||||
}
|
||||
|
||||
signature file-php2 {
|
||||
file-magic /^.*<\?php/
|
||||
file-mime "text/x-php", 40
|
||||
}
|
||||
|
@ -135,3 +244,23 @@ signature file-skp {
|
|||
file-magic /^\xFF\xFE\xFF\x0E\x53\x00\x6B\x00\x65\x00\x74\x00\x63\x00\x68\x00\x55\x00\x70\x00\x20\x00\x4D\x00\x6F\x00\x64\x00\x65\x00\x6C\x00/
|
||||
file-mime "application/skp", 100
|
||||
}
|
||||
|
||||
signature file-elf-object {
|
||||
file-mime "application/x-object", 50
|
||||
file-magic /\x7fELF[\x01\x02](\x01.{10}\x01\x00|\x02.{10}\x00\x01)/
|
||||
}
|
||||
|
||||
signature file-elf {
|
||||
file-mime "application/x-executable", 50
|
||||
file-magic /\x7fELF[\x01\x02](\x01.{10}\x02\x00|\x02.{10}\x00\x02)/
|
||||
}
|
||||
|
||||
signature file-elf-sharedlib {
|
||||
file-mime "application/x-sharedlib", 50
|
||||
file-magic /\x7fELF[\x01\x02](\x01.{10}\x03\x00|\x02.{10}\x00\x03)/
|
||||
}
|
||||
|
||||
signature file-elf-coredump {
|
||||
file-mime "application/x-coredump", 50
|
||||
file-magic /\x7fELF[\x01\x02](\x01.{10}\x04\x00|\x02.{10}\x00\x04)/
|
||||
}
|
||||
|
|
166
scripts/base/frameworks/files/magic/image.sig
Normal file
166
scripts/base/frameworks/files/magic/image.sig
Normal file
|
@ -0,0 +1,166 @@
|
|||
|
||||
signature file-tiff {
|
||||
file-mime "image/tiff", 70
|
||||
file-magic /^(MM\x00[\x2a\x2b]|II[\x2a\x2b]\x00)/
|
||||
}
|
||||
|
||||
signature file-gif {
|
||||
file-mime "image/gif", 70
|
||||
file-magic /^GIF8/
|
||||
}
|
||||
|
||||
# JPEG image
|
||||
signature file-jpeg {
|
||||
file-mime "image/jpeg", 52
|
||||
file-magic /^\xff\xd8/
|
||||
}
|
||||
|
||||
signature file-bmp {
|
||||
file-mime "image/x-ms-bmp", 50
|
||||
file-magic /BM.{12}[\x0c\x28\x40\x6c\x7c\x80]\x00/
|
||||
}
|
||||
|
||||
signature file-ico {
|
||||
file-magic /^\x00\x00\x01\x00/
|
||||
file-mime "image/x-icon", 70
|
||||
}
|
||||
|
||||
signature file-cur {
|
||||
file-magic /^\x00\x00\x02\x00/
|
||||
file-mime "image/x-cursor", 70
|
||||
}
|
||||
|
||||
signature file-magic-auto289 {
|
||||
file-mime "image/vnd.adobe.photoshop", 70
|
||||
file-magic /^8BPS/
|
||||
}
|
||||
|
||||
signature file-png {
|
||||
file-mime "image/png", 110
|
||||
file-magic /^\x89PNG/
|
||||
}
|
||||
|
||||
# JPEG 2000
|
||||
signature file-jp2 {
|
||||
file-mime "image/jp2", 60
|
||||
file-magic /.{4}ftypjp2/
|
||||
}
|
||||
|
||||
# JPEG 2000
|
||||
signature file-jp22 {
|
||||
file-mime "image/jp2", 70
|
||||
file-magic /\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a.{8}jp2 /
|
||||
}
|
||||
|
||||
# JPEG 2000
|
||||
signature file-jpx {
|
||||
file-mime "image/jpx", 70
|
||||
file-magic /\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a.{8}jpx /
|
||||
}
|
||||
|
||||
# JPEG 2000
|
||||
signature file-jpm {
|
||||
file-mime "image/jpm", 70
|
||||
file-magic /\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a.{8}jpm /
|
||||
}
|
||||
|
||||
# Xcursor image
|
||||
signature file-x-cursor {
|
||||
file-mime "image/x-xcursor", 70
|
||||
file-magic /^Xcur/
|
||||
}
|
||||
|
||||
# NIFF image
|
||||
signature file-niff {
|
||||
file-mime "image/x-niff", 70
|
||||
file-magic /^IIN1/
|
||||
}
|
||||
|
||||
# OpenEXR image
|
||||
signature file-openexr {
|
||||
file-mime "image/x-exr", 70
|
||||
file-magic /^\x76\x2f\x31\x01/
|
||||
}
|
||||
|
||||
# DPX image
|
||||
signature file-dpx {
|
||||
file-mime "image/x-dpx", 70
|
||||
file-magic /^SDPX/
|
||||
}
|
||||
|
||||
# Cartesian Perceptual Compression image
|
||||
signature file-cpi {
|
||||
file-mime "image/x-cpi", 70
|
||||
file-magic /(CPC\xb2)/
|
||||
}
|
||||
|
||||
signature file-orf {
|
||||
file-mime "image/x-olympus-orf", 70
|
||||
file-magic /IIR[OS]|MMOR/
|
||||
}
|
||||
|
||||
# Foveon X3F raw image
|
||||
signature file-x3r {
|
||||
file-mime "image/x-x3f", 70
|
||||
file-magic /^FOVb/
|
||||
}
|
||||
|
||||
# Paint.NET image
|
||||
signature file-paint-net {
|
||||
file-mime "image/x-paintnet", 70
|
||||
file-magic /^PDN3/
|
||||
}
|
||||
|
||||
# Corel Draw Picture
|
||||
signature file-coreldraw {
|
||||
file-mime "image/x-coreldraw", 70
|
||||
file-magic /^RIFF....CDR[A6]/
|
||||
}
|
||||
|
||||
# Netpbm PAM image
|
||||
signature file-netbpm{
|
||||
file-mime "image/x-portable-pixmap", 50
|
||||
file-magic /^P7/
|
||||
}
|
||||
|
||||
# JPEG 2000 image
|
||||
signature file-jpeg-2000 {
|
||||
file-mime "image/jp2", 50
|
||||
file-magic /^....jP/
|
||||
}
|
||||
|
||||
# DjVU Images
|
||||
signature file-djvu {
|
||||
file-mime "image/vnd.djvu", 70
|
||||
file-magic /AT\x26TFORM.{4}(DJV[MUI]|THUM)/
|
||||
}
|
||||
|
||||
# DWG AutoDesk AutoCAD
|
||||
signature file-dwg {
|
||||
file-mime "image/vnd.dwg", 90
|
||||
file-magic /^(AC[12]\.|AC10)/
|
||||
}
|
||||
|
||||
# GIMP XCF image
|
||||
signature file-gimp-xcf {
|
||||
file-mime "image/x-xcf", 110
|
||||
file-magic /^gimp xcf/
|
||||
}
|
||||
|
||||
# Polar Monitor Bitmap text
|
||||
signature file-polar-monitor-bitmap {
|
||||
file-mime "image/x-polar-monitor-bitmap", 160
|
||||
file-magic /^\x5bBitmapInfo2\x5d/
|
||||
}
|
||||
|
||||
# Award BIOS bitmap
|
||||
signature file-award-bitmap {
|
||||
file-mime "image/x-award-bmp", 20
|
||||
file-magic /^AWBM/
|
||||
}
|
||||
|
||||
# Award BIOS Logo, 136 x 84
|
||||
signature file-award-bios-logo {
|
||||
file-mime "image/x-award-bioslogo", 50
|
||||
file-magic /^\x11[\x06\x09]/
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -26,3 +26,9 @@ signature file-pptx {
|
|||
file-magic /^PK\x03\x04.{26}(\[Content_Types\]\.xml|_rels\x2f\.rels|ppt\x2f).*PK\x03\x04.{26}ppt\x2f/
|
||||
file-mime "application/vnd.openxmlformats-officedocument.presentationml.presentation", 80
|
||||
}
|
||||
|
||||
signature file-msaccess {
|
||||
file-mime "application/x-msaccess", 180
|
||||
file-magic /.{4}Standard (Jet|ACE) DB\x00/
|
||||
}
|
||||
|
||||
|
|
96
scripts/base/frameworks/files/magic/video.sig
Normal file
96
scripts/base/frameworks/files/magic/video.sig
Normal file
|
@ -0,0 +1,96 @@
|
|||
|
||||
# Macromedia Flash Video
|
||||
signature file-flv {
|
||||
file-mime "video/x-flv", 60
|
||||
file-magic /^FLV/
|
||||
}
|
||||
|
||||
# FLI animation
|
||||
signature file-fli {
|
||||
file-mime "video/x-fli", 50
|
||||
file-magic /^.{4}\x11\xaf/
|
||||
}
|
||||
|
||||
# FLC animation
|
||||
signature file-flc {
|
||||
file-mime "video/x-flc", 50
|
||||
file-magic /^.{4}\x12\xaf/
|
||||
}
|
||||
|
||||
# Motion JPEG 2000
|
||||
signature file-mj2 {
|
||||
file-mime "video/mj2", 70
|
||||
file-magic /\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a.{8}mjp2/
|
||||
}
|
||||
|
||||
# MNG video
|
||||
signature file-mng {
|
||||
file-mime "video/x-mng", 70
|
||||
file-magic /^\x8aMNG/
|
||||
}
|
||||
|
||||
# JNG video
|
||||
signature file-jng {
|
||||
file-mime "video/x-jng", 70
|
||||
file-magic /^\x8bJNG/
|
||||
}
|
||||
|
||||
# Generic MPEG container
|
||||
signature file-mpeg {
|
||||
file-mime "video/mpeg", 50
|
||||
file-magic /(\x00\x00\x01[\xb0-\xbb])/
|
||||
}
|
||||
|
||||
# MPV
|
||||
signature file-mpv {
|
||||
file-mime "video/mpv", 71
|
||||
file-magic /(\x00\x00\x01\xb3)/
|
||||
}
|
||||
|
||||
# H.264
|
||||
signature file-h264 {
|
||||
file-mime "video/h264", 41
|
||||
file-magic /(\x00\x00\x00\x01)([\x07\x27\x47\x67\x87\xa7\xc7\xe7])/
|
||||
}
|
||||
|
||||
# WebM video
|
||||
signature file-webm {
|
||||
file-mime "video/webm", 70
|
||||
file-magic /(\x1a\x45\xdf\xa3)(.*)(B\x82)(.{1})(webm)/
|
||||
}
|
||||
|
||||
# Matroska video
|
||||
signature file-matroska {
|
||||
file-mime "video/x-matroska", 110
|
||||
file-magic /(\x1a\x45\xdf\xa3)(.*)(B\x82)(.{1})(matroska)/
|
||||
}
|
||||
|
||||
# MP2P
|
||||
signature file-mp2p {
|
||||
file-mime "video/mp2p", 21
|
||||
file-magic /\x00\x00\x01\xba([\x40-\x7f\xc0-\xff])/
|
||||
}
|
||||
|
||||
# Silicon Graphics video
|
||||
signature file-sgi-movie {
|
||||
file-mime "video/x-sgi-movie", 70
|
||||
file-magic /^MOVI/
|
||||
}
|
||||
|
||||
# Apple QuickTime movie
|
||||
signature file-quicktime {
|
||||
file-mime "video/quicktime", 70
|
||||
file-magic /^....(mdat|moov)/
|
||||
}
|
||||
|
||||
# MPEG v4 video
|
||||
signature file-mp4 {
|
||||
file-mime "video/mp4", 70
|
||||
file-magic /^....ftyp(isom|mp4[12])/
|
||||
}
|
||||
|
||||
# 3GPP Video
|
||||
signature file-3gpp {
|
||||
file-mime "video/3gpp", 60
|
||||
file-magic /^....ftyp(3g[egps2]|avc1|mmp4)/
|
||||
}
|
|
@ -129,12 +129,11 @@ export {
|
|||
## files based on the detected mime type of the file.
|
||||
const analyze_by_mime_type_automatically = T &redef;
|
||||
|
||||
## The default setting for if the file reassembler is enabled for
|
||||
## each file.
|
||||
## The default setting for file reassembly.
|
||||
const enable_reassembler = T &redef;
|
||||
|
||||
## The default per-file reassembly buffer size.
|
||||
const reassembly_buffer_size = 1048576 &redef;
|
||||
const reassembly_buffer_size = 524288 &redef;
|
||||
|
||||
## Allows the file reassembler to be used if it's necessary because the
|
||||
## file is transferred out of order.
|
||||
|
@ -484,16 +483,19 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori
|
|||
add f$info$rx_hosts[f$is_orig ? cid$resp_h : cid$orig_h];
|
||||
}
|
||||
|
||||
event file_mime_type(f: fa_file, mime_type: string) &priority=10
|
||||
event file_sniff(f: fa_file, meta: fa_metadata) &priority=10
|
||||
{
|
||||
set_info(f);
|
||||
|
||||
f$info$mime_type = mime_type;
|
||||
if ( ! meta?$mime_type )
|
||||
return;
|
||||
|
||||
f$info$mime_type = meta$mime_type;
|
||||
|
||||
if ( analyze_by_mime_type_automatically &&
|
||||
mime_type in mime_type_to_analyzers )
|
||||
meta$mime_type in mime_type_to_analyzers )
|
||||
{
|
||||
local analyzers = mime_type_to_analyzers[mime_type];
|
||||
local analyzers = mime_type_to_analyzers[meta$mime_type];
|
||||
for ( a in analyzers )
|
||||
{
|
||||
add f$info$analyzers[Files::analyzer_name(a)];
|
||||
|
|
|
@ -345,8 +345,6 @@ type connection: record {
|
|||
## to parse the same data. If so, all will be recorded. Also note that
|
||||
## the recorded services are independent of any transport-level protocols.
|
||||
service: set[string];
|
||||
addl: string; ##< Deprecated.
|
||||
hot: count; ##< Deprecated.
|
||||
history: string; ##< State history of connections. See *history* in :bro:see:`Conn::Info`.
|
||||
## A globally unique connection identifier. For each connection, Bro
|
||||
## creates an ID that is very likely unique across independent Bro runs.
|
||||
|
@ -426,6 +424,14 @@ type fa_file: record {
|
|||
bof_buffer: string &optional;
|
||||
} &redef;
|
||||
|
||||
## Metadata that's been inferred about a particular file.
|
||||
type fa_metadata: record {
|
||||
## The strongest matching mime type if one was discovered.
|
||||
mime_type: string &optional;
|
||||
## All matching mime types if any were discovered.
|
||||
mime_types: mime_matches &optional;
|
||||
};
|
||||
|
||||
## Fields of a SYN packet.
|
||||
##
|
||||
## .. bro:see:: connection_SYN_packet
|
||||
|
@ -1093,27 +1099,6 @@ const ENDIAN_LITTLE = 1; ##< Little endian.
|
|||
const ENDIAN_BIG = 2; ##< Big endian.
|
||||
const ENDIAN_CONFUSED = 3; ##< Tried to determine endian, but failed.
|
||||
|
||||
## Deprecated.
|
||||
function append_addl(c: connection, addl: string)
|
||||
{
|
||||
if ( c$addl == "" )
|
||||
c$addl= addl;
|
||||
|
||||
else if ( addl !in c$addl )
|
||||
c$addl = fmt("%s %s", c$addl, addl);
|
||||
}
|
||||
|
||||
## Deprecated.
|
||||
function append_addl_marker(c: connection, addl: string, marker: string)
|
||||
{
|
||||
if ( c$addl == "" )
|
||||
c$addl= addl;
|
||||
|
||||
else if ( addl !in c$addl )
|
||||
c$addl = fmt("%s%s%s", c$addl, marker, addl);
|
||||
}
|
||||
|
||||
|
||||
# Values for :bro:see:`set_contents_file` *direction* argument.
|
||||
# todo:: these should go into an enum to make them autodoc'able
|
||||
const CONTENTS_NONE = 0; ##< Turn off recording of contents.
|
||||
|
@ -2559,6 +2544,145 @@ type irc_join_info: record {
|
|||
## .. bro:see:: irc_join_message
|
||||
type irc_join_list: set[irc_join_info];
|
||||
|
||||
module PE;
|
||||
export {
|
||||
type PE::DOSHeader: record {
|
||||
## The magic number of a portable executable file ("MZ").
|
||||
signature : string;
|
||||
## The number of bytes in the last page that are used.
|
||||
used_bytes_in_last_page : count;
|
||||
## The number of pages in the file that are part of the PE file itself.
|
||||
file_in_pages : count;
|
||||
## Number of relocation entries stored after the header.
|
||||
num_reloc_items : count;
|
||||
## Number of paragraphs in the header.
|
||||
header_in_paragraphs : count;
|
||||
## Number of paragraps of additional memory that the program will need.
|
||||
min_extra_paragraphs : count;
|
||||
## Maximum number of paragraphs of additional memory.
|
||||
max_extra_paragraphs : count;
|
||||
## Relative value of the stack segment.
|
||||
init_relative_ss : count;
|
||||
## Initial value of the SP register.
|
||||
init_sp : count;
|
||||
## Checksum. The 16-bit sum of all words in the file should be 0. Normally not set.
|
||||
checksum : count;
|
||||
## Initial value of the IP register.
|
||||
init_ip : count;
|
||||
## Initial value of the CS register (relative to the initial segment).
|
||||
init_relative_cs : count;
|
||||
## Offset of the first relocation table.
|
||||
addr_of_reloc_table : count;
|
||||
## Overlays allow you to append data to the end of the file. If this is the main program,
|
||||
## this will be 0.
|
||||
overlay_num : count;
|
||||
## OEM identifier.
|
||||
oem_id : count;
|
||||
## Additional OEM info, specific to oem_id.
|
||||
oem_info : count;
|
||||
## Address of the new EXE header.
|
||||
addr_of_new_exe_header : count;
|
||||
};
|
||||
|
||||
type PE::FileHeader: record {
|
||||
## The target machine that the file was compiled for.
|
||||
machine : count;
|
||||
## The time that the file was created at.
|
||||
ts : time;
|
||||
## Pointer to the symbol table.
|
||||
sym_table_ptr : count;
|
||||
## Number of symbols.
|
||||
num_syms : count;
|
||||
## The size of the optional header.
|
||||
optional_header_size : count;
|
||||
## Bit flags that determine if this file is executable, non-relocatable, and/or a DLL.
|
||||
characteristics : set[count];
|
||||
};
|
||||
|
||||
type PE::OptionalHeader: record {
|
||||
## PE32 or PE32+ indicator.
|
||||
magic : count;
|
||||
## The major version of the linker used to create the PE.
|
||||
major_linker_version : count;
|
||||
## The minor version of the linker used to create the PE.
|
||||
minor_linker_version : count;
|
||||
## Size of the .text section.
|
||||
size_of_code : count;
|
||||
## Size of the .data section.
|
||||
size_of_init_data : count;
|
||||
## Size of the .bss section.
|
||||
size_of_uninit_data : count;
|
||||
## The relative virtual address (RVA) of the entry point.
|
||||
addr_of_entry_point : count;
|
||||
## The relative virtual address (RVA) of the .text section.
|
||||
base_of_code : count;
|
||||
## The relative virtual address (RVA) of the .data section.
|
||||
base_of_data : count &optional;
|
||||
## Preferred memory location for the image to be based at.
|
||||
image_base : count;
|
||||
## The alignment (in bytes) of sections when they're loaded in memory.
|
||||
section_alignment : count;
|
||||
## The alignment (in bytes) of the raw data of sections.
|
||||
file_alignment : count;
|
||||
## The major version of the required OS.
|
||||
os_version_major : count;
|
||||
## The minor version of the required OS.
|
||||
os_version_minor : count;
|
||||
## The major version of this image.
|
||||
major_image_version : count;
|
||||
## The minor version of this image.
|
||||
minor_image_version : count;
|
||||
## The major version of the subsystem required to run this file.
|
||||
major_subsys_version : count;
|
||||
## The minor version of the subsystem required to run this file.
|
||||
minor_subsys_version : count;
|
||||
## The size (in bytes) of the iamge as the image is loaded in memory.
|
||||
size_of_image : count;
|
||||
## The size (in bytes) of the headers, rounded up to file_alignment.
|
||||
size_of_headers : count;
|
||||
## The image file checksum.
|
||||
checksum : count;
|
||||
## The subsystem that's required to run this image.
|
||||
subsystem : count;
|
||||
## Bit flags that determine how to execute or load this file.
|
||||
dll_characteristics : set[count];
|
||||
## A vector with the sizes of various tables and strings that are
|
||||
## defined in the optional header data directories. Examples include
|
||||
## the import table, the resource table, and debug information.
|
||||
table_sizes : vector of count;
|
||||
|
||||
};
|
||||
|
||||
## Record for Portable Executable (PE) section headers.
|
||||
type PE::SectionHeader: record {
|
||||
## The name of the section
|
||||
name : string;
|
||||
## The total size of the section when loaded into memory.
|
||||
virtual_size : count;
|
||||
## The relative virtual address (RVA) of the section.
|
||||
virtual_addr : count;
|
||||
## The size of the initialized data for the section, as it is
|
||||
## in the file on disk.
|
||||
size_of_raw_data : count;
|
||||
## The virtual address of the initialized dat for the section,
|
||||
## as it is in the file on disk.
|
||||
ptr_to_raw_data : count;
|
||||
## The file pointer to the beginning of relocation entries for
|
||||
## the section.
|
||||
ptr_to_relocs : count;
|
||||
## The file pointer to the beginning of line-number entries for
|
||||
## the section.
|
||||
ptr_to_line_nums : count;
|
||||
## The number of relocation entries for the section.
|
||||
num_of_relocs : count;
|
||||
## The number of line-number entrie for the section.
|
||||
num_of_line_nums : count;
|
||||
## Bit-flags that describe the characteristics of the section.
|
||||
characteristics : set[count];
|
||||
};
|
||||
}
|
||||
module GLOBAL;
|
||||
|
||||
## Deprecated.
|
||||
##
|
||||
## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere
|
||||
|
@ -2683,60 +2807,6 @@ global generate_OS_version_event: set[subnet] &redef;
|
|||
# number>``), which were seen during the sample.
|
||||
type load_sample_info: set[string];
|
||||
|
||||
## ID for NetFlow header. This is primarily a means to sort together NetFlow
|
||||
## headers and flow records at the script level.
|
||||
type nfheader_id: record {
|
||||
## Name of the NetFlow file (e.g., ``netflow.dat``) or the receiving
|
||||
## socket address (e.g., ``127.0.0.1:5555``), or an explicit name if
|
||||
## specified to ``-y`` or ``-Y``.
|
||||
rcvr_id: string;
|
||||
## A serial number, ignoring any overflows.
|
||||
pdu_id: count;
|
||||
};
|
||||
|
||||
## A NetFlow v5 header.
|
||||
##
|
||||
## .. bro:see:: netflow_v5_header
|
||||
type nf_v5_header: record {
|
||||
h_id: nfheader_id; ##< ID for sorting.
|
||||
cnt: count; ##< TODO.
|
||||
sysuptime: interval; ##< Router's uptime.
|
||||
exporttime: time; ##< When the data was exported.
|
||||
flow_seq: count; ##< Sequence number.
|
||||
eng_type: count; ##< Engine type.
|
||||
eng_id: count; ##< Engine ID.
|
||||
sample_int: count; ##< Sampling interval.
|
||||
exporter: addr; ##< Exporter address.
|
||||
};
|
||||
|
||||
## A NetFlow v5 record.
|
||||
##
|
||||
## .. bro:see:: netflow_v5_record
|
||||
type nf_v5_record: record {
|
||||
h_id: nfheader_id; ##< ID for sorting.
|
||||
id: conn_id; ##< Connection ID.
|
||||
nexthop: addr; ##< Address of next hop.
|
||||
input: count; ##< Input interface.
|
||||
output: count; ##< Output interface.
|
||||
pkts: count; ##< Number of packets.
|
||||
octets: count; ##< Number of bytes.
|
||||
first: time; ##< Timestamp of first packet.
|
||||
last: time; ##< Timestamp of last packet.
|
||||
tcpflag_fin: bool; ##< FIN flag for TCP flows.
|
||||
tcpflag_syn: bool; ##< SYN flag for TCP flows.
|
||||
tcpflag_rst: bool; ##< RST flag for TCP flows.
|
||||
tcpflag_psh: bool; ##< PSH flag for TCP flows.
|
||||
tcpflag_ack: bool; ##< ACK flag for TCP flows.
|
||||
tcpflag_urg: bool; ##< URG flag for TCP flows.
|
||||
proto: count; ##< IP protocol.
|
||||
tos: count; ##< Type of service.
|
||||
src_as: count; ##< Source AS.
|
||||
dst_as: count; ##< Destination AS.
|
||||
src_mask: count; ##< Source mask.
|
||||
dst_mask: count; ##< Destination mask.
|
||||
};
|
||||
|
||||
|
||||
## A BitTorrent peer.
|
||||
##
|
||||
## .. bro:see:: bittorrent_peer_set
|
||||
|
@ -3057,6 +3127,186 @@ export {
|
|||
};
|
||||
}
|
||||
|
||||
@load base/bif/plugins/Bro_KRB.types.bif
|
||||
|
||||
module KRB;
|
||||
export {
|
||||
## KDC Options. See :rfc:`4120`
|
||||
type KRB::KDC_Options: record {
|
||||
## The ticket to be issued should have its forwardable flag set.
|
||||
forwardable : bool;
|
||||
## A (TGT) request for forwarding.
|
||||
forwarded : bool;
|
||||
## The ticket to be issued should have its proxiable flag set.
|
||||
proxiable : bool;
|
||||
## A request for a proxy.
|
||||
proxy : bool;
|
||||
## The ticket to be issued should have its may-postdate flag set.
|
||||
allow_postdate : bool;
|
||||
## A request for a postdated ticket.
|
||||
postdated : bool;
|
||||
## The ticket to be issued should have its renewable flag set.
|
||||
renewable : bool;
|
||||
## Reserved for opt_hardware_auth
|
||||
opt_hardware_auth : bool;
|
||||
## Request that the KDC not check the transited field of a TGT against
|
||||
## the policy of the local realm before it will issue derivative tickets
|
||||
## based on the TGT.
|
||||
disable_transited_check : bool;
|
||||
## If a ticket with the requested lifetime cannot be issued, a renewable
|
||||
## ticket is acceptable
|
||||
renewable_ok : bool;
|
||||
## The ticket for the end server is to be encrypted in the session key
|
||||
## from the additional TGT provided
|
||||
enc_tkt_in_skey : bool;
|
||||
## The request is for a renewal
|
||||
renew : bool;
|
||||
## The request is to validate a postdated ticket.
|
||||
validate : bool;
|
||||
};
|
||||
|
||||
## AP Options. See :rfc:`4120`
|
||||
type KRB::AP_Options: record {
|
||||
## Indicates that user-to-user-authentication is in use
|
||||
use_session_key : bool;
|
||||
## Mutual authentication is required
|
||||
mutual_required : bool;
|
||||
};
|
||||
|
||||
## Used in a few places in the Kerberos analyzer for elements
|
||||
## that have a type and a string value.
|
||||
type KRB::Type_Value: record {
|
||||
## The data type
|
||||
data_type : count;
|
||||
## The data value
|
||||
val : string;
|
||||
};
|
||||
|
||||
type KRB::Type_Value_Vector: vector of KRB::Type_Value;
|
||||
|
||||
## A Kerberos host address See :rfc:`4120`.
|
||||
type KRB::Host_Address: record {
|
||||
## IPv4 or IPv6 address
|
||||
ip : addr &log &optional;
|
||||
## NetBIOS address
|
||||
netbios : string &log &optional;
|
||||
## Some other type that we don't support yet
|
||||
unknown : KRB::Type_Value &optional;
|
||||
};
|
||||
|
||||
type KRB::Host_Address_Vector: vector of KRB::Host_Address;
|
||||
|
||||
## The data from the SAFE message. See :rfc:`4120`.
|
||||
type KRB::SAFE_Msg: record {
|
||||
## Protocol version number (5 for KRB5)
|
||||
pvno : count;
|
||||
## The message type (20 for SAFE_MSG)
|
||||
msg_type : count;
|
||||
## The application-specific data that is being passed
|
||||
## from the sender to the reciever
|
||||
data : string;
|
||||
## Current time from the sender of the message
|
||||
timestamp : time &optional;
|
||||
## Sequence number used to detect replays
|
||||
seq : count &optional;
|
||||
## Sender address
|
||||
sender : Host_Address &optional;
|
||||
## Recipient address
|
||||
recipient : Host_Address &optional;
|
||||
};
|
||||
|
||||
## The data from the ERROR_MSG message. See :rfc:`4120`.
|
||||
type KRB::Error_Msg: record {
|
||||
## Protocol version number (5 for KRB5)
|
||||
pvno : count;
|
||||
## The message type (30 for ERROR_MSG)
|
||||
msg_type : count;
|
||||
## Current time on the client
|
||||
client_time : time &optional;
|
||||
## Current time on the server
|
||||
server_time : time;
|
||||
## The specific error code
|
||||
error_code : count;
|
||||
## Realm of the ticket
|
||||
client_realm : string &optional;
|
||||
## Name on the ticket
|
||||
client_name : string &optional;
|
||||
## Realm of the service
|
||||
service_realm : string;
|
||||
## Name of the service
|
||||
service_name : string;
|
||||
## Additional text to explain the error
|
||||
error_text : string &optional;
|
||||
## Optional pre-authentication data
|
||||
pa_data : vector of KRB::Type_Value &optional;
|
||||
};
|
||||
|
||||
## A Kerberos ticket. See :rfc:`4120`.
|
||||
type KRB::Ticket: record {
|
||||
## Protocol version number (5 for KRB5)
|
||||
pvno : count;
|
||||
## Realm
|
||||
realm : string;
|
||||
## Name of the service
|
||||
service_name : string;
|
||||
## Cipher the ticket was encrypted with
|
||||
cipher : count;
|
||||
};
|
||||
|
||||
type KRB::Ticket_Vector: vector of KRB::Ticket;
|
||||
|
||||
## The data from the AS_REQ and TGS_REQ messages. See :rfc:`4120`.
|
||||
type KRB::KDC_Request: record {
|
||||
## Protocol version number (5 for KRB5)
|
||||
pvno : count;
|
||||
## The message type (10 for AS_REQ, 12 for TGS_REQ)
|
||||
msg_type : count;
|
||||
## Optional pre-authentication data
|
||||
pa_data : vector of KRB::Type_Value &optional;
|
||||
## Options specified in the request
|
||||
kdc_options : KRB::KDC_Options;
|
||||
## Name on the ticket
|
||||
client_name : string &optional;
|
||||
|
||||
## Realm of the service
|
||||
service_realm : string;
|
||||
## Name of the service
|
||||
service_name : string &optional;
|
||||
## Time the ticket is good from
|
||||
from : time &optional;
|
||||
## Time the ticket is good till
|
||||
till : time;
|
||||
## The requested renew-till time
|
||||
rtime : time &optional;
|
||||
|
||||
## A random nonce generated by the client
|
||||
nonce : count;
|
||||
## The desired encryption algorithms, in order of preference
|
||||
encryption_types : vector of count;
|
||||
## Any additional addresses the ticket should be valid for
|
||||
host_addrs : vector of KRB::Host_Address &optional;
|
||||
## Additional tickets may be included for certain transactions
|
||||
additional_tickets : vector of KRB::Ticket &optional;
|
||||
};
|
||||
|
||||
## The data from the AS_REQ and TGS_REQ messages. See :rfc:`4120`.
|
||||
type KRB::KDC_Response: record {
|
||||
## Protocol version number (5 for KRB5)
|
||||
pvno : count;
|
||||
## The message type (11 for AS_REP, 13 for TGS_REP)
|
||||
msg_type : count;
|
||||
## Optional pre-authentication data
|
||||
pa_data : vector of KRB::Type_Value &optional;
|
||||
## Realm on the ticket
|
||||
client_realm : string &optional;
|
||||
## Name on the service
|
||||
client_name : string;
|
||||
|
||||
## The ticket that was issued
|
||||
ticket : KRB::Ticket;
|
||||
};
|
||||
}
|
||||
|
||||
module GLOBAL;
|
||||
|
||||
@load base/bif/event.bif
|
||||
|
|
|
@ -47,11 +47,13 @@
|
|||
@load base/protocols/ftp
|
||||
@load base/protocols/http
|
||||
@load base/protocols/irc
|
||||
@load base/protocols/krb
|
||||
@load base/protocols/modbus
|
||||
@load base/protocols/mysql
|
||||
@load base/protocols/pop3
|
||||
@load base/protocols/radius
|
||||
@load base/protocols/rdp
|
||||
@load base/protocols/sip
|
||||
@load base/protocols/snmp
|
||||
@load base/protocols/smtp
|
||||
@load base/protocols/socks
|
||||
|
@ -60,6 +62,7 @@
|
|||
@load base/protocols/syslog
|
||||
@load base/protocols/tunnels
|
||||
|
||||
@load base/files/pe
|
||||
@load base/files/hash
|
||||
@load base/files/extract
|
||||
@load base/files/unified2
|
||||
|
|
|
@ -63,10 +63,13 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori
|
|||
f$ftp = ftp;
|
||||
}
|
||||
|
||||
event file_mime_type(f: fa_file, mime_type: string) &priority=5
|
||||
event file_sniff(f: fa_file, meta: fa_metadata) &priority=5
|
||||
{
|
||||
if ( ! f?$ftp )
|
||||
return;
|
||||
|
||||
f$ftp$mime_type = mime_type;
|
||||
if ( ! meta?$mime_type )
|
||||
return;
|
||||
|
||||
f$ftp$mime_type = meta$mime_type;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ export {
|
|||
|
||||
event http_begin_entity(c: connection, is_orig: bool) &priority=10
|
||||
{
|
||||
set_state(c, F, is_orig);
|
||||
set_state(c, is_orig);
|
||||
|
||||
if ( is_orig )
|
||||
++c$http$orig_mime_depth;
|
||||
|
@ -93,24 +93,27 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori
|
|||
}
|
||||
}
|
||||
|
||||
event file_mime_type(f: fa_file, mime_type: string) &priority=5
|
||||
event file_sniff(f: fa_file, meta: fa_metadata) &priority=5
|
||||
{
|
||||
if ( ! f?$http || ! f?$is_orig )
|
||||
return;
|
||||
|
||||
if ( ! meta?$mime_type )
|
||||
return;
|
||||
|
||||
if ( f$is_orig )
|
||||
{
|
||||
if ( ! f$http?$orig_mime_types )
|
||||
f$http$orig_mime_types = string_vec(mime_type);
|
||||
f$http$orig_mime_types = string_vec(meta$mime_type);
|
||||
else
|
||||
f$http$orig_mime_types[|f$http$orig_mime_types|] = mime_type;
|
||||
f$http$orig_mime_types[|f$http$orig_mime_types|] = meta$mime_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ! f$http?$resp_mime_types )
|
||||
f$http$resp_mime_types = string_vec(mime_type);
|
||||
f$http$resp_mime_types = string_vec(meta$mime_type);
|
||||
else
|
||||
f$http$resp_mime_types[|f$http$resp_mime_types|] = mime_type;
|
||||
f$http$resp_mime_types[|f$http$resp_mime_types|] = meta$mime_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,10 @@ export {
|
|||
current_request: count &default=0;
|
||||
## Current response in the pending queue.
|
||||
current_response: count &default=0;
|
||||
## Track the current deepest transaction.
|
||||
## This is meant to cope with missing requests
|
||||
## and responses.
|
||||
trans_depth: count &default=0;
|
||||
};
|
||||
|
||||
## A list of HTTP headers typically used to indicate proxied requests.
|
||||
|
@ -150,13 +154,11 @@ function new_http_session(c: connection): Info
|
|||
tmp$ts=network_time();
|
||||
tmp$uid=c$uid;
|
||||
tmp$id=c$id;
|
||||
# $current_request is set prior to the Info record creation so we
|
||||
# can use the value directly here.
|
||||
tmp$trans_depth = c$http_state$current_request;
|
||||
tmp$trans_depth = ++c$http_state$trans_depth;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function set_state(c: connection, request: bool, is_orig: bool)
|
||||
function set_state(c: connection, is_orig: bool)
|
||||
{
|
||||
if ( ! c?$http_state )
|
||||
{
|
||||
|
@ -165,15 +167,20 @@ function set_state(c: connection, request: bool, is_orig: bool)
|
|||
}
|
||||
|
||||
# These deal with new requests and responses.
|
||||
if ( request || c$http_state$current_request !in c$http_state$pending )
|
||||
c$http_state$pending[c$http_state$current_request] = new_http_session(c);
|
||||
if ( ! is_orig && c$http_state$current_response !in c$http_state$pending )
|
||||
c$http_state$pending[c$http_state$current_response] = new_http_session(c);
|
||||
|
||||
if ( is_orig )
|
||||
{
|
||||
if ( c$http_state$current_request !in c$http_state$pending )
|
||||
c$http_state$pending[c$http_state$current_request] = new_http_session(c);
|
||||
|
||||
c$http = c$http_state$pending[c$http_state$current_request];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( c$http_state$current_response !in c$http_state$pending )
|
||||
c$http_state$pending[c$http_state$current_response] = new_http_session(c);
|
||||
|
||||
c$http = c$http_state$pending[c$http_state$current_response];
|
||||
}
|
||||
}
|
||||
|
||||
event http_request(c: connection, method: string, original_URI: string,
|
||||
|
@ -186,7 +193,7 @@ event http_request(c: connection, method: string, original_URI: string,
|
|||
}
|
||||
|
||||
++c$http_state$current_request;
|
||||
set_state(c, T, T);
|
||||
set_state(c, T);
|
||||
|
||||
c$http$method = method;
|
||||
c$http$uri = unescaped_URI;
|
||||
|
@ -208,8 +215,10 @@ event http_reply(c: connection, version: string, code: count, reason: string) &p
|
|||
if ( c$http_state$current_response !in c$http_state$pending ||
|
||||
(c$http_state$pending[c$http_state$current_response]?$status_code &&
|
||||
! code_in_range(c$http_state$pending[c$http_state$current_response]$status_code, 100, 199)) )
|
||||
{
|
||||
++c$http_state$current_response;
|
||||
set_state(c, F, F);
|
||||
}
|
||||
set_state(c, F);
|
||||
|
||||
c$http$status_code = code;
|
||||
c$http$status_msg = reason;
|
||||
|
@ -233,7 +242,7 @@ event http_reply(c: connection, version: string, code: count, reason: string) &p
|
|||
|
||||
event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=5
|
||||
{
|
||||
set_state(c, F, is_orig);
|
||||
set_state(c, is_orig);
|
||||
|
||||
if ( is_orig ) # client headers
|
||||
{
|
||||
|
@ -257,7 +266,7 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr
|
|||
add c$http$proxied[fmt("%s -> %s", name, value)];
|
||||
}
|
||||
|
||||
else if ( name == "AUTHORIZATION" )
|
||||
else if ( name == "AUTHORIZATION" || name == "PROXY-AUTHORIZATION" )
|
||||
{
|
||||
if ( /^[bB][aA][sS][iI][cC] / in value )
|
||||
{
|
||||
|
@ -278,12 +287,11 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) &priority = 5
|
||||
{
|
||||
set_state(c, F, is_orig);
|
||||
set_state(c, is_orig);
|
||||
|
||||
if ( is_orig )
|
||||
c$http$request_body_len = stat$body_length;
|
||||
|
|
|
@ -42,8 +42,8 @@ event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priori
|
|||
f$irc = irc;
|
||||
}
|
||||
|
||||
event file_mime_type(f: fa_file, mime_type: string) &priority=5
|
||||
event file_sniff(f: fa_file, meta: fa_metadata) &priority=5
|
||||
{
|
||||
if ( f?$irc )
|
||||
f$irc$dcc_mime_type = mime_type;
|
||||
}
|
||||
if ( f?$irc && meta?$mime_type )
|
||||
f$irc$dcc_mime_type = meta$mime_type;
|
||||
}
|
||||
|
|
3
scripts/base/protocols/krb/__load__.bro
Normal file
3
scripts/base/protocols/krb/__load__.bro
Normal file
|
@ -0,0 +1,3 @@
|
|||
@load ./main
|
||||
@load ./files
|
||||
@load-sigs ./dpd.sig
|
99
scripts/base/protocols/krb/consts.bro
Normal file
99
scripts/base/protocols/krb/consts.bro
Normal file
|
@ -0,0 +1,99 @@
|
|||
module KRB;
|
||||
|
||||
export {
|
||||
|
||||
const error_msg: table[count] of string = {
|
||||
[0] = "KDC_ERR_NONE",
|
||||
[1] = "KDC_ERR_NAME_EXP",
|
||||
[2] = "KDC_ERR_SERVICE_EXP",
|
||||
[3] = "KDC_ERR_BAD_PVNO",
|
||||
[4] = "KDC_ERR_C_OLD_MAST_KVNO",
|
||||
[5] = "KDC_ERR_S_OLD_MAST_KVNO",
|
||||
[6] = "KDC_ERR_C_PRINCIPAL_UNKNOWN",
|
||||
[7] = "KDC_ERR_S_PRINCIPAL_UNKNOWN",
|
||||
[8] = "KDC_ERR_PRINCIPAL_NOT_UNIQUE",
|
||||
[9] = "KDC_ERR_NULL_KEY",
|
||||
[10] = "KDC_ERR_CANNOT_POSTDATE",
|
||||
[11] = "KDC_ERR_NEVER_VALID",
|
||||
[12] = "KDC_ERR_POLICY",
|
||||
[13] = "KDC_ERR_BADOPTION",
|
||||
[14] = "KDC_ERR_ETYPE_NOSUPP",
|
||||
[15] = "KDC_ERR_SUMTYPE_NOSUPP",
|
||||
[16] = "KDC_ERR_PADATA_TYPE_NOSUPP",
|
||||
[17] = "KDC_ERR_TRTYPE_NOSUPP",
|
||||
[18] = "KDC_ERR_CLIENT_REVOKED",
|
||||
[19] = "KDC_ERR_SERVICE_REVOKED",
|
||||
[20] = "KDC_ERR_TGT_REVOKED",
|
||||
[21] = "KDC_ERR_CLIENT_NOTYET",
|
||||
[22] = "KDC_ERR_SERVICE_NOTYET",
|
||||
[23] = "KDC_ERR_KEY_EXPIRED",
|
||||
[24] = "KDC_ERR_PREAUTH_FAILED",
|
||||
[25] = "KDC_ERR_PREAUTH_REQUIRED",
|
||||
[26] = "KDC_ERR_SERVER_NOMATCH",
|
||||
[27] = "KDC_ERR_MUST_USE_USER2USER",
|
||||
[28] = "KDC_ERR_PATH_NOT_ACCEPTED",
|
||||
[29] = "KDC_ERR_SVC_UNAVAILABLE",
|
||||
[31] = "KRB_AP_ERR_BAD_INTEGRITY",
|
||||
[32] = "KRB_AP_ERR_TKT_EXPIRED",
|
||||
[33] = "KRB_AP_ERR_TKT_NYV",
|
||||
[34] = "KRB_AP_ERR_REPEAT",
|
||||
[35] = "KRB_AP_ERR_NOT_US",
|
||||
[36] = "KRB_AP_ERR_BADMATCH",
|
||||
[37] = "KRB_AP_ERR_SKEW",
|
||||
[38] = "KRB_AP_ERR_BADADDR",
|
||||
[39] = "KRB_AP_ERR_BADVERSION",
|
||||
[40] = "KRB_AP_ERR_MSG_TYPE",
|
||||
[41] = "KRB_AP_ERR_MODIFIED",
|
||||
[42] = "KRB_AP_ERR_BADORDER",
|
||||
[44] = "KRB_AP_ERR_BADKEYVER",
|
||||
[45] = "KRB_AP_ERR_NOKEY",
|
||||
[46] = "KRB_AP_ERR_MUT_FAIL",
|
||||
[47] = "KRB_AP_ERR_BADDIRECTION",
|
||||
[48] = "KRB_AP_ERR_METHOD",
|
||||
[49] = "KRB_AP_ERR_BADSEQ",
|
||||
[50] = "KRB_AP_ERR_INAPP_CKSUM",
|
||||
[51] = "KRB_AP_PATH_NOT_ACCEPTED",
|
||||
[52] = "KRB_ERR_RESPONSE_TOO_BIG",
|
||||
[60] = "KRB_ERR_GENERIC",
|
||||
[61] = "KRB_ERR_FIELD_TOOLONG",
|
||||
[62] = "KDC_ERROR_CLIENT_NOT_TRUSTED",
|
||||
[63] = "KDC_ERROR_KDC_NOT_TRUSTED",
|
||||
[64] = "KDC_ERROR_INVALID_SIG",
|
||||
[65] = "KDC_ERR_KEY_TOO_WEAK",
|
||||
[66] = "KDC_ERR_CERTIFICATE_MISMATCH",
|
||||
[67] = "KRB_AP_ERR_NO_TGT",
|
||||
[68] = "KDC_ERR_WRONG_REALM",
|
||||
[69] = "KRB_AP_ERR_USER_TO_USER_REQUIRED",
|
||||
[70] = "KDC_ERR_CANT_VERIFY_CERTIFICATE",
|
||||
[71] = "KDC_ERR_INVALID_CERTIFICATE",
|
||||
[72] = "KDC_ERR_REVOKED_CERTIFICATE",
|
||||
[73] = "KDC_ERR_REVOCATION_STATUS_UNKNOWN",
|
||||
[74] = "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE",
|
||||
[75] = "KDC_ERR_CLIENT_NAME_MISMATCH",
|
||||
[76] = "KDC_ERR_KDC_NAME_MISMATCH",
|
||||
};
|
||||
|
||||
const cipher_name: table[count] of string = {
|
||||
[1] = "des-cbc-crc",
|
||||
[2] = "des-cbc-md4",
|
||||
[3] = "des-cbc-md5",
|
||||
[5] = "des3-cbc-md5",
|
||||
[7] = "des3-cbc-sha1",
|
||||
[9] = "dsaWithSHA1-CmsOID",
|
||||
[10] = "md5WithRSAEncryption-CmsOID",
|
||||
[11] = "sha1WithRSAEncryption-CmsOID",
|
||||
[12] = "rc2CBC-EnvOID",
|
||||
[13] = "rsaEncryption-EnvOID",
|
||||
[14] = "rsaES-OAEP-ENV-OID",
|
||||
[15] = "des-ede3-cbc-Env-OID",
|
||||
[16] = "des3-cbc-sha1-kd",
|
||||
[17] = "aes128-cts-hmac-sha1-96",
|
||||
[18] = "aes256-cts-hmac-sha1-96",
|
||||
[23] = "rc4-hmac",
|
||||
[24] = "rc4-hmac-exp",
|
||||
[25] = "camellia128-cts-cmac",
|
||||
[26] = "camellia256-cts-cmac",
|
||||
[65] = "subkey-keymaterial",
|
||||
};
|
||||
|
||||
}
|
26
scripts/base/protocols/krb/dpd.sig
Normal file
26
scripts/base/protocols/krb/dpd.sig
Normal file
|
@ -0,0 +1,26 @@
|
|||
# This is the ASN.1 encoded version and message type headers
|
||||
|
||||
signature dpd_krb_udp_requests {
|
||||
ip-proto == udp
|
||||
payload /(\x6a|\x6c).{1,4}\x30.{1,4}\xa1\x03\x02\x01\x05\xa2\x03\x02\x01/
|
||||
enable "krb"
|
||||
}
|
||||
|
||||
signature dpd_krb_udp_replies {
|
||||
ip-proto == udp
|
||||
payload /(\x6b|\x6d|\x7e).{1,4}\x30.{1,4}\xa0\x03\x02\x01\x05\xa1\x03\x02\x01/
|
||||
enable "krb"
|
||||
}
|
||||
|
||||
signature dpd_krb_tcp_requests {
|
||||
ip-proto == tcp
|
||||
payload /.{4}(\x6a|\x6c).{1,4}\x30.{1,4}\xa1\x03\x02\x01\x05\xa2\x03\x02\x01/
|
||||
enable "krb_tcp"
|
||||
}
|
||||
|
||||
signature dpd_krb_tcp_replies {
|
||||
ip-proto == tcp
|
||||
payload /.{4}(\x6b|\x6d|\x7e).{1,4}\x30.{1,4}\xa0\x03\x02\x01\x05\xa1\x03\x02\x01/
|
||||
enable "krb_tcp"
|
||||
}
|
||||
|
142
scripts/base/protocols/krb/files.bro
Normal file
142
scripts/base/protocols/krb/files.bro
Normal file
|
@ -0,0 +1,142 @@
|
|||
@load ./main
|
||||
@load base/utils/conn-ids
|
||||
@load base/frameworks/files
|
||||
@load base/files/x509
|
||||
|
||||
module KRB;
|
||||
|
||||
export {
|
||||
redef record Info += {
|
||||
# Client certificate
|
||||
client_cert: Files::Info &optional;
|
||||
# Subject of client certificate, if any
|
||||
client_cert_subject: string &log &optional;
|
||||
# File unique ID of client cert, if any
|
||||
client_cert_fuid: string &log &optional;
|
||||
|
||||
# Server certificate
|
||||
server_cert: Files::Info &optional;
|
||||
# Subject of server certificate, if any
|
||||
server_cert_subject: string &log &optional;
|
||||
# File unique ID of server cert, if any
|
||||
server_cert_fuid: string &log &optional;
|
||||
};
|
||||
|
||||
## Default file handle provider for KRB.
|
||||
global get_file_handle: function(c: connection, is_orig: bool): string;
|
||||
|
||||
## Default file describer for KRB.
|
||||
global describe_file: function(f: fa_file): string;
|
||||
}
|
||||
|
||||
function get_file_handle(c: connection, is_orig: bool): string
|
||||
{
|
||||
# Unused. File handles are generated in the analyzer.
|
||||
return "";
|
||||
}
|
||||
|
||||
function describe_file(f: fa_file): string
|
||||
{
|
||||
if ( f$source != "KRB_TCP" && f$source != "KRB" )
|
||||
return "";
|
||||
|
||||
if ( ! f?$info || ! f$info?$x509 || ! f$info$x509?$certificate )
|
||||
return "";
|
||||
|
||||
# It is difficult to reliably describe a certificate - especially since
|
||||
# we do not know when this function is called (hence, if the data structures
|
||||
# are already populated).
|
||||
#
|
||||
# Just return a bit of our connection information and hope that that is good enough.
|
||||
for ( cid in f$conns )
|
||||
{
|
||||
if ( f$conns[cid]?$krb )
|
||||
{
|
||||
local c = f$conns[cid];
|
||||
return cat(c$id$resp_h, ":", c$id$resp_p);
|
||||
}
|
||||
}
|
||||
|
||||
return cat("Serial: ", f$info$x509$certificate$serial, " Subject: ",
|
||||
f$info$x509$certificate$subject, " Issuer: ",
|
||||
f$info$x509$certificate$issuer);
|
||||
}
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Files::register_protocol(Analyzer::ANALYZER_KRB_TCP,
|
||||
[$get_file_handle = KRB::get_file_handle,
|
||||
$describe = KRB::describe_file]);
|
||||
|
||||
Files::register_protocol(Analyzer::ANALYZER_KRB,
|
||||
[$get_file_handle = KRB::get_file_handle,
|
||||
$describe = KRB::describe_file]);
|
||||
}
|
||||
|
||||
event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=5
|
||||
{
|
||||
if ( f$source != "KRB_TCP" && f$source != "KRB" )
|
||||
return;
|
||||
|
||||
local info: Info;
|
||||
|
||||
if ( ! c?$krb )
|
||||
{
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
}
|
||||
else
|
||||
info = c$krb;
|
||||
|
||||
if ( is_orig )
|
||||
{
|
||||
info$client_cert = f$info;
|
||||
info$client_cert_fuid = f$id;
|
||||
}
|
||||
else
|
||||
{
|
||||
info$server_cert = f$info;
|
||||
info$server_cert_fuid = f$id;
|
||||
}
|
||||
|
||||
c$krb = info;
|
||||
|
||||
Files::add_analyzer(f, Files::ANALYZER_X509);
|
||||
# Always calculate hashes. They are not necessary for base scripts
|
||||
# but very useful for identification, and required for policy scripts
|
||||
Files::add_analyzer(f, Files::ANALYZER_MD5);
|
||||
Files::add_analyzer(f, Files::ANALYZER_SHA1);
|
||||
}
|
||||
|
||||
function fill_in_subjects(c: connection)
|
||||
{
|
||||
if ( !c?$krb )
|
||||
return;
|
||||
|
||||
if ( c$krb?$client_cert && c$krb$client_cert?$x509 && c$krb$client_cert$x509?$certificate )
|
||||
c$krb$client_cert_subject = c$krb$client_cert$x509$certificate$subject;
|
||||
|
||||
if ( c$krb?$server_cert && c$krb$server_cert?$x509 && c$krb$server_cert$x509?$certificate )
|
||||
c$krb$server_cert_subject = c$krb$server_cert$x509$certificate$subject;
|
||||
}
|
||||
|
||||
event krb_error(c: connection, msg: Error_Msg)
|
||||
{
|
||||
fill_in_subjects(c);
|
||||
}
|
||||
|
||||
event krb_as_response(c: connection, msg: KDC_Response)
|
||||
{
|
||||
fill_in_subjects(c);
|
||||
}
|
||||
|
||||
event krb_tgs_response(c: connection, msg: KDC_Response)
|
||||
{
|
||||
fill_in_subjects(c);
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection)
|
||||
{
|
||||
fill_in_subjects(c);
|
||||
}
|
250
scripts/base/protocols/krb/main.bro
Normal file
250
scripts/base/protocols/krb/main.bro
Normal file
|
@ -0,0 +1,250 @@
|
|||
##! Implements base functionality for KRB analysis. Generates the krb.log file.
|
||||
|
||||
module KRB;
|
||||
|
||||
@load ./consts
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Timestamp for when the event happened.
|
||||
ts: time &log;
|
||||
## Unique ID for the connection.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
|
||||
## Request type - Authentication Service ("AS") or
|
||||
## Ticket Granting Service ("TGS")
|
||||
request_type: string &log &optional;
|
||||
## Client
|
||||
client: string &log &optional;
|
||||
## Service
|
||||
service: string &log;
|
||||
|
||||
## Request result
|
||||
success: bool &log &optional;
|
||||
## Error code
|
||||
error_code: count &optional;
|
||||
## Error message
|
||||
error_msg: string &log &optional;
|
||||
|
||||
## Ticket valid from
|
||||
from: time &log &optional;
|
||||
## Ticket valid till
|
||||
till: time &log &optional;
|
||||
## Ticket encryption type
|
||||
cipher: string &log &optional;
|
||||
|
||||
## Forwardable ticket requested
|
||||
forwardable: bool &log &optional;
|
||||
## Renewable ticket requested
|
||||
renewable: bool &log &optional;
|
||||
|
||||
## We've already logged this
|
||||
logged: bool &default=F;
|
||||
};
|
||||
|
||||
## The server response error texts which are *not* logged.
|
||||
const ignored_errors: set[string] = {
|
||||
# This will significantly increase the noisiness of the log.
|
||||
# However, one attack is to iterate over principals, looking
|
||||
# for ones that don't require preauth, and then performn
|
||||
# an offline attack on that ticket. To detect that attack,
|
||||
# log NEEDED_PREAUTH.
|
||||
"NEEDED_PREAUTH",
|
||||
# This is a more specific version of NEEDED_PREAUTH that's used
|
||||
# by Windows AD Kerberos.
|
||||
"Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
|
||||
} &redef;
|
||||
|
||||
## Event that can be handled to access the KRB record as it is sent on
|
||||
## to the logging framework.
|
||||
global log_krb: event(rec: Info);
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
krb: Info &optional;
|
||||
};
|
||||
|
||||
const tcp_ports = { 88/tcp };
|
||||
const udp_ports = { 88/udp };
|
||||
redef likely_server_ports += { tcp_ports, udp_ports };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_KRB, udp_ports);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_KRB_TCP, tcp_ports);
|
||||
Log::create_stream(KRB::LOG, [$columns=Info, $ev=log_krb, $path="kerberos"]);
|
||||
}
|
||||
|
||||
event krb_error(c: connection, msg: Error_Msg) &priority=5
|
||||
{
|
||||
local info: Info;
|
||||
|
||||
if ( msg?$error_text && msg$error_text in ignored_errors )
|
||||
{
|
||||
if ( c?$krb ) delete c$krb;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( c?$krb && c$krb$logged )
|
||||
return;
|
||||
|
||||
if ( c?$krb )
|
||||
info = c$krb;
|
||||
|
||||
if ( ! info?$ts )
|
||||
{
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
}
|
||||
|
||||
if ( ! info?$client && ( msg?$client_name || msg?$client_realm ) )
|
||||
info$client = fmt("%s%s", msg?$client_name ? msg$client_name + "/" : "",
|
||||
msg?$client_realm ? msg$client_realm : "");
|
||||
|
||||
info$service = msg$service_name;
|
||||
info$success = F;
|
||||
|
||||
info$error_code = msg$error_code;
|
||||
|
||||
if ( msg?$error_text ) info$error_msg = msg$error_text;
|
||||
else if ( msg$error_code in error_msg ) info$error_msg = error_msg[msg$error_code];
|
||||
|
||||
c$krb = info;
|
||||
}
|
||||
|
||||
event krb_error(c: connection, msg: Error_Msg) &priority=-5
|
||||
{
|
||||
if ( c?$krb )
|
||||
{
|
||||
Log::write(KRB::LOG, c$krb);
|
||||
c$krb$logged = T;
|
||||
}
|
||||
}
|
||||
|
||||
event krb_as_request(c: connection, msg: KDC_Request) &priority=5
|
||||
{
|
||||
if ( c?$krb && c$krb$logged )
|
||||
return;
|
||||
|
||||
local info: Info;
|
||||
|
||||
if ( !c?$krb )
|
||||
{
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
}
|
||||
else
|
||||
info = c$krb;
|
||||
|
||||
info$request_type = "AS";
|
||||
info$client = fmt("%s/%s", msg$client_name, msg$service_realm);
|
||||
info$service = msg$service_name;
|
||||
|
||||
if ( msg?$from )
|
||||
info$from = msg$from;
|
||||
|
||||
info$till = msg$till;
|
||||
|
||||
info$forwardable = msg$kdc_options$forwardable;
|
||||
info$renewable = msg$kdc_options$renewable;
|
||||
|
||||
c$krb = info;
|
||||
}
|
||||
|
||||
event krb_tgs_request(c: connection, msg: KDC_Request) &priority=5
|
||||
{
|
||||
if ( c?$krb && c$krb$logged )
|
||||
return;
|
||||
|
||||
local info: Info;
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
info$request_type = "TGS";
|
||||
info$service = msg$service_name;
|
||||
if ( msg?$from ) info$from = msg$from;
|
||||
info$till = msg$till;
|
||||
|
||||
info$forwardable = msg$kdc_options$forwardable;
|
||||
info$renewable = msg$kdc_options$renewable;
|
||||
|
||||
c$krb = info;
|
||||
}
|
||||
|
||||
event krb_as_response(c: connection, msg: KDC_Response) &priority=5
|
||||
{
|
||||
local info: Info;
|
||||
|
||||
if ( c?$krb && c$krb$logged )
|
||||
return;
|
||||
|
||||
if ( c?$krb )
|
||||
info = c$krb;
|
||||
|
||||
if ( ! info?$ts )
|
||||
{
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
}
|
||||
|
||||
if ( ! info?$client )
|
||||
info$client = fmt("%s/%s", msg$client_name, msg$client_realm);
|
||||
|
||||
info$service = msg$ticket$service_name;
|
||||
info$cipher = cipher_name[msg$ticket$cipher];
|
||||
info$success = T;
|
||||
|
||||
c$krb = info;
|
||||
}
|
||||
|
||||
event krb_as_response(c: connection, msg: KDC_Response) &priority=-5
|
||||
{
|
||||
Log::write(KRB::LOG, c$krb);
|
||||
c$krb$logged = T;
|
||||
}
|
||||
|
||||
event krb_tgs_response(c: connection, msg: KDC_Response) &priority=5
|
||||
{
|
||||
local info: Info;
|
||||
|
||||
if ( c?$krb && c$krb$logged )
|
||||
return;
|
||||
|
||||
if ( c?$krb )
|
||||
info = c$krb;
|
||||
|
||||
if ( ! info?$ts )
|
||||
{
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
}
|
||||
|
||||
if ( ! info?$client )
|
||||
info$client = fmt("%s/%s", msg$client_name, msg$client_realm);
|
||||
|
||||
info$service = msg$ticket$service_name;
|
||||
info$cipher = cipher_name[msg$ticket$cipher];
|
||||
info$success = T;
|
||||
|
||||
c$krb = info;
|
||||
}
|
||||
|
||||
event krb_tgs_response(c: connection, msg: KDC_Response) &priority=-5
|
||||
{
|
||||
Log::write(KRB::LOG, c$krb);
|
||||
c$krb$logged = T;
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
if ( c?$krb && ! c$krb$logged )
|
||||
Log::write(KRB::LOG, c$krb);
|
||||
}
|
3
scripts/base/protocols/sip/__load__.bro
Normal file
3
scripts/base/protocols/sip/__load__.bro
Normal file
|
@ -0,0 +1,3 @@
|
|||
@load ./main
|
||||
|
||||
@load-sigs ./dpd.sig
|
19
scripts/base/protocols/sip/dpd.sig
Normal file
19
scripts/base/protocols/sip/dpd.sig
Normal file
|
@ -0,0 +1,19 @@
|
|||
signature dpd_sip_udp_req {
|
||||
ip-proto == udp
|
||||
payload /.* SIP\/[0-9]\.[0-9]\x0d\x0a/
|
||||
enable "sip"
|
||||
}
|
||||
|
||||
signature dpd_sip_udp_resp {
|
||||
ip-proto == udp
|
||||
payload /^ ?SIP\/[0-9]\.[0-9](\x0d\x0a| [0-9][0-9][0-9] )/
|
||||
enable "sip"
|
||||
}
|
||||
|
||||
# We don't support SIP-over-TCP yet.
|
||||
#
|
||||
# signature dpd_sip_tcp {
|
||||
# ip-proto == tcp
|
||||
# payload /^( SIP\/[0-9]\.[0-9]\x0d\x0a|SIP\/[0-9]\.[0-9] [0-9][0-9][0-9] )/
|
||||
# enable "sip_tcp"
|
||||
# }
|
272
scripts/base/protocols/sip/main.bro
Normal file
272
scripts/base/protocols/sip/main.bro
Normal file
|
@ -0,0 +1,272 @@
|
|||
##! Implements base functionality for SIP analysis. The logging model is
|
||||
##! to log request/response pairs and all relevant metadata together in
|
||||
##! a single record.
|
||||
|
||||
@load base/utils/numbers
|
||||
@load base/utils/files
|
||||
|
||||
module SIP;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Timestamp for when the request happened.
|
||||
ts: time &log;
|
||||
## Unique ID for the connection.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## Represents the pipelined depth into the connection of this
|
||||
## request/response transaction.
|
||||
trans_depth: count &log;
|
||||
## Verb used in the SIP request (INVITE, REGISTER etc.).
|
||||
method: string &log &optional;
|
||||
## URI used in the request.
|
||||
uri: string &log &optional;
|
||||
## Contents of the Date: header from the client
|
||||
date: string &log &optional;
|
||||
## Contents of the request From: header
|
||||
## Note: The tag= value that's usually appended to the sender
|
||||
## is stripped off and not logged.
|
||||
request_from: string &log &optional;
|
||||
## Contents of the To: header
|
||||
request_to: string &log &optional;
|
||||
## Contents of the response From: header
|
||||
## Note: The ``tag=`` value that's usually appended to the sender
|
||||
## is stripped off and not logged.
|
||||
response_from: string &log &optional;
|
||||
## Contents of the response To: header
|
||||
response_to: string &log &optional;
|
||||
|
||||
## Contents of the Reply-To: header
|
||||
reply_to: string &log &optional;
|
||||
## Contents of the Call-ID: header from the client
|
||||
call_id: string &log &optional;
|
||||
## Contents of the CSeq: header from the client
|
||||
seq: string &log &optional;
|
||||
## Contents of the Subject: header from the client
|
||||
subject: string &log &optional;
|
||||
## The client message transmission path, as extracted from the headers.
|
||||
request_path: vector of string &log &optional;
|
||||
## The server message transmission path, as extracted from the headers.
|
||||
response_path: vector of string &log &optional;
|
||||
## Contents of the User-Agent: header from the client
|
||||
user_agent: string &log &optional;
|
||||
## Status code returned by the server.
|
||||
status_code: count &log &optional;
|
||||
## Status message returned by the server.
|
||||
status_msg: string &log &optional;
|
||||
## Contents of the Warning: header
|
||||
warning: string &log &optional;
|
||||
## Contents of the Content-Length: header from the client
|
||||
request_body_len: string &log &optional;
|
||||
## Contents of the Content-Length: header from the server
|
||||
response_body_len: string &log &optional;
|
||||
## Contents of the Content-Type: header from the server
|
||||
content_type: string &log &optional;
|
||||
};
|
||||
|
||||
type State: record {
|
||||
## Pending requests.
|
||||
pending: table[count] of Info;
|
||||
## Current request in the pending queue.
|
||||
current_request: count &default=0;
|
||||
## Current response in the pending queue.
|
||||
current_response: count &default=0;
|
||||
};
|
||||
|
||||
## A list of SIP methods. Other methods will generate a weird. Note
|
||||
## that the SIP analyzer will only accept methods consisting solely
|
||||
## of letters ``[A-Za-z]``.
|
||||
const sip_methods: set[string] = {
|
||||
"REGISTER", "INVITE", "ACK", "CANCEL", "BYE", "OPTIONS"
|
||||
} &redef;
|
||||
|
||||
## Event that can be handled to access the SIP record as it is sent on
|
||||
## to the logging framework.
|
||||
global log_sip: event(rec: Info);
|
||||
}
|
||||
|
||||
# Add the sip state tracking fields to the connection record.
|
||||
redef record connection += {
|
||||
sip: Info &optional;
|
||||
sip_state: State &optional;
|
||||
};
|
||||
|
||||
const ports = { 5060/udp };
|
||||
redef likely_server_ports += { ports };
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(SIP::LOG, [$columns=Info, $ev=log_sip, $path="sip"]);
|
||||
Analyzer::register_for_ports(Analyzer::ANALYZER_SIP, ports);
|
||||
}
|
||||
|
||||
function new_sip_session(c: connection): Info
|
||||
{
|
||||
local tmp: Info;
|
||||
tmp$ts=network_time();
|
||||
tmp$uid=c$uid;
|
||||
tmp$id=c$id;
|
||||
# $current_request is set prior to the Info record creation so we
|
||||
# can use the value directly here.
|
||||
tmp$trans_depth = c$sip_state$current_request;
|
||||
|
||||
tmp$request_path = vector();
|
||||
tmp$response_path = vector();
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function set_state(c: connection, is_request: bool)
|
||||
{
|
||||
if ( ! c?$sip_state )
|
||||
{
|
||||
local s: State;
|
||||
c$sip_state = s;
|
||||
}
|
||||
|
||||
# These deal with new requests and responses.
|
||||
if ( is_request && c$sip_state$current_request !in c$sip_state$pending )
|
||||
c$sip_state$pending[c$sip_state$current_request] = new_sip_session(c);
|
||||
if ( ! is_request && c$sip_state$current_response !in c$sip_state$pending )
|
||||
c$sip_state$pending[c$sip_state$current_response] = new_sip_session(c);
|
||||
|
||||
if ( is_request )
|
||||
c$sip = c$sip_state$pending[c$sip_state$current_request];
|
||||
else
|
||||
c$sip = c$sip_state$pending[c$sip_state$current_response];
|
||||
|
||||
if ( is_request )
|
||||
{
|
||||
if ( c$sip_state$current_request !in c$sip_state$pending )
|
||||
c$sip_state$pending[c$sip_state$current_request] = new_sip_session(c);
|
||||
|
||||
c$sip = c$sip_state$pending[c$sip_state$current_request];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( c$sip_state$current_response !in c$sip_state$pending )
|
||||
c$sip_state$pending[c$sip_state$current_response] = new_sip_session(c);
|
||||
|
||||
c$sip = c$sip_state$pending[c$sip_state$current_response];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function flush_pending(c: connection)
|
||||
{
|
||||
# Flush all pending but incomplete request/response pairs.
|
||||
if ( c?$sip_state )
|
||||
{
|
||||
for ( r in c$sip_state$pending )
|
||||
{
|
||||
# We don't use pending elements at index 0.
|
||||
if ( r == 0 ) next;
|
||||
Log::write(SIP::LOG, c$sip_state$pending[r]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event sip_request(c: connection, method: string, original_URI: string, version: string) &priority=5
|
||||
{
|
||||
set_state(c, T);
|
||||
|
||||
c$sip$method = method;
|
||||
c$sip$uri = original_URI;
|
||||
|
||||
if ( method !in sip_methods )
|
||||
event conn_weird("unknown_SIP_method", c, method);
|
||||
}
|
||||
|
||||
event sip_reply(c: connection, version: string, code: count, reason: string) &priority=5
|
||||
{
|
||||
set_state(c, F);
|
||||
|
||||
if ( c$sip_state$current_response !in c$sip_state$pending &&
|
||||
(code < 100 && 200 <= code) )
|
||||
++c$sip_state$current_response;
|
||||
|
||||
c$sip$status_code = code;
|
||||
c$sip$status_msg = reason;
|
||||
}
|
||||
|
||||
event sip_header(c: connection, is_request: bool, name: string, value: string) &priority=5
|
||||
{
|
||||
if ( ! c?$sip_state )
|
||||
{
|
||||
local s: State;
|
||||
c$sip_state = s;
|
||||
}
|
||||
|
||||
if ( is_request ) # from client
|
||||
{
|
||||
if ( c$sip_state$current_request !in c$sip_state$pending )
|
||||
++c$sip_state$current_request;
|
||||
set_state(c, is_request);
|
||||
if ( name == "CALL-ID" ) c$sip$call_id = value;
|
||||
else if ( name == "CONTENT-LENGTH" || name == "L" ) c$sip$request_body_len = value;
|
||||
else if ( name == "CSEQ" ) c$sip$seq = value;
|
||||
else if ( name == "DATE" ) c$sip$date = value;
|
||||
else if ( name == "FROM" || name == "F" ) c$sip$request_from = split_string1(value, /;[ ]?tag=/)[0];
|
||||
else if ( name == "REPLY-TO" ) c$sip$reply_to = value;
|
||||
else if ( name == "SUBJECT" || name == "S" ) c$sip$subject = value;
|
||||
else if ( name == "TO" || name == "T" ) c$sip$request_to = value;
|
||||
else if ( name == "USER-AGENT" ) c$sip$user_agent = value;
|
||||
else if ( name == "VIA" || name == "V" ) c$sip$request_path[|c$sip$request_path|] = split_string1(value, /;[ ]?branch/)[0];
|
||||
|
||||
c$sip_state$pending[c$sip_state$current_request] = c$sip;
|
||||
}
|
||||
else # from server
|
||||
{
|
||||
if ( c$sip_state$current_response !in c$sip_state$pending )
|
||||
++c$sip_state$current_response;
|
||||
set_state(c, is_request);
|
||||
if ( name == "CONTENT-LENGTH" || name == "L" ) c$sip$response_body_len = value;
|
||||
else if ( name == "CONTENT-TYPE" || name == "C" ) c$sip$content_type = value;
|
||||
else if ( name == "WARNING" ) c$sip$warning = value;
|
||||
else if ( name == "FROM" || name == "F" ) c$sip$response_from = split_string1(value, /;[ ]?tag=/)[0];
|
||||
else if ( name == "TO" || name == "T" ) c$sip$response_to = value;
|
||||
else if ( name == "VIA" || name == "V" ) c$sip$response_path[|c$sip$response_path|] = split_string1(value, /;[ ]?branch/)[0];
|
||||
|
||||
c$sip_state$pending[c$sip_state$current_response] = c$sip;
|
||||
}
|
||||
}
|
||||
|
||||
event sip_end_entity(c: connection, is_request: bool) &priority = 5
|
||||
{
|
||||
set_state(c, is_request);
|
||||
}
|
||||
|
||||
event sip_end_entity(c: connection, is_request: bool) &priority = -5
|
||||
{
|
||||
# The reply body is done so we're ready to log.
|
||||
if ( ! is_request )
|
||||
{
|
||||
Log::write(SIP::LOG, c$sip);
|
||||
|
||||
if ( c$sip$status_code < 100 || 200 <= c$sip$status_code )
|
||||
delete c$sip_state$pending[c$sip_state$current_response];
|
||||
|
||||
if ( ! c$sip?$method || ( c$sip$method == "BYE" &&
|
||||
c$sip$status_code >= 200 && c$sip$status_code < 300 ) )
|
||||
{
|
||||
flush_pending(c);
|
||||
delete c$sip;
|
||||
delete c$sip_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) &priority=-5
|
||||
{
|
||||
if ( c?$sip_state )
|
||||
{
|
||||
for ( r in c$sip_state$pending )
|
||||
{
|
||||
Log::write(SIP::LOG, c$sip_state$pending[r]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -93,6 +93,10 @@ function set_session(c: connection)
|
|||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
|
||||
# If both hosts are local or non-local, we can't reliably set a direction.
|
||||
if ( Site::is_local_addr(c$id$orig_h) != Site::is_local_addr(c$id$resp_h) )
|
||||
info$direction = Site::is_local_addr(c$id$orig_h) ? OUTBOUND: INBOUND;
|
||||
c$ssh = info;
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +118,7 @@ event ssh_client_version(c: connection, version: string)
|
|||
c$ssh$version = 2;
|
||||
}
|
||||
|
||||
event ssh_auth_successful(c: connection, auth_method_none: bool)
|
||||
event ssh_auth_successful(c: connection, auth_method_none: bool) &priority=5
|
||||
{
|
||||
# TODO - what to do here?
|
||||
if ( !c?$ssh || ( c$ssh?$auth_success && c$ssh$auth_success ) )
|
||||
|
@ -142,7 +146,7 @@ event ssh_auth_successful(c: connection, auth_method_none: bool) &priority=-5
|
|||
}
|
||||
}
|
||||
|
||||
event ssh_auth_failed(c: connection)
|
||||
event ssh_auth_failed(c: connection) &priority=5
|
||||
{
|
||||
if ( !c?$ssh || ( c$ssh?$auth_success && !c$ssh$auth_success ) )
|
||||
return;
|
||||
|
|
|
@ -12,14 +12,14 @@ export {
|
|||
## notice will be generated.
|
||||
Watched_Country_Login,
|
||||
};
|
||||
|
||||
|
||||
redef record Info += {
|
||||
## Add geographic data related to the "remote" host of the
|
||||
## connection.
|
||||
remote_location: geo_location &log &optional;
|
||||
};
|
||||
|
||||
## The set of countries for which you'd like to generate notices upon
|
||||
|
||||
## The set of countries for which you'd like to generate notices upon
|
||||
## successful login.
|
||||
const watched_countries: set[string] = {"RO"} &redef;
|
||||
}
|
||||
|
@ -32,21 +32,27 @@ function get_location(c: connection): geo_location
|
|||
|
||||
event ssh_auth_successful(c: connection, auth_method_none: bool) &priority=3
|
||||
{
|
||||
if ( ! c$ssh?$direction )
|
||||
return;
|
||||
|
||||
# Add the location data to the SSH record.
|
||||
c$ssh$remote_location = get_location(c);
|
||||
|
||||
|
||||
if ( c$ssh$remote_location?$country_code && c$ssh$remote_location$country_code in watched_countries )
|
||||
{
|
||||
NOTICE([$note=Watched_Country_Login,
|
||||
$conn=c,
|
||||
$msg=fmt("SSH login %s watched country: %s",
|
||||
(c$ssh$direction == OUTBOUND) ? "to" : "from",
|
||||
$msg=fmt("SSH login %s watched country: %s",
|
||||
(c$ssh$direction == OUTBOUND) ? "to" : "from",
|
||||
c$ssh$remote_location$country_code)]);
|
||||
}
|
||||
}
|
||||
|
||||
event ssh_auth_failed(c: connection) &priority=3
|
||||
{
|
||||
if ( ! c$ssh?$direction )
|
||||
return;
|
||||
|
||||
# Add the location data to the SSH record.
|
||||
c$ssh$remote_location = get_location(c);
|
||||
}
|
||||
|
|
|
@ -194,22 +194,7 @@ char* BroString::Render(int format, int* len) const
|
|||
|
||||
for ( int i = 0; i < n; ++i )
|
||||
{
|
||||
if ( b[i] == '\0' && (format & ESC_NULL) )
|
||||
{
|
||||
*sp++ = '\\'; *sp++ = '0';
|
||||
}
|
||||
|
||||
else if ( b[i] == '\x7f' && (format & ESC_DEL) )
|
||||
{
|
||||
*sp++ = '^'; *sp++ = '?';
|
||||
}
|
||||
|
||||
else if ( b[i] <= 26 && (format & ESC_LOW) )
|
||||
{
|
||||
*sp++ = '^'; *sp++ = b[i] + 'A' - 1;
|
||||
}
|
||||
|
||||
else if ( b[i] == '\\' && (format & ESC_ESC) )
|
||||
if ( b[i] == '\\' && (format & ESC_ESC) )
|
||||
{
|
||||
*sp++ = '\\'; *sp++ = '\\';
|
||||
}
|
||||
|
|
|
@ -75,21 +75,17 @@ public:
|
|||
|
||||
enum render_style {
|
||||
ESC_NONE = 0,
|
||||
|
||||
ESC_NULL = (1 << 0), // 0 -> "\0"
|
||||
ESC_DEL = (1 << 1), // DEL -> "^?"
|
||||
ESC_LOW = (1 << 2), // values <= 26 mapped into "^[A-Z]"
|
||||
ESC_ESC = (1 << 3), // '\' -> "\\"
|
||||
ESC_QUOT = (1 << 4), // '"' -> "\"", ''' -> "\'"
|
||||
ESC_HEX = (1 << 5), // Not in [32, 126]? -> "%XX"
|
||||
ESC_DOT = (1 << 6), // Not in [32, 126]? -> "."
|
||||
ESC_ESC = (1 << 1), // '\' -> "\\"
|
||||
ESC_QUOT = (1 << 2), // '"' -> "\"", ''' -> "\'"
|
||||
ESC_HEX = (1 << 3), // Not in [32, 126]? -> "\xXX"
|
||||
ESC_DOT = (1 << 4), // Not in [32, 126]? -> "."
|
||||
|
||||
// For serialization: '<string len> <string>'
|
||||
ESC_SER = (1 << 7),
|
||||
};
|
||||
|
||||
static const int EXPANDED_STRING = // the original style
|
||||
ESC_NULL | ESC_DEL | ESC_LOW | ESC_HEX;
|
||||
ESC_HEX;
|
||||
|
||||
static const int BRO_STRING_LITERAL = // as in a Bro string literal
|
||||
ESC_ESC | ESC_QUOT | ESC_HEX;
|
||||
|
|
10
src/Conn.cc
10
src/Conn.cc
|
@ -375,17 +375,15 @@ RecordVal* Connection::BuildConnVal()
|
|||
conn_val->Assign(2, resp_endp);
|
||||
// 3 and 4 are set below.
|
||||
conn_val->Assign(5, new TableVal(string_set)); // service
|
||||
conn_val->Assign(6, new StringVal("")); // addl
|
||||
conn_val->Assign(7, new Val(0, TYPE_COUNT)); // hot
|
||||
conn_val->Assign(8, new StringVal("")); // history
|
||||
conn_val->Assign(6, new StringVal("")); // history
|
||||
|
||||
if ( ! uid )
|
||||
uid.Set(bits_per_uid);
|
||||
|
||||
conn_val->Assign(9, new StringVal(uid.Base62("C").c_str()));
|
||||
conn_val->Assign(7, new StringVal(uid.Base62("C").c_str()));
|
||||
|
||||
if ( encapsulation && encapsulation->Depth() > 0 )
|
||||
conn_val->Assign(10, encapsulation->GetVectorVal());
|
||||
conn_val->Assign(8, encapsulation->GetVectorVal());
|
||||
}
|
||||
|
||||
if ( root_analyzer )
|
||||
|
@ -393,7 +391,7 @@ RecordVal* Connection::BuildConnVal()
|
|||
|
||||
conn_val->Assign(3, new Val(start_time, TYPE_TIME)); // ###
|
||||
conn_val->Assign(4, new Val(last_time - start_time, TYPE_INTERVAL));
|
||||
conn_val->Assign(8, new StringVal(history.c_str()));
|
||||
conn_val->Assign(6, new StringVal(history.c_str()));
|
||||
|
||||
conn_val->SetOrigin(this);
|
||||
|
||||
|
|
10
src/Desc.cc
10
src/Desc.cc
|
@ -181,13 +181,7 @@ void ODesc::AddBytes(const BroString* s)
|
|||
AddBytes(reinterpret_cast<const char*>(s->Bytes()), s->Len());
|
||||
else
|
||||
{
|
||||
int render_style = BroString::EXPANDED_STRING;
|
||||
if ( Style() == ALTERNATIVE_STYLE )
|
||||
// Only change NULs, since we can't in any case
|
||||
// cope with them.
|
||||
render_style = BroString::ESC_NULL;
|
||||
|
||||
const char* str = s->Render(render_style);
|
||||
const char* str = s->Render(BroString::EXPANDED_STRING);
|
||||
Add(str);
|
||||
delete [] str;
|
||||
}
|
||||
|
@ -256,7 +250,7 @@ pair<const char*, size_t> ODesc::FirstEscapeLoc(const char* bytes, size_t n)
|
|||
|
||||
for ( size_t i = 0; i < n; ++i )
|
||||
{
|
||||
if ( ! isprint(bytes[i]) )
|
||||
if ( ! isprint(bytes[i]) || bytes[i] == '\\' )
|
||||
return escape_pos(bytes + i, 1);
|
||||
|
||||
size_t len = StartsWithEscapeSequence(bytes + i, bytes + n);
|
||||
|
|
|
@ -17,7 +17,6 @@ typedef enum {
|
|||
|
||||
typedef enum {
|
||||
STANDARD_STYLE,
|
||||
ALTERNATIVE_STYLE,
|
||||
RAW_STYLE,
|
||||
} desc_style;
|
||||
|
||||
|
|
576
src/Expr.cc
576
src/Expr.cc
|
@ -249,18 +249,6 @@ NameExpr::~NameExpr()
|
|||
Unref(id);
|
||||
}
|
||||
|
||||
Expr* NameExpr::Simplify(SimplifyType simp_type)
|
||||
{
|
||||
if ( simp_type != SIMPLIFY_LHS && id->IsConst() )
|
||||
{
|
||||
Val* v = Eval(0);
|
||||
if ( v )
|
||||
return new ConstExpr(v);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* NameExpr::Eval(Frame* f) const
|
||||
{
|
||||
Val* v;
|
||||
|
@ -410,11 +398,6 @@ void ConstExpr::ExprDescribe(ODesc* d) const
|
|||
val->Describe(d);
|
||||
}
|
||||
|
||||
Expr* ConstExpr::Simplify(SimplifyType /* simp_type */)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* ConstExpr::Eval(Frame* /* f */) const
|
||||
{
|
||||
return Value()->Ref();
|
||||
|
@ -457,16 +440,6 @@ UnaryExpr::~UnaryExpr()
|
|||
Unref(op);
|
||||
}
|
||||
|
||||
Expr* UnaryExpr::Simplify(SimplifyType simp_type)
|
||||
{
|
||||
if ( IsError() )
|
||||
return this;
|
||||
|
||||
op = simplify_expr(op, simp_type);
|
||||
Canonicize();
|
||||
return DoSimplify();
|
||||
}
|
||||
|
||||
Val* UnaryExpr::Eval(Frame* f) const
|
||||
{
|
||||
if ( IsError() )
|
||||
|
@ -516,11 +489,6 @@ TraversalCode UnaryExpr::Traverse(TraversalCallback* cb) const
|
|||
HANDLE_TC_EXPR_POST(tc);
|
||||
}
|
||||
|
||||
Expr* UnaryExpr::DoSimplify()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* UnaryExpr::Fold(Val* v) const
|
||||
{
|
||||
return v->Ref();
|
||||
|
@ -573,19 +541,6 @@ BinaryExpr::~BinaryExpr()
|
|||
Unref(op2);
|
||||
}
|
||||
|
||||
Expr* BinaryExpr::Simplify(SimplifyType /* simp_type */)
|
||||
{
|
||||
if ( IsError() )
|
||||
return this;
|
||||
|
||||
SimplifyOps();
|
||||
|
||||
if ( BothConst() )
|
||||
return new ConstExpr(Fold(op1->ExprVal(), op2->ExprVal()));
|
||||
else
|
||||
return DoSimplify();
|
||||
}
|
||||
|
||||
Val* BinaryExpr::Eval(Frame* f) const
|
||||
{
|
||||
if ( IsError() )
|
||||
|
@ -687,11 +642,6 @@ TraversalCode BinaryExpr::Traverse(TraversalCallback* cb) const
|
|||
HANDLE_TC_EXPR_POST(tc);
|
||||
}
|
||||
|
||||
Expr* BinaryExpr::DoSimplify()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void BinaryExpr::ExprDescribe(ODesc* d) const
|
||||
{
|
||||
op1->Describe(d);
|
||||
|
@ -703,13 +653,6 @@ void BinaryExpr::ExprDescribe(ODesc* d) const
|
|||
op2->Describe(d);
|
||||
}
|
||||
|
||||
void BinaryExpr::SimplifyOps()
|
||||
{
|
||||
op1 = simplify_expr(op1, SIMPLIFY_GENERAL);
|
||||
op2 = simplify_expr(op2, SIMPLIFY_GENERAL);
|
||||
Canonicize();
|
||||
}
|
||||
|
||||
Val* BinaryExpr::Fold(Val* v1, Val* v2) const
|
||||
{
|
||||
InternalTypeTag it = v1->Type()->InternalType();
|
||||
|
@ -1147,21 +1090,6 @@ NotExpr::NotExpr(Expr* arg_op) : UnaryExpr(EXPR_NOT, arg_op)
|
|||
SetType(base_type(TYPE_BOOL));
|
||||
}
|
||||
|
||||
Expr* NotExpr::DoSimplify()
|
||||
{
|
||||
op = simplify_expr(op, SIMPLIFY_GENERAL);
|
||||
Canonicize();
|
||||
|
||||
if ( op->Tag() == EXPR_NOT )
|
||||
// !!x == x
|
||||
return ((NotExpr*) op)->Op()->Ref();
|
||||
|
||||
if ( op->IsConst() )
|
||||
return new ConstExpr(Fold(op->ExprVal()));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* NotExpr::Fold(Val* v) const
|
||||
{
|
||||
return new Val(! v->InternalInt(), type->Tag());
|
||||
|
@ -1207,22 +1135,6 @@ PosExpr::PosExpr(Expr* arg_op) : UnaryExpr(EXPR_POSITIVE, arg_op)
|
|||
SetType(base_result_type);
|
||||
}
|
||||
|
||||
Expr* PosExpr::DoSimplify()
|
||||
{
|
||||
op = simplify_expr(op, SIMPLIFY_GENERAL);
|
||||
Canonicize();
|
||||
|
||||
TypeTag t = op->Type()->Tag();
|
||||
|
||||
if ( t == TYPE_DOUBLE || t == TYPE_INTERVAL || t == TYPE_INT )
|
||||
return op->Ref();
|
||||
|
||||
if ( op->IsConst() && ! is_vector(op->ExprVal()) )
|
||||
return new ConstExpr(Fold(op->ExprVal()));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* PosExpr::Fold(Val* v) const
|
||||
{
|
||||
TypeTag t = v->Type()->Tag();
|
||||
|
@ -1273,27 +1185,6 @@ NegExpr::NegExpr(Expr* arg_op) : UnaryExpr(EXPR_NEGATE, arg_op)
|
|||
SetType(base_result_type);
|
||||
}
|
||||
|
||||
Expr* NegExpr::DoSimplify()
|
||||
{
|
||||
op = simplify_expr(op, SIMPLIFY_GENERAL);
|
||||
Canonicize();
|
||||
|
||||
if ( op->Tag() == EXPR_NEGATE )
|
||||
// -(-x) == x
|
||||
return ((NegExpr*) op)->Op()->Ref();
|
||||
|
||||
if ( op->IsConst() && ! is_vector(op->ExprVal()) )
|
||||
return new ConstExpr(Fold(op->ExprVal()));
|
||||
|
||||
if ( op->Tag() == EXPR_SUB )
|
||||
{ // -(a-b) == b-a
|
||||
SubExpr* s = (SubExpr*) op;
|
||||
return new SubExpr(s->Op2()->Ref(), s->Op1()->Ref());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* NegExpr::Fold(Val* v) const
|
||||
{
|
||||
if ( v->Type()->Tag() == TYPE_DOUBLE )
|
||||
|
@ -1396,24 +1287,6 @@ AddExpr::AddExpr(Expr* arg_op1, Expr* arg_op2)
|
|||
}
|
||||
}
|
||||
|
||||
Expr* AddExpr::DoSimplify()
|
||||
{
|
||||
// If there's a constant, then it's in op1, since Canonicize()
|
||||
// makes sure of that.
|
||||
if ( op1->IsZero() )
|
||||
return op2->Ref();
|
||||
|
||||
else if ( op1->Tag() == EXPR_NEGATE )
|
||||
// (-a)+b = b-a
|
||||
return new AddExpr(op2->Ref(), ((NegExpr*) op1)->Op()->Ref());
|
||||
|
||||
else if ( op2->Tag() == EXPR_NEGATE )
|
||||
// a+(-b) == a-b
|
||||
return new SubExpr(op1->Ref(), ((NegExpr*) op2)->Op()->Ref());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void AddExpr::Canonicize()
|
||||
{
|
||||
if ( expr_greater(op2, op1) ||
|
||||
|
@ -1532,21 +1405,6 @@ SubExpr::SubExpr(Expr* arg_op1, Expr* arg_op2)
|
|||
}
|
||||
}
|
||||
|
||||
Expr* SubExpr::DoSimplify()
|
||||
{
|
||||
if ( op1->IsZero() )
|
||||
return new NegExpr(op2->Ref());
|
||||
|
||||
else if ( op2->IsZero() )
|
||||
return op1->Ref();
|
||||
|
||||
else if ( op2->Tag() == EXPR_NEGATE )
|
||||
// a-(-b) = a+b
|
||||
return new AddExpr(op1->Ref(), ((NegExpr*) op2)->Op()->Ref());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIAL(SubExpr, SER_SUB_EXPR);
|
||||
|
||||
bool SubExpr::DoSerialize(SerialInfo* info) const
|
||||
|
@ -1648,27 +1506,6 @@ TimesExpr::TimesExpr(Expr* arg_op1, Expr* arg_op2)
|
|||
ExprError("requires arithmetic operands");
|
||||
}
|
||||
|
||||
Expr* TimesExpr::DoSimplify()
|
||||
{
|
||||
// If there's a constant, then it's in op1, since Canonicize()
|
||||
// makes sure of that.
|
||||
if ( op1->IsConst() )
|
||||
{
|
||||
if ( op1->IsZero() )
|
||||
{
|
||||
if ( IsVector(op2->Type()->Tag()) )
|
||||
return this;
|
||||
else
|
||||
return make_zero(type);
|
||||
}
|
||||
|
||||
else if ( op1->IsOne() )
|
||||
return op2->Ref();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void TimesExpr::Canonicize()
|
||||
{
|
||||
if ( expr_greater(op2, op1) || op2->Type()->Tag() == TYPE_INTERVAL ||
|
||||
|
@ -1741,31 +1578,6 @@ Val* DivideExpr::AddrFold(Val* v1, Val* v2) const
|
|||
return new SubNetVal(v1->AsAddr(), mask);
|
||||
}
|
||||
|
||||
Expr* DivideExpr::DoSimplify()
|
||||
{
|
||||
if ( IsError() )
|
||||
return this;
|
||||
|
||||
if ( op1->Type()->Tag() == TYPE_ADDR )
|
||||
return this;
|
||||
|
||||
if ( is_vector(op1) || is_vector(op2) )
|
||||
return this;
|
||||
|
||||
if ( op2->IsConst() )
|
||||
{
|
||||
if ( op2->IsOne() )
|
||||
return op1->Ref();
|
||||
else if ( op2->IsZero() )
|
||||
Error("zero divisor");
|
||||
}
|
||||
|
||||
else if ( same_expr(op1, op2) )
|
||||
return make_one(type);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIAL(DivideExpr, SER_DIVIDE_EXPR);
|
||||
|
||||
bool DivideExpr::DoSerialize(SerialInfo* info) const
|
||||
|
@ -1800,31 +1612,6 @@ ModExpr::ModExpr(Expr* arg_op1, Expr* arg_op2)
|
|||
ExprError("requires integral operands");
|
||||
}
|
||||
|
||||
Expr* ModExpr::DoSimplify()
|
||||
{
|
||||
if ( IsError() )
|
||||
return this;
|
||||
|
||||
TypeTag bt1 = op1->Type()->Tag();
|
||||
TypeTag bt2 = op2->Type()->Tag();
|
||||
|
||||
if ( IsVector(bt1) || IsVector(bt2) )
|
||||
return this;
|
||||
|
||||
if ( op2->IsConst() )
|
||||
{
|
||||
if ( op2->IsOne() )
|
||||
return make_zero(type);
|
||||
else if ( op2->IsZero() )
|
||||
Error("zero modulus");
|
||||
}
|
||||
|
||||
else if ( same_expr(op1, op2) )
|
||||
return make_zero(type);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIAL(ModExpr, SER_MOD_EXPR);
|
||||
|
||||
bool ModExpr::DoSerialize(SerialInfo* info) const
|
||||
|
@ -2011,37 +1798,6 @@ Val* BoolExpr::Eval(Frame* f) const
|
|||
return result;
|
||||
}
|
||||
|
||||
Expr* BoolExpr::DoSimplify()
|
||||
{
|
||||
if ( op1->IsConst() && ! is_vector(op1) )
|
||||
{
|
||||
if ( op1->IsZero() )
|
||||
// F && x or F || x
|
||||
return (tag == EXPR_AND) ? make_zero(type) : op2->Ref();
|
||||
else
|
||||
// T && x or T || x
|
||||
return (tag == EXPR_AND) ? op2->Ref() : make_one(type);
|
||||
}
|
||||
|
||||
else if ( op2->IsConst() && ! is_vector(op2) )
|
||||
{
|
||||
if ( op1->IsZero() )
|
||||
// x && F or x || F
|
||||
return (tag == EXPR_AND) ? make_zero(type) : op1->Ref();
|
||||
else
|
||||
// x && T or x || T
|
||||
return (tag == EXPR_AND) ? op1->Ref() : make_one(type);
|
||||
}
|
||||
|
||||
else if ( same_expr(op1, op2) )
|
||||
{
|
||||
Warn("redundant boolean operation");
|
||||
return op1->Ref();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIAL(BoolExpr, SER_BOOL_EXPR);
|
||||
|
||||
bool BoolExpr::DoSerialize(SerialInfo* info) const
|
||||
|
@ -2128,22 +1884,6 @@ void EqExpr::Canonicize()
|
|||
SwapOps();
|
||||
}
|
||||
|
||||
Expr* EqExpr::DoSimplify()
|
||||
{
|
||||
if ( same_expr(op1, op2) && ! is_vector(op1) )
|
||||
{
|
||||
if ( ! optimize )
|
||||
Warn("redundant comparison");
|
||||
|
||||
if ( tag == EXPR_EQ )
|
||||
return make_one(type);
|
||||
else
|
||||
return make_zero(type);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* EqExpr::Fold(Val* v1, Val* v2) const
|
||||
{
|
||||
if ( op1->Type()->Tag() == TYPE_PATTERN )
|
||||
|
@ -2207,22 +1947,6 @@ RelExpr::RelExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2)
|
|||
ExprError("illegal comparison");
|
||||
}
|
||||
|
||||
Expr* RelExpr::DoSimplify()
|
||||
{
|
||||
if ( same_expr(op1, op2) )
|
||||
{
|
||||
Warn("redundant comparison");
|
||||
// Here we use the fact that the canonical form of
|
||||
// a RelExpr only uses EXPR_LE or EXPR_LT.
|
||||
if ( tag == EXPR_LE )
|
||||
return make_one(type);
|
||||
else
|
||||
return make_zero(type);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void RelExpr::Canonicize()
|
||||
{
|
||||
if ( tag == EXPR_GT )
|
||||
|
@ -2314,25 +2038,6 @@ CondExpr::~CondExpr()
|
|||
Unref(op3);
|
||||
}
|
||||
|
||||
Expr* CondExpr::Simplify(SimplifyType /* simp_type */)
|
||||
{
|
||||
op1 = simplify_expr(op1, SIMPLIFY_GENERAL);
|
||||
op2 = simplify_expr(op2, SIMPLIFY_GENERAL);
|
||||
op3 = simplify_expr(op3, SIMPLIFY_GENERAL);
|
||||
|
||||
if ( op1->IsConst() && ! is_vector(op1) )
|
||||
{
|
||||
Val* v = op1->ExprVal();
|
||||
return (v->IsZero() ? op3 : op2)->Ref();
|
||||
}
|
||||
|
||||
if ( op1->Tag() == EXPR_NOT )
|
||||
return new CondExpr(((NotExpr*) op1)->Op()->Ref(),
|
||||
op3->Ref(), op2->Ref());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* CondExpr::Eval(Frame* f) const
|
||||
{
|
||||
if ( ! is_vector(op1) )
|
||||
|
@ -2684,13 +2389,6 @@ bool AssignExpr::TypeCheckArithmetics(TypeTag bt1, TypeTag bt2)
|
|||
}
|
||||
|
||||
|
||||
Expr* AssignExpr::Simplify(SimplifyType /* simp_type */)
|
||||
{
|
||||
op1 = simplify_expr(op1, SIMPLIFY_LHS);
|
||||
op2 = simplify_expr(op2, SIMPLIFY_GENERAL);
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* AssignExpr::Eval(Frame* f) const
|
||||
{
|
||||
if ( is_init )
|
||||
|
@ -3006,13 +2704,6 @@ Expr* IndexExpr::MakeLvalue()
|
|||
return new RefExpr(this);
|
||||
}
|
||||
|
||||
Expr* IndexExpr::Simplify(SimplifyType simp_type)
|
||||
{
|
||||
op1 = simplify_expr(op1, simp_type);
|
||||
op2 = simplify_expr(op2, SIMPLIFY_GENERAL);
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* IndexExpr::Eval(Frame* f) const
|
||||
{
|
||||
Val* v1 = op1->Eval(f);
|
||||
|
@ -3264,12 +2955,6 @@ Expr* FieldExpr::MakeLvalue()
|
|||
return new RefExpr(this);
|
||||
}
|
||||
|
||||
Expr* FieldExpr::Simplify(SimplifyType simp_type)
|
||||
{
|
||||
op = simplify_expr(op, simp_type);
|
||||
return this;
|
||||
}
|
||||
|
||||
int FieldExpr::CanDel() const
|
||||
{
|
||||
return td->FindAttr(ATTR_DEFAULT) || td->FindAttr(ATTR_OPTIONAL);
|
||||
|
@ -3995,73 +3680,6 @@ ArithCoerceExpr::ArithCoerceExpr(Expr* arg_op, TypeTag t)
|
|||
ExprError("bad coercion value");
|
||||
}
|
||||
|
||||
Expr* ArithCoerceExpr::DoSimplify()
|
||||
{
|
||||
if ( is_vector(op) )
|
||||
return this;
|
||||
|
||||
InternalTypeTag my_int = type->InternalType();
|
||||
InternalTypeTag op_int = op->Type()->InternalType();
|
||||
|
||||
if ( my_int == TYPE_INTERNAL_UNSIGNED )
|
||||
my_int = TYPE_INTERNAL_INT;
|
||||
if ( op_int == TYPE_INTERNAL_UNSIGNED )
|
||||
op_int = TYPE_INTERNAL_INT;
|
||||
|
||||
if ( my_int == op_int )
|
||||
return op->Ref();
|
||||
|
||||
if ( op->IsConst() )
|
||||
{
|
||||
if ( my_int == TYPE_INTERNAL_INT )
|
||||
{
|
||||
if ( op_int != TYPE_INTERNAL_DOUBLE )
|
||||
Internal("bad coercion in CoerceExpr::DoSimplify");
|
||||
double d = op->ExprVal()->InternalDouble();
|
||||
bro_int_t i = bro_int_t(d);
|
||||
|
||||
if ( i < 0 &&
|
||||
type->InternalType() == TYPE_INTERNAL_UNSIGNED )
|
||||
Warn("coercion produces negative count value");
|
||||
|
||||
if ( d != double(i) )
|
||||
Warn("coercion loses precision");
|
||||
|
||||
return new ConstExpr(new Val(i, type->Tag()));
|
||||
}
|
||||
|
||||
if ( my_int == TYPE_INTERNAL_DOUBLE )
|
||||
{
|
||||
if ( op_int == TYPE_INTERNAL_INT )
|
||||
{
|
||||
bro_int_t i = op->ExprVal()->InternalInt();
|
||||
double d = double(i);
|
||||
|
||||
if ( i != bro_int_t(d) )
|
||||
Warn("coercion loses precision");
|
||||
|
||||
return new ConstExpr(new Val(d, type->Tag()));
|
||||
}
|
||||
|
||||
if ( op_int == TYPE_INTERNAL_UNSIGNED )
|
||||
{
|
||||
bro_uint_t u = op->ExprVal()->InternalUnsigned();
|
||||
double d = double(u);
|
||||
|
||||
if ( u != (bro_uint_t) (d) )
|
||||
Warn("coercion loses precision");
|
||||
|
||||
return new ConstExpr(new Val(d, type->Tag()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Internal("bad coercion in CoerceExpr::DoSimplify");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* ArithCoerceExpr::FoldSingleVal(Val* v, InternalTypeTag t) const
|
||||
{
|
||||
switch ( t ) {
|
||||
|
@ -4186,6 +3804,9 @@ RecordCoerceExpr::RecordCoerceExpr(Expr* op, RecordType* r)
|
|||
map[t_i] = i;
|
||||
}
|
||||
|
||||
if ( IsError() )
|
||||
return;
|
||||
|
||||
for ( i = 0; i < map_size; ++i )
|
||||
{
|
||||
if ( map[i] == -1 )
|
||||
|
@ -4550,22 +4171,6 @@ int ScheduleExpr::IsPure() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
Expr* ScheduleExpr::Simplify(SimplifyType simp_type)
|
||||
{
|
||||
when = when->Simplify(simp_type);
|
||||
Expr* generic_event = event->Simplify(simp_type);
|
||||
|
||||
if ( ! generic_event )
|
||||
return 0;
|
||||
|
||||
if ( generic_event->Tag() != EXPR_CALL )
|
||||
Internal("bad event type in ScheduleExpr::Simplify");
|
||||
|
||||
event = (EventExpr*) generic_event;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* ScheduleExpr::Eval(Frame* f) const
|
||||
{
|
||||
if ( terminating )
|
||||
|
@ -4898,20 +4503,6 @@ int CallExpr::IsPure() const
|
|||
return pure;
|
||||
}
|
||||
|
||||
Expr* CallExpr::Simplify(SimplifyType /* simp_type */)
|
||||
{
|
||||
if ( IsError() )
|
||||
return this;
|
||||
|
||||
func = simplify_expr(func, SIMPLIFY_GENERAL);
|
||||
args = simplify_expr_list(args, SIMPLIFY_GENERAL);
|
||||
|
||||
if ( IsPure() )
|
||||
return new ConstExpr(Eval(0));
|
||||
else
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* CallExpr::Eval(Frame* f) const
|
||||
{
|
||||
if ( IsError() )
|
||||
|
@ -5064,14 +4655,6 @@ EventExpr::~EventExpr()
|
|||
Unref(args);
|
||||
}
|
||||
|
||||
Expr* EventExpr::Simplify(SimplifyType /* simp_type */)
|
||||
{
|
||||
if ( ! IsError() )
|
||||
args = simplify_expr_list(args, SIMPLIFY_GENERAL);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* EventExpr::Eval(Frame* f) const
|
||||
{
|
||||
if ( IsError() )
|
||||
|
@ -5178,17 +4761,6 @@ int ListExpr::AllConst() const
|
|||
return 1;
|
||||
}
|
||||
|
||||
Expr* ListExpr::Simplify(SimplifyType /* simp_type */)
|
||||
{
|
||||
loop_over_list(exprs, i)
|
||||
exprs.replace(i, simplify_expr(exprs[i], SIMPLIFY_GENERAL));
|
||||
|
||||
// Note that we do *not* simplify a list with one element
|
||||
// to just that element. The assumption that simplify_expr(ListExpr*)
|
||||
// returns a ListExpr* is widespread.
|
||||
return this;
|
||||
}
|
||||
|
||||
Val* ListExpr::Eval(Frame* f) const
|
||||
{
|
||||
ListVal* v = new ListVal(TYPE_ANY);
|
||||
|
@ -5820,25 +5392,6 @@ int check_and_promote_exprs_to_type(ListExpr*& elements, BroType* type)
|
|||
return 1;
|
||||
}
|
||||
|
||||
Expr* simplify_expr(Expr* e, SimplifyType simp_type)
|
||||
{
|
||||
if ( ! e )
|
||||
return 0;
|
||||
|
||||
for ( Expr* s = e->Simplify(simp_type); s != e; s = e->Simplify(simp_type) )
|
||||
{
|
||||
Unref(e);
|
||||
e = s;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
ListExpr* simplify_expr_list(ListExpr* l, SimplifyType simp_type)
|
||||
{
|
||||
return (ListExpr*) simplify_expr(l, simp_type);
|
||||
}
|
||||
|
||||
val_list* eval_list(Frame* f, const ListExpr* l)
|
||||
{
|
||||
const expr_list& e = l->Exprs();
|
||||
|
@ -5864,129 +5417,6 @@ val_list* eval_list(Frame* f, const ListExpr* l)
|
|||
return v;
|
||||
}
|
||||
|
||||
int same_expr(const Expr* e1, const Expr* e2)
|
||||
{
|
||||
if ( e1 == e2 )
|
||||
return 1;
|
||||
|
||||
if ( e1->Tag() != e2->Tag() || ! same_type(e1->Type(), e2->Type()) )
|
||||
return 0;
|
||||
|
||||
if ( e1->IsError() || e2->IsError() )
|
||||
return 0;
|
||||
|
||||
switch ( e1->Tag() ) {
|
||||
case EXPR_NAME:
|
||||
{
|
||||
const NameExpr* n1 = (NameExpr*) e1;
|
||||
const NameExpr* n2 = (NameExpr*) e2;
|
||||
return n1->Id() == n2->Id();
|
||||
}
|
||||
|
||||
case EXPR_CONST:
|
||||
{
|
||||
const ConstExpr* c1 = (ConstExpr*) e1;
|
||||
const ConstExpr* c2 = (ConstExpr*) e2;
|
||||
return same_val(c1->Value(), c2->Value());
|
||||
}
|
||||
|
||||
case EXPR_INCR:
|
||||
case EXPR_DECR:
|
||||
case EXPR_NOT:
|
||||
case EXPR_NEGATE:
|
||||
case EXPR_POSITIVE:
|
||||
case EXPR_REF:
|
||||
case EXPR_RECORD_CONSTRUCTOR:
|
||||
case EXPR_TABLE_CONSTRUCTOR:
|
||||
case EXPR_SET_CONSTRUCTOR:
|
||||
case EXPR_VECTOR_CONSTRUCTOR:
|
||||
case EXPR_FIELD_ASSIGN:
|
||||
case EXPR_ARITH_COERCE:
|
||||
case EXPR_RECORD_COERCE:
|
||||
case EXPR_TABLE_COERCE:
|
||||
case EXPR_FLATTEN:
|
||||
{
|
||||
const UnaryExpr* u1 = (UnaryExpr*) e1;
|
||||
const UnaryExpr* u2 = (UnaryExpr*) e2;
|
||||
return same_expr(u1->Op(), u2->Op());
|
||||
}
|
||||
|
||||
case EXPR_FIELD:
|
||||
{
|
||||
const FieldExpr* f1 = (FieldExpr*) e1;
|
||||
const FieldExpr* f2 = (FieldExpr*) e2;
|
||||
return same_expr(f1->Op(), f2->Op()) &&
|
||||
f1->Field() == f2->Field();
|
||||
}
|
||||
|
||||
case EXPR_SCHEDULE:
|
||||
{
|
||||
const ScheduleExpr* s1 = (ScheduleExpr*) e1;
|
||||
const ScheduleExpr* s2 = (ScheduleExpr*) e2;
|
||||
return same_expr(s1->When(), s2->When()) &&
|
||||
same_expr(s1->Event(), s2->Event());
|
||||
}
|
||||
|
||||
case EXPR_ADD:
|
||||
case EXPR_ADD_TO:
|
||||
case EXPR_SUB:
|
||||
case EXPR_REMOVE_FROM:
|
||||
case EXPR_TIMES:
|
||||
case EXPR_DIVIDE:
|
||||
case EXPR_MOD:
|
||||
case EXPR_AND:
|
||||
case EXPR_OR:
|
||||
case EXPR_LT:
|
||||
case EXPR_LE:
|
||||
case EXPR_EQ:
|
||||
case EXPR_NE:
|
||||
case EXPR_GE:
|
||||
case EXPR_GT:
|
||||
case EXPR_ASSIGN:
|
||||
case EXPR_MATCH:
|
||||
case EXPR_INDEX:
|
||||
case EXPR_IN:
|
||||
{
|
||||
const BinaryExpr* b1 = (BinaryExpr*) e1;
|
||||
const BinaryExpr* b2 = (BinaryExpr*) e2;
|
||||
return same_expr(b1->Op1(), b2->Op1()) &&
|
||||
same_expr(b1->Op2(), b2->Op2());
|
||||
}
|
||||
|
||||
case EXPR_LIST:
|
||||
{
|
||||
const ListExpr* l1 = (ListExpr*) e1;
|
||||
const ListExpr* l2 = (ListExpr*) e2;
|
||||
|
||||
const expr_list& le1 = l1->Exprs();
|
||||
const expr_list& le2 = l2->Exprs();
|
||||
|
||||
if ( le1.length() != le2.length() )
|
||||
return 0;
|
||||
|
||||
loop_over_list(le1, i)
|
||||
if ( ! same_expr(le1[i], le2[i]) )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
case EXPR_CALL:
|
||||
{
|
||||
const CallExpr* c1 = (CallExpr*) e1;
|
||||
const CallExpr* c2 = (CallExpr*) e2;
|
||||
|
||||
return same_expr(c1->Func(), c2->Func()) &&
|
||||
c1->IsPure() && same_expr(c1->Args(), c2->Args());
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad tag in same_expr()");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int expr_greater(const Expr* e1, const Expr* e2)
|
||||
{
|
||||
return int(e1->Tag()) > int(e2->Tag());
|
||||
|
|
69
src/Expr.h
69
src/Expr.h
|
@ -47,11 +47,6 @@ typedef enum {
|
|||
#define NUM_EXPRS (int(EXPR_FLATTEN) + 1)
|
||||
} BroExprTag;
|
||||
|
||||
typedef enum {
|
||||
SIMPLIFY_GENERAL, // regular simplification
|
||||
SIMPLIFY_LHS, // simplify as the LHS of an assignment
|
||||
} SimplifyType;
|
||||
|
||||
extern const char* expr_name(BroExprTag t);
|
||||
|
||||
class Stmt;
|
||||
|
@ -72,11 +67,6 @@ public:
|
|||
|
||||
Expr* Ref() { ::Ref(this); return this; }
|
||||
|
||||
// Returns a fully simplified version of the expression (this
|
||||
// may be the same expression, or a newly created one). simp_type
|
||||
// gives the context of the simplification.
|
||||
virtual Expr* Simplify(SimplifyType simp_type) = 0;
|
||||
|
||||
// Evaluates the expression and returns a corresponding Val*,
|
||||
// or nil if the expression's value isn't fixed.
|
||||
virtual Val* Eval(Frame* f) const = 0;
|
||||
|
@ -230,7 +220,6 @@ public:
|
|||
|
||||
ID* Id() const { return id; }
|
||||
|
||||
Expr* Simplify(SimplifyType simp_type);
|
||||
Val* Eval(Frame* f) const;
|
||||
void Assign(Frame* f, Val* v, Opcode op = OP_ASSIGN);
|
||||
Expr* MakeLvalue();
|
||||
|
@ -257,7 +246,6 @@ public:
|
|||
|
||||
Val* Value() const { return val; }
|
||||
|
||||
Expr* Simplify(SimplifyType simp_type);
|
||||
Val* Eval(Frame* f) const;
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const;
|
||||
|
@ -276,9 +264,6 @@ class UnaryExpr : public Expr {
|
|||
public:
|
||||
Expr* Op() const { return op; }
|
||||
|
||||
// Simplifies the operand and calls DoSimplify().
|
||||
virtual Expr* Simplify(SimplifyType simp_type);
|
||||
|
||||
// UnaryExpr::Eval correctly handles vector types. Any child
|
||||
// class that overrides Eval() should be modified to handle
|
||||
// vectors correctly as necessary.
|
||||
|
@ -297,10 +282,6 @@ protected:
|
|||
|
||||
void ExprDescribe(ODesc* d) const;
|
||||
|
||||
// Can be overridden by subclasses that want to take advantage
|
||||
// of UnaryExpr's Simplify() method.
|
||||
virtual Expr* DoSimplify();
|
||||
|
||||
// Returns the expression folded using the given constant.
|
||||
virtual Val* Fold(Val* v) const;
|
||||
|
||||
|
@ -314,9 +295,6 @@ public:
|
|||
Expr* Op1() const { return op1; }
|
||||
Expr* Op2() const { return op2; }
|
||||
|
||||
// Simplifies both operands, folds them if constant,
|
||||
// otherwise calls DoSimplify().
|
||||
virtual Expr* Simplify(SimplifyType simp_type);
|
||||
int IsPure() const;
|
||||
|
||||
// BinaryExpr::Eval correctly handles vector types. Any child
|
||||
|
@ -340,10 +318,6 @@ protected:
|
|||
}
|
||||
virtual ~BinaryExpr();
|
||||
|
||||
// Can be overridden by subclasses that want to take advantage
|
||||
// of BinaryExpr's Simplify() method.
|
||||
virtual Expr* DoSimplify();
|
||||
|
||||
// Returns the expression folded using the given constants.
|
||||
virtual Val* Fold(Val* v1, Val* v2) const;
|
||||
|
||||
|
@ -356,9 +330,6 @@ protected:
|
|||
|
||||
int BothConst() const { return op1->IsConst() && op2->IsConst(); }
|
||||
|
||||
// Simplify both operands and canonicize.
|
||||
void SimplifyOps();
|
||||
|
||||
// Exchange op1 and op2.
|
||||
void SwapOps();
|
||||
|
||||
|
@ -414,7 +385,6 @@ protected:
|
|||
friend class Expr;
|
||||
NotExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
Val* Fold(Val* v) const;
|
||||
|
||||
DECLARE_SERIAL(NotExpr);
|
||||
|
@ -428,7 +398,6 @@ protected:
|
|||
friend class Expr;
|
||||
PosExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
Val* Fold(Val* v) const;
|
||||
|
||||
DECLARE_SERIAL(PosExpr);
|
||||
|
@ -442,7 +411,6 @@ protected:
|
|||
friend class Expr;
|
||||
NegExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
Val* Fold(Val* v) const;
|
||||
|
||||
DECLARE_SERIAL(NegExpr);
|
||||
|
@ -470,8 +438,6 @@ protected:
|
|||
friend class Expr;
|
||||
AddExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
|
||||
DECLARE_SERIAL(AddExpr);
|
||||
|
||||
};
|
||||
|
@ -508,8 +474,6 @@ protected:
|
|||
friend class Expr;
|
||||
SubExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
|
||||
DECLARE_SERIAL(SubExpr);
|
||||
|
||||
};
|
||||
|
@ -523,8 +487,6 @@ protected:
|
|||
friend class Expr;
|
||||
TimesExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
|
||||
DECLARE_SERIAL(TimesExpr);
|
||||
|
||||
};
|
||||
|
@ -538,7 +500,6 @@ protected:
|
|||
DivideExpr() { }
|
||||
|
||||
Val* AddrFold(Val* v1, Val* v2) const;
|
||||
Expr* DoSimplify();
|
||||
|
||||
DECLARE_SERIAL(DivideExpr);
|
||||
|
||||
|
@ -552,8 +513,6 @@ protected:
|
|||
friend class Expr;
|
||||
ModExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
|
||||
DECLARE_SERIAL(ModExpr);
|
||||
};
|
||||
|
||||
|
@ -568,8 +527,6 @@ protected:
|
|||
friend class Expr;
|
||||
BoolExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
|
||||
DECLARE_SERIAL(BoolExpr);
|
||||
};
|
||||
|
||||
|
@ -582,8 +539,6 @@ protected:
|
|||
friend class Expr;
|
||||
EqExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
|
||||
Val* Fold(Val* v1, Val* v2) const;
|
||||
|
||||
DECLARE_SERIAL(EqExpr);
|
||||
|
@ -598,8 +553,6 @@ protected:
|
|||
friend class Expr;
|
||||
RelExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
|
||||
DECLARE_SERIAL(RelExpr);
|
||||
};
|
||||
|
||||
|
@ -612,7 +565,6 @@ public:
|
|||
const Expr* Op2() const { return op2; }
|
||||
const Expr* Op3() const { return op3; }
|
||||
|
||||
Expr* Simplify(SimplifyType simp_type);
|
||||
Val* Eval(Frame* f) const;
|
||||
int IsPure() const;
|
||||
|
||||
|
@ -652,7 +604,6 @@ public:
|
|||
AssignExpr(Expr* op1, Expr* op2, int is_init, Val* val = 0, attr_list* attrs = 0);
|
||||
virtual ~AssignExpr() { Unref(val); }
|
||||
|
||||
Expr* Simplify(SimplifyType simp_type);
|
||||
Val* Eval(Frame* f) const;
|
||||
void EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const;
|
||||
BroType* InitType() const;
|
||||
|
@ -683,7 +634,6 @@ public:
|
|||
void Add(Frame* f);
|
||||
void Delete(Frame* f);
|
||||
|
||||
Expr* Simplify(SimplifyType simp_type);
|
||||
void Assign(Frame* f, Val* v, Opcode op = OP_ASSIGN);
|
||||
Expr* MakeLvalue();
|
||||
|
||||
|
@ -714,7 +664,6 @@ public:
|
|||
|
||||
int CanDel() const;
|
||||
|
||||
Expr* Simplify(SimplifyType simp_type);
|
||||
void Assign(Frame* f, Val* v, Opcode op = OP_ASSIGN);
|
||||
void Delete(Frame* f);
|
||||
|
||||
|
@ -866,8 +815,6 @@ protected:
|
|||
friend class Expr;
|
||||
ArithCoerceExpr() { }
|
||||
|
||||
Expr* DoSimplify();
|
||||
|
||||
Val* FoldSingleVal(Val* v, InternalTypeTag t) const;
|
||||
Val* Fold(Val* v) const;
|
||||
|
||||
|
@ -962,8 +909,6 @@ public:
|
|||
|
||||
int IsPure() const;
|
||||
|
||||
Expr* Simplify(SimplifyType simp_type);
|
||||
|
||||
Val* Eval(Frame* f) const;
|
||||
|
||||
Expr* When() const { return when; }
|
||||
|
@ -1007,7 +952,6 @@ public:
|
|||
|
||||
int IsPure() const;
|
||||
|
||||
Expr* Simplify(SimplifyType simp_type);
|
||||
Val* Eval(Frame* f) const;
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const;
|
||||
|
@ -1033,7 +977,6 @@ public:
|
|||
ListExpr* Args() const { return args; }
|
||||
EventHandlerPtr Handler() const { return handler; }
|
||||
|
||||
Expr* Simplify(SimplifyType simp_type);
|
||||
Val* Eval(Frame* f) const;
|
||||
|
||||
TraversalCode Traverse(TraversalCallback* cb) const;
|
||||
|
@ -1068,7 +1011,6 @@ public:
|
|||
// True if the entire list represents constant values.
|
||||
int AllConst() const;
|
||||
|
||||
Expr* Simplify(SimplifyType simp_type);
|
||||
Val* Eval(Frame* f) const;
|
||||
|
||||
BroType* InitType() const;
|
||||
|
@ -1127,21 +1069,10 @@ extern int check_and_promote_exprs(ListExpr*& elements, TypeList* types);
|
|||
extern int check_and_promote_args(ListExpr*& args, RecordType* types);
|
||||
extern int check_and_promote_exprs_to_type(ListExpr*& elements, BroType* type);
|
||||
|
||||
// Returns a fully simplified form of the expression. Note that passed
|
||||
// expression and its subexpressions may be modified, Unref()'d, etc.
|
||||
Expr* simplify_expr(Expr* e, SimplifyType simp_type);
|
||||
|
||||
// Returns a simplified ListExpr - guaranteed to still be a ListExpr,
|
||||
// even if it only contains one expr.
|
||||
ListExpr* simplify_expr_list(ListExpr* l, SimplifyType simp_type);
|
||||
|
||||
// Returns a ListExpr simplified down to a list a values, or a nil
|
||||
// pointer if they couldn't all be reduced.
|
||||
val_list* eval_list(Frame* f, const ListExpr* l);
|
||||
|
||||
// Returns true if two expressions are identical.
|
||||
extern int same_expr(const Expr* e1, const Expr* e2);
|
||||
|
||||
// Returns true if e1 is "greater" than e2 - here "greater" is just
|
||||
// a heuristic, used with commutative operators to put them into
|
||||
// a canonical form.
|
||||
|
|
|
@ -10,6 +10,7 @@ RecordType* endpoint;
|
|||
RecordType* endpoint_stats;
|
||||
RecordType* connection_type;
|
||||
RecordType* fa_file_type;
|
||||
RecordType* fa_metadata_type;
|
||||
RecordType* icmp_conn;
|
||||
RecordType* icmp_context;
|
||||
RecordType* SYN_packet;
|
||||
|
@ -318,6 +319,7 @@ void init_net_var()
|
|||
endpoint_stats = internal_type("endpoint_stats")->AsRecordType();
|
||||
connection_type = internal_type("connection")->AsRecordType();
|
||||
fa_file_type = internal_type("fa_file")->AsRecordType();
|
||||
fa_metadata_type = internal_type("fa_metadata")->AsRecordType();
|
||||
icmp_conn = internal_type("icmp_conn")->AsRecordType();
|
||||
icmp_context = internal_type("icmp_context")->AsRecordType();
|
||||
signature_state = internal_type("signature_state")->AsRecordType();
|
||||
|
|
|
@ -13,6 +13,7 @@ extern RecordType* endpoint;
|
|||
extern RecordType* endpoint_stats;
|
||||
extern RecordType* connection_type;
|
||||
extern RecordType* fa_file_type;
|
||||
extern RecordType* fa_metadata_type;
|
||||
extern RecordType* icmp_conn;
|
||||
extern RecordType* icmp_context;
|
||||
extern RecordType* signature_state;
|
||||
|
|
369
src/Stmt.cc
369
src/Stmt.cc
|
@ -79,11 +79,6 @@ bool Stmt::SetLocationInfo(const Location* start, const Location* end)
|
|||
return true;
|
||||
}
|
||||
|
||||
Stmt* Stmt::Simplify()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
int Stmt::IsPure() const
|
||||
{
|
||||
return 0;
|
||||
|
@ -201,18 +196,6 @@ Val* ExprListStmt::Exec(Frame* f, stmt_flow_type& flow) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
Stmt* ExprListStmt::Simplify()
|
||||
{
|
||||
l = simplify_expr_list(l, SIMPLIFY_GENERAL);
|
||||
DoSimplify();
|
||||
return this;
|
||||
}
|
||||
|
||||
Stmt* ExprListStmt::DoSimplify()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void ExprListStmt::Describe(ODesc* d) const
|
||||
{
|
||||
Stmt::Describe(d);
|
||||
|
@ -383,17 +366,6 @@ Val* ExprStmt::DoExec(Frame* /* f */, Val* /* v */, stmt_flow_type& /* flow */)
|
|||
return 0;
|
||||
}
|
||||
|
||||
Stmt* ExprStmt::Simplify()
|
||||
{
|
||||
e = simplify_expr(e, SIMPLIFY_GENERAL);
|
||||
return DoSimplify();
|
||||
}
|
||||
|
||||
Stmt* ExprStmt::DoSimplify()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
int ExprStmt::IsPure() const
|
||||
{
|
||||
return ! e || e->IsPure();
|
||||
|
@ -490,33 +462,6 @@ Val* IfStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const
|
|||
return result;
|
||||
}
|
||||
|
||||
Stmt* IfStmt::DoSimplify()
|
||||
{
|
||||
s1 = simplify_stmt(s1);
|
||||
s2 = simplify_stmt(s2);
|
||||
|
||||
if ( e->IsConst() )
|
||||
{
|
||||
if ( ! optimize )
|
||||
Warn("constant in conditional");
|
||||
|
||||
return e->IsZero() ? s2->Ref() : s1->Ref();
|
||||
}
|
||||
|
||||
if ( e->Tag() == EXPR_NOT )
|
||||
{
|
||||
Stmt* t = s1;
|
||||
s1 = s2;
|
||||
s2 = t;
|
||||
|
||||
e = new NotExpr(e);
|
||||
|
||||
return Simplify();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
int IfStmt::IsPure() const
|
||||
{
|
||||
return e->IsPure() && s1->IsPure() && s2->IsPure();
|
||||
|
@ -602,7 +547,7 @@ static BroStmtTag get_last_stmt_tag(const Stmt* stmt)
|
|||
}
|
||||
|
||||
Case::Case(ListExpr* c, Stmt* arg_s)
|
||||
: cases(simplify_expr_list(c, SIMPLIFY_GENERAL)), s(arg_s)
|
||||
: cases(c), s(arg_s)
|
||||
{
|
||||
BroStmtTag t = get_last_stmt_tag(Body());
|
||||
|
||||
|
@ -729,8 +674,8 @@ SwitchStmt::SwitchStmt(Expr* index, case_list* arg_cases) :
|
|||
|
||||
loop_over_list(*cases, i)
|
||||
{
|
||||
const Case* c = (*cases)[i];
|
||||
const ListExpr* le = c->Cases();
|
||||
Case* c = (*cases)[i];
|
||||
ListExpr* le = c->Cases();
|
||||
|
||||
if ( le )
|
||||
{
|
||||
|
@ -740,10 +685,53 @@ SwitchStmt::SwitchStmt(Expr* index, case_list* arg_cases) :
|
|||
continue;
|
||||
}
|
||||
|
||||
const expr_list& exprs = le->Exprs();
|
||||
expr_list& exprs = le->Exprs();
|
||||
|
||||
loop_over_list(exprs, j)
|
||||
{
|
||||
if ( ! exprs[j]->IsConst() )
|
||||
{
|
||||
Expr* expr = exprs[j];
|
||||
|
||||
switch ( expr->Tag() ) {
|
||||
// Simplify trivial unary plus/minus expressions on consts.
|
||||
case EXPR_NEGATE:
|
||||
{
|
||||
NegExpr* ne = (NegExpr*)(expr);
|
||||
|
||||
if ( ne->Op()->IsConst() )
|
||||
Unref(exprs.replace(j, new ConstExpr(ne->Eval(0))));
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_POSITIVE:
|
||||
{
|
||||
PosExpr* pe = (PosExpr*)(expr);
|
||||
|
||||
if ( pe->Op()->IsConst() )
|
||||
Unref(exprs.replace(j, new ConstExpr(pe->Eval(0))));
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_NAME:
|
||||
{
|
||||
NameExpr* ne = (NameExpr*)(expr);
|
||||
|
||||
if ( ne->Id()->IsConst() )
|
||||
{
|
||||
Val* v = ne->Eval(0);
|
||||
|
||||
if ( v )
|
||||
Unref(exprs.replace(j, new ConstExpr(v)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! exprs[j]->IsConst() )
|
||||
exprs[j]->Error("case label expression isn't constant");
|
||||
else
|
||||
|
@ -845,36 +833,6 @@ Val* SwitchStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const
|
|||
return rval;
|
||||
}
|
||||
|
||||
Stmt* SwitchStmt::DoSimplify()
|
||||
{
|
||||
loop_over_list(*cases, i)
|
||||
{
|
||||
Case* c = (*cases)[i];
|
||||
ListExpr* new_cases = simplify_expr_list(c->Cases(), SIMPLIFY_GENERAL);
|
||||
Stmt* new_body = simplify_stmt(c->Body());
|
||||
|
||||
if ( new_cases != c->Cases() || new_body != c->Body() )
|
||||
{
|
||||
cases->replace(i, new Case(new_cases, new_body));
|
||||
Unref(c);
|
||||
}
|
||||
}
|
||||
|
||||
if ( e->IsConst() )
|
||||
{
|
||||
// Could possibly remove all case labels before the one
|
||||
// that will match, but may be tricky to tell if any
|
||||
// subsequent ones can also be removed since it depends
|
||||
// on the evaluation of the body executing a break/return
|
||||
// statement. Then still need a way to bypass the lookup
|
||||
// DoExec for it to be beneficial.
|
||||
if ( ! optimize )
|
||||
Warn("constant in switch");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
int SwitchStmt::IsPure() const
|
||||
{
|
||||
if ( ! e->IsPure() )
|
||||
|
@ -1212,17 +1170,6 @@ Val* WhileStmt::Exec(Frame* f, stmt_flow_type& flow) const
|
|||
return rval;
|
||||
}
|
||||
|
||||
Stmt* WhileStmt::Simplify()
|
||||
{
|
||||
loop_condition = simplify_expr(loop_condition, SIMPLIFY_GENERAL);
|
||||
|
||||
if ( loop_condition->IsConst() && loop_condition->IsZero() )
|
||||
return new NullStmt();
|
||||
|
||||
body = simplify_stmt(body);
|
||||
return this;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIAL(WhileStmt, SER_WHILE_STMT);
|
||||
|
||||
bool WhileStmt::DoSerialize(SerialInfo* info) const
|
||||
|
@ -1416,21 +1363,6 @@ Val* ForStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const
|
|||
return ret;
|
||||
}
|
||||
|
||||
Stmt* ForStmt::DoSimplify()
|
||||
{
|
||||
body = simplify_stmt(body);
|
||||
|
||||
if ( e->IsConst() )
|
||||
{
|
||||
const PDict(TableEntryVal)* vt = e->ExprVal()->AsTable();
|
||||
|
||||
if ( vt->Length() == 0 )
|
||||
return new NullStmt();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
int ForStmt::IsPure() const
|
||||
{
|
||||
return e->IsPure() && body->IsPure();
|
||||
|
@ -1774,20 +1706,6 @@ Val* StmtList::Exec(Frame* f, stmt_flow_type& flow) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
Stmt* StmtList::Simplify()
|
||||
{
|
||||
if ( stmts.length() == 0 )
|
||||
return new NullStmt();
|
||||
|
||||
if ( stmts.length() == 1 )
|
||||
return stmts[0]->Ref();
|
||||
|
||||
loop_over_list(stmts, i)
|
||||
stmts.replace(i, simplify_stmt(stmts[i]));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
int StmtList::IsPure() const
|
||||
{
|
||||
loop_over_list(stmts, i)
|
||||
|
@ -1909,17 +1827,6 @@ Val* EventBodyList::Exec(Frame* f, stmt_flow_type& flow) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
Stmt* EventBodyList::Simplify()
|
||||
{
|
||||
if ( stmts.length() <= 1 )
|
||||
// Don't simplify these, we don't want to lose our
|
||||
// "execute even across returns" property.
|
||||
return this;
|
||||
|
||||
else
|
||||
return StmtList::Simplify();
|
||||
}
|
||||
|
||||
void EventBodyList::Describe(ODesc* d) const
|
||||
{
|
||||
if ( d->IsReadable() && stmts.length() > 0 )
|
||||
|
@ -2168,19 +2075,6 @@ Val* WhenStmt::Exec(Frame* f, stmt_flow_type& flow) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
Stmt* WhenStmt::Simplify()
|
||||
{
|
||||
cond = simplify_expr(cond, SIMPLIFY_GENERAL);
|
||||
s1 = simplify_stmt(s1);
|
||||
if ( s2 )
|
||||
s2 = simplify_stmt(s2);
|
||||
|
||||
if ( cond->IsPure() )
|
||||
Warn("non-varying expression in when clause");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
int WhenStmt::IsPure() const
|
||||
{
|
||||
return cond->IsPure() && s1->IsPure() && (! s2 || s2->IsPure());
|
||||
|
@ -2276,172 +2170,3 @@ bool WhenStmt::DoUnserialize(UnserialInfo* info)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
Stmt* simplify_stmt(Stmt* s)
|
||||
{
|
||||
for ( Stmt* ss = s->Simplify(); ss != s; ss = s->Simplify() )
|
||||
{
|
||||
Unref(s);
|
||||
s = ss;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int same_stmt(const Stmt* s1, const Stmt* s2)
|
||||
{
|
||||
if ( s1 == s2 )
|
||||
return 1;
|
||||
|
||||
if ( s1->Tag() != s2->Tag() )
|
||||
return 0;
|
||||
|
||||
switch ( s1->Tag() ) {
|
||||
case STMT_PRINT:
|
||||
{
|
||||
const ListExpr* l1 = ((const ExprListStmt*) s1)->ExprList();
|
||||
const ListExpr* l2 = ((const ExprListStmt*) s2)->ExprList();
|
||||
return same_expr(l1, l2);
|
||||
}
|
||||
|
||||
case STMT_ADD:
|
||||
case STMT_DELETE:
|
||||
case STMT_RETURN:
|
||||
case STMT_EXPR:
|
||||
case STMT_EVENT:
|
||||
{
|
||||
const ExprStmt* e1 = (const ExprStmt*) s1;
|
||||
const ExprStmt* e2 = (const ExprStmt*) s2;
|
||||
return same_expr(e1->StmtExpr(), e2->StmtExpr());
|
||||
}
|
||||
|
||||
case STMT_FOR:
|
||||
{
|
||||
const ForStmt* f1 = (const ForStmt*) s1;
|
||||
const ForStmt* f2 = (const ForStmt*) s2;
|
||||
|
||||
return f1->LoopVar() == f2->LoopVar() &&
|
||||
same_expr(f1->LoopExpr(), f2->LoopExpr()) &&
|
||||
same_stmt(f1->LoopBody(), f2->LoopBody());
|
||||
}
|
||||
|
||||
case STMT_IF:
|
||||
{
|
||||
const IfStmt* i1 = (const IfStmt*) s1;
|
||||
const IfStmt* i2 = (const IfStmt*) s2;
|
||||
|
||||
if ( ! same_expr(i1->StmtExpr(), i2->StmtExpr()) )
|
||||
return 0;
|
||||
|
||||
if ( i1->TrueBranch() || i2->TrueBranch() )
|
||||
{
|
||||
if ( ! i1->TrueBranch() || ! i2->TrueBranch() )
|
||||
return 0;
|
||||
if ( ! same_stmt(i1->TrueBranch(), i2->TrueBranch()) )
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( i1->FalseBranch() || i2->FalseBranch() )
|
||||
{
|
||||
if ( ! i1->FalseBranch() || ! i2->FalseBranch() )
|
||||
return 0;
|
||||
if ( ! same_stmt(i1->FalseBranch(), i2->FalseBranch()) )
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
case STMT_SWITCH:
|
||||
{
|
||||
const SwitchStmt* sw1 = (const SwitchStmt*) s1;
|
||||
const SwitchStmt* sw2 = (const SwitchStmt*) s2;
|
||||
|
||||
if ( ! same_expr(sw1->StmtExpr(), sw2->StmtExpr()) )
|
||||
return 0;
|
||||
|
||||
const case_list* c1 = sw1->Cases();
|
||||
const case_list* c2 = sw1->Cases();
|
||||
|
||||
if ( c1->length() != c2->length() )
|
||||
return 0;
|
||||
|
||||
loop_over_list(*c1, i)
|
||||
{
|
||||
if ( ! same_expr((*c1)[i]->Cases(), (*c2)[i]->Cases()) )
|
||||
return 0;
|
||||
if ( ! same_stmt((*c1)[i]->Body(), (*c2)[i]->Body()) )
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
case STMT_LIST:
|
||||
case STMT_EVENT_BODY_LIST:
|
||||
{
|
||||
const stmt_list& l1 = ((const StmtList*) s1)->Stmts();
|
||||
const stmt_list& l2 = ((const StmtList*) s2)->Stmts();
|
||||
|
||||
if ( l1.length() != l2.length() )
|
||||
return 0;
|
||||
|
||||
loop_over_list(l1, i)
|
||||
if ( ! same_stmt(l1[i], l2[i]) )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
case STMT_INIT:
|
||||
{
|
||||
const id_list* i1 = ((const InitStmt*) s1)->Inits();
|
||||
const id_list* i2 = ((const InitStmt*) s2)->Inits();
|
||||
|
||||
if ( i1->length() != i2->length() )
|
||||
return 0;
|
||||
|
||||
loop_over_list(*i1, i)
|
||||
if ( (*i1)[i] != (*i2)[i] )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
case STMT_WHEN:
|
||||
{
|
||||
const WhenStmt* w1 = (const WhenStmt*) s1;
|
||||
const WhenStmt* w2 = (const WhenStmt*) s2;
|
||||
|
||||
if ( ! same_expr(w1->Cond(), w2->Cond()) )
|
||||
return 0;
|
||||
|
||||
if ( ! same_stmt(w1->Body(), w2->Body()) )
|
||||
return 0;
|
||||
|
||||
if ( w1->TimeoutBody() || w2->TimeoutBody() )
|
||||
{
|
||||
if ( ! w1->TimeoutBody() || ! w2->TimeoutBody() )
|
||||
return 0;
|
||||
|
||||
if ( ! same_expr(w1->TimeoutExpr(), w2->TimeoutExpr()) )
|
||||
return 0;
|
||||
|
||||
if ( ! same_stmt(w1->TimeoutBody(), w2->TimeoutBody()) )
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
case STMT_NEXT:
|
||||
case STMT_BREAK:
|
||||
case STMT_NULL:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
reporter->Error("bad tag in same_stmt()");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
21
src/Stmt.h
21
src/Stmt.h
|
@ -33,10 +33,6 @@ public:
|
|||
{ return Stmt::SetLocationInfo(loc, loc); }
|
||||
bool SetLocationInfo(const Location* start, const Location* end);
|
||||
|
||||
// Returns a fully simplified version of the statement (this
|
||||
// may be the same statement, or a newly created one).
|
||||
virtual Stmt* Simplify();
|
||||
|
||||
// True if the statement has no side effects, false otherwise.
|
||||
virtual int IsPure() const;
|
||||
|
||||
|
@ -112,9 +108,6 @@ protected:
|
|||
Val* Exec(Frame* f, stmt_flow_type& flow) const;
|
||||
virtual Val* DoExec(val_list* vals, stmt_flow_type& flow) const = 0;
|
||||
|
||||
Stmt* Simplify();
|
||||
virtual Stmt* DoSimplify();
|
||||
|
||||
void Describe(ODesc* d) const;
|
||||
void PrintVals(ODesc* d, val_list* vals, int offset) const;
|
||||
|
||||
|
@ -156,12 +149,8 @@ protected:
|
|||
|
||||
virtual Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const;
|
||||
|
||||
Stmt* Simplify();
|
||||
int IsPure() const;
|
||||
|
||||
// Called by Simplify(), after the expression's been simplified.
|
||||
virtual Stmt* DoSimplify();
|
||||
|
||||
DECLARE_SERIAL(ExprStmt);
|
||||
|
||||
Expr* e;
|
||||
|
@ -184,7 +173,6 @@ protected:
|
|||
IfStmt() { s1 = s2 = 0; }
|
||||
|
||||
Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const;
|
||||
Stmt* DoSimplify();
|
||||
int IsPure() const;
|
||||
|
||||
DECLARE_SERIAL(IfStmt);
|
||||
|
@ -237,7 +225,6 @@ protected:
|
|||
SwitchStmt() { cases = 0; default_case_idx = -1; comp_hash = 0; }
|
||||
|
||||
Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const;
|
||||
Stmt* DoSimplify();
|
||||
int IsPure() const;
|
||||
|
||||
DECLARE_SERIAL(SwitchStmt);
|
||||
|
@ -329,7 +316,6 @@ protected:
|
|||
{ loop_condition = 0; body = 0; }
|
||||
|
||||
Val* Exec(Frame* f, stmt_flow_type& flow) const;
|
||||
Stmt* Simplify();
|
||||
|
||||
DECLARE_SERIAL(WhileStmt);
|
||||
|
||||
|
@ -359,7 +345,6 @@ protected:
|
|||
ForStmt() { loop_vars = 0; body = 0; }
|
||||
|
||||
Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const;
|
||||
Stmt* DoSimplify();
|
||||
|
||||
DECLARE_SERIAL(ForStmt);
|
||||
|
||||
|
@ -442,7 +427,6 @@ public:
|
|||
TraversalCode Traverse(TraversalCallback* cb) const;
|
||||
|
||||
protected:
|
||||
Stmt* Simplify();
|
||||
int IsPure() const;
|
||||
|
||||
DECLARE_SERIAL(StmtList);
|
||||
|
@ -464,7 +448,6 @@ public:
|
|||
// bool IsTopmost() { return topmost; }
|
||||
|
||||
protected:
|
||||
Stmt* Simplify();
|
||||
|
||||
DECLARE_SERIAL(EventBodyList);
|
||||
|
||||
|
@ -522,7 +505,6 @@ public:
|
|||
|
||||
Val* Exec(Frame* f, stmt_flow_type& flow) const;
|
||||
int IsPure() const;
|
||||
Stmt* Simplify();
|
||||
|
||||
const Expr* Cond() const { return cond; }
|
||||
const Stmt* Body() const { return s1; }
|
||||
|
@ -545,7 +527,4 @@ protected:
|
|||
bool is_return;
|
||||
};
|
||||
|
||||
extern Stmt* simplify_stmt(Stmt* s);
|
||||
extern int same_stmt(const Stmt* s1, const Stmt* s2);
|
||||
|
||||
#endif
|
||||
|
|
31
src/Type.cc
31
src/Type.cc
|
@ -1977,18 +1977,33 @@ int same_attrs(const Attributes* a1, const Attributes* a2)
|
|||
return (*a1 == *a2);
|
||||
}
|
||||
|
||||
int record_promotion_compatible(const RecordType* /* super_rec */,
|
||||
const RecordType* /* sub_rec */)
|
||||
int record_promotion_compatible(const RecordType* super_rec,
|
||||
const RecordType* sub_rec)
|
||||
{
|
||||
#if 0
|
||||
int n = sub_rec->NumFields();
|
||||
|
||||
for ( int i = 0; i < n; ++i )
|
||||
for ( int i = 0; i < sub_rec->NumFields(); ++i )
|
||||
{
|
||||
if ( ! super_rec->HasField(sub_rec->FieldName(i)) )
|
||||
int o = super_rec->FieldOffset(sub_rec->FieldName(i));
|
||||
|
||||
if ( o < 0 )
|
||||
// Orphaned field.
|
||||
continue;
|
||||
|
||||
BroType* sub_field_type = sub_rec->FieldType(i);
|
||||
BroType* super_field_type = super_rec->FieldType(o);
|
||||
|
||||
if ( same_type(sub_field_type, super_field_type) )
|
||||
continue;
|
||||
|
||||
if ( sub_field_type->Tag() != TYPE_RECORD )
|
||||
return 0;
|
||||
|
||||
if ( super_field_type->Tag() != TYPE_RECORD )
|
||||
return 0;
|
||||
|
||||
if ( ! record_promotion_compatible(super_field_type->AsRecordType(),
|
||||
sub_field_type->AsRecordType()) )
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -2985,8 +2985,10 @@ bool VectorVal::Assign(unsigned int index, Val* element, Opcode op)
|
|||
}
|
||||
}
|
||||
|
||||
Val* val_at_index = 0;
|
||||
|
||||
if ( index < val.vector_val->size() )
|
||||
Unref((*val.vector_val)[index]);
|
||||
val_at_index = (*val.vector_val)[index];
|
||||
else
|
||||
val.vector_val->resize(index + 1);
|
||||
|
||||
|
@ -2999,10 +3001,12 @@ bool VectorVal::Assign(unsigned int index, Val* element, Opcode op)
|
|||
|
||||
StateAccess::Log(new StateAccess(op == OP_INCR ?
|
||||
OP_INCR_IDX : OP_ASSIGN_IDX,
|
||||
this, ival, element, (*val.vector_val)[index]));
|
||||
this, ival, element, val_at_index));
|
||||
Unref(ival);
|
||||
}
|
||||
|
||||
Unref(val_at_index);
|
||||
|
||||
// Note: we do *not* Ref() the element, if any, at this point.
|
||||
// AssignExpr::Eval() already does this; other callers must remember
|
||||
// to do it similarly.
|
||||
|
|
|
@ -64,9 +64,6 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init,
|
|||
}
|
||||
}
|
||||
|
||||
if ( init && optimize )
|
||||
init = init->Simplify(SIMPLIFY_GENERAL);
|
||||
|
||||
if ( t && t->IsSet() )
|
||||
{ // Check for set with explicit elements.
|
||||
SetType* st = t->AsTableType()->AsSetType();
|
||||
|
|
|
@ -18,19 +18,20 @@ add_subdirectory(icmp)
|
|||
add_subdirectory(ident)
|
||||
add_subdirectory(interconn)
|
||||
add_subdirectory(irc)
|
||||
add_subdirectory(krb)
|
||||
add_subdirectory(login)
|
||||
add_subdirectory(mime)
|
||||
add_subdirectory(modbus)
|
||||
add_subdirectory(mysql)
|
||||
add_subdirectory(ncp)
|
||||
add_subdirectory(netbios)
|
||||
add_subdirectory(netflow)
|
||||
add_subdirectory(ntp)
|
||||
add_subdirectory(pia)
|
||||
add_subdirectory(pop3)
|
||||
add_subdirectory(radius)
|
||||
add_subdirectory(rdp)
|
||||
add_subdirectory(rpc)
|
||||
add_subdirectory(sip)
|
||||
add_subdirectory(snmp)
|
||||
add_subdirectory(smb)
|
||||
add_subdirectory(smtp)
|
||||
|
|
194
src/analyzer/protocol/asn1/asn1.pac
Normal file
194
src/analyzer/protocol/asn1/asn1.pac
Normal file
|
@ -0,0 +1,194 @@
|
|||
%extern{
|
||||
#include <cstdlib>
|
||||
%}
|
||||
|
||||
%header{
|
||||
Val* asn1_integer_to_val(const ASN1Encoding* i, TypeTag t);
|
||||
Val* asn1_integer_to_val(const ASN1Integer* i, TypeTag t);
|
||||
StringVal* asn1_oid_to_val(const ASN1Encoding* oid);
|
||||
StringVal* asn1_oid_to_val(const ASN1ObjectIdentifier* oid);
|
||||
StringVal* asn1_octet_string_to_val(const ASN1Encoding* s);
|
||||
StringVal* asn1_octet_string_to_val(const ASN1OctetString* s);
|
||||
%}
|
||||
|
||||
############################## ASN.1 Encodings
|
||||
|
||||
enum ASN1TypeTag {
|
||||
ASN1_INTEGER_TAG = 0x02,
|
||||
ASN1_OCTET_STRING_TAG = 0x04,
|
||||
ASN1_NULL_TAG = 0x05,
|
||||
ASN1_OBJECT_IDENTIFIER_TAG = 0x06,
|
||||
ASN1_SEQUENCE_TAG = 0x30,
|
||||
ASN1_APP_TAG_OFFSET = 0x60,
|
||||
ASN1_INDEX_TAG_OFFSET = 0xa0,
|
||||
};
|
||||
|
||||
type ASN1Encoding = record {
|
||||
meta: ASN1EncodingMeta;
|
||||
content: bytestring &length = meta.length;
|
||||
};
|
||||
|
||||
type ASN1EncodingMeta = record {
|
||||
tag: uint8;
|
||||
len: uint8;
|
||||
more_len: bytestring &length = long_len ? len & 0x7f : 0;
|
||||
} &let {
|
||||
long_len : bool = (len & 0x80) > 0;
|
||||
length: uint64 = long_len ? binary_to_int64(more_len) : len;
|
||||
index : uint8 = tag - ASN1_INDEX_TAG_OFFSET;
|
||||
};
|
||||
|
||||
type ASN1OptionalEncodingMeta(is_present: bool, previous_metadata: ASN1EncodingMeta) = case is_present of {
|
||||
true -> data: ASN1EncodingMeta;
|
||||
false -> none: empty;
|
||||
} &let {
|
||||
length: uint64 = is_present ? data.length : previous_metadata.length;
|
||||
};
|
||||
|
||||
type ASN1SequenceMeta = record {
|
||||
encoding: ASN1EncodingMeta;
|
||||
};
|
||||
|
||||
type ASN1Integer = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type ASN1OctetString = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type ASN1ObjectIdentifier = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type ASN1Boolean = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type ASN1Enumerated = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type SequenceElement(grab_content: bool) = record {
|
||||
index_meta: ASN1EncodingMeta;
|
||||
have_content: case grab_content of {
|
||||
true -> data: ASN1Encoding;
|
||||
false -> meta: ASN1EncodingMeta;
|
||||
};
|
||||
} &let {
|
||||
index: uint8 = index_meta.index;
|
||||
length: uint64 = index_meta.length;
|
||||
};
|
||||
|
||||
type Array = record {
|
||||
array_meta: ASN1EncodingMeta;
|
||||
data: ASN1Encoding[];
|
||||
};
|
||||
|
||||
############################## ASN.1 Conversion Functions
|
||||
|
||||
function binary_to_int64(bs: bytestring): int64
|
||||
%{
|
||||
int64 rval = 0;
|
||||
|
||||
for ( int i = 0; i < bs.length(); ++i )
|
||||
{
|
||||
uint64 byte = bs[i];
|
||||
rval |= byte << (8 * (bs.length() - (i + 1)));
|
||||
}
|
||||
|
||||
return rval;
|
||||
%}
|
||||
|
||||
%code{
|
||||
|
||||
Val* asn1_integer_to_val(const ASN1Integer* i, TypeTag t)
|
||||
{
|
||||
return asn1_integer_to_val(i->encoding(), t);
|
||||
}
|
||||
|
||||
Val* asn1_integer_to_val(const ASN1Encoding* i, TypeTag t)
|
||||
{
|
||||
return new Val(binary_to_int64(i->content()), t);
|
||||
}
|
||||
|
||||
StringVal* asn1_oid_to_val(const ASN1ObjectIdentifier* oid)
|
||||
{
|
||||
return asn1_oid_to_val(oid->encoding());
|
||||
}
|
||||
|
||||
StringVal* asn1_oid_to_val(const ASN1Encoding* oid)
|
||||
{
|
||||
vector<uint64> oid_components;
|
||||
vector<vector<uint8> > subidentifiers;
|
||||
vector<uint64> subidentifier_values;
|
||||
vector<uint8> subidentifier;
|
||||
bytestring const& bs = oid->content();
|
||||
|
||||
for ( int i = 0; i < bs.length(); ++i )
|
||||
{
|
||||
if ( bs[i] & 0x80 )
|
||||
subidentifier.push_back(bs[i] & 0x7f);
|
||||
else
|
||||
{
|
||||
subidentifier.push_back(bs[i]);
|
||||
subidentifiers.push_back(subidentifier);
|
||||
subidentifier.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! subidentifier.empty() || subidentifiers.size() < 1 )
|
||||
// Underflow.
|
||||
return new StringVal("");
|
||||
|
||||
for ( size_t i = 0; i < subidentifiers.size(); ++i )
|
||||
{
|
||||
subidentifier = subidentifiers[i];
|
||||
uint64 value = 0;
|
||||
|
||||
for ( size_t j = 0; j < subidentifier.size(); ++j )
|
||||
{
|
||||
uint64 byte = subidentifier[j];
|
||||
value |= byte << (7 * (subidentifier.size() - (j + 1)));
|
||||
}
|
||||
|
||||
subidentifier_values.push_back(value);
|
||||
}
|
||||
|
||||
string rval;
|
||||
|
||||
for ( size_t i = 0; i < subidentifier_values.size(); ++i )
|
||||
{
|
||||
char tmp[32];
|
||||
|
||||
if ( i > 0 )
|
||||
{
|
||||
rval += ".";
|
||||
snprintf(tmp, sizeof(tmp), "%" PRIu64, subidentifier_values[i]);
|
||||
rval += tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::div_t result = std::div(subidentifier_values[i], 40);
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.quot);
|
||||
rval += tmp;
|
||||
rval += ".";
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.rem);
|
||||
rval += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return new StringVal(rval);
|
||||
}
|
||||
|
||||
StringVal* asn1_octet_string_to_val(const ASN1OctetString* s)
|
||||
{
|
||||
return asn1_octet_string_to_val(s->encoding());
|
||||
}
|
||||
|
||||
StringVal* asn1_octet_string_to_val(const ASN1Encoding* s)
|
||||
{
|
||||
bytestring const& bs = s->content();
|
||||
return new StringVal(bs.length(), reinterpret_cast<const char*>(bs.data()));
|
||||
}
|
||||
%}
|
|
@ -6,7 +6,7 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI
|
|||
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.pac dce_rpc-protocol.pac dce_rpc-analyzer.pac epmapper.pac)
|
||||
bro_plugin_pac(dce_rpc_simple.pac dce_rpc-protocol.pac epmapper.pac)
|
||||
bro_plugin_end()
|
||||
|
||||
|
|
|
@ -239,7 +239,9 @@ int HTTP_Entity::Undelivered(int64_t len)
|
|||
len, expect_data_length);
|
||||
}
|
||||
|
||||
if ( end_of_data && in_header )
|
||||
// Don't propogate an entity (file) gap if we're still in the headers,
|
||||
// or the body length was declared to be zero.
|
||||
if ( (end_of_data && in_header) || body_length == 0 )
|
||||
return 0;
|
||||
|
||||
if ( is_partial_content )
|
||||
|
|
26
src/analyzer/protocol/krb/CMakeLists.txt
Normal file
26
src/analyzer/protocol/krb/CMakeLists.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
include(BroPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
bro_plugin_begin(Bro KRB)
|
||||
bro_plugin_cc(Plugin.cc)
|
||||
bro_plugin_cc(KRB.cc)
|
||||
bro_plugin_cc(KRB_TCP.cc)
|
||||
bro_plugin_bif(types.bif)
|
||||
bro_plugin_bif(events.bif)
|
||||
bro_plugin_pac(krb.pac krb-protocol.pac krb-analyzer.pac
|
||||
krb-asn1.pac
|
||||
krb-defs.pac
|
||||
krb-types.pac
|
||||
krb-padata.pac
|
||||
../asn1/asn1.pac
|
||||
)
|
||||
bro_plugin_pac(krb_TCP.pac krb-protocol.pac krb-analyzer.pac
|
||||
krb-asn1.pac
|
||||
krb-defs.pac
|
||||
krb-types.pac
|
||||
krb-padata.pac
|
||||
../asn1/asn1.pac
|
||||
)
|
||||
bro_plugin_end()
|
39
src/analyzer/protocol/krb/KRB.cc
Normal file
39
src/analyzer/protocol/krb/KRB.cc
Normal file
|
@ -0,0 +1,39 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "KRB.h"
|
||||
#include "types.bif.h"
|
||||
#include "events.bif.h"
|
||||
|
||||
using namespace analyzer::krb;
|
||||
|
||||
KRB_Analyzer::KRB_Analyzer(Connection* conn)
|
||||
: Analyzer("KRB", conn)
|
||||
{
|
||||
interp = new binpac::KRB::KRB_Conn(this);
|
||||
}
|
||||
|
||||
KRB_Analyzer::~KRB_Analyzer()
|
||||
{
|
||||
delete interp;
|
||||
}
|
||||
|
||||
void KRB_Analyzer::Done()
|
||||
{
|
||||
Analyzer::Done();
|
||||
}
|
||||
|
||||
void KRB_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
|
||||
uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
|
||||
|
||||
try
|
||||
{
|
||||
interp->NewData(orig, data, data + len);
|
||||
}
|
||||
catch ( const binpac::Exception& e )
|
||||
{
|
||||
ProtocolViolation(e.c_msg());
|
||||
}
|
||||
}
|
||||
|
30
src/analyzer/protocol/krb/KRB.h
Normal file
30
src/analyzer/protocol/krb/KRB.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#ifndef ANALYZER_PROTOCOL_KRB_KRB_H
|
||||
#define ANALYZER_PROTOCOL_KRB_KRB_H
|
||||
|
||||
#include "krb_pac.h"
|
||||
|
||||
namespace analyzer { namespace krb {
|
||||
|
||||
class KRB_Analyzer : public analyzer::Analyzer {
|
||||
|
||||
public:
|
||||
KRB_Analyzer(Connection* conn);
|
||||
virtual ~KRB_Analyzer();
|
||||
|
||||
virtual void Done();
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
static analyzer::Analyzer* Instantiate(Connection* conn)
|
||||
{ return new KRB_Analyzer(conn); }
|
||||
|
||||
protected:
|
||||
|
||||
binpac::KRB::KRB_Conn* interp;
|
||||
};
|
||||
|
||||
} } // namespace analyzer::*
|
||||
|
||||
#endif
|
65
src/analyzer/protocol/krb/KRB_TCP.cc
Normal file
65
src/analyzer/protocol/krb/KRB_TCP.cc
Normal file
|
@ -0,0 +1,65 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "KRB_TCP.h"
|
||||
#include "analyzer/protocol/tcp/TCP_Reassembler.h"
|
||||
#include "types.bif.h"
|
||||
#include "events.bif.h"
|
||||
|
||||
using namespace analyzer::krb_tcp;
|
||||
|
||||
KRB_Analyzer::KRB_Analyzer(Connection* conn)
|
||||
: tcp::TCP_ApplicationAnalyzer("KRB_TCP", conn)
|
||||
{
|
||||
interp = new binpac::KRB_TCP::KRB_Conn(this);
|
||||
had_gap = false;
|
||||
}
|
||||
|
||||
KRB_Analyzer::~KRB_Analyzer()
|
||||
{
|
||||
delete interp;
|
||||
}
|
||||
|
||||
void KRB_Analyzer::Done()
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::Done();
|
||||
|
||||
interp->FlowEOF(true);
|
||||
interp->FlowEOF(false);
|
||||
}
|
||||
|
||||
void KRB_Analyzer::EndpointEOF(bool is_orig)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
|
||||
interp->FlowEOF(is_orig);
|
||||
}
|
||||
|
||||
void KRB_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
|
||||
|
||||
assert(TCP());
|
||||
if ( TCP()->IsPartial() )
|
||||
return;
|
||||
|
||||
if ( had_gap )
|
||||
// If only one side had a content gap, we could still try to
|
||||
// deliver data to the other side if the script layer can
|
||||
// handle this.
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
interp->NewData(orig, data, data + len);
|
||||
}
|
||||
catch ( const binpac::Exception& e )
|
||||
{
|
||||
ProtocolViolation(e.c_msg());
|
||||
}
|
||||
}
|
||||
|
||||
void KRB_Analyzer::Undelivered(uint64 seq, int len, bool orig)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
|
||||
had_gap = true;
|
||||
interp->NewGap(orig, len);
|
||||
}
|
35
src/analyzer/protocol/krb/KRB_TCP.h
Normal file
35
src/analyzer/protocol/krb/KRB_TCP.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#ifndef ANALYZER_PROTOCOL_KRB_KRB_TCP_H
|
||||
#define ANALYZER_PROTOCOL_KRB_KRB_TCP_H
|
||||
|
||||
#include "analyzer/protocol/tcp/TCP.h"
|
||||
|
||||
#include "krb_TCP_pac.h"
|
||||
|
||||
namespace analyzer { namespace krb_tcp {
|
||||
|
||||
class KRB_Analyzer : public tcp::TCP_ApplicationAnalyzer {
|
||||
|
||||
public:
|
||||
KRB_Analyzer(Connection* conn);
|
||||
virtual ~KRB_Analyzer();
|
||||
|
||||
virtual void Done();
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
virtual void Undelivered(uint64 seq, int len, bool orig);
|
||||
|
||||
// Overriden from tcp::TCP_ApplicationAnalyzer.
|
||||
virtual void EndpointEOF(bool is_orig);
|
||||
|
||||
static analyzer::Analyzer* Instantiate(Connection* conn)
|
||||
{ return new KRB_Analyzer(conn); }
|
||||
|
||||
protected:
|
||||
binpac::KRB_TCP::KRB_Conn* interp;
|
||||
bool had_gap;
|
||||
};
|
||||
|
||||
} } // namespace analyzer::*
|
||||
|
||||
#endif
|
22
src/analyzer/protocol/krb/Plugin.cc
Normal file
22
src/analyzer/protocol/krb/Plugin.cc
Normal file
|
@ -0,0 +1,22 @@
|
|||
//See the file in the main distribution directory for copyright.
|
||||
|
||||
#include "plugin/Plugin.h"
|
||||
#include "KRB.h"
|
||||
#include "KRB_TCP.h"
|
||||
|
||||
namespace plugin {
|
||||
namespace Bro_KRB {
|
||||
class Plugin : public plugin::Plugin {
|
||||
public:
|
||||
plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new ::analyzer::Component("KRB", ::analyzer::krb::KRB_Analyzer::Instantiate));
|
||||
AddComponent(new ::analyzer::Component("KRB_TCP", ::analyzer::krb_tcp::KRB_Analyzer::Instantiate));
|
||||
plugin::Configuration config;
|
||||
config.name = "Bro::KRB";
|
||||
config.description = "Kerberos analyzer";
|
||||
return config;
|
||||
}
|
||||
} plugin;
|
||||
}
|
||||
}
|
159
src/analyzer/protocol/krb/events.bif
Normal file
159
src/analyzer/protocol/krb/events.bif
Normal file
|
@ -0,0 +1,159 @@
|
|||
## A Kerberos 5 ``Authentication Server (AS) Request`` as defined
|
||||
## in :rfc:`4120`. The AS request contains a username of the client
|
||||
## requesting authentication, and returns an AS reply with an
|
||||
## encrypted Ticket Granting Ticket (TGT) for that user. The TGT
|
||||
## can then be used to request further tickets for other services.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Kerberos_%28protocol%29>`__ for
|
||||
## more information about the Kerberos protocol.
|
||||
##
|
||||
## c: The connection over which this Kerberos message was sent.
|
||||
##
|
||||
## msg: A Kerberos KDC request message data structure.
|
||||
##
|
||||
## .. bro:see:: krb_as_response krb_tgs_request krb_tgs_response krb_ap_request
|
||||
## krb_ap_response krb_priv krb_safe krb_cred krb_error
|
||||
event krb_as_request%(c: connection, msg: KRB::KDC_Request%);
|
||||
|
||||
## A Kerberos 5 ``Authentication Server (AS) Response`` as defined
|
||||
## in :rfc:`4120`. Following the AS request for a user, an AS reply
|
||||
## contains an encrypted Ticket Granting Ticket (TGT) for that user.
|
||||
## The TGT can then be used to request further tickets for other services.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Kerberos_%28protocol%29>`__ for
|
||||
## more information about the Kerberos protocol.
|
||||
##
|
||||
## c: The connection over which this Kerberos message was sent.
|
||||
##
|
||||
## msg: A Kerberos KDC reply message data structure.
|
||||
##
|
||||
## .. bro:see:: krb_as_request krb_tgs_request krb_tgs_response krb_ap_request
|
||||
## krb_ap_response krb_priv krb_safe krb_cred krb_error
|
||||
event krb_as_response%(c: connection, msg: KRB::KDC_Response%);
|
||||
|
||||
## A Kerberos 5 ``Ticket Granting Service (TGS) Request`` as defined
|
||||
## in :rfc:`4120`. Following the Authentication Server exchange, if
|
||||
## successful, the client now has a Ticket Granting Ticket (TGT). To
|
||||
## authenticate to a Kerberized service, the client requests a Service
|
||||
## Ticket, which will be returned in the TGS reply.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Kerberos_%28protocol%29>`__ for
|
||||
## more information about the Kerberos protocol.
|
||||
##
|
||||
## c: The connection over which this Kerberos message was sent.
|
||||
##
|
||||
## msg: A Kerberos KDC request message data structure.
|
||||
##
|
||||
## .. bro:see:: krb_as_request krb_as_response krb_tgs_response krb_ap_request
|
||||
## krb_ap_response krb_priv krb_safe krb_cred krb_error
|
||||
event krb_tgs_request%(c: connection, msg: KRB::KDC_Request%);
|
||||
|
||||
## A Kerberos 5 ``Ticket Granting Service (TGS) Response`` as defined
|
||||
## in :rfc:`4120`. This message returns a Service Ticket to the client,
|
||||
## which is encrypted with the service's long-term key, and which the
|
||||
## client can use to authenticate to that service.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Kerberos_%28protocol%29>`__ for
|
||||
## more information about the Kerberos protocol.
|
||||
##
|
||||
## c: The connection over which this Kerberos message was sent.
|
||||
##
|
||||
## msg: A Kerberos KDC reply message data structure.
|
||||
##
|
||||
## .. bro:see:: krb_as_request krb_as_response krb_tgs_request krb_ap_request
|
||||
## krb_ap_response krb_priv krb_safe krb_cred krb_error
|
||||
event krb_tgs_response%(c: connection, msg: KRB::KDC_Response%);
|
||||
|
||||
## A Kerberos 5 ``Authentication Header (AP) Request`` as defined
|
||||
## in :rfc:`4120`. This message contains authentication information
|
||||
## that should be part of the first message in an authenticated
|
||||
## transaction.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Kerberos_%28protocol%29>`__ for
|
||||
## more information about the Kerberos protocol.
|
||||
##
|
||||
## c: The connection over which this Kerberos message was sent.
|
||||
##
|
||||
## ticket: The Kerberos ticket being used for authentication.
|
||||
##
|
||||
## opts: A Kerberos AP options data structure.
|
||||
##
|
||||
## .. bro:see:: krb_as_request krb_as_response krb_tgs_request krb_tgs_response
|
||||
## krb_ap_response krb_priv krb_safe krb_cred krb_error
|
||||
event krb_ap_request%(c: connection, ticket: KRB::Ticket, opts: KRB::AP_Options%);
|
||||
|
||||
## A Kerberos 5 ``Authentication Header (AP) Response`` as defined
|
||||
## in :rfc:`4120`. This is used if mutual authentication is desired.
|
||||
## All of the interesting information in here is encrypted, so the event
|
||||
## doesn't have much useful data, but it's provided in case it's important
|
||||
## to know that this message was sent.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Kerberos_%28protocol%29>`__ for
|
||||
## more information about the Kerberos protocol.
|
||||
##
|
||||
## c: The connection over which this Kerberos message was sent.
|
||||
##
|
||||
## .. bro:see:: krb_as_request krb_as_response krb_tgs_request krb_tgs_response
|
||||
## krb_ap_request krb_priv krb_safe krb_cred krb_error
|
||||
event krb_ap_response%(c: connection%);
|
||||
|
||||
## A Kerberos 5 ``Private Message`` as defined in :rfc:`4120`. This
|
||||
## is a private (encrypted) application message, so the event doesn't
|
||||
## have much useful data, but it's provided in case it's important to
|
||||
## know that this message was sent.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Kerberos_%28protocol%29>`__ for
|
||||
## more information about the Kerberos protocol.
|
||||
##
|
||||
## c: The connection over which this Kerberos message was sent.
|
||||
##
|
||||
## is_orig: Whether the originator of the connection sent this message.
|
||||
##
|
||||
## .. bro:see:: krb_as_request krb_as_response krb_tgs_request krb_tgs_response
|
||||
## krb_ap_request krb_ap_response krb_safe krb_cred krb_error
|
||||
event krb_priv%(c: connection, is_orig: bool%);
|
||||
|
||||
## A Kerberos 5 ``Safe Message`` as defined in :rfc:`4120`. This is a
|
||||
## safe (checksummed) application message.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Kerberos_%28protocol%29>`__ for
|
||||
## more information about the Kerberos protocol.
|
||||
##
|
||||
## c: The connection over which this Kerberos message was sent.
|
||||
##
|
||||
## is_orig: Whether the originator of the connection sent this message.
|
||||
##
|
||||
## msg: A Kerberos SAFE message data structure.
|
||||
##
|
||||
## .. bro:see:: krb_as_request krb_as_response krb_tgs_request krb_tgs_response
|
||||
## krb_ap_request krb_ap_response krb_priv krb_cred krb_error
|
||||
event krb_safe%(c: connection, is_orig: bool, msg: KRB::SAFE_Msg%);
|
||||
|
||||
## A Kerberos 5 ``Credential Message`` as defined in :rfc:`4120`. This is
|
||||
## a private (encrypted) message to forward credentials.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Kerberos_%28protocol%29>`__ for
|
||||
## more information about the Kerberos protocol.
|
||||
##
|
||||
## c: The connection over which this Kerberos message was sent.
|
||||
##
|
||||
## is_orig: Whether the originator of the connection sent this message.
|
||||
##
|
||||
## tickets: Tickets obtained from the KDC that are being forwarded.
|
||||
##
|
||||
## .. bro:see:: krb_as_request krb_as_response krb_tgs_request krb_tgs_response
|
||||
## krb_ap_request krb_ap_response krb_priv krb_safe krb_error
|
||||
event krb_cred%(c: connection, is_orig: bool, tickets: KRB::Ticket_Vector%);
|
||||
|
||||
## A Kerberos 5 ``Error Message`` as defined in :rfc:`4120`.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Kerberos_%28protocol%29>`__ for
|
||||
## more information about the Kerberos protocol.
|
||||
##
|
||||
## c: The connection over which this Kerberos message was sent.
|
||||
##
|
||||
## msg: A Kerberos error message data structure.
|
||||
##
|
||||
## .. bro:see:: krb_as_request krb_as_response krb_tgs_request krb_tgs_response
|
||||
## krb_ap_request krb_ap_response krb_priv krb_safe krb_cred
|
||||
event krb_error%(c: connection, msg: KRB::Error_Msg%);
|
383
src/analyzer/protocol/krb/krb-analyzer.pac
Normal file
383
src/analyzer/protocol/krb/krb-analyzer.pac
Normal file
|
@ -0,0 +1,383 @@
|
|||
%header{
|
||||
RecordVal* proc_krb_kdc_options(const KRB_KDC_Options* opts);
|
||||
RecordVal* proc_krb_kdc_req_arguments(KRB_KDC_REQ* msg, const BroAnalyzer bro_analyzer);
|
||||
|
||||
bool proc_error_arguments(RecordVal* rv, const std::vector<KRB_ERROR_Arg*>* args, int64 error_code);
|
||||
%}
|
||||
|
||||
%code{
|
||||
RecordVal* proc_krb_kdc_options(const KRB_KDC_Options* opts)
|
||||
{
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::KDC_Options);
|
||||
|
||||
rv->Assign(0, new Val(opts->forwardable(), TYPE_BOOL));
|
||||
rv->Assign(1, new Val(opts->forwarded(), TYPE_BOOL));
|
||||
rv->Assign(2, new Val(opts->proxiable(), TYPE_BOOL));
|
||||
rv->Assign(3, new Val(opts->proxy(), TYPE_BOOL));
|
||||
rv->Assign(4, new Val(opts->allow_postdate(), TYPE_BOOL));
|
||||
rv->Assign(5, new Val(opts->postdated(), TYPE_BOOL));
|
||||
rv->Assign(6, new Val(opts->renewable(), TYPE_BOOL));
|
||||
rv->Assign(7, new Val(opts->opt_hardware_auth(), TYPE_BOOL));
|
||||
rv->Assign(8, new Val(opts->disable_transited_check(), TYPE_BOOL));
|
||||
rv->Assign(9, new Val(opts->renewable_ok(), TYPE_BOOL));
|
||||
rv->Assign(10, new Val(opts->enc_tkt_in_skey(), TYPE_BOOL));
|
||||
rv->Assign(11, new Val(opts->renew(), TYPE_BOOL));
|
||||
rv->Assign(12, new Val(opts->validate(), TYPE_BOOL));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
RecordVal* proc_krb_kdc_req_arguments(KRB_KDC_REQ* msg, const BroAnalyzer bro_analyzer)
|
||||
{
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::KDC_Request);
|
||||
|
||||
rv->Assign(0, asn1_integer_to_val(msg->pvno()->data(), TYPE_COUNT));
|
||||
rv->Assign(1, asn1_integer_to_val(msg->msg_type()->data(), TYPE_COUNT));
|
||||
|
||||
if ( msg->padata()->has_padata() )
|
||||
rv->Assign(2, proc_padata(msg->padata()->padata()->padata(), bro_analyzer, false));
|
||||
|
||||
for ( uint i = 0; i < msg->body_args()->size(); ++i )
|
||||
{
|
||||
KRB_REQ_Arg* element = (*msg->body_args())[i];
|
||||
switch ( element->seq_meta()->index() )
|
||||
{
|
||||
case 0:
|
||||
rv->Assign(3, proc_krb_kdc_options(element->data()->options()));
|
||||
break;
|
||||
case 1:
|
||||
rv->Assign(4, GetStringFromPrincipalName(element->data()->principal()));
|
||||
break;
|
||||
case 2:
|
||||
rv->Assign(5, bytestring_to_val(element->data()->realm()->encoding()->content()));
|
||||
break;
|
||||
case 3:
|
||||
rv->Assign(6, GetStringFromPrincipalName(element->data()->sname()));
|
||||
break;
|
||||
case 4:
|
||||
rv->Assign(7, GetTimeFromAsn1(element->data()->from(), 0));
|
||||
break;
|
||||
case 5:
|
||||
rv->Assign(8, GetTimeFromAsn1(element->data()->till(), 0));
|
||||
break;
|
||||
case 6:
|
||||
rv->Assign(9, GetTimeFromAsn1(element->data()->rtime(), 0));
|
||||
break;
|
||||
case 7:
|
||||
rv->Assign(10, asn1_integer_to_val(element->data()->nonce(), TYPE_COUNT));
|
||||
break;
|
||||
case 8:
|
||||
if ( element->data()->etype()->data()->size() )
|
||||
rv->Assign(11, proc_cipher_list(element->data()->etype()));
|
||||
|
||||
break;
|
||||
case 9:
|
||||
if ( element->data()->addrs()->addresses()->size() )
|
||||
rv->Assign(12, proc_host_address_list(element->data()->addrs()));
|
||||
|
||||
break;
|
||||
case 10:
|
||||
// TODO
|
||||
break;
|
||||
case 11:
|
||||
if ( element->data()->addl_tkts()->tickets()->size() )
|
||||
rv->Assign(13, proc_tickets(element->data()->addl_tkts()));
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
bool proc_error_arguments(RecordVal* rv, const std::vector<KRB_ERROR_Arg*>* args, int64 error_code )
|
||||
{
|
||||
uint ctime_i = 0, stime_i = 0;
|
||||
int64 ctime_usecs = 0, stime_usecs = 0;
|
||||
|
||||
// We need to do a pass first, to see if we have microseconds for the timestamp values, which are optional
|
||||
|
||||
for ( uint i = 0; i < args->size(); i++ )
|
||||
{
|
||||
switch ( (*args)[i]->seq_meta()->index() )
|
||||
{
|
||||
case 2:
|
||||
ctime_i = i;
|
||||
break;
|
||||
case 3:
|
||||
ctime_usecs = binary_to_int64((*args)[i]->args()->cusec()->encoding()->content());
|
||||
break;
|
||||
case 4:
|
||||
stime_i = i;
|
||||
break;
|
||||
case 5:
|
||||
stime_usecs = binary_to_int64((*args)[i]->args()->susec()->encoding()->content());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ctime_i )
|
||||
rv->Assign(2, GetTimeFromAsn1((*args)[ctime_i]->args()->ctime(), ctime_usecs));
|
||||
|
||||
if ( stime_i )
|
||||
rv->Assign(3, GetTimeFromAsn1((*args)[stime_i]->args()->stime(), stime_usecs));
|
||||
|
||||
for ( uint i = 0; i < args->size(); ++i )
|
||||
{
|
||||
switch ( (*args)[i]->seq_meta()->index() )
|
||||
{
|
||||
case 0:
|
||||
rv->Assign(0, asn1_integer_to_val((*args)[i]->args()->pvno(), TYPE_COUNT));
|
||||
break;
|
||||
case 1:
|
||||
rv->Assign(1, asn1_integer_to_val((*args)[i]->args()->msg_type(), TYPE_COUNT));
|
||||
break;
|
||||
// ctime/stime handled above
|
||||
case 7:
|
||||
rv->Assign(5, bytestring_to_val((*args)[i]->args()->crealm()->encoding()->content()));
|
||||
break;
|
||||
case 8:
|
||||
rv->Assign(6, GetStringFromPrincipalName((*args)[i]->args()->cname()));
|
||||
break;
|
||||
case 9:
|
||||
rv->Assign(7, bytestring_to_val((*args)[i]->args()->realm()->encoding()->content()));
|
||||
break;
|
||||
case 10:
|
||||
rv->Assign(8, GetStringFromPrincipalName((*args)[i]->args()->sname()));
|
||||
break;
|
||||
case 11:
|
||||
rv->Assign(9, bytestring_to_val((*args)[i]->args()->e_text()->encoding()->content()));
|
||||
break;
|
||||
case 12:
|
||||
if ( error_code == KDC_ERR_PREAUTH_REQUIRED )
|
||||
rv->Assign(10, proc_padata((*args)[i]->args()->e_data()->padata(), NULL, true));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
refine connection KRB_Conn += {
|
||||
|
||||
function proc_krb_kdc_req_msg(msg: KRB_KDC_REQ): bool
|
||||
%{
|
||||
bro_analyzer()->ProtocolConfirmation();
|
||||
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 10 ) && ! krb_as_request )
|
||||
return false;
|
||||
|
||||
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 12 ) && ! krb_tgs_request )
|
||||
return false;
|
||||
|
||||
RecordVal* rv = proc_krb_kdc_req_arguments(${msg}, bro_analyzer());
|
||||
|
||||
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 10 ) )
|
||||
BifEvent::generate_krb_as_request(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||
|
||||
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 12 ) )
|
||||
BifEvent::generate_krb_tgs_request(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_krb_kdc_rep_msg(msg: KRB_KDC_REP): bool
|
||||
%{
|
||||
bro_analyzer()->ProtocolConfirmation();
|
||||
|
||||
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 11 ) && ! krb_as_response )
|
||||
return false;
|
||||
|
||||
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 13 ) && ! krb_tgs_response )
|
||||
return false;
|
||||
|
||||
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::KDC_Response);
|
||||
|
||||
rv->Assign(0, asn1_integer_to_val(${msg.pvno.data}, TYPE_COUNT));
|
||||
rv->Assign(1, asn1_integer_to_val(${msg.msg_type.data}, TYPE_COUNT));
|
||||
|
||||
if ( ${msg.padata.has_padata} )
|
||||
rv->Assign(2, proc_padata(${msg.padata.padata.padata}, bro_analyzer(), false));
|
||||
|
||||
rv->Assign(3, bytestring_to_val(${msg.client_realm.encoding.content}));
|
||||
rv->Assign(4, GetStringFromPrincipalName(${msg.client_name}));
|
||||
|
||||
rv->Assign(5, proc_ticket(${msg.ticket}));
|
||||
|
||||
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 11 ) )
|
||||
BifEvent::generate_krb_as_response(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||
|
||||
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 13 ) )
|
||||
BifEvent::generate_krb_tgs_response(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_krb_error_msg(msg: KRB_ERROR_MSG): bool
|
||||
%{
|
||||
bro_analyzer()->ProtocolConfirmation();
|
||||
if ( krb_error )
|
||||
{
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::Error_Msg);
|
||||
proc_error_arguments(rv, ${msg.args1}, 0);
|
||||
rv->Assign(4, asn1_integer_to_val(${msg.error_code}, TYPE_COUNT));
|
||||
proc_error_arguments(rv, ${msg.args2}, binary_to_int64(${msg.error_code.encoding.content}));
|
||||
BifEvent::generate_krb_error(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_krb_ap_req_msg(msg: KRB_AP_REQ): bool
|
||||
%{
|
||||
bro_analyzer()->ProtocolConfirmation();
|
||||
if ( krb_ap_request )
|
||||
{
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::AP_Options);
|
||||
rv->Assign(0, new Val(${msg.ap_options.use_session_key}, TYPE_BOOL));
|
||||
rv->Assign(1, new Val(${msg.ap_options.mutual_required}, TYPE_BOOL));
|
||||
|
||||
BifEvent::generate_krb_ap_request(bro_analyzer(), bro_analyzer()->Conn(),
|
||||
proc_ticket(${msg.ticket}), rv);
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_krb_ap_rep_msg(msg: KRB_AP_REP): bool
|
||||
%{
|
||||
bro_analyzer()->ProtocolConfirmation();
|
||||
if ( krb_ap_response )
|
||||
{
|
||||
BifEvent::generate_krb_ap_response(bro_analyzer(), bro_analyzer()->Conn());
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_krb_safe_msg(msg: KRB_SAFE_MSG): bool
|
||||
%{
|
||||
bro_analyzer()->ProtocolConfirmation();
|
||||
if ( krb_safe )
|
||||
{
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::SAFE_Msg);
|
||||
|
||||
rv->Assign(0, asn1_integer_to_val(${msg.pvno.data}, TYPE_COUNT));
|
||||
rv->Assign(1, asn1_integer_to_val(${msg.msg_type.data}, TYPE_COUNT));
|
||||
|
||||
uint timestamp_i = 0;
|
||||
int64 timestamp_usecs = 0;
|
||||
|
||||
// We need to do a pass first, to see if we have microseconds for the timestamp values, which are optional
|
||||
|
||||
for ( uint i = 0; i < ${msg.safe_body.args}->size(); ++i )
|
||||
{
|
||||
switch ( ${msg.safe_body.args[i].seq_meta.index} )
|
||||
{
|
||||
case 1:
|
||||
timestamp_i = i;
|
||||
break;
|
||||
case 2:
|
||||
timestamp_usecs = binary_to_int64(${msg.safe_body.args[i].args.usec.encoding.content});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( timestamp_i )
|
||||
rv->Assign(4, GetTimeFromAsn1(${msg.safe_body.args[timestamp_i].args.timestamp}, timestamp_usecs));
|
||||
|
||||
for ( uint i = 0; i < ${msg.safe_body.args}->size(); ++i )
|
||||
{
|
||||
switch ( ${msg.safe_body.args[i].seq_meta.index} )
|
||||
{
|
||||
case 0:
|
||||
rv->Assign(3, bytestring_to_val(${msg.safe_body.args[i].args.user_data.encoding.content}));
|
||||
break;
|
||||
case 3:
|
||||
rv->Assign(5, asn1_integer_to_val(${msg.safe_body.args[i].args.seq_number}, TYPE_COUNT));
|
||||
break;
|
||||
case 4:
|
||||
rv->Assign(6, proc_host_address(${msg.safe_body.args[i].args.sender_addr}));
|
||||
break;
|
||||
case 5:
|
||||
rv->Assign(7, proc_host_address(${msg.safe_body.args[i].args.recp_addr}));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
BifEvent::generate_krb_safe(bro_analyzer(), bro_analyzer()->Conn(), ${msg.is_orig}, rv);
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_krb_priv_msg(msg: KRB_PRIV_MSG): bool
|
||||
%{
|
||||
bro_analyzer()->ProtocolConfirmation();
|
||||
if ( krb_priv )
|
||||
{
|
||||
BifEvent::generate_krb_priv(bro_analyzer(), bro_analyzer()->Conn(), ${msg.is_orig});
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_krb_cred_msg(msg: KRB_CRED_MSG): bool
|
||||
%{
|
||||
bro_analyzer()->ProtocolConfirmation();
|
||||
if ( krb_cred )
|
||||
{
|
||||
BifEvent::generate_krb_cred(bro_analyzer(), bro_analyzer()->Conn(), ${msg.is_orig},
|
||||
proc_tickets(${msg.tickets}));
|
||||
}
|
||||
return true;
|
||||
|
||||
%}
|
||||
}
|
||||
|
||||
refine typeattr KRB_AS_REQ += &let {
|
||||
proc: bool = $context.connection.proc_krb_kdc_req_msg(data);
|
||||
};
|
||||
|
||||
refine typeattr KRB_TGS_REQ += &let {
|
||||
proc: bool = $context.connection.proc_krb_kdc_req_msg(data);
|
||||
};
|
||||
|
||||
refine typeattr KRB_AS_REP += &let {
|
||||
proc: bool = $context.connection.proc_krb_kdc_rep_msg(data);
|
||||
};
|
||||
|
||||
refine typeattr KRB_TGS_REP += &let {
|
||||
proc: bool = $context.connection.proc_krb_kdc_rep_msg(data);
|
||||
};
|
||||
|
||||
refine typeattr KRB_AP_REQ += &let {
|
||||
proc: bool = $context.connection.proc_krb_ap_req_msg(this);
|
||||
};
|
||||
|
||||
refine typeattr KRB_AP_REP += &let {
|
||||
proc: bool = $context.connection.proc_krb_ap_rep_msg(this);
|
||||
};
|
||||
|
||||
refine typeattr KRB_ERROR_MSG += &let {
|
||||
proc: bool = $context.connection.proc_krb_error_msg(this);
|
||||
};
|
||||
|
||||
refine typeattr KRB_SAFE_MSG += &let {
|
||||
proc: bool = $context.connection.proc_krb_safe_msg(this);
|
||||
};
|
||||
|
||||
refine typeattr KRB_PRIV_MSG += &let {
|
||||
proc: bool = $context.connection.proc_krb_priv_msg(this);
|
||||
};
|
||||
|
||||
refine typeattr KRB_CRED_MSG += &let {
|
||||
proc: bool = $context.connection.proc_krb_cred_msg(this);
|
||||
};
|
58
src/analyzer/protocol/krb/krb-asn1.pac
Normal file
58
src/analyzer/protocol/krb/krb-asn1.pac
Normal file
|
@ -0,0 +1,58 @@
|
|||
|
||||
%include ../asn1/asn1.pac
|
||||
|
||||
%header{
|
||||
Val* GetTimeFromAsn1(const KRB_Time* atime, int64 usecs);
|
||||
Val* GetTimeFromAsn1(StringVal* atime, int64 usecs);
|
||||
%}
|
||||
|
||||
%code{
|
||||
|
||||
Val* GetTimeFromAsn1(const KRB_Time* atime, int64 usecs)
|
||||
{
|
||||
StringVal* atime_bytestring = bytestring_to_val(atime->time());
|
||||
Val* result = GetTimeFromAsn1(atime_bytestring, usecs);
|
||||
Unref(atime_bytestring);
|
||||
return result;
|
||||
}
|
||||
|
||||
Val* GetTimeFromAsn1(StringVal* atime, int64 usecs)
|
||||
{
|
||||
time_t lResult = 0;
|
||||
|
||||
char lBuffer[17];
|
||||
char* pBuffer = lBuffer;
|
||||
|
||||
size_t lTimeLength = atime->Len();
|
||||
char * pString = (char *) atime->Bytes();
|
||||
|
||||
if ( lTimeLength != 15 && lTimeLength != 17 )
|
||||
return 0;
|
||||
|
||||
if (lTimeLength == 17 )
|
||||
pString = pString + 2;
|
||||
|
||||
memcpy(pBuffer, pString, 15);
|
||||
*(pBuffer+15) = '\0';
|
||||
|
||||
tm lTime;
|
||||
lTime.tm_sec = ((lBuffer[12] - '0') * 10) + (lBuffer[13] - '0');
|
||||
lTime.tm_min = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
|
||||
lTime.tm_hour = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
|
||||
lTime.tm_mday = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
|
||||
lTime.tm_mon = (((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0')) - 1;
|
||||
lTime.tm_year = ((lBuffer[0] - '0') * 1000) + ((lBuffer[1] - '0') * 100) + ((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0') - 1900;
|
||||
|
||||
lTime.tm_wday = 0;
|
||||
lTime.tm_yday = 0;
|
||||
lTime.tm_isdst = 0;
|
||||
|
||||
lResult = timegm(&lTime);
|
||||
|
||||
if ( !lResult )
|
||||
lResult = 0;
|
||||
|
||||
return new Val(double(lResult + double(usecs/100000.0)), TYPE_TIME);
|
||||
}
|
||||
|
||||
%}
|
27
src/analyzer/protocol/krb/krb-defs.pac
Normal file
27
src/analyzer/protocol/krb/krb-defs.pac
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Defined in RFC 4120
|
||||
enum KRBMessageTypes {
|
||||
AS_REQ = 10,
|
||||
AS_REP = 11,
|
||||
TGS_REQ = 12,
|
||||
TGS_REP = 13,
|
||||
AP_REQ = 14,
|
||||
AP_REP = 15,
|
||||
KRB_SAFE = 20,
|
||||
KRB_PRIV = 21,
|
||||
KRB_CRED = 22,
|
||||
KRB_ERROR = 30,
|
||||
};
|
||||
|
||||
# Defined by IANA in Kerberos Parameters - Pre-authentication and Typed Data
|
||||
enum KRBPADataTypes {
|
||||
PA_TGS_REQ = 1,
|
||||
PA_ENC_TIMESTAMP = 2,
|
||||
PA_PW_SALT = 3,
|
||||
PA_PW_AS_REQ = 16,
|
||||
PA_PW_AS_REP = 17,
|
||||
};
|
||||
|
||||
# Defined in RFC 4120
|
||||
enum KRBErrorCodes {
|
||||
KDC_ERR_PREAUTH_REQUIRED = 25,
|
||||
};
|
212
src/analyzer/protocol/krb/krb-padata.pac
Normal file
212
src/analyzer/protocol/krb/krb-padata.pac
Normal file
|
@ -0,0 +1,212 @@
|
|||
# Kerberos pre-authentication data is a significant piece of the complexity,
|
||||
# so we're splitting this off
|
||||
|
||||
%extern{
|
||||
#include "file_analysis/Manager.h"
|
||||
%}
|
||||
|
||||
%header{
|
||||
VectorVal* proc_padata(const KRB_PA_Data_Sequence* data, const BroAnalyzer bro_analyzer, bool is_error);
|
||||
%}
|
||||
|
||||
%code{
|
||||
VectorVal* proc_padata(const KRB_PA_Data_Sequence* data, const BroAnalyzer bro_analyzer, bool is_error)
|
||||
{
|
||||
VectorVal* vv = new VectorVal(internal_type("KRB::Type_Value_Vector")->AsVectorType());
|
||||
|
||||
if ( ! data->data()->has_padata() )
|
||||
return vv;
|
||||
|
||||
for ( uint i = 0; i < data->data()->padata_elems()->size(); ++i)
|
||||
{
|
||||
KRB_PA_Data* element = (*data->data()->padata_elems())[i];
|
||||
int64 data_type = element->data_type();
|
||||
|
||||
if ( is_error && ( data_type == PA_PW_AS_REQ || data_type == PA_PW_AS_REP ) )
|
||||
data_type = 0;
|
||||
|
||||
switch( data_type )
|
||||
{
|
||||
case PA_TGS_REQ:
|
||||
// will be generated as separate event
|
||||
break;
|
||||
case PA_ENC_TIMESTAMP:
|
||||
// encrypted timestamp is unreadable
|
||||
break;
|
||||
case PA_PW_SALT:
|
||||
{
|
||||
RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
type_val->Assign(0, new Val(element->data_type(), TYPE_COUNT));
|
||||
type_val->Assign(1, bytestring_to_val(element->pa_data_element()->pa_pw_salt()->encoding()->content()));
|
||||
vv->Assign(vv->Size(), type_val);
|
||||
break;
|
||||
}
|
||||
case PA_PW_AS_REQ:
|
||||
{
|
||||
const bytestring& cert = element->pa_data_element()->pa_pk_as_req()->cert();
|
||||
|
||||
ODesc common;
|
||||
common.AddRaw("Analyzer::ANALYZER_KRB");
|
||||
common.Add(bro_analyzer->Conn()->StartTime());
|
||||
// Request means is_orig=T
|
||||
common.AddRaw("T", 1);
|
||||
bro_analyzer->Conn()->IDString(&common);
|
||||
|
||||
ODesc file_handle;
|
||||
file_handle.Add(common.Description());
|
||||
file_handle.Add(0);
|
||||
|
||||
string file_id = file_mgr->HashHandle(file_handle.Description());
|
||||
|
||||
file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()),
|
||||
cert.length(), bro_analyzer->GetAnalyzerTag(),
|
||||
bro_analyzer->Conn(), true, file_id);
|
||||
file_mgr->EndOfFile(file_id);
|
||||
|
||||
break;
|
||||
}
|
||||
case PA_PW_AS_REP:
|
||||
{
|
||||
const bytestring& cert = element->pa_data_element()->pa_pk_as_rep()->cert();
|
||||
|
||||
ODesc common;
|
||||
common.AddRaw("Analyzer::ANALYZER_KRB");
|
||||
common.Add(bro_analyzer->Conn()->StartTime());
|
||||
// Response means is_orig=F
|
||||
common.AddRaw("F", 1);
|
||||
bro_analyzer->Conn()->IDString(&common);
|
||||
|
||||
ODesc file_handle;
|
||||
file_handle.Add(common.Description());
|
||||
file_handle.Add(1);
|
||||
|
||||
string file_id = file_mgr->HashHandle(file_handle.Description());
|
||||
|
||||
file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()),
|
||||
cert.length(), bro_analyzer->GetAnalyzerTag(),
|
||||
bro_analyzer->Conn(), false, file_id);
|
||||
file_mgr->EndOfFile(file_id);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if ( ! is_error && element->pa_data_element()->unknown().length() )
|
||||
{
|
||||
RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
type_val->Assign(0, new Val(element->data_type(), TYPE_COUNT));
|
||||
type_val->Assign(1, bytestring_to_val(element->pa_data_element()->unknown()));
|
||||
vv->Assign(vv->Size(), type_val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return vv;
|
||||
}
|
||||
%}
|
||||
|
||||
# Basic structure:
|
||||
# 1) In KDC_REQ/KDC_REP packets, the PA_Data is optional and needs a bit of "lookahead."
|
||||
# KRB_PA_Data_Optional -> KRB_PA_Data_Optional_Contents -> KRB_PA_Data_Sequence
|
||||
#
|
||||
# 2) Once we get to the KRB_PA_Data_Sequence level:
|
||||
# KRB_PA_Data_Sequence -> KRB_PA_Data_Container -> KRB_PA_Data -> KRB_PA_Data_Element
|
||||
|
||||
|
||||
# Encapsulating header #1 for KDC_REQ/KDC_REP packets where the PADATA is optional.
|
||||
type KRB_PA_Data_Optional(is_orig: bool, pkt_type: uint8, desired_index: uint8) = record {
|
||||
first_meta : ASN1EncodingMeta;
|
||||
padata : KRB_PA_Data_Optional_Contents(is_orig, has_padata, pkt_type, first_meta.length);
|
||||
next_meta : ASN1OptionalEncodingMeta(has_padata, first_meta);
|
||||
} &let {
|
||||
has_padata : bool = first_meta.index == desired_index;
|
||||
};
|
||||
|
||||
# Encapsulating header #2 for KDC_REQ/KDC_REP packets where the PADATA is optional.
|
||||
#
|
||||
# Note: Split off due to a BinPAC bug
|
||||
type KRB_PA_Data_Optional_Contents(is_orig: bool, is_present: bool, pkt_type: uint8, length: uint64) = case is_present of {
|
||||
true -> padata : KRB_PA_Data_Sequence(is_orig, pkt_type) &length=length;
|
||||
false -> none : empty;
|
||||
};
|
||||
|
||||
# This is our main type
|
||||
type KRB_PA_Data_Sequence(is_orig: bool, pkt_type: uint8) = record {
|
||||
meta : ASN1EncodingMeta;
|
||||
data : KRB_PA_Data_Container(is_orig, pkt_type, meta.tag, meta.length);
|
||||
};
|
||||
|
||||
# The data in KRB_PA_Data_Sequence is usually (and supposed to be) a sequence, which we'll parse,
|
||||
# but is sometimes an octet string. We'll grab that but ignore it.
|
||||
#
|
||||
# Note: This is a separate type due to a BinPAC bug.
|
||||
type KRB_PA_Data_Container(is_orig: bool, pkt_type: uint8, tag: uint8, length: uint64) = case tag of {
|
||||
ASN1_SEQUENCE_TAG -> padata_elems : KRB_PA_Data(is_orig, pkt_type)[];
|
||||
default -> unknown : bytestring &length=length;
|
||||
} &let {
|
||||
has_padata: bool = (tag == ASN1_SEQUENCE_TAG);
|
||||
};
|
||||
|
||||
# The pre-auth data sequence.
|
||||
#
|
||||
# Note: Error packets don't have pre-auth data, they just advertise which mechanisms they support.
|
||||
type KRB_PA_Data(is_orig: bool, pkt_type: uint8) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
pa_data_type : SequenceElement(true);
|
||||
pa_data_elem_meta : ASN1EncodingMeta;
|
||||
have_data : case pkt_type of {
|
||||
KRB_ERROR -> pa_data_placeholder: bytestring &length=pa_data_elem_meta.length;
|
||||
default -> pa_data_element : KRB_PA_Data_Element(is_orig, data_type, pa_data_elem_meta.length);
|
||||
} &requires(data_type);
|
||||
} &let {
|
||||
data_type: int64 = binary_to_int64(pa_data_type.data.content);
|
||||
};
|
||||
|
||||
# Each pre-auth element
|
||||
type KRB_PA_Data_Element(is_orig: bool, type: int64, length: uint64) = case type of {
|
||||
PA_TGS_REQ -> pa_tgs_req : KRB_AP_REQ(is_orig);
|
||||
PA_PW_SALT -> pa_pw_salt : ASN1OctetString;
|
||||
PA_PW_AS_REQ -> pa_pk_as_req : KRB_PA_PK_AS_Req &length=length;
|
||||
PA_PW_AS_REP -> pa_pk_as_rep : KRB_PA_PK_AS_Rep &length=length;
|
||||
default -> unknown : bytestring &length=length;
|
||||
};
|
||||
|
||||
|
||||
# The PKINIT certificate structure for a request
|
||||
type KRB_PA_PK_AS_Req = record {
|
||||
string_meta : ASN1EncodingMeta;
|
||||
seq_meta1 : ASN1EncodingMeta;
|
||||
elem_0_meta1 : ASN1EncodingMeta;
|
||||
seq_meta2 : ASN1EncodingMeta;
|
||||
oid : ASN1Encoding;
|
||||
elem_0_meta2 : ASN1EncodingMeta;
|
||||
seq_meta3 : ASN1EncodingMeta;
|
||||
version : ASN1Encoding;
|
||||
digest_algs : ASN1Encoding;
|
||||
signed_data : ASN1Encoding;
|
||||
cert_meta : ASN1EncodingMeta;
|
||||
cert : bytestring &length=cert_meta.length;
|
||||
# Ignore everything else
|
||||
: bytestring &restofdata &transient;
|
||||
};
|
||||
|
||||
# The PKINIT certificate structure for a reply
|
||||
type KRB_PA_PK_AS_Rep = record {
|
||||
string_meta : ASN1EncodingMeta;
|
||||
elem_0_meta1 : ASN1EncodingMeta;
|
||||
seq_meta1 : ASN1EncodingMeta;
|
||||
elem_0_meta2 : ASN1EncodingMeta;
|
||||
seq_meta2 : ASN1EncodingMeta;
|
||||
oid : ASN1Encoding;
|
||||
elem_0_meta3 : ASN1EncodingMeta;
|
||||
seq_meta3 : ASN1EncodingMeta;
|
||||
version : ASN1Encoding;
|
||||
digest_algs : ASN1Encoding;
|
||||
signed_data : ASN1Encoding;
|
||||
cert_meta : ASN1EncodingMeta;
|
||||
cert : bytestring &length=cert_meta.length;
|
||||
# Ignore everything else
|
||||
: bytestring &restofdata &transient;
|
||||
};
|
||||
|
240
src/analyzer/protocol/krb/krb-protocol.pac
Normal file
240
src/analyzer/protocol/krb/krb-protocol.pac
Normal file
|
@ -0,0 +1,240 @@
|
|||
# ASN1 parsing
|
||||
%include krb-asn1.pac
|
||||
|
||||
# Constants
|
||||
%include krb-defs.pac
|
||||
|
||||
# Basic types
|
||||
%include krb-types.pac
|
||||
|
||||
# Preauth data parsing
|
||||
%include krb-padata.pac
|
||||
|
||||
# KRB over TCP is the same as over UDP, but prefixed with a uint32 denoting the size
|
||||
type KRB_PDU_TCP(is_orig: bool) = record {
|
||||
size : uint32;
|
||||
pdu : KRB_PDU(is_orig);
|
||||
} &length=size+4 &byteorder=bigendian;
|
||||
|
||||
type KRB_PDU(is_orig: bool) = record {
|
||||
app_meta : ASN1EncodingMeta;
|
||||
msg_type : case (app_meta.tag - ASN1_APP_TAG_OFFSET) of {
|
||||
AS_REQ -> as_req : KRB_AS_REQ(is_orig);
|
||||
AS_REP -> as_rep : KRB_AS_REP(is_orig);
|
||||
TGS_REQ -> tgs_req : KRB_TGS_REQ(is_orig);
|
||||
TGS_REP -> tgs_rep : KRB_TGS_REP(is_orig);
|
||||
AP_REQ -> ap_req : KRB_AP_REQ(is_orig);
|
||||
AP_REP -> ap_rep : KRB_AP_REP(is_orig);
|
||||
KRB_SAFE -> krb_safe : KRB_SAFE_MSG(is_orig);
|
||||
KRB_PRIV -> krb_priv : KRB_PRIV_MSG(is_orig);
|
||||
KRB_CRED -> krb_cred : KRB_CRED_MSG(is_orig);
|
||||
KRB_ERROR -> krb_error: KRB_ERROR_MSG(is_orig);
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
type KRB_AS_REQ(is_orig: bool) = record {
|
||||
data: KRB_KDC_REQ(is_orig, AS_REQ);
|
||||
};
|
||||
|
||||
type KRB_TGS_REQ(is_orig: bool) = record {
|
||||
data: KRB_KDC_REQ(is_orig, TGS_REQ);
|
||||
};
|
||||
|
||||
type KRB_AS_REP(is_orig: bool) = record {
|
||||
data: KRB_KDC_REP(is_orig, AS_REP);
|
||||
};
|
||||
|
||||
type KRB_TGS_REP(is_orig: bool) = record {
|
||||
data: KRB_KDC_REP(is_orig, TGS_REP);
|
||||
};
|
||||
|
||||
### A Kerberos ticket-granting-service or authentication-service request
|
||||
|
||||
type KRB_KDC_REQ(is_orig: bool, pkt_type: uint8) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
pvno : SequenceElement(true);
|
||||
msg_type : SequenceElement(true);
|
||||
padata : KRB_PA_Data_Optional(is_orig, pkt_type, 3);
|
||||
body_meta : ASN1EncodingMeta;
|
||||
body_args : KRB_REQ_Arg[];
|
||||
};
|
||||
|
||||
type KRB_REQ_Arg = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
data : KRB_REQ_Arg_Data(seq_meta.index) &length=seq_meta.length;
|
||||
};
|
||||
|
||||
type KRB_REQ_Arg_Data(index: uint8) = case index of {
|
||||
0 -> options : KRB_KDC_Options;
|
||||
1 -> principal : KRB_Principal_Name;
|
||||
2 -> realm : ASN1OctetString;
|
||||
3 -> sname : KRB_Principal_Name;
|
||||
4 -> from : KRB_Time;
|
||||
5 -> till : KRB_Time;
|
||||
6 -> rtime : KRB_Time;
|
||||
7 -> nonce : ASN1Integer;
|
||||
8 -> etype : Array;
|
||||
9 -> addrs : KRB_Host_Addresses;
|
||||
10 -> auth_data : ASN1OctetString;
|
||||
11 -> addl_tkts : KRB_Ticket_Sequence;
|
||||
default -> unknown : bytestring &restofdata;
|
||||
};
|
||||
|
||||
type KRB_KDC_Options = record {
|
||||
meta : ASN1EncodingMeta;
|
||||
pad : uint8;
|
||||
flags : uint32;
|
||||
} &let {
|
||||
reserved : bool = (flags & 0x80000000) > 0;
|
||||
forwardable : bool = (flags & 0x40000000) > 0;
|
||||
forwarded : bool = (flags & 0x20000000) > 0;
|
||||
proxiable : bool = (flags & 0x10000000) > 0;
|
||||
proxy : bool = (flags & 0x8000000) > 0;
|
||||
allow_postdate : bool = (flags & 0x4000000) > 0;
|
||||
postdated : bool = (flags & 0x2000000) > 0;
|
||||
unused7 : bool = (flags & 0x1000000) > 0;
|
||||
renewable : bool = (flags & 0x800000) > 0;
|
||||
unused9 : bool = (flags & 0x400000) > 0;
|
||||
unused10 : bool = (flags & 0x200000) > 0;
|
||||
opt_hardware_auth : bool = (flags & 0x100000) > 0;
|
||||
unused12 : bool = (flags & 0x80000) > 0;
|
||||
unused13 : bool = (flags & 0x40000) > 0;
|
||||
# ...
|
||||
unused15 : bool = (flags & 0x10000) > 0;
|
||||
# ...
|
||||
disable_transited_check : bool = (flags & 0x10) > 0;
|
||||
renewable_ok : bool = (flags & 0x8) > 0;
|
||||
enc_tkt_in_skey : bool = (flags & 0x4) > 0;
|
||||
renew : bool = (flags & 0x2) > 0;
|
||||
validate : bool = (flags & 0x1) > 0;
|
||||
};
|
||||
|
||||
### KDC_REP
|
||||
|
||||
type KRB_KDC_REP(is_orig: bool, pkt_type: uint8) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
pvno : SequenceElement(true);
|
||||
msg_type : SequenceElement(true);
|
||||
padata : KRB_PA_Data_Optional(is_orig, pkt_type, 2);
|
||||
client_realm: ASN1OctetString &length=padata.next_meta.length;
|
||||
cname_meta : ASN1EncodingMeta;
|
||||
client_name : KRB_Principal_Name &length=cname_meta.length;
|
||||
ticket : KRB_Ticket(true);
|
||||
enc_part : KRB_Encrypted_Data_in_Seq;
|
||||
};
|
||||
|
||||
### AP_REQ
|
||||
|
||||
type KRB_AP_REQ(is_orig: bool) = record {
|
||||
string_meta : ASN1EncodingMeta;
|
||||
app_meta : ASN1EncodingMeta;
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
pvno : SequenceElement(true);
|
||||
msg_type : SequenceElement(true);
|
||||
ap_options : KRB_AP_Options;
|
||||
ticket : KRB_Ticket(true);
|
||||
enc_part : KRB_Encrypted_Data_in_Seq;
|
||||
};
|
||||
|
||||
type KRB_AP_Options = record {
|
||||
meta : SequenceElement(false);
|
||||
flags : uint32;
|
||||
: padding[1];
|
||||
} &let {
|
||||
reserved : bool = (flags & 0x80000000) > 0;
|
||||
use_session_key : bool = (flags & 0x40000000) > 0;
|
||||
mutual_required : bool = (flags & 0x20000000) > 0;
|
||||
};
|
||||
|
||||
|
||||
### AP_REP
|
||||
|
||||
type KRB_AP_REP(is_orig: bool) = record {
|
||||
pvno : SequenceElement(true);
|
||||
msg_type: SequenceElement(true);
|
||||
enc_part: KRB_Encrypted_Data_in_Seq;
|
||||
};
|
||||
|
||||
### KRB_ERROR
|
||||
|
||||
type KRB_ERROR_MSG(is_orig: bool) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
args1 : KRB_ERROR_Arg(is_orig, 0)[] &until ($element.process_in_parent);
|
||||
error_code : ASN1Integer;
|
||||
args2 : KRB_ERROR_Arg(is_orig, binary_to_int64(error_code.encoding.content))[];
|
||||
};
|
||||
|
||||
type KRB_ERROR_Arg(is_orig: bool, error_code: int64) = record {
|
||||
seq_meta: ASN1EncodingMeta;
|
||||
args : KRB_ERROR_Arg_Data(is_orig, seq_meta.index, error_code) &length=arg_length;
|
||||
} &let {
|
||||
process_in_parent : bool = seq_meta.index == 6;
|
||||
arg_length : uint64 = ( process_in_parent ? 0 : seq_meta.length);
|
||||
};
|
||||
|
||||
type KRB_ERROR_Arg_Data(is_orig: bool, index: uint8, error_code: int64) = case index of {
|
||||
0 -> pvno : ASN1Integer;
|
||||
1 -> msg_type : ASN1Integer;
|
||||
2 -> ctime : KRB_Time;
|
||||
3 -> cusec : ASN1Integer;
|
||||
4 -> stime : KRB_Time;
|
||||
5 -> susec : ASN1Integer;
|
||||
6 -> err_code : empty;
|
||||
7 -> crealm : ASN1OctetString;
|
||||
8 -> cname : KRB_Principal_Name;
|
||||
9 -> realm : ASN1OctetString;
|
||||
10 -> sname : KRB_Principal_Name;
|
||||
11 -> e_text : ASN1OctetString;
|
||||
12 -> e_data : KRB_ERROR_E_Data(is_orig, error_code);
|
||||
};
|
||||
|
||||
type KRB_ERROR_E_Data(is_orig: bool, error_code: uint64) = case ( error_code == KDC_ERR_PREAUTH_REQUIRED ) of {
|
||||
true -> padata : KRB_PA_Data_Sequence(is_orig, KRB_ERROR);
|
||||
false -> unknown : bytestring &restofdata;
|
||||
};
|
||||
|
||||
### KRB_SAFE
|
||||
|
||||
type KRB_SAFE_MSG(is_orig: bool) = record {
|
||||
pvno : SequenceElement(true);
|
||||
msg_type : SequenceElement(true);
|
||||
safe_body: KRB_SAFE_Body;
|
||||
checksum : KRB_Checksum;
|
||||
};
|
||||
|
||||
type KRB_SAFE_Body = record {
|
||||
seq_meta: ASN1EncodingMeta;
|
||||
args : KRB_SAFE_Arg[];
|
||||
};
|
||||
|
||||
type KRB_SAFE_Arg = record {
|
||||
seq_meta: ASN1EncodingMeta;
|
||||
args : KRB_SAFE_Arg_Data(seq_meta.index) &length=seq_meta.length;
|
||||
};
|
||||
|
||||
type KRB_SAFE_Arg_Data(index: uint8) = case index of {
|
||||
0 -> user_data : ASN1OctetString;
|
||||
1 -> timestamp : KRB_Time;
|
||||
2 -> usec : ASN1Integer;
|
||||
3 -> seq_number : ASN1Integer;
|
||||
4 -> sender_addr: KRB_Host_Address;
|
||||
5 -> recp_addr : KRB_Host_Address;
|
||||
};
|
||||
|
||||
### KRB_PRIV
|
||||
|
||||
type KRB_PRIV_MSG(is_orig: bool) = record {
|
||||
pvno : SequenceElement(true);
|
||||
msg_type: SequenceElement(true);
|
||||
enc_part: KRB_Encrypted_Data_in_Seq;
|
||||
};
|
||||
|
||||
### KRB_CRED
|
||||
|
||||
type KRB_CRED_MSG(is_orig: bool) = record {
|
||||
pvno : SequenceElement(true);
|
||||
msg_type : SequenceElement(true);
|
||||
tkts_meta: SequenceElement(false);
|
||||
tickets : KRB_Ticket_Sequence;
|
||||
enc_part : KRB_Encrypted_Data_in_Seq;
|
||||
};
|
171
src/analyzer/protocol/krb/krb-types.pac
Normal file
171
src/analyzer/protocol/krb/krb-types.pac
Normal file
|
@ -0,0 +1,171 @@
|
|||
# Fundamental KRB types
|
||||
|
||||
%header{
|
||||
Val* GetStringFromPrincipalName(const KRB_Principal_Name* pname);
|
||||
|
||||
VectorVal* proc_cipher_list(const Array* list);
|
||||
|
||||
VectorVal* proc_host_address_list(const KRB_Host_Addresses* list);
|
||||
RecordVal* proc_host_address(const KRB_Host_Address* addr);
|
||||
|
||||
VectorVal* proc_tickets(const KRB_Ticket_Sequence* list);
|
||||
RecordVal* proc_ticket(const KRB_Ticket* ticket);
|
||||
%}
|
||||
|
||||
%code{
|
||||
Val* GetStringFromPrincipalName(const KRB_Principal_Name* pname)
|
||||
{
|
||||
if ( pname->data()->size() == 1 )
|
||||
return bytestring_to_val(pname->data()[0][0]->encoding()->content());
|
||||
if ( pname->data()->size() == 2 )
|
||||
return new StringVal(fmt("%s/%s", (char *) pname->data()[0][0]->encoding()->content().begin(), (char *)pname->data()[0][1]->encoding()->content().begin()));
|
||||
|
||||
return new StringVal("unknown");
|
||||
}
|
||||
|
||||
VectorVal* proc_cipher_list(const Array* list)
|
||||
{
|
||||
VectorVal* ciphers = new VectorVal(internal_type("index_vec")->AsVectorType());
|
||||
for ( uint i = 0; i < list->data()->size(); ++i )
|
||||
ciphers->Assign(ciphers->Size(), asn1_integer_to_val((*list->data())[i], TYPE_COUNT));
|
||||
return ciphers;
|
||||
}
|
||||
|
||||
VectorVal* proc_host_address_list(const KRB_Host_Addresses* list)
|
||||
{
|
||||
VectorVal* addrs = new VectorVal(internal_type("KRB::Host_Address_Vector")->AsVectorType());
|
||||
|
||||
for ( uint i = 0; i < list->addresses()->size(); ++i )
|
||||
{
|
||||
addrs->Assign(addrs->Size(), proc_host_address((*list->addresses())[i]));
|
||||
}
|
||||
|
||||
return addrs;
|
||||
}
|
||||
|
||||
RecordVal* proc_host_address(const KRB_Host_Address* addr)
|
||||
{
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::Host_Address);
|
||||
|
||||
switch ( binary_to_int64(addr->addr_type()->encoding()->content()) )
|
||||
{
|
||||
case 2:
|
||||
rv->Assign(0, new AddrVal(IPAddr(IPv4,
|
||||
(const uint32_t*) c_str(addr->address()->data()->content()),
|
||||
IPAddr::Network)));
|
||||
break;
|
||||
case 24:
|
||||
rv->Assign(0, new AddrVal(IPAddr(IPv6,
|
||||
(const uint32_t*) c_str(addr->address()->data()->content()),
|
||||
IPAddr::Network)));
|
||||
break;
|
||||
case 20:
|
||||
rv->Assign(1, bytestring_to_val(addr->address()->data()->content()));
|
||||
break;
|
||||
default:
|
||||
RecordVal* unk = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
unk->Assign(0, asn1_integer_to_val(addr->addr_type(), TYPE_COUNT));
|
||||
unk->Assign(1, bytestring_to_val(addr->address()->data()->content()));
|
||||
rv->Assign(2, unk);
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
VectorVal* proc_tickets(const KRB_Ticket_Sequence* list)
|
||||
{
|
||||
VectorVal* tickets = new VectorVal(internal_type("KRB::Ticket_Vector")->AsVectorType());
|
||||
for ( uint i = 0; i < list->tickets()->size(); ++i )
|
||||
{
|
||||
KRB_Ticket* element = (*list->tickets())[i];
|
||||
tickets->Assign(tickets->Size(), proc_ticket(element));
|
||||
}
|
||||
|
||||
return tickets;
|
||||
}
|
||||
|
||||
RecordVal* proc_ticket(const KRB_Ticket* ticket)
|
||||
{
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::Ticket);
|
||||
|
||||
rv->Assign(0, asn1_integer_to_val(ticket->tkt_vno()->data(), TYPE_COUNT));
|
||||
rv->Assign(1, bytestring_to_val(ticket->realm()->data()->content()));
|
||||
rv->Assign(2, GetStringFromPrincipalName(ticket->sname()));
|
||||
rv->Assign(3, asn1_integer_to_val(ticket->enc_part()->data()->etype()->data(), TYPE_COUNT));
|
||||
|
||||
return rv;
|
||||
}
|
||||
%}
|
||||
|
||||
type KRB_Principal_Name = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
name_meta : ASN1EncodingMeta;
|
||||
name_type : ASN1Integer;
|
||||
seq_meta_1: ASN1EncodingMeta;
|
||||
seq_meta_2: ASN1EncodingMeta;
|
||||
data : ASN1OctetString[];
|
||||
};
|
||||
|
||||
type KRB_Time = record {
|
||||
meta: ASN1EncodingMeta;
|
||||
time: bytestring &restofdata;
|
||||
};
|
||||
|
||||
type KRB_Host_Addresses = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
addresses: KRB_Host_Address[];
|
||||
};
|
||||
|
||||
type KRB_Host_Address = record {
|
||||
addr_type_meta : SequenceElement(false);
|
||||
addr_type : ASN1Integer;
|
||||
address : SequenceElement(true);
|
||||
};
|
||||
|
||||
type KRB_Ticket(in_sequence: bool) = record {
|
||||
have_seq : case in_sequence of {
|
||||
true -> meta: ASN1EncodingMeta;
|
||||
false -> none: empty;
|
||||
};
|
||||
app_meta : ASN1EncodingMeta;
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
tkt_vno : SequenceElement(true);
|
||||
realm : SequenceElement(true);
|
||||
sname_meta: ASN1EncodingMeta;
|
||||
sname : KRB_Principal_Name &length=sname_meta.length;
|
||||
enc_part : KRB_Encrypted_Data_in_Seq;
|
||||
};
|
||||
|
||||
type KRB_Ticket_Sequence = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
tickets : KRB_Ticket(false)[] &length=seq_meta.length;
|
||||
};
|
||||
|
||||
type KRB_Encrypted_Data_in_Seq = record {
|
||||
index_meta : ASN1EncodingMeta;
|
||||
data : KRB_Encrypted_Data &length=index_meta.length;
|
||||
};
|
||||
|
||||
type KRB_Encrypted_Data = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
etype : SequenceElement(true);
|
||||
kvno_meta : ASN1EncodingMeta;
|
||||
case_kvno : case have_kvno of {
|
||||
true -> kvno : ASN1Integer;
|
||||
false -> none : empty;
|
||||
};
|
||||
grab_next_meta : case have_kvno of {
|
||||
true -> next_meta: ASN1EncodingMeta;
|
||||
false -> none_meta: empty;
|
||||
};
|
||||
ciphertext : bytestring &length=have_kvno ? next_meta.length : kvno_meta.length;
|
||||
} &let {
|
||||
have_kvno : bool = kvno_meta.index == 1;
|
||||
};
|
||||
|
||||
type KRB_Checksum = record {
|
||||
checksum_type: SequenceElement(true);
|
||||
checksum : SequenceElement(true);
|
||||
};
|
||||
|
25
src/analyzer/protocol/krb/krb.pac
Normal file
25
src/analyzer/protocol/krb/krb.pac
Normal file
|
@ -0,0 +1,25 @@
|
|||
%include binpac.pac
|
||||
%include bro.pac
|
||||
|
||||
%extern{
|
||||
#include "types.bif.h"
|
||||
#include "events.bif.h"
|
||||
%}
|
||||
|
||||
analyzer KRB withcontext {
|
||||
connection: KRB_Conn;
|
||||
flow: KRB_Flow;
|
||||
};
|
||||
|
||||
connection KRB_Conn(bro_analyzer: BroAnalyzer) {
|
||||
upflow = KRB_Flow(true);
|
||||
downflow = KRB_Flow(false);
|
||||
};
|
||||
|
||||
%include krb-protocol.pac
|
||||
|
||||
flow KRB_Flow(is_orig: bool) {
|
||||
datagram = KRB_PDU(is_orig) withcontext(connection, this);
|
||||
};
|
||||
|
||||
%include krb-analyzer.pac
|
25
src/analyzer/protocol/krb/krb_TCP.pac
Normal file
25
src/analyzer/protocol/krb/krb_TCP.pac
Normal file
|
@ -0,0 +1,25 @@
|
|||
%include binpac.pac
|
||||
%include bro.pac
|
||||
|
||||
%extern{
|
||||
#include "types.bif.h"
|
||||
#include "events.bif.h"
|
||||
%}
|
||||
|
||||
analyzer KRB_TCP withcontext {
|
||||
connection: KRB_Conn;
|
||||
flow: KRB_Flow;
|
||||
};
|
||||
|
||||
connection KRB_Conn(bro_analyzer: BroAnalyzer) {
|
||||
upflow = KRB_Flow(true);
|
||||
downflow = KRB_Flow(false);
|
||||
};
|
||||
|
||||
%include krb-protocol.pac
|
||||
|
||||
flow KRB_Flow(is_orig: bool) {
|
||||
flowunit = KRB_PDU_TCP(is_orig) withcontext(connection, this);
|
||||
};
|
||||
|
||||
%include krb-analyzer.pac
|
17
src/analyzer/protocol/krb/types.bif
Normal file
17
src/analyzer/protocol/krb/types.bif
Normal file
|
@ -0,0 +1,17 @@
|
|||
module KRB;
|
||||
|
||||
type Error_Msg: record;
|
||||
type SAFE_Msg: record;
|
||||
|
||||
type KDC_Options: record;
|
||||
type AP_Options: record;
|
||||
type Type_Value: record;
|
||||
type Ticket: record;
|
||||
type Ticket_Vector: vector;
|
||||
type Host_Address: record;
|
||||
|
||||
type KDC_Request: record;
|
||||
|
||||
type KDC_Response: record;
|
||||
|
||||
module GLOBAL;
|
|
@ -1,16 +0,0 @@
|
|||
|
||||
# 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()
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
## 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%);
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
# Code written by Bernhard Ager (2007).
|
||||
|
||||
analyzer NetFlow withcontext {
|
||||
analyzer: NetFlow_Analyzer;
|
||||
flow: NetFlow_Flow;
|
||||
}
|
||||
|
||||
analyzer NetFlow_Analyzer {
|
||||
downflow = NetFlow_Flow;
|
||||
upflow = NetFlow_Flow;
|
||||
};
|
||||
|
||||
flow NetFlow_Flow {
|
||||
datagram = NetFlowPacket withcontext(connection, this);
|
||||
|
||||
%member{
|
||||
RecordType* nf_v5_header_type;
|
||||
RecordType* nf_v5_record_type;
|
||||
RecordType* nfheader_id_type;
|
||||
char* identifier;
|
||||
uint32 exporter_ip;
|
||||
uint32 uptime;
|
||||
double export_time;
|
||||
bro_uint_t pdu_id;
|
||||
%}
|
||||
|
||||
%init{
|
||||
nf_v5_header_type =
|
||||
internal_type("nf_v5_header")->AsRecordType();
|
||||
nf_v5_record_type =
|
||||
internal_type("nf_v5_record")->AsRecordType();
|
||||
nfheader_id_type =
|
||||
internal_type("nfheader_id")->AsRecordType();
|
||||
identifier = NULL;
|
||||
exporter_ip = 0;
|
||||
uptime = 0;
|
||||
export_time = 0;
|
||||
pdu_id = 0;
|
||||
%}
|
||||
|
||||
# %cleanup does not only put the cleanup code into the destructor,
|
||||
# but also at the end of the catch clause in NewData(). This is
|
||||
# different from the documentation at
|
||||
# http://www.bro.org/wiki/index.php/BinPAC_Userguide#.25cleanup.7B....25.7D
|
||||
#
|
||||
# Unfortunately this means that we cannot clean up the identifier
|
||||
# string. Note that IOSource destructors seemingly are never
|
||||
# called anyway.
|
||||
#
|
||||
# %cleanup{
|
||||
# delete[] identifier;
|
||||
# %}
|
||||
|
||||
function set_exporter_ip(exporter_ip: uint32): bool
|
||||
%{
|
||||
this->exporter_ip = exporter_ip;
|
||||
return true;
|
||||
%}
|
||||
|
||||
function set_identifier(idf: const_charptr): bool
|
||||
%{
|
||||
if ( identifier )
|
||||
delete[] identifier;
|
||||
identifier = new char[strlen(idf) + 1];
|
||||
strcpy(identifier, idf);
|
||||
return true;
|
||||
%}
|
||||
|
||||
function deliver_v5_header(count: uint16, sysuptime: uint32,
|
||||
unix_secs: uint32, unix_nsecs: uint32,
|
||||
flow_seq: uint32, eng_type: uint8,
|
||||
eng_id: uint8, sample_int: uint16): bool
|
||||
%{
|
||||
uptime = sysuptime;
|
||||
export_time = unix_secs + unix_nsecs / 1e9;
|
||||
++pdu_id;
|
||||
|
||||
if ( ! ::netflow_v5_header )
|
||||
return false;
|
||||
|
||||
RecordVal* nfheader = new RecordVal(nfheader_id_type);
|
||||
nfheader->Assign(0, new StringVal(identifier));
|
||||
nfheader->Assign(1, new Val(pdu_id, TYPE_COUNT));
|
||||
|
||||
RecordVal* v5header = new RecordVal(nf_v5_header_type);
|
||||
v5header->Assign(0, nfheader);
|
||||
v5header->Assign(1, new Val(count, TYPE_COUNT));
|
||||
v5header->Assign(2, new IntervalVal(sysuptime, Milliseconds));
|
||||
v5header->Assign(3, new Val(export_time, TYPE_TIME));
|
||||
v5header->Assign(4, new Val(flow_seq, TYPE_COUNT));
|
||||
v5header->Assign(5, new Val(eng_type, TYPE_COUNT));
|
||||
v5header->Assign(6, new Val(eng_id, TYPE_COUNT));
|
||||
v5header->Assign(7, new Val(sample_int, TYPE_COUNT));
|
||||
v5header->Assign(8, new AddrVal(exporter_ip));
|
||||
|
||||
val_list* vl = new val_list;
|
||||
vl->append(v5header);
|
||||
mgr.QueueEvent(netflow_v5_header, vl);
|
||||
|
||||
return true;
|
||||
%}
|
||||
|
||||
function deliver_v5_record(srcaddr: uint32, dstaddr: uint32,
|
||||
nexthop: uint32, input: uint16, output: uint16,
|
||||
dPkts: uint32, dOctets: uint32,
|
||||
first: uint32, last: uint32,
|
||||
srcport: uint16, dstport: uint16,
|
||||
tcp_flags: uint8, prot: uint8, tos: uint8,
|
||||
src_as: uint16, dst_as: uint16,
|
||||
src_mask: uint8, dst_mask: uint8): bool
|
||||
%{
|
||||
if ( ! ::netflow_v5_record )
|
||||
return false;
|
||||
|
||||
TransportProto proto = TRANSPORT_UNKNOWN;
|
||||
switch ( prot ) {
|
||||
case 1: proto = TRANSPORT_ICMP; break;
|
||||
case 6: proto = TRANSPORT_TCP; break;
|
||||
case 17: proto = TRANSPORT_UDP; break;
|
||||
}
|
||||
|
||||
RecordVal* connid = new RecordVal(conn_id);
|
||||
connid->Assign(0, new AddrVal(htonl(srcaddr)));
|
||||
connid->Assign(1, new PortVal(srcport, proto));
|
||||
connid->Assign(2, new AddrVal(htonl(dstaddr)));
|
||||
connid->Assign(3, new PortVal(dstport, proto));
|
||||
|
||||
RecordVal* nfheader = new RecordVal(nfheader_id_type);
|
||||
nfheader->Assign(0, new StringVal(identifier));
|
||||
nfheader->Assign(1, new Val(pdu_id, TYPE_COUNT));
|
||||
|
||||
RecordVal* v5record = new RecordVal(nf_v5_record_type);
|
||||
v5record->Assign(0, nfheader);
|
||||
v5record->Assign(1, connid);
|
||||
v5record->Assign(2, new AddrVal(htonl(nexthop)));
|
||||
v5record->Assign(3, new Val(input, TYPE_COUNT));
|
||||
v5record->Assign(4, new Val(output, TYPE_COUNT));
|
||||
v5record->Assign(5, new Val(dPkts, TYPE_COUNT));
|
||||
v5record->Assign(6, new Val(dOctets, TYPE_COUNT));
|
||||
|
||||
// Overflows are handled correctly by using 32 bit
|
||||
// unsigned integer arithmetic.
|
||||
double c_first = export_time - (uptime - first) * Milliseconds;
|
||||
double c_last = export_time - (uptime - last) * Milliseconds;
|
||||
v5record->Assign(7, new Val(c_first, TYPE_TIME));
|
||||
v5record->Assign(8, new Val(c_last, TYPE_TIME));
|
||||
|
||||
v5record->Assign(9,
|
||||
new Val((tcp_flags & TH_FIN) != 0, TYPE_BOOL));
|
||||
v5record->Assign(10,
|
||||
new Val((tcp_flags & TH_SYN) != 0, TYPE_BOOL));
|
||||
v5record->Assign(11,
|
||||
new Val((tcp_flags & TH_RST) != 0, TYPE_BOOL));
|
||||
v5record->Assign(12,
|
||||
new Val((tcp_flags & TH_PUSH) != 0, TYPE_BOOL));
|
||||
v5record->Assign(13,
|
||||
new Val((tcp_flags & TH_ACK) != 0, TYPE_BOOL));
|
||||
v5record->Assign(14,
|
||||
new Val((tcp_flags & TH_URG) != 0, TYPE_BOOL));
|
||||
|
||||
v5record->Assign(15, new Val(prot, TYPE_COUNT));
|
||||
v5record->Assign(16, new Val(tos, TYPE_COUNT));
|
||||
v5record->Assign(17, new Val(src_as, TYPE_COUNT));
|
||||
v5record->Assign(18, new Val(dst_as, TYPE_COUNT));
|
||||
v5record->Assign(19, new Val(src_mask, TYPE_COUNT));
|
||||
v5record->Assign(20, new Val(dst_mask, TYPE_COUNT));
|
||||
|
||||
val_list* vl = new val_list;
|
||||
vl->append(v5record);
|
||||
mgr.QueueEvent(netflow_v5_record, vl);
|
||||
|
||||
return true;
|
||||
%}
|
||||
};
|
|
@ -1,89 +0,0 @@
|
|||
# Code written by Bernhard Ager (2007).
|
||||
|
||||
type NetFlowPacket = record {
|
||||
# Count and version are the first two fields, at least for
|
||||
# versions 1, 5, 7, 8 and 9.
|
||||
version: uint16;
|
||||
|
||||
# This does not generate any code in current binpac.
|
||||
count: uint16 &check(count <= 30);
|
||||
|
||||
header: NFHeader(version, count);
|
||||
records: NFRecord(version)[count];
|
||||
} &byteorder = bigendian;
|
||||
|
||||
type NFHeader(version: uint16, count: uint16) = case version of {
|
||||
5 -> v5header: NFv5HeaderRest(count);
|
||||
9 -> v9header: NFv9HeaderRest(count);
|
||||
# default -> string: bytestring &restofdata &transient;
|
||||
};
|
||||
|
||||
type NFv5HeaderRest(count: uint16) = record {
|
||||
sysuptime: uint32;
|
||||
unix_secs: uint32;
|
||||
unix_nsecs: uint32;
|
||||
flow_seq: uint32;
|
||||
eng_type: uint8;
|
||||
eng_id: uint8;
|
||||
sample_int: uint16;
|
||||
} &let {
|
||||
delivered: bool =
|
||||
$context.flow.deliver_v5_header(count, sysuptime,
|
||||
unix_secs, unix_nsecs,
|
||||
flow_seq, eng_type,
|
||||
eng_id, sample_int);
|
||||
};
|
||||
|
||||
type NFv9HeaderRest(count: uint16) = record {
|
||||
sysuptime: uint32;
|
||||
unix_secs: uint32;
|
||||
pack_seq: uint32;
|
||||
src_id: uint32;
|
||||
};
|
||||
|
||||
# We only handle version 5 and 9. Others will throw a parsing exception.
|
||||
type NFRecord(nf_version: uint32) = case nf_version of {
|
||||
5 -> v5: NFv5Record;
|
||||
9 -> v9: NFv9Record;
|
||||
};
|
||||
|
||||
type NFv5Record = record {
|
||||
srcaddr: uint32;
|
||||
dstaddr: uint32;
|
||||
nexthop: uint32;
|
||||
input: uint16;
|
||||
output: uint16;
|
||||
dPkts: uint32;
|
||||
dOctets: uint32;
|
||||
first: uint32;
|
||||
last: uint32;
|
||||
srcport: uint16;
|
||||
dstport: uint16;
|
||||
: uint8; # PAD1
|
||||
tcp_flags: uint8;
|
||||
prot: uint8;
|
||||
tos: uint8;
|
||||
src_as: uint16;
|
||||
dst_as: uint16;
|
||||
src_mask: uint8;
|
||||
dst_mask: uint8;
|
||||
: uint16; # PAD2
|
||||
} &let {
|
||||
delivered: bool =
|
||||
$context.flow.deliver_v5_record(srcaddr, dstaddr,
|
||||
nexthop, input, output,
|
||||
dPkts, dOctets, first,
|
||||
last, srcport, dstport,
|
||||
tcp_flags, prot, tos,
|
||||
src_as, dst_as,
|
||||
src_mask, dst_mask);
|
||||
};
|
||||
|
||||
# Works for both template and data flow sets. Data parsing will have
|
||||
# to be done externally - no event generation yet. We need sample
|
||||
# flow data to implement that.
|
||||
type NFv9Record = record {
|
||||
flowset_id: uint32;
|
||||
length: uint32;
|
||||
data: bytestring &length = length - 8;
|
||||
};
|
|
@ -1,13 +0,0 @@
|
|||
# Code written by Bernhard Ager (2007).
|
||||
|
||||
%extern{
|
||||
#include "net_util.h"
|
||||
#include "Event.h"
|
||||
extern RecordType* conn_id;
|
||||
|
||||
#include "events.bif.h"
|
||||
%}
|
||||
|
||||
%include bro.pac
|
||||
%include netflow-analyzer.pac
|
||||
%include netflow-protocol.pac
|
|
@ -6,5 +6,5 @@ bro_plugin_begin(Bro RDP)
|
|||
bro_plugin_cc(RDP.cc Plugin.cc)
|
||||
bro_plugin_bif(events.bif)
|
||||
bro_plugin_bif(types.bif)
|
||||
bro_plugin_pac(rdp.pac rdp-analyzer.pac rdp-protocol.pac)
|
||||
bro_plugin_pac(rdp.pac rdp-analyzer.pac rdp-protocol.pac ../asn1/asn1.pac)
|
||||
bro_plugin_end()
|
||||
|
|
|
@ -12,16 +12,23 @@ refine flow RDP_Flow += {
|
|||
size_t widesize = utf16.length();
|
||||
|
||||
size_t utf8size = 3 * widesize + 1;
|
||||
|
||||
if ( utf8size > resultstring.max_size() )
|
||||
{
|
||||
connection()->bro_analyzer()->Weird("excessive_utf16_length");
|
||||
return new StringVal("");
|
||||
}
|
||||
|
||||
resultstring.resize(utf8size, '\0');
|
||||
const UTF16* sourcestart = reinterpret_cast<const UTF16*>(utf16.begin());
|
||||
const UTF16* sourceend = sourcestart + widesize;
|
||||
UTF8* targetstart = reinterpret_cast<UTF8*>(&resultstring[0]);
|
||||
UTF8* targetend = targetstart + utf8size;
|
||||
|
||||
ConversionResult res = ConvertUTF16toUTF8(&sourcestart,
|
||||
ConversionResult res = ConvertUTF16toUTF8(&sourcestart,
|
||||
sourceend,
|
||||
&targetstart,
|
||||
targetend,
|
||||
&targetstart,
|
||||
targetend,
|
||||
lenientConversion);
|
||||
if ( res != conversionOK )
|
||||
{
|
||||
|
@ -42,7 +49,7 @@ refine flow RDP_Flow += {
|
|||
connection()->bro_analyzer()->Conn(),
|
||||
bytestring_to_val(${cr.cookie_value}));
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
%}
|
||||
|
||||
|
@ -54,7 +61,7 @@ refine flow RDP_Flow += {
|
|||
connection()->bro_analyzer()->Conn(),
|
||||
${nr.selected_protocol});
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
%}
|
||||
|
||||
|
@ -168,9 +175,9 @@ refine flow RDP_Flow += {
|
|||
string file_id = file_mgr->HashHandle(file_handle.Description());
|
||||
|
||||
file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()),
|
||||
cert.length(),
|
||||
cert.length(),
|
||||
connection()->bro_analyzer()->GetAnalyzerTag(),
|
||||
connection()->bro_analyzer()->Conn(),
|
||||
connection()->bro_analyzer()->Conn(),
|
||||
false, // It seems there are only server certs?
|
||||
file_id);
|
||||
file_mgr->EndOfFile(file_id);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
%include ../asn1/asn1.pac
|
||||
|
||||
type TPKT(is_orig: bool) = record {
|
||||
version: uint8;
|
||||
|
@ -5,7 +6,7 @@ type TPKT(is_orig: bool) = record {
|
|||
tpkt_len: uint16;
|
||||
|
||||
# These data structures are merged together into TPKT
|
||||
# because there are packets that report incorrect
|
||||
# because there are packets that report incorrect
|
||||
# lengths in the tpkt length field. No clue why.
|
||||
|
||||
cotp: COTP(this);
|
||||
|
@ -129,7 +130,7 @@ type RDP_Negotiation_Response = record {
|
|||
length: uint16; # must be set to 8
|
||||
selected_protocol: uint32;
|
||||
} &let {
|
||||
# Seems to be SSL encrypted (maybe CredSSP also?)
|
||||
# Seems to be SSL encrypted (maybe CredSSP also?)
|
||||
# after this message if the selected_protocol is > 0.
|
||||
enc_ssl: bool = $context.connection.go_encrypted(selected_protocol) &if(selected_protocol > 0);
|
||||
} &byteorder=littleendian;
|
||||
|
@ -204,7 +205,7 @@ type Client_Core_Data = record {
|
|||
supported_color_depths: uint16;
|
||||
early_capability_flags: uint16;
|
||||
dig_product_id: bytestring &length=64;
|
||||
# There are more optional fields here but they are
|
||||
# There are more optional fields here but they are
|
||||
# annoying to optionally parse in binpac.
|
||||
# Documented here: https://msdn.microsoft.com/en-us/library/cc240510.aspx
|
||||
} &let {
|
||||
|
@ -280,7 +281,7 @@ type Server_Security_Data = record {
|
|||
server_random: bytestring &length=server_random_length;
|
||||
server_certificate: Server_Certificate &length=server_cert_length;
|
||||
} &let {
|
||||
# Seems to be encrypted after this message if
|
||||
# Seems to be encrypted after this message if
|
||||
# encryption level is >0
|
||||
# 0 means RDP encryption.
|
||||
enc: bool = $context.connection.go_encrypted(0) &if(encryption_method > 0 && encryption_level > 0);
|
||||
|
@ -326,64 +327,6 @@ type X509_Cert_Data = record {
|
|||
cert: bytestring &length=cert_len;
|
||||
} &byteorder=littleendian;
|
||||
|
||||
######################################################################
|
||||
# ASN.1 Encodings
|
||||
######################################################################
|
||||
|
||||
type ASN1Encoding = record {
|
||||
meta: ASN1EncodingMeta;
|
||||
content: bytestring &length = meta.length;
|
||||
};
|
||||
|
||||
type ASN1EncodingMeta = record {
|
||||
tag: uint8;
|
||||
len: uint8;
|
||||
more_len: bytestring &length = long_len ? len & 0x7f : 0;
|
||||
} &let {
|
||||
long_len: bool = (len & 0x80) > 0;
|
||||
length: uint64 = long_len ? binary_to_int64(more_len) : len & 0x7f;
|
||||
};
|
||||
|
||||
type ASN1SequenceMeta = record {
|
||||
encoding: ASN1EncodingMeta;
|
||||
};
|
||||
|
||||
type ASN1Integer = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type ASN1OctetString = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type ASN1ObjectIdentifier = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type ASN1Boolean = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type ASN1Enumerated = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
######################################################################
|
||||
# ASN.1 Conversion Functions
|
||||
######################################################################
|
||||
|
||||
function binary_to_int64(bs: bytestring): int64
|
||||
%{
|
||||
int64 rval = 0;
|
||||
for ( int i = 0; i < bs.length(); ++i )
|
||||
{
|
||||
uint64 byte = bs[i];
|
||||
rval |= byte << (8 * (bs.length() - (i + 1)));
|
||||
}
|
||||
|
||||
return rval;
|
||||
%}
|
||||
|
||||
refine connection RDP_Conn += {
|
||||
|
||||
%member{
|
||||
|
@ -420,4 +363,4 @@ refine connection RDP_Conn += {
|
|||
%{
|
||||
return encryption_method_;
|
||||
%}
|
||||
};
|
||||
};
|
||||
|
|
14
src/analyzer/protocol/sip/CMakeLists.txt
Normal file
14
src/analyzer/protocol/sip/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
include(BroPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
bro_plugin_begin(Bro SIP)
|
||||
bro_plugin_cc(Plugin.cc)
|
||||
bro_plugin_cc(SIP.cc)
|
||||
bro_plugin_cc(SIP_TCP.cc)
|
||||
bro_plugin_bif(events.bif)
|
||||
bro_plugin_pac(sip.pac sip-analyzer.pac sip-protocol.pac)
|
||||
bro_plugin_pac(sip_TCP.pac sip-protocol.pac sip-analyzer.pac)
|
||||
bro_plugin_end()
|
||||
|
29
src/analyzer/protocol/sip/Plugin.cc
Normal file
29
src/analyzer/protocol/sip/Plugin.cc
Normal file
|
@ -0,0 +1,29 @@
|
|||
// See the file in the main distribution directory for copyright.
|
||||
|
||||
|
||||
#include "plugin/Plugin.h"
|
||||
|
||||
#include "SIP.h"
|
||||
#include "SIP_TCP.h"
|
||||
|
||||
namespace plugin {
|
||||
namespace Bro_SIP {
|
||||
|
||||
class Plugin : public plugin::Plugin {
|
||||
public:
|
||||
plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new ::analyzer::Component("SIP", ::analyzer::SIP::SIP_Analyzer::Instantiate));
|
||||
|
||||
// We don't fully support SIP-over-TCP yet, so we don't activate this component.
|
||||
// AddComponent(new ::analyzer::Component("SIP_TCP", ::analyzer::sip_tcp::SIP_Analyzer::Instantiate));
|
||||
|
||||
plugin::Configuration config;
|
||||
config.name = "Bro::SIP";
|
||||
config.description = "SIP analyzer UDP-only";
|
||||
return config;
|
||||
}
|
||||
} plugin;
|
||||
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue