os/security/authorisation/userpromptservice/policies/source/policycache.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2007-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 "policycache.h"
    20 #include "policylist.h"
    21 #include "policyreader.h"
    22 #include "promptrequest.h"
    23 #include "serviceconfig.h"
    24 #include <f32file.h>
    25 #include <ups/upserr.h>
    26 #include "upslog.h"
    27 
    28 using namespace UserPromptService;
    29 
    30 EXPORT_C CPolicyCache* CPolicyCache::NewL(RFs& aFs, const TDesC& aPolicyPath)
    31 /**
    32 Creates a new policy cache.
    33 @param aFs			The file server session used to load policy files.\n
    34 					Ownership is not transferred.
    35 @param aPolicyPath	The path of the policy files (minus the drive). It must be
    36 					in the following form "\private\sid\policies\"
    37 @return				A pointer to the new policy cache object.
    38 */
    39 	{
    40 	CPolicyCache* self = new(ELeave) CPolicyCache(aFs);
    41 	CleanupStack::PushL(self);
    42 	self->ConstructL(aPolicyPath);
    43 	CleanupStack::Pop(self);
    44 	return self;
    45 	}
    46 
    47 CPolicyCache::CPolicyCache(RFs& aFs) 
    48 /**
    49 Constructor
    50 @param aFs	The file server session used to load policy files.
    51 */
    52 	: iFs(aFs)
    53 	{	
    54 	}
    55 
    56 CPolicyCache::~CPolicyCache()
    57 /**
    58 Destructor
    59 */
    60 	{
    61 	iPolicyLists.ResetAndDestroy();
    62 	delete iPolicyPath;
    63 	}
    64 
    65 void CPolicyCache::ConstructL(const TDesC& aPolicyPath)
    66 /**
    67 Second phase constructor, resolves the system drive.
    68 @param aPolicyPath	The directory where the policy files are stored.
    69 */
    70 	{
    71 	iPolicyPath = aPolicyPath.AllocL();
    72 	iSystemDriveChar = iFs.GetSystemDriveChar();
    73 	}
    74 
    75 EXPORT_C const CPolicy* CPolicyCache::MatchL(const CPromptRequest& aRequest)
    76 /**
    77 Finds the first policy that matches the request.
    78 
    79 @param	aRequest	The request data from the system server.
    80 @return				A copy of the policy object to apply to the request. If a policy
    81 					file exists but no policy is defined then a default policy object
    82 					is returned that current request to be accepted or denied.
    83 					
    84 @leave KErrUpsMissingPolicyFile	If no policy file is found for the requested server sid and service id.								
    85 @leave KErrUpsBadPolicyFile		If an error occured whilst parsing a policy file.
    86 */
    87 	{
    88 	CPolicyList::TId id(aRequest.ServerSid(), aRequest.ServiceId());		
    89 	const CPolicyList* list = PolicyList(id);
    90 	
    91 	if (!list)
    92 		{
    93 		// Policy list not found so try and load it. This
    94 		// leaves if a UPS policy file is not found.
    95 		list = LoadPolicyListL(id);				
    96 		}
    97 		
    98 	ASSERT(list);	
    99 	return list->Match(aRequest);
   100 	}
   101 
   102 const CPolicyList* CPolicyCache::PolicyList(const CPolicyList::TId& aId) const
   103 /**
   104 Gets the specified policy list if it is loaded.
   105 @param	The ID of the policy list.
   106 @return A pointer to the policy list if it is loaded; otherwise, is returned.
   107 */
   108 	{
   109 	TInt count = iPolicyLists.Count();
   110 	for (TInt i = 0; i < count; ++i) // Check if policy list is in the cache
   111 		{
   112 		if (iPolicyLists[i]->Id() == aId)
   113 			{
   114 			return iPolicyLists[i];			
   115 			}
   116 		}
   117 	return 0;
   118 	}
   119 
   120 CPolicyList* CPolicyCache::LoadPolicyListL(const CPolicyList::TId& aId)
   121 /**
   122 Loads a list of policies from the policy file for the specified system server and service.
   123 @param	aId	A tuple of the system server SID and service UID that identifies a policy file.
   124 
   125 @return		The list of policies, or N
   126 @leave		KErrUpsBadPolicyFile if an error occured whilst parsing a policy file.
   127 			KErrUpsMissingPolicyFile if the policy file was not found on the Z or the system drive.
   128 */
   129 	{
   130 	RBuf fn;
   131 	fn.CreateL(KMaxFileName);
   132 	CleanupClosePushL(fn);
   133 	
   134 	LocatePolicyFileL(fn, aId);		
   135 	
   136 	CPolicyList* l(0);
   137 	TRAPD(err, l = ParseListL(aId, fn));			
   138 	if (err != KErrNone && err != KErrNoMemory)
   139 		{
   140 		DEBUG_PRINTF2(_L("Unable to parse %S"), &fn);
   141 		err = KErrUpsBadPolicyFile;
   142 		
   143 		if (fn[0] == 'Z')
   144 			{			
   145 			DEBUG_PRINTF2(_L("Unable to parse %S"), &fn);
   146 			User::Panic(KUpsPoliciesPanicCat, EUpsPoliciesCorruptRomPolicy);			
   147 			}
   148 		else {
   149 			// If we failed to read the policy file from the system 
   150 			// drive then try the Z drive.
   151 			fn[0] = 'Z';
   152 			TRAP(err, l = ParseListL(aId, fn));
   153 			if (err == KErrNone)
   154 				{
   155 				DEBUG_PRINTF2(_L("Ignoring corrupt policy file on system drive. Loading %S"), &fn);
   156 				}
   157 			else if (err != KErrNotFound && err != KErrNoMemory)
   158 				{
   159 				DEBUG_PRINTF2(_L("Unable to parse %S"), &fn);
   160 				User::Panic(KUpsPoliciesPanicCat, EUpsPoliciesCorruptRomPolicy);
   161 				}			
   162 			}
   163 		}
   164 	User::LeaveIfError(err);
   165 	
   166 	CleanupStack::PushL(l);
   167 	iPolicyLists.AppendL(l);
   168 	CleanupStack::Pop(l);		
   169 	CleanupStack::PopAndDestroy(&fn);
   170 	return l;
   171 	}
   172 
   173 void CPolicyCache::LocatePolicyFileL(TDes& aPolicyFileName, const CPolicyList::TId& aId)
   174 /**
   175 Determines whether the policy file should be loaded from the Z drive 
   176 or the system drive and returns the filename.
   177 
   178 @param aPolicyFileName	Descriptor to populate with the filename.
   179 @param aId				The id of the policy file to load.
   180 						
   181 @leave KErrUpsMissingPolicyFile The policy file was not found on either the Z drive
   182 								or the system drive.
   183 */	
   184 	{
   185 	_LIT(KDriveSpec, "!:");
   186 		
   187 	aPolicyFileName.Zero();
   188 	aPolicyFileName.Append(KDriveSpec);
   189 	aPolicyFileName.Append(*iPolicyPath);
   190 	aId.AppendNameToPath(aPolicyFileName);
   191 	
   192 	// System drive eclipses Z drive	
   193 	aPolicyFileName[0] = iSystemDriveChar;
   194 	if (! FileExistsL(aPolicyFileName))
   195 		{
   196 		aPolicyFileName[0] = 'Z';
   197 		if (! FileExistsL(aPolicyFileName))
   198 			{
   199 			DEBUG_PRINTF3(_L8("No policy file for system server sid = 0x%08x, service id = 0x%08x"),
   200 				aId.iServerSid.iId, aId.iServiceId.iUid);
   201 			User::Leave(KErrUpsMissingPolicyFile);	
   202 			}
   203 		}
   204 	}
   205 
   206 CPolicyList* CPolicyCache::ParseListL(const CPolicyList::TId& aId, const TDesC& aPolicyFileName)
   207 /**
   208 Parses a policy file and constructs a policy list object.
   209 
   210 @param	aId				The policy file id that will be used to locate the policy list within
   211 						the policy cache.
   212 @param	aPolicyFileName	The absolute path of the policy file to parse.
   213 @return The new policy list object.
   214 */
   215 	{
   216 	CPolicyReader* r = CPolicyReader::NewLC(iFs, aPolicyFileName);
   217 	CPolicyList* l = CPolicyList::NewL(aId, *r);	
   218 	CleanupStack::PopAndDestroy(r);
   219 	return l;
   220 	}
   221 
   222 EXPORT_C void CPolicyCache::ServiceConfigL(const TSecureId& aServerSid, RArray<TServiceConfig>& aConfigs)
   223 /**
   224 Loads the service configuration data from the policy files for every service provided
   225 by a given system server.
   226 @param	aServerSid	The secure id of the system server.
   227 @param	aConfigs	The RArray to populate with the configuration data.
   228 */
   229 	{				
   230 	RArray<TUint> services;
   231 	CleanupClosePushL(services);
   232 	
   233 	DEBUG_PRINTF2(_L8("Loading service configuration for system server 0x%08x"), aServerSid.iId);
   234 	
   235 	FindServicesL(aServerSid, services);
   236 	TInt numServices = services.Count();
   237 	
   238 	// Load the services
   239 	for (TInt i = 0; i < numServices; ++i)
   240 		{
   241 		CPolicyList::TId id(aServerSid, TUid::Uid(services[i]));		
   242 		const CPolicyList* list = PolicyList(id);
   243 		if (list)
   244 			{
   245 			// Use in-memory service configuration
   246 			aConfigs.AppendL(list->ServiceConfig());
   247 			}
   248 		else 
   249 			{
   250 			// Load policy file into cache
   251 			CPolicyList* loadedList = LoadPolicyListL(id);
   252 			aConfigs.AppendL(loadedList->ServiceConfig());
   253 			}
   254 		}						
   255 	CleanupStack::PopAndDestroy(&services);
   256 	}
   257 
   258 void CPolicyCache::FindServicesL(const TSecureId& aServerSid, RArray<TUint>& aServices)
   259 /**
   260 Finds all of the policy files on Z drive and C drive for this system server		
   261 A wildcard string is used to filter out policy files for other system servers.
   262 
   263 @param aServerSid	The secure id of the system server.
   264 @param aServices	The array of service ids to populate.
   265 */
   266 	{
   267 	_LIT(KFilenameTemplate, "ups_%08x_????????.rsc");
   268 	TBuf<32> pattern;
   269 	pattern.AppendFormat(KFilenameTemplate, aServerSid.iId);
   270 		
   271 	RBuf fn;	// Store current file/directory name.
   272 	fn.CreateL(KMaxFileName);
   273 	CleanupClosePushL(fn);	
   274 	for (TInt i = 0; i < 2; ++i)	
   275 		{
   276 		TUint driveChar = (i == 0) ? TChar('Z') : iSystemDriveChar;
   277 		
   278 		fn.Zero();
   279 		_LIT(KDirFormat, "%c:%S");
   280 		fn.AppendFormat(KDirFormat, driveChar, &*iPolicyPath);
   281 		
   282 		CDir* dir(0);	
   283 		TInt err = iFs.GetDir(fn, KEntryAttNormal, ESortNone, dir);
   284 		if (err == KErrPathNotFound) 
   285 			{
   286 			continue;
   287 			}
   288 		User::LeaveIfError(err);
   289 		CleanupStack::PushL(dir);
   290 		
   291 		// Find the services
   292 		TInt count = dir->Count();
   293 		for (TInt j = 0; j < count; ++j)
   294 			{
   295 			const TEntry& e((*dir)[j]);
   296 			if (e.iName.MatchF(pattern) >= 0)
   297 				{
   298 				fn.Zero();
   299 				_LIT(KFileFormat, "%C:%S%S");
   300 				fn.AppendFormat(KFileFormat, driveChar, iPolicyPath, &e.iName);
   301 								
   302 				CPolicyList::TId policyListId;
   303 				TRAP(err, CPolicyList::TId::IdL(fn, policyListId))
   304 				if (err == KErrNoMemory)
   305 					{
   306 					// Do not let OOM cause us to ignore policy files
   307 					User::Leave(err);
   308 					}
   309 				if (err == KErrNone)
   310 					{
   311 					// Ensure there are no duplicate service configs due to eclisped policy files.
   312 					err = aServices.InsertInOrder(static_cast<TUint>(policyListId.iServiceId.iUid));
   313 					if (err != KErrAlreadyExists)
   314 						{
   315 						User::LeaveIfError(err);
   316 						}
   317 					}
   318 				else
   319 					{
   320 					DEBUG_PRINTF2(_L("%S does not match UPS policy filename rules"), &fn);
   321 					}
   322 				}
   323 			// Policy file is for a different system server
   324 			}		
   325 		CleanupStack::PopAndDestroy(dir);
   326 		}	
   327 	CleanupStack::PopAndDestroy(&fn);
   328 	}
   329 
   330 TBool CPolicyCache::FileExistsL(const TDesC& aFileName)
   331 /**
   332 Checks whether a file exists.
   333 - If the FileName corresponds to a directory then EFalse is returned.
   334 
   335 @param	aFileName	The absolute path of the file to check.
   336 @return ETrue, if aFileName exists; otherwise, EFalse is returned.
   337 */
   338 	{
   339 	TBool exists = EFalse;
   340 	TEntry* e = new(ELeave) TEntry();		
   341 	TInt err = iFs.Entry(aFileName, *e);
   342 	if (err == KErrNone && ! e->IsDir())
   343 		{
   344 		exists = ETrue;			
   345 		}
   346 	delete e;
   347 	return exists;
   348 	}
   349