]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/nfs4: improve NFSPROC4_OPEN op parser
authorSam Muhammed <ghostinthehive.vx@gmail.com>
Sun, 20 Feb 2022 10:33:44 +0000 (12:33 +0200)
committerVictor Julien <vjulien@oisf.net>
Fri, 4 Mar 2022 15:50:55 +0000 (16:50 +0100)
Improve nfs4_res_open() parser to reflect other file-delegation types
Reflect the changes on test_nfs4_response_open() unittest

rust/src/nfs/nfs4_records.rs

index 4962b27c7462fa3ecf6afdf17646461e0211e52b..5a8fc685d359fd26d8f026e368c1b37bcfe7233c 100644 (file)
@@ -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<Nfs4ResponseOpenDelegateRead<'a>>,
+    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 {