os/security/authorisation/userpromptservice/policies/source/policycache.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/security/authorisation/userpromptservice/policies/source/policycache.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,349 @@
     1.4 +/*
     1.5 +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of the License "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +*
    1.19 +*/
    1.20 +
    1.21 +
    1.22 +#include "policycache.h"
    1.23 +#include "policylist.h"
    1.24 +#include "policyreader.h"
    1.25 +#include "promptrequest.h"
    1.26 +#include "serviceconfig.h"
    1.27 +#include <f32file.h>
    1.28 +#include <ups/upserr.h>
    1.29 +#include "upslog.h"
    1.30 +
    1.31 +using namespace UserPromptService;
    1.32 +
    1.33 +EXPORT_C CPolicyCache* CPolicyCache::NewL(RFs& aFs, const TDesC& aPolicyPath)
    1.34 +/**
    1.35 +Creates a new policy cache.
    1.36 +@param aFs			The file server session used to load policy files.\n
    1.37 +					Ownership is not transferred.
    1.38 +@param aPolicyPath	The path of the policy files (minus the drive). It must be
    1.39 +					in the following form "\private\sid\policies\"
    1.40 +@return				A pointer to the new policy cache object.
    1.41 +*/
    1.42 +	{
    1.43 +	CPolicyCache* self = new(ELeave) CPolicyCache(aFs);
    1.44 +	CleanupStack::PushL(self);
    1.45 +	self->ConstructL(aPolicyPath);
    1.46 +	CleanupStack::Pop(self);
    1.47 +	return self;
    1.48 +	}
    1.49 +
    1.50 +CPolicyCache::CPolicyCache(RFs& aFs) 
    1.51 +/**
    1.52 +Constructor
    1.53 +@param aFs	The file server session used to load policy files.
    1.54 +*/
    1.55 +	: iFs(aFs)
    1.56 +	{	
    1.57 +	}
    1.58 +
    1.59 +CPolicyCache::~CPolicyCache()
    1.60 +/**
    1.61 +Destructor
    1.62 +*/
    1.63 +	{
    1.64 +	iPolicyLists.ResetAndDestroy();
    1.65 +	delete iPolicyPath;
    1.66 +	}
    1.67 +
    1.68 +void CPolicyCache::ConstructL(const TDesC& aPolicyPath)
    1.69 +/**
    1.70 +Second phase constructor, resolves the system drive.
    1.71 +@param aPolicyPath	The directory where the policy files are stored.
    1.72 +*/
    1.73 +	{
    1.74 +	iPolicyPath = aPolicyPath.AllocL();
    1.75 +	iSystemDriveChar = iFs.GetSystemDriveChar();
    1.76 +	}
    1.77 +
    1.78 +EXPORT_C const CPolicy* CPolicyCache::MatchL(const CPromptRequest& aRequest)
    1.79 +/**
    1.80 +Finds the first policy that matches the request.
    1.81 +
    1.82 +@param	aRequest	The request data from the system server.
    1.83 +@return				A copy of the policy object to apply to the request. If a policy
    1.84 +					file exists but no policy is defined then a default policy object
    1.85 +					is returned that current request to be accepted or denied.
    1.86 +					
    1.87 +@leave KErrUpsMissingPolicyFile	If no policy file is found for the requested server sid and service id.								
    1.88 +@leave KErrUpsBadPolicyFile		If an error occured whilst parsing a policy file.
    1.89 +*/
    1.90 +	{
    1.91 +	CPolicyList::TId id(aRequest.ServerSid(), aRequest.ServiceId());		
    1.92 +	const CPolicyList* list = PolicyList(id);
    1.93 +	
    1.94 +	if (!list)
    1.95 +		{
    1.96 +		// Policy list not found so try and load it. This
    1.97 +		// leaves if a UPS policy file is not found.
    1.98 +		list = LoadPolicyListL(id);				
    1.99 +		}
   1.100 +		
   1.101 +	ASSERT(list);	
   1.102 +	return list->Match(aRequest);
   1.103 +	}
   1.104 +
   1.105 +const CPolicyList* CPolicyCache::PolicyList(const CPolicyList::TId& aId) const
   1.106 +/**
   1.107 +Gets the specified policy list if it is loaded.
   1.108 +@param	The ID of the policy list.
   1.109 +@return A pointer to the policy list if it is loaded; otherwise, is returned.
   1.110 +*/
   1.111 +	{
   1.112 +	TInt count = iPolicyLists.Count();
   1.113 +	for (TInt i = 0; i < count; ++i) // Check if policy list is in the cache
   1.114 +		{
   1.115 +		if (iPolicyLists[i]->Id() == aId)
   1.116 +			{
   1.117 +			return iPolicyLists[i];			
   1.118 +			}
   1.119 +		}
   1.120 +	return 0;
   1.121 +	}
   1.122 +
   1.123 +CPolicyList* CPolicyCache::LoadPolicyListL(const CPolicyList::TId& aId)
   1.124 +/**
   1.125 +Loads a list of policies from the policy file for the specified system server and service.
   1.126 +@param	aId	A tuple of the system server SID and service UID that identifies a policy file.
   1.127 +
   1.128 +@return		The list of policies, or N
   1.129 +@leave		KErrUpsBadPolicyFile if an error occured whilst parsing a policy file.
   1.130 +			KErrUpsMissingPolicyFile if the policy file was not found on the Z or the system drive.
   1.131 +*/
   1.132 +	{
   1.133 +	RBuf fn;
   1.134 +	fn.CreateL(KMaxFileName);
   1.135 +	CleanupClosePushL(fn);
   1.136 +	
   1.137 +	LocatePolicyFileL(fn, aId);		
   1.138 +	
   1.139 +	CPolicyList* l(0);
   1.140 +	TRAPD(err, l = ParseListL(aId, fn));			
   1.141 +	if (err != KErrNone && err != KErrNoMemory)
   1.142 +		{
   1.143 +		DEBUG_PRINTF2(_L("Unable to parse %S"), &fn);
   1.144 +		err = KErrUpsBadPolicyFile;
   1.145 +		
   1.146 +		if (fn[0] == 'Z')
   1.147 +			{			
   1.148 +			DEBUG_PRINTF2(_L("Unable to parse %S"), &fn);
   1.149 +			User::Panic(KUpsPoliciesPanicCat, EUpsPoliciesCorruptRomPolicy);			
   1.150 +			}
   1.151 +		else {
   1.152 +			// If we failed to read the policy file from the system 
   1.153 +			// drive then try the Z drive.
   1.154 +			fn[0] = 'Z';
   1.155 +			TRAP(err, l = ParseListL(aId, fn));
   1.156 +			if (err == KErrNone)
   1.157 +				{
   1.158 +				DEBUG_PRINTF2(_L("Ignoring corrupt policy file on system drive. Loading %S"), &fn);
   1.159 +				}
   1.160 +			else if (err != KErrNotFound && err != KErrNoMemory)
   1.161 +				{
   1.162 +				DEBUG_PRINTF2(_L("Unable to parse %S"), &fn);
   1.163 +				User::Panic(KUpsPoliciesPanicCat, EUpsPoliciesCorruptRomPolicy);
   1.164 +				}			
   1.165 +			}
   1.166 +		}
   1.167 +	User::LeaveIfError(err);
   1.168 +	
   1.169 +	CleanupStack::PushL(l);
   1.170 +	iPolicyLists.AppendL(l);
   1.171 +	CleanupStack::Pop(l);		
   1.172 +	CleanupStack::PopAndDestroy(&fn);
   1.173 +	return l;
   1.174 +	}
   1.175 +
   1.176 +void CPolicyCache::LocatePolicyFileL(TDes& aPolicyFileName, const CPolicyList::TId& aId)
   1.177 +/**
   1.178 +Determines whether the policy file should be loaded from the Z drive 
   1.179 +or the system drive and returns the filename.
   1.180 +
   1.181 +@param aPolicyFileName	Descriptor to populate with the filename.
   1.182 +@param aId				The id of the policy file to load.
   1.183 +						
   1.184 +@leave KErrUpsMissingPolicyFile The policy file was not found on either the Z drive
   1.185 +								or the system drive.
   1.186 +*/	
   1.187 +	{
   1.188 +	_LIT(KDriveSpec, "!:");
   1.189 +		
   1.190 +	aPolicyFileName.Zero();
   1.191 +	aPolicyFileName.Append(KDriveSpec);
   1.192 +	aPolicyFileName.Append(*iPolicyPath);
   1.193 +	aId.AppendNameToPath(aPolicyFileName);
   1.194 +	
   1.195 +	// System drive eclipses Z drive	
   1.196 +	aPolicyFileName[0] = iSystemDriveChar;
   1.197 +	if (! FileExistsL(aPolicyFileName))
   1.198 +		{
   1.199 +		aPolicyFileName[0] = 'Z';
   1.200 +		if (! FileExistsL(aPolicyFileName))
   1.201 +			{
   1.202 +			DEBUG_PRINTF3(_L8("No policy file for system server sid = 0x%08x, service id = 0x%08x"),
   1.203 +				aId.iServerSid.iId, aId.iServiceId.iUid);
   1.204 +			User::Leave(KErrUpsMissingPolicyFile);	
   1.205 +			}
   1.206 +		}
   1.207 +	}
   1.208 +
   1.209 +CPolicyList* CPolicyCache::ParseListL(const CPolicyList::TId& aId, const TDesC& aPolicyFileName)
   1.210 +/**
   1.211 +Parses a policy file and constructs a policy list object.
   1.212 +
   1.213 +@param	aId				The policy file id that will be used to locate the policy list within
   1.214 +						the policy cache.
   1.215 +@param	aPolicyFileName	The absolute path of the policy file to parse.
   1.216 +@return The new policy list object.
   1.217 +*/
   1.218 +	{
   1.219 +	CPolicyReader* r = CPolicyReader::NewLC(iFs, aPolicyFileName);
   1.220 +	CPolicyList* l = CPolicyList::NewL(aId, *r);	
   1.221 +	CleanupStack::PopAndDestroy(r);
   1.222 +	return l;
   1.223 +	}
   1.224 +
   1.225 +EXPORT_C void CPolicyCache::ServiceConfigL(const TSecureId& aServerSid, RArray<TServiceConfig>& aConfigs)
   1.226 +/**
   1.227 +Loads the service configuration data from the policy files for every service provided
   1.228 +by a given system server.
   1.229 +@param	aServerSid	The secure id of the system server.
   1.230 +@param	aConfigs	The RArray to populate with the configuration data.
   1.231 +*/
   1.232 +	{				
   1.233 +	RArray<TUint> services;
   1.234 +	CleanupClosePushL(services);
   1.235 +	
   1.236 +	DEBUG_PRINTF2(_L8("Loading service configuration for system server 0x%08x"), aServerSid.iId);
   1.237 +	
   1.238 +	FindServicesL(aServerSid, services);
   1.239 +	TInt numServices = services.Count();
   1.240 +	
   1.241 +	// Load the services
   1.242 +	for (TInt i = 0; i < numServices; ++i)
   1.243 +		{
   1.244 +		CPolicyList::TId id(aServerSid, TUid::Uid(services[i]));		
   1.245 +		const CPolicyList* list = PolicyList(id);
   1.246 +		if (list)
   1.247 +			{
   1.248 +			// Use in-memory service configuration
   1.249 +			aConfigs.AppendL(list->ServiceConfig());
   1.250 +			}
   1.251 +		else 
   1.252 +			{
   1.253 +			// Load policy file into cache
   1.254 +			CPolicyList* loadedList = LoadPolicyListL(id);
   1.255 +			aConfigs.AppendL(loadedList->ServiceConfig());
   1.256 +			}
   1.257 +		}						
   1.258 +	CleanupStack::PopAndDestroy(&services);
   1.259 +	}
   1.260 +
   1.261 +void CPolicyCache::FindServicesL(const TSecureId& aServerSid, RArray<TUint>& aServices)
   1.262 +/**
   1.263 +Finds all of the policy files on Z drive and C drive for this system server		
   1.264 +A wildcard string is used to filter out policy files for other system servers.
   1.265 +
   1.266 +@param aServerSid	The secure id of the system server.
   1.267 +@param aServices	The array of service ids to populate.
   1.268 +*/
   1.269 +	{
   1.270 +	_LIT(KFilenameTemplate, "ups_%08x_????????.rsc");
   1.271 +	TBuf<32> pattern;
   1.272 +	pattern.AppendFormat(KFilenameTemplate, aServerSid.iId);
   1.273 +		
   1.274 +	RBuf fn;	// Store current file/directory name.
   1.275 +	fn.CreateL(KMaxFileName);
   1.276 +	CleanupClosePushL(fn);	
   1.277 +	for (TInt i = 0; i < 2; ++i)	
   1.278 +		{
   1.279 +		TUint driveChar = (i == 0) ? TChar('Z') : iSystemDriveChar;
   1.280 +		
   1.281 +		fn.Zero();
   1.282 +		_LIT(KDirFormat, "%c:%S");
   1.283 +		fn.AppendFormat(KDirFormat, driveChar, &*iPolicyPath);
   1.284 +		
   1.285 +		CDir* dir(0);	
   1.286 +		TInt err = iFs.GetDir(fn, KEntryAttNormal, ESortNone, dir);
   1.287 +		if (err == KErrPathNotFound) 
   1.288 +			{
   1.289 +			continue;
   1.290 +			}
   1.291 +		User::LeaveIfError(err);
   1.292 +		CleanupStack::PushL(dir);
   1.293 +		
   1.294 +		// Find the services
   1.295 +		TInt count = dir->Count();
   1.296 +		for (TInt j = 0; j < count; ++j)
   1.297 +			{
   1.298 +			const TEntry& e((*dir)[j]);
   1.299 +			if (e.iName.MatchF(pattern) >= 0)
   1.300 +				{
   1.301 +				fn.Zero();
   1.302 +				_LIT(KFileFormat, "%C:%S%S");
   1.303 +				fn.AppendFormat(KFileFormat, driveChar, iPolicyPath, &e.iName);
   1.304 +								
   1.305 +				CPolicyList::TId policyListId;
   1.306 +				TRAP(err, CPolicyList::TId::IdL(fn, policyListId))
   1.307 +				if (err == KErrNoMemory)
   1.308 +					{
   1.309 +					// Do not let OOM cause us to ignore policy files
   1.310 +					User::Leave(err);
   1.311 +					}
   1.312 +				if (err == KErrNone)
   1.313 +					{
   1.314 +					// Ensure there are no duplicate service configs due to eclisped policy files.
   1.315 +					err = aServices.InsertInOrder(static_cast<TUint>(policyListId.iServiceId.iUid));
   1.316 +					if (err != KErrAlreadyExists)
   1.317 +						{
   1.318 +						User::LeaveIfError(err);
   1.319 +						}
   1.320 +					}
   1.321 +				else
   1.322 +					{
   1.323 +					DEBUG_PRINTF2(_L("%S does not match UPS policy filename rules"), &fn);
   1.324 +					}
   1.325 +				}
   1.326 +			// Policy file is for a different system server
   1.327 +			}		
   1.328 +		CleanupStack::PopAndDestroy(dir);
   1.329 +		}	
   1.330 +	CleanupStack::PopAndDestroy(&fn);
   1.331 +	}
   1.332 +
   1.333 +TBool CPolicyCache::FileExistsL(const TDesC& aFileName)
   1.334 +/**
   1.335 +Checks whether a file exists.
   1.336 +- If the FileName corresponds to a directory then EFalse is returned.
   1.337 +
   1.338 +@param	aFileName	The absolute path of the file to check.
   1.339 +@return ETrue, if aFileName exists; otherwise, EFalse is returned.
   1.340 +*/
   1.341 +	{
   1.342 +	TBool exists = EFalse;
   1.343 +	TEntry* e = new(ELeave) TEntry();		
   1.344 +	TInt err = iFs.Entry(aFileName, *e);
   1.345 +	if (err == KErrNone && ! e->IsDir())
   1.346 +		{
   1.347 +		exists = ETrue;			
   1.348 +		}
   1.349 +	delete e;
   1.350 +	return exists;
   1.351 +	}
   1.352 +