diff --git a/rust/Cargo.toml.in b/rust/Cargo.toml.in index 9bc2198cfb..c56f8a0b5f 100644 --- a/rust/Cargo.toml.in +++ b/rust/Cargo.toml.in @@ -18,6 +18,7 @@ debug = [] nom = "~3.2.1" libc = "^0.2.36" crc = "~1.7.0" -der-parser = "0.5.1" +der-parser = "0.5.2" +kerberos-parser = "0.1.0" ntp-parser = { version = "^0", optional = true } diff --git a/rust/src/smb/auth.rs b/rust/src/smb/auth.rs index f34f25ae41..8ec2b9bcab 100644 --- a/rust/src/smb/auth.rs +++ b/rust/src/smb/auth.rs @@ -15,6 +15,9 @@ * 02110-1301, USA. */ +use smb::kerberos_parser::krb5_parser; +use smb::kerberos_parser::krb5::{ApReq,Realm,PrincipalName}; + use log::*; use smb::ntlmssp_records::*; use smb::smb::*; @@ -25,113 +28,8 @@ use der_parser; #[derive(Debug,PartialEq)] pub struct Kerberos5Ticket { - pub realm: Vec, - pub snames: Vec>, -} - -/// ticket starts with custom header [APPLICATION 1] -fn parse_kerberos5_request_ticket(blob: &[u8]) -> IResult<&[u8], Kerberos5Ticket> -{ - let (rem, ticket_hdr) = match der_parser::der_read_element_header(blob) { - IResult::Done(rem, o) => (rem, o), - IResult::Incomplete(needed) => { return IResult::Incomplete(needed); }, - IResult::Error(err) => { return IResult::Error(err); }, - }; - SCLogDebug!("parse_kerberos5_request_ticket: ticket {:?}, remaining data {}", ticket_hdr, rem.len()); - - if !(ticket_hdr.class == 1 && ticket_hdr.structured == 1 && ticket_hdr.tag == 1 && ticket_hdr.len == rem.len() as u64) { - SCLogDebug!("parse_kerberos5_request_ticket: bad data"); - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - } - let (_, ticket_seq) = match der_parser::parse_der_sequence(rem) { - IResult::Done(rem, o) => (rem, o), - IResult::Incomplete(needed) => { return IResult::Incomplete(needed); }, - IResult::Error(err) => { return IResult::Error(err); }, - }; - SCLogDebug!("parse_kerberos5_request_ticket: ticket {:?}", ticket_seq); - - let ticket_vec = ticket_seq.as_sequence().unwrap(); // parse_der_sequence is checked - SCLogDebug!("parse_kerberos5_request_ticket: ticket_vec {:?}", ticket_vec); - if ticket_vec.len() != 4 { - SCLogDebug!("parse_kerberos5_request_ticket: unexpected format"); - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - } - - SCLogDebug!("parse_kerberos5_request_ticket: tkt-vno {:?}", ticket_vec[0]); - SCLogDebug!("parse_kerberos5_request_ticket: realm {:?}", ticket_vec[1]); - SCLogDebug!("parse_kerberos5_request_ticket: sname {:?}", ticket_vec[2]); - SCLogDebug!("parse_kerberos5_request_ticket: enc-part {:?}", ticket_vec[3]); - - let gs = match ticket_vec[1].content.as_slice() { - Ok(s) => s, - Err(_) => { - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - }, - }; - let realm = match der_parser::parse_der_generalstring(gs) { - IResult::Done(_, o) => o, - IResult::Incomplete(needed) => { return IResult::Incomplete(needed); }, - IResult::Error(err) => { return IResult::Error(err); }, - }; - SCLogDebug!("parse_kerberos5_request_ticket: realm {:?}", realm); - - if !(realm.class == 0 && realm.structured == 0 && realm.tag == 27) { - SCLogDebug!("bad realm data"); - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - } - let realm_v = realm.content.as_slice().unwrap().to_vec(); - SCLogDebug!("parse_kerberos5_request_ticket: realm_v {:?}", realm_v); - - let sname = match der_parser::parse_der_sequence(ticket_vec[2].content.as_slice().unwrap()) { - IResult::Done(_, o) => o, - IResult::Incomplete(needed) => { - SCLogDebug!("parse_kerberos5_request_ticket: needed {:?}", needed); - return IResult::Incomplete(needed); - }, - IResult::Error(err) => { - SCLogDebug!("parse_kerberos5_request_ticket: err {:?}", err); - return IResult::Error(err); - }, - }; - SCLogDebug!("parse_kerberos5_request_ticket: sname {:?}", sname); - - let sname_vec = sname.as_sequence().unwrap(); // parse_der_sequence is checked - SCLogDebug!("parse_kerberos5_request_ticket: sname_vec {:?}", sname_vec); - - if sname_vec.len() != 2 { - SCLogDebug!("parse_kerberos5_request_ticket: unexpected format"); - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - } - let sname_seq = match der_parser::parse_der_sequence(sname_vec[1].content.as_slice().unwrap()) { - IResult::Done(_, o) => o, - IResult::Incomplete(needed) => { - SCLogDebug!("parse_kerberos5_request_ticket: needed {:?}", needed); - return IResult::Incomplete(needed); - }, - IResult::Error(err) => { - SCLogDebug!("parse_kerberos5_request_ticket: err {:?}", err); - return IResult::Error(err); - }, - }; - SCLogDebug!("parse_kerberos5_request_ticket: sname_seq {:?}", sname_seq); - let snamestr_vec = sname_seq.as_sequence().unwrap(); // parse_der_sequence is checked - - let mut snames : Vec> = Vec::new(); - for o in snamestr_vec { - SCLogDebug!("parse_kerberos5_request_ticket: sname o {:?}", o); - if o.tag == 27 { - let v = o.content.as_slice().unwrap().to_vec(); - SCLogDebug!("sname {:?}", v); - snames.push(v); - } - } - - let t = Kerberos5Ticket { - realm: realm_v, - snames: snames, - }; - SCLogDebug!("ticket {:?}", t); - IResult::Done(&[],t) + pub realm: Realm, + pub sname: PrincipalName, } // get SPNEGO @@ -140,7 +38,7 @@ fn parse_kerberos5_request_ticket(blob: &[u8]) -> IResult<&[u8], Kerberos5Ticket // else if OID has NTLMSSP get NTLMSSP // else bruteforce NTLMSSP -fn parse_kerberos5_request(blob: &[u8]) -> IResult<&[u8], Kerberos5Ticket> +fn parse_kerberos5_request(blob: &[u8]) -> IResult<&[u8], ApReq> { let blob = match der_parser::parse_der(blob) { IResult::Done(_, b) => { @@ -167,75 +65,7 @@ fn parse_kerberos5_request(blob: &[u8]) -> IResult<&[u8], Kerberos5Ticket> }; SCLogDebug!("parse_kerberos5_request: tok_id {}", tok_id); - // APPLICATION 14 - let (rem, base_o) = match der_parser::der_read_element_header(rem) { - IResult::Done(rem, o) => (rem, o), - IResult::Incomplete(needed) => { return IResult::Incomplete(needed); }, - IResult::Error(err) => { return IResult::Error(err); }, - }; - if !(base_o.class == 1 && base_o.structured == 1 && base_o.tag == 14 && base_o.len == rem.len() as u64) { - SCLogDebug!("parse_kerberos5_request_ticket: bad data"); - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - } - - let base_seq = match der_parser::parse_der_sequence(rem) { - IResult::Done(_, o) => o, - IResult::Incomplete(needed) => { return IResult::Incomplete(needed); }, - IResult::Error(err) => { return IResult::Error(err); }, - }; - SCLogDebug!("parse_kerberos5_request: base_seq {:?}", base_seq); - - if base_seq.as_sequence().unwrap().len() < 4 { - SCLogDebug!("parse_kerberos5_request_ticket: bad data"); - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - } - - let pvno_s = match base_seq[0].content.as_slice() { - Ok(s) => s, - Err(_) => { - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - }, - }; - let pvno = match der_parser::parse_der_integer(pvno_s) { - IResult::Done(_, o) => o, - IResult::Incomplete(needed) => { return IResult::Incomplete(needed); }, - IResult::Error(err) => { return IResult::Error(err); }, - }; - SCLogDebug!("pvno {:?}", pvno); - - let msg_type_s = match base_seq[1].content.as_slice() { - Ok(s) => s, - Err(_) => { - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - }, - }; - let msg_type = match der_parser::parse_der_integer(msg_type_s) { - IResult::Done(_, o) => o, - IResult::Incomplete(needed) => { return IResult::Incomplete(needed); }, - IResult::Error(err) => { return IResult::Error(err); }, - }; - SCLogDebug!("msg_type {:?}", msg_type); - - let padding_s = match base_seq[2].content.as_slice() { - Ok(s) => s, - Err(_) => { - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - }, - }; - let padding = match der_parser::parse_der_bitstring(padding_s) { - IResult::Done(_, o) => o, - IResult::Incomplete(needed) => { return IResult::Incomplete(needed); }, - IResult::Error(err) => { return IResult::Error(err); }, - }; - SCLogDebug!("padding {:?}", padding); - - let ticket_s = match base_seq[3].content.as_slice() { - Ok(s) => s, - Err(_) => { - return IResult::Error(error_code!(ErrorKind::Custom(SECBLOB_KRB_FMT_ERR))); - }, - }; - parse_kerberos5_request_ticket(ticket_s) + krb5_parser::parse_ap_req(rem) } @@ -358,7 +188,11 @@ fn parse_secblob_spnego(blob: &[u8]) -> Option der_parser::DerObjectContent::OctetString(ref os) => { if have_kerberos { match parse_kerberos5_request(os) { - IResult::Done(_, t) => { + IResult::Done(_, req) => { + let t = Kerberos5Ticket { + realm: req.ticket.realm, + sname: req.ticket.sname, + }; kticket = Some(t) }, _ => { }, diff --git a/rust/src/smb/log.rs b/rust/src/smb/log.rs index fe3f901826..ded03ef452 100644 --- a/rust/src/smb/log.rs +++ b/rust/src/smb/log.rs @@ -173,18 +173,10 @@ fn smb_common_header(state: &SMBState, tx: &SMBTransaction) -> Json if let Some(ref ticket) = x.krb_ticket { let jsd = Json::object(); - let realm = match str::from_utf8(&ticket.realm) { - Ok(v) => v, - Err(_) => "UTF8_ERROR", - }; - jsd.set_string("realm", &realm); + jsd.set_string("realm", &ticket.realm.0); let jsa = Json::array(); - for sname in &ticket.snames { - let name = match str::from_utf8(&sname) { - Ok(v) => v, - Err(_) => "UTF8_ERROR", - }; - jsa.array_append_string(&name); + for sname in ticket.sname.name_string.iter() { + jsa.array_append_string(&sname); } jsd.set("snames", jsa); js.set("kerberos", jsd); diff --git a/rust/src/smb/mod.rs b/rust/src/smb/mod.rs index 65e1577ffc..618a59c3c0 100644 --- a/rust/src/smb/mod.rs +++ b/rust/src/smb/mod.rs @@ -15,6 +15,8 @@ * 02110-1301, USA. */ +extern crate kerberos_parser; + pub mod smb_records; pub mod smb1_records; pub mod smb2_records;