[PATCH] EAP-TTLS: Fix parsing auth= and autheap= Phase2 params

Pali Rohár pali.rohar at gmail.com
Sun Dec 6 03:01:32 PST 2015


This patch fix security issue when Phase2 param auth=MSCHAPv2 was handled as
MSCHAP (v1) which degraded security. Now when invalid or unsupported auth=
Phase2 param combinations are specified then EAP-TTLS throw error instead
silently doing something.

More then one auth= Phase2 type cannot be specified and also both auth= and
autheap= options cannot be specified.

Parsing Phase2 type is case sensitive (as in other EAP parts), so Phase2
param auth=MSCHAPv2 is invalid. Only auth=MSCHAPV2 is correct.
---
 src/eap_peer/eap_ttls.c |   78 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 66 insertions(+), 12 deletions(-)

diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c
index b186c91..fa9d60d 100644
--- a/src/eap_peer/eap_ttls.c
+++ b/src/eap_peer/eap_ttls.c
@@ -70,6 +70,7 @@ static void * eap_ttls_init(struct eap_sm *sm)
 {
 	struct eap_ttls_data *data;
 	struct eap_peer_config *config = eap_get_config(sm);
+	int selected_non_eap;
 	char *selected;
 
 	data = os_zalloc(sizeof(*data));
@@ -77,26 +78,79 @@ static void * eap_ttls_init(struct eap_sm *sm)
 		return NULL;
 	data->ttls_version = EAP_TTLS_VERSION;
 	selected = "EAP";
+	selected_non_eap = 0;
 	data->phase2_type = EAP_TTLS_PHASE2_EAP;
 
+	/* Either one auth= type is specified or more autheap= methods are specified */
 	if (config && config->phase2) {
+		char *start, *pos, *buf;
+
+		start = buf = os_strdup(config->phase2);
+		if (buf == NULL) {
+			eap_ttls_deinit(sm, data);
+			return NULL;
+		}
+
+		while (start && *start != '\0') {
+			pos = os_strstr(start, "auth=");
+			if (pos == NULL)
+				break;
+			if (start != pos && *(pos - 1) != ' ') {
+				start = pos + 5; /* os_strlen("auth=") */
+				continue;
+			}
+
+			start = pos + 5; /* os_strlen("auth=") */
+			pos = os_strchr(start, ' ');
+			if (pos)
+				*pos++ = '\0';
+
+			if (os_strcmp(start, "MSCHAPV2") == 0) {
+				selected = "MSCHAPV2";
+				data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
+			} else if (os_strcmp(start, "MSCHAP") == 0) {
+				selected = "MSCHAP";
+				data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
+			} else if (os_strcmp(start, "PAP") == 0) {
+				selected = "PAP";
+				data->phase2_type = EAP_TTLS_PHASE2_PAP;
+			} else if (os_strcmp(start, "CHAP") == 0) {
+				selected = "CHAP";
+				data->phase2_type = EAP_TTLS_PHASE2_CHAP;
+			} else {
+				wpa_printf(MSG_ERROR, "EAP-TTLS: Unsupported Phase2 "
+					   "type '%s'", start);
+				os_free(buf);
+				eap_ttls_deinit(sm, data);
+				return NULL;
+			}
+
+			if (selected_non_eap) {
+				wpa_printf(MSG_ERROR, "EAP-TTLS: Only one Phase2 "
+					   "type can be specified");
+				os_free(buf);
+				eap_ttls_deinit(sm, data);
+				return NULL;
+			}
+
+			selected_non_eap = 1;
+			start = pos;
+		}
+
+		os_free(buf);
+
 		if (os_strstr(config->phase2, "autheap=")) {
+			if (selected_non_eap) {
+				wpa_printf(MSG_ERROR, "EAP-TTLS: Both auth= and "
+					   "autheap= params cannot be specified");
+				eap_ttls_deinit(sm, data);
+				return NULL;
+			}
 			selected = "EAP";
 			data->phase2_type = EAP_TTLS_PHASE2_EAP;
-		} else if (os_strstr(config->phase2, "auth=MSCHAPV2")) {
-			selected = "MSCHAPV2";
-			data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
-		} else if (os_strstr(config->phase2, "auth=MSCHAP")) {
-			selected = "MSCHAP";
-			data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
-		} else if (os_strstr(config->phase2, "auth=PAP")) {
-			selected = "PAP";
-			data->phase2_type = EAP_TTLS_PHASE2_PAP;
-		} else if (os_strstr(config->phase2, "auth=CHAP")) {
-			selected = "CHAP";
-			data->phase2_type = EAP_TTLS_PHASE2_CHAP;
 		}
 	}
+
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected);
 
 	if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
-- 
1.7.9.5




More information about the Hostap mailing list