📄 eap_peap.c
字号:
encr_req = eap_server_tls_encrypt(sm, &data->ssl, (u8 *) hdr, req_len); os_free(hdr); return encr_req;}static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id){ struct eap_peap_data *data = priv; if (data->ssl.state == FRAG_ACK) { return eap_server_tls_build_ack(id, EAP_TYPE_PEAP, data->peap_version); } if (data->ssl.state == WAIT_FRAG_ACK) { return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, data->peap_version, id); } switch (data->state) { case START: return eap_peap_build_start(sm, data, id); case PHASE1: case PHASE1_ID2: if (data->peap_version < 2 && tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, " "starting Phase2"); eap_peap_state(data, PHASE2_START); } break; case PHASE2_ID: case PHASE2_METHOD: wpabuf_free(data->ssl.out_buf); data->ssl.out_used = 0; data->ssl.out_buf = eap_peap_build_phase2_req(sm, data, id); break;#ifdef EAP_TNC case PHASE2_SOH: wpabuf_free(data->ssl.out_buf); data->ssl.out_used = 0; data->ssl.out_buf = eap_peap_build_phase2_soh(sm, data, id); break;#endif /* EAP_TNC */ case PHASE2_TLV: wpabuf_free(data->ssl.out_buf); data->ssl.out_used = 0; data->ssl.out_buf = eap_peap_build_phase2_tlv(sm, data, id); break; case SUCCESS_REQ: wpabuf_free(data->ssl.out_buf); data->ssl.out_used = 0; data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id, 1); break; case FAILURE_REQ: wpabuf_free(data->ssl.out_buf); data->ssl.out_used = 0; data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id, 0); break; default: wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", __func__, data->state); return NULL; } return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, data->peap_version, id);}static Boolean eap_peap_check(struct eap_sm *sm, void *priv, struct wpabuf *respData){ const u8 *pos; size_t len; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame"); return TRUE; } return FALSE;}static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data, 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); if (!data->phase2_method) return -1; sm->init_phase2 = 1; data->phase2_priv = data->phase2_method->init(sm); sm->init_phase2 = 0; return 0;}static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, struct eap_peap_data *data, const u8 *crypto_tlv, size_t crypto_tlv_len){ u8 buf[61], mac[SHA1_MAC_LEN]; const u8 *pos; if (crypto_tlv_len != 4 + 56) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " "length %d", (int) crypto_tlv_len); return -1; } pos = crypto_tlv; pos += 4; /* TLV header */ if (pos[1] != data->peap_version) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " "mismatch (was %d; expected %d)", pos[1], data->peap_version); return -1; } if (pos[3] != 1) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " "SubType %d", pos[3]); return -1; } pos += 4; pos += 32; /* Nonce */ /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ os_memcpy(buf, crypto_tlv, 60); os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ buf[60] = EAP_TYPE_PEAP; hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " "cryptobinding TLV"); wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20); wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data", buf, 61); return -1; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); return 0;}static void eap_peap_process_phase2_tlv(struct eap_sm *sm, struct eap_peap_data *data, struct wpabuf *in_data){ const u8 *pos; size_t left; const u8 *result_tlv = NULL, *crypto_tlv = NULL; size_t result_tlv_len = 0, crypto_tlv_len = 0; int tlv_type, mandatory, tlv_len; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left); if (pos == NULL) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header"); return; } /* Parse TLVs */ wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left); while (left >= 4) { mandatory = !!(pos[0] & 0x80); tlv_type = pos[0] & 0x3f; tlv_type = (tlv_type << 8) | pos[1]; tlv_len = ((int) pos[2] << 8) | pos[3]; pos += 4; left -= 4; if ((size_t) tlv_len > left) { wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " "(tlv_len=%d left=%lu)", tlv_len, (unsigned long) left); eap_peap_state(data, FAILURE); return; } switch (tlv_type) { case EAP_TLV_RESULT_TLV: result_tlv = pos; result_tlv_len = tlv_len; break; case EAP_TLV_CRYPTO_BINDING_TLV: crypto_tlv = pos; crypto_tlv_len = tlv_len; break; default: wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " "%d%s", tlv_type, mandatory ? " (mandatory)" : ""); if (mandatory) { eap_peap_state(data, FAILURE); return; } /* Ignore this TLV, but process other TLVs */ break; } pos += tlv_len; left -= tlv_len; } if (left) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " "Request (left=%lu)", (unsigned long) left); eap_peap_state(data, FAILURE); return; } /* Process supported TLVs */ if (crypto_tlv && data->crypto_binding_sent) { wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", crypto_tlv, crypto_tlv_len); if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, crypto_tlv_len + 4) < 0) { eap_peap_state(data, FAILURE); return; } data->crypto_binding_used = 1; } else if (!crypto_tlv && data->crypto_binding_sent && data->crypto_binding == REQUIRE_BINDING) { wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); eap_peap_state(data, FAILURE); return; } if (result_tlv) { int status; const char *requested; wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV", result_tlv, result_tlv_len); if (result_tlv_len < 2) { wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV " "(len=%lu)", (unsigned long) result_tlv_len); eap_peap_state(data, FAILURE); return; } requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" : "Failure"; status = WPA_GET_BE16(result_tlv); 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) eap_peap_state(data, SUCCESS); else eap_peap_state(data, FAILURE); } else if (status == EAP_TLV_RESULT_FAILURE) { wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure " "- requested %s", requested); eap_peap_state(data, FAILURE); } else { wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result " "Status %d", status); eap_peap_state(data, FAILURE); } }}#ifdef EAP_TNCstatic void eap_peap_process_phase2_soh(struct eap_sm *sm, struct eap_peap_data *data, struct wpabuf *in_data){ const u8 *pos, *vpos; size_t left; const u8 *soh_tlv = NULL; size_t soh_tlv_len = 0; int tlv_type, mandatory, tlv_len, vtlv_len; u8 next_type; u32 vendor_id; pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left); if (pos == NULL) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP " "Extensions Method header - skip TNC"); goto auth_method; } /* Parse TLVs */ wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left); while (left >= 4) { mandatory = !!(pos[0] & 0x80); tlv_type = pos[0] & 0x3f; tlv_type = (tlv_type << 8) | pos[1]; tlv_len = ((int) pos[2] << 8) | pos[3]; pos += 4; left -= 4; if ((size_t) tlv_len > left) { wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " "(tlv_len=%d left=%lu)", tlv_len, (unsigned long) left); eap_peap_state(data, FAILURE); return; } switch (tlv_type) { case EAP_TLV_VENDOR_SPECIFIC_TLV: if (tlv_len < 4) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short " "vendor specific TLV (len=%d)", (int) tlv_len); eap_peap_state(data, FAILURE); return; } vendor_id = WPA_GET_BE32(pos); if (vendor_id != EAP_VENDOR_MICROSOFT) { if (mandatory) { eap_peap_state(data, FAILURE); return; } break; } vpos = pos + 4; mandatory = !!(vpos[0] & 0x80); tlv_type = vpos[0] & 0x3f; tlv_type = (tlv_type << 8) | vpos[1]; vtlv_len = ((int) vpos[2] << 8) | vpos[3]; vpos += 4; if (vpos + vtlv_len > pos + left) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV " "underrun"); eap_peap_state(data, FAILURE); return; } if (tlv_type == 1) { soh_tlv = vpos; soh_tlv_len = vtlv_len; break; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV " "Type %d%s", tlv_type, mandatory ? " (mandatory)" : ""); if (mandatory) { eap_peap_state(data, FAILURE); return; } /* Ignore this TLV, but process other TLVs */ break; default: wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " "%d%s", tlv_type, mandatory ? " (mandatory)" : ""); if (mandatory) { eap_peap_state(data, FAILURE); return; } /* Ignore this TLV, but process other TLVs */ break; } pos += tlv_len; left -= tlv_len; } if (left) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " "Request (left=%lu)", (unsigned long) left); eap_peap_state(data, FAILURE); return; } /* Process supported TLVs */ if (soh_tlv) { int failure = 0; wpabuf_free(data->soh_response); data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len, &failure); if (failure) { eap_peap_state(data, FAILURE); return; } } else { wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received"); eap_peap_state(data, FAILURE); return; }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);}#endif /* EAP_TNC */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; const struct eap_hdr *hdr; const u8 *pos; size_t left; if (data->state == PHASE2_TLV) { eap_peap_process_phase2_tlv(sm, data, in_data); return; }#ifdef EAP_TNC if (data->state == PHASE2_SOH) { eap_peap_process_phase2_soh(sm, data, in_data); return; }#endif /* EAP_TNC */ if (data->phase2_priv == NULL) { wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not " "initialized?!", __func__); return; } hdr = wpabuf_head(in_data); pos = (const u8 *) (hdr + 1); if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { left = wpabuf_len(in_data) - sizeof(*hdr); wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; " "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) { next_type = sm->user->methods[ sm->user_eap_method_index++].method; wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type); } else { eap_peap_req_failure(sm, data); next_type = EAP_TYPE_NONE; } eap_peap_phase2_init(sm, data, next_type); return; } if (data->phase2_method->check(sm, data->phase2_priv, in_data)) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to " "ignore the packet"); return; } data->phase2_method->process(sm, data->phase2_priv, in_data); if (sm->method_pending == METHOD_PENDING_WAIT) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in " "pending wait state - save decrypted response"); wpabuf_free(data->pending_phase2_resp); data->pending_phase2_resp = wpabuf_dup(in_data); } if (!data->phase2_method->isDone(sm, data->phase2_priv)) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -