use nom::IResult;
use nom::combinator::rest;
use nom::number::streaming::{le_u8, le_u16, le_u32};
#[derive(Debug,PartialEq)]
pub struct NTLMSSPVersion {
pub ver_major: u8,
pub ver_minor: u8,
pub ver_build: u16,
pub ver_ntlm_rev: u8,
}
impl NTLMSSPVersion {
pub fn to_string(&self) -> String {
format!("{}.{} build {} rev {}",
self.ver_major, self.ver_minor,
self.ver_build, self.ver_ntlm_rev)
}
}
named!(parse_ntlm_auth_version<NTLMSSPVersion>,
do_parse!(
ver_major: le_u8
>> ver_minor: le_u8
>> ver_build: le_u16
>> take!(3)
>> ver_ntlm_rev: le_u8
>> ( NTLMSSPVersion {
ver_major: ver_major,
ver_minor: ver_minor,
ver_build: ver_build,
ver_ntlm_rev: ver_ntlm_rev,
})
));
#[derive(Debug,PartialEq)]
pub struct NTLMSSPAuthRecord<'a> {
pub domain: &'a[u8],
pub user: &'a[u8],
pub host: &'a[u8],
pub version: Option<NTLMSSPVersion>,
}
fn parse_ntlm_auth_nego_flags(i:&[u8]) -> IResult<&[u8],(u8,u8,u32)> {
bits!(i, tuple!(take_bits!(6u8),take_bits!(1u8),take_bits!(25u32)))
}
named!(pub parse_ntlm_auth_record<NTLMSSPAuthRecord>,
do_parse!(
_lm_blob_len: le_u16
>> _lm_blob_maxlen: le_u16
>> _lm_blob_offset: le_u32
>> _ntlmresp_blob_len: le_u16
>> _ntlmresp_blob_maxlen: le_u16
>> _ntlmresp_blob_offset: le_u32
>> domain_blob_len: le_u16
>> _domain_blob_maxlen: le_u16
>> domain_blob_offset: le_u32
>> user_blob_len: le_u16
>> _user_blob_maxlen: le_u16
>> _user_blob_offset: le_u32
>> host_blob_len: le_u16
>> _host_blob_maxlen: le_u16
>> _host_blob_offset: le_u32
>> _ssnkey_blob_len: le_u16
>> _ssnkey_blob_maxlen: le_u16
>> _ssnkey_blob_offset: le_u32
>> nego_flags: parse_ntlm_auth_nego_flags
>> version: cond!(nego_flags.1==1, parse_ntlm_auth_version)
>> cond!(nego_flags.1==1, take!(domain_blob_offset - (12 + 60)))
>> cond!(nego_flags.1==0, take!(domain_blob_offset - (12 + 52)))
>> domain_blob: take!(domain_blob_len)
>> user_blob: take!(user_blob_len)
>> host_blob: take!(host_blob_len)
>> ( NTLMSSPAuthRecord {
domain: domain_blob,
user: user_blob,
host: host_blob,
version: version,
})
));
#[derive(Debug,PartialEq)]
pub struct NTLMSSPRecord<'a> {
pub msg_type: u32,
pub data: &'a[u8],
}
named!(pub parse_ntlmssp<NTLMSSPRecord>,
do_parse!(
take_until!("NTLMSSP\x00")
>> tag!("NTLMSSP\x00")
>> msg_type: le_u32
>> data: rest
>> (NTLMSSPRecord {
msg_type:msg_type,
data:data,
})
));