diff options
Diffstat (limited to 'src/libcharon/sa/ikev2')
-rw-r--r-- | src/libcharon/sa/ikev2/authenticators/eap_authenticator.c | 10 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/task_manager_v2.c | 17 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_create.c | 9 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_delete.c | 4 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_rekey.c | 37 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_auth.c | 68 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_dpd.c | 10 |
7 files changed, 105 insertions, 50 deletions
diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c index aa0644033..b8359cc88 100644 --- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c +++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c @@ -667,6 +667,16 @@ METHOD(authenticator_t, build_client, status_t, METHOD(authenticator_t, is_mutual, bool, private_eap_authenticator_t *this) { + if (this->method) + { + u_int32_t vendor; + + if (this->method->get_type(this->method, &vendor) != EAP_IDENTITY || + vendor != 0) + { + return this->method->is_mutual(this->method); + } + } /* we don't know yet, but insist on it after EAP is complete */ this->require_mutual = TRUE; return TRUE; diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index ea0117c54..5298abf79 100644 --- a/src/libcharon/sa/ikev2/task_manager_v2.c +++ b/src/libcharon/sa/ikev2/task_manager_v2.c @@ -475,6 +475,7 @@ METHOD(task_manager_t, initiate, status_t, break; case FAILED: default: + this->initiating.type = EXCHANGE_TYPE_UNDEFINED; if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING) { charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); @@ -1123,6 +1124,18 @@ METHOD(task_manager_t, process_message, status_t, { if (mid == this->responding.mid) { + /* reject initial messages once established */ + if (msg->get_exchange_type(msg) == IKE_SA_INIT || + msg->get_exchange_type(msg) == IKE_AUTH) + { + if (this->ike_sa->get_state(this->ike_sa) != IKE_CREATED && + this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING) + { + DBG1(DBG_IKE, "ignoring %N in established IKE_SA state", + exchange_type_names, msg->get_exchange_type(msg)); + return FAILED; + } + } if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED || this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING || msg->get_exchange_type(msg) != IKE_SA_INIT) @@ -1163,6 +1176,10 @@ METHOD(task_manager_t, process_message, status_t, { DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored", mid, this->responding.mid); + if (msg->get_exchange_type(msg) == IKE_SA_INIT) + { /* clean up IKE_SA state if IKE_SA_INIT has invalid msg ID */ + return DESTROY_ME; + } } } else diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index eb3972c29..32c0e8c4a 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -18,6 +18,7 @@ #include "child_create.h" #include <daemon.h> +#include <hydra.h> #include <sa/ikev2/keymat_v2.h> #include <crypto/diffie_hellman.h> #include <credentials/certificates/x509.h> @@ -615,6 +616,7 @@ static void build_payloads(private_child_create_t *this, message_t *message) nonce_payload_t *nonce_payload; ke_payload_t *ke_payload; ts_payload_t *ts_payload; + kernel_feature_t features; /* add SA payload */ if (this->initiator) @@ -661,6 +663,13 @@ static void build_payloads(private_child_create_t *this, message_t *message) default: break; } + + features = hydra->kernel_interface->get_features(hydra->kernel_interface); + if (!(features & KERNEL_ESP_V3_TFC)) + { + message->add_notify(message, FALSE, ESP_TFC_PADDING_NOT_SUPPORTED, + chunk_empty); + } } /** diff --git a/src/libcharon/sa/ikev2/tasks/child_delete.c b/src/libcharon/sa/ikev2/tasks/child_delete.c index 644af782c..8652942ad 100644 --- a/src/libcharon/sa/ikev2/tasks/child_delete.c +++ b/src/libcharon/sa/ikev2/tasks/child_delete.c @@ -264,8 +264,8 @@ static void log_children(private_child_delete_t *this) } else { - child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in); - child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out); + child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in, NULL); + child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, NULL); DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs %.8x_i " "(%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R", diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c index f8c2ed141..262cb10e0 100644 --- a/src/libcharon/sa/ikev2/tasks/child_rekey.c +++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c @@ -87,6 +87,24 @@ struct private_child_rekey_t { }; /** + * Schedule a retry if rekeying temporary failed + */ +static void schedule_delayed_rekey(private_child_rekey_t *this) +{ + u_int32_t retry; + job_t *job; + + retry = RETRY_INTERVAL - (random() % RETRY_JITTER); + job = (job_t*)rekey_child_sa_job_create( + this->child_sa->get_reqid(this->child_sa), + this->child_sa->get_protocol(this->child_sa), + this->child_sa->get_spi(this->child_sa, TRUE)); + DBG1(DBG_IKE, "CHILD_SA rekeying failed, trying again in %d seconds", retry); + this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); + lib->scheduler->schedule_job(lib->scheduler, job, retry); +} + +/** * Implementation of task_t.build for initiator, after rekeying */ static status_t build_i_delete(private_child_rekey_t *this, message_t *message) @@ -166,8 +184,13 @@ METHOD(task_t, build_i, status_t, } reqid = this->child_sa->get_reqid(this->child_sa); this->child_create->use_reqid(this->child_create, reqid); - this->child_create->task.build(&this->child_create->task, message); + if (this->child_create->task.build(&this->child_create->task, + message) != NEED_MORE) + { + schedule_delayed_rekey(this); + return FAILED; + } this->child_sa->set_state(this->child_sa, CHILD_REKEYING); return NEED_MORE; @@ -316,17 +339,7 @@ METHOD(task_t, process_i, status_t, if (!(this->collision && this->collision->get_type(this->collision) == TASK_CHILD_DELETE)) { - job_t *job; - u_int32_t retry = RETRY_INTERVAL - (random() % RETRY_JITTER); - - job = (job_t*)rekey_child_sa_job_create( - this->child_sa->get_reqid(this->child_sa), - this->child_sa->get_protocol(this->child_sa), - this->child_sa->get_spi(this->child_sa, TRUE)); - DBG1(DBG_IKE, "CHILD_SA rekeying failed, " - "trying again in %d seconds", retry); - this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); - lib->scheduler->schedule_job(lib->scheduler, job, retry); + schedule_delayed_rekey(this); } return SUCCESS; } diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c index 70efcd7af..942f97cf5 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_auth.c +++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c @@ -223,6 +223,18 @@ static auth_cfg_t *get_auth_cfg(private_ike_auth_t *this, bool local) } /** + * Move the currently active auth config to the auth configs completed + */ +static void apply_auth_cfg(private_ike_auth_t *this, bool local) +{ + auth_cfg_t *cfg; + + cfg = auth_cfg_create(); + cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, local), local); + this->ike_sa->add_auth_cfg(this->ike_sa, local, cfg); +} + +/** * Check if we have should initiate another authentication round */ static bool do_another_auth(private_ike_auth_t *this) @@ -307,7 +319,7 @@ static bool update_cfg_candidates(private_ike_auth_t *this, bool strict) { if (this->peer_cfg) { - bool complies = TRUE; + char *comply_error = NULL; enumerator_t *e1, *e2, *tmp; auth_cfg_t *c1, *c2; @@ -324,22 +336,30 @@ static bool update_cfg_candidates(private_ike_auth_t *this, bool strict) while (e1->enumerate(e1, &c1)) { /* check if done authentications comply to configured ones */ - if ((!e2->enumerate(e2, &c2)) || - (!strict && !c1->complies(c1, c2, TRUE)) || - (strict && !c2->complies(c2, c1, TRUE))) + if (!e2->enumerate(e2, &c2)) + { + comply_error = "insufficient authentication rounds"; + break; + } + if (!strict && !c1->complies(c1, c2, TRUE)) { - complies = FALSE; + comply_error = "non-matching authentication done"; + break; + } + if (strict && !c2->complies(c2, c1, TRUE)) + { + comply_error = "constraint checking failed"; break; } } e1->destroy(e1); e2->destroy(e2); - if (complies) + if (!comply_error) { break; } - DBG1(DBG_CFG, "selected peer config '%s' inacceptable", - this->peer_cfg->get_name(this->peer_cfg)); + DBG1(DBG_CFG, "selected peer config '%s' inacceptable: %s", + this->peer_cfg->get_name(this->peer_cfg), comply_error); this->peer_cfg->destroy(this->peer_cfg); } if (this->candidates->remove_first(this->candidates, @@ -464,10 +484,7 @@ METHOD(task_t, build_i, status_t, switch (this->my_auth->build(this->my_auth, message)) { case SUCCESS: - /* authentication step complete, reset authenticator */ - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE), TRUE); - this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg); + apply_auth_cfg(this, TRUE); this->my_auth->destroy(this->my_auth); this->my_auth = NULL; break; @@ -640,10 +657,7 @@ METHOD(task_t, process_r, status_t, return NEED_MORE; } - /* store authentication information */ - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE); - this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg); + apply_auth_cfg(this, FALSE); if (!update_cfg_candidates(this, FALSE)) { @@ -778,10 +792,7 @@ METHOD(task_t, build_r, status_t, switch (this->my_auth->build(this->my_auth, message)) { case SUCCESS: - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE), - TRUE); - this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg); + apply_auth_cfg(this, TRUE); this->my_auth->destroy(this->my_auth); this->my_auth = NULL; break; @@ -969,10 +980,10 @@ METHOD(task_t, process_i, status_t, goto peer_auth_failed; } - /* store authentication information, reset authenticator */ - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE); - this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg); + if (!mutual_eap) + { + apply_auth_cfg(this, FALSE); + } } if (this->my_auth) @@ -980,10 +991,11 @@ METHOD(task_t, process_i, status_t, switch (this->my_auth->process(this->my_auth, message)) { case SUCCESS: - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE), - TRUE); - this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg); + apply_auth_cfg(this, TRUE); + if (this->my_auth->is_mutual(this->my_auth)) + { + apply_auth_cfg(this, FALSE); + } this->my_auth->destroy(this->my_auth); this->my_auth = NULL; this->do_another_auth = do_another_auth(this); diff --git a/src/libcharon/sa/ikev2/tasks/ike_dpd.c b/src/libcharon/sa/ikev2/tasks/ike_dpd.c index 28ccc2efe..7a33f7938 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_dpd.c +++ b/src/libcharon/sa/ikev2/tasks/ike_dpd.c @@ -37,12 +37,6 @@ METHOD(task_t, return_need_more, status_t, return NEED_MORE; } -METHOD(task_t, return_success, status_t, - private_ike_dpd_t *this, message_t *message) -{ - return SUCCESS; -} - METHOD(task_t, get_type, task_type_t, private_ike_dpd_t *this) { @@ -82,11 +76,11 @@ ike_dpd_t *ike_dpd_create(bool initiator) if (initiator) { this->public.task.build = _return_need_more; - this->public.task.process = _return_success; + this->public.task.process = (void*)return_success; } else { - this->public.task.build = _return_success; + this->public.task.build = (void*)return_success; this->public.task.process = _return_need_more; } |