os/security/authorisation/userpromptservice/server/source/upsserver/authoriser.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-2009 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 CAuthoriser.	 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 "authoriser.h"
sl@0
    28
#include <ups/upsdbw.h>
sl@0
    29
#include "upslog.h"
sl@0
    30
#include <ups/dialogcreator.h>
sl@0
    31
#include <ups/policyevaluator.h>
sl@0
    32
sl@0
    33
namespace UserPromptService
sl@0
    34
{
sl@0
    35
sl@0
    36
CAuthoriser* CAuthoriser::NewL(RPolicyCacheCountedHandle &aPolicyCache,
sl@0
    37
								   CUpsSession* aSession, CUpsSubsession* aSubsession, TBool aServerCheckOk,
sl@0
    38
								   TThreadId &aClientTid, TProcessId &aClientPId,
sl@0
    39
								   const RMessage2& aMessage, const TServiceId& aServiceId,
sl@0
    40
								   RBuf &aDestination, RBuf8 &aOpaqueData)
sl@0
    41
	/**
sl@0
    42
	   Factory function allocates a new, initialized instance of CAuthoriser,
sl@0
    43
	   registered for the supplied session and subsession.
sl@0
    44
	   
sl@0
    45
	   If construction is successful, the caller should pass ownership to
sl@0
    46
	   the SCS framework (TransferToScsFrameworkL), and pop the
sl@0
    47
	   CAuthoriser from the cleanupstack. From this point onwards the
sl@0
    48
	   request should be completed by the CAuthoriser/CAsyncRequst code,
sl@0
    49
	   so the caller must not return or leave with any code except
sl@0
    50
	   KErrScsSetupAsync. This is why the StartProcessingRequest function
sl@0
    51
	   is defined as non-leaving.
sl@0
    52
sl@0
    53
	   @param	aPolicyCache	The server policy cache manager.
sl@0
    54
	   @param	aSession		Session on which this request was launched.
sl@0
    55
	   @param	aSubsession		Subsession on which this request was launched.
sl@0
    56
	   @param	aServerCheckOk	Did the system server checks pass?
sl@0
    57
	   @param	aClientThread	Handle to the user client thread.
sl@0
    58
	   @param	aMessage		Standard server-side handle to message.
sl@0
    59
	   @param	aDestination	We take ownership of the RBuf and close the callers handle
sl@0
    60
	   @param	aOpaqueData		We take ownership of the RBuf and close the callers handle
sl@0
    61
	   @return					New, initialized instance of CAuthoriser, which
sl@0
    62
	   is owned by the server's collection of outstanding
sl@0
    63
	   requests.
sl@0
    64
	*/
sl@0
    65
	{
sl@0
    66
	CAuthoriser* self = new(ELeave) CAuthoriser(aPolicyCache, aSession, aSubsession, aMessage);
sl@0
    67
	CleanupStack::PushL(self);
sl@0
    68
	self->ConstructL(aServerCheckOk, aClientTid, aClientPId, aServiceId, aDestination, aOpaqueData);
sl@0
    69
	CleanupStack::Pop(self);
sl@0
    70
	return self;
sl@0
    71
	}
sl@0
    72
sl@0
    73
CAuthoriser::CAuthoriser(RPolicyCacheCountedHandle &aPolicyCache,
sl@0
    74
						   CUpsSession* aSession, CUpsSubsession* aSubsession,
sl@0
    75
						   const RMessage2& aMessage)
sl@0
    76
	/**
sl@0
    77
	   This private constructor initializes the superclass and prevents direct instantiation.
sl@0
    78
sl@0
    79
	   @param	aPolicyCache		The server policy cache manager.
sl@0
    80
	   @param	aSession			Session on which this request was launched.
sl@0
    81
	   @param	aSubsession		Subsession on which this request was launched.
sl@0
    82
	   @param	aMessage		Standard server-side handle to message.
sl@0
    83
	   @param	aDestination	HBufC description, takes ownership.
sl@0
    84
	   @param	aOpaqueData		0 or HBufC opaqueData, takes ownership.
sl@0
    85
	*/
sl@0
    86
	:	CAsyncRequest(aSession, aSubsession, aMessage),
sl@0
    87
		iPolicyCache(aPolicyCache)
sl@0
    88
	{
sl@0
    89
	// empty.
sl@0
    90
	}
sl@0
    91
sl@0
    92
void CAuthoriser::ConstructL(TBool aServerCheckOk, TThreadId &aClientTid, TProcessId &aClientPid, const TServiceId& aServiceId, RBuf &aDestination, RBuf8 &aOpaqueData)
sl@0
    93
	/**
sl@0
    94
	   Second-phase constructor allocates the timer which is used to generate
sl@0
    95
	   a delay, and adds this object to the server's collection of outstanding
sl@0
    96
	   requests.
sl@0
    97
	*/
sl@0
    98
	{
sl@0
    99
	iState = ECheckPolicy;
sl@0
   100
sl@0
   101
	RProcess clientProcess;
sl@0
   102
	TInt r = clientProcess.Open(aClientPid);
sl@0
   103
	if(r != KErrNone)
sl@0
   104
		{
sl@0
   105
		User::Leave(KErrUpsBadClientProcessId);
sl@0
   106
		}
sl@0
   107
	CleanupClosePushL(clientProcess);
sl@0
   108
	
sl@0
   109
	// Create a CPromptReqest for the policy lookup
sl@0
   110
	iPromptRequest = CPromptRequest::NewL(clientProcess.SecureId(), // Client details
sl@0
   111
										  clientProcess.VendorId(),
sl@0
   112
										  aClientTid,
sl@0
   113
										  aClientPid,
sl@0
   114
										  iMessagePtr2.SecureId(), // Server SID
sl@0
   115
										  aServiceId, // Server service ID
sl@0
   116
										  aDestination, // Request detail, takes ownership
sl@0
   117
										  aOpaqueData,	//				   takes ownership
sl@0
   118
										  aServerCheckOk); 
sl@0
   119
	
sl@0
   120
	CleanupStack::PopAndDestroy(&clientProcess);
sl@0
   121
	}
sl@0
   122
sl@0
   123
void CAuthoriser::ProcessEventL(TAuthoriserEvent aEvent)
sl@0
   124
	{
sl@0
   125
	//	DEBUG_PRINTF4(_L8("0x%x CAuthoriser::ProcessEventL state %d, event %d\n"), this, iState, aEvent);
sl@0
   126
	_LIT(KServerPanicState, "UPS-ProcessEventL");
sl@0
   127
	switch(iState)
sl@0
   128
		{
sl@0
   129
		case ECheckPolicy:
sl@0
   130
			CheckPolicyStateL(aEvent);
sl@0
   131
			return;
sl@0
   132
		case ECreatingFingerprints:
sl@0
   133
			CreatingFingerprintsStateL(aEvent);
sl@0
   134
			return;
sl@0
   135
		case ECheckDatabase:
sl@0
   136
			CheckDatabaseStateL(aEvent);
sl@0
   137
			return;
sl@0
   138
		case EPreparingDialog:
sl@0
   139
			PreparingDialogStateL(aEvent);
sl@0
   140
			return;
sl@0
   141
		case EExecutingDialog:
sl@0
   142
			ExecutingDialogStateL(aEvent);
sl@0
   143
			return;
sl@0
   144
BULLSEYE_OFF
sl@0
   145
		}
sl@0
   146
	
sl@0
   147
	// Should not get here
sl@0
   148
	User::Panic(KServerPanicState, iState);
sl@0
   149
BULLSEYE_RESTORE
sl@0
   150
	}
sl@0
   151
sl@0
   152
sl@0
   153
void CAuthoriser::CheckPolicyStateL(TAuthoriserEvent aEvent)
sl@0
   154
	{
sl@0
   155
	switch(aEvent)
sl@0
   156
		{
sl@0
   157
		case EInternalRequestComplete:
sl@0
   158
			// Caused by the ups sub session code calling Wakeup
sl@0
   159
			// to start the request processing. We are now within the
sl@0
   160
			// active scheduler error handling framework.
sl@0
   161
sl@0
   162
			// This call will lookup the policy and move to the next
sl@0
   163
			// state, or leave.
sl@0
   164
			LookupPolicyL();
sl@0
   165
			break;
sl@0
   166
sl@0
   167
			BULLSEYE_OFF
sl@0
   168
		case EClearedToDisplayDialog:
sl@0
   169
			ASSERT(EFalse);
sl@0
   170
			break;
sl@0
   171
			BULLSEYE_RESTORE
sl@0
   172
sl@0
   173
		case ECancel:
sl@0
   174
			// This WILL happen if am authorise request is made and immediately cancelled (before CAuthoriser::Runl has
sl@0
   175
			// the chance to run). We should complete our "fake" internal request so we do not block
sl@0
   176
			// when we return to the DoCancel/CActive::Cancel which caused this event.
sl@0
   177
			CompleteSelf();
sl@0
   178
			break;
sl@0
   179
BULLSEYE_OFF
sl@0
   180
		}
sl@0
   181
BULLSEYE_RESTORE
sl@0
   182
	}
sl@0
   183
sl@0
   184
void CAuthoriser::CreatingFingerprintsStateL(TAuthoriserEvent aEvent)
sl@0
   185
	{
sl@0
   186
	switch(aEvent)
sl@0
   187
		{
sl@0
   188
		case EInternalRequestComplete:
sl@0
   189
			// This will move to the next state and lookup the fingerprints, or leave.
sl@0
   190
			LookupFingerprintsL();
sl@0
   191
			break;
sl@0
   192
sl@0
   193
			BULLSEYE_OFF
sl@0
   194
		case EClearedToDisplayDialog:
sl@0
   195
			ASSERT(EFalse);
sl@0
   196
			break;
sl@0
   197
			BULLSEYE_RESTORE
sl@0
   198
sl@0
   199
		case ECancel:
sl@0
   200
			// Cancel the request to create the fingerprints
sl@0
   201
			iPolicyEvaluator->Imp().Cancel();
sl@0
   202
			break;
sl@0
   203
BULLSEYE_OFF
sl@0
   204
		}
sl@0
   205
BULLSEYE_RESTORE
sl@0
   206
	}
sl@0
   207
sl@0
   208
void CAuthoriser::CheckDatabaseStateL(TAuthoriserEvent aEvent)
sl@0
   209
	{
sl@0
   210
	switch(aEvent)
sl@0
   211
		{
sl@0
   212
		case EInternalRequestComplete:
sl@0
   213
			// Normally the create fingerprints state code will call
sl@0
   214
			// LookupFingerprintsL to move to this state and do the
sl@0
   215
			// lookup, but if we need to re-lookup the fingerprints a
sl@0
   216
			// "fake" request will be issued and this code will be
sl@0
   217
			// used.
sl@0
   218
			LookupFingerprintsL();
sl@0
   219
			break;
sl@0
   220
		case EClearedToDisplayDialog:
sl@0
   221
			// Change state and ask the dialog creator to start creating
sl@0
   222
			// the dialog, or leave.
sl@0
   223
			PrepareDialogL();
sl@0
   224
			break;
sl@0
   225
		case ECancel:
sl@0
   226
			// Complete the fake request which was issued to try and
sl@0
   227
			// get us to redo the fingerprint lookup.
sl@0
   228
			CompleteSelf();
sl@0
   229
			break;
sl@0
   230
BULLSEYE_OFF
sl@0
   231
		}
sl@0
   232
BULLSEYE_RESTORE
sl@0
   233
	}
sl@0
   234
sl@0
   235
void CAuthoriser::PreparingDialogStateL(TAuthoriserEvent aEvent)
sl@0
   236
	{
sl@0
   237
	switch(aEvent)
sl@0
   238
		{
sl@0
   239
		case EInternalRequestComplete:
sl@0
   240
			// Created dialog, now change state to execute and display
sl@0
   241
			// it.
sl@0
   242
			ExecuteDialogL();
sl@0
   243
			break;
sl@0
   244
sl@0
   245
			BULLSEYE_OFF
sl@0
   246
		case EClearedToDisplayDialog:
sl@0
   247
			ASSERT(EFalse);
sl@0
   248
			break;
sl@0
   249
			BULLSEYE_RESTORE
sl@0
   250
sl@0
   251
		case ECancel:
sl@0
   252
			// Cancel the request to create the dialog
sl@0
   253
			iDialogCreator->Imp().Cancel();
sl@0
   254
			break;
sl@0
   255
BULLSEYE_OFF
sl@0
   256
		}
sl@0
   257
BULLSEYE_RESTORE
sl@0
   258
	}
sl@0
   259
sl@0
   260
void CAuthoriser::ExecutingDialogStateL(TAuthoriserEvent aEvent)
sl@0
   261
	{
sl@0
   262
	switch(aEvent)
sl@0
   263
		{
sl@0
   264
		case EInternalRequestComplete:
sl@0
   265
			// Dialog complete, process the result and complete the
sl@0
   266
			// client request.
sl@0
   267
			ProcessDialogResultL();
sl@0
   268
			break;
sl@0
   269
sl@0
   270
			BULLSEYE_OFF
sl@0
   271
		case EClearedToDisplayDialog:
sl@0
   272
			ASSERT(EFalse);
sl@0
   273
			break;
sl@0
   274
			BULLSEYE_RESTORE
sl@0
   275
sl@0
   276
		case ECancel:
sl@0
   277
			// Cancel the request to execute the dialog
sl@0
   278
			iDialogCreator->Imp().Cancel();
sl@0
   279
			break;
sl@0
   280
BULLSEYE_OFF
sl@0
   281
		}
sl@0
   282
BULLSEYE_RESTORE
sl@0
   283
	}
sl@0
   284
sl@0
   285
void CAuthoriser::Wakeup()
sl@0
   286
	/**
sl@0
   287
	   Raise and complete a request against self. Will cause RunL to
sl@0
   288
	   be run within the active scheduler.
sl@0
   289
	*/
sl@0
   290
	{
sl@0
   291
	iStatus = KRequestPending;
sl@0
   292
	SetActive();
sl@0
   293
	CompleteSelf();
sl@0
   294
	}
sl@0
   295
sl@0
   296
void CAuthoriser::CompleteSelf()
sl@0
   297
	{
sl@0
   298
	_LIT(KServerPanicState, "UPS-CompleteSelf");
sl@0
   299
	switch(iState)
sl@0
   300
		{
sl@0
   301
		case ECheckPolicy:
sl@0
   302
		case ECheckDatabase:
sl@0
   303
			break;
sl@0
   304
sl@0
   305
	BULLSEYE_OFF
sl@0
   306
		case ECreatingFingerprints:
sl@0
   307
		case EPreparingDialog:
sl@0
   308
		case EExecutingDialog:
sl@0
   309
			User::Panic(KServerPanicState, iState);
sl@0
   310
			/*lint -unreachable */
sl@0
   311
			return; // Not legal in these states
sl@0
   312
		}
sl@0
   313
	BULLSEYE_RESTORE
sl@0
   314
		
sl@0
   315
	if(iStatus == KRequestPending)
sl@0
   316
		{
sl@0
   317
		TRequestStatus *status = &iStatus;
sl@0
   318
		User::RequestComplete(status, KErrNone);
sl@0
   319
		}
sl@0
   320
	}
sl@0
   321
sl@0
   322
sl@0
   323
sl@0
   324
void CAuthoriser::ClearedToDisplayL()
sl@0
   325
	/**
sl@0
   326
	   The UPS server GateKeeper has granted us permission to proceed
sl@0
   327
	   with dialog generation and display.
sl@0
   328
	*/
sl@0
   329
	{
sl@0
   330
	ProcessEventL(EClearedToDisplayDialog);
sl@0
   331
	}
sl@0
   332
sl@0
   333
sl@0
   334
sl@0
   335
sl@0
   336
sl@0
   337
sl@0
   338
CAuthoriser::~CAuthoriser()
sl@0
   339
	/**
sl@0
   340
	   Close the timer which was initialized in ConstructL.
sl@0
   341
	*/
sl@0
   342
	{
sl@0
   343
	iDialogFingerprint = 0; // MUST not delete, owned by CDialogCreator
sl@0
   344
	
sl@0
   345
	delete iDialogCreator;
sl@0
   346
	iDialogCreator = 0;
sl@0
   347
	
sl@0
   348
	iDialogCreatorParams = 0; // MUST not delete, owned by evaluator
sl@0
   349
	
sl@0
   350
	iClientEntity = 0;	// MUST not delete, owned by evaluator
sl@0
   351
	
sl@0
   352
	iFingerprints.ResetAndDestroy();
sl@0
   353
	
sl@0
   354
	delete iPolicyEvaluator;
sl@0
   355
	iPolicyEvaluator = 0;	
sl@0
   356
sl@0
   357
	iPolicyCache.Release();
sl@0
   358
	iPolicy = 0; // MUST not delete, ownded by policy cache
sl@0
   359
	
sl@0
   360
	delete iPromptRequest;
sl@0
   361
	iPromptRequest = 0;
sl@0
   362
	}
sl@0
   363
sl@0
   364
void CAuthoriser::RunL()
sl@0
   365
	{
sl@0
   366
	// Wake up the next pending request now (if any), to make sure it
sl@0
   367
	// will be processed ahead of any incoming requests.
sl@0
   368
	UpsServer()->WakeupNextPendingL();
sl@0
   369
	
sl@0
   370
	// Reset our priority to standard
sl@0
   371
	if(Priority() != CActive::EPriorityStandard)
sl@0
   372
		{
sl@0
   373
		SetPriority(CActive::EPriorityStandard);
sl@0
   374
		}
sl@0
   375
	User::LeaveIfError(iStatus.Int());
sl@0
   376
	
sl@0
   377
	ProcessEventL(EInternalRequestComplete);
sl@0
   378
	}
sl@0
   379
sl@0
   380
sl@0
   381
void CAuthoriser::DoCleanup()
sl@0
   382
	{
sl@0
   383
	if(iPromptForced)
sl@0
   384
		{
sl@0
   385
		// Have previously called ForcePromptL on a database record and it told us to 
sl@0
   386
		// prompt,  so have previously marked the record as disputed.
sl@0
   387
		TRAP_IGNORE(UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId));
sl@0
   388
		iPromptForced = EFalse;
sl@0
   389
		}
sl@0
   390
sl@0
   391
	// Cancel current internal operation
sl@0
   392
	Cancel();
sl@0
   393
	
sl@0
   394
	// Let the server know we are done
sl@0
   395
	UpsServer()->AuthoriserDone(this);
sl@0
   396
sl@0
   397
	// The framework will complete the client request and schedule us
sl@0
   398
	// for deletion.
sl@0
   399
	}
