From: Victor Julien Date: Wed, 14 Jun 2017 08:22:08 +0000 (+0200) Subject: nfs: split record parsers into different files X-Git-Tag: suricata-4.0.0-rc1~48 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9edbb6f235c6fd9e8b14a4c3cc0f128d03473341;p=thirdparty%2Fsuricata.git nfs: split record parsers into different files --- diff --git a/rust/src/nfs/mod.rs b/rust/src/nfs/mod.rs index 0b515a7c9f..0a03505aec 100644 --- a/rust/src/nfs/mod.rs +++ b/rust/src/nfs/mod.rs @@ -16,9 +16,10 @@ */ pub mod types; -#[macro_use] -pub mod parser; +pub mod rpc_records; +pub mod nfs_records; pub mod nfs2_records; +pub mod nfs3_records; pub mod nfs3; pub mod log; diff --git a/rust/src/nfs/nfs2_records.rs b/rust/src/nfs/nfs2_records.rs index 0d8733d346..46663eb29f 100644 --- a/rust/src/nfs/nfs2_records.rs +++ b/rust/src/nfs/nfs2_records.rs @@ -17,7 +17,7 @@ //! Nom parsers for NFSv2 records use nom::{be_u32, rest}; -use nfs::parser::*; +use nfs::nfs_records::*; #[derive(Debug,PartialEq)] pub struct Nfs2Handle<'a> { @@ -73,14 +73,14 @@ named!(pub parse_nfs2_request_read, )) ); -named!(pub parse_nfs2_reply_read, +named!(pub parse_nfs2_reply_read, do_parse!( status: be_u32 >> attr_blob: take!(68) >> data_len: be_u32 >> data_contents: rest >> ( - Nfs3ReplyRead { + NfsReplyRead { status:status, attr_follows:1, attr_blob:attr_blob, diff --git a/rust/src/nfs/nfs3.rs b/rust/src/nfs/nfs3.rs index 7dc18e2907..edfc719d49 100644 --- a/rust/src/nfs/nfs3.rs +++ b/rust/src/nfs/nfs3.rs @@ -35,8 +35,10 @@ use filecontainer::*; //use storage::*; use nfs::types::*; -use nfs::parser::*; +use nfs::rpc_records::*; +use nfs::nfs_records::*; use nfs::nfs2_records::*; +use nfs::nfs3_records::*; /// nom bug leads to this wrappers being necessary /// TODO for some reason putting these in parser.rs and making them public @@ -1038,7 +1040,7 @@ impl NFS3State { /// xidmapr is an Option as it's already removed from the map if we /// have a complete record. Otherwise we do a lookup ourselves. fn process_read_record<'b>(&mut self, r: &RpcReplyPacket<'b>, - reply: &Nfs3ReplyRead<'b>, xidmapr: Option<&NFS3RequestXidMap>) -> u32 + reply: &NfsReplyRead<'b>, xidmapr: Option<&NFS3RequestXidMap>) -> u32 { let file_name; let file_handle; @@ -1141,7 +1143,7 @@ impl NFS3State { 0 } - fn process_partial_read_reply_record<'b>(&mut self, r: &RpcReplyPacket<'b>, reply: &Nfs3ReplyRead<'b>) -> u32 { + fn process_partial_read_reply_record<'b>(&mut self, r: &RpcReplyPacket<'b>, reply: &NfsReplyRead<'b>) -> u32 { SCLogDebug!("REPLY {} to procedure READ blob size {} / {}", r.hdr.xid, r.prog_data.len(), reply.count); diff --git a/rust/src/nfs/parser.rs b/rust/src/nfs/nfs3_records.rs similarity index 59% rename from rust/src/nfs/parser.rs rename to rust/src/nfs/nfs3_records.rs index 5a8714c329..41e88679fc 100644 --- a/rust/src/nfs/parser.rs +++ b/rust/src/nfs/nfs3_records.rs @@ -18,42 +18,7 @@ //! Nom parsers for RPC & NFSv3 use nom::{be_u32, be_u64, rest}; - -#[derive(Debug,PartialEq)] -pub struct RpcRequestCredsUnix<'a> { - pub stamp: u32, - pub machine_name_len: u32, - pub machine_name_buf: &'a[u8], - pub uid: u32, - pub gid: u32, - pub aux_gids: Option>, - // list of gids -} - -//named!(parse_rpc_creds_unix_aux_gids>, -// many0!(be_u32) -//); - -named!(pub parse_rfc_request_creds_unix, - do_parse!( - stamp: be_u32 - >> machine_name_len: be_u32 - >> machine_name_buf: take!(machine_name_len) - >> uid: be_u32 - >> gid: be_u32 - //>> aux_gids: parse_rpc_creds_unix_aux_gids - - >> ( - RpcRequestCredsUnix { - stamp:stamp, - machine_name_len:machine_name_len, - machine_name_buf:machine_name_buf, - uid:uid, - gid:gid, - aux_gids:None, - } - )) -); +use nfs::nfs_records::*; #[derive(Debug,PartialEq)] pub struct Nfs3Handle<'a> { @@ -439,7 +404,7 @@ named!(pub parse_nfs3_request_write, } )) ); - +/* #[derive(Debug,PartialEq)] pub struct Nfs3ReplyRead<'a> { pub status: u32, @@ -450,8 +415,8 @@ pub struct Nfs3ReplyRead<'a> { pub data_len: u32, pub data: &'a[u8], // likely partial } - -named!(pub parse_nfs3_reply_read, +*/ +named!(pub parse_nfs3_reply_read, do_parse!( status: be_u32 >> attr_follows: be_u32 @@ -461,7 +426,7 @@ named!(pub parse_nfs3_reply_read, >> data_len: be_u32 >> data_contents: rest >> ( - Nfs3ReplyRead { + NfsReplyRead { status:status, attr_follows:attr_follows, attr_blob:attr_blob, @@ -472,274 +437,3 @@ named!(pub parse_nfs3_reply_read, } )) ); - -#[derive(Debug,PartialEq)] -pub struct RpcPacketHeader<> { - pub frag_is_last: bool, - pub frag_len: u32, - pub xid: u32, - pub msgtype: u32, -} - -named!(pub parse_rpc_packet_header, - do_parse!( - fraghdr: bits!(tuple!( - take_bits!(u8, 1), // is_last - take_bits!(u32, 31))) // len - - >> xid: be_u32 - >> msgtype: be_u32 - >> ( - RpcPacketHeader { - frag_is_last:fraghdr.0 == 1, - frag_len:fraghdr.1, - xid:xid, - msgtype:msgtype, - } - )) -); - -#[derive(Debug,PartialEq)] -pub struct RpcReplyPacket<'a> { - pub hdr: RpcPacketHeader<>, - - pub verifier_flavor: u32, - pub verifier_len: u32, - pub verifier: Option<&'a[u8]>, - - pub reply_state: u32, - pub accept_state: u32, - - pub prog_data: &'a[u8], -} - -// top of request packet, just to get to procedure -#[derive(Debug)] -pub struct RpcRequestPacketPartial { - pub hdr: RpcPacketHeader, - - pub rpcver: u32, - pub program: u32, - pub progver: u32, - pub procedure: u32, -} - -named!(pub parse_rpc_request_partial, - do_parse!( - hdr: parse_rpc_packet_header - >> rpcver: be_u32 - >> program: be_u32 - >> progver: be_u32 - >> procedure: be_u32 - >> ( - RpcRequestPacketPartial { - hdr:hdr, - rpcver:rpcver, - program:program, - progver:progver, - procedure:procedure, - } - )) -); - -#[derive(Debug,PartialEq)] -pub struct RpcPacket<'a> { - pub hdr: RpcPacketHeader<>, - - pub rpcver: u32, - pub program: u32, - pub progver: u32, - pub procedure: u32, - - pub creds_flavor: u32, - pub creds_len: u32, - pub creds: Option<&'a[u8]>, - pub creds_unix:Option>, - - pub verifier_flavor: u32, - pub verifier_len: u32, - pub verifier: Option<&'a[u8]>, - - pub prog_data: &'a[u8], -} - -named!(pub parse_rpc, - do_parse!( - hdr: parse_rpc_packet_header - - >> rpcver: be_u32 - >> program: be_u32 - >> progver: be_u32 - >> procedure: be_u32 - - >> creds_flavor: be_u32 - >> creds_len: be_u32 - >> creds: cond!(creds_flavor != 1 && creds_len > 0, take!(creds_len as usize)) - >> creds_unix: cond!(creds_len > 0 && creds_flavor == 1, flat_map!(take!((creds_len) as usize),parse_rfc_request_creds_unix)) - - >> verifier_flavor: be_u32 - >> verifier_len: be_u32 - >> verifier: cond!(verifier_len > 0, take!(verifier_len as usize)) - - >> pl: rest - - >> ( - RpcPacket { - hdr:hdr, - - rpcver:rpcver, - program:program, - progver:progver, - procedure:procedure, - - creds_flavor:creds_flavor, - creds_len:creds_len, - creds:creds, - creds_unix:creds_unix, - - verifier_flavor:verifier_flavor, - verifier_len:verifier_len, - verifier:verifier, - - prog_data:pl, - } - )) -); - -// to be called with data <= hdr.frag_len + 4. Sending more data is undefined. -named!(pub parse_rpc_reply, - do_parse!( - hdr: parse_rpc_packet_header - - >> verifier_flavor: be_u32 - >> verifier_len: be_u32 - >> verifier: cond!(verifier_len > 0, take!(verifier_len as usize)) - - >> reply_state: be_u32 - >> accept_state: be_u32 - - >> pl: rest - - >> ( - RpcReplyPacket { - hdr:hdr, - - verifier_flavor:verifier_flavor, - verifier_len:verifier_len, - verifier:verifier, - - reply_state:reply_state, - accept_state:accept_state, - - prog_data:pl, - } - )) -); - -named!(pub parse_rpc_udp_packet_header, - do_parse!( - xid: be_u32 - >> msgtype: be_u32 - >> ( - RpcPacketHeader { - frag_is_last:false, - frag_len:0, - - xid:xid, - msgtype:msgtype, - } - )) -); - -#[derive(Debug,PartialEq)] -pub struct RpcUdpRequestPacket<'a> { - pub hdr: RpcPacketHeader<>, - - pub rpcver: u32, - pub program: u32, - pub progver: u32, - pub procedure: u32, - - pub creds_flavor: u32, - pub creds_len: u32, - pub creds: Option<&'a[u8]>, - pub creds_unix:Option>, - - pub verifier_flavor: u32, - pub verifier_len: u32, - pub verifier: Option<&'a[u8]>, - - pub prog_data: &'a[u8], -} - -named!(pub parse_rpc_udp_request, - do_parse!( - hdr: parse_rpc_udp_packet_header - - >> rpcver: be_u32 - >> program: be_u32 - >> progver: be_u32 - >> procedure: be_u32 - - >> creds_flavor: be_u32 - >> creds_len: be_u32 - >> creds: cond!(creds_flavor != 1 && creds_len > 0, take!(creds_len as usize)) - >> creds_unix: cond!(creds_len > 0 && creds_flavor == 1, flat_map!(take!((creds_len) as usize),parse_rfc_request_creds_unix)) - - >> verifier_flavor: be_u32 - >> verifier_len: be_u32 - >> verifier: cond!(verifier_len > 0, take!(verifier_len as usize)) - - >> pl: rest - - >> ( - RpcPacket { - hdr:hdr, - - rpcver:rpcver, - program:program, - progver:progver, - procedure:procedure, - - creds_flavor:creds_flavor, - creds_len:creds_len, - creds:creds, - creds_unix:creds_unix, - - verifier_flavor:verifier_flavor, - verifier_len:verifier_len, - verifier:verifier, - - prog_data:pl, - } - )) -); - -named!(pub parse_rpc_udp_reply, - do_parse!( - hdr: parse_rpc_udp_packet_header - - >> verifier_flavor: be_u32 - >> verifier_len: be_u32 - >> verifier: cond!(verifier_len > 0, take!(verifier_len as usize)) - - >> reply_state: be_u32 - >> accept_state: be_u32 - - >> pl: rest - - >> ( - RpcReplyPacket { - hdr:hdr, - - verifier_flavor:verifier_flavor, - verifier_len:verifier_len, - verifier:verifier, - - reply_state:reply_state, - accept_state:accept_state, - - prog_data:pl, - } - )) -); diff --git a/rust/src/nfs/nfs_records.rs b/rust/src/nfs/nfs_records.rs new file mode 100644 index 0000000000..a81878871e --- /dev/null +++ b/rust/src/nfs/nfs_records.rs @@ -0,0 +1,29 @@ +/* Copyright (C) 2017 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +//! Nom parsers for NFS + +#[derive(Debug,PartialEq)] +pub struct NfsReplyRead<'a> { + pub status: u32, + pub attr_follows: u32, + pub attr_blob: &'a[u8], + pub count: u32, + pub eof: bool, + pub data_len: u32, + pub data: &'a[u8], // likely partial +} diff --git a/rust/src/nfs/rpc_records.rs b/rust/src/nfs/rpc_records.rs new file mode 100644 index 0000000000..361d5c0de0 --- /dev/null +++ b/rust/src/nfs/rpc_records.rs @@ -0,0 +1,327 @@ +/* Copyright (C) 2017 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +//! Nom parsers for RPC & NFSv3 + +use nom::{be_u32, be_u64, rest}; + +#[derive(Debug,PartialEq)] +pub struct RpcRequestCredsUnix<'a> { + pub stamp: u32, + pub machine_name_len: u32, + pub machine_name_buf: &'a[u8], + pub uid: u32, + pub gid: u32, + pub aux_gids: Option>, + // list of gids +} + +//named!(parse_rpc_creds_unix_aux_gids>, +// many0!(be_u32) +//); + +named!(pub parse_rfc_request_creds_unix, + do_parse!( + stamp: be_u32 + >> machine_name_len: be_u32 + >> machine_name_buf: take!(machine_name_len) + >> uid: be_u32 + >> gid: be_u32 + //>> aux_gids: parse_rpc_creds_unix_aux_gids + + >> ( + RpcRequestCredsUnix { + stamp:stamp, + machine_name_len:machine_name_len, + machine_name_buf:machine_name_buf, + uid:uid, + gid:gid, + aux_gids:None, + } + )) +); + +#[derive(Debug,PartialEq)] +pub struct RpcPacketHeader<> { + pub frag_is_last: bool, + pub frag_len: u32, + pub xid: u32, + pub msgtype: u32, +} + +named!(pub parse_rpc_packet_header, + do_parse!( + fraghdr: bits!(tuple!( + take_bits!(u8, 1), // is_last + take_bits!(u32, 31))) // len + + >> xid: be_u32 + >> msgtype: be_u32 + >> ( + RpcPacketHeader { + frag_is_last:fraghdr.0 == 1, + frag_len:fraghdr.1, + xid:xid, + msgtype:msgtype, + } + )) +); + +#[derive(Debug,PartialEq)] +pub struct RpcReplyPacket<'a> { + pub hdr: RpcPacketHeader<>, + + pub verifier_flavor: u32, + pub verifier_len: u32, + pub verifier: Option<&'a[u8]>, + + pub reply_state: u32, + pub accept_state: u32, + + pub prog_data: &'a[u8], +} + +// top of request packet, just to get to procedure +#[derive(Debug)] +pub struct RpcRequestPacketPartial { + pub hdr: RpcPacketHeader, + + pub rpcver: u32, + pub program: u32, + pub progver: u32, + pub procedure: u32, +} + +named!(pub parse_rpc_request_partial, + do_parse!( + hdr: parse_rpc_packet_header + >> rpcver: be_u32 + >> program: be_u32 + >> progver: be_u32 + >> procedure: be_u32 + >> ( + RpcRequestPacketPartial { + hdr:hdr, + rpcver:rpcver, + program:program, + progver:progver, + procedure:procedure, + } + )) +); + +#[derive(Debug,PartialEq)] +pub struct RpcPacket<'a> { + pub hdr: RpcPacketHeader<>, + + pub rpcver: u32, + pub program: u32, + pub progver: u32, + pub procedure: u32, + + pub creds_flavor: u32, + pub creds_len: u32, + pub creds: Option<&'a[u8]>, + pub creds_unix:Option>, + + pub verifier_flavor: u32, + pub verifier_len: u32, + pub verifier: Option<&'a[u8]>, + + pub prog_data: &'a[u8], +} + +named!(pub parse_rpc, + do_parse!( + hdr: parse_rpc_packet_header + + >> rpcver: be_u32 + >> program: be_u32 + >> progver: be_u32 + >> procedure: be_u32 + + >> creds_flavor: be_u32 + >> creds_len: be_u32 + >> creds: cond!(creds_flavor != 1 && creds_len > 0, take!(creds_len as usize)) + >> creds_unix: cond!(creds_len > 0 && creds_flavor == 1, flat_map!(take!((creds_len) as usize),parse_rfc_request_creds_unix)) + + >> verifier_flavor: be_u32 + >> verifier_len: be_u32 + >> verifier: cond!(verifier_len > 0, take!(verifier_len as usize)) + + >> pl: rest + + >> ( + RpcPacket { + hdr:hdr, + + rpcver:rpcver, + program:program, + progver:progver, + procedure:procedure, + + creds_flavor:creds_flavor, + creds_len:creds_len, + creds:creds, + creds_unix:creds_unix, + + verifier_flavor:verifier_flavor, + verifier_len:verifier_len, + verifier:verifier, + + prog_data:pl, + } + )) +); + +// to be called with data <= hdr.frag_len + 4. Sending more data is undefined. +named!(pub parse_rpc_reply, + do_parse!( + hdr: parse_rpc_packet_header + + >> verifier_flavor: be_u32 + >> verifier_len: be_u32 + >> verifier: cond!(verifier_len > 0, take!(verifier_len as usize)) + + >> reply_state: be_u32 + >> accept_state: be_u32 + + >> pl: rest + + >> ( + RpcReplyPacket { + hdr:hdr, + + verifier_flavor:verifier_flavor, + verifier_len:verifier_len, + verifier:verifier, + + reply_state:reply_state, + accept_state:accept_state, + + prog_data:pl, + } + )) +); + +named!(pub parse_rpc_udp_packet_header, + do_parse!( + xid: be_u32 + >> msgtype: be_u32 + >> ( + RpcPacketHeader { + frag_is_last:false, + frag_len:0, + + xid:xid, + msgtype:msgtype, + } + )) +); + +#[derive(Debug,PartialEq)] +pub struct RpcUdpRequestPacket<'a> { + pub hdr: RpcPacketHeader<>, + + pub rpcver: u32, + pub program: u32, + pub progver: u32, + pub procedure: u32, + + pub creds_flavor: u32, + pub creds_len: u32, + pub creds: Option<&'a[u8]>, + pub creds_unix:Option>, + + pub verifier_flavor: u32, + pub verifier_len: u32, + pub verifier: Option<&'a[u8]>, + + pub prog_data: &'a[u8], +} + +named!(pub parse_rpc_udp_request, + do_parse!( + hdr: parse_rpc_udp_packet_header + + >> rpcver: be_u32 + >> program: be_u32 + >> progver: be_u32 + >> procedure: be_u32 + + >> creds_flavor: be_u32 + >> creds_len: be_u32 + >> creds: cond!(creds_flavor != 1 && creds_len > 0, take!(creds_len as usize)) + >> creds_unix: cond!(creds_len > 0 && creds_flavor == 1, flat_map!(take!((creds_len) as usize),parse_rfc_request_creds_unix)) + + >> verifier_flavor: be_u32 + >> verifier_len: be_u32 + >> verifier: cond!(verifier_len > 0, take!(verifier_len as usize)) + + >> pl: rest + + >> ( + RpcPacket { + hdr:hdr, + + rpcver:rpcver, + program:program, + progver:progver, + procedure:procedure, + + creds_flavor:creds_flavor, + creds_len:creds_len, + creds:creds, + creds_unix:creds_unix, + + verifier_flavor:verifier_flavor, + verifier_len:verifier_len, + verifier:verifier, + + prog_data:pl, + } + )) +); + +named!(pub parse_rpc_udp_reply, + do_parse!( + hdr: parse_rpc_udp_packet_header + + >> verifier_flavor: be_u32 + >> verifier_len: be_u32 + >> verifier: cond!(verifier_len > 0, take!(verifier_len as usize)) + + >> reply_state: be_u32 + >> accept_state: be_u32 + + >> pl: rest + + >> ( + RpcReplyPacket { + hdr:hdr, + + verifier_flavor:verifier_flavor, + verifier_len:verifier_len, + verifier:verifier, + + reply_state:reply_state, + accept_state:accept_state, + + prog_data:pl, + } + )) +);