diff --git a/rust/src/ntp/ntp.rs b/rust/src/ntp/ntp.rs index 3405ec5e26..00c1a860c9 100644 --- a/rust/src/ntp/ntp.rs +++ b/rust/src/ntp/ntp.rs @@ -20,10 +20,12 @@ extern crate ntp_parser; use self::ntp_parser::*; use core; +use core::{AppProto,ALPROTO_UNKNOWN,ALPROTO_FAILED}; use applayer; +use parser::*; use libc; use std; -use std::ffi::CStr; +use std::ffi::{CStr,CString}; use log::*; @@ -170,33 +172,6 @@ impl Drop for NTPTransaction { } -/// TOSERVER probe function -#[no_mangle] -pub extern "C" fn rs_ntp_probe(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) - }; - match parse_ntp(slice) { - IResult::Done(_, ref msg) => { - if msg.version == 3 || msg.version == 4 { - return 1; - } else { - return -1; - } - }, - IResult::Incomplete(_) => { - return 0; - }, - IResult::Error(_) => { - return -1; - }, - } -} - - - @@ -220,31 +195,34 @@ pub extern "C" fn rs_ntp_state_free(state: *mut libc::c_void) { #[no_mangle] pub extern "C" fn rs_ntp_parse_request(_flow: *const core::Flow, - state: &mut NTPState, + state: *mut libc::c_void, _pstate: *const libc::c_void, input: *const libc::uint8_t, input_len: u32, _data: *const libc::c_void) -> i8 { - let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)}; + let buf = build_slice!(input,input_len as usize); + let state = cast_pointer!(state,NTPState); state.parse(buf, 0) } #[no_mangle] pub extern "C" fn rs_ntp_parse_response(_flow: *const core::Flow, - state: &mut NTPState, + state: *mut libc::c_void, _pstate: *const libc::c_void, input: *const libc::uint8_t, input_len: u32, _data: *const libc::c_void) -> i8 { - let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)}; + let buf = build_slice!(input,input_len as usize); + let state = cast_pointer!(state,NTPState); state.parse(buf, 1) } #[no_mangle] -pub extern "C" fn rs_ntp_state_get_tx(state: &mut NTPState, +pub extern "C" fn rs_ntp_state_get_tx(state: *mut libc::c_void, tx_id: libc::uint64_t) - -> *mut NTPTransaction + -> *mut libc::c_void { + let state = cast_pointer!(state,NTPState); match state.get_tx_by_id(tx_id) { Some(tx) => unsafe{std::mem::transmute(tx)}, None => std::ptr::null_mut(), @@ -252,16 +230,18 @@ pub extern "C" fn rs_ntp_state_get_tx(state: &mut NTPState, } #[no_mangle] -pub extern "C" fn rs_ntp_state_get_tx_count(state: &mut NTPState) +pub extern "C" fn rs_ntp_state_get_tx_count(state: *mut libc::c_void) -> libc::uint64_t { + let state = cast_pointer!(state,NTPState); state.tx_id } #[no_mangle] -pub extern "C" fn rs_ntp_state_tx_free(state: &mut NTPState, +pub extern "C" fn rs_ntp_state_tx_free(state: *mut libc::c_void, tx_id: libc::uint64_t) { + let state = cast_pointer!(state,NTPState); state.free_tx(tx_id); } @@ -274,9 +254,9 @@ pub extern "C" fn rs_ntp_state_progress_completion_status( } #[no_mangle] -pub extern "C" fn rs_ntp_tx_get_alstate_progress(_tx: &mut NTPTransaction, +pub extern "C" fn rs_ntp_tx_get_alstate_progress(_tx: *mut libc::c_void, _direction: libc::uint8_t) - -> libc::uint8_t + -> libc::c_int { 1 } @@ -308,19 +288,23 @@ pub extern "C" fn rs_ntp_tx_get_logged(_state: &mut NTPState, #[no_mangle] pub extern "C" fn rs_ntp_state_set_tx_detect_state( - state: &mut NTPState, - tx: &mut NTPTransaction, - de_state: &mut core::DetectEngineState) + state: *mut libc::c_void, + tx: *mut libc::c_void, + de_state: &mut core::DetectEngineState) -> libc::c_int { + let state = cast_pointer!(state,NTPState); + let tx = cast_pointer!(tx,NTPTransaction); state.de_state_count += 1; tx.de_state = Some(de_state); + 0 } #[no_mangle] pub extern "C" fn rs_ntp_state_get_tx_detect_state( - tx: &mut NTPTransaction) + tx: *mut libc::c_void) -> *mut core::DetectEngineState { + let tx = cast_pointer!(tx,NTPTransaction); match tx.de_state { Some(ds) => ds, None => std::ptr::null_mut(), @@ -329,7 +313,8 @@ pub extern "C" fn rs_ntp_state_get_tx_detect_state( #[no_mangle] -pub extern "C" fn rs_ntp_state_has_events(state: &mut NTPState) -> u8 { +pub extern "C" fn rs_ntp_state_has_events(state: *mut libc::c_void) -> libc::c_int { + let state = cast_pointer!(state,NTPState); if state.events > 0 { return 1; } @@ -337,10 +322,11 @@ pub extern "C" fn rs_ntp_state_has_events(state: &mut NTPState) -> u8 { } #[no_mangle] -pub extern "C" fn rs_ntp_state_get_events(state: &mut NTPState, +pub extern "C" fn rs_ntp_state_get_events(state: *mut libc::c_void, tx_id: libc::uint64_t) -> *mut core::AppLayerDecoderEvents { + let state = cast_pointer!(state,NTPState); match state.get_tx_by_id(tx_id) { Some(tx) => tx.events, _ => std::ptr::null_mut(), @@ -351,7 +337,7 @@ pub extern "C" fn rs_ntp_state_get_events(state: &mut NTPState, pub extern "C" fn rs_ntp_state_get_event_info(event_name: *const libc::c_char, event_id: *mut libc::c_int, event_type: *mut core::AppLayerEventType) - -> i8 + -> libc::c_int { if event_name == std::ptr::null() { return -1; } let c_event_name: &CStr = unsafe { CStr::from_ptr(event_name) }; @@ -371,6 +357,80 @@ pub extern "C" fn rs_ntp_state_get_event_info(event_name: *const libc::c_char, 0 } + +static mut ALPROTO_NTP : AppProto = ALPROTO_UNKNOWN; + +#[no_mangle] +pub extern "C" fn ntp_probing_parser(input:*const i8, input_len: u32, _offset: *const i8) -> AppProto { + let slice: &[u8] = unsafe { std::slice::from_raw_parts(input as *mut u8, input_len as usize) }; + let alproto = unsafe{ ALPROTO_NTP }; + match parse_ntp(slice) { + IResult::Done(_, ref msg) => { + if msg.version == 3 || msg.version == 4 { + return alproto; + } else { + return unsafe{ALPROTO_FAILED}; + } + }, + IResult::Incomplete(_) => { + return ALPROTO_UNKNOWN; + }, + IResult::Error(_) => { + return unsafe{ALPROTO_FAILED}; + }, + } +} + +#[no_mangle] +pub unsafe extern "C" fn rs_register_ntp_parser() { + let name = CString::new("ntp").unwrap(); + let default_port = CString::new("123").unwrap(); + let parser = RustParser { + name : name.as_ptr(), + default_port : default_port.as_ptr(), + ipproto : libc::IPPROTO_UDP, + probe_ts : ntp_probing_parser, + probe_tc : ntp_probing_parser, + min_depth : 0, + max_depth : 16, + state_new : rs_ntp_state_new, + state_free : rs_ntp_state_free, + tx_free : rs_ntp_state_tx_free, + parse_ts : rs_ntp_parse_request, + parse_tc : rs_ntp_parse_response, + get_tx_count : rs_ntp_state_get_tx_count, + get_tx : rs_ntp_state_get_tx, + tx_get_comp_st : rs_ntp_state_progress_completion_status, + tx_get_progress : rs_ntp_tx_get_alstate_progress, + get_tx_logged : None, + set_tx_logged : None, + get_de_state : rs_ntp_state_get_tx_detect_state, + set_de_state : rs_ntp_state_set_tx_detect_state, + has_de_state : None, + has_events : Some(rs_ntp_state_has_events), + get_events : Some(rs_ntp_state_get_events), + get_eventinfo : Some(rs_ntp_state_get_event_info), + localstorage_new : None, + localstorage_free : None, + get_tx_mpm_id : None, + set_tx_mpm_id : None, + get_files : None, + }; + + let ip_proto_str = CString::new("udp").unwrap(); + if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 { + let alproto = AppLayerRegisterProtocolDetection(&parser, 1); + // store the allocated ID for the probe function + ALPROTO_NTP = alproto; + if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 { + let _ = AppLayerRegisterParser(&parser, alproto); + } + } else { + SCLogDebug!("Protocol detecter and parser disabled for NTP."); + } +} + + #[cfg(test)] mod tests { use super::NTPState; diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 4e298b6476..acbb8183c5 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -150,7 +150,7 @@ pub type GetFilesFn = extern "C" fn (*mut c_void, u8) -> *mut FileContai // Defined in app-layer-register.h extern { pub fn AppLayerRegisterProtocolDetection(parser: *const RustParser, enable_default: c_int) -> AppProto; - pub fn AppLayerRegisterParser(parser: *const RustParser) -> AppProto; + pub fn AppLayerRegisterParser(parser: *const RustParser, alproto: AppProto) -> c_int; } // Defined in app-layer-detect-proto.h diff --git a/src/app-layer-ntp.c b/src/app-layer-ntp.c index 3ffc6b5593..aa5d700345 100644 --- a/src/app-layer-ntp.c +++ b/src/app-layer-ntp.c @@ -38,250 +38,9 @@ #include "rust-ntp-ntp-gen.h" -/* The default port to probe for NTP traffic if not provided in the - * configuration file. */ -#define NTP_DEFAULT_PORT "123" - -/* The minimum size for an NTP message. */ -#define NTP_MIN_FRAME_LEN 2 - - -static void *NTPStateAlloc(void) -{ - return rs_ntp_state_new(); -} - -static void NTPStateFree(void *state) -{ - rs_ntp_state_free(state); -} - -/** - * \brief Callback from the application layer to have a transaction freed. - * - * \param state a void pointer to the NTPState object. - * \param tx_id the transaction ID to free. - */ -static void NTPStateTxFree(void *state, uint64_t tx_id) -{ - rs_ntp_state_tx_free(state, tx_id); -} - -static int NTPStateGetEventInfo(const char *event_name, int *event_id, - AppLayerEventType *event_type) -{ - return rs_ntp_state_get_event_info(event_name, event_id, event_type); -} - -static AppLayerDecoderEvents *NTPGetEvents(void *state, uint64_t tx_id) -{ - return rs_ntp_state_get_events(state, tx_id); -} - -static int NTPHasEvents(void *state) -{ - return rs_ntp_state_has_events(state); -} - -/** - * \brief Probe the input to see if it looks like NTP. - * - * \retval ALPROTO_NTP if it looks like NTP, otherwise - * ALPROTO_UNKNOWN. - */ -static AppProto NTPProbingParser(uint8_t *input, uint32_t input_len, - uint32_t *offset) -{ - if (input_len < NTP_MIN_FRAME_LEN) { - return ALPROTO_UNKNOWN; - } - - int8_t r = rs_ntp_probe(input, input_len); - if (r == 1) { - return ALPROTO_NTP; - } else if (r == -1) { - return ALPROTO_FAILED; - } - - SCLogDebug("Protocol not detected as ALPROTO_NTP."); - return ALPROTO_UNKNOWN; -} - -static int RustNTPParseRequest(Flow *f, void *state, - AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, - void *local_data) -{ - SCLogDebug("RustNTPParseRequest"); - return rs_ntp_parse_request(f, state, pstate, input, input_len, - local_data); -} - -static int RustNTPParseResponse(Flow *f, void *state, - AppLayerParserState *pstate, uint8_t *input, uint32_t input_len, - void *local_data) -{ - SCLogDebug("RustNTPParseResponse"); - return rs_ntp_parse_response(f, state, pstate, input, input_len, - local_data); -} - -static uint64_t NTPGetTxCnt(void *state) -{ - return rs_ntp_state_get_tx_count(state); -} - -static void *NTPGetTx(void *state, uint64_t tx_id) -{ - return rs_ntp_state_get_tx(state, tx_id); -} - -// static void NTPSetTxLogged(void *state, void *vtx, uint32_t logger) -// { -// rs_ntp_tx_set_logged(state, vtx, logger); -// } -// -// static int NTPGetTxLogged(void *state, void *vtx, uint32_t logger) -// { -// return rs_ntp_tx_get_logged(state, vtx, logger); -// } - - - - - - - -/** - * \brief Called by the application layer. - * - * In most cases 1 can be returned here. - */ -static int NTPGetAlstateProgressCompletionStatus(uint8_t direction) { - return rs_ntp_state_progress_completion_status(direction); -} - -/** - * \brief Return the state of a transaction in a given direction. - */ -static int NTPGetStateProgress(void *tx, uint8_t direction) -{ - return rs_ntp_tx_get_alstate_progress(tx, direction); -} - -/** - * \brief Get stored Tx detect state - */ -static DetectEngineState *NTPGetTxDetectState(void *vtx) -{ - return rs_ntp_state_get_tx_detect_state(vtx); -} - -/** - * \brief Set stored Tx detect state - */ -static int NTPSetTxDetectState(void *state, void *vtx, - DetectEngineState *s) -{ - rs_ntp_state_set_tx_detect_state(state, vtx, s); - return 0; -} - void RegisterNTPParsers(void) { - const char *proto_name = "ntp"; - - /* Check if NTP UDP detection is enabled. If it does not exist in - * the configuration file then it will be enabled by default. */ - if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) { - - SCLogDebug("NTP UDP protocol detection enabled."); - - AppLayerProtoDetectRegisterProtocol(ALPROTO_NTP, proto_name); - - if (RunmodeIsUnittests()) { - - SCLogDebug("Unittest mode, registeringd default configuration."); - AppLayerProtoDetectPPRegister(IPPROTO_UDP, NTP_DEFAULT_PORT, - ALPROTO_NTP, 0, NTP_MIN_FRAME_LEN, STREAM_TOSERVER, - NTPProbingParser, NULL); - - } - else { - - if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP, - proto_name, ALPROTO_NTP, 0, NTP_MIN_FRAME_LEN, - NTPProbingParser, NULL)) { - SCLogDebug("No NTP app-layer configuration, enabling NTP" - " detection UDP detection on port %s.", - NTP_DEFAULT_PORT); - AppLayerProtoDetectPPRegister(IPPROTO_UDP, - NTP_DEFAULT_PORT, ALPROTO_NTP, 0, - NTP_MIN_FRAME_LEN, STREAM_TOSERVER, - NTPProbingParser, NULL); - } - - } - - } - - else { - SCLogDebug("Protocol detecter and parser disabled for NTP."); - return; - } - - if (AppLayerParserConfParserEnabled("udp", proto_name)) { - - SCLogDebug("Registering NTP protocol parser."); - - /* Register functions for state allocation and freeing. A - * state is allocated for every new NTP flow. */ - AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_NTP, - NTPStateAlloc, NTPStateFree); - - /* Register request parser for parsing frame from server to client. */ - AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_NTP, - STREAM_TOSERVER, RustNTPParseRequest); - - /* Register response parser for parsing frames from server to client. */ - AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_NTP, - STREAM_TOCLIENT, RustNTPParseResponse); - - /* Register a function to be called by the application layer - * when a transaction is to be freed. */ - AppLayerParserRegisterTxFreeFunc(IPPROTO_UDP, ALPROTO_NTP, - NTPStateTxFree); - - // AppLayerParserRegisterLoggerFuncs(IPPROTO_UDP, ALPROTO_NTP, - // NTPGetTxLogged, NTPSetTxLogged); - - /* Register a function to return the current transaction count. */ - AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_NTP, - NTPGetTxCnt); - - /* Transaction handling. */ - AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_NTP, - NTPGetAlstateProgressCompletionStatus); - AppLayerParserRegisterGetStateProgressFunc(IPPROTO_UDP, - ALPROTO_NTP, NTPGetStateProgress); - AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_NTP, - NTPGetTx); - - /* Application layer event handling. */ - AppLayerParserRegisterHasEventsFunc(IPPROTO_UDP, ALPROTO_NTP, - NTPHasEvents); - - /* What is this being registered for? */ - AppLayerParserRegisterDetectStateFuncs(IPPROTO_UDP, ALPROTO_NTP, - NULL, NTPGetTxDetectState, NTPSetTxDetectState); - - AppLayerParserRegisterGetEventInfo(IPPROTO_UDP, ALPROTO_NTP, - NTPStateGetEventInfo); - AppLayerParserRegisterGetEventsFunc(IPPROTO_UDP, ALPROTO_NTP, - NTPGetEvents); - } - else { - SCLogDebug("NTP protocol parsing disabled."); - } + rs_register_ntp_parser(); #ifdef UNITTESTS AppLayerParserRegisterProtocolUnittests(IPPROTO_UDP, ALPROTO_NTP,