sl@0
   400
sl@0
   401
sl@0
   402
sl@0
   403
sl@0
   404
void CAuthoriser::DoCancel()
sl@0
   405
	/**
sl@0
   406
	   Cancel the current operation.  This does not complete the client
sl@0
   407
	   request or mark this object for deletion.
sl@0
   408
	*/
sl@0
   409
	{
sl@0
   410
	TRAP_IGNORE(
sl@0
   411
		// Wake up the next pending request now (if any), to make sure it
sl@0
   412
		// will be processed ahead of any incoming requests.
sl@0
   413
		UpsServer()->WakeupNextPendingL();
sl@0
   414
		ProcessEventL(ECancel);
sl@0
   415
		);
sl@0
   416
	}
sl@0
   417
sl@0
   418
void CAuthoriser::LookupPolicyL()
sl@0
   419
	{
sl@0
   420
	// This returns a ptr into the cache, so we have to be careful not to use it after the cache is deleted.
sl@0
   421
	// This is why we wrap the cache in a RPolicyCacheCountedHandle.
sl@0
   422
	iPolicy = iPolicyCache->MatchL(*iPromptRequest);
sl@0
   423
	
sl@0
   424
	ASSERT(iPolicy);
sl@0
   425
	
sl@0
   426
	if(iPolicy->PromptRequired())
sl@0
   427
		{
sl@0
   428
		// Policy contains both yes and no responses...
sl@0
   429
		// Start creating the fingerprints
sl@0
   430
		CreateFingerprintsL();
sl@0
   431
		return;
sl@0
   432
		}
sl@0
   433
	
sl@0
   434
	// Return result to system server
sl@0
   435
	TUpsDecisionPckgBuf decisionBuf;
sl@0
   436
	decisionBuf() = MapCPolicyTOptions2TUpsDecision(iPolicy->Options());
sl@0
   437
	iMessagePtr2.WriteL(0, decisionBuf);
sl@0
   438
	
sl@0
   439
	CompleteAndMarkForDeletion(KErrNone);
sl@0
   440
	}
