Shivani Bhardwaj 1 day ago committed by GitHub
commit d7c70b24f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -205,6 +205,8 @@ pub struct DCERPCTransaction {
pub resp_lost: bool, pub resp_lost: bool,
pub req_cmd: u8, pub req_cmd: u8,
pub resp_cmd: u8, pub resp_cmd: u8,
pub req_seen: bool,
pub resp_seen: bool,
pub activityuuid: Vec<u8>, pub activityuuid: Vec<u8>,
pub seqnum: u32, pub seqnum: u32,
pub tx_data: AppLayerTxData, pub tx_data: AppLayerTxData,
@ -221,9 +223,9 @@ impl DCERPCTransaction {
return Self { return Self {
stub_data_buffer_ts: Vec::new(), stub_data_buffer_ts: Vec::new(),
stub_data_buffer_tc: Vec::new(), stub_data_buffer_tc: Vec::new(),
req_cmd: DCERPC_TYPE_REQUEST,
resp_cmd: DCERPC_TYPE_RESPONSE,
activityuuid: Vec::new(), activityuuid: Vec::new(),
req_cmd: DCERPC_TYPE_UNKNOWN,
resp_cmd: DCERPC_TYPE_UNKNOWN,
tx_data: AppLayerTxData::new(), tx_data: AppLayerTxData::new(),
..Default::default() ..Default::default()
}; };
@ -278,13 +280,13 @@ pub struct Uuid {
pub node: Vec<u8>, pub node: Vec<u8>,
} }
#[derive(Debug)] #[derive(Debug, Clone, Copy)]
pub struct DCERPCHdr { pub struct DCERPCHdr {
pub rpc_vers: u8, pub rpc_vers: u8,
pub rpc_vers_minor: u8, pub rpc_vers_minor: u8,
pub hdrtype: u8, pub hdrtype: u8,
pub pfc_flags: u8, pub pfc_flags: u8,
pub packed_drep: Vec<u8>, pub packed_drep: [u8; 4],
pub frag_length: u16, pub frag_length: u16,
pub auth_length: u16, pub auth_length: u16,
pub call_id: u32, pub call_id: u32,
@ -445,8 +447,8 @@ impl DCERPCState {
if tx.req_done || tx.req_lost { if tx.req_done || tx.req_lost {
continue; continue;
} }
let resp_cmd = get_resp_type_for_req(cmd); /* do not match if the transaction's command does not match expected */
if resp_cmd != tx.resp_cmd { if tx.req_cmd != cmd && get_req_type_for_resp(tx.resp_cmd) != cmd {
continue; continue;
} }
} }
@ -454,8 +456,8 @@ impl DCERPCState {
if tx.resp_done || tx.resp_lost { if tx.resp_done || tx.resp_lost {
continue; continue;
} }
let req_cmd = get_req_type_for_resp(cmd); /* do not match if the transaction's command does not match expected */
if req_cmd != tx.req_cmd { if tx.resp_cmd != cmd && get_resp_type_for_req(tx.req_cmd) != cmd {
continue; continue;
} }
} }
@ -585,6 +587,7 @@ impl DCERPCState {
} }
let mut tx = self.create_tx(hdr); let mut tx = self.create_tx(hdr);
tx.req_cmd = hdr.hdrtype; tx.req_cmd = hdr.hdrtype;
tx.req_seen = true;
tx.req_done = true; tx.req_done = true;
if let Some(flow) = self.flow { if let Some(flow) = self.flow {
sc_app_layer_parser_trigger_raw_stream_inspection( sc_app_layer_parser_trigger_raw_stream_inspection(
@ -762,6 +765,7 @@ impl DCERPCState {
match transaction { match transaction {
Some(ref mut tx) => { Some(ref mut tx) => {
tx.req_cmd = hdr_type; tx.req_cmd = hdr_type;
tx.req_seen = true;
tx.ctxid = request.ctxid; tx.ctxid = request.ctxid;
tx.opnum = request.opnum; tx.opnum = request.opnum;
tx.first_request_seen = request.first_request_seen; tx.first_request_seen = request.first_request_seen;
@ -769,6 +773,7 @@ impl DCERPCState {
None => { None => {
let mut tx = self.create_tx(hdr); let mut tx = self.create_tx(hdr);
tx.req_cmd = hdr_type; tx.req_cmd = hdr_type;
tx.req_seen = true;
tx.ctxid = request.ctxid; tx.ctxid = request.ctxid;
tx.opnum = request.opnum; tx.opnum = request.opnum;
tx.first_request_seen = request.first_request_seen; tx.first_request_seen = request.first_request_seen;
@ -796,6 +801,24 @@ impl DCERPCState {
} }
} }
fn save_unhandled_ptypes(&mut self, hdr: &DCERPCHdr, direction: Direction) {
/* Create tx even on unhandled PDU types to be able to
* at least issue a match on header only fields */
let mut tx = self.create_tx(hdr);
if direction == Direction::ToServer {
tx.req_cmd = hdr.hdrtype;
tx.req_seen = true;
} else {
tx.resp_cmd = hdr.hdrtype;
tx.resp_seen = true;
}
tx.req_done = true;
tx.resp_done = true;
self.transactions.push_back(tx);
// recognized DCERPC PDU types that we do not process
SCLogDebug!("Unhandled packet type: {:?}", hdr.hdrtype);
}
pub fn handle_input_data( pub fn handle_input_data(
&mut self, stream_slice: StreamSlice, direction: Direction, &mut self, stream_slice: StreamSlice, direction: Direction,
) -> AppLayerResult { ) -> AppLayerResult {
@ -888,6 +911,15 @@ impl DCERPCState {
// input only consists of the header and that was consumed, so, return early // input only consists of the header and that was consumed, so, return early
cur_i = &cur_i[fraglen as usize..]; cur_i = &cur_i[fraglen as usize..];
consumed += fraglen as u32; consumed += fraglen as u32;
// save header-only PDU types too
if matches!(
hdr.hdrtype,
DCERPC_TYPE_SHUTDOWN | DCERPC_TYPE_CO_CANCEL | DCERPC_TYPE_ORPHANED
) {
self.save_unhandled_ptypes(&hdr, direction);
/* DCERPC_TYPE_CO_CANCEL and ORPHANED can optionally be more than header
* too so they're also handled later on the in the unrecognized branch */
}
continue; continue;
} }
cmp::Ordering::Greater => {} cmp::Ordering::Greater => {}
@ -949,10 +981,12 @@ impl DCERPCState {
self.get_tx_by_call_id(current_call_id, Direction::ToClient, hdrtype) self.get_tx_by_call_id(current_call_id, Direction::ToClient, hdrtype)
{ {
tx.resp_cmd = hdrtype; tx.resp_cmd = hdrtype;
tx.resp_seen = true;
tx tx
} else { } else {
let mut tx = self.create_tx(&hdr); let mut tx = self.create_tx(&hdr);
tx.resp_cmd = hdrtype; tx.resp_cmd = hdrtype;
tx.resp_seen = true;
self.transactions.push_back(tx); self.transactions.push_back(tx);
self.transactions.back_mut().unwrap() self.transactions.back_mut().unwrap()
}; };
@ -980,10 +1014,12 @@ impl DCERPCState {
match transaction { match transaction {
Some(tx) => { Some(tx) => {
tx.resp_cmd = hdrtype; tx.resp_cmd = hdrtype;
tx.resp_seen = true;
} }
None => { None => {
let mut tx = self.create_tx(&hdr); let mut tx = self.create_tx(&hdr);
tx.resp_cmd = hdrtype; tx.resp_cmd = hdrtype;
tx.resp_seen = true;
self.transactions.push_back(tx); self.transactions.push_back(tx);
} }
}; };
@ -997,9 +1033,24 @@ impl DCERPCState {
return AppLayerResult::err(); return AppLayerResult::err();
} }
} }
DCERPC_TYPE_PING
| DCERPC_TYPE_FAULT
| DCERPC_TYPE_WORKING
| DCERPC_TYPE_NOCALL
| DCERPC_TYPE_REJECT
| DCERPC_TYPE_ACK
| DCERPC_TYPE_CL_CANCEL
| DCERPC_TYPE_FACK
| DCERPC_TYPE_CANCEL_ACK
| DCERPC_TYPE_BINDNAK
| DCERPC_TYPE_AUTH3
| DCERPC_TYPE_CO_CANCEL
| DCERPC_TYPE_ORPHANED
| DCERPC_TYPE_RTS => {
self.save_unhandled_ptypes(&hdr, direction);
}
_ => { _ => {
SCLogDebug!("Unrecognized packet type: {:?}", hdrtype); SCLogDebug!("Unrecognized packet type: {:?}", hdrtype);
// skip unrecognized packet types such as AUTH3
} }
} }
consumed += fraglen as u32; consumed += fraglen as u32;

@ -190,6 +190,8 @@ impl DCERPCUDPState {
let max_size = cfg_max_stub_size() as usize; let max_size = cfg_max_stub_size() as usize;
match hdr.pkt_type { match hdr.pkt_type {
DCERPC_TYPE_REQUEST => { DCERPC_TYPE_REQUEST => {
tx.req_cmd = hdr.pkt_type;
tx.req_seen = true;
tx.frag_cnt_ts = tx.frag_cnt_ts.saturating_add(1); tx.frag_cnt_ts = tx.frag_cnt_ts.saturating_add(1);
if input.len() + tx.stub_data_buffer_ts.len() < max_size { if input.len() + tx.stub_data_buffer_ts.len() < max_size {
tx.stub_data_buffer_ts.extend_from_slice(input); tx.stub_data_buffer_ts.extend_from_slice(input);
@ -203,6 +205,8 @@ impl DCERPCUDPState {
return true; return true;
} }
DCERPC_TYPE_RESPONSE => { DCERPC_TYPE_RESPONSE => {
tx.resp_cmd = hdr.pkt_type;
tx.resp_seen = true;
tx.frag_cnt_tc = tx.frag_cnt_tc.saturating_add(1); tx.frag_cnt_tc = tx.frag_cnt_tc.saturating_add(1);
if input.len() + tx.stub_data_buffer_tc.len() < max_size { if input.len() + tx.stub_data_buffer_tc.len() < max_size {
tx.stub_data_buffer_tc.extend_from_slice(input); tx.stub_data_buffer_tc.extend_from_slice(input);

@ -233,7 +233,12 @@ pub(super) fn parse_dcerpc_header(i: &[u8]) -> IResult<&[u8], DCERPCHdr> {
rpc_vers_minor, rpc_vers_minor,
hdrtype, hdrtype,
pfc_flags, pfc_flags,
packed_drep: packed_drep.to_vec(), packed_drep: [
packed_drep[0],
packed_drep[1],
packed_drep[2],
packed_drep[3],
],
frag_length, frag_length,
auth_length, auth_length,
call_id, call_id,

Loading…
Cancel
Save