You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/app-layer-ftp.h

137 lines
3.8 KiB
C

/* Copyright (C) 2007-2025 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
* \author Jeff Lucovsky <jeff@lucovsky.org>
*/
#ifndef SURICATA_APP_LAYER_FTP_H
#define SURICATA_APP_LAYER_FTP_H
#include "rust.h"
#include "app-layer-parser.h"
struct FtpCommand;
typedef uint32_t FtpRequestCommandArgOfs;
/** used to hold the line state when we have fragmentation. */
typedef struct FtpLineState_ {
/** used to indicate if the current_line buffer is a malloced buffer. We
* use a malloced buffer, if a line is fragmented */
const uint8_t *buf;
uint32_t len;
uint8_t delim_len;
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
/** the line was longer than the configured maximum and buf holds only
* what fit; set by the line getter for the line it hands back */
bool truncated;
} FtpLineState;
typedef struct FTPResponseWrapper_ {
FTPResponseLine *response;
TAILQ_ENTRY(FTPResponseWrapper_) next;
} FTPResponseWrapper;
/*
* These are the values for the table index value and the FTP command
* enum value. These *should* be the same if the enum and command insertion
* order remain the same. However, we store each value to protect against
* drift between enum and insertion order.
*/
typedef struct FtpCommandInfo_ {
uint8_t command_index;
FtpRequestCommand command_code;
} FtpCommandInfo;
typedef struct FTPTransaction_ {
/** id of this tx, starting at 0 */
uint64_t tx_id;
AppLayerTxData tx_data;
/* for the request */
uint32_t request_length;
uint8_t *request;
bool request_truncated;
/* for the command description */
FtpCommandInfo command_descriptor;
uint16_t dyn_port; /* dynamic port, if applicable */
bool done; /* transaction complete? */
bool active; /* active or passive mode */
uint8_t direction;
/* Handle multiple responses */
TAILQ_HEAD(, FTPResponseWrapper_) response_list;
TAILQ_ENTRY(FTPTransaction_) next;
} FTPTransaction;
/** FTP State for app layer parser */
typedef struct FtpState_ {
bool active;
FTPTransaction *curr_tx;
TAILQ_HEAD(, FTPTransaction_) tx_list; /**< transaction list */
uint64_t tx_cnt;
bool current_line_truncated_ts;
bool current_line_truncated_tc;
FtpRequestCommand command;
FtpRequestCommandArgOfs arg_offset;
uint32_t port_line_len;
uint32_t port_line_size;
uint8_t *port_line;
uint16_t dyn_port;
AppLayerStateData state_data;
} FtpState;
/** FTP Data State for app layer parser */
typedef struct FtpDataState_ {
uint8_t *input;
uint8_t *file_name;
FileContainer *files;
int32_t input_len;
int16_t file_len;
FtpRequestCommand command;
uint8_t state;
uint8_t direction;
AppLayerTxData tx_data;
AppLayerStateData state_data;
bool initialized;
} FtpDataState;
void RegisterFTPParsers(void);
void FTPParserRegisterTests(void);
void FTPParserCleanup(void);
int FTPSetMemcap(uint64_t size);
uint64_t FTPMemuseGlobalCounter(void);
uint64_t FTPMemcapGlobalCounter(void);
uint16_t JsonGetNextLineFromBuffer(const char *buffer, const uint16_t len);
bool EveFTPDataAddMetadata(const void *vtx, void *jb);
#endif /* SURICATA_APP_LAYER_FTP_H */