Coverage Report

Created: 2026-09-28 07:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/rust/src/smb/dcerpc.rs
Line
Count
Source
1
/* Copyright (C) 2017-2026 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
// written by Victor Julien
19
20
use uuid;
21
use crate::smb::smb::{cfg_max_stub_size, *};
22
use crate::smb::smb2::*;
23
use crate::smb::dcerpc_records::*;
24
use crate::smb::events::*;
25
use crate::dcerpc::dcerpc::*;
26
use crate::smb::smb_status::*;
27
28
impl SMBCommonHdr {
29
    /// helper for DCERPC tx tracking. Check if we need
30
    /// to use the msg_id/multiplex_id in TX tracking.
31
    ///
32
50.3k
    pub fn to_dcerpc(&self, vercmd: &SMBVerCmdStat) -> SMBCommonHdr {
33
        // only use the msg id for IOCTL, not for READ/WRITE
34
        // as there request/response are different transactions
35
50.3k
        let mut use_msg_id = self.msg_id;
36
50.3k
        match vercmd.get_version() {
37
            2 => {
38
49.7k
                let (_, cmd2) = vercmd.get_smb2_cmd();
39
49.7k
                let x = match cmd2 {
40
23.4k
                    SMB2_COMMAND_READ => { 0 },
41
26.3k
                    SMB2_COMMAND_WRITE => { 0 },
42
2
                    SMB2_COMMAND_IOCTL => { self.msg_id },
43
0
                    _ => { self.msg_id },
44
                };
45
49.7k
                use_msg_id = x;
46
            },
47
636
            1 => {
48
636
                SCLogDebug!("FIXME TODO");
49
636
                //let (_, cmd1) = vercmd.get_smb1_cmd();
50
636
                //if cmd1 != SMB1_COMMAND_IOCTL {
51
636
                use_msg_id = 0;
52
636
                //}
53
636
            },
54
0
            _ => { },
55
        }
56
50.3k
        SMBCommonHdr {
57
50.3k
            ssn_id: self.ssn_id,
58
50.3k
            tree_id: self.tree_id,
59
50.3k
            msg_id: use_msg_id,
60
50.3k
            rec_type: SMBHDR_TYPE_DCERPCTX,
61
50.3k
        }
62
50.3k
    }
63
}
64
65
#[derive(Default, Debug)]
66
pub struct DCERPCIface {
67
    pub uuid: Vec<u8>,
68
    pub ver: u16,
69
    pub ver_min: u16,
70
    pub ack_result: u16,
71
    pub ack_reason: u16,
72
    pub acked: bool,
73
    pub context_id: u16,
74
}
75
76
impl DCERPCIface {
77
20.5k
    pub fn new(uuid: Vec<u8>, ver: u16, ver_min: u16, context_id: u16) -> Self {
78
20.5k
        Self {
79
20.5k
            uuid,
80
20.5k
            ver,
81
20.5k
            ver_min,
82
20.5k
            context_id,
83
20.5k
            ..Default::default()
84
20.5k
        }
85
20.5k
    }
86
}
87
88
#[derive(Default, Debug)]
89
pub struct SMBTransactionDCERPC {
90
    pub opnum: u16,
91
    pub context_id: u16,
92
    pub req_cmd: u8,
93
    pub req_set: bool,
94
    pub res_cmd: u8,
95
    pub res_set: bool,
96
    pub call_id: u32,
97
    pub frag_cnt_ts: u16,
98
    pub frag_cnt_tc: u16,
99
    pub stub_data_ts: Vec<u8>,
100
    pub stub_data_tc: Vec<u8>,
101
}
102
103
impl SMBTransactionDCERPC {
104
14.9k
    fn new_request(req: u8, call_id: u32) -> Self {
105
14.9k
        return Self {
106
14.9k
            opnum: 0,
107
14.9k
            context_id: 0,
108
14.9k
            req_cmd: req,
109
14.9k
            req_set: true,
110
14.9k
            call_id,
111
14.9k
            ..Default::default()
112
14.9k
        }
113
14.9k
    }
114
461
    fn new_response(call_id: u32) -> Self {
115
461
       return  Self {
116
461
            call_id,
117
461
            ..Default::default()
118
461
        };
119
461
    }
120
1.37k
    pub fn set_result(&mut self, res: u8) {
121
1.37k
        self.res_set = true;
122
1.37k
        self.res_cmd = res;
123
1.37k
    }
124
}
125
126
impl SMBState {
127
14.9k
    fn new_dcerpc_tx(&mut self, hdr: SMBCommonHdr, vercmd: SMBVerCmdStat, cmd: u8, call_id: u32)
128
14.9k
        -> Option<&mut SMBTransaction>
129
    {
130
14.9k
        let mut tx = self.new_tx()?;
131
14.9k
        tx.hdr = hdr;
132
14.9k
        tx.vercmd = vercmd;
133
14.9k
        tx.type_data = Some(SMBTransactionTypeData::DCERPC(
134
14.9k
                    SMBTransactionDCERPC::new_request(cmd, call_id)));
135
136
        SCLogDebug!("SMB: TX DCERPC created: ID {} hdr {:?}", tx.id, tx.hdr);
137
14.9k
        self.transactions.push_back(tx);
138
14.9k
        self.transactions.back_mut()
139
14.9k
    }
140
141
461
    fn new_dcerpc_tx_for_response(&mut self, hdr: SMBCommonHdr, vercmd: SMBVerCmdStat, call_id: u32)
142
461
        -> Option<&mut SMBTransaction>
143
    {
144
461
        let mut tx = self.new_tx()?;
145
461
        tx.hdr = hdr;
146
461
        tx.vercmd = vercmd;
147
461
        tx.type_data = Some(SMBTransactionTypeData::DCERPC(
148
461
                    SMBTransactionDCERPC::new_response(call_id)));
149
150
        SCLogDebug!("SMB: TX DCERPC created: ID {} hdr {:?}", tx.id, tx.hdr);
151
461
        self.transactions.push_back(tx);
152
461
        self.transactions.back_mut()
153
461
    }
154
155
3.40k
    fn get_dcerpc_tx(&mut self, hdr: &SMBCommonHdr, vercmd: &SMBVerCmdStat, call_id: u32)
156
3.40k
        -> Option<&mut SMBTransaction>
157
    {
158
3.40k
        let dce_hdr = hdr.to_dcerpc(vercmd);
159
160
        SCLogDebug!("looking for {:?}", dce_hdr);
161
48.4k
        for tx in &mut self.transactions {
162
46.9k
            let found = dce_hdr.compare(&tx.hdr.to_dcerpc(vercmd)) &&
163
4.15k
                match tx.type_data {
164
4.02k
                Some(SMBTransactionTypeData::DCERPC(ref x)) => {
165
4.02k
                    x.call_id == call_id
166
                },
167
1.46k
                _ => { false },
168
            };
169
46.9k
            if found {
170
1.90k
                tx.tx_data.updated_tc = true;
171
1.90k
                tx.tx_data.updated_ts = true;
172
1.90k
                return Some(tx);
173
45.0k
            }
174
        }
175
1.50k
        return None;
176
3.40k
    }
177
}
178
179
/// Handle DCERPC request data from a WRITE, IOCTL or TRANS record.
180
/// return bool indicating whether an tx has been created/updated.
181
///
182
21.1k
pub fn smb_write_dcerpc_record(state: &mut SMBState,
183
21.1k
        vercmd: SMBVerCmdStat,
184
21.1k
        hdr: SMBCommonHdr,
185
21.1k
        data: &[u8]) -> bool
186
{
187
21.1k
    let mut bind_ifaces : Option<Vec<DCERPCIface>> = None;
188
21.1k
    let mut is_bind = false;
189
190
    SCLogDebug!("called for {} bytes of data", data.len());
191
21.1k
    match parse_dcerpc_record(data) {
192
20.7k
        Ok((_, dcer)) => {
193
            SCLogDebug!("DCERPC: version {}.{} write data {} => {:?}",
194
                    dcer.version_major, dcer.version_minor, dcer.data.len(), dcer);
195
196
            /* if this isn't the first frag, simply update the existing
197
             * tx with the additional stub data */
