Browse Source

EAP-TTLS peer: Fix success after fragmented final Phase 2 message

If the final Phase 2 message needed fragmentation, EAP method decision
was cleared from UNCOND_SUCC or COND_SUCC to FAIL and that resulted in
the authentication failing when the EAP-Success message from the server
got rejected. Fix this by restoring the EAP method decision after
fragmentation.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Jouni Malinen 9 years ago
parent
commit
0daa9f6a13
1 changed files with 15 additions and 0 deletions
  1. 15 0
      src/eap_peer/eap_ttls.c

+ 15 - 0
src/eap_peer/eap_ttls.c

@@ -35,6 +35,7 @@ struct eap_ttls_data {
 	void *phase2_priv;
 	int phase2_success;
 	int phase2_start;
+	EapDecision decision_succ;
 
 	enum phase2_types {
 		EAP_TTLS_PHASE2_EAP,
@@ -1547,6 +1548,7 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm,
 			wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
 				   "completed successfully");
 			data->phase2_success = 1;
+			data->decision_succ = ret->decision;
 #ifdef EAP_TNC
 			if (!data->ready_for_tnc && !data->tnc_started) {
 				/*
@@ -1564,6 +1566,18 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm,
 			wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
 				   "completed successfully (MAY_CONT)");
 			data->phase2_success = 1;
+			data->decision_succ = ret->decision;
+	} else if (data->decision_succ != DECISION_FAIL &&
+		   data->phase2_success &&
+		   !data->ssl.tls_out) {
+		/*
+		 * This is needed to cover the case where the final Phase 2
+		 * message gets fragmented since fragmentation clears
+		 * decision back to FAIL.
+		 */
+		wpa_printf(MSG_DEBUG,
+			   "EAP-TTLS: Restore success decision after fragmented frame sent completely");
+		ret->decision = data->decision_succ;
 	}
 }
 
@@ -1638,6 +1652,7 @@ static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
 	data->pending_phase2_req = NULL;
 	wpabuf_free(data->pending_resp);
 	data->pending_resp = NULL;
+	data->decision_succ = DECISION_FAIL;
 #ifdef EAP_TNC
 	data->ready_for_tnc = 0;
 	data->tnc_started = 0;