diff options
Diffstat (limited to 'src/charon/sa/tasks/child_create.c')
-rw-r--r-- | src/charon/sa/tasks/child_create.c | 223 |
1 files changed, 106 insertions, 117 deletions
diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c index bddca621b..767ceef55 100644 --- a/src/charon/sa/tasks/child_create.c +++ b/src/charon/sa/tasks/child_create.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 Tobias Brunner - * Copyright (C) 2005-2007 Martin Willi + * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -14,7 +14,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: child_create.c 4358 2008-09-25 13:56:23Z tobias $ + * $Id: child_create.c 4618 2008-11-11 09:22:00Z tobias $ */ #include "child_create.h" @@ -97,6 +97,11 @@ struct private_child_create_t { diffie_hellman_group_t dh_group; /** + * IKE_SAs keymat + */ + keymat_t *keymat; + + /** * mode the new CHILD_SA uses (transport/tunnel/beet) */ ipsec_mode_t mode; @@ -191,38 +196,22 @@ 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) { - prf_plus_t *prf_plus; status_t status; - chunk_t nonce_i, nonce_r, secret, seed; + chunk_t nonce_i, nonce_r, encr_i, integ_i, encr_r, integ_r; linked_list_t *my_ts, *other_ts; host_t *me, *other, *other_vip, *my_vip; if (this->proposals == NULL) { - SIG_CHD(UP_FAILED, this->child_sa, "SA payload missing in message"); + DBG1(DBG_IKE, "SA payload missing in message"); return FAILED; } if (this->tsi == NULL || this->tsr == NULL) { - SIG_CHD(UP_FAILED, this->child_sa, "TS payloads missing in message"); + DBG1(DBG_IKE, "TS payloads missing in message"); return NOT_FOUND; } - if (this->initiator) - { - nonce_i = this->my_nonce; - nonce_r = this->other_nonce; - my_ts = this->tsi; - other_ts = this->tsr; - } - else - { - nonce_r = this->my_nonce; - nonce_i = this->other_nonce; - my_ts = this->tsr; - other_ts = this->tsi; - } - me = this->ike_sa->get_my_host(this->ike_sa); other = this->ike_sa->get_other_host(this->ike_sa); my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); @@ -232,7 +221,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) no_dh); if (this->proposal == NULL) { - SIG_CHD(UP_FAILED, this->child_sa, "no acceptable proposal found"); + DBG1(DBG_IKE, "no acceptable proposal found"); return FAILED; } @@ -243,15 +232,15 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, &group, NULL)) { - SIG_CHD(UP_FAILED, this->child_sa, "DH group %N inacceptable, " - "requesting %N", diffie_hellman_group_names, this->dh_group, - diffie_hellman_group_names, group); + DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N", + diffie_hellman_group_names, this->dh_group, + diffie_hellman_group_names, group); this->dh_group = group; return INVALID_ARG; } else { - SIG_CHD(UP_FAILED, this->child_sa, "no acceptable proposal found"); + DBG1(DBG_IKE, "no acceptable proposal found"); return FAILED; } } @@ -260,16 +249,25 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) { my_vip = me; } - else if (this->initiator) - { - /* to setup firewall rules correctly, CHILD_SA needs the virtual IP */ - this->child_sa->set_virtual_ip(this->child_sa, my_vip); - } if (other_vip == NULL) { other_vip = other; } + if (this->initiator) + { + nonce_i = this->my_nonce; + nonce_r = this->other_nonce; + my_ts = this->tsi; + other_ts = this->tsr; + } + else + { + nonce_r = this->my_nonce; + nonce_i = this->other_nonce; + my_ts = this->tsr; + other_ts = this->tsi; + } my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts, my_vip); other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts, @@ -279,7 +277,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) { my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy)); - SIG_CHD(UP_FAILED, this->child_sa, "no acceptable traffic selectors found"); + DBG1(DBG_IKE, "no acceptable traffic selectors found"); return NOT_FOUND; } @@ -302,16 +300,18 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) switch (this->mode) { case MODE_TRANSPORT: - if (!ts_list_is_host(this->tsi, other) || - !ts_list_is_host(this->tsr, me)) + if (!this->config->use_proxy_mode(this->config) && + (!ts_list_is_host(this->tsi, other) || + !ts_list_is_host(this->tsr, me)) + ) { this->mode = MODE_TUNNEL; - DBG1(DBG_IKE, "not using tranport mode, not host-to-host"); + DBG1(DBG_IKE, "not using transport mode, not host-to-host"); } else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) { this->mode = MODE_TUNNEL; - DBG1(DBG_IKE, "not using tranport mode, connection NATed"); + DBG1(DBG_IKE, "not using transport mode, connection NATed"); } break; case MODE_BEET: @@ -327,55 +327,51 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) } } - if (this->dh) + this->child_sa->set_state(this->child_sa, CHILD_INSTALLING); + + if (this->ipcomp != IPCOMP_NONE) { - if (this->dh->get_shared_secret(this->dh, &secret) != SUCCESS) - { - SIG_CHD(UP_FAILED, this->child_sa, "DH exchange incomplete"); - return FAILED; - } - DBG3(DBG_IKE, "DH secret %B", &secret); - seed = chunk_cata("mcc", secret, nonce_i, nonce_r); + this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp, + this->other_cpi); } - else + + 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)) { - seed = chunk_cata("cc", nonce_i, nonce_r); + if (this->initiator) + { + status = this->child_sa->update(this->child_sa, this->proposal, + this->mode, integ_r, integ_i, encr_r, encr_i); + } + else + { + status = this->child_sa->add(this->child_sa, this->proposal, + this->mode, integ_i, integ_r, encr_i, encr_r); + } } + chunk_clear(&integ_i); + chunk_clear(&integ_r); + chunk_clear(&encr_i); + chunk_clear(&encr_r); - if (this->ipcomp != IPCOMP_NONE) + if (status != SUCCESS) { - this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp, - this->other_cpi); + DBG1(DBG_IKE, "unable to install IPsec SA (SAD) in kernel"); + return FAILED; } status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts, this->mode, this->proposal->get_protocol(this->proposal)); if (status != SUCCESS) { - SIG_CHD(UP_FAILED, this->child_sa, - "unable to install IPsec policies (SPD) in kernel"); + DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel"); return NOT_FOUND; } - prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); - if (this->initiator) - { - status = this->child_sa->update(this->child_sa, this->proposal, - this->mode, prf_plus); - } - else - { - status = this->child_sa->add(this->child_sa, this->proposal, - this->mode, prf_plus); - } - prf_plus->destroy(prf_plus); + charon->bus->child_keys(charon->bus, this->child_sa, this->dh, + nonce_i, nonce_r); - if (status != SUCCESS) - { - SIG_CHD(UP_FAILED, this->child_sa, - "unable to install IPsec SA (SAD) in kernel"); - return FAILED; - } /* add to IKE_SA, and remove from task */ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); @@ -499,7 +495,7 @@ static void process_payloads(private_child_create_t *this, message_t *message) if (!this->initiator) { this->dh_group = ke_payload->get_dh_group_number(ke_payload); - this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group); + this->dh = this->keymat->create_dh(this->keymat, this->dh_group); } if (this->dh) { @@ -592,13 +588,13 @@ static status_t build_i(private_child_create_t *this, message_t *message) if (this->reqid) { - SIG_CHD(UP_START, NULL, "establishing CHILD_SA %s{%d}", - this->config->get_name(this->config), this->reqid); + DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}", + this->config->get_name(this->config), this->reqid); } else { - SIG_CHD(UP_START, NULL, "establishing CHILD_SA %s", - this->config->get_name(this->config)); + DBG0(DBG_IKE, "establishing CHILD_SA %s", + this->config->get_name(this->config)); } /* reuse virtual IP if we already have one */ @@ -641,23 +637,19 @@ static status_t build_i(private_child_create_t *this, message_t *message) this->dh_group == MODP_NONE); this->mode = this->config->get_mode(this->config); - this->child_sa = child_sa_create( - this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid, + this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), + 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) { - SIG_CHD(UP_FAILED, this->child_sa, - "unable to allocate SPIs from kernel"); + DBG1(DBG_IKE, "unable to allocate SPIs from kernel"); return FAILED; } if (this->dh_group != MODP_NONE) { - this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group); + this->dh = this->keymat->create_dh(this->keymat, this->dh_group); } if (this->config->use_ipcomp(this->config)) { @@ -679,7 +671,7 @@ static status_t build_i(private_child_create_t *this, message_t *message) } /** - * Implementation of task_t.process for initiator + * Implementation of task_t.process for responder */ static status_t process_r(private_child_create_t *this, message_t *message) { @@ -785,16 +777,15 @@ static status_t build_r(private_child_create_t *this, message_t *message) if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING) { - SIG_CHD(UP_FAILED, NULL, - "unable to create CHILD_SA while rekeying IKE_SA"); + DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA"); message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty); return SUCCESS; } if (this->config == NULL) { - SIG_CHD(UP_FAILED, NULL, "traffic selectors %#R=== %#R inacceptable", - this->tsr, this->tsi); + DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable", + this->tsr, this->tsi); message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty); handle_child_sa_failure(this, message); return SUCCESS; @@ -813,8 +804,8 @@ static status_t build_r(private_child_create_t *this, message_t *message) case INTERNAL_ADDRESS_FAILURE: case FAILED_CP_REQUIRED: { - SIG_CHD(UP_FAILED, NULL, "configuration payload negotation " - "failed, no CHILD_SA built"); + DBG1(DBG_IKE,"configuration payload negotation " + "failed, no CHILD_SA built"); iterator->destroy(iterator); handle_child_sa_failure(this, message); return SUCCESS; @@ -826,11 +817,8 @@ static status_t build_r(private_child_create_t *this, message_t *message) } iterator->destroy(iterator); - this->child_sa = child_sa_create( - this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid, + this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), + 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) && @@ -870,14 +858,14 @@ static status_t build_r(private_child_create_t *this, message_t *message) build_payloads(this, message); - SIG_CHD(UP_SUCCESS, this->child_sa, "CHILD_SA %s{%d} established " - "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", - this->child_sa->get_name(this->child_sa), - this->child_sa->get_reqid(this->child_sa), - ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), - ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), - this->child_sa->get_traffic_selectors(this->child_sa, TRUE), - this->child_sa->get_traffic_selectors(this->child_sa, FALSE)); + DBG0(DBG_IKE, "CHILD_SA %s{%d} established " + "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", + this->child_sa->get_name(this->child_sa), + this->child_sa->get_reqid(this->child_sa), + ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), + ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), + this->child_sa->get_traffic_selectors(this->child_sa, TRUE), + this->child_sa->get_traffic_selectors(this->child_sa, FALSE)); return SUCCESS; } @@ -929,8 +917,8 @@ static status_t process_i(private_child_create_t *this, message_t *message) case TS_UNACCEPTABLE: case INVALID_SELECTORS: { - SIG_CHD(UP_FAILED, this->child_sa, "received %N notify, " - "no CHILD_SA built", notify_type_names, type); + DBG1(DBG_IKE, "received %N notify, no CHILD_SA built", + notify_type_names, type); iterator->destroy(iterator); handle_child_sa_failure(this, message); /* an error in CHILD_SA creation is not critical */ @@ -963,35 +951,35 @@ static status_t process_i(private_child_create_t *this, message_t *message) if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE) { - SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify" - " but we did not send one previously, no CHILD_SA built"); + DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting" + " one, no CHILD_SA built"); handle_child_sa_failure(this, message); return SUCCESS; } else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE) { DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, " - "IPComp is disabled"); + "IPComp is disabled"); this->ipcomp = IPCOMP_NONE; } else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received) { - SIG_CHD(UP_FAILED, this->child_sa, "received an IPCOMP_SUPPORTED notify" - " for a transform we did not propose, no CHILD_SA built"); + DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, " + "no CHILD_SA built"); handle_child_sa_failure(this, message); return SUCCESS; } if (select_and_install(this, no_dh) == SUCCESS) { - SIG_CHD(UP_SUCCESS, this->child_sa, "CHILD_SA %s{%d} established " - "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", - this->child_sa->get_name(this->child_sa), - this->child_sa->get_reqid(this->child_sa), - ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), - ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), - this->child_sa->get_traffic_selectors(this->child_sa, TRUE), - this->child_sa->get_traffic_selectors(this->child_sa, FALSE)); + DBG0(DBG_IKE, "CHILD_SA %s{%d} established " + "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", + this->child_sa->get_name(this->child_sa), + this->child_sa->get_reqid(this->child_sa), + ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), + ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), + this->child_sa->get_traffic_selectors(this->child_sa, TRUE), + this->child_sa->get_traffic_selectors(this->child_sa, FALSE)); } else { @@ -1144,6 +1132,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config) this->tsr = NULL; this->dh = NULL; this->dh_group = MODP_NONE; + this->keymat = ike_sa->get_keymat(ike_sa); this->child_sa = NULL; this->mode = MODE_TUNNEL; this->ipcomp = IPCOMP_NONE; |