sl@0
   441
sl@0
   442
sl@0
   443
void CAuthoriser::CreateFingerprintsL()
sl@0
   444
	/**
sl@0
   445
	   Load Policy Evaluator and tell it to start generating the fingerprints
sl@0
   446
	*/
sl@0
   447
	{
sl@0
   448
	iState = ECreatingFingerprints;
sl@0
   449
sl@0
   450
	iPolicyEvaluator = UpsServer()->iPluginManager->CreateEvaluatorL(iPolicy->PolicyEvaluator());
sl@0
   451
	
sl@0
   452
	iPolicyEvaluator->Imp().GenerateFingerprints(*iPromptRequest, *iPolicy, 
sl@0
   453
												 iFingerprints, iClientEntity, iDialogCreatorParams, iStatus);
sl@0
   454
	
sl@0
   455
	SetActive();
sl@0
   456
	}
sl@0
   457
sl@0
   458
_LIT8(KDefaultFingerprint,"*");
sl@0
   459
//_LIT(KServerPanicDb, "UPS-BadDB");
sl@0
   460
static const char * const KCorruptDb = "UPS-BadDB error=%d line=%d\n";
sl@0
   461
sl@0
   462
void CAuthoriser::LookupFingerprintsL()
sl@0
   463
	{
sl@0
   464
	// Lookup in DB
sl@0
   465
	iState = ECheckDatabase;
sl@0
   466
sl@0
   467
	TPtrC8 clientEntityName(KNullDesC8());
sl@0
   468
	if(iClientEntity)
sl@0
   469
		{
sl@0
   470
		clientEntityName.Set(iClientEntity->Name());
sl@0
   471
		}
sl@0
   472
	
sl@0
   473
	CDecisionFilter *filter = CDecisionFilter::NewLC(iPromptRequest->ClientSid(),
sl@0
   474
													 iPolicy->PolicyEvaluator(),
sl@0
   475
													 iPromptRequest->ServiceId(),
sl@0
   476
													 iPromptRequest->ServerSid(),
sl@0
   477
													 KDefaultFingerprint(),
sl@0
   478
													 clientEntityName,
sl@0
   479
													 iPolicy->MajorVersion());
sl@0
   480
	//
sl@0
   481
	// Lookup the fingerprints in the DB and return the first match
sl@0
   482
	//
sl@0
   483
	CDecisionRecord *record = 0;
sl@0
   484
	TInt fingerprintCount = iFingerprints.Count();
sl@0
   485
	for(TInt i=0; i<fingerprintCount; ++i)
sl@0
   486
		{
sl@0
   487
		filter->SetFingerprintL(iFingerprints[i]->Fingerprint(), EEqual);
sl@0
   488
		record = 0;
sl@0
   489
		TRAPD(err, record = UpsServer()->iDbHandle->GetDecisionL(*filter));
sl@0
   490
		if(err != KErrNone)
sl@0
   491
			{
sl@0
   492
			HandleDbErrorL(err);
sl@0
   493
			}
sl@0
   494
		
sl@0
   495
		if(record)
sl@0
   496
			{
sl@0
   497
			break;
sl@0
   498
			}
sl@0
   499
		}
sl@0
   500
	
sl@0
   501
	if(record)
sl@0
   502
		{
sl@0
   503
		// Found record
sl@0
   504
		CleanupStack::PushL(record);
sl@0
   505
		// Read current eval info value from record.
sl@0
   506
		iDialogEvaluatorInfo = record->iEvaluatorInfo;
sl@0
   507
sl@0
   508
		if(UpsServer()->IsRecordIdDisputed(record->iRecordId))
sl@0
   509
			{
sl@0
   510
			// Matching record is under dispute so a dialog must be in progress.
sl@0
   511
			// Queue for later re-evaluation.
sl@0
   512
			UpsServer()->GateKeeperL(this);
sl@0
   513
			return;
sl@0
   514
			}
sl@0
   515
sl@0
   516
		if(iPromptForced && (record->iRecordId != iPromptForcedRecordId))
sl@0
   517
			{
sl@0
   518
			// Have previously called ForcePromptL on a database record and it told us to 
sl@0
   519
			// prompt, BUT we have now matched a different record ID! Presumably
sl@0
   520
			// someone else overwrote or deleted our record....
sl@0
   521
			//
sl@0
   522
			// We need to undispute the old record id and continue as if ForcePromptL had
sl@0
   523
			// never been called/returned yes. 
sl@0
   524
			iPromptForced = EFalse;
sl@0
   525
			UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId);
sl@0
   526
			}
sl@0
   527
		
sl@0
   528
		// Call ForcePrompt to see if we need to prompt anyway
sl@0
   529
		TUint newDialogEvaluatorInfo = iDialogEvaluatorInfo;
sl@0
   530
		TBool forcePrompt = iPolicyEvaluator->Imp().ForcePromptL(*record, newDialogEvaluatorInfo);
sl@0
   531
		if(forcePrompt)
sl@0
   532
			{
sl@0
   533
			iPromptForced = ETrue;
sl@0
   534
			iPromptForcedRecordId = record->iRecordId;
sl@0
   535
			UpsServer()->DisputeRecordIdL(iPromptForcedRecordId);
sl@0
   536
			}
sl@0
   537
		
sl@0
   538
		if(newDialogEvaluatorInfo != iDialogEvaluatorInfo)
sl@0
   539
			{
sl@0
   540
			// Eavluator info changes, update our member variable copy
sl@0
   541
			// so it is used in the dialog
sl@0
   542
			iDialogEvaluatorInfo = newDialogEvaluatorInfo;
sl@0
   543
			// If we ARE displaying a prompt, then when it completes,
sl@0
   544
			// we will delete the existing record. If the user choice
sl@0
   545
			// requires a new record we will use the evaluator value
sl@0
   546
			// from our member variable
sl@0
   547
			if(!forcePrompt)
sl@0
   548
				{
sl@0
   549
				// Not forcing a prompt, so update the DB now.
sl@0
   550
				record->iEvaluatorInfo = newDialogEvaluatorInfo;
sl@0
   551
				// If the update fails, we carry on anyway...
sl@0
   552
				TRAPD(err, UpsServer()->iDbHandle->UpdateDecisionL(*filter, *record));
sl@0
   553
				if(err != KErrNone)
sl@0
   554
					{
sl@0
   555
					HandleDbErrorL(err);
sl@0
   556
					}				
sl@0
   557
				}
sl@0
   558
			}
sl@0
   559
		
sl@0
   560
		if(!forcePrompt)
sl@0
   561
			{
sl@0
   562
			// Return the result found in the DB to the system server
sl@0
   563
			TUpsDecisionPckgBuf decisionBuf;
sl@0
   564
			decisionBuf() = MapCPolicyTOptions2TUpsDecision((record->iResult) ? (CPolicy::EAlways) : (CPolicy::ENever));
sl@0
   565
			iMessagePtr2.WriteL(0, decisionBuf);
sl@0
   566
			
sl@0
   567
			CleanupStack::PopAndDestroy(record);
sl@0
   568
			CleanupStack::PopAndDestroy(filter);
sl@0
   569
			CompleteAndMarkForDeletion(KErrNone);
sl@0
   570
			return;
sl@0
   571
			}
sl@0
   572
		
sl@0
   573
		// Prompt is being forced, so fall through
sl@0
   574
		CleanupStack::PopAndDestroy(record);
sl@0
   575
		}
