static void eap_eke_process_identity(struct eap_sm *sm,
				     struct eap_eke_data *data,
				     const struct wpabuf *respData,
				     const u8 *payload, size_t payloadlen)
{
	const u8 *pos, *end;
	int i;

	wpa_printf(MSG_DEBUG, "EAP-EKE: Received Response/Identity");

	if (data->state != IDENTITY) {
		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
		return;
	}

	pos = payload;
	end = payload + payloadlen;

	if (pos + 2 + 4 + 1 > end) {
		wpa_printf(MSG_INFO, "EAP-EKE: Too short EAP-EKE-ID payload");
		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
		return;
	}

	if (*pos != 1) {
		wpa_printf(MSG_INFO, "EAP-EKE: Unexpected NumProposals %d (expected 1)",
			   *pos);
		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
		return;
	}

	pos += 2;

	if (!supported_proposal(pos)) {
		wpa_printf(MSG_INFO, "EAP-EKE: Unexpected Proposal (%u:%u:%u:%u)",
			   pos[0], pos[1], pos[2], pos[3]);
		eap_eke_fail(data, EAP_EKE_FAIL_PROTO_ERROR);
		return;
	}

	wpa_printf(MSG_DEBUG, "EAP-EKE: Selected Proposal (%u:%u:%u:%u)",
		   pos[0], pos[1], pos[2], pos[3]);
	if (eap_eke_session_init(&data->sess, pos[0], pos[1], pos[2], pos[3]) <
	    0) {
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return;
	}
	pos += 4;

	data->peerid_type = *pos++;
	os_free(data->peerid);
	data->peerid = os_memdup(pos, end - pos);
	if (data->peerid == NULL) {
		wpa_printf(MSG_INFO, "EAP-EKE: Failed to allocate memory for peerid");
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return;
	}
	data->peerid_len = end - pos;
	wpa_printf(MSG_DEBUG, "EAP-EKE: Peer IDType %u", data->peerid_type);
	wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Peer Identity",
			  data->peerid, data->peerid_len);

	if (eap_user_get(sm, data->peerid, data->peerid_len, data->phase2)) {
		wpa_printf(MSG_INFO, "EAP-EKE: Peer Identity not found from user database");
		eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
		return;
	}

	for (i = 0; i < EAP_MAX_METHODS; i++) {
		if (sm->user->methods[i].vendor == EAP_VENDOR_IETF &&
		    sm->user->methods[i].method == EAP_TYPE_EKE)
			break;
	}
	if (i == EAP_MAX_METHODS) {
		wpa_printf(MSG_INFO, "EAP-EKE: Matching user entry does not allow EAP-EKE");
		eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
		return;
	}

	if (sm->user->password == NULL || sm->user->password_len == 0) {
		wpa_printf(MSG_INFO, "EAP-EKE: No password configured for peer");
		eap_eke_fail(data, EAP_EKE_FAIL_PASSWD_NOT_FOUND);
		return;
	}

	if (wpabuf_resize(&data->msgs, wpabuf_len(respData)) < 0) {
		eap_eke_fail(data, EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
		return;
	}
	wpabuf_put_buf(data->msgs, respData);

	eap_eke_state(data, COMMIT);
}
示例#2
0
static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data,
					  struct eap_method_ret *ret,
					  const struct wpabuf *reqData,
					  const u8 *payload,
					  size_t payload_len)
{
	struct wpabuf *resp;
	unsigned num_prop, i;
	const u8 *pos, *end;
	const u8 *prop = NULL;
	u8 idtype;
	u8 id = eap_get_id(reqData);

	if (data->state != IDENTITY) {
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PROTO_ERROR);
	}

	wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-ID/Request");

	if (payload_len < 2 + 4) {
		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data");
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PROTO_ERROR);
	}

	pos = payload;
	end = payload + payload_len;

	num_prop = *pos++;
	pos++; /* Ignore Reserved field */

	if (pos + num_prop * 4 > end) {
		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data (num_prop=%u)",
			   num_prop);
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PROTO_ERROR);
	}

	for (i = 0; i < num_prop; i++) {
		const u8 *tmp = pos;

		wpa_printf(MSG_DEBUG, "EAP-EKE: Proposal #%u: dh=%u encr=%u prf=%u mac=%u",
			   i, pos[0], pos[1], pos[2], pos[3]);
		pos += 4;

		if ((data->dhgroup && data->dhgroup != *tmp) ||
		    !eap_eke_supp_dhgroup(*tmp))
			continue;
		tmp++;
		if ((data->encr && data->encr != *tmp) ||
		    !eap_eke_supp_encr(*tmp))
			continue;
		tmp++;
		if ((data->prf && data->prf != *tmp) ||
		    !eap_eke_supp_prf(*tmp))
			continue;
		tmp++;
		if ((data->mac && data->mac != *tmp) ||
		    !eap_eke_supp_mac(*tmp))
			continue;

		prop = tmp - 3;
		if (eap_eke_session_init(&data->sess, prop[0], prop[1], prop[2],
					 prop[3]) < 0) {
			prop = NULL;
			continue;
		}

		wpa_printf(MSG_DEBUG, "EAP-EKE: Selected proposal");
		break;
	}

	if (prop == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-EKE: No acceptable proposal found");
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_NO_PROPOSAL_CHOSEN);
	}

	pos += (num_prop - i - 1) * 4;

	if (pos == end) {
		wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data to include IDType/Identity");
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PROTO_ERROR);
	}

	idtype = *pos++;
	wpa_printf(MSG_DEBUG, "EAP-EKE: Server IDType %u", idtype);
	wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Server Identity",
			  pos, end - pos);
	os_free(data->serverid);
	data->serverid = os_malloc(end - pos);
	if (data->serverid == NULL) {
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
	}
	os_memcpy(data->serverid, pos, end - pos);
	data->serverid_len = end - pos;

	wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-ID/Response");

	resp = eap_eke_build_msg(data, id,
				 2 + 4 + 1 + data->peerid_len,
				 EAP_EKE_ID);
	if (resp == NULL) {
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
	}

	wpabuf_put_u8(resp, 1); /* NumProposals */
	wpabuf_put_u8(resp, 0); /* Reserved */
	wpabuf_put_data(resp, prop, 4); /* Selected Proposal */
	wpabuf_put_u8(resp, EAP_EKE_ID_NAI);
	if (data->peerid)
		wpabuf_put_data(resp, data->peerid, data->peerid_len);

	wpabuf_free(data->msgs);
	data->msgs = wpabuf_alloc(wpabuf_len(reqData) + wpabuf_len(resp));
	if (data->msgs == NULL) {
		wpabuf_free(resp);
		return eap_eke_build_fail(data, ret, id,
					  EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
	}
	wpabuf_put_buf(data->msgs, reqData);
	wpabuf_put_buf(data->msgs, resp);

	eap_eke_state(data, COMMIT);

	return resp;
}