/*
 * Example application showing how EAP peer code from wpa_supplicant can be
 * used as a library.
 * Copyright (c) 2007, 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_peer/eap.h"
#include "eap_peer/eap_config.h"
#include "wpabuf.h"

void eap_example_server_rx(const u8 *data, size_t data_len);


struct eap_peer_ctx {
	Boolean eapSuccess;
	Boolean eapRestart;
	Boolean eapFail;
	Boolean eapResp;
	Boolean eapNoResp;
	Boolean eapReq;
	Boolean portEnabled;
	Boolean altAccept; /* for EAP */
	Boolean altReject; /* for EAP */
	Boolean eapTriggerStart;

	struct wpabuf *eapReqData; /* for EAP */

	unsigned int idleWhile; /* for EAP state machine */

	struct eap_peer_config eap_config;
	struct eap_sm *eap;
};


static struct eap_peer_ctx eap_ctx;


static struct eap_peer_config * peer_get_config(void *ctx)
{
	struct eap_peer_ctx *peer = ctx;
	return &peer->eap_config;
}


static Boolean peer_get_bool(void *ctx, enum eapol_bool_var variable)
{
	struct eap_peer_ctx *peer = ctx;
	if (peer == NULL)
		return FALSE;
	switch (variable) {
	case EAPOL_eapSuccess:
		return peer->eapSuccess;
	case EAPOL_eapRestart:
		return peer->eapRestart;
	case EAPOL_eapFail:
		return peer->eapFail;
	case EAPOL_eapResp:
		return peer->eapResp;
	case EAPOL_eapNoResp:
		return peer->eapNoResp;
	case EAPOL_eapReq:
		return peer->eapReq;
	case EAPOL_portEnabled:
		return peer->portEnabled;
	case EAPOL_altAccept:
		return peer->altAccept;
	case EAPOL_altReject:
		return peer->altReject;
	case EAPOL_eapTriggerStart:
		return peer->eapTriggerStart;
	}
	return FALSE;
}


static void peer_set_bool(void *ctx, enum eapol_bool_var variable,
			  Boolean value)
{
	struct eap_peer_ctx *peer = ctx;
	if (peer == NULL)
		return;
	switch (variable) {
	case EAPOL_eapSuccess:
		peer->eapSuccess = value;
		break;
	case EAPOL_eapRestart:
		peer->eapRestart = value;
		break;
	case EAPOL_eapFail:
		peer->eapFail = value;
		break;
	case EAPOL_eapResp:
		peer->eapResp = value;
		break;
	case EAPOL_eapNoResp:
		peer->eapNoResp = value;
		break;
	case EAPOL_eapReq:
		peer->eapReq = value;
		break;
	case EAPOL_portEnabled:
		peer->portEnabled = value;
		break;
	case EAPOL_altAccept:
		peer->altAccept = value;
		break;
	case EAPOL_altReject:
		peer->altReject = value;
		break;
	case EAPOL_eapTriggerStart:
		peer->eapTriggerStart = value;
		break;
	}
}


static unsigned int peer_get_int(void *ctx, enum eapol_int_var variable)
{
	struct eap_peer_ctx *peer = ctx;
	if (peer == NULL)
		return 0;
	switch (variable) {
	case EAPOL_idleWhile:
		return peer->idleWhile;
	}
	return 0;
}


static void peer_set_int(void *ctx, enum eapol_int_var variable,
			 unsigned int value)
{
	struct eap_peer_ctx *peer = ctx;
	if (peer == NULL)
		return;
	switch (variable) {
	case EAPOL_idleWhile:
		peer->idleWhile = value;
		break;
	}
}


static struct wpabuf * peer_get_eapReqData(void *ctx)
{
	struct eap_peer_ctx *peer = ctx;
	if (peer == NULL || peer->eapReqData == NULL)
		return NULL;

	return peer->eapReqData;
}


static void peer_set_config_blob(void *ctx, struct wpa_config_blob *blob)
{
	printf("TODO: %s\n", __func__);
}


static const struct wpa_config_blob *
peer_get_config_blob(void *ctx, const char *name)
{
	printf("TODO: %s\n", __func__);
	return NULL;
}


static void peer_notify_pending(void *ctx)
{
	printf("TODO: %s\n", __func__);
}


static int eap_peer_register_methods(void)
{
	int ret = 0;

#ifdef EAP_MD5
	if (ret == 0)
		ret = eap_peer_md5_register();
#endif /* EAP_MD5 */

#ifdef EAP_TLS
	if (ret == 0)
		ret = eap_peer_tls_register();
#endif /* EAP_TLS */

#ifdef EAP_MSCHAPv2
	if (ret == 0)
		ret = eap_peer_mschapv2_register();
#endif /* EAP_MSCHAPv2 */

#ifdef EAP_PEAP
	if (ret == 0)
		ret = eap_peer_peap_register();
#endif /* EAP_PEAP */

#ifdef EAP_TTLS
	if (ret == 0)
		ret = eap_peer_ttls_register();
#endif /* EAP_TTLS */

#ifdef EAP_GTC
	if (ret == 0)
		ret = eap_peer_gtc_register();
#endif /* EAP_GTC */

#ifdef EAP_OTP
	if (ret == 0)
		ret = eap_peer_otp_register();
#endif /* EAP_OTP */

#ifdef EAP_SIM
	if (ret == 0)
		ret = eap_peer_sim_register();
#endif /* EAP_SIM */

#ifdef EAP_LEAP
	if (ret == 0)
		ret = eap_peer_leap_register();
#endif /* EAP_LEAP */

#ifdef EAP_PSK
	if (ret == 0)
		ret = eap_peer_psk_register();
#endif /* EAP_PSK */

#ifdef EAP_AKA
	if (ret == 0)
		ret = eap_peer_aka_register();
#endif /* EAP_AKA */

#ifdef EAP_AKA_PRIME
	if (ret == 0)
		ret = eap_peer_aka_prime_register();
#endif /* EAP_AKA_PRIME */

#ifdef EAP_FAST
	if (ret == 0)
		ret = eap_peer_fast_register();
#endif /* EAP_FAST */

#ifdef EAP_PAX
	if (ret == 0)
		ret = eap_peer_pax_register();
#endif /* EAP_PAX */

#ifdef EAP_SAKE
	if (ret == 0)
		ret = eap_peer_sake_register();
#endif /* EAP_SAKE */

#ifdef EAP_GPSK
	if (ret == 0)
		ret = eap_peer_gpsk_register();
#endif /* EAP_GPSK */

#ifdef EAP_WSC
	if (ret == 0)
		ret = eap_peer_wsc_register();
#endif /* EAP_WSC */

#ifdef EAP_IKEV2
	if (ret == 0)
		ret = eap_peer_ikev2_register();
#endif /* EAP_IKEV2 */

#ifdef EAP_VENDOR_TEST
	if (ret == 0)
		ret = eap_peer_vendor_test_register();
#endif /* EAP_VENDOR_TEST */

#ifdef EAP_TNC
	if (ret == 0)
		ret = eap_peer_tnc_register();
#endif /* EAP_TNC */

	return ret;
}


static struct eapol_callbacks eap_cb;
static struct eap_config eap_conf;

int eap_example_peer_init(void)
{
	if (eap_peer_register_methods() < 0)
		return -1;

	os_memset(&eap_ctx, 0, sizeof(eap_ctx));

	eap_ctx.eap_config.identity = (u8 *) os_strdup("user");
	eap_ctx.eap_config.identity_len = 4;
	eap_ctx.eap_config.password = (u8 *) os_strdup("password");
	eap_ctx.eap_config.password_len = 8;
	eap_ctx.eap_config.ca_cert = (u8 *) os_strdup("ca.pem");
	eap_ctx.eap_config.fragment_size = 1398;

	os_memset(&eap_cb, 0, sizeof(eap_cb));
	eap_cb.get_config = peer_get_config;
	eap_cb.get_bool = peer_get_bool;
	eap_cb.set_bool = peer_set_bool;
	eap_cb.get_int = peer_get_int;
	eap_cb.set_int = peer_set_int;
	eap_cb.get_eapReqData = peer_get_eapReqData;
	eap_cb.set_config_blob = peer_set_config_blob;
	eap_cb.get_config_blob = peer_get_config_blob;
	eap_cb.notify_pending = peer_notify_pending;

	os_memset(&eap_conf, 0, sizeof(eap_conf));
	eap_ctx.eap = eap_peer_sm_init(&eap_ctx, &eap_cb, &eap_ctx, &eap_conf);
	if (eap_ctx.eap == NULL)
		return -1;

	/* Enable "port" to allow authentication */
	eap_ctx.portEnabled = TRUE;

	return 0;
}


void eap_example_peer_deinit(void)
{
	eap_peer_sm_deinit(eap_ctx.eap);
	eap_peer_unregister_methods();
	wpabuf_free(eap_ctx.eapReqData);
	os_free(eap_ctx.eap_config.identity);
	os_free(eap_ctx.eap_config.password);
	os_free(eap_ctx.eap_config.ca_cert);
}


int eap_example_peer_step(void)
{
	int res;
	res = eap_peer_sm_step(eap_ctx.eap);

	if (eap_ctx.eapResp) {
		struct wpabuf *resp;
		printf("==> Response\n");
		eap_ctx.eapResp = FALSE;
		resp = eap_get_eapRespData(eap_ctx.eap);
		if (resp) {
			/* Send EAP response to the server */
			eap_example_server_rx(wpabuf_head(resp),
					      wpabuf_len(resp));
			wpabuf_free(resp);
		}
	}

	if (eap_ctx.eapSuccess) {
		res = 0;
		if (eap_key_available(eap_ctx.eap)) {
			const u8 *key;
			size_t key_len;
			key = eap_get_eapKeyData(eap_ctx.eap, &key_len);
			wpa_hexdump(MSG_DEBUG, "EAP keying material",
				    key, key_len);
		}
	}

	return res;
}


void eap_example_peer_rx(const u8 *data, size_t data_len)
{
	/* Make received EAP message available to the EAP library */
	eap_ctx.eapReq = TRUE;
	wpabuf_free(eap_ctx.eapReqData);
	eap_ctx.eapReqData = wpabuf_alloc_copy(data, data_len);
}
