ike: log ikev1 tx fields instead of state ones

As state fields can grow abitrarily, and this can lead to DOS
by quadratic complexity (CPU time and disk space)

Adds a direction field to retain all the information in the
transaction.

Also checks array vendor_ids had at least one element before
logging it.

Ticket: #5455
pull/7713/head
Philippe Antoine 4 years ago committed by Victor Julien
parent d0171d7418
commit 3de735ae70

@ -97,6 +97,7 @@ pub struct IKETransaction {
tx_id: u64, tx_id: u64,
pub ike_version: u8, pub ike_version: u8,
pub direction: Direction,
pub hdr: IkeHeaderWrapper, pub hdr: IkeHeaderWrapper,
pub payload_types: IkePayloadWrapper, pub payload_types: IkePayloadWrapper,
pub notify_types: Vec<NotifyType>, pub notify_types: Vec<NotifyType>,
@ -119,6 +120,7 @@ impl IKETransaction {
IKETransaction { IKETransaction {
tx_id: 0, tx_id: 0,
ike_version: 0, ike_version: 0,
direction: Direction::ToServer,
hdr: IkeHeaderWrapper::new(), hdr: IkeHeaderWrapper::new(),
payload_types: Default::default(), payload_types: Default::default(),
notify_types: vec![], notify_types: vec![],

@ -40,27 +40,27 @@ pub struct IkeV1Header {
pub struct Ikev1ParticipantData { pub struct Ikev1ParticipantData {
pub key_exchange: String, pub key_exchange: String,
pub nonce: String, pub nonce: String,
pub vendor_ids: HashSet<String>, pub nb_transforms: u64,
/// nested Vec, outer Vec per Proposal/Transform, inner Vec has the list of attributes. pub transform: Vec<SaAttribute>,
pub transforms: Vec<Vec<SaAttribute>>,
} }
impl Ikev1ParticipantData { impl Ikev1ParticipantData {
pub fn reset(&mut self) { pub fn reset(&mut self) {
self.key_exchange.clear(); self.key_exchange.clear();
self.nonce.clear(); self.nonce.clear();
self.vendor_ids.clear(); self.nb_transforms = 0;
self.transforms.clear(); self.transform.clear();
} }
pub fn update( pub fn update(
&mut self, key_exchange: &String, nonce: &String, vendor_ids: &Vec<String>, &mut self, key_exchange: &String, nonce: &String, transforms: &Vec<Vec<SaAttribute>>,
transforms: &Vec<Vec<SaAttribute>>,
) { ) {
self.key_exchange = key_exchange.clone(); self.key_exchange = key_exchange.clone();
self.nonce = nonce.clone(); self.nonce = nonce.clone();
self.vendor_ids.extend(vendor_ids.iter().cloned()); if self.nb_transforms == 0 && transforms.len() > 0 {
self.transforms.extend(transforms.iter().cloned()); self.transform.extend(transforms[0].iter().cloned());
}
self.nb_transforms += transforms.len() as u64;
} }
} }
@ -77,6 +77,7 @@ pub fn handle_ikev1(
let mut tx = state.new_tx(); let mut tx = state.new_tx();
tx.ike_version = 1; tx.ike_version = 1;
tx.direction = direction;
tx.hdr.spi_initiator = format!("{:016x}", isakmp_header.init_spi); tx.hdr.spi_initiator = format!("{:016x}", isakmp_header.init_spi);
tx.hdr.spi_responder = format!("{:016x}", isakmp_header.resp_spi); tx.hdr.spi_responder = format!("{:016x}", isakmp_header.resp_spi);
tx.hdr.maj_ver = isakmp_header.maj_ver; tx.hdr.maj_ver = isakmp_header.maj_ver;
@ -126,13 +127,12 @@ pub fn handle_ikev1(
state.ikev1_container.client.update( state.ikev1_container.client.update(
&to_hex(tx.hdr.ikev1_header.key_exchange.as_ref()), &to_hex(tx.hdr.ikev1_header.key_exchange.as_ref()),
&to_hex(tx.hdr.ikev1_header.nonce.as_ref()), &to_hex(tx.hdr.ikev1_header.nonce.as_ref()),
&tx.hdr.ikev1_header.vendor_ids,
&tx.hdr.ikev1_transforms, &tx.hdr.ikev1_transforms,
); );
} else { } else {
if state.ikev1_container.server.transforms.len() <= 1 if state.ikev1_container.server.nb_transforms <= 1
&& state.ikev1_container.server.transforms.len() && state.ikev1_container.server.nb_transforms
+ tx.hdr.ikev1_transforms.len() + tx.hdr.ikev1_transforms.len() as u64
> 1 > 1
{ {
SCLogDebug!("More than one chosen server proposal"); SCLogDebug!("More than one chosen server proposal");
@ -142,7 +142,6 @@ pub fn handle_ikev1(
state.ikev1_container.server.update( state.ikev1_container.server.update(
&to_hex(tx.hdr.ikev1_header.key_exchange.as_ref()), &to_hex(tx.hdr.ikev1_header.key_exchange.as_ref()),
&to_hex(tx.hdr.ikev1_header.nonce.as_ref()), &to_hex(tx.hdr.ikev1_header.nonce.as_ref()),
&tx.hdr.ikev1_header.vendor_ids,
&tx.hdr.ikev1_transforms, &tx.hdr.ikev1_transforms,
); );
} }

@ -17,6 +17,7 @@
use super::ike::{IKEState, IKETransaction}; use super::ike::{IKEState, IKETransaction};
use super::ipsec_parser::IKEV2_FLAG_INITIATOR; use super::ipsec_parser::IKEV2_FLAG_INITIATOR;
use crate::core::Direction;
use crate::ike::parser::{ExchangeType, IsakmpPayloadType, SaAttribute}; use crate::ike::parser::{ExchangeType, IsakmpPayloadType, SaAttribute};
use crate::jsonbuilder::{JsonBuilder, JsonError}; use crate::jsonbuilder::{JsonBuilder, JsonError};
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
@ -73,14 +74,14 @@ fn log_ike(
} }
if tx.ike_version == 1 { if tx.ike_version == 1 {
if state.ikev1_container.server.transforms.len() > 0 { if state.ikev1_container.server.nb_transforms > 0 {
// log the first transform as the chosen one // log the first transform as the chosen one
add_attributes(&state.ikev1_container.server.transforms[0], jb)?; add_attributes(&state.ikev1_container.server.transform, jb)?;
} }
if state.ikev1_container.server.transforms.len() > 1 { if tx.direction == Direction::ToClient && tx.hdr.ikev1_transforms.len() > 1 {
// in case we have multiple server transforms log them in a list // in case we have multiple server transforms log them in a list
jb.open_array("server_proposals")?; jb.open_array("server_proposals")?;
for server_transform in &state.ikev1_container.server.transforms { for server_transform in &tx.hdr.ikev1_transforms {
jb.start_object()?; jb.start_object()?;
add_attributes(server_transform, jb)?; add_attributes(server_transform, jb)?;
jb.close()?; jb.close()?;
@ -156,13 +157,15 @@ fn log_ikev1(state: &IKEState, tx: &IKETransaction, jb: &mut JsonBuilder) -> Res
} }
} }
jb.open_array("proposals")?; if tx.direction == Direction::ToServer && tx.hdr.ikev1_transforms.len() > 0 {
for client_transform in &state.ikev1_container.client.transforms { jb.open_array("proposals")?;
jb.start_object()?; for client_transform in &tx.hdr.ikev1_transforms {
add_attributes(client_transform, jb)?; jb.start_object()?;
jb.close()?; add_attributes(client_transform, jb)?;
jb.close()?;
}
jb.close()?; // proposals
} }
jb.close()?; // proposals
jb.close()?; // client jb.close()?; // client
// server data // server data
@ -187,16 +190,13 @@ fn log_ikev1(state: &IKEState, tx: &IKETransaction, jb: &mut JsonBuilder) -> Res
} }
jb.close()?; // server jb.close()?; // server
jb.open_array("vendor_ids")?; if tx.hdr.ikev1_header.vendor_ids.len() > 0 {
for vendor in state jb.open_array("vendor_ids")?;
.ikev1_container for vendor in &tx.hdr.ikev1_header.vendor_ids {
.client jb.append_string(vendor)?;
.vendor_ids }
.union(&state.ikev1_container.server.vendor_ids) jb.close()?; // vendor_ids
{
jb.append_string(vendor)?;
} }
jb.close()?; // vendor_ids
} }
jb.close()?; jb.close()?;

Loading…
Cancel
Save