Browse Source

EAP-PEAP server: Add support for session resumption

This allows TLS session resumption to be used to enable abbreviated
handshake and skipping of Phase 2.

Signed-off-by: Jouni Malinen <j@w1.fi>
Jouni Malinen 9 years ago
parent
commit
8bb5b875d1
1 changed files with 93 additions and 3 deletions
  1. 93 3
      src/eap_server/eap_server_peap.c

+ 93 - 3
src/eap_server/eap_server_peap.c

@@ -95,6 +95,37 @@ static void eap_peap_state(struct eap_peap_data *data, int state)
 		   eap_peap_state_txt(data->state),
 		   eap_peap_state_txt(state));
 	data->state = state;
+	if (state == FAILURE || state == FAILURE_REQ)
+		tls_connection_remove_session(data->ssl.conn);
+}
+
+
+static void eap_peap_valid_session(struct eap_sm *sm,
+				   struct eap_peap_data *data)
+{
+	struct wpabuf *buf;
+
+	if (!sm->tls_session_lifetime ||
+	    tls_connection_resumed(sm->ssl_ctx, data->ssl.conn))
+		return;
+
+	buf = wpabuf_alloc(1 + 1 + sm->identity_len);
+	if (!buf)
+		return;
+	wpabuf_put_u8(buf, EAP_TYPE_PEAP);
+	if (sm->identity) {
+		u8 id_len;
+
+		if (sm->identity_len <= 255)
+			id_len = sm->identity_len;
+		else
+			id_len = 255;
+		wpabuf_put_u8(buf, id_len);
+		wpabuf_put_data(buf, sm->identity, id_len);
+	} else {
+		wpabuf_put_u8(buf, 0);
+	}
+	tls_connection_set_success_data(data->ssl.conn, buf);
 }
 
 
@@ -708,10 +739,12 @@ static void eap_peap_process_phase2_tlv(struct eap_sm *sm,
 		if (status == EAP_TLV_RESULT_SUCCESS) {
 			wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success "
 				   "- requested %s", requested);
-			if (data->tlv_request == TLV_REQ_SUCCESS)
+			if (data->tlv_request == TLV_REQ_SUCCESS) {
 				eap_peap_state(data, SUCCESS);
-			else
+				eap_peap_valid_session(sm, data);
+			} else {
 				eap_peap_state(data, FAILURE);
+			}
 			
 		} else if (status == EAP_TLV_RESULT_FAILURE) {
 			wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure "
@@ -1094,6 +1127,7 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
 		if (data->state == SUCCESS_REQ) {
 			eap_peap_state(data, SUCCESS);
+			eap_peap_valid_session(sm, data);
 		}
 		break;
 	case EAP_CODE_FAILURE:
@@ -1159,6 +1193,7 @@ static void eap_peap_process_msg(struct eap_sm *sm, void *priv,
 		break;
 	case SUCCESS_REQ:
 		eap_peap_state(data, SUCCESS);
+		eap_peap_valid_session(sm, data);
 		break;
 	case FAILURE_REQ:
 		eap_peap_state(data, FAILURE);
@@ -1175,10 +1210,65 @@ static void eap_peap_process(struct eap_sm *sm, void *priv,
 			     struct wpabuf *respData)
 {
 	struct eap_peap_data *data = priv;
+	const struct wpabuf *buf;
+	const u8 *pos;
+	u8 id_len;
+
 	if (eap_server_tls_process(sm, &data->ssl, respData, data,
 				   EAP_TYPE_PEAP, eap_peap_process_version,
-				   eap_peap_process_msg) < 0)
+				   eap_peap_process_msg) < 0) {
 		eap_peap_state(data, FAILURE);
+		return;
+	}
+
+	if (data->state == SUCCESS ||
+	    !tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
+	    !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn))
+		return;
+
+	buf = tls_connection_get_success_data(data->ssl.conn);
+	if (!buf || wpabuf_len(buf) < 2) {
+		wpa_printf(MSG_DEBUG,
+			   "EAP-PEAP: No success data in resumed session - reject attempt");
+		eap_peap_state(data, FAILURE);
+		return;
+	}
+
+	pos = wpabuf_head(buf);
+	if (*pos != EAP_TYPE_PEAP) {
+		wpa_printf(MSG_DEBUG,
+			   "EAP-PEAP: Resumed session for another EAP type (%u) - reject attempt",
+			   *pos);
+		eap_peap_state(data, FAILURE);
+		return;
+	}
+
+	pos++;
+	id_len = *pos++;
+	wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Identity from cached session",
+			  pos, id_len);
+	os_free(sm->identity);
+	sm->identity = os_malloc(id_len ? id_len : 1);
+	if (!sm->identity) {
+		sm->identity_len = 0;
+		eap_peap_state(data, FAILURE);
+		return;
+	}
+
+	os_memcpy(sm->identity, pos, id_len);
+	sm->identity_len = id_len;
+
+	if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
+		wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Phase2 Identity not found in the user database",
+				  sm->identity, sm->identity_len);
+		eap_peap_state(data, FAILURE);
+		return;
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "EAP-PEAP: Resuming previous session - skip Phase2");
+	eap_peap_state(data, SUCCESS_REQ);
+	tls_connection_set_success_data_resumed(data->ssl.conn);
 }