diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2009-02-28 22:02:31 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2009-02-28 22:02:31 +0000 |
commit | 19364e11c66714324bd3d5d0dc9212db397085cb (patch) | |
tree | fe7f5e55f0474dad1d0c29ba7c0a6f4546c99c3a /src/charon/sa/tasks | |
parent | c7f1b0530b85bc7654e68992f25ed8ced5d0a80d (diff) | |
download | vyos-strongswan-19364e11c66714324bd3d5d0dc9212db397085cb.tar.gz vyos-strongswan-19364e11c66714324bd3d5d0dc9212db397085cb.zip |
[svn-upgrade] Integrating new upstream version, strongswan (4.2.12)
Diffstat (limited to 'src/charon/sa/tasks')
-rw-r--r-- | src/charon/sa/tasks/child_create.c | 242 | ||||
-rw-r--r-- | src/charon/sa/tasks/child_delete.c | 36 | ||||
-rw-r--r-- | src/charon/sa/tasks/child_delete.h | 8 | ||||
-rw-r--r-- | src/charon/sa/tasks/child_rekey.c | 112 | ||||
-rw-r--r-- | src/charon/sa/tasks/child_rekey.h | 8 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_auth.c | 76 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_config.c | 106 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_init.c | 69 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_mobike.c | 21 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_rekey.c | 48 |
10 files changed, 483 insertions, 243 deletions
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c index 767ceef55..f6043979f 100644 --- a/src/charon/sa/tasks/child_create.c +++ b/src/charon/sa/tasks/child_create.c @@ -14,7 +14,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: child_create.c 4618 2008-11-11 09:22:00Z tobias $ + * $Id: child_create.c 4860 2009-02-11 13:09:52Z martin $ */ #include "child_create.h" @@ -117,7 +117,22 @@ struct private_child_create_t { ipcomp_transform_t ipcomp_received; /** - * Other Compression Parameter Index (CPI) + * Own allocated SPI + */ + u_int32_t my_spi; + + /** + * SPI received in proposal + */ + u_int32_t other_spi; + + /** + * Own allocated Compression Parameter Index (CPI) + */ + u_int16_t my_cpi; + + /** + * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED */ u_int16_t other_cpi; @@ -189,6 +204,36 @@ static bool ts_list_is_host(linked_list_t *list, host_t *host) } /** + * Allocate SPIs and update proposals + */ +static bool allocate_spi(private_child_create_t *this) +{ + enumerator_t *enumerator; + proposal_t *proposal; + + /* TODO: allocate additional SPI for AH if we have such proposals */ + this->my_spi = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP); + if (this->my_spi) + { + if (this->initiator) + { + enumerator = this->proposals->create_enumerator(this->proposals); + while (enumerator->enumerate(enumerator, &proposal)) + { + proposal->set_spi(proposal, this->my_spi); + } + enumerator->destroy(enumerator); + } + else + { + this->proposal->set_spi(this->proposal, this->my_spi); + } + return TRUE; + } + return FALSE; +} + +/** * Install a CHILD_SA for usage, return value: * - FAILED: no acceptable proposal * - INVALID_ARG: diffie hellman group inacceptable @@ -197,7 +242,9 @@ static bool ts_list_is_host(linked_list_t *list, host_t *host) static status_t select_and_install(private_child_create_t *this, bool no_dh) { status_t status; - chunk_t nonce_i, nonce_r, encr_i, integ_i, encr_r, integ_r; + 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; linked_list_t *my_ts, *other_ts; host_t *me, *other, *other_vip, *my_vip; @@ -216,7 +263,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) other = this->ike_sa->get_other_host(this->ike_sa); my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE); - + this->proposal = this->config->select_proposal(this->config, this->proposals, no_dh); if (this->proposal == NULL) @@ -224,6 +271,14 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) DBG1(DBG_IKE, "no acceptable proposal found"); return FAILED; } + this->other_spi = this->proposal->get_spi(this->proposal); + + if (!this->initiator && !allocate_spi(this)) + { /* responder has no SPI allocated yet */ + DBG1(DBG_IKE, "allocating SPI failed"); + return FAILED; + } + this->child_sa->set_proposal(this->child_sa, this->proposal); if (!this->proposal->has_dh_group(this->proposal, this->dh_group)) { @@ -328,26 +383,33 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) } 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); + this->child_sa->set_protocol(this->child_sa, + this->proposal->get_protocol(this->proposal)); - if (this->ipcomp != IPCOMP_NONE) + if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE) { - this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp, - this->other_cpi); + this->my_cpi = this->other_cpi = 0; + this->ipcomp = IPCOMP_NONE; } - status = FAILED; if (this->keymat->derive_child_keys(this->keymat, this->proposal, this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r)) { if (this->initiator) { - status = this->child_sa->update(this->child_sa, this->proposal, - this->mode, integ_r, integ_i, encr_r, encr_i); + status = this->child_sa->install(this->child_sa, encr_r, integ_r, + this->my_spi, this->my_cpi, TRUE); + status = this->child_sa->install(this->child_sa, encr_i, integ_i, + this->other_spi, this->other_cpi, FALSE); } else { - status = this->child_sa->add(this->child_sa, this->proposal, - this->mode, integ_i, integ_r, encr_i, encr_r); + status = this->child_sa->install(this->child_sa, encr_i, integ_i, + this->my_spi, this->my_cpi, TRUE); + status = this->child_sa->install(this->child_sa, encr_r, integ_r, + this->other_spi, this->other_cpi, FALSE); } } chunk_clear(&integ_i); @@ -361,8 +423,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) return FAILED; } - status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts, - this->mode, this->proposal->get_protocol(this->proposal)); + status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts); if (status != SUCCESS) { DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel"); @@ -436,33 +497,71 @@ static void build_payloads(private_child_create_t *this, message_t *message) } /** - * Adds an IPCOMP_SUPPORTED notify to the message, if possible + * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI */ -static void build_ipcomp_supported_notify(private_child_create_t *this, - message_t *message) +static void add_ipcomp_notify(private_child_create_t *this, + message_t *message, u_int8_t ipcomp) { - u_int16_t cpi; - u_int8_t tid; - if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) { DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, " "IPComp disabled"); - this->ipcomp = IPCOMP_NONE; return; } - cpi = this->child_sa->allocate_cpi(this->child_sa); - tid = this->ipcomp; - if (cpi) + this->my_cpi = this->child_sa->alloc_cpi(this->child_sa); + if (this->my_cpi) { - message->add_notify(message, FALSE, IPCOMP_SUPPORTED, - chunk_cata("cc", chunk_from_thing(cpi), chunk_from_thing(tid))); + this->ipcomp = ipcomp; + message->add_notify(message, FALSE, IPCOMP_SUPPORTED, + chunk_cata("cc", chunk_from_thing(this->my_cpi), + chunk_from_thing(ipcomp))); } else { DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled"); - this->ipcomp = IPCOMP_NONE; + } +} + +/** + * handle a received notify payload + */ +static void handle_notify(private_child_create_t *this, notify_payload_t *notify) +{ + switch (notify->get_notify_type(notify)) + { + case USE_TRANSPORT_MODE: + this->mode = MODE_TRANSPORT; + break; + case USE_BEET_MODE: + this->mode = MODE_BEET; + break; + case IPCOMP_SUPPORTED: + { + ipcomp_transform_t ipcomp; + u_int16_t cpi; + chunk_t data; + + data = notify->get_notification_data(notify); + cpi = *(u_int16_t*)data.ptr; + ipcomp = (ipcomp_transform_t)(*(data.ptr + 2)); + switch (ipcomp) + { + case IPCOMP_DEFLATE: + this->other_cpi = cpi; + this->ipcomp_received = ipcomp; + break; + case IPCOMP_LZS: + case IPCOMP_LZJH: + default: + DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a " + "transform ID we don't support %N", + ipcomp_transform_names, ipcomp); + break; + } + } + default: + break; } } @@ -476,7 +575,6 @@ static void process_payloads(private_child_create_t *this, message_t *message) sa_payload_t *sa_payload; ke_payload_t *ke_payload; ts_payload_t *ts_payload; - notify_payload_t *notify_payload; /* defaults to TUNNEL mode */ this->mode = MODE_TUNNEL; @@ -512,37 +610,7 @@ static void process_payloads(private_child_create_t *this, message_t *message) this->tsr = ts_payload->get_traffic_selectors(ts_payload); break; case NOTIFY: - notify_payload = (notify_payload_t*)payload; - switch (notify_payload ->get_notify_type(notify_payload )) - { - case USE_TRANSPORT_MODE: - this->mode = MODE_TRANSPORT; - break; - case USE_BEET_MODE: - this->mode = MODE_BEET; - break; - case IPCOMP_SUPPORTED: - { - chunk_t data = notify_payload->get_notification_data(notify_payload); - u_int16_t cpi = *(u_int16_t*)data.ptr; - ipcomp_transform_t ipcomp = (ipcomp_transform_t)(*(data.ptr + 2)); - switch(ipcomp) - { - case IPCOMP_DEFLATE: - this->other_cpi = cpi; - this->ipcomp_received = ipcomp; - break; - case IPCOMP_LZS: - case IPCOMP_LZJH: - default: - DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a transform" - " ID we don't support %N", ipcomp_transform_names, ipcomp); - break; - } - } - default: - break; - } + handle_notify(this, (notify_payload_t*)payload); break; default: break; @@ -557,9 +625,8 @@ static void process_payloads(private_child_create_t *this, message_t *message) static status_t build_i(private_child_create_t *this, message_t *message) { host_t *me, *other, *vip; - bool propose_all = FALSE; peer_cfg_t *peer_cfg; - + switch (message->get_exchange_type(message)) { case IKE_SA_INIT: @@ -610,23 +677,18 @@ static status_t build_i(private_child_create_t *this, message_t *message) } /* check if we want a virtual IP, but don't have one */ - if (!this->reqid) + peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); + vip = peer_cfg->get_virtual_ip(peer_cfg); + if (!this->reqid && vip) { - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - vip = peer_cfg->get_virtual_ip(peer_cfg); - if (vip) - { - propose_all = TRUE; - } - } - - if (propose_all) - { /* propose a 0.0.0.0/0 subnet when we use virtual ip */ + /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */ + vip = host_create_any(vip->get_family(vip)); this->tsi = this->config->get_traffic_selectors(this->config, TRUE, - NULL, NULL); + NULL, vip); + vip->destroy(vip); } else - { /* but shorten a 0.0.0.0/0 subnet for host2host/we already have a vip */ + { /* but narrow it for host2host / if we already have a vip */ this->tsi = this->config->get_traffic_selectors(this->config, TRUE, NULL, me); } @@ -641,7 +703,7 @@ static status_t build_i(private_child_create_t *this, message_t *message) this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid, this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)); - if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS) + if (!allocate_spi(this)) { DBG1(DBG_IKE, "unable to allocate SPIs from kernel"); return FAILED; @@ -652,10 +714,10 @@ static status_t build_i(private_child_create_t *this, message_t *message) this->dh = this->keymat->create_dh(this->keymat, this->dh_group); } - if (this->config->use_ipcomp(this->config)) { + if (this->config->use_ipcomp(this->config)) + { /* IPCOMP_DEFLATE is the only transform we support at the moment */ - this->ipcomp = IPCOMP_DEFLATE; - build_ipcomp_supported_notify(this, message); + add_ipcomp_notify(this, message, IPCOMP_DEFLATE); } build_payloads(this, message); @@ -821,16 +883,17 @@ static status_t build_r(private_child_create_t *this, message_t *message) this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid, this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)); - if (this->config->use_ipcomp(this->config) && - this->ipcomp_received != IPCOMP_NONE) + if (this->ipcomp_received != IPCOMP_NONE) { - this->ipcomp = this->ipcomp_received; - build_ipcomp_supported_notify(this, message); - } - else if (this->ipcomp_received != IPCOMP_NONE) - { - DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring", - notify_type_names, IPCOMP_SUPPORTED); + if (this->config->use_ipcomp(this->config)) + { + add_ipcomp_notify(this, message, this->ipcomp_received); + } + else + { + DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring", + notify_type_names, IPCOMP_SUPPORTED); + } } switch (select_and_install(this, no_dh)) @@ -1052,6 +1115,8 @@ static void migrate(private_child_create_t *this, ike_sa_t *ike_sa) } this->ike_sa = ike_sa; + this->keymat = ike_sa->get_keymat(ike_sa); + this->proposal = NULL; this->proposals = NULL; this->tsi = NULL; this->tsr = NULL; @@ -1137,6 +1202,9 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config) this->mode = MODE_TUNNEL; this->ipcomp = IPCOMP_NONE; this->ipcomp_received = IPCOMP_NONE; + this->my_spi = 0; + this->other_spi = 0; + this->my_cpi = 0; this->other_cpi = 0; this->reqid = 0; this->established = FALSE; diff --git a/src/charon/sa/tasks/child_delete.c b/src/charon/sa/tasks/child_delete.c index cab1d63f0..0fd4a056b 100644 --- a/src/charon/sa/tasks/child_delete.c +++ b/src/charon/sa/tasks/child_delete.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: child_delete.c 4434 2008-10-14 08:52:13Z martin $ + * $Id: child_delete.c 4730 2008-12-01 18:38:28Z martin $ */ #include "child_delete.h" @@ -44,9 +44,19 @@ struct private_child_delete_t { bool initiator; /** - * wheter to enforce delete action policy - */ - bool check_delete_action; + * Protocol of CHILD_SA to delete + */ + protocol_id_t protocol; + + /** + * Inbound SPI of CHILD_SA to delete + */ + u_int32_t spi; + + /** + * wheter to enforce delete action policy + */ + bool check_delete_action; /** * CHILD_SAs which get deleted @@ -238,6 +248,16 @@ static void log_children(private_child_delete_t *this) */ static status_t build_i(private_child_delete_t *this, message_t *message) { + child_sa_t *child_sa; + + child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol, + this->spi, TRUE); + if (!child_sa) + { /* child does not exist anymore */ + return SUCCESS; + } + this->child_sas->insert_last(this->child_sas, child_sa); + log_children(this); build_payloads(this, message); return NEED_MORE; @@ -323,7 +343,8 @@ static void destroy(private_child_delete_t *this) /* * Described in header. */ -child_delete_t *child_delete_create(ike_sa_t *ike_sa, child_sa_t *child_sa) +child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol, + u_int32_t spi) { private_child_delete_t *this = malloc_thing(private_child_delete_t); @@ -335,13 +356,14 @@ child_delete_t *child_delete_create(ike_sa_t *ike_sa, child_sa_t *child_sa) this->ike_sa = ike_sa; this->check_delete_action = FALSE; this->child_sas = linked_list_create(); + this->protocol = protocol; + this->spi = spi; - if (child_sa != NULL) + if (protocol != PROTO_NONE) { this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; this->initiator = TRUE; - this->child_sas->insert_last(this->child_sas, child_sa); } else { diff --git a/src/charon/sa/tasks/child_delete.h b/src/charon/sa/tasks/child_delete.h index c304ea9d8..c5ebec338 100644 --- a/src/charon/sa/tasks/child_delete.h +++ b/src/charon/sa/tasks/child_delete.h @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: child_delete.h 3589 2008-03-13 14:14:44Z martin $ + * $Id: child_delete.h 4730 2008-12-01 18:38:28Z martin $ */ /** @@ -52,9 +52,11 @@ struct child_delete_t { * Create a new child_delete task. * * @param ike_sa IKE_SA this task works for - * @param child_sa CHILD_SA to delete, or NULL as responder + * @param protocol protocol of CHILD_SA to delete, PROTO_NONE as responder + * @param spi inbound SPI of CHILD_SA to delete * @return child_delete task to handle by the task_manager */ -child_delete_t *child_delete_create(ike_sa_t *ike_sa, child_sa_t *child_sa); +child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol, + u_int32_t spi); #endif /* CHILD_DELETE_H_ @} */ diff --git a/src/charon/sa/tasks/child_rekey.c b/src/charon/sa/tasks/child_rekey.c index e50ad33be..0d8cf2db7 100644 --- a/src/charon/sa/tasks/child_rekey.c +++ b/src/charon/sa/tasks/child_rekey.c @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: child_rekey.c 4659 2008-11-14 14:05:47Z martin $ + * $Id: child_rekey.c 4730 2008-12-01 18:38:28Z martin $ */ #include "child_rekey.h" @@ -49,11 +49,26 @@ struct private_child_rekey_t { bool initiator; /** + * Protocol of CHILD_SA to rekey + */ + protocol_id_t protocol; + + /** + * Inbound SPI of CHILD_SA to rekey + */ + u_int32_t spi; + + /** * the CHILD_CREATE task which is reused to simplify rekeying */ child_create_t *child_create; /** + * the CHILD_DELETE task to delete rekeyed CHILD_SA + */ + child_delete_t *child_delete; + + /** * CHILD_SA which gets rekeyed */ child_sa_t *child_sa; @@ -65,6 +80,25 @@ struct private_child_rekey_t { }; /** + * Implementation of task_t.build for initiator, after rekeying + */ +static status_t build_i_delete(private_child_rekey_t *this, message_t *message) +{ + /* update exchange type to INFORMATIONAL for the delete */ + message->set_exchange_type(message, INFORMATIONAL); + + return this->child_delete->task.build(&this->child_delete->task, message); +} + +/** + * Implementation of task_t.process for initiator, after rekeying + */ +static status_t process_i_delete(private_child_rekey_t *this, message_t *message) +{ + return this->child_delete->task.process(&this->child_delete->task, message); +} + +/** * find a child using the REKEY_SA notify */ static void find_child(private_child_rekey_t *this, message_t *message) @@ -104,25 +138,33 @@ static void find_child(private_child_rekey_t *this, message_t *message) * Implementation of task_t.build for initiator */ static status_t build_i(private_child_rekey_t *this, message_t *message) -{ +{ notify_payload_t *notify; - protocol_id_t protocol; - u_int32_t spi, reqid; + u_int32_t reqid; + child_cfg_t *config; + + this->child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol, + this->spi, TRUE); + if (!this->child_sa) + { /* CHILD_SA is gone, unable to rekey */ + return SUCCESS; + } + config = this->child_sa->get_config(this->child_sa); /* we just need the rekey notify ... */ - protocol = this->child_sa->get_protocol(this->child_sa); - spi = this->child_sa->get_spi(this->child_sa, TRUE); - notify = notify_payload_create_from_protocol_and_type(protocol, REKEY_SA); - notify->set_spi(notify, spi); + notify = notify_payload_create_from_protocol_and_type(this->protocol, + REKEY_SA); + notify->set_spi(notify, this->spi); message->add_payload(message, (payload_t*)notify); - + /* ... our CHILD_CREATE task does the hard work for us. */ reqid = this->child_sa->get_reqid(this->child_sa); + this->child_create = child_create_create(this->ike_sa, config); this->child_create->use_reqid(this->child_create, reqid); this->child_create->task.build(&this->child_create->task, message); this->child_sa->set_state(this->child_sa, CHILD_REKEYING); - + return NEED_MORE; } @@ -133,7 +175,7 @@ static status_t process_r(private_child_rekey_t *this, message_t *message) { /* let the CHILD_CREATE task process the message */ this->child_create->task.process(&this->child_create->task, message); - + find_child(this, message); return NEED_MORE; @@ -265,11 +307,13 @@ static status_t process_i(private_child_rekey_t *this, message_t *message) spi = to_delete->get_spi(to_delete, TRUE); protocol = to_delete->get_protocol(to_delete); - if (this->ike_sa->delete_child_sa(this->ike_sa, protocol, spi) != SUCCESS) - { - return FAILED; - } - return SUCCESS; + + /* rekeying done, delete the obsolete CHILD_SA using a subtask */ + this->child_delete = child_delete_create(this->ike_sa, protocol, spi); + this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete; + this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete; + + return NEED_MORE; } /** @@ -319,9 +363,16 @@ static void collide(private_child_rekey_t *this, task_t *other) */ static void migrate(private_child_rekey_t *this, ike_sa_t *ike_sa) { - this->child_create->task.migrate(&this->child_create->task, ike_sa); + if (this->child_create) + { + this->child_create->task.migrate(&this->child_create->task, ike_sa); + } + if (this->child_delete) + { + this->child_delete->task.migrate(&this->child_delete->task, ike_sa); + } DESTROY_IF(this->collision); - + this->ike_sa = ike_sa; this->collision = NULL; } @@ -331,7 +382,14 @@ static void migrate(private_child_rekey_t *this, ike_sa_t *ike_sa) */ static void destroy(private_child_rekey_t *this) { - this->child_create->task.destroy(&this->child_create->task); + if (this->child_create) + { + this->child_create->task.destroy(&this->child_create->task); + } + if (this->child_delete) + { + this->child_delete->task.destroy(&this->child_delete->task); + } DESTROY_IF(this->collision); free(this); } @@ -339,22 +397,21 @@ static void destroy(private_child_rekey_t *this) /* * Described in header. */ -child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, child_sa_t *child_sa) +child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol, + u_int32_t spi) { - child_cfg_t *config; private_child_rekey_t *this = malloc_thing(private_child_rekey_t); - + this->public.collide = (void (*)(child_rekey_t*,task_t*))collide; this->public.task.get_type = (task_type_t(*)(task_t*))get_type; this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; this->public.task.destroy = (void(*)(task_t*))destroy; - if (child_sa != NULL) + if (protocol != PROTO_NONE) { this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; this->public.task.process = (status_t(*)(task_t*,message_t*))process_i; this->initiator = TRUE; - config = child_sa->get_config(child_sa); - this->child_create = child_create_create(ike_sa, config); + this->child_create = NULL; } else { @@ -365,8 +422,11 @@ child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, child_sa_t *child_sa) } this->ike_sa = ike_sa; - this->child_sa = child_sa; + this->child_sa = NULL; + this->protocol = protocol; + this->spi = spi; this->collision = NULL; + this->child_delete = NULL; return &this->public; } diff --git a/src/charon/sa/tasks/child_rekey.h b/src/charon/sa/tasks/child_rekey.h index b386ef3c6..37b61a9ef 100644 --- a/src/charon/sa/tasks/child_rekey.h +++ b/src/charon/sa/tasks/child_rekey.h @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: child_rekey.h 3589 2008-03-13 14:14:44Z martin $ + * $Id: child_rekey.h 4730 2008-12-01 18:38:28Z martin $ */ /** @@ -56,9 +56,11 @@ struct child_rekey_t { * Create a new CHILD_REKEY task. * * @param ike_sa IKE_SA this task works for - * @param child_sa child_sa to rekey, NULL if responder + * @param protocol protocol of CHILD_SA to rekey, PROTO_NONE as responder + * @param spi inbound SPI of CHILD_SA to rekey * @return child_rekey task to handle by the task_manager */ -child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, child_sa_t *child_sa); +child_rekey_t *child_rekey_create(ike_sa_t *ike_sa, protocol_id_t protocol, + u_int32_t spi); #endif /* CHILD_REKEY_H_ @} */ diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c index 5c3f33cbd..93b145755 100644 --- a/src/charon/sa/tasks/ike_auth.c +++ b/src/charon/sa/tasks/ike_auth.c @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details * - * $Id: ike_auth.c 4463 2008-10-20 11:38:16Z martin $ + * $Id: ike_auth.c 4858 2009-02-10 17:21:44Z martin $ */ #include "ike_auth.h" @@ -88,70 +88,6 @@ struct private_ike_auth_t { }; /** - * check uniqueness and delete duplicates - */ -static bool check_uniqueness(private_ike_auth_t *this) -{ - ike_sa_t *duplicate; - unique_policy_t policy; - status_t status = SUCCESS; - peer_cfg_t *peer_cfg; - bool cancel = FALSE; - - peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); - policy = peer_cfg->get_unique_policy(peer_cfg); - if (policy == UNIQUE_NO) - { - return FALSE; - } - duplicate = charon->ike_sa_manager->checkout_duplicate( - charon->ike_sa_manager, this->ike_sa); - if (duplicate) - { - peer_cfg = duplicate->get_peer_cfg(duplicate); - if (peer_cfg && - peer_cfg->equals(peer_cfg, this->ike_sa->get_peer_cfg(this->ike_sa))) - { - switch (duplicate->get_state(duplicate)) - { - case IKE_ESTABLISHED: - case IKE_REKEYING: - switch (policy) - { - case UNIQUE_REPLACE: - DBG1(DBG_IKE, "deleting duplicate IKE_SA due " - "uniqueness policy"); - status = duplicate->delete(duplicate); - break; - case UNIQUE_KEEP: - DBG1(DBG_IKE, "cancelling IKE_SA setup due " - "uniqueness policy"); - cancel = TRUE; - break; - default: - break; - } - break; - default: - break; - } - } - if (status == DESTROY_ME) - { - charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, - duplicate); - } - else - { - charon->ike_sa_manager->checkin(charon->ike_sa_manager, duplicate); - } - } - /* set threads active IKE_SA after checkin */ - charon->bus->set_sa(charon->bus, this->ike_sa); - return cancel; -} - -/** * get the authentication class of a config */ auth_class_t get_auth_class(peer_cfg_t *config) @@ -400,6 +336,12 @@ static status_t build_auth_eap(private_ike_auth_t *this, message_t *message) authenticator_t *auth; auth_payload_t *auth_payload; + if (!this->initiator && !this->peer_authenticated) + { + message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); + return FAILED; + } + auth = (authenticator_t*)this->eap_auth; if (auth->build(auth, this->my_packet->get_data(this->my_packet), this->other_nonce, &auth_payload) != SUCCESS) @@ -681,8 +623,10 @@ static status_t build_r(private_ike_auth_t *this, message_t *message) return FAILED; } - if (check_uniqueness(this)) + if (charon->ike_sa_manager->check_uniqueness(charon->ike_sa_manager, + this->ike_sa)) { + DBG1(DBG_IKE, "cancelling IKE_SA setup due uniqueness policy"); message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); return FAILED; } diff --git a/src/charon/sa/tasks/ike_config.c b/src/charon/sa/tasks/ike_config.c index e89f381d3..b890e93ba 100644 --- a/src/charon/sa/tasks/ike_config.c +++ b/src/charon/sa/tasks/ike_config.c @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: ike_config.c 4129 2008-07-01 06:36:52Z martin $ + * $Id: ike_config.c 4867 2009-02-13 11:57:50Z andreas $ */ #include "ike_config.h" @@ -21,6 +21,9 @@ #include <daemon.h> #include <encoding/payloads/cp_payload.h> +#define DNS_SERVER_MAX 2 +#define NBNS_SERVER_MAX 2 + typedef struct private_ike_config_t private_ike_config_t; /** @@ -52,6 +55,11 @@ struct private_ike_config_t { * list of DNS servers */ linked_list_t *dns; + + /** + * list of WINS servers + */ + linked_list_t *nbns; }; /** @@ -121,7 +129,10 @@ static void build_payloads(private_ike_config_t *this, message_t *message, else { host_t *ip; - iterator_t *iterator = this->dns->create_iterator(this->dns, TRUE); + iterator_t *iterator; + + /* Add internal DNS servers */ + iterator = this->dns->create_iterator(this->dns, TRUE); while (iterator->iterate(iterator, (void**)&ip)) { ca = configuration_attribute_create(); @@ -138,6 +149,25 @@ static void build_payloads(private_ike_config_t *this, message_t *message, cp->add_configuration_attribute(cp, ca); } iterator->destroy(iterator); + + /* Add internal WINS servers */ + iterator = this->nbns->create_iterator(this->nbns, TRUE); + while (iterator->iterate(iterator, (void**)&ip)) + { + ca = configuration_attribute_create(); + if (ip->get_family(ip) == AF_INET) + { + ca->set_type(ca, INTERNAL_IP4_NBNS); + } + else + { + ca->set_type(ca, INTERNAL_IP6_NBNS); + } + chunk = ip->get_address(ip); + ca->set_value(ca, chunk); + cp->add_configuration_attribute(cp, ca); + } + iterator->destroy(iterator); } message->add_payload(message, (payload_t*)cp); } @@ -201,7 +231,22 @@ static void process_attribute(private_ike_config_t *this, } case INTERNAL_IP4_NBNS: case INTERNAL_IP6_NBNS: - /* TODO */ + { + addr = ca->get_value(ca); + if (addr.len == 0) + { + ip = host_create_any(family); + } + else + { + ip = host_create_from_chunk(family, addr, 0); + } + if (ip) + { + this->nbns->insert_last(this->nbns, ip); + } + break; + } default: DBG1(DBG_IKE, "ignoring %N config attribute", configuration_attribute_type_names, @@ -351,7 +396,7 @@ static status_t process_i(private_ike_config_t *this, message_t *message) process_payloads(this, message); if (this->virtual_ip == NULL) - { /* force a configured virtual IP, even server didn't return one */ + { /* force a configured virtual IP, even if server didn't return one */ config = this->ike_sa->get_peer_cfg(this->ike_sa); this->virtual_ip = config->get_virtual_ip(config); if (this->virtual_ip) @@ -406,6 +451,7 @@ static void destroy(private_ike_config_t *this) { DESTROY_IF(this->virtual_ip); this->dns->destroy_offset(this->dns, offsetof(host_t, destroy)); + this->nbns->destroy_offset(this->nbns, offsetof(host_t, destroy)); free(this); } @@ -420,6 +466,12 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator) this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate; this->public.task.destroy = (void(*)(task_t*))destroy; + this->initiator = initiator; + this->ike_sa = ike_sa; + this->virtual_ip = NULL; + this->dns = linked_list_create(); + this->nbns = linked_list_create(); + if (initiator) { this->public.task.build = (status_t(*)(task_t*,message_t*))build_i; @@ -427,13 +479,49 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator) } else { + int i; + + /* assign DNS servers */ + for (i = 1; i <= DNS_SERVER_MAX; i++) + { + char dns_key[16], *dns_str; + + snprintf(dns_key, sizeof(dns_key), "charon.dns%d", i); + dns_str = lib->settings->get_str(lib->settings, dns_key, NULL); + if (dns_str) + { + host_t *dns = host_create_from_string(dns_str, 0); + + if (dns) + { + DBG2(DBG_CFG, "assigning DNS server %H to peer", dns); + this->dns->insert_last(this->dns, dns); + } + } + } + + /* assign WINS servers */ + for (i = 1; i <= NBNS_SERVER_MAX; i++) + { + char nbns_key[16], *nbns_str; + + snprintf(nbns_key, sizeof(nbns_key), "charon.nbns%d", i); + nbns_str = lib->settings->get_str(lib->settings, nbns_key, NULL); + if (nbns_str) + { + host_t *nbns = host_create_from_string(nbns_str, 0); + + if (nbns) + { + DBG2(DBG_CFG, "assigning NBNS server %H to peer", nbns); + this->nbns->insert_last(this->nbns, nbns); + } + } + } + this->public.task.build = (status_t(*)(task_t*,message_t*))build_r; this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; } - this->initiator = initiator; - this->ike_sa = ike_sa; - this->virtual_ip = NULL; - this->dns = linked_list_create(); - + return &this->public; } diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c index bd2cd39bb..139107480 100644 --- a/src/charon/sa/tasks/ike_init.c +++ b/src/charon/sa/tasks/ike_init.c @@ -14,7 +14,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: ike_init.c 4531 2008-10-30 12:58:54Z martin $ + * $Id: ike_init.c 4717 2008-11-28 09:51:44Z martin $ */ #include "ike_init.h" @@ -370,13 +370,46 @@ static status_t process_r(private_ike_init_t *this, message_t *message) } /** - * Implementation of task_t.build for responder + * Derive the keymat for the IKE_SA */ -static status_t build_r(private_ike_init_t *this, message_t *message) +static bool derive_keys(private_ike_init_t *this, + chunk_t nonce_i, chunk_t nonce_r) { - keymat_t *old_keymat = NULL; + keymat_t *old_keymat; + pseudo_random_function_t prf_alg = PRF_UNDEFINED; + chunk_t skd = chunk_empty; ike_sa_id_t *id; + id = this->ike_sa->get_id(this->ike_sa); + if (this->old_sa) + { + /* rekeying: Include old SKd, use old PRF, apply SPI */ + old_keymat = this->old_sa->get_keymat(this->old_sa); + prf_alg = old_keymat->get_skd(old_keymat, &skd); + if (this->initiator) + { + id->set_responder_spi(id, this->proposal->get_spi(this->proposal)); + } + else + { + id->set_initiator_spi(id, this->proposal->get_spi(this->proposal)); + } + } + if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh, + nonce_i, nonce_r, id, prf_alg, skd)) + { + return FALSE; + } + charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, + nonce_i, nonce_r, this->old_sa); + return TRUE; +} + +/** + * Implementation of task_t.build for responder + */ +static status_t build_r(private_ike_init_t *this, message_t *message) +{ /* check if we have everything we need */ if (this->proposal == NULL || this->other_nonce.len == 0 || this->my_nonce.len == 0) @@ -410,23 +443,12 @@ static status_t build_r(private_ike_init_t *this, message_t *message) return FAILED; } - id = this->ike_sa->get_id(this->ike_sa); - if (this->old_sa) - { /* rekeying: Apply SPI, include keymat from old SA in key derivation */ - id->set_initiator_spi(id, this->proposal->get_spi(this->proposal)); - old_keymat = this->old_sa->get_keymat(this->old_sa); - } - if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh, - this->other_nonce, this->my_nonce, id, old_keymat)) + if (!derive_keys(this, this->other_nonce, this->my_nonce)) { DBG1(DBG_IKE, "key derivation failed"); message->add_notify(message, TRUE, NO_PROPOSAL_CHOSEN, chunk_empty); return FAILED; } - - charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, - this->other_nonce, this->my_nonce, this->old_sa); - build_payloads(this, message); return SUCCESS; } @@ -436,8 +458,6 @@ static status_t build_r(private_ike_init_t *this, message_t *message) */ static status_t process_i(private_ike_init_t *this, message_t *message) { - keymat_t *old_keymat = NULL; - ike_sa_id_t *id; iterator_t *iterator; payload_t *payload; @@ -521,22 +541,11 @@ static status_t process_i(private_ike_init_t *this, message_t *message) return FAILED; } - id = this->ike_sa->get_id(this->ike_sa); - if (this->old_sa) - { /* rekeying: Apply SPI, include keymat from old SA in key derivation */ - id->set_responder_spi(id, this->proposal->get_spi(this->proposal)); - old_keymat = this->old_sa->get_keymat(this->old_sa); - } - if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh, - this->my_nonce, this->other_nonce, id, old_keymat)) + if (!derive_keys(this, this->my_nonce, this->other_nonce)) { DBG1(DBG_IKE, "key derivation failed"); return FAILED; } - - charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, - this->my_nonce, this->other_nonce, this->old_sa); - return SUCCESS; } diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c index a791d1892..b5e065081 100644 --- a/src/charon/sa/tasks/ike_mobike.c +++ b/src/charon/sa/tasks/ike_mobike.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: ike_mobike.c 4618 2008-11-11 09:22:00Z tobias $ + * $Id: ike_mobike.c 4816 2008-12-19 14:34:40Z martin $ */ #include "ike_mobike.h" @@ -24,6 +24,7 @@ #include <encoding/payloads/notify_payload.h> #define COOKIE2_SIZE 16 +#define MAX_ADDITIONAL_ADDRS 8 typedef struct private_ike_mobike_t private_ike_mobike_t; @@ -191,8 +192,8 @@ static void build_address_list(private_ike_mobike_t *this, message_t *message) enumerator_t *enumerator; host_t *host, *me; notify_type_t type; - bool additional = FALSE; - + int added = 0; + me = this->ike_sa->get_my_host(this->ike_sa); enumerator = charon->kernel_interface->create_address_enumerator( charon->kernel_interface, FALSE, FALSE); @@ -214,9 +215,13 @@ static void build_address_list(private_ike_mobike_t *this, message_t *message) continue; } message->add_notify(message, FALSE, type, host->get_address(host)); - additional = TRUE; + if (++added >= MAX_ADDITIONAL_ADDRS) + { /* limit number of notifys, some implementations do not like too + * many of them (f.e. strongSwan ;-) */ + break; + } } - if (!additional) + if (!added) { message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty); } @@ -251,7 +256,7 @@ static void update_children(private_ike_mobike_t *this) iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa); while (iterator->iterate(iterator, (void**)&child_sa)) { - if (child_sa->update_hosts(child_sa, + if (child_sa->update(child_sa, this->ike_sa->get_my_host(this->ike_sa), this->ike_sa->get_other_host(this->ike_sa), this->ike_sa->get_virtual_ip(this->ike_sa, TRUE), @@ -516,6 +521,10 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) /* start the update with the same task */ this->check = FALSE; this->address = FALSE; + if (this->natd) + { + this->natd->task.destroy(&this->natd->task); + } this->natd = ike_natd_create(this->ike_sa, this->initiator); this->ike_sa->set_pending_updates(this->ike_sa, 1); return NEED_MORE; diff --git a/src/charon/sa/tasks/ike_rekey.c b/src/charon/sa/tasks/ike_rekey.c index 28d63cca7..e61d161bc 100644 --- a/src/charon/sa/tasks/ike_rekey.c +++ b/src/charon/sa/tasks/ike_rekey.c @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: ike_rekey.c 4659 2008-11-14 14:05:47Z martin $ + * $Id: ike_rekey.c 4730 2008-12-01 18:38:28Z martin $ */ #include "ike_rekey.h" @@ -21,6 +21,7 @@ #include <daemon.h> #include <encoding/payloads/notify_payload.h> #include <sa/tasks/ike_init.h> +#include <sa/tasks/ike_delete.h> #include <processing/jobs/delete_ike_sa_job.h> #include <processing/jobs/rekey_ike_sa_job.h> @@ -58,12 +59,36 @@ struct private_ike_rekey_t { ike_init_t *ike_init; /** + * IKE_DELETE task to delete the old IKE_SA after rekeying was successful + */ + ike_delete_t *ike_delete; + + /** * colliding task detected by the task manager */ task_t *collision; }; /** + * Implementation of task_t.build for initiator, after rekeying + */ +static status_t build_i_delete(private_ike_rekey_t *this, message_t *message) +{ + /* update exchange type to INFORMATIONAL for the delete */ + message->set_exchange_type(message, INFORMATIONAL); + + return this->ike_delete->task.build(&this->ike_delete->task, message); +} + +/** + * Implementation of task_t.process for initiator, after rekeying + */ +static status_t process_i_delete(private_ike_rekey_t *this, message_t *message) +{ + return this->ike_delete->task.process(&this->ike_delete->task, message); +} + +/** * Implementation of task_t.build for initiator */ static status_t build_i(private_ike_rekey_t *this, message_t *message) @@ -168,7 +193,6 @@ static status_t build_r(private_ike_rekey_t *this, message_t *message) */ static status_t process_i(private_ike_rekey_t *this, message_t *message) { - job_t *job; ike_sa_id_t *to_delete; iterator_t *iterator; payload_t *payload; @@ -271,10 +295,12 @@ static status_t process_i(private_ike_rekey_t *this, message_t *message) charon->bus->set_sa(charon->bus, this->ike_sa); } - job = (job_t*)delete_ike_sa_job_create(to_delete, TRUE); - charon->processor->queue_job(charon->processor, job); + /* rekeying successful, delete the IKE_SA using a subtask */ + this->ike_delete = ike_delete_create(this->ike_sa, TRUE); + this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_delete; + this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_delete; - return SUCCESS; + return NEED_MORE; } /** @@ -300,6 +326,10 @@ static void migrate(private_ike_rekey_t *this, ike_sa_t *ike_sa) { this->ike_init->task.destroy(&this->ike_init->task); } + if (this->ike_delete) + { + this->ike_delete->task.destroy(&this->ike_delete->task); + } if (this->new_sa) { charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, @@ -308,11 +338,12 @@ static void migrate(private_ike_rekey_t *this, ike_sa_t *ike_sa) charon->bus->set_sa(charon->bus, this->ike_sa); } DESTROY_IF(this->collision); - + this->collision = NULL; this->ike_sa = ike_sa; this->new_sa = NULL; this->ike_init = NULL; + this->ike_delete = NULL; } /** @@ -339,6 +370,10 @@ static void destroy(private_ike_rekey_t *this) { this->ike_init->task.destroy(&this->ike_init->task); } + if (this->ike_delete) + { + this->ike_delete->task.destroy(&this->ike_delete->task); + } DESTROY_IF(this->collision); free(this); } @@ -368,6 +403,7 @@ ike_rekey_t *ike_rekey_create(ike_sa_t *ike_sa, bool initiator) this->ike_sa = ike_sa; this->new_sa = NULL; this->ike_init = NULL; + this->ike_delete = NULL; this->initiator = initiator; this->collision = NULL; |