summaryrefslogtreecommitdiff
path: root/src/libcharon/sa
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa')
-rw-r--r--src/libcharon/sa/child_sa.c41
-rw-r--r--src/libcharon/sa/ike_sa.c19
-rw-r--r--src/libcharon/sa/ikev1/keymat_v1.c25
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c17
-rw-r--r--src/libcharon/sa/ikev1/tasks/isakmp_vendor.c3
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c40
-rw-r--r--src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c4
-rw-r--r--src/libcharon/sa/ikev2/keymat_v2.c56
-rw-r--r--src/libcharon/sa/ikev2/task_manager_v2.c25
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c69
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_init.c8
11 files changed, 185 insertions, 122 deletions
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 8a405d93c..e4364de12 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -111,12 +111,17 @@ struct private_child_sa_t {
*/
bool static_reqid;
- /*
+ /**
* Unique CHILD_SA identifier
*/
uint32_t unique_id;
/**
+ * Whether FWD policieis in the outbound direction should be installed
+ */
+ bool policies_fwd_out;
+
+ /**
* inbound mark used for this child_sa
*/
mark_t mark_in;
@@ -931,15 +936,19 @@ static status_t install_policies_internal(private_child_sa_t *this,
* policies of two SAs we install them with reduced priority. As they
* basically act as bypass policies for drop policies we use a higher
* priority than is used for them. */
- out_id.dir = POLICY_FWD;
- other_sa->reqid = 0;
- if (priority == POLICY_PRIORITY_DEFAULT)
+ if (this->policies_fwd_out)
{
- out_policy.prio = POLICY_PRIORITY_ROUTED;
+ out_id.dir = POLICY_FWD;
+ other_sa->reqid = 0;
+ if (priority == POLICY_PRIORITY_DEFAULT)
+ {
+ out_policy.prio = POLICY_PRIORITY_ROUTED;
+ }
+ status |= charon->kernel->add_policy(charon->kernel, &out_id,
+ &out_policy);
+ /* reset the reqid for any other further policies */
+ other_sa->reqid = this->reqid;
}
- status |= charon->kernel->add_policy(charon->kernel, &out_id, &out_policy);
- /* reset the reqid for any other further policies */
- other_sa->reqid = this->reqid;
}
return status;
}
@@ -988,14 +997,17 @@ static void del_policies_internal(private_child_sa_t *this,
in_id.dir = POLICY_FWD;
charon->kernel->del_policy(charon->kernel, &in_id, &in_policy);
- out_id.dir = POLICY_FWD;
- other_sa->reqid = 0;
- if (priority == POLICY_PRIORITY_DEFAULT)
+ if (this->policies_fwd_out)
{
- out_policy.prio = POLICY_PRIORITY_ROUTED;
+ out_id.dir = POLICY_FWD;
+ other_sa->reqid = 0;
+ if (priority == POLICY_PRIORITY_DEFAULT)
+ {
+ out_policy.prio = POLICY_PRIORITY_ROUTED;
+ }
+ charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
+ other_sa->reqid = this->reqid;
}
- charon->kernel->del_policy(charon->kernel, &out_id, &out_policy);
- other_sa->reqid = this->reqid;
}
}
@@ -1443,6 +1455,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
.mark_in = config->get_mark(config, TRUE),
.mark_out = config->get_mark(config, FALSE),
.install_time = time_monotonic(NULL),
+ .policies_fwd_out = config->install_fwd_out_policy(config),
);
this->config = config;
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 009277ddd..7b87918d3 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -921,6 +921,7 @@ METHOD(ike_sa_t, reset, void,
this->ike_sa_id->is_initiator(this->ike_sa_id));
this->task_manager->reset(this->task_manager, 0, 0);
+ this->task_manager->queue_ike(this->task_manager);
}
METHOD(ike_sa_t, get_keymat, keymat_t*,
@@ -1780,16 +1781,12 @@ METHOD(ike_sa_t, delete_, status_t,
{
switch (this->state)
{
- case IKE_REKEYING:
- if (this->version == IKEV1)
- { /* SA has been reauthenticated, delete */
- charon->bus->ike_updown(charon->bus, &this->public, FALSE);
- break;
- }
- /* FALL */
case IKE_ESTABLISHED:
- if (time_monotonic(NULL) >= this->stats[STAT_DELETE])
- { /* IKE_SA hard lifetime hit */
+ case IKE_REKEYING:
+ if (time_monotonic(NULL) >= this->stats[STAT_DELETE] &&
+ !(this->version == IKEV1 && this->state == IKE_REKEYING))
+ { /* IKE_SA hard lifetime hit, ignored for reauthenticated
+ * IKEv1 SAs */
charon->bus->alert(charon->bus, ALERT_IKE_SA_EXPIRED);
}
this->task_manager->queue_ike_delete(this->task_manager);
@@ -1831,7 +1828,6 @@ METHOD(ike_sa_t, reauth, status_t,
DBG0(DBG_IKE, "reinitiating IKE_SA %s[%d]",
get_name(this), this->unique_id);
reset(this);
- this->task_manager->queue_ike(this->task_manager);
return this->task_manager->initiate(this->task_manager);
}
/* we can't reauthenticate as responder when we use EAP or virtual IPs.
@@ -2335,7 +2331,6 @@ METHOD(ike_sa_t, retransmit, status_t,
this->keyingtry + 1, tries);
reset(this);
resolve_hosts(this);
- this->task_manager->queue_ike(this->task_manager);
return this->task_manager->initiate(this->task_manager);
}
DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding");
@@ -2980,7 +2975,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
.flush_auth_cfg = lib->settings->get_bool(lib->settings,
"%s.flush_auth_cfg", FALSE, lib->ns),
.fragment_size = lib->settings->get_int(lib->settings,
- "%s.fragment_size", 0, lib->ns),
+ "%s.fragment_size", 1280, lib->ns),
.follow_redirects = lib->settings->get_bool(lib->settings,
"%s.follow_redirects", TRUE, lib->ns),
);
diff --git a/src/libcharon/sa/ikev1/keymat_v1.c b/src/libcharon/sa/ikev1/keymat_v1.c
index be6b03bef..d1d4cbd9b 100644
--- a/src/libcharon/sa/ikev1/keymat_v1.c
+++ b/src/libcharon/sa/ikev1/keymat_v1.c
@@ -75,11 +75,6 @@ struct private_keymat_v1_t {
hasher_t *hasher;
/**
- * Key used for authentication during main mode
- */
- chunk_t skeyid;
-
- /**
* Key to derive key material from for non-ISAKMP SAs, rekeying
*/
chunk_t skeyid_d;
@@ -269,12 +264,12 @@ static bool expand_skeyid_e(chunk_t skeyid_e, size_t key_size, prf_t *prf,
* Create a simple implementation of the aead_t interface which only encrypts
* or decrypts data.
*/
-static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e)
+static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e,
+ chunk_t *ka)
{
private_aead_t *this;
uint16_t alg, key_size;
crypter_t *crypter;
- chunk_t ka;
if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg,
&key_size))
@@ -292,17 +287,16 @@ static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e)
return NULL;
}
key_size = crypter->get_key_size(crypter);
- if (!expand_skeyid_e(skeyid_e, crypter->get_key_size(crypter), prf, &ka))
+ if (!expand_skeyid_e(skeyid_e, crypter->get_key_size(crypter), prf, ka))
{
return NULL;
}
- DBG4(DBG_IKE, "encryption key Ka %B", &ka);
- if (!crypter->set_key(crypter, ka))
+ DBG4(DBG_IKE, "encryption key Ka %B", ka);
+ if (!crypter->set_key(crypter, *ka))
{
- chunk_clear(&ka);
+ chunk_clear(ka);
return NULL;
}
- chunk_clear(&ka);
INIT(this,
.aead = {
@@ -392,7 +386,7 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
auth_method_t auth, shared_key_t *shared_key)
{
chunk_t g_xy, g_xi, g_xr, dh_me, spi_i, spi_r, nonces, data, skeyid_e;
- chunk_t skeyid;
+ chunk_t skeyid, ka;
uint16_t alg;
spi_i = chunk_alloca(sizeof(uint64_t));
@@ -550,11 +544,14 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
}
chunk_clear(&skeyid);
- this->aead = create_aead(proposal, this->prf, skeyid_e);
+ this->aead = create_aead(proposal, this->prf, skeyid_e, &ka);
if (!this->aead)
{
return FALSE;
}
+ charon->bus->ike_derived_keys(charon->bus, ka, chunk_empty, this->skeyid_a,
+ chunk_empty);
+ chunk_clear(&ka);
if (!this->hasher && !this->public.create_hasher(&this->public, proposal))
{
return FALSE;
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index b0c4f5f84..3b0c1cfd1 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -515,13 +515,13 @@ METHOD(task_manager_t, initiate, status_t,
new_mid = TRUE;
break;
}
- if (activate_task(this, TASK_ISAKMP_DELETE))
+ if (activate_task(this, TASK_QUICK_DELETE))
{
exchange = INFORMATIONAL_V1;
new_mid = TRUE;
break;
}
- if (activate_task(this, TASK_QUICK_DELETE))
+ if (activate_task(this, TASK_ISAKMP_DELETE))
{
exchange = INFORMATIONAL_V1;
new_mid = TRUE;
@@ -547,6 +547,14 @@ METHOD(task_manager_t, initiate, status_t,
break;
}
break;
+ case IKE_REKEYING:
+ if (activate_task(this, TASK_ISAKMP_DELETE))
+ {
+ exchange = INFORMATIONAL_V1;
+ new_mid = TRUE;
+ break;
+ }
+ break;
default:
break;
}
@@ -1181,7 +1189,7 @@ static status_t process_response(private_task_manager_t *this,
}
enumerator->destroy(enumerator);
- if (this->initiating.retransmitted)
+ if (this->initiating.retransmitted > 1)
{
packet_t *packet = NULL;
array_get(this->initiating.packets, 0, &packet);
@@ -1661,6 +1669,9 @@ METHOD(task_manager_t, queue_ike_delete, void,
enumerator_t *enumerator;
child_sa_t *child_sa;
+ /* cancel any currently active task to get the DELETE done quickly */
+ flush_queue(this, TASK_QUEUE_ACTIVE);
+
enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, &child_sa))
{
diff --git a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
index f28b83e8a..dc86fc504 100644
--- a/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
+++ b/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c
@@ -102,6 +102,7 @@ static struct {
{ "DPD", EXT_DPD, TRUE, 16,
"\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00"},
+ /* CISCO-UNITY, similar to DPD the last two bytes indicate the version */
{ "Cisco Unity", EXT_CISCO_UNITY, FALSE, 16,
"\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00"},
@@ -190,6 +191,8 @@ static bool is_known_vid(chunk_t data, int i)
break;
case EXT_MS_WINDOWS:
return data.len == 20 && memeq(data.ptr, vendor_ids[i].id, 16);
+ case EXT_CISCO_UNITY:
+ return data.len == 16 && memeq(data.ptr, vendor_ids[i].id, 14);
default:
return chunk_equals(data, chunk_create(vendor_ids[i].id,
vendor_ids[i].len));
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index bbd1cb09f..6b896416a 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -348,10 +348,6 @@ static bool install(private_quick_mode_t *this)
this->initiator, FALSE, FALSE, tsr, tsi);
}
}
- chunk_clear(&integ_i);
- chunk_clear(&integ_r);
- chunk_clear(&encr_i);
- chunk_clear(&encr_r);
if (status_i != SUCCESS || status_o != SUCCESS)
{
@@ -361,22 +357,38 @@ static bool install(private_quick_mode_t *this)
(status_o != SUCCESS) ? "outbound " : "");
tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
- return FALSE;
- }
-
- if (this->initiator)
- {
- status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
+ status = FAILED;
}
else
{
- status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
+ if (this->initiator)
+ {
+ status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
+ }
+ else
+ {
+ status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
+ }
+ tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
+ tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+ if (status != SUCCESS)
+ {
+ DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
+ }
+ else
+ {
+ charon->bus->child_derived_keys(charon->bus, this->child_sa,
+ this->initiator, encr_i, encr_r,
+ integ_i, integ_r);
+ }
}
- tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
- tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
+ chunk_clear(&integ_i);
+ chunk_clear(&integ_r);
+ chunk_clear(&encr_i);
+ chunk_clear(&encr_r);
+
if (status != SUCCESS)
{
- DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
return FALSE;
}
diff --git a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
index 6fd34e0a6..592f49770 100644
--- a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
@@ -161,8 +161,8 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat,
if (key_type == KEY_RSA)
{
signature_scheme_t schemes[] = {
- SIGN_RSA_EMSA_PKCS1_SHA384,
- SIGN_RSA_EMSA_PKCS1_SHA256,
+ SIGN_RSA_EMSA_PKCS1_SHA2_384,
+ SIGN_RSA_EMSA_PKCS1_SHA2_256,
SIGN_RSA_EMSA_PKCS1_SHA1,
}, contained;
bool found;
diff --git a/src/libcharon/sa/ikev2/keymat_v2.c b/src/libcharon/sa/ikev2/keymat_v2.c
index e37399841..58efdbabe 100644
--- a/src/libcharon/sa/ikev2/keymat_v2.c
+++ b/src/libcharon/sa/ikev2/keymat_v2.c
@@ -103,7 +103,7 @@ static bool derive_ike_aead(private_keymat_v2_t *this, uint16_t alg,
uint16_t key_size, prf_plus_t *prf_plus)
{
aead_t *aead_i, *aead_r;
- chunk_t key = chunk_empty;
+ chunk_t sk_ei = chunk_empty, sk_er = chunk_empty;
u_int salt_size;
switch (alg)
@@ -146,23 +146,22 @@ static bool derive_ike_aead(private_keymat_v2_t *this, uint16_t alg,
{
goto failure;
}
- if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ei))
{
goto failure;
}
- DBG4(DBG_IKE, "Sk_ei secret %B", &key);
- if (!aead_i->set_key(aead_i, key))
+ DBG4(DBG_IKE, "Sk_ei secret %B", &sk_ei);
+ if (!aead_i->set_key(aead_i, sk_ei))
{
goto failure;
}
- chunk_clear(&key);
- if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_er))
{
goto failure;
}
- DBG4(DBG_IKE, "Sk_er secret %B", &key);
- if (!aead_r->set_key(aead_r, key))
+ DBG4(DBG_IKE, "Sk_er secret %B", &sk_er);
+ if (!aead_r->set_key(aead_r, sk_er))
{
goto failure;
}
@@ -178,11 +177,14 @@ static bool derive_ike_aead(private_keymat_v2_t *this, uint16_t alg,
this->aead_out = aead_r;
}
aead_i = aead_r = NULL;
+ charon->bus->ike_derived_keys(charon->bus, sk_ei, sk_er, chunk_empty,
+ chunk_empty);
failure:
DESTROY_IF(aead_i);
DESTROY_IF(aead_r);
- chunk_clear(&key);
+ chunk_clear(&sk_ei);
+ chunk_clear(&sk_er);
return this->aead_in && this->aead_out;
}
@@ -196,7 +198,8 @@ static bool derive_ike_traditional(private_keymat_v2_t *this, uint16_t enc_alg,
signer_t *signer_i, *signer_r;
iv_gen_t *ivg_i, *ivg_r;
size_t key_size;
- chunk_t key = chunk_empty;
+ chunk_t sk_ei = chunk_empty, sk_er = chunk_empty,
+ sk_ai = chunk_empty, sk_ar = chunk_empty;
signer_i = lib->crypto->create_signer(lib->crypto, int_alg);
signer_r = lib->crypto->create_signer(lib->crypto, int_alg);
@@ -220,48 +223,45 @@ static bool derive_ike_traditional(private_keymat_v2_t *this, uint16_t enc_alg,
/* SK_ai/SK_ar used for integrity protection */
key_size = signer_i->get_key_size(signer_i);
- if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ai))
{
goto failure;
}
- DBG4(DBG_IKE, "Sk_ai secret %B", &key);
- if (!signer_i->set_key(signer_i, key))
+ DBG4(DBG_IKE, "Sk_ai secret %B", &sk_ai);
+ if (!signer_i->set_key(signer_i, sk_ai))
{
goto failure;
}
- chunk_clear(&key);
- if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ar))
{
goto failure;
}
- DBG4(DBG_IKE, "Sk_ar secret %B", &key);
- if (!signer_r->set_key(signer_r, key))
+ DBG4(DBG_IKE, "Sk_ar secret %B", &sk_ar);
+ if (!signer_r->set_key(signer_r, sk_ar))
{
goto failure;
}
- chunk_clear(&key);
/* SK_ei/SK_er used for encryption */
key_size = crypter_i->get_key_size(crypter_i);
- if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ei))
{
goto failure;
}
- DBG4(DBG_IKE, "Sk_ei secret %B", &key);
- if (!crypter_i->set_key(crypter_i, key))
+ DBG4(DBG_IKE, "Sk_ei secret %B", &sk_ei);
+ if (!crypter_i->set_key(crypter_i, sk_ei))
{
goto failure;
}
- chunk_clear(&key);
- if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
+ if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_er))
{
goto failure;
}
- DBG4(DBG_IKE, "Sk_er secret %B", &key);
- if (!crypter_r->set_key(crypter_r, key))
+ DBG4(DBG_IKE, "Sk_er secret %B", &sk_er);
+ if (!crypter_r->set_key(crypter_r, sk_er))
{
goto failure;
}
@@ -284,9 +284,13 @@ static bool derive_ike_traditional(private_keymat_v2_t *this, uint16_t enc_alg,
}
signer_i = signer_r = NULL;
crypter_i = crypter_r = NULL;
+ charon->bus->ike_derived_keys(charon->bus, sk_ei, sk_er, sk_ai, sk_ar);
failure:
- chunk_clear(&key);
+ chunk_clear(&sk_ai);
+ chunk_clear(&sk_ar);
+ chunk_clear(&sk_ei);
+ chunk_clear(&sk_er);
DESTROY_IF(signer_i);
DESTROY_IF(signer_r);
DESTROY_IF(crypter_i);
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index 41a4e1b75..60a262ffc 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -709,7 +709,7 @@ static status_t process_response(private_task_manager_t *this,
}
enumerator->destroy(enumerator);
- if (this->initiating.retransmitted)
+ if (this->initiating.retransmitted > 1)
{
packet_t *packet = NULL;
array_get(this->initiating.packets, 0, &packet);
@@ -1827,15 +1827,22 @@ METHOD(task_manager_t, queue_dpd, void,
if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE) &&
this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
{
- /* use mobike enabled DPD to detect NAT mapping changes */
- mobike = ike_mobike_create(this->ike_sa, TRUE);
- mobike->dpd(mobike);
- queue_task(this, &mobike->task);
- }
- else
- {
- queue_task(this, (task_t*)ike_dpd_create(TRUE));
+#ifdef ME
+ peer_cfg_t *cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
+ if (cfg->get_peer_id(cfg) ||
+ this->ike_sa->has_condition(this->ike_sa, COND_ORIGINAL_INITIATOR))
+#else
+ if (this->ike_sa->has_condition(this->ike_sa, COND_ORIGINAL_INITIATOR))
+#endif
+ {
+ /* use mobike enabled DPD to detect NAT mapping changes */
+ mobike = ike_mobike_create(this->ike_sa, TRUE);
+ mobike->dpd(mobike);
+ queue_task(this, &mobike->task);
+ return;
+ }
}
+ queue_task(this, (task_t*)ike_dpd_create(TRUE));
}
METHOD(task_manager_t, adopt_tasks, void,
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 64a82850b..71cb6b8ea 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -666,10 +666,6 @@ static status_t select_and_install(private_child_create_t *this,
FALSE, this->tfcv3, my_ts, other_ts);
}
}
- chunk_clear(&integ_i);
- chunk_clear(&integ_r);
- chunk_clear(&encr_i);
- chunk_clear(&encr_r);
if (status_i != SUCCESS || status_o != SUCCESS)
{
@@ -679,41 +675,62 @@ static status_t select_and_install(private_child_create_t *this,
(status_o != SUCCESS) ? "outbound " : "");
charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
this->child_sa);
- return FAILED;
- }
-
- if (this->initiator)
- {
- status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts);
+ status = FAILED;
}
else
{
- /* use a copy of the traffic selectors, as the POST hook should not
- * change payloads */
- my_ts = this->tsr->clone_offset(this->tsr,
+ if (this->initiator)
+ {
+ status = this->child_sa->add_policies(this->child_sa,
+ my_ts, other_ts);
+ }
+ else
+ {
+ /* use a copy of the traffic selectors, as the POST hook should not
+ * change payloads */
+ my_ts = this->tsr->clone_offset(this->tsr,
offsetof(traffic_selector_t, clone));
- other_ts = this->tsi->clone_offset(this->tsi,
+ other_ts = this->tsi->clone_offset(this->tsi,
offsetof(traffic_selector_t, clone));
- charon->bus->narrow(charon->bus, this->child_sa,
- NARROW_RESPONDER_POST, my_ts, other_ts);
- if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_RESPONDER_POST, my_ts, other_ts);
+ if (my_ts->get_count(my_ts) == 0 ||
+ other_ts->get_count(other_ts) == 0)
+ {
+ status = FAILED;
+ }
+ else
+ {
+ status = this->child_sa->add_policies(this->child_sa,
+ my_ts, other_ts);
+ }
+ my_ts->destroy_offset(my_ts,
+ offsetof(traffic_selector_t, destroy));
+ other_ts->destroy_offset(other_ts,
+ offsetof(traffic_selector_t, destroy));
+ }
+ if (status != SUCCESS)
{
- status = FAILED;
+ DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
+ charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_POLICY_FAILED,
+ this->child_sa);
+ status = NOT_FOUND;
}
else
{
- status = this->child_sa->add_policies(this->child_sa,
- my_ts, other_ts);
+ charon->bus->child_derived_keys(charon->bus, this->child_sa,
+ this->initiator, encr_i, encr_r,
+ integ_i, integ_r);
}
- my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
- other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
}
+ chunk_clear(&integ_i);
+ chunk_clear(&integ_r);
+ chunk_clear(&encr_i);
+ chunk_clear(&encr_r);
+
if (status != SUCCESS)
{
- DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
- charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_POLICY_FAILED,
- this->child_sa);
- return NOT_FOUND;
+ return status;
}
charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index 801b6d8f3..d82e206b8 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -457,6 +457,11 @@ static void process_payloads(private_ike_init_t *this, message_t *message)
}
enumerator->destroy(enumerator);
+ if (this->proposal)
+ {
+ this->ike_sa->set_proposal(this->ike_sa, this->proposal);
+ }
+
if (ke_payload && this->proposal &&
this->proposal->has_dh_group(this->proposal, this->dh_group))
{
@@ -614,7 +619,6 @@ METHOD(task_t, build_r, status_t,
message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
return FAILED;
}
- this->ike_sa->set_proposal(this->ike_sa, this->proposal);
/* check if we'd have to redirect the client */
if (!this->old_sa &&
@@ -651,6 +655,7 @@ METHOD(task_t, build_r, status_t,
else
{
DBG1(DBG_IKE, "no acceptable proposal found");
+ message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty);
}
return FAILED;
}
@@ -849,7 +854,6 @@ METHOD(task_t, process_i, status_t,
DBG1(DBG_IKE, "peers proposal selection invalid");
return FAILED;
}
- this->ike_sa->set_proposal(this->ike_sa, this->proposal);
if (this->dh == NULL ||
!this->proposal->has_dh_group(this->proposal, this->dh_group))