From: Martin Willi Date: Thu, 7 Jan 2010 14:51:30 +0000 (+0100) Subject: Support EAP-only authentication for mutual and key deriving EAP methods X-Git-Tag: 4.3.6~42 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f34702ff3fa3461597b3bb44a7cc734592f13fb4;p=thirdparty%2Fstrongswan.git Support EAP-only authentication for mutual and key deriving EAP methods --- diff --git a/src/charon/sa/authenticators/authenticator.h b/src/charon/sa/authenticators/authenticator.h index 299b9e6e72..fff91ed349 100644 --- a/src/charon/sa/authenticators/authenticator.h +++ b/src/charon/sa/authenticators/authenticator.h @@ -127,6 +127,16 @@ struct authenticator_t { */ status_t (*build)(authenticator_t *this, message_t *message); + /** + * Check if the authenticator is capable of mutual authentication. + * + * Some authenticator authenticate both peers, e.g. EAP. To support + * mutual authentication with only a single authenticator (EAP-only + * authentication), it must be mutual. This method is invoked in ike_auth + * to check if the given authenticator is capable of doing so. + */ + bool (*is_mutual)(authenticator_t *this); + /** * Destroy authenticator instance. */ diff --git a/src/charon/sa/authenticators/eap_authenticator.c b/src/charon/sa/authenticators/eap_authenticator.c index 922a95f5d5..16911050a2 100644 --- a/src/charon/sa/authenticators/eap_authenticator.c +++ b/src/charon/sa/authenticators/eap_authenticator.c @@ -72,6 +72,11 @@ struct private_eap_authenticator_t { */ bool eap_complete; + /** + * Set if we require mutual EAP due EAP-only authentication + */ + bool require_mutual; + /** * authentication payload verified successfully */ @@ -526,6 +531,15 @@ static status_t process_client(private_eap_authenticator_t *this, { return FAILED; } + if (this->require_mutual && !this->method->is_mutual(this->method)) + { /* we require mutual authentication due to EAP-only */ + u_int32_t vendor; + + DBG1(DBG_IKE, "EAP-only authentication requires a mutual and " + "MSK deriving EAP method, but %N is not", + eap_type_names, this->method->get_type(this->method, &vendor)); + return FAILED; + } return SUCCESS; } @@ -607,6 +621,16 @@ static status_t build_client(private_eap_authenticator_t *this, return NEED_MORE; } +/** + * Implementation of authenticator_t.is_mutual. + */ +static bool is_mutual(private_eap_authenticator_t *this) +{ + /* we don't know yet, but insist on it after EAP is complete */ + this->require_mutual = TRUE; + return TRUE; +} + /** * Implementation of authenticator_t.destroy. */ @@ -630,6 +654,7 @@ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa, this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build_client; this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process_client; + this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))is_mutual; this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy; this->ike_sa = ike_sa; @@ -643,6 +668,7 @@ eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa, this->eap_complete = FALSE; this->auth_complete = FALSE; this->eap_identity = NULL; + this->require_mutual = FALSE; return &this->public; } @@ -658,6 +684,7 @@ eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa, this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *messageh))build_server; this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process_server; + this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))is_mutual; this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy; this->ike_sa = ike_sa; @@ -671,6 +698,7 @@ eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa, this->eap_complete = FALSE; this->auth_complete = FALSE; this->eap_identity = NULL; + this->require_mutual = FALSE; return &this->public; } diff --git a/src/charon/sa/authenticators/psk_authenticator.c b/src/charon/sa/authenticators/psk_authenticator.c index 83a4b22726..67197d6902 100644 --- a/src/charon/sa/authenticators/psk_authenticator.c +++ b/src/charon/sa/authenticators/psk_authenticator.c @@ -169,6 +169,7 @@ psk_authenticator_t *psk_authenticator_create_builder(ike_sa_t *ike_sa, this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build; this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed; + this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false; this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy; this->ike_sa = ike_sa; @@ -188,6 +189,7 @@ psk_authenticator_t *psk_authenticator_create_verifier(ike_sa_t *ike_sa, this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *messageh))return_failed; this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process; + this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false; this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy; this->ike_sa = ike_sa; diff --git a/src/charon/sa/authenticators/pubkey_authenticator.c b/src/charon/sa/authenticators/pubkey_authenticator.c index 7e558db616..f1dca27027 100644 --- a/src/charon/sa/authenticators/pubkey_authenticator.c +++ b/src/charon/sa/authenticators/pubkey_authenticator.c @@ -234,6 +234,7 @@ pubkey_authenticator_t *pubkey_authenticator_create_builder(ike_sa_t *ike_sa, this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))build; this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))return_failed; + this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false; this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy; this->ike_sa = ike_sa; @@ -253,6 +254,7 @@ pubkey_authenticator_t *pubkey_authenticator_create_verifier(ike_sa_t *ike_sa, this->public.authenticator.build = (status_t(*)(authenticator_t*, message_t *message))return_failed; this->public.authenticator.process = (status_t(*)(authenticator_t*, message_t *message))process; + this->public.authenticator.is_mutual = (bool(*)(authenticator_t*))return_false; this->public.authenticator.destroy = (void(*)(authenticator_t*))destroy; this->ike_sa = ike_sa; diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c index 0e81d2bea9..fb79cb20fc 100644 --- a/src/charon/sa/tasks/ike_auth.c +++ b/src/charon/sa/tasks/ike_auth.c @@ -650,15 +650,31 @@ static status_t build_r(private_ike_auth_t *this, message_t *message) id_payload = id_payload_create_from_identification(ID_RESPONDER, id); message->add_payload(message, (payload_t*)id_payload); - /* build authentication data */ - this->my_auth = authenticator_create_builder(this->ike_sa, cfg, - this->other_nonce, this->my_nonce, - this->other_packet->get_data(this->other_packet), - this->my_packet->get_data(this->my_packet)); - if (!this->my_auth) + if ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS) == AUTH_CLASS_EAP) + { /* EAP-only authentication */ + if (!this->ike_sa->supports_extension(this->ike_sa, + EXT_EAP_ONLY_AUTHENTICATION)) + { + DBG1(DBG_IKE, "configured EAP-only authentication, but peer " + "does not support it"); + message->add_notify(message, TRUE, AUTHENTICATION_FAILED, + chunk_empty); + return FAILED; + } + } + else { - message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); - return FAILED; + /* build authentication data */ + this->my_auth = authenticator_create_builder(this->ike_sa, cfg, + this->other_nonce, this->my_nonce, + this->other_packet->get_data(this->other_packet), + this->my_packet->get_data(this->my_packet)); + if (!this->my_auth) + { + message->add_notify(message, TRUE, AUTHENTICATION_FAILED, + chunk_empty); + return FAILED; + } } } @@ -837,13 +853,6 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) id_payload_t *id_payload; identification_t *id; - /* responder is not allowed to do EAP */ - if (!message->get_payload(message, AUTHENTICATION)) - { - DBG1(DBG_IKE, "AUTH payload missing"); - return FAILED; - } - /* handle IDr payload */ id_payload = (id_payload_t*)message->get_payload(message, ID_RESPONDER); @@ -857,31 +866,45 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id)); - /* verify authentication data */ - this->other_auth = authenticator_create_verifier(this->ike_sa, - message, this->other_nonce, this->my_nonce, - this->other_packet->get_data(this->other_packet), - this->my_packet->get_data(this->my_packet)); - if (!this->other_auth) + if (message->get_payload(message, AUTHENTICATION)) { - return FAILED; + /* verify authentication data */ + this->other_auth = authenticator_create_verifier(this->ike_sa, + message, this->other_nonce, this->my_nonce, + this->other_packet->get_data(this->other_packet), + this->my_packet->get_data(this->my_packet)); + if (!this->other_auth) + { + return FAILED; + } + } + else + { /* responder omited AUTH payload, indicating EAP-only */ + if (!this->my_auth || + !this->my_auth->is_mutual(this->my_auth)) + { + return FAILED; + } } } - switch (this->other_auth->process(this->other_auth, message)) + if (this->other_auth) { - case SUCCESS: - break; - case NEED_MORE: - return NEED_MORE; - default: - return FAILED; + switch (this->other_auth->process(this->other_auth, message)) + { + case SUCCESS: + break; + case NEED_MORE: + return NEED_MORE; + default: + return FAILED; + } + this->other_auth->destroy(this->other_auth); + this->other_auth = NULL; } /* 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); - this->other_auth->destroy(this->other_auth); - this->other_auth = NULL; /* another auth round done, invoke authorize hook */ if (!charon->bus->authorize(charon->bus, FALSE))