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
|
||||
|
||||
* 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
|
||||
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
|
||||
|
||||
* 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
|
||||
compressed Bro-to-Bro communication.
|
||||
* Libmagic
|
||||
|
||||
* Libz
|
||||
|
||||
Bro can make uses of some optional libraries if they are found at
|
||||
installation time:
|
||||
|
@ -27,11 +28,13 @@ installation time:
|
|||
Bro also needs the following tools, but on most systems they will
|
||||
already come preinstalled:
|
||||
|
||||
* Bash (For Bro Control).
|
||||
* BIND8 (headers and libraries)
|
||||
* Bison (GNU Parser Generator)
|
||||
* Flex (Fast Lexical Analyzer)
|
||||
* Perl (Used only during the Bro build process)
|
||||
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
|
@ -69,8 +72,8 @@ Running Bro
|
|||
===========
|
||||
|
||||
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
|
||||
:doc:`quick start guide <quickstart>`.
|
||||
with it. A good place for newcomers to start is the Quickstart Guide
|
||||
at http://www.bro-ids.org/documentation/quickstart.bro.html.
|
||||
|
||||
For developers that wish to run Bro directly from the ``build/``
|
||||
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
|
||||
$(MAKE) -C $(BUILD) $@
|
||||
|
||||
install: configured
|
||||
install: configured all
|
||||
$(MAKE) -C $(BUILD) $@
|
||||
|
||||
install-aux: configured
|
||||
|
@ -60,6 +60,9 @@ bindist:
|
|||
distclean:
|
||||
rm -rf $(BUILD)
|
||||
|
||||
test:
|
||||
@(cd testing && make )
|
||||
|
||||
configured:
|
||||
@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 )
|
||||
|
|
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
|
||||
monitoring. Please see the INSTALL file for installation instructions
|
||||
and pointers for getting started. For more documentation, research
|
||||
publications, and community contact information, see Bro's home page:
|
||||
and pointers for getting started. NEWS contains releases notes for the
|
||||
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
|
||||
|
||||
Please see COPYING for licensing information.
|
||||
|
||||
On behalf of the Bro Development Team,
|
||||
|
||||
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
|
||||
*.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 {
|
||||
font-weight: bold;
|
||||
font-size: 32px;
|
||||
|
@ -14,3 +28,133 @@ th.field-name
|
|||
{
|
||||
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" %}
|
||||
|
||||
{% 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="http://www.bro-ids.org/css/960.css" />
|
||||
<link rel="stylesheet" type="text/css" href="http://www.bro-ids.org/css/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="{{ pathto('_static/broxygen.css', 1) }}"></script>
|
||||
<link rel="stylesheet" type="text/css" href="{{ pathto('_static/960.css', 1) }}"></script>
|
||||
<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>
|
||||
<script type="text/javascript" src="{{ pathto('_static/download.js', 1) }}"></script>
|
||||
|
||||
<script type="text/javascript" src="{{ pathto('_static/broxygen-extra.js', 1) }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
|
@ -47,6 +48,7 @@
|
|||
Table of Contents
|
||||
</h3>
|
||||
<p>
|
||||
<!-- <ul id="sidebar-toc"></ul> -->
|
||||
<ul>{{toc}}</ul>
|
||||
</p>
|
||||
</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
|
||||
# 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.
|
||||
templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static']
|
||||
|
@ -40,7 +40,7 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
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
|
||||
# |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.
|
||||
htmlhelp_basename = 'Broxygen'
|
||||
|
||||
html_add_permalinks = None
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
|
@ -208,7 +209,6 @@ latex_documents = [
|
|||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# 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
|
||||
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?
|
||||
---------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@ Building From Source
|
|||
Required Dependencies
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following dependencies are required to build Bro:
|
||||
|
||||
* RPM/RedHat-based Linux:
|
||||
|
||||
.. console::
|
||||
|
@ -75,7 +77,11 @@ Required Dependencies
|
|||
|
||||
.. 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
|
||||
|
||||
|
|
|
@ -168,10 +168,6 @@ New Default Settings
|
|||
are loaded. See ``PacketFilter::all_packets`` for how to revert to old
|
||||
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
|
||||
-----------
|
||||
|
||||
|
|
|
@ -14,14 +14,17 @@ export {
|
|||
## Address to send the pretty-printed reports to. Default if not set is
|
||||
## :bro:id:`Notice::mail_dest`.
|
||||
const mail_dest_pretty_printed = "" &redef;
|
||||
|
||||
## 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.
|
||||
global flag_nets: set[subnet] &redef;
|
||||
|
||||
## Function that renders a single alarm. Can be overidden.
|
||||
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.
|
||||
|
@ -32,6 +35,9 @@ global pp_alarms_open: bool = F;
|
|||
# Returns True if pretty-printed alarm summaries are activated.
|
||||
function want_pp() : bool
|
||||
{
|
||||
if ( force_email_summaries )
|
||||
return T;
|
||||
|
||||
return (pretty_print_alarms && ! reading_traces()
|
||||
&& (mail_dest != "" || mail_dest_pretty_printed != ""));
|
||||
}
|
||||
|
@ -44,34 +50,45 @@ function pp_open()
|
|||
|
||||
pp_alarms_open = T;
|
||||
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.
|
||||
function pp_send()
|
||||
function pp_send(rinfo: Log::RotationInfo)
|
||||
{
|
||||
if ( ! pp_alarms_open )
|
||||
return;
|
||||
|
||||
write_file(pp_alarms, "\n\n--\n[Automatically generated]\n\n");
|
||||
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;
|
||||
|
||||
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.
|
||||
function pp_postprocessor(info: Log::RotationInfo): bool
|
||||
{
|
||||
if ( want_pp() )
|
||||
pp_send();
|
||||
pp_send(info);
|
||||
|
||||
return T;
|
||||
}
|
||||
|
@ -93,7 +110,7 @@ event notice(n: Notice::Info) &priority=-5
|
|||
if ( ! want_pp() )
|
||||
return;
|
||||
|
||||
if ( ACTION_LOG !in n$actions )
|
||||
if ( ACTION_ALARM !in n$actions )
|
||||
return;
|
||||
|
||||
if ( ! pp_alarms_open )
|
||||
|
@ -154,30 +171,24 @@ function pretty_print_alarm(out: file, n: Info)
|
|||
|
||||
if ( n?$id )
|
||||
{
|
||||
orig_p = fmt(":%s", n$id$orig_p);
|
||||
resp_p = fmt(":%s", n$id$resp_p);
|
||||
h1 = n$id$orig_h;
|
||||
h2 = n$id$resp_h;
|
||||
who = fmt("%s:%s -> %s:%s", h1, n$id$orig_p, h2, n$id$resp_p);
|
||||
}
|
||||
|
||||
if ( n?$src && n?$dst )
|
||||
else if ( n?$src && n?$dst )
|
||||
{
|
||||
h1 = n$src;
|
||||
h2 = n$dst;
|
||||
who = fmt("%s%s -> %s%s", h1, orig_p, h2, resp_p);
|
||||
who = fmt("%s -> %s", h1, h2);
|
||||
}
|
||||
else if ( n?$src )
|
||||
{
|
||||
h1 = n$src;
|
||||
who = fmt("%s%s", h1, (n?$p ? fmt(":%s", n$p) : ""));
|
||||
}
|
||||
|
||||
if ( n?$uid )
|
||||
who = fmt("%s (uid %s)", who, n$uid );
|
||||
}
|
||||
|
||||
else if ( n?$src )
|
||||
{
|
||||
local p = "";
|
||||
|
||||
if ( n?$p )
|
||||
p = fmt(":%s", n$p);
|
||||
|
||||
h1 = n$src;
|
||||
who = fmt("%s%s", h1, p);
|
||||
}
|
||||
|
||||
local flag = (h1 in flag_nets || h2 in flag_nets);
|
||||
|
||||
|
@ -191,6 +202,12 @@ function pretty_print_alarm(out: file, n: Info)
|
|||
return;
|
||||
}
|
||||
|
||||
if ( reading_traces() )
|
||||
{
|
||||
do_msg(out, n, line1, line2, line3, h1, "<skipped>", h2, "<skipped>");
|
||||
return;
|
||||
}
|
||||
|
||||
when ( local h1name = lookup_addr(h1) )
|
||||
{
|
||||
if ( h2 == 0.0.0.0 )
|
||||
|
|
|
@ -74,7 +74,11 @@ export {
|
|||
## the notice policy.
|
||||
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;
|
||||
## The human readable message for the notice.
|
||||
msg: string &log &optional;
|
||||
|
@ -535,8 +539,12 @@ function apply_policy(n: Notice::Info)
|
|||
n$p = n$id$resp_p;
|
||||
}
|
||||
|
||||
if ( n?$p )
|
||||
n$proto = get_port_transport_proto(n$p);
|
||||
|
||||
if ( n?$iconn )
|
||||
{
|
||||
n$proto = icmp;
|
||||
if ( ! n?$src )
|
||||
n$src = n$iconn$orig_h;
|
||||
if ( ! n?$dst )
|
||||
|
|
|
@ -2331,6 +2331,9 @@ const ignore_keep_alive_rexmit = F &redef;
|
|||
## .. bro:see:: tunnel_port
|
||||
const parse_udp_tunnels = F &redef;
|
||||
|
||||
## 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.
|
||||
@load base/frameworks/logging
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
##! 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
|
||||
##! 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
|
||||
##! would be to handle the connection_established event elsewhere and set the
|
||||
##! extract_orig and extract_resp options there. However, there may be trouble
|
||||
##! with the timing due the event queue delay.
|
||||
##! ``c$extract_resp`` variable must be set to ``T``. One way to achieve this
|
||||
##! would be to handle the :bro:id:`connection_established` event elsewhere
|
||||
##! and set the ``extract_orig`` and ``extract_resp`` options there.
|
||||
##! However, there may be trouble with the timing due to event queue delay.
|
||||
##!
|
||||
##! .. note::
|
||||
##!
|
||||
##! This script does not work well in a cluster context unless it has a
|
||||
##! remotely mounted disk to write the content files to.
|
||||
|
||||
|
@ -13,11 +16,12 @@
|
|||
module Conn;
|
||||
|
||||
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;
|
||||
|
||||
## If this variable is set to T, then all contents of all files will be
|
||||
## extracted.
|
||||
## If this variable is set to ``T``, then all contents of all connections
|
||||
## will be extracted.
|
||||
const default_extract = F &redef;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
module Conn;
|
||||
|
||||
export {
|
||||
## Define inactivty timeouts by the service detected being used over
|
||||
## Define inactivity timeouts by the service detected being used over
|
||||
## the connection.
|
||||
const analyzer_inactivity_timeouts: table[AnalyzerTag] of interval = {
|
||||
# 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
|
||||
|
||||
module Conn;
|
||||
|
||||
export {
|
||||
## The connection logging stream identifier.
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
## The record type which contains column fields of the connection log.
|
||||
type Info: record {
|
||||
## This is the time of the first packet.
|
||||
ts: time &log;
|
||||
## A unique identifier of a connection.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## The transport layer protocol of the connection.
|
||||
proto: transport_proto &log;
|
||||
## An identification of an application protocol being sent over the
|
||||
## the connection.
|
||||
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;
|
||||
## The number of payload bytes the originator sent. For TCP
|
||||
## this is taken from sequence numbers and might be inaccurate
|
||||
|
@ -51,8 +67,8 @@ export {
|
|||
## have been completed prior to the packet loss.
|
||||
missed_bytes: count &log &default=0;
|
||||
|
||||
## Records the state history of (TCP) connections as
|
||||
## a string of letters.
|
||||
## Records the state history of connections as a string of letters.
|
||||
## For TCP connections the meaning of those letters is:
|
||||
##
|
||||
## ====== ====================================================
|
||||
## Letter Meaning
|
||||
|
@ -71,7 +87,8 @@ export {
|
|||
## originator and lower case then means the responder.
|
||||
## 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.
|
||||
## 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;
|
||||
## Number of packets the originator sent.
|
||||
## Only set if :bro:id:`use_conn_size_analyzer` = T
|
||||
|
@ -86,6 +103,8 @@ export {
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
module DNS;
|
||||
|
||||
export {
|
||||
const PTR = 12;
|
||||
const EDNS = 41;
|
||||
const ANY = 255;
|
||||
const PTR = 12; ##< RR TYPE value for a domain name pointer.
|
||||
const EDNS = 41; ##< An OPT RR TYPE value described by EDNS.
|
||||
const ANY = 255; ##< A QTYPE value describing a request for all records.
|
||||
|
||||
## Mapping of DNS query type codes to human readable string representation.
|
||||
const query_types = {
|
||||
|
@ -29,50 +29,43 @@ export {
|
|||
[ANY] = "*",
|
||||
} &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.
|
||||
const base_errors = {
|
||||
[0] = "NOERROR", ##< No Error
|
||||
[1] = "FORMERR", ##< Format Error
|
||||
[2] = "SERVFAIL", ##< Server Failure
|
||||
[3] = "NXDOMAIN", ##< Non-Existent Domain
|
||||
[4] = "NOTIMP", ##< Not Implemented
|
||||
[5] = "REFUSED", ##< Query Refused
|
||||
[6] = "YXDOMAIN", ##< Name Exists when it should not
|
||||
[7] = "YXRRSET", ##< RR Set Exists when it should not
|
||||
[8] = "NXRRSet", ##< RR Set that should exist does not
|
||||
[9] = "NOTAUTH", ##< Server Not Authoritative for zone
|
||||
[10] = "NOTZONE", ##< Name not contained in zone
|
||||
[11] = "unassigned-11", ##< available for assignment
|
||||
[12] = "unassigned-12", ##< available for assignment
|
||||
[13] = "unassigned-13", ##< available for assignment
|
||||
[14] = "unassigned-14", ##< available for assignment
|
||||
[15] = "unassigned-15", ##< available for assignment
|
||||
[16] = "BADVERS", ##< for EDNS, collision w/ TSIG
|
||||
[17] = "BADKEY", ##< Key not recognized
|
||||
[18] = "BADTIME", ##< Signature out of time window
|
||||
[19] = "BADMODE", ##< Bad TKEY Mode
|
||||
[20] = "BADNAME", ##< Duplicate key name
|
||||
[21] = "BADALG", ##< Algorithm not supported
|
||||
[22] = "BADTRUNC", ##< draft-ietf-dnsext-tsig-sha-05.txt
|
||||
[3842] = "BADSIG", ##< 16 <= number collision with EDNS(16);
|
||||
##< this is a translation from TSIG(16)
|
||||
[0] = "NOERROR", # No Error
|
||||
[1] = "FORMERR", # Format Error
|
||||
[2] = "SERVFAIL", # Server Failure
|
||||
[3] = "NXDOMAIN", # Non-Existent Domain
|
||||
[4] = "NOTIMP", # Not Implemented
|
||||
[5] = "REFUSED", # Query Refused
|
||||
[6] = "YXDOMAIN", # Name Exists when it should not
|
||||
[7] = "YXRRSET", # RR Set Exists when it should not
|
||||
[8] = "NXRRSet", # RR Set that should exist does not
|
||||
[9] = "NOTAUTH", # Server Not Authoritative for zone
|
||||
[10] = "NOTZONE", # Name not contained in zone
|
||||
[11] = "unassigned-11", # available for assignment
|
||||
[12] = "unassigned-12", # available for assignment
|
||||
[13] = "unassigned-13", # available for assignment
|
||||
[14] = "unassigned-14", # available for assignment
|
||||
[15] = "unassigned-15", # available for assignment
|
||||
[16] = "BADVERS", # for EDNS, collision w/ TSIG
|
||||
[17] = "BADKEY", # Key not recognized
|
||||
[18] = "BADTIME", # Signature out of time window
|
||||
[19] = "BADMODE", # Bad TKEY Mode
|
||||
[20] = "BADNAME", # Duplicate key name
|
||||
[21] = "BADALG", # Algorithm not supported
|
||||
[22] = "BADTRUNC", # draft-ietf-dnsext-tsig-sha-05.txt
|
||||
[3842] = "BADSIG", # 16 <= number collision with EDNS(16);
|
||||
# this is a translation from TSIG(16)
|
||||
} &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 = {
|
||||
[0] = "NOVALUE", # regular entry
|
||||
[32768] = "DNS_SEC_OK", # accepts DNS Sec RRs
|
||||
} &default="?";
|
||||
|
||||
## Possible values of the CLASS field in resource records or QCLASS field
|
||||
## in query messages.
|
||||
const classes = {
|
||||
[1] = "C_INTERNET",
|
||||
[2] = "C_CSNET",
|
||||
|
|
|
@ -1,38 +1,80 @@
|
|||
##! Base DNS analysis script which tracks and logs DNS queries along with
|
||||
##! their responses.
|
||||
|
||||
@load ./consts
|
||||
|
||||
module DNS;
|
||||
|
||||
export {
|
||||
## The DNS logging stream identifier.
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
## The record type which contains the column fields of the DNS log.
|
||||
type Info: record {
|
||||
## The earliest time at which a DNS protocol message over the
|
||||
## associated connection is observed.
|
||||
ts: time &log;
|
||||
## A unique identifier of the connection over which DNS messages
|
||||
## are being transferred.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
## The transport layer protocol of the connection.
|
||||
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;
|
||||
## The domain name that is the subject of the DNS query.
|
||||
query: string &log &optional;
|
||||
## The QCLASS value specifying the class of the query.
|
||||
qclass: count &log &optional;
|
||||
## A descriptive name for the class of the query.
|
||||
qclass_name: string &log &optional;
|
||||
## A QTYPE value specifying the type of the query.
|
||||
qtype: count &log &optional;
|
||||
## A descriptive name for the type of the query.
|
||||
qtype_name: string &log &optional;
|
||||
## The response code value in DNS response messages.
|
||||
rcode: count &log &optional;
|
||||
## A descriptive name for the response code value.
|
||||
rcode_name: string &log &optional;
|
||||
## Whether the message is a query (F) or response (T).
|
||||
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;
|
||||
## The Truncation bit specifies that the message was truncated.
|
||||
TC: bool &log &default=F;
|
||||
## The Recursion Desired bit indicates to a name server to recursively
|
||||
## purse the query.
|
||||
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;
|
||||
## A reserved field that is currently supposed to be zero in all
|
||||
## queries and responses.
|
||||
Z: count &log &default=0;
|
||||
## The set of resource descriptions in answer of the query.
|
||||
answers: vector of string &log &optional;
|
||||
## The caching intervals of the associated RRs described by the
|
||||
## ``answers`` field.
|
||||
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;
|
||||
## The total number of resource records in a reply message's answer
|
||||
## section.
|
||||
total_answers: count &optional;
|
||||
## The total number of resource records in a reply message's answer,
|
||||
## authority, and additional sections.
|
||||
total_replies: count &optional;
|
||||
};
|
||||
|
||||
## A record type which tracks the status of DNS queries for a given
|
||||
## :bro:type:`connection`.
|
||||
type State: record {
|
||||
## Indexed by query id, returns Info record corresponding to
|
||||
## query/response which haven't completed yet.
|
||||
|
@ -44,11 +86,21 @@ export {
|
|||
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);
|
||||
|
||||
## 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
|
||||
## 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
##! Base SSL analysis script.
|
||||
|
||||
@load ./consts
|
||||
|
||||
module SSL;
|
||||
|
@ -6,6 +8,7 @@ export {
|
|||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Time when the SSL connection began.
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
|
|
|
@ -8,6 +8,7 @@ export {
|
|||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Timestamp of when the syslog message was seen.
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
module Known;
|
||||
|
||||
export {
|
||||
## The known-hosts logging stream identifier.
|
||||
redef enum Log::ID += { HOSTS_LOG };
|
||||
|
||||
## The record type which contains the column fields of the known-hosts log.
|
||||
type HostsInfo: record {
|
||||
## The timestamp at which the host was detected.
|
||||
ts: time &log;
|
||||
|
@ -19,7 +21,7 @@ export {
|
|||
};
|
||||
|
||||
## 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;
|
||||
|
||||
## The set of all known addresses to store for preventing duplicate
|
||||
|
@ -29,6 +31,8 @@ export {
|
|||
## of each individual address is logged each day.
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,29 +8,41 @@
|
|||
module Known;
|
||||
|
||||
export {
|
||||
## The known-services logging stream identifier.
|
||||
redef enum Log::ID += { SERVICES_LOG };
|
||||
|
||||
## The record type which contains the column fields of the known-services
|
||||
## log.
|
||||
type ServicesInfo: record {
|
||||
## The time at which the service was detected.
|
||||
ts: time &log;
|
||||
## The host address on which the service is running.
|
||||
host: addr &log;
|
||||
## The port number on which the service is running.
|
||||
port_num: port &log;
|
||||
## The transport-layer protocol which the service uses.
|
||||
port_proto: transport_proto &log;
|
||||
## A set of protocols that match the service's connection payloads.
|
||||
service: set[string] &log;
|
||||
|
||||
done: bool &default=F;
|
||||
};
|
||||
|
||||
## The hosts whose services should be tracked and logged.
|
||||
## See :bro:type:`Host` for possible choices.
|
||||
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;
|
||||
|
||||
## 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);
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
## This field is to indicate whether or not the processing for detecting
|
||||
## and logging the service for this connection is complete.
|
||||
# This field is to indicate whether or not the processing for detecting
|
||||
# and logging the service for this connection is complete.
|
||||
known_services_done: bool &default=F;
|
||||
};
|
||||
|
||||
|
|
|
@ -170,13 +170,26 @@ void BroDoc::WriteDocFile() const
|
|||
{
|
||||
WriteToDoc(".. Automatically generated. Do not edit.\n\n");
|
||||
|
||||
WriteToDoc(":tocdepth: 3\n\n");
|
||||
|
||||
WriteSectionHeading(doc_title.c_str(), '=');
|
||||
|
||||
WriteToDoc("\n:download:`Original Source File <%s>`\n\n",
|
||||
downloadable_filename.c_str());
|
||||
WriteStringList(".. bro:namespace:: %s\n", modules);
|
||||
|
||||
WriteSectionHeading("Overview", '-');
|
||||
WriteStringList("%s\n", "%s\n\n", summary);
|
||||
WriteToDoc("\n");
|
||||
|
||||
// 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() )
|
||||
{
|
||||
|
@ -196,39 +209,38 @@ void BroDoc::WriteDocFile() const
|
|||
WriteToDoc("\n");
|
||||
}
|
||||
|
||||
WriteToDoc(":Source File: :download:`%s`\n",
|
||||
downloadable_filename.c_str());
|
||||
|
||||
WriteToDoc("\n");
|
||||
|
||||
WriteInterface("Summary", '~', '#', true, true);
|
||||
|
||||
if ( ! modules.empty() )
|
||||
{
|
||||
WriteSectionHeading("Namespaces", '~');
|
||||
WriteStringList(".. bro:namespace:: %s\n", modules);
|
||||
WriteToDoc("\n");
|
||||
}
|
||||
|
||||
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() )
|
||||
{
|
||||
WriteSectionHeading("Port Analysis", '-');
|
||||
WriteSectionHeading("Port Analysis", '^');
|
||||
WriteToDoc("Loading this script makes the following changes to "
|
||||
":bro:see:`dpd_config`.\n\n");
|
||||
WriteStringList("%s", port_analysis);
|
||||
WriteStringList("%s, ", "%s", port_analysis);
|
||||
}
|
||||
|
||||
if ( ! packet_filter.empty() )
|
||||
{
|
||||
WriteSectionHeading("Packet Filter", '-');
|
||||
WriteSectionHeading("Packet Filter", '^');
|
||||
WriteToDoc("Loading this script makes the following changes to "
|
||||
":bro:see:`capture_filters`.\n\n");
|
||||
WriteToDoc("Filters added::\n\n");
|
||||
WriteToDoc("%s\n", packet_filter.c_str());
|
||||
}
|
||||
|
||||
WriteInterface("Detailed Interface", '~', '#', true, false);
|
||||
|
||||
#if 0 // Disabled for now.
|
||||
BroDocObjList::const_iterator it;
|
||||
bool hasPrivateIdentifiers = false;
|
||||
|
@ -243,7 +255,7 @@ void BroDoc::WriteDocFile() const
|
|||
}
|
||||
|
||||
if ( hasPrivateIdentifiers )
|
||||
WriteInterface("Private Interface", '-', '~', false, false);
|
||||
WriteInterface("Private Interface", '~', '#', false, false);
|
||||
#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
|
||||
// in the data format.
|
||||
static const uint32 DATA_FORMAT_VERSION = 20;
|
||||
static const uint32 DATA_FORMAT_VERSION = 21;
|
||||
|
||||
ChunkedIO* io;
|
||||
|
||||
|
|
138
src/Type.cc
138
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)
|
||||
{
|
||||
types = arg_types;
|
||||
base = 0;
|
||||
fields = 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()
|
||||
{
|
||||
if ( types )
|
||||
|
@ -953,9 +891,6 @@ RecordType::~RecordType()
|
|||
|
||||
delete types;
|
||||
}
|
||||
|
||||
delete fields;
|
||||
Unref(base);
|
||||
}
|
||||
|
||||
int RecordType::HasField(const char* field) const
|
||||
|
@ -971,17 +906,7 @@ BroType* RecordType::FieldType(const char* field) const
|
|||
|
||||
BroType* RecordType::FieldType(int field) const
|
||||
{
|
||||
if ( types )
|
||||
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
|
||||
|
@ -997,8 +922,6 @@ Val* RecordType::FieldDefault(int field) const
|
|||
}
|
||||
|
||||
int RecordType::FieldOffset(const char* field) const
|
||||
{
|
||||
if ( types )
|
||||
{
|
||||
loop_over_list(*types, i)
|
||||
{
|
||||
|
@ -1010,16 +933,6 @@ int RecordType::FieldOffset(const char* field) const
|
|||
return -1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
RecordField* rf = fields->Lookup(field);
|
||||
if ( ! rf )
|
||||
return -1;
|
||||
else
|
||||
return rf->total_offset;
|
||||
}
|
||||
}
|
||||
|
||||
const char* RecordType::FieldName(int field) const
|
||||
{
|
||||
return FieldDecl(field)->id;
|
||||
|
@ -1027,33 +940,12 @@ const char* RecordType::FieldName(int field) const
|
|||
|
||||
const TypeDecl* RecordType::FieldDecl(int field) const
|
||||
{
|
||||
if ( types )
|
||||
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)
|
||||
{
|
||||
if ( types )
|
||||
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
|
||||
|
@ -1151,11 +1043,6 @@ void RecordType::DescribeFields(ODesc* d) const
|
|||
d->SP();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
d->AddCount(1);
|
||||
base->Describe(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1208,9 +1095,6 @@ bool RecordType::DoSerialize(SerialInfo* info) const
|
|||
else if ( ! SERIALIZE(false) )
|
||||
return false;
|
||||
|
||||
SERIALIZE_OPTIONAL(base);
|
||||
|
||||
// We don't serialize the fields as we can reconstruct them.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1245,13 +1129,6 @@ bool RecordType::DoUnserialize(UnserialInfo* info)
|
|||
else
|
||||
types = 0;
|
||||
|
||||
BroType* type;
|
||||
UNSERIALIZE_OPTIONAL(type, BroType::Unserialize(info, TYPE_LIST));
|
||||
base = (TypeList*) type;
|
||||
|
||||
if ( base )
|
||||
Init(base);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1594,21 +1471,6 @@ bool VectorType::DoUnserialize(UnserialInfo* info)
|
|||
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)
|
||||
{
|
||||
static BroType* base_types[NUM_TYPES];
|
||||
|
|
21
src/Type.h
21
src/Type.h
|
@ -426,20 +426,9 @@ public:
|
|||
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 {
|
||||
public:
|
||||
RecordType(type_decl_list* types);
|
||||
RecordType(TypeList* base, type_decl_list* refinements);
|
||||
|
||||
~RecordType();
|
||||
|
||||
|
@ -473,15 +462,11 @@ public:
|
|||
void DescribeFieldsReST(ODesc* d, bool func_args) const;
|
||||
|
||||
protected:
|
||||
RecordType() { fields = 0; base = 0; types = 0; }
|
||||
|
||||
void Init(TypeList* arg_base);
|
||||
RecordType() { types = 0; }
|
||||
|
||||
DECLARE_SERIAL(RecordType)
|
||||
|
||||
int num_fields;
|
||||
PDict(RecordField)* fields;
|
||||
TypeList* base;
|
||||
type_decl_list* types;
|
||||
};
|
||||
|
||||
|
@ -587,10 +572,6 @@ protected:
|
|||
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.
|
||||
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
|
||||
#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 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:
|
||||
#
|
||||
|
@ -4574,7 +4579,8 @@ event ssh_server_version%(c: connection, version: string%);
|
|||
## maps them to descriptive names.
|
||||
##
|
||||
## .. 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%);
|
||||
|
||||
## 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.
|
||||
##
|
||||
## .. 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%);
|
||||
|
||||
## 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.
|
||||
##
|
||||
## .. 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%);
|
||||
|
||||
## 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.
|
||||
##
|
||||
## .. 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%);
|
||||
|
||||
## 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.
|
||||
##
|
||||
## .. 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%);
|
||||
|
||||
## 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
|
||||
## 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
|
||||
|
|
10
src/main.cc
10
src/main.cc
|
@ -97,7 +97,7 @@ extern char version[];
|
|||
char* command_line_policy = 0;
|
||||
vector<string> params;
|
||||
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;
|
||||
|
||||
|
@ -145,7 +145,6 @@ void usage()
|
|||
fprintf(stderr, " -g|--dump-config | dump current config into .state dir\n");
|
||||
fprintf(stderr, " -h|--help|-? | command line help\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, " -r|--readfile <readfile> | read from given tcpdump 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'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"iface", required_argument, 0, 'i'},
|
||||
{"snaplen", required_argument, 0, 'l'},
|
||||
{"doc-scripts", no_argument, 0, 'Z'},
|
||||
{"prefix", required_argument, 0, 'p'},
|
||||
{"readfile", required_argument, 0, 'r'},
|
||||
|
@ -481,10 +479,6 @@ int main(int argc, char** argv)
|
|||
interfaces.append(optarg);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
snaplen = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
prefixes.append(optarg);
|
||||
break;
|
||||
|
@ -833,6 +827,8 @@ int main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
snaplen = internal_val("snaplen")->AsCount();
|
||||
|
||||
// Initialize the secondary path, if it's needed.
|
||||
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.
|
||||
%}
|
||||
|
||||
%expect 88
|
||||
%expect 87
|
||||
|
||||
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
|
||||
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
|
||||
|
@ -53,7 +53,7 @@
|
|||
%type <expr> expr init anonymous_function
|
||||
%type <event_expr> event
|
||||
%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 <type_l> type_list
|
||||
%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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -1220,13 +1220,6 @@ func_params:
|
|||
{ $$ = 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:
|
||||
':' type
|
||||
{ $$ = $2; }
|
||||
|
|
|
@ -206,6 +206,18 @@ refine connection SSL_Conn += {
|
|||
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
|
||||
%{
|
||||
if ( ssl_extension )
|
||||
|
@ -269,13 +281,14 @@ refine connection SSL_Conn += {
|
|||
der_cert);
|
||||
|
||||
// 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 )
|
||||
{
|
||||
int num_ext = X509_get_ext_count(pTemp);
|
||||
for ( int k = 0; k < num_ext; ++k )
|
||||
{
|
||||
unsigned char *pBuffer = 0;
|
||||
int length = 0;
|
||||
uint length = 0;
|
||||
|
||||
X509_EXTENSION* ex = X509_get_ext(pTemp, k);
|
||||
if (ex)
|
||||
|
@ -283,7 +296,7 @@ refine connection SSL_Conn += {
|
|||
ASN1_STRING *pString = X509_EXTENSION_get_data(ex);
|
||||
length = ASN1_STRING_to_UTF8(&pBuffer, pString);
|
||||
//i2t_ASN1_OBJECT(&pBuffer, length, obj)
|
||||
|
||||
// printf("extension length: %u\n", length);
|
||||
// -1 indicates an error.
|
||||
if ( length < 0 )
|
||||
continue;
|
||||
|
@ -442,6 +455,10 @@ refine typeattr Handshake += &let {
|
|||
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 {
|
||||
proc : bool = $context.connection.proc_unknown_record(rec);
|
||||
};
|
||||
|
|
|
@ -61,17 +61,10 @@ type RecordText(rec: SSLRecord) = case $context.connection.state() of {
|
|||
-> 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 {
|
||||
CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec);
|
||||
ALERT -> alert : Alert(rec);
|
||||
HANDSHAKE -> handshake : PossibleEncryptedHandshake(rec);
|
||||
HANDSHAKE -> handshake : Handshake(rec);
|
||||
APPLICATION_DATA -> app_data : ApplicationData(rec);
|
||||
V2_ERROR -> v2_error : V2Error(rec);
|
||||
V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec);
|
||||
|
@ -263,6 +256,7 @@ enum HandshakeType {
|
|||
HELLO_REQUEST = 0,
|
||||
CLIENT_HELLO = 1,
|
||||
SERVER_HELLO = 2,
|
||||
SESSION_TICKET = 4, # RFC 5077
|
||||
CERTIFICATE = 11,
|
||||
SERVER_KEY_EXCHANGE = 12,
|
||||
CERTIFICATE_REQUEST = 13,
|
||||
|
@ -281,6 +275,7 @@ enum HandshakeType {
|
|||
case HELLO_REQUEST: return string("HELLO_REQUEST");
|
||||
case CLIENT_HELLO: return string("CLIENT_HELLO");
|
||||
case SERVER_HELLO: return string("SERVER_HELLO");
|
||||
case SESSION_TICKET: return string("SESSION_TICKET");
|
||||
case CERTIFICATE: return string("CERTIFICATE");
|
||||
case SERVER_KEY_EXCHANGE: return string("SERVER_KEY_EXCHANGE");
|
||||
case CERTIFICATE_REQUEST: return string("CERTIFICATE_REQUEST");
|
||||
|
@ -452,8 +447,7 @@ type V2ServerHello(rec: SSLRecord) = record {
|
|||
cert_data : bytestring &length = cert_len;
|
||||
ciphers : uint24[ciph_len/3];
|
||||
conn_id_data : bytestring &length = conn_id_len;
|
||||
} #&length = 8 + cert_len + ciph_len + conn_id_len,
|
||||
&let {
|
||||
} &let {
|
||||
state_changed : bool =
|
||||
(session_id_hit > 0 ?
|
||||
$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,
|
||||
# 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 {
|
||||
cont : bytestring &restofdata &transient;
|
||||
} &let {
|
||||
|
@ -615,13 +609,17 @@ type Finished(rec: SSLRecord) = record {
|
|||
$context.connection.lost_track();
|
||||
};
|
||||
|
||||
type SessionTicketHandshake(rec: SSLRecord) = record {
|
||||
ticket_lifetime_hint: uint32;
|
||||
data: bytestring &restofdata;
|
||||
};
|
||||
|
||||
######################################################################
|
||||
# V3 Handshake Protocol (7.)
|
||||
######################################################################
|
||||
|
||||
type UnknownHandshake(hs: Handshake, is_orig: bool) = record {
|
||||
cont : bytestring &restofdata &transient;
|
||||
data : bytestring &restofdata &transient;
|
||||
} &let {
|
||||
state_changed : bool = $context.connection.lost_track();
|
||||
};
|
||||
|
@ -634,6 +632,7 @@ type Handshake(rec: SSLRecord) = record {
|
|||
HELLO_REQUEST -> hello_request : HelloRequest(rec);
|
||||
CLIENT_HELLO -> client_hello : ClientHello(rec);
|
||||
SERVER_HELLO -> server_hello : ServerHello(rec);
|
||||
SESSION_TICKET -> session_ticket : SessionTicketHandshake(rec);
|
||||
CERTIFICATE -> certificate : Certificate(rec);
|
||||
SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec);
|
||||
CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
##! Declaration of various types that the Bro core uses internally.
|
||||
|
||||
enum dce_rpc_ptype %{
|
||||
DCE_RPC_REQUEST,
|
||||
|
@ -134,8 +135,8 @@ enum createmode_t %{
|
|||
EXCLUSIVE = 2,
|
||||
%}
|
||||
|
||||
# Decleare record types that we want to access from the even engine. These are
|
||||
# defined in bro.init.
|
||||
# Declare record types that we want to access from the event engine. These are
|
||||
# defined in init-bare.bro.
|
||||
type info_t: record;
|
||||
type fattr_t: record;
|
||||
type diropargs_t: record;
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
#empty_field (empty)
|
||||
#unset_field -
|
||||
#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
|
||||
#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
|
||||
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 - -
|
||||
#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 enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
||||
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)
|
||||
#unset_field -
|
||||
#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
|
||||
#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
|
||||
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 - -
|
||||
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 - -
|
||||
#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 enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
||||
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 - -
|
||||
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)
|
||||
#unset_field -
|
||||
#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
|
||||
#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
|
||||
1324314363.721823 - - - - - Test_Notice test notice! - - - - - worker-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
|
||||
#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 enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
||||
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)
|
||||
#unset_field -
|
||||
#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
|
||||
#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
|
||||
1324314378.560010 - - - - - Test_Notice test notice! - - - - - worker-2 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
|
||||
#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 enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
|
||||
1325633150.723248 - - - - - - Test_Notice test notice! - - - - - worker-2 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
#empty_field (empty)
|
||||
#unset_field -
|
||||
#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
|
||||
#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
|
||||
1324314387.663586 - - - - - Test_Notice test - - - - - bro Notice::ACTION_LOG 6 3600.000000 F - - - - -
|
||||
#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 enum string string addr addr port count string table[enum] table[count] interval bool string string string double double
|
||||
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 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-wait -k 2
|
||||
# @TEST-EXEC: btest-bg-wait -k 10
|
||||
# @TEST-EXEC: btest-diff manager-1/.stdout
|
||||
# @TEST-EXEC: btest-diff proxy-1/.stdout
|
||||
# @TEST-EXEC: btest-diff proxy-2/.stdout
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# @TEST-EXEC: btest-bg-run receiver bro -b ../receiver.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
|
||||
# @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 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-wait 1
|
||||
# @TEST-EXEC: btest-bg-wait 10
|
||||
# @TEST-EXEC: btest-diff controllee/.stdout
|
||||
|
||||
redef Communication::nodes = {
|
||||
|
|
|
@ -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 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
|
||||
|
||||
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 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 = {
|
||||
# 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 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: cmp receiver/test.log sender/test.log
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# @TEST-EXEC: sleep 1
|
||||
# @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro
|
||||
# @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.failure.log
|
||||
# @TEST-EXEC: btest-diff sender/test.success.log
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# @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-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-START-FILE cluster-layout.bro
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# @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-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-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: sleep 1
|
||||
# @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-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: 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-wait -k 5
|
||||
# @TEST-EXEC: btest-bg-wait -k 10
|
||||
# @TEST-EXEC: btest-diff manager-1/notice.log
|
||||
|
||||
@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 $@`
|
||||
|
||||
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
|
||||
echo "" >>$diag
|
||||
echo "#### btest-diff $i" >>$diag
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
`dirname $0`/diff-remove-timestamps \
|
||||
| `dirname $0`/diff-remove-uids \
|
||||
| `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