diff --git a/rust/src/nfs/nfs.rs b/rust/src/nfs/nfs.rs index 5bbf8c82e4..98aa5cf5a4 100644 --- a/rust/src/nfs/nfs.rs +++ b/rust/src/nfs/nfs.rs @@ -39,6 +39,7 @@ use crate::nfs::nfs3_records::*; pub static mut SURICATA_NFS_FILE_CONFIG: Option<&'static SuricataFileContext> = None; +static mut ALPROTO_NFS: AppProto = ALPROTO_UNKNOWN; /* * Record parsing. * @@ -1387,14 +1388,17 @@ pub extern "C" fn rs_nfs_state_free(state: *mut std::os::raw::c_void) { /// C binding parse a NFS TCP request. Returns 1 on success, -1 on failure. #[no_mangle] -pub extern "C" fn rs_nfs_parse_request(flow: &mut Flow, - state: &mut NFSState, +pub extern "C" fn rs_nfs_parse_request(flow: *const Flow, + state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void, input: *const u8, input_len: u32, - _data: *mut std::os::raw::c_void) - -> AppLayerResult + _data: *const std::os::raw::c_void, + _flags: u8, + ) -> AppLayerResult { + let state = cast_pointer!(state, NFSState); + let flow = cast_pointer!(flow, Flow); let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)}; SCLogDebug!("parsing {} bytes of request data", input_len); @@ -1412,14 +1416,17 @@ pub extern "C" fn rs_nfs_parse_request_tcp_gap( } #[no_mangle] -pub extern "C" fn rs_nfs_parse_response(flow: &mut Flow, - state: &mut NFSState, +pub extern "C" fn rs_nfs_parse_response(flow: *const Flow, + state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void, input: *const u8, input_len: u32, - _data: *mut std::os::raw::c_void) - -> AppLayerResult + _data: *const std::os::raw::c_void, + _flags: u8, + ) -> AppLayerResult { + let state = cast_pointer!(state, NFSState); + let flow = cast_pointer!(flow, Flow); SCLogDebug!("parsing {} bytes of response data", input_len); let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)}; @@ -1438,46 +1445,52 @@ pub extern "C" fn rs_nfs_parse_response_tcp_gap( /// C binding parse a DNS request. Returns 1 on success, -1 on failure. #[no_mangle] -pub extern "C" fn rs_nfs_parse_request_udp(_flow: *mut Flow, - state: &mut NFSState, +pub extern "C" fn rs_nfs_parse_request_udp(_f: *const Flow, + state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void, input: *const u8, input_len: u32, - _data: *mut std::os::raw::c_void) - -> AppLayerResult + _data: *const std::os::raw::c_void, + _flags: u8) -> AppLayerResult { + let state = cast_pointer!(state, NFSState); + let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)}; SCLogDebug!("parsing {} bytes of request data", input_len); state.parse_udp_ts(buf) } #[no_mangle] -pub extern "C" fn rs_nfs_parse_response_udp(_flow: *mut Flow, - state: &mut NFSState, +pub extern "C" fn rs_nfs_parse_response_udp(_f: *const Flow, + state: *mut std::os::raw::c_void, _pstate: *mut std::os::raw::c_void, input: *const u8, input_len: u32, - _data: *mut std::os::raw::c_void) - -> AppLayerResult + _data: *const std::os::raw::c_void, + _flags: u8) -> AppLayerResult { + let state = cast_pointer!(state, NFSState); + SCLogDebug!("parsing {} bytes of response data", input_len); let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)}; state.parse_udp_tc(buf) } #[no_mangle] -pub extern "C" fn rs_nfs_state_get_tx_count(state: &mut NFSState) +pub extern "C" fn rs_nfs_state_get_tx_count(state: *mut std::os::raw::c_void) -> u64 { + let state = cast_pointer!(state, NFSState); SCLogDebug!("rs_nfs_state_get_tx_count: returning {}", state.tx_id); return state.tx_id; } #[no_mangle] -pub extern "C" fn rs_nfs_state_get_tx(state: &mut NFSState, +pub extern "C" fn rs_nfs_state_get_tx(state: *mut std::os::raw::c_void, tx_id: u64) - -> *mut NFSTransaction + -> *mut std::os::raw::c_void { + let state = cast_pointer!(state, NFSState); match state.get_tx_by_id(tx_id) { Some(tx) => { return unsafe{transmute(tx)}; @@ -1491,11 +1504,15 @@ pub extern "C" fn rs_nfs_state_get_tx(state: &mut NFSState, // for use with the C API call StateGetTxIterator #[no_mangle] pub extern "C" fn rs_nfs_state_get_tx_iterator( - state: &mut NFSState, + _ipproto: u8, + _alproto: AppProto, + state: *mut std::os::raw::c_void, min_tx_id: u64, + _max_tx_id: u64, istate: &mut u64) -> applayer::AppLayerGetTxIterTuple { + let state = cast_pointer!(state, NFSState); match state.get_tx_iterator(min_tx_id, istate) { Some((tx, out_tx_id, has_next)) => { let c_tx = unsafe { transmute(tx) }; @@ -1509,17 +1526,19 @@ pub extern "C" fn rs_nfs_state_get_tx_iterator( } #[no_mangle] -pub extern "C" fn rs_nfs_state_tx_free(state: &mut NFSState, +pub extern "C" fn rs_nfs_state_tx_free(state: *mut std::os::raw::c_void, tx_id: u64) { + let state = cast_pointer!(state, NFSState); state.free_tx(tx_id); } #[no_mangle] -pub extern "C" fn rs_nfs_tx_get_alstate_progress(tx: &mut NFSTransaction, +pub extern "C" fn rs_nfs_tx_get_alstate_progress(tx: *mut std::os::raw::c_void, direction: u8) - -> u8 + -> std::os::raw::c_int { + let tx = cast_pointer!(tx, NFSTransaction); if direction == STREAM_TOSERVER && tx.request_done { //SCLogNotice!("TOSERVER progress 1"); return 1; @@ -1543,17 +1562,20 @@ pub extern "C" fn rs_nfs_get_tx_data( #[no_mangle] pub extern "C" fn rs_nfs_state_set_tx_detect_state( - tx: &mut NFSTransaction, - de_state: &mut DetectEngineState) + tx: *mut std::os::raw::c_void, + de_state: &mut DetectEngineState) -> i32 { + let tx = cast_pointer!(tx, NFSTransaction); tx.de_state = Some(de_state); + 0 } #[no_mangle] pub extern "C" fn rs_nfs_state_get_tx_detect_state( - tx: &mut NFSTransaction) + tx: *mut std::os::raw::c_void) -> *mut DetectEngineState { + let tx = cast_pointer!(tx, NFSTransaction); match tx.de_state { Some(ds) => { SCLogDebug!("{}: getting de_state", tx.id); @@ -1595,11 +1617,13 @@ pub extern "C" fn rs_nfs_state_get_event_info_by_id(event_id: std::os::raw::c_in -1 } } + + #[no_mangle] pub extern "C" fn rs_nfs_state_get_event_info(event_name: *const std::os::raw::c_char, event_id: *mut std::os::raw::c_int, event_type: *mut AppLayerEventType) - -> i8 + -> std::os::raw::c_int { if event_name == std::ptr::null() { return -1; @@ -1693,7 +1717,7 @@ fn nfs_probe_dir(i: &[u8], rdir: *mut u8) -> i8 { } } -pub fn nfs_probe(i: &[u8], direction: u8) -> i8 { +pub fn nfs_probe(i: &[u8], direction: u8) -> i32 { if direction == STREAM_TOCLIENT { match parse_rpc_reply(i) { Ok((_, ref rpc)) => { @@ -1734,7 +1758,7 @@ pub fn nfs_probe(i: &[u8], direction: u8) -> i8 { rpc.program == 100003 && rpc.procedure <= NFSPROC3_COMMIT { - return rpc_auth_type_known(rpc.creds_flavor); + return rpc_auth_type_known(rpc.creds_flavor) as i32; } else { return -1; } @@ -1749,7 +1773,7 @@ pub fn nfs_probe(i: &[u8], direction: u8) -> i8 { } } -pub fn nfs_probe_udp(i: &[u8], direction: u8) -> i8 { +pub fn nfs_probe_udp(i: &[u8], direction: u8) -> i32 { if direction == STREAM_TOCLIENT { match parse_rpc_udp_reply(i) { Ok((_, ref rpc)) => { @@ -1786,8 +1810,9 @@ pub fn nfs_probe_udp(i: &[u8], direction: u8) -> i8 { /// MIDSTREAM #[no_mangle] pub extern "C" fn rs_nfs_probe_ms( + _flow: *const Flow, direction: u8, input: *const u8, - len: u32, rdir: *mut u8) -> i8 + len: u32, rdir: *mut u8) -> AppProto { let slice: &[u8] = build_slice!(input, len as usize); SCLogDebug!("rs_nfs_probe_ms: probing direction {:02x}", direction); @@ -1799,57 +1824,83 @@ pub extern "C" fn rs_nfs_probe_ms( } else { SCLogDebug!("nfs_probe_dir said STREAM_TOCLIENT"); } - let r = nfs_probe(slice, adirection); - if r == 1 { - SCLogDebug!("nfs_probe success: dir {:02x} adir {:02x}", direction, adirection); - if (direction & (STREAM_TOSERVER|STREAM_TOCLIENT)) != adirection { - unsafe { *rdir = adirection; } - } - return 1; + match nfs_probe(slice, adirection) { + 1 => { + SCLogDebug!("nfs_probe success: dir {:02x} adir {:02x}", direction, adirection); + if (direction & (STREAM_TOSERVER|STREAM_TOCLIENT)) != adirection { + unsafe { *rdir = adirection; } + } + unsafe { ALPROTO_NFS } + }, + 0 => { ALPROTO_UNKNOWN }, + _ => { unsafe { ALPROTO_FAILED } }, } - return r; }, 0 => { - return 0; + ALPROTO_UNKNOWN }, _ => { - return -1; + unsafe { ALPROTO_FAILED } } } } #[no_mangle] -pub extern "C" fn rs_nfs_probe(direction: u8, - input: *const u8, len: u32) - -> i8 +pub extern "C" fn rs_nfs_probe(_f: *const Flow, + direction: u8, + input: *const u8, + len: u32, + _rdir: *mut u8) + -> AppProto { let slice: &[u8] = build_slice!(input, len as usize); SCLogDebug!("rs_nfs_probe: running probe"); - return nfs_probe(slice, direction); + match nfs_probe(slice, direction) { + 1 => { unsafe { ALPROTO_NFS } }, + -1 => { unsafe { ALPROTO_FAILED } }, + _ => { ALPROTO_UNKNOWN }, + } } /// TOSERVER probe function #[no_mangle] -pub extern "C" fn rs_nfs_probe_udp_ts(input: *const u8, len: u32) - -> i8 +pub extern "C" fn rs_nfs_probe_udp_ts(_f: *const Flow, + _direction: u8, + input: *const u8, + len: u32, + _rdir: *mut u8) + -> AppProto { let slice: &[u8] = build_slice!(input, len as usize); - return nfs_probe_udp(slice, STREAM_TOSERVER); + match nfs_probe_udp(slice, STREAM_TOSERVER) { + 1 => { unsafe { ALPROTO_NFS } }, + -1 => { unsafe { ALPROTO_FAILED } }, + _ => { ALPROTO_UNKNOWN }, + } } /// TOCLIENT probe function #[no_mangle] -pub extern "C" fn rs_nfs_probe_udp_tc(input: *const u8, len: u32) - -> i8 +pub extern "C" fn rs_nfs_probe_udp_tc(_f: *const Flow, + _direction: u8, + input: *const u8, + len: u32, + _rdir: *mut u8) + -> AppProto { let slice: &[u8] = build_slice!(input, len as usize); - return nfs_probe_udp(slice, STREAM_TOCLIENT); + match nfs_probe_udp(slice, STREAM_TOCLIENT) { + 1 => { unsafe { ALPROTO_NFS } }, + -1 => { unsafe { ALPROTO_FAILED } }, + _ => { ALPROTO_UNKNOWN }, + } } #[no_mangle] -pub extern "C" fn rs_nfs_getfiles(direction: u8, ptr: *mut NFSState) -> * mut FileContainer { +pub extern "C" fn rs_nfs_getfiles(ptr: *mut std::ffi::c_void, direction: u8) -> * mut FileContainer { if ptr.is_null() { panic!("NULL ptr"); }; - let parser = unsafe { &mut *ptr }; + let ptr = cast_pointer!(ptr, NFSState); + let parser = &mut *ptr; parser.getfiles(direction) } #[no_mangle] @@ -1859,3 +1910,4 @@ pub extern "C" fn rs_nfs_setfileflags(direction: u8, ptr: *mut NFSState, flags: SCLogDebug!("direction {} flags {}", direction, flags); parser.setfileflags(direction, flags) } + diff --git a/src/app-layer-nfs-tcp.c b/src/app-layer-nfs-tcp.c index d921db5f98..8599e04922 100644 --- a/src/app-layer-nfs-tcp.c +++ b/src/app-layer-nfs-tcp.c @@ -100,7 +100,7 @@ static AppProto NFSTCPProbingParserMidstream(Flow *f, return ALPROTO_UNKNOWN; } - int8_t r = rs_nfs_probe_ms(direction, input, input_len, rdir); + int8_t r = rs_nfs_probe_ms(f, direction, input, input_len, rdir); if (r == 1) { return ALPROTO_NFS; } else if (r == -1) { @@ -126,7 +126,7 @@ static AppProto NFSTCPProbingParser(Flow *f, return ALPROTO_UNKNOWN; } - int8_t r = rs_nfs_probe(direction, input, input_len); + int8_t r = rs_nfs_probe(f, direction, input, input_len, rdir); if (r == 1) { return ALPROTO_NFS; } else if (r == -1) { @@ -148,8 +148,8 @@ static AppLayerResult NFSTCPParseRequest(Flow *f, void *state, AppLayerResult res = rs_nfs_parse_request_tcp_gap(state, input_len); SCReturnStruct(res); } else { - AppLayerResult res = rs_nfs_parse_request(f, state, pstate, - input, input_len, local_data); + AppLayerResult res = + rs_nfs_parse_request(f, state, pstate, input, input_len, local_data, flags); SCReturnStruct(res); } } @@ -165,8 +165,8 @@ static AppLayerResult NFSTCPParseResponse(Flow *f, void *state, AppLayerParserSt AppLayerResult res = rs_nfs_parse_response_tcp_gap(state, input_len); SCReturnStruct(res); } else { - AppLayerResult res = rs_nfs_parse_response(f, state, pstate, - input, input_len, local_data); + AppLayerResult res = + rs_nfs_parse_response(f, state, pstate, input, input_len, local_data, flags); SCReturnStruct(res); } } @@ -186,7 +186,8 @@ static AppLayerGetTxIterTuple RustNFSTCPGetTxIterator( void *alstate, uint64_t min_tx_id, uint64_t max_tx_id, AppLayerGetTxIterState *istate) { - return rs_nfs_state_get_tx_iterator(alstate, min_tx_id, (uint64_t *)istate); + return rs_nfs_state_get_tx_iterator( + ipproto, alproto, alstate, min_tx_id, max_tx_id, (uint64_t *)istate); } /** @@ -226,7 +227,7 @@ static int NFSTCPSetTxDetectState(void *vtx, DetectEngineState *s) static FileContainer *NFSTCPGetFiles(void *state, uint8_t direction) { - return rs_nfs_getfiles(direction, state); + return rs_nfs_getfiles(state, direction); } static StreamingBufferConfig sbcfg = STREAMING_BUFFER_CONFIG_INITIALIZER; diff --git a/src/app-layer-nfs-udp.c b/src/app-layer-nfs-udp.c index 209de497b3..88a72b8579 100644 --- a/src/app-layer-nfs-udp.c +++ b/src/app-layer-nfs-udp.c @@ -120,9 +120,9 @@ static AppProto NFSProbingParser(Flow *f, uint8_t direction, int8_t r = 0; if (direction & STREAM_TOSERVER) - r = rs_nfs_probe_udp_ts(input, input_len); + r = rs_nfs_probe_udp_ts(f, direction, input, input_len, rdir); else - r = rs_nfs_probe_udp_tc(input, input_len); + r = rs_nfs_probe_udp_tc(f, direction, input, input_len, rdir); if (r == 1) { SCLogDebug("nfs"); @@ -143,8 +143,8 @@ static AppLayerResult NFSParseRequest(Flow *f, void *state, uint16_t file_flags = FileFlowToFlags(f, STREAM_TOSERVER); rs_nfs_setfileflags(0, state, file_flags); - AppLayerResult res = rs_nfs_parse_request_udp(f, state, pstate, - input, input_len, local_data); + AppLayerResult res = + rs_nfs_parse_request_udp(f, state, pstate, input, input_len, local_data, flags); SCReturnStruct(res); } @@ -155,8 +155,8 @@ static AppLayerResult NFSParseResponse(Flow *f, void *state, AppLayerParserState uint16_t file_flags = FileFlowToFlags(f, STREAM_TOCLIENT); rs_nfs_setfileflags(1, state, file_flags); - AppLayerResult res = rs_nfs_parse_response_udp(f, state, pstate, - input, input_len, local_data); + AppLayerResult res = + rs_nfs_parse_response_udp(f, state, pstate, input, input_len, local_data, flags); SCReturnStruct(res); } @@ -175,7 +175,8 @@ static AppLayerGetTxIterTuple RustNFSGetTxIterator( void *alstate, uint64_t min_tx_id, uint64_t max_tx_id, AppLayerGetTxIterState *istate) { - return rs_nfs_state_get_tx_iterator(alstate, min_tx_id, (uint64_t *)istate); + return rs_nfs_state_get_tx_iterator( + ipproto, alproto, alstate, min_tx_id, max_tx_id, (uint64_t *)istate); } /** @@ -215,7 +216,7 @@ static int NFSSetTxDetectState(void *vtx, DetectEngineState *s) static FileContainer *NFSGetFiles(void *state, uint8_t direction) { - return rs_nfs_getfiles(direction, state); + return rs_nfs_getfiles(state, direction); } static StreamingBufferConfig sbcfg = STREAMING_BUFFER_CONFIG_INITIALIZER;