sl@0
   576
	
sl@0
   577
	// Record not found, or prompt forced
sl@0
   578
	CleanupStack::PopAndDestroy(filter);
sl@0
   579
	
sl@0
   580
	// Queue for clearence to display a dialog
sl@0
   581
	UpsServer()->GateKeeperL(this);
sl@0
   582
	}
sl@0
   583
sl@0
   584
void CAuthoriser::PrepareDialogL()
sl@0
   585
	{
sl@0
   586
	iState = EPreparingDialog;
sl@0
   587
	
sl@0
   588
	iDialogCreator = UpsServer()->iPluginManager->CreateDialogCreatorL(iPolicy->DialogCreator());
sl@0
   589
	
sl@0
   590
	iDialogCreator->Imp().PrepareDialog(*iPromptRequest, *iPolicy, iFingerprints, 
sl@0
   591
										iClientEntity, iDialogCreatorParams, iStatus);
sl@0
   592
	SetActive();
sl@0
   593
	}
sl@0
   594
sl@0
   595
sl@0
   596
sl@0
   597
sl@0
   598
void CAuthoriser::ExecuteDialogL()
sl@0
   599
	{
sl@0
   600
	iState = EExecutingDialog;
sl@0
   601
	iDialogCreator->Imp().DisplayDialog(iDialogSelectedOption, iDialogFingerprint, iDialogEvaluatorInfo, iStatus);
sl@0
   602
	SetActive();
sl@0
   603
	}
sl@0
   604
sl@0
   605
void CAuthoriser::ProcessDialogResultL()
sl@0
   606
	{
sl@0
   607
	if(iPromptForced)
sl@0
   608
		{
sl@0
   609
		// Pormpt was forced therefore we must have matched an existing record in the
sl@0
   610
		// database.
sl@0
   611
		// Delete the old decision.
sl@0
   612
		CDecisionFilter *filter = CDecisionFilter::NewLC();
sl@0
   613
		filter->SetRecordId(iPromptForcedRecordId, EEqual);
sl@0
   614
		TRAPD(err, UpsServer()->iDbHandle->RemoveDecisionsL(*filter));
sl@0
   615
		CleanupStack::PopAndDestroy(filter);
sl@0
   616
		if(err != KErrNone)
sl@0
   617
			{
sl@0
   618
			HandleDbErrorL(err);
sl@0
   619
			}
sl@0
   620
sl@0
   621
		// No longer disputing the record ID because we have a new decision
sl@0
   622
		iPromptForced = EFalse;
sl@0
   623
		UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId);
sl@0
   624
		}
sl@0
   625
	
sl@0
   626
	TUpsDecisionPckgBuf decisionBuf;
sl@0
   627
	// Mask out any illegal responses - ie buttons which we did not
