aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2020-10-07 23:52:37 +0000
committerBeno�t Ganne <bganne@cisco.com>2020-10-21 13:30:41 +0000
commitec112e5a9eb708c1ee85faf569fef6fa40178294 (patch)
treee56ba2f771a7884145c675378ace857c1ec1812d
parent6960da528443ea40b1cdab323c76f978f7b16a8b (diff)
ikev2: fix setting responder/initiator addresses
Type: fix Change-Id: Ic406aa914d92e802a5fb0f27c2ffa1b98db012b0 Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
-rw-r--r--src/plugins/ikev2/ikev2.c82
-rw-r--r--src/plugins/ikev2/ikev2_payload.c24
-rw-r--r--src/plugins/ikev2/ikev2_priv.h1
-rw-r--r--src/plugins/ikev2/test/test_ikev2.py55
4 files changed, 95 insertions, 67 deletions
diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c
index 4b318605df3..3ce9114e358 100644
--- a/src/plugins/ikev2/ikev2.c
+++ b/src/plugins/ikev2/ikev2.c
@@ -640,7 +640,7 @@ ikev2_compute_nat_sha1 (u64 ispi, u64 rspi, ip_address_t * ia, u16 port)
clib_memcpy_fast (&buf[8], &rspi, sizeof (rspi));
clib_memcpy_fast (&buf[8 + 8], ip_addr_bytes (ia), ip_address_size (ia));
clib_memcpy_fast (&buf[8 + 8 + ip_address_size (ia)], &port, sizeof (port));
- SHA1 (buf, sizeof (buf), res);
+ SHA1 (buf, 2 * sizeof (ispi) + sizeof (port) + ip_address_size (ia), res);
return res;
}
@@ -2734,11 +2734,9 @@ ikev2_rewrite_v4_addrs (ikev2_sa_t * sa, ip4_header_t * ih)
}
static_always_inline void
-ikev2_set_ip_address (ikev2_sa_t * sa, const void *src,
- const void *dst, const int af, const int is_initiator)
+ikev2_set_ip_address (ikev2_sa_t * sa, const void *iaddr,
+ const void *raddr, const int af)
{
- const void *raddr = is_initiator ? src : dst;
- const void *iaddr = is_initiator ? dst : src;
ip_address_set (&sa->raddr, raddr, af);
ip_address_set (&sa->iaddr, iaddr, af);
}
@@ -2854,19 +2852,16 @@ ikev2_node_internal (vlib_main_t * vm,
sa0 = &sa;
clib_memset (sa0, 0, sizeof (*sa0));
- u8 is_initiator = ike0->flags & IKEV2_HDR_FLAG_INITIATOR;
- if (is_initiator)
+ if (ike0->flags & IKEV2_HDR_FLAG_INITIATOR)
{
if (ike0->rspi == 0)
{
if (is_ip4)
- ikev2_set_ip_address (sa0, &ip40->dst_address,
- &ip40->src_address, AF_IP4,
- is_initiator);
+ ikev2_set_ip_address (sa0, &ip40->src_address,
+ &ip40->dst_address, AF_IP4);
else
- ikev2_set_ip_address (sa0, &ip60->dst_address,
- &ip60->src_address, AF_IP6,
- is_initiator);
+ ikev2_set_ip_address (sa0, &ip60->src_address,
+ &ip60->dst_address, AF_IP6);
sa0->dst_port = clib_net_to_host_u16 (udp0->src_port);
@@ -2927,13 +2922,11 @@ ikev2_node_internal (vlib_main_t * vm,
else //received sa_init without initiator flag
{
if (is_ip4)
- ikev2_set_ip_address (sa0, &ip40->src_address,
- &ip40->dst_address, AF_IP4,
- is_initiator);
+ ikev2_set_ip_address (sa0, &ip40->dst_address,
+ &ip40->src_address, AF_IP4);
else
- ikev2_set_ip_address (sa0, &ip60->src_address,
- &ip60->dst_address, AF_IP6,
- is_initiator);
+ ikev2_set_ip_address (sa0, &ip60->dst_address,
+ &ip60->src_address, AF_IP6);
ikev2_process_sa_init_resp (vm, sa0, ike0, udp0, rlen);
@@ -4757,33 +4750,12 @@ ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa)
}
}
-static ike_payload_header_t *
-ikev2_find_ike_payload (ike_header_t * ike, u32 payload_type)
-{
- int p = 0;
- ike_payload_header_t *ikep;
- u32 payload = ike->nextpayload;
-
- while (payload != IKEV2_PAYLOAD_NONE)
- {
- ikep = (ike_payload_header_t *) & ike->payload[p];
- if (payload == payload_type)
- return ikep;
-
- u16 plen = clib_net_to_host_u16 (ikep->length);
- payload = ikep->nextpayload;
- p += plen;
- }
- return 0;
-}
-
static void
ikev2_process_pending_sa_init_one (ikev2_main_t * km, ikev2_sa_t * sa)
{
ikev2_profile_t *p;
u32 bi0;
- u8 *nat_sha;
- ike_payload_header_t *ph;
+ u8 *nat_sha, *np;
if (ip_address_is_zero (&sa->iaddr))
{
@@ -4794,20 +4766,20 @@ ikev2_process_pending_sa_init_one (ikev2_main_t * km, ikev2_sa_t * sa)
return;
/* update NAT detection payload */
- ph =
- ikev2_find_ike_payload ((ike_header_t *)
- sa->last_sa_init_req_packet_data,
- IKEV2_NOTIFY_MSG_NAT_DETECTION_SOURCE_IP);
- if (!ph)
- return;
-
- nat_sha =
- ikev2_compute_nat_sha1 (clib_host_to_net_u64 (sa->ispi),
- clib_host_to_net_u64 (sa->rspi),
- &sa->iaddr,
- clib_host_to_net_u16 (IKEV2_PORT));
- clib_memcpy_fast (ph->payload, nat_sha, vec_len (nat_sha));
- vec_free (nat_sha);
+ np =
+ ikev2_find_ike_notify_payload
+ ((ike_header_t *) sa->last_sa_init_req_packet_data,
+ IKEV2_NOTIFY_MSG_NAT_DETECTION_SOURCE_IP);
+ if (np)
+ {
+ nat_sha =
+ ikev2_compute_nat_sha1 (clib_host_to_net_u64 (sa->ispi),
+ clib_host_to_net_u64 (sa->rspi),
+ &sa->iaddr,
+ clib_host_to_net_u16 (IKEV2_PORT));
+ clib_memcpy_fast (np, nat_sha, vec_len (nat_sha));
+ vec_free (nat_sha);
+ }
}
if (vlib_buffer_alloc (km->vlib_main, &bi0, 1) != 1)
diff --git a/src/plugins/ikev2/ikev2_payload.c b/src/plugins/ikev2/ikev2_payload.c
index c03054aa9cd..294864d8c43 100644
--- a/src/plugins/ikev2/ikev2_payload.c
+++ b/src/plugins/ikev2/ikev2_payload.c
@@ -588,6 +588,30 @@ ikev2_parse_delete_payload (ike_payload_header_t * ikep, u32 rlen)
return r;
}
+u8 *
+ikev2_find_ike_notify_payload (ike_header_t * ike, u32 msg_type)
+{
+ int p = 0;
+ ike_notify_payload_header_t *n;
+ ike_payload_header_t *ikep;
+ u32 payload = ike->nextpayload;
+
+ while (payload != IKEV2_PAYLOAD_NONE)
+ {
+ ikep = (ike_payload_header_t *) & ike->payload[p];
+ if (payload == IKEV2_PAYLOAD_NOTIFY)
+ {
+ n = (ike_notify_payload_header_t *)ikep;
+ if (n->msg_type == clib_net_to_host_u16 (msg_type))
+ return n->payload;
+ }
+ u16 plen = clib_net_to_host_u16 (ikep->length);
+ payload = ikep->nextpayload;
+ p += plen;
+ }
+ return 0;
+}
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/src/plugins/ikev2/ikev2_priv.h b/src/plugins/ikev2/ikev2_priv.h
index 68a546a0f48..115a5b2a6b3 100644
--- a/src/plugins/ikev2/ikev2_priv.h
+++ b/src/plugins/ikev2/ikev2_priv.h
@@ -568,6 +568,7 @@ ikev2_delete_t *ikev2_parse_delete_payload (ike_payload_header_t * ikep,
ikev2_notify_t *ikev2_parse_notify_payload (ike_payload_header_t * ikep,
u32 rlen);
int ikev2_set_log_level (ikev2_log_level_t log_level);
+u8 *ikev2_find_ike_notify_payload (ike_header_t * ike, u32 msg_type);
static_always_inline ikev2_main_per_thread_data_t *
ikev2_get_per_thread_data ()
diff --git a/src/plugins/ikev2/test/test_ikev2.py b/src/plugins/ikev2/test/test_ikev2.py
index 4f64b56d853..f75a517f824 100644
--- a/src/plugins/ikev2/test/test_ikev2.py
+++ b/src/plugins/ikev2/test/test_ikev2.py
@@ -1,4 +1,5 @@
import os
+from socket import inet_pton
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, hmac
@@ -510,8 +511,10 @@ class IKEv2SA(object):
def esp_crypto_attr(self):
return self.crypto_attr(self.esp_crypto_key_len)
- def compute_nat_sha1(self, ip, port):
- data = self.ispi + self.rspi + ip + (port).to_bytes(2, 'big')
+ def compute_nat_sha1(self, ip, port, rspi=None):
+ if rspi is None:
+ rspi = self.rspi
+ data = self.ispi + rspi + ip + (port).to_bytes(2, 'big')
digest = hashes.Hash(hashes.SHA1(), backend=default_backend())
digest.update(data)
return digest.finalize()
@@ -775,6 +778,36 @@ class TemplateInitiator(IkePeer):
def tearDown(self):
super(TemplateInitiator, self).tearDown()
+ @staticmethod
+ def find_notify_payload(packet, notify_type):
+ n = packet[ikev2.IKEv2_payload_Notify]
+ while n is not None:
+ if n.type == notify_type:
+ return n
+ n = n.payload
+ return None
+
+ def verify_nat_detection(self, packet):
+ if self.ip6:
+ iph = packet[IPv6]
+ else:
+ iph = packet[IP]
+ udp = packet[UDP]
+
+ # NAT_DETECTION_SOURCE_IP
+ s = self.find_notify_payload(packet, 16388)
+ self.assertIsNotNone(s)
+ src_sha = self.sa.compute_nat_sha1(
+ inet_pton(socket.AF_INET, iph.src), udp.sport, b'\x00' * 8)
+ self.assertEqual(s.load, src_sha)
+
+ # NAT_DETECTION_DESTINATION_IP
+ s = self.find_notify_payload(packet, 16389)
+ self.assertIsNotNone(s)
+ dst_sha = self.sa.compute_nat_sha1(
+ inet_pton(socket.AF_INET, iph.dst), udp.dport, b'\x00' * 8)
+ self.assertEqual(s.load, dst_sha)
+
def verify_sa_init_request(self, packet):
ih = packet[ikev2.IKEv2]
self.assertNotEqual(ih.init_SPI, 8 * b'\x00')
@@ -798,6 +831,7 @@ class TemplateInitiator(IkePeer):
self.assertEqual(prop.trans[2].transform_id,
self.p.ike_transforms['dh_group'])
+ self.verify_nat_detection(packet)
self.sa.complete_dh_data()
self.sa.calc_keys()
@@ -957,11 +991,6 @@ class TemplateResponder(IkePeer):
props = (ikev2.IKEv2_payload_Proposal(proposal=1, proto='IKEv2',
trans_nb=4, trans=trans))
- if behind_nat:
- next_payload = 'Notify'
- else:
- next_payload = None
-
self.sa.init_req_packet = (
ikev2.IKEv2(init_SPI=self.sa.ispi,
flags='Initiator', exch_type='IKE_SA_INIT') /
@@ -969,19 +998,21 @@ class TemplateResponder(IkePeer):
ikev2.IKEv2_payload_KE(next_payload='Nonce',
group=self.sa.ike_dh,
load=self.sa.my_dh_pub_key) /
- ikev2.IKEv2_payload_Nonce(next_payload=next_payload,
+ ikev2.IKEv2_payload_Nonce(next_payload='Notify',
load=self.sa.i_nonce))
if behind_nat:
src_address = b'\x0a\x0a\x0a\x01'
else:
- src_address = bytes(self.pg0.local_ip4, 'ascii')
+ src_address = inet_pton(socket.AF_INET, self.pg0.remote_ip4)
src_nat = self.sa.compute_nat_sha1(src_address, self.sa.sport)
- dst_nat = self.sa.compute_nat_sha1(bytes(self.pg0.remote_ip4, 'ascii'),
- self.sa.sport)
+ dst_nat = self.sa.compute_nat_sha1(
+ inet_pton(socket.AF_INET, self.pg0.local_ip4),
+ self.sa.dport)
nat_src_detection = ikev2.IKEv2_payload_Notify(
- type='NAT_DETECTION_SOURCE_IP', load=src_nat)
+ type='NAT_DETECTION_SOURCE_IP', load=src_nat,
+ next_payload='Notify')
nat_dst_detection = ikev2.IKEv2_payload_Notify(
type='NAT_DETECTION_DESTINATION_IP', load=dst_nat)
self.sa.init_req_packet = (self.sa.init_req_packet /