*/
bool eap_complete;
+ /**
+ * Set if we require mutual EAP due EAP-only authentication
+ */
+ bool require_mutual;
+
/**
* authentication payload verified successfully
*/
{
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 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.
*/
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;
this->eap_complete = FALSE;
this->auth_complete = FALSE;
this->eap_identity = NULL;
+ this->require_mutual = FALSE;
return &this->public;
}
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;
this->eap_complete = FALSE;
this->auth_complete = FALSE;
this->eap_identity = NULL;
+ this->require_mutual = FALSE;
return &this->public;
}
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;
+ }
}
}
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);
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))