sl@0
   628
	// ask to be displayed...
sl@0
   629
	iDialogSelectedOption = CPolicy::TOptions(TUint(iDialogSelectedOption) & TUint(iPolicy->Options()));
sl@0
   630
	
sl@0
   631
	decisionBuf() = MapCPolicyTOptions2TUpsDecision(iDialogSelectedOption);
sl@0
   632
	
sl@0
   633
	if((iDialogSelectedOption & CPolicy::EAlways) || (iDialogSelectedOption & CPolicy::ENever))
sl@0
   634
		{
sl@0
   635
sl@0
   636
		__ASSERT_ALWAYS(NULL != iDialogFingerprint,
sl@0
   637
						User::Panic(KUpsServerName,
sl@0
   638
								KErrUpsBadFingerprintLength));	
sl@0
   639
	
sl@0
   640
		// Save yes/no result to database
sl@0
   641
		TPtrC8 clientEntityName(KNullDesC8());
sl@0
   642
		if(iClientEntity)
sl@0
   643
			{
sl@0
   644
			clientEntityName.Set(iClientEntity->Name());
sl@0
   645
			}
sl@0
   646
		
sl@0
   647
		CDecisionRecord *record = CDecisionRecord::NewLC(iPromptRequest->ClientSid(),
sl@0
   648
														 iPolicy->PolicyEvaluator(),
sl@0
   649
														 iPromptRequest->ServiceId(),
sl@0
   650
														 iPromptRequest->ServerSid(),
sl@0
   651
														 iDialogFingerprint->Fingerprint(),
sl@0
   652
														 clientEntityName,
sl@0
   653
														 iDialogFingerprint->Description(),
sl@0
   654
														 ((iDialogSelectedOption & CPolicy::EAlways) != 0),
sl@0
   655
														 iPolicy->MajorVersion(),
sl@0
   656
														 iDialogEvaluatorInfo);
sl@0
   657
		
sl@0
   658
		// Create new record - Failure is not fatal...
sl@0
   659
		TRAPD(err, UpsServer()->iDbHandle->CreateDecisionL(*record));
sl@0
   660
		if(err == KErrAlreadyExists)
sl@0
   661
			{
sl@0
   662
			/// You might think this will never happen, but under OOM conditions it can/does. The original database query can fail,
sl@0
   663
			/// even though there is a matching record in the database, we then choose to display a prompt, then the above code attempts to
sl@0
   664
			/// insert a "new" record and fails.... We recover by just updating the existing record.
sl@0
   665
			CDecisionFilter *filter = CDecisionFilter::NewLC(iPromptRequest->ClientSid(),
sl@0
   666
															 iPolicy->PolicyEvaluator(),
sl@0
   667
															 iPromptRequest->ServiceId(),
sl@0
   668
															 iPromptRequest->ServerSid(),
sl@0
   669
															 iDialogFingerprint->Fingerprint(),
sl@0
   670
													 		 clientEntityName,
sl@0
   671
													 		 iPolicy->MajorVersion());
sl@0
   672
sl@0
   673
			TRAP(err, UpsServer()->iDbHandle->UpdateDecisionL(*filter, *record));
sl@0
   674
			CleanupStack::PopAndDestroy(filter);
sl@0
   675
			}
sl@0
   676
		if(err != KErrNone)
sl@0
   677
			{
sl@0
   678
			HandleDbErrorL(err);
sl@0
   679
			}
sl@0
   680
		
sl@0
   681
		CleanupStack::PopAndDestroy(record);
sl@0
   682
		}
