/// Parsing function, handling TCP chunks fragmentation
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
    {
        let max_tx_id = self.tx_id;
        let mut v : Vec<u8>;
        // 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;
        debug!("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);
        if consumed > 0 {
            if consumed > cur_i.len() as u32 {
                self.set_event(SMBEvent::InternalError);
                return 1;
            }
            cur_i = &cur_i[consumed as usize..];
        }
        // take care of in progress file chunk transfers
        // and skip buffer beyond it
        let consumed = self.filetracker_update(STREAM_TOCLIENT, cur_i, 0);
        if consumed > 0 {
            if consumed > cur_i.len() as u32 {
                self.set_event(SMBEvent::InternalError);
                return 1;
            }
            cur_i = &cur_i[consumed as usize..];
        }
        // gap
        if self.tc_gap {
            debug!("TC trying to catch up after GAP (input {})", cur_i.len());
            match search_smb_record(cur_i) {
                IResult::Done(_, pg) => {
                    debug!("smb record found");
                    let smb2_offset = cur_i.len() - pg.data.len();
                    if smb2_offset < 4 {
                        return 0;
                    }
                    let nbss_offset = smb2_offset - 4;
                    cur_i = &cur_i[nbss_offset..];
                    self.tc_gap = false;
                },
                _ => {
                    debug!("smb record NOT found");
                    self.tcp_buffer_tc.extend_from_slice(cur_i);
                    return 0;
                },
            }
        }
        while cur_i.len() > 0 { // min record size
            match parse_nbss_record(cur_i) {
                IResult::Done(rem, ref nbss_hdr) => {
                    if nbss_hdr.message_type == NBSS_MSGTYPE_SESSION_MESSAGE {
                        // we have the full records size worth of data,
                        // let's parse it
                        match parse_smb_version(&nbss_hdr.data) {
                            IResult::Done(_, ref smb) => {
                                debug!("SMB {:?}", smb);
                                if smb.version == 0xff_u8 { // SMB1
                                    debug!("SMBv1 record");
                                    match parse_smb_record(&nbss_hdr.data) {
                                        IResult::Done(_, ref smb_record) => {
                                            smb1_response_record(self, smb_record);
                                        },
                                        _ => {
                                            self.set_event(SMBEvent::MalformedData);
                                            return 1;
                                        },
                                    }
                                } else if smb.version == 0xfe_u8 { // SMB2
                                    let mut nbss_data = nbss_hdr.data;
                                    while nbss_data.len() > 0 {
                                        debug!("SMBv2 record");
                                        match parse_smb2_response_record(&nbss_data) {
                                            IResult::Done(nbss_data_rem, ref smb_record) => {
                                                smb2_response_record(self, smb_record);
                                                nbss_data = nbss_data_rem;
                                            },
                                            _ => {
                                                self.set_event(SMBEvent::MalformedData);
                                                return 1;
                                            },
                                        }
                                    }
                                } else if smb.version == 0xfd_u8 { // SMB3 transform
                                    let mut nbss_data = nbss_hdr.data;
                                    while nbss_data.len() > 0 {
                                        debug!("SMBv3 transform record");
                                        match parse_smb3_transform_record(&nbss_data) {
                                            IResult::Done(nbss_data_rem, ref _smb3_record) => {
                                                nbss_data = nbss_data_rem;
                                            },
                                            _ => {
                                                self.set_event(SMBEvent::MalformedData);
                                                return 1;
                                            },
                                        }
                                    }
                                }
                            },
                            IResult::Incomplete(_) => {
                                // not enough data to contain basic SMB hdr
                                // TODO event: empty NBSS_MSGTYPE_SESSION_MESSAGE
                            },
                            IResult::Error(_) => {
                                self.set_event(SMBEvent::MalformedData);
                                return 1;
                            },
                        }
                    } else {
                        debug!("NBSS message {:X}", nbss_hdr.message_type);
                    }
                    cur_i = rem;
                },
                IResult::Incomplete(needed) => {
                    debug!("INCOMPLETE have {} needed {:?}", cur_i.len(), needed);
                    let consumed = self.parse_tcp_data_tc_partial(cur_i);
                    cur_i = &cur_i[consumed ..];
                    debug!("INCOMPLETE have {}", cur_i.len());
                    self.tcp_buffer_tc.extend_from_slice(cur_i);
                    break;
                },
                IResult::Error(_) => {
                    self.set_event(SMBEvent::MalformedData);
                    return 1;
                },
            }
        };
        self.check_gap_resync(max_tx_id);
        self._debug_tx_stats();
        0
    }
pub fn parse_tcp_data_tc < ' b > ( & mut self , i : & ' b [ u8 ] ) -> u32 { let max_tx_id = self . tx_id ; let mut v : Vec < u8 > ; // 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 ; debug ! ( " " 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 ) ; if consumed > 0 { if consumed > cur_i . len ( ) as u32 { self . set_event ( SMBEvent :: InternalError ) ; return 1 ; } cur_i = & cur_i [ consumed as usize .. ] ; } // take care of in progress file chunk transfers // and skip buffer beyond it let consumed = self . filetracker_update ( STREAM_TOCLIENT , cur_i , 0 ) ; if consumed > 0 { if consumed > cur_i . len ( ) as u32 { self . set_event ( SMBEvent :: InternalError ) ; return 1 ; } cur_i = & cur_i [ consumed as usize .. ] ; } // gap if self . tc_gap { debug ! ( " " cur_i len ( ) ) ; match search_smb_record ( cur_i ) { IResult :: Done ( _ , pg ) => { debug ! ( " " ) ; let smb2_offset = cur_i . len ( ) - pg . data . len ( ) ; if smb2_offset < 4 { return 0 ; } let nbss_offset = smb2_offset - 4 ; cur_i = & cur_i [ nbss_offset .. ] ; self . tc_gap = false ; } , _ => { debug ! ( " " ) ; self . tcp_buffer_tc . extend_from_slice ( cur_i ) ; return 0 ; } , } } while cur_i . len ( ) > 0 { // min record size match parse_nbss_record ( cur_i ) { IResult :: Done ( rem , ref nbss_hdr ) => { if nbss_hdr . message_type == NBSS_MSGTYPE_SESSION_MESSAGE { // we have the full records size worth of data, // let's parse it match parse_smb_version ( & nbss_hdr . data ) { IResult :: Done ( _ , ref smb ) => { debug ! ( " " smb ) ; if smb . version == 0xff_u8 { // SMB1 debug ! ( " " ) ; match parse_smb_record ( & nbss_hdr . data ) { IResult :: Done ( _ , ref smb_record ) => { smb1_response_record ( self , smb_record ) ; } , _ => { self . set_event ( SMBEvent :: MalformedData ) ; return 1 ; } , } } else if smb . version == 0xfe_u8 { // SMB2 let mut nbss_data = nbss_hdr . data ; while nbss_data . len ( ) > 0 { debug ! ( " " ) ; match parse_smb2_response_record ( & nbss_data ) { IResult :: Done ( nbss_data_rem , ref smb_record ) => { smb2_response_record ( self , smb_record ) ; nbss_data = nbss_data_rem ; } , _ => { self . set_event ( SMBEvent :: MalformedData ) ; return 1 ; } , } } } else if smb . version == 0xfd_u8 { // SMB3 transform let mut nbss_data = nbss_hdr . data ; while nbss_data . len ( ) > 0 { debug ! ( " " ) ; match parse_smb3_transform_record ( & nbss_data ) { IResult :: Done ( nbss_data_rem , ref _smb3_record ) => { nbss_data = nbss_data_rem ; } , _ => { self . set_event ( SMBEvent :: MalformedData ) ; return 1 ; } , } } } } , IResult :: Incomplete ( _ ) => { // not enough data to contain basic SMB hdr // TODO event: empty NBSS_MSGTYPE_SESSION_MESSAGE } , IResult :: Error ( _ ) => { self . set_event ( SMBEvent :: MalformedData ) ; return 1 ; } , } } else { debug ! ( " " nbss_hdr message_type ) ; } cur_i = rem ; } , IResult :: Incomplete ( needed ) => { debug ! ( " " cur_i len ( ) needed ) ; let consumed = self . parse_tcp_data_tc_partial ( cur_i ) ; cur_i = & cur_i [ consumed .. ] ; debug ! ( " " cur_i len ( ) ) ; self . tcp_buffer_tc . extend_from_slice ( cur_i ) ; break ; } , IResult :: Error ( _ ) => { self . set_event ( SMBEvent :: MalformedData ) ; return 1 ; } , } } ; self . check_gap_resync ( max_tx_id ) ; self . _debug_tx_stats ( ) ; 0 }
Parsing function, handling TCP chunks fragmentation
Parsing function handling TCP chunks fragmentation
&mut self
i
&'b[u8]