diff options
Diffstat (limited to 'src/eap_server')
-rw-r--r-- | src/eap_server/.gitignore | 1 | ||||
-rw-r--r-- | src/eap_server/eap.c | 15 | ||||
-rw-r--r-- | src/eap_server/eap_fast.c | 77 | ||||
-rw-r--r-- | src/eap_server/eap_gpsk.c | 2 | ||||
-rw-r--r-- | src/eap_server/eap_i.h | 2 | ||||
-rw-r--r-- | src/eap_server/eap_tls_common.c | 2 | ||||
-rw-r--r-- | src/eap_server/eap_tnc.c | 2 | ||||
-rw-r--r-- | src/eap_server/eap_ttls.c | 13 |
8 files changed, 84 insertions, 30 deletions
diff --git a/src/eap_server/.gitignore b/src/eap_server/.gitignore deleted file mode 100644 index a4383358ec72f..0000000000000 --- a/src/eap_server/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.d diff --git a/src/eap_server/eap.c b/src/eap_server/eap.c index dea91e635d2f4..897adc3b1a2aa 100644 --- a/src/eap_server/eap.c +++ b/src/eap_server/eap.c @@ -573,6 +573,13 @@ SM_STATE(EAP, SUCCESS2) } sm->eap_if.eapSuccess = TRUE; + + /* + * Start reauthentication with identity request even though we know the + * previously used identity. This is needed to get reauthentication + * started properly. + */ + sm->start_reauth = TRUE; } @@ -1070,7 +1077,7 @@ static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor) static int eap_sm_Policy_getDecision(struct eap_sm *sm) { - if (!sm->eap_server && sm->identity) { + if (!sm->eap_server && sm->identity && !sm->start_reauth) { wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH"); return DECISION_PASSTHROUGH; } @@ -1091,7 +1098,8 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm) return DECISION_FAILURE; } - if ((sm->user == NULL || sm->update_user) && sm->identity) { + if ((sm->user == NULL || sm->update_user) && sm->identity && + !sm->start_reauth) { /* * Allow Identity method to be started once to allow identity * selection hint to be sent from the authentication server, @@ -1118,6 +1126,7 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm) } sm->update_user = FALSE; } + sm->start_reauth = FALSE; if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && (sm->user->methods[sm->user_eap_method_index].vendor != @@ -1252,7 +1261,7 @@ void eap_server_sm_deinit(struct eap_sm *sm) sm->m->reset(sm, sm->eap_method_priv); wpabuf_free(sm->eap_if.eapReqData); os_free(sm->eap_if.eapKeyData); - os_free(sm->lastReqData); + wpabuf_free(sm->lastReqData); wpabuf_free(sm->eap_if.eapRespData); os_free(sm->identity); os_free(sm->pac_opaque_encr_key); diff --git a/src/eap_server/eap_fast.c b/src/eap_server/eap_fast.c index b474c99a1ff3d..c06f396ffd675 100644 --- a/src/eap_server/eap_fast.c +++ b/src/eap_server/eap_fast.c @@ -73,6 +73,10 @@ struct eap_fast_data { }; +static int eap_fast_process_phase2_start(struct eap_sm *sm, + struct eap_fast_data *data); + + static const char * eap_fast_state_txt(int state) { switch (state) { @@ -804,11 +808,48 @@ static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm, } +static int eap_fast_encrypt_phase2(struct eap_sm *sm, + struct eap_fast_data *data, + struct wpabuf *plain, int piggyback) +{ + struct wpabuf *encr; + + wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 TLVs", + plain); + encr = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_mhead(plain), + wpabuf_len(plain)); + wpabuf_free(plain); + + if (data->ssl.out_buf && piggyback) { + wpa_printf(MSG_DEBUG, "EAP-FAST: Piggyback Phase 2 data " + "(len=%d) with last Phase 1 Message (len=%d " + "used=%d)", + (int) wpabuf_len(encr), + (int) wpabuf_len(data->ssl.out_buf), + (int) data->ssl.out_used); + if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(encr)) < 0) { + wpa_printf(MSG_WARNING, "EAP-FAST: Failed to resize " + "output buffer"); + wpabuf_free(encr); + return -1; + } + wpabuf_put_buf(data->ssl.out_buf, encr); + wpabuf_free(encr); + } else { + wpabuf_free(data->ssl.out_buf); + data->ssl.out_used = 0; + data->ssl.out_buf = encr; + } + + return 0; +} + + static struct wpabuf * eap_fast_buildReq(struct eap_sm *sm, void *priv, u8 id) { struct eap_fast_data *data = priv; struct wpabuf *req = NULL; - struct wpabuf *encr; + int piggyback = 0; if (data->ssl.state == FRAG_ACK) { return eap_server_tls_build_ack(id, EAP_TYPE_FAST, @@ -827,6 +868,19 @@ static struct wpabuf * eap_fast_buildReq(struct eap_sm *sm, void *priv, u8 id) if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { if (eap_fast_phase1_done(sm, data) < 0) return NULL; + if (data->state == PHASE2_START) { + /* + * Try to generate Phase 2 data to piggyback + * with the end of Phase 1 to avoid extra + * roundtrip. + */ + wpa_printf(MSG_DEBUG, "EAP-FAST: Try to start " + "Phase 2"); + if (eap_fast_process_phase2_start(sm, data)) + break; + req = eap_fast_build_phase2_req(sm, data, id); + piggyback = 1; + } } break; case PHASE2_ID: @@ -856,18 +910,9 @@ static struct wpabuf * eap_fast_buildReq(struct eap_sm *sm, void *priv, u8 id) return NULL; } - if (req) { - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 " - "TLVs", req); - encr = eap_server_tls_encrypt(sm, &data->ssl, - wpabuf_mhead(req), - wpabuf_len(req)); - wpabuf_free(req); - - wpabuf_free(data->ssl.out_buf); - data->ssl.out_used = 0; - data->ssl.out_buf = encr; - } + if (req && + eap_fast_encrypt_phase2(sm, data, req, piggyback) < 0) + return NULL; return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST, data->fast_version, id); @@ -1443,8 +1488,8 @@ static int eap_fast_process_phase1(struct eap_sm *sm, } -static void eap_fast_process_phase2_start(struct eap_sm *sm, - struct eap_fast_data *data) +static int eap_fast_process_phase2_start(struct eap_sm *sm, + struct eap_fast_data *data) { u8 next_type; @@ -1474,7 +1519,7 @@ static void eap_fast_process_phase2_start(struct eap_sm *sm, next_type = EAP_TYPE_IDENTITY; } - eap_fast_phase2_init(sm, data, next_type); + return eap_fast_phase2_init(sm, data, next_type); } diff --git a/src/eap_server/eap_gpsk.c b/src/eap_server/eap_gpsk.c index c87d4526884af..d0c7559d758b4 100644 --- a/src/eap_server/eap_gpsk.c +++ b/src/eap_server/eap_gpsk.c @@ -1,5 +1,5 @@ /* - * hostapd / EAP-GPSK (draft-ietf-emu-eap-gpsk-08.txt) server + * hostapd / EAP-GPSK (RFC 5433) server * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify diff --git a/src/eap_server/eap_i.h b/src/eap_server/eap_i.h index 61f564d5c49f3..d52b86f9558f0 100644 --- a/src/eap_server/eap_i.h +++ b/src/eap_server/eap_i.h @@ -183,6 +183,8 @@ struct eap_sm { int tnc; struct wps_context *wps; struct wpabuf *assoc_wps_ie; + + Boolean start_reauth; }; int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len, diff --git a/src/eap_server/eap_tls_common.c b/src/eap_server/eap_tls_common.c index befc1bf80f83d..bda1184c02bd2 100644 --- a/src/eap_server/eap_tls_common.c +++ b/src/eap_server/eap_tls_common.c @@ -344,7 +344,7 @@ struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm, size_t buf_len; /* reserve some extra room for encryption overhead */ - buf_len = plain_len + 200; + buf_len = plain_len + 300; buf = wpabuf_alloc(buf_len); if (buf == NULL) return NULL; diff --git a/src/eap_server/eap_tnc.c b/src/eap_server/eap_tnc.c index 834685bb7dc27..4cb3ecfb05655 100644 --- a/src/eap_server/eap_tnc.c +++ b/src/eap_server/eap_tnc.c @@ -500,7 +500,7 @@ static void eap_tnc_process(struct eap_sm *sm, void *priv, static Boolean eap_tnc_isDone(struct eap_sm *sm, void *priv) { struct eap_tnc_data *data = priv; - return data->state == DONE; + return data->state == DONE || data->state == FAIL; } diff --git a/src/eap_server/eap_ttls.c b/src/eap_server/eap_ttls.c index b097ab2ea0b67..21e4b21b15db6 100644 --- a/src/eap_server/eap_ttls.c +++ b/src/eap_server/eap_ttls.c @@ -954,7 +954,7 @@ static int eap_ttls_phase2_eap_init(struct eap_sm *sm, sm->init_phase2 = 1; data->phase2_priv = data->phase2_method->init(sm); sm->init_phase2 = 0; - return 0; + return data->phase2_priv == NULL ? -1 : 0; } @@ -1045,6 +1045,11 @@ static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm, next_type = sm->user->methods[0].method; sm->user_eap_method_index = 1; wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type); + if (eap_ttls_phase2_eap_init(sm, data, next_type)) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize " + "EAP type %d", next_type); + eap_ttls_state(data, FAILURE); + } break; case PHASE2_METHOD: if (data->ttls_version > 0) { @@ -1066,12 +1071,6 @@ static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm, __func__, data->state); break; } - - if (eap_ttls_phase2_eap_init(sm, data, next_type)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize EAP " - "type %d", next_type); - eap_ttls_state(data, FAILURE); - } } |