Ok((_, rd)) => {
SCLogDebug!("SMB2_COMMAND_SET_INFO: {:?}", rd);
- if let Some(ref ren) = rd.rename {
- let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX);
- let mut newname = ren.name.to_vec();
- newname.retain(|&i|i != 0x00);
- let oldname = match state.guid2name_map.get(rd.guid) {
- Some(n) => { n.to_vec() },
- None => { b"<unknown>".to_vec() },
- };
- let tx = state.new_rename_tx(rd.guid.to_vec(), oldname, newname);
- tx.hdr = tx_hdr;
- tx.request_done = true;
- tx.vercmd.set_smb2_cmd(SMB2_COMMAND_SET_INFO);
- true
- } else {
- false
+ match rd.data {
+ Smb2SetInfoRequestData::RENAME(ref ren) => {
+ let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX);
+ let mut newname = ren.name.to_vec();
+ newname.retain(|&i|i != 0x00);
+ let oldname = match state.guid2name_map.get(rd.guid) {
+ Some(n) => { n.to_vec() },
+ None => { b"<unknown>".to_vec() },
+ };
+ let tx = state.new_rename_tx(rd.guid.to_vec(), oldname, newname);
+ tx.hdr = tx_hdr;
+ tx.request_done = true;
+ tx.vercmd.set_smb2_cmd(SMB2_COMMAND_SET_INFO);
+ true
+ }
+ Smb2SetInfoRequestData::DISPOSITION(ref dis) => {
+ let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX);
+ let fname = match state.guid2name_map.get(rd.guid) {
+ Some(n) => { n.to_vec() },
+ None => { b"<unknown>".to_vec() },
+ };
+ let tx = state.new_setfileinfo_tx(fname, rd.guid.to_vec(), rd.class as u16, rd.infolvl as u16, dis.delete);
+ tx.hdr = tx_hdr;
+ tx.request_done = true;
+ tx.vercmd.set_smb2_cmd(SMB2_COMMAND_SET_INFO);
+ true
+ }
+ _ => false,
}
},
Err(nom::Err::Incomplete(_n)) => {
pub name: &'a[u8],
}
-named!(pub parse_smb2_request_setinfo_rename<Smb2SetInfoRequestRenameRecord>,
+named!(pub parse_smb2_request_setinfo_rename<Smb2SetInfoRequestData>,
do_parse!(
_replace: le_u8
>> _reserved: take!(7)
>> _root_handle: take!(8)
>> name_len: le_u32
>> name: take!(name_len)
- >> (Smb2SetInfoRequestRenameRecord {
+ >> (Smb2SetInfoRequestData::RENAME(Smb2SetInfoRequestRenameRecord {
name
- })
+ }))
+));
+
+#[derive(Debug)]
+pub struct Smb2SetInfoRequestDispoRecord {
+ pub delete: bool,
+}
+
+named!(pub parse_smb2_request_setinfo_disposition<&[u8], Smb2SetInfoRequestData>,
+ do_parse!(
+ info: le_u8 >>
+ (Smb2SetInfoRequestData::DISPOSITION(Smb2SetInfoRequestDispoRecord {
+ delete: info & 1 != 0,
+ }))
));
+#[derive(Debug)]
+pub enum Smb2SetInfoRequestData<'a> {
+ DISPOSITION(Smb2SetInfoRequestDispoRecord),
+ RENAME(Smb2SetInfoRequestRenameRecord<'a>),
+ UNHANDLED,
+}
+
#[derive(Debug)]
pub struct Smb2SetInfoRequestRecord<'a> {
pub guid: &'a[u8],
pub class: u8,
pub infolvl: u8,
- pub rename: Option<Smb2SetInfoRequestRenameRecord<'a>>,
+ pub data: Smb2SetInfoRequestData<'a>,
+}
+
+fn parse_smb2_request_setinfo_data(
+ i: &[u8], class: u8, infolvl: u8,
+) -> IResult<&[u8], Smb2SetInfoRequestData> {
+ if class == 1 {
+ // constants from [MS-FSCC] section 2.4
+ match infolvl {
+ 10 => {
+ return parse_smb2_request_setinfo_rename(i);
+ }
+ 0xd => {
+ return parse_smb2_request_setinfo_disposition(i);
+ }
+ _ => {}
+ }
+ }
+ return Ok((i, Smb2SetInfoRequestData::UNHANDLED));
}
named!(pub parse_smb2_request_setinfo<Smb2SetInfoRequestRecord>,
>> _reserved: take!(2)
>> _additional_info: le_u32
>> guid: take!(16)
- >> rename: cond!(class == 1 && infolvl == 10, flat_map!(take!(setinfo_size),parse_smb2_request_setinfo_rename))
+ >> data: flat_map!(take!(setinfo_size), call!(parse_smb2_request_setinfo_data, class, infolvl))
>> (Smb2SetInfoRequestRecord {
guid: guid,
class: class,
infolvl: infolvl,
- rename: rename,
+ data: data,
})
));