]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
pgsql: add events
authorJuliana Fajardini <jufajardini@gmail.com>
Mon, 17 Feb 2025 15:05:09 +0000 (12:05 -0300)
committerVictor Julien <victor@inliniac.net>
Wed, 19 Feb 2025 08:21:37 +0000 (09:21 +0100)
Events for:
- parsing error when parsing pgsql packet length
- parsing error for pgsql requests (post length parsing)
- parsing error for pgsql responses (post length parsing)
- too many transactions

Include `pgsql-events.rules` file, and PGSQL events SID range definition

Task #5566

rules/README.md
rules/pgsql-events.rules [new file with mode: 0644]
rust/src/pgsql/pgsql.rs

index a2c47f169c3dfc52220d271c2591a185d986743f..93cee89f11607e596579e509a36361333ef9760c 100644 (file)
@@ -29,6 +29,7 @@ signature IDs.
 | QUIC     | 2231000 | 2231999 |
 | FTP      | 2232000 | 2232999 |
 | DNS      | 2240000 | 2240999 |
+| PGSQL    | 2241000 | 2241999 |
 | MODBUS   | 2250000 | 2250999 |
 | DNP3     | 2270000 | 2270999 |
 | HTTP2    | 2290000 | 2290999 |
diff --git a/rules/pgsql-events.rules b/rules/pgsql-events.rules
new file mode 100644 (file)
index 0000000..c193320
--- /dev/null
@@ -0,0 +1,8 @@
+# PGSQL app-layer event rules
+#
+# SID range start: 2241000
+# SID range end:   2241999
+alert pgsql any any -> any any (msg:"SURICATA PGSQL Too many transactions"; app-layer-event:pgsql.too_many_transactions; sid:2241000; rev:1;)
+alert pgsql any any -> any any (msg:"SURICATA PGSQL Malformed request"; app-layer-event:pgsql.malformed_request; flow:to_server; sid:2241001; rev:1;)
+alert pgsql any any -> any any (msg:"SURICATA PGSQL Malformed response"; app-layer-event:pgsql.malformed_response; flow:to_client; sid:2241002; rev:1;)
+alert pgsql any any -> any any (msg:"SURICATA PGSQL Invalid length"; app-layer-event:pgsql.invalid_length; sid:2241003; rev:1;)
index 5b8ad8d88e05e7bba1a63cbf4bc6c8437cee497d..513e24cf7ea9fbbc9b360b198741f063d1e2ca6d 100644 (file)
@@ -27,10 +27,10 @@ use crate::core::{ALPROTO_FAILED, ALPROTO_UNKNOWN, IPPROTO_TCP, *};
 use crate::direction::Direction;
 use crate::flow::Flow;
 use nom7::{Err, IResult};
-use suricata_sys::sys::AppProto;
 use std;
 use std::collections::VecDeque;
 use std::ffi::CString;
+use suricata_sys::sys::AppProto;
 
 pub const PGSQL_CONFIG_DEFAULT_STREAM_DEPTH: u32 = 0;
 
@@ -38,6 +38,14 @@ static mut ALPROTO_PGSQL: AppProto = ALPROTO_UNKNOWN;
 
 static mut PGSQL_MAX_TX: usize = 1024;
 
+#[derive(AppLayerEvent, Debug, PartialEq, Eq)]
+pub enum PgsqlEvent {
+    InvalidLength,     // Can't parse the length field
+    MalformedRequest,  // Enough data, but unexpected request format
+    MalformedResponse, // Enough data, but unexpected response format
+    TooManyTransactions,
+}
+
 #[repr(u8)]
 #[derive(Copy, Clone, PartialOrd, PartialEq, Eq, Debug)]
 pub enum PgsqlTxProgress {
@@ -218,7 +226,9 @@ impl PgsqlState {
                     // when they're parsed, as of now
                     tx_old.tx_req_state = PgsqlTxProgress::TxFlushedOut;
                     tx_old.tx_res_state = PgsqlTxProgress::TxFlushedOut;
-                    //TODO set event
+                    tx_old
+                        .tx_data
+                        .set_event(PgsqlEvent::TooManyTransactions as u8);
                     break;
                 }
             }
@@ -400,15 +410,18 @@ impl PgsqlState {
                     return AppLayerResult::incomplete(consumed as u32, needed_estimation as u32);
                 }
                 Err(Err::Error(err)) => {
+                    let mut tx = self.new_tx();
                     match err {
                         PgsqlParseError::InvalidLength => {
-                            // TODO set event invalid length event
+                            tx.tx_data.set_event(PgsqlEvent::InvalidLength as u8);
+                            self.transactions.push_back(tx);
                             // If we don't get a valid length, we can't know how to proceed
                             return AppLayerResult::err();
                         }
                         PgsqlParseError::NomError(_i, error_kind) => {
                             if error_kind == nom7::error::ErrorKind::Switch {
-                                // TODO set event switch / PgsqlEvent::MalformedData // or something like that
+                                tx.tx_data.set_event(PgsqlEvent::MalformedRequest as u8);
+                                self.transactions.push_back(tx);
                             }
                             SCLogDebug!("Parsing error: {:?}", error_kind);
                         }
@@ -593,15 +606,18 @@ impl PgsqlState {
                     return AppLayerResult::incomplete(consumed as u32, needed_estimation as u32);
                 }
                 Err(Err::Error(err)) => {
+                    let mut tx = self.new_tx();
                     match err {
                         PgsqlParseError::InvalidLength => {
-                            // TODO set event invalid length event
+                            tx.tx_data.set_event(PgsqlEvent::InvalidLength as u8);
+                            self.transactions.push_back(tx);
                             // If we don't get a valid length, we can't know how to proceed
                             return AppLayerResult::err();
                         }
                         PgsqlParseError::NomError(_i, error_kind) => {
                             if error_kind == nom7::error::ErrorKind::Switch {
-                                // TODO set event switch / PgsqlEvent::MalformedData // or something like that
+                                tx.tx_data.set_event(PgsqlEvent::MalformedResponse as u8);
+                                self.transactions.push_back(tx);
                             }
                             SCLogDebug!("Parsing error: {:?}", error_kind);
                         }
@@ -830,8 +846,8 @@ pub unsafe extern "C" fn SCRegisterPgsqlParser() {
         tx_comp_st_ts: PgsqlTxProgress::TxDone as i32,
         tx_comp_st_tc: PgsqlTxProgress::TxDone as i32,
         tx_get_progress: tx_get_al_state_progress,
-        get_eventinfo: None,
-        get_eventinfo_byid: None,
+        get_eventinfo: Some(PgsqlEvent::get_event_info),
+        get_eventinfo_byid: Some(PgsqlEvent::get_event_info_by_id),
         localstorage_new: None,
         localstorage_free: None,
         get_tx_files: None,