suricata/smb/
smb2_ioctl.rs1use crate::smb::smb::*;
19use crate::smb::smb2::*;
20use crate::smb::smb2_records::*;
21use crate::smb::dcerpc::*;
22use crate::smb::events::*;
23#[cfg(feature = "debug")]
24use crate::smb::funcs::*;
25use crate::smb::smb_status::*;
26
27#[derive(Debug)]
28pub struct SMBTransactionIoctl {
29 pub func: u32,
30}
31
32impl SMBTransactionIoctl {
33 pub fn new(func: u32) -> Self {
34 return Self {
35 func,
36 };
37 }
38}
39
40impl SMBState {
41 pub fn new_ioctl_tx(&mut self, hdr: SMBCommonHdr, func: u32)
42 -> &mut SMBTransaction
43 {
44 let mut tx = self.new_tx();
45 tx.hdr = hdr;
46 tx.type_data = Some(SMBTransactionTypeData::IOCTL(
47 SMBTransactionIoctl::new(func)));
48 tx.request_done = true;
49 tx.response_done = self.tc_trunc; SCLogDebug!("SMB: TX IOCTL created: ID {} FUNC {:08x}: {}",
52 tx.id, func, &fsctl_func_to_string(func));
53 self.transactions.push_back(tx);
54 let tx_ref = self.transactions.back_mut();
55 return tx_ref.unwrap();
56 }
57}
58
59pub fn smb2_ioctl_request_record(state: &mut SMBState, r: &Smb2Record)
61{
62 let hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_HEADER);
63 match parse_smb2_request_ioctl(r.data) {
64 Ok((_, rd)) => {
65 SCLogDebug!("IOCTL request data: {:?}", rd);
66 let is_dcerpc = if rd.is_pipe {
67 state.get_service_for_guid(rd.guid).1
68 } else {
69 false
70 };
71 if is_dcerpc {
72 SCLogDebug!("IOCTL request data is_pipe. Calling smb_write_dcerpc_record");
73 let vercmd = SMBVerCmdStat::new2(SMB2_COMMAND_IOCTL);
74 smb_write_dcerpc_record(state, vercmd, hdr, rd.data);
75 } else {
76 SCLogDebug!("IOCTL {:08x} {}", rd.function, &fsctl_func_to_string(rd.function));
77 let tx = state.new_ioctl_tx(hdr, rd.function);
78 tx.vercmd.set_smb2_cmd(SMB2_COMMAND_IOCTL);
79 }
80 },
81 _ => {
82 let tx = state.new_generic_tx(2, r.command, hdr);
83 tx.set_event(SMBEvent::MalformedData);
84 },
85 };
86}
87
88pub fn smb2_ioctl_response_record(state: &mut SMBState, r: &Smb2Record)
90{
91 let hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_HEADER);
92 match parse_smb2_response_ioctl(r.data) {
93 Ok((_, rd)) => {
94 SCLogDebug!("IOCTL response data: {:?}", rd);
95
96 let is_dcerpc = if rd.is_pipe {
97 state.get_service_for_guid(rd.guid).1
98 } else {
99 false
100 };
101 #[allow(clippy::collapsible_else_if)]
103 if is_dcerpc {
104 SCLogDebug!("IOCTL response data is_pipe. Calling smb_read_dcerpc_record");
105 let vercmd = SMBVerCmdStat::new2_with_ntstatus(SMB2_COMMAND_IOCTL, r.nt_status);
106 SCLogDebug!("TODO passing empty GUID");
107 smb_read_dcerpc_record(state, vercmd, hdr, &[],rd.data);
108 } else {
109 SCLogDebug!("SMB2_COMMAND_IOCTL/SMB_NTSTATUS_PENDING looking for {:?}", hdr);
110 if let Some(tx) = state.get_generic_tx(2, SMB2_COMMAND_IOCTL, &hdr) {
111 tx.set_status(r.nt_status, false);
112 if r.nt_status != SMB_NTSTATUS_PENDING {
113 tx.response_done = true;
114 }
115 }
116 }
117 },
118 _ => {
119 SCLogDebug!("SMB2_COMMAND_IOCTL/SMB_NTSTATUS_PENDING looking for {:?}", hdr);
120 if let Some(tx) = state.get_generic_tx(2, SMB2_COMMAND_IOCTL, &hdr) {
121 SCLogDebug!("updated status of tx {}", tx.id);
122 tx.set_status(r.nt_status, false);
123 if r.nt_status != SMB_NTSTATUS_PENDING {
124 tx.response_done = true;
125 }
126
127 if r.nt_status == SMB_NTSTATUS_SUCCESS {
129 SCLogDebug!("parse fail {:?}", r);
130 tx.set_event(SMBEvent::MalformedData);
131 }
132 }
133 },
134 };
135}