Commit Graph

201 Commits (5cb7a0d7be0699ee5c3e1cbdfd505c81f8e2597e)

Author SHA1 Message Date
Jason Ish 9451642a28 eve: fix C logger signatures for generic callbacks
Several C loggers are registered through a cast to
EveJsonSimpleTxLogFunc, which has an incompatible signature. Clang's
function sanitizer reports this as a call through a pointer to an
incorrect function type.

Change these loggers to the generic callback signature and register them
without casts.

Ticket: 9226
1 week ago
Philippe Antoine 6b8aa7e7b6 src: do not have util-memcmp.h in suricata-common.h
Let every user include it directly

Ticket: 945
3 weeks ago
Philippe Antoine 999582b149 app-layer: standardize includes with iwyu
Ticket: 945
4 weeks ago
Philippe Antoine 79fd1826ef ftp: exclude imap from probing parser
Ticket: 8265
1 month ago
Jeff Lucovsky 46fce26900 ftp: a too-long line drops the rest of the stream slice
Both parse loops stopped as soon as a command or reply reached the
configured maximum length: they advanced the input cursor past the end and
broke out. When that line ended with an LF in the same stream slice it was
already complete, and the bytes behind the LF were ordinary FTP lines that
the break discarded. A segment holding "PORT <long>\r\nQUIT\r\n" lost the
QUIT: it never became a transaction, so inspection and logging never saw
it, and a hidden RETR or PORT never reached AppLayerExpectationCreate,
leaving its data connection unrecognized as ftp-data.

Remove both breaks so the loop continues to the next line. The cursor
assignment goes with them, since nothing reads it once the loop ends, and a
line with no LF still finishes the slice on its own because the getter
zeroes the remaining length.

Removing the breaks is not enough for a line that never reaches the clear.
Truncation was cleared deep inside command and reply handling, which is
skipped for an unrecognized request command, a reply the parser rejects (a
run of spaces, empty once trimmed), or an invalid EPRT/PORT that jumps to
tx_complete. The connection flag then stayed set and the getter dropped the
line behind it as this line's remainder. Snapshot and clear the flag up
front in both loops, for every line whose LF was consumed, so the following
line survives.

Issue: 8884
2 months ago
Jeff Lucovsky 60dc5d0e75 ftp: mark truncation on the line, not the connection
The truncation flag lived in FtpState, where the line getter set it and
the two callers cleared it once FtpLineState.lf_found said the line had
ended. The callers reuse one FtpLineState for every line in a slice, and
only the LF branch ever set lf_found, so a complete line left it set for
whatever came after. An over-long line behind a complete one in the same
slice therefore had its truncation state cleared, its remainder was parsed
as ordinary traffic, and a "PASS s3cret" sitting in that remainder became
a transaction of its own.

The flag could just as easily be left set. The request loop reached its
clear only for a line that matched an FTP command, continuing to the next
line otherwise, so an over-long run of "Z" left the flag standing and the
next command to arrive was discarded as that line's remainder. The
response loop's clear sat three ifs deep, inside blocks entered only when
the reply parsed, so a line that SCFTPParseResponseLine rejects -- a run
of spaces is empty once trimmed -- left it standing too.

The getter also raised the flag for a line whose LF it had just consumed.
Nothing of that line remained to discard, so the caller had to clear it
straight back.

Truncation is a property of the line, so FtpLineState now carries it. The
getter sets line.truncated for the line it hands back, and the FtpState
flag stays set only where truncation genuinely spans slices: the over-long
line that arrives without an LF. The callers read line.truncated and no
longer touch the shared state, so lf_found goes away entirely.

Issue: 8859
2 months ago
Jeff Lucovsky 7564d4d5a9 ftp: keep parsing after a truncated line's LF
When a command or reply runs past the configured maximum length, the
parser keeps what fits, reports it truncated, and discards the remainder
of that line as it arrives. Only the remainder should go, but the parser
was discarding the whole stream slice that the line's LF landed in.

A slice holding "<remainder>\r\nQUIT\r\n" carries a complete QUIT behind
the remainder, and a response slice carries whatever reply comes next. The
recovery branch zeroed the remaining length and returned an error, which
ended the caller's parse loop, so those lines were discarded along with
the remainder they followed. They never became transactions, so nothing
inspected them and nothing logged them, which means a command can be
hidden by placing it after an over-long one.

