aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2008-02-15 03:07:04 (GMT)
committerJouni Malinen <j@w1.fi>2008-02-15 03:07:04 (GMT)
commita04e1144fb3488f372851c7f45e05adfb4277d95 (patch)
treed235ce5bb7b8c9e480f8b9603e66cd54b2da5411
parentc2717b85e445abbcce63bb5e8e74ed18b0de50a9 (diff)
downloadhostap-history-a04e1144fb3488f372851c7f45e05adfb4277d95.zip
hostap-history-a04e1144fb3488f372851c7f45e05adfb4277d95.tar.gz
hostap-history-a04e1144fb3488f372851c7f45e05adfb4277d95.tar.bz2
Fixed EAP-PEAP not to allow server to claim success when Phase 2 EAP method
has been started, but has not yet completed successfully. Server is still allowed to skip Phase 2 EAP completely since that is the standard way of handling fast session resumption. However, if the server starts Phase 2 EAP authentication, this negotiation has to be completed before protected success notification can be used to terminate EAP-PEAP successfully.
-rw-r--r--src/eap_peer/eap_peap.c21
-rw-r--r--src/eap_peer/eap_tlv.c17
-rw-r--r--src/eap_peer/eap_tlv.h5
3 files changed, 36 insertions, 7 deletions
diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c
index 027027d..1f77aa7 100644
--- a/src/eap_peer/eap_peap.c
+++ b/src/eap_peer/eap_peap.c
@@ -41,6 +41,8 @@ struct eap_peap_data {
const struct eap_method *phase2_method;
void *phase2_priv;
int phase2_success;
+ int phase2_eap_success;
+ int phase2_eap_started;
struct eap_method_type phase2_type;
struct eap_method_type *phase2_types;
@@ -204,7 +206,9 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
break;
case EAP_TYPE_TLV:
os_memset(&iret, 0, sizeof(iret));
- if (eap_tlv_process(sm, &iret, req, resp)) {
+ if (eap_tlv_process(sm, &iret, req, resp,
+ data->phase2_eap_started &&
+ !data->phase2_eap_success)) {
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
return -1;
@@ -264,6 +268,7 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
ret->decision = DECISION_FAIL;
return -1;
}
+ data->phase2_eap_started = 1;
os_memset(&iret, 0, sizeof(iret));
*resp = data->phase2_method->process(sm, data->phase2_priv,
&iret, req);
@@ -271,6 +276,7 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
iret.methodState == METHOD_MAY_CONT) &&
(iret.decision == DECISION_UNCOND_SUCC ||
iret.decision == DECISION_COND_SUCC)) {
+ data->phase2_eap_success = 1;
data->phase2_success = 1;
}
break;
@@ -458,6 +464,17 @@ continue_req:
/* EAP-Success within TLS tunnel is used to indicate
* shutdown of the TLS channel. The authentication has
* been completed. */
+ if (data->phase2_eap_started &&
+ !data->phase2_eap_success) {
+ wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 "
+ "Success used to indicate success, "
+ "but Phase 2 EAP was not yet "
+ "completed successfully");
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ wpabuf_free(in_decrypted);
+ return 0;
+ }
wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
"EAP-Success within TLS tunnel - "
"authentication completed");
@@ -712,6 +729,8 @@ static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
data->phase2_method->init_for_reauth)
data->phase2_method->init_for_reauth(sm, data->phase2_priv);
data->phase2_success = 0;
+ data->phase2_eap_success = 0;
+ data->phase2_eap_started = 0;
data->resuming = 1;
sm->peap_done = FALSE;
return priv;
diff --git a/src/eap_peer/eap_tlv.c b/src/eap_peer/eap_tlv.c
index 33f7b75..e2b9483 100644
--- a/src/eap_peer/eap_tlv.c
+++ b/src/eap_peer/eap_tlv.c
@@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
- * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -85,10 +85,12 @@ struct wpabuf * eap_tlv_build_result(int id, u16 status)
* field should be initialized to %NULL before the call. The value will be
* updated if a response message is generated. The caller is responsible for
* freeing the allocated message.
+ * @force_failure: Force negotiation to fail
* Returns: 0 on success, -1 on failure
*/
int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret,
- const struct wpabuf *req, struct wpabuf **resp)
+ const struct wpabuf *req, struct wpabuf **resp,
+ int force_failure)
{
size_t left, tlv_len;
const u8 *pos;
@@ -159,8 +161,15 @@ int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret,
if (status == EAP_TLV_RESULT_SUCCESS) {
wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success "
"- EAP-TLV/Phase2 Completed");
- resp_status = EAP_TLV_RESULT_SUCCESS;
- ret->decision = DECISION_UNCOND_SUCC;
+ if (force_failure) {
+ wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure"
+ " - force failed Phase 2");
+ resp_status = EAP_TLV_RESULT_FAILURE;
+ ret->decision = DECISION_FAIL;
+ } else {
+ resp_status = EAP_TLV_RESULT_SUCCESS;
+ ret->decision = DECISION_UNCOND_SUCC;
+ }
} else if (status == EAP_TLV_RESULT_FAILURE) {
wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure");
resp_status = EAP_TLV_RESULT_FAILURE;
diff --git a/src/eap_peer/eap_tlv.h b/src/eap_peer/eap_tlv.h
index c9d438d..ce70aba 100644
--- a/src/eap_peer/eap_tlv.h
+++ b/src/eap_peer/eap_tlv.h
@@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
- * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -20,6 +20,7 @@
struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type);
struct wpabuf * eap_tlv_build_result(int id, u16 status);
int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret,
- const struct wpabuf *req, struct wpabuf **resp);
+ const struct wpabuf *req, struct wpabuf **resp,
+ int force_failure);
#endif /* EAP_TLV_H */