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();
}
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);
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 {
smb_ver: smb_ver,
dialects: Vec::new(),
dialects2: Vec::new(),
+ client_guid: None,
+ server_guid: Vec::with_capacity(16),
}
}
}
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;
}
}
},
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
// 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
));
#[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>,
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],