]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
ftp: add events for command too long
authorJason Ish <jason.ish@oisf.net>
Fri, 20 Jan 2023 22:12:54 +0000 (16:12 -0600)
committerVictor Julien <vjulien@oisf.net>
Thu, 26 Jan 2023 14:51:54 +0000 (15:51 +0100)
Issue: 5235

rules/Makefile.am
rules/ftp-events.rules [new file with mode: 0644]
rust/cbindgen.toml
rust/src/ftp/event.rs [new file with mode: 0644]
rust/src/ftp/mod.rs
src/app-layer-ftp.c

index 0eaf5be8906c4dd2eddd039198af7abb1f979549..4c0c744c9b8cfba82d56443043175d949a4be018 100644 (file)
@@ -7,6 +7,7 @@ dhcp-events.rules \
 dnp3-events.rules \
 dns-events.rules \
 files.rules \
+ftp-events.rules \
 http-events.rules \
 http2-events.rules \
 ipsec-events.rules \
diff --git a/rules/ftp-events.rules b/rules/ftp-events.rules
new file mode 100644 (file)
index 0000000..d32c93f
--- /dev/null
@@ -0,0 +1,6 @@
+# FTP app-layer event rules
+#
+# SID range start: 2232000
+
+alert ftp any any -> any any (msg:"SURICATA FTP Request command too long"; flow:to_server; app-layer-event:ftp.request_command_too_long; classtype:protocol-command-decode; sid:2232000; rev:1;)
+alert ftp any any -> any any (msg:"SURICATA FTP Response command too long"; flow:to_client; app-layer-event:ftp.response_command_too_long; classtype:protocol-command-decode; sid:2232001; rev:1;)
index 635b972945fc4824a91e3aeb8db04cdf412080f5..15c56e2e7da2b6b376f87c6c5ff61de854c37a14 100644 (file)
@@ -80,7 +80,8 @@ include = [
     "ModbusState",
     "CMark",
     "QuicState",
-    "QuicTransaction"
+    "QuicTransaction",
+    "FtpEvent",
 ]
 
 # A list of items to not include in the generated bindings
diff --git a/rust/src/ftp/event.rs b/rust/src/ftp/event.rs
new file mode 100644 (file)
index 0000000..04cc9e3
--- /dev/null
@@ -0,0 +1,50 @@
+/* Copyright (C) 2023 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.
+ */
+
+use crate::core::AppLayerEventType;
+use std::os::raw::{c_char, c_int};
+
+#[derive(Debug, PartialEq, Eq, AppLayerEvent)]
+#[repr(C)]
+pub enum FtpEvent {
+    #[name("request_command_too_long")]
+    FtpEventRequestCommandTooLong,
+    #[name("response_command_too_long")]
+    FtpEventResponseCommandTooLong,
+}
+
+/// Wrapper around the Rust generic function for get_event_info.
+///
+/// # Safety
+/// Unsafe as called from C.
+#[no_mangle]
+pub unsafe extern "C" fn ftp_get_event_info(
+    event_name: *const c_char, event_id: *mut c_int, event_type: *mut AppLayerEventType,
+) -> c_int {
+    crate::applayer::get_event_info::<FtpEvent>(event_name, event_id, event_type)
+}
+
+/// Wrapper around the Rust generic function for get_event_info_by_id.
+///
+/// # Safety
+/// Unsafe as called from C.
+#[no_mangle]
+pub unsafe extern "C" fn ftp_get_event_info_by_id(
+    event_id: c_int, event_name: *mut *const c_char, event_type: *mut AppLayerEventType,
+) -> c_int {
+    crate::applayer::get_event_info_by_id::<FtpEvent>(event_id, event_name, event_type) as c_int
+}
index 4c01b78dc118d2168492d8c707d0b51550e180c0..1a60ca470c34d5eb634bca16f0da339e3ce84d8e 100644 (file)
@@ -24,6 +24,8 @@ use std;
 use std::str;
 use std::str::FromStr;
 
+pub mod event;
+
 // We transform an integer string into a i64, ignoring surrounding whitespaces
 // We look for a digit suite, and try to convert it.
 // If either str::from_utf8 or FromStr::from_str fail,
index 2857e02b55d99bd61941b62f214780ede154ced5..4f7ed0b16baf56e7d85ba877e26555b6de8f30bf 100644 (file)
@@ -323,6 +323,10 @@ static void FTPTransactionFree(FTPTransaction *tx)
         FTPStringFree(str);
     }
 
+    if (tx->tx_data.events) {
+        AppLayerDecoderEventsFreeEvents(&tx->tx_data.events);
+    }
+
     FTPFree(tx, sizeof(*tx));
 }
 
@@ -526,6 +530,10 @@ static AppLayerResult FTPParseRequest(Flow *f, void *ftp_state, AppLayerParserSt
         tx->request_length = CopyCommandLine(&tx->request, &line);
         tx->request_truncated = state->current_line_truncated;
 
+        if (tx->request_truncated) {
+            AppLayerDecoderEventsSetEventRaw(&tx->tx_data.events, FtpEventRequestCommandTooLong);
+        }
+
         /* change direction (default to server) so expectation will handle
          * the correct message when expectation will match.
          * For ftp active mode, data connection direction is opposite to
@@ -761,6 +769,10 @@ static AppLayerResult FTPParseResponse(Flow *f, void *ftp_state, AppLayerParserS
             if (likely(response)) {
                 response->len = CopyCommandLine(&response->str, &line);
                 response->truncated = state->current_line_truncated;
+                if (response->truncated) {
+                    AppLayerDecoderEventsSetEventRaw(
+                            &tx->tx_data.events, FtpEventResponseCommandTooLong);
+                }
                 TAILQ_INSERT_TAIL(&tx->response_list, response, next);
             }
         }
@@ -1334,6 +1346,9 @@ void RegisterFTPParsers(void)
         AppLayerParserRegisterStateProgressCompletionStatus(
                 ALPROTO_FTPDATA, FTPDATA_STATE_FINISHED, FTPDATA_STATE_FINISHED);
 
+        AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_FTP, ftp_get_event_info);
+        AppLayerParserRegisterGetEventInfoById(IPPROTO_TCP, ALPROTO_FTP, ftp_get_event_info_by_id);
+
         sbcfg.buf_size = 4096;
         sbcfg.Calloc = FTPCalloc;
         sbcfg.Realloc = FTPRealloc;