198
20.7k
            if dcer.packet_type == DCERPC_TYPE_REQUEST && !dcer.first_frag {
199
                SCLogDebug!("NOT the first frag. Need to find an existing TX");
200
5.79k
                match parse_dcerpc_request_record(dcer.data, dcer.frag_len, dcer.little_endian) {
201
1.70k
                    Ok((_, recr)) => {
202
1.70k
                        let found = match state.get_dcerpc_tx(&hdr, &vercmd, dcer.call_id) {
203
669
                            Some(tx) => {
204
                                SCLogDebug!("previous CMD {} found at tx {} => {:?}",
205
                                        dcer.packet_type, tx.id, tx);
206
669
                                if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
207
669
                                    tdn.frag_cnt_ts = tdn.frag_cnt_ts.saturating_add(1);
208
669
                                    let max_size = cfg_max_stub_size() as usize;
209
669
                                    if recr.data.len() + tdn.stub_data_ts.len() < max_size {
210
669
                                        SCLogDebug!("additional frag of size {}", recr.data.len());
211
669
                                        tdn.stub_data_ts.extend_from_slice(recr.data);
212
669
                                        SCLogDebug!("stub_data now {}", tdn.stub_data_ts.len());
213
669
                                    } else if tdn.stub_data_ts.len() < max_size {
214
0
                                        tdn.stub_data_ts.extend_from_slice(&recr.data[..max_size - tdn.stub_data_ts.len()]);
215
0
                                    }
216
0
                                }
217
669
                                if dcer.last_frag {
218
1
                                    SCLogDebug!("last frag set, so request side of DCERPC closed");
219
1
                                    tx.request_done = true;
220
668
                                } else {
221
668
                                    SCLogDebug!("NOT last frag, so request side of DCERPC remains open");
222
668
                                }
223
669
                                true
224
                            },
225
                            None => {
226
                                SCLogDebug!("NO previous CMD {} found", dcer.packet_type);
227
1.03k
                                false
228
                            },
229
                        };
230
1.70k
                        return found;
231
                    },
232
                    _ => {
233
4.09k
                        state.set_event(SMBEvent::MalformedData);
234
4.09k
                        return false;
235
                    },
236
                }
