|
|
|
|
@ -94,6 +94,8 @@ pub struct SMBTransactionDCERPC {
|
|
|
|
|
pub res_cmd: u8,
|
|
|
|
|
pub res_set: bool,
|
|
|
|
|
pub call_id: u32,
|
|
|
|
|
pub req_flags: u8,
|
|
|
|
|
pub resp_flags: u8,
|
|
|
|
|
pub frag_cnt_ts: u16,
|
|
|
|
|
pub frag_cnt_tc: u16,
|
|
|
|
|
pub stub_data_ts: Vec<u8>,
|
|
|
|
|
@ -101,19 +103,21 @@ pub struct SMBTransactionDCERPC {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl SMBTransactionDCERPC {
|
|
|
|
|
fn new_request(req: u8, call_id: u32) -> Self {
|
|
|
|
|
fn new_request(req: u8, call_id: u32, flags: u8) -> Self {
|
|
|
|
|
return Self {
|
|
|
|
|
opnum: 0,
|
|
|
|
|
context_id: 0,
|
|
|
|
|
req_cmd: req,
|
|
|
|
|
req_set: true,
|
|
|
|
|
req_flags: flags,
|
|
|
|
|
call_id,
|
|
|
|
|
..Default::default()
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
fn new_response(call_id: u32) -> Self {
|
|
|
|
|
fn new_response(call_id: u32, flags: u8) -> Self {
|
|
|
|
|
return Self {
|
|
|
|
|
call_id,
|
|
|
|
|
resp_flags: flags,
|
|
|
|
|
..Default::default()
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
@ -126,12 +130,13 @@ impl SMBTransactionDCERPC {
|
|
|
|
|
impl SMBState {
|
|
|
|
|
fn new_dcerpc_tx(
|
|
|
|
|
&mut self, hdr: SMBCommonHdr, vercmd: SMBVerCmdStat, cmd: u8, call_id: u32,
|
|
|
|
|
packet_flags: u8,
|
|
|
|
|
) -> Option<&mut SMBTransaction> {
|
|
|
|
|
let mut tx = self.new_tx()?;
|
|
|
|
|
tx.hdr = hdr;
|
|
|
|
|
tx.vercmd = vercmd;
|
|
|
|
|
tx.type_data = Some(SMBTransactionTypeData::DCERPC(
|
|
|
|
|
SMBTransactionDCERPC::new_request(cmd, call_id),
|
|
|
|
|
SMBTransactionDCERPC::new_request(cmd, call_id, packet_flags),
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
SCLogDebug!("SMB: TX DCERPC created: ID {} hdr {:?}", tx.id, tx.hdr);
|
|
|
|
|
@ -140,13 +145,13 @@ impl SMBState {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn new_dcerpc_tx_for_response(
|
|
|
|
|
&mut self, hdr: SMBCommonHdr, vercmd: SMBVerCmdStat, call_id: u32,
|
|
|
|
|
&mut self, hdr: SMBCommonHdr, vercmd: SMBVerCmdStat, call_id: u32, packet_flags: u8,
|
|
|
|
|
) -> Option<&mut SMBTransaction> {
|
|
|
|
|
let mut tx = self.new_tx()?;
|
|
|
|
|
tx.hdr = hdr;
|
|
|
|
|
tx.vercmd = vercmd;
|
|
|
|
|
tx.type_data = Some(SMBTransactionTypeData::DCERPC(
|
|
|
|
|
SMBTransactionDCERPC::new_response(call_id),
|
|
|
|
|
SMBTransactionDCERPC::new_response(call_id, packet_flags),
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
SCLogDebug!("SMB: TX DCERPC created: ID {} hdr {:?}", tx.id, tx.hdr);
|
|
|
|
|
@ -213,6 +218,7 @@ pub fn smb_write_dcerpc_record(
|
|
|
|
|
if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) =
|
|
|
|
|
tx.type_data
|
|
|
|
|
{
|
|
|
|
|
tdn.req_flags |= dcer.packet_flags;
|
|
|
|
|
tdn.frag_cnt_ts = tdn.frag_cnt_ts.saturating_add(1);
|
|
|
|
|
let max_size = cfg_max_stub_size() as usize;
|
|
|
|
|
if recr.data.len() + tdn.stub_data_ts.len() < max_size {
|
|
|
|
|
@ -249,7 +255,13 @@ pub fn smb_write_dcerpc_record(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let Some(tx) = state.new_dcerpc_tx(hdr, vercmd, dcer.packet_type, dcer.call_id) else {
|
|
|
|
|
let Some(tx) = state.new_dcerpc_tx(
|
|
|
|
|
hdr,
|
|
|
|
|
vercmd,
|
|
|
|
|
dcer.packet_type,
|
|
|
|
|
dcer.call_id,
|
|
|
|
|
dcer.packet_flags,
|
|
|
|
|
) else {
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
match dcer.packet_type {
|
|
|
|
|
@ -390,6 +402,7 @@ fn smb_dcerpc_response_bindack(
|
|
|
|
|
Some(tx) => {
|
|
|
|
|
if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
|
|
|
|
|
tdn.set_result(DCERPC_TYPE_BINDACK);
|
|
|
|
|
tdn.resp_flags |= dcer.packet_flags;
|
|
|
|
|
}
|
|
|
|
|
tx.vercmd.set_ntstatus(ntstatus);
|
|
|
|
|
tx.response_done = true;
|
|
|
|
|
@ -460,6 +473,7 @@ fn dcerpc_response_handle(tx: &mut SMBTransaction, vercmd: SMBVerCmdStat, dcer:
|
|
|
|
|
tdn.stub_data_tc
|
|
|
|
|
.extend_from_slice(&respr.data[..max_size - tdn.stub_data_tc.len()]);
|
|
|
|
|
}
|
|
|
|
|
tdn.resp_flags |= dcer.packet_flags;
|
|
|
|
|
}
|
|
|
|
|
tx.vercmd.set_ntstatus(ntstatus);
|
|
|
|
|
tx.response_done = dcer.last_frag;
|
|
|
|
|
@ -474,6 +488,7 @@ fn dcerpc_response_handle(tx: &mut SMBTransaction, vercmd: SMBVerCmdStat, dcer:
|
|
|
|
|
21..=255 => {
|
|
|
|
|
if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
|
|
|
|
|
tdn.set_result(dcer.packet_type);
|
|
|
|
|
tdn.resp_flags |= dcer.packet_flags;
|
|
|
|
|
}
|
|
|
|
|
tx.vercmd.set_ntstatus(ntstatus);
|
|
|
|
|
tx.response_done = true;
|
|
|
|
|
@ -483,6 +498,7 @@ fn dcerpc_response_handle(tx: &mut SMBTransaction, vercmd: SMBVerCmdStat, dcer:
|
|
|
|
|
// valid type w/o special processing
|
|
|
|
|
if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
|
|
|
|
|
tdn.set_result(dcer.packet_type);
|
|
|
|
|
tdn.resp_flags |= dcer.packet_flags;
|
|
|
|
|
}
|
|
|
|
|
tx.vercmd.set_ntstatus(ntstatus);
|
|
|
|
|
tx.response_done = true;
|
|
|
|
|
@ -556,9 +572,12 @@ pub fn smb_read_dcerpc_record(
|
|
|
|
|
};
|
|
|
|
|
if !found {
|
|
|
|
|
// pick up DCERPC tx even if we missed the request
|
|
|
|
|
let Some(tx) =
|
|
|
|
|
state.new_dcerpc_tx_for_response(hdr, vercmd.clone(), dcer.call_id)
|
|
|
|
|
else {
|
|
|
|
|
let Some(tx) = state.new_dcerpc_tx_for_response(
|
|
|
|
|
hdr,
|
|
|
|
|
vercmd.clone(),
|
|
|
|
|
dcer.call_id,
|
|
|
|
|
dcer.packet_flags,
|
|
|
|
|
) else {
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
dcerpc_response_handle(tx, vercmd, &dcer);
|
|
|
|
|
|