commonappservices/alarmserver/Server/Source/ASSrvServer.cpp
changeset 0 2e3d3ce01487
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commonappservices/alarmserver/Server/Source/ASSrvServer.cpp	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,251 @@
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "ASSrvServer.h"
+
+// System includes
+#include <e32base.h>
+
+// User includes
+#include "ASSrvSession.h"
+#include "ASSrvStaticUtils.h"
+
+//Only include these in the secured platform 
+#include "ASSrvAlarmQueue.h"
+#include "ASShdOpCodes.h"
+
+
+#define KPolicyElementWriteUserData 0
+#define KPolicyElementWriteDeviceData 1
+
+
+const TUint KRangeCount = 5; 
+
+const TInt KOpCodeRanges[KRangeCount] = 
+	{	
+	KCapabilityNone,
+	KCapabilityCustomCheckData, 
+	KCapabilityWriteUserData, 
+	KCapabilityWriteDeviceData, 
+	EASShdOpCodeLast,
+	};
+
+
+const TUint8 KElementsIndex[KRangeCount] =
+	{
+	CPolicyServer::EAlwaysPass, 	//Allways passing no capability required 0-99
+	CPolicyServer::ECustomCheck, 	//Custom check for the Alarm SID 		 100-199
+	KPolicyElementWriteUserData,	//Requires WriteUserData				 200-299
+	KPolicyElementWriteDeviceData,	//Requires WriteDeviceData				 300-(EASShdOpCodeLast-1)
+	CPolicyServer::ENotSupported, 	//Not Supported					 		 EASShdOpCodeLast-End
+	};
+
+const CPolicyServer::TPolicyElement KPolicyElements[] = 
+	{ 
+	{_INIT_SECURITY_POLICY_C1(ECapabilityWriteUserData), CPolicyServer::EFailClient},
+	{_INIT_SECURITY_POLICY_C1(ECapabilityWriteDeviceData), CPolicyServer::EFailClient} 
+	};
+
+const CPolicyServer::TPolicy KAlarmServerPolicy =
+	{
+	CPolicyServer::EAlwaysPass, //specifies all connect attempts should pass
+	KRangeCount,
+	KOpCodeRanges,
+	KElementsIndex, 	// what each range is compared to 
+	KPolicyElements 	// what policies range is compared to
+	};
+ 	
+
+
+//
+// ----> CASSrvServer (source)
+//
+
+//*************************************************************************************
+CASSrvServer::CASSrvServer()
+ 	:CPolicyServer(CActive::EPriorityHigh, KAlarmServerPolicy)
+	{
+	}
+
+
+//*************************************************************************************
+CASSrvServer::~CASSrvServer()
+	{
+	// In order to prevent access violations as the server
+	// shuts down, we inform all sessions that the server is
+	// about to be destroyed
+	iSessionIter.SetToFirst();
+	//
+	CASSrvSession* session = static_cast<CASSrvSession*>(iSessionIter++);
+	while(session)
+		{
+		session->HandleServerDestruction();
+		session = static_cast<CASSrvSession*>(iSessionIter++);
+		}
+	//
+	delete iServerWideData;
+	}
+
+
+//*************************************************************************************
+void CASSrvServer::ConstructL()
+	{
+	// We "start" the server here (i.e before completing construction) since
+	// if two sessions attempt to connect at the same time, we will end up
+	// setting up an alarm alert notification with a server instance which is
+	// about to be destroyed. Calling StartL here won't actually allow any connections
+	// to be created until the active scheduler has a chance to run. However, the 
+	// call below will leave should there already be a started alarm server instance.
+	//
+	StartL(ASSrvStaticUtils::ASName());
+	iServerWideData = CASSrvServerWideData::NewL();
+	}
+
+
+//*************************************************************************************
+CASSrvServer* CASSrvServer::NewLC()
+	{
+	CASSrvServer* self = new(ELeave) CASSrvServer();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+CSession2* CASSrvServer::NewSessionL(const TVersion& aVersion,const RMessage2& /*aMessage*/) const
+	{
+	// Check client version is correct
+	const TVersion alarmServerVersion(ASSrvStaticUtils::ASVersion());
+	if	(!User::QueryVersionSupported(alarmServerVersion, aVersion))
+		User::Leave(KErrNotSupported);
+
+	// Get non-const reference
+	CASSrvServerWideData& nonConstServerWideData = *const_cast<CASSrvServerWideData*>(iServerWideData);
+
+	// Create new session
+	CASSrvSession* session = CASSrvSession::NewL(nonConstServerWideData);
+	return session;
+	}
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+TInt CASSrvServer::RunError(TInt aError)
+	{
+	// A bad descriptor error implies a badly programmed client, so panic it;
+	// otherwise report the error to the client
+	if	(aError == KErrBadDescriptor)
+		{
+		ASSrvStaticUtils::PanicClient(Message(), EAlarmServerInitiatedClientPanicBadDescriptor);
+		}
+	else
+		{
+		Message().Complete(aError);
+		}
+
+	// The leave will result in an early return from CServer2::RunL(), skipping
+	// the call to request another message. So do that now in order to keep the
+	// server running.
+	ReStart();
+
+	// Indicate that we've handled the error fully
+	return KErrNone;
+	}
+	
+CPolicyServer::TCustomResult CASSrvServer::CustomSecurityCheckL(const RMessage2& aMsg, TInt& /*aAction*/, TSecurityInfo& /*aMissing*/)
+	{
+	CPolicyServer::TCustomResult returnValue = CPolicyServer::EFail;	
+	
+	// Initially, make sure there is alarms in the queue
+	const CASSrvAlarmQueue& queue = iServerWideData->Queue();
+	if(queue.QueueAlarmCount() > 0)
+		{	
+		// Get the alarm id from the client
+		const TAlarmId alarmId = static_cast<TAlarmId>(aMsg.Int0());
+		const TASSrvAlarm* theAlarm = queue.QueueAlarmById(alarmId);
+		if (theAlarm)
+			{
+			//Now get the SID of the alarm, it should be const since we do not want to change the alarm here
+			//Check that the SID of the alarm is equal to the SID of the client
+			TSecureId AlarmOwnerSID = theAlarm->GetSid();
+			TSecureId ClientSID = aMsg.SecureId();
+			if (AlarmOwnerSID == ClientSID)
+				{
+				returnValue = CPolicyServer::EPass;
+				}		
+			}
+		}
+		
+	// If the return value is not CPolicyServer::EPass that means that the client
+	// does not own the alarm (he was not the one creating it)
+	if (returnValue != CPolicyServer::EPass)
+		{
+		// Since different OP Codes require different capabilities
+		// we then need to check the OP code
+		// It is OK to 
+		//		- EASShdOpCodeGetAlarmDetails
+		//		- EASShdOpCodeGetAlarmData
+		//		- EASShdOpCodeAlarmAtIndex
+		// even if the client is not owning the alarm, as long as it has ReadUserData
+		const TInt opCode = aMsg.Function();
+		switch(opCode)
+			{
+			case EASShdOpCodeGetAlarmDetails:
+			case EASShdOpCodeGetAlarmData:
+			case EASShdOpCodeAlarmAtIndex:
+				// Check that the client has ReadUserData
+				if (aMsg.HasCapability(ECapabilityReadUserData))
+					{
+					returnValue = CPolicyServer::EPass;
+					}
+				break;
+			case EASShdOpCodeAlarmNotificationCancelAndDeQueue:	
+			case EASShdOpCodeAlarmDelete:						
+			case EASShdOpCodeSetAlarmStatus:						
+			case EASShdOpCodeSetAlarmDayOrTimed:					
+			case EASShdOpCodeSetAlarmCharacteristics:			
+			case EASShdOpCodeSetClientData:						
+			case EASShdOpCodeAlarmDataAttach:					
+			case EASShdOpCodeAlarmDataDetach:
+#ifdef SYMBIAN_ALARM_REPEAT_EXTENSIONS
+			case EASShdOpCodeSetAlarmDays:
+#endif
+				// Check that the client has WriteDeviceData
+				if (aMsg.HasCapability(ECapabilityWriteDeviceData))
+					{
+					returnValue = CPolicyServer::EPass;
+					}
+				break;
+			default:
+				if (aMsg.HasCapability(ECapabilityReadUserData, ECapabilityWriteDeviceData))
+					{
+					// If the Client has booth ReadUserData and WriteDeviceData then just return CPolicyServer::EPass
+					returnValue = CPolicyServer::EPass;
+					}
+				break;		
+			}
+		}
+	return(returnValue);
+	}