]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
smb2: log client and server guid from negotiate
authorVictor Julien <victor@inliniac.net>
Mon, 12 Mar 2018 08:32:17 +0000 (09:32 +0100)
committerVictor Julien <victor@inliniac.net>
Mon, 12 Mar 2018 14:34:43 +0000 (15:34 +0100)
rust/src/smb/log.rs
rust/src/smb/smb.rs
rust/src/smb/smb2.rs
rust/src/smb/smb2_records.rs

index bc2c6c6b1ba043ccabdd8dc8f71a654d2c69995c..a8b3cb170e2e844eeac63975d99938e72ab02ff8 100644 (file)
@@ -26,6 +26,19 @@ use smb::smb2::*;
 use smb::dcerpc::*;
 use nom;
 
+fn guid_to_string(guid: &Vec<u8>) -> String {
+    if guid.len() == 16 {
+        let output = format!("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
+                guid[3],  guid[2],  guid[1],  guid[0],
+                guid[5],  guid[4],  guid[7],  guid[6],
+                guid[9],  guid[8],  guid[11], guid[10],
+                guid[15], guid[14], guid[13], guid[12]);
+        output
+    } else {
+        "".to_string()
+    }
+}
+
 fn smb_common_header(state: &SMBState, tx: &SMBTransaction) -> Json
 {
     let js = Json::object();
@@ -222,6 +235,12 @@ fn smb_common_header(state: &SMBState, tx: &SMBTransaction) -> Json
                 }
                 js.set("client_dialects", jsa);
             }
+
+            if let Some(ref g) = x.client_guid {
+                js.set_string("client_guid", &guid_to_string(g));
+            }
+
+            js.set_string("server_guid", &guid_to_string(&x.server_guid));
         },
         Some(SMBTransactionTypeData::TREECONNECT(ref x)) => {
             js.set_integer("tree_id", x.tree_id as u64);
index 19535f2876a2128e08e882a9e10093d9a1104a08..929a4c4ce8750838c37053607197f4bda28f9743 100644 (file)
@@ -376,6 +376,10 @@ pub struct SMBTransactionNegotiate {
     pub smb_ver: u8,
     pub dialects: Vec<Vec<u8>>,
     pub dialects2: Vec<Vec<u8>>,
+
+    // SMB1 doesn't have the client GUID
+    pub client_guid: Option<Vec<u8>>,
+    pub server_guid: Vec<u8>,
 }
 
 impl SMBTransactionNegotiate {
@@ -384,6 +388,8 @@ impl SMBTransactionNegotiate {
             smb_ver: smb_ver,
             dialects: Vec::new(),
             dialects2: Vec::new(),
+            client_guid: None,
+            server_guid: Vec::with_capacity(16),
         }
     }
 }
index 346c58b17cc7065147844f42f7d818b7dd95fae0..3a582b22046621cbdb4bb91cc70d2f9759a35ea5 100644 (file)
@@ -322,6 +322,7 @@ pub fn smb2_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>)
                         let tx = state.new_negotiate_tx(2);
                         if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data {
                             tdn.dialects2 = dialects;
+                            tdn.client_guid = Some(rd.client_guid.to_vec());
                         }
                         tx.request_done = true;
                     }
@@ -685,13 +686,21 @@ pub fn smb2_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>)
             }
         },
         SMB2_COMMAND_NEGOTIATE_PROTOCOL => {
-            match parse_smb2_response_negotiate_protocol(r.data) {
+            let res = if r.nt_status == SMB_NTSTATUS_SUCCESS {
+                parse_smb2_response_negotiate_protocol(r.data)
+            } else {
+                parse_smb2_response_negotiate_protocol_error(r.data)
+            };
+            match res {
                 IResult::Done(_, rd) => {
                     SCLogDebug!("SERVER dialect => {}", &smb2_dialect_string(rd.dialect));
 
                     state.dialect = rd.dialect;
                     let found2 = match state.get_negotiate_tx(2) {
                         Some(tx) => {
+                            if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data {
+                                tdn.server_guid = rd.server_guid.to_vec();
+                            }
                             tx.set_status(r.nt_status, false);
                             tx.response_done = true;
                             true
@@ -701,6 +710,9 @@ pub fn smb2_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>)
                     // SMB2 response to SMB1 request?
                     let found1 = !found2 && match state.get_negotiate_tx(1) {
                         Some(tx) => {
+                            if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data {
+                                tdn.server_guid = rd.server_guid.to_vec();
+                            }
                             tx.set_status(r.nt_status, false);
                             tx.response_done = true;
                             true
index 2283b2a907c249b202b7d7f9bd0e49df3815ece0..d39e47fec5315fd7648985ed4df79812630ec9fc 100644 (file)
@@ -82,25 +82,33 @@ named!(pub parse_smb2_request_record<Smb2Record>,
 ));
 
 #[derive(Debug,PartialEq)]
-pub struct Smb2NegotiateProtocolRequestRecord<> {
+pub struct Smb2NegotiateProtocolRequestRecord<'a> {
     pub dialects_vec: Vec<u16>,
+    pub client_guid: &'a[u8],
 }
 
 named!(pub parse_smb2_request_negotiate_protocol<Smb2NegotiateProtocolRequestRecord>,
     do_parse!(
             struct_size: take!(2)
         >>  dialects_count: le_u16
-        >>  blob1: take!(32)
+        >>  sec_mode: le_u16
+        >>  reserved1: le_u16
+        >>  capabilities: le_u32
+        >>  client_guid: take!(16)
+        >>  ctx_offset: le_u32
+        >>  ctx_cnt: le_u16
+        >>  reserved2: le_u16
         >>  dia_vec: count!(le_u16, dialects_count as usize)
-        >>  blob2: rest
         >>  (Smb2NegotiateProtocolRequestRecord {
                 dialects_vec: dia_vec,
+                client_guid: client_guid,
             })
 ));
 
 #[derive(Debug,PartialEq)]
-pub struct Smb2NegotiateProtocolResponseRecord<> {
+pub struct Smb2NegotiateProtocolResponseRecord<'a> {
     pub dialect: u16,
+    pub server_guid: &'a[u8],
 }
 
 named!(pub parse_smb2_response_negotiate_protocol<Smb2NegotiateProtocolResponseRecord>,
@@ -108,11 +116,25 @@ named!(pub parse_smb2_response_negotiate_protocol<Smb2NegotiateProtocolResponseR
             struct_size: take!(2)
         >>  skip1: take!(2)
         >>  dialect: le_u16
+        >>  ctx_cnt: le_u16
+        >>  server_guid: take!(16)
         >>  (Smb2NegotiateProtocolResponseRecord {
                 dialect: dialect,
+                server_guid: server_guid,
             })
 ));
 
+named!(pub parse_smb2_response_negotiate_protocol_error<Smb2NegotiateProtocolResponseRecord>,
+    do_parse!(
+            struct_size: take!(2)
+        >>  skip1: take!(2)
+        >>  (Smb2NegotiateProtocolResponseRecord {
+                dialect: 0,
+                server_guid: &[],
+            })
+));
+
+
 #[derive(Debug,PartialEq)]
 pub struct Smb2SessionSetupRequestRecord<'a> {
     pub data: &'a[u8],