]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
dcerpc: add probe function
authorShivani Bhardwaj <shivanib134@gmail.com>
Sat, 20 Feb 2021 06:32:28 +0000 (12:02 +0530)
committerVictor Julien <victor@inliniac.net>
Fri, 26 Feb 2021 09:42:50 +0000 (10:42 +0100)
(cherry picked from commit 3641f1b52256b7eb289048d6b83e660fe4907aaf)

rust/src/dcerpc/dcerpc.rs
rust/src/dcerpc/dcerpc_udp.rs
src/app-layer-dcerpc-udp.c
src/app-layer-dcerpc.c

index 70786abe02ee8b0d724fe445009c03b876229a01..bfd39956d42d6c7986b034d00c8eb57f1ed4cfe2 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 use std::mem::transmute;
-use crate::applayer::{AppLayerResult, AppLayerTxData};
+use crate::applayer::*;
 use crate::core::{self, sc_detect_engine_state_free};
 use crate::dcerpc::parser;
 use nom::error::ErrorKind;
@@ -1323,6 +1323,46 @@ pub unsafe extern "C" fn rs_dcerpc_get_stub_data(
     *endianness = tx.get_endianness();
 }
 
+/// Probe input to see if it looks like DCERPC.
+fn probe(input: &[u8]) -> (bool, bool) {
+    match parser::parse_dcerpc_header(input) {
+        Ok((_, hdr)) => {
+            let is_request = hdr.hdrtype == 0x00;
+            let is_dcerpc = hdr.rpc_vers == 0x05 && hdr.rpc_vers_minor == 0x00;
+            return (is_dcerpc, is_request);
+        },
+        Err(_) => (false, false),
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_probe_tcp(direction: u8, input: *const u8,
+                                      len: u32, rdir: *mut u8) -> i32
+{
+    SCLogDebug!("Probing packet for DCERPC");
+    if len == 0 {
+        return core::ALPROTO_UNKNOWN;
+    }
+    let slice: &[u8] = unsafe {
+        std::slice::from_raw_parts(input as *mut u8, len as usize)
+    };
+    //is_incomplete is checked by caller
+    let (is_dcerpc, is_request, ) = probe(slice);
+    if is_dcerpc {
+        let dir = if is_request {
+            core::STREAM_TOSERVER
+        } else {
+            core::STREAM_TOCLIENT
+        };
+        if direction & (core::STREAM_TOSERVER|core::STREAM_TOCLIENT) != dir {
+            unsafe { *rdir = dir };
+        }
+        return 1;
+    }
+    return 0;
+
+}
+
 #[cfg(test)]
 mod tests {
     use crate::applayer::AppLayerResult;
index 14a09be94b4aa929c4ea1e054d54182fd3639680..0f86404048af1b7c37a7b1262f6279fe94302f2f 100644 (file)
@@ -289,6 +289,47 @@ pub extern "C" fn rs_dcerpc_udp_get_tx_cnt(vtx: *mut std::os::raw::c_void) -> u6
     dce_state.tx_id
 }
 
+/// Probe input to see if it looks like DCERPC.
+fn probe(input: &[u8]) -> (bool, bool) {
+    match parser::parse_dcerpc_udp_header(input) {
+        Ok((_, hdr)) => {
+            let is_request = hdr.pkt_type == 0x00;
+            let is_dcerpc = hdr.rpc_vers == 0x04;
+            return (is_dcerpc, is_request);
+        },
+        Err(_) => (false, false),
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_probe_udp(direction: u8, input: *const u8,
+                                      len: u32, rdir: *mut u8) -> i32
+{
+    SCLogDebug!("Probing the packet for DCERPC/UDP");
+    if len == 0 {
+        return core::ALPROTO_UNKNOWN;
+    }
+    let slice: &[u8] = unsafe {
+        std::slice::from_raw_parts(input as *mut u8, len as usize)
+    };
+    //is_incomplete is checked by caller
+    let (is_dcerpc, is_request) = probe(slice);
+    if is_dcerpc {
+        let dir = if is_request {
+            core::STREAM_TOSERVER
+        } else {
+            core::STREAM_TOCLIENT
+        };
+        if direction & (core::STREAM_TOSERVER|core::STREAM_TOCLIENT) != dir {
+            unsafe { *rdir = dir };
+        }
+        return 1;
+    }
+    return 0;
+
+}
+
+
 #[cfg(test)]
 mod tests {
     use crate::applayer::AppLayerResult;
index d38378ae070e37e6bc636505c501b900e61cbc1d..b784865ba447f0c5d6c478c5e2c7ccdefadcb33e 100644 (file)
@@ -102,11 +102,27 @@ static int RustDCERPCUDPGetAlstateProgress(void *tx, uint8_t direction)
     return rs_dcerpc_get_alstate_progress(tx, direction);
 }
 
+static uint16_t DCERPCUDPProbe(
+        Flow *f, uint8_t direction, const uint8_t *input, uint32_t len, uint8_t *rdir)
+{
+    SCLogDebug("DCERPCUDPProbe");
+
+    const int r = rs_dcerpc_probe_udp(direction, input, len, rdir);
+    switch (r) {
+        case 1:
+            return ALPROTO_DCERPC;
+        case 0:
+            return ALPROTO_UNKNOWN;
+        case -1:
+        default:
+            return ALPROTO_FAILED;
+    }
+}
+
 static int DCERPCUDPRegisterPatternsForProtocolDetection(void)
 {
-    if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_UDP, ALPROTO_DCERPC,
-            "|04 00|", 2, 0, STREAM_TOSERVER) < 0)
-    {
+    if (AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_UDP, ALPROTO_DCERPC, "|04 00|", 2, 0,
+                STREAM_TOSERVER, DCERPCUDPProbe, 0, 0) < 0) {
         return -1;
     }
 
index 40cd753bf0a2ac9bcf5551ddbf342de87b55f1b0..82700b1cdda247d136747b53fff4d16fd45253a1 100644 (file)
@@ -126,16 +126,31 @@ static int DCERPCGetAlstateProgress(void *tx, uint8_t direction)
     return rs_dcerpc_get_alstate_progress(tx, direction);
 }
 
+static uint16_t DCERPCTCPProbe(
+        Flow *f, uint8_t direction, const uint8_t *input, uint32_t len, uint8_t *rdir)
+{
+    SCLogDebug("DCERPCTCPProbe");
+
+    const int r = rs_dcerpc_probe_tcp(direction, input, len, rdir);
+    switch (r) {
+        case 1:
+            return ALPROTO_DCERPC;
+        case 0:
+            return ALPROTO_UNKNOWN;
+        case -1:
+        default:
+            return ALPROTO_FAILED;
+    }
+}
+
 static int DCERPCRegisterPatternsForProtocolDetection(void)
 {
-    if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC,
-                                               "|05 00|", 2, 0, STREAM_TOSERVER) < 0)
-    {
+    if (AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0,
+                STREAM_TOSERVER, DCERPCTCPProbe, 0, 0) < 0) {
         return -1;
     }
-    if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_DCERPC,
-                                               "|05 00|", 2, 0, STREAM_TOCLIENT) < 0)
-    {
+    if (AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0,
+                STREAM_TOCLIENT, DCERPCTCPProbe, 0, 0) < 0) {
         return -1;
     }