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