aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2015-08-23 19:06:55 (GMT)
committerJouni Malinen <j@w1.fi>2015-08-24 15:01:40 (GMT)
commit8bb5b875d1b570a6e51f2b25e151973b0f70eb6a (patch)
treecc81cbac20989488b695bf45d4dfb02583b17be9 /src
parente23e35e39a65c59ca10caa880640db1a0dac9a8d (diff)
downloadhostap-8bb5b875d1b570a6e51f2b25e151973b0f70eb6a.zip
hostap-8bb5b875d1b570a6e51f2b25e151973b0f70eb6a.tar.gz
hostap-8bb5b875d1b570a6e51f2b25e151973b0f70eb6a.tar.bz2
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>
Diffstat (limited to 'src')
-rw-r--r--src/eap_server/eap_server_peap.c96
1 files changed, 93 insertions, 3 deletions
diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c
index ff3401b..51062b0 100644
--- a/src/eap_server/eap_server_peap.c
+++ b/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);
}