ike: do not keep server transforms in state

Fixes #4534

Now, only the tx with the transforms will match
with ike.chosen_sa_attribute
pull/6469/head
Philippe Antoine 4 years ago committed by Victor Julien
parent 83887510a8
commit accdad7881

@ -166,35 +166,34 @@ pub extern "C" fn rs_ike_state_get_sa_attribute(
} }
} }
} else if tx.ike_version == 2 { } else if tx.ike_version == 2 {
'outer2: for server_transform in tx.hdr.ikev2_transforms.iter() { for attr in tx.hdr.ikev2_transforms.iter() {
for attr in server_transform {
match attr { match attr {
IkeV2Transform::Encryption(e) => { IkeV2Transform::Encryption(e) => {
if sa == "alg_enc" { if sa == "alg_enc" {
ret_val = e.0 as u32; ret_val = e.0 as u32;
ret_code = 1; ret_code = 1;
break 'outer2; break;
} }
} }
IkeV2Transform::Auth(e) => { IkeV2Transform::Auth(e) => {
if sa == "alg_auth" { if sa == "alg_auth" {
ret_val = e.0 as u32; ret_val = e.0 as u32;
ret_code = 1; ret_code = 1;
break 'outer2; break;
} }
} }
IkeV2Transform::PRF(ref e) => { IkeV2Transform::PRF(ref e) => {
if sa == "alg_prf" { if sa == "alg_prf" {
ret_val = e.0 as u32; ret_val = e.0 as u32;
ret_code = 1; ret_code = 1;
break 'outer2; break;
} }
} }
IkeV2Transform::DH(ref e) => { IkeV2Transform::DH(ref e) => {
if sa == "alg_dh" { if sa == "alg_dh" {
ret_val = e.0 as u32; ret_val = e.0 as u32;
ret_code = 1; ret_code = 1;
break 'outer2; break;
} }
} }
_ => (), _ => (),
@ -202,7 +201,6 @@ pub extern "C" fn rs_ike_state_get_sa_attribute(
} }
} }
} }
}
unsafe { unsafe {
*value = ret_val; *value = ret_val;

@ -57,7 +57,7 @@ pub struct IkeHeaderWrapper {
pub msg_id: u32, pub msg_id: u32,
pub flags: u8, pub flags: u8,
pub ikev1_transforms: Vec<Vec<SaAttribute>>, pub ikev1_transforms: Vec<Vec<SaAttribute>>,
pub ikev2_transforms: Vec<Vec<IkeV2Transform>>, pub ikev2_transforms: Vec<IkeV2Transform>,
pub ikev1_header: IkeV1Header, pub ikev1_header: IkeV1Header,
pub ikev2_header: IkeV2Header, pub ikev2_header: IkeV2Header,
} }
@ -136,6 +136,12 @@ impl IKETransaction {
core::sc_detect_engine_state_free(state); core::sc_detect_engine_state_free(state);
} }
} }
/// Set an event.
pub fn set_event(&mut self, event: IkeEvent) {
let ev = event as u8;
core::sc_app_layer_decoder_events_set_event_raw(&mut self.events, ev);
}
} }
impl Drop for IKETransaction { impl Drop for IKETransaction {

@ -22,7 +22,7 @@ use crate::core::STREAM_TOCLIENT;
use crate::ike::ipsec_parser::*; use crate::ike::ipsec_parser::*;
use super::ipsec_parser::IkeV2Transform; use super::ipsec_parser::IkeV2Transform;
use crate::ike::ike::{IKEState, IkeEvent}; use crate::ike::ike::{IKEState, IKETransaction, IkeEvent};
use crate::ike::parser::IsakmpHeader; use crate::ike::parser::IsakmpHeader;
use ipsec_parser::{IkeExchangeType, IkePayloadType, IkeV2Header}; use ipsec_parser::{IkeExchangeType, IkePayloadType, IkeV2Header};
@ -69,9 +69,6 @@ pub struct Ikev2Container {
/// The transforms proposed by the initiator /// The transforms proposed by the initiator
pub client_transforms: Vec<Vec<IkeV2Transform>>, pub client_transforms: Vec<Vec<IkeV2Transform>>,
/// The transforms selected by the responder
pub server_transforms: Vec<Vec<IkeV2Transform>>,
/// The encryption algorithm selected by the responder /// The encryption algorithm selected by the responder
pub alg_enc: IkeTransformEncType, pub alg_enc: IkeTransformEncType,
/// The authentication algorithm selected by the responder /// The authentication algorithm selected by the responder
@ -92,7 +89,6 @@ impl Default for Ikev2Container {
connection_state: IKEV2ConnectionState::Init, connection_state: IKEV2ConnectionState::Init,
dh_group: IkeTransformDHType::None, dh_group: IkeTransformDHType::None,
client_transforms: Vec::new(), client_transforms: Vec::new(),
server_transforms: Vec::new(),
alg_enc: IkeTransformEncType::ENCR_NULL, alg_enc: IkeTransformEncType::ENCR_NULL,
alg_auth: IkeTransformAuthType::NONE, alg_auth: IkeTransformAuthType::NONE,
alg_prf: IkeTransformPRFType::PRF_NULL, alg_prf: IkeTransformPRFType::PRF_NULL,
@ -128,7 +124,6 @@ pub fn handle_ikev2(
tx.hdr.min_ver = isakmp_header.min_ver; tx.hdr.min_ver = isakmp_header.min_ver;
tx.hdr.msg_id = isakmp_header.msg_id; tx.hdr.msg_id = isakmp_header.msg_id;
tx.hdr.flags = isakmp_header.flags; tx.hdr.flags = isakmp_header.flags;
state.transactions.push(tx);
let mut payload_types = Vec::new(); let mut payload_types = Vec::new();
let mut errors = 0; let mut errors = 0;
let mut notify_types = Vec::new(); let mut notify_types = Vec::new();
@ -140,7 +135,7 @@ pub fn handle_ikev2(
IkeV2PayloadContent::Dummy => (), IkeV2PayloadContent::Dummy => (),
IkeV2PayloadContent::SA(ref prop) => { IkeV2PayloadContent::SA(ref prop) => {
// if hdr.flags & IKEV2_FLAG_INITIATOR != 0 { // if hdr.flags & IKEV2_FLAG_INITIATOR != 0 {
add_proposals(state, prop, direction); add_proposals(state, &mut tx, prop, direction);
// } // }
} }
IkeV2PayloadContent::KE(ref kex) => { IkeV2PayloadContent::KE(ref kex) => {
@ -171,50 +166,22 @@ pub fn handle_ikev2(
} }
state.ikev2_container.connection_state = state.ikev2_container.connection_state =
state.ikev2_container.connection_state.advance(payload); state.ikev2_container.connection_state.advance(payload);
if let Some(tx) = state.transactions.last_mut() {
// borrow back tx to update it
tx.payload_types tx.payload_types
.ikev2_payload_types .ikev2_payload_types
.append(&mut payload_types); .append(&mut payload_types);
tx.errors = errors; tx.errors = errors;
tx.notify_types.append(&mut notify_types); tx.notify_types.append(&mut notify_types);
if direction == STREAM_TOCLIENT
&& state.ikev2_container.server_transforms.len() > 0
{
tx.hdr.ikev2_transforms.clear();
for transforms in &state.ikev2_container.server_transforms {
let mut proposal = Vec::new();
transforms.iter().for_each(|t| match *t {
IkeV2Transform::Encryption(ref e) => {
proposal.push(IkeV2Transform::Encryption(*e))
}
IkeV2Transform::Auth(ref e) => {
proposal.push(IkeV2Transform::Auth(*e))
}
IkeV2Transform::PRF(ref e) => {
proposal.push(IkeV2Transform::PRF(*e))
}
IkeV2Transform::DH(ref e) => proposal.push(IkeV2Transform::DH(*e)),
IkeV2Transform::ESN(ref e) => {
proposal.push(IkeV2Transform::ESN(*e))
}
_ => (),
});
tx.hdr.ikev2_transforms.push(proposal);
}
}
}
} }
} }
_e => { _e => {
SCLogDebug!("parse_ikev2_payload_with_type: {:?}", _e); SCLogDebug!("parse_ikev2_payload_with_type: {:?}", _e);
} }
} }
state.transactions.push(tx);
return AppLayerResult::ok(); return AppLayerResult::ok();
} }
fn add_proposals(state: &mut IKEState, prop: &Vec<IkeV2Proposal>, direction: u8) { fn add_proposals(state: &mut IKEState, tx: &mut IKETransaction, prop: &Vec<IkeV2Proposal>, direction: u8) {
for p in prop { for p in prop {
let transforms: Vec<IkeV2Transform> = p.transforms.iter().map(|x| x.into()).collect(); let transforms: Vec<IkeV2Transform> = p.transforms.iter().map(|x| x.into()).collect();
// Rule 1: warn on weak or unknown transforms // Rule 1: warn on weak or unknown transforms
@ -234,7 +201,7 @@ fn add_proposals(state: &mut IKEState, prop: &Vec<IkeV2Proposal>, direction: u8)
| IkeTransformEncType::ENCR_NULL => { | IkeTransformEncType::ENCR_NULL => {
SCLogDebug!("Weak Encryption: {:?}", enc); SCLogDebug!("Weak Encryption: {:?}", enc);
// XXX send event only if direction == STREAM_TOCLIENT ? // XXX send event only if direction == STREAM_TOCLIENT ?
state.set_event(IkeEvent::WeakCryptoEnc); tx.set_event(IkeEvent::WeakCryptoEnc);
} }
_ => (), _ => (),
} }
@ -242,11 +209,11 @@ fn add_proposals(state: &mut IKEState, prop: &Vec<IkeV2Proposal>, direction: u8)
IkeV2Transform::PRF(ref prf) => match *prf { IkeV2Transform::PRF(ref prf) => match *prf {
IkeTransformPRFType::PRF_NULL => { IkeTransformPRFType::PRF_NULL => {
SCLogDebug!("'Null' PRF transform proposed"); SCLogDebug!("'Null' PRF transform proposed");
state.set_event(IkeEvent::InvalidProposal); tx.set_event(IkeEvent::InvalidProposal);
} }
IkeTransformPRFType::PRF_HMAC_MD5 | IkeTransformPRFType::PRF_HMAC_SHA1 => { IkeTransformPRFType::PRF_HMAC_MD5 | IkeTransformPRFType::PRF_HMAC_SHA1 => {
SCLogDebug!("Weak PRF: {:?}", prf); SCLogDebug!("Weak PRF: {:?}", prf);
state.set_event(IkeEvent::WeakCryptoPrf); tx.set_event(IkeEvent::WeakCryptoPrf);
} }
_ => (), _ => (),
}, },
@ -264,7 +231,7 @@ fn add_proposals(state: &mut IKEState, prop: &Vec<IkeV2Proposal>, direction: u8)
| IkeTransformAuthType::AUTH_HMAC_MD5_128 | IkeTransformAuthType::AUTH_HMAC_MD5_128
| IkeTransformAuthType::AUTH_HMAC_SHA1_160 => { | IkeTransformAuthType::AUTH_HMAC_SHA1_160 => {
SCLogDebug!("Weak auth: {:?}", auth); SCLogDebug!("Weak auth: {:?}", auth);
state.set_event(IkeEvent::WeakCryptoAuth); tx.set_event(IkeEvent::WeakCryptoAuth);
} }
_ => (), _ => (),
} }
@ -272,20 +239,20 @@ fn add_proposals(state: &mut IKEState, prop: &Vec<IkeV2Proposal>, direction: u8)
IkeV2Transform::DH(ref dh) => match *dh { IkeV2Transform::DH(ref dh) => match *dh {
IkeTransformDHType::None => { IkeTransformDHType::None => {
SCLogDebug!("'None' DH transform proposed"); SCLogDebug!("'None' DH transform proposed");
state.set_event(IkeEvent::InvalidProposal); tx.set_event(IkeEvent::InvalidProposal);
} }
IkeTransformDHType::Modp768 IkeTransformDHType::Modp768
| IkeTransformDHType::Modp1024 | IkeTransformDHType::Modp1024
| IkeTransformDHType::Modp1024s160 | IkeTransformDHType::Modp1024s160
| IkeTransformDHType::Modp1536 => { | IkeTransformDHType::Modp1536 => {
SCLogDebug!("Weak DH: {:?}", dh); SCLogDebug!("Weak DH: {:?}", dh);
state.set_event(IkeEvent::WeakCryptoDh); tx.set_event(IkeEvent::WeakCryptoDh);
} }
_ => (), _ => (),
}, },
IkeV2Transform::Unknown(_tx_type, _tx_id) => { IkeV2Transform::Unknown(_tx_type, _tx_id) => {
SCLogDebug!("Unknown proposal: type={:?}, id={}", _tx_type, _tx_id); SCLogDebug!("Unknown proposal: type={:?}, id={}", _tx_type, _tx_id);
state.set_event(IkeEvent::UnknownProposal); tx.set_event(IkeEvent::UnknownProposal);
} }
_ => (), _ => (),
} }
@ -296,12 +263,12 @@ fn add_proposals(state: &mut IKEState, prop: &Vec<IkeV2Proposal>, direction: u8)
_ => false, _ => false,
}) { }) {
SCLogDebug!("No DH transform found"); SCLogDebug!("No DH transform found");
state.set_event(IkeEvent::WeakCryptoNoDh); tx.set_event(IkeEvent::WeakCryptoNoDh);
} }
// Rule 3: check if proposing AH ([RFC7296] section 3.3.1) // Rule 3: check if proposing AH ([RFC7296] section 3.3.1)
if p.protocol_id == ProtocolID::AH { if p.protocol_id == ProtocolID::AH {
SCLogDebug!("Proposal uses protocol AH - no confidentiality"); SCLogDebug!("Proposal uses protocol AH - no confidentiality");
state.set_event(IkeEvent::NoEncryption); tx.set_event(IkeEvent::NoEncryption);
} }
// Rule 4: lack of integrity is accepted only if using an AEAD proposal // Rule 4: lack of integrity is accepted only if using an AEAD proposal
// Look if no auth was proposed, including if proposal is Auth::None // Look if no auth was proposed, including if proposal is Auth::None
@ -315,21 +282,35 @@ fn add_proposals(state: &mut IKEState, prop: &Vec<IkeV2Proposal>, direction: u8)
_ => false, _ => false,
}) { }) {
SCLogDebug!("No integrity transform found"); SCLogDebug!("No integrity transform found");
state.set_event(IkeEvent::WeakCryptoNoAuth); tx.set_event(IkeEvent::WeakCryptoNoAuth);
} }
} }
// Finally // Finally
if direction == STREAM_TOCLIENT { if direction == STREAM_TOCLIENT {
transforms.iter().for_each(|t| match *t { transforms.iter().for_each(|t| match *t {
IkeV2Transform::Encryption(ref e) => state.ikev2_container.alg_enc = *e, IkeV2Transform::Encryption(ref e) => {
IkeV2Transform::Auth(ref a) => state.ikev2_container.alg_auth = *a, state.ikev2_container.alg_enc = *e;
IkeV2Transform::PRF(ref p) => state.ikev2_container.alg_prf = *p, tx.hdr.ikev2_transforms.push(IkeV2Transform::Encryption(*e));
IkeV2Transform::DH(ref dh) => state.ikev2_container.alg_dh = *dh, }
IkeV2Transform::ESN(ref e) => state.ikev2_container.alg_esn = *e, IkeV2Transform::Auth(ref a) => {
_ => (), state.ikev2_container.alg_auth = *a;
tx.hdr.ikev2_transforms.push(IkeV2Transform::Auth(*a));
}
IkeV2Transform::PRF(ref p) => {
state.ikev2_container.alg_prf = *p;
tx.hdr.ikev2_transforms.push(IkeV2Transform::PRF(*p));
}
IkeV2Transform::DH(ref dh) => {
state.ikev2_container.alg_dh = *dh;
tx.hdr.ikev2_transforms.push(IkeV2Transform::DH(*dh));
}
IkeV2Transform::ESN(ref e) => {
state.ikev2_container.alg_esn = *e;
tx.hdr.ikev2_transforms.push(IkeV2Transform::ESN(*e));
}
_ => {},
}); });
SCLogDebug!("Selected transforms: {:?}", transforms); SCLogDebug!("Selected transforms: {:?}", transforms);
state.ikev2_container.server_transforms.push(transforms);
} else { } else {
SCLogDebug!("Proposed transforms: {:?}", transforms); SCLogDebug!("Proposed transforms: {:?}", transforms);
state.ikev2_container.client_transforms.push(transforms); state.ikev2_container.client_transforms.push(transforms);

Loading…
Cancel
Save