237
14.9k
            }
238
239
14.9k
            let Some(tx) = state.new_dcerpc_tx(hdr, vercmd, dcer.packet_type, dcer.call_id) else {
240
47
                return false;
241
            };
242
14.9k
            match dcer.packet_type {
243
                DCERPC_TYPE_REQUEST => {
244
1.60k
                    match parse_dcerpc_request_record(dcer.data, dcer.frag_len, dcer.little_endian) {
245
232
                        Ok((_, recr)) => {
246
                            SCLogDebug!("DCERPC: REQUEST {:?}", recr);
247
232
                            if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
248
                                SCLogDebug!("first frag size {}", recr.data.len());
249
232
                                tdn.opnum = recr.opnum;
250
232
                                tdn.context_id = recr.context_id;
251
232
                                tdn.frag_cnt_ts = tdn.frag_cnt_ts.saturating_add(1);
252
232
                                let max_size = cfg_max_stub_size() as usize;
253
232
                                if tdn.stub_data_ts.len() + recr.data.len() < max_size {
254
232
                                    tdn.stub_data_ts.extend_from_slice(recr.data);
255
232
                                    SCLogDebug!("DCERPC: REQUEST opnum {} stub data len {}",
256
232
                                            tdn.opnum, tdn.stub_data_ts.len());
257
232
                                } else if tdn.stub_data_ts.len() < max_size {
258
0
                                    tdn.stub_data_ts.extend_from_slice(&recr.data[..max_size - tdn.stub_data_ts.len()]);
259
0
                                }
260
0
                            }
261
232
                            if dcer.last_frag {
262
174
                                tx.request_done = true;
263
174
                            } else {
264
58
                                SCLogDebug!("NOT last frag, so request side of DCERPC remains open");
265
58
                            }
266
                        },
267
1.37k
                        _ => {
268
1.37k
                            tx.set_event(SMBEvent::MalformedData);
269
1.37k
                            tx.request_done = true;
270
1.37k
                        },
271
                    }
272
                },
