From: Sam Muhammed Date: Sun, 20 Feb 2022 10:33:44 +0000 (+0200) Subject: rust/nfs4: improve NFSPROC4_OPEN op parser X-Git-Tag: suricata-7.0.0-beta1~820 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fe7a49b7378618721bf27c616d0cb9bd1fcf386b;p=thirdparty%2Fsuricata.git rust/nfs4: improve NFSPROC4_OPEN op parser Improve nfs4_res_open() parser to reflect other file-delegation types Reflect the changes on test_nfs4_response_open() unittest --- diff --git a/rust/src/nfs/nfs4_records.rs b/rust/src/nfs/nfs4_records.rs index 4962b27c74..5a8fc685d3 100644 --- a/rust/src/nfs/nfs4_records.rs +++ b/rust/src/nfs/nfs4_records.rs @@ -25,6 +25,11 @@ use nom7::{Err, IResult}; use crate::nfs::types::*; +/*https://datatracker.ietf.org/doc/html/rfc7530 - section 16.16 File Delegation Types */ +const OPEN_DELEGATE_NONE: u32 = 0; +const OPEN_DELEGATE_READ: u32 = 1; +const OPEN_DELEGATE_WRITE: u32 = 2; + // Maximum number of operations per compound // Linux defines NFSD_MAX_OPS_PER_COMPOUND to 16 (tested in Linux 5.15.1). const NFSD_MAX_OPS_PER_COMPOUND: usize = 64; @@ -550,8 +555,35 @@ fn nfs4_res_read(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> { pub struct Nfs4ResponseOpen<'a> { pub stateid: Nfs4StateId<'a>, pub result_flags: u32, - pub delegation_type: u32, - pub delegate_read: Option>, + pub delegate: Nfs4ResponseFileDelegation<'a>, +} + +#[derive(Debug, PartialEq)] +pub enum Nfs4ResponseFileDelegation<'a> { + DelegateRead(Nfs4ResponseOpenDelegateRead<'a>), + DelegateWrite(Nfs4ResponseOpenDelegateWrite<'a>), + DelegateNone(u32), +} + +#[derive(Debug, PartialEq)] +pub struct Nfs4ResponseOpenDelegateWrite<'a> { + pub stateid: Nfs4StateId<'a>, + pub who: &'a[u8], +} + +fn nfs4_res_open_ok_delegate_write(i: &[u8]) -> IResult<&[u8], Nfs4ResponseFileDelegation> { + let (i, stateid) = nfs4_parse_stateid(i)?; + let (i, _recall) = be_u32(i)?; + let (i, _space_limit) = be_u32(i)?; + let (i, _filesize) = be_u32(i)?; + let (i, _access_type) = be_u32(i)?; + let (i, _ace_flags) = be_u32(i)?; + let (i, _ace_mask) = be_u32(i)?; + let (i, who) = nfs4_parse_nfsstring(i)?; + Ok((i, Nfs4ResponseFileDelegation::DelegateWrite(Nfs4ResponseOpenDelegateWrite { + stateid, + who, + }))) } #[derive(Debug,PartialEq)] @@ -559,7 +591,7 @@ pub struct Nfs4ResponseOpenDelegateRead<'a> { pub stateid: Nfs4StateId<'a>, } -fn nfs4_res_open_ok_delegate_read(i: &[u8]) -> IResult<&[u8], Nfs4ResponseOpenDelegateRead> { +fn nfs4_res_open_ok_delegate_read(i: &[u8]) -> IResult<&[u8], Nfs4ResponseFileDelegation> { let (i, stateid) = nfs4_parse_stateid(i)?; let (i, _recall) = be_u32(i)?; let (i, _ace_type) = be_u32(i)?; @@ -567,7 +599,20 @@ fn nfs4_res_open_ok_delegate_read(i: &[u8]) -> IResult<&[u8], Nfs4ResponseOpenDe let (i, _ace_mask) = be_u32(i)?; let (i, who_len) = be_u32(i)?; let (i, _who) = take(who_len as usize)(i)?; - Ok((i, Nfs4ResponseOpenDelegateRead { stateid })) + Ok((i, Nfs4ResponseFileDelegation::DelegateRead(Nfs4ResponseOpenDelegateRead { + stateid, + }))) +} + +fn nfs4_parse_file_delegation(i: &[u8]) -> IResult<&[u8], Nfs4ResponseFileDelegation> { + let (i, delegation_type) = be_u32(i)?; + let (i, file_delegation) = match delegation_type { + OPEN_DELEGATE_READ => nfs4_res_open_ok_delegate_read(i)?, + OPEN_DELEGATE_WRITE => nfs4_res_open_ok_delegate_write(i)?, + OPEN_DELEGATE_NONE => (i, Nfs4ResponseFileDelegation::DelegateNone(OPEN_DELEGATE_NONE)), + _ => { return Err(Err::Error(make_error(i, ErrorKind::Switch))); } + }; + Ok((i, file_delegation)) } fn nfs4_res_open_ok(i: &[u8]) -> IResult<&[u8], Nfs4ResponseOpen> { @@ -575,13 +620,11 @@ fn nfs4_res_open_ok(i: &[u8]) -> IResult<&[u8], Nfs4ResponseOpen> { let (i, _change_info) = take(20_usize)(i)?; let (i, result_flags) = be_u32(i)?; let (i, _attrs) = nfs4_parse_attrbits(i)?; - let (i, delegation_type) = be_u32(i)?; - let (i, delegate_read) = cond(delegation_type == 1, nfs4_res_open_ok_delegate_read)(i)?; + let (i, delegate) = nfs4_parse_file_delegation(i)?; let resp = Nfs4ResponseOpen { stateid, result_flags, - delegation_type, - delegate_read + delegate, }; Ok((i, resp)) } @@ -1185,29 +1228,31 @@ mod tests { 0x5b, 0x00, 0x88, 0xd9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x16, 0xf8, 0x2f, 0xd5, /*_change_info*/ 0xdb, 0xb7, 0xfe, 0x38, 0x16, 0xf8, 0x2f, 0xdf, - 0x21, 0xa8, 0x2a, 0x48, - 0x00, 0x00, 0x00, 0x04, /*result_flags*/ - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, /*_attrs*/ + 0x21, 0xa8, 0x2a, 0x48, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, /*_attrs*/ + 0x00, 0x00, 0x00, 0x00, + // delegate_write 0x00, 0x00, 0x00, 0x02, /*delegation_type*/ - // delegate_read - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x82, 0x14, 0xe0, 0x5b, 0x00, 0x89, 0xd9, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, ]; let stateid_buf = &buf[8..24]; let (_, res_stateid) = nfs4_parse_stateid(stateid_buf).unwrap(); + let delegate_buf = &buf[64..]; + let (_, delegate) = nfs4_parse_file_delegation(delegate_buf).unwrap(); + let open_data_buf = &buf[8..]; let (_, res_open_data) = nfs4_res_open_ok(open_data_buf).unwrap(); assert_eq!(res_open_data.stateid, res_stateid); assert_eq!(res_open_data.result_flags, 4); - assert_eq!(res_open_data.delegation_type, 2); - assert_eq!(res_open_data.delegate_read, None); + assert_eq!(res_open_data.delegate, delegate); let (_, response) = nfs4_res_open(&buf[4..]).unwrap(); match response {