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 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap