From 8ca93c59e002e9359f7fe5b707979b8f5012167c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 2 Aug 2012 18:40:45 +0300 Subject: [PATCH] Interworking: Allow pre-configuration of EAP parameters 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 --- wpa_supplicant/config.c | 32 ++++++++++++++++++++++++++++++ wpa_supplicant/config.h | 23 +++++++++++++++++++++ wpa_supplicant/interworking.c | 25 +++++++++++++++++++++++ wpa_supplicant/wpa_supplicant.conf | 11 ++++++++++ 4 files changed, 91 insertions(+) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 427242d94..9b252e9a1 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -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); diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 9ae57d018..5db919408 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -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; }; diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 7d3fbcd54..86f2ee3e9 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -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; diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index b3cacab54..fa4e39773 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -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={