Jeff Lucovsky [Mon, 2 Oct 2023 15:00:46 +0000 (11:00 -0400)]
conf/output: Buffering related config settings
This commit adds 2 EVE output buffering settings
- buffer-size value which specifies the amount of buffering, if any,
for regular/file output types.
- flush-interval Specifies the cadence at which Suricata will direct
detect threads to flush EVE output.
Victor Julien [Mon, 11 Sep 2023 07:22:16 +0000 (07:22 +0000)]
app-layer: optimize pstate check
To assist branch prediction, which showed a 100% miss rate, assume pstate
is non-NULL. Code review suggests all paths leading to the function actually
check pstate first, or alstate which can only be non-NULL if pstate was first
initialized. For now add a debug check.
Jeff Lucovsky [Sun, 2 Feb 2025 16:10:59 +0000 (11:10 -0500)]
ftp: Move config file handling to Rust
Issue: 4082
Move the configuration file handling to Rust.
These changes will no longer terminate Suricata when there's an invalid
value for ftp.memcap. Like earlier Suricata releases, an error message
is logged "Invalid value <value> for ftp.memcap" but Suricata will no
longer terminate execution. It will use a default value of "0" instead.
Philippe Antoine [Thu, 20 Feb 2025 22:36:27 +0000 (23:36 +0100)]
dcerpc: consume bytes after gap resync
Ticket: 7567
After a gap, we search a new record that may start later than
the beginning of current stream slice.
If so, consume the first bytes before the start of the record,
so that AppLayerResult::incomplete can be consistent and not
trigger assertion !((res.needed + res.consumed < input_len))
Philippe Antoine [Fri, 21 Feb 2025 09:38:06 +0000 (10:38 +0100)]
quic: discard late retry packets
Ticket: 7556
See RFC 9000 section 17.2.5.2 :
After the client has received and processed an Initial
or Retry packet from the server,
it MUST discard any subsequent Retry packets that it receives.
Alice Akaki [Thu, 6 Feb 2025 04:16:20 +0000 (00:16 -0400)]
detect: add ldap.responses.dn
ldap.responses.dn matches on LDAPDN from responses operations
This keyword maps the following eve fields:
ldap.responses[].search_result_entry.base_object
ldap.responses[].bind_response.matched_dn
ldap.responses[].search_result_done.matched_dn
ldap.responses[].modify_response.matched_dn
ldap.responses[].add_response.matched_dn
ldap.responses[].del_response.matched_dn
ldap.responses[].mod_dn_response.matched_dn
ldap.responses[].compare_response.matched_dn
ldap.responses[].extended_response.matched_dn
It is a sticky buffer
Supports prefiltering
Alice Akaki [Tue, 4 Feb 2025 02:37:15 +0000 (22:37 -0400)]
detect: add ldap.request.dn
ldap.request.dn matches on LDAPDN from request operations
This keyword maps the following eve fields:
ldap.request.bind_request.name
ldap.request.add_request.entry
ldap.request.search_request.base_object
ldap.request.modify_request.object
ldap.request.del_request.dn
ldap.request.mod_dn_request.entry
ldap.request.compare_request.entry
It is a sticky buffer
Supports prefiltering
Philippe Antoine [Mon, 17 Feb 2025 10:13:20 +0000 (11:13 +0100)]
quic: handle fragmented hello over multiple packets
Ticket: 7556
To do so, we need to add 2 buffers (one for each direction)
to the QuicState structure, so that on parsing the second packet
with hello/crypto fragment, we still have the data of the first
hello/crypto fragment.
Use a hardcoded limit so that these buffers cannot grow indefinitely
and set an event when reaching the limit
This may happen in some situations if the app-layer parser only sees
unknown messages and sets an event: there will be an empty transaction,
but nothing to log.
pgsql/parser: always use fn for parsing PDU length
Some inner parsers were using it, some weren't. Better to standardize
this. Also take the time to avoid magic numbers for representing the
expected lengths for pgsql PDUs.
Also throwing PgsqlParseError and allowing for incomplete results.
Jason Ish [Fri, 24 Jan 2025 15:56:58 +0000 (09:56 -0600)]
rust: add bindings to SCPlugin.* to sys crate
Also disable bindgen's generated layout tests. They are valid for the
platform generating the tests, but may not be valid for other
platforms. For example, if the tests are generated on a 64 bit
platform the tests will not be valid when run on a 32 bit platform as
pointers are a different size.
However, the generating bindings are valid for both platform.
Jason Ish [Fri, 24 Jan 2025 15:05:03 +0000 (09:05 -0600)]
rust: add auto-generated header to sys.rs
We don't keep bindgen's autogenerated do not edit line as it contains
the bindgen version which could break the CI check for out of date
bindings. So add our own do not edit line.
Jason Ish [Thu, 23 Jan 2025 22:26:25 +0000 (16:26 -0600)]
rust: integrate bindgen to generate Rust bindings to C
Bindgen works by processing a header file which includes all other
header files it should generate bindings for. For this I've created
bindgen.h which just includes app-layer-protos.h for now as an
example.
These bindings are then generated and saved in the "suricata-sys"
crate and become availale as "suricata_sys::sys".
Jason Ish [Thu, 23 Jan 2025 22:19:09 +0000 (16:19 -0600)]
rust/sys: stub in suricata-sys crate for Rust bindings to C
Follow Rust convention of using a "sys" crate for bindings to C
functions. The bindings don't exist yet, but will be generated by
bindgen and put into this crate.
Victor Julien [Thu, 13 Feb 2025 13:30:39 +0000 (14:30 +0100)]
tls: more permissive empty data eof check
If not all data is ACK'd during the FIN session shutdown, the last calls
to the parser can be with a non-NULL data pointer, but a input length of
0. This wasn't considered by the EOF check, which then lead to it being
seen as an error. No event was raised, but the tls error stats were
incremented.
In a recent warning reported by scan-build, datasets were found to be
using a blocking call in a critical section.
datasets.c:187:12: warning: Call to blocking function 'fgets' inside of critical section [unix.BlockInCriticalSection]
187 | while (fgets(line, (int)sizeof(line), fp) != NULL) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
datasets.c:292:12: warning: Call to blocking function 'fgets' inside of critical section [unix.BlockInCriticalSection]
292 | while (fgets(line, (int)sizeof(line), fp) != NULL) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
datasets.c:368:12: warning: Call to blocking function 'fgets' inside of critical section [unix.BlockInCriticalSection]
368 | while (fgets(line, (int)sizeof(line), fp) != NULL) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
datasets.c:442:12: warning: Call to blocking function 'fgets' inside of critical section [unix.BlockInCriticalSection]
442 | while (fgets(line, (int)sizeof(line), fp) != NULL) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
datasets.c:512:12: warning: Call to blocking function 'fgets' inside of critical section [unix.BlockInCriticalSection]
512 | while (fgets(line, (int)sizeof(line), fp) != NULL) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 warnings generated.
These calls are blocking in the multi tenant mode where several tenants
may be trying to load the same dataset in parallel.
In a single tenant mode, this operation is performed as a part of a
single thread before the engine startup.
In order to evade the warning and simplify the code, the initial file
reading is moved to Rust with this commit with a much simpler handling
of dataset and datarep.
Jason Ish [Tue, 11 Feb 2025 22:26:39 +0000 (16:26 -0600)]
output-lua: lua module search path configuration
By default, use an empty search path. This gives us a predictable
default. If a user needs access to external modules, the search path
must be set in the configuration file.
Jason Ish [Thu, 30 Jan 2025 16:49:37 +0000 (10:49 -0600)]
base64: expose no padding and padding optional variants
A no padding option is provided as a mode, as its a variant suitable
for encoding and decoding.
A padding optional function is added that is indifferent to padding
when decoding. This can be useful when you're not sure if padding
exists, and don't really care.
Victor Julien [Tue, 21 Jan 2025 19:03:17 +0000 (20:03 +0100)]
lua: add initial suricata.packet lib
Example:
```
local packet = require "suricata.packet"
function init (args)
local needs = {}
return needs
end
function match (args)
p = packet.get()
payload = p:payload()
ts = p:timestring()
for line in payload:gmatch("([^\r\n]*)[\r\n]+") do
if line == "GET /index.html HTTP/1.0" then
ipver, srcip, dstip, proto, sp, dp = p:tuple()
SCLogNotice(string.format("%s %s->%s %d->%d (pcap_cnt:%d) match! %s", ts, srcip, dstip, sp, dp, p:pcap_cnt(), line));
return 1
end
end
return 0
end
```
Methods:
`get` creates the packet object.
`payload` returns the packet payload as a buffer
`packet` returns the whole packet (includes headers)
`pcap_cnt` returns the `pcap_cnt` (pcap file mode only)
`tuple` returns various fields: srcip, dstip, proto, sp, dp
`sp` returns source port
`dp` returns destination port
`timestamp` returns time as 2 numbers: seconds and microseconds
`timestring_legacy` returns a timestamp as a string (like fastlog)
`timestring_iso8601` returns a iso8601 compat timestring (like eve)