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:
commit
11ddda2ecd
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Tobias Brunner
|
||||
* Copyright (C) 2012-2014 Reto Buerki
|
||||
* 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
|
||||
* 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,
|
||||
private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
|
||||
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->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, "
|
||||
"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,
|
||||
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,
|
||||
id->spi, id->proto);
|
||||
id->spi, id->proto, TRUE);
|
||||
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,
|
||||
ntohl(id->spi));
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -358,6 +382,7 @@ tkm_kernel_ipsec_t *tkm_kernel_ipsec_create()
|
|||
INIT(this,
|
||||
.public = {
|
||||
.interface = {
|
||||
.get_features = _get_features,
|
||||
.get_spi = _get_spi,
|
||||
.get_cpi = _get_cpi,
|
||||
.add_sa = _add_sa,
|
||||
|
|
|
@ -107,16 +107,23 @@ CALLBACK(sad_entry_match, bool,
|
|||
const host_t *src, *dst;
|
||||
const uint32_t *spi;
|
||||
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 src->ip_equals(entry->src, (host_t *)src) &&
|
||||
dst->ip_equals(entry->dst, (host_t *)dst) &&
|
||||
entry->spi_rem == *spi && entry->proto == *proto;
|
||||
if (*local)
|
||||
{
|
||||
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,
|
||||
|
@ -131,26 +138,6 @@ CALLBACK(sad_entry_match_dst, bool,
|
|||
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,
|
||||
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,
|
||||
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;
|
||||
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);
|
||||
const bool res = this->data->find_first(this->data, sad_entry_match,
|
||||
(void**)&entry, src, dst, &spi,
|
||||
&proto);
|
||||
&proto, &local);
|
||||
if (res && entry)
|
||||
{
|
||||
id = entry->esa_id;
|
||||
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
|
||||
{
|
||||
DBG3(DBG_KNL, "no SAD entry found for src %H, dst %H, spi %x, proto %u",
|
||||
src, dst, 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);
|
||||
DBG3(DBG_KNL, "no SAD entry found for src %H, dst %H, %sbound spi %x, "
|
||||
"proto %u", src, dst, local ? "in" : "out", ntohl(spi), proto);
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
return id;
|
||||
|
@ -350,7 +305,6 @@ tkm_kernel_sad_t *tkm_kernel_sad_create()
|
|||
.public = {
|
||||
.insert = _insert,
|
||||
.get_esa_id = _get_esa_id,
|
||||
.get_other_esa_id = _get_other_esa_id,
|
||||
.get_dst_host = _get_dst_host,
|
||||
.remove = __remove,
|
||||
.destroy = _destroy,
|
||||
|
|
|
@ -55,23 +55,14 @@ struct tkm_kernel_sad_t {
|
|||
*
|
||||
* @param src source 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 local whether the SPI is local or remote
|
||||
* @return ESA id of entry if found, 0 otherwise
|
||||
*/
|
||||
esa_id_type (*get_esa_id)(tkm_kernel_sad_t * const this,
|
||||
const host_t * const src, const host_t * const dst,
|
||||
const uint32_t spi, const uint8_t proto);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
const uint32_t spi, const uint8_t proto, const bool local);
|
||||
|
||||
/**
|
||||
* 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();
|
||||
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, 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");
|
||||
sad->destroy(sad);
|
||||
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);
|
||||
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");
|
||||
sad->destroy(sad);
|
||||
addr->destroy(addr);
|
||||
}
|
||||
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)
|
||||
{
|
||||
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");
|
||||
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);
|
||||
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");
|
||||
tcase_add_test(tc, test_get_dst_host);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -77,6 +77,8 @@ enum kernel_feature_t {
|
|||
KERNEL_REQUIRE_UDP_ENCAPSULATION = (1<<2),
|
||||
/** IPsec backend does not require a policy reinstall on SA updates */
|
||||
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,
|
||||
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 {
|
||||
uint8_t proto;
|
||||
uint32_t spi;
|
||||
bool use;
|
||||
} protos[] = {
|
||||
{ IPPROTO_COMP, ipsec->cfg.ipcomp.transform != IPCOMP_NONE },
|
||||
{ IPPROTO_ESP, ipsec->cfg.esp.use },
|
||||
{ IPPROTO_AH, ipsec->cfg.ah.use },
|
||||
{ IPPROTO_COMP, htonl(ntohs(ipsec->cfg.ipcomp.cpi)),
|
||||
ipsec->cfg.ipcomp.transform != IPCOMP_NONE },
|
||||
{ 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;
|
||||
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->id.proto = protos[i].proto;
|
||||
if (policy->direction == POLICY_OUT)
|
||||
{
|
||||
tmpl->id.spi = protos[i].spi;
|
||||
}
|
||||
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
|
||||
tmpl->mode = mode2kernel(proto_mode);
|
||||
tmpl->optional = protos[i].proto == IPPROTO_COMP &&
|
||||
|
|
|
@ -40,10 +40,10 @@ ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
|
|||
"DESTROYING",
|
||||
);
|
||||
|
||||
ENUM(child_sa_outbound_state_names, CHILD_OUTBOUND_NONE, CHILD_OUTBOUND_INSTALLED,
|
||||
"NONE",
|
||||
ENUM_FLAGS(child_sa_outbound_state_names, CHILD_OUTBOUND_REGISTERED, CHILD_OUTBOUND_POLICIES,
|
||||
"REGISTERED",
|
||||
"INSTALLED",
|
||||
"SA",
|
||||
"POLICIES",
|
||||
);
|
||||
|
||||
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
|
||||
{
|
||||
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 = {
|
||||
.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);
|
||||
}
|
||||
this->outbound_state = CHILD_OUTBOUND_INSTALLED;
|
||||
this->outbound_state |= CHILD_OUTBOUND_SA;
|
||||
}
|
||||
|
||||
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;
|
||||
traffic_selector_t *my_ts, *other_ts;
|
||||
status_t status = SUCCESS;
|
||||
bool install_outbound = FALSE;
|
||||
|
||||
if (!this->reqid_allocated && !this->static_reqid)
|
||||
{
|
||||
|
@ -1207,12 +1208,17 @@ METHOD(child_sa_t, install_policies, status_t,
|
|||
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))
|
||||
{
|
||||
policy_priority_t priority;
|
||||
ipsec_sa_cfg_t my_sa, other_sa;
|
||||
uint32_t manual_prio;
|
||||
bool install_outbound;
|
||||
|
||||
prepare_sa_cfg(this, &my_sa, &other_sa);
|
||||
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;
|
||||
priority = this->trap ? POLICY_PRIORITY_ROUTED
|
||||
: POLICY_PRIORITY_DEFAULT;
|
||||
install_outbound = this->outbound_state != CHILD_OUTBOUND_REGISTERED;
|
||||
|
||||
/* enumerate pairs of traffic selectors */
|
||||
enumerator = create_policy_enumerator(this);
|
||||
|
@ -1250,7 +1255,6 @@ METHOD(child_sa_t, install_policies, status_t,
|
|||
this->other_addr, my_ts, other_ts,
|
||||
&my_sa, &other_sa, POLICY_IPSEC,
|
||||
priority, manual_prio);
|
||||
|
||||
}
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
|
@ -1267,21 +1271,35 @@ METHOD(child_sa_t, install_policies, status_t,
|
|||
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,
|
||||
uint16_t cpi, bool tfcv3)
|
||||
{
|
||||
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);
|
||||
status_t status;
|
||||
|
||||
this->other_spi = spi;
|
||||
this->other_cpi = cpi;
|
||||
this->encr_r = chunk_clone(encr);
|
||||
this->integ_r = chunk_clone(integ);
|
||||
this->tfcv3 = tfcv3;
|
||||
this->outbound_state = CHILD_OUTBOUND_REGISTERED;
|
||||
/* if the kernel supports installing SPIs with policies we install the
|
||||
* SA immediately as it will only be used once we update the policies */
|
||||
if (charon->kernel->get_features(charon->kernel) & KERNEL_POLICY_SPI)
|
||||
{
|
||||
status = install_internal(this, encr, integ, spi, cpi, FALSE, FALSE,
|
||||
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,
|
||||
|
@ -1289,18 +1307,23 @@ METHOD(child_sa_t, install_outbound, status_t,
|
|||
{
|
||||
enumerator_t *enumerator;
|
||||
traffic_selector_t *my_ts, *other_ts;
|
||||
status_t status;
|
||||
status_t status = SUCCESS;
|
||||
|
||||
status = install_internal(this, this->encr_r, this->integ_r,
|
||||
this->other_spi, this->other_cpi, FALSE, FALSE,
|
||||
this->tfcv3);
|
||||
chunk_clear(&this->encr_r);
|
||||
chunk_clear(&this->integ_r);
|
||||
if (!(this->outbound_state & CHILD_OUTBOUND_SA))
|
||||
{
|
||||
status = install_internal(this, this->encr_r, this->integ_r,
|
||||
this->other_spi, this->other_cpi, FALSE,
|
||||
FALSE, this->tfcv3);
|
||||
chunk_clear(&this->encr_r);
|
||||
chunk_clear(&this->integ_r);
|
||||
}
|
||||
this->outbound_state &= ~CHILD_OUTBOUND_REGISTERED;
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
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;
|
||||
uint32_t manual_prio;
|
||||
|
@ -1331,6 +1354,7 @@ METHOD(child_sa_t, install_outbound, status_t,
|
|||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
this->outbound_state |= CHILD_OUTBOUND_POLICIES;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1340,20 +1364,19 @@ METHOD(child_sa_t, remove_outbound, void,
|
|||
enumerator_t *enumerator;
|
||||
traffic_selector_t *my_ts, *other_ts;
|
||||
|
||||
switch (this->outbound_state)
|
||||
if (!(this->outbound_state & CHILD_OUTBOUND_SA))
|
||||
{
|
||||
case CHILD_OUTBOUND_INSTALLED:
|
||||
break;
|
||||
case CHILD_OUTBOUND_REGISTERED:
|
||||
if (this->outbound_state & CHILD_OUTBOUND_REGISTERED)
|
||||
{
|
||||
chunk_clear(&this->encr_r);
|
||||
chunk_clear(&this->integ_r);
|
||||
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;
|
||||
uint32_t manual_prio;
|
||||
|
@ -1598,8 +1621,8 @@ METHOD(child_sa_t, destroy, void,
|
|||
|
||||
prepare_sa_cfg(this, &my_sa, &other_sa);
|
||||
manual_prio = this->config->get_manual_prio(this->config);
|
||||
del_outbound = this->trap ||
|
||||
this->outbound_state == CHILD_OUTBOUND_INSTALLED;
|
||||
del_outbound = (this->outbound_state & CHILD_OUTBOUND_POLICIES) ||
|
||||
this->trap;
|
||||
|
||||
/* delete all policies in the kernel */
|
||||
enumerator = create_policy_enumerator(this);
|
||||
|
@ -1640,7 +1663,7 @@ METHOD(child_sa_t, destroy, void,
|
|||
};
|
||||
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 = {
|
||||
.src = this->my_addr,
|
||||
|
|
|
@ -102,17 +102,28 @@ enum child_sa_outbound_state_t {
|
|||
/**
|
||||
* 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
|
||||
* 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 integ integrity key (cloned)
|
||||
* @param spi SPI to use, allocated for inbound
|
||||
* @param cpi CPI to use, allocated for outbound
|
||||
* @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,
|
||||
uint32_t spi, uint16_t cpi, bool tfcv3);
|
||||
status_t (*register_outbound)(child_sa_t *this, chunk_t encr, chunk_t integ,
|
||||
uint32_t spi, uint16_t cpi, bool tfcv3);
|
||||
|
||||
/**
|
||||
* Install the outbound SA and the outbound policies as responder during a
|
||||
* rekeying.
|
||||
* Install the outbound policies and, if not already done, the outbound SA
|
||||
* as responder during a rekeying.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
status_t status, status_i, status_o;
|
||||
child_sa_outbound_state_t out_state;
|
||||
chunk_t nonce_i, nonce_r;
|
||||
chunk_t encr_i = chunk_empty, encr_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,
|
||||
this->my_spi, this->my_cpi, this->initiator,
|
||||
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,
|
||||
this->my_spi, this->my_cpi, this->initiator,
|
||||
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,
|
||||
FALSE, this->tfcv3);
|
||||
}
|
||||
else
|
||||
{ /* as responder during a rekeying we only install the inbound
|
||||
* SA now, the outbound SA and policies are installed when we
|
||||
* receive the delete for the old SA */
|
||||
status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
|
||||
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;
|
||||
{
|
||||
status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
|
||||
this->other_spi, this->other_cpi, this->initiator,
|
||||
FALSE, this->tfcv3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
other_ts = linked_list_create_from_enumerator(
|
||||
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 "
|
||||
"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_unique_id(this->child_sa),
|
||||
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? */
|
||||
return;
|
||||
}
|
||||
child_sa->set_state(child_sa, CHILD_INSTALLED);
|
||||
|
||||
my_ts = linked_list_create_from_enumerator(
|
||||
child_sa->create_ts_enumerator(child_sa, TRUE));
|
||||
|
|
|
@ -283,7 +283,8 @@ METHOD(task_t, build_r, status_t,
|
|||
/**
|
||||
* 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;
|
||||
|
||||
|
@ -303,6 +304,7 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
|
|||
child_sa_t *child_sa;
|
||||
|
||||
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;
|
||||
/* don't touch child other created, it has already been deleted */
|
||||
if (!this->other_child_destroyed)
|
||||
|
@ -353,7 +355,7 @@ METHOD(task_t, process_i, status_t,
|
|||
{
|
||||
protocol_id_t protocol;
|
||||
uint32_t spi;
|
||||
child_sa_t *to_delete;
|
||||
child_sa_t *to_delete, *to_install = NULL;
|
||||
|
||||
if (message->get_notify(message, NO_ADDITIONAL_SAS))
|
||||
{
|
||||
|
@ -415,19 +417,48 @@ METHOD(task_t, process_i, status_t,
|
|||
/* check for rekey collisions */
|
||||
if (this->collision)
|
||||
{
|
||||
to_delete = handle_collision(this);
|
||||
to_delete = handle_collision(this, &to_install);
|
||||
}
|
||||
else
|
||||
{
|
||||
to_install = this->child_create->get_child(this->child_create);
|
||||
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))
|
||||
{ /* invoke rekey hook if rekeying successful */
|
||||
charon->bus->child_rekey(charon->bus, this->child_sa,
|
||||
this->child_create->get_child(this->child_create));
|
||||
}
|
||||
|
||||
if (to_delete == NULL)
|
||||
{
|
||||
return SUCCESS;
|
||||
|
|
|
@ -483,6 +483,9 @@ START_TEST(test_collision)
|
|||
CHILD_OUTBOUND_REGISTERED);
|
||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_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
|
||||
{
|
||||
|
@ -493,10 +496,10 @@ START_TEST(test_collision)
|
|||
CHILD_OUTBOUND_INSTALLED);
|
||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||
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 } --> */
|
||||
if (data[_i].spi_del_b == 2)
|
||||
{
|
||||
|
@ -507,6 +510,9 @@ START_TEST(test_collision)
|
|||
CHILD_OUTBOUND_REGISTERED);
|
||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_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
|
||||
{
|
||||
|
@ -517,10 +523,10 @@ START_TEST(test_collision)
|
|||
CHILD_OUTBOUND_INSTALLED);
|
||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||
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 */
|
||||
assert_hook_not_called(child_rekey);
|
||||
|
@ -528,27 +534,41 @@ START_TEST(test_collision)
|
|||
assert_jobs_scheduled(1);
|
||||
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
|
||||
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,
|
||||
CHILD_OUTBOUND_NONE);
|
||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||
CHILD_OUTBOUND_INSTALLED);
|
||||
assert_child_sa_count(b, 3);
|
||||
assert_ipsec_sas_installed(b, 2, 4, 5, 6,
|
||||
data[_i].spi_del_b == 2 ? 1 : 3);
|
||||
if (data[_i].spi_del_b == 2)
|
||||
{
|
||||
assert_ipsec_sas_installed(b, 1, 2, 4, 5, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_ipsec_sas_installed(b, 2, 3, 4, 5);
|
||||
}
|
||||
assert_scheduler();
|
||||
/* <-- INFORMATIONAL { D } */
|
||||
assert_jobs_scheduled(1);
|
||||
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
|
||||
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,
|
||||
CHILD_OUTBOUND_NONE);
|
||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||
CHILD_OUTBOUND_INSTALLED);
|
||||
assert_child_sa_count(a, 3);
|
||||
assert_ipsec_sas_installed(a, 1, 3, 5, 6,
|
||||
data[_i].spi_del_a == 1 ? 2 : 4);
|
||||
if (data[_i].spi_del_a == 1)
|
||||
{
|
||||
assert_ipsec_sas_installed(a, 1, 2, 3, 5, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_ipsec_sas_installed(a, 1, 3, 4, 6);
|
||||
}
|
||||
assert_scheduler();
|
||||
/* <-- INFORMATIONAL { D } */
|
||||
assert_jobs_scheduled(1);
|
||||
|
@ -682,6 +702,9 @@ START_TEST(test_collision_delayed_response)
|
|||
CHILD_OUTBOUND_REGISTERED);
|
||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_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
|
||||
{
|
||||
|
@ -692,10 +715,10 @@ START_TEST(test_collision_delayed_response)
|
|||
CHILD_OUTBOUND_INSTALLED);
|
||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||
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 } */
|
||||
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);
|
||||
exchange_test_helper->process_message(exchange_test_helper, a, msg);
|
||||
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
|
||||
{
|
||||
assert_hook_not_called(child_rekey);
|
||||
exchange_test_helper->process_message(exchange_test_helper, a, msg);
|
||||
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,
|
||||
CHILD_OUTBOUND_NONE);
|
||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_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);
|
||||
|
||||
/* we don't expect this hook to get called anymore */
|
||||
|
@ -1173,6 +1198,8 @@ START_TEST(test_collision_ke_invalid)
|
|||
CHILD_OUTBOUND_REGISTERED);
|
||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||
CHILD_OUTBOUND_INSTALLED);
|
||||
assert_child_sa_state(a, data[_i].spi_del_a, CHILD_DELETING,
|
||||
CHILD_OUTBOUND_INSTALLED);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1181,9 +1208,9 @@ START_TEST(test_collision_ke_invalid)
|
|||
CHILD_OUTBOUND_INSTALLED);
|
||||
assert_child_sa_state(a, data[_i].spi_a, CHILD_INSTALLED,
|
||||
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 } --> */
|
||||
if (data[_i].spi_del_b == 2)
|
||||
{
|
||||
|
@ -1194,6 +1221,8 @@ START_TEST(test_collision_ke_invalid)
|
|||
CHILD_OUTBOUND_REGISTERED);
|
||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||
CHILD_OUTBOUND_INSTALLED);
|
||||
assert_child_sa_state(b, data[_i].spi_del_b, CHILD_DELETING,
|
||||
CHILD_OUTBOUND_INSTALLED);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1202,9 +1231,10 @@ START_TEST(test_collision_ke_invalid)
|
|||
CHILD_OUTBOUND_INSTALLED);
|
||||
assert_child_sa_state(b, data[_i].spi_b, CHILD_INSTALLED,
|
||||
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 */
|
||||
assert_hook_not_called(child_rekey);
|
||||
|
@ -1212,7 +1242,8 @@ START_TEST(test_collision_ke_invalid)
|
|||
assert_jobs_scheduled(1);
|
||||
exchange_test_helper->process_message(exchange_test_helper, b, NULL);
|
||||
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,
|
||||
CHILD_OUTBOUND_NONE);
|
||||
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);
|
||||
exchange_test_helper->process_message(exchange_test_helper, a, NULL);
|
||||
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,
|
||||
CHILD_OUTBOUND_NONE);
|
||||
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", \
|
||||
child_sa_state_names, _state, \
|
||||
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, _child->get_outbound_state(_child)); \
|
||||
})
|
||||
|
|
|
@ -416,29 +416,50 @@ do
|
|||
STATUS="passed"
|
||||
|
||||
eval `awk -F "::" '{
|
||||
host=$1
|
||||
command=$2
|
||||
pattern=$3
|
||||
hit=$4
|
||||
if (host !~ /^#.*/ && command != "")
|
||||
{
|
||||
host=$1
|
||||
command=$2
|
||||
pattern=$3
|
||||
hit=$4
|
||||
if (host ~ /^#.*/ || command == "")
|
||||
{
|
||||
next
|
||||
}
|
||||
printf("cmd_err=\044(tempfile -p test -s err); ")
|
||||
if (command == "tcpdump")
|
||||
{
|
||||
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("ssh \044SSHCONF root@\044ipv4_%s cat /tmp/tcpdump.log | grep \"%s\"; ", host, pattern)
|
||||
printf("if [ \044TDUP_%s == \"true\" ]; then stop_tcpdump %s; fi; \n", host, host)
|
||||
printf("cmd_out=\044(ssh \044SSHCONF root@\044ipv4_%s cat /tmp/tcpdump.log | grep \"%s\"); ", host, pattern)
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("echo \"%s# %s | grep \047%s\047 [%s]\"; ", host, command, pattern, hit)
|
||||
printf("ssh \044SSHCONF root@\044ipv4_%s %s | grep \"%s\"; ", host, command, pattern)
|
||||
printf("cmd_out=\044(ssh \044SSHCONF root@\044ipv4_%s %s 2>\044cmd_err | grep \"%s\"); ", host, command, pattern)
|
||||
}
|
||||
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("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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
leftid=@moon.strongswan.org
|
||||
leftsubnet=10.1.0.0/16
|
||||
leftfirewall=yes
|
||||
right=PH_IP_SUN
|
||||
rightid=@sun.strongswan.org
|
||||
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
|
||||
leftid=@sun.strongswan.org
|
||||
leftsubnet=10.2.0.0/16
|
||||
leftfirewall=yes
|
||||
right=PH_IP_MOON
|
||||
rightid=@moon.strongswan.org
|
||||
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
|
||||
leftid=@moon.strongswan.org
|
||||
leftsubnet=10.1.0.0/16
|
||||
leftfirewall=yes
|
||||
right=PH_IP_SUN
|
||||
rightid=@sun.strongswan.org
|
||||
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
|
||||
leftid=@sun.strongswan.org
|
||||
leftsubnet=10.2.0.0/16
|
||||
leftfirewall=yes
|
||||
right=PH_IP_MOON
|
||||
rightid=@moon.strongswan.org
|
||||
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
|
||||
moon::ipsec stroke status 2> /dev/null::conn1.*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
|
||||
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 for rekeying::NO
|
||||
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::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::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 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::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
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# /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
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<ip>192.168.0.2</ip>
|
||||
</remote>
|
||||
<lifetime>
|
||||
<soft>2</soft>
|
||||
<soft>4</soft>
|
||||
<hard>60</hard>
|
||||
</lifetime>
|
||||
</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"
|
Loading…
Reference in New Issue