os/security/authorisation/userpromptservice/server/source/upsserver/upsserver.cpp
First public contribution.
2 * Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
15 * Implements CUpsServer. See class and function definitions for
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"
37 #include "upsserver_p.h"
39 namespace UserPromptService
42 static const TInt upsPolicyRangeCount = 8;
43 static const TInt upsPolicyRanges[upsPolicyRangeCount] =
46 // Range 0 - 0 to EBaseSession-1
48 CScsServer::EBaseSession,
49 // Range 1 - EBaseSession to EBaseSession | EMngmntRead-1
51 // These codes used to create subsessions and to query the policy
52 // authorisation settings.
54 // (ESessSubsessFromThreadId/EGetClientConfigLength/EGetClientConfigData)
56 CScsServer::EBaseSession | EMngmntRead,
57 // Range 2 - EBaseSession | EMngmntRead to EBaseSession | EMngmntDelete - 1
59 // Management READ APIs
61 CScsServer::EBaseSession | EMngmntDelete,
62 // Range 3 - EBaseSession | EMngmntDelete to EBaseSession | EMngmntUpdate - 1
63 // Management DELETE API (ie. delete entire database or selected entries).
65 CScsServer::EBaseSession | EMngmntUpdate,
66 // Range 4 - EBaseSession | EMngmntUpdate to EBaseSession | ESwiObserver - 1
67 // Management UPDATE API (ie. change an existing decision).
69 CScsServer::EBaseSession | ESwiObserver,
70 // Range 5 - EBaseSession | ESwiObserver to EBaseSubSession - 1
71 // SWI observer management API.
73 CScsServer::EBaseSubSession,
74 // Range 6 - EBaseSubSession to EBaseMustAllow-1
77 // Authorise - (ESubsessPreparePrompt/ESubsessExecutePrompt)
78 CScsServer::EBaseMustAllow
79 // Range 7 - EBaseMustAllow to KMaxTInt inclusive
81 // SCS internal APIs to create subsessions, cancel requests etc.
84 static const TUint8 upsPolicyElementsIndex[upsPolicyRangeCount] =
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
96 // 0x102836C3 == Swi::KUidSwiObserver.iUid from swiobserver.h BUT we can not include that because SWI is optional
98 static const TSecureId KSwiObserverSid(0x102836C3);
99 static const CPolicyServer::TPolicyElement upsPolicyPolicyElements[5] =
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}
108 static const CPolicyServer::TPolicy upsPolicy =
110 CPolicyServer::EAlwaysPass, // Allow all connects
113 upsPolicyElementsIndex,
114 upsPolicyPolicyElements,
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.
120 CUpsServer* CUpsServer::NewLC()
122 Factory function allocates new, initialized instance of
123 CUpsServer which is left on the cleanup stack.
125 @return New, initialized instance of CUpsServer
126 which is left on the cleanup stack.
129 CUpsServer* self = new(ELeave) CUpsServer();
130 CleanupStack::PushL(self);
135 CUpsServer::CUpsServer()
137 Initializes the superclass with this server's version.
139 : CScsServer(UserPromptService::Version(), upsPolicy),
146 void CUpsServer::ConstructL()
148 Second-phase construction initializes the superclass and
152 CScsServer::ConstructL(UserPromptService::KShutdownPeriodUs);
153 User::LeaveIfError(iFs.Connect());
155 TInt r = RProperty::Define(KUpsServiceConfigProperty, RProperty::EInt, KAllowProtServ, KAllowUpsServer);
156 if(r != KErrAlreadyExists)
158 User::LeaveIfError(r);
161 iSwiWatcher = CSwiWatcher::NewL(*this);
165 StartL(UserPromptService::KUpsServerName);
168 void CUpsServer::SetupL()
170 Setup memory variables which are not already setup.
171 Used during intial construction and after a call to FreeUncompressableMemory.
174 if(!iPolicyCache.IsOpen())
176 iPolicyCache.OpenL();
180 iPluginManager = CPluginManager::NewL();
183 // Create/Open the database
184 if(!iDbHandle.IsOpen())
191 iFlurryQueue = CAuthoriserFifo::NewL();
193 if(!iFlurryQueueBeingProcessed)
195 iFlurryQueueBeingProcessed = CAuthoriserFifo::NewL();
199 void CUpsServer::FreeUncompressableMemory()
201 Frees memory which can not be compressed down to a known level for OOM testing.
208 iPluginManager->Unload();
209 delete iPluginManager;
213 iPolicyCache.Release();
217 CUpsServer::~CUpsServer()
219 Cleanup the server, in particular close the RFs session.
224 (void) RProperty::Delete(KUpsServiceConfigProperty);
226 delete iFlurryQueueBeingProcessed;
227 iFlurryQueueBeingProcessed = 0;
232 FreeUncompressableMemory();
239 CScsSession* CUpsServer::DoNewSessionL(const RMessage2& /*aMessage*/)
241 Implement CScsServer by allocating a new instance of CUpsSession.
243 @param aMessage Standard server-side handle to message. Not used.
244 @return New instance of CUpsSession which is owned by the
248 return CUpsSession::NewL(*this);
252 void CUpsServer::DoPreHeapMarkOrCheckL()
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.
259 if(iAsyncRequests.Count() != 0)
261 User::Leave(KErrServerBusy);
263 iDisputed.Compress();
264 iFlurryQueue->Compress();
265 iFlurryQueueBeingProcessed->Compress();
266 FreeUncompressableMemory();
270 void CUpsServer::DoPostHeapMarkOrCheckL()
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.
281 void CUpsServer::GateKeeperL(CAuthoriser *aAuthoriser)
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
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.
291 If a dialog is already in progress, the the aAuthoriser will be
292 added to iFlurryQueue for later processing.
294 @param aAuthoriser to queue
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);
305 iCurrentDialog = aAuthoriser;
306 iCurrentDialog->ClearedToDisplayL();
309 void CUpsServer::AuthoriserDone(CAuthoriser *aAuthoriser)
311 See CUpsServer::AuthoriserDoneL for documentation.
314 TRAP_IGNORE(AuthoriserDoneL(aAuthoriser));
317 void CUpsServer::AuthoriserDoneL(CAuthoriser *aAuthoriser)
319 The CAuthoriser has either completed the request, been
320 cancelled, or failed somehow.
322 If it is in either FIFO it needs removing.
324 If it is the current display dialog, then we need to check the
325 FIFOs, and maybe swap them, and call WakeupNextPending.
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);
333 if(aAuthoriser == iCurrentDialog)
337 if(iFlurryQueueBeingProcessed->IsEmpty())
340 CAuthoriserFifo *tmp = iFlurryQueue;
341 iFlurryQueue = iFlurryQueueBeingProcessed;
342 iFlurryQueueBeingProcessed = tmp;
344 WakeupNextPendingL();
348 void CUpsServer::WakeupNextPendingL()
350 This function does the following:-
352 1) If iFlurryQueueBeingProcessed is empty it returns.
354 2) Removes the first authoriser from iFlurryQueueBeingProcessed
355 and calls SetPending to mark it as no longer pending.
357 3) Increases its priority to EPriorityUserInput (this makes
358 sure it will be handled ahead of any incoming requests)
360 4) Sets it active and completes it so it runs.
362 It will run BEFORE any incoming requests.
364 The first thing it must do is call this function again. This
365 ensures all pending requests are re-processed in order.
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
373 if(iFlurryQueueBeingProcessed->IsEmpty())
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();
385 void CUpsServer::DisputeRecordIdL(TUint32 aRecordId)
387 Add the specified record to the list of disputed record IDs.
390 DEBUG_PRINTF2(_L8("CUpsServer::DisputeRecordIdL(%d)\n"), aRecordId);
391 User::LeaveIfError(iDisputed.InsertInOrder(aRecordId));
394 void CUpsServer::UnDisputeRecordIdL(TUint32 aRecordId)
396 Deletes the specified record from the list of disputed record IDs.
399 DEBUG_PRINTF2(_L8("CUpsServer::UnDisputeRecordIdL(%d)\n"), aRecordId);
400 TInt i = iDisputed.FindInOrderL(aRecordId);
401 User::LeaveIfError(i);
405 TBool CUpsServer::IsRecordIdDisputed(TUint32 aRecordId) const
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.
412 TBool disputed = iDisputed.FindInOrder(aRecordId) >= 0;
413 //RDebug::Printf("CUpsServer::IsRecordIdDisputed(%d) - returning %s\n",
415 // (disputed)?("EFalse"):("EFalse"));
420 // Implementation of CSwiWatcher
422 CSwiWatcher *CSwiWatcher::NewL(CUpsServer &aUpsServer)
424 CSwiWatcher *self = new(ELeave) CSwiWatcher(aUpsServer);
425 CleanupStack::PushL(self);
427 CleanupStack::Pop(self);
431 CSwiWatcher::CSwiWatcher(CUpsServer &aUpsServer)
432 : CActive(CActive::EPriorityHigh),
433 iUpsServer(aUpsServer)
435 CActiveScheduler::Add(this);
438 void CSwiWatcher::ConstructL()
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.
444 User::LeaveIfError(iSwiProperty.Attach(KUidSystemCategory, KSAUidSoftwareInstallKeyValue));
445 iSwiProperty.Subscribe(iStatus);
449 void CSwiWatcher::RunL()
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.
456 User::LeaveIfError(iStatus.Int());
458 iSwiProperty.Subscribe(iStatus);
461 // Tell the plugin manager to unload plugins which are NOT in use.
462 iUpsServer.iPluginManager->Unload();
465 void CSwiWatcher::DoCancel()
467 iSwiProperty.Cancel();
470 CSwiWatcher::~CSwiWatcher()
473 iSwiProperty.Close();
477 } // End of namespace UserPromptService