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 +