mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Merge branch 'topic/script-reference' of ssh://git.bro-ids.org/bro into topic/script-reference
This commit is contained in:
commit
a8f9af3531
68 changed files with 1823 additions and 1388 deletions
44
CHANGES
44
CHANGES
|
@ -1,4 +1,48 @@
|
||||||
|
|
||||||
|
2.0-beta-177 | 2012-01-05 15:01:07 -0800
|
||||||
|
|
||||||
|
* Replace the --snaplen/-l command line option with a
|
||||||
|
scripting-layer option called "snaplen" (which can also be
|
||||||
|
redefined on the command line, e.g. `bro -i eth0 snaplen=65535`).
|
||||||
|
|
||||||
|
* Reduce snaplen default from 65535 to old default of 8192. Fixes
|
||||||
|
#720. (Jon Siwek)
|
||||||
|
|
||||||
|
2.0-beta-174 | 2012-01-04 12:47:10 -0800
|
||||||
|
|
||||||
|
* SSL improvements. (Seth Hall)
|
||||||
|
|
||||||
|
- Added the ssl_session_ticket_handshake event back.
|
||||||
|
|
||||||
|
- Fixed a few bugs.
|
||||||
|
|
||||||
|
- Removed the SSLv2.cc file since it's not used.
|
||||||
|
|
||||||
|
2.0-beta-169 | 2012-01-04 12:44:39 -0800
|
||||||
|
|
||||||
|
* Tuning the pretty-printed alarm mails, which now include the
|
||||||
|
covered time range into the subject. (Robin Sommer)
|
||||||
|
|
||||||
|
* Adding top-level "test" target to Makefile. (Robin Sommer)
|
||||||
|
|
||||||
|
* Adding SWIG as dependency to INSTALL. (Robin Sommer)
|
||||||
|
|
||||||
|
2.0-beta-155 | 2012-01-03 15:42:32 -0800
|
||||||
|
|
||||||
|
* Remove dead code related to record type inheritance. (Jon Siwek)
|
||||||
|
|
||||||
|
2.0-beta-152 | 2012-01-03 14:51:34 -0800
|
||||||
|
|
||||||
|
* Notices now record the transport-layer protocol. (Bernhard Amann)
|
||||||
|
|
||||||
|
2.0-beta-150 | 2012-01-03 14:42:45 -0800
|
||||||
|
|
||||||
|
* CMake 2.6 top-level 'install' target compat. Fixes #729. (Jon Siwek)
|
||||||
|
|
||||||
|
* Minor fixes to test process. Addresses #298.
|
||||||
|
|
||||||
|
* Increase timeout interval of communication-related btests. (Jon Siwek)
|
||||||
|
|
||||||
2.0-beta-145 | 2011-12-19 11:37:15 -0800
|
2.0-beta-145 | 2011-12-19 11:37:15 -0800
|
||||||
|
|
||||||
* Empty fields are now logged as "(empty)" by default. (Robin
|
* Empty fields are now logged as "(empty)" by default. (Robin
|
||||||
|
|
2
COPYING
2
COPYING
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 1995-2011, The Regents of the University of California
|
Copyright (c) 1995-2012, The Regents of the University of California
|
||||||
through the Lawrence Berkeley National Laboratory and the
|
through the Lawrence Berkeley National Laboratory and the
|
||||||
International Computer Science Institute. All rights reserved.
|
International Computer Science Institute. All rights reserved.
|
||||||
|
|
||||||
|
|
13
INSTALL
13
INSTALL
|
@ -14,10 +14,11 @@ before you begin:
|
||||||
|
|
||||||
* OpenSSL (headers and libraries) http://www.openssl.org
|
* OpenSSL (headers and libraries) http://www.openssl.org
|
||||||
|
|
||||||
* Libmagic For identifying file types (e.g., in FTP transfers).
|
* SWIG http://www.swig.org
|
||||||
|
|
||||||
* Libz For decompressing HTTP bodies by the HTTP analyzer, and for
|
* Libmagic
|
||||||
compressed Bro-to-Bro communication.
|
|
||||||
|
* Libz
|
||||||
|
|
||||||
Bro can make uses of some optional libraries if they are found at
|
Bro can make uses of some optional libraries if they are found at
|
||||||
installation time:
|
installation time:
|
||||||
|
@ -27,11 +28,13 @@ installation time:
|
||||||
Bro also needs the following tools, but on most systems they will
|
Bro also needs the following tools, but on most systems they will
|
||||||
already come preinstalled:
|
already come preinstalled:
|
||||||
|
|
||||||
|
* Bash (For Bro Control).
|
||||||
* BIND8 (headers and libraries)
|
* BIND8 (headers and libraries)
|
||||||
* Bison (GNU Parser Generator)
|
* Bison (GNU Parser Generator)
|
||||||
* Flex (Fast Lexical Analyzer)
|
* Flex (Fast Lexical Analyzer)
|
||||||
* Perl (Used only during the Bro build process)
|
* Perl (Used only during the Bro build process)
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
|
@ -69,8 +72,8 @@ Running Bro
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Bro is a complex program and it takes a bit of time to get familiar
|
Bro is a complex program and it takes a bit of time to get familiar
|
||||||
with it. A good place for newcomers to start is the
|
with it. A good place for newcomers to start is the Quickstart Guide
|
||||||
:doc:`quick start guide <quickstart>`.
|
at http://www.bro-ids.org/documentation/quickstart.bro.html.
|
||||||
|
|
||||||
For developers that wish to run Bro directly from the ``build/``
|
For developers that wish to run Bro directly from the ``build/``
|
||||||
directory (i.e., without performing ``make install``), they will have
|
directory (i.e., without performing ``make install``), they will have
|
||||||
|
|
5
Makefile
5
Makefile
|
@ -14,7 +14,7 @@ HAVE_MODULES=git submodule | grep -v cmake >/dev/null
|
||||||
all: configured
|
all: configured
|
||||||
$(MAKE) -C $(BUILD) $@
|
$(MAKE) -C $(BUILD) $@
|
||||||
|
|
||||||
install: configured
|
install: configured all
|
||||||
$(MAKE) -C $(BUILD) $@
|
$(MAKE) -C $(BUILD) $@
|
||||||
|
|
||||||
install-aux: configured
|
install-aux: configured
|
||||||
|
@ -60,6 +60,9 @@ bindist:
|
||||||
distclean:
|
distclean:
|
||||||
rm -rf $(BUILD)
|
rm -rf $(BUILD)
|
||||||
|
|
||||||
|
test:
|
||||||
|
@(cd testing && make )
|
||||||
|
|
||||||
configured:
|
configured:
|
||||||
@test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 )
|
@test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 )
|
||||||
@test -e $(BUILD)/Makefile || ( echo "Error: No build/Makefile found. Did you run configure?" && exit 1 )
|
@test -e $(BUILD)/Makefile || ( echo "Error: No build/Makefile found. Did you run configure?" && exit 1 )
|
||||||
|
|
51
NEWS
Normal file
51
NEWS
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
Release Notes
|
||||||
|
=============
|
||||||
|
|
||||||
|
This document summarizes the most important changes in the current Bro
|
||||||
|
release. For a complete list of changes, see the ``CHANGES`` file.
|
||||||
|
|
||||||
|
Bro 2.0
|
||||||
|
-------
|
||||||
|
|
||||||
|
As the version number jump suggests, Bro 2.0 is a major upgrade and
|
||||||
|
lots of things have changed. We have assembled a separate upprade
|
||||||
|
guide with the most important changes compared to Bro 1.5 at
|
||||||
|
http://www.bro-ids.org/documentation/upgrade.bro.html. You can find
|
||||||
|
the offline version of that document in ``doc/upgrade.rst.``.
|
||||||
|
|
||||||
|
Compared to the earlier 2.0 Beta version, the major changes in the
|
||||||
|
final release are:
|
||||||
|
|
||||||
|
* The default scripts now come with complete reference
|
||||||
|
documentation. See
|
||||||
|
http://www.bro-ids.org/documentation/index.html.
|
||||||
|
|
||||||
|
* libz and libmagic are now required dependencies.
|
||||||
|
|
||||||
|
* Reduced snaplen default from 65535 to old default of 8192. The
|
||||||
|
large value was introducing performance problems on many
|
||||||
|
systems.
|
||||||
|
|
||||||
|
* Replaced the --snaplen/-l command line option with a
|
||||||
|
scripting-layer option called "snaplen". The new option can also
|
||||||
|
be redefined on the command line, e.g. ``bro -i eth0
|
||||||
|
snaplen=65535``.
|
||||||
|
|
||||||
|
* Reintroduced the BRO_LOG_SUFFIX environment that the ASCII
|
||||||
|
logger now respects to add a suffix to the log files it creates.
|
||||||
|
|
||||||
|
* The ASCII logs now include further header information, and
|
||||||
|
fields set to an empty value are now logged as ``(empty)`` by
|
||||||
|
default (instead of ``-``, which is already used for fields that
|
||||||
|
are not set at all).
|
||||||
|
|
||||||
|
* Some NOTICES were renamed, and the signatures of some SSL events
|
||||||
|
have changed.
|
||||||
|
|
||||||
|
* Many smaller bug fixes, portability improvements, and general
|
||||||
|
polishing.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
10
README
10
README
|
@ -4,13 +4,15 @@ Bro Network Security Monitor
|
||||||
|
|
||||||
Bro is a powerful framework for network analysis and security
|
Bro is a powerful framework for network analysis and security
|
||||||
monitoring. Please see the INSTALL file for installation instructions
|
monitoring. Please see the INSTALL file for installation instructions
|
||||||
and pointers for getting started. For more documentation, research
|
and pointers for getting started. NEWS contains releases notes for the
|
||||||
publications, and community contact information, see Bro's home page:
|
current version, and CHANGES has the complete history of changes.
|
||||||
|
Please see COPYING for licensing information.
|
||||||
|
|
||||||
|
For more documentation, research publications, and community contact
|
||||||
|
information, please see Bro's home page:
|
||||||
|
|
||||||
http://www.bro-ids.org
|
http://www.bro-ids.org
|
||||||
|
|
||||||
Please see COPYING for licensing information.
|
|
||||||
|
|
||||||
On behalf of the Bro Development Team,
|
On behalf of the Bro Development Team,
|
||||||
|
|
||||||
Vern Paxson & Robin Sommer,
|
Vern Paxson & Robin Sommer,
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2.0-beta-145
|
2.0-beta-177
|
||||||
|
|
1
doc/.gitignore
vendored
1
doc/.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
html
|
html
|
||||||
|
*.pyc
|
||||||
|
|
1
doc/_static/960.css
vendored
Normal file
1
doc/_static/960.css
vendored
Normal file
File diff suppressed because one or more lines are too long
513
doc/_static/basic.css
vendored
Normal file
513
doc/_static/basic.css
vendored
Normal file
|
@ -0,0 +1,513 @@
|
||||||
|
/*
|
||||||
|
* basic.css
|
||||||
|
* ~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Sphinx stylesheet -- basic theme.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -- main layout ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.clearer {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- relbar ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.related {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related h3 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0 10px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related li {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related li.right {
|
||||||
|
float: right;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- sidebar --------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.sphinxsidebarwrapper {
|
||||||
|
padding: 10px 5px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar {
|
||||||
|
float: left;
|
||||||
|
width: 230px;
|
||||||
|
margin-left: -100%;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul ul,
|
||||||
|
div.sphinxsidebar ul.want-points {
|
||||||
|
margin-left: 20px;
|
||||||
|
list-style: square;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul ul {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar form {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar input {
|
||||||
|
border: 1px solid #98dbcc;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar input[type="text"] {
|
||||||
|
width: 170px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar input[type="submit"] {
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- search page ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
ul.search {
|
||||||
|
margin: 10px 0 0 20px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li {
|
||||||
|
padding: 5px 0 5px 20px;
|
||||||
|
background-image: url(file.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 0 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li div.context {
|
||||||
|
color: #888;
|
||||||
|
margin: 2px 0 0 30px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.keywordmatches li.goodmatch a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- index page ------------------------------------------------------------ */
|
||||||
|
|
||||||
|
table.contentstable {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.contentstable p.biglink {
|
||||||
|
line-height: 150%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.biglink {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.linkdescr {
|
||||||
|
font-style: italic;
|
||||||
|
padding-top: 5px;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- general index --------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.indextable {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable td {
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable dl, table.indextable dd {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable tr.pcap {
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable tr.cap {
|
||||||
|
margin-top: 10px;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.toggler {
|
||||||
|
margin-right: 3px;
|
||||||
|
margin-top: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.modindex-jumpbox {
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin: 1em 0 1em 0;
|
||||||
|
padding: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.genindex-jumpbox {
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin: 1em 0 1em 0;
|
||||||
|
padding: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- general body styles --------------------------------------------------- */
|
||||||
|
|
||||||
|
a.headerlink {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p.caption {
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-list ul {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.first {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.rubric {
|
||||||
|
margin-top: 30px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-left, .figure.align-left, object.align-left {
|
||||||
|
clear: left;
|
||||||
|
float: left;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-right, .figure.align-right, object.align-right {
|
||||||
|
clear: right;
|
||||||
|
float: right;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-center, .figure.align-center, object.align-center {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- sidebars -------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.sidebar {
|
||||||
|
margin: 0 0 0.5em 1em;
|
||||||
|
border: 1px solid #ddb;
|
||||||
|
padding: 7px 7px 0 7px;
|
||||||
|
background-color: #ffe;
|
||||||
|
width: 40%;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.sidebar-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- topics ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.topic {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 7px 7px 0 7px;
|
||||||
|
margin: 10px 0 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.topic-title {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- admonitions ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.admonition {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition dt {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition dl {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.admonition-title {
|
||||||
|
margin: 0px 10px 5px 0px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p.centered {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- tables ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.field-list td, table.field-list th {
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.footnote td, table.footnote th {
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.citation {
|
||||||
|
border-left: solid 1px gray;
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.citation td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- other body styles ----------------------------------------------------- */
|
||||||
|
|
||||||
|
ol.arabic {
|
||||||
|
list-style: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.loweralpha {
|
||||||
|
list-style: lower-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.upperalpha {
|
||||||
|
list-style: upper-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.lowerroman {
|
||||||
|
list-style: lower-roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.upperroman {
|
||||||
|
list-style: upper-roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd p {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd ul, dd table {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt:target, .highlighted {
|
||||||
|
background-color: #fbe54e;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.glossary dt {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-list ul {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-list p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcount {
|
||||||
|
color: #060;
|
||||||
|
}
|
||||||
|
|
||||||
|
.optional {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.versionmodified {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-message {
|
||||||
|
background-color: #fda;
|
||||||
|
padding: 5px;
|
||||||
|
border: 3px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footnote:target {
|
||||||
|
background-color: #ffa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-block {
|
||||||
|
display: block;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-block .line-block {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-left: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guilabel, .menuselection {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accelerator {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.classifier {
|
||||||
|
font-style: oblique;
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr, acronym {
|
||||||
|
border-bottom: dotted 1px;
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- code displays --------------------------------------------------------- */
|
||||||
|
|
||||||
|
pre {
|
||||||
|
overflow: auto;
|
||||||
|
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||||
|
}
|
||||||
|
|
||||||
|
td.linenos pre {
|
||||||
|
padding: 5px 0px;
|
||||||
|
border: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable td {
|
||||||
|
padding: 0 0.5em 0 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.descname {
|
||||||
|
background-color: transparent;
|
||||||
|
font-weight: bold;
|
||||||
|
# font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.descclassname {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.xref, a tt {
|
||||||
|
background-color: transparent;
|
||||||
|
# font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-link {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-back {
|
||||||
|
float: right;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.viewcode-block:target {
|
||||||
|
margin: -1px -10px;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- math display ---------------------------------------------------------- */
|
||||||
|
|
||||||
|
img.math {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body div.math p {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.eqno {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- printout stylesheet --------------------------------------------------- */
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
div.document,
|
||||||
|
div.documentwrapper,
|
||||||
|
div.bodywrapper {
|
||||||
|
margin: 0 !important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar,
|
||||||
|
div.related,
|
||||||
|
div.footer,
|
||||||
|
#top-link {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
144
doc/_static/broxygen-extra.css
vendored
144
doc/_static/broxygen-extra.css
vendored
|
@ -1,3 +1,17 @@
|
||||||
|
|
||||||
|
a.toc-backref {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6,
|
||||||
|
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
|
||||||
|
padding:0 0 0px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
|
@ -14,3 +28,133 @@ th.field-name
|
||||||
{
|
{
|
||||||
white-space:nowrap;
|
white-space:nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 50px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
border-color: #aaa;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.section h3 {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: 40px;
|
||||||
|
margin-bottom: 0¡px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3.widgettitle {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size:18px;
|
||||||
|
font-style: normal;
|
||||||
|
margin-bottom: 0em;
|
||||||
|
margin-top: 40px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size:16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size:15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc-backref {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents ul {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.namespace {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl dt {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils tbody {
|
||||||
|
margin: 1em 1em 1em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils td {
|
||||||
|
padding: 5pt 5pt 5pt 5pt;
|
||||||
|
font-size: 14px;
|
||||||
|
border-left: 0;
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl pre {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils th {
|
||||||
|
padding: 5pt 5pt 5pt 5pt;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
border-left: 0;
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils tr:first-child td {
|
||||||
|
#border-top: 1px solid #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download {
|
||||||
|
font-family:"Courier New", Courier, mono;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt:target, .highlighted {
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.last {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
padding: 1em 1em 1em 1em;
|
||||||
|
background: #fffff0;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table.docutils {
|
||||||
|
background: #fffff0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl table.docutils {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils dl {
|
||||||
|
border: 1px dashed #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
0
doc/_static/broxygen-extra.js
vendored
Normal file
0
doc/_static/broxygen-extra.js
vendored
Normal file
437
doc/_static/broxygen.css
vendored
Normal file
437
doc/_static/broxygen.css
vendored
Normal file
|
@ -0,0 +1,437 @@
|
||||||
|
/* Automatically generated. Do not edit. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#bro-main, #bro-standalone-main {
|
||||||
|
padding: 0 0 0 0;
|
||||||
|
position:relative;
|
||||||
|
z-index:1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bro-main {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bro-standalone-main {
|
||||||
|
margin-bottom: 0em;
|
||||||
|
padding-left: 50px;
|
||||||
|
padding-right: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bro-outer {
|
||||||
|
color: #333;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bro-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 32px;
|
||||||
|
line-height:32px;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 3px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
font-family: Palatino,'Palatino Linotype',Georgia,serif;;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opening:first-letter {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opening {
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
text-align: right;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #aaa;
|
||||||
|
line-height: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-info-version {
|
||||||
|
position: relative;
|
||||||
|
height: 2em;
|
||||||
|
top: -1em;
|
||||||
|
color: #ccc;
|
||||||
|
float: left;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-info-date {
|
||||||
|
position: relative;
|
||||||
|
height: 2em;
|
||||||
|
top: -1em;
|
||||||
|
color: #ccc;
|
||||||
|
float: right;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family:Arial, Helvetica, sans-serif;
|
||||||
|
font-size:15px;
|
||||||
|
line-height:22px;
|
||||||
|
color: #333;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6,
|
||||||
|
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
|
||||||
|
padding:0 0 20px 0;
|
||||||
|
font-weight:bold;
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.section h3, div.section h4, div.section h5, div.section h6 {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
font-size:27px;
|
||||||
|
letter-spacing:-1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-top: 1em;
|
||||||
|
font-size:18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size:16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size:15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size:12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
padding:0 0 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
background:none;
|
||||||
|
height:1px;
|
||||||
|
line-height:1px;
|
||||||
|
border:0;
|
||||||
|
margin:0 0 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul, ol {
|
||||||
|
margin:0 20px 20px 0;
|
||||||
|
padding-left:40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.simple, ol.simple {
|
||||||
|
margin:0 0px 0px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin:0 0 0 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong, dfn {
|
||||||
|
font-weight:bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
em, dfn {
|
||||||
|
font-style:italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup, sub {
|
||||||
|
line-height:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
white-space:pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre, code, tt {
|
||||||
|
font-family:"Courier New", Courier, mono;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl dt {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin:0 0 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size:75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:link,
|
||||||
|
a:visited,
|
||||||
|
a:active
|
||||||
|
{
|
||||||
|
color: #2a85a7;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover
|
||||||
|
{
|
||||||
|
color:#c24444;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6,
|
||||||
|
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a
|
||||||
|
{
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border-bottom:1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
color: #333;
|
||||||
|
background: #FFFAE2;
|
||||||
|
padding: 7px 5px 3px 5px;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-bottom: 50px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
border-bottom: 1px solid;
|
||||||
|
border-color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
-moz-box-shadow:0 0 6px #ddd;
|
||||||
|
-webkit-box-shadow:0 0 6px #ddd;
|
||||||
|
box-shadow:0 0 6px #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, dd, li {
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#footer .widget_links ul a,
|
||||||
|
#footer .widget_links ol a
|
||||||
|
{
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer .widget_links ul a:hover,
|
||||||
|
#footer .widget_links ol a:hover
|
||||||
|
{
|
||||||
|
color:#c24444;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#footer .widget li {
|
||||||
|
padding-bottom:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer .widget_links li {
|
||||||
|
padding-bottom:1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer .widget li:last-child {
|
||||||
|
padding-bottom:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer .widgettitle {
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.widget {
|
||||||
|
margin:0 0 40px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget, .widgettitle {
|
||||||
|
font-size:12px;
|
||||||
|
line-height:18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widgettitle {
|
||||||
|
font-weight:bold;
|
||||||
|
text-transform:uppercase;
|
||||||
|
padding:0 0 10px 0;
|
||||||
|
margin:0 0 20px 0;
|
||||||
|
line-height:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget UL, .widget OL {
|
||||||
|
list-style-type:none;
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget p {
|
||||||
|
padding:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget li {
|
||||||
|
padding-bottom:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget a {
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bro-main .widgettitle,
|
||||||
|
{
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.widget img.left {
|
||||||
|
padding:5px 10px 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget img.right {
|
||||||
|
padding:5px 0 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ads .widgettitle {
|
||||||
|
margin-right:16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widgettitle {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widgettitle {
|
||||||
|
border-bottom:1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.sidebar-toc ul li {
|
||||||
|
padding-bottom: 0px;
|
||||||
|
text-align: left;
|
||||||
|
list-style-type: square;
|
||||||
|
list-style-position: inside;
|
||||||
|
padding-left: 1em;
|
||||||
|
text-indent: -1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-toc ul li li {
|
||||||
|
margin-left: 1em;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
list-style-type: square;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-toc ul li li a {
|
||||||
|
font-size: 8pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents {
|
||||||
|
padding: 10px;
|
||||||
|
background: #FFFAE2;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topic-title {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 0px 0px 5px 0px;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents li {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
list-style-type: square;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents ul ul li {
|
||||||
|
margin-left: 0px;
|
||||||
|
padding-left: 0px;
|
||||||
|
padding-top: 0em;
|
||||||
|
font-size: 90%;
|
||||||
|
list-style-type: square;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents ul ul ul li {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents ul ul ul ul li {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents ul li {
|
||||||
|
padding-top: 1em;
|
||||||
|
list-style-type: none;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents ul {
|
||||||
|
margin-left: 0px;
|
||||||
|
padding-left: 2em;
|
||||||
|
margin: 0px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note, .warning, .error {
|
||||||
|
margin-left: 2em;
|
||||||
|
margin-right: 2em;
|
||||||
|
margin-top: 1.5em;
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
padding: 0.5em 1em 0.5em 1em;
|
||||||
|
overflow: auto;
|
||||||
|
border-left: solid 3px #aaa;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition p {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #000;
|
||||||
|
padding-bottom: 0em;
|
||||||
|
margin-bottom: .5em;
|
||||||
|
margin-top: 0em;
|
||||||
|
}
|
3
doc/_static/download.js
vendored
3
doc/_static/download.js
vendored
|
@ -1,3 +0,0 @@
|
||||||
$(document).ready(function() {
|
|
||||||
$('.docutils.download').removeClass('download');
|
|
||||||
});
|
|
58
doc/_static/pygments.css
vendored
Normal file
58
doc/_static/pygments.css
vendored
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
.hll { background-color: #ffffcc }
|
||||||
|
.c { color: #aaaaaa; font-style: italic } /* Comment */
|
||||||
|
.err { color: #F00000; background-color: #F0A0A0 } /* Error */
|
||||||
|
.k { color: #0000aa } /* Keyword */
|
||||||
|
.cm { color: #aaaaaa; font-style: italic } /* Comment.Multiline */
|
||||||
|
.cp { color: #4c8317 } /* Comment.Preproc */
|
||||||
|
.c1 { color: #aaaaaa; font-style: italic } /* Comment.Single */
|
||||||
|
.cs { color: #0000aa; font-style: italic } /* Comment.Special */
|
||||||
|
.gd { color: #aa0000 } /* Generic.Deleted */
|
||||||
|
.ge { font-style: italic } /* Generic.Emph */
|
||||||
|
.gr { color: #aa0000 } /* Generic.Error */
|
||||||
|
.gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||||
|
.gi { color: #00aa00 } /* Generic.Inserted */
|
||||||
|
.go { color: #888888 } /* Generic.Output */
|
||||||
|
.gp { color: #555555 } /* Generic.Prompt */
|
||||||
|
.gs { font-weight: bold } /* Generic.Strong */
|
||||||
|
.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||||
|
.gt { color: #aa0000 } /* Generic.Traceback */
|
||||||
|
.kc { color: #0000aa } /* Keyword.Constant */
|
||||||
|
.kd { color: #0000aa } /* Keyword.Declaration */
|
||||||
|
.kn { color: #0000aa } /* Keyword.Namespace */
|
||||||
|
.kp { color: #0000aa } /* Keyword.Pseudo */
|
||||||
|
.kr { color: #0000aa } /* Keyword.Reserved */
|
||||||
|
.kt { color: #00aaaa } /* Keyword.Type */
|
||||||
|
.m { color: #009999 } /* Literal.Number */
|
||||||
|
.s { color: #aa5500 } /* Literal.String */
|
||||||
|
.na { color: #1e90ff } /* Name.Attribute */
|
||||||
|
.nb { color: #00aaaa } /* Name.Builtin */
|
||||||
|
.nc { color: #00aa00; text-decoration: underline } /* Name.Class */
|
||||||
|
.no { color: #aa0000 } /* Name.Constant */
|
||||||
|
.nd { color: #888888 } /* Name.Decorator */
|
||||||
|
.ni { color: #800000; font-weight: bold } /* Name.Entity */
|
||||||
|
.nf { color: #00aa00 } /* Name.Function */
|
||||||
|
.nn { color: #00aaaa; text-decoration: underline } /* Name.Namespace */
|
||||||
|
.nt { color: #1e90ff; font-weight: bold } /* Name.Tag */
|
||||||
|
.nv { color: #aa0000 } /* Name.Variable */
|
||||||
|
.ow { color: #0000aa } /* Operator.Word */
|
||||||
|
.w { color: #bbbbbb } /* Text.Whitespace */
|
||||||
|
.mf { color: #009999 } /* Literal.Number.Float */
|
||||||
|
.mh { color: #009999 } /* Literal.Number.Hex */
|
||||||
|
.mi { color: #009999 } /* Literal.Number.Integer */
|
||||||
|
.mo { color: #009999 } /* Literal.Number.Oct */
|
||||||
|
.sb { color: #aa5500 } /* Literal.String.Backtick */
|
||||||
|
.sc { color: #aa5500 } /* Literal.String.Char */
|
||||||
|
.sd { color: #aa5500 } /* Literal.String.Doc */
|
||||||
|
.s2 { color: #aa5500 } /* Literal.String.Double */
|
||||||
|
.se { color: #aa5500 } /* Literal.String.Escape */
|
||||||
|
.sh { color: #aa5500 } /* Literal.String.Heredoc */
|
||||||
|
.si { color: #aa5500 } /* Literal.String.Interpol */
|
||||||
|
.sx { color: #aa5500 } /* Literal.String.Other */
|
||||||
|
.sr { color: #009999 } /* Literal.String.Regex */
|
||||||
|
.s1 { color: #aa5500 } /* Literal.String.Single */
|
||||||
|
.ss { color: #0000aa } /* Literal.String.Symbol */
|
||||||
|
.bp { color: #00aaaa } /* Name.Builtin.Pseudo */
|
||||||
|
.vc { color: #aa0000 } /* Name.Variable.Class */
|
||||||
|
.vg { color: #aa0000 } /* Name.Variable.Global */
|
||||||
|
.vi { color: #aa0000 } /* Name.Variable.Instance */
|
||||||
|
.il { color: #009999 } /* Literal.Number.Integer.Long */
|
10
doc/_templates/layout.html
vendored
10
doc/_templates/layout.html
vendored
|
@ -1,11 +1,12 @@
|
||||||
{% extends "!layout.html" %}
|
{% extends "!layout.html" %}
|
||||||
|
|
||||||
{% block extrahead %}
|
{% block extrahead %}
|
||||||
<link rel="stylesheet" type="text/css" href="http://www.bro-ids.org/css/bro-ids.css" />
|
<link rel="stylesheet" type="text/css" href="{{ pathto('_static/broxygen.css', 1) }}"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="http://www.bro-ids.org/css/960.css" />
|
<link rel="stylesheet" type="text/css" href="{{ pathto('_static/960.css', 1) }}"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="http://www.bro-ids.org/css/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="{{ pathto('_static/pygments.css', 1) }}"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ pathto('_static/broxygen-extra.css', 1) }}"></script>
|
<link rel="stylesheet" type="text/css" href="{{ pathto('_static/broxygen-extra.css', 1) }}"></script>
|
||||||
<script type="text/javascript" src="{{ pathto('_static/download.js', 1) }}"></script>
|
|
||||||
|
<script type="text/javascript" src="{{ pathto('_static/broxygen-extra.js', 1) }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
Table of Contents
|
Table of Contents
|
||||||
</h3>
|
</h3>
|
||||||
<p>
|
<p>
|
||||||
|
<!-- <ul id="sidebar-toc"></ul> -->
|
||||||
<ul>{{toc}}</ul>
|
<ul>{{toc}}</ul>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -24,7 +24,7 @@ sys.path.insert(0, os.path.abspath('sphinx-sources/ext'))
|
||||||
|
|
||||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||||
extensions = ['bro', 'rst_directive', 'sphinx.ext.todo']
|
extensions = ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc']
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static']
|
templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static']
|
||||||
|
@ -40,7 +40,7 @@ master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'Bro'
|
project = u'Bro'
|
||||||
copyright = u'2011, The Bro Project'
|
copyright = u'2012, The Bro Project'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
@ -169,6 +169,7 @@ html_sidebars = {
|
||||||
# Output file base name for HTML help builder.
|
# Output file base name for HTML help builder.
|
||||||
htmlhelp_basename = 'Broxygen'
|
htmlhelp_basename = 'Broxygen'
|
||||||
|
|
||||||
|
html_add_permalinks = None
|
||||||
|
|
||||||
# -- Options for LaTeX output --------------------------------------------------
|
# -- Options for LaTeX output --------------------------------------------------
|
||||||
|
|
||||||
|
@ -208,7 +209,6 @@ latex_documents = [
|
||||||
# If false, no module index is generated.
|
# If false, no module index is generated.
|
||||||
#latex_domain_indices = True
|
#latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output --------------------------------------------
|
# -- Options for manual page output --------------------------------------------
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
|
|
29
doc/ext/adapt-toc.py
Normal file
29
doc/ext/adapt-toc.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
# Removes the first TOC level, which is just the page title.
|
||||||
|
def process_html_toc(app, pagename, templatename, context, doctree):
|
||||||
|
|
||||||
|
if not "toc" in context:
|
||||||
|
return
|
||||||
|
|
||||||
|
toc = context["toc"]
|
||||||
|
|
||||||
|
lines = toc.strip().split("\n")
|
||||||
|
lines = lines[2:-2]
|
||||||
|
|
||||||
|
toc = "\n".join(lines)
|
||||||
|
toc = "<ul>" + toc
|
||||||
|
|
||||||
|
context["toc"] = toc
|
||||||
|
|
||||||
|
# print >>sys.stderr, pagename
|
||||||
|
# print >>sys.stderr, context["toc"]
|
||||||
|
# print >>sys.stderr, "-----"
|
||||||
|
# print >>sys.stderr, toc
|
||||||
|
# print >>sys.stderr, "===="
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.connect('html-page-context', process_html_toc)
|
||||||
|
|
17
doc/faq.rst
17
doc/faq.rst
|
@ -28,6 +28,23 @@ Here are some pointers to more information:
|
||||||
Lothar Braun et. al evaluates packet capture performance on
|
Lothar Braun et. al evaluates packet capture performance on
|
||||||
commodity hardware
|
commodity hardware
|
||||||
|
|
||||||
|
Are there any gotchas regarding interface configuration for live capture? Or why might I be seeing abnormally large packets much greater than interface MTU?
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Some NICs offload the reassembly of traffic into "superpackets" so that
|
||||||
|
fewer packets are then passed up the stack (e.g. "TCP segmentation
|
||||||
|
offload", or "generic segmentation offload"). The result is that the
|
||||||
|
capturing application will observe packets much larger than the MTU size
|
||||||
|
of the interface they were captured from and may also interfere with the
|
||||||
|
maximum packet capture length, ``snaplen``, so it's a good idea to disable
|
||||||
|
an interface's offloading features.
|
||||||
|
|
||||||
|
You can use the ``ethtool`` program on Linux to view and disable
|
||||||
|
offloading features of an interface. See this page for more explicit
|
||||||
|
directions:
|
||||||
|
|
||||||
|
http://securityonion.blogspot.com/2011/10/when-is-full-packet-capture-not-full.html
|
||||||
|
|
||||||
What does an error message like ``internal error: NB-DNS error`` mean?
|
What does an error message like ``internal error: NB-DNS error`` mean?
|
||||||
---------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -31,15 +31,15 @@ See the `bro downloads page`_ for currently supported/targeted platforms.
|
||||||
|
|
||||||
* RPM
|
* RPM
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo yum localinstall Bro-all*.rpm
|
sudo yum localinstall Bro-all*.rpm
|
||||||
|
|
||||||
* DEB
|
* DEB
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo gdebi Bro-all-*.deb
|
sudo gdebi Bro-all-*.deb
|
||||||
|
|
||||||
* MacOS Disk Image with Installer
|
* MacOS Disk Image with Installer
|
||||||
|
|
||||||
|
@ -56,26 +56,32 @@ Building From Source
|
||||||
Required Dependencies
|
Required Dependencies
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The following dependencies are required to build Bro:
|
||||||
|
|
||||||
* RPM/RedHat-based Linux:
|
* RPM/RedHat-based Linux:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel
|
sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel
|
||||||
|
|
||||||
* DEB/Debian-based Linux:
|
* DEB/Debian-based Linux:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev
|
sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev
|
||||||
|
|
||||||
* FreeBSD
|
* FreeBSD
|
||||||
|
|
||||||
Most required dependencies should come with a minimal FreeBSD install
|
Most required dependencies should come with a minimal FreeBSD install
|
||||||
except for the following.
|
except for the following.
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo pkg_add -r cmake swig bison python
|
sudo pkg_add -r bash cmake swig bison python
|
||||||
|
|
||||||
|
Note that ``bash`` needs to be in ``PATH``, which by default it is
|
||||||
|
not. The FreeBSD package installs the binary into
|
||||||
|
``/usr/local/bin``.
|
||||||
|
|
||||||
* Mac OS X
|
* Mac OS X
|
||||||
|
|
||||||
|
@ -99,21 +105,21 @@ sending emails.
|
||||||
|
|
||||||
* RPM/RedHat-based Linux:
|
* RPM/RedHat-based Linux:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo yum install GeoIP-devel sendmail
|
sudo yum install GeoIP-devel sendmail
|
||||||
|
|
||||||
* DEB/Debian-based Linux:
|
* DEB/Debian-based Linux:
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo apt-get install libgeoip-dev sendmail
|
sudo apt-get install libgeoip-dev sendmail
|
||||||
|
|
||||||
* Ports-based FreeBSD
|
* Ports-based FreeBSD
|
||||||
|
|
||||||
.. console::
|
.. console::
|
||||||
|
|
||||||
sudo pkg_add -r GeoIP
|
sudo pkg_add -r GeoIP
|
||||||
|
|
||||||
sendmail is typically already available.
|
sendmail is typically already available.
|
||||||
|
|
||||||
|
|
|
@ -168,10 +168,6 @@ New Default Settings
|
||||||
are loaded. See ``PacketFilter::all_packets`` for how to revert to old
|
are loaded. See ``PacketFilter::all_packets`` for how to revert to old
|
||||||
behavior.
|
behavior.
|
||||||
|
|
||||||
- By default, Bro now sets a libpcap snaplen of 65535. Depending on
|
|
||||||
the OS, this may have performance implications and you can use the
|
|
||||||
``--snaplen`` option to change the value.
|
|
||||||
|
|
||||||
API Changes
|
API Changes
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
|
@ -10,18 +10,21 @@ module Notice;
|
||||||
export {
|
export {
|
||||||
## Activate pretty-printed alarm summaries.
|
## Activate pretty-printed alarm summaries.
|
||||||
const pretty_print_alarms = T &redef;
|
const pretty_print_alarms = T &redef;
|
||||||
|
|
||||||
## Address to send the pretty-printed reports to. Default if not set is
|
## Address to send the pretty-printed reports to. Default if not set is
|
||||||
## :bro:id:`Notice::mail_dest`.
|
## :bro:id:`Notice::mail_dest`.
|
||||||
const mail_dest_pretty_printed = "" &redef;
|
const mail_dest_pretty_printed = "" &redef;
|
||||||
|
|
||||||
## If an address from one of these networks is reported, we mark
|
## If an address from one of these networks is reported, we mark
|
||||||
## the entry with an addition quote symbol (that is, ">"). Many MUAs
|
## the entry with an additional quote symbol (i.e., ">"). Many MUAs
|
||||||
## then highlight such lines differently.
|
## then highlight such lines differently.
|
||||||
global flag_nets: set[subnet] &redef;
|
global flag_nets: set[subnet] &redef;
|
||||||
|
|
||||||
## Function that renders a single alarm. Can be overidden.
|
## Function that renders a single alarm. Can be overidden.
|
||||||
global pretty_print_alarm: function(out: file, n: Info) &redef;
|
global pretty_print_alarm: function(out: file, n: Info) &redef;
|
||||||
|
|
||||||
|
## Force generating mail file, even if reading from traces or no mail
|
||||||
|
## destination is defined. This is mainly for testing.
|
||||||
|
global force_email_summaries = F &redef;
|
||||||
}
|
}
|
||||||
|
|
||||||
# We maintain an old-style file recording the pretty-printed alarms.
|
# We maintain an old-style file recording the pretty-printed alarms.
|
||||||
|
@ -32,6 +35,9 @@ global pp_alarms_open: bool = F;
|
||||||
# Returns True if pretty-printed alarm summaries are activated.
|
# Returns True if pretty-printed alarm summaries are activated.
|
||||||
function want_pp() : bool
|
function want_pp() : bool
|
||||||
{
|
{
|
||||||
|
if ( force_email_summaries )
|
||||||
|
return T;
|
||||||
|
|
||||||
return (pretty_print_alarms && ! reading_traces()
|
return (pretty_print_alarms && ! reading_traces()
|
||||||
&& (mail_dest != "" || mail_dest_pretty_printed != ""));
|
&& (mail_dest != "" || mail_dest_pretty_printed != ""));
|
||||||
}
|
}
|
||||||
|
@ -41,38 +47,49 @@ function pp_open()
|
||||||
{
|
{
|
||||||
if ( pp_alarms_open )
|
if ( pp_alarms_open )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pp_alarms_open = T;
|
pp_alarms_open = T;
|
||||||
pp_alarms = open(pp_alarms_name);
|
pp_alarms = open(pp_alarms_name);
|
||||||
|
|
||||||
local dest = mail_dest_pretty_printed != "" ? mail_dest_pretty_printed
|
|
||||||
: mail_dest;
|
|
||||||
|
|
||||||
local headers = email_headers("Alarm summary", dest);
|
|
||||||
write_file(pp_alarms, headers + "\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Closes and mails out the current output file.
|
# Closes and mails out the current output file.
|
||||||
function pp_send()
|
function pp_send(rinfo: Log::RotationInfo)
|
||||||
{
|
{
|
||||||
if ( ! pp_alarms_open )
|
if ( ! pp_alarms_open )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
write_file(pp_alarms, "\n\n--\n[Automatically generated]\n\n");
|
write_file(pp_alarms, "\n\n--\n[Automatically generated]\n\n");
|
||||||
close(pp_alarms);
|
close(pp_alarms);
|
||||||
|
|
||||||
system(fmt("/bin/cat %s | %s -t -oi && /bin/rm %s",
|
|
||||||
pp_alarms_name, sendmail, pp_alarms_name));
|
|
||||||
|
|
||||||
pp_alarms_open = F;
|
pp_alarms_open = F;
|
||||||
|
|
||||||
|
local from = strftime("%H:%M:%S", rinfo$open);
|
||||||
|
local to = strftime("%H:%M:%S", rinfo$close);
|
||||||
|
local subject = fmt("Alarm summary from %s-%s", from, to);
|
||||||
|
local dest = mail_dest_pretty_printed != "" ? mail_dest_pretty_printed
|
||||||
|
: mail_dest;
|
||||||
|
|
||||||
|
if ( dest == "" )
|
||||||
|
# No mail destination configured, just leave the file alone. This is mainly for
|
||||||
|
# testing.
|
||||||
|
return;
|
||||||
|
|
||||||
|
local headers = email_headers(subject, dest);
|
||||||
|
|
||||||
|
local header_name = pp_alarms_name + ".tmp";
|
||||||
|
local header = open(header_name);
|
||||||
|
write_file(header, headers + "\n");
|
||||||
|
close(header);
|
||||||
|
|
||||||
|
system(fmt("/bin/cat %s %s | %s -t -oi && /bin/rm -f %s %s",
|
||||||
|
header_name, pp_alarms_name, sendmail, header_name, pp_alarms_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
# Postprocessor function that triggers the email.
|
# Postprocessor function that triggers the email.
|
||||||
function pp_postprocessor(info: Log::RotationInfo): bool
|
function pp_postprocessor(info: Log::RotationInfo): bool
|
||||||
{
|
{
|
||||||
if ( want_pp() )
|
if ( want_pp() )
|
||||||
pp_send();
|
pp_send(info);
|
||||||
|
|
||||||
return T;
|
return T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +97,7 @@ event bro_init()
|
||||||
{
|
{
|
||||||
if ( ! want_pp() )
|
if ( ! want_pp() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
# This replaces the standard non-pretty-printing filter.
|
# This replaces the standard non-pretty-printing filter.
|
||||||
Log::add_filter(Notice::ALARM_LOG,
|
Log::add_filter(Notice::ALARM_LOG,
|
||||||
[$name="alarm-mail", $writer=Log::WRITER_NONE,
|
[$name="alarm-mail", $writer=Log::WRITER_NONE,
|
||||||
|
@ -92,13 +109,13 @@ event notice(n: Notice::Info) &priority=-5
|
||||||
{
|
{
|
||||||
if ( ! want_pp() )
|
if ( ! want_pp() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( ACTION_LOG !in n$actions )
|
if ( ACTION_ALARM !in n$actions )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( ! pp_alarms_open )
|
if ( ! pp_alarms_open )
|
||||||
pp_open();
|
pp_open();
|
||||||
|
|
||||||
pretty_print_alarm(pp_alarms, n);
|
pretty_print_alarm(pp_alarms, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,12 +125,12 @@ function do_msg(out: file, n: Info, line1: string, line2: string, line3: string,
|
||||||
@ifdef ( Notice::ACTION_ADD_GEODATA ) # Make tests happy, cyclic dependency.
|
@ifdef ( Notice::ACTION_ADD_GEODATA ) # Make tests happy, cyclic dependency.
|
||||||
if ( n?$remote_location && n$remote_location?$country_code )
|
if ( n?$remote_location && n$remote_location?$country_code )
|
||||||
country = fmt(" (remote location %s)", n$remote_location$country_code);
|
country = fmt(" (remote location %s)", n$remote_location$country_code);
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
line1 = cat(line1, country);
|
line1 = cat(line1, country);
|
||||||
|
|
||||||
local resolved = "";
|
local resolved = "";
|
||||||
|
|
||||||
if ( host1 != 0.0.0.0 )
|
if ( host1 != 0.0.0.0 )
|
||||||
resolved = fmt("%s # %s = %s", resolved, host1, name1);
|
resolved = fmt("%s # %s = %s", resolved, host1, name1);
|
||||||
|
|
||||||
|
@ -133,64 +150,64 @@ function do_msg(out: file, n: Info, line1: string, line2: string, line3: string,
|
||||||
function pretty_print_alarm(out: file, n: Info)
|
function pretty_print_alarm(out: file, n: Info)
|
||||||
{
|
{
|
||||||
local pdescr = "";
|
local pdescr = "";
|
||||||
|
|
||||||
@if ( Cluster::is_enabled() )
|
@if ( Cluster::is_enabled() )
|
||||||
pdescr = "local";
|
pdescr = "local";
|
||||||
|
|
||||||
if ( n?$src_peer )
|
if ( n?$src_peer )
|
||||||
pdescr = n$src_peer?$descr ? n$src_peer$descr : fmt("%s", n$src_peer$host);
|
pdescr = n$src_peer?$descr ? n$src_peer$descr : fmt("%s", n$src_peer$host);
|
||||||
|
|
||||||
pdescr = fmt("<%s> ", pdescr);
|
pdescr = fmt("<%s> ", pdescr);
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
local msg = fmt( "%s%s", pdescr, n$msg);
|
local msg = fmt( "%s%s", pdescr, n$msg);
|
||||||
|
|
||||||
local who = "";
|
local who = "";
|
||||||
local h1 = 0.0.0.0;
|
local h1 = 0.0.0.0;
|
||||||
local h2 = 0.0.0.0;
|
local h2 = 0.0.0.0;
|
||||||
|
|
||||||
local orig_p = "";
|
local orig_p = "";
|
||||||
local resp_p = "";
|
local resp_p = "";
|
||||||
|
|
||||||
if ( n?$id )
|
if ( n?$id )
|
||||||
{
|
{
|
||||||
orig_p = fmt(":%s", n$id$orig_p);
|
h1 = n$id$orig_h;
|
||||||
resp_p = fmt(":%s", n$id$resp_p);
|
h2 = n$id$resp_h;
|
||||||
|
who = fmt("%s:%s -> %s:%s", h1, n$id$orig_p, h2, n$id$resp_p);
|
||||||
}
|
}
|
||||||
|
else if ( n?$src && n?$dst )
|
||||||
if ( n?$src && n?$dst )
|
|
||||||
{
|
{
|
||||||
h1 = n$src;
|
h1 = n$src;
|
||||||
h2 = n$dst;
|
h2 = n$dst;
|
||||||
who = fmt("%s%s -> %s%s", h1, orig_p, h2, resp_p);
|
who = fmt("%s -> %s", h1, h2);
|
||||||
|
|
||||||
if ( n?$uid )
|
|
||||||
who = fmt("%s (uid %s)", who, n$uid );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( n?$src )
|
else if ( n?$src )
|
||||||
{
|
{
|
||||||
local p = "";
|
|
||||||
|
|
||||||
if ( n?$p )
|
|
||||||
p = fmt(":%s", n$p);
|
|
||||||
|
|
||||||
h1 = n$src;
|
h1 = n$src;
|
||||||
who = fmt("%s%s", h1, p);
|
who = fmt("%s%s", h1, (n?$p ? fmt(":%s", n$p) : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( n?$uid )
|
||||||
|
who = fmt("%s (uid %s)", who, n$uid );
|
||||||
|
|
||||||
local flag = (h1 in flag_nets || h2 in flag_nets);
|
local flag = (h1 in flag_nets || h2 in flag_nets);
|
||||||
|
|
||||||
local line1 = fmt(">%s %D %s %s", (flag ? ">" : " "), network_time(), n$note, who);
|
local line1 = fmt(">%s %D %s %s", (flag ? ">" : " "), network_time(), n$note, who);
|
||||||
local line2 = fmt(" %s", msg);
|
local line2 = fmt(" %s", msg);
|
||||||
local line3 = n?$sub ? fmt(" %s", n$sub) : "";
|
local line3 = n?$sub ? fmt(" %s", n$sub) : "";
|
||||||
|
|
||||||
if ( h1 == 0.0.0.0 )
|
if ( h1 == 0.0.0.0 )
|
||||||
{
|
{
|
||||||
do_msg(out, n, line1, line2, line3, h1, "", h2, "");
|
do_msg(out, n, line1, line2, line3, h1, "", h2, "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( reading_traces() )
|
||||||
|
{
|
||||||
|
do_msg(out, n, line1, line2, line3, h1, "<skipped>", h2, "<skipped>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
when ( local h1name = lookup_addr(h1) )
|
when ( local h1name = lookup_addr(h1) )
|
||||||
{
|
{
|
||||||
if ( h2 == 0.0.0.0 )
|
if ( h2 == 0.0.0.0 )
|
||||||
|
|
|
@ -73,8 +73,12 @@ export {
|
||||||
## reference to the actual connection will be deleted after applying
|
## reference to the actual connection will be deleted after applying
|
||||||
## the notice policy.
|
## the notice policy.
|
||||||
iconn: icmp_conn &optional;
|
iconn: icmp_conn &optional;
|
||||||
|
|
||||||
## The type of the notice.
|
## The transport protocol. Filled automatically when either conn, iconn
|
||||||
|
## or p is specified.
|
||||||
|
proto: transport_proto &log &optional;
|
||||||
|
|
||||||
|
## The :bro:enum:`Notice::Type` of the notice.
|
||||||
note: Type &log;
|
note: Type &log;
|
||||||
## The human readable message for the notice.
|
## The human readable message for the notice.
|
||||||
msg: string &log &optional;
|
msg: string &log &optional;
|
||||||
|
@ -535,8 +539,12 @@ function apply_policy(n: Notice::Info)
|
||||||
n$p = n$id$resp_p;
|
n$p = n$id$resp_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( n?$p )
|
||||||
|
n$proto = get_port_transport_proto(n$p);
|
||||||
|
|
||||||
if ( n?$iconn )
|
if ( n?$iconn )
|
||||||
{
|
{
|
||||||
|
n$proto = icmp;
|
||||||
if ( ! n?$src )
|
if ( ! n?$src )
|
||||||
n$src = n$iconn$orig_h;
|
n$src = n$iconn$orig_h;
|
||||||
if ( ! n?$dst )
|
if ( ! n?$dst )
|
||||||
|
|
|
@ -2331,6 +2331,9 @@ const ignore_keep_alive_rexmit = F &redef;
|
||||||
## .. bro:see:: tunnel_port
|
## .. bro:see:: tunnel_port
|
||||||
const parse_udp_tunnels = F &redef;
|
const parse_udp_tunnels = F &redef;
|
||||||
|
|
||||||
# Load the logging framework here because it uses fairly deep integration with
|
## Number of bytes per packet to capture from live interfaces.
|
||||||
|
const snaplen = 8192 &redef;
|
||||||
|
|
||||||
|
# Load the logging framework here because it uses fairly deep integration with
|
||||||
# BiFs and script-land defined types.
|
# BiFs and script-land defined types.
|
||||||
@load base/frameworks/logging
|
@load base/frameworks/logging
|
||||||
|
|
|
@ -1,23 +1,27 @@
|
||||||
##! This script can be used to extract either the originator's data or the
|
##! This script can be used to extract either the originator's data or the
|
||||||
##! responders data or both. By default nothing is extracted, and in order
|
##! responders data or both. By default nothing is extracted, and in order
|
||||||
##! to actually extract data the ``c$extract_orig`` and/or the
|
##! to actually extract data the ``c$extract_orig`` and/or the
|
||||||
##! ``c$extract_resp`` variable must be set to T. One way to achieve this
|
##! ``c$extract_resp`` variable must be set to ``T``. One way to achieve this
|
||||||
##! would be to handle the connection_established event elsewhere and set the
|
##! would be to handle the :bro:id:`connection_established` event elsewhere
|
||||||
##! extract_orig and extract_resp options there. However, there may be trouble
|
##! and set the ``extract_orig`` and ``extract_resp`` options there.
|
||||||
##! with the timing due the event queue delay.
|
##! However, there may be trouble with the timing due to event queue delay.
|
||||||
##! This script does not work well in a cluster context unless it has a
|
##!
|
||||||
##! remotely mounted disk to write the content files to.
|
##! .. note::
|
||||||
|
##!
|
||||||
|
##! This script does not work well in a cluster context unless it has a
|
||||||
|
##! remotely mounted disk to write the content files to.
|
||||||
|
|
||||||
@load base/utils/files
|
@load base/utils/files
|
||||||
|
|
||||||
module Conn;
|
module Conn;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
## The prefix given to files as they are opened on disk.
|
## The prefix given to files containing extracted connections as they are
|
||||||
|
## opened on disk.
|
||||||
const extraction_prefix = "contents" &redef;
|
const extraction_prefix = "contents" &redef;
|
||||||
|
|
||||||
## If this variable is set to T, then all contents of all files will be
|
## If this variable is set to ``T``, then all contents of all connections
|
||||||
## extracted.
|
## will be extracted.
|
||||||
const default_extract = F &redef;
|
const default_extract = F &redef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
module Conn;
|
module Conn;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
## Define inactivty timeouts by the service detected being used over
|
## Define inactivity timeouts by the service detected being used over
|
||||||
## the connection.
|
## the connection.
|
||||||
const analyzer_inactivity_timeouts: table[AnalyzerTag] of interval = {
|
const analyzer_inactivity_timeouts: table[AnalyzerTag] of interval = {
|
||||||
# For interactive services, allow longer periods of inactivity.
|
# For interactive services, allow longer periods of inactivity.
|
||||||
|
|
|
@ -1,17 +1,33 @@
|
||||||
|
##! This script manages the tracking/logging of general information regarding
|
||||||
|
##! TCP, UDP, and ICMP traffic. For UDP and ICMP, "connections" are to
|
||||||
|
##! be interpreted using flow semantics (sequence of packets from a source
|
||||||
|
##! host/post to a destination host/port). Further, ICMP "ports" are to
|
||||||
|
##! be interpreted as the source port meaning the ICMP message type and
|
||||||
|
##! the destination port being the ICMP message code.
|
||||||
|
|
||||||
@load base/utils/site
|
@load base/utils/site
|
||||||
|
|
||||||
module Conn;
|
module Conn;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
## The connection logging stream identifier.
|
||||||
redef enum Log::ID += { LOG };
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
|
## The record type which contains column fields of the connection log.
|
||||||
type Info: record {
|
type Info: record {
|
||||||
## This is the time of the first packet.
|
## This is the time of the first packet.
|
||||||
ts: time &log;
|
ts: time &log;
|
||||||
|
## A unique identifier of a connection.
|
||||||
uid: string &log;
|
uid: string &log;
|
||||||
|
## The connection's 4-tuple of endpoint addresses/ports.
|
||||||
id: conn_id &log;
|
id: conn_id &log;
|
||||||
|
## The transport layer protocol of the connection.
|
||||||
proto: transport_proto &log;
|
proto: transport_proto &log;
|
||||||
|
## An identification of an application protocol being sent over the
|
||||||
|
## the connection.
|
||||||
service: string &log &optional;
|
service: string &log &optional;
|
||||||
|
## How long the connection lasted. For 3-way or 4-way connection
|
||||||
|
## tear-downs, this will not include the final ACK.
|
||||||
duration: interval &log &optional;
|
duration: interval &log &optional;
|
||||||
## The number of payload bytes the originator sent. For TCP
|
## The number of payload bytes the originator sent. For TCP
|
||||||
## this is taken from sequence numbers and might be inaccurate
|
## this is taken from sequence numbers and might be inaccurate
|
||||||
|
@ -51,8 +67,8 @@ export {
|
||||||
## have been completed prior to the packet loss.
|
## have been completed prior to the packet loss.
|
||||||
missed_bytes: count &log &default=0;
|
missed_bytes: count &log &default=0;
|
||||||
|
|
||||||
## Records the state history of (TCP) connections as
|
## Records the state history of connections as a string of letters.
|
||||||
## a string of letters.
|
## For TCP connections the meaning of those letters is:
|
||||||
##
|
##
|
||||||
## ====== ====================================================
|
## ====== ====================================================
|
||||||
## Letter Meaning
|
## Letter Meaning
|
||||||
|
@ -71,7 +87,8 @@ export {
|
||||||
## originator and lower case then means the responder.
|
## originator and lower case then means the responder.
|
||||||
## Also, there is compression. We only record one "d" in each direction,
|
## Also, there is compression. We only record one "d" in each direction,
|
||||||
## for instance. I.e., we just record that data went in that direction.
|
## for instance. I.e., we just record that data went in that direction.
|
||||||
## This history is not meant to encode how much data that happened to be.
|
## This history is not meant to encode how much data that happened to
|
||||||
|
## be.
|
||||||
history: string &log &optional;
|
history: string &log &optional;
|
||||||
## Number of packets the originator sent.
|
## Number of packets the originator sent.
|
||||||
## Only set if :bro:id:`use_conn_size_analyzer` = T
|
## Only set if :bro:id:`use_conn_size_analyzer` = T
|
||||||
|
@ -85,7 +102,9 @@ export {
|
||||||
## Number IP level bytes the responder sent. See ``orig_pkts``.
|
## Number IP level bytes the responder sent. See ``orig_pkts``.
|
||||||
resp_ip_bytes: count &log &optional;
|
resp_ip_bytes: count &log &optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
## Event that can be handled to access the :bro:type:`Conn::Info`
|
||||||
|
## record as it is sent on to the logging framework.
|
||||||
global log_conn: event(rec: Info);
|
global log_conn: event(rec: Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
module DNS;
|
module DNS;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
const PTR = 12;
|
const PTR = 12; ##< RR TYPE value for a domain name pointer.
|
||||||
const EDNS = 41;
|
const EDNS = 41; ##< An OPT RR TYPE value described by EDNS.
|
||||||
const ANY = 255;
|
const ANY = 255; ##< A QTYPE value describing a request for all records.
|
||||||
|
|
||||||
## Mapping of DNS query type codes to human readable string representation.
|
## Mapping of DNS query type codes to human readable string representation.
|
||||||
const query_types = {
|
const query_types = {
|
||||||
|
@ -29,50 +29,43 @@ export {
|
||||||
[ANY] = "*",
|
[ANY] = "*",
|
||||||
} &default = function(n: count): string { return fmt("query-%d", n); };
|
} &default = function(n: count): string { return fmt("query-%d", n); };
|
||||||
|
|
||||||
const code_types = {
|
|
||||||
[0] = "X0",
|
|
||||||
[1] = "Xfmt",
|
|
||||||
[2] = "Xsrv",
|
|
||||||
[3] = "Xnam",
|
|
||||||
[4] = "Ximp",
|
|
||||||
[5] = "X[",
|
|
||||||
} &default="?";
|
|
||||||
|
|
||||||
## Errors used for non-TSIG/EDNS types.
|
## Errors used for non-TSIG/EDNS types.
|
||||||
const base_errors = {
|
const base_errors = {
|
||||||
[0] = "NOERROR", ##< No Error
|
[0] = "NOERROR", # No Error
|
||||||
[1] = "FORMERR", ##< Format Error
|
[1] = "FORMERR", # Format Error
|
||||||
[2] = "SERVFAIL", ##< Server Failure
|
[2] = "SERVFAIL", # Server Failure
|
||||||
[3] = "NXDOMAIN", ##< Non-Existent Domain
|
[3] = "NXDOMAIN", # Non-Existent Domain
|
||||||
[4] = "NOTIMP", ##< Not Implemented
|
[4] = "NOTIMP", # Not Implemented
|
||||||
[5] = "REFUSED", ##< Query Refused
|
[5] = "REFUSED", # Query Refused
|
||||||
[6] = "YXDOMAIN", ##< Name Exists when it should not
|
[6] = "YXDOMAIN", # Name Exists when it should not
|
||||||
[7] = "YXRRSET", ##< RR Set Exists when it should not
|
[7] = "YXRRSET", # RR Set Exists when it should not
|
||||||
[8] = "NXRRSet", ##< RR Set that should exist does not
|
[8] = "NXRRSet", # RR Set that should exist does not
|
||||||
[9] = "NOTAUTH", ##< Server Not Authoritative for zone
|
[9] = "NOTAUTH", # Server Not Authoritative for zone
|
||||||
[10] = "NOTZONE", ##< Name not contained in zone
|
[10] = "NOTZONE", # Name not contained in zone
|
||||||
[11] = "unassigned-11", ##< available for assignment
|
[11] = "unassigned-11", # available for assignment
|
||||||
[12] = "unassigned-12", ##< available for assignment
|
[12] = "unassigned-12", # available for assignment
|
||||||
[13] = "unassigned-13", ##< available for assignment
|
[13] = "unassigned-13", # available for assignment
|
||||||
[14] = "unassigned-14", ##< available for assignment
|
[14] = "unassigned-14", # available for assignment
|
||||||
[15] = "unassigned-15", ##< available for assignment
|
[15] = "unassigned-15", # available for assignment
|
||||||
[16] = "BADVERS", ##< for EDNS, collision w/ TSIG
|
[16] = "BADVERS", # for EDNS, collision w/ TSIG
|
||||||
[17] = "BADKEY", ##< Key not recognized
|
[17] = "BADKEY", # Key not recognized
|
||||||
[18] = "BADTIME", ##< Signature out of time window
|
[18] = "BADTIME", # Signature out of time window
|
||||||
[19] = "BADMODE", ##< Bad TKEY Mode
|
[19] = "BADMODE", # Bad TKEY Mode
|
||||||
[20] = "BADNAME", ##< Duplicate key name
|
[20] = "BADNAME", # Duplicate key name
|
||||||
[21] = "BADALG", ##< Algorithm not supported
|
[21] = "BADALG", # Algorithm not supported
|
||||||
[22] = "BADTRUNC", ##< draft-ietf-dnsext-tsig-sha-05.txt
|
[22] = "BADTRUNC", # draft-ietf-dnsext-tsig-sha-05.txt
|
||||||
[3842] = "BADSIG", ##< 16 <= number collision with EDNS(16);
|
[3842] = "BADSIG", # 16 <= number collision with EDNS(16);
|
||||||
##< this is a translation from TSIG(16)
|
# this is a translation from TSIG(16)
|
||||||
} &default = function(n: count): string { return fmt("rcode-%d", n); };
|
} &default = function(n: count): string { return fmt("rcode-%d", n); };
|
||||||
|
|
||||||
# This deciphers EDNS Z field values.
|
## This deciphers EDNS Z field values.
|
||||||
const edns_zfield = {
|
const edns_zfield = {
|
||||||
[0] = "NOVALUE", # regular entry
|
[0] = "NOVALUE", # regular entry
|
||||||
[32768] = "DNS_SEC_OK", # accepts DNS Sec RRs
|
[32768] = "DNS_SEC_OK", # accepts DNS Sec RRs
|
||||||
} &default="?";
|
} &default="?";
|
||||||
|
|
||||||
|
## Possible values of the CLASS field in resource records or QCLASS field
|
||||||
|
## in query messages.
|
||||||
const classes = {
|
const classes = {
|
||||||
[1] = "C_INTERNET",
|
[1] = "C_INTERNET",
|
||||||
[2] = "C_CSNET",
|
[2] = "C_CSNET",
|
||||||
|
@ -81,4 +74,4 @@ export {
|
||||||
[254] = "C_NONE",
|
[254] = "C_NONE",
|
||||||
[255] = "C_ANY",
|
[255] = "C_ANY",
|
||||||
} &default = function(n: count): string { return fmt("qclass-%d", n); };
|
} &default = function(n: count): string { return fmt("qclass-%d", n); };
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,80 @@
|
||||||
|
##! Base DNS analysis script which tracks and logs DNS queries along with
|
||||||
|
##! their responses.
|
||||||
|
|
||||||
@load ./consts
|
@load ./consts
|
||||||
|
|
||||||
module DNS;
|
module DNS;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
## The DNS logging stream identifier.
|
||||||
redef enum Log::ID += { LOG };
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
|
## The record type which contains the column fields of the DNS log.
|
||||||
type Info: record {
|
type Info: record {
|
||||||
|
## The earliest time at which a DNS protocol message over the
|
||||||
|
## associated connection is observed.
|
||||||
ts: time &log;
|
ts: time &log;
|
||||||
|
## A unique identifier of the connection over which DNS messages
|
||||||
|
## are being transferred.
|
||||||
uid: string &log;
|
uid: string &log;
|
||||||
|
## The connection's 4-tuple of endpoint addresses/ports.
|
||||||
id: conn_id &log;
|
id: conn_id &log;
|
||||||
|
## The transport layer protocol of the connection.
|
||||||
proto: transport_proto &log;
|
proto: transport_proto &log;
|
||||||
|
## A 16 bit identifier assigned by the program that generated the
|
||||||
|
## DNS query. Also used in responses to match up replies to
|
||||||
|
## outstanding queries.
|
||||||
trans_id: count &log &optional;
|
trans_id: count &log &optional;
|
||||||
|
## The domain name that is the subject of the DNS query.
|
||||||
query: string &log &optional;
|
query: string &log &optional;
|
||||||
|
## The QCLASS value specifying the class of the query.
|
||||||
qclass: count &log &optional;
|
qclass: count &log &optional;
|
||||||
|
## A descriptive name for the class of the query.
|
||||||
qclass_name: string &log &optional;
|
qclass_name: string &log &optional;
|
||||||
|
## A QTYPE value specifying the type of the query.
|
||||||
qtype: count &log &optional;
|
qtype: count &log &optional;
|
||||||
|
## A descriptive name for the type of the query.
|
||||||
qtype_name: string &log &optional;
|
qtype_name: string &log &optional;
|
||||||
|
## The response code value in DNS response messages.
|
||||||
rcode: count &log &optional;
|
rcode: count &log &optional;
|
||||||
|
## A descriptive name for the response code value.
|
||||||
rcode_name: string &log &optional;
|
rcode_name: string &log &optional;
|
||||||
|
## Whether the message is a query (F) or response (T).
|
||||||
QR: bool &log &default=F;
|
QR: bool &log &default=F;
|
||||||
|
## The Authoritative Answer bit for response messages specifies that
|
||||||
|
## the responding name server is an authority for the domain name
|
||||||
|
## in the question section.
|
||||||
AA: bool &log &default=F;
|
AA: bool &log &default=F;
|
||||||
|
## The Truncation bit specifies that the message was truncated.
|
||||||
TC: bool &log &default=F;
|
TC: bool &log &default=F;
|
||||||
|
## The Recursion Desired bit indicates to a name server to recursively
|
||||||
|
## purse the query.
|
||||||
RD: bool &log &default=F;
|
RD: bool &log &default=F;
|
||||||
|
## The Recursion Available bit in a response message indicates if
|
||||||
|
## the name server supports recursive queries.
|
||||||
RA: bool &log &default=F;
|
RA: bool &log &default=F;
|
||||||
|
## A reserved field that is currently supposed to be zero in all
|
||||||
|
## queries and responses.
|
||||||
Z: count &log &default=0;
|
Z: count &log &default=0;
|
||||||
|
## The set of resource descriptions in answer of the query.
|
||||||
answers: vector of string &log &optional;
|
answers: vector of string &log &optional;
|
||||||
|
## The caching intervals of the associated RRs described by the
|
||||||
|
## ``answers`` field.
|
||||||
TTLs: vector of interval &log &optional;
|
TTLs: vector of interval &log &optional;
|
||||||
|
|
||||||
## This value indicates if this request/response pair is ready to be logged.
|
## This value indicates if this request/response pair is ready to be
|
||||||
|
## logged.
|
||||||
ready: bool &default=F;
|
ready: bool &default=F;
|
||||||
|
## The total number of resource records in a reply message's answer
|
||||||
|
## section.
|
||||||
total_answers: count &optional;
|
total_answers: count &optional;
|
||||||
|
## The total number of resource records in a reply message's answer,
|
||||||
|
## authority, and additional sections.
|
||||||
total_replies: count &optional;
|
total_replies: count &optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
## A record type which tracks the status of DNS queries for a given
|
||||||
|
## :bro:type:`connection`.
|
||||||
type State: record {
|
type State: record {
|
||||||
## Indexed by query id, returns Info record corresponding to
|
## Indexed by query id, returns Info record corresponding to
|
||||||
## query/response which haven't completed yet.
|
## query/response which haven't completed yet.
|
||||||
|
@ -44,11 +86,21 @@ export {
|
||||||
finished_answers: set[count] &optional;
|
finished_answers: set[count] &optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
## An event that can be handled to access the :bro:type:`DNS::Info`
|
||||||
|
## record as it is sent to the logging framework.
|
||||||
global log_dns: event(rec: Info);
|
global log_dns: event(rec: Info);
|
||||||
|
|
||||||
## This is called by the specific dns_*_reply events with a "reply" which
|
## This is called by the specific dns_*_reply events with a "reply" which
|
||||||
## may not represent the full data available from the resource record, but
|
## may not represent the full data available from the resource record, but
|
||||||
## it's generally considered a summarization of the response(s).
|
## it's generally considered a summarization of the response(s).
|
||||||
|
##
|
||||||
|
## c: The connection record for which to fill in DNS reply data.
|
||||||
|
##
|
||||||
|
## msg: The DNS message header information for the response.
|
||||||
|
##
|
||||||
|
## ans: The general information of a RR response.
|
||||||
|
##
|
||||||
|
## reply: The specific response information according to RR type/class.
|
||||||
global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string);
|
global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
##! Base SSL analysis script.
|
||||||
|
|
||||||
@load ./consts
|
@load ./consts
|
||||||
|
|
||||||
module SSL;
|
module SSL;
|
||||||
|
@ -6,6 +8,7 @@ export {
|
||||||
redef enum Log::ID += { LOG };
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
type Info: record {
|
type Info: record {
|
||||||
|
## Time when the SSL connection began.
|
||||||
ts: time &log;
|
ts: time &log;
|
||||||
uid: string &log;
|
uid: string &log;
|
||||||
id: conn_id &log;
|
id: conn_id &log;
|
||||||
|
|
|
@ -8,6 +8,7 @@ export {
|
||||||
redef enum Log::ID += { LOG };
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
type Info: record {
|
type Info: record {
|
||||||
|
## Timestamp of when the syslog message was seen.
|
||||||
ts: time &log;
|
ts: time &log;
|
||||||
uid: string &log;
|
uid: string &log;
|
||||||
id: conn_id &log;
|
id: conn_id &log;
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
module Known;
|
module Known;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
## The known-hosts logging stream identifier.
|
||||||
redef enum Log::ID += { HOSTS_LOG };
|
redef enum Log::ID += { HOSTS_LOG };
|
||||||
|
|
||||||
|
## The record type which contains the column fields of the known-hosts log.
|
||||||
type HostsInfo: record {
|
type HostsInfo: record {
|
||||||
## The timestamp at which the host was detected.
|
## The timestamp at which the host was detected.
|
||||||
ts: time &log;
|
ts: time &log;
|
||||||
|
@ -19,7 +21,7 @@ export {
|
||||||
};
|
};
|
||||||
|
|
||||||
## The hosts whose existence should be logged and tracked.
|
## The hosts whose existence should be logged and tracked.
|
||||||
## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS
|
## See :bro:type:`Host` for possible choices.
|
||||||
const host_tracking = LOCAL_HOSTS &redef;
|
const host_tracking = LOCAL_HOSTS &redef;
|
||||||
|
|
||||||
## The set of all known addresses to store for preventing duplicate
|
## The set of all known addresses to store for preventing duplicate
|
||||||
|
@ -28,7 +30,9 @@ export {
|
||||||
## Maintain the list of known hosts for 24 hours so that the existence
|
## Maintain the list of known hosts for 24 hours so that the existence
|
||||||
## of each individual address is logged each day.
|
## of each individual address is logged each day.
|
||||||
global known_hosts: set[addr] &create_expire=1day &synchronized &redef;
|
global known_hosts: set[addr] &create_expire=1day &synchronized &redef;
|
||||||
|
|
||||||
|
## An event that can be handled to access the :bro:type:`Known::HostsInfo`
|
||||||
|
## record as it is sent on to the logging framework.
|
||||||
global log_known_hosts: event(rec: HostsInfo);
|
global log_known_hosts: event(rec: HostsInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,29 +8,41 @@
|
||||||
module Known;
|
module Known;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
## The known-services logging stream identifier.
|
||||||
redef enum Log::ID += { SERVICES_LOG };
|
redef enum Log::ID += { SERVICES_LOG };
|
||||||
|
|
||||||
|
## The record type which contains the column fields of the known-services
|
||||||
|
## log.
|
||||||
type ServicesInfo: record {
|
type ServicesInfo: record {
|
||||||
|
## The time at which the service was detected.
|
||||||
ts: time &log;
|
ts: time &log;
|
||||||
|
## The host address on which the service is running.
|
||||||
host: addr &log;
|
host: addr &log;
|
||||||
|
## The port number on which the service is running.
|
||||||
port_num: port &log;
|
port_num: port &log;
|
||||||
|
## The transport-layer protocol which the service uses.
|
||||||
port_proto: transport_proto &log;
|
port_proto: transport_proto &log;
|
||||||
|
## A set of protocols that match the service's connection payloads.
|
||||||
service: set[string] &log;
|
service: set[string] &log;
|
||||||
|
|
||||||
done: bool &default=F;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
## The hosts whose services should be tracked and logged.
|
## The hosts whose services should be tracked and logged.
|
||||||
|
## See :bro:type:`Host` for possible choices.
|
||||||
const service_tracking = LOCAL_HOSTS &redef;
|
const service_tracking = LOCAL_HOSTS &redef;
|
||||||
|
|
||||||
|
## Tracks the set of daily-detected services for preventing the logging
|
||||||
|
## of duplicates, but can also be inspected by other scripts for
|
||||||
|
## different purposes.
|
||||||
global known_services: set[addr, port] &create_expire=1day &synchronized;
|
global known_services: set[addr, port] &create_expire=1day &synchronized;
|
||||||
|
|
||||||
|
## Event that can be handled to access the :bro:type:`Known::ServicesInfo`
|
||||||
|
## record as it is sent on to the logging framework.
|
||||||
global log_known_services: event(rec: ServicesInfo);
|
global log_known_services: event(rec: ServicesInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
redef record connection += {
|
redef record connection += {
|
||||||
## This field is to indicate whether or not the processing for detecting
|
# This field is to indicate whether or not the processing for detecting
|
||||||
## and logging the service for this connection is complete.
|
# and logging the service for this connection is complete.
|
||||||
known_services_done: bool &default=F;
|
known_services_done: bool &default=F;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -170,13 +170,26 @@ void BroDoc::WriteDocFile() const
|
||||||
{
|
{
|
||||||
WriteToDoc(".. Automatically generated. Do not edit.\n\n");
|
WriteToDoc(".. Automatically generated. Do not edit.\n\n");
|
||||||
|
|
||||||
|
WriteToDoc(":tocdepth: 3\n\n");
|
||||||
|
|
||||||
WriteSectionHeading(doc_title.c_str(), '=');
|
WriteSectionHeading(doc_title.c_str(), '=');
|
||||||
|
|
||||||
WriteToDoc("\n:download:`Original Source File <%s>`\n\n",
|
WriteStringList(".. bro:namespace:: %s\n", modules);
|
||||||
downloadable_filename.c_str());
|
|
||||||
|
|
||||||
WriteSectionHeading("Overview", '-');
|
WriteToDoc("\n");
|
||||||
WriteStringList("%s\n", "%s\n\n", summary);
|
|
||||||
|
// WriteSectionHeading("Overview", '-');
|
||||||
|
WriteStringList("%s\n", summary);
|
||||||
|
|
||||||
|
WriteToDoc("\n");
|
||||||
|
|
||||||
|
if ( ! modules.empty() )
|
||||||
|
{
|
||||||
|
WriteToDoc(":Namespace%s: ", (modules.size() > 1 ? "s" : ""));
|
||||||
|
// WriteStringList(":bro:namespace:`%s`", modules);
|
||||||
|
WriteStringList("``%s``, ", "``%s``", modules);
|
||||||
|
WriteToDoc("\n");
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! imports.empty() )
|
if ( ! imports.empty() )
|
||||||
{
|
{
|
||||||
|
@ -196,39 +209,38 @@ void BroDoc::WriteDocFile() const
|
||||||
WriteToDoc("\n");
|
WriteToDoc("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WriteToDoc(":Source File: :download:`%s`\n",
|
||||||
|
downloadable_filename.c_str());
|
||||||
|
|
||||||
WriteToDoc("\n");
|
WriteToDoc("\n");
|
||||||
|
|
||||||
WriteInterface("Summary", '~', '#', true, true);
|
WriteInterface("Summary", '~', '#', true, true);
|
||||||
|
|
||||||
if ( ! modules.empty() )
|
|
||||||
{
|
|
||||||
WriteSectionHeading("Namespaces", '~');
|
|
||||||
WriteStringList(".. bro:namespace:: %s\n", modules);
|
|
||||||
WriteToDoc("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! notices.empty() )
|
if ( ! notices.empty() )
|
||||||
WriteBroDocObjList(notices, "Notices", '~');
|
WriteBroDocObjList(notices, "Notices", '#');
|
||||||
|
|
||||||
WriteInterface("Public Interface", '-', '~', true, false);
|
if ( port_analysis.size() || packet_filter.size() )
|
||||||
|
WriteSectionHeading("Configuration Changes", '#');
|
||||||
|
|
||||||
if ( ! port_analysis.empty() )
|
if ( ! port_analysis.empty() )
|
||||||
{
|
{
|
||||||
WriteSectionHeading("Port Analysis", '-');
|
WriteSectionHeading("Port Analysis", '^');
|
||||||
WriteToDoc("Loading this script makes the following changes to "
|
WriteToDoc("Loading this script makes the following changes to "
|
||||||
":bro:see:`dpd_config`.\n\n");
|
":bro:see:`dpd_config`.\n\n");
|
||||||
WriteStringList("%s", port_analysis);
|
WriteStringList("%s, ", "%s", port_analysis);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! packet_filter.empty() )
|
if ( ! packet_filter.empty() )
|
||||||
{
|
{
|
||||||
WriteSectionHeading("Packet Filter", '-');
|
WriteSectionHeading("Packet Filter", '^');
|
||||||
WriteToDoc("Loading this script makes the following changes to "
|
WriteToDoc("Loading this script makes the following changes to "
|
||||||
":bro:see:`capture_filters`.\n\n");
|
":bro:see:`capture_filters`.\n\n");
|
||||||
WriteToDoc("Filters added::\n\n");
|
WriteToDoc("Filters added::\n\n");
|
||||||
WriteToDoc("%s\n", packet_filter.c_str());
|
WriteToDoc("%s\n", packet_filter.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WriteInterface("Detailed Interface", '~', '#', true, false);
|
||||||
|
|
||||||
#if 0 // Disabled for now.
|
#if 0 // Disabled for now.
|
||||||
BroDocObjList::const_iterator it;
|
BroDocObjList::const_iterator it;
|
||||||
bool hasPrivateIdentifiers = false;
|
bool hasPrivateIdentifiers = false;
|
||||||
|
@ -243,7 +255,7 @@ void BroDoc::WriteDocFile() const
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( hasPrivateIdentifiers )
|
if ( hasPrivateIdentifiers )
|
||||||
WriteInterface("Private Interface", '-', '~', false, false);
|
WriteInterface("Private Interface", '~', '#', false, false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
944
src/SSLv2.cc
944
src/SSLv2.cc
|
@ -1,944 +0,0 @@
|
||||||
#include "SSLv2.h"
|
|
||||||
#include "SSLv3.h"
|
|
||||||
|
|
||||||
// --- Initalization of static variables --------------------------------------
|
|
||||||
|
|
||||||
uint SSLv2_Interpreter::totalConnections = 0;
|
|
||||||
uint SSLv2_Interpreter::analyzedConnections = 0;
|
|
||||||
uint SSLv2_Interpreter::openedConnections = 0;
|
|
||||||
uint SSLv2_Interpreter::failedConnections = 0;
|
|
||||||
uint SSLv2_Interpreter::weirdConnections = 0;
|
|
||||||
uint SSLv2_Interpreter::totalRecords = 0;
|
|
||||||
uint SSLv2_Interpreter::clientHelloRecords = 0;
|
|
||||||
uint SSLv2_Interpreter::serverHelloRecords = 0;
|
|
||||||
uint SSLv2_Interpreter::clientMasterKeyRecords = 0;
|
|
||||||
uint SSLv2_Interpreter::errorRecords = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// --- SSLv2_Interpreter -------------------------------------------------------
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* The Constructor.
|
|
||||||
*
|
|
||||||
* \param proxy Pointer to the SSLProxy_Analyzer who created this instance.
|
|
||||||
*/
|
|
||||||
SSLv2_Interpreter::SSLv2_Interpreter(SSLProxy_Analyzer* proxy)
|
|
||||||
: SSL_Interpreter(proxy)
|
|
||||||
{
|
|
||||||
++totalConnections;
|
|
||||||
records = 0;
|
|
||||||
bAnalyzedCounted = false;
|
|
||||||
connState = START;
|
|
||||||
|
|
||||||
pServerCipherSpecs = 0;
|
|
||||||
pClientCipherSpecs = 0;
|
|
||||||
bClientWantsCachedSession = false;
|
|
||||||
usedCipherSpec = (SSLv2_CipherSpec) 0;
|
|
||||||
|
|
||||||
pConnectionId = 0;
|
|
||||||
pChallenge = 0;
|
|
||||||
pSessionId = 0;
|
|
||||||
pMasterClearKey = 0;
|
|
||||||
pMasterEncryptedKey = 0;
|
|
||||||
pClientReadKey = 0;
|
|
||||||
pServerReadKey = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* The Destructor.
|
|
||||||
*/
|
|
||||||
SSLv2_Interpreter::~SSLv2_Interpreter()
|
|
||||||
{
|
|
||||||
if ( connState != CLIENT_MASTERKEY_SEEN &&
|
|
||||||
connState != CACHED_SESSION &&
|
|
||||||
connState != START && // we only complain if we saw some data
|
|
||||||
connState != ERROR_SEEN )
|
|
||||||
++failedConnections;
|
|
||||||
|
|
||||||
if ( connState != CLIENT_MASTERKEY_SEEN && connState != CACHED_SESSION )
|
|
||||||
++weirdConnections;
|
|
||||||
|
|
||||||
delete pServerCipherSpecs;
|
|
||||||
delete pClientCipherSpecs;
|
|
||||||
delete pConnectionId;
|
|
||||||
delete pChallenge;
|
|
||||||
delete pSessionId;
|
|
||||||
delete pMasterClearKey;
|
|
||||||
delete pMasterEncryptedKey;
|
|
||||||
delete pClientReadKey;
|
|
||||||
delete pServerReadKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This method implements SSL_Interpreter::BuildInterpreterEndpoints()
|
|
||||||
*/
|
|
||||||
void SSLv2_Interpreter::BuildInterpreterEndpoints()
|
|
||||||
{
|
|
||||||
orig = new SSLv2_Endpoint(this, 1);
|
|
||||||
resp = new SSLv2_Endpoint(this, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This method prints some counters.
|
|
||||||
*/
|
|
||||||
void SSLv2_Interpreter::printStats()
|
|
||||||
{
|
|
||||||
printf("SSLv2:\n");
|
|
||||||
printf("totalConnections = %u\n", totalConnections);
|
|
||||||
printf("analyzedConnections = %u\n", analyzedConnections);
|
|
||||||
printf("openedConnections = %u\n", openedConnections);
|
|
||||||
printf("failedConnections = %u\n", failedConnections);
|
|
||||||
printf("weirdConnections = %u\n", weirdConnections);
|
|
||||||
|
|
||||||
printf("totalRecords = %u\n", totalRecords);
|
|
||||||
printf("clientHelloRecords = %u\n", clientHelloRecords);
|
|
||||||
printf("serverHelloRecords = %u\n", serverHelloRecords);
|
|
||||||
printf("clientMasterKeyRecords = %u\n", clientMasterKeyRecords);
|
|
||||||
printf("errorRecords = %u\n", errorRecords);
|
|
||||||
|
|
||||||
printf("SSL_RecordBuilder::maxAllocCount = %u\n", SSL_RecordBuilder::maxAllocCount);
|
|
||||||
printf("SSL_RecordBuilder::maxFragmentCount = %u\n", SSL_RecordBuilder::maxFragmentCount);
|
|
||||||
printf("SSL_RecordBuilder::fragmentedHeaders = %u\n", SSL_RecordBuilder::fragmentedHeaders);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \return the current state of the ssl connection
|
|
||||||
*/
|
|
||||||
SSLv2_States SSLv2_Interpreter::ConnState()
|
|
||||||
{
|
|
||||||
return connState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This method is called by SSLv2_Endpoint::Deliver(). It is the main entry
|
|
||||||
* point of this class. The header of the given SSLV2 record is analyzed and
|
|
||||||
* its contents are then passed to the corresponding analyzer method. After
|
|
||||||
* the record has been analyzed, the ssl connection state is updated.
|
|
||||||
*
|
|
||||||
* \param s Pointer to the endpoint which sent the record
|
|
||||||
* \param length length of SSLv2 record
|
|
||||||
* \param data pointer to SSLv2 record to analyze
|
|
||||||
*/
|
|
||||||
void SSLv2_Interpreter::NewSSLRecord(SSL_InterpreterEndpoint* s,
|
|
||||||
int length, const u_char* data)
|
|
||||||
{
|
|
||||||
++records;
|
|
||||||
++totalRecords;
|
|
||||||
|
|
||||||
if ( ! bAnalyzedCounted )
|
|
||||||
{
|
|
||||||
++analyzedConnections;
|
|
||||||
bAnalyzedCounted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should see a maximum of 4 cleartext records.
|
|
||||||
if ( records == 5 )
|
|
||||||
{ // so this should never happen
|
|
||||||
Weird("SSLv2: Saw more than 4 records, skipping connection...");
|
|
||||||
proxy->SetSkip(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SSLv2 record header analysis
|
|
||||||
uint32 recordLength = 0; // data length of SSLv2 record
|
|
||||||
bool isEscape = false;
|
|
||||||
uint8 padding = 0;
|
|
||||||
const u_char* contents;
|
|
||||||
|
|
||||||
if ( (data[0] & 0x80) > 0 )
|
|
||||||
{ // we have a two-byte record header
|
|
||||||
recordLength = ((data[0] & 0x7f) << 8) | data[1];
|
|
||||||
contents = data + 2;
|
|
||||||
if ( recordLength + 2 != uint32(length) )
|
|
||||||
{
|
|
||||||
// This should never happen, otherwise
|
|
||||||
// we have a bug in the SSL_RecordBuilder.
|
|
||||||
Weird("SSLv2: FATAL: recordLength doesn't match data block length!");
|
|
||||||
connState = ERROR_REQUIRED;
|
|
||||||
proxy->SetSkip(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // We have a three-byte record header.
|
|
||||||
recordLength = ((data[0] & 0x3f) << 8) | data[1];
|
|
||||||
isEscape = (data[0] & 0x40) != 0;
|
|
||||||
padding = data[2];
|
|
||||||
contents = data + 3;
|
|
||||||
if ( recordLength + 3 != uint32(length) )
|
|
||||||
{
|
|
||||||
// This should never happen, otherwise
|
|
||||||
// we have a bug in the SSL_RecordBuilder.
|
|
||||||
Weird("SSLv2: FATAL: recordLength doesn't match data block length!");
|
|
||||||
connState = ERROR_REQUIRED;
|
|
||||||
proxy->SetSkip(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( padding == 0 && ! isEscape )
|
|
||||||
Weird("SSLv2: 3 Byte record header, but no escape, no padding!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( recordLength == 0 )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Record length is zero (no record data)!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isEscape )
|
|
||||||
Weird("SSLv2: Record has escape bit set (security escape)!");
|
|
||||||
|
|
||||||
if ( padding > 0 && connState != CACHED_SESSION &&
|
|
||||||
connState != CLIENT_MASTERKEY_SEEN )
|
|
||||||
Weird("SSLv2 record with padding > 0 in cleartext!");
|
|
||||||
|
|
||||||
// MISSING:
|
|
||||||
// A final consistency check is done when a block cipher is used
|
|
||||||
// and the protocol is using encryption. The amount of data present
|
|
||||||
// in a record (RECORD-LENGTH))must be a multiple of the cipher's
|
|
||||||
// block size. If the received record is not a multiple of the
|
|
||||||
// cipher's block size then the record is considered damaged, and it
|
|
||||||
// is to be treated as if an "I/O Error" had occurred (i.e. an
|
|
||||||
// unrecoverable error is asserted and the connection is closed).
|
|
||||||
|
|
||||||
switch ( connState ) {
|
|
||||||
case START:
|
|
||||||
// Only CLIENT-HELLLOs allowed here.
|
|
||||||
if ( contents[0] != SSLv2_MT_CLIENT_HELLO )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: First packet is not a CLIENT-HELLO!");
|
|
||||||
analyzeRecord(s, recordLength, contents);
|
|
||||||
connState = ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
connState = ClientHelloRecord(s, recordLength, contents);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CLIENT_HELLO_SEEN:
|
|
||||||
// Only SERVER-HELLOs or ERRORs allowed here.
|
|
||||||
if ( contents[0] == SSLv2_MT_SERVER_HELLO )
|
|
||||||
connState = ServerHelloRecord(s, recordLength, contents);
|
|
||||||
else if ( contents[0] == SSLv2_MT_ERROR )
|
|
||||||
connState = ErrorRecord(s, recordLength, contents);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Weird("SSLv2: State violation in CLIENT_HELLO_SEEN!");
|
|
||||||
analyzeRecord(s, recordLength, contents);
|
|
||||||
connState = ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NEW_SESSION:
|
|
||||||
// We expect a client master key.
|
|
||||||
if ( contents[0] == SSLv2_MT_CLIENT_MASTER_KEY )
|
|
||||||
connState = ClientMasterKeyRecord(s, recordLength, contents);
|
|
||||||
else if ( contents[0] == SSLv2_MT_ERROR )
|
|
||||||
connState = ErrorRecord(s, recordLength, contents);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Weird("SSLv2: State violation in NEW_SESSION or encrypted record!");
|
|
||||||
analyzeRecord(s, recordLength, contents);
|
|
||||||
connState = ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete pServerCipherSpecs;
|
|
||||||
pServerCipherSpecs = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CACHED_SESSION:
|
|
||||||
delete pServerCipherSpecs;
|
|
||||||
pServerCipherSpecs = 0;
|
|
||||||
// No break here.
|
|
||||||
|
|
||||||
case CLIENT_MASTERKEY_SEEN:
|
|
||||||
// If no error record, no further analysis.
|
|
||||||
if ( contents[0] == SSLv2_MT_ERROR &&
|
|
||||||
recordLength == SSLv2_ERROR_RECORD_SIZE )
|
|
||||||
connState = ErrorRecord(s, recordLength, contents);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// So we finished the cleartext handshake.
|
|
||||||
// Skip all further data.
|
|
||||||
|
|
||||||
proxy->SetSkip(1);
|
|
||||||
++openedConnections;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ERROR_REQUIRED:
|
|
||||||
if ( contents[0] == SSLv2_MT_ERROR )
|
|
||||||
connState = ErrorRecord(s, recordLength, contents);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We lost tracking: this should not happen.
|
|
||||||
Weird("SSLv2: State inconsistency in ERROR_REQUIRED (lost tracking!)!");
|
|
||||||
analyzeRecord(s, recordLength, contents);
|
|
||||||
connState = ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ERROR_SEEN:
|
|
||||||
// We don't have recoverable errors in cleartext phase,
|
|
||||||
// so we shouldn't see anymore packets.
|
|
||||||
Weird("SSLv2: Traffic after error record!");
|
|
||||||
analyzeRecord(s, recordLength, contents);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
reporter->InternalError("SSLv2: unknown state");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This method is called whenever the connection tracking failed. It calls
|
|
||||||
* the corresponding analyzer method for the given SSLv2 record, but does not
|
|
||||||
* update the ssl connection state.
|
|
||||||
*
|
|
||||||
* \param s Pointer to the endpoint which sent the record
|
|
||||||
* \param length length of SSLv2 record
|
|
||||||
* \param data pointer to SSLv2 record to analyze
|
|
||||||
*/
|
|
||||||
void SSLv2_Interpreter::analyzeRecord(SSL_InterpreterEndpoint* s,
|
|
||||||
int length, const u_char* data)
|
|
||||||
{
|
|
||||||
switch ( data[0] ) {
|
|
||||||
case SSLv2_MT_ERROR:
|
|
||||||
ErrorRecord(s, length, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSLv2_MT_CLIENT_HELLO:
|
|
||||||
ClientHelloRecord(s, length, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSLv2_MT_CLIENT_MASTER_KEY:
|
|
||||||
ClientMasterKeyRecord(s, length, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSLv2_MT_SERVER_HELLO:
|
|
||||||
ServerHelloRecord(s, length, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSLv2_MT_CLIENT_FINISHED:
|
|
||||||
case SSLv2_MT_SERVER_VERIFY:
|
|
||||||
case SSLv2_MT_SERVER_FINISHED:
|
|
||||||
case SSLv2_MT_REQUEST_CERTIFICATE:
|
|
||||||
case SSLv2_MT_CLIENT_CERTIFICATE:
|
|
||||||
Weird("SSLv2: Encrypted record type seems to be in cleartext");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Unknown record type.
|
|
||||||
Weird("SSLv2: Unknown record type or encrypted record");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This method analyses a SSLv2 CLIENT-HELLO record.
|
|
||||||
*
|
|
||||||
* \param s Pointer to the endpoint which sent the record
|
|
||||||
* \param length length of SSLv2 CLIENT-HELLO record
|
|
||||||
* \param data pointer to SSLv2 CLIENT-HELLO record to analyze
|
|
||||||
*
|
|
||||||
* \return the updated state of the current ssl connection
|
|
||||||
*/
|
|
||||||
SSLv2_States SSLv2_Interpreter::ClientHelloRecord(SSL_InterpreterEndpoint* s,
|
|
||||||
int recordLength, const u_char* recordData)
|
|
||||||
{
|
|
||||||
// This method gets the record's data (without the header).
|
|
||||||
++clientHelloRecords;
|
|
||||||
|
|
||||||
if ( s != orig )
|
|
||||||
Weird("SSLv2: CLIENT-HELLO record from server!");
|
|
||||||
|
|
||||||
// There should not be any pending data in the SSLv2 reassembler,
|
|
||||||
// because the client should wait for a server response.
|
|
||||||
if ( ((SSLv2_Endpoint*) s)->isDataPending() )
|
|
||||||
Weird("SSLv2: Pending data in SSL_RecordBuilder after CLIENT-HELLO!");
|
|
||||||
|
|
||||||
// Client hello minimum header size check.
|
|
||||||
if ( recordLength < SSLv2_CLIENT_HELLO_HEADER_SIZE )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: CLIENT-HELLO is too small!");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the data of the client hello header.
|
|
||||||
SSLv2_ClientHelloHeader ch;
|
|
||||||
ch.clientVersion = uint16(recordData[1] << 8) | recordData[2];
|
|
||||||
ch.cipherSpecLength = uint16(recordData[3] << 8) | recordData[4];
|
|
||||||
ch.sessionIdLength = uint16(recordData[5] << 8) | recordData[6];
|
|
||||||
ch.challengeLength = uint16(recordData[7] << 8) | recordData[8];
|
|
||||||
|
|
||||||
if ( ch.clientVersion != SSLProxy_Analyzer::SSLv20 &&
|
|
||||||
ch.clientVersion != SSLProxy_Analyzer::SSLv30 &&
|
|
||||||
ch.clientVersion != SSLProxy_Analyzer::SSLv31 )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Unsupported SSL-Version in CLIENT-HELLO");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ch.challengeLength + ch.cipherSpecLength + ch.sessionIdLength +
|
|
||||||
SSLv2_CLIENT_HELLO_HEADER_SIZE != recordLength )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Size inconsistency in CLIENT-HELLO");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The CIPHER-SPECS-LENGTH must be > 0 and a multiple of 3.
|
|
||||||
if ( ch.cipherSpecLength == 0 || ch.cipherSpecLength % 3 != 0 )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Nonconform CIPHER-SPECS-LENGTH in CLIENT-HELLO.");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The SESSION-ID-LENGTH must either be zero or 16.
|
|
||||||
if ( ch.sessionIdLength != 0 && ch.sessionIdLength != 16 )
|
|
||||||
Weird("SSLv2: Nonconform SESSION-ID-LENGTH in CLIENT-HELLO.");
|
|
||||||
|
|
||||||
if ( (ch.challengeLength < 16) || (ch.challengeLength > 32))
|
|
||||||
Weird("SSLv2: Nonconform CHALLENGE-LENGTH in CLIENT-HELLO.");
|
|
||||||
|
|
||||||
const u_char* ptr = recordData;
|
|
||||||
ptr += SSLv2_CLIENT_HELLO_HEADER_SIZE + ch.cipherSpecLength;
|
|
||||||
|
|
||||||
pSessionId = new SSL_DataBlock(ptr, ch.sessionIdLength);
|
|
||||||
|
|
||||||
// If decrypting, store the challenge.
|
|
||||||
if ( ssl_store_key_material && ch.challengeLength <= 32 )
|
|
||||||
pChallenge = new SSL_DataBlock(ptr, ch.challengeLength);
|
|
||||||
|
|
||||||
bClientWantsCachedSession = ch.sessionIdLength != 0;
|
|
||||||
|
|
||||||
TableVal* currentCipherSuites =
|
|
||||||
analyzeCiphers(s, ch.cipherSpecLength,
|
|
||||||
recordData + SSLv2_CLIENT_HELLO_HEADER_SIZE);
|
|
||||||
|
|
||||||
fire_ssl_conn_attempt(ch.clientVersion, currentCipherSuites);
|
|
||||||
|
|
||||||
return CLIENT_HELLO_SEEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This method analyses a SSLv2 SERVER-HELLO record.
|
|
||||||
*
|
|
||||||
* \param s Pointer to the endpoint which sent the record
|
|
||||||
* \param length length of SSLv2 SERVER-HELLO record
|
|
||||||
* \param data pointer to SSLv2 SERVER-HELLO record to analyze
|
|
||||||
*
|
|
||||||
* \return the updated state of the current ssl connection
|
|
||||||
*/
|
|
||||||
SSLv2_States SSLv2_Interpreter::ServerHelloRecord(SSL_InterpreterEndpoint* s,
|
|
||||||
int recordLength, const u_char* recordData)
|
|
||||||
{
|
|
||||||
++serverHelloRecords;
|
|
||||||
TableVal* currentCipherSuites = NULL;
|
|
||||||
|
|
||||||
if ( s != resp )
|
|
||||||
Weird("SSLv2: SERVER-HELLO from client!");
|
|
||||||
|
|
||||||
if ( recordLength < SSLv2_SERVER_HELLO_HEADER_SIZE )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: SERVER-HELLO is too small!");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the data of the client hello header.
|
|
||||||
SSLv2_ServerHelloHeader sh;
|
|
||||||
sh.sessionIdHit = recordData[1];
|
|
||||||
sh.certificateType = recordData[2];
|
|
||||||
sh.serverVersion = uint16(recordData[3] << 8) | recordData[4];
|
|
||||||
sh.certificateLength = uint16(recordData[5] << 8) | recordData[6];
|
|
||||||
sh.cipherSpecLength = uint16(recordData[7] << 8) | recordData[8];
|
|
||||||
sh.connectionIdLength = uint16(recordData[9] << 8) | recordData[10];
|
|
||||||
|
|
||||||
if ( sh.serverVersion != SSLProxy_Analyzer::SSLv20 )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Unsupported SSL-Version in SERVER-HELLO");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( sh.certificateLength + sh.cipherSpecLength +
|
|
||||||
sh.connectionIdLength +
|
|
||||||
SSLv2_SERVER_HELLO_HEADER_SIZE != recordLength )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Size inconsistency in SERVER-HELLO");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The length of the CONNECTION-ID must be between 16 and 32 bytes.
|
|
||||||
if ( sh.connectionIdLength < 16 || sh.connectionIdLength > 32 )
|
|
||||||
Weird("SSLv2: Nonconform CONNECTION-ID-LENGTH in SERVER-HELLO");
|
|
||||||
|
|
||||||
// If decrypting, store the connection ID.
|
|
||||||
if ( ssl_store_key_material && sh.connectionIdLength <= 32 )
|
|
||||||
{
|
|
||||||
const u_char* ptr = recordData;
|
|
||||||
|
|
||||||
ptr += SSLv2_SERVER_HELLO_HEADER_SIZE + sh.cipherSpecLength +
|
|
||||||
sh.certificateLength;
|
|
||||||
|
|
||||||
pConnectionId = new SSL_DataBlock(ptr, sh.connectionIdLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( sh.sessionIdHit == 0 )
|
|
||||||
{
|
|
||||||
// Generating reusing-connection event.
|
|
||||||
EventHandlerPtr event = ssl_session_insertion;
|
|
||||||
|
|
||||||
if ( event )
|
|
||||||
{
|
|
||||||
TableVal* sessionIDTable =
|
|
||||||
MakeSessionID(
|
|
||||||
recordData +
|
|
||||||
SSLv2_SERVER_HELLO_HEADER_SIZE +
|
|
||||||
sh.certificateLength +
|
|
||||||
sh.cipherSpecLength,
|
|
||||||
sh.connectionIdLength);
|
|
||||||
|
|
||||||
val_list* vl = new val_list;
|
|
||||||
vl->append(proxy->BuildConnVal());
|
|
||||||
vl->append(sessionIDTable);
|
|
||||||
|
|
||||||
proxy->ConnectionEvent(ssl_session_insertion, vl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SSLv2_States nextState;
|
|
||||||
|
|
||||||
if ( sh.sessionIdHit != 0 )
|
|
||||||
{ // we're using a cached session
|
|
||||||
|
|
||||||
// There should not be any pending data in the SSLv2
|
|
||||||
// reassembler, because the server should wait for a
|
|
||||||
// client response.
|
|
||||||
if ( ((SSLv2_Endpoint*) s)->isDataPending() )
|
|
||||||
{
|
|
||||||
// But turns out some SSL Implementations do this
|
|
||||||
// when using a cached session.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consistency check for SESSION-ID-HIT.
|
|
||||||
if ( ! bClientWantsCachedSession )
|
|
||||||
Weird("SSLv2: SESSION-ID hit in SERVER-HELLO, but no SESSION-ID in CLIENT-HELLO!");
|
|
||||||
|
|
||||||
// If the SESSION-ID-HIT flag is non-zero then the
|
|
||||||
// CERTIFICATE-TYPE, CERTIFICATE-LENGTH and
|
|
||||||
// CIPHER-SPECS-LENGTH fields will be zero.
|
|
||||||
if ( sh.certificateType != 0 || sh.certificateLength != 0 ||
|
|
||||||
sh.cipherSpecLength != 0 )
|
|
||||||
Weird("SSLv2: SESSION-ID-HIT, but session data in SERVER-HELLO");
|
|
||||||
|
|
||||||
// Generate reusing-connection event.
|
|
||||||
if ( pSessionId )
|
|
||||||
{
|
|
||||||
fire_ssl_conn_reused(pSessionId);
|
|
||||||
delete pSessionId;
|
|
||||||
pSessionId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
nextState = CACHED_SESSION;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // we're starting a new session
|
|
||||||
|
|
||||||
// There should not be any pending data in the SSLv2
|
|
||||||
// reassembler, because the server should wait for
|
|
||||||
// a client response.
|
|
||||||
if ( ((SSLv2_Endpoint*) s)->isDataPending() )
|
|
||||||
Weird("SSLv2: Pending data in SSL_RecordBuilder after SERVER-HELLO (new session)!");
|
|
||||||
|
|
||||||
// TODO: check certificate length ???
|
|
||||||
if ( sh.certificateLength == 0 )
|
|
||||||
Weird("SSLv2: No certificate in SERVER-HELLO!");
|
|
||||||
|
|
||||||
// The CIPHER-SPECS-LENGTH must be > zero and a multiple of 3.
|
|
||||||
if ( sh.cipherSpecLength == 0 )
|
|
||||||
Weird("SSLv2: No CIPHER-SPECS in SERVER-HELLO!");
|
|
||||||
|
|
||||||
if ( sh.cipherSpecLength % 3 != 0 )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Nonconform CIPHER-SPECS-LENGTH in SERVER-HELLO");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u_char* ptr = recordData;
|
|
||||||
ptr += sh.certificateLength + SSLv2_SERVER_HELLO_HEADER_SIZE;
|
|
||||||
currentCipherSuites = analyzeCiphers(s, sh.cipherSpecLength, ptr);
|
|
||||||
|
|
||||||
nextState = NEW_SESSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if at least one cipher is supported by the client.
|
|
||||||
if ( pClientCipherSpecs && pServerCipherSpecs )
|
|
||||||
{
|
|
||||||
bool bFound = false;
|
|
||||||
for ( int i = 0; i < pClientCipherSpecs->len; i += 3 )
|
|
||||||
{
|
|
||||||
for ( int j = 0; j < pServerCipherSpecs->len; j += 3 )
|
|
||||||
{
|
|
||||||
if ( memcmp(pClientCipherSpecs + i,
|
|
||||||
pServerCipherSpecs + j, 3) == 0 )
|
|
||||||
{
|
|
||||||
bFound = true;
|
|
||||||
i = pClientCipherSpecs->len;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! bFound )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Client's and server's CIPHER-SPECS don't match!");
|
|
||||||
nextState = ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete pClientCipherSpecs;
|
|
||||||
pClientCipherSpecs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Certificate analysis.
|
|
||||||
if ( sh.certificateLength > 0 && ssl_analyze_certificates != 0 )
|
|
||||||
{
|
|
||||||
analyzeCertificate(s, recordData + SSLv2_SERVER_HELLO_HEADER_SIZE,
|
|
||||||
sh.certificateLength, sh.certificateType, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( nextState == NEW_SESSION )
|
|
||||||
// generate server-reply event
|
|
||||||
fire_ssl_conn_server_reply(sh.serverVersion, currentCipherSuites);
|
|
||||||
|
|
||||||
else if ( nextState == CACHED_SESSION )
|
|
||||||
{ // generate server-reply event
|
|
||||||
fire_ssl_conn_server_reply(sh.serverVersion, currentCipherSuites);
|
|
||||||
// Generate a connection-established event with a dummy
|
|
||||||
// cipher suite, since we can't remember session information
|
|
||||||
// (yet).
|
|
||||||
// Note: A new session identifier is sent encrypted in SSLv2!
|
|
||||||
fire_ssl_conn_established(sh.serverVersion, 0xABCD);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// Unref, since the table is not delivered to any event.
|
|
||||||
Unref(currentCipherSuites);
|
|
||||||
|
|
||||||
return nextState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This method analyses a SSLv2 CLIENT-MASTER-KEY record.
|
|
||||||
*
|
|
||||||
* \param s Pointer to the endpoint which sent the record
|
|
||||||
* \param length length of SSLv2 CLIENT-MASTER-KEY record
|
|
||||||
* \param data pointer to SSLv2 CLIENT-MASTER-KEY record to analyze
|
|
||||||
*
|
|
||||||
* \return the updated state of the current ssl connection
|
|
||||||
*/
|
|
||||||
SSLv2_States SSLv2_Interpreter::
|
|
||||||
ClientMasterKeyRecord(SSL_InterpreterEndpoint* s, int recordLength,
|
|
||||||
const u_char* recordData)
|
|
||||||
{
|
|
||||||
++clientMasterKeyRecords;
|
|
||||||
SSLv2_States nextState = CLIENT_MASTERKEY_SEEN;
|
|
||||||
|
|
||||||
if ( s != orig )
|
|
||||||
Weird("SSLv2: CLIENT-MASTER-KEY from server!");
|
|
||||||
|
|
||||||
if ( recordLength < SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: CLIENT-MASTER-KEY is too small!");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the data of the client master key header.
|
|
||||||
SSLv2_ClientMasterKeyHeader cmk;
|
|
||||||
cmk.cipherKind =
|
|
||||||
((recordData[1] << 16) | recordData[2] << 8) | recordData[3];
|
|
||||||
cmk.clearKeyLength = uint16(recordData[4] << 8) | recordData[5];
|
|
||||||
cmk.encryptedKeyLength = uint16(recordData[6] << 8) | recordData[7];
|
|
||||||
cmk.keyArgLength = uint16(recordData[8] << 8) | recordData[9];
|
|
||||||
|
|
||||||
if ( cmk.clearKeyLength + cmk.encryptedKeyLength + cmk.keyArgLength +
|
|
||||||
SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE != recordLength )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Size inconsistency in CLIENT-MASTER-KEY");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if cipher is supported by the server.
|
|
||||||
if ( pServerCipherSpecs )
|
|
||||||
{
|
|
||||||
bool bFound = false;
|
|
||||||
for ( int i = 0; i < pServerCipherSpecs->len; i += 3 )
|
|
||||||
{
|
|
||||||
uint32 cipherSpec =
|
|
||||||
((pServerCipherSpecs->data[i] << 16) |
|
|
||||||
pServerCipherSpecs->data[i+1] << 8) |
|
|
||||||
pServerCipherSpecs->data[i+2];
|
|
||||||
|
|
||||||
if ( cmk.cipherKind == cipherSpec )
|
|
||||||
{
|
|
||||||
bFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! bFound )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Client chooses unadvertised cipher in CLIENT-MASTER-KEY!");
|
|
||||||
nextState = ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
nextState = CLIENT_MASTERKEY_SEEN;
|
|
||||||
|
|
||||||
delete pServerCipherSpecs;
|
|
||||||
pServerCipherSpecs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check if cipher has been advertised before.
|
|
||||||
|
|
||||||
SSL_CipherSpec* pCipherSpecTemp = 0;
|
|
||||||
|
|
||||||
HashKey h(static_cast<bro_uint_t>(cmk.cipherKind));
|
|
||||||
pCipherSpecTemp = (SSL_CipherSpec*) SSL_CipherSpecDict.Lookup(&h);
|
|
||||||
if ( ! pCipherSpecTemp || ! (pCipherSpecTemp->flags & SSL_FLAG_SSLv20) )
|
|
||||||
Weird("SSLv2: Unknown CIPHER-SPEC in CLIENT-MASTER-KEY!");
|
|
||||||
else
|
|
||||||
{ // check for conistency of clearKeyLength
|
|
||||||
if ( cmk.clearKeyLength * 8 != pCipherSpecTemp->clearKeySize )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Inconsistency of clearKeyLength in CLIENT-MASTER-KEY!");
|
|
||||||
// nextState = ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check for consistency of encryptedKeyLength.
|
|
||||||
// TODO: check for consistency of keyArgLength.
|
|
||||||
// switch ( cmk.cipherKind )
|
|
||||||
// {
|
|
||||||
// case SSL_CK_RC4_128_WITH_MD5:
|
|
||||||
// case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
|
|
||||||
// if ( cmk.keyArgLength != 0 )
|
|
||||||
// {
|
|
||||||
// Weird("SSLv2: Inconsistency of keyArgLength in CLIENT-MASTER-KEY!");
|
|
||||||
// //nextState = ERROR_REQUIRED;
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// case SSL_CK_DES_64_CBC_WITH_MD5:
|
|
||||||
// case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
|
|
||||||
// case SSL_CK_RC2_128_CBC_WITH_MD5:
|
|
||||||
// case SSL_CK_IDEA_128_CBC_WITH_MD5:
|
|
||||||
// case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
|
|
||||||
// if ( cmk.keyArgLength != 8 )
|
|
||||||
// {
|
|
||||||
// Weird("SSLv2: Inconsistency of keyArgLength in CLIENT-MASTER-KEY!");
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember the used cipher spec.
|
|
||||||
usedCipherSpec = SSLv2_CipherSpec(cmk.cipherKind);
|
|
||||||
|
|
||||||
// If decrypting, store the clear key part of the master key.
|
|
||||||
if ( ssl_store_key_material /* && cmk.clearKeyLength == 11 */ )
|
|
||||||
{
|
|
||||||
pMasterClearKey =
|
|
||||||
new SSL_DataBlock((recordData + SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE), cmk.clearKeyLength);
|
|
||||||
|
|
||||||
pMasterEncryptedKey =
|
|
||||||
new SSL_DataBlock((recordData + SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE + cmk.clearKeyLength ), cmk.encryptedKeyLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( nextState == CLIENT_MASTERKEY_SEEN )
|
|
||||||
fire_ssl_conn_established(SSLProxy_Analyzer::SSLv20,
|
|
||||||
cmk.cipherKind);
|
|
||||||
|
|
||||||
return nextState;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This method analyses a SSLv2 ERROR record.
|
|
||||||
*
|
|
||||||
* \param s Pointer to the endpoint which sent the record
|
|
||||||
* \param length length of SSLv2 ERROR record
|
|
||||||
* \param data pointer to SSLv2 ERROR record to analyze
|
|
||||||
*
|
|
||||||
* \return the updated state of the current ssl connection
|
|
||||||
*/
|
|
||||||
SSLv2_States SSLv2_Interpreter::ErrorRecord(SSL_InterpreterEndpoint* s,
|
|
||||||
int recordLength, const u_char* recordData)
|
|
||||||
{
|
|
||||||
++errorRecords;
|
|
||||||
|
|
||||||
if ( unsigned(recordLength) != SSLv2_ERROR_RECORD_SIZE )
|
|
||||||
{
|
|
||||||
Weird("SSLv2: Size mismatch in Error Record!");
|
|
||||||
return ERROR_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSLv2_ErrorRecord er;
|
|
||||||
er.errorCode = (recordData[1] << 8) | recordData[2];
|
|
||||||
SSL3x_AlertLevel al = SSL3x_AlertLevel(255);
|
|
||||||
|
|
||||||
switch ( er.errorCode ) {
|
|
||||||
case SSLv2_PE_NO_CIPHER:
|
|
||||||
// The client doesn't support a cipher which the server
|
|
||||||
// supports. Only from client to server and not recoverable!
|
|
||||||
al = SSL3x_ALERT_LEVEL_FATAL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSLv2_PE_NO_CERTIFICATE:
|
|
||||||
if ( s == orig )
|
|
||||||
// from client to server: not recoverable
|
|
||||||
al = SSL3x_ALERT_LEVEL_FATAL;
|
|
||||||
else
|
|
||||||
// from server to client: recoverable
|
|
||||||
al = SSL3x_ALERT_LEVEL_WARNING;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSLv2_PE_BAD_CERTIFICATE:
|
|
||||||
if ( s == orig )
|
|
||||||
// from client to server: not recoverable
|
|
||||||
al = SSL3x_ALERT_LEVEL_FATAL;
|
|
||||||
else
|
|
||||||
// from server to client: recoverable
|
|
||||||
al = SSL3x_ALERT_LEVEL_WARNING;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSLv2_PE_UNSUPPORTED_CERTIFICATE_TYPE:
|
|
||||||
if ( s == orig )
|
|
||||||
// from client to server: not recoverable
|
|
||||||
al = SSL3x_ALERT_LEVEL_FATAL;
|
|
||||||
else
|
|
||||||
// from server to client: recoverable
|
|
||||||
al = SSL3x_ALERT_LEVEL_WARNING;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
al = SSL3x_ALERT_LEVEL_FATAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fire_ssl_conn_alert(SSLProxy_Analyzer::SSLv20, al, er.errorCode);
|
|
||||||
|
|
||||||
return ERROR_SEEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This method analyses a set of SSLv2 cipher suites.
|
|
||||||
*
|
|
||||||
* \param s Pointer to the endpoint which sent the cipher suites
|
|
||||||
* \param length length of cipher suites
|
|
||||||
* \param data pointer to cipher suites to analyze
|
|
||||||
*
|
|
||||||
* \return a pointer to a Bro TableVal (of type cipher_suites_list) which contains
|
|
||||||
* the cipher suites list of the current analyzed record
|
|
||||||
*/
|
|
||||||
TableVal* SSLv2_Interpreter::analyzeCiphers(SSL_InterpreterEndpoint* s,
|
|
||||||
int length, const u_char* data)
|
|
||||||
{
|
|
||||||
if ( length > MAX_CIPHERSPEC_SIZE )
|
|
||||||
{
|
|
||||||
if ( s == orig )
|
|
||||||
Weird("SSLv2: Client has CipherSpecs > MAX_CIPHERSPEC_SIZE");
|
|
||||||
else
|
|
||||||
Weird("SSLv2: Server has CipherSpecs > MAX_CIPHERSPEC_SIZE");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // cipher specs are not too big
|
|
||||||
if ( ssl_compare_cipherspecs )
|
|
||||||
{ // store cipher specs for state analysis
|
|
||||||
if ( s == resp )
|
|
||||||
pServerCipherSpecs =
|
|
||||||
new SSL_DataBlock(data, length);
|
|
||||||
else
|
|
||||||
pClientCipherSpecs =
|
|
||||||
new SSL_DataBlock(data, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const u_char* pCipher = data;
|
|
||||||
bool bExtractCipherSuite = false;
|
|
||||||
TableVal* pCipherTable = 0;
|
|
||||||
|
|
||||||
// We only extract the cipher suite when the corresponding
|
|
||||||
// ssl events are defined (otherwise we do work for nothing
|
|
||||||
// and suffer a memory leak).
|
|
||||||
// FIXME: This check needs to be done only once!
|
|
||||||
if ( (s == orig && ssl_conn_attempt) ||
|
|
||||||
(s == resp && ssl_conn_server_reply) )
|
|
||||||
{
|
|
||||||
pCipherTable = new TableVal(cipher_suites_list);
|
|
||||||
bExtractCipherSuite = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( int i = 0; i < length; i += 3 )
|
|
||||||
{
|
|
||||||
SSL_CipherSpec* pCurrentCipherSpec;
|
|
||||||
uint32 cipherSpecID =
|
|
||||||
((pCipher[0] << 16) | pCipher[1] << 8) | pCipher[2];
|
|
||||||
|
|
||||||
// Check for unknown cipher specs.
|
|
||||||
HashKey h(static_cast<bro_uint_t>(cipherSpecID));
|
|
||||||
pCurrentCipherSpec =
|
|
||||||
(SSL_CipherSpec*) SSL_CipherSpecDict.Lookup(&h);
|
|
||||||
|
|
||||||
if ( ! pCurrentCipherSpec )
|
|
||||||
{
|
|
||||||
if ( s == orig )
|
|
||||||
Weird("SSLv2: Unknown CIPHER-SPEC in CLIENT-HELLO!");
|
|
||||||
else
|
|
||||||
Weird("SSLv2: Unknown CIPHER-SPEC in SERVER-HELLO!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bExtractCipherSuite )
|
|
||||||
{
|
|
||||||
Val* index = new Val(cipherSpecID, TYPE_COUNT);
|
|
||||||
pCipherTable->Assign(index, 0);
|
|
||||||
Unref(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
pCipher += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pCipherTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- SSLv2_EndPoint ---------------------------------------------------------
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* The constructor.
|
|
||||||
*
|
|
||||||
* \param interpreter Pointer to the SSLv2 interpreter to whom this endpoint belongs to
|
|
||||||
* \param is_orig true if this is the originating endpoint of the ssl connection,
|
|
||||||
* false otherwise
|
|
||||||
*/
|
|
||||||
SSLv2_Endpoint::SSLv2_Endpoint(SSLv2_Interpreter* interpreter, int is_orig)
|
|
||||||
: SSL_InterpreterEndpoint(interpreter, is_orig)
|
|
||||||
{
|
|
||||||
sentRecords = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* The destructor.
|
|
||||||
*/
|
|
||||||
SSLv2_Endpoint::~SSLv2_Endpoint()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* This method is called by the SSLProxy_Analyzer with a complete reassembled
|
|
||||||
* SSLv2 record. It passes the record to SSLv2_Interpreter::NewSSLRecord().
|
|
||||||
*
|
|
||||||
* \param t <b>reserved</b> (always zero)
|
|
||||||
* \param seq <b>reserved</b> (always zero)
|
|
||||||
* \param len length of the data block containing the ssl record
|
|
||||||
* \param data pointer to the data block containing the ssl record
|
|
||||||
*/
|
|
||||||
void SSLv2_Endpoint::Deliver(int len, const u_char* data)
|
|
||||||
{
|
|
||||||
++((SSLv2_Endpoint*)peer)->sentRecords;
|
|
||||||
|
|
||||||
((SSLv2_Interpreter*)interpreter)->NewSSLRecord(this, len, data);
|
|
||||||
}
|
|
|
@ -121,7 +121,7 @@ protected:
|
||||||
|
|
||||||
// This will be increased whenever there is an incompatible change
|
// This will be increased whenever there is an incompatible change
|
||||||
// in the data format.
|
// in the data format.
|
||||||
static const uint32 DATA_FORMAT_VERSION = 20;
|
static const uint32 DATA_FORMAT_VERSION = 21;
|
||||||
|
|
||||||
ChunkedIO* io;
|
ChunkedIO* io;
|
||||||
|
|
||||||
|
|
154
src/Type.cc
154
src/Type.cc
|
@ -876,74 +876,12 @@ void CommentedTypeDecl::DescribeReST(ODesc* d) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordField::RecordField(int arg_base, int arg_offset, int arg_total_offset)
|
|
||||||
{
|
|
||||||
base = arg_base;
|
|
||||||
offset = arg_offset;
|
|
||||||
total_offset = arg_total_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordType::RecordType(type_decl_list* arg_types) : BroType(TYPE_RECORD)
|
RecordType::RecordType(type_decl_list* arg_types) : BroType(TYPE_RECORD)
|
||||||
{
|
{
|
||||||
types = arg_types;
|
types = arg_types;
|
||||||
base = 0;
|
|
||||||
fields = 0;
|
|
||||||
num_fields = types ? types->length() : 0;
|
num_fields = types ? types->length() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordType::RecordType(TypeList* arg_base, type_decl_list* refinements)
|
|
||||||
: BroType(TYPE_RECORD)
|
|
||||||
{
|
|
||||||
if ( refinements )
|
|
||||||
arg_base->Append(new RecordType(refinements));
|
|
||||||
|
|
||||||
Init(arg_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecordType::Init(TypeList* arg_base)
|
|
||||||
{
|
|
||||||
assert(false); // Is this ever used?
|
|
||||||
|
|
||||||
base = arg_base;
|
|
||||||
|
|
||||||
if ( ! base )
|
|
||||||
Internal("empty RecordType");
|
|
||||||
|
|
||||||
fields = new PDict(RecordField)(ORDERED);
|
|
||||||
types = 0;
|
|
||||||
|
|
||||||
type_list* t = base->Types();
|
|
||||||
|
|
||||||
loop_over_list(*t, i)
|
|
||||||
{
|
|
||||||
BroType* ti = (*t)[i];
|
|
||||||
|
|
||||||
if ( ti->Tag() != TYPE_RECORD )
|
|
||||||
(*t)[i]->Error("non-record in base type list");
|
|
||||||
|
|
||||||
RecordType* rti = ti->AsRecordType();
|
|
||||||
int n = rti->NumFields();
|
|
||||||
|
|
||||||
for ( int j = 0; j < n; ++j )
|
|
||||||
{
|
|
||||||
const TypeDecl* tdij = rti->FieldDecl(j);
|
|
||||||
|
|
||||||
if ( fields->Lookup(tdij->id) )
|
|
||||||
{
|
|
||||||
reporter->Error("duplicate field %s", tdij->id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordField* rf = new RecordField(i, j, fields->Length());
|
|
||||||
|
|
||||||
if ( fields->Insert(tdij->id, rf) )
|
|
||||||
Internal("duplicate field when constructing record");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
num_fields = fields->Length();
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordType::~RecordType()
|
RecordType::~RecordType()
|
||||||
{
|
{
|
||||||
if ( types )
|
if ( types )
|
||||||
|
@ -953,9 +891,6 @@ RecordType::~RecordType()
|
||||||
|
|
||||||
delete types;
|
delete types;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete fields;
|
|
||||||
Unref(base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int RecordType::HasField(const char* field) const
|
int RecordType::HasField(const char* field) const
|
||||||
|
@ -971,17 +906,7 @@ BroType* RecordType::FieldType(const char* field) const
|
||||||
|
|
||||||
BroType* RecordType::FieldType(int field) const
|
BroType* RecordType::FieldType(int field) const
|
||||||
{
|
{
|
||||||
if ( types )
|
return (*types)[field]->type;
|
||||||
return (*types)[field]->type;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RecordField* rf = fields->NthEntry(field);
|
|
||||||
if ( ! rf )
|
|
||||||
Internal("missing field in RecordType::FieldType");
|
|
||||||
BroType* bt = (*base->Types())[rf->base];
|
|
||||||
RecordType* rbt = bt->AsRecordType();
|
|
||||||
return rbt->FieldType(rf->offset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* RecordType::FieldDefault(int field) const
|
Val* RecordType::FieldDefault(int field) const
|
||||||
|
@ -998,26 +923,14 @@ Val* RecordType::FieldDefault(int field) const
|
||||||
|
|
||||||
int RecordType::FieldOffset(const char* field) const
|
int RecordType::FieldOffset(const char* field) const
|
||||||
{
|
{
|
||||||
if ( types )
|
loop_over_list(*types, i)
|
||||||
{
|
{
|
||||||
loop_over_list(*types, i)
|
TypeDecl* td = (*types)[i];
|
||||||
{
|
if ( streq(td->id, field) )
|
||||||
TypeDecl* td = (*types)[i];
|
return i;
|
||||||
if ( streq(td->id, field) )
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
return -1;
|
||||||
{
|
|
||||||
RecordField* rf = fields->Lookup(field);
|
|
||||||
if ( ! rf )
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return rf->total_offset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* RecordType::FieldName(int field) const
|
const char* RecordType::FieldName(int field) const
|
||||||
|
@ -1027,33 +940,12 @@ const char* RecordType::FieldName(int field) const
|
||||||
|
|
||||||
const TypeDecl* RecordType::FieldDecl(int field) const
|
const TypeDecl* RecordType::FieldDecl(int field) const
|
||||||
{
|
{
|
||||||
if ( types )
|
return (*types)[field];
|
||||||
return (*types)[field];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RecordField* rf = fields->NthEntry(field);
|
|
||||||
if ( ! rf )
|
|
||||||
reporter->InternalError("missing field in RecordType::FieldDecl");
|
|
||||||
|
|
||||||
BroType* bt = (*base->Types())[rf->base];
|
|
||||||
RecordType* rbt = bt->AsRecordType();
|
|
||||||
return rbt->FieldDecl(rf->offset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeDecl* RecordType::FieldDecl(int field)
|
TypeDecl* RecordType::FieldDecl(int field)
|
||||||
{
|
{
|
||||||
if ( types )
|
return (*types)[field];
|
||||||
return (*types)[field];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RecordField* rf = fields->NthEntry(field);
|
|
||||||
if ( ! rf )
|
|
||||||
Internal("missing field in RecordType::FieldDecl");
|
|
||||||
BroType* bt = (*base->Types())[rf->base];
|
|
||||||
RecordType* rbt = bt->AsRecordType();
|
|
||||||
return rbt->FieldDecl(rf->offset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordType::Describe(ODesc* d) const
|
void RecordType::Describe(ODesc* d) const
|
||||||
|
@ -1151,11 +1043,6 @@ void RecordType::DescribeFields(ODesc* d) const
|
||||||
d->SP();
|
d->SP();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
d->AddCount(1);
|
|
||||||
base->Describe(d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1208,9 +1095,6 @@ bool RecordType::DoSerialize(SerialInfo* info) const
|
||||||
else if ( ! SERIALIZE(false) )
|
else if ( ! SERIALIZE(false) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SERIALIZE_OPTIONAL(base);
|
|
||||||
|
|
||||||
// We don't serialize the fields as we can reconstruct them.
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1245,13 +1129,6 @@ bool RecordType::DoUnserialize(UnserialInfo* info)
|
||||||
else
|
else
|
||||||
types = 0;
|
types = 0;
|
||||||
|
|
||||||
BroType* type;
|
|
||||||
UNSERIALIZE_OPTIONAL(type, BroType::Unserialize(info, TYPE_LIST));
|
|
||||||
base = (TypeList*) type;
|
|
||||||
|
|
||||||
if ( base )
|
|
||||||
Init(base);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1594,21 +1471,6 @@ bool VectorType::DoUnserialize(UnserialInfo* info)
|
||||||
return yield_type != 0;
|
return yield_type != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BroType* refine_type(TypeList* base, type_decl_list* refinements)
|
|
||||||
{
|
|
||||||
type_list* t = base->Types();
|
|
||||||
|
|
||||||
if ( t->length() == 1 && ! refinements )
|
|
||||||
{ // Just a direct reference to a single type.
|
|
||||||
BroType* rt = (*t)[0]->Ref();
|
|
||||||
Unref(base);
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RecordType(base, refinements);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BroType* base_type(TypeTag tag)
|
BroType* base_type(TypeTag tag)
|
||||||
{
|
{
|
||||||
static BroType* base_types[NUM_TYPES];
|
static BroType* base_types[NUM_TYPES];
|
||||||
|
|
21
src/Type.h
21
src/Type.h
|
@ -426,20 +426,9 @@ public:
|
||||||
std::list<std::string>* comments;
|
std::list<std::string>* comments;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RecordField {
|
|
||||||
public:
|
|
||||||
RecordField(int arg_base, int arg_offset, int arg_total_offset);
|
|
||||||
|
|
||||||
int base; // which base element it belongs to
|
|
||||||
int offset; // where it is in that base
|
|
||||||
int total_offset; // where it is in the aggregate record
|
|
||||||
};
|
|
||||||
declare(PDict,RecordField);
|
|
||||||
|
|
||||||
class RecordType : public BroType {
|
class RecordType : public BroType {
|
||||||
public:
|
public:
|
||||||
RecordType(type_decl_list* types);
|
RecordType(type_decl_list* types);
|
||||||
RecordType(TypeList* base, type_decl_list* refinements);
|
|
||||||
|
|
||||||
~RecordType();
|
~RecordType();
|
||||||
|
|
||||||
|
@ -473,15 +462,11 @@ public:
|
||||||
void DescribeFieldsReST(ODesc* d, bool func_args) const;
|
void DescribeFieldsReST(ODesc* d, bool func_args) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RecordType() { fields = 0; base = 0; types = 0; }
|
RecordType() { types = 0; }
|
||||||
|
|
||||||
void Init(TypeList* arg_base);
|
|
||||||
|
|
||||||
DECLARE_SERIAL(RecordType)
|
DECLARE_SERIAL(RecordType)
|
||||||
|
|
||||||
int num_fields;
|
int num_fields;
|
||||||
PDict(RecordField)* fields;
|
|
||||||
TypeList* base;
|
|
||||||
type_decl_list* types;
|
type_decl_list* types;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -587,10 +572,6 @@ protected:
|
||||||
BroType* yield_type;
|
BroType* yield_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Returns the given type refinement, or error_type() if it's illegal.
|
|
||||||
extern BroType* refine_type(TypeList* base, type_decl_list* refinements);
|
|
||||||
|
|
||||||
// Returns the BRO basic (non-parameterized) type with the given type.
|
// Returns the BRO basic (non-parameterized) type with the given type.
|
||||||
extern BroType* base_type(TypeTag tag);
|
extern BroType* base_type(TypeTag tag);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
# Definitions of Bro built-in functions.
|
##! A collection of built-in functions that implement a variety of things
|
||||||
|
##! such as general programming algorithms, string processing, math functions,
|
||||||
|
##! introspection, type conversion, file/directory manipulation, packet
|
||||||
|
##! filtering, inter-process communication and controlling protocol analyzer
|
||||||
|
##! behavior.
|
||||||
|
|
||||||
%%{ // C segment
|
%%{ // C segment
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
# Documentation and default values for these are located in policy/bro.init.
|
##! Declaration of various scripting-layer constants that the Bro core uses
|
||||||
|
##! internally. Documentation and default values for the scripting-layer
|
||||||
|
##! variables themselves are found in :doc:`/scripts/base/init-bare`.
|
||||||
|
|
||||||
const ignore_keep_alive_rexmit: bool;
|
const ignore_keep_alive_rexmit: bool;
|
||||||
const skip_http_data: bool;
|
const skip_http_data: bool;
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
##! The events that the C/C++ core of Bro can generate. This is mostly
|
||||||
|
##! consisting of high-level network events that protocol analyzers detect,
|
||||||
|
##! but there are also several general-utility events generated by internal
|
||||||
|
##! Bro frameworks.
|
||||||
|
|
||||||
#
|
#
|
||||||
# Documentation conventions:
|
# Documentation conventions:
|
||||||
#
|
#
|
||||||
|
@ -4574,7 +4579,8 @@ event ssh_server_version%(c: connection, version: string%);
|
||||||
## maps them to descriptive names.
|
## maps them to descriptive names.
|
||||||
##
|
##
|
||||||
## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello
|
## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello
|
||||||
## x509_certificate x509_error x509_extension ssl_max_cipherspec_size
|
## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
|
||||||
|
## ssl_max_cipherspec_size
|
||||||
event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%);
|
event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%);
|
||||||
|
|
||||||
## Generated for an SSL/TLS servers's initial *hello* message. SSL/TLS sessions
|
## Generated for an SSL/TLS servers's initial *hello* message. SSL/TLS sessions
|
||||||
|
@ -4604,7 +4610,8 @@ event ssl_client_hello%(c: connection, version: count, possible_ts: time, sessio
|
||||||
## standardized as part of the SSL/TLS protocol.
|
## standardized as part of the SSL/TLS protocol.
|
||||||
##
|
##
|
||||||
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension
|
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension
|
||||||
## x509_certificate x509_error x509_extension ssl_max_cipherspec_size
|
## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
|
||||||
|
## ssl_max_cipherspec_size
|
||||||
event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%);
|
event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%);
|
||||||
|
|
||||||
## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS sessions
|
## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS sessions
|
||||||
|
@ -4623,7 +4630,7 @@ event ssl_server_hello%(c: connection, version: count, possible_ts: time, sessio
|
||||||
## val: The raw extension value that was sent in the message.
|
## val: The raw extension value that was sent in the message.
|
||||||
##
|
##
|
||||||
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello
|
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello
|
||||||
## x509_certificate x509_error x509_extension
|
## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
|
||||||
event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);
|
event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);
|
||||||
|
|
||||||
## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with
|
## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with
|
||||||
|
@ -4638,7 +4645,7 @@ event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);
|
||||||
## c: The connection.
|
## c: The connection.
|
||||||
##
|
##
|
||||||
## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello
|
## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello
|
||||||
## x509_certificate x509_error x509_extension
|
## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
|
||||||
event ssl_established%(c: connection%);
|
event ssl_established%(c: connection%);
|
||||||
|
|
||||||
## Generated for SSL/TLS alert records. SSL/TLS sessions start with an unencrypted
|
## Generated for SSL/TLS alert records. SSL/TLS sessions start with an unencrypted
|
||||||
|
@ -4661,9 +4668,30 @@ event ssl_established%(c: connection%);
|
||||||
## defined as part of the SSL/TLS protocol.
|
## defined as part of the SSL/TLS protocol.
|
||||||
##
|
##
|
||||||
## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello
|
## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello
|
||||||
## x509_certificate x509_error x509_extension
|
## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
|
||||||
event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%);
|
event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%);
|
||||||
|
|
||||||
|
## Generated for SSL/TLS handshake messages that are a part of the stateless-server
|
||||||
|
## session resumption mechanism. SSL/TLS sessions start with an unencrypted
|
||||||
|
## handshake, and Bro extracts as much information out of that as it can. This
|
||||||
|
## event is raised when an SSL/TLS server passes session ticket to the client that
|
||||||
|
## can later be used for resuming the session. The mechanism is described in
|
||||||
|
## :rfc:`4507`
|
||||||
|
##
|
||||||
|
## See `Wikipedia <http://en.wikipedia.org/wiki/Transport_Layer_Security>`__ for
|
||||||
|
## more information about the SSL/TLS protocol.
|
||||||
|
##
|
||||||
|
## c: The connection.
|
||||||
|
##
|
||||||
|
## ticket_lifetime_hint: A hint from the server about how long the ticket
|
||||||
|
## should be stored by the client.
|
||||||
|
##
|
||||||
|
## ticket: The raw ticket data.
|
||||||
|
##
|
||||||
|
## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello
|
||||||
|
## x509_certificate x509_error x509_extension ssl_alert
|
||||||
|
event ssl_session_ticket_handshake%(c: connection, ticket_lifetime_hint: count, ticket: string%);
|
||||||
|
|
||||||
## Generated for x509 certificates seen in SSL/TLS connections. During the initial
|
## Generated for x509 certificates seen in SSL/TLS connections. During the initial
|
||||||
## SSL/TLS handshake, certificates are exchanged in the clear. Bro raises this
|
## SSL/TLS handshake, certificates are exchanged in the clear. Bro raises this
|
||||||
## event for each certificate seen (including both a site's primary cert, and
|
## event for each certificate seen (including both a site's primary cert, and
|
||||||
|
|
10
src/main.cc
10
src/main.cc
|
@ -97,7 +97,7 @@ extern char version[];
|
||||||
char* command_line_policy = 0;
|
char* command_line_policy = 0;
|
||||||
vector<string> params;
|
vector<string> params;
|
||||||
char* proc_status_file = 0;
|
char* proc_status_file = 0;
|
||||||
int snaplen = 65535; // really want "capture entire packet"
|
int snaplen = 0; // this gets set from the scripting-layer's value
|
||||||
|
|
||||||
int FLAGS_use_binpac = false;
|
int FLAGS_use_binpac = false;
|
||||||
|
|
||||||
|
@ -145,7 +145,6 @@ void usage()
|
||||||
fprintf(stderr, " -g|--dump-config | dump current config into .state dir\n");
|
fprintf(stderr, " -g|--dump-config | dump current config into .state dir\n");
|
||||||
fprintf(stderr, " -h|--help|-? | command line help\n");
|
fprintf(stderr, " -h|--help|-? | command line help\n");
|
||||||
fprintf(stderr, " -i|--iface <interface> | read from given interface\n");
|
fprintf(stderr, " -i|--iface <interface> | read from given interface\n");
|
||||||
fprintf(stderr, " -l|--snaplen <snaplen> | number of bytes per packet to capture from interfaces (default 65535)\n");
|
|
||||||
fprintf(stderr, " -p|--prefix <prefix> | add given prefix to policy file resolution\n");
|
fprintf(stderr, " -p|--prefix <prefix> | add given prefix to policy file resolution\n");
|
||||||
fprintf(stderr, " -r|--readfile <readfile> | read from given tcpdump file\n");
|
fprintf(stderr, " -r|--readfile <readfile> | read from given tcpdump file\n");
|
||||||
fprintf(stderr, " -y|--flowfile <file>[=<ident>] | read from given flow file\n");
|
fprintf(stderr, " -y|--flowfile <file>[=<ident>] | read from given flow file\n");
|
||||||
|
@ -372,7 +371,6 @@ int main(int argc, char** argv)
|
||||||
{"filter", required_argument, 0, 'f'},
|
{"filter", required_argument, 0, 'f'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"iface", required_argument, 0, 'i'},
|
{"iface", required_argument, 0, 'i'},
|
||||||
{"snaplen", required_argument, 0, 'l'},
|
|
||||||
{"doc-scripts", no_argument, 0, 'Z'},
|
{"doc-scripts", no_argument, 0, 'Z'},
|
||||||
{"prefix", required_argument, 0, 'p'},
|
{"prefix", required_argument, 0, 'p'},
|
||||||
{"readfile", required_argument, 0, 'r'},
|
{"readfile", required_argument, 0, 'r'},
|
||||||
|
@ -481,10 +479,6 @@ int main(int argc, char** argv)
|
||||||
interfaces.append(optarg);
|
interfaces.append(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
|
||||||
snaplen = atoi(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
prefixes.append(optarg);
|
prefixes.append(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -833,6 +827,8 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snaplen = internal_val("snaplen")->AsCount();
|
||||||
|
|
||||||
// Initialize the secondary path, if it's needed.
|
// Initialize the secondary path, if it's needed.
|
||||||
secondary_path = new SecondaryPath();
|
secondary_path = new SecondaryPath();
|
||||||
|
|
||||||
|
|
15
src/parse.y
15
src/parse.y
|
@ -2,7 +2,7 @@
|
||||||
// See the file "COPYING" in the main distribution directory for copyright.
|
// See the file "COPYING" in the main distribution directory for copyright.
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%expect 88
|
%expect 87
|
||||||
|
|
||||||
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
|
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
|
||||||
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
|
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
%type <expr> expr init anonymous_function
|
%type <expr> expr init anonymous_function
|
||||||
%type <event_expr> event
|
%type <event_expr> event
|
||||||
%type <stmt> stmt stmt_list func_body for_head
|
%type <stmt> stmt stmt_list func_body for_head
|
||||||
%type <type> type opt_type refined_type enum_body
|
%type <type> type opt_type enum_body
|
||||||
%type <func_type> func_hdr func_params
|
%type <func_type> func_hdr func_params
|
||||||
%type <type_l> type_list
|
%type <type_l> type_list
|
||||||
%type <type_decl> type_decl formal_args_decl
|
%type <type_decl> type_decl formal_args_decl
|
||||||
|
@ -1104,7 +1104,7 @@ decl:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_TYPE global_id ':' refined_type opt_attr ';'
|
| TOK_TYPE global_id ':' type opt_attr ';'
|
||||||
{
|
{
|
||||||
add_type($2, $4, $5, 0);
|
add_type($2, $4, $5, 0);
|
||||||
|
|
||||||
|
@ -1134,7 +1134,7 @@ decl:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_EVENT event_id ':' refined_type opt_attr ';'
|
| TOK_EVENT event_id ':' type_list opt_attr ';'
|
||||||
{
|
{
|
||||||
add_type($2, $4, $5, 1);
|
add_type($2, $4, $5, 1);
|
||||||
|
|
||||||
|
@ -1220,13 +1220,6 @@ func_params:
|
||||||
{ $$ = new FuncType($2, base_type(TYPE_VOID), 0); }
|
{ $$ = new FuncType($2, base_type(TYPE_VOID), 0); }
|
||||||
;
|
;
|
||||||
|
|
||||||
refined_type:
|
|
||||||
type_list '{' type_decl_list '}'
|
|
||||||
{ $$ = refine_type($1, $3); }
|
|
||||||
| type_list
|
|
||||||
{ $$ = refine_type($1, 0); }
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_type:
|
opt_type:
|
||||||
':' type
|
':' type
|
||||||
{ $$ = $2; }
|
{ $$ = $2; }
|
||||||
|
|
|
@ -144,7 +144,7 @@ refine connection SSL_Conn += {
|
||||||
if ( ssl_client_hello )
|
if ( ssl_client_hello )
|
||||||
{
|
{
|
||||||
vector<int>* cipher_suites = new vector<int>();
|
vector<int>* cipher_suites = new vector<int>();
|
||||||
if ( cipher_suites16 )
|
if ( cipher_suites16 )
|
||||||
std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*cipher_suites));
|
std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*cipher_suites));
|
||||||
else
|
else
|
||||||
std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*cipher_suites), to_int());
|
std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*cipher_suites), to_int());
|
||||||
|
@ -205,6 +205,18 @@ refine connection SSL_Conn += {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
function proc_session_ticket_handshake(rec: SessionTicketHandshake, is_orig: bool): bool
|
||||||
|
%{
|
||||||
|
if ( ssl_session_ticket_handshake )
|
||||||
|
{
|
||||||
|
BifEvent::generate_ssl_session_ticket_handshake(bro_analyzer(),
|
||||||
|
bro_analyzer()->Conn(),
|
||||||
|
${rec.ticket_lifetime_hint},
|
||||||
|
new StringVal(${rec.data}.length(), (const char*) ${rec.data}.data()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
function proc_ssl_extension(rec: SSLRecord, type: int, data: bytestring) : bool
|
function proc_ssl_extension(rec: SSLRecord, type: int, data: bytestring) : bool
|
||||||
%{
|
%{
|
||||||
|
@ -269,13 +281,14 @@ refine connection SSL_Conn += {
|
||||||
der_cert);
|
der_cert);
|
||||||
|
|
||||||
// Are there any X509 extensions?
|
// Are there any X509 extensions?
|
||||||
|
//printf("Number of x509 extensions: %d\n", X509_get_ext_count(pTemp));
|
||||||
if ( x509_extension && X509_get_ext_count(pTemp) > 0 )
|
if ( x509_extension && X509_get_ext_count(pTemp) > 0 )
|
||||||
{
|
{
|
||||||
int num_ext = X509_get_ext_count(pTemp);
|
int num_ext = X509_get_ext_count(pTemp);
|
||||||
for ( int k = 0; k < num_ext; ++k )
|
for ( int k = 0; k < num_ext; ++k )
|
||||||
{
|
{
|
||||||
unsigned char *pBuffer = 0;
|
unsigned char *pBuffer = 0;
|
||||||
int length = 0;
|
uint length = 0;
|
||||||
|
|
||||||
X509_EXTENSION* ex = X509_get_ext(pTemp, k);
|
X509_EXTENSION* ex = X509_get_ext(pTemp, k);
|
||||||
if (ex)
|
if (ex)
|
||||||
|
@ -283,7 +296,7 @@ refine connection SSL_Conn += {
|
||||||
ASN1_STRING *pString = X509_EXTENSION_get_data(ex);
|
ASN1_STRING *pString = X509_EXTENSION_get_data(ex);
|
||||||
length = ASN1_STRING_to_UTF8(&pBuffer, pString);
|
length = ASN1_STRING_to_UTF8(&pBuffer, pString);
|
||||||
//i2t_ASN1_OBJECT(&pBuffer, length, obj)
|
//i2t_ASN1_OBJECT(&pBuffer, length, obj)
|
||||||
|
// printf("extension length: %u\n", length);
|
||||||
// -1 indicates an error.
|
// -1 indicates an error.
|
||||||
if ( length < 0 )
|
if ( length < 0 )
|
||||||
continue;
|
continue;
|
||||||
|
@ -442,6 +455,10 @@ refine typeattr Handshake += &let {
|
||||||
proc : bool = $context.connection.proc_handshake(this, rec.is_orig);
|
proc : bool = $context.connection.proc_handshake(this, rec.is_orig);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
refine typeattr SessionTicketHandshake += &let {
|
||||||
|
proc : bool = $context.connection.proc_session_ticket_handshake(this, rec.is_orig);
|
||||||
|
}
|
||||||
|
|
||||||
refine typeattr UnknownRecord += &let {
|
refine typeattr UnknownRecord += &let {
|
||||||
proc : bool = $context.connection.proc_unknown_record(rec);
|
proc : bool = $context.connection.proc_unknown_record(rec);
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,17 +61,10 @@ type RecordText(rec: SSLRecord) = case $context.connection.state() of {
|
||||||
-> plaintext : PlaintextRecord(rec);
|
-> plaintext : PlaintextRecord(rec);
|
||||||
};
|
};
|
||||||
|
|
||||||
type PossibleEncryptedHandshake(rec: SSLRecord) = case $context.connection.state() of {
|
|
||||||
# Deal with encrypted handshakes before the server cipher spec change.
|
|
||||||
STATE_CLIENT_FINISHED, STATE_CLIENT_ENCRYPTED
|
|
||||||
-> ct : CiphertextRecord(rec);
|
|
||||||
default -> hs : Handshake(rec);
|
|
||||||
};
|
|
||||||
|
|
||||||
type PlaintextRecord(rec: SSLRecord) = case rec.content_type of {
|
type PlaintextRecord(rec: SSLRecord) = case rec.content_type of {
|
||||||
CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec);
|
CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec);
|
||||||
ALERT -> alert : Alert(rec);
|
ALERT -> alert : Alert(rec);
|
||||||
HANDSHAKE -> handshake : PossibleEncryptedHandshake(rec);
|
HANDSHAKE -> handshake : Handshake(rec);
|
||||||
APPLICATION_DATA -> app_data : ApplicationData(rec);
|
APPLICATION_DATA -> app_data : ApplicationData(rec);
|
||||||
V2_ERROR -> v2_error : V2Error(rec);
|
V2_ERROR -> v2_error : V2Error(rec);
|
||||||
V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec);
|
V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec);
|
||||||
|
@ -260,18 +253,19 @@ enum AnalyzerState {
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
enum HandshakeType {
|
enum HandshakeType {
|
||||||
HELLO_REQUEST = 0,
|
HELLO_REQUEST = 0,
|
||||||
CLIENT_HELLO = 1,
|
CLIENT_HELLO = 1,
|
||||||
SERVER_HELLO = 2,
|
SERVER_HELLO = 2,
|
||||||
CERTIFICATE = 11,
|
SESSION_TICKET = 4, # RFC 5077
|
||||||
SERVER_KEY_EXCHANGE = 12,
|
CERTIFICATE = 11,
|
||||||
CERTIFICATE_REQUEST = 13,
|
SERVER_KEY_EXCHANGE = 12,
|
||||||
SERVER_HELLO_DONE = 14,
|
CERTIFICATE_REQUEST = 13,
|
||||||
CERTIFICATE_VERIFY = 15,
|
SERVER_HELLO_DONE = 14,
|
||||||
CLIENT_KEY_EXCHANGE = 16,
|
CERTIFICATE_VERIFY = 15,
|
||||||
FINISHED = 20,
|
CLIENT_KEY_EXCHANGE = 16,
|
||||||
CERTIFICATE_URL = 21, # RFC 3546
|
FINISHED = 20,
|
||||||
CERTIFICATE_STATUS = 22, # RFC 3546
|
CERTIFICATE_URL = 21, # RFC 3546
|
||||||
|
CERTIFICATE_STATUS = 22, # RFC 3546
|
||||||
};
|
};
|
||||||
|
|
||||||
%code{
|
%code{
|
||||||
|
@ -281,6 +275,7 @@ enum HandshakeType {
|
||||||
case HELLO_REQUEST: return string("HELLO_REQUEST");
|
case HELLO_REQUEST: return string("HELLO_REQUEST");
|
||||||
case CLIENT_HELLO: return string("CLIENT_HELLO");
|
case CLIENT_HELLO: return string("CLIENT_HELLO");
|
||||||
case SERVER_HELLO: return string("SERVER_HELLO");
|
case SERVER_HELLO: return string("SERVER_HELLO");
|
||||||
|
case SESSION_TICKET: return string("SESSION_TICKET");
|
||||||
case CERTIFICATE: return string("CERTIFICATE");
|
case CERTIFICATE: return string("CERTIFICATE");
|
||||||
case SERVER_KEY_EXCHANGE: return string("SERVER_KEY_EXCHANGE");
|
case SERVER_KEY_EXCHANGE: return string("SERVER_KEY_EXCHANGE");
|
||||||
case CERTIFICATE_REQUEST: return string("CERTIFICATE_REQUEST");
|
case CERTIFICATE_REQUEST: return string("CERTIFICATE_REQUEST");
|
||||||
|
@ -452,8 +447,7 @@ type V2ServerHello(rec: SSLRecord) = record {
|
||||||
cert_data : bytestring &length = cert_len;
|
cert_data : bytestring &length = cert_len;
|
||||||
ciphers : uint24[ciph_len/3];
|
ciphers : uint24[ciph_len/3];
|
||||||
conn_id_data : bytestring &length = conn_id_len;
|
conn_id_data : bytestring &length = conn_id_len;
|
||||||
} #&length = 8 + cert_len + ciph_len + conn_id_len,
|
} &let {
|
||||||
&let {
|
|
||||||
state_changed : bool =
|
state_changed : bool =
|
||||||
(session_id_hit > 0 ?
|
(session_id_hit > 0 ?
|
||||||
$context.connection.transition(STATE_CLIENT_HELLO_RCVD,
|
$context.connection.transition(STATE_CLIENT_HELLO_RCVD,
|
||||||
|
@ -603,7 +597,7 @@ type CertificateVerify(rec: SSLRecord) = record {
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
# The finished messages are always sent after encryption is in effect,
|
# The finished messages are always sent after encryption is in effect,
|
||||||
# so we will not be able to read those message.
|
# so we will not be able to read those messages.
|
||||||
type Finished(rec: SSLRecord) = record {
|
type Finished(rec: SSLRecord) = record {
|
||||||
cont : bytestring &restofdata &transient;
|
cont : bytestring &restofdata &transient;
|
||||||
} &let {
|
} &let {
|
||||||
|
@ -615,13 +609,17 @@ type Finished(rec: SSLRecord) = record {
|
||||||
$context.connection.lost_track();
|
$context.connection.lost_track();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type SessionTicketHandshake(rec: SSLRecord) = record {
|
||||||
|
ticket_lifetime_hint: uint32;
|
||||||
|
data: bytestring &restofdata;
|
||||||
|
};
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# V3 Handshake Protocol (7.)
|
# V3 Handshake Protocol (7.)
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
type UnknownHandshake(hs: Handshake, is_orig: bool) = record {
|
type UnknownHandshake(hs: Handshake, is_orig: bool) = record {
|
||||||
cont : bytestring &restofdata &transient;
|
data : bytestring &restofdata &transient;
|
||||||
} &let {
|
} &let {
|
||||||
state_changed : bool = $context.connection.lost_track();
|
state_changed : bool = $context.connection.lost_track();
|
||||||
};
|
};
|
||||||
|
@ -631,19 +629,20 @@ type Handshake(rec: SSLRecord) = record {
|
||||||
length : uint24;
|
length : uint24;
|
||||||
|
|
||||||
body : case msg_type of {
|
body : case msg_type of {
|
||||||
HELLO_REQUEST -> hello_request : HelloRequest(rec);
|
HELLO_REQUEST -> hello_request : HelloRequest(rec);
|
||||||
CLIENT_HELLO -> client_hello : ClientHello(rec);
|
CLIENT_HELLO -> client_hello : ClientHello(rec);
|
||||||
SERVER_HELLO -> server_hello : ServerHello(rec);
|
SERVER_HELLO -> server_hello : ServerHello(rec);
|
||||||
CERTIFICATE -> certificate : Certificate(rec);
|
SESSION_TICKET -> session_ticket : SessionTicketHandshake(rec);
|
||||||
SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec);
|
CERTIFICATE -> certificate : Certificate(rec);
|
||||||
CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec);
|
SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec);
|
||||||
SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec);
|
CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec);
|
||||||
CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec);
|
SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec);
|
||||||
CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec);
|
CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec);
|
||||||
FINISHED -> finished : Finished(rec);
|
CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec);
|
||||||
CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient;
|
FINISHED -> finished : Finished(rec);
|
||||||
CERTIFICATE_STATUS -> certificate_status : bytestring &restofdata &transient;
|
CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient;
|
||||||
default -> unknown_handshake : UnknownHandshake(this, rec.is_orig);
|
CERTIFICATE_STATUS -> certificate_status : bytestring &restofdata &transient;
|
||||||
|
default -> unknown_handshake : UnknownHandshake(this, rec.is_orig);
|
||||||
} &length = to_int()(length);
|
} &length = to_int()(length);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Definitions of Bro built-in functions related to strings.
|
##! Definitions of built-in functions related to string processing and
|
||||||
|
##! manipulation.
|
||||||
|
|
||||||
|
|
||||||
%%{ // C segment
|
%%{ // C segment
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
##! Declaration of various types that the Bro core uses internally.
|
||||||
|
|
||||||
enum dce_rpc_ptype %{
|
enum dce_rpc_ptype %{
|
||||||
DCE_RPC_REQUEST,
|
DCE_RPC_REQUEST,
|
||||||
|
@ -134,8 +135,8 @@ enum createmode_t %{
|
||||||
EXCLUSIVE = 2,
|
EXCLUSIVE = 2,
|
||||||
%}
|
%}
|
||||||
|
|
||||||
# Decleare record types that we want to access from the even engine. These are
|
# Declare record types that we want to access from the event engine. These are
|
||||||
# defined in bro.init.
|
# defined in init-bare.bro.
|
||||||
type info_t: record;
|
type info_t: record;
|
||||||
type fattr_t: record;
|
type fattr_t: record;
|
||||||
type diropargs_t: record;
|
type diropargs_t: record;
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
#empty_field (empty)
|
#empty_field (empty)
|
||||||
#unset_field -
|
#unset_field -
|
||||||
#path notice
|
#path notice
|
||||||
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
|
||||||
#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
||||||
1324314350.184962 - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 100/100 - 1.2.3.4 - - 100 manager-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - -
|
1325633225.777902 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 100/100 - 1.2.3.4 - - 100 manager-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - -
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#empty_field (empty)
|
#empty_field (empty)
|
||||||
#unset_field -
|
#unset_field -
|
||||||
#path notice
|
#path notice
|
||||||
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
|
||||||
#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
||||||
1324314359.357148 - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 3/2 - 1.2.3.4 - - 3 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - -
|
1325633274.875473 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 3/2 - 1.2.3.4 - - 3 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - -
|
||||||
1324314359.357148 - - - - - Test_Notice Threshold crossed by metric_index(host=6.5.4.3) 2/2 - 6.5.4.3 - - 2 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 6.5.4.3 - -
|
1325633274.875473 - - - - - - Test_Notice Threshold crossed by metric_index(host=6.5.4.3) 2/2 - 6.5.4.3 - - 2 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 6.5.4.3 - -
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
#empty_field (empty)
|
#empty_field (empty)
|
||||||
#unset_field -
|
#unset_field -
|
||||||
#path notice
|
#path notice
|
||||||
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
|
||||||
#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
||||||
1324314363.721823 - - - - - Test_Notice test notice! - - - - - worker-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
|
1325633122.490990 - - - - - - Test_Notice test notice! - - - - - worker-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
> 2005-10-07-23:23:55 Test_Notice 141.42.64.125:56730/tcp -> 125.190.109.199:80/tcp (uid arKYeMETxOg)
|
||||||
|
test
|
||||||
|
# 141.42.64.125 = <skipped> 125.190.109.199 = <skipped>
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
#empty_field (empty)
|
#empty_field (empty)
|
||||||
#unset_field -
|
#unset_field -
|
||||||
#path notice
|
#path notice
|
||||||
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
|
||||||
#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
||||||
1324314378.560010 - - - - - Test_Notice test notice! - - - - - worker-2 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
|
1325633150.723248 - - - - - - Test_Notice test notice! - - - - - worker-2 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
#empty_field (empty)
|
#empty_field (empty)
|
||||||
#unset_field -
|
#unset_field -
|
||||||
#path notice
|
#path notice
|
||||||
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude
|
||||||
#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double
|
#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double
|
||||||
1324314387.663586 - - - - - Test_Notice test - - - - - bro Notice::ACTION_LOG 6 3600.000000 F - - - - -
|
1325633207.922993 - - - - - - Test_Notice test - - - - - bro Notice::ACTION_LOG 6 3600.000000 F - - - - -
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# @TEST-EXEC: btest-bg-run proxy-2 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-2 bro %INPUT
|
# @TEST-EXEC: btest-bg-run proxy-2 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-2 bro %INPUT
|
||||||
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
|
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
|
||||||
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
|
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
|
||||||
# @TEST-EXEC: btest-bg-wait -k 2
|
# @TEST-EXEC: btest-bg-wait -k 10
|
||||||
# @TEST-EXEC: btest-diff manager-1/.stdout
|
# @TEST-EXEC: btest-diff manager-1/.stdout
|
||||||
# @TEST-EXEC: btest-diff proxy-1/.stdout
|
# @TEST-EXEC: btest-diff proxy-1/.stdout
|
||||||
# @TEST-EXEC: btest-diff proxy-2/.stdout
|
# @TEST-EXEC: btest-diff proxy-2/.stdout
|
||||||
|
@ -23,4 +23,4 @@ redef Cluster::nodes = {
|
||||||
event remote_connection_handshake_done(p: event_peer)
|
event remote_connection_handshake_done(p: event_peer)
|
||||||
{
|
{
|
||||||
print "Connected to a peer";
|
print "Connected to a peer";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
# @TEST-EXEC: btest-bg-run receiver bro -b ../receiver.bro
|
# @TEST-EXEC: btest-bg-run receiver bro -b ../receiver.bro
|
||||||
# @TEST-EXEC: btest-bg-run sender bro -b ../sender.bro
|
# @TEST-EXEC: btest-bg-run sender bro -b ../sender.bro
|
||||||
# @TEST-EXEC: btest-bg-wait -k 2
|
# @TEST-EXEC: btest-bg-wait -k 10
|
||||||
#
|
#
|
||||||
# Don't diff the receiver log just because port is always going to change
|
# Don't diff the receiver log just because port is always going to change
|
||||||
# @TEST-EXEC: egrep -v 'pid|socket buffer size' sender/communication.log >send.log
|
# @TEST-EXEC: egrep -v 'pid|socket buffer size' sender/communication.log >send.log
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65531/tcp
|
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65531/tcp
|
||||||
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT test-redef frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=configuration_update
|
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT test-redef frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=configuration_update
|
||||||
# @TEST-EXEC: btest-bg-run controller2 BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=shutdown
|
# @TEST-EXEC: btest-bg-run controller2 BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=shutdown
|
||||||
# @TEST-EXEC: btest-bg-wait 1
|
# @TEST-EXEC: btest-bg-wait 10
|
||||||
# @TEST-EXEC: btest-diff controllee/.stdout
|
# @TEST-EXEC: btest-diff controllee/.stdout
|
||||||
|
|
||||||
redef Communication::nodes = {
|
redef Communication::nodes = {
|
||||||
|
@ -23,4 +23,4 @@ event bro_init()
|
||||||
event bro_done()
|
event bro_done()
|
||||||
{
|
{
|
||||||
print test_var;
|
print test_var;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT only-for-controllee frameworks/control/controllee Communication::listen_port=65532/tcp
|
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT only-for-controllee frameworks/control/controllee Communication::listen_port=65532/tcp
|
||||||
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65532/tcp Control::cmd=id_value Control::arg=test_var
|
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65532/tcp Control::cmd=id_value Control::arg=test_var
|
||||||
# @TEST-EXEC: btest-bg-wait -k 1
|
# @TEST-EXEC: btest-bg-wait -k 10
|
||||||
# @TEST-EXEC: btest-diff controller/.stdout
|
# @TEST-EXEC: btest-diff controller/.stdout
|
||||||
|
|
||||||
redef Communication::nodes = {
|
redef Communication::nodes = {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65530/tcp
|
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65530/tcp
|
||||||
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65530/tcp Control::cmd=shutdown
|
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65530/tcp Control::cmd=shutdown
|
||||||
# @TEST-EXEC: btest-bg-wait 1
|
# @TEST-EXEC: btest-bg-wait 10
|
||||||
|
|
||||||
redef Communication::nodes = {
|
redef Communication::nodes = {
|
||||||
# We're waiting for connections from this host for control.
|
# We're waiting for connections from this host for control.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
# @TEST-EXEC: btest-bg-run sender bro --pseudo-realtime %INPUT ../sender.bro
|
# @TEST-EXEC: btest-bg-run sender bro --pseudo-realtime %INPUT ../sender.bro
|
||||||
# @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro
|
# @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro
|
||||||
# @TEST-EXEC: btest-bg-wait -k 1
|
# @TEST-EXEC: btest-bg-wait -k 10
|
||||||
# @TEST-EXEC: btest-diff receiver/test.log
|
# @TEST-EXEC: btest-diff receiver/test.log
|
||||||
# @TEST-EXEC: cmp receiver/test.log sender/test.log
|
# @TEST-EXEC: cmp receiver/test.log sender/test.log
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# @TEST-EXEC: sleep 1
|
# @TEST-EXEC: sleep 1
|
||||||
# @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro
|
# @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro
|
||||||
# @TEST-EXEC: sleep 1
|
# @TEST-EXEC: sleep 1
|
||||||
# @TEST-EXEC: btest-bg-wait -k 1
|
# @TEST-EXEC: btest-bg-wait -k 10
|
||||||
# @TEST-EXEC: btest-diff sender/test.log
|
# @TEST-EXEC: btest-diff sender/test.log
|
||||||
# @TEST-EXEC: btest-diff sender/test.failure.log
|
# @TEST-EXEC: btest-diff sender/test.failure.log
|
||||||
# @TEST-EXEC: btest-diff sender/test.success.log
|
# @TEST-EXEC: btest-diff sender/test.success.log
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# @TEST-EXEC: sleep 1
|
# @TEST-EXEC: sleep 1
|
||||||
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
|
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
|
||||||
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
|
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
|
||||||
# @TEST-EXEC: btest-bg-wait -k 6
|
# @TEST-EXEC: btest-bg-wait -k 10
|
||||||
# @TEST-EXEC: btest-diff manager-1/metrics.log
|
# @TEST-EXEC: btest-diff manager-1/metrics.log
|
||||||
|
|
||||||
@TEST-START-FILE cluster-layout.bro
|
@TEST-START-FILE cluster-layout.bro
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# @TEST-EXEC: sleep 1
|
# @TEST-EXEC: sleep 1
|
||||||
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
|
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
|
||||||
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
|
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
|
||||||
# @TEST-EXEC: btest-bg-wait -k 5
|
# @TEST-EXEC: btest-bg-wait -k 10
|
||||||
# @TEST-EXEC: btest-diff manager-1/notice.log
|
# @TEST-EXEC: btest-diff manager-1/notice.log
|
||||||
|
|
||||||
@TEST-START-FILE cluster-layout.bro
|
@TEST-START-FILE cluster-layout.bro
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT
|
# @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT
|
||||||
# @TEST-EXEC: sleep 1
|
# @TEST-EXEC: sleep 1
|
||||||
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
|
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
|
||||||
# @TEST-EXEC: btest-bg-wait -k 6
|
# @TEST-EXEC: btest-bg-wait -k 10
|
||||||
# @TEST-EXEC: btest-diff manager-1/notice.log
|
# @TEST-EXEC: btest-diff manager-1/notice.log
|
||||||
|
|
||||||
@TEST-START-FILE cluster-layout.bro
|
@TEST-START-FILE cluster-layout.bro
|
||||||
|
|
17
testing/btest/scripts/base/frameworks/notice/mail-alarms.bro
Normal file
17
testing/btest/scripts/base/frameworks/notice/mail-alarms.bro
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# @TEST-EXEC: bro -C -r $TRACES/web.trace %INPUT
|
||||||
|
# @TEST-EXEC: btest-diff alarm-mail.txt
|
||||||
|
|
||||||
|
redef Notice::policy += { [$action = Notice::ACTION_ALARM, $priority = 1 ] };
|
||||||
|
redef Notice::force_email_summaries = T;
|
||||||
|
|
||||||
|
redef enum Notice::Type += {
|
||||||
|
Test_Notice,
|
||||||
|
};
|
||||||
|
|
||||||
|
event connection_established(c: connection)
|
||||||
|
{
|
||||||
|
NOTICE([$note=Test_Notice, $conn=c, $msg="test", $identifier="static"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# @TEST-EXEC: sleep 1
|
# @TEST-EXEC: sleep 1
|
||||||
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
|
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
|
||||||
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
|
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
|
||||||
# @TEST-EXEC: btest-bg-wait -k 5
|
# @TEST-EXEC: btest-bg-wait -k 10
|
||||||
# @TEST-EXEC: btest-diff manager-1/notice.log
|
# @TEST-EXEC: btest-diff manager-1/notice.log
|
||||||
|
|
||||||
@TEST-START-FILE cluster-layout.bro
|
@TEST-START-FILE cluster-layout.bro
|
||||||
|
|
11
testing/external/scripts/diff-all
vendored
11
testing/external/scripts/diff-all
vendored
|
@ -22,7 +22,16 @@ files_cwd=`ls $@`
|
||||||
files_baseline=`cd $TEST_BASELINE && ls $@`
|
files_baseline=`cd $TEST_BASELINE && ls $@`
|
||||||
|
|
||||||
for i in `echo $files_cwd $files_baseline | sort | uniq`; do
|
for i in `echo $files_cwd $files_baseline | sort | uniq`; do
|
||||||
if [[ "$i" != "loaded_scripts.log" && "$i" != "prof.log" ]]; then
|
if [[ "$i" != "loaded_scripts.log" && "$i" != "prof.log" && "$i" != "debug.log" ]]; then
|
||||||
|
|
||||||
|
if [[ "$i" == "reporter.log" ]]; then
|
||||||
|
# Do not diff the reporter.log if it only complains about missing
|
||||||
|
# GeoIP support.
|
||||||
|
if ! egrep -v "^#|Bro was not configured for GeoIP support" $i; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if ! btest-diff $i; then
|
if ! btest-diff $i; then
|
||||||
echo "" >>$diag
|
echo "" >>$diag
|
||||||
echo "#### btest-diff $i" >>$diag
|
echo "#### btest-diff $i" >>$diag
|
||||||
|
|
|
@ -5,3 +5,4 @@
|
||||||
`dirname $0`/diff-remove-timestamps \
|
`dirname $0`/diff-remove-timestamps \
|
||||||
| `dirname $0`/diff-remove-uids \
|
| `dirname $0`/diff-remove-uids \
|
||||||
| `dirname $0`/diff-remove-mime-types \
|
| `dirname $0`/diff-remove-mime-types \
|
||||||
|
| `dirname $0`/diff-remove-x509-names \
|
||||||
|
|
32
testing/scripts/diff-remove-x509-names
Executable file
32
testing/scripts/diff-remove-x509-names
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
#! /usr/bin/awk -f
|
||||||
|
#
|
||||||
|
# A diff canonifier that removes all X.509 Distinguished Name subject fields
|
||||||
|
# because that output can differ depending on installed OpenSSL version.
|
||||||
|
|
||||||
|
BEGIN { FS="\t"; OFS="\t"; s_col = -1; i_col = -1 }
|
||||||
|
|
||||||
|
/^#fields/ {
|
||||||
|
for ( i = 2; i < NF; ++i )
|
||||||
|
{
|
||||||
|
if ( $i == "subject" )
|
||||||
|
s_col = i-1;
|
||||||
|
if ( $i == "issuer_subject" )
|
||||||
|
i_col = i-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s_col >= 0 {
|
||||||
|
if ( $s_col != "-" )
|
||||||
|
# Mark that it's set, but ignore content.
|
||||||
|
$s_col = "+";
|
||||||
|
}
|
||||||
|
|
||||||
|
i_col >= 0 {
|
||||||
|
if ( $i_col != "-" )
|
||||||
|
# Mark that it's set, but ignore content.
|
||||||
|
$i_col = "+";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
print;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue