Initial commit

Change-Id: I6a4444e3c193dae437cd7929f4c39aba7b749efa
diff --git a/extensions/app_diameap/diameap_eap.c b/extensions/app_diameap/diameap_eap.c
new file mode 100644
index 0000000..72885ea
--- /dev/null
+++ b/extensions/app_diameap/diameap_eap.c
@@ -0,0 +1,604 @@
+/*****************************************************************************************************
+ * Software License Agreement (BSD License)
+ * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
+ *
+ * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
+ *
+ * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************************************/
+
+#include "diameap_common.h"
+
+static void diameap_ba_nextid(struct eap_state_machine * sm, int * id)
+{
+	TRACE_ENTRY("%p %p",sm,id);
+
+	if (sm->currentId < 0)
+	{
+		*id = (u8) (255 * rand() / RAND_MAX) & 0xFFU;
+	}
+	else
+	{
+		*id = (sm->currentId++) & 0xFFU;
+	}
+	if (*id == sm->lastId)
+	{
+		*id=*id+1;
+	}
+}
+
+static void diameap_ba_policyupdate(struct eap_state_machine * eap_sm,
+		struct eap_packet *eapPacket)
+{
+	TRACE_ENTRY("%p %p",eap_sm, eapPacket);
+	if ((eap_sm->respMethod == TYPE_NAK))
+	{
+		int id;
+		eap_sm->user.pmethods = 0;
+		u32 vendor;
+		eap_type type;
+		u8 *data = (u8 *) eapPacket->data;
+		data += 5;
+		id = 5;
+		while (id < eapPacket->length)
+		{
+			vendor = VENDOR_IETF;
+			type = G8(data);
+			if (diameap_plugin_exist(vendor, type) == TRUE)
+			{
+				eap_sm->user.proposedmethods[id - 5].method = type;
+				eap_sm->user.proposedmethods[id - 5].vendor = vendor;
+				eap_sm->user.pmethods++;
+			}
+			data++;
+			id++;
+		}
+		eap_sm->user.methodId = -1;
+	}
+}
+
+static int diameap_ba_policygetnextmethod(struct eap_state_machine * eap_sm,
+		eap_type * eaptype, u32 * vendor)
+{
+	TRACE_ENTRY("%p %p %p",eap_sm,eaptype,vendor);
+	*vendor = 0;
+	*eaptype = TYPE_NONE;
+	if (eap_sm == NULL)
+	{
+		return EINVAL;
+	}
+
+	eap_sm->selectedMethod = NULL;
+
+	if (eap_sm->user.userid == NULL)
+	{
+		if ((eap_sm->currentMethod == TYPE_NONE))
+		{
+			*vendor = VENDOR_IETF;
+			*eaptype = TYPE_IDENTITY;
+			if (eap_sm->selectedMethod != NULL)
+			{
+				(*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+				eap_sm->methodData = NULL;
+			}
+			CHECK_FCT(diameap_plugin_get(VENDOR_IETF,TYPE_IDENTITY,&eap_sm->selectedMethod));
+			return 0;
+		}
+
+		eap_sm->selectedMethod = NULL;
+		*vendor = 0;
+		*eaptype = TYPE_NONE;
+		return 0;
+	}
+
+	if (eap_sm->user.methodId == -1)
+	{
+		if (eap_sm->user.proposed_eap_method >= TYPE_EAP_MD5)
+		{
+			*vendor = eap_sm->user.proposed_eap_method_vendor;
+			if (*vendor == VENDOR_IETF)
+			{
+				*eaptype = eap_sm->user.proposed_eap_method;
+			}
+			else
+			{
+				*eaptype = TYPE_EXPANDED_TYPES;
+			}
+			if (eap_sm->selectedMethod != NULL)
+			{
+				(*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+				eap_sm->methodData = NULL;
+			}
+			CHECK_FCT_DO(diameap_plugin_get(*vendor,*eaptype,&eap_sm->selectedMethod),
+					{	TRACE_DEBUG(INFO,"%s [EAP Protocol] Invalid EAP-TYPE %d (vendor %d)",DIAMEAP_EXTENSION,*eaptype,*vendor);return 1;});
+
+		}
+		eap_sm->user.proposed_eap_method = TYPE_NONE;
+	}
+	else
+	{
+		*vendor = eap_sm->user.proposedmethods[eap_sm->user.methodId].vendor;
+		if (eap_sm->user.proposedmethods[eap_sm->user.methodId].vendor
+				== VENDOR_IETF)
+		{
+			*eaptype
+					= eap_sm->user.proposedmethods[eap_sm->user.methodId].method;
+		}
+		else
+		{
+			*eaptype = TYPE_EXPANDED_TYPES;
+		}
+		if (eap_sm->selectedMethod != NULL)
+		{
+			(*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+			eap_sm->methodData=NULL;
+		}
+		CHECK_FCT(diameap_plugin_get(eap_sm->user.proposedmethods[eap_sm->user.methodId].vendor,eap_sm->user.proposedmethods[eap_sm->user.methodId].method,&eap_sm->selectedMethod));
+
+		eap_sm->user.methodId++;
+	}
+
+	return 0;
+}
+
+static int diameap_ba_policygetdecision(struct eap_state_machine * eap_sm,
+		struct diameap_eap_interface * eap_i, decision * gdecision)
+{
+	TRACE_ENTRY("%p %p %p",eap_sm,eap_i,gdecision);
+
+	if (eap_sm->user.userid != NULL)
+	{
+
+		if (eap_sm->methodState == EAP_M_END)
+		{
+
+			if (eap_sm->respMethod == TYPE_IDENTITY)
+			{
+
+				*gdecision = DECISION_CONTINUE;
+				return 0;
+			}
+
+			if ((eap_sm->respMethod == TYPE_NAK) || ((eap_sm->respMethod
+					== TYPE_EXPANDED_TYPES) && (eap_sm->respVendor
+					== VENDOR_IETF) && (eap_sm->respVendorMethod == TYPE_NAK)))
+			{
+				goto SelectNextMethod;
+			}
+
+			if (eap_sm->user.success == TRUE)
+			{
+
+				*gdecision = DECISION_SUCCESS;
+			}
+			else
+			{
+
+				*gdecision = DECISION_FAILURE;
+			}
+
+		}
+		else
+		{
+			goto SelectNextMethod;
+		}
+		return 0;
+
+		SelectNextMethod: if ((eap_sm->user.methodId
+				== (MAXPROPOSEDMETHODS - 1))
+				|| ((eap_sm->user.proposedmethods[eap_sm->user.methodId + 1].method
+						== TYPE_NONE)
+						&& (eap_sm->user.proposedmethods[eap_sm->user.methodId
+								+ 1].vendor == VENDOR_IETF)))
+		{
+			TRACE_DEBUG(FULL+1,
+					"%s [EAP protocol] None of proposed EAP Methods authenticated the user.(FAILURE)",DIAMEAP_EXTENSION);
+			*gdecision = DECISION_FAILURE;
+			return 0;
+		}
+
+		eap_sm->user.methodId = 0;
+		*gdecision = DECISION_CONTINUE;
+		return 0;
+	}
+
+	if (eap_sm->currentMethod == TYPE_IDENTITY)
+	{
+		*gdecision = DECISION_FAILURE;
+		return 0;
+	}
+
+	*gdecision = DECISION_CONTINUE;
+	return 0;
+}
+
+static boolean diameap_ba_policydopickup(eap_type type)
+{
+	TRACE_ENTRY("%d",type);
+	if (type == TYPE_IDENTITY)
+	{
+		return TRUE;
+	}
+	return FALSE;
+}
+
+int diameap_eap_statemachine(struct eap_state_machine * eap_sm,
+		struct diameap_eap_interface * eap_i, boolean * non_fatal_error)
+{
+	TRACE_ENTRY("%p %p %p", eap_sm, eap_i, non_fatal_error);
+	int ret;
+
+	if ((eap_sm->eap_state == EAP_IDLE) && (eap_i->aaaEapResp == TRUE))
+	{
+		eap_sm->eap_state = EAP_RECEIVED;
+	}
+	while (!((eap_sm->eap_state == EAP_IDLE) || (eap_sm->eap_state == EAP_END)))
+	{
+		switch (eap_sm->eap_state)
+		{
+		case EAP_INITIALIZE:
+			if (eap_sm->rxResp == TRUE)
+			{
+				eap_sm->lastId = eap_sm->currentId;
+				eap_sm->currentId = eap_sm->respId;
+			}
+			else
+			{
+				eap_sm->lastId = -1;
+				eap_sm->currentId = -1;
+			}
+			if (eap_sm->rxResp == FALSE)
+			{
+				eap_sm->eap_state = EAP_SELECT_ACTION;
+			}
+			else if ((eap_sm->respMethod == TYPE_NAK) || (eap_sm->respMethod
+					== TYPE_EXPANDED_TYPES && eap_sm->respVendor == VENDOR_IETF
+					&& eap_sm->respVendorMethod == TYPE_NAK))
+			{
+				eap_sm->eap_state = EAP_NAK;
+			}
+			else
+			{
+				eap_sm->eap_state = EAP_PICK_UP_METHOD;
+			}
+			break;
+		case EAP_PICK_UP_METHOD:
+			if (diameap_ba_policydopickup(eap_sm->respMethod) == TRUE)
+			{
+				eap_sm->currentMethod = eap_sm->respMethod;
+
+				if (diameap_plugin_get(eap_sm->currentVendor,
+						eap_sm->currentMethod, &eap_sm->selectedMethod))
+				{
+					TRACE_DEBUG(INFO,"%sNo EAP Method plugin available for EAP Method {Type=%d, Vendor=%d}.",DIAMEAP_EXTENSION,eap_sm->currentMethod, eap_sm->currentVendor);
+				}
+				else
+				{
+					TRACE_DEBUG(FULL,"%sCurrent EAP Method {Type=%d, Vendor=%d} (EAP Method plugin selected).",DIAMEAP_EXTENSION,eap_sm->currentMethod, eap_sm->currentVendor);
+				}
+				eap_sm->currentVendor = VENDOR_IETF;
+				if (eap_sm->selectedMethod != NULL)
+				{
+					ret = (*eap_sm->selectedMethod->eap_method_initPickUp)(
+							eap_sm);
+					if (ret)
+					{
+						TRACE_DEBUG(INFO, "%sEAP Method InitPickUp returned error.",DIAMEAP_EXTENSION);
+						eap_sm->selectedMethod = NULL;
+						eap_sm->currentMethod = TYPE_NONE;
+					}
+				}
+			}
+			if (eap_sm->currentMethod == TYPE_NONE)
+			{
+				eap_sm->eap_state = EAP_SELECT_ACTION;
+			}
+			else
+			{
+				eap_sm->eap_state = EAP_METHOD_RESPONSE;
+			}
+			break;
+
+		case EAP_RECEIVED:
+			TRACE_DEBUG(FULL+1,"%s[EAP Protocol] New EAP Response received",DIAMEAP_EXTENSION)
+			;
+			diameap_eap_dump(FULL + 1, &eap_i->aaaEapRespData);
+			if ((eap_sm->rxResp == TRUE) && (eap_sm->respId
+					== eap_sm->currentId) && ((eap_sm->respMethod
+					== eap_sm->currentMethod) || ((eap_sm->respMethod
+					== TYPE_EXPANDED_TYPES) && (eap_sm->respVendor
+					== VENDOR_IETF) && (eap_sm->respVendorMethod
+					== eap_sm->currentMethod))))
+			{
+				eap_sm->eap_state = EAP_INTEGRITY_CHECK;
+			}
+			else if ((eap_sm->rxResp == TRUE) && (eap_sm->respId
+					== eap_sm->currentId) && ((eap_sm->respMethod == TYPE_NAK)
+					|| (eap_sm->respMethod == TYPE_EXPANDED_TYPES
+							&& eap_sm->respVendor == VENDOR_IETF
+							&& eap_sm->respVendorMethod == TYPE_NAK))
+					&& (eap_sm->methodState == EAP_M_PROPOSED))
+			{
+				eap_sm->eap_state = EAP_NAK;
+			}
+			else
+			{
+				eap_sm->eap_state = EAP_DISCARD;
+			}
+			break;
+		case EAP_DISCARD:
+			TRACE_DEBUG(INFO,"%s[EAP Protocol] Invalid EAP Packet received (Non fatal error).",DIAMEAP_EXTENSION)
+			;
+			*non_fatal_error = TRUE;
+			eap_sm->eap_state = EAP_IDLE;
+			break;
+
+		case EAP_SEND_REQUEST:
+			TRACE_DEBUG(FULL+1,"%s[EAP Protocol] New EAP packet request created.",DIAMEAP_EXTENSION)
+			;
+			diameap_eap_dump(FULL, &eap_i->aaaEapReqData);
+			eap_i->aaaEapResp = FALSE;
+			eap_i->aaaEapReq = TRUE;
+			eap_sm->eap_state = EAP_IDLE;
+			break;
+
+		case EAP_INTEGRITY_CHECK:
+			if ((*eap_sm->selectedMethod->eap_method_check)(eap_sm,
+					&eap_i->aaaEapRespData) == FALSE)
+			{
+				TRACE_DEBUG(INFO,"%s[EAP Protocol] Invalid EAP packet received {Type=%d, Vendor=%d}. Integrity check failed (non fatal error).",DIAMEAP_EXTENSION,eap_sm->currentMethod,eap_sm->currentVendor);
+				//non_fata_error
+				*non_fatal_error = TRUE;
+				eap_sm->eap_state = EAP_IDLE;
+			}
+			else
+			{
+				eap_sm->eap_state = EAP_METHOD_RESPONSE;
+			}
+
+			break;
+		case EAP_METHOD_REQUEST:
+			eap_sm->lastId = eap_sm->currentId;
+			diameap_ba_nextid(eap_sm, &eap_sm->currentId);
+			CHECK_FCT((*eap_sm->selectedMethod->eap_method_buildReq)(
+							eap_sm, eap_sm->currentId,&eap_i->aaaEapReqData))
+			;
+			if (eap_sm->selectedMethod->eap_method_getTimeout)
+			{
+				if ((*eap_sm->selectedMethod->eap_method_getTimeout)(eap_sm,
+						&eap_i->aaaMethodTimeout))
+				{
+					TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] getTimeout failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+					eap_i->aaaMethodTimeout = 0;
+				}
+			}
+			else
+			{
+				eap_i->aaaMethodTimeout = 0;
+			}
+			eap_sm->eap_state = EAP_SEND_REQUEST;
+			break;
+
+		case EAP_METHOD_RESPONSE:
+			if (eap_sm->respMethod >= TYPE_EAP_MD5)
+			{
+				if (eap_sm->user.methodId < 0)
+				{
+					eap_sm->user.methodId = 0;
+					eap_sm->user.methods[eap_sm->user.methodId].vendor
+							= eap_sm->respVendor;
+					eap_sm->user.methods[eap_sm->user.methodId].method
+							= eap_sm->respMethod;
+					eap_sm->user.methodId++;
+
+				}
+				else if (!((eap_sm->user.methods[eap_sm->user.methodId - 1].vendor
+						== eap_sm->respVendor)
+						&& (eap_sm->user.methods[eap_sm->user.methodId - 1].method
+								== eap_sm->respMethod)))
+				{
+					eap_sm->user.methods[eap_sm->user.methodId].vendor
+							= eap_sm->respVendor;
+					eap_sm->user.methods[eap_sm->user.methodId].method
+							= eap_sm->respMethod;
+					eap_sm->user.methodId++;
+				}
+			}
+			if ((*eap_sm->selectedMethod->eap_method_process)(eap_sm,
+					&eap_i->aaaEapRespData))
+			{
+				TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Authentication process failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+				*non_fatal_error = TRUE;
+				eap_sm->eap_state = EAP_IDLE;
+
+			}else{
+			if ((*eap_sm->selectedMethod->eap_method_isDone)(eap_sm) == TRUE)
+			{
+				/*diameap_ba_PolicyUpdate();*/
+				eap_i->aaaEapMSKLength = 0;
+				eap_i->aaaEapEMSKLength = 0;
+				if (eap_sm->selectedMethod->eap_method_getKey)
+				{
+					if ((*eap_sm->selectedMethod->eap_method_getKey)(eap_sm,
+							&eap_i->aaaEapMSKData, &eap_i->aaaEapMSKLength,
+							&eap_i->aaaEapEMSKData, &eap_i->aaaEapEMSKLength))
+					{
+						TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Generating EAP Master Key failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname)
+						eap_i->aaaEapMSKLength = 0;
+						eap_i->aaaEapEMSKLength = 0;
+						eap_i->aaaEapKeyAvailable = FALSE;
+					}
+					else
+					{
+						eap_i->aaaEapKeyAvailable = TRUE;
+					}
+				}
+				eap_sm->methodState = EAP_M_END;
+				eap_sm->eap_state = EAP_SELECT_ACTION;
+			}
+			else
+			{
+				eap_sm->methodState = EAP_M_CONTINUE;
+				eap_sm->eap_state = EAP_METHOD_REQUEST;
+			}
+			}
+			break;
+		case EAP_PROPOSE_METHOD:
+			if (diameap_ba_policygetnextmethod(eap_sm, &eap_sm->currentMethod,
+					&eap_sm->currentVendor))
+			{
+				TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Selecting EAP Method plugin failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+
+				*non_fatal_error = TRUE;
+				eap_sm->eap_state = EAP_END;
+
+			}
+			TRACE_DEBUG(FULL,"%s[EAP Protocol] Selecting EAP Method plugin: %s(%d). [user: %s]",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname,eap_sm->selectedMethod->methodtype,eap_sm->user.userid)
+			;
+			if ((*eap_sm->selectedMethod->eap_method_init)(eap_sm))
+			{
+				TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Initializing EAP plugin failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
+			}
+
+			if ((eap_sm->currentMethod == TYPE_IDENTITY)
+					|| (eap_sm->currentMethod == TYPE_NOTIFICATION))
+			{
+				eap_sm->methodState = EAP_M_CONTINUE;
+			}
+			else
+			{
+				eap_sm->methodState = EAP_M_PROPOSED;
+			}
+			eap_sm->eap_state = EAP_METHOD_REQUEST;
+			break;
+		case EAP_NAK:
+			TRACE_DEBUG(FULL+1,"%s[EAP Protocol] EAP NAK Packet received.",DIAMEAP_EXTENSION)
+			;
+			if (eap_sm->selectedMethod->eap_method_free)
+			{
+				(*eap_sm->selectedMethod->eap_method_free)(eap_sm->methodData);
+				eap_sm->methodData = NULL;
+			}
+			else
+			{
+				if (eap_sm->methodData)
+				{
+					free(eap_sm->methodData);
+					eap_sm->methodData = NULL;
+				}
+			}
+			diameap_ba_policyupdate(eap_sm, &eap_i->aaaEapRespData);
+			eap_sm->eap_state = EAP_SELECT_ACTION;
+			break;
+		case EAP_SELECT_ACTION:
+			CHECK_FCT(diameap_ba_policygetdecision(eap_sm, eap_i,&eap_sm->sm_decision))
+			;
+			switch (eap_sm->sm_decision)
+			{
+			case DECISION_CONTINUE:
+				eap_sm->eap_state = EAP_PROPOSE_METHOD;
+				break;
+			case DECISION_FAILURE:
+				TRACE_DEBUG(FULL,"%s[EAP Protocol] Authentication Failure [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid)
+				;
+				eap_sm->lastId = eap_sm->currentId;
+				diameap_ba_nextid(eap_sm, &eap_sm->currentId);
+				CHECK_FCT(diameap_eap_new(EAP_FAILURE, (u8) eap_sm->currentId, TYPE_NONE, NULL, 0,&eap_i->aaaEapReqData))
+				;
+				eap_i->aaaFail = TRUE;
+				*non_fatal_error = FALSE;
+				eap_sm->eap_state = EAP_END;
+				if (eap_sm->methodData)
+				{
+					if (eap_sm->selectedMethod->eap_method_free)
+					{
+						(*eap_sm->selectedMethod->eap_method_free)(
+								eap_sm->methodData);
+						eap_sm->methodData = NULL;
+					}
+					else
+					{
+						free(eap_sm->methodData);
+						eap_sm->methodData = NULL;
+					}
+				}
+				break;
+			case DECISION_SUCCESS:
+				TRACE_DEBUG(FULL,"%s[EAP Protocol] Authentication Success [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid)
+				;
+				eap_sm->lastId = eap_sm->currentId;
+				diameap_ba_nextid(eap_sm, &eap_sm->currentId);
+				CHECK_FCT(diameap_eap_new(EAP_SUCCESS, (u8) eap_sm->currentId, TYPE_NONE, NULL, 0,&eap_i->aaaEapReqData))
+				;
+				if (eap_i->aaaEapMSKData != NULL)
+				{
+					TRACE_DEBUG(FULL+1,"%s[EAP Protocol] EAP Key available [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid);
+					eap_i->aaaEapKeyAvailable = TRUE;
+				}
+				else
+				{
+					TRACE_DEBUG(FULL+1,"%s[EAP Protocol] No EAP Key available [User: %s].",DIAMEAP_EXTENSION,eap_sm->user.userid);
+				}
+				eap_i->aaaSuccess = TRUE;
+				*non_fatal_error = FALSE;
+				eap_sm->eap_state = EAP_END;
+				if (eap_sm->selectedMethod->eap_method_free)
+				{
+					(*eap_sm->selectedMethod->eap_method_free)(
+							eap_sm->methodData);
+					eap_sm->methodData = NULL;
+				}
+				else
+				{
+					if (eap_sm->methodData)
+					{
+						free(eap_sm->methodData);
+						eap_sm->methodData = NULL;
+					}
+				}
+				break;
+			default:
+				TRACE_DEBUG(INFO,"%sIncorrect EAP Decision.(Please report this problem.)",DIAMEAP_EXTENSION)
+				;
+			}
+			break;
+
+		case EAP_END:
+			break;
+
+		case EAP_IDLE:
+			break;
+		}
+	}
+
+	return 0;
+}
+