273
                DCERPC_TYPE_BIND => {
274
11.9k
                    let brec = if dcer.little_endian {
275
7.50k
                        parse_dcerpc_bind_record(dcer.data)
276
                    } else {
277
4.39k
                        parse_dcerpc_bind_record_big(dcer.data)
278
                    };
279
11.9k
                    match brec {
280
1.44k
                        Ok((_, bindr)) => {
281
1.44k
                            is_bind = true;
282
                            SCLogDebug!("SMB DCERPC {:?} BIND {:?}", dcer, bindr);
283
284
1.44k
                            if !bindr.ifaces.is_empty() {
285
1.02k
                                let mut ifaces: Vec<DCERPCIface> = Vec::new();
286
21.5k
                                for i in bindr.ifaces {
287
20.5k
                                    let x = if dcer.little_endian {
288
9.69k
                                        vec![i.iface[3],  i.iface[2],  i.iface[1],  i.iface[0],
289
9.69k
                                             i.iface[5],  i.iface[4],  i.iface[7],  i.iface[6],
290
9.69k
                                             i.iface[8],  i.iface[9],  i.iface[10], i.iface[11],
291
9.69k
                                             i.iface[12], i.iface[13], i.iface[14], i.iface[15]]
292
                                    } else {
293
10.8k
                                        i.iface.to_vec()
294
                                    };
295
20.5k
                                    let uuid_str = uuid::Uuid::from_slice(&x.clone());
296
20.5k
                                    let _uuid_str = uuid_str.map(|uuid_str| uuid_str.to_hyphenated().to_string()).unwrap();
297
20.5k
                                    let d = DCERPCIface::new(x,i.ver,i.ver_min,i.ctx_id);
298
                                    SCLogDebug!("UUID {} version {}/{} bytes {:?}",
299
                                            _uuid_str,
300
                                            i.ver, i.ver_min,i.iface);
301
20.5k
                                    ifaces.push(d);
302
                                }
303
1.02k
                                bind_ifaces = Some(ifaces);
304
423
                            }
305
                        },
306
10.4k
                        _ => {
307
10.4k
                            tx.set_event(SMBEvent::MalformedData);
308
10.4k
                        },
309
                    }
310
11.9k
                    tx.request_done = true;
311
                }
312
738
                21..=255 => {
313
738
                    tx.set_event(SMBEvent::MalformedData);
314
738
                    tx.request_done = true;
315
738
                },
316
671
                _ => {
317
671
                    // valid type w/o special processing
318
671
                    tx.request_done = true;
319
671
                },
320
            }
321
        },
322
444
        _ => {
323
444
            state.set_event(SMBEvent::MalformedData);
324
444
        },
325
    }
326
327
15.3k
    if is_bind {
328
1.44k
        // We have to write here the interfaces
329
1.44k
        // rather than in the BIND block
330
1.44k
        // due to borrow issues with the tx mutable reference
331
1.44k
        // that is part of the state
332
1.44k
        state.dcerpc_ifaces = bind_ifaces; // TODO store per ssn
333
13.9k
    }
334
15.3k
    return true;
335
21.1k
}
336
337
/// Update TX for bind ack. Needs to update both tx and state.
338
///
339
1.36k
fn smb_dcerpc_response_bindack(
340
1.36k
        state: &mut SMBState,
341
1.36k
        vercmd: SMBVerCmdStat,
342
1.36k
        hdr: SMBCommonHdr,
343
1.36k
        dcer: &DceRpcRecord,
344
1.36k
        ntstatus: u32)
345
{
346
1.36k
    match parse_dcerpc_bindack_record(dcer.data) {
347
32
        Ok((_, bindackr)) => {
348
            SCLogDebug!("SMB READ BINDACK {:?}", bindackr);
349
350
32
            let found = match state.get_dcerpc_tx(&hdr, &vercmd, dcer.call_id) {
351
22
                Some(tx) => {
352
22
                    if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
353
22
                        tdn.set_result(DCERPC_TYPE_BINDACK);
354
22
                    }
355
22
                    tx.vercmd.set_ntstatus(ntstatus);
356
22
                    tx.response_done = true;
357
22
                    true
358
                },
359
10
                None => false,
360
            };
361
32
            if found {
362
22
                if let Some(ref mut ifaces) = state.dcerpc_ifaces {
363
5
                    for (i, r) in bindackr.results.into_iter().enumerate() {
364
5
                        if i >= ifaces.len() {
365
                            // TODO set event: more acks that requests
366
0
                            break;
367
5
                        }
368
5
                        ifaces[i].ack_result = r.ack_result;
369
5
                        ifaces[i].acked = true;
370
                    }
371
18
                }
372
10
            }
373
        },
374
1.33k
        _ => {
375
1.33k
            state.set_event(SMBEvent::MalformedData);
376
1.33k
        },
377
    }
