| /***************************************************************************************************** |
| * 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; |
| } |
| |