summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/tasks
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2010-08-09 08:09:54 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2010-08-09 08:09:54 +0000
commitb8064f4099997a9e2179f3ad4ace605f5ccac3a1 (patch)
tree81778e976b476374c48b4fe83d084b986b890421 /src/libcharon/sa/tasks
parent1ac70afcc1f7d6d2738a34308810719b0976d29f (diff)
downloadvyos-strongswan-b8064f4099997a9e2179f3ad4ace605f5ccac3a1.tar.gz
vyos-strongswan-b8064f4099997a9e2179f3ad4ace605f5ccac3a1.zip
[svn-upgrade] new version strongswan (4.4.1)
Diffstat (limited to 'src/libcharon/sa/tasks')
-rw-r--r--src/libcharon/sa/tasks/child_create.c111
-rw-r--r--src/libcharon/sa/tasks/child_delete.c4
-rw-r--r--src/libcharon/sa/tasks/child_rekey.c95
-rw-r--r--src/libcharon/sa/tasks/ike_auth.c12
-rw-r--r--src/libcharon/sa/tasks/ike_cert_post.c10
-rw-r--r--src/libcharon/sa/tasks/ike_cert_pre.c14
-rw-r--r--src/libcharon/sa/tasks/ike_config.c4
-rw-r--r--src/libcharon/sa/tasks/ike_init.c1
8 files changed, 141 insertions, 110 deletions
diff --git a/src/libcharon/sa/tasks/child_create.c b/src/libcharon/sa/tasks/child_create.c
index bea4f73d5..3de27ee3f 100644
--- a/src/libcharon/sa/tasks/child_create.c
+++ b/src/libcharon/sa/tasks/child_create.c
@@ -273,7 +273,8 @@ static void schedule_inactivity_timeout(private_child_create_t *this)
* - INVALID_ARG: diffie hellman group inacceptable
* - NOT_FOUND: TS inacceptable
*/
-static status_t select_and_install(private_child_create_t *this, bool no_dh)
+static status_t select_and_install(private_child_create_t *this,
+ bool no_dh, bool ike_auth)
{
status_t status, status_i, status_o;
chunk_t nonce_i, nonce_r;
@@ -364,6 +365,25 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts,
other_vip);
+ if (this->initiator)
+ {
+ if (ike_auth)
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_POST_NOAUTH, my_ts, other_ts);
+ }
+ else
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_POST_AUTH, my_ts, other_ts);
+ }
+ }
+ else
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_RESPONDER, my_ts, other_ts);
+ }
+
if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
{
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
@@ -418,66 +438,6 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
}
}
- /* check for any certificate-based IP address block constraints */
- if (this->mode == MODE_BEET || this->mode == MODE_TUNNEL)
- {
- auth_cfg_t *auth;
- enumerator_t *auth_enum;
- certificate_t *cert = NULL;
-
- auth_enum = this->ike_sa->create_auth_cfg_enumerator(this->ike_sa, FALSE);
- while (auth_enum->enumerate(auth_enum, &auth))
- {
- cert = auth->get(auth, AUTH_HELPER_SUBJECT_CERT);
- if (cert)
- {
- break;
- }
- }
- auth_enum->destroy(auth_enum);
-
- if (cert && cert->get_type(cert) == CERT_X509)
- {
- x509_t *x509 = (x509_t*)cert;
-
- if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
- {
- enumerator_t *enumerator, *block_enum;
- traffic_selector_t *ts, *block_ts;
-
- DBG1(DBG_IKE, "checking certificate-based traffic selector "
- "constraints [RFC 3779]");
- enumerator = other_ts->create_enumerator(other_ts);
- while (enumerator->enumerate(enumerator, &ts))
- {
- bool contained = FALSE;
-
- block_enum = x509->create_ipAddrBlock_enumerator(x509);
- while (block_enum->enumerate(block_enum, &block_ts))
- {
- if (ts->is_contained_in(ts, block_ts))
- {
- DBG1(DBG_IKE, " TS %R is contained in address block"
- " constraint %R", ts, block_ts);
- contained = TRUE;
- break;
- }
- }
- block_enum->destroy(block_enum);
-
- if (!contained)
- {
- DBG1(DBG_IKE, " TS %R is not contained in any"
- " address block constraint", ts);
- enumerator->destroy(enumerator);
- return FAILED;
- }
- }
- enumerator->destroy(enumerator);
- }
- }
- }
-
this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
this->child_sa->set_mode(this->child_sa, this->mode);
@@ -529,8 +489,8 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
return NOT_FOUND;
}
- charon->bus->child_keys(charon->bus, this->child_sa, this->dh,
- nonce_i, nonce_r);
+ charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
+ this->dh, nonce_i, nonce_r);
/* add to IKE_SA, and remove from task */
this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
@@ -848,6 +808,17 @@ static status_t build_i(private_child_create_t *this, message_t *message)
add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
}
+ if (message->get_exchange_type(message) == IKE_AUTH)
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_PRE_NOAUTH, this->tsi, this->tsr);
+ }
+ else
+ {
+ charon->bus->narrow(charon->bus, this->child_sa,
+ NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr);
+ }
+
build_payloads(this, message);
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
@@ -914,7 +885,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
peer_cfg_t *peer_cfg;
payload_t *payload;
enumerator_t *enumerator;
- bool no_dh = TRUE;
+ bool no_dh = TRUE, ike_auth = FALSE;
switch (message->get_exchange_type(message))
{
@@ -934,6 +905,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
{ /* wait until all authentication round completed */
return NEED_MORE;
}
+ ike_auth = TRUE;
default:
break;
}
@@ -1016,7 +988,7 @@ static status_t build_r(private_child_create_t *this, message_t *message)
}
}
- switch (select_and_install(this, no_dh))
+ switch (select_and_install(this, no_dh, ike_auth))
{
case SUCCESS:
break;
@@ -1064,7 +1036,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
{
enumerator_t *enumerator;
payload_t *payload;
- bool no_dh = TRUE;
+ bool no_dh = TRUE, ike_auth = FALSE;
switch (message->get_exchange_type(message))
{
@@ -1079,6 +1051,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
{ /* wait until all authentication round completed */
return NEED_MORE;
}
+ ike_auth = TRUE;
default:
break;
}
@@ -1159,7 +1132,7 @@ static status_t process_i(private_child_create_t *this, message_t *message)
return SUCCESS;
}
- if (select_and_install(this, no_dh) == SUCCESS)
+ if (select_and_install(this, no_dh, ike_auth) == SUCCESS)
{
DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
"with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
@@ -1229,11 +1202,11 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa)
{
chunk_free(&this->my_nonce);
chunk_free(&this->other_nonce);
- if (this->tsi)
+ if (this->tsr)
{
this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
}
- if (this->tsr)
+ if (this->tsi)
{
this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
}
diff --git a/src/libcharon/sa/tasks/child_delete.c b/src/libcharon/sa/tasks/child_delete.c
index d7c6b0541..b0cd30e1e 100644
--- a/src/libcharon/sa/tasks/child_delete.c
+++ b/src/libcharon/sa/tasks/child_delete.c
@@ -191,6 +191,7 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
child_cfg_t *child_cfg;
protocol_id_t protocol;
u_int32_t spi;
+ action_t action;
status_t status = SUCCESS;
iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
@@ -205,10 +206,11 @@ static status_t destroy_and_reestablish(private_child_delete_t *this)
protocol = child_sa->get_protocol(child_sa);
child_cfg = child_sa->get_config(child_sa);
child_cfg->get_ref(child_cfg);
+ action = child_sa->get_close_action(child_sa);
this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
if (this->check_delete_action)
{ /* enforce child_cfg policy if deleted passively */
- switch (child_cfg->get_close_action(child_cfg))
+ switch (action)
{
case ACTION_RESTART:
child_cfg->get_ref(child_cfg);
diff --git a/src/libcharon/sa/tasks/child_rekey.c b/src/libcharon/sa/tasks/child_rekey.c
index b5e4e84b4..fb3452efd 100644
--- a/src/libcharon/sa/tasks/child_rekey.c
+++ b/src/libcharon/sa/tasks/child_rekey.c
@@ -215,6 +215,64 @@ static status_t build_r(private_child_rekey_t *this, message_t *message)
}
/**
+ * Handle a rekey collision
+ */
+static child_sa_t *handle_collision(private_child_rekey_t *this)
+{
+ child_sa_t *to_delete;
+
+ if (this->collision->get_type(this->collision) == CHILD_REKEY)
+ {
+ chunk_t this_nonce, other_nonce;
+ private_child_rekey_t *other = (private_child_rekey_t*)this->collision;
+
+ this_nonce = this->child_create->get_lower_nonce(this->child_create);
+ other_nonce = other->child_create->get_lower_nonce(other->child_create);
+
+ /* if we have the lower nonce, delete rekeyed SA. If not, delete
+ * the redundant. */
+ if (memcmp(this_nonce.ptr, other_nonce.ptr,
+ min(this_nonce.len, other_nonce.len)) < 0)
+ {
+ child_sa_t *child_sa;
+
+ DBG1(DBG_IKE, "CHILD_SA rekey collision won, "
+ "deleting rekeyed child");
+ to_delete = this->child_sa;
+ /* disable close action for the redundand child */
+ child_sa = other->child_create->get_child(other->child_create);
+ child_sa->set_close_action(child_sa, ACTION_NONE);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey collision lost, "
+ "deleting redundant child");
+ to_delete = this->child_create->get_child(this->child_create);
+ }
+ }
+ else
+ { /* CHILD_DELETE */
+ child_delete_t *del = (child_delete_t*)this->collision;
+
+ /* we didn't had a chance to compare the nonces, so we delete
+ * the CHILD_SA the other is not deleting. */
+ if (del->get_child(del) != this->child_sa)
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, "
+ "deleting rekeyed child");
+ to_delete = this->child_sa;
+ }
+ else
+ {
+ DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, "
+ "deleting redundant child");
+ to_delete = this->child_create->get_child(this->child_create);
+ }
+ }
+ return to_delete;
+}
+
+/**
* Implementation of task_t.process for initiator
*/
static status_t process_i(private_child_rekey_t *this, message_t *message)
@@ -263,35 +321,14 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
return SUCCESS;
}
- to_delete = this->child_sa;
-
/* check for rekey collisions */
- if (this->collision &&
- this->collision->get_type(this->collision) == CHILD_REKEY)
+ if (this->collision)
{
- chunk_t this_nonce, other_nonce;
- private_child_rekey_t *other = (private_child_rekey_t*)this->collision;
-
- this_nonce = this->child_create->get_lower_nonce(this->child_create);
- other_nonce = other->child_create->get_lower_nonce(other->child_create);
-
- /* if we have the lower nonce, delete rekeyed SA. If not, delete
- * the redundant. */
- if (memcmp(this_nonce.ptr, other_nonce.ptr,
- min(this_nonce.len, other_nonce.len)) < 0)
- {
- DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting rekeyed child");
- }
- else
- {
- DBG1(DBG_IKE, "CHILD_SA rekey collision lost, deleting redundant child");
- to_delete = this->child_create->get_child(this->child_create);
- if (to_delete == NULL)
- {
- /* ooops, should not happen, fallback */
- to_delete = this->child_sa;
- }
- }
+ to_delete = handle_collision(this);
+ }
+ else
+ {
+ to_delete = this->child_sa;
}
if (to_delete != this->child_create->get_child(this->child_create))
@@ -300,6 +337,10 @@ static status_t process_i(private_child_rekey_t *this, message_t *message)
this->child_create->get_child(this->child_create));
}
+ if (to_delete == NULL)
+ {
+ return SUCCESS;
+ }
spi = to_delete->get_spi(to_delete, TRUE);
protocol = to_delete->get_protocol(to_delete);
diff --git a/src/libcharon/sa/tasks/ike_auth.c b/src/libcharon/sa/tasks/ike_auth.c
index a07f96767..a954782f2 100644
--- a/src/libcharon/sa/tasks/ike_auth.c
+++ b/src/libcharon/sa/tasks/ike_auth.c
@@ -518,6 +518,7 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
(uintptr_t)cand->get(cand, AUTH_RULE_EAP_TYPE) == EAP_NAK &&
(uintptr_t)cand->get(cand, AUTH_RULE_EAP_VENDOR) == 0))
{ /* peer requested EAP, but current config does not match */
+ DBG1(DBG_IKE, "peer requested EAP, config inacceptable");
this->peer_cfg->destroy(this->peer_cfg);
this->peer_cfg = NULL;
if (!update_cfg_candidates(this, FALSE))
@@ -527,7 +528,16 @@ static status_t process_r(private_ike_auth_t *this, message_t *message)
}
cand = get_auth_cfg(this, FALSE);
}
- cfg->merge(cfg, cand, TRUE);
+ /* copy over the EAP specific rules for authentication */
+ cfg->add(cfg, AUTH_RULE_EAP_TYPE,
+ cand->get(cand, AUTH_RULE_EAP_TYPE));
+ cfg->add(cfg, AUTH_RULE_EAP_VENDOR,
+ cand->get(cand, AUTH_RULE_EAP_VENDOR));
+ id = (identification_t*)cand->get(cand, AUTH_RULE_EAP_IDENTITY);
+ if (id)
+ {
+ cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, id->clone(id));
+ }
}
/* verify authentication data */
diff --git a/src/libcharon/sa/tasks/ike_cert_post.c b/src/libcharon/sa/tasks/ike_cert_post.c
index c831df975..cc810a49a 100644
--- a/src/libcharon/sa/tasks/ike_cert_post.c
+++ b/src/libcharon/sa/tasks/ike_cert_post.c
@@ -72,14 +72,18 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
return cert_payload_create_from_cert(cert);
}
- encoded = cert->get_encoding(cert);
+ if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
+ {
+ DBG1(DBG_IKE, "encoding certificate for cert payload failed");
+ hasher->destroy(hasher);
+ return NULL;
+ }
hasher->allocate_hash(hasher, encoded, &hash);
chunk_free(&encoded);
hasher->destroy(hasher);
id = identification_create_from_encoding(ID_KEY_ID, hash);
- enumerator = charon->credentials->create_cdp_enumerator(charon->credentials,
- CERT_X509, id);
+ enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr, CERT_X509, id);
if (enumerator->enumerate(enumerator, &url))
{
payload = cert_payload_create_from_hash_and_url(hash, url);
diff --git a/src/libcharon/sa/tasks/ike_cert_pre.c b/src/libcharon/sa/tasks/ike_cert_pre.c
index 0805d0290..1c0c54727 100644
--- a/src/libcharon/sa/tasks/ike_cert_pre.c
+++ b/src/libcharon/sa/tasks/ike_cert_pre.c
@@ -93,8 +93,8 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message)
certificate_t *cert;
id = identification_create_from_encoding(ID_KEY_ID, keyid);
- cert = charon->credentials->get_cert(charon->credentials,
- CERT_X509, KEY_ANY, id, TRUE);
+ cert = lib->credmgr->get_cert(lib->credmgr,
+ CERT_X509, KEY_ANY, id, TRUE);
if (cert)
{
DBG1(DBG_IKE, "received cert request for \"%Y\"",
@@ -156,8 +156,8 @@ static certificate_t *try_get_cert(cert_payload_t *cert_payload)
break;
}
id = identification_create_from_encoding(ID_KEY_ID, hash);
- cert = charon->credentials->get_cert(charon->credentials,
- CERT_X509, KEY_ANY, id, FALSE);
+ cert = lib->credmgr->get_cert(lib->credmgr,
+ CERT_X509, KEY_ANY, id, FALSE);
id->destroy(id);
break;
}
@@ -299,7 +299,7 @@ static void add_certreq(certreq_payload_t **req, certificate_t *cert)
{
*req = certreq_payload_create_type(CERT_X509);
}
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
+ if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
{
(*req)->add_keyid(*req, keyid);
DBG1(DBG_IKE, "sending cert request for \"%Y\"",
@@ -370,8 +370,8 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message)
if (!req)
{
/* otherwise add all trusted CA certificates */
- enumerator = charon->credentials->create_cert_enumerator(
- charon->credentials, CERT_ANY, KEY_ANY, NULL, TRUE);
+ enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+ CERT_ANY, KEY_ANY, NULL, TRUE);
while (enumerator->enumerate(enumerator, &cert))
{
add_certreq(&req, cert);
diff --git a/src/libcharon/sa/tasks/ike_config.c b/src/libcharon/sa/tasks/ike_config.c
index 58bcf0762..c92b5bca5 100644
--- a/src/libcharon/sa/tasks/ike_config.c
+++ b/src/libcharon/sa/tasks/ike_config.c
@@ -333,7 +333,7 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
chunk_empty);
return SUCCESS;
}
- DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip);
+ DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id);
this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
cp = cp_payload_create_type(CFG_REPLY);
@@ -342,7 +342,7 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
/* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator(
- hydra->attributes, id, vip);
+ hydra->attributes, config->get_pool(config), id, vip);
while (enumerator->enumerate(enumerator, &type, &value))
{
if (!cp)
diff --git a/src/libcharon/sa/tasks/ike_init.c b/src/libcharon/sa/tasks/ike_init.c
index 5eb33b540..38fb572f4 100644
--- a/src/libcharon/sa/tasks/ike_init.c
+++ b/src/libcharon/sa/tasks/ike_init.c
@@ -543,6 +543,7 @@ static void migrate(private_ike_init_t *this, ike_sa_t *ike_sa)
chunk_free(&this->other_nonce);
this->ike_sa = ike_sa;
+ this->keymat = ike_sa->get_keymat(ike_sa);
this->proposal = NULL;
DESTROY_IF(this->dh);
this->dh = this->keymat->create_dh(this->keymat, this->dh_group);