378
1.36k
}
379
380
0
fn smb_read_dcerpc_record_error(state: &mut SMBState,
381
0
        hdr: SMBCommonHdr, vercmd: SMBVerCmdStat, ntstatus: u32)
382
0
    -> bool
383
{
384
0
    let ver = vercmd.get_version();
385
0
    let cmd = if ver == 2 {
386
0
        let (_, c) = vercmd.get_smb2_cmd();
387
0
        c
388
    } else {
389
0
        let (_, c) = vercmd.get_smb1_cmd();
390
0
        c as u16
391
    };
392
393
0
    let found = match state.get_generic_tx(ver, cmd, &hdr) {
394
0
        Some(tx) => {
395
            SCLogDebug!("found");
396
0
            tx.set_status(ntstatus, false);
397
0
            tx.response_done = true;
398
0
            true
399
        },
400
        None => {
401
            SCLogDebug!("NOT found");
402
0
            false
403
        },
404
    };
405
0
    return found;
406
0
}
407
408
1.67k
fn dcerpc_response_handle(tx: &mut SMBTransaction,
409
1.67k
        vercmd: SMBVerCmdStat,
410
1.67k
        dcer: &DceRpcRecord)
411
{
412
1.67k
    let (_, ntstatus) = vercmd.get_ntstatus();
413
1.67k
    match dcer.packet_type {
414
        DCERPC_TYPE_RESPONSE => {
415
486
            match parse_dcerpc_response_record(dcer.data, dcer.frag_len) {
416
166
                Ok((_, respr)) => {
417
                    SCLogDebug!("SMBv1 READ RESPONSE {:?}", respr);
418
166
                    if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
419
                        SCLogDebug!("CMD 11 found at tx {}", tx.id);
420
166
                        tdn.set_result(DCERPC_TYPE_RESPONSE);
421
166
                        let max_size = cfg_max_stub_size() as usize;
422
166
                        tdn.frag_cnt_tc = tdn.frag_cnt_tc.saturating_add(1);
423
166
                        if tdn.stub_data_tc.len() + respr.data.len() < max_size {
424
166
                            tdn.stub_data_tc.extend_from_slice(respr.data);
425
166
                        } else if tdn.stub_data_tc.len() < max_size {
426
0
                            tdn.stub_data_tc.extend_from_slice(&respr.data[..max_size - tdn.stub_data_tc.len()]);
427
0
                        }
428
0
                    }
429
166
                    tx.vercmd.set_ntstatus(ntstatus);
430
166
                    tx.response_done = dcer.last_frag;
431
                },
432
320
                _ => {
433
320
                    tx.set_event(SMBEvent::MalformedData);
434
320
                },
435
            }
436
        },
437
0
        DCERPC_TYPE_BINDACK => {
438
0
            // handled elsewhere
439
0
        },
440
199
        21..=255 => {
441
199
            if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
442
199
                tdn.set_result(dcer.packet_type);
443
199
            }
444
199
            tx.vercmd.set_ntstatus(ntstatus);
445
199
            tx.response_done = true;
446
199
            tx.set_event(SMBEvent::MalformedData);
447
        }
448
        _ => { // valid type w/o special processing
449
987
            if let Some(SMBTransactionTypeData::DCERPC(ref mut tdn)) = tx.type_data {
450
987
                tdn.set_result(dcer.packet_type);
451
987
            }
452
987
            tx.vercmd.set_ntstatus(ntstatus);
453
987
            tx.response_done = true;
454
        },
455
    }
456
1.67k
}
457
458
/// Handle DCERPC reply record. Called for READ, TRANS, IOCTL
459
///
460
3.27k
pub fn smb_read_dcerpc_record(state: &mut SMBState,
461
3.27k
        vercmd: SMBVerCmdStat,
462
3.27k
        hdr: SMBCommonHdr,
463
3.27k
        guid: &[u8],
464
3.27k
        indata: &[u8]) -> bool
