authorisation/userpromptservice/server/source/upsserver/upsserver.cpp
changeset 8 35751d3474b7
equal deleted inserted replaced
2:675a964f4eb5 8:35751d3474b7
       
     1 /*
       
     2 * Copyright (c) 2007-2009 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 * Implements CUpsServer.	See class and function definitions for
       
    16 * more information.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 /**
       
    22  @file
       
    23 */
       
    24 
       
    25 #include "upsserver.h"
       
    26 #include "policycache.h"
       
    27 #include "pluginmanager.h"
       
    28 #include <ups/upsdbw.h>
       
    29 #include <ups/cliententity.h>
       
    30 #include <ups/dialogcreator.h>
       
    31 #include <ups/fingerprint.h>
       
    32 #include <ups/policy.h>
       
    33 #include <ups/policyevaluator.h>
       
    34 #include <e32property.h>
       
    35 #include "authoriser.h"
       
    36 #include <sacls.h>
       
    37 #include "upsserver_p.h"
       
    38 
       
    39 namespace UserPromptService
       
    40 {
       
    41 
       
    42 static const TInt upsPolicyRangeCount = 8;
       
    43 static const TInt upsPolicyRanges[upsPolicyRangeCount] = 
       
    44 				{
       
    45 					0,
       
    46 					// Range 0 - 0 to EBaseSession-1
       
    47 					// Not used
       
    48 					CScsServer::EBaseSession,
       
    49 					// Range 1 - EBaseSession  to EBaseSession | EMngmntRead-1
       
    50 					//
       
    51 					// These codes used to create subsessions and to query the policy
       
    52 					// authorisation settings.
       
    53 					//
       
    54 					// (ESessSubsessFromThreadId/EGetClientConfigLength/EGetClientConfigData)
       
    55 					//
       
    56 					CScsServer::EBaseSession | EMngmntRead,
       
    57 					// Range 2 - EBaseSession | EMngmntRead to EBaseSession | EMngmntDelete - 1
       
    58 					//
       
    59 					// Management READ APIs
       
    60 					//
       
    61 					CScsServer::EBaseSession | EMngmntDelete,
       
    62 					// Range 3 - EBaseSession | EMngmntDelete to EBaseSession | EMngmntUpdate - 1
       
    63 					// Management DELETE API (ie. delete entire database or selected entries).
       
    64 					//
       
    65 					CScsServer::EBaseSession | EMngmntUpdate,
       
    66 					// Range 4 - EBaseSession | EMngmntUpdate to EBaseSession | ESwiObserver - 1
       
    67 					// Management  UPDATE API (ie. change an existing decision).
       
    68 					//
       
    69 					CScsServer::EBaseSession | ESwiObserver,
       
    70 					// Range 5 - EBaseSession | ESwiObserver to EBaseSubSession - 1
       
    71 					// SWI observer management API.
       
    72 					//
       
    73 					CScsServer::EBaseSubSession,
       
    74 					// Range 6 - EBaseSubSession to EBaseMustAllow-1
       
    75 					//
       
    76 					// System Server APIs
       
    77 					// Authorise - (ESubsessPreparePrompt/ESubsessExecutePrompt)
       
    78 					CScsServer::EBaseMustAllow	
       
    79 					// Range 7 - EBaseMustAllow to KMaxTInt inclusive
       
    80 					//
       
    81 					// SCS internal APIs to create subsessions, cancel requests etc.
       
    82 				};
       
    83 
       
    84 static const TUint8 upsPolicyElementsIndex[upsPolicyRangeCount] = 
       
    85 				{
       
    86 					CPolicyServer::ENotSupported, // Range 0 - Not used
       
    87 					CPolicyServer::EAlwaysPass, // Range 1 - Subsess and auth policy
       
    88 					0, // Range 2 - Management READ APIs
       
    89 					1, // Range 3 - Management DELETE APIs
       
    90 					2, // Range 4 - Management UPDATE APIs
       
    91 					3, // Range 5 - SWI observer APIs
       
    92 					4, // Range 6 - System Server APIs
       
    93 					CPolicyServer::EAlwaysPass // Range 7 - SCS internal
       
    94 				};
       
    95 
       
    96 // 0x102836C3 == Swi::KUidSwiObserver.iUid from swiobserver.h BUT we can not include that because SWI is optional
       
    97 // and we are not!
       
    98 static const TSecureId KSwiObserverSid(0x102836C3);
       
    99 static const CPolicyServer::TPolicyElement upsPolicyPolicyElements[5] = 
       
   100 {
       
   101 				{_INIT_SECURITY_POLICY_C1(ECapabilityReadDeviceData), CPolicyServer::EFailClient},	
       
   102 				{_INIT_SECURITY_POLICY_C1(ECapabilityWriteDeviceData), CPolicyServer::EFailClient},	
       
   103 				{_INIT_SECURITY_POLICY_C1(ECapabilityAllFiles), CPolicyServer::EFailClient},
       
   104 				{_INIT_SECURITY_POLICY_S0(KSwiObserverSid), CPolicyServer::EFailClient},
       
   105 				{_INIT_SECURITY_POLICY_C1(ECapabilityProtServ), CPolicyServer::EFailClient}
       
   106 };
       
   107 
       
   108 static const CPolicyServer::TPolicy upsPolicy =
       
   109 				{
       
   110 				CPolicyServer::EAlwaysPass, // Allow all connects
       
   111 				upsPolicyRangeCount,
       
   112 				upsPolicyRanges,
       
   113 				upsPolicyElementsIndex,
       
   114 				upsPolicyPolicyElements,
       
   115 				};
       
   116 
       
   117 _LIT_SECURITY_POLICY_S0(KAllowUpsServer, KUpsServerUid.iUid); //< Only the UPS server can update the P&S flag used to tell clients to re-read client authorisation policies
       
   118 _LIT_SECURITY_POLICY_C1(KAllowProtServ, ECapabilityProtServ); //< All our system server clients will have ProtServ, so limit reading of the (internal) flag to them.
       
   119 
       
   120 CUpsServer* CUpsServer::NewLC()
       
   121 /**
       
   122 	Factory function allocates new, initialized instance of
       
   123 	CUpsServer which is left on the cleanup stack.
       
   124 
       
   125 	@return					New, initialized instance of CUpsServer
       
   126 							which is left on the cleanup stack.
       
   127  */
       
   128 	{
       
   129 	CUpsServer* self = new(ELeave) CUpsServer();
       
   130 	CleanupStack::PushL(self);
       
   131 	self->ConstructL();
       
   132 	return self;
       
   133 	}
       
   134 
       
   135 CUpsServer::CUpsServer()
       
   136 /**
       
   137 	Initializes the superclass with this server's version.
       
   138  */
       
   139 	:	CScsServer(UserPromptService::Version(), upsPolicy),
       
   140 		iPolicyCache(iFs),
       
   141 		iDbHandle(iFs)
       
   142 	{
       
   143 	// empty.
       
   144 	}
       
   145 
       
   146 void CUpsServer::ConstructL()
       
   147 /**
       
   148 	Second-phase construction initializes the superclass and
       
   149 	starts the server.
       
   150  */
       
   151 	{
       
   152 	CScsServer::ConstructL(UserPromptService::KShutdownPeriodUs);
       
   153 	User::LeaveIfError(iFs.Connect());
       
   154 
       
   155 	TInt r = RProperty::Define(KUpsServiceConfigProperty, RProperty::EInt, KAllowProtServ, KAllowUpsServer);
       
   156 	if(r != KErrAlreadyExists)
       
   157 		{
       
   158 		User::LeaveIfError(r);
       
   159 		}
       
   160 
       
   161 	iSwiWatcher = CSwiWatcher::NewL(*this);
       
   162 
       
   163 	SetupL();
       
   164 
       
   165 	StartL(UserPromptService::KUpsServerName);
       
   166 	}
       
   167 
       
   168 void CUpsServer::SetupL()
       
   169 /**
       
   170 	Setup memory variables which are not already setup.
       
   171 	Used during intial construction and after a call to FreeUncompressableMemory.
       
   172  */
       
   173 	{
       
   174 	if(!iPolicyCache.IsOpen())
       
   175 		{
       
   176 		iPolicyCache.OpenL();
       
   177 		}
       
   178 	if(!iPluginManager)
       
   179 		{
       
   180 		iPluginManager = CPluginManager::NewL();
       
   181 		}
       
   182 
       
   183 	// Create/Open the database
       
   184 	if(!iDbHandle.IsOpen())
       
   185 		{
       
   186 		iDbHandle.OpenL();
       
   187 		}
       
   188 
       
   189 	if(!iFlurryQueue)
       
   190 		{
       
   191 		iFlurryQueue = CAuthoriserFifo::NewL();
       
   192 		}
       
   193 	if(!iFlurryQueueBeingProcessed)
       
   194 		{
       
   195 		iFlurryQueueBeingProcessed = CAuthoriserFifo::NewL();
       
   196 		}
       
   197 	}
       
   198 
       
   199 void CUpsServer::FreeUncompressableMemory()
       
   200 /**
       
   201 	Frees memory which can not be compressed down to a known level for OOM testing.
       
   202  */
       
   203 	{
       
   204 	iDbHandle.Close();
       
   205 	
       
   206 	if(iPluginManager)
       
   207 		{
       
   208 		iPluginManager->Unload();
       
   209 		delete iPluginManager;
       
   210 		iPluginManager = 0;
       
   211 		}
       
   212 
       
   213 	iPolicyCache.Release();
       
   214 	}
       
   215 
       
   216 
       
   217 CUpsServer::~CUpsServer()
       
   218 /**
       
   219 	Cleanup the server, in particular close the RFs session.
       
   220  */
       
   221 	{
       
   222 	iDisputed.Close();
       
   223 	
       
   224 	(void) RProperty::Delete(KUpsServiceConfigProperty);
       
   225 	
       
   226 	delete iFlurryQueueBeingProcessed;
       
   227 	iFlurryQueueBeingProcessed = 0;
       
   228 
       
   229 	delete iFlurryQueue;
       
   230 	iFlurryQueue = 0;
       
   231 
       
   232 	FreeUncompressableMemory();
       
   233 
       
   234 	delete iSwiWatcher;
       
   235 	iSwiWatcher = 0;
       
   236 	iFs.Close();
       
   237 	}
       
   238 
       
   239 CScsSession* CUpsServer::DoNewSessionL(const RMessage2& /*aMessage*/)
       
   240 /**
       
   241 	Implement CScsServer by allocating a new instance of CUpsSession.
       
   242 
       
   243 	@param	aMessage		Standard server-side handle to message.	 Not used.
       
   244 	@return					New instance of CUpsSession which is owned by the
       
   245 							caller.
       
   246  */
       
   247 	{
       
   248 	return CUpsSession::NewL(*this);
       
   249 	}
       
   250 
       
   251 
       
   252 void CUpsServer::DoPreHeapMarkOrCheckL()
       
   253 /**
       
   254 	This function is called by the framework just before settingchecking a heap mark. We need to compress/free memory
       
   255 	down to a state which should be the same both before and after the test operations.
       
   256 */
       
   257 	{
       
   258 #ifdef _DEBUG
       
   259 	if(iAsyncRequests.Count() != 0)
       
   260 		{
       
   261 		User::Leave(KErrServerBusy);
       
   262 		}
       
   263 	iDisputed.Compress();
       
   264 	iFlurryQueue->Compress();
       
   265 	iFlurryQueueBeingProcessed->Compress();
       
   266 	FreeUncompressableMemory();
       
   267 #endif
       
   268 	}
       
   269 
       
   270 void CUpsServer::DoPostHeapMarkOrCheckL()
       
   271 /**
       
   272 	Called immediately after setting/checking the heap mark and therefore just after DoPreHeapMarkOrCheckL.
       
   273 	This function needs to re-allocate uncompressable data structures which were destroyed by DoPreHeapMarkOrCheckL.
       
   274 */
       
   275 	{
       
   276 #ifdef _DEBUG
       
   277 	SetupL();
       
   278 #endif
       
   279 	}
       
   280 
       
   281 void CUpsServer::GateKeeperL(CAuthoriser *aAuthoriser)
       
   282 	/**
       
   283 	   If no dialog is in progress, the server will note one is in
       
   284 	   progress, and tell the aAuthoriser it can continue (by calling
       
   285 	   ClearedToDisplayL).
       
   286 
       
   287 	   Whenever a CAuthoriser finishes it MUST call our AuthoriserDone
       
   288 	   function. This will allow us to cleanup our queues and clear
       
   289 	   the next dialog to display.
       
   290 
       
   291 	   If a dialog is already in progress, the the aAuthoriser will be
       
   292 	   added to iFlurryQueue for later processing.
       
   293 
       
   294 	   @param aAuthoriser to queue
       
   295 	 */
       
   296 	{
       
   297 	if(iCurrentDialog)
       
   298 		{
       
   299 		// Add to queue of requests requiring re-processing later. This includes requests which want to display
       
   300 		// a dialog and ones which matches a recordId which is under dispute (i.e. Where ForcePrompt has been
       
   301 		// called and returned yes, but the prompt hasn't been displayed yet).
       
   302 		iFlurryQueue->PushL(aAuthoriser);
       
   303 		return;
       
   304 		}
       
   305 	iCurrentDialog = aAuthoriser;
       
   306 	iCurrentDialog->ClearedToDisplayL();
       
   307 	}
       
   308 
       
   309 void CUpsServer::AuthoriserDone(CAuthoriser *aAuthoriser)
       
   310 /**
       
   311 	See CUpsServer::AuthoriserDoneL for documentation.
       
   312 */
       
   313 	{
       
   314 	TRAP_IGNORE(AuthoriserDoneL(aAuthoriser));
       
   315 	}
       
   316 
       
   317 void CUpsServer::AuthoriserDoneL(CAuthoriser *aAuthoriser)
       
   318 	/**
       
   319 	   The CAuthoriser has either completed the request, been
       
   320 	   cancelled, or failed somehow.
       
   321 
       
   322 	   If it is in either FIFO it needs removing.
       
   323 
       
   324 	   If it is the current display dialog, then we need to check the
       
   325 	   FIFOs, and maybe swap them, and call WakeupNextPending.
       
   326 	*/
       
   327 	{
       
   328 	// Remove from lists.
       
   329 	// Note the FIFO object does NOT leave if the object is not found.
       
   330 	iFlurryQueue->RemoveL(aAuthoriser);
       
   331 	iFlurryQueueBeingProcessed->RemoveL(aAuthoriser);
       
   332 
       
   333 	if(aAuthoriser == iCurrentDialog)
       
   334 		{
       
   335 		iCurrentDialog = 0;
       
   336 
       
   337 		if(iFlurryQueueBeingProcessed->IsEmpty())
       
   338 			{
       
   339 			// Swap queues
       
   340 			CAuthoriserFifo *tmp = iFlurryQueue;
       
   341 			iFlurryQueue = iFlurryQueueBeingProcessed;
       
   342 			iFlurryQueueBeingProcessed = tmp;
       
   343 			}
       
   344 		WakeupNextPendingL();
       
   345 		}
       
   346 	}
       
   347 
       
   348 void CUpsServer::WakeupNextPendingL()
       
   349 	/**
       
   350 	   This function does the following:-
       
   351 
       
   352 	   1) If iFlurryQueueBeingProcessed is empty it returns.
       
   353 	   
       
   354 	   2) Removes the first authoriser from iFlurryQueueBeingProcessed
       
   355 	   and calls SetPending to mark it as no longer pending.
       
   356 	   
       
   357 	   3) Increases its priority to EPriorityUserInput (this makes
       
   358 	   sure it will be handled ahead of any incoming requests)
       
   359 
       
   360 	   4) Sets it active and completes it so it runs.
       
   361 
       
   362 	   It will run BEFORE any incoming requests.
       
   363 	   
       
   364 	   The first thing it must do is call this function again. This
       
   365 	   ensures all pending requests are re-processed in order.
       
   366 
       
   367 	   Normally it will then re-lookup its fingerprints in the
       
   368 	   database, if found it may complete client request. If it
       
   369 	   decides it still needs to display a dialog it should call
       
   370 	   GateKeeper again.
       
   371 	 */
       
   372 	{
       
   373 	if(iFlurryQueueBeingProcessed->IsEmpty())
       
   374 		{
       
   375 		return;
       
   376 		}
       
   377 	
       
   378 	CAuthoriser *authoriser = iFlurryQueueBeingProcessed->PopL();
       
   379 	// Set priority of authoriser to EPriorityHigh-1. This is higher
       
   380 	// than any incoming work, but lower than deferred deletes.
       
   381 	authoriser->SetPriority(CActive::EPriorityHigh - 1);
       
   382 	authoriser->Wakeup();
       
   383 	}
       
   384 
       
   385 void CUpsServer::DisputeRecordIdL(TUint32 aRecordId)
       
   386 /**
       
   387 	Add the specified record to the list of disputed record IDs.
       
   388 */
       
   389 	{
       
   390 	DEBUG_PRINTF2(_L8("CUpsServer::DisputeRecordIdL(%d)\n"), aRecordId);
       
   391 	User::LeaveIfError(iDisputed.InsertInOrder(aRecordId));
       
   392 	}
       
   393 
       
   394 void CUpsServer::UnDisputeRecordIdL(TUint32 aRecordId)
       
   395 /**
       
   396 	Deletes the specified record from the list of disputed record IDs.
       
   397 */
       
   398 	{
       
   399 	DEBUG_PRINTF2(_L8("CUpsServer::UnDisputeRecordIdL(%d)\n"), aRecordId);
       
   400 	TInt i = iDisputed.FindInOrderL(aRecordId);
       
   401 	User::LeaveIfError(i);
       
   402 	iDisputed.Remove(i);
       
   403 	}
       
   404 
       
   405 TBool CUpsServer::IsRecordIdDisputed(TUint32 aRecordId) const
       
   406 /**
       
   407 	Checks if the specified record is under dispute. A record is disputed
       
   408 	if the evaluator ForcePromptL call for a match on that record return ETrue to
       
   409 	force a prompt to be displayed.
       
   410 */
       
   411 	{
       
   412 	TBool disputed = iDisputed.FindInOrder(aRecordId) >= 0;
       
   413 	//RDebug::Printf("CUpsServer::IsRecordIdDisputed(%d) - returning %s\n", 
       
   414 	//				aRecordId,
       
   415 	//				(disputed)?("EFalse"):("EFalse"));
       
   416 	return disputed;
       
   417 	}
       
   418 
       
   419 //
       
   420 // Implementation of CSwiWatcher
       
   421 //
       
   422 CSwiWatcher *CSwiWatcher::NewL(CUpsServer &aUpsServer)
       
   423 	{
       
   424 	CSwiWatcher *self = new(ELeave) CSwiWatcher(aUpsServer);
       
   425 	CleanupStack::PushL(self);
       
   426 	self->ConstructL();
       
   427 	CleanupStack::Pop(self);
       
   428 	return self;
       
   429 	}
       
   430 
       
   431 CSwiWatcher::CSwiWatcher(CUpsServer &aUpsServer)
       
   432 	: CActive(CActive::EPriorityHigh),
       
   433 	  iUpsServer(aUpsServer)
       
   434 	{
       
   435 	CActiveScheduler::Add(this);
       
   436 	}
       
   437 
       
   438 void CSwiWatcher::ConstructL()
       
   439 /**
       
   440 	Subscribe for notification for writes to the SWI P&S property.
       
   441 	We do not check the actual value because it is not guaranteed that we will run for every change.
       
   442 */
       
   443 	{
       
   444 	User::LeaveIfError(iSwiProperty.Attach(KUidSystemCategory, KSAUidSoftwareInstallKeyValue));
       
   445 	iSwiProperty.Subscribe(iStatus);
       
   446 	SetActive();
       
   447 	}
       
   448 
       
   449 void CSwiWatcher::RunL()
       
   450 /**
       
   451 	SWI has changed state, so unload any unused plugins.
       
   452 	We do this for EVERY state change which we manage to run for, which is overkill, but the unload call
       
   453 	is cheap/free if there are no plugins which require unloading.
       
   454 */
       
   455 	{
       
   456 	User::LeaveIfError(iStatus.Int());
       
   457 	
       
   458 	iSwiProperty.Subscribe(iStatus);
       
   459 	SetActive();
       
   460 
       
   461 	// Tell the plugin manager to unload plugins which are NOT in use. 
       
   462 	iUpsServer.iPluginManager->Unload();
       
   463 	}
       
   464 
       
   465 void CSwiWatcher::DoCancel()
       
   466 	{
       
   467 	iSwiProperty.Cancel();
       
   468 	}
       
   469 
       
   470 CSwiWatcher::~CSwiWatcher()
       
   471 	{
       
   472 	Cancel();
       
   473 	}
       
   474 
       
   475 
       
   476 } // End of namespace UserPromptService
       
   477 // End of file