/*
 * hostapd / EAP-Identity
 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "includes.h"

#include "common.h"
#include "eap_i.h"


struct eap_identity_data {
	enum { CONTINUE, SUCCESS, FAILURE } state;
	int pick_up;
};


static void * eap_identity_init(struct eap_sm *sm)
{
	struct eap_identity_data *data;

	data = os_zalloc(sizeof(*data));
	if (data == NULL)
		return NULL;
	data->state = CONTINUE;

	return data;
}


static void * eap_identity_initPickUp(struct eap_sm *sm)
{
	struct eap_identity_data *data;
	data = eap_identity_init(sm);
	if (data) {
		data->pick_up = 1;
	}
	return data;
}


static void eap_identity_reset(struct eap_sm *sm, void *priv)
{
	struct eap_identity_data *data = priv;
	os_free(data);
}


static struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv,
					     u8 id)
{
	struct eap_identity_data *data = priv;
	struct wpabuf *req;
	const char *req_data;
	size_t req_data_len;

	if (sm->eapol_cb->get_eap_req_id_text) {
		req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx,
							     &req_data_len);
	} else {
		req_data = NULL;
		req_data_len = 0;
	}
	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len,
			    EAP_CODE_REQUEST, id);
	if (req == NULL) {
		wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate "
			   "memory for request");
		data->state = FAILURE;
		return NULL;
	}

	wpabuf_put_data(req, req_data, req_data_len);

	return req;
}


static Boolean eap_identity_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_IDENTITY,
			       respData, &len);
	if (pos == NULL) {
		wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame");
		return TRUE;
	}

	return FALSE;
}


static void eap_identity_process(struct eap_sm *sm, void *priv,
				 struct wpabuf *respData)
{
	struct eap_identity_data *data = priv;
	const u8 *pos;
	size_t len;

	if (data->pick_up) {
		if (eap_identity_check(sm, data, respData)) {
			wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick "
				   "up already started negotiation");
			data->state = FAILURE;
			return;
		}
		data->pick_up = 0;
	}

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
			       respData, &len);
	if (pos == NULL)
		return; /* Should not happen - frame already validated */

	wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len);
	if (sm->identity)
		sm->update_user = TRUE;
	os_free(sm->identity);
	sm->identity = os_malloc(len ? len : 1);
	if (sm->identity == NULL) {
		data->state = FAILURE;
	} else {
		os_memcpy(sm->identity, pos, len);
		sm->identity_len = len;
		data->state = SUCCESS;
	}
}


static Boolean eap_identity_isDone(struct eap_sm *sm, void *priv)
{
	struct eap_identity_data *data = priv;
	return data->state != CONTINUE;
}


static Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv)
{
	struct eap_identity_data *data = priv;
	return data->state == SUCCESS;
}


int eap_server_identity_register(void)
{
	struct eap_method *eap;
	int ret;

	eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
				      EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
				      "Identity");
	if (eap == NULL)
		return -1;

	eap->init = eap_identity_init;
	eap->initPickUp = eap_identity_initPickUp;
	eap->reset = eap_identity_reset;
	eap->buildReq = eap_identity_buildReq;
	eap->check = eap_identity_check;
	eap->process = eap_identity_process;
	eap->isDone = eap_identity_isDone;
	eap->isSuccess = eap_identity_isSuccess;

	ret = eap_server_method_register(eap);
	if (ret)
		eap_server_method_free(eap);
	return ret;
}
