diff -r 000000000000 -r 2e3d3ce01487 commonappservices/alarmserver/Server/Source/ASSrvServer.cpp --- /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 + +// 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(iSessionIter++); + while(session) + { + session->HandleServerDestruction(); + session = static_cast(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(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(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); + }