diff -r 5cc91383ab1e -r 7333d7932ef7 installationservices/swtransactionservices/source/server/stsserver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/installationservices/swtransactionservices/source/server/stsserver.cpp Tue Aug 31 15:21:33 2010 +0300 @@ -0,0 +1,271 @@ +/* +* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: +* Implements CStsServer. +* +*/ + + +/** + @file + @internalComponent + @released +*/ + +#include "stsserver.h" +#include "stsserversession.h" +#include "usiflog.h" +#include + +namespace Usif +{ +static const TUint stsServerRangeCount = 5; + +static const TInt stsServerRanges[stsServerRangeCount] = + { + 0, //Range 0 - 0 to EBaseSession-1. Not used. + CScsServer::EBaseSession, //Range 1 - EBaseSession to (EBaseSession+ERegisterNew)-1. ==> from ECreateTransaction to EGetId inclusive + CScsServer::EBaseSession|static_cast(ERegisterNew), //Range 2 - (EBaseSession+ERegisterNew) to (EBaseSession+ERollBackAllPending)-1 ==> from ERegisterNew to EOverwrite inclusive + CScsServer::EBaseSession|static_cast(ERollBackAllPending), //Range 3 - (EBaseSession+ERollBackAllPending) to ((EBaseSession+ERollBackAllPending)+1)-1==> only ERollBackAllPending + CScsServer::EBaseSession|static_cast(ERollBackAllPending)+1 //Range 4 - (EBaseSession+ERollBackAllPending)+1 to KMaxTInt inclusive (i.e: ScsImpl::EPreCloseSession) + }; + +static const TUint8 stsServerElementsIndex[stsServerRangeCount] = + { + CPolicyServer::ENotSupported, // Range 0 : is not supported. + CPolicyServer::EAlwaysPass, // Range 1 + CPolicyServer::ECustomCheck, // Range 2 : custom check will be made made for each function to see if client is authorised to do that + 0, // Range 3 : Can only be issued by KUidDaemon + CPolicyServer::EAlwaysPass // Range 4 + }; + +static const CPolicyServer::TPolicyElement stsServerElements[] = + { + {_INIT_SECURITY_POLICY_S0(KUidDaemon), CPolicyServer::EFailClient}, //special handling of function ERollBackAllPending + }; + +static const CPolicyServer::TPolicy stsServerPolicy = + { + CPolicyServer::EAlwaysPass, // Allow all connects + stsServerRangeCount, + stsServerRanges, + stsServerElementsIndex, + stsServerElements, + }; + +// +//CStsServer +// + +CStsServer::CStsServer() +/** + Intializes the STS server object with its version and policy. + */ + : CScsServer(TVersion(KStsVerMajor, KStsVerMinor, KStsVerBuild),stsServerPolicy) + { + //empty + } + +CStsServer::~CStsServer() +/** + Destructor. Cleanup the STS server. + */ + { + iTransactionWrapperContainer.ResetAndDestroy(); + } + + +CStsServer* CStsServer::NewLC() +/** + Factory function allocates new, initialized instance of CStsServer. + + @return New, initialized instance of CStsServer + which is left on the cleanup stack. + */ + { + CStsServer *so = new (ELeave) CStsServer(); + CleanupStack::PushL(so); + so->ConstructL(); + return so; + } + + +void CStsServer::ConstructL() +/** + Second phase constructor starts the STS server. + */ + { + // Roll back all previous transactions in case the STS process died unexpectedly + // Note: error returned from RollBackAllPendingL() is ignored at this point to prevent STS server startup from failing + // It is important to roll back before calling CScsServer::ConstructL as the roll back may be longer than the shutdown period for the timer started by that function + TRAP_IGNORE(RollBackAllPendingL()); + + CScsServer::ConstructL(KStsServerShutdownPeriod); + + StartL(KStsServerName); + } + + +CScsSession* CStsServer::DoNewSessionL(const RMessage2& aMessage) +/** + Implement CStsServer by allocating a new instance of CStsServerSession. + + @param aMessage Standard server-side handle to message. + @return New instance of CStsServerSession which is owned by the caller. + */ + { + return CStsServerSession::NewL(*this, aMessage); + } + +void CStsServer::RollBackAllPendingL() +/** + Rolls back all pending transactions that have persistent information stored in the transaction + path in the file system. + Important note: this function can only be invoked if there are no active transactions in the server as it is + not intended to roll back active transactions. (ie: intended to be invoked at boot-up time and STS start up only) + */ + { + if(iTransactionWrapperContainer.Count()!=0) + { + User::Leave(KErrInUse); //there can be no active transaction when this function is invoked + } + CIntegrityServices::RollbackAllL(); + } + +TInt TransactionWrapperLinearOrderByIdKey(const TStsTransactionId *id, const CReferenceCountedTransactionWrapper &aSecond) + { + return *id-aSecond.TransactionId(); + } + +TInt TransactionWrapperLinearOrder(const CReferenceCountedTransactionWrapper &aFirst, const CReferenceCountedTransactionWrapper &aSecond) + { + return aFirst.TransactionId()-aSecond.TransactionId(); + } + +TStsTransactionId CStsServer::CreateTransactionID() + { + TTime currentTime; + TStsTransactionId transactionID; + do + { + currentTime.UniversalTime(); + transactionID = I64LOW(currentTime.Int64()); + } + while(IsExistingTransaction(transactionID)); + return transactionID; + } + +TBool CStsServer::IsExistingTransaction(TStsTransactionId aTransactionID) + { + return (FindActiveTransaction(aTransactionID)>=0); + } + +CIntegrityServices* CStsServer::CreateTransactionL() + { + TStsTransactionId id = CreateTransactionID(); + CReferenceCountedTransactionWrapper* wrapper = CReferenceCountedTransactionWrapper::NewLC(id); + iTransactionWrapperContainer.InsertInOrderL(wrapper, TLinearOrder(&TransactionWrapperLinearOrder)); + CleanupStack::Pop(wrapper); + return wrapper->Attach(); + } + +CIntegrityServices* CStsServer::AttachTransactionL(TStsTransactionId aTransactionID) + { + TInt pos=FindActiveTransaction(aTransactionID); + if(pos>=0) //joining an existing active transaction + { + return iTransactionWrapperContainer[pos]->Attach(); + } + User::Leave(KErrNotFound); + return 0; + } + +void CStsServer::ReleaseTransactionL(CIntegrityServices* &aTransactionPtr, TBool aMarkAsCompleted /*=EFalse*/) + { + __ASSERT_DEBUG(aTransactionPtr, User::Invariant()); + TInt pos=FindActiveTransaction(aTransactionPtr->TransactionId()); + __ASSERT_DEBUG(pos>=0, User::Invariant()); + CReferenceCountedTransactionWrapper* wrapper=iTransactionWrapperContainer[pos]; + if(aMarkAsCompleted) + wrapper->SetCompleted(); //set transaction as completed (this should be done after a succesful commit or rollback) + TInt refCount=wrapper->Detach(); + __ASSERT_DEBUG(refCount>=0, User::Invariant()); + if(refCount==0) + { + if(!wrapper->IsCompleted()) //do an auto roll back if and only if the transaction has not been committed or rolled-back previously + aTransactionPtr->RollBackL(); + delete wrapper; + iTransactionWrapperContainer.Remove(pos); + } + aTransactionPtr=0; + } +/* + This function is a slight optimization of CStsServer::ReleaseTransactionL() as it is intended to be called + on cleanup of a committed or rolled-back transaction that obviously don't need auto rollbak again. + */ +void CStsServer::FinaliseTransactionL(CIntegrityServices* &aTransactionPtr) + { + ReleaseTransactionL(aTransactionPtr, ETrue); + } + +TInt CStsServer::FindActiveTransaction(TStsTransactionId aTransactionID) + { + return iTransactionWrapperContainer.FindInOrder(aTransactionID, &TransactionWrapperLinearOrderByIdKey); + } + +CPolicyServer::TCustomResult CStsServer::CustomSecurityCheckL(const RMessage2& aMsg, TInt& /*aAction*/, TSecurityInfo& /*aMissing*/) + { + TInt functionId(StripScsFunctionMask(aMsg.Function())); + CPolicyServer::TCustomResult ret(EFail); + + switch(functionId) + { + case ERegisterNew: + case ECreateNew: + case ERemove: + case ERegisterTemporary: + case ECreateTemporary: + case EOverwrite: + ret = CheckIfFileModificationAllowedL(aMsg)? EPass : EFail; + break; + } + return ret; + } + +/*static*/TBool CStsServer::CheckIfFileModificationAllowedL(const RMessage2& aMsg) + { + RBuf filePath; + filePath.CreateL(KMaxFileName); + filePath.CleanupClosePushL(); + aMsg.ReadL(KFilePathIPCSlot, filePath, 0); + + // Retrieve the required capabilities for write access to this path + TCapabilitySet requiredCapabilities = SecCommonUtils::FileModificationRequiredCapabilitiesL(filePath, aMsg.SecureId()); + + TBool result = EFalse; + TBool allFilesRequired = requiredCapabilities.HasCapability(ECapabilityAllFiles); + TBool tcbRequired = requiredCapabilities.HasCapability(ECapabilityTCB); + + // Test whether the client has at least one of the required capabilities + if (allFilesRequired) + result = aMsg.HasCapability(ECapabilityAllFiles); + if (!result && tcbRequired) + result = aMsg.HasCapability(ECapabilityTCB); + if (!allFilesRequired && !tcbRequired) + result = ETrue; + + CleanupStack::PopAndDestroy(&filePath); + return result; + } +}//end of namespace Usif