From: Victor Julien Date: Mon, 1 Apr 2019 20:21:06 +0000 (+0200) Subject: nfs: implement midstream reverse flow support X-Git-Tag: suricata-5.0.0-beta1~92 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=822a434036f084bf9ff0380a9e7e925f75346645;p=thirdparty%2Fsuricata.git nfs: implement midstream reverse flow support Register special midstream version of protocol detection that can indicate the flow is the wrong direction based on the record properties. --- diff --git a/rust/src/nfs/nfs.rs b/rust/src/nfs/nfs.rs index d50162deb2..83e1414782 100644 --- a/rust/src/nfs/nfs.rs +++ b/rust/src/nfs/nfs.rs @@ -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 diff --git a/src/app-layer-nfs-tcp.c b/src/app-layer-nfs-tcp.c index 45dbaa5a90..1fe61e2cb2 100644 --- a/src/app-layer-nfs-tcp.c +++ b/src/app-layer-nfs-tcp.c @@ -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); } }