smb: convert to return AppLayerResult

Support returning 'incomplete' and remove the buffering
code from the parser.
pull/4691/head
Victor Julien 6 years ago
parent 674b8dc0fb
commit 4bf87d30e4

@ -1,4 +1,4 @@
/* Copyright (C) 2018 Open Information Security Foundation /* Copyright (C) 2018-2020 Open Information Security Foundation
* *
* You can copy, redistribute or modify this Program under the terms of * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free
@ -73,6 +73,6 @@ impl SMBState {
#[cfg(feature = "debug")] #[cfg(feature = "debug")]
pub fn _debug_state_stats(&self) { pub fn _debug_state_stats(&self) {
SCLogDebug!("ssn2vec_map {} guid2name_map {} ssn2vecoffset_map {} ssn2tree_map {} ssnguid2vec_map {} tcp_buffer_ts {} tcp_buffer_tc {} file_ts_guid {} file_tc_guid {} transactions {}", self.ssn2vec_map.len(), self.guid2name_map.len(), self.ssn2vecoffset_map.len(), self.ssn2tree_map.len(), self.ssnguid2vec_map.len(), self.tcp_buffer_ts.len(), self.tcp_buffer_tc.len(), self.file_ts_guid.len(), self.file_tc_guid.len(), self.transactions.len()); SCLogDebug!("ssn2vec_map {} guid2name_map {} ssn2vecoffset_map {} ssn2tree_map {} ssnguid2vec_map {} file_ts_guid {} file_tc_guid {} transactions {}", self.ssn2vec_map.len(), self.guid2name_map.len(), self.ssn2vecoffset_map.len(), self.ssn2tree_map.len(), self.ssnguid2vec_map.len(), self.file_ts_guid.len(), self.file_tc_guid.len(), self.transactions.len());
} }
} }

@ -38,6 +38,7 @@ use crate::core::*;
use crate::log::*; use crate::log::*;
use crate::applayer; use crate::applayer;
use crate::applayer::LoggerFlags; use crate::applayer::LoggerFlags;
use crate::parser::AppLayerResult;
use crate::smb::nbss_records::*; use crate::smb::nbss_records::*;
use crate::smb::smb1_records::*; use crate::smb::smb1_records::*;
@ -761,10 +762,6 @@ pub struct SMBState<> {
// requests for DCERPC. // requests for DCERPC.
pub ssnguid2vec_map: HashMap<SMBHashKeyHdrGuid, Vec<u8>>, pub ssnguid2vec_map: HashMap<SMBHashKeyHdrGuid, Vec<u8>>,
/// TCP segments defragmentation buffer
pub tcp_buffer_ts: Vec<u8>,
pub tcp_buffer_tc: Vec<u8>,
pub files: SMBFiles, pub files: SMBFiles,
skip_ts: u32, skip_ts: u32,
@ -817,8 +814,6 @@ impl SMBState {
ssn2vecoffset_map:HashMap::new(), ssn2vecoffset_map:HashMap::new(),
ssn2tree_map:HashMap::new(), ssn2tree_map:HashMap::new(),
ssnguid2vec_map:HashMap::new(), ssnguid2vec_map:HashMap::new(),
tcp_buffer_ts:Vec::new(),
tcp_buffer_tc:Vec::new(),
files: SMBFiles::new(), files: SMBFiles::new(),
skip_ts:0, skip_ts:0,
skip_tc:0, skip_tc:0,
@ -1328,6 +1323,7 @@ impl SMBState {
} }
} else if smb.version == 0xfe_u8 { // SMB2 } else if smb.version == 0xfe_u8 { // SMB2
SCLogDebug!("NBSS record {:?}", nbss_part_hdr);
SCLogDebug!("SMBv2 record"); SCLogDebug!("SMBv2 record");
match parse_smb2_request_record(&nbss_part_hdr.data) { match parse_smb2_request_record(&nbss_part_hdr.data) {
Ok((_, ref smb_record)) => { Ok((_, ref smb_record)) => {
@ -1336,6 +1332,7 @@ impl SMBState {
if smb_record.command == SMB2_COMMAND_WRITE { if smb_record.command == SMB2_COMMAND_WRITE {
smb2_write_request_record(self, smb_record); smb2_write_request_record(self, smb_record);
let consumed = input.len() - output.len(); let consumed = input.len() - output.len();
SCLogDebug!("consumed {}", consumed);
return consumed; return consumed;
} }
}, },
@ -1355,35 +1352,14 @@ impl SMBState {
} }
/// Parsing function, handling TCP chunks fragmentation /// Parsing function, handling TCP chunks fragmentation
pub fn parse_tcp_data_ts<'b>(&mut self, i: &'b[u8]) -> u32 pub fn parse_tcp_data_ts<'b>(&mut self, i: &'b[u8]) -> AppLayerResult
{ {
let mut v : Vec<u8>; let mut cur_i = i;
//println!("parse_tcp_data_ts ({})",i.len());
//println!("{:?}",i);
// Check if TCP data is being defragmented
let tcp_buffer = match self.tcp_buffer_ts.len() {
0 => i,
_ => {
v = self.tcp_buffer_ts.split_off(0);
if self.tcp_buffer_ts.len() + i.len() > 100000 {
self.set_event(SMBEvent::RecordOverflow);
return 1;
};
v.extend_from_slice(i);
v.as_slice()
},
};
//println!("tcp_buffer ({})",tcp_buffer.len());
let mut cur_i = tcp_buffer;
if cur_i.len() > 1000000 {
self.set_event(SMBEvent::RecordOverflow);
return 1;
}
let consumed = self.handle_skip(STREAM_TOSERVER, cur_i.len() as u32); let consumed = self.handle_skip(STREAM_TOSERVER, cur_i.len() as u32);
if consumed > 0 { if consumed > 0 {
if consumed > cur_i.len() as u32 { if consumed > cur_i.len() as u32 {
self.set_event(SMBEvent::InternalError); self.set_event(SMBEvent::InternalError);
return 1; return AppLayerResult::err();
} }
cur_i = &cur_i[consumed as usize..]; cur_i = &cur_i[consumed as usize..];
} }
@ -1393,30 +1369,42 @@ impl SMBState {
if consumed > 0 { if consumed > 0 {
if consumed > cur_i.len() as u32 { if consumed > cur_i.len() as u32 {
self.set_event(SMBEvent::InternalError); self.set_event(SMBEvent::InternalError);
return 1; return AppLayerResult::err();
} }
cur_i = &cur_i[consumed as usize..]; cur_i = &cur_i[consumed as usize..];
} }
if cur_i.len() == 0 {
return AppLayerResult::ok();
}
// gap // gap
if self.ts_gap { if self.ts_gap {
SCLogDebug!("TS trying to catch up after GAP (input {})", cur_i.len()); SCLogDebug!("TS trying to catch up after GAP (input {})", cur_i.len());
match search_smb_record(cur_i) { while cur_i.len() > 0 { // min record size
Ok((_, pg)) => { match search_smb_record(cur_i) {
SCLogDebug!("smb record found"); Ok((_, pg)) => {
let smb2_offset = cur_i.len() - pg.len(); SCLogDebug!("smb record found");
if smb2_offset < 4 { let smb2_offset = cur_i.len() - pg.len();
return 0; if smb2_offset < 4 {
} cur_i = &cur_i[smb2_offset+4..];
let nbss_offset = smb2_offset - 4; continue; // see if we have another record in our data
cur_i = &cur_i[nbss_offset..]; }
let nbss_offset = smb2_offset - 4;
cur_i = &cur_i[nbss_offset..];
self.ts_gap = false; self.ts_gap = false;
}, break;
_ => { },
SCLogDebug!("smb record NOT found"); _ => {
self.tcp_buffer_ts.extend_from_slice(cur_i); let mut consumed = i.len();
return 0; if consumed < 4 {
}, consumed = 0;
} else {
consumed = consumed - 3;
}
SCLogDebug!("smb record NOT found");
return AppLayerResult::incomplete(consumed as u32, 8);
},
}
} }
} }
while cur_i.len() > 0 { // min record size while cur_i.len() > 0 { // min record size
@ -1436,7 +1424,7 @@ impl SMBState {
}, },
_ => { _ => {
self.set_event(SMBEvent::MalformedData); self.set_event(SMBEvent::MalformedData);
return 1; return AppLayerResult::err();
}, },
} }
} else if smb.version == 0xfe_u8 { // SMB2 } else if smb.version == 0xfe_u8 { // SMB2
@ -1452,7 +1440,7 @@ impl SMBState {
}, },
_ => { _ => {
self.set_event(SMBEvent::MalformedData); self.set_event(SMBEvent::MalformedData);
return 1; return AppLayerResult::err();
}, },
} }
} }
@ -1466,7 +1454,7 @@ impl SMBState {
}, },
_ => { _ => {
self.set_event(SMBEvent::MalformedData); self.set_event(SMBEvent::MalformedData);
return 1; return AppLayerResult::err();
}, },
} }
} }
@ -1474,7 +1462,7 @@ impl SMBState {
}, },
_ => { _ => {
self.set_event(SMBEvent::MalformedData); self.set_event(SMBEvent::MalformedData);
return 1; return AppLayerResult::err();
}, },
} }
} else { } else {
@ -1482,16 +1470,34 @@ impl SMBState {
} }
cur_i = rem; cur_i = rem;
}, },
Err(nom::Err::Incomplete(_)) => { Err(nom::Err::Incomplete(needed)) => {
let consumed = self.parse_tcp_data_ts_partial(cur_i); if let nom::Needed::Size(n) = needed {
cur_i = &cur_i[consumed ..]; // 512 is the minimum for parse_tcp_data_ts_partial
if n >= 512 && cur_i.len() < 512 {
self.tcp_buffer_ts.extend_from_slice(cur_i); let total_consumed = i.len() - cur_i.len();
break; return AppLayerResult::incomplete(total_consumed as u32, 512);
}
let consumed = self.parse_tcp_data_ts_partial(cur_i);
if consumed == 0 {
// if we consumed none we will buffer the entire record
let total_consumed = i.len() - cur_i.len();
SCLogDebug!("setting consumed {} need {} needed {:?} total input {}",
total_consumed, n, needed, i.len());
let need = n + 4; // Incomplete returns size of data minus NBSS header
return AppLayerResult::incomplete(total_consumed as u32, need as u32);
}
// tracking a write record, which we don't need to
// queue up at the stream level, but can feed to us
// in small chunks
return AppLayerResult::ok();
} else {
self.set_event(SMBEvent::InternalError);
return AppLayerResult::err();
}
}, },
Err(_) => { Err(_) => {
self.set_event(SMBEvent::MalformedData); self.set_event(SMBEvent::MalformedData);
return 1; return AppLayerResult::err();
}, },
} }
}; };
@ -1500,7 +1506,7 @@ impl SMBState {
if self.check_post_gap_file_txs { if self.check_post_gap_file_txs {
self.post_gap_housekeeping_for_files(); self.post_gap_housekeeping_for_files();
} }
0 AppLayerResult::ok()
} }
/// return bytes consumed /// return bytes consumed
@ -1584,33 +1590,14 @@ impl SMBState {
} }
/// Parsing function, handling TCP chunks fragmentation /// Parsing function, handling TCP chunks fragmentation
pub fn parse_tcp_data_tc<'b>(&mut self, i: &'b[u8]) -> u32 pub fn parse_tcp_data_tc<'b>(&mut self, i: &'b[u8]) -> AppLayerResult
{ {
let mut v : Vec<u8>; let mut cur_i = i;
// Check if TCP data is being defragmented
let tcp_buffer = match self.tcp_buffer_tc.len() {
0 => i,
_ => {
v = self.tcp_buffer_tc.split_off(0);
if self.tcp_buffer_tc.len() + i.len() > 100000 {
self.set_event(SMBEvent::RecordOverflow);
return 1;
};
v.extend_from_slice(i);
v.as_slice()
},
};
let mut cur_i = tcp_buffer;
SCLogDebug!("cur_i.len {}", cur_i.len());
if cur_i.len() > 100000 {
self.set_event(SMBEvent::RecordOverflow);
return 1;
}
let consumed = self.handle_skip(STREAM_TOCLIENT, cur_i.len() as u32); let consumed = self.handle_skip(STREAM_TOCLIENT, cur_i.len() as u32);
if consumed > 0 { if consumed > 0 {
if consumed > cur_i.len() as u32 { if consumed > cur_i.len() as u32 {
self.set_event(SMBEvent::InternalError); self.set_event(SMBEvent::InternalError);
return 1; return AppLayerResult::err();
} }
cur_i = &cur_i[consumed as usize..]; cur_i = &cur_i[consumed as usize..];
} }
@ -1620,30 +1607,42 @@ impl SMBState {
if consumed > 0 { if consumed > 0 {
if consumed > cur_i.len() as u32 { if consumed > cur_i.len() as u32 {
self.set_event(SMBEvent::InternalError); self.set_event(SMBEvent::InternalError);
return 1; return AppLayerResult::err();
} }
cur_i = &cur_i[consumed as usize..]; cur_i = &cur_i[consumed as usize..];
} }
if cur_i.len() == 0 {
return AppLayerResult::ok();
}
// gap // gap
if self.tc_gap { if self.tc_gap {
SCLogDebug!("TC trying to catch up after GAP (input {})", cur_i.len()); SCLogDebug!("TC trying to catch up after GAP (input {})", cur_i.len());
match search_smb_record(cur_i) { while cur_i.len() > 0 { // min record size
Ok((_, pg)) => { match search_smb_record(cur_i) {
SCLogDebug!("smb record found"); Ok((_, pg)) => {
let smb2_offset = cur_i.len() - pg.len(); SCLogDebug!("smb record found");
if smb2_offset < 4 { let smb2_offset = cur_i.len() - pg.len();
return 0; if smb2_offset < 4 {
} cur_i = &cur_i[smb2_offset+4..];
let nbss_offset = smb2_offset - 4; continue; // see if we have another record in our data
cur_i = &cur_i[nbss_offset..]; }
let nbss_offset = smb2_offset - 4;
cur_i = &cur_i[nbss_offset..];
self.tc_gap = false; self.tc_gap = false;
}, break;
_ => { },
SCLogDebug!("smb record NOT found"); _ => {
self.tcp_buffer_tc.extend_from_slice(cur_i); let mut consumed = i.len();
return 0; if consumed < 4 {
}, consumed = 0;
} else {
consumed = consumed - 3;
}
SCLogDebug!("smb record NOT found");
return AppLayerResult::incomplete(consumed as u32, 8);
},
}
} }
} }
while cur_i.len() > 0 { // min record size while cur_i.len() > 0 { // min record size
@ -1663,7 +1662,7 @@ impl SMBState {
}, },
_ => { _ => {
self.set_event(SMBEvent::MalformedData); self.set_event(SMBEvent::MalformedData);
return 1; return AppLayerResult::err();
}, },
} }
} else if smb.version == 0xfe_u8 { // SMB2 } else if smb.version == 0xfe_u8 { // SMB2
@ -1677,7 +1676,7 @@ impl SMBState {
}, },
_ => { _ => {
self.set_event(SMBEvent::MalformedData); self.set_event(SMBEvent::MalformedData);
return 1; return AppLayerResult::err();
}, },
} }
} }
@ -1691,7 +1690,7 @@ impl SMBState {
}, },
_ => { _ => {
self.set_event(SMBEvent::MalformedData); self.set_event(SMBEvent::MalformedData);
return 1; return AppLayerResult::err();
}, },
} }
} }
@ -1703,7 +1702,7 @@ impl SMBState {
}, },
Err(_) => { Err(_) => {
self.set_event(SMBEvent::MalformedData); self.set_event(SMBEvent::MalformedData);
return 1; return AppLayerResult::err();
}, },
} }
} else { } else {
@ -1713,16 +1712,33 @@ impl SMBState {
}, },
Err(nom::Err::Incomplete(needed)) => { Err(nom::Err::Incomplete(needed)) => {
SCLogDebug!("INCOMPLETE have {} needed {:?}", cur_i.len(), needed); SCLogDebug!("INCOMPLETE have {} needed {:?}", cur_i.len(), needed);
let consumed = self.parse_tcp_data_tc_partial(cur_i); if let nom::Needed::Size(n) = needed {
cur_i = &cur_i[consumed ..]; // 512 is the minimum for parse_tcp_data_tc_partial
if n >= 512 && cur_i.len() < 512 {
SCLogDebug!("INCOMPLETE have {}", cur_i.len()); let total_consumed = i.len() - cur_i.len();
self.tcp_buffer_tc.extend_from_slice(cur_i); return AppLayerResult::incomplete(total_consumed as u32, 512);
break; }
let consumed = self.parse_tcp_data_tc_partial(cur_i);
if consumed == 0 {
// if we consumed none we will buffer the entire record
let total_consumed = i.len() - cur_i.len();
SCLogDebug!("setting consumed {} need {} needed {:?} total input {}",
total_consumed, n, needed, i.len());
let need = n + 4; // Incomplete returns size of data minus NBSS header
return AppLayerResult::incomplete(total_consumed as u32, need as u32);
}
// tracking a read record, which we don't need to
// queue up at the stream level, but can feed to us
// in small chunks
return AppLayerResult::ok();
} else {
self.set_event(SMBEvent::InternalError);
return AppLayerResult::err();
}
}, },
Err(_) => { Err(_) => {
self.set_event(SMBEvent::MalformedData); self.set_event(SMBEvent::MalformedData);
return 1; return AppLayerResult::err();
}, },
} }
}; };
@ -1731,15 +1747,12 @@ impl SMBState {
self.post_gap_housekeeping_for_files(); self.post_gap_housekeeping_for_files();
} }
self._debug_tx_stats(); self._debug_tx_stats();
0 AppLayerResult::ok()
} }
/// handle a gap in the TOSERVER direction /// handle a gap in the TOSERVER direction
/// returns: 0 ok, 1 unrecoverable error /// returns: 0 ok, 1 unrecoverable error
pub fn parse_tcp_data_ts_gap(&mut self, gap_size: u32) -> u32 { pub fn parse_tcp_data_ts_gap(&mut self, gap_size: u32) -> u32 {
if self.tcp_buffer_ts.len() > 0 {
self.tcp_buffer_ts.clear();
}
let consumed = self.handle_skip(STREAM_TOSERVER, gap_size); let consumed = self.handle_skip(STREAM_TOSERVER, gap_size);
if consumed < gap_size { if consumed < gap_size {
let new_gap_size = gap_size - consumed; let new_gap_size = gap_size - consumed;
@ -1761,9 +1774,6 @@ impl SMBState {
/// handle a gap in the TOCLIENT direction /// handle a gap in the TOCLIENT direction
/// returns: 0 ok, 1 unrecoverable error /// returns: 0 ok, 1 unrecoverable error
pub fn parse_tcp_data_tc_gap(&mut self, gap_size: u32) -> u32 { pub fn parse_tcp_data_tc_gap(&mut self, gap_size: u32) -> u32 {
if self.tcp_buffer_tc.len() > 0 {
self.tcp_buffer_tc.clear();
}
let consumed = self.handle_skip(STREAM_TOCLIENT, gap_size); let consumed = self.handle_skip(STREAM_TOCLIENT, gap_size);
if consumed < gap_size { if consumed < gap_size {
let new_gap_size = gap_size - consumed; let new_gap_size = gap_size - consumed;
@ -1785,7 +1795,6 @@ impl SMBState {
pub fn trunc_ts(&mut self) { pub fn trunc_ts(&mut self) {
SCLogDebug!("TRUNC TS"); SCLogDebug!("TRUNC TS");
self.ts_trunc = true; self.ts_trunc = true;
self.tcp_buffer_ts.clear();
for tx in &mut self.transactions { for tx in &mut self.transactions {
if !tx.request_done { if !tx.request_done {
@ -1797,7 +1806,6 @@ impl SMBState {
pub fn trunc_tc(&mut self) { pub fn trunc_tc(&mut self) {
SCLogDebug!("TRUNC TC"); SCLogDebug!("TRUNC TC");
self.tc_trunc = true; self.tc_trunc = true;
self.tcp_buffer_tc.clear();
for tx in &mut self.transactions { for tx in &mut self.transactions {
if !tx.response_done { if !tx.response_done {
@ -1836,7 +1844,7 @@ pub extern "C" fn rs_smb_parse_request_tcp(flow: &mut Flow,
input_len: u32, input_len: u32,
_data: *mut std::os::raw::c_void, _data: *mut std::os::raw::c_void,
flags: u8) flags: u8)
-> i8 -> AppLayerResult
{ {
let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)}; let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)};
SCLogDebug!("parsing {} bytes of request data", input_len); SCLogDebug!("parsing {} bytes of request data", input_len);
@ -1847,11 +1855,7 @@ pub extern "C" fn rs_smb_parse_request_tcp(flow: &mut Flow,
} }
state.ts = flow.get_last_time().as_secs(); state.ts = flow.get_last_time().as_secs();
if state.parse_tcp_data_ts(buf) == 0 { state.parse_tcp_data_ts(buf)
return 0;
} else {
return -1;
}
} }
#[no_mangle] #[no_mangle]
@ -1875,7 +1879,7 @@ pub extern "C" fn rs_smb_parse_response_tcp(flow: &mut Flow,
input_len: u32, input_len: u32,
_data: *mut std::os::raw::c_void, _data: *mut std::os::raw::c_void,
flags: u8) flags: u8)
-> i8 -> AppLayerResult
{ {
SCLogDebug!("parsing {} bytes of response data", input_len); SCLogDebug!("parsing {} bytes of response data", input_len);
let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)}; let buf = unsafe{std::slice::from_raw_parts(input, input_len as usize)};
@ -1886,11 +1890,7 @@ pub extern "C" fn rs_smb_parse_response_tcp(flow: &mut Flow,
} }
state.ts = flow.get_last_time().as_secs(); state.ts = flow.get_last_time().as_secs();
if state.parse_tcp_data_tc(buf) == 0 { state.parse_tcp_data_tc(buf)
return 0;
} else {
return -1;
}
} }
#[no_mangle] #[no_mangle]

@ -38,19 +38,20 @@ static AppLayerResult SMBTCPParseRequest(Flow *f, void *state,
uint16_t file_flags = FileFlowToFlags(f, STREAM_TOSERVER); uint16_t file_flags = FileFlowToFlags(f, STREAM_TOSERVER);
rs_smb_setfileflags(0, state, file_flags|FILE_USE_DETECT); rs_smb_setfileflags(0, state, file_flags|FILE_USE_DETECT);
int res;
if (input == NULL && input_len > 0) { if (input == NULL && input_len > 0) {
res = rs_smb_parse_request_tcp_gap(state, input_len); int res = rs_smb_parse_request_tcp_gap(state, input_len);
SCLogDebug("SMB request GAP of %u bytes, retval %d", input_len, res);
if (res != 0) {
SCReturnStruct(APP_LAYER_ERROR);
}
SCReturnStruct(APP_LAYER_OK);
} else { } else {
res = rs_smb_parse_request_tcp(f, state, pstate, input, input_len, AppLayerResult res = rs_smb_parse_request_tcp(f, state, pstate,
local_data, flags); input, input_len, local_data, flags);
}
if (res != 0) {
SCLogDebug("SMB request%s of %u bytes, retval %d", SCLogDebug("SMB request%s of %u bytes, retval %d",
(input == NULL && input_len > 0) ? " is GAP" : "", input_len, res); (input == NULL && input_len > 0) ? " is GAP" : "", input_len, res.status);
SCReturnStruct(APP_LAYER_ERROR); SCReturnStruct(res);
} }
SCReturnStruct(APP_LAYER_OK);
} }
static AppLayerResult SMBTCPParseResponse(Flow *f, void *state, static AppLayerResult SMBTCPParseResponse(Flow *f, void *state,
@ -62,19 +63,19 @@ static AppLayerResult SMBTCPParseResponse(Flow *f, void *state,
rs_smb_setfileflags(1, state, file_flags|FILE_USE_DETECT); rs_smb_setfileflags(1, state, file_flags|FILE_USE_DETECT);
SCLogDebug("SMBTCPParseResponse %p/%u", input, input_len); SCLogDebug("SMBTCPParseResponse %p/%u", input, input_len);
int res;
if (input == NULL && input_len > 0) { if (input == NULL && input_len > 0) {
res = rs_smb_parse_response_tcp_gap(state, input_len); int res = rs_smb_parse_response_tcp_gap(state, input_len);
if (res != 0) {
SCLogDebug("SMB response%s of %u bytes, retval %d",
(input == NULL && input_len > 0) ? " is GAP" : "", input_len, res);
SCReturnStruct(APP_LAYER_ERROR);
}
SCReturnStruct(APP_LAYER_OK);
} else { } else {
res = rs_smb_parse_response_tcp(f, state, pstate, input, input_len, AppLayerResult res = rs_smb_parse_response_tcp(f, state, pstate,
local_data, flags); input, input_len, local_data, flags);
} SCReturnStruct(res);
if (res != 0) {
SCLogDebug("SMB response%s of %u bytes, retval %d",
(input == NULL && input_len > 0) ? " is GAP" : "", input_len, res);
SCReturnStruct(APP_LAYER_ERROR);
} }
SCReturnStruct(APP_LAYER_OK);
} }
static uint16_t SMBTCPProbe(Flow *f, uint8_t direction, static uint16_t SMBTCPProbe(Flow *f, uint8_t direction,

Loading…
Cancel
Save