From: Jeff Lucovsky Date: Fri, 25 Apr 2025 14:47:47 +0000 (-0400) Subject: detect/ftp: Add ftp.mode command X-Git-Tag: suricata-8.0.0-rc1~292 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=ddb4361432f499396a0ee736bf5071ea451a24af;p=thirdparty%2Fsuricata.git detect/ftp: Add ftp.mode command Issue: 7505 This commit adds support for the ftp.mode keyword. ftp.mode: active|passive --- diff --git a/src/Makefile.am b/src/Makefile.am index 8c4db1df66..47c123798b 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -180,6 +180,7 @@ noinst_HEADERS = \ detect-ftp-reply.h \ detect-ftpbounce.h \ detect-ftpdata.h \ + detect-ftp-mode.h \ detect-geoip.h \ detect-gid.h \ detect-hostbits.h \ @@ -770,6 +771,7 @@ libsuricata_c_a_SOURCES = \ detect-ftp-reply.c \ detect-ftpbounce.c \ detect-ftpdata.c \ + detect-ftp-mode.c \ detect-geoip.c \ detect-gid.c \ detect-hostbits.c \ diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 49d34ce5f9..b60555d590 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -213,6 +213,7 @@ #include "detect-entropy.h" #include "detect-ftp-command-data.h" #include "detect-ftp-reply.h" +#include "detect-ftp-mode.h" #include "detect-bypass.h" #include "detect-ftpdata.h" @@ -726,6 +727,7 @@ void SigTableSetup(void) DetectFtpCommandRegister(); DetectFtpCommandDataRegister(); DetectFtpReplyRegister(); + DetectFtpModeRegister(); DetectBypassRegister(); DetectConfigRegister(); diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index 1f714e4b46..5f9053e777 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -331,6 +331,7 @@ enum DetectKeywordId { DETECT_FTP_COMMAND, DETECT_FTP_COMMAND_DATA, DETECT_FTP_REPLY, + DETECT_FTP_MODE, DETECT_VLAN_ID, DETECT_VLAN_LAYERS, diff --git a/src/detect-ftp-mode.c b/src/detect-ftp-mode.c new file mode 100644 index 0000000000..1f4124e67d --- /dev/null +++ b/src/detect-ftp-mode.c @@ -0,0 +1,142 @@ +/* Copyright (C) 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. + */ + +/** + * + * \author Jeff Lucovsky + * + * Implements the ftp.mode sticky buffer + * + */ + +#include "suricata-common.h" + +#include "detect.h" +#include "detect-parse.h" +#include "detect-engine.h" + +#include "rust.h" +#include "flow.h" + +#include "util-debug.h" + +#include "app-layer.h" +#include "app-layer-ftp.h" + +#include "detect-ftp-mode.h" + +#define KEYWORD_NAME "ftp.mode" +#define KEYWORD_DOC "ftp-keywords.html#ftp-mode" +#define BUFFER_NAME "ftp.mode" +#define BUFFER_DESC "ftp mode" + +static int g_ftp_mode_buffer_id = 0; + +/** + * \brief This function is used to check matches from the FTP App Layer Parser + * + * \param t pointer to thread vars + * \param det_ctx pointer to the pattern matcher thread + * \param p pointer to the current packet + * \param m pointer to the sigmatch + * \retval 0 no match + * \retval 1 match + */ +static int DetectFtpModeMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, + void *txv, const Signature *s, const SigMatchCtx *m) +{ + FTPTransaction *tx = (FTPTransaction *)txv; + if (tx->command_descriptor.command_code == FTP_COMMAND_UNKNOWN) { + return 0; + } + if (!tx->dyn_port) { + return 0; + } + + const DetectFtpModeData *ftpmoded = (const DetectFtpModeData *)m; + return ftpmoded->active == tx->active; +} + +/** + * \brief this function will free memory associated with DetectFtpModeData + * + * \param ptr pointer to DetectFtpModeData + */ +static void DetectFtpModeFree(DetectEngineCtx *de_ctx, void *ptr) +{ + SCFTPFreeModeData(ptr); +} + +/** + * \brief This function is used to parse ftp.mode options passed via ftp.mode keyword + * + * \param str Pointer to the user provided ftp.mode options + * + * \retval pointer to DetectFtpModeData on success + * \retval NULL on failure + */ +static DetectFtpModeData *DetectFtpModeParse(const char *optstr) +{ + DetectFtpModeData *ftpmoded = SCFTPParseMode(optstr); + if (unlikely(ftpmoded == NULL)) { + SCLogError("Invalid command value"); + return NULL; + } + + return ftpmoded; +} + +static int DetectFtpModeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str) +{ + if (DetectSignatureSetAppProto(s, ALPROTO_FTP) != 0) + return -1; + + DetectFtpModeData *ftpmoded = DetectFtpModeParse(str); + if (ftpmoded == NULL) + return -1; + + if (SigMatchAppendSMToList(de_ctx, s, DETECT_FTP_MODE, (SigMatchCtx *)ftpmoded, + g_ftp_mode_buffer_id) == NULL) { + DetectFtpModeFree(de_ctx, ftpmoded); + return -1; + } + + return 0; +} + +void DetectFtpModeRegister(void) +{ + /* ftp.mode sticky buffer */ + sigmatch_table[DETECT_FTP_MODE].name = KEYWORD_NAME; + sigmatch_table[DETECT_FTP_MODE].desc = "sticky buffer to match on the FTP mode buffer"; + sigmatch_table[DETECT_FTP_MODE].url = "/rules/" KEYWORD_DOC; + sigmatch_table[DETECT_FTP_MODE].Setup = DetectFtpModeSetup; + sigmatch_table[DETECT_FTP_MODE].AppLayerTxMatch = DetectFtpModeMatch; + sigmatch_table[DETECT_FTP_MODE].Free = DetectFtpModeFree; + + DetectAppLayerInspectEngineRegister( + BUFFER_NAME, ALPROTO_FTP, SIG_FLAG_TOCLIENT, 0, DetectEngineInspectGenericList, NULL); + + DetectAppLayerInspectEngineRegister( + BUFFER_NAME, ALPROTO_FTP, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL); + + DetectBufferTypeSetDescriptionByName(BUFFER_NAME, BUFFER_DESC); + + g_ftp_mode_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME); + + SCLogDebug("registering " BUFFER_NAME " rule option"); +} diff --git a/src/detect-ftp-mode.h b/src/detect-ftp-mode.h new file mode 100644 index 0000000000..35f36ca5ce --- /dev/null +++ b/src/detect-ftp-mode.h @@ -0,0 +1,29 @@ +/* Copyright (C) 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 Jeff Lucovsky + */ + +#ifndef SURICATA_DETECT_FTP_MODE_H +#define SURICATA_DETECT_FTP_MODE_H + +void DetectFtpModeRegister(void); + +#endif /* SURICATA_DETECT_FTP_MODE_H */