sl@0
   683
sl@0
   684
	iMessagePtr2.WriteL(0, decisionBuf);
sl@0
   685
	
sl@0
   686
	CompleteAndMarkForDeletion(KErrNone);
sl@0
   687
	}
sl@0
   688
sl@0
   689
TUpsDecision CAuthoriser::MapCPolicyTOptions2TUpsDecision(CPolicy::TOptions aOptions)
sl@0
   690
/**
sl@0
   691
	Map the specified policy option bitmap (normally only a single bit should be set) into 
sl@0
   692
	a TUpsDecision.
sl@0
   693
sl@0
   694
	If the server supports session decisions, then return never/always as EUpsDecSessionNo/EUpsDecSessionYes.
sl@0
   695
sl@0
   696
	Usually a single option should be specified, but we consider the options in the order which
sl@0
   697
	minimises UPS traffic...
sl@0
   698
*/
sl@0
   699
	{
sl@0
   700
	if( (aOptions & (CPolicy::ENever | CPolicy::ESessionNo)) != 0)
sl@0
   701
		{
sl@0
   702
		// A Never - If the session supports "session no" then return it to cut down on UPS traffic
sl@0
   703
		if(iPolicy->Options() & CPolicy::ESessionNo)
sl@0
   704
			{
sl@0
   705
			return EUpsDecSessionNo;
sl@0
   706
			}
sl@0
   707
		// Otherwise return "single shot no" so the server will re-query us later (we may silently answer).
sl@0
   708
		return EUpsDecNo;
sl@0
   709
		}
sl@0
   710
sl@0
   711
	if( (aOptions & (CPolicy::EAlways| CPolicy::ESessionYes)) != 0)
sl@0
   712
		{
sl@0
   713
		// An Always - If the session supports "session yes" then return it to cut down on UPS traffic
sl@0
   714
		if(iPolicy->Options() & CPolicy::ESessionYes)
sl@0
   715
			{
sl@0
   716
			return EUpsDecSessionYes;
sl@0
   717
			}
sl@0
   718
		// Otherwise return "single shot yes" so the server will re-query us later (so force prompt handling works).
sl@0
   719
		return EUpsDecYes;
sl@0
   720
		}
sl@0
   721
sl@0
   722
	if( (aOptions & CPolicy::ENo) != 0)
sl@0
   723
		{
sl@0
   724
		// A "single shot no"
sl@0
   725
		return EUpsDecNo;
sl@0
   726
		}
sl@0
   727
sl@0
   728
	// Only possibility left is a single shot yes
sl@0
   729
	// If it is not one, then map to no
sl@0
   730
	BULLSEYE_OFF
sl@0
   731
	if( (aOptions & CPolicy::EYes) == 0)
sl@0
   732
		{
sl@0
   733
		return EUpsDecNo; // No option set!
sl@0
   734
		}
sl@0
   735
	BULLSEYE_RESTORE
sl@0
   736
sl@0
   737
	// A "single shot yes"
sl@0
   738
	return EUpsDecYes;
sl@0
   739
	}
