Merge branch 'topic/script-reference' of ssh://git.bro-ids.org/bro into topic/script-reference

This commit is contained in:
Seth Hall 2012-01-10 00:25:54 -05:00
commit a8f9af3531
68 changed files with 1823 additions and 1388 deletions

44
CHANGES
View file

@ -1,4 +1,48 @@
2.0-beta-177 | 2012-01-05 15:01:07 -0800
* Replace the --snaplen/-l command line option with a
scripting-layer option called "snaplen" (which can also be
redefined on the command line, e.g. `bro -i eth0 snaplen=65535`).
* Reduce snaplen default from 65535 to old default of 8192. Fixes
#720. (Jon Siwek)
2.0-beta-174 | 2012-01-04 12:47:10 -0800
* SSL improvements. (Seth Hall)
- Added the ssl_session_ticket_handshake event back.
- Fixed a few bugs.
- Removed the SSLv2.cc file since it's not used.
2.0-beta-169 | 2012-01-04 12:44:39 -0800
* Tuning the pretty-printed alarm mails, which now include the
covered time range into the subject. (Robin Sommer)
* Adding top-level "test" target to Makefile. (Robin Sommer)
* Adding SWIG as dependency to INSTALL. (Robin Sommer)
2.0-beta-155 | 2012-01-03 15:42:32 -0800
* Remove dead code related to record type inheritance. (Jon Siwek)
2.0-beta-152 | 2012-01-03 14:51:34 -0800
* Notices now record the transport-layer protocol. (Bernhard Amann)
2.0-beta-150 | 2012-01-03 14:42:45 -0800
* CMake 2.6 top-level 'install' target compat. Fixes #729. (Jon Siwek)
* Minor fixes to test process. Addresses #298.
* Increase timeout interval of communication-related btests. (Jon Siwek)
2.0-beta-145 | 2011-12-19 11:37:15 -0800 2.0-beta-145 | 2011-12-19 11:37:15 -0800
* Empty fields are now logged as "(empty)" by default. (Robin * Empty fields are now logged as "(empty)" by default. (Robin

View file

@ -1,4 +1,4 @@
Copyright (c) 1995-2011, The Regents of the University of California Copyright (c) 1995-2012, The Regents of the University of California
through the Lawrence Berkeley National Laboratory and the through the Lawrence Berkeley National Laboratory and the
International Computer Science Institute. All rights reserved. International Computer Science Institute. All rights reserved.

13
INSTALL
View file

@ -14,10 +14,11 @@ before you begin:
* OpenSSL (headers and libraries) http://www.openssl.org * OpenSSL (headers and libraries) http://www.openssl.org
* Libmagic For identifying file types (e.g., in FTP transfers). * SWIG http://www.swig.org
* Libz For decompressing HTTP bodies by the HTTP analyzer, and for * Libmagic
compressed Bro-to-Bro communication.
* Libz
Bro can make uses of some optional libraries if they are found at Bro can make uses of some optional libraries if they are found at
installation time: installation time:
@ -27,11 +28,13 @@ installation time:
Bro also needs the following tools, but on most systems they will Bro also needs the following tools, but on most systems they will
already come preinstalled: already come preinstalled:
* Bash (For Bro Control).
* BIND8 (headers and libraries) * BIND8 (headers and libraries)
* Bison (GNU Parser Generator) * Bison (GNU Parser Generator)
* Flex (Fast Lexical Analyzer) * Flex (Fast Lexical Analyzer)
* Perl (Used only during the Bro build process) * Perl (Used only during the Bro build process)
Installation Installation
============ ============
@ -69,8 +72,8 @@ Running Bro
=========== ===========
Bro is a complex program and it takes a bit of time to get familiar Bro is a complex program and it takes a bit of time to get familiar
with it. A good place for newcomers to start is the with it. A good place for newcomers to start is the Quickstart Guide
:doc:`quick start guide <quickstart>`. at http://www.bro-ids.org/documentation/quickstart.bro.html.
For developers that wish to run Bro directly from the ``build/`` For developers that wish to run Bro directly from the ``build/``
directory (i.e., without performing ``make install``), they will have directory (i.e., without performing ``make install``), they will have

View file

@ -14,7 +14,7 @@ HAVE_MODULES=git submodule | grep -v cmake >/dev/null
all: configured all: configured
$(MAKE) -C $(BUILD) $@ $(MAKE) -C $(BUILD) $@
install: configured install: configured all
$(MAKE) -C $(BUILD) $@ $(MAKE) -C $(BUILD) $@
install-aux: configured install-aux: configured
@ -60,6 +60,9 @@ bindist:
distclean: distclean:
rm -rf $(BUILD) rm -rf $(BUILD)
test:
@(cd testing && make )
configured: configured:
@test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 ) @test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 )
@test -e $(BUILD)/Makefile || ( echo "Error: No build/Makefile found. Did you run configure?" && exit 1 ) @test -e $(BUILD)/Makefile || ( echo "Error: No build/Makefile found. Did you run configure?" && exit 1 )

51
NEWS Normal file
View 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
View file

@ -4,13 +4,15 @@ Bro Network Security Monitor
Bro is a powerful framework for network analysis and security Bro is a powerful framework for network analysis and security
monitoring. Please see the INSTALL file for installation instructions monitoring. Please see the INSTALL file for installation instructions
and pointers for getting started. For more documentation, research and pointers for getting started. NEWS contains releases notes for the
publications, and community contact information, see Bro's home page: current version, and CHANGES has the complete history of changes.
Please see COPYING for licensing information.
For more documentation, research publications, and community contact
information, please see Bro's home page:
http://www.bro-ids.org http://www.bro-ids.org
Please see COPYING for licensing information.
On behalf of the Bro Development Team, On behalf of the Bro Development Team,
Vern Paxson & Robin Sommer, Vern Paxson & Robin Sommer,

View file

@ -1 +1 @@
2.0-beta-145 2.0-beta-177

1
doc/.gitignore vendored
View file

@ -1 +1,2 @@
html html
*.pyc

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
View 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;
}
}

View file

@ -1,3 +1,17 @@
a.toc-backref {
color: #333;
}
h1, h2, h3, h4, h5, h6,
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
padding:0 0 0px 0;
}
ul {
padding-bottom: 0px;
}
h1 { h1 {
font-weight: bold; font-weight: bold;
font-size: 32px; font-size: 32px;
@ -14,3 +28,133 @@ th.field-name
{ {
white-space:nowrap; white-space:nowrap;
} }
h2 {
margin-top: 50px;
padding-bottom: 5px;
margin-bottom: 30px;
border-bottom: 1px solid;
border-color: #aaa;
font-style: normal;
}
div.section h3 {
font-style: normal;
}
h3 {
font-size: 20px;
margin-top: 40px;
margin-bottom: 0¡px;
font-weight: bold;
font-style: normal;
}
h3.widgettitle {
font-style: normal;
}
h4 {
font-size:18px;
font-style: normal;
margin-bottom: 0em;
margin-top: 40px;
font-style: italic;
}
h5 {
font-size:16px;
}
h6 {
font-size:15px;
}
.toc-backref {
color: #333;
}
.contents ul {
padding-bottom: 1em;
}
dl.namespace {
display: none;
}
dl dt {
font-weight: normal;
}
table.docutils tbody {
margin: 1em 1em 1em 1em;
}
table.docutils td {
padding: 5pt 5pt 5pt 5pt;
font-size: 14px;
border-left: 0;
border-right: 0;
}
dl pre {
font-size: 14px;
}
table.docutils th {
padding: 5pt 5pt 5pt 5pt;
font-size: 14px;
font-style: normal;
border-left: 0;
border-right: 0;
}
table.docutils tr:first-child td {
#border-top: 1px solid #aaa;
}
.download {
font-family:"Courier New", Courier, mono;
font-weight: normal;
}
dt:target, .highlighted {
background-color: #ccc;
}
p {
padding-bottom: 0px;
}
p.last {
margin-bottom: 0px;
}
dl {
padding: 1em 1em 1em 1em;
background: #fffff0;
border: 1px solid #aaa;
}
dl {
margin-bottom: 10px;
}
table.docutils {
background: #fffff0;
border-collapse: collapse;
border: 1px solid #ddd;
}
dl table.docutils {
border: 0;
}
table.docutils dl {
border: 1px dashed #666;
}

0
doc/_static/broxygen-extra.js vendored Normal file
View file

437
doc/_static/broxygen.css vendored Normal file
View 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;
}

View file

@ -1,3 +0,0 @@
$(document).ready(function() {
$('.docutils.download').removeClass('download');
});

58
doc/_static/pygments.css vendored Normal file
View 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 */

View file

@ -1,11 +1,12 @@
{% extends "!layout.html" %} {% extends "!layout.html" %}
{% block extrahead %} {% block extrahead %}
<link rel="stylesheet" type="text/css" href="http://www.bro-ids.org/css/bro-ids.css" /> <link rel="stylesheet" type="text/css" href="{{ pathto('_static/broxygen.css', 1) }}"></script>
<link rel="stylesheet" type="text/css" href="http://www.bro-ids.org/css/960.css" /> <link rel="stylesheet" type="text/css" href="{{ pathto('_static/960.css', 1) }}"></script>
<link rel="stylesheet" type="text/css" href="http://www.bro-ids.org/css/pygments.css" /> <link rel="stylesheet" type="text/css" href="{{ pathto('_static/pygments.css', 1) }}"></script>
<link rel="stylesheet" type="text/css" href="{{ pathto('_static/broxygen-extra.css', 1) }}"></script> <link rel="stylesheet" type="text/css" href="{{ pathto('_static/broxygen-extra.css', 1) }}"></script>
<script type="text/javascript" src="{{ pathto('_static/download.js', 1) }}"></script>
<script type="text/javascript" src="{{ pathto('_static/broxygen-extra.js', 1) }}"></script>
{% endblock %} {% endblock %}
{% block header %} {% block header %}
@ -47,6 +48,7 @@
Table of Contents Table of Contents
</h3> </h3>
<p> <p>
<!-- <ul id="sidebar-toc"></ul> -->
<ul>{{toc}}</ul> <ul>{{toc}}</ul>
</p> </p>
</div> </div>

View file

@ -24,7 +24,7 @@ sys.path.insert(0, os.path.abspath('sphinx-sources/ext'))
# Add any Sphinx extension module names here, as strings. They can be extensions # Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['bro', 'rst_directive', 'sphinx.ext.todo'] extensions = ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc']
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static'] templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static']
@ -40,7 +40,7 @@ master_doc = 'index'
# General information about the project. # General information about the project.
project = u'Bro' project = u'Bro'
copyright = u'2011, The Bro Project' copyright = u'2012, The Bro Project'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@ -169,6 +169,7 @@ html_sidebars = {
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = 'Broxygen' htmlhelp_basename = 'Broxygen'
html_add_permalinks = None
# -- Options for LaTeX output -------------------------------------------------- # -- Options for LaTeX output --------------------------------------------------
@ -208,7 +209,6 @@ latex_documents = [
# If false, no module index is generated. # If false, no module index is generated.
#latex_domain_indices = True #latex_domain_indices = True
# -- Options for manual page output -------------------------------------------- # -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples # One entry per manual page. List of tuples

29
doc/ext/adapt-toc.py Normal file
View 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)

View file

@ -28,6 +28,23 @@ Here are some pointers to more information:
Lothar Braun et. al evaluates packet capture performance on Lothar Braun et. al evaluates packet capture performance on
commodity hardware commodity hardware
Are there any gotchas regarding interface configuration for live capture? Or why might I be seeing abnormally large packets much greater than interface MTU?
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Some NICs offload the reassembly of traffic into "superpackets" so that
fewer packets are then passed up the stack (e.g. "TCP segmentation
offload", or "generic segmentation offload"). The result is that the
capturing application will observe packets much larger than the MTU size
of the interface they were captured from and may also interfere with the
maximum packet capture length, ``snaplen``, so it's a good idea to disable
an interface's offloading features.
You can use the ``ethtool`` program on Linux to view and disable
offloading features of an interface. See this page for more explicit
directions:
http://securityonion.blogspot.com/2011/10/when-is-full-packet-capture-not-full.html
What does an error message like ``internal error: NB-DNS error`` mean? What does an error message like ``internal error: NB-DNS error`` mean?
--------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------

View file

@ -31,15 +31,15 @@ See the `bro downloads page`_ for currently supported/targeted platforms.
* RPM * RPM
.. console:: .. console::
sudo yum localinstall Bro-all*.rpm sudo yum localinstall Bro-all*.rpm
* DEB * DEB
.. console:: .. console::
sudo gdebi Bro-all-*.deb sudo gdebi Bro-all-*.deb
* MacOS Disk Image with Installer * MacOS Disk Image with Installer
@ -56,26 +56,32 @@ Building From Source
Required Dependencies Required Dependencies
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
The following dependencies are required to build Bro:
* RPM/RedHat-based Linux: * RPM/RedHat-based Linux:
.. console:: .. console::
sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel
* DEB/Debian-based Linux: * DEB/Debian-based Linux:
.. console:: .. console::
sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev
* FreeBSD * FreeBSD
Most required dependencies should come with a minimal FreeBSD install Most required dependencies should come with a minimal FreeBSD install
except for the following. except for the following.
.. console:: .. console::
sudo pkg_add -r cmake swig bison python sudo pkg_add -r bash cmake swig bison python
Note that ``bash`` needs to be in ``PATH``, which by default it is
not. The FreeBSD package installs the binary into
``/usr/local/bin``.
* Mac OS X * Mac OS X
@ -99,21 +105,21 @@ sending emails.
* RPM/RedHat-based Linux: * RPM/RedHat-based Linux:
.. console:: .. console::
sudo yum install GeoIP-devel sendmail sudo yum install GeoIP-devel sendmail
* DEB/Debian-based Linux: * DEB/Debian-based Linux:
.. console:: .. console::
sudo apt-get install libgeoip-dev sendmail sudo apt-get install libgeoip-dev sendmail
* Ports-based FreeBSD * Ports-based FreeBSD
.. console:: .. console::
sudo pkg_add -r GeoIP sudo pkg_add -r GeoIP
sendmail is typically already available. sendmail is typically already available.

View file

@ -168,10 +168,6 @@ New Default Settings
are loaded. See ``PacketFilter::all_packets`` for how to revert to old are loaded. See ``PacketFilter::all_packets`` for how to revert to old
behavior. behavior.
- By default, Bro now sets a libpcap snaplen of 65535. Depending on
the OS, this may have performance implications and you can use the
``--snaplen`` option to change the value.
API Changes API Changes
----------- -----------

View file

@ -10,18 +10,21 @@ module Notice;
export { export {
## Activate pretty-printed alarm summaries. ## Activate pretty-printed alarm summaries.
const pretty_print_alarms = T &redef; const pretty_print_alarms = T &redef;
## Address to send the pretty-printed reports to. Default if not set is ## Address to send the pretty-printed reports to. Default if not set is
## :bro:id:`Notice::mail_dest`. ## :bro:id:`Notice::mail_dest`.
const mail_dest_pretty_printed = "" &redef; const mail_dest_pretty_printed = "" &redef;
## If an address from one of these networks is reported, we mark ## If an address from one of these networks is reported, we mark
## the entry with an addition quote symbol (that is, ">"). Many MUAs ## the entry with an additional quote symbol (i.e., ">"). Many MUAs
## then highlight such lines differently. ## then highlight such lines differently.
global flag_nets: set[subnet] &redef; global flag_nets: set[subnet] &redef;
## Function that renders a single alarm. Can be overidden. ## Function that renders a single alarm. Can be overidden.
global pretty_print_alarm: function(out: file, n: Info) &redef; global pretty_print_alarm: function(out: file, n: Info) &redef;
## Force generating mail file, even if reading from traces or no mail
## destination is defined. This is mainly for testing.
global force_email_summaries = F &redef;
} }
# We maintain an old-style file recording the pretty-printed alarms. # We maintain an old-style file recording the pretty-printed alarms.
@ -32,6 +35,9 @@ global pp_alarms_open: bool = F;
# Returns True if pretty-printed alarm summaries are activated. # Returns True if pretty-printed alarm summaries are activated.
function want_pp() : bool function want_pp() : bool
{ {
if ( force_email_summaries )
return T;
return (pretty_print_alarms && ! reading_traces() return (pretty_print_alarms && ! reading_traces()
&& (mail_dest != "" || mail_dest_pretty_printed != "")); && (mail_dest != "" || mail_dest_pretty_printed != ""));
} }
@ -41,38 +47,49 @@ function pp_open()
{ {
if ( pp_alarms_open ) if ( pp_alarms_open )
return; return;
pp_alarms_open = T; pp_alarms_open = T;
pp_alarms = open(pp_alarms_name); pp_alarms = open(pp_alarms_name);
local dest = mail_dest_pretty_printed != "" ? mail_dest_pretty_printed
: mail_dest;
local headers = email_headers("Alarm summary", dest);
write_file(pp_alarms, headers + "\n");
} }
# Closes and mails out the current output file. # Closes and mails out the current output file.
function pp_send() function pp_send(rinfo: Log::RotationInfo)
{ {
if ( ! pp_alarms_open ) if ( ! pp_alarms_open )
return; return;
write_file(pp_alarms, "\n\n--\n[Automatically generated]\n\n"); write_file(pp_alarms, "\n\n--\n[Automatically generated]\n\n");
close(pp_alarms); close(pp_alarms);
system(fmt("/bin/cat %s | %s -t -oi && /bin/rm %s",
pp_alarms_name, sendmail, pp_alarms_name));
pp_alarms_open = F; pp_alarms_open = F;
local from = strftime("%H:%M:%S", rinfo$open);
local to = strftime("%H:%M:%S", rinfo$close);
local subject = fmt("Alarm summary from %s-%s", from, to);
local dest = mail_dest_pretty_printed != "" ? mail_dest_pretty_printed
: mail_dest;
if ( dest == "" )
# No mail destination configured, just leave the file alone. This is mainly for
# testing.
return;
local headers = email_headers(subject, dest);
local header_name = pp_alarms_name + ".tmp";
local header = open(header_name);
write_file(header, headers + "\n");
close(header);
system(fmt("/bin/cat %s %s | %s -t -oi && /bin/rm -f %s %s",
header_name, pp_alarms_name, sendmail, header_name, pp_alarms_name));
} }
# Postprocessor function that triggers the email. # Postprocessor function that triggers the email.
function pp_postprocessor(info: Log::RotationInfo): bool function pp_postprocessor(info: Log::RotationInfo): bool
{ {
if ( want_pp() ) if ( want_pp() )
pp_send(); pp_send(info);
return T; return T;
} }
@ -80,7 +97,7 @@ event bro_init()
{ {
if ( ! want_pp() ) if ( ! want_pp() )
return; return;
# This replaces the standard non-pretty-printing filter. # This replaces the standard non-pretty-printing filter.
Log::add_filter(Notice::ALARM_LOG, Log::add_filter(Notice::ALARM_LOG,
[$name="alarm-mail", $writer=Log::WRITER_NONE, [$name="alarm-mail", $writer=Log::WRITER_NONE,
@ -92,13 +109,13 @@ event notice(n: Notice::Info) &priority=-5
{ {
if ( ! want_pp() ) if ( ! want_pp() )
return; return;
if ( ACTION_LOG !in n$actions ) if ( ACTION_ALARM !in n$actions )
return; return;
if ( ! pp_alarms_open ) if ( ! pp_alarms_open )
pp_open(); pp_open();
pretty_print_alarm(pp_alarms, n); pretty_print_alarm(pp_alarms, n);
} }
@ -108,12 +125,12 @@ function do_msg(out: file, n: Info, line1: string, line2: string, line3: string,
@ifdef ( Notice::ACTION_ADD_GEODATA ) # Make tests happy, cyclic dependency. @ifdef ( Notice::ACTION_ADD_GEODATA ) # Make tests happy, cyclic dependency.
if ( n?$remote_location && n$remote_location?$country_code ) if ( n?$remote_location && n$remote_location?$country_code )
country = fmt(" (remote location %s)", n$remote_location$country_code); country = fmt(" (remote location %s)", n$remote_location$country_code);
@endif @endif
line1 = cat(line1, country); line1 = cat(line1, country);
local resolved = ""; local resolved = "";
if ( host1 != 0.0.0.0 ) if ( host1 != 0.0.0.0 )
resolved = fmt("%s # %s = %s", resolved, host1, name1); resolved = fmt("%s # %s = %s", resolved, host1, name1);
@ -133,64 +150,64 @@ function do_msg(out: file, n: Info, line1: string, line2: string, line3: string,
function pretty_print_alarm(out: file, n: Info) function pretty_print_alarm(out: file, n: Info)
{ {
local pdescr = ""; local pdescr = "";
@if ( Cluster::is_enabled() ) @if ( Cluster::is_enabled() )
pdescr = "local"; pdescr = "local";
if ( n?$src_peer ) if ( n?$src_peer )
pdescr = n$src_peer?$descr ? n$src_peer$descr : fmt("%s", n$src_peer$host); pdescr = n$src_peer?$descr ? n$src_peer$descr : fmt("%s", n$src_peer$host);
pdescr = fmt("<%s> ", pdescr); pdescr = fmt("<%s> ", pdescr);
@endif @endif
local msg = fmt( "%s%s", pdescr, n$msg); local msg = fmt( "%s%s", pdescr, n$msg);
local who = ""; local who = "";
local h1 = 0.0.0.0; local h1 = 0.0.0.0;
local h2 = 0.0.0.0; local h2 = 0.0.0.0;
local orig_p = ""; local orig_p = "";
local resp_p = ""; local resp_p = "";
if ( n?$id ) if ( n?$id )
{ {
orig_p = fmt(":%s", n$id$orig_p); h1 = n$id$orig_h;
resp_p = fmt(":%s", n$id$resp_p); h2 = n$id$resp_h;
who = fmt("%s:%s -> %s:%s", h1, n$id$orig_p, h2, n$id$resp_p);
} }
else if ( n?$src && n?$dst )
if ( n?$src && n?$dst )
{ {
h1 = n$src; h1 = n$src;
h2 = n$dst; h2 = n$dst;
who = fmt("%s%s -> %s%s", h1, orig_p, h2, resp_p); who = fmt("%s -> %s", h1, h2);
if ( n?$uid )
who = fmt("%s (uid %s)", who, n$uid );
} }
else if ( n?$src ) else if ( n?$src )
{ {
local p = "";
if ( n?$p )
p = fmt(":%s", n$p);
h1 = n$src; h1 = n$src;
who = fmt("%s%s", h1, p); who = fmt("%s%s", h1, (n?$p ? fmt(":%s", n$p) : ""));
} }
if ( n?$uid )
who = fmt("%s (uid %s)", who, n$uid );
local flag = (h1 in flag_nets || h2 in flag_nets); local flag = (h1 in flag_nets || h2 in flag_nets);
local line1 = fmt(">%s %D %s %s", (flag ? ">" : " "), network_time(), n$note, who); local line1 = fmt(">%s %D %s %s", (flag ? ">" : " "), network_time(), n$note, who);
local line2 = fmt(" %s", msg); local line2 = fmt(" %s", msg);
local line3 = n?$sub ? fmt(" %s", n$sub) : ""; local line3 = n?$sub ? fmt(" %s", n$sub) : "";
if ( h1 == 0.0.0.0 ) if ( h1 == 0.0.0.0 )
{ {
do_msg(out, n, line1, line2, line3, h1, "", h2, ""); do_msg(out, n, line1, line2, line3, h1, "", h2, "");
return; return;
} }
if ( reading_traces() )
{
do_msg(out, n, line1, line2, line3, h1, "<skipped>", h2, "<skipped>");
return;
}
when ( local h1name = lookup_addr(h1) ) when ( local h1name = lookup_addr(h1) )
{ {
if ( h2 == 0.0.0.0 ) if ( h2 == 0.0.0.0 )

View file

@ -73,8 +73,12 @@ export {
## reference to the actual connection will be deleted after applying ## reference to the actual connection will be deleted after applying
## the notice policy. ## the notice policy.
iconn: icmp_conn &optional; iconn: icmp_conn &optional;
## The type of the notice. ## The transport protocol. Filled automatically when either conn, iconn
## or p is specified.
proto: transport_proto &log &optional;
## The :bro:enum:`Notice::Type` of the notice.
note: Type &log; note: Type &log;
## The human readable message for the notice. ## The human readable message for the notice.
msg: string &log &optional; msg: string &log &optional;
@ -535,8 +539,12 @@ function apply_policy(n: Notice::Info)
n$p = n$id$resp_p; n$p = n$id$resp_p;
} }
if ( n?$p )
n$proto = get_port_transport_proto(n$p);
if ( n?$iconn ) if ( n?$iconn )
{ {
n$proto = icmp;
if ( ! n?$src ) if ( ! n?$src )
n$src = n$iconn$orig_h; n$src = n$iconn$orig_h;
if ( ! n?$dst ) if ( ! n?$dst )

View file

@ -2331,6 +2331,9 @@ const ignore_keep_alive_rexmit = F &redef;
## .. bro:see:: tunnel_port ## .. bro:see:: tunnel_port
const parse_udp_tunnels = F &redef; const parse_udp_tunnels = F &redef;
# Load the logging framework here because it uses fairly deep integration with ## Number of bytes per packet to capture from live interfaces.
const snaplen = 8192 &redef;
# Load the logging framework here because it uses fairly deep integration with
# BiFs and script-land defined types. # BiFs and script-land defined types.
@load base/frameworks/logging @load base/frameworks/logging

View file

@ -1,23 +1,27 @@
##! This script can be used to extract either the originator's data or the ##! This script can be used to extract either the originator's data or the
##! responders data or both. By default nothing is extracted, and in order ##! responders data or both. By default nothing is extracted, and in order
##! to actually extract data the ``c$extract_orig`` and/or the ##! to actually extract data the ``c$extract_orig`` and/or the
##! ``c$extract_resp`` variable must be set to T. One way to achieve this ##! ``c$extract_resp`` variable must be set to ``T``. One way to achieve this
##! would be to handle the connection_established event elsewhere and set the ##! would be to handle the :bro:id:`connection_established` event elsewhere
##! extract_orig and extract_resp options there. However, there may be trouble ##! and set the ``extract_orig`` and ``extract_resp`` options there.
##! with the timing due the event queue delay. ##! However, there may be trouble with the timing due to event queue delay.
##! This script does not work well in a cluster context unless it has a ##!
##! remotely mounted disk to write the content files to. ##! .. note::
##!
##! This script does not work well in a cluster context unless it has a
##! remotely mounted disk to write the content files to.
@load base/utils/files @load base/utils/files
module Conn; module Conn;
export { export {
## The prefix given to files as they are opened on disk. ## The prefix given to files containing extracted connections as they are
## opened on disk.
const extraction_prefix = "contents" &redef; const extraction_prefix = "contents" &redef;
## If this variable is set to T, then all contents of all files will be ## If this variable is set to ``T``, then all contents of all connections
## extracted. ## will be extracted.
const default_extract = F &redef; const default_extract = F &redef;
} }

View file

@ -4,7 +4,7 @@
module Conn; module Conn;
export { export {
## Define inactivty timeouts by the service detected being used over ## Define inactivity timeouts by the service detected being used over
## the connection. ## the connection.
const analyzer_inactivity_timeouts: table[AnalyzerTag] of interval = { const analyzer_inactivity_timeouts: table[AnalyzerTag] of interval = {
# For interactive services, allow longer periods of inactivity. # For interactive services, allow longer periods of inactivity.

View file

@ -1,17 +1,33 @@
##! This script manages the tracking/logging of general information regarding
##! TCP, UDP, and ICMP traffic. For UDP and ICMP, "connections" are to
##! be interpreted using flow semantics (sequence of packets from a source
##! host/post to a destination host/port). Further, ICMP "ports" are to
##! be interpreted as the source port meaning the ICMP message type and
##! the destination port being the ICMP message code.
@load base/utils/site @load base/utils/site
module Conn; module Conn;
export { export {
## The connection logging stream identifier.
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
## The record type which contains column fields of the connection log.
type Info: record { type Info: record {
## This is the time of the first packet. ## This is the time of the first packet.
ts: time &log; ts: time &log;
## A unique identifier of a connection.
uid: string &log; uid: string &log;
## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log; id: conn_id &log;
## The transport layer protocol of the connection.
proto: transport_proto &log; proto: transport_proto &log;
## An identification of an application protocol being sent over the
## the connection.
service: string &log &optional; service: string &log &optional;
## How long the connection lasted. For 3-way or 4-way connection
## tear-downs, this will not include the final ACK.
duration: interval &log &optional; duration: interval &log &optional;
## The number of payload bytes the originator sent. For TCP ## The number of payload bytes the originator sent. For TCP
## this is taken from sequence numbers and might be inaccurate ## this is taken from sequence numbers and might be inaccurate
@ -51,8 +67,8 @@ export {
## have been completed prior to the packet loss. ## have been completed prior to the packet loss.
missed_bytes: count &log &default=0; missed_bytes: count &log &default=0;
## Records the state history of (TCP) connections as ## Records the state history of connections as a string of letters.
## a string of letters. ## For TCP connections the meaning of those letters is:
## ##
## ====== ==================================================== ## ====== ====================================================
## Letter Meaning ## Letter Meaning
@ -71,7 +87,8 @@ export {
## originator and lower case then means the responder. ## originator and lower case then means the responder.
## Also, there is compression. We only record one "d" in each direction, ## Also, there is compression. We only record one "d" in each direction,
## for instance. I.e., we just record that data went in that direction. ## for instance. I.e., we just record that data went in that direction.
## This history is not meant to encode how much data that happened to be. ## This history is not meant to encode how much data that happened to
## be.
history: string &log &optional; history: string &log &optional;
## Number of packets the originator sent. ## Number of packets the originator sent.
## Only set if :bro:id:`use_conn_size_analyzer` = T ## Only set if :bro:id:`use_conn_size_analyzer` = T
@ -85,7 +102,9 @@ export {
## Number IP level bytes the responder sent. See ``orig_pkts``. ## Number IP level bytes the responder sent. See ``orig_pkts``.
resp_ip_bytes: count &log &optional; resp_ip_bytes: count &log &optional;
}; };
## Event that can be handled to access the :bro:type:`Conn::Info`
## record as it is sent on to the logging framework.
global log_conn: event(rec: Info); global log_conn: event(rec: Info);
} }

View file

@ -4,9 +4,9 @@
module DNS; module DNS;
export { export {
const PTR = 12; const PTR = 12; ##< RR TYPE value for a domain name pointer.
const EDNS = 41; const EDNS = 41; ##< An OPT RR TYPE value described by EDNS.
const ANY = 255; const ANY = 255; ##< A QTYPE value describing a request for all records.
## Mapping of DNS query type codes to human readable string representation. ## Mapping of DNS query type codes to human readable string representation.
const query_types = { const query_types = {
@ -29,50 +29,43 @@ export {
[ANY] = "*", [ANY] = "*",
} &default = function(n: count): string { return fmt("query-%d", n); }; } &default = function(n: count): string { return fmt("query-%d", n); };
const code_types = {
[0] = "X0",
[1] = "Xfmt",
[2] = "Xsrv",
[3] = "Xnam",
[4] = "Ximp",
[5] = "X[",
} &default="?";
## Errors used for non-TSIG/EDNS types. ## Errors used for non-TSIG/EDNS types.
const base_errors = { const base_errors = {
[0] = "NOERROR", ##< No Error [0] = "NOERROR", # No Error
[1] = "FORMERR", ##< Format Error [1] = "FORMERR", # Format Error
[2] = "SERVFAIL", ##< Server Failure [2] = "SERVFAIL", # Server Failure
[3] = "NXDOMAIN", ##< Non-Existent Domain [3] = "NXDOMAIN", # Non-Existent Domain
[4] = "NOTIMP", ##< Not Implemented [4] = "NOTIMP", # Not Implemented
[5] = "REFUSED", ##< Query Refused [5] = "REFUSED", # Query Refused
[6] = "YXDOMAIN", ##< Name Exists when it should not [6] = "YXDOMAIN", # Name Exists when it should not
[7] = "YXRRSET", ##< RR Set Exists when it should not [7] = "YXRRSET", # RR Set Exists when it should not
[8] = "NXRRSet", ##< RR Set that should exist does not [8] = "NXRRSet", # RR Set that should exist does not
[9] = "NOTAUTH", ##< Server Not Authoritative for zone [9] = "NOTAUTH", # Server Not Authoritative for zone
[10] = "NOTZONE", ##< Name not contained in zone [10] = "NOTZONE", # Name not contained in zone
[11] = "unassigned-11", ##< available for assignment [11] = "unassigned-11", # available for assignment
[12] = "unassigned-12", ##< available for assignment [12] = "unassigned-12", # available for assignment
[13] = "unassigned-13", ##< available for assignment [13] = "unassigned-13", # available for assignment
[14] = "unassigned-14", ##< available for assignment [14] = "unassigned-14", # available for assignment
[15] = "unassigned-15", ##< available for assignment [15] = "unassigned-15", # available for assignment
[16] = "BADVERS", ##< for EDNS, collision w/ TSIG [16] = "BADVERS", # for EDNS, collision w/ TSIG
[17] = "BADKEY", ##< Key not recognized [17] = "BADKEY", # Key not recognized
[18] = "BADTIME", ##< Signature out of time window [18] = "BADTIME", # Signature out of time window
[19] = "BADMODE", ##< Bad TKEY Mode [19] = "BADMODE", # Bad TKEY Mode
[20] = "BADNAME", ##< Duplicate key name [20] = "BADNAME", # Duplicate key name
[21] = "BADALG", ##< Algorithm not supported [21] = "BADALG", # Algorithm not supported
[22] = "BADTRUNC", ##< draft-ietf-dnsext-tsig-sha-05.txt [22] = "BADTRUNC", # draft-ietf-dnsext-tsig-sha-05.txt
[3842] = "BADSIG", ##< 16 <= number collision with EDNS(16); [3842] = "BADSIG", # 16 <= number collision with EDNS(16);
##< this is a translation from TSIG(16) # this is a translation from TSIG(16)
} &default = function(n: count): string { return fmt("rcode-%d", n); }; } &default = function(n: count): string { return fmt("rcode-%d", n); };
# This deciphers EDNS Z field values. ## This deciphers EDNS Z field values.
const edns_zfield = { const edns_zfield = {
[0] = "NOVALUE", # regular entry [0] = "NOVALUE", # regular entry
[32768] = "DNS_SEC_OK", # accepts DNS Sec RRs [32768] = "DNS_SEC_OK", # accepts DNS Sec RRs
} &default="?"; } &default="?";
## Possible values of the CLASS field in resource records or QCLASS field
## in query messages.
const classes = { const classes = {
[1] = "C_INTERNET", [1] = "C_INTERNET",
[2] = "C_CSNET", [2] = "C_CSNET",
@ -81,4 +74,4 @@ export {
[254] = "C_NONE", [254] = "C_NONE",
[255] = "C_ANY", [255] = "C_ANY",
} &default = function(n: count): string { return fmt("qclass-%d", n); }; } &default = function(n: count): string { return fmt("qclass-%d", n); };
} }

View file

@ -1,38 +1,80 @@
##! Base DNS analysis script which tracks and logs DNS queries along with
##! their responses.
@load ./consts @load ./consts
module DNS; module DNS;
export { export {
## The DNS logging stream identifier.
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
## The record type which contains the column fields of the DNS log.
type Info: record { type Info: record {
## The earliest time at which a DNS protocol message over the
## associated connection is observed.
ts: time &log; ts: time &log;
## A unique identifier of the connection over which DNS messages
## are being transferred.
uid: string &log; uid: string &log;
## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log; id: conn_id &log;
## The transport layer protocol of the connection.
proto: transport_proto &log; proto: transport_proto &log;
## A 16 bit identifier assigned by the program that generated the
## DNS query. Also used in responses to match up replies to
## outstanding queries.
trans_id: count &log &optional; trans_id: count &log &optional;
## The domain name that is the subject of the DNS query.
query: string &log &optional; query: string &log &optional;
## The QCLASS value specifying the class of the query.
qclass: count &log &optional; qclass: count &log &optional;
## A descriptive name for the class of the query.
qclass_name: string &log &optional; qclass_name: string &log &optional;
## A QTYPE value specifying the type of the query.
qtype: count &log &optional; qtype: count &log &optional;
## A descriptive name for the type of the query.
qtype_name: string &log &optional; qtype_name: string &log &optional;
## The response code value in DNS response messages.
rcode: count &log &optional; rcode: count &log &optional;
## A descriptive name for the response code value.
rcode_name: string &log &optional; rcode_name: string &log &optional;
## Whether the message is a query (F) or response (T).
QR: bool &log &default=F; QR: bool &log &default=F;
## The Authoritative Answer bit for response messages specifies that
## the responding name server is an authority for the domain name
## in the question section.
AA: bool &log &default=F; AA: bool &log &default=F;
## The Truncation bit specifies that the message was truncated.
TC: bool &log &default=F; TC: bool &log &default=F;
## The Recursion Desired bit indicates to a name server to recursively
## purse the query.
RD: bool &log &default=F; RD: bool &log &default=F;
## The Recursion Available bit in a response message indicates if
## the name server supports recursive queries.
RA: bool &log &default=F; RA: bool &log &default=F;
## A reserved field that is currently supposed to be zero in all
## queries and responses.
Z: count &log &default=0; Z: count &log &default=0;
## The set of resource descriptions in answer of the query.
answers: vector of string &log &optional; answers: vector of string &log &optional;
## The caching intervals of the associated RRs described by the
## ``answers`` field.
TTLs: vector of interval &log &optional; TTLs: vector of interval &log &optional;
## This value indicates if this request/response pair is ready to be logged. ## This value indicates if this request/response pair is ready to be
## logged.
ready: bool &default=F; ready: bool &default=F;
## The total number of resource records in a reply message's answer
## section.
total_answers: count &optional; total_answers: count &optional;
## The total number of resource records in a reply message's answer,
## authority, and additional sections.
total_replies: count &optional; total_replies: count &optional;
}; };
## A record type which tracks the status of DNS queries for a given
## :bro:type:`connection`.
type State: record { type State: record {
## Indexed by query id, returns Info record corresponding to ## Indexed by query id, returns Info record corresponding to
## query/response which haven't completed yet. ## query/response which haven't completed yet.
@ -44,11 +86,21 @@ export {
finished_answers: set[count] &optional; finished_answers: set[count] &optional;
}; };
## An event that can be handled to access the :bro:type:`DNS::Info`
## record as it is sent to the logging framework.
global log_dns: event(rec: Info); global log_dns: event(rec: Info);
## This is called by the specific dns_*_reply events with a "reply" which ## This is called by the specific dns_*_reply events with a "reply" which
## may not represent the full data available from the resource record, but ## may not represent the full data available from the resource record, but
## it's generally considered a summarization of the response(s). ## it's generally considered a summarization of the response(s).
##
## c: The connection record for which to fill in DNS reply data.
##
## msg: The DNS message header information for the response.
##
## ans: The general information of a RR response.
##
## reply: The specific response information according to RR type/class.
global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string); global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string);
} }

View file

@ -1,3 +1,5 @@
##! Base SSL analysis script.
@load ./consts @load ./consts
module SSL; module SSL;
@ -6,6 +8,7 @@ export {
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
type Info: record { type Info: record {
## Time when the SSL connection began.
ts: time &log; ts: time &log;
uid: string &log; uid: string &log;
id: conn_id &log; id: conn_id &log;

View file

@ -8,6 +8,7 @@ export {
redef enum Log::ID += { LOG }; redef enum Log::ID += { LOG };
type Info: record { type Info: record {
## Timestamp of when the syslog message was seen.
ts: time &log; ts: time &log;
uid: string &log; uid: string &log;
id: conn_id &log; id: conn_id &log;

View file

@ -8,8 +8,10 @@
module Known; module Known;
export { export {
## The known-hosts logging stream identifier.
redef enum Log::ID += { HOSTS_LOG }; redef enum Log::ID += { HOSTS_LOG };
## The record type which contains the column fields of the known-hosts log.
type HostsInfo: record { type HostsInfo: record {
## The timestamp at which the host was detected. ## The timestamp at which the host was detected.
ts: time &log; ts: time &log;
@ -19,7 +21,7 @@ export {
}; };
## The hosts whose existence should be logged and tracked. ## The hosts whose existence should be logged and tracked.
## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS ## See :bro:type:`Host` for possible choices.
const host_tracking = LOCAL_HOSTS &redef; const host_tracking = LOCAL_HOSTS &redef;
## The set of all known addresses to store for preventing duplicate ## The set of all known addresses to store for preventing duplicate
@ -28,7 +30,9 @@ export {
## Maintain the list of known hosts for 24 hours so that the existence ## Maintain the list of known hosts for 24 hours so that the existence
## of each individual address is logged each day. ## of each individual address is logged each day.
global known_hosts: set[addr] &create_expire=1day &synchronized &redef; global known_hosts: set[addr] &create_expire=1day &synchronized &redef;
## An event that can be handled to access the :bro:type:`Known::HostsInfo`
## record as it is sent on to the logging framework.
global log_known_hosts: event(rec: HostsInfo); global log_known_hosts: event(rec: HostsInfo);
} }

View file

@ -8,29 +8,41 @@
module Known; module Known;
export { export {
## The known-services logging stream identifier.
redef enum Log::ID += { SERVICES_LOG }; redef enum Log::ID += { SERVICES_LOG };
## The record type which contains the column fields of the known-services
## log.
type ServicesInfo: record { type ServicesInfo: record {
## The time at which the service was detected.
ts: time &log; ts: time &log;
## The host address on which the service is running.
host: addr &log; host: addr &log;
## The port number on which the service is running.
port_num: port &log; port_num: port &log;
## The transport-layer protocol which the service uses.
port_proto: transport_proto &log; port_proto: transport_proto &log;
## A set of protocols that match the service's connection payloads.
service: set[string] &log; service: set[string] &log;
done: bool &default=F;
}; };
## The hosts whose services should be tracked and logged. ## The hosts whose services should be tracked and logged.
## See :bro:type:`Host` for possible choices.
const service_tracking = LOCAL_HOSTS &redef; const service_tracking = LOCAL_HOSTS &redef;
## Tracks the set of daily-detected services for preventing the logging
## of duplicates, but can also be inspected by other scripts for
## different purposes.
global known_services: set[addr, port] &create_expire=1day &synchronized; global known_services: set[addr, port] &create_expire=1day &synchronized;
## Event that can be handled to access the :bro:type:`Known::ServicesInfo`
## record as it is sent on to the logging framework.
global log_known_services: event(rec: ServicesInfo); global log_known_services: event(rec: ServicesInfo);
} }
redef record connection += { redef record connection += {
## This field is to indicate whether or not the processing for detecting # This field is to indicate whether or not the processing for detecting
## and logging the service for this connection is complete. # and logging the service for this connection is complete.
known_services_done: bool &default=F; known_services_done: bool &default=F;
}; };

View file

@ -170,13 +170,26 @@ void BroDoc::WriteDocFile() const
{ {
WriteToDoc(".. Automatically generated. Do not edit.\n\n"); WriteToDoc(".. Automatically generated. Do not edit.\n\n");
WriteToDoc(":tocdepth: 3\n\n");
WriteSectionHeading(doc_title.c_str(), '='); WriteSectionHeading(doc_title.c_str(), '=');
WriteToDoc("\n:download:`Original Source File <%s>`\n\n", WriteStringList(".. bro:namespace:: %s\n", modules);
downloadable_filename.c_str());
WriteSectionHeading("Overview", '-'); WriteToDoc("\n");
WriteStringList("%s\n", "%s\n\n", summary);
// WriteSectionHeading("Overview", '-');
WriteStringList("%s\n", summary);
WriteToDoc("\n");
if ( ! modules.empty() )
{
WriteToDoc(":Namespace%s: ", (modules.size() > 1 ? "s" : ""));
// WriteStringList(":bro:namespace:`%s`", modules);
WriteStringList("``%s``, ", "``%s``", modules);
WriteToDoc("\n");
}
if ( ! imports.empty() ) if ( ! imports.empty() )
{ {
@ -196,39 +209,38 @@ void BroDoc::WriteDocFile() const
WriteToDoc("\n"); WriteToDoc("\n");
} }
WriteToDoc(":Source File: :download:`%s`\n",
downloadable_filename.c_str());
WriteToDoc("\n"); WriteToDoc("\n");
WriteInterface("Summary", '~', '#', true, true); WriteInterface("Summary", '~', '#', true, true);
if ( ! modules.empty() )
{
WriteSectionHeading("Namespaces", '~');
WriteStringList(".. bro:namespace:: %s\n", modules);
WriteToDoc("\n");
}
if ( ! notices.empty() ) if ( ! notices.empty() )
WriteBroDocObjList(notices, "Notices", '~'); WriteBroDocObjList(notices, "Notices", '#');
WriteInterface("Public Interface", '-', '~', true, false); if ( port_analysis.size() || packet_filter.size() )
WriteSectionHeading("Configuration Changes", '#');
if ( ! port_analysis.empty() ) if ( ! port_analysis.empty() )
{ {
WriteSectionHeading("Port Analysis", '-'); WriteSectionHeading("Port Analysis", '^');
WriteToDoc("Loading this script makes the following changes to " WriteToDoc("Loading this script makes the following changes to "
":bro:see:`dpd_config`.\n\n"); ":bro:see:`dpd_config`.\n\n");
WriteStringList("%s", port_analysis); WriteStringList("%s, ", "%s", port_analysis);
} }
if ( ! packet_filter.empty() ) if ( ! packet_filter.empty() )
{ {
WriteSectionHeading("Packet Filter", '-'); WriteSectionHeading("Packet Filter", '^');
WriteToDoc("Loading this script makes the following changes to " WriteToDoc("Loading this script makes the following changes to "
":bro:see:`capture_filters`.\n\n"); ":bro:see:`capture_filters`.\n\n");
WriteToDoc("Filters added::\n\n"); WriteToDoc("Filters added::\n\n");
WriteToDoc("%s\n", packet_filter.c_str()); WriteToDoc("%s\n", packet_filter.c_str());
} }
WriteInterface("Detailed Interface", '~', '#', true, false);
#if 0 // Disabled for now. #if 0 // Disabled for now.
BroDocObjList::const_iterator it; BroDocObjList::const_iterator it;
bool hasPrivateIdentifiers = false; bool hasPrivateIdentifiers = false;
@ -243,7 +255,7 @@ void BroDoc::WriteDocFile() const
} }
if ( hasPrivateIdentifiers ) if ( hasPrivateIdentifiers )
WriteInterface("Private Interface", '-', '~', false, false); WriteInterface("Private Interface", '~', '#', false, false);
#endif #endif
} }

View file

@ -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);
}

View file

@ -121,7 +121,7 @@ protected:
// This will be increased whenever there is an incompatible change // This will be increased whenever there is an incompatible change
// in the data format. // in the data format.
static const uint32 DATA_FORMAT_VERSION = 20; static const uint32 DATA_FORMAT_VERSION = 21;
ChunkedIO* io; ChunkedIO* io;

View file

@ -876,74 +876,12 @@ void CommentedTypeDecl::DescribeReST(ODesc* d) const
} }
} }
RecordField::RecordField(int arg_base, int arg_offset, int arg_total_offset)
{
base = arg_base;
offset = arg_offset;
total_offset = arg_total_offset;
}
RecordType::RecordType(type_decl_list* arg_types) : BroType(TYPE_RECORD) RecordType::RecordType(type_decl_list* arg_types) : BroType(TYPE_RECORD)
{ {
types = arg_types; types = arg_types;
base = 0;
fields = 0;
num_fields = types ? types->length() : 0; num_fields = types ? types->length() : 0;
} }
RecordType::RecordType(TypeList* arg_base, type_decl_list* refinements)
: BroType(TYPE_RECORD)
{
if ( refinements )
arg_base->Append(new RecordType(refinements));
Init(arg_base);
}
void RecordType::Init(TypeList* arg_base)
{
assert(false); // Is this ever used?
base = arg_base;
if ( ! base )
Internal("empty RecordType");
fields = new PDict(RecordField)(ORDERED);
types = 0;
type_list* t = base->Types();
loop_over_list(*t, i)
{
BroType* ti = (*t)[i];
if ( ti->Tag() != TYPE_RECORD )
(*t)[i]->Error("non-record in base type list");
RecordType* rti = ti->AsRecordType();
int n = rti->NumFields();
for ( int j = 0; j < n; ++j )
{
const TypeDecl* tdij = rti->FieldDecl(j);
if ( fields->Lookup(tdij->id) )
{
reporter->Error("duplicate field %s", tdij->id);
continue;
}
RecordField* rf = new RecordField(i, j, fields->Length());
if ( fields->Insert(tdij->id, rf) )
Internal("duplicate field when constructing record");
}
}
num_fields = fields->Length();
}
RecordType::~RecordType() RecordType::~RecordType()
{ {
if ( types ) if ( types )
@ -953,9 +891,6 @@ RecordType::~RecordType()
delete types; delete types;
} }
delete fields;
Unref(base);
} }
int RecordType::HasField(const char* field) const int RecordType::HasField(const char* field) const
@ -971,17 +906,7 @@ BroType* RecordType::FieldType(const char* field) const
BroType* RecordType::FieldType(int field) const BroType* RecordType::FieldType(int field) const
{ {
if ( types ) return (*types)[field]->type;
return (*types)[field]->type;
else
{
RecordField* rf = fields->NthEntry(field);
if ( ! rf )
Internal("missing field in RecordType::FieldType");
BroType* bt = (*base->Types())[rf->base];
RecordType* rbt = bt->AsRecordType();
return rbt->FieldType(rf->offset);
}
} }
Val* RecordType::FieldDefault(int field) const Val* RecordType::FieldDefault(int field) const
@ -998,26 +923,14 @@ Val* RecordType::FieldDefault(int field) const
int RecordType::FieldOffset(const char* field) const int RecordType::FieldOffset(const char* field) const
{ {
if ( types ) loop_over_list(*types, i)
{ {
loop_over_list(*types, i) TypeDecl* td = (*types)[i];
{ if ( streq(td->id, field) )
TypeDecl* td = (*types)[i]; return i;
if ( streq(td->id, field) )
return i;
}
return -1;
} }
else return -1;
{
RecordField* rf = fields->Lookup(field);
if ( ! rf )
return -1;
else
return rf->total_offset;
}
} }
const char* RecordType::FieldName(int field) const const char* RecordType::FieldName(int field) const
@ -1027,33 +940,12 @@ const char* RecordType::FieldName(int field) const
const TypeDecl* RecordType::FieldDecl(int field) const const TypeDecl* RecordType::FieldDecl(int field) const
{ {
if ( types ) return (*types)[field];
return (*types)[field];
else
{
RecordField* rf = fields->NthEntry(field);
if ( ! rf )
reporter->InternalError("missing field in RecordType::FieldDecl");
BroType* bt = (*base->Types())[rf->base];
RecordType* rbt = bt->AsRecordType();
return rbt->FieldDecl(rf->offset);
}
} }
TypeDecl* RecordType::FieldDecl(int field) TypeDecl* RecordType::FieldDecl(int field)
{ {
if ( types ) return (*types)[field];
return (*types)[field];
else
{
RecordField* rf = fields->NthEntry(field);
if ( ! rf )
Internal("missing field in RecordType::FieldDecl");
BroType* bt = (*base->Types())[rf->base];
RecordType* rbt = bt->AsRecordType();
return rbt->FieldDecl(rf->offset);
}
} }
void RecordType::Describe(ODesc* d) const void RecordType::Describe(ODesc* d) const
@ -1151,11 +1043,6 @@ void RecordType::DescribeFields(ODesc* d) const
d->SP(); d->SP();
} }
} }
else
{
d->AddCount(1);
base->Describe(d);
}
} }
} }
@ -1208,9 +1095,6 @@ bool RecordType::DoSerialize(SerialInfo* info) const
else if ( ! SERIALIZE(false) ) else if ( ! SERIALIZE(false) )
return false; return false;
SERIALIZE_OPTIONAL(base);
// We don't serialize the fields as we can reconstruct them.
return true; return true;
} }
@ -1245,13 +1129,6 @@ bool RecordType::DoUnserialize(UnserialInfo* info)
else else
types = 0; types = 0;
BroType* type;
UNSERIALIZE_OPTIONAL(type, BroType::Unserialize(info, TYPE_LIST));
base = (TypeList*) type;
if ( base )
Init(base);
return true; return true;
} }
@ -1594,21 +1471,6 @@ bool VectorType::DoUnserialize(UnserialInfo* info)
return yield_type != 0; return yield_type != 0;
} }
BroType* refine_type(TypeList* base, type_decl_list* refinements)
{
type_list* t = base->Types();
if ( t->length() == 1 && ! refinements )
{ // Just a direct reference to a single type.
BroType* rt = (*t)[0]->Ref();
Unref(base);
return rt;
}
return new RecordType(base, refinements);
}
BroType* base_type(TypeTag tag) BroType* base_type(TypeTag tag)
{ {
static BroType* base_types[NUM_TYPES]; static BroType* base_types[NUM_TYPES];

View file

@ -426,20 +426,9 @@ public:
std::list<std::string>* comments; std::list<std::string>* comments;
}; };
class RecordField {
public:
RecordField(int arg_base, int arg_offset, int arg_total_offset);
int base; // which base element it belongs to
int offset; // where it is in that base
int total_offset; // where it is in the aggregate record
};
declare(PDict,RecordField);
class RecordType : public BroType { class RecordType : public BroType {
public: public:
RecordType(type_decl_list* types); RecordType(type_decl_list* types);
RecordType(TypeList* base, type_decl_list* refinements);
~RecordType(); ~RecordType();
@ -473,15 +462,11 @@ public:
void DescribeFieldsReST(ODesc* d, bool func_args) const; void DescribeFieldsReST(ODesc* d, bool func_args) const;
protected: protected:
RecordType() { fields = 0; base = 0; types = 0; } RecordType() { types = 0; }
void Init(TypeList* arg_base);
DECLARE_SERIAL(RecordType) DECLARE_SERIAL(RecordType)
int num_fields; int num_fields;
PDict(RecordField)* fields;
TypeList* base;
type_decl_list* types; type_decl_list* types;
}; };
@ -587,10 +572,6 @@ protected:
BroType* yield_type; BroType* yield_type;
}; };
// Returns the given type refinement, or error_type() if it's illegal.
extern BroType* refine_type(TypeList* base, type_decl_list* refinements);
// Returns the BRO basic (non-parameterized) type with the given type. // Returns the BRO basic (non-parameterized) type with the given type.
extern BroType* base_type(TypeTag tag); extern BroType* base_type(TypeTag tag);

View file

@ -1,4 +1,8 @@
# Definitions of Bro built-in functions. ##! A collection of built-in functions that implement a variety of things
##! such as general programming algorithms, string processing, math functions,
##! introspection, type conversion, file/directory manipulation, packet
##! filtering, inter-process communication and controlling protocol analyzer
##! behavior.
%%{ // C segment %%{ // C segment
#include <math.h> #include <math.h>

View file

@ -1,4 +1,6 @@
# Documentation and default values for these are located in policy/bro.init. ##! Declaration of various scripting-layer constants that the Bro core uses
##! internally. Documentation and default values for the scripting-layer
##! variables themselves are found in :doc:`/scripts/base/init-bare`.
const ignore_keep_alive_rexmit: bool; const ignore_keep_alive_rexmit: bool;
const skip_http_data: bool; const skip_http_data: bool;

View file

@ -1,3 +1,8 @@
##! The events that the C/C++ core of Bro can generate. This is mostly
##! consisting of high-level network events that protocol analyzers detect,
##! but there are also several general-utility events generated by internal
##! Bro frameworks.
# #
# Documentation conventions: # Documentation conventions:
# #
@ -4574,7 +4579,8 @@ event ssh_server_version%(c: connection, version: string%);
## maps them to descriptive names. ## maps them to descriptive names.
## ##
## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello ## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello
## x509_certificate x509_error x509_extension ssl_max_cipherspec_size ## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
## ssl_max_cipherspec_size
event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%); event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%);
## Generated for an SSL/TLS servers's initial *hello* message. SSL/TLS sessions ## Generated for an SSL/TLS servers's initial *hello* message. SSL/TLS sessions
@ -4604,7 +4610,8 @@ event ssl_client_hello%(c: connection, version: count, possible_ts: time, sessio
## standardized as part of the SSL/TLS protocol. ## standardized as part of the SSL/TLS protocol.
## ##
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension ## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension
## x509_certificate x509_error x509_extension ssl_max_cipherspec_size ## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
## ssl_max_cipherspec_size
event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%); event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%);
## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS sessions ## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS sessions
@ -4623,7 +4630,7 @@ event ssl_server_hello%(c: connection, version: count, possible_ts: time, sessio
## val: The raw extension value that was sent in the message. ## val: The raw extension value that was sent in the message.
## ##
## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello ## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello
## x509_certificate x509_error x509_extension ## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%); event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);
## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with ## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with
@ -4638,7 +4645,7 @@ event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);
## c: The connection. ## c: The connection.
## ##
## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello ## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello
## x509_certificate x509_error x509_extension ## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
event ssl_established%(c: connection%); event ssl_established%(c: connection%);
## Generated for SSL/TLS alert records. SSL/TLS sessions start with an unencrypted ## Generated for SSL/TLS alert records. SSL/TLS sessions start with an unencrypted
@ -4661,9 +4668,30 @@ event ssl_established%(c: connection%);
## defined as part of the SSL/TLS protocol. ## defined as part of the SSL/TLS protocol.
## ##
## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello ## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello
## x509_certificate x509_error x509_extension ## ssl_session_ticket_handshake x509_certificate x509_error x509_extension
event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%); event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%);
## Generated for SSL/TLS handshake messages that are a part of the stateless-server
## session resumption mechanism. SSL/TLS sessions start with an unencrypted
## handshake, and Bro extracts as much information out of that as it can. This
## event is raised when an SSL/TLS server passes session ticket to the client that
## can later be used for resuming the session. The mechanism is described in
## :rfc:`4507`
##
## See `Wikipedia <http://en.wikipedia.org/wiki/Transport_Layer_Security>`__ for
## more information about the SSL/TLS protocol.
##
## c: The connection.
##
## ticket_lifetime_hint: A hint from the server about how long the ticket
## should be stored by the client.
##
## ticket: The raw ticket data.
##
## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello
## x509_certificate x509_error x509_extension ssl_alert
event ssl_session_ticket_handshake%(c: connection, ticket_lifetime_hint: count, ticket: string%);
## Generated for x509 certificates seen in SSL/TLS connections. During the initial ## Generated for x509 certificates seen in SSL/TLS connections. During the initial
## SSL/TLS handshake, certificates are exchanged in the clear. Bro raises this ## SSL/TLS handshake, certificates are exchanged in the clear. Bro raises this
## event for each certificate seen (including both a site's primary cert, and ## event for each certificate seen (including both a site's primary cert, and

View file

@ -97,7 +97,7 @@ extern char version[];
char* command_line_policy = 0; char* command_line_policy = 0;
vector<string> params; vector<string> params;
char* proc_status_file = 0; char* proc_status_file = 0;
int snaplen = 65535; // really want "capture entire packet" int snaplen = 0; // this gets set from the scripting-layer's value
int FLAGS_use_binpac = false; int FLAGS_use_binpac = false;
@ -145,7 +145,6 @@ void usage()
fprintf(stderr, " -g|--dump-config | dump current config into .state dir\n"); fprintf(stderr, " -g|--dump-config | dump current config into .state dir\n");
fprintf(stderr, " -h|--help|-? | command line help\n"); fprintf(stderr, " -h|--help|-? | command line help\n");
fprintf(stderr, " -i|--iface <interface> | read from given interface\n"); fprintf(stderr, " -i|--iface <interface> | read from given interface\n");
fprintf(stderr, " -l|--snaplen <snaplen> | number of bytes per packet to capture from interfaces (default 65535)\n");
fprintf(stderr, " -p|--prefix <prefix> | add given prefix to policy file resolution\n"); fprintf(stderr, " -p|--prefix <prefix> | add given prefix to policy file resolution\n");
fprintf(stderr, " -r|--readfile <readfile> | read from given tcpdump file\n"); fprintf(stderr, " -r|--readfile <readfile> | read from given tcpdump file\n");
fprintf(stderr, " -y|--flowfile <file>[=<ident>] | read from given flow file\n"); fprintf(stderr, " -y|--flowfile <file>[=<ident>] | read from given flow file\n");
@ -372,7 +371,6 @@ int main(int argc, char** argv)
{"filter", required_argument, 0, 'f'}, {"filter", required_argument, 0, 'f'},
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"iface", required_argument, 0, 'i'}, {"iface", required_argument, 0, 'i'},
{"snaplen", required_argument, 0, 'l'},
{"doc-scripts", no_argument, 0, 'Z'}, {"doc-scripts", no_argument, 0, 'Z'},
{"prefix", required_argument, 0, 'p'}, {"prefix", required_argument, 0, 'p'},
{"readfile", required_argument, 0, 'r'}, {"readfile", required_argument, 0, 'r'},
@ -481,10 +479,6 @@ int main(int argc, char** argv)
interfaces.append(optarg); interfaces.append(optarg);
break; break;
case 'l':
snaplen = atoi(optarg);
break;
case 'p': case 'p':
prefixes.append(optarg); prefixes.append(optarg);
break; break;
@ -833,6 +827,8 @@ int main(int argc, char** argv)
} }
} }
snaplen = internal_val("snaplen")->AsCount();
// Initialize the secondary path, if it's needed. // Initialize the secondary path, if it's needed.
secondary_path = new SecondaryPath(); secondary_path = new SecondaryPath();

