os/security/authorisation/userpromptservice/server/source/upsserver/authoriser.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/authorisation/userpromptservice/server/source/upsserver/authoriser.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,844 @@
1.4 +/*
1.5 +* Copyright (c) 2007-2009 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 +* Implements CAuthoriser. See class and function definitions for
1.19 +* more information.
1.20 +*
1.21 +*/
1.22 +
1.23 +
1.24 +/**
1.25 + @file
1.26 +*/
1.27 +
1.28 +#include "upsserver.h"
1.29 +#include "policycache.h"
1.30 +#include "authoriser.h"
1.31 +#include <ups/upsdbw.h>
1.32 +#include "upslog.h"
1.33 +#include <ups/dialogcreator.h>
1.34 +#include <ups/policyevaluator.h>
1.35 +
1.36 +namespace UserPromptService
1.37 +{
1.38 +
1.39 +CAuthoriser* CAuthoriser::NewL(RPolicyCacheCountedHandle &aPolicyCache,
1.40 + CUpsSession* aSession, CUpsSubsession* aSubsession, TBool aServerCheckOk,
1.41 + TThreadId &aClientTid, TProcessId &aClientPId,
1.42 + const RMessage2& aMessage, const TServiceId& aServiceId,
1.43 + RBuf &aDestination, RBuf8 &aOpaqueData)
1.44 + /**
1.45 + Factory function allocates a new, initialized instance of CAuthoriser,
1.46 + registered for the supplied session and subsession.
1.47 +
1.48 + If construction is successful, the caller should pass ownership to
1.49 + the SCS framework (TransferToScsFrameworkL), and pop the
1.50 + CAuthoriser from the cleanupstack. From this point onwards the
1.51 + request should be completed by the CAuthoriser/CAsyncRequst code,
1.52 + so the caller must not return or leave with any code except
1.53 + KErrScsSetupAsync. This is why the StartProcessingRequest function
1.54 + is defined as non-leaving.
1.55 +
1.56 + @param aPolicyCache The server policy cache manager.
1.57 + @param aSession Session on which this request was launched.
1.58 + @param aSubsession Subsession on which this request was launched.
1.59 + @param aServerCheckOk Did the system server checks pass?
1.60 + @param aClientThread Handle to the user client thread.
1.61 + @param aMessage Standard server-side handle to message.
1.62 + @param aDestination We take ownership of the RBuf and close the callers handle
1.63 + @param aOpaqueData We take ownership of the RBuf and close the callers handle
1.64 + @return New, initialized instance of CAuthoriser, which
1.65 + is owned by the server's collection of outstanding
1.66 + requests.
1.67 + */
1.68 + {
1.69 + CAuthoriser* self = new(ELeave) CAuthoriser(aPolicyCache, aSession, aSubsession, aMessage);
1.70 + CleanupStack::PushL(self);
1.71 + self->ConstructL(aServerCheckOk, aClientTid, aClientPId, aServiceId, aDestination, aOpaqueData);
1.72 + CleanupStack::Pop(self);
1.73 + return self;
1.74 + }
1.75 +
1.76 +CAuthoriser::CAuthoriser(RPolicyCacheCountedHandle &aPolicyCache,
1.77 + CUpsSession* aSession, CUpsSubsession* aSubsession,
1.78 + const RMessage2& aMessage)
1.79 + /**
1.80 + This private constructor initializes the superclass and prevents direct instantiation.
1.81 +
1.82 + @param aPolicyCache The server policy cache manager.
1.83 + @param aSession Session on which this request was launched.
1.84 + @param aSubsession Subsession on which this request was launched.
1.85 + @param aMessage Standard server-side handle to message.
1.86 + @param aDestination HBufC description, takes ownership.
1.87 + @param aOpaqueData 0 or HBufC opaqueData, takes ownership.
1.88 + */
1.89 + : CAsyncRequest(aSession, aSubsession, aMessage),
1.90 + iPolicyCache(aPolicyCache)
1.91 + {
1.92 + // empty.
1.93 + }
1.94 +
1.95 +void CAuthoriser::ConstructL(TBool aServerCheckOk, TThreadId &aClientTid, TProcessId &aClientPid, const TServiceId& aServiceId, RBuf &aDestination, RBuf8 &aOpaqueData)
1.96 + /**
1.97 + Second-phase constructor allocates the timer which is used to generate
1.98 + a delay, and adds this object to the server's collection of outstanding
1.99 + requests.
1.100 + */
1.101 + {
1.102 + iState = ECheckPolicy;
1.103 +
1.104 + RProcess clientProcess;
1.105 + TInt r = clientProcess.Open(aClientPid);
1.106 + if(r != KErrNone)
1.107 + {
1.108 + User::Leave(KErrUpsBadClientProcessId);
1.109 + }
1.110 + CleanupClosePushL(clientProcess);
1.111 +
1.112 + // Create a CPromptReqest for the policy lookup
1.113 + iPromptRequest = CPromptRequest::NewL(clientProcess.SecureId(), // Client details
1.114 + clientProcess.VendorId(),
1.115 + aClientTid,
1.116 + aClientPid,
1.117 + iMessagePtr2.SecureId(), // Server SID
1.118 + aServiceId, // Server service ID
1.119 + aDestination, // Request detail, takes ownership
1.120 + aOpaqueData, // takes ownership
1.121 + aServerCheckOk);
1.122 +
1.123 + CleanupStack::PopAndDestroy(&clientProcess);
1.124 + }
1.125 +
1.126 +void CAuthoriser::ProcessEventL(TAuthoriserEvent aEvent)
1.127 + {
1.128 + // DEBUG_PRINTF4(_L8("0x%x CAuthoriser::ProcessEventL state %d, event %d\n"), this, iState, aEvent);
1.129 + _LIT(KServerPanicState, "UPS-ProcessEventL");
1.130 + switch(iState)
1.131 + {
1.132 + case ECheckPolicy:
1.133 + CheckPolicyStateL(aEvent);
1.134 + return;
1.135 + case ECreatingFingerprints:
1.136 + CreatingFingerprintsStateL(aEvent);
1.137 + return;
1.138 + case ECheckDatabase:
1.139 + CheckDatabaseStateL(aEvent);
1.140 + return;
1.141 + case EPreparingDialog:
1.142 + PreparingDialogStateL(aEvent);
1.143 + return;
1.144 + case EExecutingDialog:
1.145 + ExecutingDialogStateL(aEvent);
1.146 + return;
1.147 +BULLSEYE_OFF
1.148 + }
1.149 +
1.150 + // Should not get here
1.151 + User::Panic(KServerPanicState, iState);
1.152 +BULLSEYE_RESTORE
1.153 + }
1.154 +
1.155 +
1.156 +void CAuthoriser::CheckPolicyStateL(TAuthoriserEvent aEvent)
1.157 + {
1.158 + switch(aEvent)
1.159 + {
1.160 + case EInternalRequestComplete:
1.161 + // Caused by the ups sub session code calling Wakeup
1.162 + // to start the request processing. We are now within the
1.163 + // active scheduler error handling framework.
1.164 +
1.165 + // This call will lookup the policy and move to the next
1.166 + // state, or leave.
1.167 + LookupPolicyL();
1.168 + break;
1.169 +
1.170 + BULLSEYE_OFF
1.171 + case EClearedToDisplayDialog:
1.172 + ASSERT(EFalse);
1.173 + break;
1.174 + BULLSEYE_RESTORE
1.175 +
1.176 + case ECancel:
1.177 + // This WILL happen if am authorise request is made and immediately cancelled (before CAuthoriser::Runl has
1.178 + // the chance to run). We should complete our "fake" internal request so we do not block
1.179 + // when we return to the DoCancel/CActive::Cancel which caused this event.
1.180 + CompleteSelf();
1.181 + break;
1.182 +BULLSEYE_OFF
1.183 + }
1.184 +BULLSEYE_RESTORE
1.185 + }
1.186 +
1.187 +void CAuthoriser::CreatingFingerprintsStateL(TAuthoriserEvent aEvent)
1.188 + {
1.189 + switch(aEvent)
1.190 + {
1.191 + case EInternalRequestComplete:
1.192 + // This will move to the next state and lookup the fingerprints, or leave.
1.193 + LookupFingerprintsL();
1.194 + break;
1.195 +
1.196 + BULLSEYE_OFF
1.197 + case EClearedToDisplayDialog:
1.198 + ASSERT(EFalse);
1.199 + break;
1.200 + BULLSEYE_RESTORE
1.201 +
1.202 + case ECancel:
1.203 + // Cancel the request to create the fingerprints
1.204 + iPolicyEvaluator->Imp().Cancel();
1.205 + break;
1.206 +BULLSEYE_OFF
1.207 + }
1.208 +BULLSEYE_RESTORE
1.209 + }
1.210 +
1.211 +void CAuthoriser::CheckDatabaseStateL(TAuthoriserEvent aEvent)
1.212 + {
1.213 + switch(aEvent)
1.214 + {
1.215 + case EInternalRequestComplete:
1.216 + // Normally the create fingerprints state code will call
1.217 + // LookupFingerprintsL to move to this state and do the
1.218 + // lookup, but if we need to re-lookup the fingerprints a
1.219 + // "fake" request will be issued and this code will be
1.220 + // used.
1.221 + LookupFingerprintsL();
1.222 + break;
1.223 + case EClearedToDisplayDialog:
1.224 + // Change state and ask the dialog creator to start creating
1.225 + // the dialog, or leave.
1.226 + PrepareDialogL();
1.227 + break;
1.228 + case ECancel:
1.229 + // Complete the fake request which was issued to try and
1.230 + // get us to redo the fingerprint lookup.
1.231 + CompleteSelf();
1.232 + break;
1.233 +BULLSEYE_OFF
1.234 + }
1.235 +BULLSEYE_RESTORE
1.236 + }
1.237 +
1.238 +void CAuthoriser::PreparingDialogStateL(TAuthoriserEvent aEvent)
1.239 + {
1.240 + switch(aEvent)
1.241 + {
1.242 + case EInternalRequestComplete:
1.243 + // Created dialog, now change state to execute and display
1.244 + // it.
1.245 + ExecuteDialogL();
1.246 + break;
1.247 +
1.248 + BULLSEYE_OFF
1.249 + case EClearedToDisplayDialog:
1.250 + ASSERT(EFalse);
1.251 + break;
1.252 + BULLSEYE_RESTORE
1.253 +
1.254 + case ECancel:
1.255 + // Cancel the request to create the dialog
1.256 + iDialogCreator->Imp().Cancel();
1.257 + break;
1.258 +BULLSEYE_OFF
1.259 + }
1.260 +BULLSEYE_RESTORE
1.261 + }
1.262 +
1.263 +void CAuthoriser::ExecutingDialogStateL(TAuthoriserEvent aEvent)
1.264 + {
1.265 + switch(aEvent)
1.266 + {
1.267 + case EInternalRequestComplete:
1.268 + // Dialog complete, process the result and complete the
1.269 + // client request.
1.270 + ProcessDialogResultL();
1.271 + break;
1.272 +
1.273 + BULLSEYE_OFF
1.274 + case EClearedToDisplayDialog:
1.275 + ASSERT(EFalse);
1.276 + break;
1.277 + BULLSEYE_RESTORE
1.278 +
1.279 + case ECancel:
1.280 + // Cancel the request to execute the dialog
1.281 + iDialogCreator->Imp().Cancel();
1.282 + break;
1.283 +BULLSEYE_OFF
1.284 + }
1.285 +BULLSEYE_RESTORE
1.286 + }
1.287 +
1.288 +void CAuthoriser::Wakeup()
1.289 + /**
1.290 + Raise and complete a request against self. Will cause RunL to
1.291 + be run within the active scheduler.
1.292 + */
1.293 + {
1.294 + iStatus = KRequestPending;
1.295 + SetActive();
1.296 + CompleteSelf();
1.297 + }
1.298 +
1.299 +void CAuthoriser::CompleteSelf()
1.300 + {
1.301 + _LIT(KServerPanicState, "UPS-CompleteSelf");
1.302 + switch(iState)
1.303 + {
1.304 + case ECheckPolicy:
1.305 + case ECheckDatabase:
1.306 + break;
1.307 +
1.308 + BULLSEYE_OFF
1.309 + case ECreatingFingerprints:
1.310 + case EPreparingDialog:
1.311 + case EExecutingDialog:
1.312 + User::Panic(KServerPanicState, iState);
1.313 + /*lint -unreachable */
1.314 + return; // Not legal in these states
1.315 + }
1.316 + BULLSEYE_RESTORE
1.317 +
1.318 + if(iStatus == KRequestPending)
1.319 + {
1.320 + TRequestStatus *status = &iStatus;
1.321 + User::RequestComplete(status, KErrNone);
1.322 + }
1.323 + }
1.324 +
1.325 +
1.326 +
1.327 +void CAuthoriser::ClearedToDisplayL()
1.328 + /**
1.329 + The UPS server GateKeeper has granted us permission to proceed
1.330 + with dialog generation and display.
1.331 + */
1.332 + {
1.333 + ProcessEventL(EClearedToDisplayDialog);
1.334 + }
1.335 +
1.336 +
1.337 +
1.338 +
1.339 +
1.340 +
1.341 +CAuthoriser::~CAuthoriser()
1.342 + /**
1.343 + Close the timer which was initialized in ConstructL.
1.344 + */
1.345 + {
1.346 + iDialogFingerprint = 0; // MUST not delete, owned by CDialogCreator
1.347 +
1.348 + delete iDialogCreator;
1.349 + iDialogCreator = 0;
1.350 +
1.351 + iDialogCreatorParams = 0; // MUST not delete, owned by evaluator
1.352 +
1.353 + iClientEntity = 0; // MUST not delete, owned by evaluator
1.354 +
1.355 + iFingerprints.ResetAndDestroy();
1.356 +
1.357 + delete iPolicyEvaluator;
1.358 + iPolicyEvaluator = 0;
1.359 +
1.360 + iPolicyCache.Release();
1.361 + iPolicy = 0; // MUST not delete, ownded by policy cache
1.362 +
1.363 + delete iPromptRequest;
1.364 + iPromptRequest = 0;
1.365 + }
1.366 +
1.367 +void CAuthoriser::RunL()
1.368 + {
1.369 + // Wake up the next pending request now (if any), to make sure it
1.370 + // will be processed ahead of any incoming requests.
1.371 + UpsServer()->WakeupNextPendingL();
1.372 +
1.373 + // Reset our priority to standard
1.374 + if(Priority() != CActive::EPriorityStandard)
1.375 + {
1.376 + SetPriority(CActive::EPriorityStandard);
1.377 + }
1.378 + User::LeaveIfError(iStatus.Int());
1.379 +
1.380 + ProcessEventL(EInternalRequestComplete);
1.381 + }
1.382 +
1.383 +
1.384 +void CAuthoriser::DoCleanup()
1.385 + {
1.386 + if(iPromptForced)
1.387 + {
1.388 + // Have previously called ForcePromptL on a database record and it told us to
1.389 + // prompt, so have previously marked the record as disputed.
1.390 + TRAP_IGNORE(UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId));
1.391 + iPromptForced = EFalse;
1.392 + }
1.393 +
1.394 + // Cancel current internal operation
1.395 + Cancel();
1.396 +
1.397 + // Let the server know we are done
1.398 + UpsServer()->AuthoriserDone(this);
1.399 +
1.400 + // The framework will complete the client request and schedule us
1.401 + // for deletion.
1.402 + }
1.403 +
1.404 +
1.405 +
1.406 +
1.407 +void CAuthoriser::DoCancel()
1.408 + /**
1.409 + Cancel the current operation. This does not complete the client
1.410 + request or mark this object for deletion.
1.411 + */
1.412 + {
1.413 + TRAP_IGNORE(
1.414 + // Wake up the next pending request now (if any), to make sure it
1.415 + // will be processed ahead of any incoming requests.
1.416 + UpsServer()->WakeupNextPendingL();
1.417 + ProcessEventL(ECancel);
1.418 + );
1.419 + }
1.420 +
1.421 +void CAuthoriser::LookupPolicyL()
1.422 + {
1.423 + // This returns a ptr into the cache, so we have to be careful not to use it after the cache is deleted.
1.424 + // This is why we wrap the cache in a RPolicyCacheCountedHandle.
1.425 + iPolicy = iPolicyCache->MatchL(*iPromptRequest);
1.426 +
1.427 + ASSERT(iPolicy);
1.428 +
1.429 + if(iPolicy->PromptRequired())
1.430 + {
1.431 + // Policy contains both yes and no responses...
1.432 + // Start creating the fingerprints
1.433 + CreateFingerprintsL();
1.434 + return;
1.435 + }
1.436 +
1.437 + // Return result to system server
1.438 + TUpsDecisionPckgBuf decisionBuf;
1.439 + decisionBuf() = MapCPolicyTOptions2TUpsDecision(iPolicy->Options());
1.440 + iMessagePtr2.WriteL(0, decisionBuf);
1.441 +
1.442 + CompleteAndMarkForDeletion(KErrNone);
1.443 + }
1.444 +
1.445 +
1.446 +void CAuthoriser::CreateFingerprintsL()
1.447 + /**
1.448 + Load Policy Evaluator and tell it to start generating the fingerprints
1.449 + */
1.450 + {
1.451 + iState = ECreatingFingerprints;
1.452 +
1.453 + iPolicyEvaluator = UpsServer()->iPluginManager->CreateEvaluatorL(iPolicy->PolicyEvaluator());
1.454 +
1.455 + iPolicyEvaluator->Imp().GenerateFingerprints(*iPromptRequest, *iPolicy,
1.456 + iFingerprints, iClientEntity, iDialogCreatorParams, iStatus);
1.457 +
1.458 + SetActive();
1.459 + }
1.460 +
1.461 +_LIT8(KDefaultFingerprint,"*");
1.462 +//_LIT(KServerPanicDb, "UPS-BadDB");
1.463 +static const char * const KCorruptDb = "UPS-BadDB error=%d line=%d\n";
1.464 +
1.465 +void CAuthoriser::LookupFingerprintsL()
1.466 + {
1.467 + // Lookup in DB
1.468 + iState = ECheckDatabase;
1.469 +
1.470 + TPtrC8 clientEntityName(KNullDesC8());
1.471 + if(iClientEntity)
1.472 + {
1.473 + clientEntityName.Set(iClientEntity->Name());
1.474 + }
1.475 +
1.476 + CDecisionFilter *filter = CDecisionFilter::NewLC(iPromptRequest->ClientSid(),
1.477 + iPolicy->PolicyEvaluator(),
1.478 + iPromptRequest->ServiceId(),
1.479 + iPromptRequest->ServerSid(),
1.480 + KDefaultFingerprint(),
1.481 + clientEntityName,
1.482 + iPolicy->MajorVersion());
1.483 + //
1.484 + // Lookup the fingerprints in the DB and return the first match
1.485 + //
1.486 + CDecisionRecord *record = 0;
1.487 + TInt fingerprintCount = iFingerprints.Count();
1.488 + for(TInt i=0; i<fingerprintCount; ++i)
1.489 + {
1.490 + filter->SetFingerprintL(iFingerprints[i]->Fingerprint(), EEqual);
1.491 + record = 0;
1.492 + TRAPD(err, record = UpsServer()->iDbHandle->GetDecisionL(*filter));
1.493 + if(err != KErrNone)
1.494 + {
1.495 + HandleDbErrorL(err);
1.496 + }
1.497 +
1.498 + if(record)
1.499 + {
1.500 + break;
1.501 + }
1.502 + }
1.503 +
1.504 + if(record)
1.505 + {
1.506 + // Found record
1.507 + CleanupStack::PushL(record);
1.508 + // Read current eval info value from record.
1.509 + iDialogEvaluatorInfo = record->iEvaluatorInfo;
1.510 +
1.511 + if(UpsServer()->IsRecordIdDisputed(record->iRecordId))
1.512 + {
1.513 + // Matching record is under dispute so a dialog must be in progress.
1.514 + // Queue for later re-evaluation.
1.515 + UpsServer()->GateKeeperL(this);
1.516 + return;
1.517 + }
1.518 +
1.519 + if(iPromptForced && (record->iRecordId != iPromptForcedRecordId))
1.520 + {
1.521 + // Have previously called ForcePromptL on a database record and it told us to
1.522 + // prompt, BUT we have now matched a different record ID! Presumably
1.523 + // someone else overwrote or deleted our record....
1.524 + //
1.525 + // We need to undispute the old record id and continue as if ForcePromptL had
1.526 + // never been called/returned yes.
1.527 + iPromptForced = EFalse;
1.528 + UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId);
1.529 + }
1.530 +
1.531 + // Call ForcePrompt to see if we need to prompt anyway
1.532 + TUint newDialogEvaluatorInfo = iDialogEvaluatorInfo;
1.533 + TBool forcePrompt = iPolicyEvaluator->Imp().ForcePromptL(*record, newDialogEvaluatorInfo);
1.534 + if(forcePrompt)
1.535 + {
1.536 + iPromptForced = ETrue;
1.537 + iPromptForcedRecordId = record->iRecordId;
1.538 + UpsServer()->DisputeRecordIdL(iPromptForcedRecordId);
1.539 + }
1.540 +
1.541 + if(newDialogEvaluatorInfo != iDialogEvaluatorInfo)
1.542 + {
1.543 + // Eavluator info changes, update our member variable copy
1.544 + // so it is used in the dialog
1.545 + iDialogEvaluatorInfo = newDialogEvaluatorInfo;
1.546 + // If we ARE displaying a prompt, then when it completes,
1.547 + // we will delete the existing record. If the user choice
1.548 + // requires a new record we will use the evaluator value
1.549 + // from our member variable
1.550 + if(!forcePrompt)
1.551 + {
1.552 + // Not forcing a prompt, so update the DB now.
1.553 + record->iEvaluatorInfo = newDialogEvaluatorInfo;
1.554 + // If the update fails, we carry on anyway...
1.555 + TRAPD(err, UpsServer()->iDbHandle->UpdateDecisionL(*filter, *record));
1.556 + if(err != KErrNone)
1.557 + {
1.558 + HandleDbErrorL(err);
1.559 + }
1.560 + }
1.561 + }
1.562 +
1.563 + if(!forcePrompt)
1.564 + {
1.565 + // Return the result found in the DB to the system server
1.566 + TUpsDecisionPckgBuf decisionBuf;
1.567 + decisionBuf() = MapCPolicyTOptions2TUpsDecision((record->iResult) ? (CPolicy::EAlways) : (CPolicy::ENever));
1.568 + iMessagePtr2.WriteL(0, decisionBuf);
1.569 +
1.570 + CleanupStack::PopAndDestroy(record);
1.571 + CleanupStack::PopAndDestroy(filter);
1.572 + CompleteAndMarkForDeletion(KErrNone);
1.573 + return;
1.574 + }
1.575 +
1.576 + // Prompt is being forced, so fall through
1.577 + CleanupStack::PopAndDestroy(record);
1.578 + }
1.579 +
1.580 + // Record not found, or prompt forced
1.581 + CleanupStack::PopAndDestroy(filter);
1.582 +
1.583 + // Queue for clearence to display a dialog
1.584 + UpsServer()->GateKeeperL(this);
1.585 + }
1.586 +
1.587 +void CAuthoriser::PrepareDialogL()
1.588 + {
1.589 + iState = EPreparingDialog;
1.590 +
1.591 + iDialogCreator = UpsServer()->iPluginManager->CreateDialogCreatorL(iPolicy->DialogCreator());
1.592 +
1.593 + iDialogCreator->Imp().PrepareDialog(*iPromptRequest, *iPolicy, iFingerprints,
1.594 + iClientEntity, iDialogCreatorParams, iStatus);
1.595 + SetActive();
1.596 + }
1.597 +
1.598 +
1.599 +
1.600 +
1.601 +void CAuthoriser::ExecuteDialogL()
1.602 + {
1.603 + iState = EExecutingDialog;
1.604 + iDialogCreator->Imp().DisplayDialog(iDialogSelectedOption, iDialogFingerprint, iDialogEvaluatorInfo, iStatus);
1.605 + SetActive();
1.606 + }
1.607 +
1.608 +void CAuthoriser::ProcessDialogResultL()
1.609 + {
1.610 + if(iPromptForced)
1.611 + {
1.612 + // Pormpt was forced therefore we must have matched an existing record in the
1.613 + // database.
1.614 + // Delete the old decision.
1.615 + CDecisionFilter *filter = CDecisionFilter::NewLC();
1.616 + filter->SetRecordId(iPromptForcedRecordId, EEqual);
1.617 + TRAPD(err, UpsServer()->iDbHandle->RemoveDecisionsL(*filter));
1.618 + CleanupStack::PopAndDestroy(filter);
1.619 + if(err != KErrNone)
1.620 + {
1.621 + HandleDbErrorL(err);
1.622 + }
1.623 +
1.624 + // No longer disputing the record ID because we have a new decision
1.625 + iPromptForced = EFalse;
1.626 + UpsServer()->UnDisputeRecordIdL(iPromptForcedRecordId);
1.627 + }
1.628 +
1.629 + TUpsDecisionPckgBuf decisionBuf;
1.630 + // Mask out any illegal responses - ie buttons which we did not
1.631 + // ask to be displayed...
1.632 + iDialogSelectedOption = CPolicy::TOptions(TUint(iDialogSelectedOption) & TUint(iPolicy->Options()));
1.633 +
1.634 + decisionBuf() = MapCPolicyTOptions2TUpsDecision(iDialogSelectedOption);
1.635 +
1.636 + if((iDialogSelectedOption & CPolicy::EAlways) || (iDialogSelectedOption & CPolicy::ENever))
1.637 + {
1.638 +
1.639 + __ASSERT_ALWAYS(NULL != iDialogFingerprint,
1.640 + User::Panic(KUpsServerName,
1.641 + KErrUpsBadFingerprintLength));
1.642 +
1.643 + // Save yes/no result to database
1.644 + TPtrC8 clientEntityName(KNullDesC8());
1.645 + if(iClientEntity)
1.646 + {
1.647 + clientEntityName.Set(iClientEntity->Name());
1.648 + }
1.649 +
1.650 + CDecisionRecord *record = CDecisionRecord::NewLC(iPromptRequest->ClientSid(),
1.651 + iPolicy->PolicyEvaluator(),
1.652 + iPromptRequest->ServiceId(),
1.653 + iPromptRequest->ServerSid(),
1.654 + iDialogFingerprint->Fingerprint(),
1.655 + clientEntityName,
1.656 + iDialogFingerprint->Description(),
1.657 + ((iDialogSelectedOption & CPolicy::EAlways) != 0),
1.658 + iPolicy->MajorVersion(),
1.659 + iDialogEvaluatorInfo);
1.660 +
1.661 + // Create new record - Failure is not fatal...
1.662 + TRAPD(err, UpsServer()->iDbHandle->CreateDecisionL(*record));
1.663 + if(err == KErrAlreadyExists)
1.664 + {
1.665 + /// You might think this will never happen, but under OOM conditions it can/does. The original database query can fail,
1.666 + /// even though there is a matching record in the database, we then choose to display a prompt, then the above code attempts to
1.667 + /// insert a "new" record and fails.... We recover by just updating the existing record.
1.668 + CDecisionFilter *filter = CDecisionFilter::NewLC(iPromptRequest->ClientSid(),
1.669 + iPolicy->PolicyEvaluator(),
1.670 + iPromptRequest->ServiceId(),
1.671 + iPromptRequest->ServerSid(),
1.672 + iDialogFingerprint->Fingerprint(),
1.673 + clientEntityName,
1.674 + iPolicy->MajorVersion());
1.675 +
1.676 + TRAP(err, UpsServer()->iDbHandle->UpdateDecisionL(*filter, *record));
1.677 + CleanupStack::PopAndDestroy(filter);
1.678 + }
1.679 + if(err != KErrNone)
1.680 + {
1.681 + HandleDbErrorL(err);
1.682 + }
1.683 +
1.684 + CleanupStack::PopAndDestroy(record);
1.685 + }
1.686 +
1.687 + iMessagePtr2.WriteL(0, decisionBuf);
1.688 +
1.689 + CompleteAndMarkForDeletion(KErrNone);
1.690 + }
1.691 +
1.692 +TUpsDecision CAuthoriser::MapCPolicyTOptions2TUpsDecision(CPolicy::TOptions aOptions)
1.693 +/**
1.694 + Map the specified policy option bitmap (normally only a single bit should be set) into
1.695 + a TUpsDecision.
1.696 +
1.697 + If the server supports session decisions, then return never/always as EUpsDecSessionNo/EUpsDecSessionYes.
1.698 +
1.699 + Usually a single option should be specified, but we consider the options in the order which
1.700 + minimises UPS traffic...
1.701 +*/
1.702 + {
1.703 + if( (aOptions & (CPolicy::ENever | CPolicy::ESessionNo)) != 0)
1.704 + {
1.705 + // A Never - If the session supports "session no" then return it to cut down on UPS traffic
1.706 + if(iPolicy->Options() & CPolicy::ESessionNo)
1.707 + {
1.708 + return EUpsDecSessionNo;
1.709 + }
1.710 + // Otherwise return "single shot no" so the server will re-query us later (we may silently answer).
1.711 + return EUpsDecNo;
1.712 + }
1.713 +
1.714 + if( (aOptions & (CPolicy::EAlways| CPolicy::ESessionYes)) != 0)
1.715 + {
1.716 + // An Always - If the session supports "session yes" then return it to cut down on UPS traffic
1.717 + if(iPolicy->Options() & CPolicy::ESessionYes)
1.718 + {
1.719 + return EUpsDecSessionYes;
1.720 + }
1.721 + // Otherwise return "single shot yes" so the server will re-query us later (so force prompt handling works).
1.722 + return EUpsDecYes;
1.723 + }
1.724 +
1.725 + if( (aOptions & CPolicy::ENo) != 0)
1.726 + {
1.727 + // A "single shot no"
1.728 + return EUpsDecNo;
1.729 + }
1.730 +
1.731 + // Only possibility left is a single shot yes
1.732 + // If it is not one, then map to no
1.733 + BULLSEYE_OFF
1.734 + if( (aOptions & CPolicy::EYes) == 0)
1.735 + {
1.736 + return EUpsDecNo; // No option set!
1.737 + }
1.738 + BULLSEYE_RESTORE
1.739 +
1.740 + // A "single shot yes"
1.741 + return EUpsDecYes;
1.742 + }
1.743 +
1.744 +void CAuthoriser::HandleDbErrorL(TInt aError)
1.745 + {
1.746 + if((aError != KErrNoMemory) && (aError != KErrDiskFull))
1.747 + {
1.748 + RDebug::Printf(KCorruptDb, aError, __LINE__);
1.749 + UpsServer()->iDbHandle->DeleteDatabaseL(UpsServer()->iFs);
1.750 + UpsServer()->iDbHandle.Close(); // Will auto-reopen when next used
1.751 + User::Leave(aError);
1.752 + }
1.753 + UpsServer()->iDbHandle.Close(); // Will auto-reopen when next used
1.754 + }
1.755 +
1.756 +CAuthoriserFifo* CAuthoriserFifo::NewL()
1.757 + /**
1.758 + Create a new CAuthoriserFifo instance
1.759 + */
1.760 + {
1.761 + CAuthoriserFifo *self = new(ELeave) CAuthoriserFifo;
1.762 + return self;
1.763 + }
1.764 +
1.765 +CAuthoriserFifo::~CAuthoriserFifo()
1.766 + /**
1.767 + Does not delete CAuthoriser objects in the FIFO, just frees
1.768 + storage used by the FIFO itself.
1.769 + */
1.770 + {
1.771 + iPtrArray.Close();
1.772 + }
1.773 +
1.774 +
1.775 +
1.776 +void CAuthoriserFifo::PushL(CAuthoriser *aAuthoriser)
1.777 + /**
1.778 + @param aAuthoriser The CAuthoriser to be pushed onto the FIFO.
1.779 +
1.780 + This class does NOT take ownership.
1.781 + */
1.782 + {
1.783 + iPtrArray.AppendL(aAuthoriser);
1.784 + }
1.785 +
1.786 +CAuthoriser *CAuthoriserFifo::PopL()
1.787 + {
1.788 + /**
1.789 + @return A CAuthoriser ptr, or Leaves KErrUnderflow if FIFO is empty.
1.790 + */
1.791 + TInt count = iPtrArray.Count();
1.792 + BULLSEYE_OFF
1.793 + if(count == 0)
1.794 + {
1.795 + User::Leave(KErrUnderflow);
1.796 + }
1.797 + BULLSEYE_RESTORE
1.798 +
1.799 + CAuthoriser *ret = iPtrArray[0];
1.800 + iPtrArray.Remove(0);
1.801 + return ret;
1.802 + }
1.803 +
1.804 +void CAuthoriserFifo::RemoveL(CAuthoriser *aAuthoriser)
1.805 + /**
1.806 + Remove the specified object from the FIFO.
1.807 +
1.808 + It is not considered to be an error if the object is not in the
1.809 + FIFO.
1.810 +
1.811 + @param aAuthoriser The CAuthoriser to be removed from the FIFO.
1.812 + */
1.813 + {
1.814 + TInt i = iPtrArray.Find(aAuthoriser);
1.815 + BULLSEYE_OFF
1.816 + if( i == KErrNotFound)
1.817 + {
1.818 + return; // Not found is not considered an error.
1.819 + }
1.820 + BULLSEYE_RESTORE
1.821 +
1.822 + User::LeaveIfError(i);
1.823 + iPtrArray.Remove(i);
1.824 + }
1.825 +
1.826 +
1.827 +TBool CAuthoriserFifo::IsEmpty() const
1.828 + /**
1.829 + @return ETrue if empty
1.830 + */
1.831 + {
1.832 + return (iPtrArray.Count() == 0);
1.833 + }
1.834 +
1.835 +void CAuthoriserFifo::Compress()
1.836 + /**
1.837 + Reduce memory usage as much as possible. Typically used during OOM testing.
1.838 + */
1.839 +{
1.840 + iPtrArray.Compress();
1.841 +}
1.842 +
1.843 +
1.844 +
1.845 +
1.846 +} // End of namespace UserPromptService
1.847 +// End of file