installationservices/swcomponentregistry/source/server/scrserver.cpp
branchRCL_3
changeset 25 7333d7932ef7
equal deleted inserted replaced
24:5cc91383ab1e 25:7333d7932ef7
       
     1 /*
       
     2 * Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * Implements CScrServer providing management of SCR services.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 /**
       
    21  @file
       
    22  @internalComponent
       
    23  @released
       
    24 */
       
    25 
       
    26 #include "scrserver.h"
       
    27 #include "scrrequestimpl.h"
       
    28 #include "usiflog.h"
       
    29 #include <scs/cleanuputils.h>
       
    30 #include "scrhelperclient.h"
       
    31 #include <scs/securityutils.h>
       
    32 
       
    33 using namespace Usif;
       
    34 
       
    35 static const TUint scrRangeCount = 13;
       
    36 
       
    37 static const TInt scrRanges[scrRangeCount] =
       
    38 	{
       
    39 	0,							 // Range-0 - 0 to EBaseSession-1. Not used.
       
    40 	CScsServer::EBaseSession,	 // Range-1 - EBaseSession to EBaseMustAllow exclusive.
       
    41 	CScsServer::EBaseSession | EGetSingleComponentSize, // Modification and transaction APIs have custom checks
       
    42 	CScsServer::EBaseSession | EGetComponentIdListSize, // Component-specific APIs are free for all
       
    43 	CScsServer::EBaseSession | EGetApplicationLaunchersSize, // Getting all component IDs is restricted to ReadUserData
       
    44 	CScsServer::EBaseSession | EGetIsMediaPresent, // Only allowed by apparc
       
    45 	CScsServer::EBaseSession | EAddApplicationEntry, // Component-specific APIs are free for all
       
    46 	CScsServer::EBaseSession | EGetPluginUidWithMimeType, // Custom checks (as with the rest of modification APIs)
       
    47 	CScsServer::EBaseSession | EAddSoftwareType, // File filter sub-sessions and plugin-fetching APIs are free for all	
       
    48 	CScsServer::EBaseSubSession | EOpenComponentsView, // Software Type management APIs are only allowed for SWI 
       
    49 	CScsServer::EBaseSubSession | EOpenFileList, // Component filter sub-sessions require ReadUserData	
       
    50 	CScsServer::EBaseSubSession | EOpenApplicationRegistrationInfoView, // Always pass
       
    51 	CScsServer::EBaseMustAllow // Application Registration view to be only allowed by apparc, the rest of the range is reserved for SCS, and must be allowed( EBaseMustAllow to KMaxTInt inclusive)	
       
    52 	};
       
    53 
       
    54 static const TUint8 scrElementsIndex[scrRangeCount] =
       
    55 	{
       
    56 	CPolicyServer::ENotSupported, // Range 0 is not supported.
       
    57 	CPolicyServer::ECustomCheck,
       
    58 	CPolicyServer::EAlwaysPass,
       
    59 	0, // Require ReadUserData
       
    60 	2, // Only Apparc process can invoke	
       
    61 	CPolicyServer::EAlwaysPass,
       
    62 	CPolicyServer::ECustomCheck,
       
    63 	CPolicyServer::EAlwaysPass,	
       
    64 	1, // Only SWI process can invoke	
       
    65 	0, // Require ReadUserData
       
    66 	CPolicyServer::EAlwaysPass,
       
    67 	2, // Only Apparc process can invoke
       
    68 	CPolicyServer::EAlwaysPass 
       
    69 	};							
       
    70 
       
    71 static const CPolicyServer::TPolicyElement scrElements[] =
       
    72 	{
       
    73 	{_INIT_SECURITY_POLICY_C1(ECapabilityReadUserData), CPolicyServer::EFailClient},
       
    74 	{_INIT_SECURITY_POLICY_S0(KSisRegistryServerSid.iId), CPolicyServer::EFailClient},
       
    75 	{_INIT_SECURITY_POLICY_S0(KApparcServerSid.iId), CPolicyServer::EFailClient}	
       
    76 	};
       
    77 
       
    78 static const CPolicyServer::TPolicy scrPolicy =
       
    79 	{
       
    80 	CPolicyServer::EAlwaysPass, // Allow all connections
       
    81 	scrRangeCount,
       
    82 	scrRanges,
       
    83 	scrElementsIndex,
       
    84 	scrElements,
       
    85 	};
       
    86 
       
    87 //
       
    88 // CScrServer
       
    89 //
       
    90 
       
    91 CScrServer::CScrServer()
       
    92 /**
       
    93 	Intializes the SCR server object with its version and policy.
       
    94  */
       
    95 	:	CScsServer(ScrServerVersion(), scrPolicy)
       
    96 		{
       
    97 		DEBUG_PRINTF(_L8("SCR server construction!"));
       
    98 		}
       
    99 
       
   100 CScrServer::~CScrServer()
       
   101 /**
       
   102 	Destructor. Cleanup the SCR Server.
       
   103  */
       
   104 	{
       
   105 	DEBUG_PRINTF(_L8("SCR server destruction!"));
       
   106 	delete iRequestImpl;
       
   107 	iDatabaseFile.Close();
       
   108 	iJournalFile.Close();
       
   109 	iFs.Close();
       
   110 	iSubsessionOwners.Close();
       
   111 	}
       
   112 	
       
   113 	
       
   114 CScrServer* CScrServer::NewLC()
       
   115 /**
       
   116 	Factory function allocates a new instance of CScrServer.
       
   117 
       
   118 	@return		The newly created instance of CScrServer which is left on the cleanup stack.
       
   119  */
       
   120 	{
       
   121 	CScrServer *self = new (ELeave) CScrServer();
       
   122 	CleanupStack::PushL(self);
       
   123 	self->ConstructL();
       
   124 	return self;
       
   125 	}
       
   126 
       
   127 
       
   128 void CScrServer::ConstructL()
       
   129 /**
       
   130 	Second phase constructor starts the SCR server.
       
   131  */
       
   132 	{
       
   133 	// StartL() must be called first in order to avoid concurrency issue when starting the server from two or more processes
       
   134 	StartL(KSoftwareComponentRegistryName);
       
   135 	CScsServer::ConstructL(KScrServerShutdownPeriod);
       
   136 	SetupL();
       
   137 	}
       
   138 
       
   139 void CheckFilePathL(RFs& aFs, RFile& aFile, const TDesC& aExpectedPath)
       
   140 	{
       
   141 	RBuf fileName;
       
   142 	fileName.CreateL(KMaxFileName);
       
   143 	fileName.CleanupClosePushL();
       
   144 	User::LeaveIfError(aFile.FullName(fileName));
       
   145 	
       
   146 	RBuf expectedFileName;
       
   147 	expectedFileName.CreateL(aExpectedPath.Length());
       
   148 	expectedFileName.CleanupClosePushL();
       
   149 	expectedFileName.Copy(aExpectedPath);
       
   150 	expectedFileName[0] = aFs.GetSystemDriveChar();
       
   151 	
       
   152 	__ASSERT_ALWAYS(!fileName.CompareF(expectedFileName), User::Leave(KErrBadHandle));
       
   153 		
       
   154 	CleanupStack::PopAndDestroy(2, &fileName); // fileName, expectedFileName
       
   155 	}
       
   156 
       
   157 void CScrServer::SetupL()
       
   158 	{
       
   159 	// Connect to the file server
       
   160 	User::LeaveIfError(iFs.Connect());
       
   161 	User::LeaveIfError(iFs.ShareProtected());
       
   162 	
       
   163 	// Connect to the SCR database
       
   164 	RScrHelper sh;
       
   165 	User::LeaveIfError(sh.Connect());
       
   166 	CleanupClosePushL(sh);
       
   167 	
       
   168 	// Retrieve handles for database and journal files
       
   169 	sh.RetrieveFileHandlesL(iDatabaseFile, iJournalFile);
       
   170 	CleanupStack::PopAndDestroy(&sh);
       
   171 	
       
   172 	// Check if the retrieved file handles belong to the expected files (KScrDatabaseFilePath/KScrJournalFilePath).
       
   173 	// This is an extra security measure in the SCR to check that the file handle transferred from SCR Helper Server  
       
   174 	// really corresponds to scr.db/scr.db-journal in the expected location.
       
   175 	CheckFilePathL(iFs, iDatabaseFile, KScrDatabaseFilePath);
       
   176 	CheckFilePathL(iFs, iJournalFile, KScrJournalFilePath);
       
   177 	
       
   178 	ReconnectL();
       
   179 	}
       
   180 
       
   181 CScsSession* CScrServer::DoNewSessionL(const RMessage2& aMessage)
       
   182 /**
       
   183 	Implement CScsServer by allocating a new instance of CScrSession.
       
   184 
       
   185 	@param	aMessage	Standard server-side handle to message.
       
   186 	@return				New instance of the SCR session class which is owned by the caller.
       
   187  */
       
   188 	{
       
   189 	DEBUG_PRINTF(_L8("SCR session creation!"));
       
   190 	return CScrSession::NewL(*this, aMessage);
       
   191 	}
       
   192 
       
   193 CPolicyServer::TCustomResult CScrServer::CheckComponentIdMatchingEnvironmentL(const RMessage2& aMsg, TBool aCheckForSingleApp)
       
   194 	{	
       
   195 	TComponentId componentId = 0;
       
   196 	if(aCheckForSingleApp)
       
   197 	    {
       
   198         // Get the application uid from RMessage2
       
   199         TInt applicationUid = aMsg.Int0();        
       
   200         // Get the component id for the application            
       
   201         if(!iRequestImpl->GetComponentIdForAppInternalL(TUid::Uid(applicationUid), componentId))
       
   202             return EFail;
       
   203 	    }
       
   204 	else
       
   205 	    {
       
   206 	    componentId = CScrRequestImpl::GetComponentIdFromMsgL(aMsg);
       
   207 	    }
       
   208 	
       
   209 	TSecureId clientSid = aMsg.SecureId();
       
   210 
       
   211     if (componentId == 0)
       
   212         {
       
   213         if (clientSid == KSisRegistryServerSid)
       
   214             return EPass;
       
   215         }   
       
   216     
       
   217     TBool vaildSid = EFalse;
       
   218 	RArray<TSecureId> installerSids;
       
   219 	CleanupClosePushL(installerSids);
       
   220 	if (iRequestImpl->GetInstallerOrExecutionEnvSidsForComponentL(componentId, installerSids))
       
   221 	    {
       
   222         TInt count = installerSids.Count();
       
   223         for (TInt i = 0; i < count; i++)
       
   224             {
       
   225             if (clientSid == installerSids[i])
       
   226                 {
       
   227                 vaildSid = ETrue;
       
   228                 break;
       
   229                 }
       
   230             }
       
   231 	    }
       
   232 	CleanupStack::PopAndDestroy(&installerSids);
       
   233 	
       
   234 	if (vaildSid)
       
   235 		return EPass;
       
   236 			
       
   237 	DEBUG_PRINTF3(_L("Neither installer nor execution environment matched the client while checking for component-matching environment. Client SID %d, Component ID %d"), 
       
   238 			TUint32(clientSid), componentId);
       
   239 	return EFail;
       
   240 	}
       
   241 	
       
   242 CPolicyServer::TCustomResult CScrServer::CheckDeleteComponentAllowedL(const RMessage2& aMsg)	
       
   243 	{
       
   244 	const TUint KSifServerSid = 0x10285BCB;	
       
   245 	
       
   246 	if (CheckComponentIdMatchingEnvironmentL(aMsg) == EPass)
       
   247 		return EPass;
       
   248 		
       
   249 	TSecureId clientSid = aMsg.SecureId();		
       
   250 	TComponentId componentId = CScrRequestImpl::GetComponentIdFromMsgL(aMsg);
       
   251 	// If a component does not have corresponding environments, it means that it is orphaned. In this case, SIF is allowed to forcefully remove it
       
   252 	if (iRequestImpl->GetIsComponentOrphanedL(componentId) && (TUint32(clientSid) == KSifServerSid))
       
   253 		{
       
   254 		DEBUG_PRINTF2(_L("Allowing SIF to uninstall orphaned component %d"), componentId);
       
   255 		return EPass;	
       
   256 		}
       
   257 		
       
   258 	return EFail;
       
   259 	}
       
   260 
       
   261 CPolicyServer::TCustomResult CScrServer::CheckSoftwareNameMatchingEnvironmentL(const RMessage2& aMsg)
       
   262 	{
       
   263 	HBufC* softwareTypeName = CScrRequestImpl::GetSoftwareTypeNameFromMsgLC(aMsg);
       
   264 	TSecureId clientSid = aMsg.SecureId();
       
   265 	
       
   266 	TBool vaildSid = EFalse;
       
   267     RArray<TSecureId> installerSids;
       
   268     CleanupClosePushL(installerSids);
       
   269     if (iRequestImpl->GetSidsForSoftwareTypeL(softwareTypeName, installerSids))
       
   270         {
       
   271         TInt count = installerSids.Count();
       
   272         for (TInt i = 0; i < count; i++)
       
   273             {
       
   274             if (clientSid == installerSids[i])
       
   275                 {
       
   276                 vaildSid = ETrue;
       
   277                 break;
       
   278                 }
       
   279             }
       
   280         }
       
   281     CleanupStack::PopAndDestroy(2, softwareTypeName);
       
   282 	
       
   283 	if (vaildSid)	
       
   284 		return EPass;	
       
   285 
       
   286 	DEBUG_PRINTF(_L("Client Sid is not a valid one software type!"));	
       
   287 	return EFail;
       
   288 	}
       
   289 
       
   290 CPolicyServer::TCustomResult CScrServer::CheckAllowedFilePathL(const RMessage2& aMsg)
       
   291 	{
       
   292 	HBufC* fileName = CScrRequestImpl::ReadFileNameFromMsgLC(aMsg);
       
   293 	
       
   294 	// Retrieve the required capabilities for write access to this path
       
   295 	TCapabilitySet requiredCapabilities = SecCommonUtils::FileModificationRequiredCapabilitiesL(*fileName, aMsg.SecureId());
       
   296 	
       
   297 	TBool result = EFalse;
       
   298 	TBool allFilesRequired = requiredCapabilities.HasCapability(ECapabilityAllFiles);
       
   299 	TBool tcbRequired = requiredCapabilities.HasCapability(ECapabilityTCB);
       
   300 	
       
   301 	// Test whether the client has at least one of the required capabilities
       
   302 	if (allFilesRequired)
       
   303 		result = aMsg.HasCapability(ECapabilityAllFiles);
       
   304 	if (!result && tcbRequired)
       
   305 		result = aMsg.HasCapability(ECapabilityTCB);
       
   306 	if (!allFilesRequired && !tcbRequired)
       
   307 		result = ETrue;
       
   308 	
       
   309 	CleanupStack::PopAndDestroy(fileName);
       
   310 	return result ? EPass : EFail;
       
   311 	}
       
   312 
       
   313 CPolicyServer::TCustomResult CScrServer::CheckClientIsInstallerL(const RMessage2& aMsg)
       
   314 	{
       
   315 	TSecureId clientSid = aMsg.SecureId();
       
   316 	DEBUG_PRINTF2(_L("The client SID is 0x%X"), clientSid.iId);
       
   317 	TBool isInstallerSid = iRequestImpl->IsInstallerOrExecutionEnvSidL(clientSid);
       
   318 	return isInstallerSid ? EPass : EFail;
       
   319 	}
       
   320 
       
   321 CPolicyServer::TCustomResult CScrServer::CheckCommonComponentPropertySettableL(const RMessage2& aMsg, TCapability aRequiredCapability)
       
   322 	{
       
   323 	// Setting a common component property is allowed either for the owning installer or for a process with corresponding capability
       
   324 	if (CheckComponentIdMatchingEnvironmentL(aMsg) == EPass)
       
   325 		return EPass;
       
   326 	return aMsg.HasCapability(aRequiredCapability)? EPass : EFail;
       
   327 	}
       
   328 
       
   329 CPolicyServer::TCustomResult CScrServer::CustomSecurityCheckL(const RMessage2& aMsg, TInt& /*aAction*/, TSecurityInfo& /*aMissing*/)
       
   330 	{	
       
   331 	// SCS framework adds its own bitmask to the function id - we need to strip it in order to detect the actual function invoked
       
   332 	TInt functionId = StripScsFunctionMask(aMsg.Function());
       
   333 
       
   334 	switch (functionId)
       
   335 		{
       
   336 		case ECreateTransaction:
       
   337 		case ERollbackTransaction:
       
   338 		case ECommitTransaction:
       
   339 			return CheckClientIsInstallerL(aMsg);
       
   340 		case EAddComponent:
       
   341 		case EAddComponentDependency:
       
   342 		case EDeleteComponentDependency:
       
   343 			return CheckSoftwareNameMatchingEnvironmentL(aMsg);
       
   344 		case ERegisterComponentFile:
       
   345 		case ESetFileStringProperty:
       
   346 		case ESetFileNumericProperty:
       
   347 		case EDeleteFileProperty:
       
   348 		case EUnregisterComponentFile:
       
   349 			// For file registration we check that the client is actually allowed to modify files under this location
       
   350 			// We do not check for the installer SID, since if the client can write to this location, then registering this location for other components
       
   351 			// does not pose additional risk			
       
   352 			return CheckAllowedFilePathL(aMsg);	
       
   353 		case ESetComponentLocalizableProperty:
       
   354 		case ESetComponentNumericProperty:
       
   355 		case ESetComponentBinaryProperty:
       
   356 		case ESetComponentName:
       
   357 		case ESetComponentVendor:
       
   358 		case ESetComponentVersion:
       
   359 		case ESetComponentSize:
       
   360 		case EDeleteComponentProperty:
       
   361 		case ESetScomoState:
       
   362 		case ESetIsComponentPresent:
       
   363 			return CheckComponentIdMatchingEnvironmentL(aMsg);
       
   364 		case EDeleteComponent:			
       
   365 			return CheckDeleteComponentAllowedL(aMsg);
       
   366 		case ESetIsComponentRemovable:
       
   367 			return CheckCommonComponentPropertySettableL(aMsg, ECapabilityAllFiles);
       
   368 		case ESetIsComponentDrmProtected:
       
   369 		case ESetIsComponentHidden:
       
   370 		case ESetIsComponentKnownRevoked:
       
   371 		case ESetIsComponentOriginVerified:		
       
   372 			return CheckCommonComponentPropertySettableL(aMsg, ECapabilityWriteDeviceData);
       
   373 		case EAddApplicationEntry:
       
   374 		case EDeleteApplicationEntries:
       
   375 			return CheckComponentIdMatchingEnvironmentL(aMsg);
       
   376 		case EDeleteApplicationEntry:
       
   377 		    return CheckComponentIdMatchingEnvironmentL(aMsg, ETrue);
       
   378 		default:
       
   379 			DEBUG_PRINTF2(_L("Unknown function was invoked in CustomSecurityCheck - %d"), functionId);							
       
   380 			__ASSERT_DEBUG(0, User::Invariant());
       
   381 			return EFail;
       
   382 		}
       
   383 	}
       
   384 
       
   385 void CScrServer::ReconnectL()
       
   386 	{
       
   387 	DeleteObjectZ(iRequestImpl);	
       
   388 	iRequestImpl = CScrRequestImpl::NewL(iFs, iDatabaseFile, iJournalFile);	
       
   389 	}
       
   390 
       
   391 void CScrServer::AddSubsessionOwnerL(CScrSession* aSession)
       
   392 	{
       
   393 	iSubsessionOwners.InsertInAddressOrderAllowRepeatsL(aSession);
       
   394 	}
       
   395 
       
   396 void CScrServer::RemoveSubsessionOwner(CScrSession* aSession)
       
   397 	{
       
   398 	TInt index = iSubsessionOwners.FindInAddressOrder(aSession);
       
   399 	if(KErrNotFound != index)
       
   400 		iSubsessionOwners.Remove(index);
       
   401 	}
       
   402 
       
   403 TBool CScrServer::IsTheOnlySubsessionOwner(CScrSession* aSession)
       
   404 	{
       
   405 	TInt firstElementIdx = 0;
       
   406 	TInt lastElementIdx = iSubsessionOwners.Count();
       
   407 	// if both first element and the last element in the array is the provided session
       
   408 	// it means that all active subsessions is owned by this session. 
       
   409 	if(firstElementIdx == iSubsessionOwners.SpecificFindInAddressOrder(aSession, EArrayFindMode_First) &&
       
   410 	   lastElementIdx == iSubsessionOwners.SpecificFindInAddressOrder(aSession, EArrayFindMode_Last))
       
   411 		{
       
   412 		return ETrue;
       
   413 		}
       
   414 	return EFalse; 
       
   415 	}
       
   416 
       
   417 TInt CScrServer::SubsessionCount()
       
   418 	{
       
   419 	return iSubsessionOwners.Count();
       
   420 	}
       
   421 
       
   422 void CScrServer::SetTransactionOwner(CScrSession* aSession)
       
   423 	{
       
   424 	iTransactionOwningSession = aSession;
       
   425 	}
       
   426 
       
   427 
       
   428 TBool CScrServer::IsTransactionInProgress()
       
   429 	{
       
   430 	if(iTransactionOwningSession)
       
   431 		return ETrue;
       
   432 	else 
       
   433 		return EFalse;
       
   434 	}
       
   435 
       
   436 
       
   437 TBool CScrServer::IsTransactionOwner(CScrSession* aSession)
       
   438 	{	
       
   439 	__ASSERT_ALWAYS(aSession, User::Invariant());
       
   440 	if(aSession == iTransactionOwningSession) 
       
   441 		return ETrue;
       
   442 	else 
       
   443 		return EFalse;
       
   444 	}
       
   445 
       
   446 void CScrServer::DoPreHeapMarkOrCheckL()
       
   447 /**
       
   448    This function is called by the framework just before settingchecking a heap mark. We need to compress/free memory
       
   449    down to a state which should be the same both before and after the test operations.
       
   450 */
       
   451 {
       
   452 #ifdef _DEBUG
       
   453 iSubsessionOwners.Compress();
       
   454 DeleteObjectZ(iRequestImpl);
       
   455 #endif
       
   456 }
       
   457 
       
   458 void CScrServer::DoPostHeapMarkOrCheckL()
       
   459 /**
       
   460    This function is called by the framework just before settingchecking a heap mark. We need to compress/free memory
       
   461    down to a state which should be the same both before and after the test operations.
       
   462 */
       
   463 {
       
   464 #ifdef _DEBUG
       
   465 this->ReconnectL();
       
   466 #endif
       
   467 }