]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
nfs: implement midstream reverse flow support 3765/head
authorVictor Julien <victor@inliniac.net>
Mon, 1 Apr 2019 20:21:06 +0000 (22:21 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 2 Apr 2019 13:05:31 +0000 (15:05 +0200)
Register special midstream version of protocol detection that
can indicate the flow is the wrong direction based on the record
properties.

rust/src/nfs/nfs.rs
src/app-layer-nfs-tcp.c

index d50162deb2d2d09a5800d387fdcc5d3cc1ae0aee..83e141478234986b2b0b1e5788ad82234b30c5fa 100644 (file)
@@ -1794,18 +1794,26 @@ pub fn nfs_probe_udp(i: &[u8], direction: u8) -> i8 {
 
 /// MIDSTREAM
 #[no_mangle]
-pub extern "C" fn rs_nfs_probe_ms(input: *const libc::uint8_t,
+pub extern "C" fn rs_nfs_probe_ms(
+        direction: libc::uint8_t, input: *const libc::uint8_t,
         len: libc::uint32_t, rdir: *mut u8) -> libc::int8_t
 {
-    let slice: &[u8] = unsafe {
-        std::slice::from_raw_parts(input as *mut u8, len as usize)
-    };
-    let mut direction : u8 = 0;
-    match nfs_probe_dir(slice, &mut direction) {
+    let slice: &[u8] = build_slice!(input, len as usize);
+    SCLogDebug!("rs_nfs_probe_ms: probing direction {:02x}", direction);
+    let mut adirection : u8 = 0;
+    match nfs_probe_dir(slice, &mut adirection) {
         1 => {
-            let r = nfs_probe(slice, direction);
+            if adirection == STREAM_TOSERVER {
+                SCLogDebug!("nfs_probe_dir said STREAM_TOSERVER");
+            } else {
+                SCLogDebug!("nfs_probe_dir said STREAM_TOCLIENT");
+            }
+            let r = nfs_probe(slice, adirection);
             if r == 1 {
-                unsafe { *rdir = direction; }
+                SCLogDebug!("nfs_probe success: dir {:02x} adir {:02x}", direction, adirection);
+                if (direction & (STREAM_TOSERVER|STREAM_TOCLIENT)) != adirection {
+                    unsafe { *rdir = adirection; }
+                }
                 return 1;
             }
             return r;
@@ -1819,26 +1827,16 @@ pub extern "C" fn rs_nfs_probe_ms(input: *const libc::uint8_t,
     }
 }
 
-/// TOSERVER probe function
 #[no_mangle]
-pub extern "C" fn rs_nfs_probe_ts(input: *const libc::uint8_t, len: libc::uint32_t)
-                               -> libc::int8_t
-{
-    let slice: &[u8] = unsafe {
-        std::slice::from_raw_parts(input as *mut u8, len as usize)
-    };
-    return nfs_probe(slice, STREAM_TOSERVER);
-}
-
-/// TOCLIENT probe function
-#[no_mangle]
-pub extern "C" fn rs_nfs_probe_tc(input: *const libc::uint8_t, len: libc::uint32_t)
-                               -> libc::int8_t
+pub extern "C" fn rs_nfs_probe(direction: libc::uint8_t,
+        input: *const libc::uint8_t, len: libc::uint32_t)
+    -> libc::int8_t
 {
     let slice: &[u8] = unsafe {
         std::slice::from_raw_parts(input as *mut u8, len as usize)
     };
-    return nfs_probe(slice, STREAM_TOCLIENT);
+    SCLogDebug!("rs_nfs_probe: running probe");
+    return nfs_probe(slice, direction);
 }
 
 /// TOSERVER probe function
index 45dbaa5a909c8040a68988b424cba694fd4e7968..1fe61e2cb2eea4ca36069ac2c2c67d084c634190 100644 (file)
@@ -112,7 +112,7 @@ static AppLayerDecoderEvents *NFSTCPGetEvents(void *state, uint64_t id)
  * \retval ALPROTO_NFS if it looks like echo, otherwise
  *     ALPROTO_UNKNOWN.
  */
-static AppProto NFSTCPProbingParser(Flow *f,
+static AppProto NFSTCPProbingParserMidstream(Flow *f,
         uint8_t direction,
         uint8_t *input, uint32_t input_len,
         uint8_t *rdir)
@@ -121,12 +121,33 @@ static AppProto NFSTCPProbingParser(Flow *f,
         return ALPROTO_UNKNOWN;
     }
 
-    int8_t r = 0;
-    if (direction & STREAM_TOSERVER) {
-        r = rs_nfs_probe_ts(input, input_len);
-    } else {
-        r = rs_nfs_probe_tc(input, input_len);
+    int8_t r = rs_nfs_probe_ms(direction, input, input_len, rdir);
+    if (r == 1) {
+        return ALPROTO_NFS;
+    } else if (r == -1) {
+        return ALPROTO_FAILED;
+    }
+
+    SCLogDebug("Protocol not detected as ALPROTO_NFS.");
+    return ALPROTO_UNKNOWN;
+}
+
+/**
+ * \brief Probe the input to see if it looks like echo.
+ *
+ * \retval ALPROTO_NFS if it looks like echo, otherwise
+ *     ALPROTO_UNKNOWN.
+ */
+static AppProto NFSTCPProbingParser(Flow *f,
+        uint8_t direction,
+        uint8_t *input, uint32_t input_len,
+        uint8_t *rdir)
+{
+    if (input_len < NFSTCP_MIN_FRAME_LEN) {
+        return ALPROTO_UNKNOWN;
     }
+
+    int8_t r = rs_nfs_probe(direction, input, input_len);
     if (r == 1) {
         return ALPROTO_NFS;
     } else if (r == -1) {
@@ -282,10 +303,15 @@ void RegisterNFSTCPParsers(void)
 
         }
         else {
+            int midstream = 0;
+            ConfGetBool("stream.midstream", &midstream);
+            ProbingParserFPtr FuncPtr = NFSTCPProbingParser;
+            if (midstream)
+                FuncPtr = NFSTCPProbingParserMidstream;
 
             if (!AppLayerProtoDetectPPParseConfPorts("tcp", IPPROTO_TCP,
                     proto_name, ALPROTO_NFS, 0, NFSTCP_MIN_FRAME_LEN,
-                    NFSTCPProbingParser, NFSTCPProbingParser)) {
+                    FuncPtr, FuncPtr)) {
                 SCLogDebug("No NFSTCP app-layer configuration, enabling NFSTCP"
                     " detection TCP detection on port %s.",
                     NFSTCP_DEFAULT_PORT);
@@ -293,7 +319,7 @@ void RegisterNFSTCPParsers(void)
                 AppLayerProtoDetectPPRegister(IPPROTO_TCP,
                     NFSTCP_DEFAULT_PORT, ALPROTO_NFS, 0,
                     NFSTCP_MIN_FRAME_LEN, STREAM_TOSERVER,
-                    NFSTCPProbingParser, NFSTCPProbingParser);
+                    FuncPtr, FuncPtr);
             }
 
         }