Interworking: Allow pre-configuration of EAP parameters
authorJouni Malinen <j@w1.fi>
Thu, 2 Aug 2012 15:40:45 +0000 (18:40 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 2 Aug 2012 15:40:45 +0000 (18:40 +0300)
The new cred block parameters eap, phase1, and phase2 can be used to
select which EAP method is used with network selection instead of using
the value specified in ANQP information (e.g., NAI Realm).

Signed-hostap: Jouni Malinen <j@w1.fi>

wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/interworking.c
wpa_supplicant/wpa_supplicant.conf

index 427242d..9b252e9 100644 (file)
@@ -1798,6 +1798,9 @@ void wpa_config_free_cred(struct wpa_cred *cred)
        os_free(cred->imsi);
        os_free(cred->milenage);
        os_free(cred->domain);
+       os_free(cred->eap_method);
+       os_free(cred->phase1);
+       os_free(cred->phase2);
        os_free(cred);
 }
 
@@ -2251,6 +2254,23 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
                return 0;
        }
 
+       if (os_strcmp(var, "eap") == 0) {
+               struct eap_method_type method;
+               method.method = eap_peer_get_type(value, &method.vendor);
+               if (method.vendor == EAP_VENDOR_IETF &&
+                   method.method == EAP_TYPE_NONE) {
+                       wpa_printf(MSG_ERROR, "Line %d: unknown EAP type '%s' "
+                                  "for a credential", line, value);
+                       return -1;
+               }
+               os_free(cred->eap_method);
+               cred->eap_method = os_malloc(sizeof(*cred->eap_method));
+               if (cred->eap_method == NULL)
+                       return -1;
+               os_memcpy(cred->eap_method, &method, sizeof(method));
+               return 0;
+       }
+
        val = wpa_config_parse_string(value, &len);
        if (val == NULL) {
                wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
@@ -2318,6 +2338,18 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
                return 0;
        }
 
+       if (os_strcmp(var, "phase1") == 0) {
+               os_free(cred->phase1);
+               cred->phase1 = val;
+               return 0;
+       }
+
+       if (os_strcmp(var, "phase2") == 0) {
+               os_free(cred->phase2);
+               cred->phase2 = val;
+               return 0;
+       }
+
        if (line) {
                wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.",
                           line, var);
index 9ae57d0..5db9194 100644 (file)
@@ -148,6 +148,29 @@ struct wpa_cred {
         * whether the AP is operated by the Home SP.
         */
        char *domain;
+
+       /**
+        * eap_method - EAP method to use
+        *
+        * Pre-configured EAP method to use with this credential or %NULL to
+        * indicate no EAP method is selected, i.e., the method will be
+        * selected automatically based on ANQP information.
+        */
+       struct eap_method_type *eap_method;
+
+       /**
+        * phase1 - Phase 1 (outer authentication) parameters
+        *
+        * Pre-configured EAP parameters or %NULL.
+        */
+       char *phase1;
+
+       /**
+        * phase2 - Phase 2 (inner authentication) parameters
+        *
+        * Pre-configured EAP parameters or %NULL.
+        */
+       char *phase2;
 };
 
 
index 7d3fbcd..86f2ee3 100644 (file)
@@ -15,6 +15,7 @@
 #include "utils/pcsc_funcs.h"
 #include "drivers/driver.h"
 #include "eap_common/eap_defs.h"
+#include "eap_peer/eap.h"
 #include "eap_peer/eap_methods.h"
 #include "wpa_supplicant_i.h"
 #include "config.h"
@@ -733,6 +734,21 @@ fail:
 static int interworking_set_eap_params(struct wpa_ssid *ssid,
                                       struct wpa_cred *cred, int ttls)
 {
+       if (cred->eap_method) {
+               ttls = cred->eap_method->vendor == EAP_VENDOR_IETF &&
+                       cred->eap_method->method == EAP_TYPE_TTLS;
+
+               os_free(ssid->eap.eap_methods);
+               ssid->eap.eap_methods =
+                       os_malloc(sizeof(struct eap_method_type) * 2);
+               if (ssid->eap.eap_methods == NULL)
+                       return -1;
+               os_memcpy(ssid->eap.eap_methods, cred->eap_method,
+                         sizeof(*cred->eap_method));
+               ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF;
+               ssid->eap.eap_methods[1].method = EAP_TYPE_NONE;
+       }
+
        if (ttls && cred->username && cred->username[0]) {
                const char *pos;
                char *anon;
@@ -784,6 +800,15 @@ static int interworking_set_eap_params(struct wpa_ssid *ssid,
                                  cred->private_key_passwd) < 0)
                return -1;
 
+       if (cred->phase1) {
+               os_free(ssid->eap.phase1);
+               ssid->eap.phase1 = os_strdup(cred->phase1);
+       }
+       if (cred->phase2) {
+               os_free(ssid->eap.phase2);
+               ssid->eap.phase2 = os_strdup(cred->phase2);
+       }
+
        if (cred->ca_cert && cred->ca_cert[0] &&
            wpa_config_set_quoted(ssid, "ca_cert", cred->ca_cert) < 0)
                return -1;
index b3cacab..fa4e397 100644 (file)
@@ -336,6 +336,17 @@ fast_reauth=1
 #      This is used to compare against the Domain Name List to figure out
 #      whether the AP is operated by the Home SP.
 #
+# eap: Pre-configured EAP method
+#      This optional field can be used to specify which EAP method will be
+#      used with this credential. If not set, the EAP method is selected
+#      automatically based on ANQP information (e.g., NAI Realm).
+#
+# phase1: Pre-configure Phase 1 (outer authentication) parameters
+#      This optional field is used with like the 'eap' parameter.
+#
+# phase2: Pre-configure Phase 2 (inner authentication) parameters
+#      This optional field is used with like the 'eap' parameter.
+#
 # for example:
 #
 #cred={