📄 eap_ttls.c
字号:
return (u8 *) req;}static u8 * eap_ttls_build_phase2_eap_req(struct eap_sm *sm, struct eap_ttls_data *data, int id, size_t *reqDataLen){ u8 *req, *encr_req; size_t req_len; req = data->phase2_method->buildReq(sm, data->phase2_priv, id, &req_len); if (req == NULL) return NULL; wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encapsulate Phase 2 data", req, req_len); if (eap_ttls_avp_encapsulate(&req, &req_len, RADIUS_ATTR_EAP_MESSAGE, 1) < 0) { wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Failed to encapsulate " "packet"); return NULL; } wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase " "2 data", req, req_len); encr_req = eap_ttls_encrypt(sm, data, id, req, req_len, reqDataLen); free(req); return encr_req;}static u8 * eap_ttls_build_phase2_mschapv2(struct eap_sm *sm, struct eap_ttls_data *data, int id, size_t *reqDataLen){ u8 *req, *encr_req, *pos, *end; size_t req_len; pos = req = malloc(100); if (req == NULL) return NULL; end = req + 200; if (data->mschapv2_resp_ok) { pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_SUCCESS, RADIUS_VENDOR_ID_MICROSOFT, 1, 43); *pos++ = data->mschapv2_ident; pos += snprintf((char *) pos, end - pos, "S="); pos += wpa_snprintf_hex_uppercase( (char *) pos, end - pos, data->mschapv2_auth_response, sizeof(data->mschapv2_auth_response)); } else { pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_ERROR, RADIUS_VENDOR_ID_MICROSOFT, 1, 6); memcpy(pos, "Failed", 6); pos += 6; AVP_PAD(req, pos); } req_len = pos - req; wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 " "data", req, req_len); encr_req = eap_ttls_encrypt(sm, data, id, req, req_len, reqDataLen); free(req); return encr_req;}static u8 * eap_ttls_build_phase_finished(struct eap_sm *sm, struct eap_ttls_data *data, int id, int final, size_t *reqDataLen){ int len; struct eap_hdr *req; u8 *pos; const int max_len = 300; len = sizeof(struct eap_hdr) + 2 + max_len; req = malloc(len); if (req == NULL) return NULL; req->code = EAP_CODE_REQUEST; req->identifier = id; pos = (u8 *) (req + 1); *pos++ = EAP_TYPE_TTLS; *pos++ = data->ttls_version; len = tls_connection_ia_send_phase_finished(sm->ssl_ctx, data->ssl.conn, final, pos, max_len); if (len < 0) { free(req); return NULL; } *reqDataLen = sizeof(struct eap_hdr) + 2 + len; req->length = host_to_be16(*reqDataLen); return (u8 *) req;}static u8 * eap_ttls_buildReq(struct eap_sm *sm, void *priv, int id, size_t *reqDataLen){ struct eap_ttls_data *data = priv; switch (data->state) { case START: return eap_ttls_build_start(sm, data, id, reqDataLen); case PHASE1: return eap_ttls_build_req(sm, data, id, reqDataLen); case PHASE2_METHOD: return eap_ttls_build_phase2_eap_req(sm, data, id, reqDataLen); case PHASE2_MSCHAPV2_RESP: return eap_ttls_build_phase2_mschapv2(sm, data, id, reqDataLen); case PHASE_FINISHED: return eap_ttls_build_phase_finished(sm, data, id, 1, reqDataLen); default: wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", __func__, data->state); return NULL; }}static Boolean eap_ttls_check(struct eap_sm *sm, void *priv, u8 *respData, size_t respDataLen){ struct eap_hdr *resp; u8 *pos; size_t len; resp = (struct eap_hdr *) respData; pos = (u8 *) (resp + 1); if (respDataLen < sizeof(*resp) + 2 || *pos != EAP_TYPE_TTLS || (len = ntohs(resp->length)) > respDataLen) { wpa_printf(MSG_INFO, "EAP-TTLS: Invalid frame"); return TRUE; } return FALSE;}static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm, struct eap_ttls_data *data, const u8 *key, size_t key_len){ u8 *buf; size_t buf_len; int ret; if (key) { buf_len = 2 + key_len; buf = malloc(buf_len); if (buf == NULL) return -1; WPA_PUT_BE16(buf, key_len); memcpy(buf + 2, key, key_len); } else { buf = NULL; buf_len = 0; } wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner " "secret permutation", buf, buf_len); ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx, data->ssl.conn, buf, buf_len); free(buf); return ret;}static void eap_ttls_process_phase2_pap(struct eap_sm *sm, struct eap_ttls_data *data, const u8 *user_password, size_t user_password_len){ /* TODO: add support for verifying that the user entry accepts * EAP-TTLS/PAP. */ if (!sm->user || !sm->user->password || sm->user->password_hash) { wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: No plaintext user " "password configured"); eap_ttls_state(data, FAILURE); return; } if (sm->user->password_len != user_password_len || memcmp(sm->user->password, user_password, user_password_len) != 0) { wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Invalid user password"); eap_ttls_state(data, FAILURE); return; } wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Correct user password"); eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED : SUCCESS);}static void eap_ttls_process_phase2_chap(struct eap_sm *sm, struct eap_ttls_data *data, const u8 *challenge, size_t challenge_len, const u8 *password, size_t password_len){ u8 *chal, hash[MD5_MAC_LEN]; const u8 *addr[3]; size_t len[3]; if (challenge == NULL || password == NULL || challenge_len != EAP_TTLS_CHAP_CHALLENGE_LEN || password_len != 1 + EAP_TTLS_CHAP_PASSWORD_LEN) { wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid CHAP attributes " "(challenge len %lu password len %lu)", (unsigned long) challenge_len, (unsigned long) password_len); eap_ttls_state(data, FAILURE); return; } /* TODO: add support for verifying that the user entry accepts * EAP-TTLS/CHAP. */ if (!sm->user || !sm->user->password || sm->user->password_hash) { wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: No plaintext user " "password configured"); eap_ttls_state(data, FAILURE); return; } chal = eap_ttls_implicit_challenge(sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1); if (chal == NULL) { wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Failed to generate " "challenge from TLS data"); eap_ttls_state(data, FAILURE); return; } if (memcmp(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN) != 0 || password[0] != chal[EAP_TTLS_CHAP_CHALLENGE_LEN]) { wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Challenge mismatch"); free(chal); eap_ttls_state(data, FAILURE); return; } free(chal); /* MD5(Ident + Password + Challenge) */ addr[0] = password; len[0] = 1; addr[1] = sm->user->password; len[1] = sm->user->password_len; addr[2] = challenge; len[2] = challenge_len; md5_vector(3, addr, len, hash); if (memcmp(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 0) { wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password"); eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED : SUCCESS); } else { wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid user password"); eap_ttls_state(data, FAILURE); }}static void eap_ttls_process_phase2_mschap(struct eap_sm *sm, struct eap_ttls_data *data, u8 *challenge, size_t challenge_len, u8 *response, size_t response_len){ u8 *chal, nt_response[24]; if (challenge == NULL || response == NULL || challenge_len != EAP_TTLS_MSCHAP_CHALLENGE_LEN || response_len != EAP_TTLS_MSCHAP_RESPONSE_LEN) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid MS-CHAP " "attributes (challenge len %lu response len %lu)", (unsigned long) challenge_len, (unsigned long) response_len); eap_ttls_state(data, FAILURE); return; } /* TODO: add support for verifying that the user entry accepts * EAP-TTLS/MSCHAP. */ if (!sm->user || !sm->user->password) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: No user password " "configured"); eap_ttls_state(data, FAILURE); return; } chal = eap_ttls_implicit_challenge(sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); if (chal == NULL) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Failed to generate " "challenge from TLS data"); eap_ttls_state(data, FAILURE); return; } if (memcmp(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN) != 0 || response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Challenge mismatch"); free(chal); eap_ttls_state(data, FAILURE); return; } free(chal); if (sm->user->password_hash) challenge_response(challenge, sm->user->password, nt_response); else nt_challenge_response(challenge, sm->user->password, sm->user->password_len, nt_response); if (memcmp(nt_response, response + 2 + 24, 24) == 0) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response"); eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED : SUCCESS); } else { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid NT-Response"); wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Received", response + 2 + 24, 24); wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Expected", nt_response, 24); eap_ttls_state(data, FAILURE); }}static void eap_ttls_process_phase2_mschapv2(struct eap_sm *sm, struct eap_ttls_data *data, u8 *challenge, size_t challenge_len, u8 *response, size_t response_len){ u8 *chal, *username, nt_response[24], *pos, *rx_resp, *peer_challenge, *auth_challenge; size_t username_len; int i; if (challenge == NULL || response == NULL || challenge_len != EAP_TTLS_MSCHAPV2_CHALLENGE_LEN || response_len != EAP_TTLS_MSCHAPV2_RESPONSE_LEN) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid MS-CHAP2 " "attributes (challenge len %lu response len %lu)", (unsigned long) challenge_len, (unsigned long) response_len); eap_ttls_state(data, FAILURE); return; } /* TODO: add support for verifying that the user entry accepts * EAP-TTLS/MSCHAPV2. */ if (!sm->user || !sm->user->password) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user password " "configured"); eap_ttls_state(data, FAILURE); return; } /* MSCHAPv2 does not include optional domain name in the * challenge-response calculation, so remove domain prefix * (if present). */ username = sm->identity; username_len = sm->identity_len; pos = username; for (i = 0; i < username_len; i++) { if (username[i] == '\\') { username_len -= i + 1; username += i + 1; break; } } chal = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); if (chal == NULL) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Failed to generate " "challenge from TLS data"); eap_ttls_state(data, FAILURE); return; } if (memcmp(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) != 0 || response[0] != chal[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Challenge mismatch"); free(chal); eap_ttls_state(data, FAILURE); return; } free(chal); auth_challenge = challenge; peer_challenge = response + 2; wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: User", username, username_len); wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: auth_challenge", auth_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: peer_challenge", peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); if (sm->user->password_hash) { generate_nt_response_pwhash(auth_challenge, peer_challenge, username, username_len, sm->user->password, nt_response); } else { generate_nt_response(auth_challenge, peer_challenge, username, username_len, sm->user->password, sm->user->password_len, nt_response); } rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8; if (memcmp(nt_response, rx_resp, 24) == 0) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct " "NT-Response"); data->mschapv2_resp_ok = 1; if (data->ttls_version > 0) { const u8 *pw_hash; u8 pw_hash_buf[16], pw_hash_hash[16], master_key[16]; u8 session_key[2 * MSCHAPV2_KEY_LEN]; if (sm->user->password_hash) pw_hash = sm->user->password; else { nt_password_hash(sm->user->password, sm->user->password_len, pw_hash_buf); pw_hash = pw_hash_buf; } hash_nt_password_hash(pw_hash, pw_hash_hash); get_master_key(pw_hash_hash, nt_response, master_key); get_asymetric_start_key(master_key, session_key, MSCHAPV2_KEY_LEN, 0, 0); get_asymetric_start_key(master_key, session_key + MSCHAPV2_KEY_LEN, MSCHAPV2_KEY_LEN, 1, 0); eap_ttls_ia_permute_inner_secret(sm, data, session_key, sizeof(session_key)); } if (sm->user->password_hash) { generate_authenticator_response_pwhash( sm->user->password, peer_challenge, auth_challenge, username, username_len, nt_response, data->mschapv2_auth_response); } else { generate_authenticator_response( sm->user->password, sm->user->password_len, peer_challenge, auth_challenge, username, username_len, nt_response, data->mschapv2_auth_response); } } else { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid " "NT-Response"); wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Received", rx_resp, 24); wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Expected", nt_response, 24); data->mschapv2_resp_ok = 0; } eap_ttls_state(data, PHASE2_MSCHAPV2_RESP); data->mschapv2_ident = response[0];}static int eap_ttls_phase2_eap_init(struct eap_sm *sm, struct eap_ttls_data *data, EapType eap_type)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -