mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Merge branch 'master' into topic/robin/pp-alarms
This commit is contained in:
commit
e0692b898e
26 changed files with 365 additions and 165 deletions
11
CHANGES
11
CHANGES
|
@ -1,4 +1,15 @@
|
||||||
|
|
||||||
|
2.0-beta-12 | 2011-11-03 15:21:08 -0700
|
||||||
|
|
||||||
|
* No longer write to the PacketFilter::LOG stream if not reading
|
||||||
|
traffic. (Seth Hall)
|
||||||
|
|
||||||
|
2.0-beta-10 | 2011-11-03 15:17:08 -0700
|
||||||
|
|
||||||
|
* Notice framework documentation update. (Seth Hall)
|
||||||
|
|
||||||
|
* Fixing compiler warnings (addresses #388) (Jon Siwek)
|
||||||
|
|
||||||
2.0-beta | 2011-10-27 17:46:28 -0700
|
2.0-beta | 2011-10-27 17:46:28 -0700
|
||||||
|
|
||||||
* Preliminary fix for SSH login detection: we need a counted measure
|
* Preliminary fix for SSH login detection: we need a counted measure
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2.0-beta
|
2.0-beta-12
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit c379cefad994004e6ca5f6ba7de038ab6da3a5f5
|
Subproject commit 29143bd0d3f15d4e8903acd0e60fd9280a31e6f7
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6c5c999d9fe05f0e08cc55af478b6e3e47d15c53
|
Subproject commit 17b69fd96b13a63a7ac66812b360a93e2ce0695d
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7ad1a04b3e9e63e164de00e62bd0db0f2e4597fc
|
Subproject commit c951bda3c8ee7719a129f8e15639479b3c80657c
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6d284656e4c5317a83d8ac58fe51ac8157269284
|
Subproject commit a152042822adfce7cdf7291262645b03ac5f8199
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
||||||
Subproject commit bbf129bd7bd33dfb5641ff0d9242f4b3ebba8e82
|
Subproject commit 019ea8f3e0416144c461d55b41bb935a550d9dfd
|
|
@ -13,7 +13,7 @@ The figure below illustrates the main components of a Bro cluster.
|
||||||
|
|
||||||
.. {{git_pull('bro:doc/deployment.png')}}
|
.. {{git_pull('bro:doc/deployment.png')}}
|
||||||
|
|
||||||
.. image:: deployment.png
|
.. image:: deployment.bro.png
|
||||||
|
|
||||||
Tap
|
Tap
|
||||||
***
|
***
|
||||||
|
|
|
@ -19,7 +19,7 @@ Bro Documentation
|
||||||
`FAQ <{{docroot}}/documentation/faq.html>`_
|
`FAQ <{{docroot}}/documentation/faq.html>`_
|
||||||
A list with frequently asked questions.
|
A list with frequently asked questions.
|
||||||
|
|
||||||
`How to Report a Problem <{{docroot}}/reporting-problems.html>`_
|
`How to Report a Problem <{{docroot}}/documentation/reporting-problems.html>`_
|
||||||
Some advice for when you see Bro doing something you believe it
|
Some advice for when you see Bro doing something you believe it
|
||||||
shouldn't.
|
shouldn't.
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ Frameworks
|
||||||
Bro comes with a number of frameworks, some of which are described in
|
Bro comes with a number of frameworks, some of which are described in
|
||||||
more detail here:
|
more detail here:
|
||||||
|
|
||||||
`Reporting <{{git('bro:doc/notice.rst')}}>`_
|
`Notice <{{git('bro:doc/notice.rst')}}>`_
|
||||||
The notice/alarm framework.
|
The notice framework.
|
||||||
|
|
||||||
`Logging <{{git('bro:doc/logging.rst')}}>`_
|
`Logging <{{git('bro:doc/logging.rst')}}>`_
|
||||||
Customizing and extensing Bro's logging.
|
Customizing and extensing Bro's logging.
|
||||||
|
|
343
doc/notice.rst
343
doc/notice.rst
|
@ -17,7 +17,7 @@ Notice Framework
|
||||||
Overview
|
Overview
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Let us start with a little bit of background on Bro's philosophy on reporting
|
Let's start with a little bit of background on Bro's philosophy on reporting
|
||||||
things. Bro ships with a large number of policy scripts which perform a wide
|
things. Bro ships with a large number of policy scripts which perform a wide
|
||||||
variety of analyses. Most of these scripts monitor for activity which might be
|
variety of analyses. Most of these scripts monitor for activity which might be
|
||||||
of interest for the user. However, none of these scripts determines the
|
of interest for the user. However, none of these scripts determines the
|
||||||
|
@ -25,28 +25,21 @@ importance of what it finds itself. Instead, the scripts only flags situations
|
||||||
as *potentially* interesting, leaving it to the local configuration to define
|
as *potentially* interesting, leaving it to the local configuration to define
|
||||||
which of them are in fact actionable. This decoupling of detection and
|
which of them are in fact actionable. This decoupling of detection and
|
||||||
reporting allows Bro to address the different needs that sites have:
|
reporting allows Bro to address the different needs that sites have:
|
||||||
definitions of what constitutes an attack differ quite a bit between
|
definitions of what constitutes an attack or even a compromise differ quite a
|
||||||
environments, and activity deemed malicious at one site might be fully
|
bit between environments, and activity deemed malicious at one site might be
|
||||||
acceptable at another.
|
fully acceptable at another.
|
||||||
|
|
||||||
Whenever one of Bro's analysis scripts sees something potentially interesting
|
Whenever one of Bro's analysis scripts sees something potentially interesting
|
||||||
it flags the situation by calling the NOTICE function and giving it
|
it flags the situation by calling the ``NOTICE`` function and giving it a
|
||||||
a single Notice::Info record. A Notice has a
|
single ``Notice::Info`` record. A Notice has a ``Notice::Type``, which
|
||||||
Notice::Type, which reflects the kind of activity that has been
|
reflects the kind of activity that has been seen, and it is usually also
|
||||||
seen, and it is usually also augmented with further context about the
|
augmented with further context about the situation.
|
||||||
situation. For example, whenever the base SSH analysis scripts sees an SSH
|
|
||||||
session where it is heuristically guessed to be a successful login, it raises
|
|
||||||
a Notice of the type SSH::Login. The code in the base SSH analysis script
|
|
||||||
looks like this:
|
|
||||||
|
|
||||||
.. code:: bro
|
More information about raising notices can be found in the `Raising Notices`_
|
||||||
|
section.
|
||||||
|
|
||||||
NOTICE([$note=SSH::Login,
|
Once a notice is raised, it can have any number of actions applied to it by
|
||||||
$msg="Heuristically detected successful SSH login.",
|
the ``Notice::policy`` set which is described in the `Notice Policy`_
|
||||||
$conn=c]);
|
|
||||||
|
|
||||||
Once a notice is raised, it can have any number of actions attached to it by
|
|
||||||
the Notice::policy which is described in the `Notice Policy`_
|
|
||||||
section below. Such actions can be to send a mail to the configured
|
section below. Such actions can be to send a mail to the configured
|
||||||
address(es) or to simply ignore the notice. Currently, the following actions
|
address(es) or to simply ignore the notice. Currently, the following actions
|
||||||
are defined:
|
are defined:
|
||||||
|
@ -59,49 +52,45 @@ are defined:
|
||||||
- Description
|
- Description
|
||||||
|
|
||||||
* - Notice::ACTION_LOG
|
* - Notice::ACTION_LOG
|
||||||
- Write the notice to the Notice::LOG logging stream.
|
- Write the notice to the ``Notice::LOG`` logging stream.
|
||||||
|
|
||||||
* - Notice::ACTION_ALARM
|
* - Notice::ACTION_ALARM
|
||||||
- Log into the Notice::ALARM_LOG stream which will rotate
|
- Log into the ``Notice::ALARM_LOG`` stream which will rotate
|
||||||
hourly and email the contents to the email address or addresses
|
hourly and email the contents to the email address or addresses
|
||||||
defined in the Notice::mail_dest variable.
|
defined in the ``Notice::mail_dest`` variable.
|
||||||
|
|
||||||
* - Notice::ACTION_EMAIL
|
* - Notice::ACTION_EMAIL
|
||||||
- Send the notice in an email to the email address or addresses given in
|
- Send the notice in an email to the email address or addresses given in
|
||||||
the Notice::mail_dest variable.
|
the ``Notice::mail_dest`` variable.
|
||||||
|
|
||||||
* - Notice::ACTION_PAGE
|
* - Notice::ACTION_PAGE
|
||||||
- Send an email to the email address or addresses given in the
|
- Send an email to the email address or addresses given in the
|
||||||
Notice::mail_page_dest variable.
|
``Notice::mail_page_dest`` variable.
|
||||||
|
|
||||||
* - Notice::ACTION_NO_SUPPRESS
|
* - Notice::ACTION_NO_SUPPRESS
|
||||||
- This action will disable the built in notice suppression for the
|
- This action will disable the built in notice suppression for the
|
||||||
notice. Keep in mind that this action will need to be attached to
|
notice. Keep in mind that this action will need to be applied to
|
||||||
every notice that shouldn't be suppressed including each of the future
|
every notice that shouldn't be suppressed including each of the future
|
||||||
notices that would have normally been suppressed.
|
notices that would have normally been suppressed.
|
||||||
|
|
||||||
How these notice actions are applied to notices is discussed in the
|
How these notice actions are applied to notices is discussed in the
|
||||||
`Notice Policy`_ and `Notice Policy Shortcuts`_ sections.
|
`Notice Policy`_ and `Notice Policy Shortcuts`_ sections.
|
||||||
|
|
||||||
|
Processing Notices
|
||||||
|
------------------
|
||||||
|
|
||||||
Notice Policy
|
Notice Policy
|
||||||
-------------
|
*************
|
||||||
|
|
||||||
The predefined set Notice::policy provides the mechanism for
|
The predefined set ``Notice::policy`` provides the mechanism for applying
|
||||||
applying actions and other behavior modifications to notices. Each entry of
|
actions and other behavior modifications to notices. Each entry of
|
||||||
Notice::policy defines a combination of several things, a condition
|
``Notice::policy`` is a record of the type ``Notice::PolicyItem`` which
|
||||||
to be matched against all raised notices, an action to be taken if the
|
defines a condition to be matched against all raised notices and one or more
|
||||||
condition matches, and/or a interval to suppress that distinct notice with the
|
of a variety of behavior modifiers. The notice policy is defined by adding any
|
||||||
``$suppress_for`` field. The notice policy is defined by adding any number of
|
number of ``Notice::PolicyItem`` records to the ``Notice::policy`` set.
|
||||||
Notice::Info records to the Notice::policy set.
|
|
||||||
|
|
||||||
Here's a simple example which tells Bro to send an email for all Notices of
|
Here's a simple example which tells Bro to send an email for all notices of
|
||||||
type SSH::Login if the server is 10.0.0.1:
|
type ``SSH::Login`` if the server is 10.0.0.1:
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Keep in mind that the semantics of the SSH::Login notice are
|
|
||||||
such that it is only raised when Bro heuristically detects a successful
|
|
||||||
login. No apparently failed logins will raise this notice.
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
|
@ -112,25 +101,73 @@ type SSH::Login if the server is 10.0.0.1:
|
||||||
$action = Notice::ACTION_EMAIL]
|
$action = Notice::ACTION_EMAIL]
|
||||||
};
|
};
|
||||||
|
|
||||||
While the syntax might look a bit convoluted at first, it provides a lot of
|
.. note::
|
||||||
flexibility due to having access to Bro's full programming language. ``$pred``
|
|
||||||
defines the entry's condition in the form of a predicate written as a Bro
|
Keep in mind that the semantics of the SSH::Login notice are
|
||||||
function. The function is passed the Notice::Info record and it
|
such that it is only raised when Bro heuristically detects a successful
|
||||||
returns a boolean indicating whether the entry applies. If the predicate
|
login. No apparently failed logins will raise this notice.
|
||||||
evaluates to true (``T``), Bro applies any values found in both the
|
|
||||||
``$action`` and ``$suppress_for`` fields. The lack of a predicate in a
|
While the syntax might look a bit convoluted at first, it provides a lot of
|
||||||
Notice::PolicyItem is implicitly true since an implicit false
|
flexibility due to having access to Bro's full programming language.
|
||||||
(``F``) value would never be used.
|
|
||||||
|
Predicate Field
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The ``Notice::PolicyItem`` record type has a field name ``$pred`` which
|
||||||
|
defines the entry's condition in the form of a predicate written as a Bro
|
||||||
|
function. The function is passed the notice as a ``Notice::Info`` record and
|
||||||
|
it returns a boolean value indicating if the entry is applicable to that
|
||||||
|
particular notice.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The lack of a predicate in a ``Notice::PolicyItem`` is implicitly true
|
||||||
|
(``T``) since an implicit false (``F``) value would never be used.
|
||||||
|
|
||||||
The Notice::policy set can hold an arbitrary number of such entries.
|
|
||||||
Bro evaluates the predicates of each entry in the order defined by the
|
Bro evaluates the predicates of each entry in the order defined by the
|
||||||
``$priority`` field. If multiple predicates evaluate to true, it is undefined
|
``$priority`` field in ``Notice::PolicyItem`` records. The valid values are
|
||||||
which of the matching results is taken. One can however associate a *priority*
|
0-10 with 10 being earliest evaluated. If ``$priority`` is omitted, the
|
||||||
with an entry by adding a field ``$priority=<int>`` to its definition; see
|
default priority is 5.
|
||||||
``policy/notice-policy.bro`` for examples. In the case of multiple matches
|
|
||||||
with different priorities, Bro picks the one with the highest. If
|
Behavior Modification Fields
|
||||||
``$priority`` is omitted, as it is in the example above, the default priority
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
is 1.
|
|
||||||
|
There are a set of fields in the ``Notice::PolicyItem`` record type that
|
||||||
|
indicate ways that either the notice or notice processing should be modified
|
||||||
|
if the predicate field (``$pred``) evaluated to true (``T``). Those fields are
|
||||||
|
explained in more detail in the following table.
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:widths: 20 30 20
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Field
|
||||||
|
- Description
|
||||||
|
- Example
|
||||||
|
|
||||||
|
* - ``$action=<Notice::Action>``
|
||||||
|
- Each Notice::PolicyItem can have a single action applied to the notice
|
||||||
|
with this field.
|
||||||
|
- ``$action = Notice::ACTION_EMAIL``
|
||||||
|
|
||||||
|
* - ``$suppress_for=<interval>``
|
||||||
|
- This field makes it possible for a user to modify the behavior of the
|
||||||
|
notice framework's automated suppression of intrinsically similar
|
||||||
|
notices. More information about the notice framework's automated
|
||||||
|
suppression can be found in the `Automated Suppression`_ section of
|
||||||
|
this document.
|
||||||
|
- ``$suppress_for = 10mins``
|
||||||
|
|
||||||
|
* - ``$halt=<bool>``
|
||||||
|
- This field can be used for modification of the notice policy
|
||||||
|
evaluation. To stop processing of notice policy items before
|
||||||
|
evaluating all of them, set this field to ``T`` and make the ``$pred``
|
||||||
|
field return ``T``. ``Notice::PolicyItem`` records defined at a higher
|
||||||
|
priority as defined by the ``$priority`` field will still be evaluated
|
||||||
|
but those at a lower priority won't.
|
||||||
|
- ``$halt = T``
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
|
||||||
|
@ -144,16 +181,16 @@ is 1.
|
||||||
|
|
||||||
|
|
||||||
Notice Policy Shortcuts
|
Notice Policy Shortcuts
|
||||||
-----------------------
|
***********************
|
||||||
|
|
||||||
Although the notice framework provides a great deal of flexibility and
|
Although the notice framework provides a great deal of flexibility and
|
||||||
configurability there are many times that the full expressiveness isn't needed
|
configurability there are many times that the full expressiveness isn't needed
|
||||||
and actually becomes a hindrance to achieving results. The framework provides
|
and actually becomes a hindrance to achieving results. The framework provides
|
||||||
a default Notice::policy suite as a way of giving users the
|
a default ``Notice::policy`` suite as a way of giving users the
|
||||||
shortcuts to easily apply many common actions to notices.
|
shortcuts to easily apply many common actions to notices.
|
||||||
|
|
||||||
These are implemented as sets and tables indexed with a
|
These are implemented as sets and tables indexed with a
|
||||||
Notice::Type enum value. The following table shows and describes
|
``Notice::Type`` enum value. The following table shows and describes
|
||||||
all of the variables available for shortcut configuration of the notice
|
all of the variables available for shortcut configuration of the notice
|
||||||
framework.
|
framework.
|
||||||
|
|
||||||
|
@ -165,35 +202,185 @@ framework.
|
||||||
- Description
|
- Description
|
||||||
|
|
||||||
* - Notice::ignored_types
|
* - Notice::ignored_types
|
||||||
- Adding a Notice::Type to this set results in the notice
|
- Adding a ``Notice::Type`` to this set results in the notice
|
||||||
being ignored. It won't have any other action applied to it, not even
|
being ignored. It won't have any other action applied to it, not even
|
||||||
Notice::ACTION_LOG.
|
``Notice::ACTION_LOG``.
|
||||||
|
|
||||||
* - Notice::emailed_types
|
* - Notice::emailed_types
|
||||||
- Adding a Notice::Type to this set results in
|
- Adding a ``Notice::Type`` to this set results in
|
||||||
Notice::ACTION_EMAIL being applied to the notices of that
|
``Notice::ACTION_EMAIL`` being applied to the notices of that type.
|
||||||
type.
|
|
||||||
|
|
||||||
* - Notice::alarmed_types
|
* - Notice::alarmed_types
|
||||||
- Adding a Notice::Type to this set results in
|
- Adding a Notice::Type to this set results in
|
||||||
Notice::ACTION_ALARM being applied to the notices of that
|
``Notice::ACTION_ALARM`` being applied to the notices of that type.
|
||||||
type.
|
|
||||||
|
|
||||||
* - Notice::not_suppressed_types
|
* - Notice::not_suppressed_types
|
||||||
- Adding a Notice::Type to this set results in that notice
|
- Adding a ``Notice::Type`` to this set results in that notice no longer
|
||||||
no longer undergoing the normal notice suppression that would take
|
undergoing the normal notice suppression that would take place. Be
|
||||||
place. Be careful when using this in production it could result in a
|
careful when using this in production it could result in a dramatic
|
||||||
dramatic increase in the number of notices being processed.
|
increase in the number of notices being processed.
|
||||||
|
|
||||||
|
* - Notice::type_suppression_intervals
|
||||||
|
- This is a table indexed on ``Notice::Type`` and yielding an interval.
|
||||||
|
It can be used as an easy way to extend the default suppression
|
||||||
|
interval for an entire ``Notice::Type`` without having to create a
|
||||||
|
whole ``Notice::policy`` entry and setting the ``$suppress_for``
|
||||||
|
field.
|
||||||
|
|
||||||
|
Raising Notices
|
||||||
|
---------------
|
||||||
|
|
||||||
|
A script should raise a notice for any occurrence that a user may want to be
|
||||||
|
notified about or take action on. For example, whenever the base SSH analysis
|
||||||
|
scripts sees an SSH session where it is heuristically guessed to be a
|
||||||
|
successful login, it raises a Notice of the type ``SSH::Login``. The code in
|
||||||
|
the base SSH analysis script looks like this:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
NOTICE([$note=SSH::Login,
|
||||||
|
$msg="Heuristically detected successful SSH login.",
|
||||||
|
$conn=c]);
|
||||||
|
|
||||||
|
``NOTICE`` is a normal function in the global namespace which wraps a function
|
||||||
|
within the ``Notice`` namespace. It takes a single argument of the
|
||||||
|
``Notice::Info`` record type. The most common fields used when raising notices
|
||||||
|
are described in the following table:
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:widths: 32 40
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Field name
|
||||||
|
- Description
|
||||||
|
|
||||||
|
* - ``$note``
|
||||||
|
- This field is required and is an enum value which represents the
|
||||||
|
notice type.
|
||||||
|
|
||||||
|
* - ``$msg``
|
||||||
|
- This is a human readable message which is meant to provide more
|
||||||
|
information about this particular instance of the notice type.
|
||||||
|
|
||||||
|
* - ``$sub``
|
||||||
|
- This is a sub-message which meant for human readability but will
|
||||||
|
frequently also be used to contain data meant to be matched with the
|
||||||
|
``Notice::policy``.
|
||||||
|
|
||||||
|
* - ``$conn``
|
||||||
|
- If a connection record is available when the notice is being raised
|
||||||
|
and the notice represents some attribute of the connection the
|
||||||
|
connection record can be given here. Other fields such as ``$id`` and
|
||||||
|
``$src`` will automatically be populated from this value.
|
||||||
|
|
||||||
|
* - ``$id``
|
||||||
|
- If a conn_id record is available when the notice is being raised and
|
||||||
|
the notice represents some attribute of the connection, the connection
|
||||||
|
be given here. Other fields such as ``$src`` will automatically be
|
||||||
|
populated from this value.
|
||||||
|
|
||||||
|
* - ``$src``
|
||||||
|
- If the notice represents an attribute of a single host then it's
|
||||||
|
possible that only this field should be filled out to represent the
|
||||||
|
host that is being "noticed".
|
||||||
|
|
||||||
|
* - ``$n``
|
||||||
|
- This normally represents a number if the notice has to do with some
|
||||||
|
number. It's most frequently used for numeric tests in the
|
||||||
|
``Notice::policy`` for making policy decisions.
|
||||||
|
|
||||||
|
* - ``$identifier``
|
||||||
|
- This represents a unique identifier for this notice. This field is
|
||||||
|
described in more detail in the `Automated Suppression`_ section.
|
||||||
|
|
||||||
|
* - ``$suppress_for``
|
||||||
|
- This field can be set if there is a natural suppression interval for
|
||||||
|
the notice that may be different than the default value. The value set
|
||||||
|
to this field can also be modified by a user's ``Notice::policy`` so
|
||||||
|
the value is not set permanently and unchangeably.
|
||||||
|
|
||||||
|
When writing Bro scripts which raise notices, some thought should be given to
|
||||||
|
what the notice represents and what data should be provided to give a consumer
|
||||||
|
of the notice the best information about the notice. If the notice is
|
||||||
|
representative of many connections and is an attribute of a host (e.g. a
|
||||||
|
scanning host) it probably makes most sense to fill out the ``$src`` field and
|
||||||
|
not give a connection or conn_id. If a notice is representative of a
|
||||||
|
connection attribute (e.g. an apparent SSH login) the it makes sense to fill
|
||||||
|
out either ``$conn`` or ``$id`` based on the data that is available when the
|
||||||
|
notice is raised. Using care when inserting data into a notice will make later
|
||||||
|
analysis easier when only the data to fully represent the occurrence that
|
||||||
|
raised the notice is available. If complete connection information is
|
||||||
|
available when an SSL server certificate is expiring, the logs will be very
|
||||||
|
confusing because the connection that the certificate was detected on is a
|
||||||
|
side topic to the fact that an expired certificate was detected. It's possible
|
||||||
|
in many cases that two or more separate notices may need to be generated. As
|
||||||
|
an example, one could be for the detection of the expired SSL certificate and
|
||||||
|
another could be for if the client decided to go ahead with the connection
|
||||||
|
neglecting the expired certificate.
|
||||||
|
|
||||||
|
Automated Suppression
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The notice framework supports suppression for notices if the author of the
|
||||||
|
script that is generating the notice has indicated to the notice framework how
|
||||||
|
to identify notices that are intrinsically the same. Identification of these
|
||||||
|
"intrinsically duplicate" notices is implemented with an optional field in
|
||||||
|
``Notice::Info`` records named ``$identifier`` which is a simple string.
|
||||||
|
If the ``$identifier`` and ``$type`` fields are the same for two notices, the
|
||||||
|
notice framework actually considers them to be the same thing and can use that
|
||||||
|
information to suppress duplicates for a configurable period of time.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If the ``$identifier`` is left out of a notice, no notice suppression
|
||||||
|
takes place due to the framework's inability to identify duplicates. This
|
||||||
|
could be completely legitimate usage if no notices could ever be
|
||||||
|
considered to be duplicates.
|
||||||
|
|
||||||
|
The ``$identifier`` field is typically comprised of several pieces of data
|
||||||
|
related to the notice that when combined represent a unique instance of that
|
||||||
|
notice. Here is an example of the script
|
||||||
|
``policy/protocols/ssl/validate-certs.bro`` raising a notice for session
|
||||||
|
negotiations where the certificate or certificate chain did not validate
|
||||||
|
successfully against the available certificate authority certificates.
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
NOTICE([$note=SSL::Invalid_Server_Cert,
|
||||||
|
$msg=fmt("SSL certificate validation failed with (%s)", c$ssl$validation_status),
|
||||||
|
$sub=c$ssl$subject,
|
||||||
|
$conn=c,
|
||||||
|
$identifier=cat(c$id$resp_h,c$id$resp_p,c$ssl$validation_status,c$ssl$cert_hash)]);
|
||||||
|
|
||||||
|
In the above example you can see that the ``$identifier`` field contains a
|
||||||
|
string that is built from the responder IP address and port, the validation
|
||||||
|
status message, and the MD5 sum of the server certificate. Those fields in
|
||||||
|
particular are chosen because different SSL certificates could be seen on any
|
||||||
|
port of a host, certificates could fail validation for different reasons, and
|
||||||
|
multiple server certificates could be used on that combination of IP address
|
||||||
|
and port with the ``server_name`` SSL extension (explaining the addition of
|
||||||
|
the MD5 sum of the certificate). The result is that if a certificate fails
|
||||||
|
validation and all four pieces of data match (IP address, port, validation
|
||||||
|
status, and certificate hash) that particular notice won't be raised again for
|
||||||
|
the default suppression period.
|
||||||
|
|
||||||
|
Setting the ``$identifier`` field is left to those raising notices because
|
||||||
|
it's assumed that the script author who is raising the notice understands the
|
||||||
|
full problem set and edge cases of the notice which may not be readily
|
||||||
|
apparent to users. If users don't want the suppression to take place or simply
|
||||||
|
want a different interval, they can always modify it with the
|
||||||
|
``Notice::policy``.
|
||||||
|
|
||||||
|
|
||||||
Automated Deduplication
|
Extending Notice Framework
|
||||||
-----------------------
|
--------------------------
|
||||||
|
|
||||||
Extending Notice Actions
|
Adding Custom Notice Actions
|
||||||
------------------------
|
****************************
|
||||||
|
|
||||||
Extending Emails
|
Extending Notice Emails
|
||||||
----------------
|
***********************
|
||||||
|
|
||||||
Cluster Considerations
|
Cluster Considerations
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,7 @@ function install()
|
||||||
$sub=default_filter]);
|
$sub=default_filter]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( reading_live_traffic() || reading_traces() )
|
||||||
Log::write(PacketFilter::LOG, info);
|
Log::write(PacketFilter::LOG, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ public:
|
||||||
if ( analyzer )
|
if ( analyzer )
|
||||||
analyzer->Weird("base64_illegal_encoding", msg);
|
analyzer->Weird("base64_illegal_encoding", msg);
|
||||||
else
|
else
|
||||||
reporter->Error(msg);
|
reporter->Error("%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -522,7 +522,7 @@ ListVal* CompositeHash::RecoverVals(const HashKey* k) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( kp != k_end )
|
if ( kp != k_end )
|
||||||
reporter->InternalError("under-ran key in CompositeHash::DescribeKey %ld", k_end - kp);
|
reporter->InternalError("under-ran key in CompositeHash::DescribeKey %zd", k_end - kp);
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
|
@ -797,7 +797,7 @@ int dbg_handle_debug_input()
|
||||||
input_line = (char*) safe_malloc(1024);
|
input_line = (char*) safe_malloc(1024);
|
||||||
input_line[1023] = 0;
|
input_line[1023] = 0;
|
||||||
// ### Maybe it's not always stdin.
|
// ### Maybe it's not always stdin.
|
||||||
fgets(input_line, 1023, stdin);
|
input_line = fgets(input_line, 1023, stdin);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ### Maybe not stdin; maybe do better cleanup.
|
// ### Maybe not stdin; maybe do better cleanup.
|
||||||
|
|
|
@ -296,7 +296,7 @@ void ODesc::AddBytesRaw(const void* bytes, unsigned int n)
|
||||||
if ( ! write_failed )
|
if ( ! write_failed )
|
||||||
// Most likely it's a "disk full" so report
|
// Most likely it's a "disk full" so report
|
||||||
// subsequent failures only once.
|
// subsequent failures only once.
|
||||||
reporter->Error(fmt("error writing to %s: %s", f->Name(), strerror(errno)));
|
reporter->Error("error writing to %s: %s", f->Name(), strerror(errno));
|
||||||
|
|
||||||
write_failed = true;
|
write_failed = true;
|
||||||
return;
|
return;
|
||||||
|
|
30
src/File.cc
30
src/File.cc
|
@ -149,7 +149,7 @@ BroFile::BroFile(const char* arg_name, const char* arg_access, BroType* arg_t)
|
||||||
t = arg_t ? arg_t : base_type(TYPE_STRING);
|
t = arg_t ? arg_t : base_type(TYPE_STRING);
|
||||||
if ( ! Open() )
|
if ( ! Open() )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("cannot open %s: %s", name, strerror(errno)));
|
reporter->Error("cannot open %s: %s", name, strerror(errno));
|
||||||
is_open = 0;
|
is_open = 0;
|
||||||
okay_to_manage = 0;
|
okay_to_manage = 0;
|
||||||
}
|
}
|
||||||
|
@ -641,7 +641,7 @@ void BroFile::InitEncrypt(const char* keyfile)
|
||||||
|
|
||||||
if ( ! key )
|
if ( ! key )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't open key file %s: %s", keyfile, strerror(errno)));
|
reporter->Error("can't open key file %s: %s", keyfile, strerror(errno));
|
||||||
Close();
|
Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -649,8 +649,8 @@ void BroFile::InitEncrypt(const char* keyfile)
|
||||||
pub_key = PEM_read_PUBKEY(key, 0, 0, 0);
|
pub_key = PEM_read_PUBKEY(key, 0, 0, 0);
|
||||||
if ( ! pub_key )
|
if ( ! pub_key )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't read key from %s: %s", keyfile,
|
reporter->Error("can't read key from %s: %s", keyfile,
|
||||||
ERR_error_string(ERR_get_error(), 0)));
|
ERR_error_string(ERR_get_error(), 0));
|
||||||
Close();
|
Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -671,8 +671,8 @@ void BroFile::InitEncrypt(const char* keyfile)
|
||||||
if ( ! EVP_SealInit(cipher_ctx, cipher_type, &psecret,
|
if ( ! EVP_SealInit(cipher_ctx, cipher_type, &psecret,
|
||||||
(int*) &secret_len, iv, &pub_key, 1) )
|
(int*) &secret_len, iv, &pub_key, 1) )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't init cipher context for %s: %s", keyfile,
|
reporter->Error("can't init cipher context for %s: %s", keyfile,
|
||||||
ERR_error_string(ERR_get_error(), 0)));
|
ERR_error_string(ERR_get_error(), 0));
|
||||||
Close();
|
Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -684,8 +684,8 @@ void BroFile::InitEncrypt(const char* keyfile)
|
||||||
fwrite(secret, ntohl(secret_len), 1, f) &&
|
fwrite(secret, ntohl(secret_len), 1, f) &&
|
||||||
fwrite(iv, iv_len, 1, f)) )
|
fwrite(iv, iv_len, 1, f)) )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't write header to log file %s: %s",
|
reporter->Error("can't write header to log file %s: %s",
|
||||||
name, strerror(errno)));
|
name, strerror(errno));
|
||||||
Close();
|
Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -709,8 +709,8 @@ void BroFile::FinishEncrypt()
|
||||||
|
|
||||||
if ( outl && ! fwrite(cipher_buffer, outl, 1, f) )
|
if ( outl && ! fwrite(cipher_buffer, outl, 1, f) )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("write error for %s: %s",
|
reporter->Error("write error for %s: %s",
|
||||||
name, strerror(errno)));
|
name, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,17 +741,17 @@ int BroFile::Write(const char* data, int len)
|
||||||
if ( ! EVP_SealUpdate(cipher_ctx, cipher_buffer, &outl,
|
if ( ! EVP_SealUpdate(cipher_ctx, cipher_buffer, &outl,
|
||||||
(unsigned char*)data, inl) )
|
(unsigned char*)data, inl) )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("encryption error for %s: %s",
|
reporter->Error("encryption error for %s: %s",
|
||||||
name,
|
name,
|
||||||
ERR_error_string(ERR_get_error(), 0)));
|
ERR_error_string(ERR_get_error(), 0));
|
||||||
Close();
|
Close();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( outl && ! fwrite(cipher_buffer, outl, 1, f) )
|
if ( outl && ! fwrite(cipher_buffer, outl, 1, f) )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("write error for %s: %s",
|
reporter->Error("write error for %s: %s",
|
||||||
name, strerror(errno)));
|
name, strerror(errno));
|
||||||
Close();
|
Close();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -798,7 +798,7 @@ void BroFile::UpdateFileSize()
|
||||||
struct stat s;
|
struct stat s;
|
||||||
if ( fstat(fileno(f), &s) < 0 )
|
if ( fstat(fileno(f), &s) < 0 )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't stat fd for %s: %s", name, strerror(errno)));
|
reporter->Error("can't stat fd for %s: %s", name, strerror(errno));
|
||||||
current_size = 0;
|
current_size = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,11 +74,11 @@ void File_Analyzer::InitMagic(magic_t* magic, int flags)
|
||||||
*magic = magic_open(flags);
|
*magic = magic_open(flags);
|
||||||
|
|
||||||
if ( ! *magic )
|
if ( ! *magic )
|
||||||
reporter->Error(fmt("can't init libmagic: %s", magic_error(*magic)));
|
reporter->Error("can't init libmagic: %s", magic_error(*magic));
|
||||||
|
|
||||||
else if ( magic_load(*magic, 0) < 0 )
|
else if ( magic_load(*magic, 0) < 0 )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't load magic file: %s", magic_error(*magic)));
|
reporter->Error("can't load magic file: %s", magic_error(*magic));
|
||||||
magic_close(*magic);
|
magic_close(*magic);
|
||||||
*magic = 0;
|
*magic = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1453,8 +1453,8 @@ bool LogMgr::Flush(EnumVal* id)
|
||||||
|
|
||||||
void LogMgr::Error(LogWriter* writer, const char* msg)
|
void LogMgr::Error(LogWriter* writer, const char* msg)
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("error with writer for %s: %s",
|
reporter->Error("error with writer for %s: %s",
|
||||||
writer->Path().c_str(), msg));
|
writer->Path().c_str(), msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timer which on dispatching rotates the filter.
|
// Timer which on dispatching rotates the filter.
|
||||||
|
|
|
@ -85,8 +85,8 @@ void OSFingerprint::collide(uint32 id)
|
||||||
if (sig[id].ttl % 32 && sig[id].ttl != 255 && sig[id].ttl % 30)
|
if (sig[id].ttl % 32 && sig[id].ttl != 255 && sig[id].ttl % 30)
|
||||||
{
|
{
|
||||||
problems=1;
|
problems=1;
|
||||||
reporter->Warning(fmt("OS fingerprinting: [!] Unusual TTL (%d) for signature '%s %s' (line %d).",
|
reporter->Warning("OS fingerprinting: [!] Unusual TTL (%d) for signature '%s %s' (line %d).",
|
||||||
sig[id].ttl,sig[id].os,sig[id].desc,sig[id].line));
|
sig[id].ttl,sig[id].os,sig[id].desc,sig[id].line);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0;i<id;i++)
|
for (i=0;i<id;i++)
|
||||||
|
@ -94,8 +94,8 @@ void OSFingerprint::collide(uint32 id)
|
||||||
if (!strcmp(sig[i].os,sig[id].os) &&
|
if (!strcmp(sig[i].os,sig[id].os) &&
|
||||||
!strcmp(sig[i].desc,sig[id].desc)) {
|
!strcmp(sig[i].desc,sig[id].desc)) {
|
||||||
problems=1;
|
problems=1;
|
||||||
reporter->Warning(fmt("OS fingerprinting: [!] Duplicate signature name: '%s %s' (line %d and %d).",
|
reporter->Warning("OS fingerprinting: [!] Duplicate signature name: '%s %s' (line %d and %d).",
|
||||||
sig[i].os,sig[i].desc,sig[i].line,sig[id].line));
|
sig[i].os,sig[i].desc,sig[i].line,sig[id].line);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If TTLs are sufficiently away from each other, the risk of
|
/* If TTLs are sufficiently away from each other, the risk of
|
||||||
|
@ -277,10 +277,10 @@ do_const:
|
||||||
if (sig[id].opt[j] ^ sig[i].opt[j]) goto reloop;
|
if (sig[id].opt[j] ^ sig[i].opt[j]) goto reloop;
|
||||||
|
|
||||||
problems=1;
|
problems=1;
|
||||||
reporter->Warning(fmt("OS fingerprinting: [!] Signature '%s %s' (line %d)\n"
|
reporter->Warning("OS fingerprinting: [!] Signature '%s %s' (line %d)\n"
|
||||||
" is already covered by '%s %s' (line %d).",
|
" is already covered by '%s %s' (line %d).",
|
||||||
sig[id].os,sig[id].desc,sig[id].line,sig[i].os,sig[i].desc,
|
sig[id].os,sig[id].desc,sig[id].line,sig[i].os,sig[i].desc,
|
||||||
sig[i].line));
|
sig[i].line);
|
||||||
|
|
||||||
reloop:
|
reloop:
|
||||||
;
|
;
|
||||||
|
|
|
@ -88,7 +88,8 @@ bool LoadPolicyFileText(const char* policy_filename)
|
||||||
// ### This code is not necessarily Unicode safe!
|
// ### This code is not necessarily Unicode safe!
|
||||||
// (probably fine with UTF-8)
|
// (probably fine with UTF-8)
|
||||||
pf->filedata = new char[size+1];
|
pf->filedata = new char[size+1];
|
||||||
fread(pf->filedata, size, 1, f);
|
if ( fread(pf->filedata, size, 1, f) != 1 )
|
||||||
|
reporter->InternalError("Failed to fread() file data");
|
||||||
pf->filedata[size] = 0;
|
pf->filedata[size] = 0;
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
|
|
@ -392,7 +392,7 @@ static bool sendToIO(ChunkedIO* io, ChunkedIO::Chunk* c)
|
||||||
{
|
{
|
||||||
if ( ! io->Write(c) )
|
if ( ! io->Write(c) )
|
||||||
{
|
{
|
||||||
reporter->Warning(fmt("can't send chunk: %s", io->Error()));
|
reporter->Warning("can't send chunk: %s", io->Error());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ static bool sendToIO(ChunkedIO* io, char msg_type, RemoteSerializer::PeerID id,
|
||||||
{
|
{
|
||||||
if ( ! sendCMsg(io, msg_type, id) )
|
if ( ! sendCMsg(io, msg_type, id) )
|
||||||
{
|
{
|
||||||
reporter->Warning(fmt("can't send message of type %d: %s", msg_type, io->Error()));
|
reporter->Warning("can't send message of type %d: %s", msg_type, io->Error());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ static bool sendToIO(ChunkedIO* io, char msg_type, RemoteSerializer::PeerID id,
|
||||||
{
|
{
|
||||||
if ( ! sendCMsg(io, msg_type, id) )
|
if ( ! sendCMsg(io, msg_type, id) )
|
||||||
{
|
{
|
||||||
reporter->Warning(fmt("can't send message of type %d: %s", msg_type, io->Error()));
|
reporter->Warning("can't send message of type %d: %s", msg_type, io->Error());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -715,7 +715,7 @@ bool RemoteSerializer::CloseConnection(PeerID id)
|
||||||
Peer* peer = LookupPeer(id, true);
|
Peer* peer = LookupPeer(id, true);
|
||||||
if ( ! peer )
|
if ( ! peer )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("unknown peer id %d for closing connection", int(id)));
|
reporter->Error("unknown peer id %d for closing connection", int(id));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,14 +750,14 @@ bool RemoteSerializer::RequestSync(PeerID id, bool auth)
|
||||||
Peer* peer = LookupPeer(id, true);
|
Peer* peer = LookupPeer(id, true);
|
||||||
if ( ! peer )
|
if ( ! peer )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("unknown peer id %d for request sync", int(id)));
|
reporter->Error("unknown peer id %d for request sync", int(id));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( peer->phase != Peer::HANDSHAKE )
|
if ( peer->phase != Peer::HANDSHAKE )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't request sync from peer; wrong phase %d",
|
reporter->Error("can't request sync from peer; wrong phase %d",
|
||||||
peer->phase));
|
peer->phase);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,14 +777,14 @@ bool RemoteSerializer::RequestLogs(PeerID id)
|
||||||
Peer* peer = LookupPeer(id, true);
|
Peer* peer = LookupPeer(id, true);
|
||||||
if ( ! peer )
|
if ( ! peer )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("unknown peer id %d for request logs", int(id)));
|
reporter->Error("unknown peer id %d for request logs", int(id));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( peer->phase != Peer::HANDSHAKE )
|
if ( peer->phase != Peer::HANDSHAKE )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't request logs from peer; wrong phase %d",
|
reporter->Error("can't request logs from peer; wrong phase %d",
|
||||||
peer->phase));
|
peer->phase);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,14 +802,14 @@ bool RemoteSerializer::RequestEvents(PeerID id, RE_Matcher* pattern)
|
||||||
Peer* peer = LookupPeer(id, true);
|
Peer* peer = LookupPeer(id, true);
|
||||||
if ( ! peer )
|
if ( ! peer )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("unknown peer id %d for request sync", int(id)));
|
reporter->Error("unknown peer id %d for request sync", int(id));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( peer->phase != Peer::HANDSHAKE )
|
if ( peer->phase != Peer::HANDSHAKE )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't request events from peer; wrong phase %d",
|
reporter->Error("can't request events from peer; wrong phase %d",
|
||||||
peer->phase));
|
peer->phase);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -869,8 +869,8 @@ bool RemoteSerializer::CompleteHandshake(PeerID id)
|
||||||
|
|
||||||
if ( p->phase != Peer::HANDSHAKE )
|
if ( p->phase != Peer::HANDSHAKE )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't complete handshake; wrong phase %d",
|
reporter->Error("can't complete handshake; wrong phase %d",
|
||||||
p->phase));
|
p->phase);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1138,7 +1138,7 @@ bool RemoteSerializer::SendCaptureFilter(PeerID id, const char* filter)
|
||||||
|
|
||||||
if ( peer->phase != Peer::HANDSHAKE )
|
if ( peer->phase != Peer::HANDSHAKE )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't sent capture filter to peer; wrong phase %d", peer->phase));
|
reporter->Error("can't sent capture filter to peer; wrong phase %d", peer->phase);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1215,8 +1215,8 @@ bool RemoteSerializer::SendCapabilities(Peer* peer)
|
||||||
{
|
{
|
||||||
if ( peer->phase != Peer::HANDSHAKE )
|
if ( peer->phase != Peer::HANDSHAKE )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't sent capabilties to peer; wrong phase %d",
|
reporter->Error("can't sent capabilties to peer; wrong phase %d",
|
||||||
peer->phase));
|
peer->phase);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3011,8 +3011,8 @@ bool RemoteSerializer::SendCMsgToChild(char msg_type, Peer* peer)
|
||||||
{
|
{
|
||||||
if ( ! sendCMsg(io, msg_type, peer ? peer->id : PEER_NONE) )
|
if ( ! sendCMsg(io, msg_type, peer ? peer->id : PEER_NONE) )
|
||||||
{
|
{
|
||||||
reporter->Warning(fmt("can't send message of type %d: %s",
|
reporter->Warning("can't send message of type %d: %s",
|
||||||
msg_type, io->Error()));
|
msg_type, io->Error());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -19,7 +19,7 @@ SerialObj* SerialObj::Instantiate(SerialType type)
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
reporter->Error(fmt("Unknown object type 0x%08x", type));
|
reporter->Error("Unknown object type 0x%08x", type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ const char* SerialObj::ClassName(SerialType type)
|
||||||
if ( f != names->end() )
|
if ( f != names->end() )
|
||||||
return f->second;
|
return f->second;
|
||||||
|
|
||||||
reporter->Error(fmt("Unknown object type 0x%08x", type));
|
reporter->Error("Unknown object type 0x%08x", type);
|
||||||
return "<no-class-name>";
|
return "<no-class-name>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -350,7 +350,7 @@ void StateAccess::Replay()
|
||||||
v->AsRecordVal()->Assign(idx, op2 ? op2->Ref() : 0);
|
v->AsRecordVal()->Assign(idx, op2 ? op2->Ref() : 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
reporter->Error(fmt("access replay: unknown record field %s for assign", field));
|
reporter->Error("access replay: unknown record field %s for assign", field);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( t == TYPE_VECTOR )
|
else if ( t == TYPE_VECTOR )
|
||||||
|
@ -411,7 +411,7 @@ void StateAccess::Replay()
|
||||||
v->AsRecordVal()->Assign(idx, new_val, OP_INCR);
|
v->AsRecordVal()->Assign(idx, new_val, OP_INCR);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
reporter->Error(fmt("access replay: unknown record field %s for assign", field));
|
reporter->Error("access replay: unknown record field %s for assign", field);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( t == TYPE_VECTOR )
|
else if ( t == TYPE_VECTOR )
|
||||||
|
|
|
@ -2181,7 +2181,7 @@ function send_id%(p: event_peer, id: string%) : bool
|
||||||
ID* i = global_scope()->Lookup(id->CheckString());
|
ID* i = global_scope()->Lookup(id->CheckString());
|
||||||
if ( ! i )
|
if ( ! i )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("send_id: no global id %s", id->CheckString()));
|
reporter->Error("send_id: no global id %s", id->CheckString());
|
||||||
return new Val(0, TYPE_BOOL);
|
return new Val(0, TYPE_BOOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2250,7 +2250,7 @@ function get_event_peer%(%) : event_peer
|
||||||
Val* v = remote_serializer->GetPeerVal(src);
|
Val* v = remote_serializer->GetPeerVal(src);
|
||||||
if ( ! v )
|
if ( ! v )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("peer %d does not exist anymore", int(src)));
|
reporter->Error("peer %d does not exist anymore", int(src));
|
||||||
RecordVal* p = mgr.GetLocalPeerVal();
|
RecordVal* p = mgr.GetLocalPeerVal();
|
||||||
Ref(p);
|
Ref(p);
|
||||||
return p;
|
return p;
|
||||||
|
@ -3295,13 +3295,13 @@ function identify_data%(data: string, return_mime: bool%): string
|
||||||
|
|
||||||
if ( ! *magic )
|
if ( ! *magic )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't init libmagic: %s", magic_error(*magic)));
|
reporter->Error("can't init libmagic: %s", magic_error(*magic));
|
||||||
return new StringVal("");
|
return new StringVal("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( magic_load(*magic, 0) < 0 )
|
if ( magic_load(*magic, 0) < 0 )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("can't load magic file: %s", magic_error(*magic)));
|
reporter->Error("can't load magic file: %s", magic_error(*magic));
|
||||||
magic_close(*magic);
|
magic_close(*magic);
|
||||||
*magic = 0;
|
*magic = 0;
|
||||||
return new StringVal("");
|
return new StringVal("");
|
||||||
|
|
|
@ -1030,7 +1030,7 @@ void clear_reST_doc_comments()
|
||||||
if ( ! reST_doc_comments )
|
if ( ! reST_doc_comments )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf(stderr, "Warning: %lu unconsumed reST comments:\n",
|
fprintf(stderr, "Warning: %zu unconsumed reST comments:\n",
|
||||||
reST_doc_comments->size());
|
reST_doc_comments->size());
|
||||||
|
|
||||||
print_current_reST_doc_comments();
|
print_current_reST_doc_comments();
|
||||||
|
|
30
src/util.cc
30
src/util.cc
|
@ -478,22 +478,22 @@ bool ensure_dir(const char *dirname)
|
||||||
{
|
{
|
||||||
if ( errno != ENOENT )
|
if ( errno != ENOENT )
|
||||||
{
|
{
|
||||||
reporter->Warning(fmt("can't stat directory %s: %s",
|
reporter->Warning("can't stat directory %s: %s",
|
||||||
dirname, strerror(errno)));
|
dirname, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mkdir(dirname, 0700) < 0 )
|
if ( mkdir(dirname, 0700) < 0 )
|
||||||
{
|
{
|
||||||
reporter->Warning(fmt("can't create directory %s: %s",
|
reporter->Warning("can't create directory %s: %s",
|
||||||
dirname, strerror(errno)));
|
dirname, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( ! S_ISDIR(st.st_mode) )
|
else if ( ! S_ISDIR(st.st_mode) )
|
||||||
{
|
{
|
||||||
reporter->Warning(fmt("%s exists but is not a directory", dirname));
|
reporter->Warning("%s exists but is not a directory", dirname);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,7 +506,7 @@ bool is_dir(const char* path)
|
||||||
if ( stat(path, &st) < 0 )
|
if ( stat(path, &st) < 0 )
|
||||||
{
|
{
|
||||||
if ( errno != ENOENT )
|
if ( errno != ENOENT )
|
||||||
reporter->Warning(fmt("can't stat %s: %s", path, strerror(errno)));
|
reporter->Warning("can't stat %s: %s", path, strerror(errno));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -556,15 +556,15 @@ static bool read_random_seeds(const char* read_file, uint32* seed,
|
||||||
|
|
||||||
if ( stat(read_file, &st) < 0 )
|
if ( stat(read_file, &st) < 0 )
|
||||||
{
|
{
|
||||||
reporter->Warning(fmt("Seed file '%s' does not exist: %s",
|
reporter->Warning("Seed file '%s' does not exist: %s",
|
||||||
read_file, strerror(errno)));
|
read_file, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! (f = fopen(read_file, "r")) )
|
if ( ! (f = fopen(read_file, "r")) )
|
||||||
{
|
{
|
||||||
reporter->Warning(fmt("Could not open seed file '%s': %s",
|
reporter->Warning("Could not open seed file '%s': %s",
|
||||||
read_file, strerror(errno)));
|
read_file, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,8 +599,8 @@ static bool write_random_seeds(const char* write_file, uint32 seed,
|
||||||
|
|
||||||
if ( ! (f = fopen(write_file, "w+")) )
|
if ( ! (f = fopen(write_file, "w+")) )
|
||||||
{
|
{
|
||||||
reporter->Warning(fmt("Could not create seed file '%s': %s",
|
reporter->Warning("Could not create seed file '%s': %s",
|
||||||
write_file, strerror(errno)));
|
write_file, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1024,7 +1024,7 @@ FILE* rotate_file(const char* name, RecordVal* rotate_info)
|
||||||
FILE* newf = fopen(tmpname, "w");
|
FILE* newf = fopen(tmpname, "w");
|
||||||
if ( ! newf )
|
if ( ! newf )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("rotate_file: can't open %s: %s", tmpname, strerror(errno)));
|
reporter->Error("rotate_file: can't open %s: %s", tmpname, strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,7 +1033,7 @@ FILE* rotate_file(const char* name, RecordVal* rotate_info)
|
||||||
struct stat dummy;
|
struct stat dummy;
|
||||||
if ( link(name, newname) < 0 || stat(newname, &dummy) < 0 )
|
if ( link(name, newname) < 0 || stat(newname, &dummy) < 0 )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("rotate_file: can't move %s to %s: %s", name, newname, strerror(errno)));
|
reporter->Error("rotate_file: can't move %s to %s: %s", name, newname, strerror(errno));
|
||||||
fclose(newf);
|
fclose(newf);
|
||||||
unlink(newname);
|
unlink(newname);
|
||||||
unlink(tmpname);
|
unlink(tmpname);
|
||||||
|
@ -1043,7 +1043,7 @@ FILE* rotate_file(const char* name, RecordVal* rotate_info)
|
||||||
// Close current file, and move the tmp to its place.
|
// Close current file, and move the tmp to its place.
|
||||||
if ( unlink(name) < 0 || link(tmpname, name) < 0 || unlink(tmpname) < 0 )
|
if ( unlink(name) < 0 || link(tmpname, name) < 0 || unlink(tmpname) < 0 )
|
||||||
{
|
{
|
||||||
reporter->Error(fmt("rotate_file: can't move %s to %s: %s", tmpname, name, strerror(errno)));
|
reporter->Error("rotate_file: can't move %s to %s: %s", tmpname, name, strerror(errno));
|
||||||
exit(1); // hard to fix, but shouldn't happen anyway...
|
exit(1); // hard to fix, but shouldn't happen anyway...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue