installationservices/swi/source/swis/server/restorecontroller.cpp
changeset 0 ba25891c3a9e
child 25 7333d7932ef7
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2004-2009 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 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <s32mem.h>
       
    20 
       
    21 
       
    22 #include "restorecontroller.h"
       
    23 
       
    24 #include "arrayutils.h"
       
    25 #include "sisinfo.h"
       
    26 #include "sisuid.h"
       
    27 #include "sisversion.h"
       
    28 #include "sissupportedlanguages.h"
       
    29 #include "sisinstallblock.h"
       
    30 #include "sishash.h"
       
    31 #include "userselections.h"
       
    32 #include "siselseif.h"
       
    33 #include "log.h"
       
    34 #include "securitycheckutil.h"
       
    35 #include "siscapabilities.h"
       
    36 #include "certchainconstraints.h"
       
    37 #include "sisregistryfiledescription.h"
       
    38 #include "sistruststatus.h"
       
    39 #include "secutils.h"
       
    40 
       
    41 #include <f32file.h>
       
    42 
       
    43 using namespace Swi;
       
    44 using namespace Swi::Sis;
       
    45 
       
    46 //
       
    47 // TRestoreFileInformation
       
    48 //
       
    49 
       
    50 TRestoreFileInformation::TRestoreFileInformation(CFileDescription& aFileDescription, CApplication& aParentApplication)
       
    51 	: iFileDescription(aFileDescription), 
       
    52 	iParentApplication(aParentApplication)	
       
    53 	{
       
    54 	}
       
    55   
       
    56 
       
    57 //
       
    58 // CRestoreController
       
    59 // 
       
    60    
       
    61 void CRestoreController::ConstructL(TDesC8& aController)
       
    62 	{				
       
    63 	iSystemDriveChar = RFs::GetSystemDriveChar();
       
    64 	
       
    65 	// Read the controllers from the buffer		
       
    66 	InternalizeControllersL(aController);
       
    67 	
       
    68 	//We also create a dummy plan for use when writing the 
       
    69 	//registry entries
       
    70 	TInt augmentationIndex(0);
       
    71 	TInt noOfMatchingLanguages = iMatchingSupportedLanguagesArray.Count();
       
    72 	TInt matchingLanguageCount = 0;
       
    73 	for (TInt i = 0; i < iControllers.Count(); i++)
       
    74 		{
       
    75 		
       
    76 		CPlan* plan = CPlan::NewL();
       
    77 		CleanupStack::PushL(plan);
       
    78 		User::LeaveIfError(iInstallPlans.Append(plan));
       
    79 		CleanupStack::Pop(plan);
       
    80 		
       
    81 		CApplication* application = CApplication::NewLC();
       
    82 		
       
    83 		CController* controller = iControllers[i];
       
    84 		
       
    85 		DEBUG_PRINTF3(_L8("Restore - Metadata controller %d is of type %d"),
       
    86 			i, controller->Info().InstallType());
       
    87 		
       
    88  		// Set the install type 		
       
    89  		switch (controller->Info().InstallType())
       
    90  			{
       
    91  		case EInstInstallation:
       
    92  			application->SetInstall(*controller);
       
    93 			application->UserSelections().SetDrive(iInstallDrive);		
       
    94 			
       
    95 			//if there are macthing languages then populate iMatchingDeviceLanguages array of application object
       
    96 			if ( noOfMatchingLanguages )
       
    97 				{
       
    98 				while( iMatchingSupportedLanguagesArray[matchingLanguageCount] != ELangNone)
       
    99 					{
       
   100 					application->PopulateMatchingDeviceLanguagesL(iMatchingSupportedLanguagesArray[matchingLanguageCount++]);
       
   101 					}
       
   102 				}
       
   103  			break;
       
   104  		
       
   105  		case EInstPartialUpgrade:
       
   106  			application->SetPartialUpgrade(*controller);
       
   107 			application->UserSelections().SetDrive(iInstallDrive);	
       
   108 			// Carry forwards the in-rom flag
       
   109 			if (i == 0 || iTopLevelApplications[0]->IsInROM()) 				
       
   110 				{
       
   111 				// If the first controller is a parial upgrade then 
       
   112 				// it must be a partial upgrade to a ROM stub.
       
   113 				// If there are multiple PUs then they must also be in-rom
       
   114 				application->SetInROM();
       
   115 				}
       
   116 	         if ( noOfMatchingLanguages )
       
   117 	                {
       
   118 	                TInt i = 0;
       
   119 	                while( iMatchingSupportedLanguagesArray[i] != ELangNone)
       
   120 	                    {
       
   121 	                    application->PopulateMatchingDeviceLanguagesL(iMatchingSupportedLanguagesArray[i++]);
       
   122 	                    }
       
   123 	                }
       
   124  			break;
       
   125  			
       
   126 		case EInstAugmentation:	
       
   127 			application->SetAugmentation(*controller);
       
   128 			application->UserSelections().SetDrive(iAugmentationDrives[augmentationIndex++]);
       
   129 			
       
   130 			//if there are macthing languages then populate iMatchingDeviceLanguages array of application object
       
   131 			if ( noOfMatchingLanguages )
       
   132 				{
       
   133 				while( iMatchingSupportedLanguagesArray[matchingLanguageCount] != ELangNone)
       
   134 					  {
       
   135 					   application->PopulateMatchingDeviceLanguagesL(iMatchingSupportedLanguagesArray[matchingLanguageCount++]);
       
   136 					  }
       
   137 				}
       
   138 			break;
       
   139  			
       
   140  		default:
       
   141  			User::Leave(KErrNotSupported);
       
   142  			break;
       
   143  			
       
   144  			}
       
   145  					
       
   146 		TPtrC8* buf = iControllerBinaries[i];
       
   147 		
       
   148 		application->SetController(*controller);
       
   149 		
       
   150 		CSisCertificateVerifier* verifier = CSisCertificateVerifier::NewLC(controller, *buf, iSecurityManager, application);
       
   151 		User::LeaveIfError(iVerifiers.Append(verifier));
       
   152 		CleanupStack::Pop(verifier);
       
   153 		
       
   154 		TInt languageIndex = SetApplicationLanguageL(*application);
       
   155 	
       
   156 		//This is the first controller, add it to the plan
       
   157 		User::LeaveIfError(iTopLevelApplications.Append(application));
       
   158 		plan->SetApplication(application); // ownership transferred.
       
   159 			
       
   160 		const CVersion& version = controller->Info().Version();
       
   161 		TVersion appVersion(version.Major(), version.Minor(), version.Build());
       
   162 			
       
   163 		plan->SetApplicationInformationL(controller->Info().Names()[languageIndex]->Data(),
       
   164 			controller->Info().VendorNames()[languageIndex]->Data(),
       
   165 			appVersion);	
       
   166 		
       
   167 		CleanupStack::Pop(application);			
       
   168 		}	
       
   169 	}
       
   170 	
       
   171 /**
       
   172  Locates the relevant file description in the controller and adds the file
       
   173  to be restored to the list of files for the new SIS registry object.
       
   174  
       
   175  This also checks the hash of the file if needed and generates an appropriate temporary
       
   176  filename to be used by integrity services.
       
   177  
       
   178  @param		aFile				file handle to temporary restore file.
       
   179  @param		aTempFileName		temporary filename to use with integrity services.
       
   180  @param		aHashCheckRequried	whether the restore files hash must be checked against the controllers
       
   181  */
       
   182 void CRestoreController::AddFileDescriptionL(RFile& aFile, TDesC& aTarget, TDes& aTempFilename, TBool aHashCheckRequired)
       
   183   	{
       
   184   	// Lookup file information and check the hash if needed  	
       
   185   	TRestoreFileInformation info = LookupFileInformationL(aFile, aTarget, aHashCheckRequired);
       
   186   	
       
   187   	// Add the file description to the plan
       
   188   	CApplication& application = info.ParentApplication();
       
   189   	application.AddFileL(info.FileDescription(), application.UserSelections().Drive());
       
   190   	
       
   191   	// Construct the temporary file name for this file
       
   192   	TParsePtrC parse(aTarget);  	
       
   193   	_LIT(KTemporaryFileFormat, "%c:%Stfile-%d-%d-%d-");
       
   194   	TUint driveCh(iSystemDriveChar);
       
   195   	aTempFilename.Format(KTemporaryFileFormat, driveCh, &KSysInstallTempPath, 
       
   196   		application.ControllerL().Info().Uid().Uid().iUid, application.AbsoluteDataIndex(), info.FileDescription().Index());
       
   197   	 
       
   198   	// Append a hex representation of a hash of the filename. We need the
       
   199   	// temporary filename to be effectively unique, but the filename itself
       
   200   	// may be too long.
       
   201   	
       
   202   	// Use the real target path (after path subsitution) minus the drive letter.
       
   203   	HBufC* hashBuf = SecUtils::HexHashL(aTarget.Right(aTarget.Length() - 1));
       
   204   	aTempFilename.Append(*hashBuf);
       
   205   	delete hashBuf;
       
   206   	
       
   207   	// finally, remove this file from the list of files to add entries for
       
   208   	for (TInt i = 0; i < iInstalledFiles.Count(); ++i)
       
   209   		{  		
       
   210   		HBufC* filename = iInstalledFiles[i];	
       
   211   		if (aTarget.CompareF(*filename) == 0)
       
   212   			{
       
   213   			delete filename;
       
   214   			iInstalledFiles.Remove(i);
       
   215   			break;
       
   216   			}  		
       
   217   		}  	
       
   218   	}
       
   219   
       
   220 void CRestoreController::AddEmbeddedAppsAndFilesL()
       
   221   	{
       
   222 	//for each application/controller pair, add fake file and embedded package descriptions
       
   223 	for (TInt i = 0; i < iTopLevelApplications.Count(); ++i)
       
   224 		{
       
   225 		DoAddEmbeddedAppsAndFilesL(iTopLevelApplications[i]->ControllerL().InstallBlock(), *iTopLevelApplications[i]); 
       
   226 		}
       
   227 	}
       
   228 
       
   229 // Preserves the links between embedded applications in the registry, so uninstalling the 
       
   230 // top level package will attempt to uninstall the packages below it in the tree
       
   231 // However, these applications are not processed as part of the restore 
       
   232 // hence they are entirely fake	
       
   233 
       
   234 void CRestoreController::DoAddEmbeddedAppsAndFilesL(
       
   235 	const CInstallBlock& aInstallBlock, CApplication& aApplication)
       
   236 	{
       
   237 	
       
   238 	const RPointerArray<CController>& controllers = aInstallBlock.EmbeddedControllers();
       
   239 
       
   240   	TInt i;	
       
   241 	for (i = 0; i < controllers.Count(); ++i)
       
   242 		{
       
   243 		
       
   244 		CController* controller = controllers[i];
       
   245 		
       
   246 		CApplication* application = CApplication::NewLC();
       
   247 		application->SetController(*controller);
       
   248 		SetApplicationLanguageL(*application);
       
   249 		aApplication.AddEmbeddedApplicationL(application); // Ownership transfered
       
   250 		CleanupStack::Pop(application);
       
   251 		
       
   252 		}
       
   253 		
       
   254   	const RPointerArray<CFileDescription>& fileDescriptions = aInstallBlock.FileDescriptions();
       
   255   	TChar foldedDrive = aApplication.UserSelections().Drive();
       
   256   	if (foldedDrive != 255)
       
   257   		{
       
   258   		foldedDrive.Fold();	// don't convert 'no drive selection' to the y drive 
       
   259   		}
       
   260   	
       
   261   	for (i = 0; i < fileDescriptions.Count(); ++i)
       
   262   		{
       
   263   		const TDesC& description = fileDescriptions[i]->Target().Data();
       
   264   		if (description.Length() != 0)
       
   265   			{
       
   266   			TChar sisDrive = description[0];
       
   267   			if (sisDrive == '$')
       
   268   				{
       
   269   				sisDrive = iFs.GetSystemDriveChar();	
       
   270   				}  			
       
   271   			sisDrive.Fold();
       
   272   			
       
   273   			for (TInt j = 0; j < iInstalledFiles.Count(); j++)
       
   274   				{
       
   275   				HBufC* filename = iInstalledFiles[j];
       
   276   				TChar targetDrive = (*filename)[0];
       
   277   				targetDrive.Fold();
       
   278   			
       
   279 				// if the file description matches this filename (taking into account drive letter)
       
   280 				// add it to the application.
       
   281 				// This may not be 100% the correct file description, but it will be close enough
       
   282 				if (description.Mid(1).CompareF(filename->Mid(1)) == 0 &&
       
   283 				    ((targetDrive == foldedDrive) || (targetDrive == sisDrive)))
       
   284 				       {
       
   285 				       aApplication.AddFileL(*fileDescriptions[i], aApplication.UserSelections().Drive());
       
   286 				       // Cut down the search space some
       
   287 				       delete filename;
       
   288 				       iInstalledFiles.Remove(j);
       
   289 				       break;
       
   290 				       }
       
   291 				}
       
   292 			}
       
   293   		}
       
   294   		
       
   295 	const RPointerArray<CIf>& ifBlocks = aInstallBlock.IfStatements();
       
   296 
       
   297 	for (i = 0; i < ifBlocks.Count(); ++i)
       
   298 		{
       
   299 		
       
   300 		CIf* ifBlock = ifBlocks[i];
       
   301 		DoAddEmbeddedAppsAndFilesL(ifBlock->InstallBlock(), aApplication);
       
   302 		
       
   303 		const RPointerArray<CElseIf>& elseBlocks = ifBlock->ElseIfs();
       
   304 		
       
   305 		for (TInt j = 0; j < elseBlocks.Count(); j++)
       
   306 			{
       
   307 			
       
   308 			CElseIf* elseBlock = elseBlocks[j];
       
   309 			DoAddEmbeddedAppsAndFilesL(elseBlock->InstallBlock(), aApplication);
       
   310 			
       
   311 			}
       
   312 		
       
   313 		}
       
   314 		
       
   315 	}	
       
   316 // Creates a TPtrC8* which points to the data of controllers stored in MetaData which was backedup.
       
   317 // Not using HBufC8::NewLC as it allocates memory afresh for the data.
       
   318 TPtrC8* CRestoreController::CreateRawControllerPtrLC(RDesReadStream& aStream, const TUint8* aBasePtr, TInt& aOffset )
       
   319 	{
       
   320 	TCardinality card;
       
   321 	aStream>>card;
       
   322 	TInt tmpLen = (TInt)card;
       
   323 	//Right shift TCardinality by one as its LSB is not
       
   324 	// used to represent the length of the descriptor
       
   325 	TInt len = ((TInt)card) >> 1;
       
   326 
       
   327 	//TCardinality uses 
       
   328 	// 1 Byte to store the length if it is between 0-127 
       
   329 	// 2 Bytes if length is between 128-16383
       
   330 	// 4 Bytes if length > 16383
       
   331 	
       
   332 	if ( tmpLen < 128 )
       
   333 		aOffset+=1;
       
   334 	else if ( tmpLen < 16384 )
       
   335 		aOffset+=2;
       
   336 	else
       
   337 		aOffset+=4;
       
   338 	
       
   339 	TPtrC8* controllerBuf = new (ELeave)TPtrC8(); 
       
   340 	controllerBuf->Set(aBasePtr+aOffset,len);
       
   341 	CleanupStack::PushL(controllerBuf);
       
   342 	
       
   343 	aOffset += len;
       
   344 	
       
   345 	while( len-- )
       
   346 		aStream.ReadInt8L();
       
   347 
       
   348 	return controllerBuf;
       
   349 	}
       
   350 
       
   351 void CRestoreController::InternalizeControllersL(TDesC8& aController)
       
   352 	{
       
   353 	
       
   354 	RDesReadStream stream(aController);
       
   355 	CleanupClosePushL(stream);
       
   356 	TInt offset = 0;
       
   357 	const TUint8* basePtr = aController.Ptr();
       
   358 	
       
   359 	// Drive letter to install to
       
   360 	iInstallDrive = TChar(stream.ReadUint32L());
       
   361 	offset+=4;
       
   362 	
       
   363 	// We need to count the augmentations to know how many selected drives to
       
   364 	// read after the list of files.
       
   365 	TInt augmentationsCount(0);
       
   366 
       
   367 	TInt controllerCount = stream.ReadInt32L();
       
   368 	DEBUG_PRINTF2(_L8("Restore - Metadata consists of %d seperate controllers"), 
       
   369 		controllerCount);
       
   370 	offset+=4;
       
   371 	
       
   372 	while (controllerCount--)
       
   373 		{
       
   374 		TPtrC8* controllerBuf = CreateRawControllerPtrLC(stream,basePtr,offset);
       
   375 		
       
   376 		User::LeaveIfError(iControllerBinaries.Append(controllerBuf));
       
   377 		CleanupStack::Pop(controllerBuf);
       
   378 		
       
   379 		// Create a CController object from the binary
       
   380 		
       
   381 		CDesDataProvider* provider = CDesDataProvider::NewLC(*controllerBuf);
       
   382 		CController* controller = CController::NewLC(*provider, EAssumeType);
       
   383 		User::LeaveIfError(iControllers.Append(controller));
       
   384 		CleanupStack::Pop(controller);
       
   385 		if (controller->Info().InstallType() == EInstAugmentation)
       
   386 			{
       
   387 			augmentationsCount++;
       
   388 			}
       
   389 		CleanupStack::PopAndDestroy(provider);
       
   390 		
       
   391 		}
       
   392 		
       
   393   	// Trap this to make the metadata file format BC	
       
   394   	TInt filesCount = 0;
       
   395   	TRAPD(err, filesCount = stream.ReadInt32L());
       
   396   	// If this is an old style backup metadata file, it won't include this section
       
   397   	if (err == KErrNone)
       
   398   		{
       
   399   		while (filesCount--)
       
   400   			{
       
   401   			HBufC* filename = HBufC::NewLC(stream, KMaxTInt);
       
   402   			User::LeaveIfError(iInstalledFiles.Append(filename));
       
   403   			CleanupStack::Pop(filename);
       
   404   			}
       
   405 
       
   406  		// Trap reading augmentations' selected drives, which appear after the
       
   407  		// file list in metadata files created after the fix for DEF087124.
       
   408  		// Leave if the read fails beyond the first augmentation, since we should
       
   409  		// have all or none.
       
   410   		for (TInt i = 0; i < augmentationsCount; i++)
       
   411 			{
       
   412 			if (err == KErrNone)
       
   413 				{
       
   414   				TChar selectedDrive(iInstallDrive);
       
   415   				TRAP(err, selectedDrive = stream.ReadInt32L());
       
   416   				if (i != 0)
       
   417   					{
       
   418   					User::LeaveIfError(err);
       
   419   					}
       
   420 				iAugmentationDrives.AppendL(selectedDrive);
       
   421 				}
       
   422 			else
       
   423 				{
       
   424 				// If we failed on reading the first drive, fill the rest of
       
   425 				// the array with the selected drive for the base package.
       
   426 				iAugmentationDrives.AppendL(iInstallDrive);			
       
   427 				}
       
   428 			}
       
   429   		}
       
   430   		
       
   431   		// Reading the array of matching device supported languages
       
   432   		TRAP(err, InternalizeArrayL(iMatchingSupportedLanguagesArray,stream));
       
   433 
       
   434 	CleanupStack::PopAndDestroy(&stream);
       
   435 	}
       
   436 	
       
   437 		
       
   438 CRestoreController* CRestoreController::NewL(TDesC8& aController, CSecurityManager& aSecurityManager, RFs& aFs)
       
   439 	{
       
   440 	
       
   441 	CRestoreController* self = CRestoreController::NewLC(aController, aSecurityManager, aFs);
       
   442 	CleanupStack::Pop(self);
       
   443 	return self;
       
   444 	
       
   445 	}
       
   446 		
       
   447 CRestoreController* CRestoreController::NewLC(TDesC8& aController, CSecurityManager& aSecurityManager, RFs& aFs)
       
   448 	{
       
   449 	
       
   450 	CRestoreController* self = new (ELeave) CRestoreController(aSecurityManager, aFs);
       
   451 	CleanupStack::PushL(self);
       
   452 	self->ConstructL(aController);
       
   453 	return self;
       
   454 		
       
   455 	}
       
   456 		
       
   457 CRestoreController::CRestoreController(CSecurityManager& aSecurityManager, RFs& aFs)
       
   458 	: iFs(aFs), iSecurityManager(aSecurityManager)
       
   459 	{
       
   460 	}
       
   461  /**
       
   462   Finds the matching file description in the controller and checks the hash if required.
       
   463   
       
   464   @param		aFile				handle to the file to restore
       
   465   @param 	aTarget				path that the file handle should be restored.
       
   466   @param		aHashCheckRequired	if the target path is TCB protected and a hash check is required.
       
   467   */
       
   468  TRestoreFileInformation CRestoreController::LookupFileInformationL(RFile& aFile, TDesC& aTarget, TBool aHashCheckRequired)
       
   469 
       
   470 
       
   471 	{
       
   472 	CFileDescription* desc = NULL;
       
   473 	
       
   474 	// Search through the controllers backwards in case an executable has been ugpraded with 
       
   475 	// a partial upgrade
       
   476 	TBool foundMatch = EFalse;
       
   477 	TInt i = iControllers.Count() - 1;
       
   478 	CApplication* application = NULL;
       
   479 	while (i >= 0 && ! foundMatch)
       
   480 		{
       
   481 		CController* controller = iControllers[i];
       
   482 		application = iTopLevelApplications[i];
       
   483 		TChar drive = application->UserSelections().Drive();
       
   484 		desc = FindFileDescriptionL(controller->InstallBlock(), aFile, aTarget, aHashCheckRequired, drive);
       
   485 				
       
   486 		if (desc)
       
   487 			{
       
   488 			foundMatch = ETrue;
       
   489 			}
       
   490 		else
       
   491 			{
       
   492 			--i;	// Check the next controller
       
   493 			}
       
   494 		}
       
   495 		
       
   496 	if (aHashCheckRequired && ! foundMatch)
       
   497 		{
       
   498 		// Previously the code would return either KErrNotFound or KErrSISWouldOverWrite
       
   499 		// both of these errors are incorrect and SBE does not depend on the exact error code
       
   500 		// in this scenario.
       
   501 		// N.B. It is already possible for KErrSecurityError to be returned so the backup
       
   502 		// client MUST be able to handle this.
       
   503 		DEBUG_PRINTF2(_L("No matching hash for file %S"), &aTarget);
       
   504 		User::Leave(KErrSecurityError);
       
   505 		}
       
   506 	else if (! foundMatch)
       
   507 		{
       
   508 		// It's difficult to report VerifyOnRestore mis-matches as a security error because
       
   509 		// the file could be present in multiple controllers and in multiple install blocks
       
   510 		// with and without the VerifyOnRestore flag set
       
   511 		DEBUG_PRINTF2(_L("No match in controller for %S"), &aTarget);
       
   512 		User::Leave(KErrNotFound);
       
   513 		}
       
   514 	
       
   515 	// This is where things get really interesting ...
       
   516 	// The restore machine invokes a restore processor for each controller in turn
       
   517 	// and as well as checking the exe header the restore processor builds a list of SIDs
       
   518 	// as it goes.
       
   519 	// When the files are installed private directories are checked against the list of SIDs.
       
   520 	// BUT
       
   521 	// If the exe has been upgraded via a partial upgrade then the application pointer here will
       
   522 	// refer to the partial upgrade that hasn't been checked yet so the SID isn't known and the processor
       
   523 	// will reject the restore of files to that private dir.
       
   524 	// Reversing the order of processing the controllers doesn't help because if the exe
       
   525 	// hasn't been upgraded but the PU deploys a file to the exe's private dir then again the SID
       
   526 	// isn't known so the install will be rejected.
       
   527 	
       
   528 	// The work around is to associate all of the files supplied by SBE for PUs with
       
   529 	// the first application which will be the SA
       
   530 	// It's not safe blindly do this for all applications because this would incorrectly associate
       
   531 	// the augmenation's files with the SP
       
   532 	if (application->IsPartialUpgrade()) 
       
   533 		{
       
   534 		application = iTopLevelApplications[0];
       
   535 		}
       
   536 	TRestoreFileInformation result(*desc, *application);
       
   537 	return result;	
       
   538 	}
       
   539 	
       
   540 CFileDescription* CRestoreController::FindFileDescriptionL(
       
   541 		const CInstallBlock& aInstallBlock, RFile& aFile, TDesC& aTarget, TBool aHashCheckRequired, const TChar& aDrive)
       
   542 	{	
       
   543 	const RPointerArray<CFileDescription> descriptions = aInstallBlock.FileDescriptions();
       
   544 	CFileDescription* result = NULL;
       
   545 	
       
   546 	for (TInt j = 0; j < descriptions.Count(); j++)
       
   547 		{
       
   548 		CFileDescription* description = descriptions[j];		
       
   549 		const TDesC& descTarget = (description->Target()).Data();
       
   550 		
       
   551 		// We'll acknowledge that the file matches the description iff:
       
   552 		// a) The hashes match
       
   553 		// b) The targets match, taking into account wildcard drive letters
       
   554 		
       
   555 		// substitute the drive letter and replace any relevant paths
       
   556 		HBufC* transDest =
       
   557 			iSecurityManager.SecurityPolicy().ResolveTargetFileNameLC(descTarget, aDrive);
       
   558 		
       
   559 		// check if this file matches the file name		
       
   560 		TBool match = (transDest->Left(1).CompareF(aTarget.Left(1)) == 0)
       
   561 						&&(transDest->Mid(1) == aTarget.Mid(1));
       
   562 		
       
   563 		// if it does, do we also need to do as hash check to approve this file?						
       
   564 		if ((aHashCheckRequired || (description->OperationOptions() & EInstVerifyOnRestore)) && match)
       
   565 			{
       
   566 			// If the file is TCB protected OR the VerifyOnRestore flag is set the 
       
   567 			// a match is only valid if the hash also matches
       
   568 			const CHash& hash = description->Hash();
       
   569 			TSISHashAlgorithm algorithm = hash.Algorithm();			
       
   570 			CMessageDigest* temp = CalculateHashL(aFile, algorithm);
       
   571 			CleanupStack::PushL(temp);			
       
   572 			match = (temp->Final() == hash.Data());
       
   573 			DEBUG_PRINTF3(_L("Checking hash candiate for file %S pass = %d"), &aTarget, match);
       
   574 			CleanupStack::PopAndDestroy(temp);
       
   575 			}		
       
   576 		CleanupStack::PopAndDestroy(transDest);		
       
   577 		if (match)
       
   578 			{
       
   579 			return description;
       
   580 			}
       
   581 		}
       
   582 	
       
   583 	const RPointerArray<CIf>& ifBlocks = aInstallBlock.IfStatements();
       
   584 	for (TInt i = 0; i < ifBlocks.Count(); i++)
       
   585 		{		
       
   586 		CIf* ifBlock = ifBlocks[i];
       
   587 		if (NULL != (result = FindFileDescriptionL(ifBlock->InstallBlock(), aFile, aTarget, aHashCheckRequired, aDrive)))
       
   588 			{			
       
   589 			return result;			
       
   590 			}
       
   591 		
       
   592 		const RPointerArray<CElseIf>& elseBlocks = ifBlock->ElseIfs();		
       
   593 		for (TInt j = 0; j < elseBlocks.Count(); j++)
       
   594 			{			
       
   595 			CElseIf* elseBlock = elseBlocks[j];
       
   596 			if (NULL != (result = FindFileDescriptionL(elseBlock->InstallBlock(), aFile, aTarget, aHashCheckRequired, aDrive)))
       
   597 				{				
       
   598 				return result;			
       
   599 				}			
       
   600 			}		
       
   601 		}		
       
   602 	return result;	
       
   603 	}
       
   604 	
       
   605 		
       
   606 CMessageDigest* CRestoreController::CalculateHashL(RFile& aFile, TSISHashAlgorithm aAlgorithm)
       
   607 	{		
       
   608 	HBufC8* buf = HBufC8::NewLC(1024);
       
   609 	TPtr8 bufPtr(buf->Des());
       
   610 	TInt seekPos = 0;
       
   611 	aFile.Seek(ESeekStart, seekPos);	
       
   612 	CMessageDigest* digest = NULL;
       
   613 	
       
   614 	switch (aAlgorithm)
       
   615 		{		
       
   616 	case EHashAlgSHA1:
       
   617 		digest = CSHA1::NewL();
       
   618 		break;
       
   619 			
       
   620 	default:
       
   621 		User::Leave(KErrNotSupported);
       
   622 		break;		
       
   623 		}
       
   624 			
       
   625 	while (KErrNone == aFile.Read(bufPtr) && bufPtr.Length() != 0)
       
   626 		{			
       
   627 		digest->Update(bufPtr);		
       
   628 		}
       
   629 			
       
   630 	CleanupStack::PopAndDestroy(buf);			
       
   631 	return digest;				
       
   632 	}
       
   633 		
       
   634 TInt CRestoreController::SetApplicationLanguageL(CApplication& aApplication)
       
   635 	{
       
   636 	
       
   637 	// We set either the current locale if available, or the default
       
   638 	// language.
       
   639 	
       
   640 	TLanguage locale = User::Language();
       
   641 	const CSupportedLanguages& languages = aApplication.ControllerL().SupportedLanguages();
       
   642 	TInt langIndex = 0;
       
   643 	
       
   644 	for (TInt i = 0; i < languages.Count(); i++)
       
   645 		{
       
   646 		
       
   647 		if (locale == languages[i])
       
   648 			{
       
   649 			
       
   650 			langIndex = i;
       
   651 			break;
       
   652 			
       
   653 			}
       
   654 			
       
   655 		}
       
   656 		
       
   657 	aApplication.UserSelections().SetLanguage(languages[langIndex]);
       
   658 	return langIndex;
       
   659 	
       
   660 	}
       
   661 	
       
   662 	
       
   663 CRestoreController::~CRestoreController()
       
   664 	{
       
   665 		
       
   666 	iControllers.ResetAndDestroy();
       
   667 	iVerifiers.ResetAndDestroy();
       
   668 	iControllerBinaries.ResetAndDestroy(); 
       
   669 	iInstallPlans.ResetAndDestroy();
       
   670 	iTopLevelApplications.Reset(); // These pointers owned by the plan
       
   671 	iInstalledFiles.ResetAndDestroy();
       
   672 	iAugmentationDrives.Close();
       
   673 	iMatchingSupportedLanguagesArray.Close();
       
   674 	}
       
   675 		
       
   676 		
       
   677 //
       
   678 // CSisCertificateVerifier
       
   679 //
       
   680 
       
   681 		
       
   682 CRestoreController::CSisCertificateVerifier* CRestoreController::CSisCertificateVerifier::NewL(CController* aController, TDesC8& aControllerBinary, CSecurityManager& aSecurityManager, CApplication* aApplication)
       
   683 	{
       
   684 	
       
   685 	CSisCertificateVerifier* self = CSisCertificateVerifier::NewLC(aController, aControllerBinary, aSecurityManager, aApplication);
       
   686 	CleanupStack::Pop(self);
       
   687 	return self;
       
   688 	
       
   689 	}
       
   690 		
       
   691 CRestoreController::CSisCertificateVerifier* CRestoreController::CSisCertificateVerifier::NewLC(CController* aController, TDesC8& aControllerBinary, CSecurityManager& aSecurityManager, CApplication* aApplication)
       
   692 	{
       
   693 	
       
   694 	CSisCertificateVerifier* self = new (ELeave) CSisCertificateVerifier(aController, aSecurityManager, aApplication,aControllerBinary);
       
   695 	CleanupStack::PushL(self);
       
   696 	return self;
       
   697 		
       
   698 	}
       
   699 		
       
   700 CRestoreController::CSisCertificateVerifier::CSisCertificateVerifier(CController* aController, CSecurityManager& aSecurityManager, CApplication* aApplication, TDesC8& aControllerBinary)
       
   701 	: CActive(CActive::EPriorityStandard),
       
   702 	  iSecurityManager(aSecurityManager),
       
   703 	  iApplication(aApplication),iControllerBinary(aControllerBinary)
       
   704 	{
       
   705 	
       
   706 	iController = aController;
       
   707 	CActiveScheduler::Add(this);
       
   708 	
       
   709 	}
       
   710 		
       
   711 void CRestoreController::CSisCertificateVerifier::StartL(TRequestStatus& aStatus)
       
   712 	{
       
   713 	
       
   714 	iWatcherStatus = &aStatus;
       
   715 	aStatus = KRequestPending;
       
   716 	
       
   717 	TBool isEmbedded = ETrue;
       
   718 	
       
   719 	iSecurityManager.VerifyControllerL(
       
   720 		iControllerBinary, 
       
   721 		*iController,
       
   722 		&iResult,
       
   723 		iValidationResults, 
       
   724 		iCerts,
       
   725 		&iGrantableCapabilitySet,
       
   726 		iAllowUnsigned,
       
   727 		isEmbedded,
       
   728 		iStatus);
       
   729 	
       
   730 	SetActive();
       
   731 	
       
   732 	}
       
   733 		
       
   734 void CRestoreController::CSisCertificateVerifier::RunL()
       
   735 	{
       
   736 	DEBUG_PRINTF2(_L8("Restore - Controller verification complete, verification status was %d"),
       
   737 		iResult);
       
   738 	
       
   739 	TBool verified = EFalse;
       
   740 	switch (iResult)
       
   741 		{
       
   742 		default:
       
   743 			// BC break, unknown validation code, abort
       
   744 			User::Leave(KErrNotSupported);
       
   745 			break;
       
   746 		
       
   747 		case EValidationSucceeded:
       
   748 			// Chain was validated
       
   749 			// Increase the trust status of this install process			
       
   750 			iController->SetTrust(ESisPackageCertificateChainValidatedToTrustAnchor);
       
   751 			iController->TrustStatus().SetValidationStatus(EValidatedToAnchor);
       
   752 			verified = ETrue;
       
   753 			break;				
       
   754 		case ESignatureNotPresent:
       
   755 			// This is a special case because we need to look at the policy 
       
   756 			// setting to determine if unsigned SIS files are allowed at all.
       
   757 			// Display security warning dialog.
       
   758 			iController->SetTrust(ESisPackageUnsignedOrSelfSigned);
       
   759 			iController->TrustStatus().SetValidationStatus(EUnsigned);
       
   760  			if (iAllowUnsigned)
       
   761   				{
       
   762   				verified = ETrue;
       
   763   				}	
       
   764 			break;		
       
   765 		case ESignatureSelfSigned:	
       
   766 			iController->SetTrust(ESisPackageCertificateChainNoTrustAnchor);
       
   767 			iController->TrustStatus().SetValidationStatus(EValidated);
       
   768 			verified = ETrue;
       
   769 			break;					   
       
   770 		case ECertificateValidationError:
       
   771 		case ENoCertificate:
       
   772 		case ENoCodeSigningExtension:
       
   773 		case ENoSupportedPolicyExtension:
       
   774 			// Unable to validate the chain
       
   775 			// We apply the same policy as per unsigned SIS files
       
   776 			iController->SetTrust(ESisPackageValidationFailed);	
       
   777 			iController->TrustStatus().SetValidationStatus(EInvalid);
       
   778 			break;
       
   779 		case ESignatureCouldNotBeValidated:
       
   780 		case EMandatorySignatureMissing:
       
   781 			iController->TrustStatus().SetValidationStatus(EInvalid);
       
   782 			break;
       
   783 		}
       
   784 		
       
   785 	if (verified)
       
   786 		{
       
   787 		TRAPD(err, CheckDeviceIdConstraintsL();CheckCapabilitiesL());
       
   788 		if (err)
       
   789 			{
       
   790 			DEBUG_PRINTF(_L8("Restore - Device ID or Capability Check Failed"));
       
   791 			User::RequestComplete(iWatcherStatus, err);
       
   792 			}		
       
   793 		else
       
   794 			{
       
   795 			User::RequestComplete(iWatcherStatus, KErrNone);
       
   796 			}			
       
   797 		}
       
   798 	else
       
   799 		{
       
   800 		User::RequestComplete(iWatcherStatus, KErrCorrupt);				
       
   801 		}	
       
   802 	}
       
   803 	
       
   804 		
       
   805 void CRestoreController::CSisCertificateVerifier::DoCancel()
       
   806 	{
       
   807 	
       
   808 	iSecurityManager.Cancel();
       
   809 	
       
   810 	}
       
   811 	
       
   812 CRestoreController::CSisCertificateVerifier::~CSisCertificateVerifier()
       
   813 	{
       
   814 	
       
   815 	Cancel();
       
   816 	iValidationResults.ResetAndDestroy();
       
   817 	iCerts.ResetAndDestroy();
       
   818 			
       
   819 	}
       
   820 
       
   821 void CRestoreController::CSisCertificateVerifier::CheckDeviceIdConstraintsL()
       
   822 	{
       
   823 	const CCertChainConstraints* certChainConstraints = iController->CertChainConstraints();
       
   824 
       
   825 	const RPointerArray<HBufC>& deviceIDs=iSecurityManager.DeviceIDsInfo();
       
   826 	SecurityCheckUtil::CheckDeviceIdConstraintsL(certChainConstraints, deviceIDs);
       
   827 	}
       
   828 
       
   829 void CRestoreController::CSisCertificateVerifier::CheckCapabilitiesL()
       
   830 	{	
       
   831 	TCapabilitySet requestedCaps;
       
   832 	requestedCaps.SetEmpty();	
       
   833 	const RPointerArray<CSisRegistryFileDescription>& sidFdList=iApplication->FilesToAdd();
       
   834 	TInt count=sidFdList.Count();
       
   835 	for (TInt i=0; i<count; i++)
       
   836 		{
       
   837 		const HBufC8* rawFileHeaderCaps = sidFdList[i]->CapabilitiesData();
       
   838 		if	(rawFileHeaderCaps)
       
   839 			{
       
   840 			const TInt KCapSetSize=sizeof(TUint32); // size of a capability bit set
       
   841 			const TInt KCapSetSizeBits=8*KCapSetSize;
       
   842 			const TInt KNumCapSets=rawFileHeaderCaps->Size()/KCapSetSize;
       
   843 			for (TInt set=0; set<KNumCapSets; set++)
       
   844 				{
       
   845 				TUint32 capsValue=*(reinterpret_cast<const TUint32*>(rawFileHeaderCaps->Ptr())+set);
       
   846 				for (TInt capIndex=0; capIndex<KCapSetSizeBits; capIndex++)
       
   847 					{
       
   848 					if (capsValue & (0x1<<capIndex))
       
   849 						{
       
   850 						TCapability cap=static_cast<TCapability>(capIndex+set*KCapSetSizeBits);
       
   851 						requestedCaps.AddCapability(cap);
       
   852 						}
       
   853 					}
       
   854 				}		
       
   855 			}
       
   856 		}
       
   857 		
       
   858 	//Get the CertChainConstraint instance built by the SecurityManager.
       
   859 	const CCertChainConstraints* certChainConstraints = iController->CertChainConstraints();
       
   860 
       
   861 	//Get the capbibilies contrained from the CertChainConstraints
       
   862 	TCapabilitySet initCapConstraints=certChainConstraints->ValidCapabilities();
       
   863 	TCapabilitySet supportedCapabilitiesByBoth=initCapConstraints;
       
   864 
       
   865 	//build the capability constraints from the constrained capabilities and root capbilities
       
   866 	supportedCapabilitiesByBoth.Intersection(iGrantableCapabilitySet);
       
   867 
       
   868 	// We have a set of granted capabilities, which is the intersection of iCapabilitySet  and 
       
   869 	// Capbilities constraints(filled in the security manager).
       
   870 	// Let's see if that's enough for the files to be installed.
       
   871 	requestedCaps.Remove(supportedCapabilitiesByBoth);
       
   872 	
       
   873 	// Any capabilities left in requestedCaps after this are not signed for and not in the certs constraints. 
       
   874 	// Check if any of them are system capabilities. If so, bail out.
       
   875 	TCapabilitySet requiredExtraSysCaps(requestedCaps);
       
   876 	SecurityCheckUtil::RemoveUserCaps(requiredExtraSysCaps, iSecurityManager);	
       
   877 	if (SecurityCheckUtil::NotEmpty(requiredExtraSysCaps))
       
   878 		{
       
   879 		DEBUG_PRINTF(_L8("Restore - Controller requires more system capabilities than are signed for"));
       
   880 		User::Leave(KErrSecurityError);
       
   881 		}
       
   882 	else if (SecurityCheckUtil::NotEmpty(requestedCaps)) //Required more user capabilities then
       
   883 		{
       
   884 		// User capabilities are supported by the CertChainConstraints, but not by root certificates.
       
   885 		if (!initCapConstraints.HasCapabilities(requestedCaps))
       
   886 			{
       
   887 			DEBUG_PRINTF(_L8("Restore - Controller requires user capabilities that are not supported by devcert constraints"));
       
   888 			// User capabilities are not all supported by the CertChainConstraints.
       
   889 			User::Leave(KErrSecurityError);					
       
   890 			}
       
   891 		}
       
   892 	}