FileOverlap = 7,
RequestToClient = 8,
ResponseToServer = 9,
+ /// READ request asking for more than `max_read_size`
+ ReadRequestTooLarge = 10,
+ /// READ response bigger than `max_read_size`
+ ReadResponseTooLarge = 11,
+ /// WRITE request for more than `max_write_size`
+ WriteRequestTooLarge = 12,
}
impl SMBEvent {
7 => Some(SMBEvent::FileOverlap),
8 => Some(SMBEvent::RequestToClient),
9 => Some(SMBEvent::ResponseToServer),
+ 10 => Some(SMBEvent::ReadRequestTooLarge),
+ 11 => Some(SMBEvent::ReadResponseTooLarge),
+ 12 => Some(SMBEvent::WriteRequestTooLarge),
_ => None,
}
}
"file_overlap" => SMBEvent::FileOverlap as i32,
"request_to_client" => SMBEvent::RequestToClient as i32,
"response_to_server" => SMBEvent::ResponseToServer as i32,
+ "read_request_too_large" => SMBEvent::ReadRequestTooLarge as i32,
+ "read_response_too_large" => SMBEvent::ReadResponseTooLarge as i32,
+ "write_request_too_large" => SMBEvent::WriteRequestTooLarge as i32,
_ => -1,
}
}
/// them while inspecting DCERPC REQUEST txs
pub dcerpc_ifaces: Option<Vec<DCERPCIface>>,
+ pub max_read_size: u32,
+ pub max_write_size: u32,
+
/// Timestamp in seconds of last update. This is packet time,
/// potentially coming from pcaps.
ts: u64,
dialect_vec: None,
dcerpc_ifaces: None,
ts: 0,
+ max_read_size: 0,
+ max_write_size: 0,
}
}
SMBEvent::FileOverlap => { "file_overlap\0" },
SMBEvent::RequestToClient => { "request_to_client\0" },
SMBEvent::ResponseToServer => { "response_to_server\0" },
+ SMBEvent::ReadRequestTooLarge => { "read_request_too_large\0" },
+ SMBEvent::ReadResponseTooLarge => { "read_response_too_large\0" },
+ SMBEvent::WriteRequestTooLarge => { "write_request_too_large\0" },
};
unsafe{
*event_name = estr.as_ptr() as *const std::os::raw::c_char;
return;
}
+ if state.max_read_size > 0 && rd.len > state.max_read_size {
+ state.set_event(SMBEvent::ReadResponseTooLarge);
+ state.set_skip(STREAM_TOCLIENT, rd.len, rd.data.len() as u32);
+ return;
+ }
+
SCLogDebug!("SMBv2: read response => {:?}", rd);
// get the request info. If we don't have it, there is nothing
}
match parse_smb2_request_write(r.data) {
Ok((_, wr)) => {
+ if state.max_read_size != 0 && wr.wr_len > state.max_write_size {
+ state.set_event(SMBEvent::WriteRequestTooLarge);
+ state.set_skip(STREAM_TOSERVER, wr.wr_len, wr.data.len() as u32);
+ return;
+ }
+
/* update key-guid map */
let guid_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_GUID);
state.ssn2vec_map.insert(guid_key, wr.guid.to_vec());
SMB2_COMMAND_READ => {
match parse_smb2_request_read(r.data) {
Ok((_, rd)) => {
- SCLogDebug!("SMBv2 READ: GUID {:?} requesting {} bytes at offset {}",
- rd.guid, rd.rd_len, rd.rd_offset);
+ if state.max_read_size != 0 && rd.rd_len > state.max_read_size {
+ events.push(SMBEvent::ReadRequestTooLarge);
+ } else {
+ SCLogDebug!("SMBv2 READ: GUID {:?} requesting {} bytes at offset {}",
+ rd.guid, rd.rd_len, rd.rd_offset);
- // store read guid,offset in map
- let guid_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_OFFSET);
- let guidoff = SMBFileGUIDOffset::new(rd.guid.to_vec(), rd.rd_offset);
- state.ssn2vecoffset_map.insert(guid_key, guidoff);
+ // store read guid,offset in map
+ let guid_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_OFFSET);
+ let guidoff = SMBFileGUIDOffset::new(rd.guid.to_vec(), rd.rd_offset);
+ state.ssn2vecoffset_map.insert(guid_key, guidoff);
+ }
},
_ => {
events.push(SMBEvent::MalformedData);
SCLogDebug!("SERVER dialect => {}", &smb2_dialect_string(rd.dialect));
state.dialect = rd.dialect;
+ state.max_read_size = rd.max_read_size;
+ state.max_write_size = rd.max_write_size;
+
let found2 = match state.get_negotiate_tx(2) {
Some(tx) => {
if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data {
pub struct Smb2NegotiateProtocolResponseRecord<'a> {
pub dialect: u16,
pub server_guid: &'a[u8],
+ pub max_trans_size: u32,
+ pub max_read_size: u32,
+ pub max_write_size: u32,
}
named!(pub parse_smb2_response_negotiate_protocol<Smb2NegotiateProtocolResponseRecord>,
>> dialect: le_u16
>> _ctx_cnt: le_u16
>> server_guid: take!(16)
+ >> _capabilities: le_u32
+ >> max_trans_size: le_u32
+ >> max_read_size: le_u32
+ >> max_write_size: le_u32
>> (Smb2NegotiateProtocolResponseRecord {
dialect,
- server_guid
+ server_guid,
+ max_trans_size,
+ max_read_size,
+ max_write_size
})
));
>> (Smb2NegotiateProtocolResponseRecord {
dialect: 0,
server_guid: &[],
+ max_trans_size: 0,
+ max_read_size: 0,
+ max_write_size: 0
})
));
-
#[derive(Debug,PartialEq)]
pub struct Smb2SessionSetupRequestRecord<'a> {
pub data: &'a[u8],