authorisation/userpromptservice/policies/source/policycache.cpp
changeset 8 35751d3474b7
equal deleted inserted replaced
2:675a964f4eb5 8:35751d3474b7
       
     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