os/security/authorisation/userpromptservice/server/source/upsclient/rupssession.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2007-2010 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 * RUpsSession implementation.	 See class and function definitions
    16 * for more detail.
    17 *
    18 */
    19 
    20 
    21 /**
    22  @file
    23 */
    24 
    25 
    26 #include <ups/upsclient.h>
    27 #include <e32property.h>
    28 #include <e32debug.h>
    29 #include "upscommon.h"
    30 #include "upsclientconfig.h"
    31 
    32 namespace UserPromptService
    33 	{
    34 
    35 NONSHARABLE_CLASS(CPolicyChangeWatcher) : public CActive
    36 	{
    37 public:
    38 	static CPolicyChangeWatcher *NewL(RUpsSession &aUpsSession);
    39 	~CPolicyChangeWatcher();
    40 private:
    41 	CPolicyChangeWatcher(RUpsSession &aUpsSession);
    42 	void ConstructL();
    43 	virtual void DoCancel();
    44 	virtual void RunL();
    45 	virtual TInt RunError(TInt aError);
    46 
    47 private:
    48 	RProperty iUpsPolicyChangeProperty;
    49 	RUpsSession &iUpsSession;
    50 	};
    51 
    52 EXPORT_C RUpsSession::RUpsSession()
    53 /**
    54 	This constructor provides a single point of definition from
    55 	which the superclass constructor is called.
    56  */
    57 :	RScsClientBase(),
    58 	iPolicyChangeWatcher(0),
    59 	iClientConfig(0)
    60 	{
    61 	// empty.
    62 	}
    63 
    64 EXPORT_C TInt RUpsSession::Connect()
    65 /**
    66 	Connect to the UPS server.
    67 
    68 	The thread which calls this function must be the same one which later calls Close().
    69 
    70 	Once connected, this session can be shared by multiple RUpsSubsession objects.
    71 
    72 	The RUpsSubsession objects are allowed to be in different threads, in which case ShareAuto() must be called before they are created.
    73 
    74 	@return					Symbian OS error code where KErrNone indicates
    75 							success and any other value indicates failure.
    76  */
    77 	{
    78 	TVersion v = UserPromptService::Version();
    79 	TUidType serverFullUid = UserPromptService::ServerImageFullUid();
    80 
    81 	TInt r = RScsClientBase::Connect(
    82 		UserPromptService::KUpsServerName, v, UserPromptService::KServerImageName, serverFullUid);
    83 	
    84 	if (r == KErrNone)	
    85 		{
    86 		// preload the configuration
    87 		TRAP(r, RetrieveClientConfigL());
    88 		}
    89 
    90 	if((r == KErrNone) && (CActiveScheduler::Current() != 0))
    91 		{
    92 		delete iPolicyChangeWatcher;
    93 		iPolicyChangeWatcher = 0;
    94 		TRAP(r, iPolicyChangeWatcher = CPolicyChangeWatcher::NewL(*this));
    95 		}
    96 
    97 	if(r != KErrNone)
    98 		{
    99 		Close();
   100 		}
   101 	
   102 	return r;
   103 	}
   104 	
   105 
   106 static void deleteArrayOfTServiceConfig(TAny *aPtr)
   107 	{
   108 	TServiceConfig *array = reinterpret_cast<TServiceConfig *>(aPtr);
   109 	delete [] array;
   110 	}
   111 
   112 void RUpsSession::RetrieveClientConfigL()
   113 	{
   114 	// Query how many TServiceConfig entries there are.
   115 	TPckgBuf<TInt> countBuf;
   116 	User::LeaveIfError(CallSessionFunction(EGetClientConfigLength, TIpcArgs(&countBuf)));
   117 	// Retrieve count from buffer
   118 	TInt count = countBuf();
   119 	
   120 	// Create buffer to hold entries
   121 	TServiceConfig *rawServiceConfig = new(ELeave) TServiceConfig[count];
   122 	CleanupStack::PushL(TCleanupItem(deleteArrayOfTServiceConfig, rawServiceConfig));
   123 
   124 	// Wrap array in a TPtr8 and use it to read array from server
   125 	TInt size = count * sizeof(TServiceConfig);
   126 	TPtr8 ptr((TUint8*)rawServiceConfig, size, size);
   127 	User::LeaveIfError(CallSessionFunction(EGetClientConfigData, TIpcArgs(&ptr)));
   128 
   129 	CUpsClientConfig *tmp = CUpsClientConfig::NewL(count, rawServiceConfig);
   130 	delete iClientConfig;
   131 	iClientConfig = tmp;
   132 
   133 	CleanupStack::PopAndDestroy(); // get rid of rawServiceConfig array
   134 	}
   135 	
   136 
   137 EXPORT_C void RUpsSession::Close()
   138 /**
   139 Frees the configuration object and calls RScsClientBase::Close
   140 
   141 This function MUST be called by the same thread which Connect().
   142 */
   143 	{
   144 	delete iClientConfig;
   145 	iClientConfig = 0;
   146 
   147 	if(iPolicyChangeWatcher)
   148 		{
   149 		iPolicyChangeWatcher->Cancel();
   150 		}
   151 	delete iPolicyChangeWatcher;
   152 	iPolicyChangeWatcher = 0;
   153 	
   154 	RScsClientBase::Close();
   155 	}
   156 
   157 void RUpsSession::NotifyPolicyFileChangedL()
   158 /**
   159 	@internalComponent
   160 	@released
   161 
   162 	Policy files have changed so update serviceconfig cache.
   163 */
   164 	{
   165 	RetrieveClientConfigL();
   166 	}
   167 
   168 CUpsClientConfig::CUpsClientConfig()
   169 	: iServiceConfig(1 /* granularity */, 0 /* key offset */)
   170 	{
   171 	}
   172 	
   173 CUpsClientConfig::~CUpsClientConfig()
   174 	{
   175 	iServiceConfig.Close();
   176 	}
   177 	
   178 CUpsClientConfig* CUpsClientConfig::NewL(TInt aCount, TServiceConfig *aRawServiceConfig)
   179 	/**
   180 	   @param serviceConfig
   181 
   182 	   Takes ownership of the serviceConfig array via swap. Callers array will be cleared.
   183 	*/
   184 	{
   185 	CUpsClientConfig *self = new(ELeave) CUpsClientConfig();
   186 	CleanupStack::PushL(self);
   187 	self->ConstructL(aCount, aRawServiceConfig);
   188 	CleanupStack::Pop(self);
   189 	return self;
   190 	}
   191 
   192 	
   193 void CUpsClientConfig::ConstructL(TInt aCount, TServiceConfig *aRawServiceConfig)
   194 	{
   195 	iServiceConfig.ReserveL(aCount);
   196 	for(TInt i=0; i < aCount; ++i)
   197 		{
   198 		iServiceConfig.InsertInUnsignedKeyOrderL(aRawServiceConfig[i]);
   199 		}
   200 	}
   201 
   202 CUpsClientConfig::TQueryUpsResult
   203 CUpsClientConfig::QueryUps(TBool aServerChecksPassed,
   204 							  const TServiceId &aServiceId, 
   205 							  const TSecureId &aClientSid,
   206 							  const TProcessId &aClientProcessId) const
   207 	{
   208 	TServiceConfig sc = {0};
   209 	sc.iServiceId = aServiceId.iUid; /* Only service id is used in lookup */
   210 	TInt i = iServiceConfig.FindInUnsignedKeyOrder(sc);
   211 	if(i == KErrNotFound)
   212 		{
   213 		// Must be no policy file for this service so no point in querying UPS
   214 		return aServerChecksPassed ? EAllow: EReject;
   215 		}
   216 	
   217 	
   218 	// Read entry
   219 	sc = iServiceConfig[i];
   220 
   221 	switch(sc.iPolicy)
   222 		{
   223 		case EAlwaysCheck:
   224 			return EQueryUps;
   225 			
   226 		case ECheckPostManufacture:
   227 			{
   228 			TBool isProtected = (TUint(aClientSid) & 0x80000000) == 0;
   229 			if(! isProtected)
   230 				{
   231 				return EQueryUps;
   232 				}
   233 
   234 			// Need to obtain the drive letter for the exe
   235 			//
   236 			// This requires opening the RProcess and two copies of a full filename (one 8 bit the other unicode)......
   237 			// We could optimse this by doing it when Initialise() is called, but that then slows down all Initialise calls even ones
   238 			// not doing the  ECheckPostManufacture check.
   239 			RProcess clientProcess;
   240 			if(clientProcess.Open(aClientProcessId) != KErrNone)
   241 				{
   242 				return EReject; // Presumably it exited...
   243 				}
   244 			
   245 			TFileName clientExeName = clientProcess.FileName();
   246 			clientProcess.Close();
   247 			TChar driveChar= clientExeName[0];
   248 			
   249 			if(aServerChecksPassed && 
   250 			   (driveChar == 'z' || driveChar == 'Z'))
   251 				{
   252 				return EAllow;
   253 				}
   254 
   255 			return EQueryUps;
   256 			}
   257 			
   258 		case ECheckUnprotectedSids:
   259 			{
   260 			TBool isProtected = (TUint(aClientSid) & 0x80000000) == 0;
   261 			
   262 			if(aServerChecksPassed && isProtected)
   263 				{
   264 				return EAllow;
   265 				}
   266 			
   267 			return EQueryUps;
   268 			}
   269 			
   270 		case ECheckIfFailed:
   271 			return aServerChecksPassed ? EAllow : EQueryUps;
   272 
   273 		BULLSEYE_OFF
   274 		default:
   275 		BULLSEYE_RESTORE
   276 		case ENeverCheck:
   277 			return aServerChecksPassed ? EAllow: EReject;
   278 			}
   279 	// Never gets here
   280 	}
   281 
   282 //
   283 // CPolicyChangeWatcher member functions
   284 //
   285 CPolicyChangeWatcher *CPolicyChangeWatcher::NewL(RUpsSession &aUpsSession)
   286 	{
   287 	CPolicyChangeWatcher *self = new(ELeave) CPolicyChangeWatcher(aUpsSession);
   288 	CleanupStack::PushL(self);
   289 	self->ConstructL();
   290 	CleanupStack::Pop(self);
   291 	return self;
   292 	}
   293 
   294 CPolicyChangeWatcher::CPolicyChangeWatcher(RUpsSession &aUpsSession)
   295 	:	CActive(CActive::EPriorityStandard+1), 
   296 		iUpsSession(aUpsSession)
   297 	{
   298 	CActiveScheduler::Add(this);
   299 	}
   300 
   301 void CPolicyChangeWatcher::ConstructL()
   302 	{
   303 	User::LeaveIfError(iUpsPolicyChangeProperty.Attach(KUpsServerUid, KUpsServiceConfigProperty, EOwnerThread));
   304 	iUpsPolicyChangeProperty.Subscribe(iStatus);
   305 	SetActive();
   306 	}
   307 
   308 CPolicyChangeWatcher::~CPolicyChangeWatcher()
   309 	{
   310 	Cancel();
   311 	iUpsPolicyChangeProperty.Close();
   312 	}
   313 
   314 void CPolicyChangeWatcher::DoCancel()
   315 	{
   316 	iUpsPolicyChangeProperty.Cancel();
   317 	}
   318 
   319 void CPolicyChangeWatcher::RunL()
   320 	{
   321 	// Re-subscribe for policy file change notifications
   322 	iUpsPolicyChangeProperty.Subscribe(iStatus);
   323 	SetActive();
   324 
   325 	// Tell session to update its cache.
   326 	iUpsSession.NotifyPolicyFileChangedL();
   327 	}
   328 
   329 TInt CPolicyChangeWatcher::RunError(TInt /* aError */)
   330 	{
   331 	// Ignore all errors
   332 	//RDebug::Printf("CPolicyChangeWatcher::RunError(%d)\n", aError);
   333 	return KErrNone;
   334 	}
   335 
   336 
   337 } // End of namespace UserPromptService
   338 
   339 // End of file
   340