diff options
Diffstat (limited to 'src/libcharon/sa/ikev2/tasks/child_create.c')
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_create.c | 84 |
1 files changed, 69 insertions, 15 deletions
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index a1f01c276..6d9132a68 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -105,6 +105,11 @@ struct private_child_create_t { diffie_hellman_t *dh; /** + * Applying DH public value failed? + */ + bool dh_failed; + + /** * group used for DH exchange */ diffie_hellman_group_t dh_group; @@ -160,6 +165,16 @@ struct private_child_create_t { u_int32_t reqid; /** + * Explicit inbound mark value + */ + u_int mark_in; + + /** + * Explicit outbound mark value + */ + u_int mark_out; + + /** * CHILD_SA which gets established */ child_sa_t *child_sa; @@ -286,7 +301,7 @@ static bool allocate_spi(private_child_create_t *this) */ static void schedule_inactivity_timeout(private_child_create_t *this) { - u_int32_t timeout; + u_int32_t timeout, id; bool close_ike; timeout = this->config->get_inactivity(this->config); @@ -294,9 +309,9 @@ static void schedule_inactivity_timeout(private_child_create_t *this) { close_ike = lib->settings->get_bool(lib->settings, "%s.inactivity_close_ike", FALSE, lib->ns); + id = this->child_sa->get_unique_id(this->child_sa); lib->scheduler->schedule_job(lib->scheduler, (job_t*) - inactivity_job_create(this->child_sa->get_reqid(this->child_sa), - timeout, close_ike), timeout); + inactivity_job_create(id, timeout, close_ike), timeout); } } @@ -683,10 +698,7 @@ static status_t select_and_install(private_child_create_t *this, this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); this->established = TRUE; - if (!this->rekey) - { /* a rekeyed SA uses the same reqid, no need for a new job */ - schedule_inactivity_timeout(this); - } + schedule_inactivity_timeout(this); my_ts = linked_list_create_from_enumerator( this->child_sa->create_ts_enumerator(this->child_sa, TRUE)); @@ -696,7 +708,7 @@ static status_t select_and_install(private_child_create_t *this, 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), + this->child_sa->get_unique_id(this->child_sa), ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts); @@ -709,7 +721,7 @@ static status_t select_and_install(private_child_create_t *this, /** * build the payloads for the message */ -static void build_payloads(private_child_create_t *this, message_t *message) +static bool build_payloads(private_child_create_t *this, message_t *message) { sa_payload_t *sa_payload; nonce_payload_t *nonce_payload; @@ -741,6 +753,11 @@ static void build_payloads(private_child_create_t *this, message_t *message) { ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE, this->dh); + if (!ke_payload) + { + DBG1(DBG_IKE, "creating KE payload failed"); + return FALSE; + } message->add_payload(message, (payload_t*)ke_payload); } @@ -769,6 +786,7 @@ static void build_payloads(private_child_create_t *this, message_t *message) message->add_notify(message, FALSE, ESP_TFC_PADDING_NOT_SUPPORTED, chunk_empty); } + return TRUE; } /** @@ -880,7 +898,7 @@ static void process_payloads(private_child_create_t *this, message_t *message) } if (this->dh) { - this->dh->set_other_public_value(this->dh, + this->dh_failed = !this->dh->set_other_public_value(this->dh, ke_payload->get_key_exchange_data(ke_payload)); } break; @@ -996,7 +1014,8 @@ METHOD(task_t, build_i, status_t, 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)); + this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY), + this->mark_in, this->mark_out); if (!allocate_spi(this)) { @@ -1027,7 +1046,10 @@ METHOD(task_t, build_i, status_t, NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr); } - build_payloads(this, message); + if (!build_payloads(this, message)) + { + return FAILED; + } this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy)); this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy)); @@ -1168,12 +1190,19 @@ METHOD(task_t, build_r, status_t, case IKE_SA_INIT: return get_nonce(message, &this->my_nonce); case CREATE_CHILD_SA: - if (generate_nonce(this) != SUCCESS) + if (generate_nonce(this) != SUCCESS ) { message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty); return SUCCESS; } + if (this->dh_failed) + { + DBG1(DBG_IKE, "applying DH public value failed"); + message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, + chunk_empty); + return SUCCESS; + } no_dh = FALSE; break; case IKE_AUTH: @@ -1241,7 +1270,8 @@ METHOD(task_t, build_r, status_t, 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)); + this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY), + this->mark_in, this->mark_out); if (this->ipcomp_received != IPCOMP_NONE) { @@ -1279,7 +1309,12 @@ METHOD(task_t, build_r, status_t, return SUCCESS; } - build_payloads(this, message); + if (!build_payloads(this, message)) + { + message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty); + handle_child_sa_failure(this, message); + return SUCCESS; + } if (!this->rekey) { /* invoke the child_up() hook if we are not rekeying */ @@ -1408,6 +1443,7 @@ METHOD(task_t, process_i, status_t, this->dh_group, diffie_hellman_group_names, group); this->retry = TRUE; this->dh_group = group; + this->child_sa->set_state(this->child_sa, CHILD_RETRYING); this->public.task.migrate(&this->public.task, this->ike_sa); enumerator->destroy(enumerator); return NEED_MORE; @@ -1456,6 +1492,13 @@ METHOD(task_t, process_i, status_t, return delete_failed_sa(this); } + if (this->dh_failed) + { + DBG1(DBG_IKE, "applying DH public value failed"); + handle_child_sa_failure(this, message); + return delete_failed_sa(this); + } + if (select_and_install(this, no_dh, ike_auth) == SUCCESS) { if (!this->rekey) @@ -1477,6 +1520,13 @@ METHOD(child_create_t, use_reqid, void, this->reqid = reqid; } +METHOD(child_create_t, use_marks, void, + private_child_create_t *this, u_int in, u_int out) +{ + this->mark_in = in; + this->mark_out = out; +} + METHOD(child_create_t, get_child, child_sa_t*, private_child_create_t *this) { @@ -1526,6 +1576,7 @@ METHOD(task_t, migrate, void, DESTROY_IF(this->child_sa); DESTROY_IF(this->proposal); DESTROY_IF(this->dh); + this->dh_failed = FALSE; if (this->proposals) { this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy)); @@ -1544,6 +1595,8 @@ METHOD(task_t, migrate, void, this->ipcomp_received = IPCOMP_NONE; this->other_cpi = 0; this->reqid = 0; + this->mark_in = 0; + this->mark_out = 0; this->established = FALSE; } @@ -1592,6 +1645,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, .set_config = _set_config, .get_lower_nonce = _get_lower_nonce, .use_reqid = _use_reqid, + .use_marks = _use_marks, .task = { .get_type = _get_type, .migrate = _migrate, |