|
|
|
|
@ -17,7 +17,7 @@
|
|
|
|
|
|
|
|
|
|
use std::mem::transmute;
|
|
|
|
|
use crate::applayer::*;
|
|
|
|
|
use crate::core::{self, sc_detect_engine_state_free};
|
|
|
|
|
use crate::core::{self, *};
|
|
|
|
|
use crate::dcerpc::parser;
|
|
|
|
|
use nom::error::ErrorKind;
|
|
|
|
|
use nom::number::Endianness;
|
|
|
|
|
@ -350,6 +350,7 @@ pub struct DCERPCState {
|
|
|
|
|
pub tc_ssn_gap: bool,
|
|
|
|
|
pub ts_ssn_trunc: bool, /// true if Truncated in this direction
|
|
|
|
|
pub tc_ssn_trunc: bool,
|
|
|
|
|
pub flow: Option<*const core::Flow>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl DCERPCState {
|
|
|
|
|
@ -376,6 +377,7 @@ impl DCERPCState {
|
|
|
|
|
tc_ssn_gap: false,
|
|
|
|
|
ts_ssn_trunc: false,
|
|
|
|
|
tc_ssn_trunc: false,
|
|
|
|
|
flow: None,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -618,6 +620,9 @@ impl DCERPCState {
|
|
|
|
|
tx.req_lost = true;
|
|
|
|
|
}
|
|
|
|
|
tx.req_done = true;
|
|
|
|
|
if let Some(flow) = self.flow {
|
|
|
|
|
sc_app_layer_parser_trigger_raw_stream_reassembly(flow, dir.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if self.tc_ssn_gap && dir == core::STREAM_TOCLIENT {
|
|
|
|
|
for tx in &mut self.transactions {
|
|
|
|
|
@ -633,6 +638,9 @@ impl DCERPCState {
|
|
|
|
|
}
|
|
|
|
|
tx.req_done = true;
|
|
|
|
|
tx.resp_done = true;
|
|
|
|
|
if let Some(flow) = self.flow {
|
|
|
|
|
sc_app_layer_parser_trigger_raw_stream_reassembly(flow, dir.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -745,6 +753,9 @@ impl DCERPCState {
|
|
|
|
|
let mut tx = self.create_tx(call_id);
|
|
|
|
|
tx.req_cmd = self.get_hdr_type().unwrap_or(0);
|
|
|
|
|
tx.req_done = true;
|
|
|
|
|
if let Some(flow) = self.flow {
|
|
|
|
|
sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOSERVER.into());
|
|
|
|
|
}
|
|
|
|
|
tx.frag_cnt_ts = 1;
|
|
|
|
|
self.transactions.push(tx);
|
|
|
|
|
// Bytes parsed with `parse_dcerpc_bind` + (bytes parsed per bindctxitem [44] * number
|
|
|
|
|
@ -827,6 +838,9 @@ impl DCERPCState {
|
|
|
|
|
);
|
|
|
|
|
tx.req_done = true;
|
|
|
|
|
tx.frag_cnt_ts = 1;
|
|
|
|
|
if let Some(flow) = self.flow {
|
|
|
|
|
sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOSERVER.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DCERPC_TYPE_RESPONSE => {
|
|
|
|
|
retval = evaluate_stub_params(
|
|
|
|
|
@ -839,6 +853,9 @@ impl DCERPCState {
|
|
|
|
|
);
|
|
|
|
|
tx.resp_done = true;
|
|
|
|
|
tx.frag_cnt_tc = 1;
|
|
|
|
|
if let Some(flow) = self.flow {
|
|
|
|
|
sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOCLIENT.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
SCLogDebug!("Unrecognized packet type");
|
|
|
|
|
@ -1069,6 +1086,9 @@ impl DCERPCState {
|
|
|
|
|
};
|
|
|
|
|
tx.resp_done = true;
|
|
|
|
|
tx.frag_cnt_tc = 1;
|
|
|
|
|
if let Some(flow) = self.flow {
|
|
|
|
|
sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOCLIENT.into());
|
|
|
|
|
}
|
|
|
|
|
self.handle_bind_cache(current_call_id, false);
|
|
|
|
|
}
|
|
|
|
|
DCERPC_TYPE_REQUEST => {
|
|
|
|
|
@ -1163,7 +1183,7 @@ pub extern "C" fn rs_parse_dcerpc_response_gap(
|
|
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
pub extern "C" fn rs_dcerpc_parse_request(
|
|
|
|
|
_flow: *mut core::Flow, state: &mut DCERPCState, _pstate: *mut std::os::raw::c_void,
|
|
|
|
|
flow: *mut core::Flow, state: &mut DCERPCState, _pstate: *mut std::os::raw::c_void,
|
|
|
|
|
input: *const u8, input_len: u32, _data: *mut std::os::raw::c_void, flags: u8,
|
|
|
|
|
) -> AppLayerResult {
|
|
|
|
|
SCLogDebug!("Handling request: input {:p} input_len {} flags {:x} EOF {}",
|
|
|
|
|
@ -1177,6 +1197,7 @@ pub extern "C" fn rs_dcerpc_parse_request(
|
|
|
|
|
}
|
|
|
|
|
if input_len > 0 && input != std::ptr::null_mut() {
|
|
|
|
|
let buf = build_slice!(input, input_len as usize);
|
|
|
|
|
state.flow = Some(flow);
|
|
|
|
|
return state.handle_input_data(buf, core::STREAM_TOSERVER);
|
|
|
|
|
}
|
|
|
|
|
AppLayerResult::err()
|
|
|
|
|
@ -1184,7 +1205,7 @@ pub extern "C" fn rs_dcerpc_parse_request(
|
|
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
pub extern "C" fn rs_dcerpc_parse_response(
|
|
|
|
|
_flow: *mut core::Flow, state: &mut DCERPCState, _pstate: *mut std::os::raw::c_void,
|
|
|
|
|
flow: *mut core::Flow, state: &mut DCERPCState, _pstate: *mut std::os::raw::c_void,
|
|
|
|
|
input: *const u8, input_len: u32, _data: *mut std::os::raw::c_void, flags: u8,
|
|
|
|
|
) -> AppLayerResult {
|
|
|
|
|
if flags & core::STREAM_EOF != 0 && input_len == 0 {
|
|
|
|
|
@ -1197,6 +1218,7 @@ pub extern "C" fn rs_dcerpc_parse_response(
|
|
|
|
|
if input_len > 0 {
|
|
|
|
|
if input != std::ptr::null_mut() {
|
|
|
|
|
let buf = build_slice!(input, input_len as usize);
|
|
|
|
|
state.flow = Some(flow);
|
|
|
|
|
return state.handle_input_data(buf, core::STREAM_TOCLIENT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -1229,12 +1251,18 @@ pub extern "C" fn rs_dcerpc_state_trunc(state: *mut std::os::raw::c_void, direct
|
|
|
|
|
dce_state.ts_ssn_trunc = true;
|
|
|
|
|
for tx in &mut dce_state.transactions {
|
|
|
|
|
tx.req_done = true;
|
|
|
|
|
if let Some(flow) = dce_state.flow {
|
|
|
|
|
sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOSERVER.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
SCLogDebug!("dce_state.ts_ssn_trunc = true; txs {}", dce_state.transactions.len());
|
|
|
|
|
} else if direction & core::STREAM_TOCLIENT != 0 {
|
|
|
|
|
dce_state.tc_ssn_trunc = true;
|
|
|
|
|
for tx in &mut dce_state.transactions {
|
|
|
|
|
tx.resp_done = true;
|
|
|
|
|
if let Some(flow) = dce_state.flow {
|
|
|
|
|
sc_app_layer_parser_trigger_raw_stream_reassembly(flow, core::STREAM_TOCLIENT.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
SCLogDebug!("dce_state.tc_ssn_trunc = true; txs {}", dce_state.transactions.len());
|
|
|
|
|
}
|
|
|
|
|
|