sl@0
   740
sl@0
   741
void CAuthoriser::HandleDbErrorL(TInt aError)
sl@0
   742
	{
sl@0
   743
	if((aError != KErrNoMemory) && (aError != KErrDiskFull))
sl@0
   744
		{
sl@0
   745
		RDebug::Printf(KCorruptDb, aError, __LINE__);
sl@0
   746
		UpsServer()->iDbHandle->DeleteDatabaseL(UpsServer()->iFs);
sl@0
   747
		UpsServer()->iDbHandle.Close(); // Will auto-reopen when next used
sl@0
   748
		User::Leave(aError);
sl@0
   749
		}
sl@0
   750
	UpsServer()->iDbHandle.Close(); // Will auto-reopen when next used
sl@0
   751
	}
sl@0
   752
sl@0
   753
CAuthoriserFifo* CAuthoriserFifo::NewL()
sl@0
   754
	/**
sl@0
   755
	   Create a new CAuthoriserFifo instance
sl@0
   756
	*/
sl@0
   757
	{
sl@0
   758
	CAuthoriserFifo *self = new(ELeave) CAuthoriserFifo;
sl@0
   759
	return self;
sl@0
   760
	}
sl@0
   761
sl@0
   762
CAuthoriserFifo::~CAuthoriserFifo()
sl@0
   763
	/**
sl@0
   764
	   Does not delete CAuthoriser objects in the FIFO, just frees
sl@0
   765
	   storage used by the FIFO itself.
sl@0
   766
	*/
sl@0
   767
	{
sl@0
   768
	iPtrArray.Close();
sl@0
   769
	}
sl@0
   770
sl@0
   771
sl@0
   772
sl@0
   773
void CAuthoriserFifo::PushL(CAuthoriser *aAuthoriser)
sl@0
   774
	/**
sl@0
   775
	   @param aAuthoriser The CAuthoriser to be pushed onto the FIFO.
sl@0
   776
	   
sl@0
   777
	   This class does NOT take ownership.
sl@0
   778
	*/
sl@0
   779
	{
sl@0
   780
	iPtrArray.AppendL(aAuthoriser);
sl@0
   781
	}
sl@0
   782
sl@0
   783
CAuthoriser *CAuthoriserFifo::PopL()
sl@0
   784
	{
sl@0
   785
	/**
sl@0
   786
	   @return A CAuthoriser ptr, or Leaves KErrUnderflow if FIFO is empty.
sl@0
   787
	*/
sl@0
   788
	TInt count = iPtrArray.Count();
sl@0
   789
	BULLSEYE_OFF
sl@0
   790
	if(count == 0)
sl@0
   791
		{
sl@0
   792
		User::Leave(KErrUnderflow);
sl@0
   793
		}
sl@0
   794
	BULLSEYE_RESTORE
sl@0
   795
	
sl@0
   796
	CAuthoriser *ret = iPtrArray[0];
sl@0
   797
	iPtrArray.Remove(0);
sl@0
   798
	return ret;
sl@0
   799
	}
sl@0
   800
sl@0
   801
void CAuthoriserFifo::RemoveL(CAuthoriser *aAuthoriser)
sl@0
   802
	/**
sl@0
   803
	   Remove the specified object from the FIFO.
sl@0
   804
	   
sl@0
   805
	   It is not considered to be an error if the object is not in the
sl@0
   806
	   FIFO.
sl@0
   807
	   
sl@0
   808
	   @param aAuthoriser The CAuthoriser to be removed from the FIFO.
sl@0
   809
	*/
sl@0
   810
	{
sl@0
   811
	TInt i = iPtrArray.Find(aAuthoriser);
sl@0
   812
	BULLSEYE_OFF
sl@0
   813
	if( i == KErrNotFound)
sl@0
   814
		{
sl@0
   815
		return; // Not found is not considered an error.
sl@0
   816
		}
sl@0
   817
	BULLSEYE_RESTORE
sl@0
   818
	
sl@0
   819
	User::LeaveIfError(i);
sl@0
   820
	iPtrArray.Remove(i);
sl@0
   821
	}
sl@0
   822
sl@0
   823
sl@0
   824
TBool CAuthoriserFifo::IsEmpty() const
sl@0
   825
	/**
sl@0
   826
		@return ETrue if empty
sl@0
   827
	 */
sl@0
   828
	{
sl@0
   829
	return (iPtrArray.Count() == 0);
sl@0
   830
	}
sl@0
   831
sl@0
   832
void CAuthoriserFifo::Compress()
sl@0
   833
	/**
sl@0
   834
	Reduce memory usage as much as possible. Typically used during OOM testing.
sl@0
   835
	*/
sl@0
   836
{
sl@0
   837
	iPtrArray.Compress();
sl@0
   838
}
sl@0
   839
sl@0
   840
sl@0
   841
sl@0
   842
sl@0
   843
} // End of namespace UserPromptService
sl@0
   844
// End of file