diff -r 000000000000 -r b497e44ab2fc terminalsecurity/SCP/SCPServer/src/SCPServer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/terminalsecurity/SCP/SCPServer/src/SCPServer.cpp Thu Dec 17 09:07:52 2009 +0200 @@ -0,0 +1,2915 @@ +/* +* Copyright (c) 2000 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: Implementation of terminalsecurity components +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include + +#include "SCPServer.h" +#include "SCPSession.h" + +#ifdef SCP_USE_POLICY_ENGINE +#include +#include +#include +#include "DMUtilObserver.h" +#include "SCPParamDBController.h" +#endif // SCP_USE_POLICY_ENGINE + +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS +#include "SCPPluginManager.h" +#include "SCPPluginEventHandler.h" +#include +#include "SCP_IDs.h" +// For Central Repository +#include +#include "SCPCodePrivateCRKeys.h" +#include "SCPLockCode.h" +#include +//#endif // __SAP_DEVICE_LOCK_ENHANCEMENTS + +#include + +#include "SCPDebug.h" +#include +// For Device encryption +#include +#include + +// ==================== LOCAL FUNCTIONS ==================== + +// --------------------------------------------------------- +// PanicServer Panics the server thread +// +// Status : Approved +// --------------------------------------------------------- +// +GLDEF_C void PanicServer(TSCPServPanic aPanic) + { + _LIT( KTxtServerPanic,"SCP Server panic" ); + User::Panic( KTxtServerPanic, aPanic ); + } + +// ================= MEMBER FUNCTIONS ======================= + +// --------------------------------------------------------- +// CSession2* CSCPServer::CSCPServer() +// C++ default constructor +// +// Status : Approved +// --------------------------------------------------------- +// +CSCPServer::CSCPServer(TInt aPriority) + : CPolicyServer( aPriority, CSCPServerPolicy ), + iConfiguration( &iRfs ), + iALPeriodRep( NULL ), + iShutdownTimer( NULL ), + iOverrideForCleanup(EFalse) { + Dprint( (_L("--> CSCPServer::CSCPServer()") )); + + Dprint( (_L("<-- CSCPServer::CSCPServer()") )); + } + + + +// --------------------------------------------------------- +// CSession2* CSCPServer::ConstructL() +// Symbian 2nd phase constructor +// +// Status : Approved +// --------------------------------------------------------- +// +void CSCPServer::ConstructL() + { + Dprint(_L("[CSCPServer]-> ConstructL() >>>")); + + TRAPD( errf, FeatureManager::InitializeLibL() ); + if( errf != KErrNone ) + { + User::Leave(errf); + } + + StartL( KSCPServerName ); + + User::LeaveIfError( iRfs.Connect() ); + + iConfiguration.Initialize(); + + // Assign default config flag + iConfiguration.iConfigFlag = KSCPConfigUnknown; + + // Assign the default codes + iConfiguration.iSecCode.Zero(); + iConfiguration.iSecCode.Append( KSCPDefaultSecCode ); + +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS +if(FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) +{ + // Reset code block parameters + iConfiguration.iFailedAttempts = 0; + iConfiguration.iBlockedAtTime = KSCPNotBlocked; + + iPluginEventHandler = CSCPPluginEventHandler::NewL( &iRfs ); + + iPluginManager = CSCPPluginManager::NewL( this ); + + // Hash the default code + TBuf hashBuf; + hashBuf.Zero(); + + HBufC* codeHBuf = HBufC::NewLC( KSCPPasscodeMaxLength + 1 ); + TPtr codeBuf = codeHBuf->Des(); + codeBuf.Zero(); + + codeBuf.Copy( KSCPDefaultEnchSecCode ); + iPluginEventHandler->HashInput( codeBuf, hashBuf ); + + iConfiguration.iEnhSecCode.Zero(); + iConfiguration.iEnhSecCode.Append( hashBuf ); + + CleanupStack::PopAndDestroy( codeHBuf ); +} +//#endif + + // Assign the default max timeout + iConfiguration.iMaxTimeout = KSCPDefaultMaxTO; + iConfiguration.iBlockedInOOS = 0; + + // Read the configuration, overwriting the default values + TInt ret = KErrNone; + TRAPD( err, ret = iConfiguration.ReadSetupL() ); + if ( ( err != KErrNone ) || ( ret != KErrNone ) ) + { + Dprint( (_L("CSCPServer::ConstructL(): ERROR reading the \ + configuration file: %d"), err )); + } + else + { + Dprint( (_L("CSCPServer::ConstructL(): Configration read OK") )); + } + + Dprint( (_L("CSCPServer::ConstructL(): Connecting to CenRep") )); + iALPeriodRep = CRepository::NewL( KCRUidSecuritySettings ); + + // Check for factory settings + CheckIfRfsPerformedL(); + Dprint(_L("[CSCPServer]-> ConstructL() <<< ")); + } + + + + +// --------------------------------------------------------- +// CSession2* CSCPServer::NewL() +// Static constructor. +// +// Status : Approved +// --------------------------------------------------------- +// +CSCPServer* CSCPServer::NewL() + { + Dprint( (_L("--> CSCPServer::NewL()") )); + + CSCPServer *pS = new (ELeave) CSCPServer( EPriority ); + + CleanupStack::PushL( pS ); + pS->ConstructL(); + CleanupStack::Pop( pS ); + + Dprint( (_L("<-- CSCPServer::NewL()") )); + return pS; + } + + + +// --------------------------------------------------------- +// CSession2* CSCPServer::~CSCPServer () +// Destructor +// +// Status : Approved +// --------------------------------------------------------- +// +CSCPServer::~CSCPServer() + { + Dprint( (_L("--> CSCPServer::~CSCPServer()") )); + + TRAPD( err, iConfiguration.WriteSetupL() ); + if ( err != KErrNone ) + { + Dprint( (_L("CSCPServer::~CSCPServer(): ERROR writing the \ + configuration file: %d"), err )); + } + + delete iALPeriodRep; + iALPeriodRep = NULL; + +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS +if(FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) +{ + + delete iPluginManager; + iPluginManager = NULL; + + delete iPluginEventHandler; + iPluginEventHandler = NULL; +} +FeatureManager::UnInitializeLib(); +//#endif // __SAP_DEVICE_LOCK_ENHANCEMENTS + + if ( iPhone.SubSessionHandle() ) + { + iPhone.Close(); + } + + if ( iTelServ.Handle() ) + { + iTelServ.Close(); + } + + if ( iRfs.Handle() ) + { + iRfs.Close(); + } + + Dprint( (_L("<-- CSCPServer::~CSCPServer()") )); + } + + + +// --------------------------------------------------------- +// CSession2* CSCPServer::NewSessionL (const TVersion &aVersion, const RMessage2& aMsg ) +// Checks the version and creates a new session if it matches the server version. +// +// Status : Approved +// --------------------------------------------------------- +// +CSession2* CSCPServer::NewSessionL (const TVersion &aVersion, + const RMessage2& aMsg ) const + { + Dprint( (_L("--> CSCPServer::NewSessionL()") )); + (void)aMsg; + + // Check we're the right version + TVersion v( KSCPServMajorVersionNumber, KSCPServMinorVersionNumber, + KSCPServBuildVersionNumber ); + + if ( !User::QueryVersionSupported(v, aVersion) ) + User::Leave( KErrNotSupported ); + + Dprint( (_L("<-- CSCPServer::NewSessionL()") )); + + return CSCPSession::NewL( (CSCPServer&)( *this ) ); + } + + + +// --------------------------------------------------------- +// TInt CSCPServer::ThreadFunctionStage2() +// Constructs the active scheduler and the server object, and +// runs the server. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::ThreadFunctionStage2L() + { + Dprint( (_L("--> CSCPServer::ThreadFunctionStage2()") )); + + // Naming the server thread after the server helps to debug panics + User::LeaveIfError( User::RenameThread( KSCPServerName ) ); + + // Construct the active scheduler + CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler; + CleanupStack::PushL(activeScheduler); + + // Install active scheduler + // We don't need to check whether an active scheduler is already installed + // as this is a new thread, so there won't be one + CActiveScheduler::Install( activeScheduler ); + + // Construct our server + CSCPServer* server = CSCPServer::NewL(); + CleanupStack::PushL( server ); + + RProcess::Rendezvous(KErrNone); + + // Start handling requests + Dprint( (_L("CSCPServer: Server started") )); + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy( server ); + CleanupStack::PopAndDestroy( activeScheduler ); + + Dprint( (_L("<-- CSCPServer::ThreadFunctionStage2()") )); + return KErrNone; + } + + + +// --------------------------------------------------------- +// TInt CSCPServer::ThreadFunction( TAny* ) +// First-stage server entry point, creates the cleanup stack, +// and calls the actual server worker function. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::ThreadFunction(TAny* /*aNone*/) + { + Dprint( (_L("--> CSCPServer::ThreadFunction()") )); + + __UHEAP_MARK; + + CTrapCleanup* cleanupStack = CTrapCleanup::New(); + if ( !cleanupStack ) + { + PanicServer( ECreateTrapCleanup ); + } + + TRAPD( err, ThreadFunctionStage2L() ); + if ( err != KErrNone ) + { + PanicServer( ESvrStartServer ); + } + + delete cleanupStack; + cleanupStack = NULL; + + __UHEAP_MARKEND; + + Dprint( (_L("<-- CSCPServer::ThreadFunction()") )); + return KErrNone; + } + + +// --------------------------------------------------------- +// void CSCPServer::GetEtelHandlesL() +// Opens the handles to the Etel API, if not open, and copies +// their addresses to the given pointers, if available. +// +// Status : Approved +// --------------------------------------------------------- +// +void CSCPServer::GetEtelHandlesL( RTelServer** aTelServ, RMobilePhone** aPhone ) + { + if ( !iTelServ.Handle() ) + { + // Connect to Etel + User::LeaveIfError( iTelServ.Connect() ); + + Dprint( (_L("CSCPServer::GetEtelHandlesL(): TelServ connected OK") )); + } + + if ( !iPhone.SubSessionHandle() ) + { + // Load the phone module + TInt err = iTelServ.LoadPhoneModule( KMmTsyModuleName ); + if ( err != KErrAlreadyExists ) + { + User::LeaveIfError( err ); + } + Dprint( (_L("CSCPServer::GetEtelHandlesL(): LoadPhoneModule OK") )); + + // Open the multimode TSY + User::LeaveIfError( iPhone.Open( iTelServ, KMmTsyPhoneName ) ); + + Dprint( (_L("CSCPServer::GetEtelHandlesL(): MM-Phone connected OK") )); + } + + if ( aTelServ ) + { + *aTelServ = &iTelServ; + } + + if ( aPhone ) + { + *aPhone = &iPhone; + } + } + + +// --------------------------------------------------------- +// TInt CSCPServer::GetCode( TDes& aCode ) +// Writes the stored ISA code to aCode +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::GetCode( TDes& aCode ) + { + Dprint( (_L("--> CSCPServer::GetCode()") )); + + aCode.Zero(); + aCode.Copy( iConfiguration.iSecCode ); + + Dprint( (_L("<-- CSCPServer::GetCode()") )); + return KErrNone; + } + + + +// --------------------------------------------------------- +// TInt CSCPServer::StoreCode( TDes& aCode ) +// Sets the stored ISA code to aCode and saves it to flash +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::StoreCode( TDes& aCode ) + { + Dprint( (_L("--> CSCPServer::StoreCode()") )); + + TInt ret = KErrNone; + + iConfiguration.iSecCode.Zero(); + iConfiguration.iSecCode.Copy( aCode ); + + // Unset the invalid configuration flag + iConfiguration.iConfigFlag = KSCPConfigOK; + + // The code has changed, write the new value instantly to flash + TRAPD( err, iConfiguration.WriteSetupL() ); + if ( err != KErrNone ) + { + Dprint( (_L("CSCPServer::~CSCPServer(): ERROR writing the configuration\ + file: %d"), err )); + ret = err; + } + + Dprint( (_L("<-- CSCPServer::StoreCode(): %d"), ret )); + + return ret; + } + + + +// --------------------------------------------------------- +// CSCPServer::ChangeISACodeL() +// Initializes the TSY and calls the function to change +// the ISA-side code. Automatically uses the old code stored +// on the server. +// +// Status : Approved +// --------------------------------------------------------- +// +void CSCPServer::ChangeISACodeL( RMobilePhone::TMobilePassword& aNewPassword ) + { + Dprint( (_L("--> CSCPServer::ChangeISACodeL()") )); + + RMobilePhone::TMobilePassword oldPassword; + TInt ret; + + // Check the given code + if ( !IsValidISACode( aNewPassword ) ) + { + Dprint( (_L("CSCPServer::ChangeISACodeL(): ERROR:\ + Invalid code format") )); + User::Leave( KErrArgument ); + } + + // No access to the ISA side in emulator + GetEtelHandlesL(); + + // Fetch the stored ISA password from the server + + ret = GetCode( oldPassword ); + if ( ret != KErrNone ) + { + Dprint( (_L("CSCPServer::ChangeISACodeL(): ERROR:\ + Failed to get stored code") )); + User::Leave( ret ); + } + + TRequestStatus status = KErrNone; + +#ifndef __WINS__ + // No access to the ISA side in emulator, for WINS the call always succeeds + + RMobilePhone::TMobilePhonePasswordChangeV1 changeInfo; + changeInfo.iOldPassword = oldPassword; + changeInfo.iNewPassword = aNewPassword; + + RMobilePhone::TMobilePhoneSecurityCode securityCode = + RMobilePhone::ESecurityCodePhonePassword; + + Dprint( (_L("CSCPServer::ChangeISACodeL(): Trying to change\ + the code, values %s, %s"), oldPassword.PtrZ(), aNewPassword.PtrZ() )); + + iPhone.ChangeSecurityCode(status, securityCode, changeInfo ); + + // This is a quick call, just wait here + User::WaitForRequest( status ); + +#endif // WINS + ret = status.Int(); + + if ( ret == KErrNone ) + { + Dprint( (_L("CSCPServer::ChangeISACodeL(): Code change OK") )); + + // Update the stored code in the server + if ( StoreCode( aNewPassword ) != KErrNone ) + { + Dprint( (_L("CSCPServer::ChangeISACodeL():\ + Failed to store the new code!") )); + ret = KErrGeneral; + } + } + else + { + Dprint( (_L("CSCPServer::ChangeISACodeL(): FAILED:\ + ChangeSecurityCode returned %d"), ret )); + } + + User::LeaveIfError( ret ); + Dprint( (_L("<-- CSCPServer::ChangeISACodeL()") )); + } + + + +// --------------------------------------------------------- +// TInt CSCPServer::CheckIfRfsPerformedL() +// Checks if RFS has been run from the DMUtil server. +// +// Status : Approved +// --------------------------------------------------------- +// +void CSCPServer::CheckIfRfsPerformedL() + { + Dprint( (_L("--> CSCPServer::CheckIfRfsPerformedL()") )); + + TBool resetServer = EFalse; + +#ifdef SCP_USE_POLICY_ENGINE + Dprint( (_L("--> CSCPServer::CheckIfRfsPerformedL() : checking if Rfs performed") )); + TRAPD(err,TDMUtilPassiveObserver::IsRFSPerformedL()); + if ( err == 1 ) + { + resetServer = ETrue; + } + else if ( err == 0) + { + Dprint( (_L("--> CSCPServer::CheckIfRfsPerformedL() : Rfs is not performed") )); + } + else + { + Dprint( (_L("--> CSCPServer::CheckIfRfsPerformedL() : Leave occured. Ignore it.") )); + } +#endif // SCP_USE_POLICY_ENGINE + + if ( resetServer ) + { + Dprint( (_L("CSCPServer::CheckIfRfsPerformedL(): Rfs performed, resetting parameters") )); + + // Reset max. period + iConfiguration.iMaxTimeout = 0; + +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS +if(FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) +{ + // Reset the common plugin parameter storage + TRAPD( err, iPluginEventHandler->ResetConfigurationL() ); + if ( err != KErrNone ) + { + Dprint( (_L("CSCPServer::CheckIfRfsPerformedL(): ERROR resetting the plugin\ + configuration: %d"), err )); + } + + // Reset the plugin's private storage + CSCPParamObject* inParams = CSCPParamObject::NewL(); + CleanupStack::PushL( inParams ); + + inParams->Set( KSCPParamContext, KSCPContextRfs ); + + CSCPParamObject* reply = + iPluginManager->PostEvent( KSCPEventReset, *inParams ); + CleanupStack::PopAndDestroy( inParams ); + + // Ignore the reply, no plugin should request any actions + if ( reply != NULL ) + { + delete reply; + } +} +//#endif // __SAP_DEVICE_LOCK_ENHANCEMENTS + + } + + Dprint( (_L("<-- CSCPServer::CheckIfRfsPerformedL()") )); + } + + + + +// --------------------------------------------------------- +// void CSCPServer::ValidateConfigurationL() +// Checks if the correct ISA code is stored on the server. +// This method is used to counter the 3-button format function +// available on some devices. +// +// Status : Approved +// --------------------------------------------------------- +// +void CSCPServer::ValidateConfigurationL( TInt aMode ) + { + Dprint( (_L("--> CSCPServer::ValidateConfigurationL()") )); + + if ( iConfiguration.iConfigFlag == KSCPConfigOK ) + { + // The configuration has already been checked, exit + Dprint( (_L("CSCPServer::ValidateConfigurationL(): Configuration is non-default.") )); + User::Leave( KErrNone ); + } + else if ( aMode == KSCPInitial ) + { + // Return here, must be checked by complete mode + User::Leave( KErrAccessDenied ); + } + + RMobilePhone::TMobilePassword storedCode; + storedCode.Zero(); + + User::LeaveIfError( GetCode( storedCode ) ); + TInt hashedISAcode; + TSCPSecCode hashedCode; +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS +if(FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) +{ + /*TInt*/ hashedISAcode = HashISACode( iConfiguration.iEnhSecCode ); + // TSCPSecCode hashedCode; + hashedCode.Zero(); + hashedCode.AppendNum( hashedISAcode ); +} +//#endif // __SAP_DEVICE_LOCK_ENHANCEMENTS + + Dprint( (_L("CSCPServer::ValidateConfigurationL(): Checking code: %s"), storedCode.PtrZ() )); + + // Check that the ISA code is stored correctly + TRAPD( err, CheckISACodeL( storedCode ) ); + if ( err == KErrNone ) + { + iConfiguration.iConfigFlag = KSCPConfigOK; + } + else if ( err == KErrAccessDenied ) + { + iConfiguration.iConfigFlag = KSCPConfigInvalid; + } + else if ( err == KErrLocked ) + { + Dprint( (_L("CSCPServer::ValidateConfigurationL(): ISA code locked.") )); + } + else + { + Dprint( (_L("CSCPServer::ValidateConfigurationL(): ERROR in validation.") )); + } + +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS +if(FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) +{ + if ( err == KErrNone ) + { + // Check that the codes are in-sync with each other. Especially the default ISA code must + // be changed according to the default enhanced code. + if ( storedCode.Compare( hashedCode ) != 0 ) + { + Dprint( (_L("CSCPServer::ValidateConfigurationL(): Correct ISA code stored.\ + Changing ISA code to match enhanced code => %d"), hashedISAcode )); + + storedCode.Copy( hashedCode ); + // Change the ISA code to match the hashed code + ChangeISACodeL( storedCode ); + } + } + else if ( ( err == KErrAccessDenied ) && ( storedCode.Compare( hashedCode ) != 0 ) ) + { + // Try again with the hashed code + TRAP( err, CheckISACodeL( hashedCode ) ); + + if ( err == KErrNone ) + { + Dprint( (_L("CSCPServer::ValidateConfigurationL(): Hashed code is correct.\ + Storing hashed code(%d)"), hashedISAcode )); + + if ( StoreCode( hashedCode ) == KErrNone ) + { + iConfiguration.iConfigFlag = KSCPConfigOK; + } + } + } +} +//#endif // __SAP_DEVICE_LOCK_ENHANCEMENTS + + TRAPD( err2, iConfiguration.WriteSetupL() ); + if ( err2 != KErrNone ) + { + Dprint( (_L("CSCPServer::ValidateConfigurationL(): WARNING: failed to write configuration\ + : %d"), err2 )); + } + + User::LeaveIfError( err ); + + Dprint( (_L("<-- CSCPServer::ValidateConfigurationL()") )); + } + + + + +// --------------------------------------------------------- +// void CSCPServer::CheckISACodeL( ) +// Verifies the given ISA code. +// +// Status : Approved +// --------------------------------------------------------- +// +void CSCPServer::CheckISACodeL( RMobilePhone::TMobilePassword aCode ) + { + TInt ret = KErrNone; + +#ifdef __WINS__ + + (void)aCode; + +#endif // __WINS__ + + RMobilePhone::TMobilePhoneSecurityCode secCodeType; + secCodeType = RMobilePhone::ESecurityCodePhonePassword; + + RMobilePhone::TMobilePassword required_fourth; + + TRequestStatus status = KRequestPending; + + GetEtelHandlesL(); + +#ifndef __WINS__ // We cannot check the code in WINS, always return KErrNone. + + iPhone.VerifySecurityCode( status, secCodeType, aCode, required_fourth ); + + // This should be quick, wait here + User::WaitForRequest( status ); + + ret = status.Int(); + +#endif // !__WINS__ + + if ( ret == KErrNone ) + { + // Code OK + Dprint( (_L("CSCPServer::CheckISACodeL(): ISA code OK") )); + iConfiguration.iBlockedInOOS = 0; + } + else + { + if ( ( ret == KErrAccessDenied ) || ( ret == KErrGsm0707IncorrectPassword ) ) + { + Dprint( (_L("CSCPServer::CheckISACodeL(): ISA code NOT OK") )); + if (iConfiguration.iBlockedInOOS == 1) + { + iConfiguration.iBlockedInOOS = 0; + Dprint( (_L("CSCPServer::CheckISACodeL():iBlockedInOOS = 0, KErrAccessDenied") )); + } + ret = KErrAccessDenied; + } + else if ( ( ret == KErrGsmSSPasswordAttemptsViolation ) || ( ret == KErrLocked ) ) + { + Dprint( (_L("CSCPServer::CheckISACodeL(): ISA code BLOCKED") )); + if (ret==KErrGsmSSPasswordAttemptsViolation) + { + Dprint( (_L("CSCPServer::CheckISACodeL(): KErrGsmSSPasswordAttemptsViolation") )); + } + else + { + Dprint( (_L("CSCPServer::CheckISACodeL(): KErrLocked") )); + } + ret = KErrLocked; + if (iConfiguration.iBlockedInOOS == 0) + { + iConfiguration.iBlockedInOOS = 1; + Dprint( (_L("CSCPServer::CheckISACodeL():iBlockedInOOS = 1, KSCPErrCodeBlockStarted") )); + ret = KSCPErrCodeBlockStarted; + } + } + else + { + Dprint( (_L("CSCPServer::CheckISACodeL(): ERROR reply checking ISA code: %d"), + status.Int() )); + } + } + TRAPD( err, iConfiguration.WriteSetupL() ); + if ( err != KErrNone ) + { + Dprint( (_L("CSCPServer::StoreEnhCode(): WARNING:\ + failed to write configuration: %d"), err )); + } + + User::LeaveIfError( ret ); + } + + +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS + +// --------------------------------------------------------- +// CSCPServer::HashISACode() +// Creates a 5-digit ISA code from the given MD5 digest. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::HashISACode( TDes& aHashBuf ) + { + // aHashBuf must be a MD5 hash digest + if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + return KErrNotSupported; + } + if ( aHashBuf.Length() < KSCPMD5HashLen ) + { + PanicServer( EBadHashDigest ); + } + + // Compute the hash sum as four 32-bit integers. + TInt64 hashSum = *(reinterpret_cast(&aHashBuf[0])) + + *(reinterpret_cast(&aHashBuf[4])) + + *(reinterpret_cast(&aHashBuf[8])) + + *(reinterpret_cast(&aHashBuf[12])); + + // Create a five-digit security code from this number + TInt ISAcode = ( hashSum % 90000 ) + 10000; + Dprint( (_L("CSCPServer::HashISACode(): Hashed ISA code is %d"), ISAcode )); + + return ISAcode; + } + + +// --------------------------------------------------------- +// TInt CSCPServer::StoreEnhCode( TDes& aCode ) +// Sets the stored enhanced code to aCode and saves it to flash +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::StoreEnhCode( TDes& aCode, TSCPSecCode* aNewDOSCode /*=NULL*/) + { + + if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + return KErrNotSupported; + } + Dprint( (_L("CSCPServer::StoreEnhCode()") )); + + // Hash the code and save it + TBuf hashBuf; + hashBuf.Zero(); + iPluginEventHandler->HashInput( aCode, hashBuf ); + + TInt ISAcode = HashISACode( hashBuf ); + + RMobilePhone::TMobilePassword newCode; + newCode.Zero(); + newCode.AppendNum( ISAcode ); + + // Change the ISA code + TRAPD( err, ChangeISACodeL( newCode ) ); + + if ( err == KErrNone ) + { + iConfiguration.iEnhSecCode.Zero(); + iConfiguration.iEnhSecCode.Copy( hashBuf ); + + if ( aNewDOSCode != NULL ) + { + // Copy the updated DOS code + (*aNewDOSCode).Copy( newCode ); + } + + TRAPD( err, iConfiguration.WriteSetupL() ); + if ( err != KErrNone ) + { + Dprint( (_L("CSCPServer::StoreEnhCode(): WARNING:\ + failed to write configuration: %d"), err )); + + } + else + { + /* Get the very first character of the new lock code and set the default input mode of the + lock code query on the basis of the first character. */ + ch = aCode[0]; + + CRepository* repository = NULL; + def_mode = ch.IsDigit() ? 0 : 1; + TRAPD(err, repository = CRepository::NewL( KCRUidSCPParameters )); + if (err == KErrNone) + { + err = repository->Set( KSCPLockCodeDefaultInputMode , def_mode ); + delete repository; + } + + /* Set the value in the cenrep that the default lock code has been changed if it is not + * already set + * */ + TRAP(err, repository = CRepository :: NewL(KCRUidSCPLockCode)); + + if(err == KErrNone) { + err = repository->Set(KSCPLockCodeDefaultLockCode, 0); + delete repository; + } + } + } + else + { + Dprint( (_L("CSCPServer::StoreEnhCode(): ERROR:\ + failed to change ISA code, aborting storage operation: %d"), err )); + + } + + return err; + } + +//#endif // __SAP_DEVICE_LOCK_ENHANCEMENTS + + + + +// --------------------------------------------------------- +// TBool CSCPServer::IsOperationInProgress( TSCPAdminCommand aCommand ) +// Loops through the sessions on the server and and calls the +// query command to check if the given operation is in progress. +// +// Status : Approved +// --------------------------------------------------------- +// +TBool CSCPServer::IsOperationInProgress( TSCPAdminCommand aCommand ) + { + Dprint( (_L("--> CSCPServer::IsOperationInProgress()") )); + + // Iterate through the sessions and find out if one has started the given operation + TBool ret = EFalse; + + iSessionIter.SetToFirst(); + CSCPSession* curSession = NULL; + while ( ( curSession = static_cast( iSessionIter++ ) ) != NULL ) + { + if ( curSession->IsOperationInProgress( aCommand ) ) + { + ret = ETrue; + break; + } + } + + Dprint( (_L("<-- CSCPServer::IsOperationInProgress(): %d"), ret )); + return ret; + } + + + + +// --------------------------------------------------------- +// TBool CSCPServer::AcknowledgementReceived( TSCPAdminCommand aCommand ) +// Loops through the sessions on the server, sends the acknowledgements, +// and checks if one was waiting for it (ETrue). +// +// Status : Approved +// --------------------------------------------------------- +// +TBool CSCPServer::AcknowledgementReceived( TSCPAdminCommand aCommand ) + { + Dprint( (_L("--> CSCPServer::AcknowledgementReceived()") )); + + // Iterate through the sessions and propagate the acknowledgement. + // Set the return parameter, if one was waiting for the ack + TBool ret = EFalse; + + iSessionIter.SetToFirst(); + CSCPSession* curSession = NULL; + while ( ( curSession = static_cast( iSessionIter++ ) ) != NULL ) + { + if ( curSession->AcknowledgeOperation( aCommand ) ) ret = ETrue; + } + + Dprint( (_L("<-- CSCPServer::AcknowledgementReceived(): %d"), ret )); + return ret; + } + + + + +// --------------------------------------------------------- +// TInt CSCPServer::SetAutolockPeriod() +// Sets the autolock period in either SharedData or CenRep. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer :: SetAutolockPeriodL(TInt aValue) { + Dprint( (_L("CSCPServer::SetAutolockPeriodL(): Setting the value") )); + + TInt ret = KErrNone; + + + // Change the value in CenRep + ret = iALPeriodRep->Set( KSettingsAutoLockTime, aValue ); + + Dprint( (_L("[CSCPServer]-> SetAutolockPeriodL() <<<") )); + return ret; + } + +// --------------------------------------------------------- +// TInt CSCPServer::GetAutolockPeriodL( TInt& aValue ) +// Gets the autolock period from either SharedData or CenRep. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::GetAutolockPeriodL( TInt& aValue ) + { + TInt ret = KErrNone; + + Dprint( (_L("CSCPServer::GetAutolockPeriodL(): Getting the value") )); + + // Fetch the value from CenRep + ret = iALPeriodRep->Get( KSettingsAutoLockTime, aValue ); + + return ret; + } + + + + +// --------------------------------------------------------- +// CSCPServer::ChangeCodePolicy() +// Sets the new policy either internally or through the policy +// engine. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::ChangeCodePolicy( const TDesC& aValue ) + { + TInt ret = KErrNone; + + TLex lex( aValue ); + TInt value; + + ret = lex.Val( value ); + + if ( ret == KErrNone ) + { + if ( ( value < 0 ) || ( value > 1 ) ) + { + ret = KErrArgument; + } + else + { + Dprint( (_L("CSCPServer::ChangeCodePolicy(): %d"), value )); + +#ifdef SCP_USE_POLICY_ENGINE + + RPolicyEngine policyEngine; + ret = policyEngine.Connect(); + + RPolicyManagement policyManagement; + if ( ret == KErrNone ) + { + ret = policyManagement.Open( policyEngine ); + } + + TParserResponse response; + + if ( ret == KErrNone ) + { + Dprint( (_L("CSCPServer::ChangeCodePolicy(): Executing operation") )); + if ( value == 1 ) + { + // Allow change + ret = policyManagement.ExecuteOperation( + KSCPCodePolicyAllowOperation, + response + ); + } + else + { + // Deny change + ret = policyManagement.ExecuteOperation( + KSCPCodePolicyDisallowOperation, + response + ); + } + + if ( ret == KErrNone ) + { + const TDesC8& retMsg = response.GetReturnMessage(); + + if ( retMsg.Compare( KSCPOKResponse ) != 0 ) + { + #ifdef _DEBUG + TBuf<256> dummyBuf; + dummyBuf.Copy( retMsg ); + Dprint( (_L("CSCPServer::ChangeCodePolicy(): Response not OK:\ + %S"), &dummyBuf )); + #endif + + // We must check this for an error as well + ret = KErrGeneral; + } + } + } + + if ( policyManagement.SubSessionHandle() ) + { + policyManagement.Close(); + } + + if ( policyEngine.Handle() ) + { + policyEngine.Close(); + } + +#else // !SCP_USE_POLICY_ENGINE + + iCodePolicy = value; + +#endif // SCP_USE_POLICY_ENGINE + } + } + + Dprint( (_L("<-- CSCPServer::ChangeCodePolicy(): %d"), ret )); + return ret; + } + + + + +// --------------------------------------------------------- +// CSCPServer:GetCodePolicy() +// Gets the policy from internal storage of from the policy +// engine. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::GetCodePolicy( TDes& aValue ) + { + Dprint( (_L("--> CSCPServer::GetCodePolicy()") )); + TInt ret = KErrNone; + + aValue.Zero(); + +#ifdef SCP_USE_POLICY_ENGINE + TResponse response; + RPolicyEngine policyEngine; + ret = policyEngine.Connect(); + + RPolicyRequest policyRequest; + if ( ret == KErrNone ) + { + ret = policyRequest.Open( policyEngine ); + } + + if(ret == KErrNone) { + TRequestContext context; + + using namespace PolicyEngineXACML; + TRAPD( err , + context.AddResourceAttributeL( KResourceId, + KDeviceLockPasscodeVisibility, + KStringDataType) + ); + if ( err == KErrNone ) + { + ret = policyRequest.MakeRequest( context, response ); + } + else + { + ret = err; + } + } + + if ( ret == KErrNone ) + { + if ( response.GetResponseValue() == EResponsePermit ) + { + // Allow security code change + aValue.AppendNum( 1 ); + } + else + { + // Do not allow security code change + aValue.AppendNum( 0 ); + } + } + + if ( policyRequest.SubSessionHandle() ) + { + policyRequest.Close(); + } + + if ( policyEngine.Handle() ) + { + policyEngine.Close(); + } + +#else // !SCP_USE_POLICY_ENGINE + + aValue.AppendNum( iCodePolicy ); + +#endif // SCP_USE_POLICY_ENGINE + + Dprint((_L("[CSCPServer] <<< GetCodePolicy(): %d"), ret)); + return ret; + } + + + + +// --------------------------------------------------------- +// TInt CSCPServer::SetParameterValueL( TSCPParameterID aID, TDesC& aValue ) +// Handles the setting of the parameter values. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::SetParameterValueL( TInt aID, const TDesC& aValue, TUint32 aCallerIdentity ) + { + Dprint( (_L("--> CSCPServer::SetParameterValueL( %d )"), aID )); + +#ifdef __SCP_DEBUG + // Used to "emulate 3-button boot" in debug builds + if ( aID == 9999 ) + { + iConfiguration.iConfigFlag = KSCPConfigUnknown; + iConfiguration.iSecCode = KSCPDefaultSecCode; + return KErrNone; + } +#endif // __SCP_DEBUG + + TInt lRetStatus(KErrNone); + Dprint(_L("[CSCPServer]-> Initiating branching on parameter...")); + + switch ( aID ) + { + case ( ESCPAutolockPeriod ): + // Flow through + case ( ESCPMaxAutolockPeriod ): + { + // Convert the value, and set it + TInt value; + TLex lex(aValue); + lRetStatus = lex.Val(value); + + + if((lRetStatus != KErrNone ) || ( value < 0) || ( value > KSCPAutolockPeriodMaximum )) { + lRetStatus = KErrArgument; + break; + } + + //Check if the device memory is encrypted or not. + TBool encryptionEnabled = IsDeviceMemoryEncrypted(); + + // Value OK + if(aID == ESCPMaxAutolockPeriod) + { + if ( encryptionEnabled ) + { + Dprint(_L("Memory is encrypted")); + if (( 0 == value) || value > KMaxAutolockPeriod) + { + Dprint((_L("Denying setting of max auto lock as value is %d"), value)); + User::Leave( KErrPermissionDenied ); + } + + } + else + { + Dprint(_L("Memory is decrypted, hence no restrictions to max autolock")); + } + + Dprint(_L("[CSCPServer]-> Branched to ESCPMaxAutolockPeriod...")); + CSCPParamDBController* lParamDB = CSCPParamDBController :: NewLC(); + lRetStatus = SetBestPolicyL(RTerminalControl3rdPartySession :: EMaxTimeout, aValue, aCallerIdentity, lParamDB); + + if(lRetStatus == KErrNone) + { + // Do we have to change the Autolock period as well? + TInt currentALperiod; + lRetStatus = GetAutolockPeriodL(currentALperiod); + + if(lRetStatus == KErrNone) + { + if((iConfiguration.iMaxTimeout > 0) && ((iConfiguration.iMaxTimeout < currentALperiod) || (currentALperiod == 0))) + { + Dprint((_L("[CSCPServer]-> Changing AL period to Max. AL period (Current ALP: %d, Max. ALP: %d)"), currentALperiod, value)); + lRetStatus = SetAutolockPeriodL(value); + } + } + else + { + Dprint((_L("[CSCPServer]-> ERROR: Couldn't get the Autolock period: %d"), lRetStatus)); + } + } + + CleanupStack :: PopAndDestroy(); //lParamDB + } + + else + { // Autolock Period + + //Code is commented as it is already taken care by the below condition #1343 irrespective of the drive encryption state. + /* if ( 0 == value ) + { + if ( encryptionEnabled ) + { + Dprint(_L("Permission denied!")); + User::Leave( KErrPermissionDenied ); + } + }*/ + + Dprint(_L("[CSCPServer]-> Branched to ESCPAutolockPeriod...")); + // Check if this value is not allowed by the Max. Autolock period + if ((iConfiguration.iMaxTimeout > 0) && ((iConfiguration.iMaxTimeout < value) || (value == 0))) { + Dprint((_L("[CSCPServer]-> ERROR: The value %d for AL period not allowed (Max. AL period: %d)"), value, iConfiguration.iMaxTimeout)); + + lRetStatus = KErrArgument; + } + else { + lRetStatus = SetAutolockPeriodL(value); + + if(lRetStatus != KErrNone) { + Dprint((_L("[CSCPServer]-> ERROR: Couldn't set the Autolock period: %d"), lRetStatus)); + } + } + } + } + break; + case ESCPCodeChangePolicy: + Dprint(_L("[CSCPServer]-> Branched to ESCPCodeChangePolicy...")); + lRetStatus = ChangeCodePolicy( aValue ); + break; + default: { +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS + Dprint(_L("[CSCPServer]-> Branched to default condition, aID=%d"), aID); + + if(FeatureManager :: FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) { + RPointerArray lSpecStrArray; + CleanupClosePushL(lSpecStrArray); + + Dprint(_L("[CSCPServer]-> Creating an instance of the private DB...")); + CSCPParamDBController* lParamDB = CSCPParamDBController :: NewLC(); + Dprint(_L("[CSCPServer]-> Private DB instance created successfully...")); + + Dprint(_L("[CSCPServer]-> Creating ParamObject...")); + CSCPParamObject* lInParams = CSCPParamObject :: NewLC(); + Dprint(_L("[CSCPServer]-> ParamObject created successfully...")); + + //lInParams->Set(KSCPParamIdentity, aCallerIdentity); + + /* + * Map KSCPParamIdentity with the SID of TCServer (not aCallerIdentity) + */ + lInParams->Set(KSCPParamIdentity, this->Message().SecureId()); + + switch(aID) { + case RTerminalControl3rdPartySession :: EPasscodeAllowSpecific: + case RTerminalControl3rdPartySession :: EPasscodeClearSpecificStrings: { + RPointerArray lSharedStrArray; + CleanupClosePushL(lSharedStrArray); + + /* If the choice is EPasscodeAllowSpecific then parse the specific strings mentioned and + * list the specific strings in an Array (multiple specific strings can be seperated with a single space) + * The Memory alloted for each of the tokens representing each individual specific string will be + * deallocated when the array lSpecStrArray is cleared by a call to ResetAndDestroy(). + */ + if(aID == RTerminalControl3rdPartySession :: EPasscodeAllowSpecific) { + TLex16 lex (aValue); + lex.Mark(); + + while(!lex.Eos()) { + while(lex.Peek() != ' ' && !lex.Eos()) { + lex.Inc(); + } + + const TDesC& lToken = lex.MarkedToken(); + HBufC* lBuff(NULL); + TRAP(lRetStatus, lBuff = HBufC :: NewL(lToken.Length())); + + if(lRetStatus != KErrNone) { + lSpecStrArray.ResetAndDestroy(); + User :: Leave(lRetStatus); + } + + lBuff->Des().Append(lToken); + lSpecStrArray.Append(lBuff); + lex.Inc(); + lex.Mark(); + } + } + else { + lRetStatus = lParamDB->GetValuesL(RTerminalControl3rdPartySession :: EPasscodeDisallowSpecific, + lSpecStrArray, aCallerIdentity); + } + + TInt lCnt = lSpecStrArray.Count(); + lInParams->Set(KSCPParamID, RTerminalControl3rdPartySession :: EPasscodeAllowSpecific); + + for(TInt i=0; i < lCnt; i++) { + HBufC* lPtr = lSpecStrArray[i]; + TBool lIsShared(EFalse); + + TRAPD(lErr, lIsShared = lParamDB->IsParamValueSharedL(lSpecStrArray[i], aCallerIdentity)); + + if(lErr != KErrNone) { + lSpecStrArray.ResetAndDestroy(); + lSharedStrArray.ResetAndDestroy(); + User :: Leave(lErr); + } + + if(EFalse == lIsShared) { + TUint16* ptr = const_cast(lPtr->Des().Ptr()); + TPtr valBuf(ptr, lPtr->Des().Length(), lPtr->Des().Length()); + lInParams->Set(KSCPParamValue, valBuf); + + CSCPParamObject* reply = iPluginManager->PostEvent(KSCPEventConfigurationQuery, *lInParams); + + if((reply != NULL) && (reply->Get(KSCPParamStatus, lRetStatus) == KErrNone)) { + if(lRetStatus != KErrNone) { + lSpecStrArray.ResetAndDestroy(); + lSharedStrArray.ResetAndDestroy(); + User :: Leave(lRetStatus); + } + + delete reply; + } + } + else { + lSpecStrArray.Remove(i); + lSharedStrArray.Append(lPtr); + i--; + lCnt--; + } + } + + /* + * Drop all the 'disallow strings' that are not shared between any other applications from the database. + */ + TRAPD(lErr, lRetStatus = lParamDB->DropValuesL(RTerminalControl3rdPartySession :: EPasscodeDisallowSpecific, lSpecStrArray)); + + if(lErr != KErrNone) { + lSpecStrArray.ResetAndDestroy(); + lSharedStrArray.ResetAndDestroy(); + User :: Leave(lErr); + } + + if(lRetStatus == KErrNone) { + /* + * Drop the entries of 'disallow strings' of only the called application + * (Any application that shares these 'disallow strings' will not be affected) + */ + TRAP(lErr, lRetStatus = lParamDB->DropValuesL(RTerminalControl3rdPartySession :: EPasscodeDisallowSpecific, + lSharedStrArray, aCallerIdentity)); + + if(lErr != KErrNone) { + lSpecStrArray.ResetAndDestroy(); + lSharedStrArray.ResetAndDestroy(); + User :: Leave(lErr); + } + + if(lRetStatus != KErrNone) { + Dprint(_L("[CSCPServer]-> Unable to drop 'disallow strings' from the private database...")); + } + } + else { + Dprint(_L("[CSCPServer]-> Unable to drop unshared 'disallow strings' from the private database...")); + } + + lSharedStrArray.ResetAndDestroy(); + CleanupStack :: PopAndDestroy(); // lSharedStrArray + } + break; + default: { + lInParams->Set(KSCPParamID, aID); + TUint16* ptr = const_cast(aValue.Ptr()); + TPtr valBuf(ptr, aValue.Length(), aValue.Length()); + lInParams->Set(KSCPParamValue, valBuf); + + Dprint(_L("[CSCPServer]-> INFO: Posting the event to the plugins...")); + CSCPParamObject* reply = iPluginManager->PostEvent(KSCPEventConfigurationQuery, *lInParams); + + if((reply != NULL) && (reply->Get(KSCPParamStatus, lRetStatus) == KErrNone)) { + if(lRetStatus == KErrNone) { + Dprint(_L("[CSCPServer]-> INFO: The event was consumed by one of the plugins, initiating storage activities (if any)...")); + // Check if the plugin wishes to save the parameters itself + TInt storage = KSCPStorageCommon; + reply->Get(KSCPParamStorage, storage); + + if(storage == KSCPStoragePrivate) { + switch(aID) { + /* The plugin will take care of storing the values for EPasscodeDisallowSpecific, this is to make sure the + * value is updated accordingly even in the private database (which is used as a reference to set the best policy-done + * as per MfE-Part 3 requirement + */ + case RTerminalControl3rdPartySession :: EPasscodeDisallowSpecific: { + TLex16 lex (aValue); + lex.Mark(); + + while(!lex.Eos()) { + while(lex.Peek() != ' ' && !lex.Eos()) { + lex.Inc(); + } + + const TDesC& lToken = lex.MarkedToken(); + HBufC* lBuff(NULL); + TInt lErr(KErrNone); + TRAP(lErr, lBuff = HBufC :: NewL(lToken.Length())); + + if(lErr != KErrNone) { + lSpecStrArray.ResetAndDestroy(); + delete reply; + User :: Leave(lErr); + } + + lBuff->Des().Append(lToken); + lSpecStrArray.Append(lBuff); + lex.Inc(); + lex.Mark(); + } + + TInt lRet(KErrNone); + + TRAP(lRet, lRetStatus = lParamDB->SetValuesL(RTerminalControl3rdPartySession :: EPasscodeDisallowSpecific, + lSpecStrArray, aCallerIdentity)); + + if(lRet != KErrNone) { + lRetStatus = lRet; + } + } + break; + default: + // Don't store the parameter, the plugin will handle this + Dprint((_L("[CSCPServer]-> Param %d stored in private storage..."), aID)); + break; + } + } + else { + Dprint((_L("[CSCPServer]-> Param %d stored in common storage..."), aID)); + lRetStatus = SetBestPolicyL(aID, aValue, aCallerIdentity, lParamDB); + } + } + } + else { + Dprint(_L("[CSCPServer]-> INFO: Event posting failed, reply=%d"), reply); + } + + delete reply; + break; + } + } + + lSpecStrArray.ResetAndDestroy(); + CleanupStack :: PopAndDestroy(3); // lSpecStrArray, lParamDB, lInParams + } +//#endif // __SAP_DEVICE_LOCK_ENHANCEMENTS + break; + } + } + + Dprint((_L("[CSCPServer]-> <<< SetParameterValueL(): %d"), lRetStatus)); + return lRetStatus; +} +// --------------------------------------------------------- +// TInt CSCPServer::GetParameterValueL( TSCPParameterID aID, TDes& aValue ) +// Handles the fetching of parameter values. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::GetParameterValueL( TInt aID, TDes& aValue, TUint32 aCallerIdentity ) + { + Dprint( (_L("CSCPServer::GetParameterValueL( %d )"), aID )); + TInt ret = KErrNone; + + switch ( aID ) + { + case ( ESCPAutolockPeriod ): + { + // Get the actual autolock period + TInt value; + if ( GetAutolockPeriodL( value ) != KErrNone ) + { + Dprint( (_L("CSCPServer::SetParameterValueL(): ERROR: Couldn't \ + get the Autolock period") )); + } + else + { + aValue.Zero(); + aValue.AppendNum(value); + } + } + break; + + case ( ESCPMaxAutolockPeriod ): + { + // Just fetch the value into the buffer + aValue.Zero(); + aValue.AppendNum( iConfiguration.iMaxTimeout ); + } + break; + + case ( ESCPCodeChangePolicy ): + { + ret = GetCodePolicy( aValue ); + } + break; + + default: + ret = KErrNotSupported; + +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS +if(FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + + // "Ask" the plugins, if this caller is allowed to access this value or + // if the value is in private storage, retrieve the value. + CSCPParamObject* inParams = CSCPParamObject::NewL(); + CleanupStack::PushL( inParams ); + inParams->Set( KSCPParamID, aID ); + inParams->Set( KSCPParamIdentity, aCallerIdentity ); + + CSCPParamObject* repParams = + iPluginManager->PostEvent( KSCPEventRetrieveConfiguration, *inParams ); + + CleanupStack::PopAndDestroy( inParams ); + + TBool getFromCommonStorage = ETrue; + TInt status; + if ( ( repParams != NULL ) && + ( repParams->Get( KSCPParamStatus, status ) == KErrNone ) ) + { + ret = status; + if ( ret != KErrNone ) + { + getFromCommonStorage = EFalse; + Dprint( (_L("CSCPServer::GetParameterValueL():\ + Retrieve configuration for param %d not OK: %d"), aID, ret )); + } + else + { + // Has the plugin sent the value? + TInt valueLen = repParams->GetParamLength( KSCPParamValue ); + if ( valueLen > 0 ) + { + getFromCommonStorage = EFalse; + // Try to retrieve the value (Get will check for overflow) + ret = repParams->Get( KSCPParamValue, aValue ); + } + } + } + + if ( getFromCommonStorage ) + { + // OK, no objection, so try to get the value from common storage + ret = iPluginEventHandler->GetParameters().Get( aID, aValue ); + } + + if ( repParams != NULL ) + { + delete repParams; + } + } +//#endif // __SAP_DEVICE_LOCK_ENHANCEMENTS + + break; + } + + Dprint( (_L("<-- CSCPServer::GetParameterValueL(): %d"), ret )); + return ret; + } + + + + +// --------------------------------------------------------- +// static TBool CSCPServer::IsValidISACode( TDes& aCode ) +// Checks that the given string is a valid ISA security code. +// That is, exacly 5 chars, and contains only digits. +// +// Status : Approved +// --------------------------------------------------------- +// + +TBool CSCPServer::IsValidISACode( TDes& aCode ) + { + TBool ret = ETrue; + + if ( aCode.Length() != KSCPCodeMaxLen ) + { + ret = EFalse; + } + else + { + for ( TInt i = 0; i < aCode.Length(); i++ ) + { + if ( !( ((TChar)aCode[i]).IsDigit() ) ) + { + ret = EFalse; + } + } + } + + return ret; + } + + + + +// --------------------------------------------------------- +// void CSCPServer::SessionClosed() +// Checks if this was the final session. If so, exit the +// server thread. +// +// Status : Approved +// --------------------------------------------------------- +// + +void CSCPServer::SessionClosed() + { + iSessionIter.SetToFirst(); + iSessionIter++; // Skip the closing session + + if ( iSessionIter++ == NULL ) + { + // No more sessions + Dprint( (_L("CSCPServer::SessionClosed(): No more sessions, starting timeout") )); + +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS +if(FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + // Save the plugin configuration + TRAP_IGNORE( iPluginEventHandler->WritePluginConfigurationL() ); + } +//#endif // __SAP_DEVICE_LOCK_ENHANCEMENTS + + // Start shutdown timer + TRAPD( err, iShutdownTimer = CSCPTimer::NewL( KSCPServerShutdownTimeout, + NULL, + this ) ); + if ( err != KErrNone ) + { + // Cannot create the timer! + // No more sessions + Dprint( (_L("CSCPServer::SessionClosed(): ERROR: Timer creation failed! Exiting.."))); + iShutdownTimer = NULL; + Timeout( NULL ); + } + } + } + + + +// --------------------------------------------------------- +// void CSCPServer::SessionOpened() +// Stops the shutdown timer, if started. +// +// Status : Approved +// --------------------------------------------------------- +// +void CSCPServer::SessionOpened() + { + // Stop the shutdown timer + if ( iShutdownTimer != NULL ) + { + delete iShutdownTimer; + iShutdownTimer = NULL; + } + } + + + + +// --------------------------------------------------------- +// void CSCPServer::Timeout() +// Shuts down the server stopping the active scheduler since +// the shutdown timer has elapsed. +// +// Status : Approved +// --------------------------------------------------------- +// +void CSCPServer::Timeout( TAny* aParam ) + { + (void)aParam; + + delete iShutdownTimer; + iShutdownTimer = NULL; + + Dprint( (_L("CSCPServer::Timeout(): Shutting down SCP server") )); + + CActiveScheduler::Stop(); + } + + + +// ********************** NEW FEATURES ********************>>>> + +//#ifdef __SAP_DEVICE_LOCK_ENHANCEMENTS + +// --------------------------------------------------------- +// CSCPServer::IsValidEnhCode() +// Checks that the given buffer is an alphanumeric string +// and its length is between the minimum and maximum. +// +// Status : Approved +// --------------------------------------------------------- +// +TBool CSCPServer::IsValidEnhCode( TDes& aCode ) + { + + if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + return KErrNotSupported; + } + TBool ret = ETrue; + + // Check length + if ( ( aCode.Length() < KSCPPasscodeMinLength ) || + ( aCode.Length() > KSCPPasscodeMaxLength ) ) + { + ret = EFalse; + } + + // Check the characters + if ( ret ) + { + for ( TInt i = 0; i < aCode.Length(); i++ ) + { + TChar curChar = aCode[i]; + TChar::TCategory chCat = curChar.GetCategory(); + if ( curChar < 1 || curChar > 126 || curChar.IsSpace() ) + /* if ( ( !curChar.IsAlphaDigit() ) && ( chCat != TChar::ENdCategory ) ) */ + { + ret = EFalse; + } + } + } + + return ret; + } + + +// --------------------------------------------------------- +// CSCPServer::IsCodeBlocked() +// Checks if the code is blocked, and zeroes the attempt counter +// when necessary. +// +// Status : Approved +// --------------------------------------------------------- +// +TBool CSCPServer::IsCodeBlocked() + { + + if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + return KErrNotSupported; + } + TBool ret = EFalse; + + if ( iConfiguration.iBlockedAtTime.Compare( KSCPNotBlocked ) == 0 ) + { + ret = EFalse; + } + else + { + TTime curTime; + curTime.UniversalTime(); + + TTimeIntervalMinutes interval = KSCPCodeBlockedTimeMin; + + TInt64 savedTime; + TLex lex( iConfiguration.iBlockedAtTime ); + ret = lex.Val( savedTime ); + + if ( ret == KErrNone ) + { + TTime configTime( savedTime ); + if ( ( configTime + interval ) > curTime ) + { + Dprint( (_L("CSCPServer::IsCodeBlocked(): Code BLOCKED") )); + // Restart the timer + iConfiguration.iBlockedAtTime.Zero(); + iConfiguration.iBlockedAtTime.AppendNum( curTime.Int64() ); + + ret = ETrue; + } + else + { + // Not blocked anymore + + Dprint( (_L("CSCPServer::IsCodeBlocked(): Resetting code block") )); + iConfiguration.iFailedAttempts = 0; + iConfiguration.iBlockedAtTime.Zero(); + iConfiguration.iBlockedAtTime.Copy( KSCPNotBlocked ); + + ret = EFalse; + } + + TRAPD( err, iConfiguration.WriteSetupL() ); + if ( err != KErrNone ) + { + Dprint( (_L("CSCPServer::IsCodeBlocked(): WARNING:\ + failed to write configuration: %d"), err )); + + } + } + } + + return ret; + } + + + + +// --------------------------------------------------------- +// CSCPServer::SendInvalidDOSCode() +// Resets the DOS password attempts if required and verifies the +// code. +// +// Status : Approved +// --------------------------------------------------------- +// +void CSCPServer::SendInvalidDOSCode( RMobilePhone::TMobilePassword& aCodeToSend ) + { + + if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + return ; + } + // Reset the DOS-side PSW-attempts by changing the code to the same one + RMobilePhone::TMobilePassword correctPsw; + TRAPD( err, + GetCode( correctPsw ); + ChangeISACodeL( correctPsw ); + ); + if ( err != KErrNone ) + { + Dprint( (_L("CSCPServer::SendInvalidDOSCode(): WARNING:\ + DOS code change failed, where it shouldn't have: %d"), err )); + } + + // Send the incorrect code to DOS side + TRAPD( ret, CheckISACodeL( aCodeToSend ) ); + #ifndef __WINS__ + if ( ( ret != KErrAccessDenied ) && ( ret != KErrGsm0707IncorrectPassword ) ) + { + Dprint( (_L("CSCPServer::SendInvalidDOSCode(): WARNING:\ + invalid DOS code validation error: %d"), ret )); + } + #endif // __WINS__ + } + + + + +// --------------------------------------------------------- +// CSCPServer::IsCorrectEnhCode() +// Checks if the given code is the correct enhanced code. +// If the configuration is not up-to-date, the code will be hashed +// and verified from the ISA-side. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::IsCorrectEnhCode( TDes& aCode, TInt aFlags ) + { + + if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + return KErrNotSupported; + } + TInt ret = KErrAccessDenied; + + // Hash the code + TBuf hashBuf; + hashBuf.Zero(); + iPluginEventHandler->HashInput( aCode, hashBuf ); + + TInt ISACode = HashISACode( hashBuf ); + + RMobilePhone::TMobilePassword pswCandidate; + pswCandidate.Zero(); + pswCandidate.AppendNum( ISACode ); + + TBool enhancedCodeMatches = EFalse; + if ( hashBuf.Compare( iConfiguration.iEnhSecCode ) == 0 ) + { + enhancedCodeMatches = ETrue; + } + + // Check if the code is blocked (don't check if we're out-of-sync) + if ( ( iConfiguration.iConfigFlag == KSCPConfigOK ) && ( IsCodeBlocked() ) ) + { + if ( aFlags & KSCPEtelRequest ) + { + // Check if the code is correct + if ( enhancedCodeMatches ) + { + // Mess-up the code + RMobilePhone::TMobilePassword codeToSend; + codeToSend.Zero(); + codeToSend.AppendNum( ISACode + 1 ); + + SendInvalidDOSCode( codeToSend ); + } + else + { + // OK, the code is already invalid + SendInvalidDOSCode( pswCandidate ); + } + } + return KErrLocked; + } + + TBool writeSetup = EFalse; + + if ( iConfiguration.iConfigFlag == KSCPConfigOK ) + { + // Normal situation: we have the correct code stored. + // Compare the hashes (hashing error will result in EFalse ) + if ( enhancedCodeMatches ) + { + ret = KErrNone; + + if ( aFlags & KSCPEtelRequest ) + { + // Send the correct code to DOS side + TRAP( ret, CheckISACodeL( pswCandidate ) ); + } + + if ( ret == KErrNone ) + { + if ( iConfiguration.iFailedAttempts > 0 ) + { + iConfiguration.iFailedAttempts = 0; + Dprint( (_L("CSCPServer::IsCorrectEnhCode():KErrAccessDenied: iFailedAttempts (%d)."), iConfiguration.iFailedAttempts )); + writeSetup = ETrue; + } + } + else + { + Dprint( (_L("CSCPServer::IsCorrectEnhCode(): WARNING:\ + ISA code validation failed, where it shouldn't have: %d"), ret )); + } + } + else + { + ret = KErrAccessDenied; + + iConfiguration.iFailedAttempts++; + Dprint( (_L("CSCPServer::IsCorrectEnhCode():KErrAccessDenied: iFailedAttempts (%d)."), iConfiguration.iFailedAttempts )); + writeSetup = ETrue; + + if ( iConfiguration.iFailedAttempts == KSCPCodeBlockLimit ) + { + // Block the code + TTime curTime; + curTime.UniversalTime(); + + iConfiguration.iBlockedAtTime.Zero(); + iConfiguration.iBlockedAtTime.AppendNum( curTime.Int64() ); + + // The code will be blocked for now on + ret = KSCPErrCodeBlockStarted; + } + + if ( aFlags & KSCPEtelRequest ) + { + SendInvalidDOSCode( pswCandidate ); + } + } + } + else + { + // iConfiguration.iConfigFlag == KSCPConfigInvalid or KSCPConfigUnknown + + // We might be out-of-sync, no idea about the real code. + // Check if the DOS code hashed from the given code is correct. + Dprint( (_L("CSCPServer::IsCorrectEnhCode(): Attempting to correct OoS situation.") )); + + TRAP( ret, CheckISACodeL( pswCandidate ) ); + + if ( ret == KErrNone ) + { + // OK, we must assume that this is the correct code, since + // the hashed DOS code is correct. Save the codes, and return OK. + + Dprint( (_L("CSCPServer::IsCorrectEnhCode(): Given code has the correct hash (%d)\ + , saving codes."), ISACode )); + + iConfiguration.iEnhSecCode.Zero(); + iConfiguration.iEnhSecCode.Copy( hashBuf ); + + iConfiguration.iSecCode.Zero(); + iConfiguration.iSecCode.AppendNum( ISACode ); + + // Unset the invalid configuration flag + iConfiguration.iConfigFlag = KSCPConfigOK; + writeSetup = ETrue; + } + else + { + + Dprint( (_L("CSCPServer::IsCorrectEnhCode(): Given code does not have the \ + correct hash: ret; %d user enter password: %d"), ret )); + TRAP( ret, CheckISACodeL( aCode ) ); + if (ret == KErrNone) + { + //store this code in our interal storage as it is used as oldpassword while changing at ISA side in next command + //ChangeISACodeL. + iConfiguration.iSecCode.Zero(); + iConfiguration.iSecCode.Append( aCode ); + TRAP(ret,ChangeISACodeL(pswCandidate)); + } + if (ret == KErrNone) + { + iConfiguration.iEnhSecCode.Zero(); + iConfiguration.iEnhSecCode.Copy( hashBuf ); + + iConfiguration.iSecCode.Zero(); + iConfiguration.iSecCode.AppendNum( ISACode ); + + // Unset the invalid configuration flag + iConfiguration.iConfigFlag = KSCPConfigOK; + writeSetup = ETrue; + } + } + } + + // Write setup if needed + if ( writeSetup ) + { + TRAPD( err, iConfiguration.WriteSetupL() ); + if ( err != KErrNone ) + { + Dprint( (_L("CSCPServer::IsCorrectEnhCode(): WARNING:\ + failed to write configuration: %d"), err )); + } + } + + return ret; + } + + + +// --------------------------------------------------------- +// CSCPServer::CheckCodeAndGiveISA() +// Check the given code, and notify the plugins of the result. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::CheckCodeAndGiveISAL( TDes& aCodeToCheck, + TDes& aISACodeToReturn, + CSCPParamObject*& aRetParams, + TInt aFlags ) + { + + if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + return KErrNotSupported; + } + TInt ret = KErrNone; + TInt status = KErrNone; + + // Check the code, note that IsCorrectEnhCode might change the stored code, + // so we'll get the code after the call. + + TBool isSuccessful = EFalse; + + status = IsCorrectEnhCode( aCodeToCheck, aFlags ); + + if ( status == KErrLocked ) + { + // If the code is locked, no attempts count as failed or successful + return status; + } + else if ( status == KErrNone ) + { + // OK, successful authentication + TSCPSecCode realCode; + ret = GetCode( realCode ); + + User::LeaveIfError( ret ); + + aISACodeToReturn.Copy( realCode ); + isSuccessful = ETrue; + } + else // KSCPErrCodeBlockStarted or KErrAccessDenied + { + // Authentication attempt failed + TSCPSecCode realCode; + ret = GetCode( realCode ); + + User::LeaveIfError( ret ); + + TSCPSecCode fakeCode; + do + { + // Create a fake code, which is between 10000-99999 + fakeCode.Zero(); + TUint32 code = Math::Random(); + code = code % 90000 + 10000; + fakeCode.AppendNum( code ); + } while ( fakeCode.Compare( realCode ) == 0 ); + + aISACodeToReturn.Copy( fakeCode ); + + if ( status == KSCPErrCodeBlockStarted ) + { + status = KErrLocked; // Set this as the external error code + } + } + + // Send information about the authentication attempt to the plugins + CSCPParamObject* inParams = CSCPParamObject::NewL(); + CleanupStack::PushL( inParams ); + inParams->Set( KSCPParamContext, KSCPContextQueryPsw ); + + if ( isSuccessful ) + { + // Authentication successful + inParams->Set( KSCPParamStatus, KErrNone ); + } + else + { + // Authentication failed + inParams->Set( KSCPParamStatus, KErrAccessDenied ); + } + + CSCPParamObject* repParams = + iPluginManager->PostEvent( KSCPEventAuthenticationAttempted, *inParams ); + + CleanupStack::PopAndDestroy( inParams ); + + if ( repParams != NULL ) + { + // No status information here, just propagate the paramobject + aRetParams = repParams; // pointer ownership changed + } + + return status; + } + + + + +// --------------------------------------------------------- +// CSCPServer::CheckAndChangeEnhCodeL() +// Check the given code, and if correct, send it to the plugins +// for validation. +// +// Status : Approved +// --------------------------------------------------------- +// +TInt CSCPServer::CheckAndChangeEnhCodeL( TDes& aOldPass, + TDes& aNewPass, + CSCPParamObject*& aRetParams, + TSCPSecCode& aNewDOSCode ) + { + + if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + return KErrNotSupported; + } + TInt ret = KErrNone; + + ret = IsCorrectEnhCode( aOldPass, 0 ); + if ( ret == KErrNone ) + { + // Authentication successful + CSCPParamObject* inParams = CSCPParamObject::NewL(); + CleanupStack::PushL( inParams ); + + inParams->Set( KSCPParamStatus, KErrNone ); + inParams->Set( KSCPParamContext, KSCPContextChangePsw ); + CSCPParamObject* repParams = + iPluginManager->PostEvent( KSCPEventAuthenticationAttempted, *inParams ); + + if ( repParams != NULL ) + { + // Ignore the return params at this point + delete repParams; + } + + inParams->Reset(); + + // Validate the code + inParams->Set( KSCPParamPassword, aNewPass ); + + repParams = iPluginManager->PostEvent( KSCPEventValidate, *inParams ); + + CleanupStack::PopAndDestroy( inParams ); + + if ( repParams != NULL ) + { + // Check if the validation failed + TInt status; + if ( repParams->Get( KSCPParamStatus, status ) == KErrNone ) + { + if ( status != KErrNone ) + { + ret = status; + } + } + + aRetParams = repParams; // pointer ownership changed + } + + // Set the new code, if it was OK + if ( ret == KErrNone ) + { + if ( IsValidEnhCode( aNewPass ) ) + { + ret = StoreEnhCode( aNewPass, &aNewDOSCode ); + } + else + { + // Invalid code format! Should not happen at this point, but make sure. + ret = KErrArgument; + } + + if ( ret == KErrNone ) + { + CSCPParamObject* inParams = CSCPParamObject::NewL(); + CleanupStack::PushL( inParams ); + inParams->Set( KSCPParamPassword, aNewPass ); + + CSCPParamObject* repParams = + iPluginManager->PostEvent( KSCPEventPasswordChanged, *inParams ); + + CleanupStack::PopAndDestroy( inParams ); + + if ( repParams != NULL ) + { + // Ignore the return params at this point + delete repParams; + } + } + } + } + else + { + if ( ( ret == KErrAccessDenied ) || ( ret == KSCPErrCodeBlockStarted ) ) + { + // Authentication failed + CSCPParamObject* inParams = CSCPParamObject::NewL(); + CleanupStack::PushL( inParams ); + + inParams->Set( KSCPParamStatus, KErrAccessDenied ); + inParams->Set( KSCPParamContext, KSCPContextChangePsw ); + CSCPParamObject* repParams = + iPluginManager->PostEvent( KSCPEventAuthenticationAttempted, *inParams ); + + CleanupStack::PopAndDestroy( inParams ); + + if ( repParams != NULL ) + { + // No status information here, just propagate the paramobject + aRetParams = repParams; // pointer ownership changed + } + + if ( ret == KSCPErrCodeBlockStarted ) + { + ret = KErrLocked; // Set this as the external error code + } + } + } + + return ret; + } + + + + +// --------------------------------------------------------- +// CSCPServer::GetEventHandlerL() +// Return a pointer to the event handler object. +// +// Status : Approved +// --------------------------------------------------------- +// +MSCPPluginEventHandler* CSCPServer::GetEventHandlerL() + { + if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + return NULL; + } + return iPluginEventHandler; + } + + + +// --------------------------------------------------------- +// CSCPServer::IsPasswordChangeAllowedL() +// Check from the plugins if the password is allowed to be changed. +// +// Status : Approved +// --------------------------------------------------------- + +TInt CSCPServer::IsPasswordChangeAllowedL( CSCPParamObject*& aRetParams ) + { + + if(!FeatureManager::FeatureSupported(KFeatureIdSapDeviceLockEnhancements)) + { + return KErrNotSupported; + } + TInt ret = KErrNone; + + // Post the event to the plugins to find out if the password can + // be changed + + CSCPParamObject* inParams = CSCPParamObject::NewL(); + CleanupStack::PushL( inParams ); + + // No additional parameters + + CSCPParamObject* repParams = + iPluginManager->PostEvent( KSCPEventPasswordChangeQuery, *inParams ); + + CleanupStack::PopAndDestroy( inParams ); + + if ( repParams != NULL ) + { + // Check status + TInt status; + if ( repParams->Get( KSCPParamStatus, status ) == KErrNone ) + { + if ( status != KErrNone ) + { + ret = status; + } + } + + aRetParams = repParams; // pointer ownership changed + } + + return ret; + } + + + // --------------------------------------------------------- +// CSCPServer::IsDeviceMemoryEncrypted +// Checks if phone memory is encrypted or not. +// --------------------------------------------------------- +TBool CSCPServer::IsDeviceMemoryEncrypted() + { + Dprint(_L("CSCPServer::IsDeviceMemoryEncrypted >>")); + + TBool ret(EFalse); + + //First check if the feature is supported on device + TRAPD(ferr, FeatureManager::InitializeLibL()); + if (ferr != KErrNone) + { + Dprint(_L("feature mgr initialization error, %d"), ferr); + return EFalse; + } + ret = FeatureManager::FeatureSupported( KFeatureIdFfDeviceEncryptionFeature); + FeatureManager::UnInitializeLib(); + + //If feature is supported, check if any drive is encrypted. + if (ret) + { + CDevEncSession* devEncSession = new CDevEncSession( EDriveC ); + + if (!devEncSession) + { + Dprint(_L("Can't instantiate device encryption session..")); + return EFalse; + } + + TInt err = devEncSession->Connect(); + if (err == KErrNone) + { + //Session with device encryption is established. Check if any drive is encrypted + TInt encStatus (KErrNone); + TInt err = devEncSession->DiskStatus( encStatus ); + Dprint(_L("err = %d, encstatus = %d"), err, encStatus); + if ( err == KErrNone && encStatus != EDecrypted ) + { + Dprint(_L("Memory is encrypted")); + ret = ETrue; + } + else + { + Dprint(_L("Memory is not encrypted")); + ret = EFalse; + } + } + else + { + Dprint(_L("Error %d while establishing connection with device encryption engine"), err); + ret = EFalse; + } + + delete devEncSession; devEncSession = NULL; + } + + Dprint(_L("CSCPServer::IsDeviceMemoryEncrypted, ret = %d <<"), ret); + return ret; + } + + +/** +* Sets the best policy for the parameters that are under conflict. This is part of changes done for MFE-requirement part3. +* @params aID: The ID of the parameter that needs to be set +* aValue: Value of the parameter identified in aID +* aCalledIdentity: The UID of the called application/process +* +* @return TInt: KErrNone is successful, otherwise a system error code +*/ +TInt CSCPServer :: SetBestPolicyL( TInt aID, const TDesC& aValue, TUint32 aCallerIdentity, CSCPParamDBController* aParamDB ) { + Dprint( (_L("[CSCPServer]-> SetBestPolicyL() >>>"))); + Dprint( (_L("[CSCPServer]-> ParamID=%d "), aID, aValue)); + Dprint( (_L("[CSCPServer]-> ParamValue=%d "), aValue)); + + TBool lFirstTime(EFalse); + TInt32 lNumValue (-1); + TInt32 lNumValDB (-1); + TInt32 lRetStatus = KErrNone; + + switch(aID) { + case RTerminalControl3rdPartySession :: EMaxTimeout: + case RTerminalControl3rdPartySession :: EPasscodeMinLength: + case RTerminalControl3rdPartySession :: EPasscodeMaxLength: + case RTerminalControl3rdPartySession :: EPasscodeRequireUpperAndLower: + case RTerminalControl3rdPartySession :: EPasscodeRequireCharsAndNumbers: + case RTerminalControl3rdPartySession :: EPasscodeExpiration: + case RTerminalControl3rdPartySession :: EPasscodeMaxRepeatedCharacters: + case RTerminalControl3rdPartySession :: EPasscodeMinChangeTolerance: + case RTerminalControl3rdPartySession :: EPasscodeMinChangeInterval: + case RTerminalControl3rdPartySession :: EPasscodeCheckSpecificStrings: + case RTerminalControl3rdPartySession :: EPasscodeMaxAttempts: + case RTerminalControl3rdPartySession :: EPasscodeConsecutiveNumbers: + case RTerminalControl3rdPartySession :: EPasscodeHistoryBuffer: + case RTerminalControl3rdPartySession :: EPasscodeMinSpecialCharacters: + case RTerminalControl3rdPartySession :: EPasscodeDisallowSimple: + break; + case RTerminalControl3rdPartySession :: EPasscodeClearSpecificStrings: + case RTerminalControl3rdPartySession :: EPasscodeDisallowSpecific: + case RTerminalControl3rdPartySession :: EPasscodeAllowSpecific: + return KErrNotSupported; + default: + // No best policy check required for parameters other than the above 19 (Only 19 of the current parameters conflict!) + TUint16* ptr = const_cast( aValue.Ptr()); + TPtr valBuf( ptr, aValue.Length(), aValue.Length()); + lRetStatus = iPluginEventHandler->GetParameters().Set( aID, valBuf); + return lRetStatus; + } + + TLex lex( aValue ); + // Convert the parameter value to its numeric equivalent + if (lex.Val( lNumValue ) != KErrNone) { + return KErrArgument; + } + + if(iOverrideForCleanup) { + Dprint( _L("[CSCPServer]-> SetBestPolicy() Overriding decision logic...")); + lRetStatus = aParamDB->DropValuesL(aID); + } + else { + // Fetch the previous value of the parameter from the private database + switch(aID) { + case RTerminalControl3rdPartySession :: EMaxTimeout: + case RTerminalControl3rdPartySession :: EPasscodeMinLength: + case RTerminalControl3rdPartySession :: EPasscodeMaxLength: + case RTerminalControl3rdPartySession :: EPasscodeRequireUpperAndLower: + case RTerminalControl3rdPartySession :: EPasscodeRequireCharsAndNumbers: + case RTerminalControl3rdPartySession :: EPasscodeExpiration: + case RTerminalControl3rdPartySession :: EPasscodeMaxRepeatedCharacters: + case RTerminalControl3rdPartySession :: EPasscodeMinChangeTolerance: + case RTerminalControl3rdPartySession :: EPasscodeMinChangeInterval: + case RTerminalControl3rdPartySession :: EPasscodeCheckSpecificStrings: + case RTerminalControl3rdPartySession :: EPasscodeMaxAttempts: + case RTerminalControl3rdPartySession :: EPasscodeConsecutiveNumbers: + case RTerminalControl3rdPartySession :: EPasscodeHistoryBuffer: + case RTerminalControl3rdPartySession :: EPasscodeMinSpecialCharacters: + case RTerminalControl3rdPartySession :: EPasscodeDisallowSimple: { + Dprint( (_L("[CSCPServer]-> Fetching the value of parameter '%d' from private database..."), aID)); + + TInt32 lAppID; + + lRetStatus = aParamDB->GetValueL(aID, lNumValDB, lAppID); + + switch(lRetStatus) { + case KErrNotFound: { + TInt lLSValue(0); + lFirstTime = ETrue; + + switch(aID) { + case RTerminalControl3rdPartySession :: EMaxTimeout: + case RTerminalControl3rdPartySession :: EPasscodeMaxRepeatedCharacters: + case RTerminalControl3rdPartySession :: EPasscodeExpiration: + case RTerminalControl3rdPartySession :: EPasscodeMinChangeTolerance: + case RTerminalControl3rdPartySession :: EPasscodeMinChangeInterval: + case RTerminalControl3rdPartySession :: EPasscodeMaxAttempts: + case RTerminalControl3rdPartySession :: EPasscodeMaxLength: + case RTerminalControl3rdPartySession :: EPasscodeDisallowSimple: + /* For these parameters, if it is the first time that the values are being + set then no decision is imposed regarding the best policy... + */ + break; + default: + // Get the default values for the parameter... + lRetStatus = iPluginEventHandler->GetParameters().Get(aID, lLSValue); + break; + } + + lNumValDB = lLSValue; + Dprint((_L("[CSCPServer]-> Unable to fetch the value of parameter '%d' from private database, value from internal tree=%d"), aID, lLSValue)); + } + break; + case KErrNone: + break; + default: + Dprint((_L("[CSCPServer]-> Failed to fetch parameter '%d' from the private database. ErrCode=%d"), aID, lRetStatus)); + return lRetStatus; + } + break; + } + } + + if(lNumValue == lNumValDB) { + Dprint(_L("[CSCPServer]-> INFO: New parameter value and value from the database are the same. Overriding SetBestPolicy()...")); + return KErrNone; + } + + lRetStatus = KErrNone; + + // Decision code that verifies if policy is strongest + switch(aID) { + case RTerminalControl3rdPartySession :: EMaxTimeout: + case RTerminalControl3rdPartySession :: EPasscodeMaxRepeatedCharacters: + case RTerminalControl3rdPartySession :: EPasscodeExpiration: + case RTerminalControl3rdPartySession :: EPasscodeMinChangeTolerance: + case RTerminalControl3rdPartySession :: EPasscodeMinChangeInterval: + case RTerminalControl3rdPartySession :: EPasscodeMaxAttempts: + if(!lFirstTime && ((lNumValue > lNumValDB) || (lNumValue == 0))) { + lRetStatus = KErrArgument; + } + break; + case RTerminalControl3rdPartySession :: EPasscodeMaxLength: + if(!lFirstTime && (lNumValue < lNumValDB)) { + lRetStatus = KErrArgument; + } + break; + case RTerminalControl3rdPartySession :: EPasscodeMinLength: + case RTerminalControl3rdPartySession :: EPasscodeHistoryBuffer: + case RTerminalControl3rdPartySession :: EPasscodeMinSpecialCharacters: + if(lNumValue < lNumValDB) { + lRetStatus = KErrArgument; + } + break; + case RTerminalControl3rdPartySession :: EPasscodeRequireUpperAndLower: + case RTerminalControl3rdPartySession :: EPasscodeRequireCharsAndNumbers: + case RTerminalControl3rdPartySession :: EPasscodeCheckSpecificStrings: + case RTerminalControl3rdPartySession :: EPasscodeConsecutiveNumbers: + case RTerminalControl3rdPartySession :: EPasscodeDisallowSimple: + if(lNumValue == false && lNumValDB == true) { + lRetStatus = KErrArgument; + } + break; + } + + if(lRetStatus != KErrNone) { + return KErrArgument; + } + + // Update the best policy to the DB as well as the local storage tree + Dprint((_L("[CSCPServer]-> Updating the value of parameter '%d' to private database...UID=%d"), aID, aCallerIdentity)); + + lRetStatus = aParamDB->SetValueL(aID, lNumValue, aCallerIdentity); + } + + Dprint(_L("[CSCPServer]-> lRetStatus after DB operation = %d "), lRetStatus); + /* Update is NOT ATOMIC!!! + * If the earlier aParamDB->SetValueL() was successful, there is a chance that + * the config.ini and the DB are out of sync if the operation iConfiguration.WriteSetupL() + * is not successful (disk space not enough etc) or when the WriteToFileL() in ParamObject + * from iPluginEventHandler->GetParameters() fails. + * (WriteToFileL() is called in some destructor when the SCPServer terminates) + */ + if (lRetStatus == KErrNone) { + switch (aID) { + case RTerminalControl3rdPartySession :: EMaxTimeout: + iConfiguration.iMaxTimeout = lNumValue; + lRetStatus = iConfiguration.WriteSetupL(); + Dprint(_L("[CSCPServer]-> After setting EMaxTimeout lRetStatus = %d "), lRetStatus); + break; + default: + TUint16* ptr = const_cast(aValue.Ptr()); + TPtr valBuf(ptr, aValue.Length(), aValue.Length()); + lRetStatus = iPluginEventHandler->GetParameters().Set(aID, valBuf); + Dprint(_L("[CSCPServer]-> After setting (%d ) lRetStatus = %d "), aID, lRetStatus); + break; + } + } + + Dprint(_L("[CSCPServer]-> SetBestPolicyL() lRetStatus = %d <<<"), lRetStatus); + return lRetStatus; +} + +TInt CSCPServer :: PerformCleanupL(HBufC8* aAppIDBuffer, RArray& aChangeArray, RPointerArray& aParamValArray) { + Dprint( (_L("[CSCPServer]-> PerformCleanupL() >>>"))); + + if(!aAppIDBuffer) { + return KErrArgument; + } + + TInt32 lAppCount = aAppIDBuffer->Length(); + + if(lAppCount < 1) { + return KErrArgument; + } + + lAppCount /= sizeof(TInt32); + + TPtr8 bufPtr = aAppIDBuffer->Des(); + + TInt lStatus(KErrNone); + CSCPParamDBController* lParamDB = CSCPParamDBController :: NewLC(); + + RDesReadStream lBufReadStream(bufPtr); + CleanupClosePushL(lBufReadStream); + + Dprint(_L("[CSCPServer]-> INFO: Total items received for cleanup is %d"), lAppCount); + + RArray lParamIds; + CleanupClosePushL(lParamIds); + + TBool lSubOpsFailed = EFalse; + HBufC* lDefValueBuf = HBufC :: NewLC(20); + + // Loop through each of the byte packed application ID's specified in aAppIDBuffer and clean them up iteratively + for(TInt i=0; i < lAppCount; i++) { + TInt32 lAppID = lBufReadStream.ReadInt32L(); + Dprint((_L("[CSCPServer]-> Initiating cleanup on %d "), lAppID)); + + + lParamIds.Reset(); + lStatus = lParamDB->ListParamsUsedByAppL(lParamIds, lAppID); + + Dprint(_L("[CSCPServer]-> Status of ListParamsUsedByAppL() = %d"), lStatus); + + TInt lCount = lParamIds.Count(); + + Dprint(_L("[CSCPServer]-> lCount=%d"), lCount); + + // Make sure that LockCodeMinChangeTolerance is always cleanedup before LockCodeHistoryBuffer + if(lCount > 1) { + Dprint(_L("[CSCPServer]-> Updating the cleanup order for EPasscodeMinChangeTolerance and EPasscodeHistoryBuffer if needed...")); + TInt lHistBuffIndex = -1; + TInt lMinTolIndex = -1; + + for(TInt i=0; i < lCount; i++) { + if(lHistBuffIndex >= 0 && lMinTolIndex >= 0) { + // If both the indexes have been found, stop the search + break; + } + + switch(lParamIds[i]) { + case RTerminalControl3rdPartySession :: EPasscodeMinChangeTolerance: + lMinTolIndex = i; + break; + case RTerminalControl3rdPartySession :: EPasscodeHistoryBuffer: + lHistBuffIndex = i; + break; + } + } + + // This step is required only if both the parameters are marked for cleanup + if(lHistBuffIndex >= 0 && lMinTolIndex >= 0) { + /* Switch the cleanup order of the two parameters + * This step is needed because ListParamsUsedByAppL() always returns the parameters + * in Ascending order and because LockCodeMinChangeTolerance is always required to be + * cleanedup before LockCodeHistoryBuffer + */ + lParamIds[lHistBuffIndex] = RTerminalControl3rdPartySession :: EPasscodeMinChangeTolerance; + lParamIds[lMinTolIndex] = RTerminalControl3rdPartySession :: EPasscodeHistoryBuffer; + Dprint(_L("[CSCPServer]-> Switching the cleanup order of EPasscodeHistoryBuffer and EPasscodeMinChangeTolerance")); + Dprint(_L("[CSCPServer]-> Old Index of EPasscodeHistoryBuffer=%d"), lHistBuffIndex); + Dprint(_L("[CSCPServer]-> Old Index of EPasscodeMinChangeTolerance=%d"), lMinTolIndex); + } + } + + for(TInt j=0; j < lCount; j++) { + TInt lCurrParamID = lParamIds[j]; + lDefValueBuf->Des().Zero(); + lDefValueBuf->Des().Format(_L("%d "), 0); + // Initialize the default values here... + switch(lCurrParamID) { + case RTerminalControl3rdPartySession :: EMaxTimeout: + // lDefValueBuf already has the default value, 0 initialized... + lCurrParamID = ESCPMaxAutolockPeriod; + break; + case RTerminalControl3rdPartySession :: EPasscodeMinLength: + lDefValueBuf->Des().Format(_L("%d"), 4); + break; + case RTerminalControl3rdPartySession :: EPasscodeMaxLength: + lDefValueBuf->Des().Format(_L("%d"), 255); + break; + default: + // lDefValueBuf already has the default value, 0 initialized... + break; + } + + switch(lCurrParamID) { + case RTerminalControl3rdPartySession :: EPasscodeDisallowSpecific: { + RPointerArray lDesArr; + CleanupClosePushL(lDesArr); + + lStatus = lParamDB->GetValuesL(lCurrParamID, lDesArr, lAppID); + + if(KErrNone == lStatus) { + iOverrideForCleanup = ETrue; + TInt lDesCount = lDesArr.Count(); + + for(TInt k=0; k < lDesCount; k++) { + TRAP(lStatus, lStatus = SetParameterValueL(lCurrParamID, lDesArr[k]->Des(), lAppID)); + if(KErrNone != lStatus) { + Dprint(_L("[CSCPServer]-> ERROR: Unable to cleanup parameter %d error %d"), lParamIds[j], lStatus); + lSubOpsFailed = ETrue; + } + } + + iOverrideForCleanup = EFalse; + } + + lDesArr.ResetAndDestroy(); + CleanupStack :: PopAndDestroy(1); // lDesArray + } + break; + default: { + iOverrideForCleanup = ETrue; + TRAP(lStatus, lStatus = SetParameterValueL(lCurrParamID, lDefValueBuf->Des(), lAppID)); + iOverrideForCleanup = EFalse; + + if(KErrNone == lStatus) { + HBufC8* lTmpBuffer = HBufC8 :: NewL(lDefValueBuf->Length()); + lTmpBuffer->Des().Copy(lDefValueBuf->Des()); + + const TParamChange lChange(lParamIds[j], lTmpBuffer->Des()); + aChangeArray.AppendL(lChange); + + // No need to destroy lTmpBuffer, it will be cleaned up by the caller (on cleanup of aParamValArray) + aParamValArray.AppendL(lTmpBuffer); + } + } + } + + if(KErrNone != lStatus) { + Dprint(_L("[CSCPServer]-> ERROR: Unable to cleanup parameter %d error %d"), lParamIds[j], lStatus); + lSubOpsFailed = ETrue; + } + } + } + + Dprint( (_L("[CSCPServer]-> PerformCleanupL() <<<"))); + CleanupStack :: PopAndDestroy(4); // lParamIds lParamDB lBufReadStream lDefValueBuf + return (lSubOpsFailed) ? KErrGeneral : KErrNone; +} + +//#endif // __SAP_DEVICE_LOCK_ENHANCEMENTS +// <<<< ********************** NEW FEATURES ******************** + +// ================= OTHER EXPORTED FUNCTIONS ============== + + // __ARMI__ / + +// --------------------------------------------------------- +// E32Main EXE entry point +// Returns: TInt: Process exit value +// +// Status : Approved +// --------------------------------------------------------- +// +GLDEF_C TInt E32Main() + { + return CSCPServer::ThreadFunction(NULL); + } + + + +// End of File +