View file

@ -2,7 +2,7 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
%} %}
%expect 88 %expect 87
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
@ -53,7 +53,7 @@
%type <expr> expr init anonymous_function %type <expr> expr init anonymous_function
%type <event_expr> event %type <event_expr> event
%type <stmt> stmt stmt_list func_body for_head %type <stmt> stmt stmt_list func_body for_head
%type <type> type opt_type refined_type enum_body %type <type> type opt_type enum_body
%type <func_type> func_hdr func_params %type <func_type> func_hdr func_params
%type <type_l> type_list %type <type_l> type_list
%type <type_decl> type_decl formal_args_decl %type <type_decl> type_decl formal_args_decl
@ -1104,7 +1104,7 @@ decl:
} }
} }
| TOK_TYPE global_id ':' refined_type opt_attr ';' | TOK_TYPE global_id ':' type opt_attr ';'
{ {
add_type($2, $4, $5, 0); add_type($2, $4, $5, 0);
@ -1134,7 +1134,7 @@ decl:
} }
} }
| TOK_EVENT event_id ':' refined_type opt_attr ';' | TOK_EVENT event_id ':' type_list opt_attr ';'
{ {
add_type($2, $4, $5, 1); add_type($2, $4, $5, 1);
@ -1220,13 +1220,6 @@ func_params:
{ $$ = new FuncType($2, base_type(TYPE_VOID), 0); } { $$ = new FuncType($2, base_type(TYPE_VOID), 0); }
; ;
refined_type:
type_list '{' type_decl_list '}'
{ $$ = refine_type($1, $3); }
| type_list
{ $$ = refine_type($1, 0); }
;
opt_type: opt_type:
':' type ':' type
{ $$ = $2; } { $$ = $2; }

View file

@ -144,7 +144,7 @@ refine connection SSL_Conn += {
if ( ssl_client_hello ) if ( ssl_client_hello )
{ {
vector<int>* cipher_suites = new vector<int>(); vector<int>* cipher_suites = new vector<int>();
if ( cipher_suites16 ) if ( cipher_suites16 )
std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*cipher_suites)); std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*cipher_suites));
else else
std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*cipher_suites), to_int()); std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*cipher_suites), to_int());
@ -205,6 +205,18 @@ refine connection SSL_Conn += {
return true; return true;
%} %}
function proc_session_ticket_handshake(rec: SessionTicketHandshake, is_orig: bool): bool
%{
if ( ssl_session_ticket_handshake )
{
BifEvent::generate_ssl_session_ticket_handshake(bro_analyzer(),
bro_analyzer()->Conn(),
${rec.ticket_lifetime_hint},
new StringVal(${rec.data}.length(), (const char*) ${rec.data}.data()));
}
return true;
%}
function proc_ssl_extension(rec: SSLRecord, type: int, data: bytestring) : bool function proc_ssl_extension(rec: SSLRecord, type: int, data: bytestring) : bool
%{ %{
@ -269,13 +281,14 @@ refine connection SSL_Conn += {
der_cert); der_cert);
// Are there any X509 extensions? // Are there any X509 extensions?
//printf("Number of x509 extensions: %d\n", X509_get_ext_count(pTemp));
if ( x509_extension && X509_get_ext_count(pTemp) > 0 ) if ( x509_extension && X509_get_ext_count(pTemp) > 0 )
{ {
int num_ext = X509_get_ext_count(pTemp); int num_ext = X509_get_ext_count(pTemp);
for ( int k = 0; k < num_ext; ++k ) for ( int k = 0; k < num_ext; ++k )
{ {
unsigned char *pBuffer = 0; unsigned char *pBuffer = 0;
int length = 0; uint length = 0;
X509_EXTENSION* ex = X509_get_ext(pTemp, k); X509_EXTENSION* ex = X509_get_ext(pTemp, k);
if (ex) if (ex)
@ -283,7 +296,7 @@ refine connection SSL_Conn += {
ASN1_STRING *pString = X509_EXTENSION_get_data(ex); ASN1_STRING *pString = X509_EXTENSION_get_data(ex);
length = ASN1_STRING_to_UTF8(&pBuffer, pString); length = ASN1_STRING_to_UTF8(&pBuffer, pString);
//i2t_ASN1_OBJECT(&pBuffer, length, obj) //i2t_ASN1_OBJECT(&pBuffer, length, obj)
// printf("extension length: %u\n", length);
// -1 indicates an error. // -1 indicates an error.
if ( length < 0 ) if ( length < 0 )
continue; continue;
@ -442,6 +455,10 @@ refine typeattr Handshake += &let {
proc : bool = $context.connection.proc_handshake(this, rec.is_orig); proc : bool = $context.connection.proc_handshake(this, rec.is_orig);
}; };
refine typeattr SessionTicketHandshake += &let {
proc : bool = $context.connection.proc_session_ticket_handshake(this, rec.is_orig);
}
refine typeattr UnknownRecord += &let { refine typeattr UnknownRecord += &let {
proc : bool = $context.connection.proc_unknown_record(rec); proc : bool = $context.connection.proc_unknown_record(rec);
}; };

View file

@ -61,17 +61,10 @@ type RecordText(rec: SSLRecord) = case $context.connection.state() of {
-> plaintext : PlaintextRecord(rec); -> plaintext : PlaintextRecord(rec);
}; };
type PossibleEncryptedHandshake(rec: SSLRecord) = case $context.connection.state() of {
# Deal with encrypted handshakes before the server cipher spec change.
STATE_CLIENT_FINISHED, STATE_CLIENT_ENCRYPTED
-> ct : CiphertextRecord(rec);
default -> hs : Handshake(rec);
};
type PlaintextRecord(rec: SSLRecord) = case rec.content_type of { type PlaintextRecord(rec: SSLRecord) = case rec.content_type of {
CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec); CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec);
ALERT -> alert : Alert(rec); ALERT -> alert : Alert(rec);
HANDSHAKE -> handshake : PossibleEncryptedHandshake(rec); HANDSHAKE -> handshake : Handshake(rec);
APPLICATION_DATA -> app_data : ApplicationData(rec); APPLICATION_DATA -> app_data : ApplicationData(rec);
V2_ERROR -> v2_error : V2Error(rec); V2_ERROR -> v2_error : V2Error(rec);
V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec); V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec);
@ -260,18 +253,19 @@ enum AnalyzerState {
###################################################################### ######################################################################
enum HandshakeType { enum HandshakeType {
HELLO_REQUEST = 0, HELLO_REQUEST = 0,
CLIENT_HELLO = 1, CLIENT_HELLO = 1,
SERVER_HELLO = 2, SERVER_HELLO = 2,
CERTIFICATE = 11, SESSION_TICKET = 4, # RFC 5077
SERVER_KEY_EXCHANGE = 12, CERTIFICATE = 11,
CERTIFICATE_REQUEST = 13, SERVER_KEY_EXCHANGE = 12,
SERVER_HELLO_DONE = 14, CERTIFICATE_REQUEST = 13,
CERTIFICATE_VERIFY = 15, SERVER_HELLO_DONE = 14,
CLIENT_KEY_EXCHANGE = 16, CERTIFICATE_VERIFY = 15,
FINISHED = 20, CLIENT_KEY_EXCHANGE = 16,
CERTIFICATE_URL = 21, # RFC 3546 FINISHED = 20,
CERTIFICATE_STATUS = 22, # RFC 3546 CERTIFICATE_URL = 21, # RFC 3546
CERTIFICATE_STATUS = 22, # RFC 3546
}; };
%code{ %code{
@ -281,6 +275,7 @@ enum HandshakeType {
case HELLO_REQUEST: return string("HELLO_REQUEST"); case HELLO_REQUEST: return string("HELLO_REQUEST");
case CLIENT_HELLO: return string("CLIENT_HELLO"); case CLIENT_HELLO: return string("CLIENT_HELLO");
case SERVER_HELLO: return string("SERVER_HELLO"); case SERVER_HELLO: return string("SERVER_HELLO");
case SESSION_TICKET: return string("SESSION_TICKET");
case CERTIFICATE: return string("CERTIFICATE"); case CERTIFICATE: return string("CERTIFICATE");
case SERVER_KEY_EXCHANGE: return string("SERVER_KEY_EXCHANGE"); case SERVER_KEY_EXCHANGE: return string("SERVER_KEY_EXCHANGE");
case CERTIFICATE_REQUEST: return string("CERTIFICATE_REQUEST"); case CERTIFICATE_REQUEST: return string("CERTIFICATE_REQUEST");
@ -452,8 +447,7 @@ type V2ServerHello(rec: SSLRecord) = record {
cert_data : bytestring &length = cert_len; cert_data : bytestring &length = cert_len;
ciphers : uint24[ciph_len/3]; ciphers : uint24[ciph_len/3];
conn_id_data : bytestring &length = conn_id_len; conn_id_data : bytestring &length = conn_id_len;
} #&length = 8 + cert_len + ciph_len + conn_id_len, } &let {
&let {
state_changed : bool = state_changed : bool =
(session_id_hit > 0 ? (session_id_hit > 0 ?
$context.connection.transition(STATE_CLIENT_HELLO_RCVD, $context.connection.transition(STATE_CLIENT_HELLO_RCVD,
@ -603,7 +597,7 @@ type CertificateVerify(rec: SSLRecord) = record {
###################################################################### ######################################################################
# The finished messages are always sent after encryption is in effect, # The finished messages are always sent after encryption is in effect,
# so we will not be able to read those message. # so we will not be able to read those messages.
type Finished(rec: SSLRecord) = record { type Finished(rec: SSLRecord) = record {
cont : bytestring &restofdata &transient; cont : bytestring &restofdata &transient;
} &let { } &let {
@ -615,13 +609,17 @@ type Finished(rec: SSLRecord) = record {
$context.connection.lost_track(); $context.connection.lost_track();
}; };
type SessionTicketHandshake(rec: SSLRecord) = record {
ticket_lifetime_hint: uint32;
data: bytestring &restofdata;
};
###################################################################### ######################################################################
# V3 Handshake Protocol (7.) # V3 Handshake Protocol (7.)
###################################################################### ######################################################################
type UnknownHandshake(hs: Handshake, is_orig: bool) = record { type UnknownHandshake(hs: Handshake, is_orig: bool) = record {
cont : bytestring &restofdata &transient; data : bytestring &restofdata &transient;
} &let { } &let {
state_changed : bool = $context.connection.lost_track(); state_changed : bool = $context.connection.lost_track();
}; };
@ -631,19 +629,20 @@ type Handshake(rec: SSLRecord) = record {
length : uint24; length : uint24;
body : case msg_type of { body : case msg_type of {
HELLO_REQUEST -> hello_request : HelloRequest(rec); HELLO_REQUEST -> hello_request : HelloRequest(rec);
CLIENT_HELLO -> client_hello : ClientHello(rec); CLIENT_HELLO -> client_hello : ClientHello(rec);
SERVER_HELLO -> server_hello : ServerHello(rec); SERVER_HELLO -> server_hello : ServerHello(rec);
CERTIFICATE -> certificate : Certificate(rec); SESSION_TICKET -> session_ticket : SessionTicketHandshake(rec);
SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec); CERTIFICATE -> certificate : Certificate(rec);
CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec); SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec);
SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec); CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec);
CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec); SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec);
CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec); CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec);
FINISHED -> finished : Finished(rec); CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec);
CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient; FINISHED -> finished : Finished(rec);
CERTIFICATE_STATUS -> certificate_status : bytestring &restofdata &transient; CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient;
default -> unknown_handshake : UnknownHandshake(this, rec.is_orig); CERTIFICATE_STATUS -> certificate_status : bytestring &restofdata &transient;
default -> unknown_handshake : UnknownHandshake(this, rec.is_orig);
} &length = to_int()(length); } &length = to_int()(length);
}; };

View file

@ -1,4 +1,5 @@
# Definitions of Bro built-in functions related to strings. ##! Definitions of built-in functions related to string processing and
##! manipulation.
%%{ // C segment %%{ // C segment

View file

@ -1,3 +1,4 @@
##! Declaration of various types that the Bro core uses internally.
enum dce_rpc_ptype %{ enum dce_rpc_ptype %{
DCE_RPC_REQUEST, DCE_RPC_REQUEST,
@ -134,8 +135,8 @@ enum createmode_t %{
EXCLUSIVE = 2, EXCLUSIVE = 2,
%} %}
# Decleare record types that we want to access from the even engine. These are # Declare record types that we want to access from the event engine. These are
# defined in bro.init. # defined in init-bare.bro.
type info_t: record; type info_t: record;
type fattr_t: record; type fattr_t: record;
type diropargs_t: record; type diropargs_t: record;

View file

@ -3,6 +3,6 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path notice #path notice
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet #types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
1324314350.184962 - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 100/100 - 1.2.3.4 - - 100 manager-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - - 1325633225.777902 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 100/100 - 1.2.3.4 - - 100 manager-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - -

View file

@ -3,7 +3,7 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path notice #path notice
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet #types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
1324314359.357148 - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 3/2 - 1.2.3.4 - - 3 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - - 1325633274.875473 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 3/2 - 1.2.3.4 - - 3 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - -
1324314359.357148 - - - - - Test_Notice Threshold crossed by metric_index(host=6.5.4.3) 2/2 - 6.5.4.3 - - 2 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 6.5.4.3 - - 1325633274.875473 - - - - - - Test_Notice Threshold crossed by metric_index(host=6.5.4.3) 2/2 - 6.5.4.3 - - 2 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 6.5.4.3 - -

View file

@ -3,6 +3,6 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path notice #path notice
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet #types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
1324314363.721823 - - - - - Test_Notice test notice! - - - - - worker-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - - 1325633122.490990 - - - - - - Test_Notice test notice! - - - - - worker-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -

View file

@ -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>

View file

@ -3,6 +3,6 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path notice #path notice
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network
#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet #types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet
1324314378.560010 - - - - - Test_Notice test notice! - - - - - worker-2 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - - 1325633150.723248 - - - - - - Test_Notice test notice! - - - - - worker-2 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - -

View file

@ -3,6 +3,6 @@
#empty_field (empty) #empty_field (empty)
#unset_field - #unset_field -
#path notice #path notice
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude
#types time string addr port addr port enum string string addr addr port count string table[enum] table[count] interval bool string string string double double #types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double
1324314387.663586 - - - - - Test_Notice test - - - - - bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 1325633207.922993 - - - - - - Test_Notice test - - - - - bro Notice::ACTION_LOG 6 3600.000000 F - - - - -

View file

@ -3,7 +3,7 @@
# @TEST-EXEC: btest-bg-run proxy-2 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-2 bro %INPUT # @TEST-EXEC: btest-bg-run proxy-2 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-2 bro %INPUT
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT # @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT # @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
# @TEST-EXEC: btest-bg-wait -k 2 # @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff manager-1/.stdout # @TEST-EXEC: btest-diff manager-1/.stdout
# @TEST-EXEC: btest-diff proxy-1/.stdout # @TEST-EXEC: btest-diff proxy-1/.stdout
# @TEST-EXEC: btest-diff proxy-2/.stdout # @TEST-EXEC: btest-diff proxy-2/.stdout
@ -23,4 +23,4 @@ redef Cluster::nodes = {
event remote_connection_handshake_done(p: event_peer) event remote_connection_handshake_done(p: event_peer)
{ {
print "Connected to a peer"; print "Connected to a peer";
} }

View file

@ -1,7 +1,7 @@
# #
# @TEST-EXEC: btest-bg-run receiver bro -b ../receiver.bro # @TEST-EXEC: btest-bg-run receiver bro -b ../receiver.bro
# @TEST-EXEC: btest-bg-run sender bro -b ../sender.bro # @TEST-EXEC: btest-bg-run sender bro -b ../sender.bro
# @TEST-EXEC: btest-bg-wait -k 2 # @TEST-EXEC: btest-bg-wait -k 10
# #
# Don't diff the receiver log just because port is always going to change # Don't diff the receiver log just because port is always going to change
# @TEST-EXEC: egrep -v 'pid|socket buffer size' sender/communication.log >send.log # @TEST-EXEC: egrep -v 'pid|socket buffer size' sender/communication.log >send.log

View file

@ -1,7 +1,7 @@
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65531/tcp # @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65531/tcp
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT test-redef frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=configuration_update # @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT test-redef frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=configuration_update
# @TEST-EXEC: btest-bg-run controller2 BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=shutdown # @TEST-EXEC: btest-bg-run controller2 BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=shutdown
# @TEST-EXEC: btest-bg-wait 1 # @TEST-EXEC: btest-bg-wait 10
# @TEST-EXEC: btest-diff controllee/.stdout # @TEST-EXEC: btest-diff controllee/.stdout
redef Communication::nodes = { redef Communication::nodes = {
@ -23,4 +23,4 @@ event bro_init()
event bro_done() event bro_done()
{ {
print test_var; print test_var;
} }

View file

@ -1,6 +1,6 @@
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT only-for-controllee frameworks/control/controllee Communication::listen_port=65532/tcp # @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT only-for-controllee frameworks/control/controllee Communication::listen_port=65532/tcp
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65532/tcp Control::cmd=id_value Control::arg=test_var # @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65532/tcp Control::cmd=id_value Control::arg=test_var
# @TEST-EXEC: btest-bg-wait -k 1 # @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff controller/.stdout # @TEST-EXEC: btest-diff controller/.stdout
redef Communication::nodes = { redef Communication::nodes = {

View file

@ -1,6 +1,6 @@
# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65530/tcp # @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65530/tcp
# @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65530/tcp Control::cmd=shutdown # @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65530/tcp Control::cmd=shutdown
# @TEST-EXEC: btest-bg-wait 1 # @TEST-EXEC: btest-bg-wait 10
redef Communication::nodes = { redef Communication::nodes = {
# We're waiting for connections from this host for control. # We're waiting for connections from this host for control.

View file

@ -1,7 +1,7 @@
# #
# @TEST-EXEC: btest-bg-run sender bro --pseudo-realtime %INPUT ../sender.bro # @TEST-EXEC: btest-bg-run sender bro --pseudo-realtime %INPUT ../sender.bro
# @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro # @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro
# @TEST-EXEC: btest-bg-wait -k 1 # @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff receiver/test.log # @TEST-EXEC: btest-diff receiver/test.log
# @TEST-EXEC: cmp receiver/test.log sender/test.log # @TEST-EXEC: cmp receiver/test.log sender/test.log

View file

@ -3,7 +3,7 @@
# @TEST-EXEC: sleep 1 # @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro # @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro
# @TEST-EXEC: sleep 1 # @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-wait -k 1 # @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff sender/test.log # @TEST-EXEC: btest-diff sender/test.log
# @TEST-EXEC: btest-diff sender/test.failure.log # @TEST-EXEC: btest-diff sender/test.failure.log
# @TEST-EXEC: btest-diff sender/test.success.log # @TEST-EXEC: btest-diff sender/test.success.log

View file

@ -3,7 +3,7 @@
# @TEST-EXEC: sleep 1 # @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT # @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT # @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
# @TEST-EXEC: btest-bg-wait -k 6 # @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff manager-1/metrics.log # @TEST-EXEC: btest-diff manager-1/metrics.log
@TEST-START-FILE cluster-layout.bro @TEST-START-FILE cluster-layout.bro

View file

@ -3,7 +3,7 @@
# @TEST-EXEC: sleep 1 # @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT # @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT # @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
# @TEST-EXEC: btest-bg-wait -k 5 # @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff manager-1/notice.log # @TEST-EXEC: btest-diff manager-1/notice.log
@TEST-START-FILE cluster-layout.bro @TEST-START-FILE cluster-layout.bro

View file

@ -2,7 +2,7 @@
# @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT # @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT
# @TEST-EXEC: sleep 1 # @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT # @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
# @TEST-EXEC: btest-bg-wait -k 6 # @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff manager-1/notice.log # @TEST-EXEC: btest-diff manager-1/notice.log
@TEST-START-FILE cluster-layout.bro @TEST-START-FILE cluster-layout.bro

View 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"]);
}

View file

@ -3,7 +3,7 @@
# @TEST-EXEC: sleep 1 # @TEST-EXEC: sleep 1
# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT # @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT
# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT # @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT
# @TEST-EXEC: btest-bg-wait -k 5 # @TEST-EXEC: btest-bg-wait -k 10
# @TEST-EXEC: btest-diff manager-1/notice.log # @TEST-EXEC: btest-diff manager-1/notice.log
@TEST-START-FILE cluster-layout.bro @TEST-START-FILE cluster-layout.bro

View file

@ -22,7 +22,16 @@ files_cwd=`ls $@`
files_baseline=`cd $TEST_BASELINE && ls $@` files_baseline=`cd $TEST_BASELINE && ls $@`
for i in `echo $files_cwd $files_baseline | sort | uniq`; do for i in `echo $files_cwd $files_baseline | sort | uniq`; do
if [[ "$i" != "loaded_scripts.log" && "$i" != "prof.log" ]]; then if [[ "$i" != "loaded_scripts.log" && "$i" != "prof.log" && "$i" != "debug.log" ]]; then
if [[ "$i" == "reporter.log" ]]; then
# Do not diff the reporter.log if it only complains about missing
# GeoIP support.
if ! egrep -v "^#|Bro was not configured for GeoIP support" $i; then
continue
fi
fi
if ! btest-diff $i; then if ! btest-diff $i; then
echo "" >>$diag echo "" >>$diag
echo "#### btest-diff $i" >>$diag echo "#### btest-diff $i" >>$diag

View file

@ -5,3 +5,4 @@
`dirname $0`/diff-remove-timestamps \ `dirname $0`/diff-remove-timestamps \
| `dirname $0`/diff-remove-uids \ | `dirname $0`/diff-remove-uids \
| `dirname $0`/diff-remove-mime-types \ | `dirname $0`/diff-remove-mime-types \
| `dirname $0`/diff-remove-x509-names \

View 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;
}