installationservices/swtransactionservices/source/server/stsserver.cpp
branchRCL_3
changeset 25 7333d7932ef7
--- /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 <scs/securityutils.h>
+
+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<TInt>(ERegisterNew),         //Range 2 - (EBaseSession+ERegisterNew) to (EBaseSession+ERollBackAllPending)-1 ==> from ERegisterNew to EOverwrite inclusive
+	CScsServer::EBaseSession|static_cast<TInt>(ERollBackAllPending),  //Range 3 - (EBaseSession+ERollBackAllPending) to ((EBaseSession+ERollBackAllPending)+1)-1==> only ERollBackAllPending
+	CScsServer::EBaseSession|static_cast<TInt>(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<CReferenceCountedTransactionWrapper>(&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