Spicy: Provide zeek::skip_input() to disable deliver to current analyzer.

```
## Tells Zeek to skip sending any further input data to the current analyzer.
## This is supported for protocol and file analyzers.
public function skip_input() : void;
```

Closes #3443.
This commit is contained in:
Robin Sommer 2023-11-08 11:39:13 +01:00
parent 9b1f3b5838
commit f5aa5c3466
No known key found for this signature in database
GPG key ID: D8187293B3FFE5D0
8 changed files with 140 additions and 2 deletions

2
doc

@ -1 +1 @@
Subproject commit 278f7b7d0cda1aab5789122d808f411cd05a20fc Subproject commit 7d39602b09f16e1687408b63af3fd6a3edb33d07

View file

@ -118,6 +118,10 @@ public function fuid() : string &cxxname="zeek::spicy::rt::fuid";
## called from inside a protocol analyzer. ## called from inside a protocol analyzer.
public function terminate_session() : void &cxxname="zeek::spicy::rt::terminate_session"; public function terminate_session() : void &cxxname="zeek::spicy::rt::terminate_session";
## Tells Zeek to skip sending any further input data to the current analyzer.
## This is supported for protocol and file analyzers.
public function skip_input() : void &cxxname="zeek::spicy::rt::skip_input";
## Signals the expected size of a file to Zeek's file analysis. ## Signals the expected size of a file to Zeek's file analysis.
## ##
## size: expected size of file ## size: expected size of file

View file

@ -748,6 +748,19 @@ void rt::terminate_session() {
throw spicy::rt::ValueUnavailable("terminate_session() not available in the current context"); throw spicy::rt::ValueUnavailable("terminate_session() not available in the current context");
} }
void rt::skip_input() {
auto _ = hilti::rt::profiler::start("zeek/rt/skip_input");
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());
assert(cookie);
if ( auto p = cookie->protocol )
p->analyzer->SetSkip(true);
else if ( auto f = cookie->file )
f->analyzer->SetSkip(true);
else
throw spicy::rt::ValueUnavailable("skip() not available in the current context");
}
std::string rt::fuid() { std::string rt::fuid() {
auto _ = hilti::rt::profiler::start("zeek/rt/fuid"); auto _ = hilti::rt::profiler::start("zeek/rt/fuid");
auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie()); auto cookie = static_cast<Cookie*>(hilti::rt::context::cookie());

View file

@ -381,7 +381,7 @@ void protocol_handle_close(const ProtocolHandle& handle);
* Signals the beginning of a file to Zeek's file analysis, associating it * Signals the beginning of a file to Zeek's file analysis, associating it
* with the current connection. * with the current connection.
* *
* param mime_type optional mime type passed to Zeek * @param mime_type optional mime type passed to Zeek
* @returns Zeek-side file ID of the new file * @returns Zeek-side file ID of the new file
*/ */
std::string file_begin(const std::optional<std::string>& mime_type); std::string file_begin(const std::optional<std::string>& mime_type);
@ -397,6 +397,12 @@ std::string fuid();
*/ */
void terminate_session(); void terminate_session();
/**
* Tells Zeek to skip sending any further input data to the current protocol
* or file analyzer.
*/
void skip_input();
/** /**
* Signals the expected size of a file to Zeek's file analysis. * Signals the expected size of a file to Zeek's file analysis.
* *

View file

@ -0,0 +1,4 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
1, 12
2, 34
3, 56

View file

@ -0,0 +1,7 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
1, True, 28
event
2, False, 256
event
3, True, 28
event

View file

@ -0,0 +1,60 @@
# @TEST-REQUIRES: have-spicy
#
# @TEST-EXEC: spicyz -d -o test.hlto ssh.spicy ./ssh-cond.evt
# @TEST-EXEC: zeek -r ${TRACES}/ssh/single-conn.trace test.hlto %INPUT Spicy::enable_print=T >output
# @TEST-EXEC: btest-diff output
#
# @TEST-DOC: Validate that `skip_input` works for file analyzers.
# @TEST-START-FILE ssh.spicy
module SSH;
import spicy;
import zeek;
public type Banner = unit {
magic : /SSH-/;
version : /[^-]*/;
dash : /-/;
software: /[^\r\n]*/;
};
type Context = tuple<counter: uint64>;
public type Data = unit {
%context = Context;
: (bytes &size=2)[] foreach {
self.context().counter = self.context().counter + 1;
print self.context().counter, $$;
if ( self.context().counter == 3 )
zeek::skip_input();
}
};
on Banner::%done {
local fid1 = zeek::file_begin("foo/bar");
zeek::file_data_in(b"12", fid1);
zeek::file_data_in(b"34", fid1);
zeek::file_data_in(b"56", fid1);
zeek::file_data_in(b"78", fid1);
zeek::file_data_in(b"90", fid1);
zeek::file_end(fid1);
}
# @TEST-END-FILE
# @TEST-START-FILE ssh-cond.evt
import zeek;
protocol analyzer spicy::SSH over TCP:
parse originator with SSH::Banner,
port 22/tcp,
replaces SSH;
file analyzer spicy::Text:
parse with SSH::Data,
mime-type foo/bar;
# @TEST-END-FILE

View file

@ -0,0 +1,44 @@
# @TEST-REQUIRES: have-spicy
#
# @TEST-EXEC: spicyz -d -o test.hlto test.spicy test.evt
# @TEST-EXEC: zeek -b -r ${TRACES}/dns/long-connection.pcap Zeek::Spicy test.hlto %INPUT "Spicy::enable_print = T;" >output
# @TEST-EXEC: btest-diff output
#
# @TEST-DOC: Validate that `skip_input` works for protocol analyzers.
redef likely_server_ports += { 53/udp }; # avoid flipping direction after termination
redef udp_inactivity_timeout = 24hrs; # avoid long gaps to trigger removal
event Test::foo() { print "event"; }
# @TEST-START-FILE test.spicy
module Test;
import zeek;
type Counter = tuple<counter: int64>;
public type Foo = unit {
%context = Counter;
data: bytes &eod;
on %done {
self.context().counter = self.context().counter + 1;
print self.context().counter, zeek::is_orig(), |self.data|;
if ( self.context().counter == 3 )
zeek::skip_input();
}
};
# @TEST-END-FILE
# @TEST-START-FILE test.evt
protocol analyzer spicy::Test over UDP:
port 53/udp,
parse with Test::Foo;
on Test::Foo -> event Test::foo();
# @TEST-END-FILE