Allow clients to request a configured EAP method via EAP-Nak
authorTobias Brunner <tobias@strongswan.org>
Tue, 21 Aug 2012 15:11:14 +0000 (17:11 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 31 Aug 2012 09:40:27 +0000 (11:40 +0200)
src/libcharon/encoding/payloads/eap_payload.c
src/libcharon/encoding/payloads/eap_payload.h
src/libcharon/plugins/eap_peap/eap_peap_peer.c
src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
src/libcharon/sa/ikev2/authenticators/eap_authenticator.c

index 4420f28..15a9972 100644 (file)
@@ -336,7 +336,8 @@ static void write_type(bio_writer_t *writer, eap_type_t type, u_int32_t vendor,
 /*
  * Described in header
  */
-eap_payload_t *eap_payload_create_nak(u_int8_t identifier, bool expanded)
+eap_payload_t *eap_payload_create_nak(u_int8_t identifier, eap_type_t type,
+                                                                         u_int32_t vendor, bool expanded)
 {
        enumerator_t *enumerator;
        eap_type_t reg_type;
@@ -356,6 +357,11 @@ eap_payload_t *eap_payload_create_nak(u_int8_t identifier, bool expanded)
        enumerator = charon->eap->create_enumerator(charon->eap, EAP_PEER);
        while (enumerator->enumerate(enumerator, &reg_type, &reg_vendor))
        {
+               if ((type && type != reg_type) ||
+                       (type && vendor && vendor != reg_vendor))
+               {       /* the preferred type is only sent if we actually find it */
+                       continue;
+               }
                if (!reg_vendor || expanded)
                {
                        write_type(writer, reg_type, reg_vendor, expanded);
index ad8c57d..d3c3fae 100644 (file)
@@ -127,10 +127,13 @@ eap_payload_t *eap_payload_create_code(eap_code_t code, u_int8_t identifier);
  * Creates an eap_payload_t EAP_RESPONSE containing an EAP_NAK.
  *
  * @param identifier   EAP identifier to use in payload
+ * @param type                 preferred auth type, 0 to send all supported types
+ * @param vendor               vendor identifier for auth type, 0 for default
  * @param expanded             TRUE to send an expanded Nak (as response to an expanded
  *                                             request, i.e. one with vendor specific type)
  * @return                             eap_payload_t object
  */
-eap_payload_t *eap_payload_create_nak(u_int8_t identifier, bool expanded);
+eap_payload_t *eap_payload_create_nak(u_int8_t identifier, eap_type_t type,
+                                                                         u_int32_t vendor, bool expanded);
 
 #endif /** EAP_PAYLOAD_H_ @}*/
index 96d4d0f..5e19726 100644 (file)
@@ -151,7 +151,7 @@ METHOD(tls_application_t, process, status_t,
                if (!this->ph2_method)
                {
                        DBG1(DBG_IKE, "EAP method not supported");
-                       this->out = eap_payload_create_nak(in->get_identifier(in),
+                       this->out = eap_payload_create_nak(in->get_identifier(in), 0, 0,
                                                                                           received_vendor != 0);
                        in->destroy(in);
                        return NEED_MORE;
index 59366b4..811fe05 100644 (file)
@@ -192,7 +192,7 @@ METHOD(tls_application_t, process, status_t,
                if (!this->method)
                {
                        DBG1(DBG_IKE, "EAP method not supported");
-                       this->out = eap_payload_create_nak(in->get_identifier(in),
+                       this->out = eap_payload_create_nak(in->get_identifier(in), 0, 0,
                                                                                           received_vendor != 0);
                        in->destroy(in);
                        return NEED_MORE;
index 7cc8625..c9178d0 100644 (file)
@@ -336,8 +336,8 @@ static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
 static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
                                                                                 eap_payload_t *in)
 {
-       eap_type_t type;
-       u_int32_t vendor;
+       eap_type_t type, conf_type;
+       u_int32_t vendor, conf_vendor;
        auth_cfg_t *auth;
        eap_payload_t *out;
        identification_t *id;
@@ -373,7 +373,7 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
                 * EAP method (types 3-253, 255) */
                DBG1(DBG_IKE, "%N not supported, sending EAP_NAK",
                         eap_type_names, type);
-               return eap_payload_create_nak(in->get_identifier(in), FALSE);
+               return eap_payload_create_nak(in->get_identifier(in), 0, 0, FALSE);
        }
        if (this->method == NULL)
        {
@@ -387,11 +387,31 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
                        DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)",
                                 eap_type_names, type, in->get_identifier(in));
                }
+               auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
+               conf_type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
+               conf_vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
+               if (conf_type != EAP_NAK &&
+                  (conf_type != type || conf_vendor != vendor))
+               {
+                       if (conf_vendor)
+                       {
+                               DBG1(DBG_IKE, "requesting EAP method %d-%d, sending EAP_NAK",
+                                        conf_type, conf_vendor);
+                       }
+                       else
+                       {
+                               DBG1(DBG_IKE, "requesting %N authentication, sending EAP_NAK",
+                                        eap_type_names, conf_type);
+                       }
+                       return eap_payload_create_nak(in->get_identifier(in), conf_type,
+                                                                                 conf_vendor, vendor != 0);
+               }
                this->method = load_method(this, type, vendor, EAP_PEER);
                if (!this->method)
                {
                        DBG1(DBG_IKE, "EAP method not supported, sending EAP_NAK");
-                       return eap_payload_create_nak(in->get_identifier(in), vendor != 0);
+                       return eap_payload_create_nak(in->get_identifier(in), 0, 0,
+                                                                                 vendor != 0);
                }
        }