os/security/authorisation/userpromptservice/server/source/upsclient/rupssession.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/authorisation/userpromptservice/server/source/upsclient/rupssession.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,340 @@
1.4 +/*
1.5 +* Copyright (c) 2007-2010 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 +* RUpsSession implementation. See class and function definitions
1.19 +* for more detail.
1.20 +*
1.21 +*/
1.22 +
1.23 +
1.24 +/**
1.25 + @file
1.26 +*/
1.27 +
1.28 +
1.29 +#include <ups/upsclient.h>
1.30 +#include <e32property.h>
1.31 +#include <e32debug.h>
1.32 +#include "upscommon.h"
1.33 +#include "upsclientconfig.h"
1.34 +
1.35 +namespace UserPromptService
1.36 + {
1.37 +
1.38 +NONSHARABLE_CLASS(CPolicyChangeWatcher) : public CActive
1.39 + {
1.40 +public:
1.41 + static CPolicyChangeWatcher *NewL(RUpsSession &aUpsSession);
1.42 + ~CPolicyChangeWatcher();
1.43 +private:
1.44 + CPolicyChangeWatcher(RUpsSession &aUpsSession);
1.45 + void ConstructL();
1.46 + virtual void DoCancel();
1.47 + virtual void RunL();
1.48 + virtual TInt RunError(TInt aError);
1.49 +
1.50 +private:
1.51 + RProperty iUpsPolicyChangeProperty;
1.52 + RUpsSession &iUpsSession;
1.53 + };
1.54 +
1.55 +EXPORT_C RUpsSession::RUpsSession()
1.56 +/**
1.57 + This constructor provides a single point of definition from
1.58 + which the superclass constructor is called.
1.59 + */
1.60 +: RScsClientBase(),
1.61 + iPolicyChangeWatcher(0),
1.62 + iClientConfig(0)
1.63 + {
1.64 + // empty.
1.65 + }
1.66 +
1.67 +EXPORT_C TInt RUpsSession::Connect()
1.68 +/**
1.69 + Connect to the UPS server.
1.70 +
1.71 + The thread which calls this function must be the same one which later calls Close().
1.72 +
1.73 + Once connected, this session can be shared by multiple RUpsSubsession objects.
1.74 +
1.75 + The RUpsSubsession objects are allowed to be in different threads, in which case ShareAuto() must be called before they are created.
1.76 +
1.77 + @return Symbian OS error code where KErrNone indicates
1.78 + success and any other value indicates failure.
1.79 + */
1.80 + {
1.81 + TVersion v = UserPromptService::Version();
1.82 + TUidType serverFullUid = UserPromptService::ServerImageFullUid();
1.83 +
1.84 + TInt r = RScsClientBase::Connect(
1.85 + UserPromptService::KUpsServerName, v, UserPromptService::KServerImageName, serverFullUid);
1.86 +
1.87 + if (r == KErrNone)
1.88 + {
1.89 + // preload the configuration
1.90 + TRAP(r, RetrieveClientConfigL());
1.91 + }
1.92 +
1.93 + if((r == KErrNone) && (CActiveScheduler::Current() != 0))
1.94 + {
1.95 + delete iPolicyChangeWatcher;
1.96 + iPolicyChangeWatcher = 0;
1.97 + TRAP(r, iPolicyChangeWatcher = CPolicyChangeWatcher::NewL(*this));
1.98 + }
1.99 +
1.100 + if(r != KErrNone)
1.101 + {
1.102 + Close();
1.103 + }
1.104 +
1.105 + return r;
1.106 + }
1.107 +
1.108 +
1.109 +static void deleteArrayOfTServiceConfig(TAny *aPtr)
1.110 + {
1.111 + TServiceConfig *array = reinterpret_cast<TServiceConfig *>(aPtr);
1.112 + delete [] array;
1.113 + }
1.114 +
1.115 +void RUpsSession::RetrieveClientConfigL()
1.116 + {
1.117 + // Query how many TServiceConfig entries there are.
1.118 + TPckgBuf<TInt> countBuf;
1.119 + User::LeaveIfError(CallSessionFunction(EGetClientConfigLength, TIpcArgs(&countBuf)));
1.120 + // Retrieve count from buffer
1.121 + TInt count = countBuf();
1.122 +
1.123 + // Create buffer to hold entries
1.124 + TServiceConfig *rawServiceConfig = new(ELeave) TServiceConfig[count];
1.125 + CleanupStack::PushL(TCleanupItem(deleteArrayOfTServiceConfig, rawServiceConfig));
1.126 +
1.127 + // Wrap array in a TPtr8 and use it to read array from server
1.128 + TInt size = count * sizeof(TServiceConfig);
1.129 + TPtr8 ptr((TUint8*)rawServiceConfig, size, size);
1.130 + User::LeaveIfError(CallSessionFunction(EGetClientConfigData, TIpcArgs(&ptr)));
1.131 +
1.132 + CUpsClientConfig *tmp = CUpsClientConfig::NewL(count, rawServiceConfig);
1.133 + delete iClientConfig;
1.134 + iClientConfig = tmp;
1.135 +
1.136 + CleanupStack::PopAndDestroy(); // get rid of rawServiceConfig array
1.137 + }
1.138 +
1.139 +
1.140 +EXPORT_C void RUpsSession::Close()
1.141 +/**
1.142 +Frees the configuration object and calls RScsClientBase::Close
1.143 +
1.144 +This function MUST be called by the same thread which Connect().
1.145 +*/
1.146 + {
1.147 + delete iClientConfig;
1.148 + iClientConfig = 0;
1.149 +
1.150 + if(iPolicyChangeWatcher)
1.151 + {
1.152 + iPolicyChangeWatcher->Cancel();
1.153 + }
1.154 + delete iPolicyChangeWatcher;
1.155 + iPolicyChangeWatcher = 0;
1.156 +
1.157 + RScsClientBase::Close();
1.158 + }
1.159 +
1.160 +void RUpsSession::NotifyPolicyFileChangedL()
1.161 +/**
1.162 + @internalComponent
1.163 + @released
1.164 +
1.165 + Policy files have changed so update serviceconfig cache.
1.166 +*/
1.167 + {
1.168 + RetrieveClientConfigL();
1.169 + }
1.170 +
1.171 +CUpsClientConfig::CUpsClientConfig()
1.172 + : iServiceConfig(1 /* granularity */, 0 /* key offset */)
1.173 + {
1.174 + }
1.175 +
1.176 +CUpsClientConfig::~CUpsClientConfig()
1.177 + {
1.178 + iServiceConfig.Close();
1.179 + }
1.180 +
1.181 +CUpsClientConfig* CUpsClientConfig::NewL(TInt aCount, TServiceConfig *aRawServiceConfig)
1.182 + /**
1.183 + @param serviceConfig
1.184 +
1.185 + Takes ownership of the serviceConfig array via swap. Callers array will be cleared.
1.186 + */
1.187 + {
1.188 + CUpsClientConfig *self = new(ELeave) CUpsClientConfig();
1.189 + CleanupStack::PushL(self);
1.190 + self->ConstructL(aCount, aRawServiceConfig);
1.191 + CleanupStack::Pop(self);
1.192 + return self;
1.193 + }
1.194 +
1.195 +
1.196 +void CUpsClientConfig::ConstructL(TInt aCount, TServiceConfig *aRawServiceConfig)
1.197 + {
1.198 + iServiceConfig.ReserveL(aCount);
1.199 + for(TInt i=0; i < aCount; ++i)
1.200 + {
1.201 + iServiceConfig.InsertInUnsignedKeyOrderL(aRawServiceConfig[i]);
1.202 + }
1.203 + }
1.204 +
1.205 +CUpsClientConfig::TQueryUpsResult
1.206 +CUpsClientConfig::QueryUps(TBool aServerChecksPassed,
1.207 + const TServiceId &aServiceId,
1.208 + const TSecureId &aClientSid,
1.209 + const TProcessId &aClientProcessId) const
1.210 + {
1.211 + TServiceConfig sc = {0};
1.212 + sc.iServiceId = aServiceId.iUid; /* Only service id is used in lookup */
1.213 + TInt i = iServiceConfig.FindInUnsignedKeyOrder(sc);
1.214 + if(i == KErrNotFound)
1.215 + {
1.216 + // Must be no policy file for this service so no point in querying UPS
1.217 + return aServerChecksPassed ? EAllow: EReject;
1.218 + }
1.219 +
1.220 +
1.221 + // Read entry
1.222 + sc = iServiceConfig[i];
1.223 +
1.224 + switch(sc.iPolicy)
1.225 + {
1.226 + case EAlwaysCheck:
1.227 + return EQueryUps;
1.228 +
1.229 + case ECheckPostManufacture:
1.230 + {
1.231 + TBool isProtected = (TUint(aClientSid) & 0x80000000) == 0;
1.232 + if(! isProtected)
1.233 + {
1.234 + return EQueryUps;
1.235 + }
1.236 +
1.237 + // Need to obtain the drive letter for the exe
1.238 + //
1.239 + // This requires opening the RProcess and two copies of a full filename (one 8 bit the other unicode)......
1.240 + // We could optimse this by doing it when Initialise() is called, but that then slows down all Initialise calls even ones
1.241 + // not doing the ECheckPostManufacture check.
1.242 + RProcess clientProcess;
1.243 + if(clientProcess.Open(aClientProcessId) != KErrNone)
1.244 + {
1.245 + return EReject; // Presumably it exited...
1.246 + }
1.247 +
1.248 + TFileName clientExeName = clientProcess.FileName();
1.249 + clientProcess.Close();
1.250 + TChar driveChar= clientExeName[0];
1.251 +
1.252 + if(aServerChecksPassed &&
1.253 + (driveChar == 'z' || driveChar == 'Z'))
1.254 + {
1.255 + return EAllow;
1.256 + }
1.257 +
1.258 + return EQueryUps;
1.259 + }
1.260 +
1.261 + case ECheckUnprotectedSids:
1.262 + {
1.263 + TBool isProtected = (TUint(aClientSid) & 0x80000000) == 0;
1.264 +
1.265 + if(aServerChecksPassed && isProtected)
1.266 + {
1.267 + return EAllow;
1.268 + }
1.269 +
1.270 + return EQueryUps;
1.271 + }
1.272 +
1.273 + case ECheckIfFailed:
1.274 + return aServerChecksPassed ? EAllow : EQueryUps;
1.275 +
1.276 + BULLSEYE_OFF
1.277 + default:
1.278 + BULLSEYE_RESTORE
1.279 + case ENeverCheck:
1.280 + return aServerChecksPassed ? EAllow: EReject;
1.281 + }
1.282 + // Never gets here
1.283 + }
1.284 +
1.285 +//
1.286 +// CPolicyChangeWatcher member functions
1.287 +//
1.288 +CPolicyChangeWatcher *CPolicyChangeWatcher::NewL(RUpsSession &aUpsSession)
1.289 + {
1.290 + CPolicyChangeWatcher *self = new(ELeave) CPolicyChangeWatcher(aUpsSession);
1.291 + CleanupStack::PushL(self);
1.292 + self->ConstructL();
1.293 + CleanupStack::Pop(self);
1.294 + return self;
1.295 + }
1.296 +
1.297 +CPolicyChangeWatcher::CPolicyChangeWatcher(RUpsSession &aUpsSession)
1.298 + : CActive(CActive::EPriorityStandard+1),
1.299 + iUpsSession(aUpsSession)
1.300 + {
1.301 + CActiveScheduler::Add(this);
1.302 + }
1.303 +
1.304 +void CPolicyChangeWatcher::ConstructL()
1.305 + {
1.306 + User::LeaveIfError(iUpsPolicyChangeProperty.Attach(KUpsServerUid, KUpsServiceConfigProperty, EOwnerThread));
1.307 + iUpsPolicyChangeProperty.Subscribe(iStatus);
1.308 + SetActive();
1.309 + }
1.310 +
1.311 +CPolicyChangeWatcher::~CPolicyChangeWatcher()
1.312 + {
1.313 + Cancel();
1.314 + iUpsPolicyChangeProperty.Close();
1.315 + }
1.316 +
1.317 +void CPolicyChangeWatcher::DoCancel()
1.318 + {
1.319 + iUpsPolicyChangeProperty.Cancel();
1.320 + }
1.321 +
1.322 +void CPolicyChangeWatcher::RunL()
1.323 + {
1.324 + // Re-subscribe for policy file change notifications
1.325 + iUpsPolicyChangeProperty.Subscribe(iStatus);
1.326 + SetActive();
1.327 +
1.328 + // Tell session to update its cache.
1.329 + iUpsSession.NotifyPolicyFileChangedL();
1.330 + }
1.331 +
1.332 +TInt CPolicyChangeWatcher::RunError(TInt /* aError */)
1.333 + {
1.334 + // Ignore all errors
1.335 + //RDebug::Printf("CPolicyChangeWatcher::RunError(%d)\n", aError);
1.336 + return KErrNone;
1.337 + }
1.338 +
1.339 +
1.340 +} // End of namespace UserPromptService
1.341 +
1.342 +// End of file
1.343 +