smb2: use if let for read/write parsing

pull/12094/head
Victor Julien 1 year ago committed by Victor Julien
parent 5bd2289008
commit d535d7f768

@ -164,28 +164,27 @@ pub fn smb2_read_response_record(state: &mut SMBState, r: &Smb2Record, nbss_rema
let mut set_event_fileoverlap = false; let mut set_event_fileoverlap = false;
// look up existing tracker and if we have it update it // look up existing tracker and if we have it update it
let found = match state.get_file_tx_by_fuid_with_open_file(&file_guid, Direction::ToClient) { let found = if let Some(tx) = state.get_file_tx_by_fuid_with_open_file(&file_guid, Direction::ToClient) {
Some(tx) => { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { let file_id : u32 = tx.id as u32;
let file_id : u32 = tx.id as u32; if offset < tdf.file_tracker.tracked {
if offset < tdf.file_tracker.tracked { set_event_fileoverlap = true;
set_event_fileoverlap = true;
}
if max_queue_size != 0 && tdf.file_tracker.get_inflight_size() + rd.len as u64 > max_queue_size.into() {
state.set_event(SMBEvent::ReadQueueSizeExceeded);
state.set_skip(Direction::ToClient, nbss_remaining);
} else if max_queue_cnt != 0 && tdf.file_tracker.get_inflight_cnt() >= max_queue_cnt as usize {
state.set_event(SMBEvent::ReadQueueCntExceeded);
state.set_skip(Direction::ToClient, nbss_remaining);
} else {
filetracker_newchunk(&mut tdf.file_tracker,
&tdf.file_name, rd.data, offset,
rd.len, false, &file_id);
}
} }
true if max_queue_size != 0 && tdf.file_tracker.get_inflight_size() + rd.len as u64 > max_queue_size.into() {
}, state.set_event(SMBEvent::ReadQueueSizeExceeded);
None => { false }, state.set_skip(Direction::ToClient, nbss_remaining);
} else if max_queue_cnt != 0 && tdf.file_tracker.get_inflight_cnt() >= max_queue_cnt as usize {
state.set_event(SMBEvent::ReadQueueCntExceeded);
state.set_skip(Direction::ToClient, nbss_remaining);
} else {
filetracker_newchunk(&mut tdf.file_tracker,
&tdf.file_name, rd.data, offset,
rd.len, false, &file_id);
}
}
true
} else {
false
}; };
SCLogDebug!("existing file tx? {}", found); SCLogDebug!("existing file tx? {}", found);
if !found { if !found {
@ -309,28 +308,27 @@ pub fn smb2_write_request_record(state: &mut SMBState, r: &Smb2Record, nbss_rema
}; };
let mut set_event_fileoverlap = false; let mut set_event_fileoverlap = false;
let found = match state.get_file_tx_by_fuid_with_open_file(&file_guid, Direction::ToServer) { let found = if let Some(tx) = state.get_file_tx_by_fuid_with_open_file(&file_guid, Direction::ToServer) {
Some(tx) => { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { let file_id : u32 = tx.id as u32;
let file_id : u32 = tx.id as u32; if wr.wr_offset < tdf.file_tracker.tracked {
if wr.wr_offset < tdf.file_tracker.tracked { set_event_fileoverlap = true;
set_event_fileoverlap = true;
}
if max_queue_size != 0 && tdf.file_tracker.get_inflight_size() + wr.wr_len as u64 > max_queue_size.into() {
state.set_event(SMBEvent::WriteQueueSizeExceeded);
state.set_skip(Direction::ToServer, nbss_remaining);
} else if max_queue_cnt != 0 && tdf.file_tracker.get_inflight_cnt() >= max_queue_cnt as usize {
state.set_event(SMBEvent::WriteQueueCntExceeded);
state.set_skip(Direction::ToServer, nbss_remaining);
} else {
filetracker_newchunk(&mut tdf.file_tracker,
&file_name, wr.data, wr.wr_offset,
wr.wr_len, false, &file_id);
}
} }
true if max_queue_size != 0 && tdf.file_tracker.get_inflight_size() + wr.wr_len as u64 > max_queue_size.into() {
}, state.set_event(SMBEvent::WriteQueueSizeExceeded);
None => { false }, state.set_skip(Direction::ToServer, nbss_remaining);
} else if max_queue_cnt != 0 && tdf.file_tracker.get_inflight_cnt() >= max_queue_cnt as usize {
state.set_event(SMBEvent::WriteQueueCntExceeded);
state.set_skip(Direction::ToServer, nbss_remaining);
} else {
filetracker_newchunk(&mut tdf.file_tracker,
&file_name, wr.data, wr.wr_offset,
wr.wr_len, false, &file_id);
}
}
true
} else {
false
}; };
if !found { if !found {
let tree_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_SHARE); let tree_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_SHARE);
@ -490,36 +488,26 @@ pub fn smb2_request_record(state: &mut SMBState, r: &Smb2Record)
false false
} }
SMB2_COMMAND_NEGOTIATE_PROTOCOL => { SMB2_COMMAND_NEGOTIATE_PROTOCOL => {
match parse_smb2_request_negotiate_protocol(r.data) { if let Ok((_, rd)) = parse_smb2_request_negotiate_protocol(r.data) {
Ok((_, rd)) => { let mut dialects : Vec<Vec<u8>> = Vec::new();
let mut dialects : Vec<Vec<u8>> = Vec::new(); for d in rd.dialects_vec {
for d in rd.dialects_vec { SCLogDebug!("dialect {:x} => {}", d, &smb2_dialect_string(d));
SCLogDebug!("dialect {:x} => {}", d, &smb2_dialect_string(d)); let dvec = smb2_dialect_string(d).as_bytes().to_vec();
let dvec = smb2_dialect_string(d).as_bytes().to_vec(); dialects.push(dvec);
dialects.push(dvec); }
}
let found = match state.get_negotiate_tx(2) { if state.get_negotiate_tx(2).is_none() {
Some(_) => { let tx = state.new_negotiate_tx(2);
SCLogDebug!("WEIRD, should not have NEGOTIATE tx!"); if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data {
true tdn.dialects2 = dialects;
}, tdn.client_guid = Some(rd.client_guid.to_vec());
None => { false },
};
if !found {
let tx = state.new_negotiate_tx(2);
if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data {
tdn.dialects2 = dialects;
tdn.client_guid = Some(rd.client_guid.to_vec());
}
tx.request_done = true;
} }
true tx.request_done = true;
}, }
_ => { true
events.push(SMBEvent::MalformedData); } else {
false events.push(SMBEvent::MalformedData);
}, false
} }
}, },
SMB2_COMMAND_SESSION_SETUP => { SMB2_COMMAND_SESSION_SETUP => {
@ -527,70 +515,59 @@ pub fn smb2_request_record(state: &mut SMBState, r: &Smb2Record)
true true
}, },
SMB2_COMMAND_TREE_CONNECT => { SMB2_COMMAND_TREE_CONNECT => {
match parse_smb2_request_tree_connect(r.data) { if let Ok((_, tr)) = parse_smb2_request_tree_connect(r.data) {
Ok((_, tr)) => { let name_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_TREE);
let name_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_TREE); let mut name_val = tr.share_name.to_vec();
let mut name_val = tr.share_name.to_vec(); name_val.retain(|&i|i != 0x00);
name_val.retain(|&i|i != 0x00); if name_val.len() > 1 {
if name_val.len() > 1 { name_val = name_val[1..].to_vec();
name_val = name_val[1..].to_vec();
}
let tx = state.new_treeconnect_tx(name_key, name_val);
tx.request_done = true;
tx.vercmd.set_smb2_cmd(SMB2_COMMAND_TREE_CONNECT);
true
} }
_ => {
events.push(SMBEvent::MalformedData); let tx = state.new_treeconnect_tx(name_key, name_val);
false tx.request_done = true;
}, tx.vercmd.set_smb2_cmd(SMB2_COMMAND_TREE_CONNECT);
true
} else {
events.push(SMBEvent::MalformedData);
false
} }
}, },
SMB2_COMMAND_READ => { SMB2_COMMAND_READ => {
match parse_smb2_request_read(r.data) { if let Ok((_, rd)) = parse_smb2_request_read(r.data) {
Ok((_, rd)) => { if (state.max_read_size != 0 && rd.rd_len > state.max_read_size) ||
if (state.max_read_size != 0 && rd.rd_len > state.max_read_size) || (unsafe { SMB_CFG_MAX_READ_SIZE != 0 && SMB_CFG_MAX_READ_SIZE < rd.rd_len }) {
(unsafe { SMB_CFG_MAX_READ_SIZE != 0 && SMB_CFG_MAX_READ_SIZE < rd.rd_len }) {
events.push(SMBEvent::ReadRequestTooLarge); events.push(SMBEvent::ReadRequestTooLarge);
} else { } else {
SCLogDebug!("SMBv2 READ: GUID {:?} requesting {} bytes at offset {}", SCLogDebug!("SMBv2 READ: GUID {:?} requesting {} bytes at offset {}",
rd.guid, rd.rd_len, rd.rd_offset); rd.guid, rd.rd_len, rd.rd_offset);
// store read guid,offset in map // store read guid,offset in map
let guid_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_OFFSET); let guid_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_OFFSET);
let guidoff = SMBFileGUIDOffset::new(rd.guid.to_vec(), rd.rd_offset); let guidoff = SMBFileGUIDOffset::new(rd.guid.to_vec(), rd.rd_offset);
state.ssn2vecoffset_map.insert(guid_key, guidoff); state.ssn2vecoffset_map.insert(guid_key, guidoff);
} }
}, } else {
_ => { events.push(SMBEvent::MalformedData);
events.push(SMBEvent::MalformedData);
},
} }
false false
}, },
SMB2_COMMAND_CREATE => { SMB2_COMMAND_CREATE => {
match parse_smb2_request_create(r.data) { if let Ok((_, cr)) = parse_smb2_request_create(r.data) {
Ok((_, cr)) => { let del = cr.create_options & 0x0000_1000 != 0;
let del = cr.create_options & 0x0000_1000 != 0; let dir = cr.create_options & 0x0000_0001 != 0;
let dir = cr.create_options & 0x0000_0001 != 0; SCLogDebug!("create_options {:08x}", cr.create_options);
SCLogDebug!("create_options {:08x}", cr.create_options); let name_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_FILENAME);
state.ssn2vec_map.insert(name_key, cr.data.to_vec());
let name_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_FILENAME);
state.ssn2vec_map.insert(name_key, cr.data.to_vec()); let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX);
let tx = state.new_create_tx(cr.data, cr.disposition, del, dir, tx_hdr);
let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX); tx.vercmd.set_smb2_cmd(r.command);
let tx = state.new_create_tx(cr.data, SCLogDebug!("TS CREATE TX {} created", tx.id);
cr.disposition, del, dir, tx_hdr); true
tx.vercmd.set_smb2_cmd(r.command); } else {
SCLogDebug!("TS CREATE TX {} created", tx.id); events.push(SMBEvent::MalformedData);
true false
},
_ => {
events.push(SMBEvent::MalformedData);
false
},
} }
}, },
SMB2_COMMAND_WRITE => { SMB2_COMMAND_WRITE => {
@ -598,43 +575,38 @@ pub fn smb2_request_record(state: &mut SMBState, r: &Smb2Record)
true // write handling creates both file tx and generic tx true // write handling creates both file tx and generic tx
}, },
SMB2_COMMAND_CLOSE => { SMB2_COMMAND_CLOSE => {
match parse_smb2_request_close(r.data) { if let Ok((_, cd)) = parse_smb2_request_close(r.data) {
Ok((_, cd)) => { let found_ts = if let Some(tx) = state.get_file_tx_by_fuid(cd.guid, Direction::ToServer) {
let found_ts = match state.get_file_tx_by_fuid(cd.guid, Direction::ToServer) { if !tx.request_done {
Some(tx) => { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
if !tx.request_done { filetracker_close(&mut tdf.file_tracker);
if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { }
filetracker_close(&mut tdf.file_tracker);
}
}
tx.request_done = true;
tx.response_done = true;
tx.set_status(SMB_NTSTATUS_SUCCESS, false);
true
},
None => { false },
};
let found_tc = match state.get_file_tx_by_fuid(cd.guid, Direction::ToClient) {
Some(tx) => {
if !tx.request_done {
if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
filetracker_close(&mut tdf.file_tracker);
}
}
tx.request_done = true;
tx.response_done = true;
tx.set_status(SMB_NTSTATUS_SUCCESS, false);
true
},
None => { false },
};
if !found_ts && !found_tc {
SCLogDebug!("SMBv2: CLOSE(TS): no TX at GUID {:?}", cd.guid);
} }
}, tx.request_done = true;
_ => { tx.response_done = true;
events.push(SMBEvent::MalformedData); tx.set_status(SMB_NTSTATUS_SUCCESS, false);
}, true
} else {
false
};
let found_tc = if let Some(tx) = state.get_file_tx_by_fuid(cd.guid, Direction::ToClient) {
if !tx.request_done {
if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
filetracker_close(&mut tdf.file_tracker);
}
}
tx.request_done = true;
tx.response_done = true;
tx.set_status(SMB_NTSTATUS_SUCCESS, false);
true
} else {
false
};
if !found_ts && !found_tc {
SCLogDebug!("SMBv2: CLOSE(TS): no TX at GUID {:?}", cd.guid);
}
} else {
events.push(SMBEvent::MalformedData);
} }
false false
}, },
@ -671,20 +643,16 @@ pub fn smb2_response_record(state: &mut SMBState, r: &Smb2Record)
}, },
SMB2_COMMAND_WRITE => { SMB2_COMMAND_WRITE => {
if r.nt_status == SMB_NTSTATUS_SUCCESS { if r.nt_status == SMB_NTSTATUS_SUCCESS {
match parse_smb2_response_write(r.data) if let Ok((_, _wr)) = parse_smb2_response_write(r.data) {
{ SCLogDebug!("SMBv2: Write response => {:?}", _wr);
Ok((_, _wr)) => {
SCLogDebug!("SMBv2: Write response => {:?}", _wr); /* search key-guid map */
let guid_key = SMBCommonHdr::new(SMBHDR_TYPE_GUID,
/* search key-guid map */ r.session_id, r.tree_id, r.message_id);
let guid_key = SMBCommonHdr::new(SMBHDR_TYPE_GUID, let _guid_vec = state.ssn2vec_map.remove(&guid_key).unwrap_or_default();
r.session_id, r.tree_id, r.message_id); SCLogDebug!("SMBv2 write response for GUID {:?}", _guid_vec);
let _guid_vec = state.ssn2vec_map.remove(&guid_key).unwrap_or_default(); } else {
SCLogDebug!("SMBv2 write response for GUID {:?}", _guid_vec); events.push(SMBEvent::MalformedData);
}
_ => {
events.push(SMBEvent::MalformedData);
},
} }
} }
false // the request may have created a generic tx, so handle that here false // the request may have created a generic tx, so handle that here
@ -693,75 +661,61 @@ pub fn smb2_response_record(state: &mut SMBState, r: &Smb2Record)
if r.nt_status == SMB_NTSTATUS_SUCCESS || if r.nt_status == SMB_NTSTATUS_SUCCESS ||
r.nt_status == SMB_NTSTATUS_BUFFER_OVERFLOW { r.nt_status == SMB_NTSTATUS_BUFFER_OVERFLOW {
smb2_read_response_record(state, r, 0); smb2_read_response_record(state, r, 0);
false
} else if r.nt_status == SMB_NTSTATUS_END_OF_FILE { } else if r.nt_status == SMB_NTSTATUS_END_OF_FILE {
SCLogDebug!("SMBv2: read response => EOF"); SCLogDebug!("SMBv2: read response => EOF");
let guid_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_OFFSET); let guid_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_OFFSET);
let file_guid = match state.ssn2vecoffset_map.remove(&guid_key) { let file_guid = if let Some(o) = state.ssn2vecoffset_map.remove(&guid_key) {
Some(o) => o.guid, o.guid
_ => { } else {
SCLogDebug!("SMBv2 READ response: reply to unknown request"); SCLogDebug!("SMBv2 READ response: reply to unknown request");
Vec::new() Vec::new()
},
}; };
let found = match state.get_file_tx_by_fuid(&file_guid, Direction::ToClient) { if let Some(tx) = state.get_file_tx_by_fuid(&file_guid, Direction::ToClient) {
Some(tx) => { if !tx.request_done {
if !tx.request_done { if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
if let Some(SMBTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { filetracker_close(&mut tdf.file_tracker);
filetracker_close(&mut tdf.file_tracker);
}
} }
tx.set_status(r.nt_status, false); }
tx.request_done = true; tx.set_status(r.nt_status, false);
false tx.request_done = true;
},
None => { false },
};
if !found {
SCLogDebug!("SMBv2 READ: no TX at GUID {:?}", file_guid);
} }
false
} else { } else {
SCLogDebug!("SMBv2 READ: status {}", r.nt_status); SCLogDebug!("SMBv2 READ: status {}", r.nt_status);
false
} }
false
}, },
SMB2_COMMAND_CREATE => { SMB2_COMMAND_CREATE => {
if r.nt_status == SMB_NTSTATUS_SUCCESS { if r.nt_status == SMB_NTSTATUS_SUCCESS {
match parse_smb2_response_create(r.data) { if let Ok((_, cr)) = parse_smb2_response_create(r.data) {
Ok((_, cr)) => { SCLogDebug!("SMBv2: Create response => {:?}", cr);
SCLogDebug!("SMBv2: Create response => {:?}", cr);
let guid_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_FILENAME);
if let Some(mut p) = state.ssn2vec_map.remove(&guid_key) {
p.retain(|&i|i != 0x00);
state.guid2name_map.insert(cr.guid.to_vec(), p);
} else {
SCLogDebug!("SMBv2 response: GUID NOT FOUND");
}
let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX); let guid_key = SMBCommonHdr::from2_notree(r, SMBHDR_TYPE_FILENAME);
if let Some(tx) = state.get_generic_tx(2, r.command, &tx_hdr) { if let Some(mut p) = state.ssn2vec_map.remove(&guid_key) {
SCLogDebug!("tx {} with {}/{} marked as done", p.retain(|&i|i != 0x00);
tx.id, r.command, &smb2_command_string(r.command)); state.guid2name_map.insert(cr.guid.to_vec(), p);
tx.set_status(r.nt_status, false); } else {
tx.response_done = true; SCLogDebug!("SMBv2 response: GUID NOT FOUND");
}
if let Some(SMBTransactionTypeData::CREATE(ref mut tdn)) = tx.type_data { let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX);
tdn.create_ts = cr.create_ts.as_unix(); if let Some(tx) = state.get_generic_tx(2, r.command, &tx_hdr) {
tdn.last_access_ts = cr.last_access_ts.as_unix(); SCLogDebug!("tx {} with {}/{} marked as done",
tdn.last_write_ts = cr.last_write_ts.as_unix(); tx.id, r.command, &smb2_command_string(r.command));
tdn.last_change_ts = cr.last_change_ts.as_unix(); tx.set_status(r.nt_status, false);
tdn.size = cr.size; tx.response_done = true;
tdn.guid = cr.guid.to_vec();
} if let Some(SMBTransactionTypeData::CREATE(ref mut tdn)) = tx.type_data {
tdn.create_ts = cr.create_ts.as_unix();
tdn.last_access_ts = cr.last_access_ts.as_unix();
tdn.last_write_ts = cr.last_write_ts.as_unix();
tdn.last_change_ts = cr.last_change_ts.as_unix();
tdn.size = cr.size;
tdn.guid = cr.guid.to_vec();
} }
} }
_ => { } else {
events.push(SMBEvent::MalformedData); events.push(SMBEvent::MalformedData);
},
} }
true true
} else { } else {
@ -777,50 +731,45 @@ pub fn smb2_response_record(state: &mut SMBState, r: &Smb2Record)
} }
SMB2_COMMAND_TREE_CONNECT => { SMB2_COMMAND_TREE_CONNECT => {
if r.nt_status == SMB_NTSTATUS_SUCCESS { if r.nt_status == SMB_NTSTATUS_SUCCESS {
match parse_smb2_response_tree_connect(r.data) { if let Ok((_, tr)) = parse_smb2_response_tree_connect(r.data) {
Ok((_, tr)) => { let name_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_TREE);
let name_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_TREE); let mut share_name = Vec::new();
let mut share_name = Vec::new(); let is_pipe = tr.share_type == 2;
let is_pipe = tr.share_type == 2; let found = match state.get_treeconnect_tx(name_key) {
let found = match state.get_treeconnect_tx(name_key) { Some(tx) => {
Some(tx) => { if let Some(SMBTransactionTypeData::TREECONNECT(ref mut tdn)) = tx.type_data {
if let Some(SMBTransactionTypeData::TREECONNECT(ref mut tdn)) = tx.type_data { tdn.share_type = tr.share_type;
tdn.share_type = tr.share_type; tdn.is_pipe = is_pipe;
tdn.is_pipe = is_pipe; tdn.tree_id = r.tree_id;
tdn.tree_id = r.tree_id; share_name = tdn.share_name.to_vec();
share_name = tdn.share_name.to_vec(); }
} // update hdr now that we have a tree_id
// update hdr now that we have a tree_id tx.hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_HEADER);
tx.hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_HEADER); tx.response_done = true;
tx.response_done = true; tx.set_status(r.nt_status, false);
tx.set_status(r.nt_status, false); true
true },
}, None => { false },
None => { false }, };
}; if found {
if found { let tree = SMBTree::new(share_name.to_vec(), is_pipe);
let tree = SMBTree::new(share_name.to_vec(), is_pipe); let tree_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_SHARE);
let tree_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_SHARE); state.ssn2tree_map.insert(tree_key, tree);
state.ssn2tree_map.insert(tree_key, tree);
}
true
} }
_ => { true
events.push(SMBEvent::MalformedData); } else {
false events.push(SMBEvent::MalformedData);
}, false
} }
} else { } else {
let name_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_TREE); let name_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_TREE);
let found = match state.get_treeconnect_tx(name_key) { if let Some(tx) = state.get_treeconnect_tx(name_key) {
Some(tx) => { tx.response_done = true;
tx.response_done = true; tx.set_status(r.nt_status, false);
tx.set_status(r.nt_status, false); true
true } else {
}, false
None => { false }, }
};
found
} }
}, },
SMB2_COMMAND_NEGOTIATE_PROTOCOL => { SMB2_COMMAND_NEGOTIATE_PROTOCOL => {
@ -829,52 +778,49 @@ pub fn smb2_response_record(state: &mut SMBState, r: &Smb2Record)
} else { } else {
parse_smb2_response_negotiate_protocol_error(r.data) parse_smb2_response_negotiate_protocol_error(r.data)
}; };
match res { if let Ok((_, rd)) = res {
Ok((_, rd)) => { SCLogDebug!("SERVER dialect => {}", &smb2_dialect_string(rd.dialect));
SCLogDebug!("SERVER dialect => {}", &smb2_dialect_string(rd.dialect));
let smb_cfg_max_read_size = unsafe { SMB_CFG_MAX_READ_SIZE }; let smb_cfg_max_read_size = unsafe { SMB_CFG_MAX_READ_SIZE };
if smb_cfg_max_read_size != 0 && rd.max_read_size > smb_cfg_max_read_size { if smb_cfg_max_read_size != 0 && rd.max_read_size > smb_cfg_max_read_size {
state.set_event(SMBEvent::NegotiateMaxReadSizeTooLarge); state.set_event(SMBEvent::NegotiateMaxReadSizeTooLarge);
} }
let smb_cfg_max_write_size = unsafe { SMB_CFG_MAX_WRITE_SIZE }; let smb_cfg_max_write_size = unsafe { SMB_CFG_MAX_WRITE_SIZE };
if smb_cfg_max_write_size != 0 && rd.max_write_size > smb_cfg_max_write_size { if smb_cfg_max_write_size != 0 && rd.max_write_size > smb_cfg_max_write_size {
state.set_event(SMBEvent::NegotiateMaxWriteSizeTooLarge); state.set_event(SMBEvent::NegotiateMaxWriteSizeTooLarge);
} }
state.dialect = rd.dialect; state.dialect = rd.dialect;
state.max_read_size = rd.max_read_size; state.max_read_size = rd.max_read_size;
state.max_write_size = rd.max_write_size; state.max_write_size = rd.max_write_size;
let found2 = match state.get_negotiate_tx(2) { let found2 = match state.get_negotiate_tx(2) {
Some(tx) => { Some(tx) => {
if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data { if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data {
tdn.server_guid = rd.server_guid.to_vec(); tdn.server_guid = rd.server_guid.to_vec();
} }
tx.set_status(r.nt_status, false); tx.set_status(r.nt_status, false);
tx.response_done = true; tx.response_done = true;
true true
}, },
None => { false }, None => { false },
}; };
// SMB2 response to SMB1 request? // SMB2 response to SMB1 request?
let found1 = !found2 && match state.get_negotiate_tx(1) { let found1 = !found2 && match state.get_negotiate_tx(1) {
Some(tx) => { Some(tx) => {
if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data { if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data {
tdn.server_guid = rd.server_guid.to_vec(); tdn.server_guid = rd.server_guid.to_vec();
} }
tx.set_status(r.nt_status, false); tx.set_status(r.nt_status, false);
tx.response_done = true; tx.response_done = true;
true true
}, },
None => { false }, None => { false },
}; };
found1 || found2 found1 || found2
}, } else {
_ => { events.push(SMBEvent::MalformedData);
events.push(SMBEvent::MalformedData); false
false
}
} }
}, },
_ => { _ => {

Loading…
Cancel
Save