SM_STATE(EAP, IDENTITY) { u8 *eapReqData; size_t eapReqDataLen; SM_ENTRY(EAP, IDENTITY); eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen); eap_sm_processIdentity(sm, eapReqData, eapReqDataLen); free(sm->eapRespData); sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, &sm->eapRespDataLen, 0); }
static int eap_peap_phase2_request(struct eap_sm *sm, struct eap_peap_data *data, struct eap_method_ret *ret, struct wpabuf *req, struct wpabuf **resp) { struct eap_hdr *hdr = wpabuf_mhead(req); size_t len = be_to_host16(hdr->length); u8 *pos; struct eap_method_ret iret; struct eap_peer_config *config = eap_get_config(sm); if (len <= sizeof(struct eap_hdr)) { wpa_printf(MSG_INFO, "EAP-PEAP: too short " "Phase 2 request (len=%lu)", (unsigned long) len); return -1; } pos = (u8 *) (hdr + 1); wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos); switch (*pos) { case EAP_TYPE_IDENTITY: *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); break; case EAP_TYPE_TLV: os_memset(&iret, 0, sizeof(iret)); if (eap_tlv_process(sm, data, &iret, req, resp, data->phase2_eap_started && !data->phase2_eap_success)) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return -1; } if (iret.methodState == METHOD_DONE || iret.methodState == METHOD_MAY_CONT) { ret->methodState = iret.methodState; ret->decision = iret.decision; data->phase2_success = 1; } break; case EAP_TYPE_EXPANDED: #ifdef EAP_TNC if (data->soh) { const u8 *epos; size_t eleft; epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, req, &eleft); if (epos) { struct wpabuf *buf; wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH EAP Extensions"); buf = tncc_process_soh_request(data->soh, epos, eleft); if (buf) { *resp = eap_msg_alloc( EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf), EAP_CODE_RESPONSE, hdr->identifier); if (*resp == NULL) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return -1; } wpabuf_put_buf(*resp, buf); wpabuf_free(buf); break; } } } #endif /* EAP_TNC */ /* fall through */ default: if (data->phase2_type.vendor == EAP_VENDOR_IETF && data->phase2_type.method == EAP_TYPE_NONE) { size_t i; for (i = 0; i < data->num_phase2_types; i++) { if (data->phase2_types[i].vendor != EAP_VENDOR_IETF || data->phase2_types[i].method != *pos) continue; data->phase2_type.vendor = data->phase2_types[i].vendor; data->phase2_type.method = data->phase2_types[i].method; wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected " "Phase 2 EAP vendor %d method %d", data->phase2_type.vendor, data->phase2_type.method); break; } } if (*pos != data->phase2_type.method || *pos == EAP_TYPE_NONE) { if (eap_peer_tls_phase2_nak(data->phase2_types, data->num_phase2_types, hdr, resp)) return -1; return 0; } if (data->phase2_priv == NULL) { data->phase2_method = eap_peer_get_eap_method( data->phase2_type.vendor, data->phase2_type.method); if (data->phase2_method) { sm->init_phase2 = 1; data->phase2_priv = data->phase2_method->init(sm); sm->init_phase2 = 0; } } if (data->phase2_priv == NULL || data->phase2_method == NULL) { wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize " "Phase 2 EAP method %d", *pos); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return -1; } data->phase2_eap_started = 1; os_memset(&iret, 0, sizeof(iret)); *resp = data->phase2_method->process(sm, data->phase2_priv, &iret, req); if ((iret.methodState == METHOD_DONE || iret.methodState == METHOD_MAY_CONT) && (iret.decision == DECISION_UNCOND_SUCC || iret.decision == DECISION_COND_SUCC)) { data->phase2_eap_success = 1; data->phase2_success = 1; } break; } if (*resp == NULL && (config->pending_req_identity || config->pending_req_password || config->pending_req_otp || config->pending_req_new_password)) { wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); } return 0; }
static int eap_fast_phase2_request(struct eap_sm *sm, struct eap_fast_data *data, struct eap_method_ret *ret, struct eap_hdr *hdr, struct wpabuf **resp) { size_t len = be_to_host16(hdr->length); u8 *pos; struct eap_method_ret iret; struct eap_peer_config *config = eap_get_config(sm); struct wpabuf msg; if (len <= sizeof(struct eap_hdr)) { wpa_printf(MSG_INFO, "EAP-FAST: too short " "Phase 2 request (len=%lu)", (unsigned long) len); return -1; } pos = (u8 *) (hdr + 1); wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: type=%d", *pos); if (*pos == EAP_TYPE_IDENTITY) { *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); return 0; } if (data->phase2_priv && data->phase2_method && *pos != data->phase2_type.method) { wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 EAP sequence - " "deinitialize previous method"); data->phase2_method->deinit(sm, data->phase2_priv); data->phase2_method = NULL; data->phase2_priv = NULL; data->phase2_type.vendor = EAP_VENDOR_IETF; data->phase2_type.method = EAP_TYPE_NONE; } if (data->phase2_type.vendor == EAP_VENDOR_IETF && data->phase2_type.method == EAP_TYPE_NONE && eap_fast_select_phase2_method(data, *pos) < 0) { if (eap_peer_tls_phase2_nak(data->phase2_types, data->num_phase2_types, hdr, resp)) return -1; return 0; } if (data->phase2_priv == NULL && eap_fast_init_phase2_method(sm, data) < 0) { wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize " "Phase 2 EAP method %d", *pos); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return -1; } os_memset(&iret, 0, sizeof(iret)); wpabuf_set(&msg, hdr, len); *resp = data->phase2_method->process(sm, data->phase2_priv, &iret, &msg); if (*resp == NULL || (iret.methodState == METHOD_DONE && iret.decision == DECISION_FAIL)) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; } else if ((iret.methodState == METHOD_DONE || iret.methodState == METHOD_MAY_CONT) && (iret.decision == DECISION_UNCOND_SUCC || iret.decision == DECISION_COND_SUCC)) { data->phase2_success = 1; } if (*resp == NULL && config && (config->pending_req_identity || config->pending_req_password || config->pending_req_otp || config->pending_req_new_password)) { wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); } else if (*resp == NULL) return -1; return 0; }
int eap_peer_step(void) { unsigned char data[0x4000]; int res; res = eap_peer_sm_step(eap_ctx.eap); /* This part was not tested properly */ if( !eap_ctx.eapSuccess && !eap_ctx.eapRestart && !eap_ctx.eapFail && !eap_ctx.eapResp && !eap_ctx.eapNoResp && !eap_ctx.eapReq ) { struct wpabuf *resp; resp = eap_sm_buildIdentity( eap_ctx.eap, 0, 0 ); if (resp) { // Send EAP response to the server memcpy(data,wpabuf_head(resp),wpabuf_len(resp)); // memcpy Maybe useless!!!! eap_server_rx(data, wpabuf_len(resp)); wpabuf_free(resp); } } if (eap_ctx.eapResp) { struct wpabuf *resp; eap_ctx.eapResp = FALSE; resp = eap_get_eapRespData(eap_ctx.eap); if (resp) { /* Send EAP response to the server */ memcpy(data,wpabuf_head(resp),wpabuf_len(resp)); // memcpy Maybe useless!!!! eap_server_rx(data, wpabuf_len(resp)); //eap_server_rx(wpabuf_head(resp), // wpabuf_len(resp)); wpabuf_free(resp); } } if (eap_ctx.eapSuccess) { res = 0; if (eap_key_available(eap_ctx.eap)) { const u8 *key; size_t key_len; key = eap_get_eapKeyData(eap_ctx.eap, &key_len); memcpy(data,key,key_len); eap_key(data, key_len); wpa_hexdump(MSG_DEBUG, "EAP keying material", key, key_len); } } if (eap_ctx.eapFail) { res = -1; } return res; }
static int eap_ttls_phase2_request_eap(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, struct eap_hdr *hdr, u8 **resp, size_t *resp_len) { size_t len = be_to_host16(hdr->length); u8 *pos; struct eap_method_ret iret; struct wpa_ssid *config = eap_get_config(sm); if (len <= sizeof(struct eap_hdr)) { wpa_printf(MSG_INFO, "EAP-TTLS: too short " "Phase 2 request (len=%lu)", (unsigned long) len); return -1; } pos = (u8 *) (hdr + 1); wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos); switch (*pos) { case EAP_TYPE_IDENTITY: *resp = eap_sm_buildIdentity(sm, hdr->identifier, resp_len, 1); break; default: if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF && data->phase2_eap_type.method == EAP_TYPE_NONE) { size_t i; for (i = 0; i < data->num_phase2_eap_types; i++) { if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF || data->phase2_eap_types[i].method != *pos) continue; data->phase2_eap_type.vendor = data->phase2_eap_types[i].vendor; data->phase2_eap_type.method = data->phase2_eap_types[i].method; wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " "Phase 2 EAP vendor %d method %d", data->phase2_eap_type.vendor, data->phase2_eap_type.method); break; } } if (*pos != data->phase2_eap_type.method || *pos == EAP_TYPE_NONE) { if (eap_ttls_phase2_nak(data, hdr, resp, resp_len)) return -1; break; } if (data->phase2_priv == NULL) { data->phase2_method = eap_sm_get_eap_methods( EAP_VENDOR_IETF, *pos); if (data->phase2_method) { sm->init_phase2 = 1; sm->mschapv2_full_key = 1; data->phase2_priv = data->phase2_method->init(sm); sm->init_phase2 = 0; sm->mschapv2_full_key = 0; } } if (data->phase2_priv == NULL || data->phase2_method == NULL) { wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize " "Phase 2 EAP method %d", *pos); return -1; } os_memset(&iret, 0, sizeof(iret)); *resp = data->phase2_method->process(sm, data->phase2_priv, &iret, (u8 *) hdr, len, resp_len); if ((iret.methodState == METHOD_DONE || iret.methodState == METHOD_MAY_CONT) && (iret.decision == DECISION_UNCOND_SUCC || iret.decision == DECISION_COND_SUCC || iret.decision == DECISION_FAIL)) { ret->methodState = iret.methodState; ret->decision = iret.decision; } if (data->ttls_version > 0) { const struct eap_method *m = data->phase2_method; void *priv = data->phase2_priv; /* TTLSv1 requires TLS/IA FinalPhaseFinished */ if (ret->decision == DECISION_UNCOND_SUCC) ret->decision = DECISION_COND_SUCC; ret->methodState = METHOD_CONT; if (ret->decision == DECISION_COND_SUCC && m->isKeyAvailable && m->getKey && m->isKeyAvailable(sm, priv)) { u8 *key; size_t key_len; key = m->getKey(sm, priv, &key_len); if (key) { eap_ttls_ia_permute_inner_secret( sm, data, key, key_len); os_free(key); } } } break; } if (*resp == NULL && (config->pending_req_identity || config->pending_req_password || config->pending_req_otp)) { return 0; } if (*resp == NULL) return -1; wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response", *resp, *resp_len); return eap_ttls_avp_encapsulate(resp, resp_len, RADIUS_ATTR_EAP_MESSAGE, 1); }