]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/nfs: add more record types
authorVictor Julien <victor@inliniac.net>
Tue, 23 May 2017 08:10:57 +0000 (10:10 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 6 Jun 2017 08:17:24 +0000 (10:17 +0200)
rust/src/nfs/log.rs
rust/src/nfs/nfs3.rs
rust/src/nfs/parser.rs

index bf98781807074d3db616618ea22bbfaa93a7eaad..116ed58a8fb75783c1fc3dcdd8772ac38b5eca7b 100644 (file)
@@ -36,6 +36,22 @@ pub extern "C" fn rs_nfs3_tx_logging_is_filtered(tx: &mut NFS3Transaction)
     return 0;
 }
 
+fn nfs3_rename_object(tx: &NFS3Transaction) -> Json
+{
+    let js = Json::object();
+    let from_str = String::from_utf8_lossy(&tx.file_name);
+    js.set_string("from", &from_str);
+
+    let to_vec = match tx.type_data {
+        Some(NFS3TransactionTypeData::RENAME(ref x)) => { x.to_vec() },
+        _ => { Vec::new() }
+    };
+
+    let to_str = String::from_utf8_lossy(&to_vec);
+    js.set_string("to", &to_str);
+    return js;
+}
+
 fn nfs3_creds_object(tx: &NFS3Transaction) -> Json
 {
     let js = Json::object();
@@ -100,10 +116,12 @@ pub extern "C" fn rs_nfs3_log_json_response(tx: &mut NFS3Transaction) -> *mut Js
     if tx.procedure == NFSPROC3_READ {
         let read_js = nfs3_read_object(tx);
         js.set("read", read_js);
-    }
-    if tx.procedure == NFSPROC3_WRITE {
+    } else if tx.procedure == NFSPROC3_WRITE {
         let write_js = nfs3_write_object(tx);
         js.set("write", write_js);
+    } else if tx.procedure == NFSPROC3_RENAME {
+        let rename_js = nfs3_rename_object(tx);
+        js.set("rename", rename_js);
     }
 
     return js.unwrap();
index 94019705778a2e428735928beb87e3e21e248783..a582a1b188f6e6317b1861632731edde9ff7a2c5 100644 (file)
@@ -90,12 +90,18 @@ pub static mut suricata_nfs3_file_config: Option<&'static SuricataFileContext> =
  * Transaction lookup.
  */
 
+#[derive(Debug)]
+pub enum NFS3TransactionTypeData {
+    RENAME(Vec<u8>),
+}
 
 #[derive(Debug)]
 pub struct NFS3Transaction {
     pub id: u64,    /// internal id
     pub xid: u32,   /// nfs3 req/reply pair id
     pub procedure: u32,
+    /// file name of the object we're dealing with. In case of RENAME
+    /// this is the 'from' or original name.
     pub file_name: Vec<u8>,
 
     pub request_machine_name: Vec<u8>,
@@ -120,6 +126,8 @@ pub struct NFS3Transaction {
     pub file_tx_direction: u8, // STREAM_TOCLIENT or STREAM_TOSERVER
     pub file_handle: Vec<u8>,
 
+    pub type_data: Option<NFS3TransactionTypeData>,
+
     /// additional procedures part of a single file transfer. Currently
     /// only COMMIT on WRITEs.
     pub file_additional_procs: Vec<u32>,
@@ -155,6 +163,7 @@ impl NFS3Transaction {
             is_file_tx: false,
             file_tx_direction: 0,
             file_handle:Vec::new(),
+            type_data: None,
             file_additional_procs:Vec::new(),
             file_last_xid: 0,
             file_tracker: None,
@@ -391,32 +400,54 @@ impl NFS3State {
         };
     }
 
+    fn xidmap_handle2name(&mut self, xidmap: &mut NFS3RequestXidMap) {
+        match self.namemap.get(&xidmap.file_handle) {
+            Some(n) => {
+                SCLogDebug!("xidmap_handle2name: name {:?}", n);
+                xidmap.file_name = n.to_vec();
+            },
+            _ => {
+                SCLogDebug!("xidmap_handle2name: object {:?} not found",
+                        xidmap.file_handle);
+            },
+        }
+    }
+
     /// complete request record
     fn process_request_record<'b>(&mut self, r: &RpcPacket<'b>) -> u32 {
         SCLogDebug!("REQUEST {} procedure {} ({}) blob size {}",
                 r.hdr.xid, r.procedure, self.requestmap.len(), r.prog_data.len());
 
         let mut xidmap = NFS3RequestXidMap::new(r.procedure, 0);
+        let mut aux_file_name = Vec::new();
 
         if r.procedure == NFSPROC3_LOOKUP {
             self.process_request_record_lookup(r, &mut xidmap);
 
+        } else if r.procedure == NFSPROC3_ACCESS {
+            match parse_nfs3_request_access(r.prog_data) {
+                IResult::Done(_, ar) => {
+                    xidmap.file_handle = ar.handle.value.to_vec();
+                    self.xidmap_handle2name(&mut xidmap);
+                },
+                IResult::Incomplete(_) => { panic!("WEIRD"); },
+                IResult::Error(e) => { panic!("Parsing failed: {:?}",e);  },
+            };
+        } else if r.procedure == NFSPROC3_GETATTR {
+            match parse_nfs3_request_getattr(r.prog_data) {
+                IResult::Done(_, gar) => {
+                    xidmap.file_handle = gar.handle.value.to_vec();
+                    self.xidmap_handle2name(&mut xidmap);
+                },
+                IResult::Incomplete(_) => { panic!("WEIRD"); },
+                IResult::Error(e) => { panic!("Parsing failed: {:?}",e);  },
+            };
         } else if r.procedure == NFSPROC3_READ {
             match parse_nfs3_request_read(r.prog_data) {
                 IResult::Done(_, nfs3_read_record) => {
                     xidmap.chunk_offset = nfs3_read_record.offset;
                     xidmap.file_handle = nfs3_read_record.handle.value.to_vec();
-
-                    match self.namemap.get(nfs3_read_record.handle.value) {
-                        Some(n) => {
-                            SCLogDebug!("READ name {:?}", n);
-                            xidmap.file_name = n.to_vec();
-                        },
-                        _ => {
-                            SCLogDebug!("READ object {:?} not found",
-                                    nfs3_read_record.handle.value);
-                        },
-                    }
+                    self.xidmap_handle2name(&mut xidmap);
                 },
                 IResult::Incomplete(_) => { panic!("WEIRD"); },
                 IResult::Error(e) => { panic!("Parsing failed: {:?}",e);  },
@@ -432,12 +463,34 @@ impl NFS3State {
         } else if r.procedure == NFSPROC3_CREATE {
             match parse_nfs3_request_create(r.prog_data) {
                 IResult::Done(_, nfs3_create_record) => {
+                    xidmap.file_handle = nfs3_create_record.handle.value.to_vec();
                     xidmap.file_name = nfs3_create_record.name_vec;
                 },
                 IResult::Incomplete(_) => { panic!("WEIRD"); },
                 IResult::Error(e) => { panic!("Parsing failed: {:?}",e);  },
             };
 
+        } else if r.procedure == NFSPROC3_REMOVE {
+            match parse_nfs3_request_remove(r.prog_data) {
+                IResult::Done(_, rr) => {
+                    xidmap.file_handle = rr.handle.value.to_vec();
+                    xidmap.file_name = rr.name_vec;
+                },
+                IResult::Incomplete(_) => { panic!("WEIRD"); },
+                IResult::Error(e) => { panic!("Parsing failed: {:?}",e);  },
+            };
+
+        } else if r.procedure == NFSPROC3_RENAME {
+            match parse_nfs3_request_rename(r.prog_data) {
+                IResult::Done(_, rr) => {
+                    xidmap.file_handle = rr.from_handle.value.to_vec();
+                    xidmap.file_name = rr.from_name_vec;
+                    aux_file_name = rr.to_name_vec;
+                },
+                IResult::Incomplete(_) => { panic!("WEIRD"); },
+                IResult::Error(e) => { panic!("Parsing failed: {:?}",e);  },
+            };
+
         } else if r.procedure == NFSPROC3_COMMIT {
             SCLogDebug!("COMMIT, closing shop");
 
@@ -476,6 +529,10 @@ impl NFS3State {
             tx.file_name = xidmap.file_name.to_vec();
             //self.ts_txs_updated = true;
 
+            if r.procedure == NFSPROC3_RENAME {
+                tx.type_data = Some(NFS3TransactionTypeData::RENAME(aux_file_name));
+            }
+
             match &r.creds_unix {
                 &Some(ref u) => {
                     tx.request_machine_name = u.machine_name_buf.to_vec();
index 4f67cd0203e74fa0d094a3bb4b222aee059def09..3e886a8145083e17ddd8b21bb0e97c73dd97c2db 100644 (file)
@@ -137,6 +137,71 @@ named!(pub parse_nfs3_request_create<Nfs3RequestCreate>,
         ))
 );
 
+#[derive(Debug,PartialEq)]
+pub struct Nfs3RequestRemove<'a> {
+    pub handle: Nfs3Handle<'a>,
+    pub name_len: u32,
+    pub name_vec: Vec<u8>,
+}
+
+named!(pub parse_nfs3_request_remove<Nfs3RequestRemove>,
+    do_parse!(
+            handle: parse_nfs3_handle
+        >>  name_len: be_u32
+        >>  name: take!(name_len)
+        >>  fill_bytes: rest
+        >> (
+            Nfs3RequestRemove {
+                handle:handle,
+                name_len:name_len,
+                name_vec:name.to_vec(),
+            }
+        ))
+);
+
+#[derive(Debug,PartialEq)]
+pub struct Nfs3RequestRename<'a> {
+    pub from_handle: Nfs3Handle<'a>,
+    pub from_name_vec: Vec<u8>,
+    pub to_handle: Nfs3Handle<'a>,
+    pub to_name_vec: Vec<u8>,
+}
+
+named!(pub parse_nfs3_request_rename<Nfs3RequestRename>,
+    do_parse!(
+            from_handle: parse_nfs3_handle
+        >>  from_name_len: be_u32
+        >>  from_name: take!(from_name_len)
+        >>  from_fill_bytes: cond!(from_name_len % 4 != 0, take!(4 - from_name_len % 4))
+        >>  to_handle: parse_nfs3_handle
+        >>  to_name_len: be_u32
+        >>  to_name: take!(to_name_len)
+        >>  to_fill_bytes: rest
+        >> (
+            Nfs3RequestRename {
+                from_handle:from_handle,
+                from_name_vec:from_name.to_vec(),
+                to_handle:to_handle,
+                to_name_vec:to_name.to_vec(),
+            }
+        ))
+);
+
+#[derive(Debug,PartialEq)]
+pub struct Nfs3RequestGetAttr<'a> {
+    pub handle: Nfs3Handle<'a>,
+}
+
+named!(pub parse_nfs3_request_getattr<Nfs3RequestGetAttr>,
+    do_parse!(
+            handle: parse_nfs3_handle
+        >> (
+            Nfs3RequestGetAttr {
+                handle:handle,
+            }
+        ))
+);
+
 #[derive(Debug,PartialEq)]
 pub struct Nfs3RequestAccess<'a> {
     pub handle: Nfs3Handle<'a>,