Merge commit 'child-sa-rekey-tkm'
This fixes CHILD_SA rekeying with TKM and changes how we switch to the outbound IPsec SA with Netlink/XFRM (using SPIs on the outbound policy instead of installing the outbound SA delayed). For charon-tkm it changes when esa_select() and esa_reset() are called, now with the outbound policy and the inbound SA, respectively, instead of the outbound SA in both cases. Also fixed is a potential traffic loss when a rekey collision is lost.
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2017 Tobias Brunner
|
||||||
* Copyright (C) 2012-2014 Reto Buerki
|
* Copyright (C) 2012-2014 Reto Buerki
|
||||||
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
* Copyright (C) 2012 Adrian-Ken Rueegsegger
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -52,6 +53,12 @@ struct private_tkm_kernel_ipsec_t {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
||||||
|
private_tkm_kernel_ipsec_t *this)
|
||||||
|
{
|
||||||
|
return KERNEL_POLICY_SPI;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(kernel_ipsec_t, get_spi, status_t,
|
METHOD(kernel_ipsec_t, get_spi, status_t,
|
||||||
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
|
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
uint8_t protocol, uint32_t *spi)
|
uint8_t protocol, uint32_t *spi)
|
||||||
@@ -176,15 +183,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
|||||||
tkm->chunk_map->remove(tkm->chunk_map, nonce_loc);
|
tkm->chunk_map->remove(tkm->chunk_map, nonce_loc);
|
||||||
tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nonce_loc_id);
|
tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nonce_loc_id);
|
||||||
}
|
}
|
||||||
if (ike_esa_select(esa_id) != TKM_OK)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "error selecting new child SA (%llu)", esa_id);
|
|
||||||
if (ike_esa_reset(esa_id) != TKM_OK)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "child SA (%llu) deletion failed", esa_id);
|
|
||||||
}
|
|
||||||
goto failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG1(DBG_KNL, "added child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, "
|
DBG1(DBG_KNL, "added child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, "
|
||||||
"esp_spi_rem: %x, role: %s)", esa_id, esa.isa_id, ntohl(spi_loc),
|
"esp_spi_rem: %x, role: %s)", esa_id, esa.isa_id, ntohl(spi_loc),
|
||||||
@@ -215,23 +213,12 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
|
|||||||
private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
private_tkm_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
|
||||||
kernel_ipsec_del_sa_t *data)
|
kernel_ipsec_del_sa_t *data)
|
||||||
{
|
{
|
||||||
esa_id_type esa_id, other_esa_id;
|
esa_id_type esa_id;
|
||||||
|
|
||||||
esa_id = tkm->sad->get_esa_id(tkm->sad, id->src, id->dst,
|
esa_id = tkm->sad->get_esa_id(tkm->sad, id->src, id->dst,
|
||||||
id->spi, id->proto);
|
id->spi, id->proto, TRUE);
|
||||||
if (esa_id)
|
if (esa_id)
|
||||||
{
|
{
|
||||||
other_esa_id = tkm->sad->get_other_esa_id(tkm->sad, esa_id);
|
|
||||||
if (other_esa_id)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "selecting child SA (esa: %llu)", other_esa_id);
|
|
||||||
if (ike_esa_select(other_esa_id) != TKM_OK)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "error selecting other child SA (esa: %llu)",
|
|
||||||
other_esa_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG1(DBG_KNL, "deleting child SA (esa: %llu, spi: %x)", esa_id,
|
DBG1(DBG_KNL, "deleting child SA (esa: %llu, spi: %x)", esa_id,
|
||||||
ntohl(id->spi));
|
ntohl(id->spi));
|
||||||
if (ike_esa_reset(esa_id) != TKM_OK)
|
if (ike_esa_reset(esa_id) != TKM_OK)
|
||||||
@@ -263,6 +250,43 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
|
|||||||
private_tkm_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
private_tkm_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
|
||||||
kernel_ipsec_manage_policy_t *data)
|
kernel_ipsec_manage_policy_t *data)
|
||||||
{
|
{
|
||||||
|
esa_id_type esa_id;
|
||||||
|
uint32_t spi;
|
||||||
|
uint8_t proto;
|
||||||
|
|
||||||
|
if (id->dir == POLICY_OUT && data->type == POLICY_IPSEC &&
|
||||||
|
data->prio == POLICY_PRIORITY_DEFAULT)
|
||||||
|
{
|
||||||
|
if (data->sa->esp.use)
|
||||||
|
{
|
||||||
|
spi = data->sa->esp.spi;
|
||||||
|
proto = IPPROTO_ESP;
|
||||||
|
}
|
||||||
|
else if (data->sa->ah.use)
|
||||||
|
{
|
||||||
|
spi = data->sa->ah.spi;
|
||||||
|
proto = IPPROTO_AH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
esa_id = tkm->sad->get_esa_id(tkm->sad, data->src, data->dst,
|
||||||
|
spi, proto, FALSE);
|
||||||
|
if (!esa_id)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "unable to find esa ID for policy (spi: %x)",
|
||||||
|
ntohl(spi));
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
DBG1(DBG_KNL, "selecting child SA (esa: %llu, spi: %x)", esa_id,
|
||||||
|
ntohl(spi));
|
||||||
|
if (ike_esa_select(esa_id) != TKM_OK)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "error selecting new child SA (%llu)", esa_id);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,6 +382,7 @@ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create()
|
|||||||
INIT(this,
|
INIT(this,
|
||||||
.public = {
|
.public = {
|
||||||
.interface = {
|
.interface = {
|
||||||
|
.get_features = _get_features,
|
||||||
.get_spi = _get_spi,
|
.get_spi = _get_spi,
|
||||||
.get_cpi = _get_cpi,
|
.get_cpi = _get_cpi,
|
||||||
.add_sa = _add_sa,
|
.add_sa = _add_sa,
|
||||||
|
|||||||
@@ -107,16 +107,23 @@ CALLBACK(sad_entry_match, bool,
|
|||||||
const host_t *src, *dst;
|
const host_t *src, *dst;
|
||||||
const uint32_t *spi;
|
const uint32_t *spi;
|
||||||
const uint8_t *proto;
|
const uint8_t *proto;
|
||||||
|
const bool *local;
|
||||||
|
|
||||||
VA_ARGS_VGET(args, src, dst, spi, proto);
|
VA_ARGS_VGET(args, src, dst, spi, proto, local);
|
||||||
|
|
||||||
if (entry->src == NULL || entry->dst == NULL)
|
if (entry->src == NULL || entry->dst == NULL || entry->proto != *proto)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return src->ip_equals(entry->src, (host_t *)src) &&
|
if (*local)
|
||||||
dst->ip_equals(entry->dst, (host_t *)dst) &&
|
{
|
||||||
entry->spi_rem == *spi && entry->proto == *proto;
|
return entry->src->ip_equals(entry->src, (host_t *)dst) &&
|
||||||
|
entry->dst->ip_equals(entry->dst, (host_t *)src) &&
|
||||||
|
entry->spi_loc == *spi;
|
||||||
|
}
|
||||||
|
return entry->src->ip_equals(entry->src, (host_t *)src) &&
|
||||||
|
entry->dst->ip_equals(entry->dst, (host_t *)dst) &&
|
||||||
|
entry->spi_rem == *spi;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(sad_entry_match_dst, bool,
|
CALLBACK(sad_entry_match_dst, bool,
|
||||||
@@ -131,26 +138,6 @@ CALLBACK(sad_entry_match_dst, bool,
|
|||||||
entry->proto == *proto;
|
entry->proto == *proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(sad_entry_match_esa_id, bool,
|
|
||||||
sad_entry_t * const entry, va_list args)
|
|
||||||
{
|
|
||||||
const esa_id_type *esa_id;
|
|
||||||
|
|
||||||
VA_ARGS_VGET(args, esa_id);
|
|
||||||
return entry->esa_id == *esa_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
CALLBACK(sad_entry_match_other_esa, bool,
|
|
||||||
sad_entry_t * const entry, va_list args)
|
|
||||||
{
|
|
||||||
const esa_id_type *esa_id;
|
|
||||||
const uint32_t *reqid;
|
|
||||||
|
|
||||||
VA_ARGS_VGET(args, esa_id, reqid);
|
|
||||||
return entry->reqid == *reqid &&
|
|
||||||
entry->esa_id != *esa_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
CALLBACK(sad_entry_equal, bool,
|
CALLBACK(sad_entry_equal, bool,
|
||||||
sad_entry_t * const left, va_list args)
|
sad_entry_t * const left, va_list args)
|
||||||
{
|
{
|
||||||
@@ -213,7 +200,8 @@ METHOD(tkm_kernel_sad_t, insert, bool,
|
|||||||
|
|
||||||
METHOD(tkm_kernel_sad_t, get_esa_id, esa_id_type,
|
METHOD(tkm_kernel_sad_t, get_esa_id, esa_id_type,
|
||||||
private_tkm_kernel_sad_t * const this, const host_t * const src,
|
private_tkm_kernel_sad_t * const this, const host_t * const src,
|
||||||
const host_t * const dst, const uint32_t spi, const uint8_t proto)
|
const host_t * const dst, const uint32_t spi, const uint8_t proto,
|
||||||
|
const bool local)
|
||||||
{
|
{
|
||||||
esa_id_type id = 0;
|
esa_id_type id = 0;
|
||||||
sad_entry_t *entry = NULL;
|
sad_entry_t *entry = NULL;
|
||||||
@@ -221,51 +209,18 @@ METHOD(tkm_kernel_sad_t, get_esa_id, esa_id_type,
|
|||||||
this->mutex->lock(this->mutex);
|
this->mutex->lock(this->mutex);
|
||||||
const bool res = this->data->find_first(this->data, sad_entry_match,
|
const bool res = this->data->find_first(this->data, sad_entry_match,
|
||||||
(void**)&entry, src, dst, &spi,
|
(void**)&entry, src, dst, &spi,
|
||||||
&proto);
|
&proto, &local);
|
||||||
if (res && entry)
|
if (res && entry)
|
||||||
{
|
{
|
||||||
id = entry->esa_id;
|
id = entry->esa_id;
|
||||||
DBG3(DBG_KNL, "returning ESA id %llu of SAD entry (src: %H, dst: %H, "
|
DBG3(DBG_KNL, "returning ESA id %llu of SAD entry (src: %H, dst: %H, "
|
||||||
"spi: %x, proto: %u)", id, src, dst, ntohl(spi), proto);
|
"%sbound spi: %x, proto: %u)", id, src, dst, local ? "in" : "out",
|
||||||
|
ntohl(spi), proto);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBG3(DBG_KNL, "no SAD entry found for src %H, dst %H, spi %x, proto %u",
|
DBG3(DBG_KNL, "no SAD entry found for src %H, dst %H, %sbound spi %x, "
|
||||||
src, dst, ntohl(spi), proto);
|
"proto %u", src, dst, local ? "in" : "out", ntohl(spi), proto);
|
||||||
}
|
|
||||||
this->mutex->unlock(this->mutex);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
METHOD(tkm_kernel_sad_t, get_other_esa_id, esa_id_type,
|
|
||||||
private_tkm_kernel_sad_t * const this, const esa_id_type esa_id)
|
|
||||||
{
|
|
||||||
esa_id_type id = 0;
|
|
||||||
sad_entry_t *entry = NULL;
|
|
||||||
uint32_t reqid;
|
|
||||||
bool res;
|
|
||||||
|
|
||||||
this->mutex->lock(this->mutex);
|
|
||||||
res = this->data->find_first(this->data, sad_entry_match_esa_id,
|
|
||||||
(void**)&entry, &esa_id);
|
|
||||||
if (res && entry)
|
|
||||||
{
|
|
||||||
reqid = entry->reqid;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG3(DBG_KNL, "no SAD entry found for ESA id %llu", esa_id);
|
|
||||||
this->mutex->unlock(this->mutex);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = this->data->find_first(this->data, sad_entry_match_other_esa,
|
|
||||||
(void**)&entry, &esa_id, &reqid);
|
|
||||||
if (res && entry)
|
|
||||||
{
|
|
||||||
id = entry->esa_id;
|
|
||||||
DBG3(DBG_KNL, "returning ESA id %llu of other SAD entry with reqid %u",
|
|
||||||
id, reqid);
|
|
||||||
}
|
}
|
||||||
this->mutex->unlock(this->mutex);
|
this->mutex->unlock(this->mutex);
|
||||||
return id;
|
return id;
|
||||||
@@ -350,7 +305,6 @@ tkm_kernel_sad_t *tkm_kernel_sad_create()
|
|||||||
.public = {
|
.public = {
|
||||||
.insert = _insert,
|
.insert = _insert,
|
||||||
.get_esa_id = _get_esa_id,
|
.get_esa_id = _get_esa_id,
|
||||||
.get_other_esa_id = _get_other_esa_id,
|
|
||||||
.get_dst_host = _get_dst_host,
|
.get_dst_host = _get_dst_host,
|
||||||
.remove = __remove,
|
.remove = __remove,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
|
|||||||
@@ -55,23 +55,14 @@ struct tkm_kernel_sad_t {
|
|||||||
*
|
*
|
||||||
* @param src source address of CHILD SA
|
* @param src source address of CHILD SA
|
||||||
* @param dst destination address of CHILD SA
|
* @param dst destination address of CHILD SA
|
||||||
* @param spi Remote SPI of CHILD SA
|
* @param spi SPI of CHILD SA
|
||||||
* @param proto protocol of CHILD SA (ESP/AH)
|
* @param proto protocol of CHILD SA (ESP/AH)
|
||||||
|
* @param local whether the SPI is local or remote
|
||||||
* @return ESA id of entry if found, 0 otherwise
|
* @return ESA id of entry if found, 0 otherwise
|
||||||
*/
|
*/
|
||||||
esa_id_type (*get_esa_id)(tkm_kernel_sad_t * const this,
|
esa_id_type (*get_esa_id)(tkm_kernel_sad_t * const this,
|
||||||
const host_t * const src, const host_t * const dst,
|
const host_t * const src, const host_t * const dst,
|
||||||
const uint32_t spi, const uint8_t proto);
|
const uint32_t spi, const uint8_t proto, const bool local);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get ESA id for entry associated with same security policy as the
|
|
||||||
* specified ESA.
|
|
||||||
*
|
|
||||||
* @param esa_id id of ESA identifying the security policy
|
|
||||||
* @return ESA id of entry if found, 0 otherwise
|
|
||||||
*/
|
|
||||||
esa_id_type (*get_other_esa_id)(tkm_kernel_sad_t * const this,
|
|
||||||
const esa_id_type esa_id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get destination host for entry with given parameters.
|
* Get destination host for entry with given parameters.
|
||||||
|
|||||||
@@ -63,7 +63,20 @@ START_TEST(test_get_esa_id)
|
|||||||
tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
|
tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
|
||||||
fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50),
|
fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50),
|
||||||
"Error inserting SAD entry");
|
"Error inserting SAD entry");
|
||||||
fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50) == 23,
|
fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50, FALSE) == 23,
|
||||||
|
"Error getting esa id");
|
||||||
|
sad->destroy(sad);
|
||||||
|
addr->destroy(addr);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_get_esa_id_local)
|
||||||
|
{
|
||||||
|
host_t *addr = host_create_from_string("127.0.0.1", 1024);
|
||||||
|
tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
|
||||||
|
fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50),
|
||||||
|
"Error inserting SAD entry");
|
||||||
|
fail_unless(sad->get_esa_id(sad, addr, addr, 27, 50, TRUE) == 23,
|
||||||
"Error getting esa id");
|
"Error getting esa id");
|
||||||
sad->destroy(sad);
|
sad->destroy(sad);
|
||||||
addr->destroy(addr);
|
addr->destroy(addr);
|
||||||
@@ -74,44 +87,13 @@ START_TEST(test_get_esa_id_nonexistent)
|
|||||||
{
|
{
|
||||||
host_t *addr = host_create_from_string("127.0.0.1", 1024);
|
host_t *addr = host_create_from_string("127.0.0.1", 1024);
|
||||||
tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
|
tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
|
||||||
fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50) == 0,
|
fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50, FALSE) == 0,
|
||||||
"Got esa id for nonexistent SAD entry");
|
"Got esa id for nonexistent SAD entry");
|
||||||
sad->destroy(sad);
|
sad->destroy(sad);
|
||||||
addr->destroy(addr);
|
addr->destroy(addr);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_get_other_esa_id)
|
|
||||||
{
|
|
||||||
host_t *addr = host_create_from_string("127.0.0.1", 1024);
|
|
||||||
tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
|
|
||||||
fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50),
|
|
||||||
"Error inserting SAD entry");
|
|
||||||
fail_unless(sad->insert(sad, 24, 54, addr, addr, 27, 42, 50),
|
|
||||||
"Error inserting SAD entry");
|
|
||||||
fail_unless(sad->get_other_esa_id(sad, 23) == 24,
|
|
||||||
"Error getting other esa id");
|
|
||||||
sad->destroy(sad);
|
|
||||||
addr->destroy(addr);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
START_TEST(test_get_other_esa_id_nonexistent)
|
|
||||||
{
|
|
||||||
host_t *addr = host_create_from_string("127.0.0.1", 1024);
|
|
||||||
tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
|
|
||||||
fail_unless(sad->get_other_esa_id(sad, 1) == 0,
|
|
||||||
"Got other esa id for nonexistent SAD entry");
|
|
||||||
fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50),
|
|
||||||
"Error inserting SAD entry");
|
|
||||||
fail_unless(sad->get_other_esa_id(sad, 23) == 0,
|
|
||||||
"Got own esa id");
|
|
||||||
|
|
||||||
sad->destroy(sad);
|
|
||||||
addr->destroy(addr);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
START_TEST(test_get_dst_host)
|
START_TEST(test_get_dst_host)
|
||||||
{
|
{
|
||||||
host_t *addr = host_create_from_string("127.0.0.1", 1024);
|
host_t *addr = host_create_from_string("127.0.0.1", 1024);
|
||||||
@@ -179,14 +161,10 @@ Suite *make_kernel_sad_tests()
|
|||||||
|
|
||||||
tc = tcase_create("get_esa_id");
|
tc = tcase_create("get_esa_id");
|
||||||
tcase_add_test(tc, test_get_esa_id);
|
tcase_add_test(tc, test_get_esa_id);
|
||||||
|
tcase_add_test(tc, test_get_esa_id_local);
|
||||||
tcase_add_test(tc, test_get_esa_id_nonexistent);
|
tcase_add_test(tc, test_get_esa_id_nonexistent);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("get_other_esa_id");
|
|
||||||
tcase_add_test(tc, test_get_other_esa_id);
|
|
||||||
tcase_add_test(tc, test_get_other_esa_id_nonexistent);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("get_dst_host");
|
tc = tcase_create("get_dst_host");
|
||||||
tcase_add_test(tc, test_get_dst_host);
|
tcase_add_test(tc, test_get_dst_host);
|
||||||
tcase_add_test(tc, test_get_dst_host_nonexistent);
|
tcase_add_test(tc, test_get_dst_host_nonexistent);
|
||||||
|
|||||||
@@ -827,7 +827,10 @@ METHOD(bus_t, ike_updown, void,
|
|||||||
enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
|
enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
|
||||||
while (enumerator->enumerate(enumerator, (void**)&child_sa))
|
while (enumerator->enumerate(enumerator, (void**)&child_sa))
|
||||||
{
|
{
|
||||||
child_updown(this, child_sa, FALSE);
|
if (child_sa->get_state(child_sa) != CHILD_REKEYED)
|
||||||
|
{
|
||||||
|
child_updown(this, child_sa, FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ enum kernel_feature_t {
|
|||||||
KERNEL_REQUIRE_UDP_ENCAPSULATION = (1<<2),
|
KERNEL_REQUIRE_UDP_ENCAPSULATION = (1<<2),
|
||||||
/** IPsec backend does not require a policy reinstall on SA updates */
|
/** IPsec backend does not require a policy reinstall on SA updates */
|
||||||
KERNEL_NO_POLICY_UPDATES = (1<<3),
|
KERNEL_NO_POLICY_UPDATES = (1<<3),
|
||||||
|
/** IPsec backend supports installing SPIs on policies */
|
||||||
|
KERNEL_POLICY_SPI = (1<<4),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1141,7 +1141,7 @@ static bool receive_events(private_kernel_netlink_ipsec_t *this, int fd,
|
|||||||
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
||||||
private_kernel_netlink_ipsec_t *this)
|
private_kernel_netlink_ipsec_t *this)
|
||||||
{
|
{
|
||||||
return KERNEL_ESP_V3_TFC;
|
return KERNEL_ESP_V3_TFC | KERNEL_POLICY_SPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2409,11 +2409,13 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
|
|||||||
struct xfrm_user_tmpl *tmpl;
|
struct xfrm_user_tmpl *tmpl;
|
||||||
struct {
|
struct {
|
||||||
uint8_t proto;
|
uint8_t proto;
|
||||||
|
uint32_t spi;
|
||||||
bool use;
|
bool use;
|
||||||
} protos[] = {
|
} protos[] = {
|
||||||
{ IPPROTO_COMP, ipsec->cfg.ipcomp.transform != IPCOMP_NONE },
|
{ IPPROTO_COMP, htonl(ntohs(ipsec->cfg.ipcomp.cpi)),
|
||||||
{ IPPROTO_ESP, ipsec->cfg.esp.use },
|
ipsec->cfg.ipcomp.transform != IPCOMP_NONE },
|
||||||
{ IPPROTO_AH, ipsec->cfg.ah.use },
|
{ IPPROTO_ESP, ipsec->cfg.esp.spi, ipsec->cfg.esp.use },
|
||||||
|
{ IPPROTO_AH, ipsec->cfg.ah.spi, ipsec->cfg.ah.use },
|
||||||
};
|
};
|
||||||
ipsec_mode_t proto_mode = ipsec->cfg.mode;
|
ipsec_mode_t proto_mode = ipsec->cfg.mode;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -2441,6 +2443,10 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
|
|||||||
}
|
}
|
||||||
tmpl->reqid = ipsec->cfg.reqid;
|
tmpl->reqid = ipsec->cfg.reqid;
|
||||||
tmpl->id.proto = protos[i].proto;
|
tmpl->id.proto = protos[i].proto;
|
||||||
|
if (policy->direction == POLICY_OUT)
|
||||||
|
{
|
||||||
|
tmpl->id.spi = protos[i].spi;
|
||||||
|
}
|
||||||
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
|
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
|
||||||
tmpl->mode = mode2kernel(proto_mode);
|
tmpl->mode = mode2kernel(proto_mode);
|
||||||
tmpl->optional = protos[i].proto == IPPROTO_COMP &&
|
tmpl->optional = protos[i].proto == IPPROTO_COMP &&
|
||||||
|
|||||||
+60
-37
@@ -40,10 +40,10 @@ ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
|
|||||||
"DESTROYING",
|
"DESTROYING",
|
||||||
);
|
);
|
||||||
|
|
||||||
ENUM(child_sa_outbound_state_names, CHILD_OUTBOUND_NONE, CHILD_OUTBOUND_INSTALLED,
|
ENUM_FLAGS(child_sa_outbound_state_names, CHILD_OUTBOUND_REGISTERED, CHILD_OUTBOUND_POLICIES,
|
||||||
"NONE",
|
|
||||||
"REGISTERED",
|
"REGISTERED",
|
||||||
"INSTALLED",
|
"SA",
|
||||||
|
"POLICIES",
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef struct private_child_sa_t private_child_sa_t;
|
typedef struct private_child_sa_t private_child_sa_t;
|
||||||
@@ -547,7 +547,7 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (this->other_spi && this->outbound_state == CHILD_OUTBOUND_INSTALLED)
|
if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
|
||||||
{
|
{
|
||||||
kernel_ipsec_sa_id_t id = {
|
kernel_ipsec_sa_id_t id = {
|
||||||
.src = this->my_addr,
|
.src = this->my_addr,
|
||||||
@@ -788,7 +788,7 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
|
|||||||
{
|
{
|
||||||
tfc = this->config->get_tfc(this->config);
|
tfc = this->config->get_tfc(this->config);
|
||||||
}
|
}
|
||||||
this->outbound_state = CHILD_OUTBOUND_INSTALLED;
|
this->outbound_state |= CHILD_OUTBOUND_SA;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
|
DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
|
||||||
@@ -1188,6 +1188,7 @@ METHOD(child_sa_t, install_policies, status_t,
|
|||||||
linked_list_t *my_ts_list, *other_ts_list;
|
linked_list_t *my_ts_list, *other_ts_list;
|
||||||
traffic_selector_t *my_ts, *other_ts;
|
traffic_selector_t *my_ts, *other_ts;
|
||||||
status_t status = SUCCESS;
|
status_t status = SUCCESS;
|
||||||
|
bool install_outbound = FALSE;
|
||||||
|
|
||||||
if (!this->reqid_allocated && !this->static_reqid)
|
if (!this->reqid_allocated && !this->static_reqid)
|
||||||
{
|
{
|
||||||
@@ -1207,12 +1208,17 @@ METHOD(child_sa_t, install_policies, status_t,
|
|||||||
this->reqid_allocated = TRUE;
|
this->reqid_allocated = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(this->outbound_state & CHILD_OUTBOUND_REGISTERED))
|
||||||
|
{
|
||||||
|
install_outbound = TRUE;
|
||||||
|
this->outbound_state |= CHILD_OUTBOUND_POLICIES;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->config->has_option(this->config, OPT_NO_POLICIES))
|
if (!this->config->has_option(this->config, OPT_NO_POLICIES))
|
||||||
{
|
{
|
||||||
policy_priority_t priority;
|
policy_priority_t priority;
|
||||||
ipsec_sa_cfg_t my_sa, other_sa;
|
ipsec_sa_cfg_t my_sa, other_sa;
|
||||||
uint32_t manual_prio;
|
uint32_t manual_prio;
|
||||||
bool install_outbound;
|
|
||||||
|
|
||||||
prepare_sa_cfg(this, &my_sa, &other_sa);
|
prepare_sa_cfg(this, &my_sa, &other_sa);
|
||||||
manual_prio = this->config->get_manual_prio(this->config);
|
manual_prio = this->config->get_manual_prio(this->config);
|
||||||
@@ -1222,7 +1228,6 @@ METHOD(child_sa_t, install_policies, status_t,
|
|||||||
this->trap = this->state == CHILD_CREATED;
|
this->trap = this->state == CHILD_CREATED;
|
||||||
priority = this->trap ? POLICY_PRIORITY_ROUTED
|
priority = this->trap ? POLICY_PRIORITY_ROUTED
|
||||||
: POLICY_PRIORITY_DEFAULT;
|
: POLICY_PRIORITY_DEFAULT;
|
||||||
install_outbound = this->outbound_state != CHILD_OUTBOUND_REGISTERED;
|
|
||||||
|
|
||||||
/* enumerate pairs of traffic selectors */
|
/* enumerate pairs of traffic selectors */
|
||||||
enumerator = create_policy_enumerator(this);
|
enumerator = create_policy_enumerator(this);
|
||||||
@@ -1250,7 +1255,6 @@ METHOD(child_sa_t, install_policies, status_t,
|
|||||||
this->other_addr, my_ts, other_ts,
|
this->other_addr, my_ts, other_ts,
|
||||||
&my_sa, &other_sa, POLICY_IPSEC,
|
&my_sa, &other_sa, POLICY_IPSEC,
|
||||||
priority, manual_prio);
|
priority, manual_prio);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -1267,21 +1271,35 @@ METHOD(child_sa_t, install_policies, status_t,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(child_sa_t, register_outbound, void,
|
METHOD(child_sa_t, register_outbound, status_t,
|
||||||
private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
|
private_child_sa_t *this, chunk_t encr, chunk_t integ, uint32_t spi,
|
||||||
uint16_t cpi, bool tfcv3)
|
uint16_t cpi, bool tfcv3)
|
||||||
{
|
{
|
||||||
DBG2(DBG_CHD, "registering outbound %N SA", protocol_id_names,
|
status_t status;
|
||||||
this->protocol);
|
|
||||||
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), this->my_addr,
|
|
||||||
this->other_addr);
|
|
||||||
|
|
||||||
this->other_spi = spi;
|
/* if the kernel supports installing SPIs with policies we install the
|
||||||
this->other_cpi = cpi;
|
* SA immediately as it will only be used once we update the policies */
|
||||||
this->encr_r = chunk_clone(encr);
|
if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI)
|
||||||
this->integ_r = chunk_clone(integ);
|
{
|
||||||
this->tfcv3 = tfcv3;
|
status = install_internal(this, encr, integ, spi, cpi, FALSE, FALSE,
|
||||||
this->outbound_state = CHILD_OUTBOUND_REGISTERED;
|
tfcv3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG2(DBG_CHD, "registering outbound %N SA", protocol_id_names,
|
||||||
|
this->protocol);
|
||||||
|
DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), this->my_addr,
|
||||||
|
this->other_addr);
|
||||||
|
|
||||||
|
this->other_spi = spi;
|
||||||
|
this->other_cpi = cpi;
|
||||||
|
this->encr_r = chunk_clone(encr);
|
||||||
|
this->integ_r = chunk_clone(integ);
|
||||||
|
this->tfcv3 = tfcv3;
|
||||||
|
status = SUCCESS;
|
||||||
|
}
|
||||||
|
this->outbound_state |= CHILD_OUTBOUND_REGISTERED;
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(child_sa_t, install_outbound, status_t,
|
METHOD(child_sa_t, install_outbound, status_t,
|
||||||
@@ -1289,18 +1307,23 @@ METHOD(child_sa_t, install_outbound, status_t,
|
|||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
traffic_selector_t *my_ts, *other_ts;
|
traffic_selector_t *my_ts, *other_ts;
|
||||||
status_t status;
|
status_t status = SUCCESS;
|
||||||
|
|
||||||
status = install_internal(this, this->encr_r, this->integ_r,
|
if (!(this->outbound_state & CHILD_OUTBOUND_SA))
|
||||||
this->other_spi, this->other_cpi, FALSE, FALSE,
|
{
|
||||||
this->tfcv3);
|
status = install_internal(this, this->encr_r, this->integ_r,
|
||||||
chunk_clear(&this->encr_r);
|
this->other_spi, this->other_cpi, FALSE,
|
||||||
chunk_clear(&this->integ_r);
|
FALSE, this->tfcv3);
|
||||||
|
chunk_clear(&this->encr_r);
|
||||||
|
chunk_clear(&this->integ_r);
|
||||||
|
}
|
||||||
|
this->outbound_state &= ~CHILD_OUTBOUND_REGISTERED;
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
{
|
{
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
if (!this->config->has_option(this->config, OPT_NO_POLICIES))
|
if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
|
||||||
|
!(this->outbound_state & CHILD_OUTBOUND_POLICIES))
|
||||||
{
|
{
|
||||||
ipsec_sa_cfg_t my_sa, other_sa;
|
ipsec_sa_cfg_t my_sa, other_sa;
|
||||||
uint32_t manual_prio;
|
uint32_t manual_prio;
|
||||||
@@ -1331,6 +1354,7 @@ METHOD(child_sa_t, install_outbound, status_t,
|
|||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
}
|
}
|
||||||
|
this->outbound_state |= CHILD_OUTBOUND_POLICIES;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1340,20 +1364,19 @@ METHOD(child_sa_t, remove_outbound, void,
|
|||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
traffic_selector_t *my_ts, *other_ts;
|
traffic_selector_t *my_ts, *other_ts;
|
||||||
|
|
||||||
switch (this->outbound_state)
|
if (!(this->outbound_state & CHILD_OUTBOUND_SA))
|
||||||
{
|
{
|
||||||
case CHILD_OUTBOUND_INSTALLED:
|
if (this->outbound_state & CHILD_OUTBOUND_REGISTERED)
|
||||||
break;
|
{
|
||||||
case CHILD_OUTBOUND_REGISTERED:
|
|
||||||
chunk_clear(&this->encr_r);
|
chunk_clear(&this->encr_r);
|
||||||
chunk_clear(&this->integ_r);
|
chunk_clear(&this->integ_r);
|
||||||
this->outbound_state = CHILD_OUTBOUND_NONE;
|
this->outbound_state = CHILD_OUTBOUND_NONE;
|
||||||
/* fall-through */
|
}
|
||||||
case CHILD_OUTBOUND_NONE:
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->config->has_option(this->config, OPT_NO_POLICIES))
|
if (!this->config->has_option(this->config, OPT_NO_POLICIES) &&
|
||||||
|
(this->outbound_state & CHILD_OUTBOUND_POLICIES))
|
||||||
{
|
{
|
||||||
ipsec_sa_cfg_t my_sa, other_sa;
|
ipsec_sa_cfg_t my_sa, other_sa;
|
||||||
uint32_t manual_prio;
|
uint32_t manual_prio;
|
||||||
@@ -1598,8 +1621,8 @@ METHOD(child_sa_t, destroy, void,
|
|||||||
|
|
||||||
prepare_sa_cfg(this, &my_sa, &other_sa);
|
prepare_sa_cfg(this, &my_sa, &other_sa);
|
||||||
manual_prio = this->config->get_manual_prio(this->config);
|
manual_prio = this->config->get_manual_prio(this->config);
|
||||||
del_outbound = this->trap ||
|
del_outbound = (this->outbound_state & CHILD_OUTBOUND_POLICIES) ||
|
||||||
this->outbound_state == CHILD_OUTBOUND_INSTALLED;
|
this->trap;
|
||||||
|
|
||||||
/* delete all policies in the kernel */
|
/* delete all policies in the kernel */
|
||||||
enumerator = create_policy_enumerator(this);
|
enumerator = create_policy_enumerator(this);
|
||||||
@@ -1640,7 +1663,7 @@ METHOD(child_sa_t, destroy, void,
|
|||||||
};
|
};
|
||||||
charon->kernel->del_sa(charon->kernel, &id, &sa);
|
charon->kernel->del_sa(charon->kernel, &id, &sa);
|
||||||
}
|
}
|
||||||
if (this->other_spi && this->outbound_state == CHILD_OUTBOUND_INSTALLED)
|
if (this->other_spi && (this->outbound_state & CHILD_OUTBOUND_SA))
|
||||||
{
|
{
|
||||||
kernel_ipsec_sa_id_t id = {
|
kernel_ipsec_sa_id_t id = {
|
||||||
.src = this->my_addr,
|
.src = this->my_addr,
|
||||||
|
|||||||
+24
-10
@@ -102,17 +102,28 @@ enum child_sa_outbound_state_t {
|
|||||||
/**
|
/**
|
||||||
* Outbound SA is not installed
|
* Outbound SA is not installed
|
||||||
*/
|
*/
|
||||||
CHILD_OUTBOUND_NONE,
|
CHILD_OUTBOUND_NONE = 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data for the outbound SA has been registered, but not installed yet
|
* Data for the outbound SA has been registered during a rekeying (not set
|
||||||
|
* once the SA and policies are both installed)
|
||||||
*/
|
*/
|
||||||
CHILD_OUTBOUND_REGISTERED,
|
CHILD_OUTBOUND_REGISTERED = (1<<0),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The outbound SA is currently installed
|
* The outbound SA has been installed
|
||||||
*/
|
*/
|
||||||
CHILD_OUTBOUND_INSTALLED,
|
CHILD_OUTBOUND_SA = (1<<1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The outbound policies have been installed
|
||||||
|
*/
|
||||||
|
CHILD_OUTBOUND_POLICIES = (1<<2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The outbound SA and policies are both installed
|
||||||
|
*/
|
||||||
|
CHILD_OUTBOUND_INSTALLED = (CHILD_OUTBOUND_SA|CHILD_OUTBOUND_POLICIES),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -400,20 +411,23 @@ struct child_sa_t {
|
|||||||
* Register data for the installation of an outbound SA as responder during
|
* Register data for the installation of an outbound SA as responder during
|
||||||
* a rekeying.
|
* a rekeying.
|
||||||
*
|
*
|
||||||
* The SA is not installed until install_outbound() is called.
|
* If the kernel is able to handle SPIs on policies the SA is installed
|
||||||
|
* immediately, if not it won't be installed until install_outbound() is
|
||||||
|
* called.
|
||||||
*
|
*
|
||||||
* @param encr encryption key, if any (cloned)
|
* @param encr encryption key, if any (cloned)
|
||||||
* @param integ integrity key (cloned)
|
* @param integ integrity key (cloned)
|
||||||
* @param spi SPI to use, allocated for inbound
|
* @param spi SPI to use, allocated for inbound
|
||||||
* @param cpi CPI to use, allocated for outbound
|
* @param cpi CPI to use, allocated for outbound
|
||||||
* @param tfcv3 TRUE if peer supports ESPv3 TFC
|
* @param tfcv3 TRUE if peer supports ESPv3 TFC
|
||||||
|
* @return SUCCESS or FAILED
|
||||||
*/
|
*/
|
||||||
void (*register_outbound)(child_sa_t *this, chunk_t encr, chunk_t integ,
|
status_t (*register_outbound)(child_sa_t *this, chunk_t encr, chunk_t integ,
|
||||||
uint32_t spi, uint16_t cpi, bool tfcv3);
|
uint32_t spi, uint16_t cpi, bool tfcv3);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install the outbound SA and the outbound policies as responder during a
|
* Install the outbound policies and, if not already done, the outbound SA
|
||||||
* rekeying.
|
* as responder during a rekeying.
|
||||||
*
|
*
|
||||||
* @return SUCCESS or FAILED
|
* @return SUCCESS or FAILED
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -478,6 +478,7 @@ static status_t select_and_install(private_child_create_t *this,
|
|||||||
bool no_dh, bool ike_auth)
|
bool no_dh, bool ike_auth)
|
||||||
{
|
{
|
||||||
status_t status, status_i, status_o;
|
status_t status, status_i, status_o;
|
||||||
|
child_sa_outbound_state_t out_state;
|
||||||
chunk_t nonce_i, nonce_r;
|
chunk_t nonce_i, nonce_r;
|
||||||
chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
|
chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
|
||||||
chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
|
chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
|
||||||
@@ -678,29 +679,42 @@ static status_t select_and_install(private_child_create_t *this,
|
|||||||
status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
|
status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
|
||||||
this->my_spi, this->my_cpi, this->initiator,
|
this->my_spi, this->my_cpi, this->initiator,
|
||||||
TRUE, this->tfcv3);
|
TRUE, this->tfcv3);
|
||||||
status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
|
|
||||||
this->other_spi, this->other_cpi, this->initiator,
|
|
||||||
FALSE, this->tfcv3);
|
|
||||||
}
|
}
|
||||||
else if (!this->rekey)
|
else
|
||||||
{
|
{
|
||||||
status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
|
status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
|
||||||
this->my_spi, this->my_cpi, this->initiator,
|
this->my_spi, this->my_cpi, this->initiator,
|
||||||
TRUE, this->tfcv3);
|
TRUE, this->tfcv3);
|
||||||
status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
|
}
|
||||||
|
if (this->rekey)
|
||||||
|
{ /* during rekeyings we install the outbound SA and/or policies
|
||||||
|
* separately: as responder when we receive the delete for the old
|
||||||
|
* SA, as initiator pretty much immediately in the ike-rekey task,
|
||||||
|
* unless there was a rekey collision that we lost */
|
||||||
|
if (this->initiator)
|
||||||
|
{
|
||||||
|
status_o = this->child_sa->register_outbound(this->child_sa,
|
||||||
|
encr_i, integ_i, this->other_spi, this->other_cpi,
|
||||||
|
this->tfcv3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status_o = this->child_sa->register_outbound(this->child_sa,
|
||||||
|
encr_r, integ_r, this->other_spi, this->other_cpi,
|
||||||
|
this->tfcv3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this->initiator)
|
||||||
|
{
|
||||||
|
status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
|
||||||
this->other_spi, this->other_cpi, this->initiator,
|
this->other_spi, this->other_cpi, this->initiator,
|
||||||
FALSE, this->tfcv3);
|
FALSE, this->tfcv3);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* as responder during a rekeying we only install the inbound
|
{
|
||||||
* SA now, the outbound SA and policies are installed when we
|
status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
|
||||||
* receive the delete for the old SA */
|
this->other_spi, this->other_cpi, this->initiator,
|
||||||
status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
|
FALSE, this->tfcv3);
|
||||||
this->my_spi, this->my_cpi, this->initiator,
|
|
||||||
TRUE, this->tfcv3);
|
|
||||||
this->child_sa->register_outbound(this->child_sa, encr_r, integ_r,
|
|
||||||
this->other_spi, this->other_cpi, this->tfcv3);
|
|
||||||
status_o = SUCCESS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -749,10 +763,11 @@ static status_t select_and_install(private_child_create_t *this,
|
|||||||
this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
|
this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
|
||||||
other_ts = linked_list_create_from_enumerator(
|
other_ts = linked_list_create_from_enumerator(
|
||||||
this->child_sa->create_ts_enumerator(this->child_sa, FALSE));
|
this->child_sa->create_ts_enumerator(this->child_sa, FALSE));
|
||||||
|
out_state = this->child_sa->get_outbound_state(this->child_sa);
|
||||||
|
|
||||||
DBG0(DBG_IKE, "%sCHILD_SA %s{%d} established "
|
DBG0(DBG_IKE, "%sCHILD_SA %s{%d} established "
|
||||||
"with SPIs %.8x_i %.8x_o and TS %#R === %#R",
|
"with SPIs %.8x_i %.8x_o and TS %#R === %#R",
|
||||||
this->rekey && !this->initiator ? "inbound " : "",
|
(out_state == CHILD_OUTBOUND_INSTALLED) ? "" : "inbound ",
|
||||||
this->child_sa->get_name(this->child_sa),
|
this->child_sa->get_name(this->child_sa),
|
||||||
this->child_sa->get_unique_id(this->child_sa),
|
this->child_sa->get_unique_id(this->child_sa),
|
||||||
ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
|
ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
|
||||||
|
|||||||
@@ -196,7 +196,6 @@ static void install_outbound(private_child_delete_t *this,
|
|||||||
/* FIXME: delete the new child_sa? */
|
/* FIXME: delete the new child_sa? */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
child_sa->set_state(child_sa, CHILD_INSTALLED);
|
|
||||||
|
|
||||||
my_ts = linked_list_create_from_enumerator(
|
my_ts = linked_list_create_from_enumerator(
|
||||||
child_sa->create_ts_enumerator(child_sa, TRUE));
|
child_sa->create_ts_enumerator(child_sa, TRUE));
|
||||||
|
|||||||
@@ -283,7 +283,8 @@ METHOD(task_t, build_r, status_t,
|
|||||||
/**
|
/**
|
||||||
* Handle a rekey collision
|
* Handle a rekey collision
|
||||||
*/
|
*/
|
||||||
static child_sa_t *handle_collision(private_child_rekey_t *this)
|
static child_sa_t *handle_collision(private_child_rekey_t *this,
|
||||||
|
child_sa_t **to_install)
|
||||||
{
|
{
|
||||||
child_sa_t *to_delete;
|
child_sa_t *to_delete;
|
||||||
|
|
||||||
@@ -303,6 +304,7 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
|
|||||||
child_sa_t *child_sa;
|
child_sa_t *child_sa;
|
||||||
|
|
||||||
DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting old child");
|
DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting old child");
|
||||||
|
*to_install = this->child_create->get_child(this->child_create);
|
||||||
to_delete = this->child_sa;
|
to_delete = this->child_sa;
|
||||||
/* don't touch child other created, it has already been deleted */
|
/* don't touch child other created, it has already been deleted */
|
||||||
if (!this->other_child_destroyed)
|
if (!this->other_child_destroyed)
|
||||||
@@ -353,7 +355,7 @@ METHOD(task_t, process_i, status_t,
|
|||||||
{
|
{
|
||||||
protocol_id_t protocol;
|
protocol_id_t protocol;
|
||||||
uint32_t spi;
|
uint32_t spi;
|
||||||
child_sa_t *to_delete;
|
child_sa_t *to_delete, *to_install = NULL;
|
||||||
|
|
||||||
if (message->get_notify(message, NO_ADDITIONAL_SAS))
|
if (message->get_notify(message, NO_ADDITIONAL_SAS))
|
||||||
{
|
{
|
||||||
@@ -415,19 +417,48 @@ METHOD(task_t, process_i, status_t,
|
|||||||
/* check for rekey collisions */
|
/* check for rekey collisions */
|
||||||
if (this->collision)
|
if (this->collision)
|
||||||
{
|
{
|
||||||
to_delete = handle_collision(this);
|
to_delete = handle_collision(this, &to_install);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
to_install = this->child_create->get_child(this->child_create);
|
||||||
to_delete = this->child_sa;
|
to_delete = this->child_sa;
|
||||||
}
|
}
|
||||||
|
if (to_install)
|
||||||
|
{
|
||||||
|
if (to_install->install_outbound(to_install) != SUCCESS)
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "unable to install outbound IPsec SA (SAD) in kernel");
|
||||||
|
charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
|
||||||
|
to_install);
|
||||||
|
/* FIXME: delete the child_sa? fail the task? */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linked_list_t *my_ts, *other_ts;
|
||||||
|
|
||||||
|
my_ts = linked_list_create_from_enumerator(
|
||||||
|
to_install->create_ts_enumerator(to_install, TRUE));
|
||||||
|
other_ts = linked_list_create_from_enumerator(
|
||||||
|
to_install->create_ts_enumerator(to_install, FALSE));
|
||||||
|
|
||||||
|
DBG0(DBG_IKE, "outbound CHILD_SA %s{%d} established "
|
||||||
|
"with SPIs %.8x_i %.8x_o and TS %#R === %#R",
|
||||||
|
to_install->get_name(to_install),
|
||||||
|
to_install->get_unique_id(to_install),
|
||||||
|
ntohl(to_install->get_spi(to_install, TRUE)),
|
||||||
|
ntohl(to_install->get_spi(to_install, FALSE)),
|
||||||
|
my_ts, other_ts);
|
||||||
|
|
||||||
|
my_ts->destroy(my_ts);
|
||||||
|
other_ts->destroy(other_ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (to_delete != this->child_create->get_child(this->child_create))
|
if (to_delete != this->child_create->get_child(this->child_create))
|
||||||
{ /* invoke rekey hook if rekeying successful */
|
{ /* invoke rekey hook if rekeying successful */
|
||||||
charon->bus->child_rekey(charon->bus, this->child_sa,
|
charon->bus->child_rekey(charon->bus, this->child_sa,
|
||||||
this->child_create->get_child(this->child_create));
|
this->child_create->get_child(this->child_create));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to_delete == NULL)
|
if (to_delete == NULL)
|
||||||
{
|
{
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|||||||
@@ -483,6 +483,9 @@ START_TEST(test_collision)
|
|||||||
CHILD_OUTBOUND_REGISTERED);
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
|
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
|
assert_ipsec_sas_installed(a, 1, 2, 3, 5, 6);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -493,10 +496,10 @@ START_TEST(test_collision)
|
|||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_REGISTERED);
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
|
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
|
assert_ipsec_sas_installed(a, 1, 2, 3, 6);
|
||||||
}
|
}
|
||||||
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
|
||||||
assert_ipsec_sas_installed(a, 1, 2, 3, 5, 6);
|
|
||||||
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
|
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
|
||||||
if (data[_i].spi_del_b == 2)
|
if (data[_i].spi_del_b == 2)
|
||||||
{
|
{
|
||||||
@@ -507,6 +510,9 @@ START_TEST(test_collision)
|
|||||||
CHILD_OUTBOUND_REGISTERED);
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
|
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
|
assert_ipsec_sas_installed(b, 1, 2, 4, 5, 6);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -517,10 +523,10 @@ START_TEST(test_collision)
|
|||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_REGISTERED);
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
|
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
|
assert_ipsec_sas_installed(b, 1, 2, 4, 5);
|
||||||
}
|
}
|
||||||
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
|
||||||
assert_ipsec_sas_installed(b, 1, 2, 4, 5, 6);
|
|
||||||
|
|
||||||
/* we don't expect this hook to get called anymore */
|
/* we don't expect this hook to get called anymore */
|
||||||
assert_hook_not_called(child_rekey);
|
assert_hook_not_called(child_rekey);
|
||||||
@@ -528,27 +534,41 @@ START_TEST(test_collision)
|
|||||||
assert_jobs_scheduled(1);
|
assert_jobs_scheduled(1);
|
||||||
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
|
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
|
||||||
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
data[_i].spi_del_b == 2 ? CHILD_OUTBOUND_INSTALLED
|
||||||
|
: CHILD_OUTBOUND_REGISTERED);
|
||||||
assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
|
assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
|
||||||
CHILD_OUTBOUND_NONE);
|
CHILD_OUTBOUND_NONE);
|
||||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
assert_child_sa_count(b, 3);
|
assert_child_sa_count(b, 3);
|
||||||
assert_ipsec_sas_installed(b, 2, 4, 5, 6,
|
if (data[_i].spi_del_b == 2)
|
||||||
data[_i].spi_del_b == 2 ? 1 : 3);
|
{
|
||||||
|
assert_ipsec_sas_installed(b, 1, 2, 4, 5, 6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert_ipsec_sas_installed(b, 2, 3, 4, 5);
|
||||||
|
}
|
||||||
assert_scheduler();
|
assert_scheduler();
|
||||||
/* <-- INFORMATIONAL { D } */
|
/* <-- INFORMATIONAL { D } */
|
||||||
assert_jobs_scheduled(1);
|
assert_jobs_scheduled(1);
|
||||||
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
|
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
|
||||||
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
data[_i].spi_del_a == 1 ? CHILD_OUTBOUND_INSTALLED
|
||||||
|
: CHILD_OUTBOUND_REGISTERED);
|
||||||
assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
|
assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
CHILD_OUTBOUND_NONE);
|
CHILD_OUTBOUND_NONE);
|
||||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
assert_child_sa_count(a, 3);
|
assert_child_sa_count(a, 3);
|
||||||
assert_ipsec_sas_installed(a, 1, 3, 5, 6,
|
if (data[_i].spi_del_a == 1)
|
||||||
data[_i].spi_del_a == 1 ? 2 : 4);
|
{
|
||||||
|
assert_ipsec_sas_installed(a, 1, 2, 3, 5, 6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert_ipsec_sas_installed(a, 1, 3, 4, 6);
|
||||||
|
}
|
||||||
assert_scheduler();
|
assert_scheduler();
|
||||||
/* <-- INFORMATIONAL { D } */
|
/* <-- INFORMATIONAL { D } */
|
||||||
assert_jobs_scheduled(1);
|
assert_jobs_scheduled(1);
|
||||||
@@ -682,6 +702,9 @@ START_TEST(test_collision_delayed_response)
|
|||||||
CHILD_OUTBOUND_REGISTERED);
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
|
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
|
assert_ipsec_sas_installed(b, 1, 2, 4, 5, 6);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -692,10 +715,10 @@ START_TEST(test_collision_delayed_response)
|
|||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_REGISTERED);
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
|
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
|
assert_ipsec_sas_installed(b, 1, 2, 4, 5);
|
||||||
}
|
}
|
||||||
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
|
||||||
assert_ipsec_sas_installed(b, 1, 2, 4, 5, 6);
|
|
||||||
|
|
||||||
/* <-- INFORMATIONAL { D } */
|
/* <-- INFORMATIONAL { D } */
|
||||||
assert_hook_not_called(child_rekey);
|
assert_hook_not_called(child_rekey);
|
||||||
@@ -748,21 +771,23 @@ START_TEST(test_collision_delayed_response)
|
|||||||
assert_hook_rekey(child_rekey, 1, data[_i].spi_a);
|
assert_hook_rekey(child_rekey, 1, data[_i].spi_a);
|
||||||
exchange_test_helper->process_message(exchange_test_helper, a, msg);
|
exchange_test_helper->process_message(exchange_test_helper, a, msg);
|
||||||
assert_hook();
|
assert_hook();
|
||||||
|
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
|
assert_ipsec_sas_installed(a, 1, 2, 3, 5, 6);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert_hook_not_called(child_rekey);
|
assert_hook_not_called(child_rekey);
|
||||||
exchange_test_helper->process_message(exchange_test_helper, a, msg);
|
exchange_test_helper->process_message(exchange_test_helper, a, msg);
|
||||||
assert_hook();
|
assert_hook();
|
||||||
|
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
|
assert_ipsec_sas_installed(a, 1, 3, 4, 6);
|
||||||
}
|
}
|
||||||
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
|
||||||
assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
|
assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
CHILD_OUTBOUND_NONE);
|
CHILD_OUTBOUND_NONE);
|
||||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
assert_ipsec_sas_installed(a, 1, 3, 5, 6,
|
|
||||||
data[_i].spi_del_a == 1 ? 2 : 4);
|
|
||||||
assert_child_sa_count(a, 3);
|
assert_child_sa_count(a, 3);
|
||||||
|
|
||||||
/* we don't expect this hook to get called anymore */
|
/* we don't expect this hook to get called anymore */
|
||||||
@@ -1173,6 +1198,8 @@ START_TEST(test_collision_ke_invalid)
|
|||||||
CHILD_OUTBOUND_REGISTERED);
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
|
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1181,9 +1208,9 @@ START_TEST(test_collision_ke_invalid)
|
|||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_REGISTERED);
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
|
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
}
|
}
|
||||||
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
|
||||||
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
|
/* CREATE_CHILD_SA { SA, Nr, [KEr,] TSi, TSr } --> */
|
||||||
if (data[_i].spi_del_b == 2)
|
if (data[_i].spi_del_b == 2)
|
||||||
{
|
{
|
||||||
@@ -1194,6 +1221,8 @@ START_TEST(test_collision_ke_invalid)
|
|||||||
CHILD_OUTBOUND_REGISTERED);
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
|
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1202,9 +1231,10 @@ START_TEST(test_collision_ke_invalid)
|
|||||||
CHILD_OUTBOUND_INSTALLED);
|
CHILD_OUTBOUND_INSTALLED);
|
||||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||||
CHILD_OUTBOUND_REGISTERED);
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
|
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
|
CHILD_OUTBOUND_REGISTERED);
|
||||||
}
|
}
|
||||||
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
|
||||||
|
|
||||||
/* we don't expect this hook to get called anymore */
|
/* we don't expect this hook to get called anymore */
|
||||||
assert_hook_not_called(child_rekey);
|
assert_hook_not_called(child_rekey);
|
||||||
@@ -1212,7 +1242,8 @@ START_TEST(test_collision_ke_invalid)
|
|||||||
assert_jobs_scheduled(1);
|
assert_jobs_scheduled(1);
|
||||||
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
|
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
|
||||||
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
data[_i].spi_del_b == 2 ? CHILD_OUTBOUND_INSTALLED
|
||||||
|
: CHILD_OUTBOUND_REGISTERED);
|
||||||
assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
|
assert_child_sa_state(b, data[_i].spi_del_a, CHILD_DELETING,
|
||||||
CHILD_OUTBOUND_NONE);
|
CHILD_OUTBOUND_NONE);
|
||||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||||
@@ -1223,7 +1254,8 @@ START_TEST(test_collision_ke_invalid)
|
|||||||
assert_jobs_scheduled(1);
|
assert_jobs_scheduled(1);
|
||||||
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
|
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
|
||||||
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
||||||
CHILD_OUTBOUND_INSTALLED);
|
data[_i].spi_del_a == 1 ? CHILD_OUTBOUND_INSTALLED
|
||||||
|
: CHILD_OUTBOUND_REGISTERED);
|
||||||
assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
|
assert_child_sa_state(a, data[_i].spi_del_b, CHILD_DELETING,
|
||||||
CHILD_OUTBOUND_NONE);
|
CHILD_OUTBOUND_NONE);
|
||||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||||
|
|||||||
@@ -121,7 +121,8 @@
|
|||||||
test_assert_msg(_state == _child->get_state(_child), "%N != %N", \
|
test_assert_msg(_state == _child->get_state(_child), "%N != %N", \
|
||||||
child_sa_state_names, _state, \
|
child_sa_state_names, _state, \
|
||||||
child_sa_state_names, _child->get_state(_child)); \
|
child_sa_state_names, _child->get_state(_child)); \
|
||||||
test_assert_msg(_outbound == _child->get_outbound_state(_child), "%N != %N", \
|
typeof(outbound) _cur_out = _child->get_outbound_state(_child); \
|
||||||
|
test_assert_msg(_outbound == _cur_out || _outbound & _cur_out, "%N != %N", \
|
||||||
child_sa_outbound_state_names, _outbound, \
|
child_sa_outbound_state_names, _outbound, \
|
||||||
child_sa_outbound_state_names, _child->get_outbound_state(_child)); \
|
child_sa_outbound_state_names, _child->get_outbound_state(_child)); \
|
||||||
})
|
})
|
||||||
|
|||||||
+36
-15
@@ -416,29 +416,50 @@ do
|
|||||||
STATUS="passed"
|
STATUS="passed"
|
||||||
|
|
||||||
eval `awk -F "::" '{
|
eval `awk -F "::" '{
|
||||||
host=$1
|
host=$1
|
||||||
command=$2
|
command=$2
|
||||||
pattern=$3
|
pattern=$3
|
||||||
hit=$4
|
hit=$4
|
||||||
if (host !~ /^#.*/ && command != "")
|
if (host ~ /^#.*/ || command == "")
|
||||||
{
|
{
|
||||||
|
next
|
||||||
|
}
|
||||||
|
printf("cmd_err=\044(tempfile -p test -s err); ")
|
||||||
if (command == "tcpdump")
|
if (command == "tcpdump")
|
||||||
{
|
{
|
||||||
printf("if [ \044TDUP_%s == \"true\" ]; then stop_tcpdump %s; fi; \n", host, host)
|
printf("if [ \044TDUP_%s == \"true\" ]; then stop_tcpdump %s; fi; \n", host, host)
|
||||||
printf("echo \"%s# cat /tmp/tcpdump.log | grep \047%s\047 [%s]\"; ", host, pattern, hit)
|
printf("cmd_out=\044(ssh \044SSHCONF root@\044ipv4_%s cat /tmp/tcpdump.log | grep \"%s\"); ", host, pattern)
|
||||||
printf("ssh \044SSHCONF root@\044ipv4_%s cat /tmp/tcpdump.log | grep \"%s\"; ", host, pattern)
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("echo \"%s# %s | grep \047%s\047 [%s]\"; ", host, command, pattern, hit)
|
printf("cmd_out=\044(ssh \044SSHCONF root@\044ipv4_%s %s 2>\044cmd_err | grep \"%s\"); ", host, command, pattern)
|
||||||
printf("ssh \044SSHCONF root@\044ipv4_%s %s | grep \"%s\"; ", host, command, pattern)
|
|
||||||
}
|
}
|
||||||
printf("cmd_exit=\044?; ")
|
printf("cmd_exit=\044?; ")
|
||||||
|
printf("cmd_fail=0; ")
|
||||||
|
if (hit ~ /^[0-9]+$/)
|
||||||
|
{
|
||||||
|
printf("if [ \044(echo \"\044cmd_out\" | wc -l) -ne %d ] ", hit)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("if [ \044cmd_exit -eq 0 -a \"%s\" = \"NO\" ] ", hit)
|
||||||
|
printf("|| [ \044cmd_exit -ne 0 -a \"%s\" = \"YES\" ] ", hit)
|
||||||
|
}
|
||||||
|
printf("; then STATUS=\"failed\"; cmd_fail=1; fi; \n")
|
||||||
|
|
||||||
|
printf("if [ \044cmd_fail -ne 0 ]; then echo \"~~~~~~~ FAIL ~~~~~~~\"; fi; \n")
|
||||||
|
if (command == "tcpdump")
|
||||||
|
{
|
||||||
|
printf("echo \"%s# cat /tmp/tcpdump.log | grep \047%s\047 [%s]\"; ", host, pattern, hit)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("echo \"%s# %s | grep \047%s\047 [%s]\"; ", host, command, pattern, hit)
|
||||||
|
}
|
||||||
|
printf("if [ -n \"\044cmd_out\" ]; then echo \"\044cmd_out\"; fi; \n")
|
||||||
|
printf("cat \044cmd_err; rm -f -- \044cmd_err; \n")
|
||||||
|
printf("if [ \044cmd_fail -ne 0 ]; then echo \"~~~~~~~~~~~~~~~~~~~~\"; fi; \n")
|
||||||
printf("echo; ")
|
printf("echo; ")
|
||||||
printf("if [ \044cmd_exit -eq 0 -a \"%s\" = \"NO\" ] ", hit)
|
|
||||||
printf("|| [ \044cmd_exit -ne 0 -a \"%s\" = \"YES\" ] ", hit)
|
|
||||||
printf("; then STATUS=\"failed\"; fi; \n")
|
|
||||||
}
|
|
||||||
}' $TESTDIR/evaltest.dat` >> $CONSOLE_LOG 2>&1
|
}' $TESTDIR/evaltest.dat` >> $CONSOLE_LOG 2>&1
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up.
|
||||||
|
The authentication is based on <b>X.509 certificates</b>. Upon the successful
|
||||||
|
establishment of the IPsec tunnel, <b>leftfirewall=yes</b> automatically
|
||||||
|
inserts iptables-based firewall rules that let pass the tunneled traffic.
|
||||||
|
After a while the CHILD_SA is rekeyed by <b>moon</b> (after a deliberately short
|
||||||
|
time in this test scenario).
|
||||||
|
In order to test both tunnel and firewall after the rekeying, client <b>alice</b>
|
||||||
|
behind gateway <b>moon</b> pings client <b>bob</b> located behind gateway <b>sun</b>
|
||||||
|
twice, once right after the rekeying and once after the old inbound SA has been
|
||||||
|
deleted.
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
moon::ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
|
||||||
|
sun:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
|
||||||
|
moon::ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
|
||||||
|
sun:: ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
|
||||||
|
moon::sleep 6::wait for rekeying::NO
|
||||||
|
moon::cat /var/log/daemon.log::creating rekey job for CHILD_SA::YES
|
||||||
|
moon::cat /var/log/daemon.log::generating CREATE_CHILD_SA request.*REKEY_SA::YES
|
||||||
|
moon::cat /var/log/daemon.log::deleted SAD entry with SPI::1
|
||||||
|
alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::YES
|
||||||
|
moon::sleep 2::wait until inbound SA is deleted::NO
|
||||||
|
moon::cat /var/log/daemon.log::deleted SAD entry with SPI::2
|
||||||
|
alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::YES
|
||||||
|
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
||||||
|
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||||
|
|
||||||
|
config setup
|
||||||
|
charondebug="knl 2"
|
||||||
|
|
||||||
|
conn %default
|
||||||
|
ikelifetime=60m
|
||||||
|
lifetime=10s
|
||||||
|
margintime=5s
|
||||||
|
rekeyfuzz=0%
|
||||||
|
keyingtries=1
|
||||||
|
keyexchange=ikev2
|
||||||
|
mobike=no
|
||||||
|
|
||||||
|
conn net-net
|
||||||
|
left=PH_IP_MOON
|
||||||
|
leftcert=moonCert.pem
|
||||||
|
[email protected]
|
||||||
|
leftsubnet=10.1.0.0/16
|
||||||
|
leftfirewall=yes
|
||||||
|
right=PH_IP_SUN
|
||||||
|
[email protected]
|
||||||
|
rightsubnet=10.2.0.0/16
|
||||||
|
auto=add
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
charon {
|
||||||
|
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac stroke kernel-netlink socket-default updown
|
||||||
|
# remove rekeyed inbound SA a bit quicker for the test scenario
|
||||||
|
delete_rekeyed_delay = 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||||
|
|
||||||
|
config setup
|
||||||
|
|
||||||
|
conn %default
|
||||||
|
ikelifetime=60m
|
||||||
|
keylife=20m
|
||||||
|
rekeymargin=3m
|
||||||
|
keyingtries=1
|
||||||
|
keyexchange=ikev2
|
||||||
|
mobike=no
|
||||||
|
|
||||||
|
conn net-net
|
||||||
|
left=PH_IP_SUN
|
||||||
|
leftcert=sunCert.pem
|
||||||
|
[email protected]
|
||||||
|
leftsubnet=10.2.0.0/16
|
||||||
|
leftfirewall=yes
|
||||||
|
right=PH_IP_MOON
|
||||||
|
[email protected]
|
||||||
|
rightsubnet=10.1.0.0/16
|
||||||
|
auto=add
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
charon {
|
||||||
|
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac stroke kernel-netlink socket-default updown
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
moon::ipsec stop
|
||||||
|
sun::ipsec stop
|
||||||
|
moon::iptables-restore < /etc/iptables.flush
|
||||||
|
sun::iptables-restore < /etc/iptables.flush
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
moon::iptables-restore < /etc/iptables.rules
|
||||||
|
sun::iptables-restore < /etc/iptables.rules
|
||||||
|
sun::ipsec start
|
||||||
|
moon::ipsec start
|
||||||
|
sun::expect-connection net-net
|
||||||
|
moon::expect-connection net-net
|
||||||
|
moon::ipsec up net-net
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# This configuration file provides information on the
|
||||||
|
# guest instances used for this test
|
||||||
|
|
||||||
|
# All guest instances that are required for this test
|
||||||
|
#
|
||||||
|
VIRTHOSTS="alice moon winnetou sun bob"
|
||||||
|
|
||||||
|
# Corresponding block diagram
|
||||||
|
#
|
||||||
|
DIAGRAM="a-m-w-s-b.png"
|
||||||
|
|
||||||
|
# Guest instances on which tcpdump is to be started
|
||||||
|
#
|
||||||
|
TCPDUMPHOSTS="sun"
|
||||||
|
|
||||||
|
# Guest instances on which IPsec is started
|
||||||
|
# Used for IPsec logging purposes
|
||||||
|
#
|
||||||
|
IPSECHOSTS="moon sun"
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up.
|
||||||
|
The authentication is based on <b>X.509 certificates</b>. Upon the successful
|
||||||
|
establishment of the IPsec tunnel, <b>leftfirewall=yes</b> automatically
|
||||||
|
inserts iptables-based firewall rules that let pass the tunneled traffic.
|
||||||
|
After a while the CHILD_SA is rekeyed by <b>moon</b> (after a deliberately short
|
||||||
|
time in this test scenario).
|
||||||
|
In order to test both tunnel and firewall after the rekeying, client <b>alice</b>
|
||||||
|
behind gateway <b>moon</b> pings client <b>bob</b> located behind gateway <b>sun</b>
|
||||||
|
twice, once right after the rekeying and once after the old inbound SA has been
|
||||||
|
deleted.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
moon::ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
|
||||||
|
sun:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
|
||||||
|
moon::ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
|
||||||
|
sun:: ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES
|
||||||
|
# deleting the inbound SPI
|
||||||
|
moon::cat /var/log/daemon.log::deleted SAD entry with SPI::1
|
||||||
|
moon::sleep 6::wait for rekeying::NO
|
||||||
|
moon::cat /var/log/daemon.log::creating rekey job for CHILD_SA::YES
|
||||||
|
moon::cat /var/log/daemon.log::generating CREATE_CHILD_SA request.*REKEY_SA::YES
|
||||||
|
moon::cat /var/log/daemon.log::deleted SAD entry with SPI::3
|
||||||
|
alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::YES
|
||||||
|
moon::sleep 2::wait until inbound SA is deleted::NO
|
||||||
|
moon::cat /var/log/daemon.log::deleted SAD entry with SPI::4
|
||||||
|
alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_.eq=1::YES
|
||||||
|
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
||||||
|
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||||
|
|
||||||
|
config setup
|
||||||
|
charondebug="knl 2"
|
||||||
|
|
||||||
|
conn %default
|
||||||
|
ikelifetime=60m
|
||||||
|
lifetime=10s
|
||||||
|
margintime=5s
|
||||||
|
rekeyfuzz=0%
|
||||||
|
keyingtries=1
|
||||||
|
keyexchange=ikev2
|
||||||
|
mobike=no
|
||||||
|
|
||||||
|
conn net-net
|
||||||
|
left=PH_IP_MOON
|
||||||
|
leftcert=moonCert.pem
|
||||||
|
[email protected]
|
||||||
|
leftsubnet=10.1.0.0/16
|
||||||
|
leftfirewall=yes
|
||||||
|
right=PH_IP_SUN
|
||||||
|
[email protected]
|
||||||
|
rightsubnet=10.2.0.0/16
|
||||||
|
auto=add
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
charon {
|
||||||
|
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac stroke kernel-pfkey kernel-netlink socket-default updown
|
||||||
|
# remove rekeyed inbound SA a bit quicker for the test scenario
|
||||||
|
delete_rekeyed_delay = 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||||
|
|
||||||
|
config setup
|
||||||
|
|
||||||
|
conn %default
|
||||||
|
ikelifetime=60m
|
||||||
|
keylife=20m
|
||||||
|
rekeymargin=3m
|
||||||
|
keyingtries=1
|
||||||
|
keyexchange=ikev2
|
||||||
|
mobike=no
|
||||||
|
|
||||||
|
conn net-net
|
||||||
|
left=PH_IP_SUN
|
||||||
|
leftcert=sunCert.pem
|
||||||
|
[email protected]
|
||||||
|
leftsubnet=10.2.0.0/16
|
||||||
|
leftfirewall=yes
|
||||||
|
right=PH_IP_MOON
|
||||||
|
[email protected]
|
||||||
|
rightsubnet=10.1.0.0/16
|
||||||
|
auto=add
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
charon {
|
||||||
|
load = random nonce aes sha1 sha2 pem pkcs1 curve25519 gmp x509 curl revocation hmac stroke kernel-pfkey kernel-netlink socket-default updown
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
moon::ipsec stop
|
||||||
|
sun::ipsec stop
|
||||||
|
moon::iptables-restore < /etc/iptables.flush
|
||||||
|
sun::iptables-restore < /etc/iptables.flush
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
moon::iptables-restore < /etc/iptables.rules
|
||||||
|
sun::iptables-restore < /etc/iptables.rules
|
||||||
|
sun::ipsec start
|
||||||
|
moon::ipsec start
|
||||||
|
sun::expect-connection net-net
|
||||||
|
moon::expect-connection net-net
|
||||||
|
moon::ipsec up net-net
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# This configuration file provides information on the
|
||||||
|
# guest instances used for this test
|
||||||
|
|
||||||
|
# All guest instances that are required for this test
|
||||||
|
#
|
||||||
|
VIRTHOSTS="alice moon winnetou sun bob"
|
||||||
|
|
||||||
|
# Corresponding block diagram
|
||||||
|
#
|
||||||
|
DIAGRAM="a-m-w-s-b.png"
|
||||||
|
|
||||||
|
# Guest instances on which tcpdump is to be started
|
||||||
|
#
|
||||||
|
TCPDUMPHOSTS="sun"
|
||||||
|
|
||||||
|
# Guest instances on which IPsec is started
|
||||||
|
# Used for IPsec logging purposes
|
||||||
|
#
|
||||||
|
IPSECHOSTS="moon sun"
|
||||||
@@ -2,20 +2,24 @@ moon::ipsec stroke status 2> /dev/null::conn1.*ESTABLISHED.*moon.strongswan.org.
|
|||||||
sun::ipsec status 2> /dev/null::host-host.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
|
sun::ipsec status 2> /dev/null::host-host.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
|
||||||
moon::ipsec stroke status 2> /dev/null::conn1.*INSTALLED, TRANSPORT::YES
|
moon::ipsec stroke status 2> /dev/null::conn1.*INSTALLED, TRANSPORT::YES
|
||||||
sun::ipsec status 2> /dev/null::host-host.*INSTALLED, TRANSPORT::YES
|
sun::ipsec status 2> /dev/null::host-host.*INSTALLED, TRANSPORT::YES
|
||||||
moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_.eq=1::YES
|
moon::sleep 2::wait for rekeying::NO
|
||||||
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
|
||||||
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
|
||||||
moon::cat /var/log/daemon.log::ees: acquire received for reqid 1::YES
|
moon::cat /var/log/daemon.log::ees: acquire received for reqid 1::YES
|
||||||
moon::cat /var/log/daemon.log::ees: expire received for reqid 1, spi.*, dst 192.168.0.2::YES
|
moon::cat /var/log/daemon.log::ees: expire received for reqid 1, spi.*, dst 192.168.0.2::YES
|
||||||
moon::cat /var/log/daemon.log::creating rekey job for CHILD_SA ESP/0x.*/192.168.0.2::YES
|
moon::cat /var/log/daemon.log::creating rekey job for CHILD_SA ESP/0x.*/192.168.0.2::YES
|
||||||
|
moon::cat /var/log/daemon.log::deleting child SA (esa: 1, spi:.*)::NO
|
||||||
|
moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_.eq=1::YES
|
||||||
|
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
||||||
|
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
||||||
|
moon::sleep 2::wait until inbound SA is deleted::NO
|
||||||
moon::cat /var/log/daemon.log::deleting child SA (esa: 1, spi:.*)::YES
|
moon::cat /var/log/daemon.log::deleting child SA (esa: 1, spi:.*)::YES
|
||||||
|
moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_.eq=1::YES
|
||||||
moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
|
moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
|
||||||
moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES
|
moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES
|
||||||
moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
|
moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
|
||||||
moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
|
moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
|
||||||
moon::cat /tmp/tkm.log::Creating first new ESA context with ID 1 (Isa 1, Sp 1, Ea 1, Initiator TRUE, spi_loc.*, spi_rem.*)::YES
|
moon::cat /tmp/tkm.log::Creating first new ESA context with ID 1 (Isa 1, Sp 1, Ea 1, Initiator TRUE, spi_loc.*, spi_rem.*)::YES
|
||||||
moon::cat /tmp/tkm.log::Creating ESA context with ID 2 (Isa 1, Sp 1, Ea 1, Dh_Id 1, Nc_Loc_Id 1, Initiator TRUE, spi_loc.*, spi_rem.*)::YES
|
moon::cat /tmp/tkm.log::Creating ESA context with ID 2 (Isa 1, Sp 1, Ea 1, Dh_Id 1, Nc_Loc_Id 1, Initiator TRUE, spi_loc.*, spi_rem.*)::YES
|
||||||
moon::cat /tmp/tkm.log | grep 'Adding ESA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 2, hard 60 \]' | wc -l::2::YES
|
moon::cat /tmp/tkm.log | grep 'Adding ESA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 4, hard 60 \]' | wc -l::2::YES
|
||||||
moon::cat /tmp/tkm.log::Resetting ESA context 1::YES
|
moon::cat /tmp/tkm.log::Resetting ESA context 1::YES
|
||||||
moon::cat /tmp/tkm.log::Deleting ESA \[ 1, 192.168.0.1 <=> 192.168.0.2, SPI_in.*, SPI_out.* \]::YES
|
moon::cat /tmp/tkm.log::Deleting ESA \[ 1, 192.168.0.1 <=> 192.168.0.2, SPI_in.*, SPI_out.* \]::YES
|
||||||
moon::cat /tmp/xfrm_proxy.log::Initiating ESA acquire for reqid 1::YES
|
moon::cat /tmp/xfrm_proxy.log::Initiating ESA acquire for reqid 1::YES
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# /etc/strongswan.conf - strongSwan configuration file
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
charon-tkm {
|
charon-tkm {
|
||||||
|
# remove rekeyed inbound SA a bit quicker for the test scenario
|
||||||
|
delete_rekeyed_delay = 2
|
||||||
dh_mapping {
|
dh_mapping {
|
||||||
15 = 1
|
15 = 1
|
||||||
16 = 2
|
16 = 2
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<ip>192.168.0.2</ip>
|
<ip>192.168.0.2</ip>
|
||||||
</remote>
|
</remote>
|
||||||
<lifetime>
|
<lifetime>
|
||||||
<soft>2</soft>
|
<soft>4</soft>
|
||||||
<hard>60</hard>
|
<hard>60</hard>
|
||||||
</lifetime>
|
</lifetime>
|
||||||
</policy>
|
</policy>
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
A transport connection between the hosts <b>moon</b> and <b>sun</b> is set up.
|
||||||
|
The host <b>moon</b> starts the Trusted Key Manager (TKM) and the Ada XFRM
|
||||||
|
proxy, which relays XFRM kernel messages to charon. The authentication is based
|
||||||
|
on X.509 certificates. The connection is initiated by a ping from <b>moon</b>
|
||||||
|
to <b>sun</b>. The test asserts that a rekeying initiated by <b>sun</b> works
|
||||||
|
as expected.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
moon::ipsec stroke status 2> /dev/null::conn1.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES
|
||||||
|
sun::ipsec status 2> /dev/null::host-host.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES
|
||||||
|
moon::ipsec stroke status 2> /dev/null::conn1.*INSTALLED, TRANSPORT::YES
|
||||||
|
sun::ipsec status 2> /dev/null::host-host.*INSTALLED, TRANSPORT::YES
|
||||||
|
moon::sleep 2::wait for rekeying::NO
|
||||||
|
sun::cat /var/log/daemon.log::creating rekey job for CHILD_SA ESP/0x.*/192.168.0.2::YES
|
||||||
|
moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_.eq=1::YES
|
||||||
|
sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES
|
||||||
|
sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES
|
||||||
|
moon::cat /var/log/daemon.log::deleting child SA (esa: 1, spi:.*)::NO
|
||||||
|
moon::sleep 2::wait until inbound SA is deleted::NO
|
||||||
|
moon::cat /var/log/daemon.log::deleting child SA (esa: 1, spi:.*)::YES
|
||||||
|
moon::ping -c 1 PH_IP_SUN::64 bytes from PH_IP_SUN: icmp_.eq=1::YES
|
||||||
|
moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
|
||||||
|
moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES
|
||||||
|
moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
|
||||||
|
moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
|
||||||
|
moon::cat /tmp/tkm.log::Creating first new ESA context with ID 1 (Isa 1, Sp 1, Ea 1, Initiator TRUE, spi_loc.*, spi_rem.*)::YES
|
||||||
|
moon::cat /tmp/tkm.log::Creating ESA context with ID 2 (Isa 1, Sp 1, Ea 1, Dh_Id 1, Nc_Loc_Id 1, Initiator FALSE, spi_loc.*, spi_rem.*)::YES
|
||||||
|
moon::cat /tmp/tkm.log | grep 'Adding ESA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]' | wc -l::2::YES
|
||||||
|
moon::cat /tmp/tkm.log::Resetting ESA context 1::YES
|
||||||
|
moon::cat /tmp/tkm.log::Deleting ESA \[ 1, 192.168.0.1 <=> 192.168.0.2, SPI_in.*, SPI_out.* \]::YES
|
||||||
|
moon::cat /tmp/xfrm_proxy.log::Initiating ESA acquire for reqid 1::YES
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
charon-tkm {
|
||||||
|
# remove rekeyed inbound SA a bit quicker for the test scenario
|
||||||
|
delete_rekeyed_delay = 2
|
||||||
|
dh_mapping {
|
||||||
|
15 = 1
|
||||||
|
16 = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,21 @@
|
|||||||
|
<tkmconfig>
|
||||||
|
<local_identity id="1">
|
||||||
|
<identity>moon.strongswan.org</identity>
|
||||||
|
<certificate>moonCert.pem</certificate>
|
||||||
|
</local_identity>
|
||||||
|
<policy id="1">
|
||||||
|
<mode>transport</mode>
|
||||||
|
<local>
|
||||||
|
<identity_id>1</identity_id>
|
||||||
|
<ip>192.168.0.1</ip>
|
||||||
|
</local>
|
||||||
|
<remote>
|
||||||
|
<identity>sun.strongswan.org</identity>
|
||||||
|
<ip>192.168.0.2</ip>
|
||||||
|
</remote>
|
||||||
|
<lifetime>
|
||||||
|
<soft>30</soft>
|
||||||
|
<hard>60</hard>
|
||||||
|
</lifetime>
|
||||||
|
</policy>
|
||||||
|
</tkmconfig>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||||
|
|
||||||
|
config setup
|
||||||
|
|
||||||
|
conn %default
|
||||||
|
ikelifetime=60m
|
||||||
|
keylife=10s
|
||||||
|
rekeymargin=6s
|
||||||
|
rekeyfuzz=0%
|
||||||
|
keyingtries=1
|
||||||
|
keyexchange=ikev2
|
||||||
|
|
||||||
|
conn host-host
|
||||||
|
left=PH_IP_SUN
|
||||||
|
leftcert=sunCert.pem
|
||||||
|
leftid=sun.strongswan.org
|
||||||
|
right=PH_IP_MOON
|
||||||
|
rightid=moon.strongswan.org
|
||||||
|
ike=aes256-sha512-modp4096!
|
||||||
|
esp=aes256-sha512-modp4096!
|
||||||
|
type=transport
|
||||||
|
auto=add
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# /etc/strongswan.conf - strongSwan configuration file
|
||||||
|
|
||||||
|
charon {
|
||||||
|
load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc stroke kernel-netlink socket-default updown
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
moon::DAEMON_NAME=charon-tkm ipsec stop
|
||||||
|
moon::killall xfrm_proxy
|
||||||
|
moon::killall tkm_keymanager
|
||||||
|
moon::rm -f /tmp/tkm.rpc.ike /tmp/tkm.rpc.ees /tmp/tkm.log /tmp/xfrm_proxy.log
|
||||||
|
sun::ipsec stop
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
sun::ipsec start
|
||||||
|
moon::rm /etc/ipsec.secrets
|
||||||
|
moon::tkm_cfgtool -c /etc/tkm/tkm.conf -i /etc/ipsec.conf -t /etc/tkm/tkm.bin -s /usr/local/share/tkm/tkmconfig.xsd
|
||||||
|
moon::cat /etc/ipsec.conf
|
||||||
|
moon::tkm_keymanager -c /etc/tkm/tkm.bin -k /etc/tkm/moonKey.der -r /etc/tkm/strongswanCert.der >/tmp/tkm.log 2>&1 &
|
||||||
|
moon::expect-file /tmp/tkm.rpc.ike
|
||||||
|
moon::DAEMON_NAME=charon-tkm ipsec start
|
||||||
|
moon::expect-file /tmp/tkm.rpc.ees
|
||||||
|
moon::xfrm_proxy >/tmp/xfrm_proxy.log 2>&1 &
|
||||||
|
moon::DAEMON_NAME=charon-tkm expect-connection conn1
|
||||||
|
sun::expect-connection host-host
|
||||||
|
moon::ping -c 3 192.168.0.2
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# This configuration file provides information on the
|
||||||
|
# guest instances used for this test
|
||||||
|
|
||||||
|
# All guest instances that are required for this test
|
||||||
|
#
|
||||||
|
VIRTHOSTS="moon winnetou sun"
|
||||||
|
|
||||||
|
# Corresponding block diagram
|
||||||
|
#
|
||||||
|
DIAGRAM="m-w-s.png"
|
||||||
|
|
||||||
|
# Guest instances on which tcpdump is to be started
|
||||||
|
#
|
||||||
|
TCPDUMPHOSTS="sun"
|
||||||
|
|
||||||
|
# Guest instances on which IPsec is started
|
||||||
|
# Used for IPsec logging purposes
|
||||||
|
#
|
||||||
|
IPSECHOSTS="moon sun"
|
||||||
Reference in New Issue
Block a user