Consume through the first LF, clear the truncation state there, and pick
up the next line in the same slice. The scan becomes a loop so the
remainder goes through the ordinary path, including when it is over-long
itself; the run-out-of-input check becomes the loop condition.

Raised in review of the 8859 fix.

Issue: 8859
2 months ago
Jeff Lucovsky 2e8d50a9bd ftp: point truncated lines at the unconsumed remainder
When a line exceeds the configured maximum length and contains no LF,
FTPGetLineForDirection emitted a window starting at the beginning of the
stream slice rather than at the unconsumed remainder. If a complete
command had already been taken from the same slice, that window was
shifted left by the consumed count: it began inside the previous command
and stopped short of the end of the long one.

The command MPM match, the per-transaction request copy and the port_line
capture all ran over those stale bytes, so a long command hidden behind a
short one in the same segment was classified and logged as the previous
command. The response direction had the same problem.

The LF-found branch already derives the line from input->buf + o_consumed;
do the same here, and advance consumed so the cursor still describes the
slice it was handed.

Issue: 8859
2 months ago
Jeff Lucovsky b06c134b5d ftp: strip trailing whitespace before allocating
CopyCommandLine allocated a buffer for the whole request line, stripped
the trailing whitespace and returned the shorter length. That shorter
length is what the caller stores in tx->request_length and what
FTPTransactionFree later hands to FTPFree, so one byte for every stripped
whitespace character is never subtracted from ftp_memuse. The memory
itself is released -- SCFree ignores the size it is given -- but the
counter keeps climbing for the life of the process, and a client that
pads its commands with spaces can push it up with every command it sends.

Once the counter reaches app-layer.protocols.ftp.memcap, FTPCheckMemcap
refuses any allocation that would cross it, and request buffers are the
first to be refused: the transaction is still created, but tx->request
stays NULL, so command_data is missing from the log and rules that
inspect it stop matching. Whether a new flow can still allocate its state
depends on how much room is left below the cap. With no memcap
configured, the symptom is an ftp.memuse counter that is permanently
wrong.

Strip the whitespace before allocating, so the size accounted for is the
size returned to the caller:

- CopyCommandLine shortens line->len first, then allocates and copies
  that length.
- A line that is nothing but whitespace returns without allocating. It
  used to get a buffer that was stored on the transaction and freed with
  a length of zero, leaving the whole allocation on the counter.
- When the allocation fails, line->len has already been shortened, so
  port_line, the transfer file name and the too-long-line check see the
  same length there that they see when it succeeds.
- FTPParserTest13 covers the accounting and the stored request;
  FTPParserTest14 covers the line the parser uses afterwards.

Issue: 8848
2 months ago
Philippe Antoine 82c4190558 ftp: do not create more than max-tx transactions
Ticket: 8592

