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 + -
显示快捷键?