summaryrefslogtreecommitdiff
path: root/src/eap_server/eap_server_peap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eap_server/eap_server_peap.c')
-rw-r--r--src/eap_server/eap_server_peap.c147
1 files changed, 126 insertions, 21 deletions
diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c
index faa0fd2f2387..51062b0987e4 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);
}
@@ -151,7 +182,7 @@ static void * eap_peap_init(struct eap_sm *sm)
data->state = START;
data->crypto_binding = OPTIONAL_BINDING;
- if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
+ if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_TYPE_PEAP)) {
wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
eap_peap_reset(sm, data);
return NULL;
@@ -539,15 +570,14 @@ static Boolean eap_peap_check(struct eap_sm *sm, void *priv,
static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
- EapType eap_type)
+ int vendor, EapType eap_type)
{
if (data->phase2_priv && data->phase2_method) {
data->phase2_method->reset(sm, data->phase2_priv);
data->phase2_method = NULL;
data->phase2_priv = NULL;
}
- data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF,
- eap_type);
+ data->phase2_method = eap_server_get_eap_method(vendor, eap_type);
if (!data->phase2_method)
return -1;
@@ -709,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 "
@@ -737,7 +769,7 @@ static void eap_peap_process_phase2_soh(struct eap_sm *sm,
const u8 *soh_tlv = NULL;
size_t soh_tlv_len = 0;
int tlv_type, mandatory, tlv_len, vtlv_len;
- u8 next_type;
+ u32 next_type;
u32 vendor_id;
pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left);
@@ -852,8 +884,9 @@ auth_method:
eap_peap_state(data, PHASE2_METHOD);
next_type = sm->user->methods[0].method;
sm->user_eap_method_index = 1;
- wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
- eap_peap_phase2_init(sm, data, next_type);
+ wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type %d",
+ sm->user->methods[0].vendor, next_type);
+ eap_peap_phase2_init(sm, data, sm->user->methods[0].vendor, next_type);
}
#endif /* EAP_SERVER_TNC */
@@ -862,7 +895,8 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
struct eap_peap_data *data,
struct wpabuf *in_data)
{
- u8 next_type = EAP_TYPE_NONE;
+ int next_vendor = EAP_VENDOR_IETF;
+ u32 next_type = EAP_TYPE_NONE;
const struct eap_hdr *hdr;
const u8 *pos;
size_t left;
@@ -894,17 +928,23 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
"allowed types", pos + 1, left - 1);
eap_sm_process_nak(sm, pos + 1, left - 1);
if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
- sm->user->methods[sm->user_eap_method_index].method !=
- EAP_TYPE_NONE) {
+ (sm->user->methods[sm->user_eap_method_index].vendor !=
+ EAP_VENDOR_IETF ||
+ sm->user->methods[sm->user_eap_method_index].method !=
+ EAP_TYPE_NONE)) {
+ next_vendor = sm->user->methods[
+ sm->user_eap_method_index].vendor;
next_type = sm->user->methods[
sm->user_eap_method_index++].method;
- wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d",
- next_type);
+ wpa_printf(MSG_DEBUG,
+ "EAP-PEAP: try EAP vendor %d type 0x%x",
+ next_vendor, next_type);
} else {
eap_peap_req_failure(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
}
- eap_peap_phase2_init(sm, data, next_type);
+ eap_peap_phase2_init(sm, data, next_vendor, next_type);
return;
}
@@ -929,8 +969,9 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
eap_peap_req_failure(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
- eap_peap_phase2_init(sm, data, next_type);
+ eap_peap_phase2_init(sm, data, next_vendor, next_type);
return;
}
@@ -942,7 +983,8 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey "
"failed");
eap_peap_req_failure(sm, data);
- eap_peap_phase2_init(sm, data, EAP_TYPE_NONE);
+ eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
+ EAP_TYPE_NONE);
return;
}
}
@@ -957,6 +999,7 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
"database",
sm->identity, sm->identity_len);
eap_peap_req_failure(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
break;
}
@@ -967,18 +1010,22 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
eap_peap_state(data, PHASE2_SOH);
wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "
"TNC (NAP SOH)");
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
break;
}
#endif /* EAP_SERVER_TNC */
eap_peap_state(data, PHASE2_METHOD);
+ next_vendor = sm->user->methods[0].vendor;
next_type = sm->user->methods[0].method;
sm->user_eap_method_index = 1;
- wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
+ wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type 0x%x",
+ next_vendor, next_type);
break;
case PHASE2_METHOD:
eap_peap_req_success(sm, data);
+ next_vendor = EAP_VENDOR_IETF;
next_type = EAP_TYPE_NONE;
break;
case FAILURE:
@@ -989,7 +1036,7 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
break;
}
- eap_peap_phase2_init(sm, data, next_type);
+ eap_peap_phase2_init(sm, data, next_vendor, next_type);
}
@@ -1080,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:
@@ -1133,7 +1181,8 @@ static void eap_peap_process_msg(struct eap_sm *sm, void *priv,
break;
case PHASE2_START:
eap_peap_state(data, PHASE2_ID);
- eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY);
+ eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
+ EAP_TYPE_IDENTITY);
break;
case PHASE1_ID2:
case PHASE2_ID:
@@ -1144,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);
@@ -1160,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);
}