diff options
-rw-r--r-- | src/plugins/ikev2/ikev2.c | 34 | ||||
-rw-r--r-- | test/test_ikev2.py | 43 |
2 files changed, 57 insertions, 20 deletions
diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c index 873ec136dae..c184a466c47 100644 --- a/src/plugins/ikev2/ikev2.c +++ b/src/plugins/ikev2/ikev2.c @@ -1050,7 +1050,7 @@ ikev2_decrypt_sk_payload (ikev2_sa_t * sa, ike_header_t * ike, } static int -ikev2_is_id_equal (ikev2_id_t *i1, ikev2_id_t *i2) +ikev2_is_id_equal (const ikev2_id_t *i1, const ikev2_id_t *i2) { if (i1->type != i2->type) return 0; @@ -1572,6 +1572,25 @@ ikev2_sa_generate_authmsg (ikev2_sa_t * sa, int is_responder) } static int +ikev2_match_profile (const ikev2_profile_t *p, const ikev2_id_t *id_loc, + const ikev2_id_t *id_rem, int is_initiator) +{ + /* on the initiator, IDi is always present and must match + * however on the responder, IDr (which is our local id) is optional */ + if ((is_initiator || id_loc->type != 0) && + !ikev2_is_id_equal (&p->loc_id, id_loc)) + return 0; + + /* on the initiator, we might not have configured a specific remote id + * however on the responder, the remote id should always be configured */ + if ((!is_initiator || p->rem_id.type != 0) && + !ikev2_is_id_equal (&p->rem_id, id_rem)) + return 0; + + return 1; +} + +static int ikev2_ts_cmp (ikev2_ts_t * ts1, ikev2_ts_t * ts2) { if (ts1->ts_type == ts2->ts_type && ts1->protocol_id == ts2->protocol_id && @@ -1609,9 +1628,7 @@ ikev2_sa_match_ts (ikev2_sa_t * sa) id_loc = &sa->r_id; } - /* check id */ - if (!ikev2_is_id_equal (&p->rem_id, id_rem) - || !ikev2_is_id_equal (&p->loc_id, id_loc)) + if (!ikev2_match_profile (p, id_loc, id_rem, sa->is_initiator)) continue; sa->profile_index = p - km->profiles; @@ -1679,9 +1696,7 @@ ikev2_select_profile (ikev2_main_t *km, ikev2_sa_t *sa, pool_foreach (p, km->profiles) { - /* check id */ - if (!ikev2_is_id_equal (&p->rem_id, id_rem) || - !ikev2_is_id_equal (&p->loc_id, id_loc)) + if (!ikev2_match_profile (p, id_loc, id_rem, sa->is_initiator)) continue; if (sa_auth->method == IKEV2_AUTH_METHOD_SHARED_KEY_MIC) @@ -2444,7 +2459,10 @@ ikev2_generate_message (vlib_buffer_t *b, ikev2_sa_t *sa, ike_header_t *ike, else if (sa->state == IKEV2_STATE_SA_INIT) { ikev2_payload_add_id (chain, &sa->i_id, IKEV2_PAYLOAD_IDI); - ikev2_payload_add_id (chain, &sa->r_id, IKEV2_PAYLOAD_IDR); + /* IDr is optional when sending INIT from the initiator */ + ASSERT (sa->r_id.type != 0 || sa->is_initiator); + if (sa->r_id.type != 0) + ikev2_payload_add_id (chain, &sa->r_id, IKEV2_PAYLOAD_IDR); ikev2_payload_add_auth (chain, &sa->i_auth); ikev2_payload_add_sa (chain, sa->childs[0].i_proposals); ikev2_payload_add_ts (chain, sa->childs[0].tsi, IKEV2_PAYLOAD_TSI); diff --git a/test/test_ikev2.py b/test/test_ikev2.py index 4f41ad272ba..438a674977f 100644 --- a/test/test_ikev2.py +++ b/test/test_ikev2.py @@ -802,9 +802,9 @@ class IkePeer(VppTestCase): self.assertEqual(sa.i_id.type, self.sa.id_type) self.assertEqual(sa.r_id.type, self.sa.id_type) self.assertEqual(sa.i_id.data_len, len(self.sa.i_id)) - self.assertEqual(sa.r_id.data_len, len(self.sa.r_id)) + self.assertEqual(sa.r_id.data_len, len(self.idr)) self.assertEqual(bytes(sa.i_id.data, 'ascii'), self.sa.i_id) - self.assertEqual(bytes(sa.r_id.data, 'ascii'), self.sa.r_id) + self.assertEqual(bytes(sa.r_id.data, 'ascii'), self.idr) r = self.vapi.ikev2_child_sa_dump(sa_index=sa.sa_index) self.assertEqual(len(r), 1) @@ -1003,9 +1003,12 @@ class TemplateInitiator(IkePeer): self.sa.msg_id += 1 plain = self.sa.hmac_and_decrypt(ih) idi = ikev2.IKEv2_payload_IDi(plain) - idr = ikev2.IKEv2_payload_IDr(idi.payload) self.assertEqual(idi.load, self.sa.i_id) - self.assertEqual(idr.load, self.sa.r_id) + if self.no_idr_auth: + self.assertEqual(idi.next_payload, 39) # AUTH + else: + idr = ikev2.IKEv2_payload_IDr(idi.payload) + self.assertEqual(idr.load, self.sa.r_id) prop = idi[ikev2.IKEv2_payload_Proposal] c = self.sa.child_sas[0] c.ispi = prop.SPI @@ -1264,10 +1267,15 @@ class TemplateResponder(IkePeer): proto='ESP', SPI=c.ispi)) else: first_payload = 'IDi' - ids = (ikev2.IKEv2_payload_IDi(next_payload='IDr', - IDtype=self.sa.id_type, load=self.sa.i_id) / - ikev2.IKEv2_payload_IDr(next_payload='AUTH', - IDtype=self.sa.id_type, load=self.sa.r_id)) + if self.no_idr_auth: + ids = ikev2.IKEv2_payload_IDi(next_payload='AUTH', + IDtype=self.sa.id_type, + load=self.sa.i_id) + else: + ids = (ikev2.IKEv2_payload_IDi(next_payload='IDr', + IDtype=self.sa.id_type, load=self.sa.i_id) / + ikev2.IKEv2_payload_IDr(next_payload='AUTH', + IDtype=self.sa.id_type, load=self.sa.r_id)) plain = ids / plain return plain, first_payload @@ -1394,15 +1402,23 @@ class Ikev2Params(object): is_init = True if 'is_initiator' not in params else\ params['is_initiator'] + self.no_idr_auth = params.get('no_idr_in_auth', False) idr = {'id_type': 'fqdn', 'data': b'vpp.home'} idi = {'id_type': 'fqdn', 'data': b'roadwarrior.example.com'} + r_id = self.idr = idr['data'] + i_id = self.idi = idi['data'] if is_init: + # scapy is initiator, VPP is responder self.p.add_local_id(**idr) self.p.add_remote_id(**idi) + if self.no_idr_auth: + r_id = None else: + # VPP is initiator, scapy is responder self.p.add_local_id(**idi) - self.p.add_remote_id(**idr) + if not self.no_idr_auth: + self.p.add_remote_id(**idr) loc_ts = {'start_addr': '10.10.10.0', 'end_addr': '10.10.10.255'} if\ 'loc_ts' not in params else params['loc_ts'] @@ -1436,7 +1452,7 @@ class Ikev2Params(object): self.pg0.remote_ip4) self.vapi.cli(cmd) - self.sa = IKEv2SA(self, i_id=idi['data'], r_id=idr['data'], + self.sa = IKEv2SA(self, i_id=i_id, r_id=r_id, is_initiator=is_init, id_type=self.p.local_id['id_type'], i_natt=i_natt, r_natt=r_natt, @@ -1444,6 +1460,7 @@ class Ikev2Params(object): nonce=params.get('nonce'), auth_data=auth_data, udp_encap=udp_encap, local_ts=self.p.remote_ts, remote_ts=self.p.local_ts) + if is_init: ike_crypto = ('AES-CBC', 32) if 'ike-crypto' not in params else\ params['ike-crypto'] @@ -1818,7 +1835,8 @@ class TestInitiatorDelSAFromResponder(TemplateInitiator, Ikev2Params): 'crypto_alg': 12, # "aes-cbc" 'crypto_key_size': 256, # "hmac-sha2-256-128" - 'integ_alg': 12}}) + 'integ_alg': 12}, + 'no_idr_in_auth': True}) @tag_fixme_vpp_workers @@ -1957,7 +1975,8 @@ class Test_IKE_AES_CBC_128_SHA256_128_MODP2048_ESP_AES_CBC_192_SHA_384_192\ 'esp-crypto': ('AES-CBC', 24), 'esp-integ': 'SHA2-384-192', 'ike-dh': '2048MODPgr', - 'nonce': os.urandom(256)}) + 'nonce': os.urandom(256), + 'no_idr_in_auth': True}) @tag_fixme_vpp_workers |