Fixes: 5ddd808e9b ("ftp: don't halt the flow when raising
too_many_transactions")

In the case we receive a big chunk of TCP data, we end up
creating much more than max-tx transactions, and have
quadratic complexity on this packet, even if all
these transactions get cleaned up at the end of the processing
of this packet.
4 months ago
Jason Ish f59960d42b ftp: support STOU data transfers
Support STOU on the FTP data channel.

With STOU a filename is optional. If no filname is provided, use
"<stou>". The server does respond with the filename to use, but there
can be a race condition in getting this filename and setting up file
storage before data starts flowing.

Ticket: #8664
4 months ago
Jason Ish e65bf4c905 ftp: support APPE data transfers
Support the APPE (append) command on the ftp data channel. Like STOR,
APPE uploads file content on the data channel.

Ticket: #8664
4 months ago
Jason Ish 5856ced29c ftp: support LIST and MLSD data channels
Support LIST and MLSD on the ftp data channel.

Ticket: #8664
4 months ago
Jason Ish 1b289daea3 ftp: support nlst on the data channel
Ticket: #8664
4 months ago
Philippe Antoine 52490b8c26 ftp: do not error the flow on file before port
Ticket: 8659

If a client sends a SOTR/RETR command before doing a PASV/PORT
command, ther server may reply
425 Use PORT or PASV first.\r\n
and allow the client to continue sendinf other commands

So, Suricata should not put the whole flow into error, it just
sets an event, and continues to parse further
4 months ago
Jason Ish d346e469c5 ftp: skip ts inspection on tc only transactions
In FTP, the first transaction is a banner from the server. Skip TS
inspection on this transaction.

Allows firewall mode to get past this transaction and onto the next.

Ticket: #8662
4 months ago
Philippe Antoine 94a3e03903 util/mpm: add MpmCtx argument to MpmInitThreadCtx
Ticket: 8001

Will allow algorithms such as ac to use the MpmCtx, especially
the number of patterns, to preallocate some structures.

For detect engine PatternMatchThreadPrepare, create a dummy
MpmCtx out of all the MpmCtx in the DetectEngineCtx,
and get the max value for the number of patterns
5 months ago
Jeff Lucovsky 5ddd808e9b ftp: don't halt the flow when raising too_many_transactions
The first version of the event set done=true on state->curr_tx and
returned NULL when the limit hit. curr_tx is usually the active
command just received — marking it done mid-request throws off
response matching, and subsequent commands in the flow stop getting
logged.

SMB behavior is mirrored here:
Walk the tx list, find the oldest tx that isn't done, mark
it done and tag it with the event, then fall through and
create the new tx so the flow parsing continues. One stale tx gets
reaped per overflow so memory stays bounded.

Issue: 8489
6 months ago
Jeff Lucovsky 9ea2e29581 ftp: raise too_many_transactions event on overflow
Other parsers (SMB, POP3, ENIP) already raise a too_many_transactions
event when a flow exceeds its per-flow transaction limit. FTP had
the limit wired up through app-layer.protocols.ftp.max-tx but just
dropped the excess transaction on the floor with a "FTP does not set
events yet..." TODO, so no event was raised when the limit was
reached.

Add the FtpEventTooManyTransactions variant, a stock rule at
sid 2232002, and raise the event from FTPTransactionCreate when the
live-tx count goes past ftp_config_maxtx.

Issue: 8489
6 months ago
Victor Julien c21275cab3 ftp: fix compile warnings
app-layer-ftp.c:278:14: error: initializing 'uint8_t *' (aka 'unsigned char *') with an expression of type 'const void *' discards qualifiers
      [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
  278 |     uint8_t *lf_idx = memchr(input->buf + input->consumed, 0x0a, input->len);
      |              ^        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
app-layer-ftp.c:1392:11: error: initializing 'char *' with an expression of type 'const char *' discards qualifiers
      [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
 1392 |     char *c = strchr(buffer, '\n');
      |           ^   ~~~~~~~~~~~~~~~~~~~~
2 errors generated.
6 months ago
Philippe Antoine be2d80a8e7 ftp-data: check direction before finished state
Ticket: 6813

So, in the case we have a ftp-data flow with data to client as
expected, but after to_client side completes (with timeout for
example), the client sends some data to server,

In this case, we want to check first the direction, and bail out,
then do the assertion check about the finished state.
6 months ago
Jason Ish 137f59f542 flow/storage: prefix API with SC
In preparation for adding Rust bindings.
7 months ago
Shivani Bhardwaj 4ec5f22951 ftp: trigger raw stream inspection
Internals
---------
Suricata's stream engine returns data for inspection to the detection
engine from the stream when the chunk size is reached.

Bug
---
Inspection triggered only in the specified chunk sizes may be too late
when it comes to inspection of smaller protocol specific data which
could result in delayed inspection, incorrect data logged with a transaction
and logs misindicating the pkt that triggered an alert.

Fix
---
Fix this by making an explicit call from all respective applayer parsers to
trigger raw stream inspection which shall make the data available for inspection
in the following call of the stream engine. This needs to happen per direction
on the completion of an entity like a request or a response.

Important notes
---------------
1. The above mentioned behavior with and without this patch is
affected internally by the following conditions.
- inspection depth
- stream depth
In these special cases, the inspection window will be affected and
Suricata may not consider all the data that could be expected to be
inspected.
2. This only applies to applayer protocols running over TCP.
3. The inspection window is only considered up to the ACK'd data.
4. This entire issue is about IDS mode only.

FTP parser can handle multiple command lines per direction. Appropriate calls
to trigger raw stream inspection have been added on succesful parsing of each
request line and response line.

Bug 7742
7 months ago
Philippe Antoine efcc7f9dfc ftp: remove PASS pattern for protocol detection
As FTP must have USER before PASS command
unlike IRC which can begin by PASS command

Ticket: 2978
7 months ago
Philippe Antoine 4feacfb889 smtp: refine QUIT protocol detection
with probing parser, failing when it is on port 21 as FTP QUIT

Ticket: 6591
9 months ago
Victor Julien cbaff02d66 unittests: clean up memory in ftp tests 1 year ago
Philippe Antoine c52121586a rust: move AppLayerEvents funcs out of RustContext
Ticket: 7667

just use it directly, with bindgen, and cfg not test
1 year ago
Philippe Antoine 573dd2367e rust: bindgen SCFileFlowFlagsToFlags
Ticket: 7667
1 year ago
Philippe Antoine ad0f6e388e src: remove BUG_ON in packet path
Transforms them into debug validations

Ticket: 1484

Packet path is here considered FlowWorker and all lines
covered by SV tests are here fixed
1 year ago
Philippe Antoine 6dbc421825 rust: bindgen AppLayerParserConfParserEnabled
Ticket: 7667
1 year ago
Philippe Antoine 49b2a2be5d rust: bindgen SCAppLayerParserRegisterLogger
Ticket: 7667
1 year ago
Philippe Antoine 7bfef2e1e8 rust: bindgen AppLayerParserRegisterParserAcceptableDataDirection
Ticket: 7667
1 year ago
Philippe Antoine b29d46d81f rust: bindgen SCAppLayerParserStateIssetFlag
Ticket: 7667
1 year ago
Philippe Antoine 249131e9de src: clean includes for app-layer-parser.h
To prepare bindgening
1 year ago
Philippe Antoine 7bb0c94ae9 rust: bindgen app-layer-detect-proto.h
Ticket: 7667
1 year ago
Victor Julien 3c5ce91cbb ftp: per direction tx progress
For request side, having a tx means the request is done.

For response, wait for tx to be marked complete.

Remove unused states.
2 years ago
Jeff Lucovsky 04bf28d6a1 app/ftp: Use common API naming
Modify the Rust API functions to conform to project naming format:
SCFTP*

Issue: 7504
2 years ago
Philippe Antoine f24d3ffb74 ftp: mark tx as updated when creating it
Ticket: 7668

We should set updated_tx when allocating a ftp tx

Was already done right for updated_tc
2 years ago
Jeff Lucovsky fdc43e5ac4 app/ftp: Eliminate scan-build warning
Scan-build reports that FTPRealloc could be called with size=0. Modify
the logic so it's never passed 0.
2 years ago
Jeff Lucovsky d674ce2510 app/ftp: Use Rust FTP response line handling
Use the Rust logic to parse FTP response lines with the goal to support
multi-buffer matches better.

A side effect is that the completion codes are no longer strings; the
schema update reflects this.

Issue: 4082
2 years ago
Jason Ish 155706f96b jsonbuilder: prefix C API with SC 2 years ago
Victor Julien 1542bcdc67 app-layer: add helper for AppLayerTxData cleanup 2 years ago
Lukas Sismis 59c3b8912b util-mpm: prepare MPM codebase for ruleset caching 2 years ago
Jeff Lucovsky dd344bd07c 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.
2 years ago
Jeff Lucovsky f0410c93d0 ftp: convert enumerations to Rust
As part of the effort to convert the FTP/FTPDATA parser to rust, move
the enums from C to rust.

Issue: 4082
2 years ago
Philippe Antoine b02557ac7d app-layer: track modified/processed txs
To optimize detection, and logging, to avoid going through
all the live transactions when only a few were modified.

Two boolean fields are added to the tx data: updated_tc and ts
The app-layer parsers are now responsible to set these when
needed, and the logging and detection uses them to skip
transactions that were not updated.

There may some more optimization remaining by when we set
both updated_tc and updated_ts in functions returning
a mutable transaction, by checking if all the callers
are called in one direction only (request or response)

Ticket: 7087
2 years ago
Jeff Lucovsky b30df19f1a app-layer/stats: Expand memuse/memcap handling
This commit adds memcap/memuse handling to the unix-socket interface:
- ftp
- http-byterange
- host

New stats:
- ippair: memuse, memcap
- host: memuse, memcap
- http-byterange: memuse, memcap
2 years ago
Philippe Antoine 694b2797cd ftp: adds server side detection 2 years ago
Philippe Antoine 5f35035928 filestore: do not try to store a file set to nostore
Ticket: 6390

This can happen with keyword filestore:both,flow
If one direction does not have a signature group with a filestore,
the file is set to nostore on opening, until a signature in
the other direction tries to set it to store.
Subsequent files will be stored in both directions as flow flags
are now set.
2 years ago
Philippe Antoine 0d4efe0c0f app-layer: fix -Wshorten-64-to-32 warnings
Ticket: #6186

Warnings about downcast from 64 to 32 bits
2 years ago