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