mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 22:58:20 +00:00
Merge remote-tracking branch 'origin/topic/robin/pacf' into topic/johanna/openflow
This commit is contained in:
commit
94c67dc030
9 changed files with 839 additions and 0 deletions
3
scripts/base/frameworks/pacf/__load__.bro
Normal file
3
scripts/base/frameworks/pacf/__load__.bro
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
@load ./types
|
||||||
|
@load ./main
|
||||||
|
@load ./plugins
|
477
scripts/base/frameworks/pacf/main.bro
Normal file
477
scripts/base/frameworks/pacf/main.bro
Normal file
|
@ -0,0 +1,477 @@
|
||||||
|
##! Bro's packet aquisition and control framework.
|
||||||
|
##!
|
||||||
|
##! This plugin-based framework allows to control the traffic that Bro monitors
|
||||||
|
##! as well as, if having access to the forwarding path, the traffic the network
|
||||||
|
##! forwards. By default, the framework lets evyerthing through, to both Bro
|
||||||
|
##! itself as well as on the network. Scripts can then add rules to impose
|
||||||
|
##! restrictions on entities, such as specific connections or IP addresses.
|
||||||
|
##!
|
||||||
|
##! This framework has two API: a high-level and low-level. The high-levem API
|
||||||
|
##! provides convinience functions for a set of common operations. The
|
||||||
|
##! low-level API provides full flexibility.
|
||||||
|
|
||||||
|
module Pacf;
|
||||||
|
|
||||||
|
@load ./plugin
|
||||||
|
@load ./types
|
||||||
|
|
||||||
|
export {
|
||||||
|
## The framework's logging stream identifier.
|
||||||
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
|
# ###
|
||||||
|
# ### Generic functions.
|
||||||
|
# ###
|
||||||
|
|
||||||
|
# Activates a plugin.
|
||||||
|
#
|
||||||
|
# plugin: The plugin to acticate.
|
||||||
|
#
|
||||||
|
# priority: The higher the priority, the earlier this plugin will be checked
|
||||||
|
# whether it supports an operation, relative to other plugins.
|
||||||
|
global activate: function(p: PluginState, priority: int);
|
||||||
|
|
||||||
|
# ###
|
||||||
|
# ### High-level API.
|
||||||
|
# ###
|
||||||
|
|
||||||
|
## Stops all packets involving an IP address from being forwarded.
|
||||||
|
##
|
||||||
|
## a: The address to be dropped.
|
||||||
|
##
|
||||||
|
## t: How long to drop it, with 0 being indefinitly.
|
||||||
|
##
|
||||||
|
## location: An optional string describing where the drop was triggered.
|
||||||
|
##
|
||||||
|
## Returns: True if a plugin accepted the rule for carrying it out.
|
||||||
|
global drop_address: function(a: addr, t: interval, location: string &default="") : bool;
|
||||||
|
|
||||||
|
## Stops forwarding a uni-directional flow's packets to Bro.
|
||||||
|
##
|
||||||
|
## f: The flow to shunt.
|
||||||
|
##
|
||||||
|
## t: How long to leave the shunt in place, with 0 being indefinitly.
|
||||||
|
##
|
||||||
|
## location: An optional string describing where the shunt was triggered.
|
||||||
|
##
|
||||||
|
## Returns: True if a plugin accepted the rule for carrying it out.
|
||||||
|
global shunt_flow: function(f: flow_id, t: interval, location: string &default="") : bool;
|
||||||
|
|
||||||
|
## Removes all rules and notifications for an entity.
|
||||||
|
##
|
||||||
|
## e: The entity. Note that this will be directly to entities of existing
|
||||||
|
## notifications and notifications, which must match exactly field by field.
|
||||||
|
global reset: function(e: Entity);
|
||||||
|
|
||||||
|
## Flushes all state.
|
||||||
|
global clear: function();
|
||||||
|
|
||||||
|
# ###
|
||||||
|
# ### Low-level API.
|
||||||
|
# ###
|
||||||
|
|
||||||
|
###### Manipulation of rules.
|
||||||
|
|
||||||
|
## Installs a rule.
|
||||||
|
##
|
||||||
|
## r: The rule to install.
|
||||||
|
##
|
||||||
|
## Returns: If succesful, returns an ID string unique to the rule that can later
|
||||||
|
## be used to refer to it. If unsuccessful, returns an empty string. The ID is also
|
||||||
|
## assigned to ``r$id``. Note that "successful" means "a plugin knew how to handle
|
||||||
|
## the rule", it doesn't necessarily mean that it was indeed successfully put in
|
||||||
|
## place, because that might happen asynchronously and thus fail only later.
|
||||||
|
global add_rule: function(r: Rule) : string;
|
||||||
|
|
||||||
|
## Removes a rule.
|
||||||
|
##
|
||||||
|
## id: The rule to remove, specified as the ID returned by :bro:id:`add_rule` .
|
||||||
|
##
|
||||||
|
## Returns: True if succesful, the relevant plugin indicated that ity knew how
|
||||||
|
## to handle the removal. Note that again "success" means the plugin accepted the
|
||||||
|
## removal. They might still fail to put it into effect, as that might happen
|
||||||
|
## asynchronously and thus go wrong at that point.
|
||||||
|
global remove_rule: function(id: string) : bool;
|
||||||
|
|
||||||
|
###### Asynchronous feedback on rules.
|
||||||
|
|
||||||
|
## Confirms that a rule was put in place.
|
||||||
|
##
|
||||||
|
## r: The rule now in place.
|
||||||
|
##
|
||||||
|
## plugin: The name of the plugin that put it into place.
|
||||||
|
##
|
||||||
|
## msg: An optional informational message by the plugin.
|
||||||
|
global rule_added: event(r: Rule, p: PluginState, msg: string &default="");
|
||||||
|
|
||||||
|
## Reports that a rule was removed due to a remove: function() call.
|
||||||
|
##
|
||||||
|
## r: The rule now removed.
|
||||||
|
##
|
||||||
|
## plugin: The name of the plugin that had the rule in place and now
|
||||||
|
## removed it.
|
||||||
|
##
|
||||||
|
## msg: An optional informational message by the plugin.
|
||||||
|
global rule_removed: event(r: Rule, p: PluginState, msg: string &default="");
|
||||||
|
|
||||||
|
## Reports that a rule was removed internally due to a timeout.
|
||||||
|
##
|
||||||
|
## r: The rule now removed.
|
||||||
|
##
|
||||||
|
## plugin: The name of the plugin that had the rule in place and now
|
||||||
|
## removed it.
|
||||||
|
##
|
||||||
|
## msg: An optional informational message by the plugin.
|
||||||
|
global rule_timeout: event(r: Rule, p: PluginState);
|
||||||
|
|
||||||
|
## Reports an error when operating on a rule.
|
||||||
|
##
|
||||||
|
## r: The rule that encountered an error.
|
||||||
|
##
|
||||||
|
## plugin: The name of the plugin that reported the error.
|
||||||
|
##
|
||||||
|
## msg: An optional informational message by the plugin.
|
||||||
|
global rule_error: event(r: Rule, p: PluginState, msg: string &default="");
|
||||||
|
|
||||||
|
## Installs a notification.
|
||||||
|
##
|
||||||
|
## n: The notification to install.
|
||||||
|
##
|
||||||
|
## Returns: If succesful, returns an ID string unique to the notification that can later
|
||||||
|
## be used to refer to it. If unsuccessful, returns an empty string. The ID is also
|
||||||
|
## assigned to ``r$id``. Note that "successful" means "a plugin knew how to handle
|
||||||
|
## the notification", it doesn't necessarily mean that it was indeed successfully put in
|
||||||
|
## place, because that might happen asynchronously and thus fail only later.
|
||||||
|
global add_notification: function(n: Notification) : string;
|
||||||
|
|
||||||
|
## Removes a notification.
|
||||||
|
##
|
||||||
|
## id: The notification to remove, specified as the ID returned by :bro:id:`add_notification` .
|
||||||
|
##
|
||||||
|
## Returns: True if succesful, the relevant plugin indicated that ity knew how
|
||||||
|
## to handle the removal. Note that again "success" means the plugin accepted the
|
||||||
|
## removal. They might still fail to put it into effect, as that might happen
|
||||||
|
## asynchronously and thus go wrong at that point.
|
||||||
|
global remove_notification: function(id: string) : bool;
|
||||||
|
|
||||||
|
###### Asynchronous feedback on notifications.
|
||||||
|
|
||||||
|
## Confirms that a notification was put in place.
|
||||||
|
##
|
||||||
|
## n: The notification now in place.
|
||||||
|
##
|
||||||
|
## plugin: The name of the plugin that put it into place.
|
||||||
|
##
|
||||||
|
## msg: An optional informational message by the plugin.
|
||||||
|
global notification_added: event(n: Notification, p: PluginState, msg: string &default="");
|
||||||
|
|
||||||
|
## Reports that a notification was removed due to a remove: function() call.
|
||||||
|
##
|
||||||
|
## n: The notification now removed.
|
||||||
|
##
|
||||||
|
## plugin: The name of the plugin that had the notification in place and now
|
||||||
|
## removed it.
|
||||||
|
##
|
||||||
|
## msg: An optional informational message by the plugin.
|
||||||
|
global notification_removed: event(n: Notification, p: PluginState, msg: string &default="");
|
||||||
|
|
||||||
|
## Reports that a notification was removed internally due to a timeout.
|
||||||
|
##
|
||||||
|
## n: The notification now removed.
|
||||||
|
##
|
||||||
|
## plugin: The name of the plugin that had the notification in place and now
|
||||||
|
## removed it.
|
||||||
|
##
|
||||||
|
## msg: An optional informational message by the plugin.
|
||||||
|
global notification_timeout: event(n: Notification, p: PluginState);
|
||||||
|
|
||||||
|
## Reports an error when operating on a notification.
|
||||||
|
##
|
||||||
|
## n: The notification that encountered an error.
|
||||||
|
##
|
||||||
|
## plugin: The name of the plugin that reported the error.
|
||||||
|
##
|
||||||
|
## msg: An optional informational message by the plugin.
|
||||||
|
global notification_error: event(n: Notification, p: PluginState, msg: string &default="");
|
||||||
|
|
||||||
|
## Type of an entry in the PACF log.
|
||||||
|
type InfoCategory: enum {
|
||||||
|
## A log entry reflecting a framework message.
|
||||||
|
MESSAGE,
|
||||||
|
## A log entry reflecting a framework message.
|
||||||
|
ERROR,
|
||||||
|
## A log entry about about a rule.
|
||||||
|
RULE,
|
||||||
|
## A log entry about about a notification.
|
||||||
|
NOTIFICATION
|
||||||
|
};
|
||||||
|
|
||||||
|
## State of an entry in the PACF log.
|
||||||
|
type InfoState: enum {
|
||||||
|
REQUESTED,
|
||||||
|
SUCCEEDED,
|
||||||
|
FAILED,
|
||||||
|
REMOVED,
|
||||||
|
TIMEOUT,
|
||||||
|
};
|
||||||
|
|
||||||
|
## The record type which contains column fields of the PACF log.
|
||||||
|
type Info: record {
|
||||||
|
## Time at which the recorded activity occurred.
|
||||||
|
ts: time &log;
|
||||||
|
## Type of the log entry.
|
||||||
|
category: InfoCategory &log &optional;
|
||||||
|
## The command the log entry is about.
|
||||||
|
cmd: string &log &optional;
|
||||||
|
## State the log entry reflects.
|
||||||
|
state: InfoState &log &optional;
|
||||||
|
## String describing an action the entry is about.
|
||||||
|
action: string &log &optional;
|
||||||
|
## The target type of the action.
|
||||||
|
target: TargetType &log &optional;
|
||||||
|
## Type of the entity the log entry is about.
|
||||||
|
entity_type: string &log &optional;
|
||||||
|
## String describing the entity the log entry is about.
|
||||||
|
entity: string &log &optional;
|
||||||
|
## String with an additional message.
|
||||||
|
msg: string &log &optional;
|
||||||
|
## Logcation where the underlying action was triggered.
|
||||||
|
location: string &log &optional;
|
||||||
|
## Plugin triggering the log entry.
|
||||||
|
plugin: string &log &optional;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
redef record Rule += {
|
||||||
|
##< Internally set to the plugin handling the rule.
|
||||||
|
_plugin: PluginState &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
global plugins: vector of PluginState;
|
||||||
|
global rule_counter: count = 0;
|
||||||
|
global rules: table[string] of Rule;
|
||||||
|
|
||||||
|
event bro_init() &priority=5
|
||||||
|
{
|
||||||
|
Log::create_stream(Pacf::LOG, [$columns=Info]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function entity_to_info(info: Info, e: Entity)
|
||||||
|
{
|
||||||
|
info$entity_type = fmt("%s", e$ty);
|
||||||
|
|
||||||
|
switch ( e$ty ) {
|
||||||
|
case ADDRESS, ORIGINATOR, RESPONDER:
|
||||||
|
info$entity = fmt("%s", e$ip);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONNECTION:
|
||||||
|
info$entity = fmt("%s/%d<->%s/%d",
|
||||||
|
e$conn$orig_h, e$conn$orig_p,
|
||||||
|
e$conn$resp_h, e$conn$resp_p);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FLOW:
|
||||||
|
info$entity = fmt("%s/%d->%s/%d",
|
||||||
|
e$flow$src_h, e$flow$src_p,
|
||||||
|
e$flow$dst_h, e$flow$dst_p);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAC:
|
||||||
|
info$entity = e$mac;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
info$entity = "<unknown entity type>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rule_to_info(info: Info, r: Rule)
|
||||||
|
{
|
||||||
|
info$action = fmt("%s", r$ty);
|
||||||
|
info$target = r$target;
|
||||||
|
|
||||||
|
if ( r?$location )
|
||||||
|
info$location = r$location;
|
||||||
|
|
||||||
|
entity_to_info(info, r$entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_msg(msg: string, p: PluginState)
|
||||||
|
{
|
||||||
|
Log::write(LOG, [$ts=network_time(), $category=MESSAGE, $msg=msg, $plugin=p$plugin$name(p)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_error(msg: string, p: PluginState)
|
||||||
|
{
|
||||||
|
Log::write(LOG, [$ts=network_time(), $category=ERROR, $msg=msg, $plugin=p$plugin$name(p)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_rule(r: Rule, cmd: string, state: InfoState, p: PluginState)
|
||||||
|
{
|
||||||
|
local info: Info = [$ts=network_time()];
|
||||||
|
info$category = RULE;
|
||||||
|
info$cmd = cmd;
|
||||||
|
info$state = state;
|
||||||
|
info$plugin = p$plugin$name(p);
|
||||||
|
|
||||||
|
rule_to_info(info, r);
|
||||||
|
|
||||||
|
Log::write(LOG, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_rule_error(r: Rule, msg: string, p: PluginState)
|
||||||
|
{
|
||||||
|
local info: Info = [$ts=network_time(), $category=ERROR, $msg=msg, $plugin=p$plugin$name(p)];
|
||||||
|
rule_to_info(info, r);
|
||||||
|
Log::write(LOG, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_rule_no_plugin(r: Rule, state: InfoState, msg: string)
|
||||||
|
{
|
||||||
|
local info: Info = [$ts=network_time()];
|
||||||
|
info$category = RULE;
|
||||||
|
info$state = state;
|
||||||
|
info$msg = msg;
|
||||||
|
|
||||||
|
rule_to_info(info, r);
|
||||||
|
|
||||||
|
Log::write(LOG, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
function activate(p: PluginState, priority: int)
|
||||||
|
{
|
||||||
|
p$_priority = priority;
|
||||||
|
plugins[|plugins|] = p;
|
||||||
|
sort(plugins, function(p1: PluginState, p2: PluginState) : int { return p2$_priority - p1$_priority; });
|
||||||
|
|
||||||
|
log_msg(fmt("activated plugin with priority %d", priority), p);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drop_address(a: addr, t: interval, location: string &default="") : bool
|
||||||
|
{
|
||||||
|
local e: Entity = [$ty=ADDRESS, $ip=addr_to_subnet(a)];
|
||||||
|
local r: Rule = [$ty=DROP, $target=FORWARD, $entity=e, $expire=t, $location=location];
|
||||||
|
|
||||||
|
local id = add_rule(r);
|
||||||
|
return |id| > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function shunt_flow(f: flow_id, t: interval, location: string &default="") : bool
|
||||||
|
{
|
||||||
|
local e: Entity = [$ty=FLOW, $flow=f];
|
||||||
|
local r: Rule = [$ty=DROP, $target=MONITOR, $entity=e, $expire=t, $location=location];
|
||||||
|
|
||||||
|
local id = add_rule(r);
|
||||||
|
return |id| > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset(e: Entity)
|
||||||
|
{
|
||||||
|
print "Pacf::reset not implemented yet";
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear()
|
||||||
|
{
|
||||||
|
print "Pacf::clear not implemented yet";
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_rule(r: Rule) : string
|
||||||
|
{
|
||||||
|
r$id = fmt("%d", ++rule_counter);
|
||||||
|
|
||||||
|
for ( i in plugins )
|
||||||
|
{
|
||||||
|
local p = plugins[i];
|
||||||
|
|
||||||
|
if ( p$plugin$add_rule(p, r) )
|
||||||
|
{
|
||||||
|
r$_plugin = p;
|
||||||
|
log_rule(r, "ADD", REQUESTED, p);
|
||||||
|
return r$id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_rule_no_plugin(r, FAILED, "not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_rule(id: string) : bool
|
||||||
|
{
|
||||||
|
local r = rules[id];
|
||||||
|
local p = r$_plugin;
|
||||||
|
|
||||||
|
if ( ! p$plugin$remove_rule(r$_plugin, r) )
|
||||||
|
{
|
||||||
|
log_rule_error(r, "remove failed", p);
|
||||||
|
return F;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_rule(r, "REMOVE", REQUESTED, p);
|
||||||
|
return T;
|
||||||
|
}
|
||||||
|
|
||||||
|
event rule_expire(r: Rule, p: PluginState)
|
||||||
|
{
|
||||||
|
if ( r$id !in rules )
|
||||||
|
# Remove already.
|
||||||
|
return;
|
||||||
|
|
||||||
|
event rule_timeout(r, p);
|
||||||
|
remove_rule(r$id);
|
||||||
|
}
|
||||||
|
|
||||||
|
event rule_added(r: Rule, p: PluginState, msg: string &default="")
|
||||||
|
{
|
||||||
|
log_rule(r, "ADD", SUCCEEDED, p);
|
||||||
|
|
||||||
|
rules[r$id] = r;
|
||||||
|
|
||||||
|
if ( r?$expire && ! p$plugin$can_expire )
|
||||||
|
schedule r$expire { rule_expire(r, p) };
|
||||||
|
}
|
||||||
|
|
||||||
|
event rule_removed(r: Rule, p: PluginState, msg: string &default="")
|
||||||
|
{
|
||||||
|
delete rules[r$id];
|
||||||
|
log_rule(r, "REMOVE", SUCCEEDED, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
event rule_timeout(r: Rule, p: PluginState)
|
||||||
|
{
|
||||||
|
delete rules[r$id];
|
||||||
|
log_rule(r, "EXPIRE", TIMEOUT, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
event rule_error(r: Rule, p: PluginState, msg: string &default="")
|
||||||
|
{
|
||||||
|
log_rule_error(r, msg, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_notification(n: Notification) : string
|
||||||
|
{
|
||||||
|
print "Pacf::add_notification not implemented yet";
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_notification(id: string) : bool
|
||||||
|
{
|
||||||
|
print "Pacf::remove_notification not implemented yet";
|
||||||
|
}
|
||||||
|
|
||||||
|
event notification_added(n: Notification, p: PluginState, msg: string &default="")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
event notification_removed(n: Notification, p: PluginState, msg: string &default="")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
event notification_timeout(n: Notification, p: PluginState)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
event notification_error(n: Notification, p: PluginState, msg: string &default="")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
91
scripts/base/frameworks/pacf/plugin.bro
Normal file
91
scripts/base/frameworks/pacf/plugin.bro
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
|
||||||
|
module Pacf;
|
||||||
|
|
||||||
|
@load ./types
|
||||||
|
|
||||||
|
export {
|
||||||
|
## State for a plugin instance.
|
||||||
|
type PluginState: record {
|
||||||
|
## Table for a plugin to store custom, instance-specfific state.
|
||||||
|
config: table[string] of string &default=table();
|
||||||
|
|
||||||
|
## Set internally.
|
||||||
|
_priority: int &default=+0;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Definitioan of a plugin.
|
||||||
|
#
|
||||||
|
# Generally a plugin needs to implement only what it can support. By
|
||||||
|
# returning failure, it indicates that it can't support something and the
|
||||||
|
# the framework will then try another plugin, if available; or informn the
|
||||||
|
# that the operation failed. If a function isn't implemented by a plugin,
|
||||||
|
# that's considered an implicit failure to support the operation.
|
||||||
|
#
|
||||||
|
# If plugin accepts a rule operation, it *must* generate one of the reporting
|
||||||
|
# events ``rule_{added,remove,error}`` to signal if it indeed worked out;
|
||||||
|
# this is separate from accepting the operation because often a plugin
|
||||||
|
# will only know later (i.e., asynchrously) if that was an error for
|
||||||
|
# something it thought it could handle. The same applies to notifications,
|
||||||
|
# with the corresponding ``notification_*`` events.
|
||||||
|
type Plugin: record {
|
||||||
|
# Returns a descriptive name of the plugin instance, suitable for use in logging
|
||||||
|
# messages. Note that this function is not optional.
|
||||||
|
name: function(state: PluginState) : string;
|
||||||
|
|
||||||
|
## If true, plugin can expire rules/notifications itself. If false,
|
||||||
|
## framework will manage rule expiration.
|
||||||
|
can_expire: bool;
|
||||||
|
|
||||||
|
# One-time initialization functionl called when plugin gets registered, and
|
||||||
|
# befire any ther methods are called.
|
||||||
|
init: function(state: PluginState) &optional;
|
||||||
|
|
||||||
|
# One-time finalization function called when a plugin is shutdown; no further
|
||||||
|
# functions will be called afterwords.
|
||||||
|
done: function(state: PluginState) &optional;
|
||||||
|
|
||||||
|
# Implements the add_rule() operation. If the plugin accepts the rule,
|
||||||
|
# it returns true, false otherwise. The rule will already have its
|
||||||
|
# ``id`` field set, which the plugin may use for identification
|
||||||
|
# purposes.
|
||||||
|
add_rule: function(state: PluginState, r: Rule) : bool &optional;
|
||||||
|
|
||||||
|
# Implements the remove_rule() operation. This will only be called for
|
||||||
|
# rules that the plugins has previously accepted with add_rule(). The
|
||||||
|
# ``id`` field will match that of the add_rule() call. Generally,
|
||||||
|
# a plugin that accepts an add_rule() should also accept the
|
||||||
|
# remove_rule().
|
||||||
|
remove_rule: function(state: PluginState, r: Rule) : bool &optional;
|
||||||
|
|
||||||
|
# Implements the add_notification() operation. If the plugin accepts the notification,
|
||||||
|
# it returns true, false otherwise. The notification will already have its
|
||||||
|
# ``id`` field set, which the plugin may use for identification
|
||||||
|
# purposes.
|
||||||
|
add_notification: function(state: PluginState, r: Notification) : bool &optional;
|
||||||
|
|
||||||
|
# Implements the remove_notification() operation. This will only be called for
|
||||||
|
# notifications that the plugins has previously accepted with add_notification().
|
||||||
|
# The ``id`` field will match that of the add_notification() call. Generally,
|
||||||
|
# a plugin that accepts an add_notification() should also accept the
|
||||||
|
# remove_notification().
|
||||||
|
remove_notification: function(state: PluginState, r: Notification) : bool &optional;
|
||||||
|
|
||||||
|
# A transaction groups a number of operations. The plugin can add them internally
|
||||||
|
# and postpone putting them into effect until committed. This allows to build a
|
||||||
|
# configuration of multiple rules at once, including replaying a previous state.
|
||||||
|
transaction_begin: function(state: PluginState) &optional;
|
||||||
|
transaction_end: function(state: PluginState) &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Table for a plugin to store instance-specific configuration information.
|
||||||
|
#
|
||||||
|
# Note, it would be nicer to pass the Plugin instance to all the below, instead
|
||||||
|
# of this state table. However Bro's type resolver has trouble with refering to a
|
||||||
|
# record type from inside itself.
|
||||||
|
redef record PluginState += {
|
||||||
|
## The plugin that the state belongs to. (Defined separately
|
||||||
|
## because of cyclic type dependency.)
|
||||||
|
plugin: Plugin &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
1
scripts/base/frameworks/pacf/plugins/__load__.bro
Normal file
1
scripts/base/frameworks/pacf/plugins/__load__.bro
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@load ./debug
|
119
scripts/base/frameworks/pacf/plugins/debug.bro
Normal file
119
scripts/base/frameworks/pacf/plugins/debug.bro
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
|
||||||
|
@load ../plugin
|
||||||
|
|
||||||
|
module Pacf;
|
||||||
|
|
||||||
|
export {
|
||||||
|
## Instantiates a debug plugin for the PACF framework. The debug
|
||||||
|
## plugin simply logs the operations it receives.
|
||||||
|
##
|
||||||
|
## do_something: If true, the plugin will claim it supports all operations; if
|
||||||
|
## false, it will indicate it doesn't support any.
|
||||||
|
global create_debug: function(do_something: bool) : PluginState;
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_something(p: PluginState) : bool
|
||||||
|
{
|
||||||
|
return p$config["all"] == "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_name(p: PluginState) : string
|
||||||
|
{
|
||||||
|
return fmt("Debug-%s", (do_something(p) ? "All" : "None"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_log(p: PluginState, msg: string)
|
||||||
|
{
|
||||||
|
print fmt("pacf debug (%s): %s", debug_name(p), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_init(p: PluginState)
|
||||||
|
{
|
||||||
|
debug_log(p, "init");
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_done(p: PluginState)
|
||||||
|
{
|
||||||
|
debug_log(p, "init");
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_add_rule(p: PluginState, r: Rule) : bool
|
||||||
|
{
|
||||||
|
local s = fmt("add_rule: %s", r);
|
||||||
|
debug_log(p, s);
|
||||||
|
|
||||||
|
if ( do_something(p) )
|
||||||
|
{
|
||||||
|
event Pacf::rule_added(r, p);
|
||||||
|
return T;
|
||||||
|
}
|
||||||
|
|
||||||
|
return F;
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_remove_rule(p: PluginState, r: Rule) : bool
|
||||||
|
{
|
||||||
|
local s = fmt("remove_rule: %s", r);
|
||||||
|
debug_log(p, s);
|
||||||
|
|
||||||
|
event Pacf::rule_removed(r, p);
|
||||||
|
return T;
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_add_notification(p: PluginState, r: Notification) : bool
|
||||||
|
{
|
||||||
|
local s = fmt("add_notification: %s", r);
|
||||||
|
debug_log(p, s);
|
||||||
|
|
||||||
|
if ( do_something(p) )
|
||||||
|
{
|
||||||
|
event Pacf::notification_added(r, p);
|
||||||
|
return T;
|
||||||
|
}
|
||||||
|
|
||||||
|
return F;
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_remove_notification(p: PluginState, r: Notification) : bool
|
||||||
|
{
|
||||||
|
local s = fmt("remove_notification: %s", r);
|
||||||
|
debug_log(p, s);
|
||||||
|
|
||||||
|
return do_something(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_transaction_begin(p: PluginState)
|
||||||
|
{
|
||||||
|
debug_log(p, "transaction_begin");
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug_transaction_end(p: PluginState)
|
||||||
|
{
|
||||||
|
debug_log(p, "transaction_end");
|
||||||
|
}
|
||||||
|
|
||||||
|
global debug_plugin = Plugin(
|
||||||
|
$name=debug_name,
|
||||||
|
$can_expire = F,
|
||||||
|
$init = debug_init,
|
||||||
|
$done = debug_done,
|
||||||
|
$add_rule = debug_add_rule,
|
||||||
|
$remove_rule = debug_remove_rule,
|
||||||
|
$add_notification = debug_add_notification,
|
||||||
|
$remove_notification = debug_remove_notification,
|
||||||
|
$transaction_begin = debug_transaction_begin,
|
||||||
|
$transaction_end = debug_transaction_end
|
||||||
|
);
|
||||||
|
|
||||||
|
function create_debug(do_something: bool) : PluginState
|
||||||
|
{
|
||||||
|
local p: PluginState = [$plugin=debug_plugin];
|
||||||
|
|
||||||
|
# FIXME: Why's the default not working?
|
||||||
|
p$config = table();
|
||||||
|
p$config["all"] = (do_something ? "1" : "0");
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
122
scripts/base/frameworks/pacf/types.bro
Normal file
122
scripts/base/frameworks/pacf/types.bro
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
|
||||||
|
module Pacf;
|
||||||
|
|
||||||
|
export {
|
||||||
|
## Type of a :bro:id:`Entity` for defining an action.
|
||||||
|
type EntityType: enum {
|
||||||
|
ADDRESS, ##< Activity involving a specific IP address.
|
||||||
|
ORIGINATOR, ##< Activity *from* a source IP address.
|
||||||
|
RESPONDER, ##< Activity *to* a destination IP address.
|
||||||
|
CONNECTION, ##< All of a bi-directional connection's activity.
|
||||||
|
FLOW, ##< All of a uni-directional flow's activity.
|
||||||
|
MAC, ##< Activity involving a MAC address.
|
||||||
|
};
|
||||||
|
|
||||||
|
## Type defining the enity an :bro:id:`Rule` is operating on.
|
||||||
|
type Entity: record {
|
||||||
|
ty: EntityType; ##< Type of entity.
|
||||||
|
conn: conn_id &optional; ##< Used with :bro:id:`CONNECTION` .
|
||||||
|
flow: flow_id &optional; ##< Used with :bro:id:`FLOW` .
|
||||||
|
ip: subnet &optional; ##< Used with :bro:id:`ORIGINATOR`/:bro:id:`RESPONDER`/:bro:id:`ADDRESS`; can specifiy a CIDR subnet.
|
||||||
|
mac: string &optional; ##< Used with :bro:id:`MAC` .
|
||||||
|
};
|
||||||
|
|
||||||
|
## Target of :bro:id:`Rule` action.
|
||||||
|
type TargetType: enum {
|
||||||
|
FORWARD, #< Apply rule actively to traffic on forwarding path.
|
||||||
|
MONITOR, #< Apply rule passively to traffic sent to Bro for monitoring.
|
||||||
|
};
|
||||||
|
|
||||||
|
## Type of rules that the framework supports. Each type lists the
|
||||||
|
## :bro:id:`Rule` argument(s) it uses, if any.
|
||||||
|
##
|
||||||
|
## Plugins may extend this type to define their own.
|
||||||
|
type RuleType: enum {
|
||||||
|
## Stop forwarding all packets matching entity.
|
||||||
|
##
|
||||||
|
## No arguments.
|
||||||
|
DROP,
|
||||||
|
|
||||||
|
## Begin rate-limiting flows matching entity.
|
||||||
|
##
|
||||||
|
## d: Percent of available bandwidth.
|
||||||
|
LIMIT,
|
||||||
|
|
||||||
|
## Begin modifying all packets matching entity.
|
||||||
|
##
|
||||||
|
## .. todo::
|
||||||
|
## Define arguments.
|
||||||
|
MODIFY,
|
||||||
|
|
||||||
|
## Begin redirecting all packets matching entity.
|
||||||
|
##
|
||||||
|
## .. todo::
|
||||||
|
## Define arguments.
|
||||||
|
REDIRECT,
|
||||||
|
|
||||||
|
## Begin sampling all flows matching entity.
|
||||||
|
##
|
||||||
|
## d: Probability to include a flow between 0 and 1.
|
||||||
|
SAMPLE,
|
||||||
|
|
||||||
|
## Whitelists all packets of an entity, meaning no restrictions will be applied.
|
||||||
|
## While whitelisting is the default if no rule matches an this can type can be
|
||||||
|
## used to override lower-priority rules that would otherwise take effect for the
|
||||||
|
## entity.
|
||||||
|
WHITELIST,
|
||||||
|
};
|
||||||
|
|
||||||
|
## A rule for the framework to put in place. Of all rules currently in
|
||||||
|
## place, the first match will be taken, sorted by priority. All
|
||||||
|
## further riles will be ignored.
|
||||||
|
type Rule: record {
|
||||||
|
ty: RuleType; ##< Type of rule.
|
||||||
|
target: TargetType; ##< Where to apply rule.
|
||||||
|
entity: Entity; ##< Entity to apply rule to.
|
||||||
|
expire: interval &optional; ##< Timeout after which to expire the rule.
|
||||||
|
priority: int &default=+0; ##< Priority if multiple rules match an entity (larger value is higher priority).
|
||||||
|
location: string &optional; ##< Optional string describing where/what installed the rule.
|
||||||
|
|
||||||
|
i: int &optional; ##< Argument for rule types requiring an integer argument.
|
||||||
|
d: double &optional; ##< Argument for rule types requiring a double argument.
|
||||||
|
s: string &optional; ##< Argument for rule types requiring a string argument.
|
||||||
|
|
||||||
|
id: string &default=""; ##< Internally determined unique ID for this rule. Will be set when added.
|
||||||
|
};
|
||||||
|
|
||||||
|
## Type of notifications that the framework supports. Each type lists the
|
||||||
|
## :bro:id:`Notification` argument(s) it uses, if any.
|
||||||
|
##
|
||||||
|
## Plugins may extend this type to define their own.
|
||||||
|
type NotificationType: enum {
|
||||||
|
## Notify if threshold of packets has been reached by entity.
|
||||||
|
##
|
||||||
|
## i: Number of packets.
|
||||||
|
NUM_PACKETS,
|
||||||
|
|
||||||
|
## Notify if threshold of bytes has been reached by entity.
|
||||||
|
##
|
||||||
|
## i: Number of bytes.
|
||||||
|
NUM_BYTES,
|
||||||
|
};
|
||||||
|
|
||||||
|
## A notification for the framework to raise when a condition has been reached.
|
||||||
|
## Different than with rules, all matching conditions will be reported, not only
|
||||||
|
## the first match.
|
||||||
|
type Notification: record {
|
||||||
|
ty: NotificationType; ##< Type of notification.
|
||||||
|
entity: Entity; ##< Entity to apply notification to.
|
||||||
|
expire: interval &optional; ##< Timeout after which to expire the notification.
|
||||||
|
src: string &optional; ##< Optional string describing where/what installed the notification.
|
||||||
|
|
||||||
|
i: int; ##< Argument for notification types requiring an integer argument.
|
||||||
|
d: double; ##< Argument for notification types requiring a double argument.
|
||||||
|
s: string; ##< Argument for notification types requiring a string argument.
|
||||||
|
|
||||||
|
id: string &default=""; ##< Internally determined unique ID for this notification. Will be set when added.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,18 @@ type conn_id: record {
|
||||||
resp_p: port; ##< The responder's port number.
|
resp_p: port; ##< The responder's port number.
|
||||||
} &log;
|
} &log;
|
||||||
|
|
||||||
|
## The identifying 4-tuple of a uni-directional flow.
|
||||||
|
##
|
||||||
|
## .. note:: It's actually a 5-tuple: the transport-layer protocol is stored as
|
||||||
|
## part of the port values, `src_p` and `dst_p`, and can be extracted from
|
||||||
|
## them with :bro:id:`get_port_transport_proto`.
|
||||||
|
type flow_id : record {
|
||||||
|
src_h: addr; ##< The source IP address.
|
||||||
|
src_p: port; ##< The source port number.
|
||||||
|
dst_h: addr; ##< The destination IP address.
|
||||||
|
dst_p: port; ##< The desintation port number.
|
||||||
|
};
|
||||||
|
|
||||||
## Specifics about an ICMP conversation. ICMP events typically pass this in
|
## Specifics about an ICMP conversation. ICMP events typically pass this in
|
||||||
## addition to :bro:type:`conn_id`.
|
## addition to :bro:type:`conn_id`.
|
||||||
##
|
##
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
@load base/frameworks/reporter
|
@load base/frameworks/reporter
|
||||||
@load base/frameworks/sumstats
|
@load base/frameworks/sumstats
|
||||||
@load base/frameworks/tunnels
|
@load base/frameworks/tunnels
|
||||||
|
@load base/frameworks/pacf
|
||||||
|
|
||||||
@load base/protocols/conn
|
@load base/protocols/conn
|
||||||
@load base/protocols/dhcp
|
@load base/protocols/dhcp
|
||||||
|
|
13
src/bro.bif
13
src/bro.bif
|
@ -2366,6 +2366,19 @@ function to_subnet%(sn: string%): subnet
|
||||||
return ret;
|
return ret;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
## Converts a :bro:type:`addr` to a :bro:type:`subnet`.
|
||||||
|
##
|
||||||
|
## a: The address to convert.
|
||||||
|
##
|
||||||
|
## Returns: The *sn* string as a :bro:type:`subnet`.
|
||||||
|
##
|
||||||
|
## .. bro:see:: to_subset
|
||||||
|
function addr_to_subnet%(a: addr%): subnet
|
||||||
|
%{
|
||||||
|
int width = (a->AsAddr().GetFamily() == IPv4 ? 32 : 128);
|
||||||
|
return new SubNetVal(a->AsAddr(), width);
|
||||||
|
%}
|
||||||
|
|
||||||
## Converts a :bro:type:`string` to a :bro:type:`double`.
|
## Converts a :bro:type:`string` to a :bro:type:`double`.
|
||||||
##
|
##
|
||||||
## str: The :bro:type:`string` to convert.
|
## str: The :bro:type:`string` to convert.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue