diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/simtsy/src/csimsmartcardeap.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyserverplugins/simtsy/src/csimsmartcardeap.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,1338 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Defines the CSimSmartCardEap class componenet +// +// + +/** + @file +*/ + +#include +#include "csimsmartcardeap.h" +#include "Simlog.h" +#include "etelext.h" + +// CSimSmartCardEapManager implementation; related to CSimSmartCardEap // + +/** +Default constructor to initialise Ptrs. +*/ +TEapChngResp::TEapChngResp() +: iChallenge(NULL), iResp(NULL), + iAuthStatus(RMobileSmartCardEap::ENoAuthStarted) + { + } + +/** +Default constructor to initialise Ptrs. +*/ +TEapProcedureData::TEapProcedureData() +: iEapKey(NULL), iEapExtKey(NULL), iEapId(NULL), iEapPsId(NULL) + { + } + +/** +Factory constructor. +*/ +CSimSmartCardEapManager* CSimSmartCardEapManager::NewL(CSimPhone *aPhone) + { + CSimSmartCardEapManager* phone = new(ELeave) CSimSmartCardEapManager(aPhone); + CleanupStack::PushL(phone); + phone->ConstructL(); + CleanupStack::Pop(); + return phone; + } + +/** +Default constructor, initialises a pointer to the owner phone object. +*/ +CSimSmartCardEapManager::CSimSmartCardEapManager(CSimPhone *aPhone) +: iPhone(aPhone) + { + } + +/** +Second-phase constructor. +*/ +void CSimSmartCardEapManager::ConstructL() + { + LOGPHONE1("CSimSmartCardEapManager second phase construction created"); + + ParseEapInfoL(); + + LOGPHONE1("CSimSmartCardEapManager second phase construction completed"); + } + +/** +If this is destroyed then so should all EAP sub-session objects. +*/ +CSimSmartCardEapManager::~CSimSmartCardEapManager() + { + LOGPHONE1("CSimSmartCardEapManager destructing"); + + for (TInt jj = iSubSessionObjs.Count()-1; jj >= 0; jj--) + { + delete iSubSessionObjs[jj]; + } + + iSubSessionObjs.Close(); + + ClearParsedData(); + + LOGPHONE1("CSimSmartCardEapManager destructed"); + } + +void CSimSmartCardEapManager::ClearParsedData() + { + // Cleanup remaining unused parsed EAP procedure data + for (TInt jjj = 0; jjj < iEapProcData.Count(); jjj++) + { + for (TInt aa = 0; aa < iEapProcData[jjj].iChResp.Count(); aa++) + { + TEapChngResp& temp = iEapProcData[jjj].iChResp[aa]; + delete (temp.iChallenge); + delete (temp.iResp); + temp.iChallenge = NULL; + temp.iResp = NULL; + } + iEapProcData[jjj].iChResp.Close(); + + delete iEapProcData[jjj].iEapKey; + delete iEapProcData[jjj].iEapExtKey; + delete iEapProcData[jjj].iEapId; + delete iEapProcData[jjj].iEapPsId; + iEapProcData[jjj].iEapKey = NULL; + iEapProcData[jjj].iEapExtKey = NULL; + iEapProcData[jjj].iEapId = NULL; + iEapProcData[jjj].iEapPsId = NULL; + } + + iEapProcData.Close(); + iDiscardedProcedure.Close(); + } + +/** +Returns a pointer to the selected config.txt file section. +*/ +const CTestConfigSection* CSimSmartCardEapManager::CfgFile() + { + return iPhone->CfgFile(); + } + +/** +Parses the UICC App EAP specific settings from the config.txt. +*/ +void CSimSmartCardEapManager::ParseEapInfoL() + { + LOGPHONE1("CSimSmartCardEapManager::ParseEapInfoL called"); + + CTestConfigItem* item = NULL; + + LOGPHONE1("Starting to Parse Smart Card EAP Info"); + TInt count = CfgFile()->ItemCount(KScEapProcedures); + + // Used in parsing to keep track of the nested items + TInt nestedKeyTag = 0; + TInt nestedExtKeyTag = 0; + TInt nestedIdTag = 0; + TInt nestedPsIdTag = 0; + TInt nestedChlTag = 0; + + // Counts of the total number of tags (considered as nested tags) + TInt countKey = CfgFile()->ItemCount(KScEapKeyMSK); + TInt countExtKey = CfgFile()->ItemCount(KScEapKeyEMSK); + TInt countId = CfgFile()->ItemCount(KScEapIdentity); + TInt countPsId = CfgFile()->ItemCount(KScEapPsIdentity); + TInt countChl = CfgFile()->ItemCount(KScEapChallenge); + + + for (TInt index = 0; index < count; index++) + { + item = const_cast(CfgFile()->Item(KScEapProcedures, index)); + if(item == NULL) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: SC EAP PROC INFO tag not read [%d]", index); + continue; + } + + TInt dataFrmt = 0; + TInt numChallenges = 0; + TInt ret = KErrNone; + TPtrC8 appId, eapType; + + // To be populated and appended to iEapProcData later + TEapProcedureData procInfo; + + // Get AID; convert to bin if required + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, appId); + if(ret != KErrNone) + { + LOGPARSERR("appId", ret,0,&KScEapProcedures); + continue; + } + else + { + procInfo.iAID = appId; + + // AID is always in binary format (because of the RMobileSmartCardEap::Open construction) + ParseMixedBinaryAsciiDataL(procInfo.iAID); + } + + // Get eap type + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 1, eapType); + if(ret != KErrNone) + { + LOGPARSERR("eapType", ret,1,&KScEapProcedures); + continue; + } + else + { + // EAP type is always in ASCII + procInfo.iEapType = eapType; + } + + // Find number of challenges + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 2, numChallenges); + if(ret != KErrNone) + { + LOGPARSERR("numChallenges", ret,2,&KScEapProcedures); + continue; + } + else if (numChallenges > (countChl - nestedChlTag)) + { + LOGPHONE2("ERROR CONFIGURATION FILE PARSING: error SC EAP PROC INFO specifies more challenges than available [%d]", index); + continue; + } + else if (numChallenges < 0) + { + LOGPHONE2("ERROR CONFIGURATION FILE PARSING: error SC EAP PROC INFO specifies -ve challenge number [%d]", index); + continue; + } + + // Get optional data format; this format is used for all data of this parsed procedure + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 3, dataFrmt); + if(ret != KErrNone) + { + LOGPHONE2("CONFIGURATION FILE PARSING: SC EAP PROC INFO tag with no data format [%d]", index); + } + else if (dataFrmt >= EMaxConfigDataFormat) + { + LOGPHONE2("WARNING IN CONFIGURATION FILE PARSING - error wrong data format value SC EAP PROC INFO tag [%d] (ASCII format will be used)", index); + dataFrmt = EConfigDataFormatAscii; + } + + TPtrC8 ptr; + TPtr8 tempPtr(NULL,0); + HBufC8* startData = NULL; + + // Get MSK + if (nestedKeyTag < countKey) + { + item = const_cast(CfgFile()->Item(KScEapKeyMSK, nestedKeyTag++)); + + // parse delay and key + if (item == NULL) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Key tag [%d]", nestedKeyTag-1); + } + else + { + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr); + if (ret != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Key tag's data [%d]", nestedKeyTag-1); + } + else + { + TRAPD(kAllocErr, startData = ptr.AllocL()); + if (kAllocErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Key data [%d]", nestedKeyTag-1); + } + else + { + tempPtr.Set(startData->Des()); + switch (dataFrmt) + { + case EConfigDataFormatMixedBinaryAndAscii: + ParseMixedBinaryAsciiDataL(tempPtr); + break; + //case EConfigDataFormatAscii: // Do nothing + //default: + } + // need to re-copy because converting to binary changes size + TRAP(kAllocErr, procInfo.iEapKey = tempPtr.AllocL()); + if (kAllocErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Key data copy [%d]", nestedKeyTag-1); + } + delete startData; + startData = NULL; + } + } + } + } + else + { + LOGPHONE1("ERROR CONFIGURATION FILE PARSING: NO SC EAP KEY INFO TAG"); + } + + // Get EMSK + if (nestedExtKeyTag < countExtKey) + { + item = const_cast(CfgFile()->Item(KScEapKeyEMSK, nestedExtKeyTag++)); + + // parse key + if (item == NULL) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Ext Key tag [%d]", nestedExtKeyTag-1); + } + else + { + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr); + if (ret != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Ext Key tag's data [%d]", nestedExtKeyTag-1); + } + else + { + TRAPD(kAllocErr, startData = ptr.AllocL()); + if (kAllocErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Ext Key data [%d]", nestedExtKeyTag-1); + } + else + { + tempPtr.Set(startData->Des()); + switch (dataFrmt) + { + case EConfigDataFormatMixedBinaryAndAscii: + ParseMixedBinaryAsciiDataL(tempPtr); + break; + //case EConfigDataFormatAscii: // Do nothing + //default: + } + // need to re-copy because converting to binary changes size + TRAP(kAllocErr, procInfo.iEapExtKey = tempPtr.AllocL()); + if (kAllocErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Ext Key data copy [%d]", nestedExtKeyTag-1); + } + delete startData; + startData = NULL; + } + } + } + } + else + { + LOGPHONE1("ERROR CONFIGURATION FILE PARSING: NO SC EAP EXT KEY INFO TAG"); + } + + // Get Permanent Identity + if (nestedIdTag < countId) + { + item = const_cast(CfgFile()->Item(KScEapIdentity, nestedIdTag++)); + + // parse id + if (item == NULL) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP id tag [%d]", nestedIdTag-1); + } + else + { + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr); + if (ret != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Id tag's data [%d]", nestedIdTag-1); + } + else + { + TRAPD(idAllocErr, startData = ptr.AllocL()); + if (idAllocErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Id data [%d]", nestedIdTag-1); + } + else + { + TPtr8 tempPtr(NULL,0); + tempPtr.Set(startData->Des()); + switch (dataFrmt) + { + case EConfigDataFormatMixedBinaryAndAscii: + ParseMixedBinaryAsciiDataL(tempPtr); + break; + //case EConfigDataFormatAscii: // Do nothing + //default: + } + // need to re-copy because converting to binary changes size + TRAP(idAllocErr, procInfo.iEapId = tempPtr.AllocL()); + if (idAllocErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Id data copy [%d]", nestedIdTag-1); + } + delete startData; + startData = NULL; + } + } + } + } + else + { + LOGPHONE1("WARNING CONFIGURATION FILE PARSING: NO SC EAP ID INFO TAG"); + } + + // Get Pseudonym Identity + if (nestedPsIdTag < countPsId) + { + item = const_cast(CfgFile()->Item(KScEapPsIdentity, nestedPsIdTag++)); + + // parse id + if (item == NULL) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Pseudonym id tag [%d]", nestedPsIdTag-1); + } + else + { + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr); + if (ret != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP Pseudonym Id tag's data [%d]", nestedPsIdTag-1); + } + else + { + TRAPD(idAllocErr, startData = ptr.AllocL()); + if (idAllocErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Pseudonym Id data [%d]", nestedPsIdTag-1); + } + else + { + TPtr8 tempPtr(NULL,0); + tempPtr.Set(startData->Des()); + switch (dataFrmt) + { + case EConfigDataFormatMixedBinaryAndAscii: + ParseMixedBinaryAsciiDataL(tempPtr); + break; + //case EConfigDataFormatAscii: // Do nothing + //default: + } + // need to re-copy because converting to binary changes size + TRAP(idAllocErr, procInfo.iEapPsId = tempPtr.AllocL()); + if (idAllocErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP Pseudonym Id data copy [%d]", nestedPsIdTag-1); + } + delete startData; + startData = NULL; + } + } + } + } + else + { + LOGPHONE1("WARNING CONFIGURATION FILE PARSING: NO SC EAP PS ID INFO TAG"); + } + + // Get challenges + // numChallenges is what is parsed from config.txt and will be + // decremented in loop till zero is reached. + // nestedChlTag keeps track of the current KScEapChallenge tag + // being read of the total; i.e. not just nested. + // countChl is the total number of KScEapChallenge found. + while (numChallenges != 0) + { + if (nestedChlTag >= countChl) + { + LOGPHONE1("WARNING CONFIGURATION FILE PARSING: NO MORE SC EAP Challenge INFO TAG"); + break; + } + + item = const_cast(CfgFile()->Item(KScEapChallenge, nestedChlTag++)); + numChallenges--; + + // parse delay and challenge/response and auth status + if (item == NULL) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP challenge tag [%d]", nestedChlTag-1); + continue; + } + + // Parse challenge + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 0, ptr); + if (ret != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP challenge data [%d]", nestedChlTag-1); + continue; + } + + TRAPD(leaveErr, startData = ptr.AllocL()); + if (leaveErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP challenge data [%d]", nestedChlTag-1); + continue; + } + tempPtr.Set(startData->Des()); + switch (dataFrmt) + { + case EConfigDataFormatMixedBinaryAndAscii: + ParseMixedBinaryAsciiDataL(tempPtr); + break; + //case EConfigDataFormatAscii: // Do nothing + //default: + } + TEapChngResp newChRespData; + TRAP(leaveErr, newChRespData.iChallenge = tempPtr.AllocL()); + if (leaveErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP challenge data copy [%d]", nestedKeyTag-1); + } + delete startData; + startData = NULL; + + // Parse response + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 1, ptr); + if (ret != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP response data [%d]", nestedChlTag-1); + continue; + } + + TRAP(leaveErr, startData = ptr.AllocL()); + if (leaveErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP response data [%d]", nestedChlTag-1); + continue; + } + tempPtr.Set(startData->Des()); + switch (dataFrmt) + { + case EConfigDataFormatMixedBinaryAndAscii: + ParseMixedBinaryAsciiDataL(tempPtr); + break; + //case EConfigDataFormatAscii: // Do nothing + //default: + } + TRAP(leaveErr, newChRespData.iResp = tempPtr.AllocL()); + if (leaveErr != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP response data copy [%d]", nestedKeyTag-1); + } + delete startData; + startData = NULL; + + // Parse status + TInt stat; + ret = CTestConfig::GetElement(item->Value(), KStdDelimiter, 2, stat); + if (ret != KErrNone) + { + LOGPHONE2("WARNING CONFIGURATION FILE PARSING: could not read EAP auth status [%d]", nestedChlTag-1); + continue; + } + + newChRespData.iAuthStatus = static_cast(stat); + + leaveErr = procInfo.iChResp.Append(newChRespData); + if (leaveErr != KErrNone) + { + LOGPHONE3("WARNING CONFIGURATION FILE PARSING: could not allocate mem for EAP challenge/resp data [%d] [err=%d]", nestedChlTag-1, leaveErr); + } + } // end while + + TInt errAppend = iEapProcData.Append(procInfo); + if (errAppend != KErrNone) + { + LOGPHONE2("ERROR CONFIGURATION FILE PARSING: Could not store parsed EAP procedure data [err=%d]", errAppend); + } + else + { + iDiscardedProcedure.Append(EFalse); + } + } // end for; parsing EAP procedures from config.txt + + LOGPHONE1("CSimSmartCardEapManager::ParseEapInfoL completed"); + } + +/** +Function leaves if is not in config file. + +@leave KErrNotFound if is not found. +*/ +void CSimSmartCardEapManager::AID_EapType_ExistsInConfigL(const RMobilePhone::TAID& aAID, const RMobileSmartCardEap::TEapType& aEapType) + { + for (TInt ii = 0; ii < iEapProcData.Count(); ii++) + { + TEapProcedureData& temp = iEapProcData[ii]; + if (temp.iAID == aAID) + { + // two ifs rather than && to help debug + if (temp.iEapType == aEapType) + { + if (!iDiscardedProcedure[ii]) + { + return; + } + } + } + } + User::Leave(KErrNotFound); + } + +CTelObject* CSimSmartCardEapManager::CreateScEapSubSessionL(RMobilePhone::TAID& aAID, RMobileSmartCardEap::TEapType& aEapType) + { + LOGPHONE1("CSimSmartCardEapManager::CreateScEapSubSessionL called"); + // If no config exists for this eapAID,eapType pair, then this will leave + AID_EapType_ExistsInConfigL(aAID, aEapType); + + // If exists then phoneScEap guaranteed to get data in + // InitialiseEapMethod, since only one object can be created + // using the unique pair. + + CSimSmartCardEap* phoneScEap = NULL; + TRAPD(err, phoneScEap = CSimSmartCardEap::NewL(iPhone, this, aAID, aEapType)); + + if (err != KErrNone) + { + LOGPHONE2("ERROR could not create CSimSmartCardEap object [err=%d]", err); + User::Leave(err); + } + + return phoneScEap; + } + +/** +Returns the first procedure data section, as parsed from the +config.txt, with aAID and aEapType. + +@param aAID +@param aEapType +@return The first procedure data with aAID and aEapType from the + config.txt. NULL if no such procedure data is found. +*/ +TEapProcedureData* CSimSmartCardEapManager::ProcData(const RMobilePhone::TAID& aAID, const RMobileSmartCardEap::TEapType& aEapType) + { + for (TInt ii = 0; ii < iEapProcData.Count(); ii++) + { + if (iEapProcData[ii].iAID == aAID) + { + // two ifs rather than && to help debug + if (iEapProcData[ii].iEapType == aEapType) + { + if (!iDiscardedProcedure[ii]) + { + return &iEapProcData[ii]; + } + } + } + } + return NULL; + } + +void CSimSmartCardEapManager::ProcDataUseCompleted(const TEapProcedureData* aProcData) + { + if (aProcData == NULL) + { + return; + } + + TInt pos = KErrNotFound; + + for (TInt ii = 0; ii < iEapProcData.Count(); ii++) + { + if ((&iEapProcData[ii]) == aProcData) + { + pos = ii; + break; + } + } + + if (pos != KErrNotFound) + { + iDiscardedProcedure[pos] = ETrue; + } + } + +/** +Register a sub-session object. At the present time, list is maintained +for clean-up only; i.e. this object stores pointers to all EAP sub- +session objects. +*/ +void CSimSmartCardEapManager::RegisterSubSessionL(CSimSmartCardEap* aToRegister) + { + iSubSessionObjs.AppendL(aToRegister); + } + +/** +Remove a sub-session object from list of active sub-sessions. +*/ +TInt CSimSmartCardEapManager::DeRegisterSubSession(const CSimSmartCardEap* aToDeRegister) + { + TInt index = iSubSessionObjs.Find(aToDeRegister); + + if (index < 0) + { + return index; + } + + iSubSessionObjs.Remove(index); + iSubSessionObjs.Compress(); + + return KErrNone; + } + +// CSimSmartCardEap implementation // + +CSimSmartCardEap* CSimSmartCardEap::NewL(CSimPhone *aPhone, CSimSmartCardEapManager* aEapMan, RMobilePhone::TAID& aAID, RMobileSmartCardEap::TEapType& aEapType) + { + CSimSmartCardEap* phone = new(ELeave) CSimSmartCardEap(aPhone, aAID, aEapType); + CleanupStack::PushL(phone); + phone->ConstructL(aEapMan); + CleanupStack::Pop(); + return phone; + } + +CSimSmartCardEap::CSimSmartCardEap(CSimPhone *aPhone, RMobilePhone::TAID& aAID, RMobileSmartCardEap::TEapType& aEapType) +: iPhone(aPhone), iProcedureData(NULL), iSSInitialised(EFalse), + iAccessStatus(RMobileSmartCardEap::EEapMethodAvailable), iAuthStatus(RMobileSmartCardEap::ENoAuthStarted), + iCliTerminationListener(NULL), iCurrentChallenge(0) + { + iAID = aAID; + iEapType = aEapType; + } + +void CSimSmartCardEap::ConstructL(CSimSmartCardEapManager* aEapMan) + { + LOGPHONE1("CSimSmartCardEap: starting second phase construction"); + + iSemaphr.CreateGlobal(KNullDesC, EOwnerThread); + aEapMan->RegisterSubSessionL(this); + iEapMan = aEapMan; + + LOGPHONE1("CSimSmartCardEap created"); + } + +CSimSmartCardEap::~CSimSmartCardEap() + { + if (iCliTerminationListener != NULL) + { + delete iCliTerminationListener; + iCliTerminationListener = NULL; + } + iSemaphr.Close(); + + // remove config entry from manager + if (iProcedureData != NULL) + { + iEapMan->ProcDataUseCompleted(iProcedureData); + iProcedureData = NULL; + } + + TInt err = iEapMan->DeRegisterSubSession(this); + LOGPHONE2("CSimSmartCardEap destroyed, deregistering returned %d", err); + + iEapMan = NULL; + } + + +void CSimSmartCardEap::Init() + { + // server calls this function once it has created the sub-session + // it gives the TSY chance to do any initialisation it may need to do for + // this sub-session + } + +CTelObject* CSimSmartCardEap::OpenNewObjectByNameL(const TDesC& /*aName*/) + { + // Server calls this function when a client is opening an object from the phone + // for the first time. + // Multiple clients opening handles to the same sub-session object will be dealt with + // by the server - i.e. by reference counting + User::Leave(KErrNotSupported); + return NULL; + } + +CTelObject* CSimSmartCardEap::OpenNewObjectL(TDes& /*aNewName*/) + { + // all objects opened from the phone are opened by name, hence this method + // is not supported + User::Leave(KErrNotSupported); + return NULL; + } + +CTelObject::TReqMode CSimSmartCardEap::ReqModeL(const TInt aIpc) + { + // ReqModeL is called from the server's CTelObject::ReqAnalyserL + // in order to check the type of request it has + + // The following are example request types for this dummy TSY + // All TSYs do not have to have these request types but they have been given + // "sensible" values in this test code + + CTelObject::TReqMode ret = 0; + + switch (aIpc) + { + // Non flow-controlled requests + case EMobileSmartCardEapInitialiseEapMethod: + case EMobileSmartCardEapGetUserIdentity: + case EMobileSmartCardEapGetAuthenticationStatus: + case EMobileSmartCardEapGetEapKey: + case EMobileSmartCardEapAuthenticationPhase1: + case EMobileSmartCardEapAuthenticationPhase2: + case EMobileSmartCardEapReleaseEapMethod: + case EMobileSmartCardEapGetEapMethodAccessStatus: + break; + + case EMobileSmartCardEapNotifyEapMethodAccessStatusChange: + ret = KReqModeMultipleCompletionEnabled; + break; + + default: + User::Leave(KErrNotSupported); + break; + } + + return ret; + } + +TInt CSimSmartCardEap::RegisterNotification(const TInt /*aIpc*/) + { + // RegisterNotification is called when the server recognises that this notification + // is being posted for the first time on this sub-session object. + + // It enables the TSY to "turn on" any regular notification messages that it may + // receive from the phone + + return KErrNone; + } + +TInt CSimSmartCardEap::DeregisterNotification(const TInt /*aIpc*/) + { + // DeregisterNotification is called when the server recognises that this notification + // will not be posted again because the last client to have a handle on this sub-session + // object has just closed the handle. + + // It enables the TSY to "turn off" any regular notification messages that it may + // receive from the phone + + return KErrNone; + } + +TInt CSimSmartCardEap::NumberOfSlotsL(const TInt aIpc) + { + // NumberOfSlotsL is called by the server when it is registering a new notification + // It enables the TSY to tell the server how many buffer slots to allocate for + // "repost immediately" notifications that may trigger before clients collect them + + TInt numberOfSlots = 1; + + switch (aIpc) + { + case EMobileSmartCardEapNotifyEapMethodAccessStatusChange: + numberOfSlots = 3; + break; + + default: + // Unknown or invalid Phone IPC + User::Leave(KErrNotSupported); + break; + } + + return numberOfSlots; + } + +TInt CSimSmartCardEap::ExtFunc(const TTsyReqHandle aTsyReqHandle,const TInt aIpc, + const TDataPackage& aPackage) + { + // ExtFunc is called by the server when it has a "extended", i.e. non-core ETel request + // for the TSY to process + // A request handle, request type and request data are passed to the TSY + + TAny* dataPtr = aPackage.Ptr1(); + TAny* dataPtr2 = aPackage.Ptr2(); + + // The request data has to extracted from TDataPackage and the TAny* pointers have to + // be "cast" to the expected request data type + + switch(aIpc) + { + // Non-Flow controlled requests + + case EMobileSmartCardEapInitialiseEapMethod: + return SimInitialiseEapMethod(aTsyReqHandle, + reinterpret_cast(dataPtr)); + + case EMobileSmartCardEapGetUserIdentity: + return SimGetUserIdentity(aTsyReqHandle, + reinterpret_cast(dataPtr), + aPackage.Des2n()); + + case EMobileSmartCardEapGetAuthenticationStatus: + return SimGetAuthenticationStatus(aTsyReqHandle, + reinterpret_cast(dataPtr)); + + case EMobileSmartCardEapGetEapKey: + return SimGetEapKey(aTsyReqHandle, + reinterpret_cast(dataPtr), + aPackage.Des2n()); + + case EMobileSmartCardEapAuthenticationPhase1: + return SimSetAuthenticateDataForPhase1(aTsyReqHandle, + aPackage.Des1n(), reinterpret_cast(dataPtr2)); + + case EMobileSmartCardEapAuthenticationPhase2: + return SimGetAuthenticateDataForPhase2(aTsyReqHandle, + aPackage.Des1n(), aPackage.Des2n()); + + case EMobileSmartCardEapReleaseEapMethod: + return SimReleaseEapMethod(aTsyReqHandle); + + case EMobileSmartCardEapGetEapMethodAccessStatus: + return SimGetEapMethodAccessStatus(aTsyReqHandle, + reinterpret_cast(dataPtr)); + + case EMobileSmartCardEapNotifyEapMethodAccessStatusChange: + return SimNotifyEapMethodAccessStatusChange(aTsyReqHandle, + reinterpret_cast(dataPtr)); + + default: + return KErrNotSupported; + } + } + +TInt CSimSmartCardEap::CancelService(const TInt aIpc,const TTsyReqHandle aTsyReqHandle) + { + // CancelService is called by the server when it is "cleaning-up" any still outstanding + // asynchronous requests before closing a client's sub-session. + // This will happen if a client closes its R-class handle without cancelling outstanding + // asynchronous requests. + + switch (aIpc) + { + case EMobileSmartCardEapGetUserIdentity: + return SimGetUserIdentityCancel(aTsyReqHandle); + case EMobileSmartCardEapGetAuthenticationStatus: + return SimGetAuthenticationStatusCancel(aTsyReqHandle); + case EMobileSmartCardEapGetEapKey: + return SimGetEapKeyCancel(aTsyReqHandle); + case EMobileSmartCardEapInitialiseEapMethod: + return SimInitialiseEapMethodCancel(aTsyReqHandle); + case EMobileSmartCardEapAuthenticationPhase1: + case EMobileSmartCardEapAuthenticationPhase2: + return SimSmartCardEapAuthenticationCancel(aTsyReqHandle); + case EMobileSmartCardEapNotifyEapMethodAccessStatusChange: + return SimNotifyEapMethodAccessStatusChangeCancel(aTsyReqHandle); + default: + return KErrNotSupported; + } + } + +RHandleBase* CSimSmartCardEap::GlobalKernelObjectHandle() + { + return &iSemaphr; + } + +TInt CSimSmartCardEap::SimInitialiseEapMethod(const TTsyReqHandle aTsyReqHandle, TThreadId* aThreadId) + { + LOGPHONE1("CSimSmartCardEap::SimInitialiseEapMethod called"); + // This can only be called through RMobileSmartCardEap for one instance + + if (iSSInitialised) + { + // re-initialise request sent, so will be treated as a mistake + // and nothing will happen! + ReqCompleted(aTsyReqHandle, KErrNone); + } + else + { + delete iCliTerminationListener; + TRAPD(err, iCliTerminationListener = CThreadTerminationListener::NewL(this, *aThreadId)); + if (err != KErrNone) + { + LOGPHONE2("ERROR could not create a client termination listener [err=%d] (not initialised)", err); + ReqCompleted(aTsyReqHandle, err); + } + else + { + iProcedureData = iEapMan->ProcData(iAID, iEapType); + if (iProcedureData == NULL) + { + LOGPHONE1("ERROR could not find sub-session's procedure"); + ReqCompleted(aTsyReqHandle, KErrNotFound); + return KErrNone; + } + + iSSInitialised = ETrue; + iCliTerminationListener->Start(); + iAccessStatus = RMobileSmartCardEap::EEapMethodInUseApplicationActive; + SimCompleteNotifyEapMethodAccessStatusChange(); + ReqCompleted(aTsyReqHandle, KErrNone); + } + } + + return KErrNone; + } + +TInt CSimSmartCardEap::SimInitialiseEapMethodCancel(const TTsyReqHandle aTsyReqHandle) + { + LOGPHONE1("CSimSmartCardEap::SimInitialiseEapMethodCancel called"); + iProcedureData = NULL; + iSSInitialised = EFalse; + iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable; + SimCompleteNotifyEapMethodAccessStatusChange(); + ReqCompleted(aTsyReqHandle, KErrCancel); + return KErrNone; + } + +TInt CSimSmartCardEap::SimGetUserIdentity(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapUserIdType* aEapIdType, TDes8* aUserId) + { + LOGPHONE1("CSimSmartCardEap::SimGetUserIdentity called"); + + RMobileSmartCardEap::TEapUserIdentityV6Pckg *userIdPckg = reinterpret_cast(aUserId); + RMobileSmartCardEap::TEapUserIdentityV6 &userId = (*userIdPckg)(); + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(userId); + if(err != KErrNone) + { + iPhone->ReqCompleted(aTsyReqHandle, err); + return KErrNone; + } + + if (*aEapIdType == RMobileSmartCardEap::EPermanentIdentity) + { + if (iProcedureData->iEapId == NULL) + { + ReqCompleted(aTsyReqHandle, KErrNotFound); + LOGPHONE1("ERROR EAP sub-session does not contain EPermanentIdentity"); + return KErrNone; + } + + userId.iEapId = iProcedureData->iEapId->Des(); + } + else if (*aEapIdType == RMobileSmartCardEap::EPseudonymIdentity) + { + if (iProcedureData->iEapPsId == NULL) + { + ReqCompleted(aTsyReqHandle, KErrNotFound); + LOGPHONE1("ERROR EAP sub-session does not contain EPseudonymIdentity"); + return KErrNone; + } + + userId.iEapId = iProcedureData->iEapPsId->Des(); + } + else + { + ReqCompleted(aTsyReqHandle, KErrArgument); + LOGPHONE2("ERROR invalid EAP id type requested [tag=%d]", *aEapIdType); + return KErrNone; + } + + ReqCompleted(aTsyReqHandle, KErrNone); + return KErrNone; + } + +TInt CSimSmartCardEap::SimGetUserIdentityCancel(const TTsyReqHandle aTsyReqHandle) + { + LOGPHONE1("CSimSmartCardEap::SimGetUserIdentityCancel called"); + ReqCompleted(aTsyReqHandle, KErrCancel); + return KErrNone; + } + +TInt CSimSmartCardEap::SimGetAuthenticationStatus(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapAuthStatus* aAuthStatus) + { + LOGPHONE1("CSimSmartCardEap::SimGetAuthenticationStatus called"); + + (*aAuthStatus) = iAuthStatus; + + ReqCompleted(aTsyReqHandle, KErrNone); + return KErrNone; + } + +TInt CSimSmartCardEap::SimGetAuthenticationStatusCancel(const TTsyReqHandle aTsyReqHandle) + { + LOGPHONE1("CSimSmartCardEap::SimGetAuthenticationStatusCancel called"); + ReqCompleted(aTsyReqHandle, KErrCancel); + return KErrNone; + } + +TInt CSimSmartCardEap::SimGetEapKey(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapKeyTag* aEapKeyTag, TDes8* aKey) + { + LOGPHONE1("CSimSmartCardEap::SimGetEapKey called"); + + RMobileSmartCardEap::TEapKeyV6Pckg *keyPckg = reinterpret_cast(aKey); + RMobileSmartCardEap::TEapKeyV6 &key = (*keyPckg)(); + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(key); + if(err != KErrNone) + { + iPhone->ReqCompleted(aTsyReqHandle, err); + return KErrNone; + } + + if (*aEapKeyTag == RMobileSmartCardEap::EEapKeyMSK) + { + if (iProcedureData->iEapKey == NULL) + { + ReqCompleted(aTsyReqHandle, KErrNotFound); + LOGPHONE1("ERROR EAP sub-session does not contain EEapKeyMSK"); + return KErrNone; + } + + key.iEapKey = iProcedureData->iEapKey->Des(); + } + else if (*aEapKeyTag == RMobileSmartCardEap::EEapKeyEMSK) + { + if (iProcedureData->iEapExtKey == NULL) + { + ReqCompleted(aTsyReqHandle, KErrNotFound); + LOGPHONE1("ERROR EAP sub-session does not contain EEapKeyEMSK"); + return KErrNone; + } + + key.iEapKey = iProcedureData->iEapExtKey->Des(); + } + else + { + ReqCompleted(aTsyReqHandle, KErrArgument); + LOGPHONE2("ERROR invalid EAP key tag requested [tag=%d]", *aEapKeyTag); + return KErrNone; + } + + ReqCompleted(aTsyReqHandle, KErrNone); + return KErrNone; + } + +TInt CSimSmartCardEap::SimGetEapKeyCancel(const TTsyReqHandle aTsyReqHandle) + { + LOGPHONE1("CSimSmartCardEap::SimGetEapKeyCancel called"); + ReqCompleted(aTsyReqHandle, KErrCancel); + return KErrNone; + } + +TInt CSimSmartCardEap::SimSetAuthenticateDataForPhase1(const TTsyReqHandle aTsyReqHandle, TDes8* aEapAuthData, TInt* aPhase1Size) + { + LOGPHONE1("CSimSmartCardEap::SimSetAuthenticateDataForPhase1 called"); + + if (iCurrentChallenge >= iProcedureData->iChResp.Count()) + { + ReqCompleted(aTsyReqHandle, KErrAccessDenied); + return KErrNone; + } + + RMobileSmartCardEap::CEapAuthenticateRequestDataV6* authReq = NULL; + TRAPD(err, authReq = RMobileSmartCardEap::CEapAuthenticateRequestDataV6::NewL()); + if (err != KErrNone) + { + LOGPHONE2("ERR Could not allocate memory for challenge request object [err=%d]", err); + ReqCompleted(aTsyReqHandle, err); + return KErrNone; + } + + TRAP(err, authReq->InternalizeL(*aEapAuthData)); + if (err != KErrNone) + { + LOGPHONE2("ERR Could not allocate memory for challenge request [err=%d]", err); + ReqCompleted(aTsyReqHandle, err); + return KErrNone; + } + + TPtr8 reqPacket = authReq->GetEapReqPacket(); + + TPtr8 tempPtr(NULL, 0); + tempPtr.Set(iProcedureData->iChResp[iCurrentChallenge].iChallenge->Des()); + + if (reqPacket != tempPtr) + { + LOGPHONE2("ERR challenge request does not match config [currentChallenge=%d]", iCurrentChallenge); + ReqCompleted(aTsyReqHandle, KErrCorrupt); + return KErrNone; + } + + (*aPhase1Size) = iProcedureData->iChResp[iCurrentChallenge].iResp->Length(); + + ReqCompleted(aTsyReqHandle, KErrNone); + return KErrNone; + } + +TInt CSimSmartCardEap::SimGetAuthenticateDataForPhase2(const TTsyReqHandle aTsyReqHandle, TDes8* /*aEapAuthData*/, TDes8* aPhase2Resp) + { + LOGPHONE1("CSimSmartCardEap::SimSetAuthenticateDataForPhase2 called"); + + if (iCurrentChallenge >= iProcedureData->iChResp.Count()) + { + ReqCompleted(aTsyReqHandle, KErrAccessDenied); + return KErrNone; + } + + TPtr8 tempPtr(NULL, 0); + tempPtr.Set(iProcedureData->iChResp[iCurrentChallenge].iResp->Des()); + + aPhase2Resp->Copy(tempPtr); + iAuthStatus = iProcedureData->iChResp[iCurrentChallenge].iAuthStatus; + iCurrentChallenge++; + + ReqCompleted(aTsyReqHandle, KErrNone); + return KErrNone; + } + +TInt CSimSmartCardEap::SimSmartCardEapAuthenticationCancel(const TTsyReqHandle aTsyReqHandle) + { + LOGPHONE1("CSimSmartCardEap::SimSmartCardEapAuthenticationCancel called"); + ReqCompleted(aTsyReqHandle, KErrCancel); + return KErrNone; + } + +TInt CSimSmartCardEap::SimReleaseEapMethod(const TTsyReqHandle aTsyReqHandle) + { + LOGPHONE1("CSimSmartCardEap::SimReleaseEapMethod called"); + iSSInitialised = EFalse; + iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable; + ReqCompleted(aTsyReqHandle, KErrNone); + + SimCompleteNotifyEapMethodAccessStatusChange(); + + // remove config entry from manager + iEapMan->ProcDataUseCompleted(iProcedureData); + iProcedureData = NULL; + + return KErrNone; + } + +TInt CSimSmartCardEap::SimGetEapMethodAccessStatus(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapMethodAccessStatus* aEapState) + { + LOGPHONE1("CSimSmartCardEap::SimGetEapMethodAccessStatus called"); + *aEapState = iAccessStatus; + ReqCompleted(aTsyReqHandle, KErrNone); + return KErrNone; + } + +TInt CSimSmartCardEap::SimNotifyEapMethodAccessStatusChange(const TTsyReqHandle aTsyReqHandle, RMobileSmartCardEap::TEapMethodAccessStatus* aEapState) + { + LOGPHONE1("CSimSmartCardEap::SimNotifyEapMethodAccessStatusChange called"); + __ASSERT_ALWAYS(!iEapAccessNotifyData.iNotifyPending, PanicClient(EEtelPanicRequestAsyncTwice)); + + iEapAccessNotifyData.iNotifyPending = ETrue; + iEapAccessNotifyData.iNotifyHandle = aTsyReqHandle; + iEapAccessNotifyData.iNotifyData = aEapState; + + return KErrNone; + } + +TInt CSimSmartCardEap::SimNotifyEapMethodAccessStatusChangeCancel(const TTsyReqHandle aTsyReqHandle) + { + LOGPHONE1("CSimSmartCardEap::SimNotifyEapMethodAccessStatusChangeCancel called"); + if(iEapAccessNotifyData.iNotifyPending) + { + iEapAccessNotifyData.iNotifyPending = EFalse; + ReqCompleted(aTsyReqHandle, KErrCancel); + return KErrNone; + } + +// iPhone->ReqCompleted(aTsyReqHandle,KErrNone); + return KErrNone; + } + +void CSimSmartCardEap::SimCompleteNotifyEapMethodAccessStatusChange() + { + LOGPHONE1("CSimSmartCardEap::SimCompleteNotifyEapMethodAccessStatusChange called"); + + if(iEapAccessNotifyData.iNotifyPending) + { + iEapAccessNotifyData.iNotifyPending = EFalse; + *(reinterpret_cast(iEapAccessNotifyData.iNotifyData)) = iAccessStatus; + ReqCompleted(iEapAccessNotifyData.iNotifyHandle, KErrNone); + } + } + +void CSimSmartCardEap::ClientHasTerminated(TInt /*aExitReason*/) + { + // Can TSY do anything with the thread's exit reason? + // Exit code can be a zero (e.g. for KERN-EXEC 0) a positive value + // (e.g. for KERN-EXEC 3) or a negative error. + + switch (iAccessStatus) + { + case RMobileSmartCardEap::EEapMethodInUseApplicationActive: + iSSInitialised = EFalse; + iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable; + SimCompleteNotifyEapMethodAccessStatusChange(); + iSemaphr.Signal(); + + // remove config entry from manager + iEapMan->ProcDataUseCompleted(iProcedureData); + iProcedureData = NULL; + + break; + + case RMobileSmartCardEap::EEapMethodInUseApplicationInactive: + iAccessStatus = RMobileSmartCardEap::EEapMethodAvailable; + SimCompleteNotifyEapMethodAccessStatusChange(); + iSemaphr.Signal(); + break; + + default: + ; + } + } + +// +// Class definition for monitoring thread termination +// + +CSimSmartCardEap::CThreadTerminationListener* CSimSmartCardEap::CThreadTerminationListener::NewL(CSimSmartCardEap* aSubSess, const TThreadId& aId) + { + CThreadTerminationListener* self = new(ELeave) CThreadTerminationListener(aSubSess); + CleanupStack::PushL(self); + self->ConstructL(aId); + CleanupStack::Pop(self); + return self; + } + +CSimSmartCardEap::CThreadTerminationListener::CThreadTerminationListener(CSimSmartCardEap* aSubSess) +: CActive(EPriorityStandard), iSubSess(aSubSess) + { + } + +void CSimSmartCardEap::CThreadTerminationListener::ConstructL(const TThreadId& aId) + { + TInt openTh = iCliThread.Open(aId); + User::LeaveIfError(openTh); + CActiveScheduler::Add(this); + } + +void CSimSmartCardEap::CThreadTerminationListener::Start() + { + iCliThread.Logon(iStatus); + SetActive(); + } + +void CSimSmartCardEap::CThreadTerminationListener::RunL() + { + iSubSess->ClientHasTerminated(iStatus.Int()); + } + +void CSimSmartCardEap::CThreadTerminationListener::DoCancel() + { + iCliThread.LogonCancel(iStatus); + } + +CSimSmartCardEap::CThreadTerminationListener::~CThreadTerminationListener() + { + Cancel(); + iCliThread.Close(); + }