EAP-TEAP peer: Support vendor EAP method in Phase 2
The implementation was previously hardcoded to use only the non-expanded IETF EAP methods in Phase 2. Extend that to allow vendor EAP methods with expanded header to be used. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
aba8dc82fc
commit
62af2b18f7
3 changed files with 37 additions and 16 deletions
|
@ -679,12 +679,13 @@ struct wpabuf * eap_teap_tlv_error(enum teap_error_codes error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int eap_teap_allowed_anon_prov_phase2_method(u8 type)
|
int eap_teap_allowed_anon_prov_phase2_method(int vendor, enum eap_type type)
|
||||||
{
|
{
|
||||||
/* RFC 7170, Section 3.8.3: MUST provide mutual authentication,
|
/* RFC 7170, Section 3.8.3: MUST provide mutual authentication,
|
||||||
* provide key generation, and be resistant to dictionary attack.
|
* provide key generation, and be resistant to dictionary attack.
|
||||||
* Section 3.8 also mentions requirement for using EMSK Compound MAC. */
|
* Section 3.8 also mentions requirement for using EMSK Compound MAC. */
|
||||||
return type == EAP_TYPE_PWD || type == EAP_TYPE_EKE;
|
return vendor == EAP_VENDOR_IETF &&
|
||||||
|
(type == EAP_TYPE_PWD || type == EAP_TYPE_EKE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -215,7 +215,8 @@ int eap_teap_parse_tlv(struct eap_teap_tlv_parse *tlv,
|
||||||
const char * eap_teap_tlv_type_str(enum teap_tlv_types type);
|
const char * eap_teap_tlv_type_str(enum teap_tlv_types type);
|
||||||
struct wpabuf * eap_teap_tlv_result(int status, int intermediate);
|
struct wpabuf * eap_teap_tlv_result(int status, int intermediate);
|
||||||
struct wpabuf * eap_teap_tlv_error(enum teap_error_codes error);
|
struct wpabuf * eap_teap_tlv_error(enum teap_error_codes error);
|
||||||
int eap_teap_allowed_anon_prov_phase2_method(u8 type);
|
enum eap_type;
|
||||||
|
int eap_teap_allowed_anon_prov_phase2_method(int vendor, enum eap_type type);
|
||||||
int eap_teap_allowed_anon_prov_cipher_suite(u16 cs);
|
int eap_teap_allowed_anon_prov_cipher_suite(u16 cs);
|
||||||
|
|
||||||
#endif /* EAP_TEAP_H */
|
#endif /* EAP_TEAP_H */
|
||||||
|
|
|
@ -327,7 +327,8 @@ static int eap_teap_init_phase2_method(struct eap_sm *sm,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type)
|
static int eap_teap_select_phase2_method(struct eap_teap_data *data,
|
||||||
|
int vendor, enum eap_type type)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
@ -335,15 +336,15 @@ static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type)
|
||||||
* completed inner EAP authentication (EAP-pwd or EAP-EKE) and TNC */
|
* completed inner EAP authentication (EAP-pwd or EAP-EKE) and TNC */
|
||||||
|
|
||||||
if (data->anon_provisioning &&
|
if (data->anon_provisioning &&
|
||||||
!eap_teap_allowed_anon_prov_phase2_method(type)) {
|
!eap_teap_allowed_anon_prov_phase2_method(vendor, type)) {
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"EAP-TEAP: EAP type %u not allowed during unauthenticated provisioning",
|
"EAP-TEAP: EAP type %u:%u not allowed during unauthenticated provisioning",
|
||||||
type);
|
vendor, type);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EAP_TNC
|
#ifdef EAP_TNC
|
||||||
if (type == EAP_TYPE_TNC) {
|
if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_TNC) {
|
||||||
data->phase2_type.vendor = EAP_VENDOR_IETF;
|
data->phase2_type.vendor = EAP_VENDOR_IETF;
|
||||||
data->phase2_type.method = EAP_TYPE_TNC;
|
data->phase2_type.method = EAP_TYPE_TNC;
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
|
@ -355,7 +356,7 @@ static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type)
|
||||||
#endif /* EAP_TNC */
|
#endif /* EAP_TNC */
|
||||||
|
|
||||||
for (i = 0; i < data->num_phase2_types; i++) {
|
for (i = 0; i < data->num_phase2_types; i++) {
|
||||||
if (data->phase2_types[i].vendor != EAP_VENDOR_IETF ||
|
if (data->phase2_types[i].vendor != vendor ||
|
||||||
data->phase2_types[i].method != type)
|
data->phase2_types[i].method != type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -368,7 +369,9 @@ static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != data->phase2_type.method || type == EAP_TYPE_NONE)
|
if (vendor != data->phase2_type.vendor ||
|
||||||
|
type != data->phase2_type.method ||
|
||||||
|
(vendor == EAP_VENDOR_IETF && type == EAP_TYPE_NONE))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -386,6 +389,8 @@ static int eap_teap_phase2_request(struct eap_sm *sm,
|
||||||
struct eap_method_ret iret;
|
struct eap_method_ret iret;
|
||||||
struct eap_peer_config *config = eap_get_config(sm);
|
struct eap_peer_config *config = eap_get_config(sm);
|
||||||
struct wpabuf msg;
|
struct wpabuf msg;
|
||||||
|
int vendor = EAP_VENDOR_IETF;
|
||||||
|
enum eap_type method;
|
||||||
|
|
||||||
if (len <= sizeof(struct eap_hdr)) {
|
if (len <= sizeof(struct eap_hdr)) {
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
|
@ -394,14 +399,27 @@ static int eap_teap_phase2_request(struct eap_sm *sm,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pos = (u8 *) (hdr + 1);
|
pos = (u8 *) (hdr + 1);
|
||||||
wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 Request: type=%d", *pos);
|
method = *pos;
|
||||||
if (*pos == EAP_TYPE_IDENTITY) {
|
if (method == EAP_TYPE_EXPANDED) {
|
||||||
|
if (len < sizeof(struct eap_hdr) + 8) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"EAP-TEAP: Too short Phase 2 request (expanded header) (len=%lu)",
|
||||||
|
(unsigned long) len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
vendor = WPA_GET_BE24(pos + 1);
|
||||||
|
method = WPA_GET_BE32(pos + 4);
|
||||||
|
}
|
||||||
|
wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 Request: type=%u:%u",
|
||||||
|
vendor, method);
|
||||||
|
if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_IDENTITY) {
|
||||||
*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
|
*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->phase2_priv && data->phase2_method &&
|
if (data->phase2_priv && data->phase2_method &&
|
||||||
*pos != data->phase2_type.method) {
|
(vendor != data->phase2_type.vendor ||
|
||||||
|
method != data->phase2_type.method)) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method");
|
"EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method");
|
||||||
data->phase2_method->deinit(sm, data->phase2_priv);
|
data->phase2_method->deinit(sm, data->phase2_priv);
|
||||||
|
@ -413,7 +431,7 @@ static int eap_teap_phase2_request(struct eap_sm *sm,
|
||||||
|
|
||||||
if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
|
if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
|
||||||
data->phase2_type.method == EAP_TYPE_NONE &&
|
data->phase2_type.method == EAP_TYPE_NONE &&
|
||||||
eap_teap_select_phase2_method(data, *pos) < 0) {
|
eap_teap_select_phase2_method(data, vendor, method) < 0) {
|
||||||
if (eap_peer_tls_phase2_nak(data->phase2_types,
|
if (eap_peer_tls_phase2_nak(data->phase2_types,
|
||||||
data->num_phase2_types,
|
data->num_phase2_types,
|
||||||
hdr, resp))
|
hdr, resp))
|
||||||
|
@ -424,8 +442,8 @@ static int eap_teap_phase2_request(struct eap_sm *sm,
|
||||||
if ((!data->phase2_priv && eap_teap_init_phase2_method(sm, data) < 0) ||
|
if ((!data->phase2_priv && eap_teap_init_phase2_method(sm, data) < 0) ||
|
||||||
!data->phase2_method) {
|
!data->phase2_method) {
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
"EAP-TEAP: Failed to initialize Phase 2 EAP method %d",
|
"EAP-TEAP: Failed to initialize Phase 2 EAP method %u:%u",
|
||||||
*pos);
|
vendor, method);
|
||||||
ret->methodState = METHOD_DONE;
|
ret->methodState = METHOD_DONE;
|
||||||
ret->decision = DECISION_FAIL;
|
ret->decision = DECISION_FAIL;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1333,6 +1351,7 @@ static int eap_teap_process_decrypted(struct eap_sm *sm,
|
||||||
data->phase2_method->vendor == 0 &&
|
data->phase2_method->vendor == 0 &&
|
||||||
eap_teap_allowed_anon_prov_cipher_suite(data->tls_cs) &&
|
eap_teap_allowed_anon_prov_cipher_suite(data->tls_cs) &&
|
||||||
eap_teap_allowed_anon_prov_phase2_method(
|
eap_teap_allowed_anon_prov_phase2_method(
|
||||||
|
data->phase2_method->vendor,
|
||||||
data->phase2_method->method))) &&
|
data->phase2_method->method))) &&
|
||||||
(tlv.iresult == TEAP_STATUS_SUCCESS ||
|
(tlv.iresult == TEAP_STATUS_SUCCESS ||
|
||||||
tlv.result == TEAP_STATUS_SUCCESS)) {
|
tlv.result == TEAP_STATUS_SUCCESS)) {
|
||||||
|
|
Loading…
Reference in a new issue