aboutsummaryrefslogtreecommitdiffstats
path: root/src/eap_peer/eap_fast.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2008-02-28 01:59:34 (GMT)
committerJouni Malinen <j@w1.fi>2008-02-28 01:59:34 (GMT)
commit7914585fe08e000fa49b84fded54c0731d64e177 (patch)
tree5c14107244361bd5211115060b35a1da9a7fdb11 /src/eap_peer/eap_fast.c
parent2bab8ae401b5a1ee38c801a51cddd892a05449e1 (diff)
downloadhostap-7914585fe08e000fa49b84fded54c0731d64e177.zip
hostap-7914585fe08e000fa49b84fded54c0731d64e177.tar.gz
hostap-7914585fe08e000fa49b84fded54c0731d64e177.tar.bz2
EAP-FAST: Cleaned up TLV processing and added support for EAP Sequences
Number of TLVs were processed in groups and these cases were now separated into more flexible processing of one TLV at the time. wpabuf_concat() function was added to make it easier to concatenate TLVs. EAP Sequences are now supported in both server and peer code, but the server side is not enabled by default.
Diffstat (limited to 'src/eap_peer/eap_fast.c')
-rw-r--r--src/eap_peer/eap_fast.c178
1 files changed, 94 insertions, 84 deletions
diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c
index a94ed6c..bf94e0f 100644
--- a/src/eap_peer/eap_fast.c
+++ b/src/eap_peer/eap_fast.c
@@ -706,17 +706,16 @@ static u8 * eap_fast_write_pac_request(u8 *pos, u16 pac_type)
static struct wpabuf * eap_fast_process_crypto_binding(
struct eap_sm *sm, struct eap_fast_data *data,
struct eap_method_ret *ret,
- struct eap_tlv_crypto_binding_tlv *_bind, size_t bind_len, int final)
+ struct eap_tlv_crypto_binding_tlv *_bind, size_t bind_len)
{
struct wpabuf *resp;
u8 *pos;
- struct eap_tlv_intermediate_result_tlv *rresult;
u8 cmk[EAP_FAST_CMK_LEN], cmac[SHA1_MAC_LEN];
- int res, req_tunnel_pac = 0;
+ int res;
size_t len;
if (eap_fast_validate_crypto_binding(_bind) < 0)
- return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1);
+ return NULL;
if (eap_fast_get_cmk(sm, data, cmk) < 0)
return NULL;
@@ -735,9 +734,8 @@ static struct wpabuf * eap_fast_process_crypto_binding(
_bind->compound_mac, sizeof(cmac));
if (res != 0) {
wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not match");
- resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1);
os_memcpy(_bind->compound_mac, cmac, sizeof(cmac));
- return resp;
+ return NULL;
}
/*
@@ -745,73 +743,25 @@ static struct wpabuf * eap_fast_process_crypto_binding(
* crypto binding to allow server to complete authentication.
*/
- if (data->current_pac == NULL && data->provisioning &&
- !data->anon_provisioning) {
- /*
- * Need to request Tunnel PAC when using authenticated
- * provisioning.
- */
- wpa_printf(MSG_DEBUG, "EAP-FAST: Request Tunnel PAC");
- req_tunnel_pac = 1;
- }
-
- len = sizeof(*rresult) + sizeof(struct eap_tlv_crypto_binding_tlv);
- if (req_tunnel_pac)
- len += sizeof(struct eap_tlv_hdr) +
- sizeof(struct eap_tlv_request_action_tlv) +
- sizeof(struct eap_tlv_pac_type_tlv);
+ len = sizeof(struct eap_tlv_crypto_binding_tlv);
resp = wpabuf_alloc(len);
if (resp == NULL)
return NULL;
- /*
- * Both intermediate and final Result TLVs are identical, so ok to use
- * the same structure definition for them.
- */
- rresult = wpabuf_put(resp, sizeof(*rresult));
- rresult->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
- (final ? EAP_TLV_RESULT_TLV :
- EAP_TLV_INTERMEDIATE_RESULT_TLV));
- rresult->length = host_to_be16(2);
- rresult->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);
-
if (!data->anon_provisioning && data->phase2_success &&
eap_fast_derive_msk(data) < 0) {
wpa_printf(MSG_INFO, "EAP-FAST: Failed to generate MSK");
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
- rresult->status = host_to_be16(EAP_TLV_RESULT_FAILURE);
data->phase2_success = 0;
+ wpabuf_free(resp);
+ return NULL;
}
pos = wpabuf_put(resp, sizeof(struct eap_tlv_crypto_binding_tlv));
eap_fast_write_crypto_binding((struct eap_tlv_crypto_binding_tlv *)
pos, _bind, cmk);
- if (req_tunnel_pac) {
- u8 *pos2;
- pos = wpabuf_put(resp, 0);
- pos2 = eap_fast_write_pac_request(pos, PAC_TYPE_TUNNEL_PAC);
- wpabuf_put(resp, pos2 - pos);
- }
-
- if (final && data->phase2_success) {
- if (data->anon_provisioning) {
- wpa_printf(MSG_DEBUG, "EAP-FAST: Unauthenticated "
- "provisioning completed successfully.");
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_FAIL;
- } else {
- wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication "
- "completed successfully.");
- if (data->provisioning)
- ret->methodState = METHOD_MAY_CONT;
- else
- ret->methodState = METHOD_DONE;
- ret->decision = DECISION_UNCOND_SUCC;
- }
- }
-
return resp;
}
@@ -1028,7 +978,7 @@ static struct wpabuf * eap_fast_process_pac(struct eap_sm *sm,
os_memset(&entry, 0, sizeof(entry));
if (eap_fast_process_pac_tlv(&entry, pac, pac_len) ||
eap_fast_process_pac_info(&entry))
- return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0);
+ return NULL;
eap_fast_add_pac(&data->pac, &data->current_pac, &entry);
eap_fast_pac_list_truncate(data->pac, data->max_pac_list_len);
@@ -1140,6 +1090,24 @@ static int eap_fast_encrypt_response(struct eap_sm *sm,
}
+static struct wpabuf * eap_fast_pac_request(void)
+{
+ struct wpabuf *tmp;
+ u8 *pos, *pos2;
+
+ tmp = wpabuf_alloc(sizeof(struct eap_tlv_hdr) +
+ sizeof(struct eap_tlv_request_action_tlv) +
+ sizeof(struct eap_tlv_pac_type_tlv));
+ if (tmp == NULL)
+ return NULL;
+
+ pos = wpabuf_put(tmp, 0);
+ pos2 = eap_fast_write_pac_request(pos, PAC_TYPE_TUNNEL_PAC);
+ wpabuf_put(tmp, pos2 - pos);
+ return tmp;
+}
+
+
static int eap_fast_process_decrypted(struct eap_sm *sm,
struct eap_fast_data *data,
struct eap_method_ret *ret,
@@ -1147,8 +1115,9 @@ static int eap_fast_process_decrypted(struct eap_sm *sm,
struct wpabuf *decrypted,
struct wpabuf **out_data)
{
- struct wpabuf *resp = NULL;
+ struct wpabuf *resp = NULL, *tmp;
struct eap_fast_tlv_parse tlv;
+ int failed = 0;
if (eap_fast_parse_decrypted(decrypted, &tlv, &resp) < 0)
return 0;
@@ -1168,43 +1137,84 @@ static int eap_fast_process_decrypted(struct eap_sm *sm,
req->identifier, out_data);
}
+ if (tlv.crypto_binding) {
+ tmp = eap_fast_process_crypto_binding(sm, data, ret,
+ tlv.crypto_binding,
+ tlv.crypto_binding_len);
+ if (tmp == NULL)
+ failed = 1;
+ else
+ resp = wpabuf_concat(resp, tmp);
+ }
+
+ if (tlv.iresult == EAP_TLV_RESULT_SUCCESS) {
+ tmp = eap_fast_tlv_result(failed ? EAP_TLV_RESULT_FAILURE :
+ EAP_TLV_RESULT_SUCCESS, 1);
+ resp = wpabuf_concat(resp, tmp);
+ }
+
if (tlv.eap_payload_tlv) {
- resp = eap_fast_process_eap_payload_tlv(
+ tmp = eap_fast_process_eap_payload_tlv(
sm, data, ret, req, tlv.eap_payload_tlv,
tlv.eap_payload_tlv_len);
- return eap_fast_encrypt_response(sm, data, resp,
- req->identifier, out_data);
- }
-
- if (tlv.crypto_binding) {
- int final = tlv.result == EAP_TLV_RESULT_SUCCESS;
- resp = eap_fast_process_crypto_binding(sm, data, ret,
- tlv.crypto_binding,
- tlv.crypto_binding_len,
- final);
- return eap_fast_encrypt_response(sm, data, resp,
- req->identifier, out_data);
+ resp = wpabuf_concat(resp, tmp);
}
if (tlv.pac && tlv.result != EAP_TLV_RESULT_SUCCESS) {
wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV without Result TLV "
"acknowledging success");
- resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0);
- return eap_fast_encrypt_response(sm, data, resp,
- req->identifier, out_data);
+ failed = 1;
+ } else if (tlv.pac && tlv.result == EAP_TLV_RESULT_SUCCESS) {
+ tmp = eap_fast_process_pac(sm, data, ret, tlv.pac,
+ tlv.pac_len);
+ resp = wpabuf_concat(resp, tmp);
}
- if (tlv.pac && tlv.result == EAP_TLV_RESULT_SUCCESS) {
- resp = eap_fast_process_pac(sm, data, ret, tlv.pac,
- tlv.pac_len);
- return eap_fast_encrypt_response(sm, data, resp,
- req->identifier, out_data);
+ if (data->current_pac == NULL && data->provisioning &&
+ !data->anon_provisioning) {
+ /*
+ * Need to request Tunnel PAC when using authenticated
+ * provisioning.
+ */
+ wpa_printf(MSG_DEBUG, "EAP-FAST: Request Tunnel PAC");
+ tmp = eap_fast_pac_request();
+ resp = wpabuf_concat(resp, tmp);
+ }
+
+ if (tlv.result == EAP_TLV_RESULT_SUCCESS && !failed) {
+ tmp = eap_fast_tlv_result(EAP_TLV_RESULT_SUCCESS, 0);
+ resp = wpabuf_concat(resp, tmp);
+ } else if (failed) {
+ tmp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0);
+ resp = wpabuf_concat(resp, tmp);
+ }
+
+ if (resp && tlv.result == EAP_TLV_RESULT_SUCCESS && !failed &&
+ tlv.crypto_binding && data->phase2_success) {
+ if (data->anon_provisioning) {
+ wpa_printf(MSG_DEBUG, "EAP-FAST: Unauthenticated "
+ "provisioning completed successfully.");
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ } else {
+ wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication "
+ "completed successfully.");
+ if (data->provisioning)
+ ret->methodState = METHOD_MAY_CONT;
+ else
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_UNCOND_SUCC;
+ }
+ }
+
+ if (resp == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-FAST: No recognized TLVs - send "
+ "empty response packet");
+ resp = wpabuf_alloc(1);
}
- wpa_printf(MSG_DEBUG, "EAP-FAST: No recognized TLVs - send "
- "empty response packet");
- return eap_fast_encrypt_response(sm, data, wpabuf_alloc(1),
- req->identifier, out_data);
+ return eap_fast_encrypt_response(sm, data, resp, req->identifier,
+ out_data);
}