465
{
466
3.27k
    let (_, ntstatus) = vercmd.get_ntstatus();
467
468
3.27k
    if ntstatus != SMB_NTSTATUS_SUCCESS && ntstatus != SMB_NTSTATUS_BUFFER_OVERFLOW {
469
0
        return smb_read_dcerpc_record_error(state, hdr, vercmd, ntstatus);
470
3.27k
    }
471
472
    SCLogDebug!("lets first see if we have prior data");
473
    // msg_id 0 as this data crosses cmd/reply pairs
474
3.27k
    let ehdr = SMBHashKeyHdrGuid::new(SMBCommonHdr::new(SMBHDR_TYPE_TRANS_FRAG,
475
3.27k
            hdr.ssn_id, hdr.tree_id, 0_u64), guid.to_vec());
476
3.27k
    let mut prevdata = state.dcerpc_rec_frag_cache.pop(&ehdr).unwrap_or_default();
477
    SCLogDebug!("indata {} prevdata {}", indata.len(), prevdata.len());
478
3.27k
    prevdata.extend_from_slice(indata);
479
3.27k
    let data = prevdata;
480
481
3.27k
    let mut malformed = false;
482
483
3.27k
    if data.is_empty() {
484
        SCLogDebug!("weird: no DCERPC data"); // TODO
485
        // TODO set event?
486
140
        return false;
487
488
    } else {
489
3.13k
        match parse_dcerpc_record(&data) {
490
3.03k
            Ok((_, dcer)) => {
491
                SCLogDebug!("DCERPC: version {}.{} read data {} => {:?}",
492
                        dcer.version_major, dcer.version_minor, dcer.data.len(), dcer);
493
494
3.03k
                if ntstatus == SMB_NTSTATUS_BUFFER_OVERFLOW && data.len() < dcer.frag_len as usize {
495
                    SCLogDebug!("short record {} < {}: storing partial data in state",
496
                            data.len(), dcer.frag_len);
497
0
                    state.dcerpc_rec_frag_cache.put(ehdr, data.to_vec());
498
0
                    return true; // TODO review
499
3.03k
                }
500
501
3.03k
                if dcer.packet_type == DCERPC_TYPE_BINDACK {
502
1.36k
                    smb_dcerpc_response_bindack(state, vercmd, hdr, &dcer, ntstatus);
503
1.36k
                    return true;
504
1.67k
                }
505
506
1.67k
                let found = match state.get_dcerpc_tx(&hdr, &vercmd, dcer.call_id) {
507
1.21k
                    Some(tx) => {
508
1.21k
                        dcerpc_response_handle(tx, vercmd.clone(), &dcer);
509
1.21k
                        true
510
                    },
511
                    None => {
512
                        SCLogDebug!("no tx");
513
461
                        false
514
                    },
515
                };
516
1.67k
                if !found {
517
                    // pick up DCERPC tx even if we missed the request
518
461
                    let Some(tx) =
519
461
                        state.new_dcerpc_tx_for_response(hdr, vercmd.clone(), dcer.call_id)
520
                    else {
521
0
                        return false;
522
                    };
523
461
                    dcerpc_response_handle(tx, vercmd, &dcer);
524
1.21k
                }
525
            },
526
100
            _ => {
527
100
                malformed = true;
528
100
            },
529
        }
530
    }
531
532
1.77k
    if malformed {
533
100
        state.set_event(SMBEvent::MalformedData);
534
1.67k
    }
535
536
1.77k
    return true;
537
3.27k
}
538
539
/// Try to find out if the input data looks like DCERPC
540
9.77k
pub fn smb_dcerpc_probe(data: &[u8]) -> bool
541
{
542
9.77k
    if let Ok((_, recr)) = parse_dcerpc_record(data) {
543
        SCLogDebug!("SMB: could be DCERPC {:?}", recr);
544
4.09k
        if recr.version_major == 5 && recr.version_minor < 3 &&
545
1.92k
            recr.frag_len > 0 && recr.packet_type <= 20
546
            {
547
                SCLogDebug!("SMB: looks like we have dcerpc");
548
1.89k
                return true;
549
2.19k
            }
550
5.68k
    }
551
7.88k
    return false;
552
9.77k
}