eap_ttls.c
来自「hostapd无线AP工具」· C语言 代码 · 共 1,190 行 · 第 1/3 页
C
1,190 行
req->identifier = id; pos = (u8 *) (req + 1); *pos++ = EAP_TYPE_TTLS; *pos++ = data->ttls_version; res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, plain, plain_len, pos, data->ssl.tls_out_limit); if (res < 0) { wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt Phase 2 " "data"); free(req); return NULL; } *out_len = sizeof(struct eap_hdr) + 2 + res; req->length = host_to_be16(*out_len); 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; int i; 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="); for (i = 0; i < sizeof(data->mschapv2_auth_response); i++) { pos += snprintf((char *) pos, end - pos, "%02X", data->mschapv2_auth_response[i]); } } 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_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); 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 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) { wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: No 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, 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){ MD5_CTX context; u8 *chal, hash[MD5_MAC_LEN]; 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) { wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: No user password " "configured"); eap_ttls_state(data, FAILURE); return; } chal = eap_tls_derive_key(sm, &data->ssl, "ttls challenge", 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) */ MD5Init(&context); MD5Update(&context, password, 1); MD5Update(&context, sm->user->password, sm->user->password_len); MD5Update(&context, challenge, challenge_len); MD5Final(hash, &context); 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, 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_tls_derive_key(sm, &data->ssl, "ttls challenge", 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); 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, 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_tls_derive_key(sm, &data->ssl, "ttls challenge", 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); 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; 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];}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?