Support EAP-only authentication for mutual and key deriving EAP methods
This commit is contained in:
@@ -127,6 +127,16 @@ struct authenticator_t {
|
|||||||
*/
|
*/
|
||||||
status_t (*build)(authenticator_t *this, message_t *message);
|
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.
|
* Destroy authenticator instance.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -72,6 +72,11 @@ struct private_eap_authenticator_t {
|
|||||||
*/
|
*/
|
||||||
bool eap_complete;
|
bool eap_complete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if we require mutual EAP due EAP-only authentication
|
||||||
|
*/
|
||||||
|
bool require_mutual;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* authentication payload verified successfully
|
* authentication payload verified successfully
|
||||||
*/
|
*/
|
||||||
@@ -526,6 +531,15 @@ static status_t process_client(private_eap_authenticator_t *this,
|
|||||||
{
|
{
|
||||||
return FAILED;
|
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;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,6 +621,16 @@ static status_t build_client(private_eap_authenticator_t *this,
|
|||||||
return NEED_MORE;
|
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.
|
* 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.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.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->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
|
||||||
|
|
||||||
this->ike_sa = ike_sa;
|
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->eap_complete = FALSE;
|
||||||
this->auth_complete = FALSE;
|
this->auth_complete = FALSE;
|
||||||
this->eap_identity = NULL;
|
this->eap_identity = NULL;
|
||||||
|
this->require_mutual = FALSE;
|
||||||
|
|
||||||
return &this->public;
|
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.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.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->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
|
||||||
|
|
||||||
this->ike_sa = ike_sa;
|
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->eap_complete = FALSE;
|
||||||
this->auth_complete = FALSE;
|
this->auth_complete = FALSE;
|
||||||
this->eap_identity = NULL;
|
this->eap_identity = NULL;
|
||||||
|
this->require_mutual = FALSE;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.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.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->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
|
||||||
|
|
||||||
this->ike_sa = ike_sa;
|
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.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.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->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
|
||||||
|
|
||||||
this->ike_sa = ike_sa;
|
this->ike_sa = ike_sa;
|
||||||
|
|||||||
@@ -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.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.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->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
|
||||||
|
|
||||||
this->ike_sa = ike_sa;
|
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.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.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->public.authenticator.destroy = (void(*)(authenticator_t*))destroy;
|
||||||
|
|
||||||
this->ike_sa = ike_sa;
|
this->ike_sa = ike_sa;
|
||||||
|
|||||||
@@ -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);
|
id_payload = id_payload_create_from_identification(ID_RESPONDER, id);
|
||||||
message->add_payload(message, (payload_t*)id_payload);
|
message->add_payload(message, (payload_t*)id_payload);
|
||||||
|
|
||||||
/* build authentication data */
|
if ((uintptr_t)cfg->get(cfg, AUTH_RULE_AUTH_CLASS) == AUTH_CLASS_EAP)
|
||||||
this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
|
{ /* EAP-only authentication */
|
||||||
this->other_nonce, this->my_nonce,
|
if (!this->ike_sa->supports_extension(this->ike_sa,
|
||||||
this->other_packet->get_data(this->other_packet),
|
EXT_EAP_ONLY_AUTHENTICATION))
|
||||||
this->my_packet->get_data(this->my_packet));
|
{
|
||||||
if (!this->my_auth)
|
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);
|
/* build authentication data */
|
||||||
return FAILED;
|
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;
|
id_payload_t *id_payload;
|
||||||
identification_t *id;
|
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 */
|
/* handle IDr payload */
|
||||||
id_payload = (id_payload_t*)message->get_payload(message,
|
id_payload = (id_payload_t*)message->get_payload(message,
|
||||||
ID_RESPONDER);
|
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 = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
|
||||||
cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
|
cfg->add(cfg, AUTH_RULE_IDENTITY, id->clone(id));
|
||||||
|
|
||||||
/* verify authentication data */
|
if (message->get_payload(message, AUTHENTICATION))
|
||||||
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;
|
/* 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:
|
switch (this->other_auth->process(this->other_auth, message))
|
||||||
break;
|
{
|
||||||
case NEED_MORE:
|
case SUCCESS:
|
||||||
return NEED_MORE;
|
break;
|
||||||
default:
|
case NEED_MORE:
|
||||||
return FAILED;
|
return NEED_MORE;
|
||||||
|
default:
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
this->other_auth->destroy(this->other_auth);
|
||||||
|
this->other_auth = NULL;
|
||||||
}
|
}
|
||||||
/* store authentication information, reset authenticator */
|
/* store authentication information, reset authenticator */
|
||||||
cfg = auth_cfg_create();
|
cfg = auth_cfg_create();
|
||||||
cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE);
|
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->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 */
|
/* another auth round done, invoke authorize hook */
|
||||||
if (!charon->bus->authorize(charon->bus, FALSE))
|
if (!charon->bus->authorize(charon->bus, FALSE))
|
||||||
|
|||||||
Reference in New Issue
Block a user